1 | // RUN: %clang_cc1 -fsyntax-only -verify -Wno-sizeof-array-argument %s |
2 | // |
3 | extern "C" void *bzero(void *, unsigned); |
4 | extern "C" void *memset(void *, int, unsigned); |
5 | extern "C" void *memmove(void *s1, const void *s2, unsigned n); |
6 | extern "C" void *memcpy(void *s1, const void *s2, unsigned n); |
7 | extern "C" void *memcmp(void *s1, const void *s2, unsigned n); |
8 | |
9 | struct S {int a, b, c, d;}; |
10 | typedef S* PS; |
11 | |
12 | struct Foo {}; |
13 | typedef const Foo& CFooRef; |
14 | typedef const Foo CFoo; |
15 | typedef volatile Foo VFoo; |
16 | typedef const volatile Foo CVFoo; |
17 | |
18 | typedef double Mat[4][4]; |
19 | |
20 | template <class Dest, class Source> |
21 | inline Dest bit_cast(const Source& source) { |
22 | Dest dest; |
23 | memcpy(&dest, &source, sizeof(dest)); |
24 | return dest; |
25 | } |
26 | |
27 | // http://www.lysator.liu.se/c/c-faq/c-2.html#2-6 |
28 | void f(Mat m, const Foo& const_foo, char *buffer) { |
29 | S s; |
30 | S* ps = &s; |
31 | PS ps2 = &s; |
32 | char arr[5]; |
33 | char* parr[5]; |
34 | Foo foo; |
35 | char* heap_buffer = new char[42]; |
36 | |
37 | /* Should warn */ |
38 | memset(&s, 0, sizeof(&s)); // \ |
39 | // expected-warning {{'memset' call operates on objects of type 'S' while the size is based on a different type 'S *'}} expected-note{{did you mean to remove the addressof in the argument to 'sizeof' (and multiply it by the number of elements)?}} |
40 | memset(ps, 0, sizeof(ps)); // \ |
41 | // expected-warning {{'memset' call operates on objects of type 'S' while the size is based on a different type 'S *'}} expected-note{{did you mean to dereference the argument to 'sizeof' (and multiply it by the number of elements)?}} |
42 | memset(ps2, 0, sizeof(ps2)); // \ |
43 | // expected-warning {{'memset' call operates on objects of type 'S' while the size is based on a different type 'PS' (aka 'S *')}} expected-note{{did you mean to dereference the argument to 'sizeof' (and multiply it by the number of elements)?}} |
44 | memset(ps2, 0, sizeof(typeof(ps2))); // \ |
45 | // expected-warning {{argument to 'sizeof' in 'memset' call is the same pointer type}} |
46 | memset(ps2, 0, sizeof(PS)); // \ |
47 | // expected-warning {{argument to 'sizeof' in 'memset' call is the same pointer type}} |
48 | memset(heap_buffer, 0, sizeof(heap_buffer)); // \ |
49 | // expected-warning {{'memset' call operates on objects of type 'char' while the size is based on a different type 'char *'}} expected-note{{did you mean to provide an explicit length?}} |
50 | |
51 | bzero(&s, sizeof(&s)); // \ |
52 | // expected-warning {{'bzero' call operates on objects of type 'S' while the size is based on a different type 'S *'}} expected-note{{did you mean to remove the addressof in the argument to 'sizeof' (and multiply it by the number of elements)?}} |
53 | bzero(ps, sizeof(ps)); // \ |
54 | // expected-warning {{'bzero' call operates on objects of type 'S' while the size is based on a different type 'S *'}} expected-note{{did you mean to dereference the argument to 'sizeof' (and multiply it by the number of elements)?}} |
55 | bzero(ps2, sizeof(ps2)); // \ |
56 | // expected-warning {{'bzero' call operates on objects of type 'S' while the size is based on a different type 'PS' (aka 'S *')}} expected-note{{did you mean to dereference the argument to 'sizeof' (and multiply it by the number of elements)?}} |
57 | bzero(ps2, sizeof(typeof(ps2))); // \ |
58 | // expected-warning {{argument to 'sizeof' in 'bzero' call is the same pointer type}} |
59 | bzero(ps2, sizeof(PS)); // \ |
60 | // expected-warning {{argument to 'sizeof' in 'bzero' call is the same pointer type}} |
61 | bzero(heap_buffer, sizeof(heap_buffer)); // \ |
62 | // expected-warning {{'bzero' call operates on objects of type 'char' while the size is based on a different type 'char *'}} expected-note{{did you mean to provide an explicit length?}} |
63 | |
64 | memcpy(&s, 0, sizeof(&s)); // \ |
65 | // expected-warning {{'memcpy' call operates on objects of type 'S' while the size is based on a different type 'S *'}} expected-note{{did you mean to remove the addressof in the argument to 'sizeof' (and multiply it by the number of elements)?}} |
66 | memcpy(0, &s, sizeof(&s)); // \ |
67 | // expected-warning {{'memcpy' call operates on objects of type 'S' while the size is based on a different type 'S *'}} expected-note{{did you mean to remove the addressof in the argument to 'sizeof' (and multiply it by the number of elements)?}} |
68 | |
69 | memmove(ps, 0, sizeof(ps)); // \ |
70 | // expected-warning {{'memmove' call operates on objects of type 'S' while the size is based on a different type 'S *'}} expected-note{{did you mean to dereference the argument to 'sizeof' (and multiply it by the number of elements)?}} |
71 | memcmp(ps, 0, sizeof(ps)); // \ |
72 | // expected-warning {{'memcmp' call operates on objects of type 'S' while the size is based on a different type 'S *'}} expected-note{{did you mean to dereference the argument to 'sizeof' (and multiply it by the number of elements)?}} |
73 | |
74 | /* Shouldn't warn */ |
75 | memset((void*)&s, 0, sizeof(&s)); |
76 | memset(&s, 0, sizeof(s)); |
77 | memset(&s, 0, sizeof(S)); |
78 | memset(&s, 0, sizeof(const S)); |
79 | memset(&s, 0, sizeof(volatile S)); |
80 | memset(&s, 0, sizeof(volatile const S)); |
81 | memset(&foo, 0, sizeof(CFoo)); |
82 | memset(&foo, 0, sizeof(VFoo)); |
83 | memset(&foo, 0, sizeof(CVFoo)); |
84 | memset(ps, 0, sizeof(*ps)); |
85 | memset(ps2, 0, sizeof(*ps2)); |
86 | memset(ps2, 0, sizeof(typeof(*ps2))); |
87 | memset(arr, 0, sizeof(arr)); |
88 | memset(parr, 0, sizeof(parr)); |
89 | |
90 | bzero((void*)&s, sizeof(&s)); |
91 | bzero(&s, sizeof(s)); |
92 | bzero(&s, sizeof(S)); |
93 | bzero(&s, sizeof(const S)); |
94 | bzero(&s, sizeof(volatile S)); |
95 | bzero(&s, sizeof(volatile const S)); |
96 | bzero(&foo, sizeof(CFoo)); |
97 | bzero(&foo, sizeof(VFoo)); |
98 | bzero(&foo, sizeof(CVFoo)); |
99 | bzero(ps, sizeof(*ps)); |
100 | bzero(ps2, sizeof(*ps2)); |
101 | bzero(ps2, sizeof(typeof(*ps2))); |
102 | bzero(arr, sizeof(arr)); |
103 | bzero(parr, sizeof(parr)); |
104 | |
105 | memcpy(&foo, &const_foo, sizeof(Foo)); |
106 | memcpy((void*)&s, 0, sizeof(&s)); |
107 | memcpy(0, (void*)&s, sizeof(&s)); |
108 | char *cptr; |
109 | memcpy(&cptr, buffer, sizeof(cptr)); |
110 | memcpy((char*)&cptr, buffer, sizeof(cptr)); |
111 | |
112 | CFooRef cfoo = foo; |
113 | memcpy(&foo, &cfoo, sizeof(Foo)); |
114 | |
115 | memcpy(0, &arr, sizeof(arr)); |
116 | typedef char Buff[8]; |
117 | memcpy(0, &arr, sizeof(Buff)); |
118 | |
119 | unsigned char* puc; |
120 | bit_cast<char*>(puc); |
121 | |
122 | float* pf; |
123 | bit_cast<int*>(pf); |
124 | |
125 | int iarr[14]; |
126 | memset(&iarr[0], 0, sizeof iarr); |
127 | memset(iarr, 0, sizeof iarr); |
128 | bzero(&iarr[0], sizeof iarr); |
129 | bzero(iarr, sizeof iarr); |
130 | |
131 | int* iparr[14]; |
132 | memset(&iparr[0], 0, sizeof iparr); |
133 | memset(iparr, 0, sizeof iparr); |
134 | bzero(&iparr[0], sizeof iparr); |
135 | bzero(iparr, sizeof iparr); |
136 | |
137 | memset(m, 0, sizeof(Mat)); |
138 | bzero(m, sizeof(Mat)); |
139 | |
140 | // Copy to raw buffer shouldn't warn either |
141 | memcpy(&foo, &arr, sizeof(Foo)); |
142 | memcpy(&arr, &foo, sizeof(Foo)); |
143 | |
144 | // Shouldn't warn, and shouldn't crash either. |
145 | memset(({ |
146 | if (0) {} |
147 | while (0) {} |
148 | for (;;) {} |
149 | &s; |
150 | }), 0, sizeof(s)); |
151 | |
152 | bzero(({ |
153 | if (0) {} |
154 | while (0) {} |
155 | for (;;) {} |
156 | &s; |
157 | }), sizeof(s)); |
158 | } |
159 | |
160 | namespace ns { |
161 | void memset(void* s, char c, int n); |
162 | void bzero(void* s, int n); |
163 | void f(int* i) { |
164 | memset(i, 0, sizeof(i)); |
165 | bzero(i, sizeof(i)); |
166 | } |
167 | } |
168 | |
169 | extern "C" int strncmp(const char *s1, const char *s2, unsigned n); |
170 | extern "C" int strncasecmp(const char *s1, const char *s2, unsigned n); |
171 | extern "C" char *strncpy(char *det, const char *src, unsigned n); |
172 | extern "C" char *strncat(char *dst, const char *src, unsigned n); |
173 | extern "C" char *strndup(const char *src, unsigned n); |
174 | |
175 | void strcpy_and_friends() { |
176 | const char* FOO = "<- should be an array instead"; |
177 | const char* BAR = "<- this, too"; |
178 | |
179 | strncmp(FOO, BAR, sizeof(FOO)); // \ |
180 | // expected-warning {{'strncmp' call operates on objects of type 'const char' while the size is based on a different type 'const char *'}} expected-note{{did you mean to provide an explicit length?}} |
181 | strncasecmp(FOO, BAR, sizeof(FOO)); // \ |
182 | // expected-warning {{'strncasecmp' call operates on objects of type 'const char' while the size is based on a different type 'const char *'}} expected-note{{did you mean to provide an explicit length?}} |
183 | |
184 | char buff[80]; |
185 | |
186 | strncpy(buff, BAR, sizeof(BAR)); // \ |
187 | // expected-warning {{'strncpy' call operates on objects of type 'const char' while the size is based on a different type 'const char *'}} expected-note{{did you mean to provide an explicit length?}} |
188 | strndup(FOO, sizeof(FOO)); // \ |
189 | // expected-warning {{'strndup' call operates on objects of type 'const char' while the size is based on a different type 'const char *'}} expected-note{{did you mean to provide an explicit length?}} |
190 | } |
191 | |