1 // RUN: %clang_cc1 -fsyntax-only -Wdynamic-class-memaccess -verify %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 extern "C" void *memcmp(void *s1, const void *s2, unsigned n);
7 
8 
9 // Redeclare without the extern "C" to test that we still figure out that this
10 // is the "real" memset.
11 void *memset(void *, int, unsigned);
12 
13 // Several types that should not warn.
14 struct S1 {} s1;
15 struct S2 { int x; } s2;
16 struct S3 { float x, y; S1 s[4]; void (*f)(S1**); } s3;
17 
18 class C1 {
19   int x, y, z;
20 public:
21   void foo() {}
22 } c1;
23 
24 struct X1 { virtual void f(); } x1;
25 struct X2 : virtual S1 {} x2;
26 
27 void test_warn() {
28   memset(&x1, 0, sizeof x1); // \
29       // expected-warning {{destination for this 'memset' call is a pointer to dynamic class}} \
30       // expected-note {{explicitly cast the pointer to silence this warning}}
31   memset(&x2, 0, sizeof x2); // \
32       // expected-warning {{destination for this 'memset' call is a pointer to dynamic class}} \
33       // expected-note {{explicitly cast the pointer to silence this warning}}
34 
35   memmove(&x1, 0, sizeof x1); // \
36       // expected-warning{{destination for this 'memmove' call is a pointer to dynamic class 'struct X1'; vtable pointer will be overwritten}} \
37       // expected-note {{explicitly cast the pointer to silence this warning}}
38   memmove(0, &x1, sizeof x1); // \
39       // expected-warning{{source of this 'memmove' call is a pointer to dynamic class 'struct X1'; vtable pointer will be moved}} \
40       // expected-note {{explicitly cast the pointer to silence this warning}}
41   memcpy(&x1, 0, sizeof x1); // \
42       // expected-warning{{destination for this 'memcpy' call is a pointer to dynamic class 'struct X1'; vtable pointer will be overwritten}} \
43       // expected-note {{explicitly cast the pointer to silence this warning}}
44   memcpy(0, &x1, sizeof x1); // \
45       // expected-warning{{source of this 'memcpy' call is a pointer to dynamic class 'struct X1'; vtable pointer will be copied}} \
46       // expected-note {{explicitly cast the pointer to silence this warning}}
47   memcmp(&x1, 0, sizeof x1); // \
48       // expected-warning{{first operand of this 'memcmp' call is a pointer to dynamic class 'struct X1'; vtable pointer will be compared}} \
49       // expected-note {{explicitly cast the pointer to silence this warning}}
50   memcmp(0, &x1, sizeof x1); // \
51       // expected-warning{{second operand of this 'memcmp' call is a pointer to dynamic class 'struct X1'; vtable pointer will be compared}} \
52       // expected-note {{explicitly cast the pointer to silence this warning}}
53 
54   __builtin_memset(&x1, 0, sizeof x1); // \
55       // expected-warning {{destination for this '__builtin_memset' call is a pointer to dynamic class}} \
56       // expected-note {{explicitly cast the pointer to silence this warning}}
57   __builtin_memset(&x2, 0, sizeof x2); // \
58       // expected-warning {{destination for this '__builtin_memset' call is a pointer to dynamic class}} \
59       // expected-note {{explicitly cast the pointer to silence this warning}}
60 
61   __builtin_memmove(&x1, 0, sizeof x1); // \
62       // expected-warning{{destination for this '__builtin_memmove' call is a pointer to dynamic class}} \
63       // expected-note {{explicitly cast the pointer to silence this warning}}
64   __builtin_memmove(0, &x1, sizeof x1); // \
65       // expected-warning{{source of this '__builtin_memmove' call is a pointer to dynamic class}} \
66       // expected-note {{explicitly cast the pointer to silence this warning}}
67   __builtin_memcpy(&x1, 0, sizeof x1); // \
68       // expected-warning{{destination for this '__builtin_memcpy' call is a pointer to dynamic class}} \
69       // expected-note {{explicitly cast the pointer to silence this warning}}
70   __builtin_memcpy(0, &x1, sizeof x1); // \
71       // expected-warning{{source of this '__builtin_memcpy' call is a pointer to dynamic class}} \
72       // expected-note {{explicitly cast the pointer to silence this warning}}
73 
74   __builtin___memset_chk(&x1, 0, sizeof x1, sizeof x1); //                    \
75       // expected-warning {{destination for this '__builtin___memset_chk' call is a pointer to dynamic class}} \
76       // expected-note {{explicitly cast the pointer to silence this warning}}
77   __builtin___memset_chk(&x2, 0, sizeof x2, sizeof x2); //                    \
78       // expected-warning {{destination for this '__builtin___memset_chk' call is a pointer to dynamic class}} \
79       // expected-note {{explicitly cast the pointer to silence this warning}}
80 
81   __builtin___memmove_chk(&x1, 0, sizeof x1, sizeof x1); //                   \
82       // expected-warning{{destination for this '__builtin___memmove_chk' call is a pointer to dynamic class}} \
83       // expected-note {{explicitly cast the pointer to silence this warning}}
84   __builtin___memmove_chk(0, &x1, sizeof x1, sizeof x1); //                   \
85       // expected-warning{{source of this '__builtin___memmove_chk' call is a pointer to dynamic class}} \
86       // expected-note {{explicitly cast the pointer to silence this warning}}
87   __builtin___memcpy_chk(&x1, 0, sizeof x1, sizeof x1); //                    \
88       // expected-warning{{destination for this '__builtin___memcpy_chk' call is a pointer to dynamic class}} \
89       // expected-note {{explicitly cast the pointer to silence this warning}}
90   __builtin___memcpy_chk(0, &x1, sizeof x1, sizeof x1); //                    \
91       // expected-warning{{source of this '__builtin___memcpy_chk' call is a pointer to dynamic class}} \
92       // expected-note {{explicitly cast the pointer to silence this warning}}
93 }
94 
95 void test_nowarn(void *void_ptr) {
96   int i, *iptr;
97   float y;
98   char c;
99 
100   memset(&i, 0, sizeof i);
101   memset(&iptr, 0, sizeof iptr);
102   memset(&y, 0, sizeof y);
103   memset(&c, 0, sizeof c);
104   memset(void_ptr, 0, 42);
105   memset(&s1, 0, sizeof s1);
106   memset(&s2, 0, sizeof s2);
107   memset(&s3, 0, sizeof s3);
108   memset(&c1, 0, sizeof c1);
109 
110   // Unevaluated code shouldn't warn.
111   (void)sizeof memset(&x1, 0, sizeof x1);
112 
113   // Dead code shouldn't warn.
114   if (false) memset(&x1, 0, sizeof x1);
115 }
116 
117 namespace N {
118   void *memset(void *, int, unsigned);
119   void test_nowarn() {
120     N::memset(&x1, 0, sizeof x1);
121   }
122 }
123