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