xref: /aosp_15_r20/external/clang/test/SemaCXX/warn-bad-memaccess.cpp (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li // RUN: %clang_cc1 -fsyntax-only -Wdynamic-class-memaccess -verify %s
2*67e74705SXin Li 
3*67e74705SXin Li extern "C" void *memset(void *, int, unsigned);
4*67e74705SXin Li extern "C" void *memmove(void *s1, const void *s2, unsigned n);
5*67e74705SXin Li extern "C" void *memcpy(void *s1, const void *s2, unsigned n);
6*67e74705SXin Li extern "C" void *memcmp(void *s1, const void *s2, unsigned n);
7*67e74705SXin Li 
8*67e74705SXin Li 
9*67e74705SXin Li // Redeclare without the extern "C" to test that we still figure out that this
10*67e74705SXin Li // is the "real" memset.
11*67e74705SXin Li void *memset(void *, int, unsigned);
12*67e74705SXin Li 
13*67e74705SXin Li // Several types that should not warn.
14*67e74705SXin Li struct S1 {} s1;
15*67e74705SXin Li struct S2 { int x; } s2;
16*67e74705SXin Li struct S3 { float x, y; S1 s[4]; void (*f)(S1**); } s3;
17*67e74705SXin Li 
18*67e74705SXin Li class C1 {
19*67e74705SXin Li   int x, y, z;
20*67e74705SXin Li public:
foo()21*67e74705SXin Li   void foo() {}
22*67e74705SXin Li } c1;
23*67e74705SXin Li 
24*67e74705SXin Li struct X1 { virtual void f(); } x1, x1arr[2];
25*67e74705SXin Li struct X2 : virtual S1 {} x2;
26*67e74705SXin Li 
27*67e74705SXin Li struct ContainsDynamic { X1 dynamic; } contains_dynamic;
28*67e74705SXin Li struct DeepContainsDynamic { ContainsDynamic m; } deep_contains_dynamic;
29*67e74705SXin Li struct ContainsArrayDynamic { X1 dynamic[1]; } contains_array_dynamic;
30*67e74705SXin Li struct ContainsPointerDynamic { X1 *dynamic; } contains_pointer_dynamic;
31*67e74705SXin Li 
test_warn()32*67e74705SXin Li void test_warn() {
33*67e74705SXin Li   memset(&x1, 0, sizeof x1); // \
34*67e74705SXin Li       // expected-warning {{destination for this 'memset' call is a pointer to dynamic class}} \
35*67e74705SXin Li       // expected-note {{explicitly cast the pointer to silence this warning}}
36*67e74705SXin Li   memset(x1arr, 0, sizeof x1arr); // \
37*67e74705SXin Li       // expected-warning {{destination for this 'memset' call is a pointer to dynamic class}} \
38*67e74705SXin Li       // expected-note {{explicitly cast the pointer to silence this warning}}
39*67e74705SXin Li   memset((void*)x1arr, 0, sizeof x1arr);
40*67e74705SXin Li   memset(&x2, 0, sizeof x2); // \
41*67e74705SXin Li       // expected-warning {{destination for this 'memset' call is a pointer to dynamic class}} \
42*67e74705SXin Li       // expected-note {{explicitly cast the pointer to silence this warning}}
43*67e74705SXin Li 
44*67e74705SXin Li   memmove(&x1, 0, sizeof x1); // \
45*67e74705SXin Li       // expected-warning{{destination for this 'memmove' call is a pointer to dynamic class 'X1'; vtable pointer will be overwritten}} \
46*67e74705SXin Li       // expected-note {{explicitly cast the pointer to silence this warning}}
47*67e74705SXin Li   memmove(0, &x1, sizeof x1); // \
48*67e74705SXin Li       // expected-warning{{source of this 'memmove' call is a pointer to dynamic class 'X1'; vtable pointer will be moved}} \
49*67e74705SXin Li       // expected-note {{explicitly cast the pointer to silence this warning}}
50*67e74705SXin Li   memcpy(&x1, 0, sizeof x1); // \
51*67e74705SXin Li       // expected-warning{{destination for this 'memcpy' call is a pointer to dynamic class 'X1'; vtable pointer will be overwritten}} \
52*67e74705SXin Li       // expected-note {{explicitly cast the pointer to silence this warning}}
53*67e74705SXin Li   memcpy(0, &x1, sizeof x1); // \
54*67e74705SXin Li       // expected-warning{{source of this 'memcpy' call is a pointer to dynamic class 'X1'; vtable pointer will be copied}} \
55*67e74705SXin Li       // expected-note {{explicitly cast the pointer to silence this warning}}
56*67e74705SXin Li   memcmp(&x1, 0, sizeof x1); // \
57*67e74705SXin Li       // expected-warning{{first operand of this 'memcmp' call is a pointer to dynamic class 'X1'; vtable pointer will be compared}} \
58*67e74705SXin Li       // expected-note {{explicitly cast the pointer to silence this warning}}
59*67e74705SXin Li   memcmp(0, &x1, sizeof x1); // \
60*67e74705SXin Li       // expected-warning{{second operand of this 'memcmp' call is a pointer to dynamic class 'X1'; vtable pointer will be compared}} \
61*67e74705SXin Li       // expected-note {{explicitly cast the pointer to silence this warning}}
62*67e74705SXin Li 
63*67e74705SXin Li   __builtin_memset(&x1, 0, sizeof x1); // \
64*67e74705SXin Li       // expected-warning {{destination for this '__builtin_memset' call is a pointer to dynamic class}} \
65*67e74705SXin Li       // expected-note {{explicitly cast the pointer to silence this warning}}
66*67e74705SXin Li   __builtin_memset(&x2, 0, sizeof x2); // \
67*67e74705SXin Li       // expected-warning {{destination for this '__builtin_memset' call is a pointer to dynamic class}} \
68*67e74705SXin Li       // expected-note {{explicitly cast the pointer to silence this warning}}
69*67e74705SXin Li 
70*67e74705SXin Li   __builtin_memmove(&x1, 0, sizeof x1); // \
71*67e74705SXin Li       // expected-warning{{destination for this '__builtin_memmove' call is a pointer to dynamic class}} \
72*67e74705SXin Li       // expected-note {{explicitly cast the pointer to silence this warning}}
73*67e74705SXin Li   __builtin_memmove(0, &x1, sizeof x1); // \
74*67e74705SXin Li       // expected-warning{{source of this '__builtin_memmove' call is a pointer to dynamic class}} \
75*67e74705SXin Li       // expected-note {{explicitly cast the pointer to silence this warning}}
76*67e74705SXin Li   __builtin_memcpy(&x1, 0, sizeof x1); // \
77*67e74705SXin Li       // expected-warning{{destination for this '__builtin_memcpy' call is a pointer to dynamic class}} \
78*67e74705SXin Li       // expected-note {{explicitly cast the pointer to silence this warning}}
79*67e74705SXin Li   __builtin_memcpy(0, &x1, sizeof x1); // \
80*67e74705SXin Li       // expected-warning{{source of this '__builtin_memcpy' call is a pointer to dynamic class}} \
81*67e74705SXin Li       // expected-note {{explicitly cast the pointer to silence this warning}}
82*67e74705SXin Li 
83*67e74705SXin Li   __builtin___memset_chk(&x1, 0, sizeof x1, sizeof x1); //                    \
84*67e74705SXin Li       // expected-warning {{destination for this '__builtin___memset_chk' call is a pointer to dynamic class}} \
85*67e74705SXin Li       // expected-note {{explicitly cast the pointer to silence this warning}}
86*67e74705SXin Li   __builtin___memset_chk(&x2, 0, sizeof x2, sizeof x2); //                    \
87*67e74705SXin Li       // expected-warning {{destination for this '__builtin___memset_chk' call is a pointer to dynamic class}} \
88*67e74705SXin Li       // expected-note {{explicitly cast the pointer to silence this warning}}
89*67e74705SXin Li 
90*67e74705SXin Li   __builtin___memmove_chk(&x1, 0, sizeof x1, sizeof x1); //                   \
91*67e74705SXin Li       // expected-warning{{destination for this '__builtin___memmove_chk' call is a pointer to dynamic class}} \
92*67e74705SXin Li       // expected-note {{explicitly cast the pointer to silence this warning}}
93*67e74705SXin Li   __builtin___memmove_chk(0, &x1, sizeof x1, sizeof x1); //                   \
94*67e74705SXin Li       // expected-warning{{source of this '__builtin___memmove_chk' call is a pointer to dynamic class}} \
95*67e74705SXin Li       // expected-note {{explicitly cast the pointer to silence this warning}}
96*67e74705SXin Li   __builtin___memcpy_chk(&x1, 0, sizeof x1, sizeof x1); //                    \
97*67e74705SXin Li       // expected-warning{{destination for this '__builtin___memcpy_chk' call is a pointer to dynamic class}} \
98*67e74705SXin Li       // expected-note {{explicitly cast the pointer to silence this warning}}
99*67e74705SXin Li   __builtin___memcpy_chk(0, &x1, sizeof x1, sizeof x1); //                    \
100*67e74705SXin Li       // expected-warning{{source of this '__builtin___memcpy_chk' call is a pointer to dynamic class}} \
101*67e74705SXin Li       // expected-note {{explicitly cast the pointer to silence this warning}}
102*67e74705SXin Li 
103*67e74705SXin Li   // expected-warning@+2 {{destination for this 'memset' call is a pointer to class containing a dynamic class 'X1'}}
104*67e74705SXin Li   // expected-note@+1 {{explicitly cast the pointer to silence this warning}}
105*67e74705SXin Li   memset(&contains_dynamic, 0, sizeof(contains_dynamic));
106*67e74705SXin Li   // expected-warning@+2 {{destination for this 'memset' call is a pointer to class containing a dynamic class 'X1'}}
107*67e74705SXin Li   // expected-note@+1 {{explicitly cast the pointer to silence this warning}}
108*67e74705SXin Li   memset(&deep_contains_dynamic, 0, sizeof(deep_contains_dynamic));
109*67e74705SXin Li   // expected-warning@+2 {{destination for this 'memset' call is a pointer to class containing a dynamic class 'X1'}}
110*67e74705SXin Li   // expected-note@+1 {{explicitly cast the pointer to silence this warning}}
111*67e74705SXin Li   memset(&contains_array_dynamic, 0, sizeof(contains_array_dynamic));
112*67e74705SXin Li }
113*67e74705SXin Li 
test_nowarn(void * void_ptr)114*67e74705SXin Li void test_nowarn(void *void_ptr) {
115*67e74705SXin Li   int i, *iptr;
116*67e74705SXin Li   float y;
117*67e74705SXin Li   char c;
118*67e74705SXin Li 
119*67e74705SXin Li   memset(&i, 0, sizeof i);
120*67e74705SXin Li   memset(&iptr, 0, sizeof iptr);
121*67e74705SXin Li   memset(&y, 0, sizeof y);
122*67e74705SXin Li   memset(&c, 0, sizeof c);
123*67e74705SXin Li   memset(void_ptr, 0, 42);
124*67e74705SXin Li   memset(&s1, 0, sizeof s1);
125*67e74705SXin Li   memset(&s2, 0, sizeof s2);
126*67e74705SXin Li   memset(&s3, 0, sizeof s3);
127*67e74705SXin Li   memset(&c1, 0, sizeof c1);
128*67e74705SXin Li 
129*67e74705SXin Li   memset(&contains_pointer_dynamic, 0, sizeof(contains_pointer_dynamic));
130*67e74705SXin Li 
131*67e74705SXin Li   // Unevaluated code shouldn't warn.
132*67e74705SXin Li   (void)sizeof memset(&x1, 0, sizeof x1);
133*67e74705SXin Li 
134*67e74705SXin Li   // Dead code shouldn't warn.
135*67e74705SXin Li   if (false) memset(&x1, 0, sizeof x1);
136*67e74705SXin Li }
137*67e74705SXin Li 
138*67e74705SXin Li namespace N {
139*67e74705SXin Li   void *memset(void *, int, unsigned);
test_nowarn()140*67e74705SXin Li   void test_nowarn() {
141*67e74705SXin Li     N::memset(&x1, 0, sizeof x1);
142*67e74705SXin Li   }
143*67e74705SXin Li }
144*67e74705SXin Li 
145*67e74705SXin Li namespace recursive_class {
146*67e74705SXin Li struct S {
147*67e74705SXin Li   S v;
148*67e74705SXin Li   // expected-error@-1{{field has incomplete type 'recursive_class::S'}}
149*67e74705SXin Li   // expected-note@-3{{definition of 'recursive_class::S' is not complete until the closing '}'}}
150*67e74705SXin Li } a;
151*67e74705SXin Li 
main()152*67e74705SXin Li int main() {
153*67e74705SXin Li   __builtin_memset(&a, 0, sizeof a);
154*67e74705SXin Li   return 0;
155*67e74705SXin Li }
156*67e74705SXin Li }
157