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