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 struct ContainsDynamic { X1 dynamic; } contains_dynamic; 28 struct DeepContainsDynamic { ContainsDynamic m; } deep_contains_dynamic; 29 struct ContainsArrayDynamic { X1 dynamic[1]; } contains_array_dynamic; 30 struct ContainsPointerDynamic { X1 *dynamic; } contains_pointer_dynamic; 31 32 void 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(&x2, 0, sizeof x2); // \ 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 40 memmove(&x1, 0, sizeof x1); // \ 41 // expected-warning{{destination for this 'memmove' call is a pointer to dynamic class 'X1'; vtable pointer will be overwritten}} \ 42 // expected-note {{explicitly cast the pointer to silence this warning}} 43 memmove(0, &x1, sizeof x1); // \ 44 // expected-warning{{source of this 'memmove' call is a pointer to dynamic class 'X1'; vtable pointer will be moved}} \ 45 // expected-note {{explicitly cast the pointer to silence this warning}} 46 memcpy(&x1, 0, sizeof x1); // \ 47 // expected-warning{{destination for this 'memcpy' call is a pointer to dynamic class 'X1'; vtable pointer will be overwritten}} \ 48 // expected-note {{explicitly cast the pointer to silence this warning}} 49 memcpy(0, &x1, sizeof x1); // \ 50 // expected-warning{{source of this 'memcpy' call is a pointer to dynamic class 'X1'; vtable pointer will be copied}} \ 51 // expected-note {{explicitly cast the pointer to silence this warning}} 52 memcmp(&x1, 0, sizeof x1); // \ 53 // expected-warning{{first operand of this 'memcmp' call is a pointer to dynamic class 'X1'; vtable pointer will be compared}} \ 54 // expected-note {{explicitly cast the pointer to silence this warning}} 55 memcmp(0, &x1, sizeof x1); // \ 56 // expected-warning{{second operand of this 'memcmp' call is a pointer to dynamic class 'X1'; vtable pointer will be compared}} \ 57 // expected-note {{explicitly cast the pointer to silence this warning}} 58 59 __builtin_memset(&x1, 0, sizeof x1); // \ 60 // expected-warning {{destination for this '__builtin_memset' call is a pointer to dynamic class}} \ 61 // expected-note {{explicitly cast the pointer to silence this warning}} 62 __builtin_memset(&x2, 0, sizeof x2); // \ 63 // expected-warning {{destination for this '__builtin_memset' call is a pointer to dynamic class}} \ 64 // expected-note {{explicitly cast the pointer to silence this warning}} 65 66 __builtin_memmove(&x1, 0, sizeof x1); // \ 67 // expected-warning{{destination for this '__builtin_memmove' call is a pointer to dynamic class}} \ 68 // expected-note {{explicitly cast the pointer to silence this warning}} 69 __builtin_memmove(0, &x1, sizeof x1); // \ 70 // expected-warning{{source of this '__builtin_memmove' call is a pointer to dynamic class}} \ 71 // expected-note {{explicitly cast the pointer to silence this warning}} 72 __builtin_memcpy(&x1, 0, sizeof x1); // \ 73 // expected-warning{{destination for this '__builtin_memcpy' call is a pointer to dynamic class}} \ 74 // expected-note {{explicitly cast the pointer to silence this warning}} 75 __builtin_memcpy(0, &x1, sizeof x1); // \ 76 // expected-warning{{source of this '__builtin_memcpy' call is a pointer to dynamic class}} \ 77 // expected-note {{explicitly cast the pointer to silence this warning}} 78 79 __builtin___memset_chk(&x1, 0, sizeof x1, sizeof x1); // \ 80 // expected-warning {{destination for this '__builtin___memset_chk' call is a pointer to dynamic class}} \ 81 // expected-note {{explicitly cast the pointer to silence this warning}} 82 __builtin___memset_chk(&x2, 0, sizeof x2, sizeof x2); // \ 83 // expected-warning {{destination for this '__builtin___memset_chk' call is a pointer to dynamic class}} \ 84 // expected-note {{explicitly cast the pointer to silence this warning}} 85 86 __builtin___memmove_chk(&x1, 0, sizeof x1, sizeof x1); // \ 87 // expected-warning{{destination for this '__builtin___memmove_chk' call is a pointer to dynamic class}} \ 88 // expected-note {{explicitly cast the pointer to silence this warning}} 89 __builtin___memmove_chk(0, &x1, sizeof x1, sizeof x1); // \ 90 // expected-warning{{source of this '__builtin___memmove_chk' call is a pointer to dynamic class}} \ 91 // expected-note {{explicitly cast the pointer to silence this warning}} 92 __builtin___memcpy_chk(&x1, 0, sizeof x1, sizeof x1); // \ 93 // expected-warning{{destination for this '__builtin___memcpy_chk' call is a pointer to dynamic class}} \ 94 // expected-note {{explicitly cast the pointer to silence this warning}} 95 __builtin___memcpy_chk(0, &x1, sizeof x1, sizeof x1); // \ 96 // expected-warning{{source of this '__builtin___memcpy_chk' call is a pointer to dynamic class}} \ 97 // expected-note {{explicitly cast the pointer to silence this warning}} 98 99 // expected-warning@+2 {{destination for this 'memset' call is a pointer to class containing a dynamic class 'X1'}} 100 // expected-note@+1 {{explicitly cast the pointer to silence this warning}} 101 memset(&contains_dynamic, 0, sizeof(contains_dynamic)); 102 // expected-warning@+2 {{destination for this 'memset' call is a pointer to class containing a dynamic class 'X1'}} 103 // expected-note@+1 {{explicitly cast the pointer to silence this warning}} 104 memset(&deep_contains_dynamic, 0, sizeof(deep_contains_dynamic)); 105 // expected-warning@+2 {{destination for this 'memset' call is a pointer to class containing a dynamic class 'X1'}} 106 // expected-note@+1 {{explicitly cast the pointer to silence this warning}} 107 memset(&contains_array_dynamic, 0, sizeof(contains_array_dynamic)); 108 } 109 110 void test_nowarn(void *void_ptr) { 111 int i, *iptr; 112 float y; 113 char c; 114 115 memset(&i, 0, sizeof i); 116 memset(&iptr, 0, sizeof iptr); 117 memset(&y, 0, sizeof y); 118 memset(&c, 0, sizeof c); 119 memset(void_ptr, 0, 42); 120 memset(&s1, 0, sizeof s1); 121 memset(&s2, 0, sizeof s2); 122 memset(&s3, 0, sizeof s3); 123 memset(&c1, 0, sizeof c1); 124 125 memset(&contains_pointer_dynamic, 0, sizeof(contains_pointer_dynamic)); 126 127 // Unevaluated code shouldn't warn. 128 (void)sizeof memset(&x1, 0, sizeof x1); 129 130 // Dead code shouldn't warn. 131 if (false) memset(&x1, 0, sizeof x1); 132 } 133 134 namespace N { 135 void *memset(void *, int, unsigned); 136 void test_nowarn() { 137 N::memset(&x1, 0, sizeof x1); 138 } 139 } 140