xref: /llvm-project/clang/test/SemaCXX/warn-memset-bad-sizeof.cpp (revision 50340d5c87b51bfc14a368002c442897bba39d36)
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(char fake_array[8], Mat m, const Foo& const_foo) {
27   S s;
28   S* ps = &s;
29   PS ps2 = &s;
30   char arr[5];
31   char* parr[5];
32   Foo foo;
33 
34   /* Should warn */
35   memset(&s, 0, sizeof(&s));  // \
36       // expected-warning {{the argument to sizeof is pointer type 'S *', expected 'S' to match first argument to 'memset'}}
37   memset(ps, 0, sizeof(ps));  // \
38       // expected-warning {{the argument to sizeof is pointer type 'S *', expected 'S' to match first argument to 'memset'}}
39   memset(ps2, 0, sizeof(ps2));  // \
40       // expected-warning {{the argument to sizeof is pointer type 'PS' (aka 'S *'), expected 'S' to match first argument to 'memset'}}
41   memset(ps2, 0, sizeof(typeof(ps2)));  // \
42       // expected-warning {{the argument to sizeof is pointer type 'typeof (ps2)' (aka 'S *'), expected 'S' to match first argument to 'memset'}}
43   memset(ps2, 0, sizeof(PS));  // \
44       // expected-warning {{the argument to sizeof is pointer type 'PS' (aka 'S *'), expected 'S' to match first argument to 'memset'}}
45   memset(fake_array, 0, sizeof(fake_array));  // \
46       // expected-warning {{the argument to sizeof is pointer type 'char *', expected 'char' to match first argument to 'memset'}}
47 
48   memcpy(&s, 0, sizeof(&s));  // \
49       // expected-warning {{the argument to sizeof is pointer type 'S *', expected 'S' to match first argument to 'memcpy'}}
50   memcpy(0, &s, sizeof(&s));  // \
51       // expected-warning {{the argument to sizeof is pointer type 'S *', expected 'S' to match second argument to 'memcpy'}}
52 
53   /* Shouldn't warn */
54   memset((void*)&s, 0, sizeof(&s));
55   memset(&s, 0, sizeof(s));
56   memset(&s, 0, sizeof(S));
57   memset(&s, 0, sizeof(const S));
58   memset(&s, 0, sizeof(volatile S));
59   memset(&s, 0, sizeof(volatile const S));
60   memset(&foo, 0, sizeof(CFoo));
61   memset(&foo, 0, sizeof(VFoo));
62   memset(&foo, 0, sizeof(CVFoo));
63   memset(ps, 0, sizeof(*ps));
64   memset(ps2, 0, sizeof(*ps2));
65   memset(ps2, 0, sizeof(typeof(*ps2)));
66   memset(arr, 0, sizeof(arr));
67   memset(parr, 0, sizeof(parr));
68 
69   memcpy(&foo, &const_foo, sizeof(Foo));
70   memcpy((void*)&s, 0, sizeof(&s));
71   memcpy(0, (void*)&s, sizeof(&s));
72 
73   CFooRef cfoo = foo;
74   memcpy(&foo, &cfoo, sizeof(Foo));
75 
76   memcpy(0, &arr, sizeof(arr));
77   typedef char Buff[8];
78   memcpy(0, &arr, sizeof(Buff));
79 
80   unsigned char* puc;
81   bit_cast<char*>(puc);
82 
83   float* pf;
84   bit_cast<int*>(pf);
85 
86   int iarr[14];
87   memset(&iarr[0], 0, sizeof iarr);
88 
89   int* iparr[14];
90   memset(&iparr[0], 0, sizeof iparr);
91 
92   memset(m, 0, sizeof(Mat));
93 
94   // Copy to raw buffer shouldn't warn either
95   memcpy(&foo, &arr, sizeof(Foo));
96   memcpy(&arr, &foo, sizeof(Foo));
97 }
98