1929f0135ab60166202f52e0dd19835c0490d792aChandler Carruth// RUN: %clang_cc1 -fsyntax-only -Wdynamic-class-memaccess -verify %s
27ccc95bceebb2d1c8fbe277c9e33bde7dc1ccbb1Chandler Carruth
3e452c78072156c14cd9998733e3b4b28b6fc7fd7Douglas Gregorextern "C" void *memset(void *, int, unsigned);
406bc9eb9908e42696775b395b290827bde468c8bDouglas Gregorextern "C" void *memmove(void *s1, const void *s2, unsigned n);
506bc9eb9908e42696775b395b290827bde468c8bDouglas Gregorextern "C" void *memcpy(void *s1, const void *s2, unsigned n);
65c5218e188b39b2e93b541156a69ef061e11aab8Matt Beaumont-Gayextern "C" void *memcmp(void *s1, const void *s2, unsigned n);
77ccc95bceebb2d1c8fbe277c9e33bde7dc1ccbb1Chandler Carruth
89f0c692c4db9012248c65fab6cb703f2ce444dfeRafael Espindola
99f0c692c4db9012248c65fab6cb703f2ce444dfeRafael Espindola// Redeclare without the extern "C" to test that we still figure out that this
109f0c692c4db9012248c65fab6cb703f2ce444dfeRafael Espindola// is the "real" memset.
119f0c692c4db9012248c65fab6cb703f2ce444dfeRafael Espindolavoid *memset(void *, int, unsigned);
129f0c692c4db9012248c65fab6cb703f2ce444dfeRafael Espindola
13929f0135ab60166202f52e0dd19835c0490d792aChandler Carruth// Several types that should not warn.
147ccc95bceebb2d1c8fbe277c9e33bde7dc1ccbb1Chandler Carruthstruct S1 {} s1;
157ccc95bceebb2d1c8fbe277c9e33bde7dc1ccbb1Chandler Carruthstruct S2 { int x; } s2;
167ccc95bceebb2d1c8fbe277c9e33bde7dc1ccbb1Chandler Carruthstruct S3 { float x, y; S1 s[4]; void (*f)(S1**); } s3;
177ccc95bceebb2d1c8fbe277c9e33bde7dc1ccbb1Chandler Carruth
1843fa33b4bedc28d2faa17d678ad1f40eb42817a1Chandler Carruthclass C1 {
1943fa33b4bedc28d2faa17d678ad1f40eb42817a1Chandler Carruth  int x, y, z;
2043fa33b4bedc28d2faa17d678ad1f40eb42817a1Chandler Carruthpublic:
2143fa33b4bedc28d2faa17d678ad1f40eb42817a1Chandler Carruth  void foo() {}
2243fa33b4bedc28d2faa17d678ad1f40eb42817a1Chandler Carruth} c1;
2343fa33b4bedc28d2faa17d678ad1f40eb42817a1Chandler Carruth
24929f0135ab60166202f52e0dd19835c0490d792aChandler Carruthstruct X1 { virtual void f(); } x1;
25929f0135ab60166202f52e0dd19835c0490d792aChandler Carruthstruct X2 : virtual S1 {} x2;
267ccc95bceebb2d1c8fbe277c9e33bde7dc1ccbb1Chandler Carruth
27ef8225444452a1486bd721f3285301fe84643b00Stephen Hinesstruct ContainsDynamic { X1 dynamic; } contains_dynamic;
28ef8225444452a1486bd721f3285301fe84643b00Stephen Hinesstruct DeepContainsDynamic { ContainsDynamic m; } deep_contains_dynamic;
29ef8225444452a1486bd721f3285301fe84643b00Stephen Hinesstruct ContainsArrayDynamic { X1 dynamic[1]; } contains_array_dynamic;
30ef8225444452a1486bd721f3285301fe84643b00Stephen Hinesstruct ContainsPointerDynamic { X1 *dynamic; } contains_pointer_dynamic;
31ef8225444452a1486bd721f3285301fe84643b00Stephen Hines
327ccc95bceebb2d1c8fbe277c9e33bde7dc1ccbb1Chandler Carruthvoid test_warn() {
337ccc95bceebb2d1c8fbe277c9e33bde7dc1ccbb1Chandler Carruth  memset(&x1, 0, sizeof x1); // \
3406bc9eb9908e42696775b395b290827bde468c8bDouglas Gregor      // expected-warning {{destination for this 'memset' call is a pointer to dynamic class}} \
357ccc95bceebb2d1c8fbe277c9e33bde7dc1ccbb1Chandler Carruth      // expected-note {{explicitly cast the pointer to silence this warning}}
36929f0135ab60166202f52e0dd19835c0490d792aChandler Carruth  memset(&x2, 0, sizeof x2); // \
3706bc9eb9908e42696775b395b290827bde468c8bDouglas Gregor      // expected-warning {{destination for this 'memset' call is a pointer to dynamic class}} \
3806bc9eb9908e42696775b395b290827bde468c8bDouglas Gregor      // expected-note {{explicitly cast the pointer to silence this warning}}
3906bc9eb9908e42696775b395b290827bde468c8bDouglas Gregor
4006bc9eb9908e42696775b395b290827bde468c8bDouglas Gregor  memmove(&x1, 0, sizeof x1); // \
41ef8225444452a1486bd721f3285301fe84643b00Stephen Hines      // expected-warning{{destination for this 'memmove' call is a pointer to dynamic class 'X1'; vtable pointer will be overwritten}} \
4206bc9eb9908e42696775b395b290827bde468c8bDouglas Gregor      // expected-note {{explicitly cast the pointer to silence this warning}}
4306bc9eb9908e42696775b395b290827bde468c8bDouglas Gregor  memmove(0, &x1, sizeof x1); // \
44ef8225444452a1486bd721f3285301fe84643b00Stephen Hines      // expected-warning{{source of this 'memmove' call is a pointer to dynamic class 'X1'; vtable pointer will be moved}} \
4506bc9eb9908e42696775b395b290827bde468c8bDouglas Gregor      // expected-note {{explicitly cast the pointer to silence this warning}}
4606bc9eb9908e42696775b395b290827bde468c8bDouglas Gregor  memcpy(&x1, 0, sizeof x1); // \
47ef8225444452a1486bd721f3285301fe84643b00Stephen Hines      // expected-warning{{destination for this 'memcpy' call is a pointer to dynamic class 'X1'; vtable pointer will be overwritten}} \
4806bc9eb9908e42696775b395b290827bde468c8bDouglas Gregor      // expected-note {{explicitly cast the pointer to silence this warning}}
4906bc9eb9908e42696775b395b290827bde468c8bDouglas Gregor  memcpy(0, &x1, sizeof x1); // \
50ef8225444452a1486bd721f3285301fe84643b00Stephen Hines      // expected-warning{{source of this 'memcpy' call is a pointer to dynamic class 'X1'; vtable pointer will be copied}} \
515c5218e188b39b2e93b541156a69ef061e11aab8Matt Beaumont-Gay      // expected-note {{explicitly cast the pointer to silence this warning}}
525c5218e188b39b2e93b541156a69ef061e11aab8Matt Beaumont-Gay  memcmp(&x1, 0, sizeof x1); // \
53ef8225444452a1486bd721f3285301fe84643b00Stephen Hines      // expected-warning{{first operand of this 'memcmp' call is a pointer to dynamic class 'X1'; vtable pointer will be compared}} \
545c5218e188b39b2e93b541156a69ef061e11aab8Matt Beaumont-Gay      // expected-note {{explicitly cast the pointer to silence this warning}}
555c5218e188b39b2e93b541156a69ef061e11aab8Matt Beaumont-Gay  memcmp(0, &x1, sizeof x1); // \
56ef8225444452a1486bd721f3285301fe84643b00Stephen Hines      // expected-warning{{second operand of this 'memcmp' call is a pointer to dynamic class 'X1'; vtable pointer will be compared}} \
577ccc95bceebb2d1c8fbe277c9e33bde7dc1ccbb1Chandler Carruth      // expected-note {{explicitly cast the pointer to silence this warning}}
58707a23e8b87410332b55bb4534fa1c799edef38aDouglas Gregor
59707a23e8b87410332b55bb4534fa1c799edef38aDouglas Gregor  __builtin_memset(&x1, 0, sizeof x1); // \
60707a23e8b87410332b55bb4534fa1c799edef38aDouglas Gregor      // expected-warning {{destination for this '__builtin_memset' call is a pointer to dynamic class}} \
61707a23e8b87410332b55bb4534fa1c799edef38aDouglas Gregor      // expected-note {{explicitly cast the pointer to silence this warning}}
62707a23e8b87410332b55bb4534fa1c799edef38aDouglas Gregor  __builtin_memset(&x2, 0, sizeof x2); // \
63707a23e8b87410332b55bb4534fa1c799edef38aDouglas Gregor      // expected-warning {{destination for this '__builtin_memset' call is a pointer to dynamic class}} \
64707a23e8b87410332b55bb4534fa1c799edef38aDouglas Gregor      // expected-note {{explicitly cast the pointer to silence this warning}}
65707a23e8b87410332b55bb4534fa1c799edef38aDouglas Gregor
66707a23e8b87410332b55bb4534fa1c799edef38aDouglas Gregor  __builtin_memmove(&x1, 0, sizeof x1); // \
67707a23e8b87410332b55bb4534fa1c799edef38aDouglas Gregor      // expected-warning{{destination for this '__builtin_memmove' call is a pointer to dynamic class}} \
68707a23e8b87410332b55bb4534fa1c799edef38aDouglas Gregor      // expected-note {{explicitly cast the pointer to silence this warning}}
69707a23e8b87410332b55bb4534fa1c799edef38aDouglas Gregor  __builtin_memmove(0, &x1, sizeof x1); // \
70707a23e8b87410332b55bb4534fa1c799edef38aDouglas Gregor      // expected-warning{{source of this '__builtin_memmove' call is a pointer to dynamic class}} \
71707a23e8b87410332b55bb4534fa1c799edef38aDouglas Gregor      // expected-note {{explicitly cast the pointer to silence this warning}}
72707a23e8b87410332b55bb4534fa1c799edef38aDouglas Gregor  __builtin_memcpy(&x1, 0, sizeof x1); // \
73707a23e8b87410332b55bb4534fa1c799edef38aDouglas Gregor      // expected-warning{{destination for this '__builtin_memcpy' call is a pointer to dynamic class}} \
74707a23e8b87410332b55bb4534fa1c799edef38aDouglas Gregor      // expected-note {{explicitly cast the pointer to silence this warning}}
75707a23e8b87410332b55bb4534fa1c799edef38aDouglas Gregor  __builtin_memcpy(0, &x1, sizeof x1); // \
76707a23e8b87410332b55bb4534fa1c799edef38aDouglas Gregor      // expected-warning{{source of this '__builtin_memcpy' call is a pointer to dynamic class}} \
77707a23e8b87410332b55bb4534fa1c799edef38aDouglas Gregor      // expected-note {{explicitly cast the pointer to silence this warning}}
78707a23e8b87410332b55bb4534fa1c799edef38aDouglas Gregor
79707a23e8b87410332b55bb4534fa1c799edef38aDouglas Gregor  __builtin___memset_chk(&x1, 0, sizeof x1, sizeof x1); //                    \
80707a23e8b87410332b55bb4534fa1c799edef38aDouglas Gregor      // expected-warning {{destination for this '__builtin___memset_chk' call is a pointer to dynamic class}} \
81707a23e8b87410332b55bb4534fa1c799edef38aDouglas Gregor      // expected-note {{explicitly cast the pointer to silence this warning}}
82707a23e8b87410332b55bb4534fa1c799edef38aDouglas Gregor  __builtin___memset_chk(&x2, 0, sizeof x2, sizeof x2); //                    \
83707a23e8b87410332b55bb4534fa1c799edef38aDouglas Gregor      // expected-warning {{destination for this '__builtin___memset_chk' call is a pointer to dynamic class}} \
84707a23e8b87410332b55bb4534fa1c799edef38aDouglas Gregor      // expected-note {{explicitly cast the pointer to silence this warning}}
85707a23e8b87410332b55bb4534fa1c799edef38aDouglas Gregor
86707a23e8b87410332b55bb4534fa1c799edef38aDouglas Gregor  __builtin___memmove_chk(&x1, 0, sizeof x1, sizeof x1); //                   \
87707a23e8b87410332b55bb4534fa1c799edef38aDouglas Gregor      // expected-warning{{destination for this '__builtin___memmove_chk' call is a pointer to dynamic class}} \
88707a23e8b87410332b55bb4534fa1c799edef38aDouglas Gregor      // expected-note {{explicitly cast the pointer to silence this warning}}
89707a23e8b87410332b55bb4534fa1c799edef38aDouglas Gregor  __builtin___memmove_chk(0, &x1, sizeof x1, sizeof x1); //                   \
90707a23e8b87410332b55bb4534fa1c799edef38aDouglas Gregor      // expected-warning{{source of this '__builtin___memmove_chk' call is a pointer to dynamic class}} \
91707a23e8b87410332b55bb4534fa1c799edef38aDouglas Gregor      // expected-note {{explicitly cast the pointer to silence this warning}}
92707a23e8b87410332b55bb4534fa1c799edef38aDouglas Gregor  __builtin___memcpy_chk(&x1, 0, sizeof x1, sizeof x1); //                    \
93707a23e8b87410332b55bb4534fa1c799edef38aDouglas Gregor      // expected-warning{{destination for this '__builtin___memcpy_chk' call is a pointer to dynamic class}} \
94707a23e8b87410332b55bb4534fa1c799edef38aDouglas Gregor      // expected-note {{explicitly cast the pointer to silence this warning}}
95707a23e8b87410332b55bb4534fa1c799edef38aDouglas Gregor  __builtin___memcpy_chk(0, &x1, sizeof x1, sizeof x1); //                    \
96707a23e8b87410332b55bb4534fa1c799edef38aDouglas Gregor      // expected-warning{{source of this '__builtin___memcpy_chk' call is a pointer to dynamic class}} \
97707a23e8b87410332b55bb4534fa1c799edef38aDouglas Gregor      // expected-note {{explicitly cast the pointer to silence this warning}}
98ef8225444452a1486bd721f3285301fe84643b00Stephen Hines
99ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  // expected-warning@+2 {{destination for this 'memset' call is a pointer to class containing a dynamic class 'X1'}}
100ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  // expected-note@+1 {{explicitly cast the pointer to silence this warning}}
101ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  memset(&contains_dynamic, 0, sizeof(contains_dynamic));
102ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  // expected-warning@+2 {{destination for this 'memset' call is a pointer to class containing a dynamic class 'X1'}}
103ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  // expected-note@+1 {{explicitly cast the pointer to silence this warning}}
104ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  memset(&deep_contains_dynamic, 0, sizeof(deep_contains_dynamic));
105ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  // expected-warning@+2 {{destination for this 'memset' call is a pointer to class containing a dynamic class 'X1'}}
106ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  // expected-note@+1 {{explicitly cast the pointer to silence this warning}}
107ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  memset(&contains_array_dynamic, 0, sizeof(contains_array_dynamic));
1087ccc95bceebb2d1c8fbe277c9e33bde7dc1ccbb1Chandler Carruth}
1097ccc95bceebb2d1c8fbe277c9e33bde7dc1ccbb1Chandler Carruth
110134cb4442d6205e0226944ead4c7ede425fba206Chandler Carruthvoid test_nowarn(void *void_ptr) {
111134cb4442d6205e0226944ead4c7ede425fba206Chandler Carruth  int i, *iptr;
112134cb4442d6205e0226944ead4c7ede425fba206Chandler Carruth  float y;
113134cb4442d6205e0226944ead4c7ede425fba206Chandler Carruth  char c;
114134cb4442d6205e0226944ead4c7ede425fba206Chandler Carruth
115134cb4442d6205e0226944ead4c7ede425fba206Chandler Carruth  memset(&i, 0, sizeof i);
116134cb4442d6205e0226944ead4c7ede425fba206Chandler Carruth  memset(&iptr, 0, sizeof iptr);
117134cb4442d6205e0226944ead4c7ede425fba206Chandler Carruth  memset(&y, 0, sizeof y);
118134cb4442d6205e0226944ead4c7ede425fba206Chandler Carruth  memset(&c, 0, sizeof c);
119134cb4442d6205e0226944ead4c7ede425fba206Chandler Carruth  memset(void_ptr, 0, 42);
1207ccc95bceebb2d1c8fbe277c9e33bde7dc1ccbb1Chandler Carruth  memset(&s1, 0, sizeof s1);
1217ccc95bceebb2d1c8fbe277c9e33bde7dc1ccbb1Chandler Carruth  memset(&s2, 0, sizeof s2);
1227ccc95bceebb2d1c8fbe277c9e33bde7dc1ccbb1Chandler Carruth  memset(&s3, 0, sizeof s3);
12343fa33b4bedc28d2faa17d678ad1f40eb42817a1Chandler Carruth  memset(&c1, 0, sizeof c1);
1247ccc95bceebb2d1c8fbe277c9e33bde7dc1ccbb1Chandler Carruth
125ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  memset(&contains_pointer_dynamic, 0, sizeof(contains_pointer_dynamic));
126ef8225444452a1486bd721f3285301fe84643b00Stephen Hines
1277ccc95bceebb2d1c8fbe277c9e33bde7dc1ccbb1Chandler Carruth  // Unevaluated code shouldn't warn.
1287ccc95bceebb2d1c8fbe277c9e33bde7dc1ccbb1Chandler Carruth  (void)sizeof memset(&x1, 0, sizeof x1);
1297ccc95bceebb2d1c8fbe277c9e33bde7dc1ccbb1Chandler Carruth
1307ccc95bceebb2d1c8fbe277c9e33bde7dc1ccbb1Chandler Carruth  // Dead code shouldn't warn.
1317ccc95bceebb2d1c8fbe277c9e33bde7dc1ccbb1Chandler Carruth  if (false) memset(&x1, 0, sizeof x1);
1327ccc95bceebb2d1c8fbe277c9e33bde7dc1ccbb1Chandler Carruth}
133e452c78072156c14cd9998733e3b4b28b6fc7fd7Douglas Gregor
134e452c78072156c14cd9998733e3b4b28b6fc7fd7Douglas Gregornamespace N {
135e452c78072156c14cd9998733e3b4b28b6fc7fd7Douglas Gregor  void *memset(void *, int, unsigned);
136e452c78072156c14cd9998733e3b4b28b6fc7fd7Douglas Gregor  void test_nowarn() {
137e452c78072156c14cd9998733e3b4b28b6fc7fd7Douglas Gregor    N::memset(&x1, 0, sizeof x1);
138e452c78072156c14cd9998733e3b4b28b6fc7fd7Douglas Gregor  }
139e452c78072156c14cd9998733e3b4b28b6fc7fd7Douglas Gregor}
140