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