xref: /llvm-project/clang/test/SemaCXX/warn-memset-bad-sizeof.cpp (revision 8b9e5a72cb1219d40ef12e319ac2d835a8b19ee9)
1 // RUN: %clang_cc1 -fsyntax-only -verify -Wno-sizeof-array-argument %s
2 //
3 extern "C" void *memset(void *, int, unsigned);
4 extern "C" void *memmove(void *s1, const void *s2, unsigned n);
5 extern "C" void *memcpy(void *s1, const void *s2, unsigned n);
6 
7 struct S {int a, b, c, d;};
8 typedef S* PS;
9 
10 struct Foo {};
11 typedef const Foo& CFooRef;
12 typedef const Foo CFoo;
13 typedef volatile Foo VFoo;
14 typedef const volatile Foo CVFoo;
15 
16 typedef double Mat[4][4];
17 
18 template <class Dest, class Source>
19 inline Dest bit_cast(const Source& source) {
20   Dest dest;
21   memcpy(&dest, &source, sizeof(dest));
22   return dest;
23 }
24 
25 // http://www.lysator.liu.se/c/c-faq/c-2.html#2-6
26 void f(Mat m, const Foo& const_foo, char *buffer) {
27   S s;
28   S* ps = &s;
29   PS ps2 = &s;
30   char arr[5];
31   char* parr[5];
32   Foo foo;
33   char* heap_buffer = new char[42];
34 
35   /* Should warn */
36   memset(&s, 0, sizeof(&s));  // \
37       // expected-warning {{argument to 'sizeof' in 'memset' call is the same expression as the destination}}
38   memset(ps, 0, sizeof(ps));  // \
39       // expected-warning {{argument to 'sizeof' in 'memset' call is the same expression as the destination}}
40   memset(ps2, 0, sizeof(ps2));  // \
41       // expected-warning {{argument to 'sizeof' in 'memset' call is the same expression as the destination}}
42   memset(ps2, 0, sizeof(typeof(ps2)));  // \
43       // expected-warning {{argument to 'sizeof' in 'memset' call is the same pointer type}}
44   memset(ps2, 0, sizeof(PS));  // \
45       // expected-warning {{argument to 'sizeof' in 'memset' call is the same pointer type}}
46   memset(heap_buffer, 0, sizeof(heap_buffer));  // \
47       // expected-warning {{argument to 'sizeof' in 'memset' call is the same expression as the destination}}
48 
49   memcpy(&s, 0, sizeof(&s));  // \
50       // expected-warning {{argument to 'sizeof' in 'memcpy' call is the same expression as the destination}}
51   memcpy(0, &s, sizeof(&s));  // \
52       // expected-warning {{argument to 'sizeof' in 'memcpy' call is the same expression as the source}}
53 
54   /* Shouldn't warn */
55   memset((void*)&s, 0, sizeof(&s));
56   memset(&s, 0, sizeof(s));
57   memset(&s, 0, sizeof(S));
58   memset(&s, 0, sizeof(const S));
59   memset(&s, 0, sizeof(volatile S));
60   memset(&s, 0, sizeof(volatile const S));
61   memset(&foo, 0, sizeof(CFoo));
62   memset(&foo, 0, sizeof(VFoo));
63   memset(&foo, 0, sizeof(CVFoo));
64   memset(ps, 0, sizeof(*ps));
65   memset(ps2, 0, sizeof(*ps2));
66   memset(ps2, 0, sizeof(typeof(*ps2)));
67   memset(arr, 0, sizeof(arr));
68   memset(parr, 0, sizeof(parr));
69 
70   memcpy(&foo, &const_foo, sizeof(Foo));
71   memcpy((void*)&s, 0, sizeof(&s));
72   memcpy(0, (void*)&s, sizeof(&s));
73   char *cptr;
74   memcpy(&cptr, buffer, sizeof(cptr));
75   memcpy((char*)&cptr, buffer, sizeof(cptr));
76 
77   CFooRef cfoo = foo;
78   memcpy(&foo, &cfoo, sizeof(Foo));
79 
80   memcpy(0, &arr, sizeof(arr));
81   typedef char Buff[8];
82   memcpy(0, &arr, sizeof(Buff));
83 
84   unsigned char* puc;
85   bit_cast<char*>(puc);
86 
87   float* pf;
88   bit_cast<int*>(pf);
89 
90   int iarr[14];
91   memset(&iarr[0], 0, sizeof iarr);
92 
93   int* iparr[14];
94   memset(&iparr[0], 0, sizeof iparr);
95 
96   memset(m, 0, sizeof(Mat));
97 
98   // Copy to raw buffer shouldn't warn either
99   memcpy(&foo, &arr, sizeof(Foo));
100   memcpy(&arr, &foo, sizeof(Foo));
101 }
102