1*7c3d14c8STreehugger Robot // RUN: %clangxx_msan %s -O0 -fsanitize=memory -fsanitize-memory-use-after-dtor -o %t && MSAN_OPTIONS=poison_in_dtor=1 %run %t >%t.out 2>&1
2*7c3d14c8STreehugger Robot 
3*7c3d14c8STreehugger Robot // RUN: %clangxx_msan %s -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -o %t && MSAN_OPTIONS=poison_in_dtor=1 %run %t >%t.out 2>&1
4*7c3d14c8STreehugger Robot 
5*7c3d14c8STreehugger Robot // RUN: %clangxx_msan %s -O2 -fsanitize=memory -fsanitize-memory-use-after-dtor -o %t && MSAN_OPTIONS=poison_in_dtor=1 %run %t >%t.out 2>&1
6*7c3d14c8STreehugger Robot 
7*7c3d14c8STreehugger Robot #include <sanitizer/msan_interface.h>
8*7c3d14c8STreehugger Robot #include <assert.h>
9*7c3d14c8STreehugger Robot 
10*7c3d14c8STreehugger Robot template <class T> class Vector {
11*7c3d14c8STreehugger Robot public:
12*7c3d14c8STreehugger Robot   int size;
~Vector()13*7c3d14c8STreehugger Robot   ~Vector() {
14*7c3d14c8STreehugger Robot     assert(__msan_test_shadow(&this->size, sizeof(this->size)) == -1);
15*7c3d14c8STreehugger Robot   }
16*7c3d14c8STreehugger Robot };
17*7c3d14c8STreehugger Robot 
18*7c3d14c8STreehugger Robot struct VirtualBase {
19*7c3d14c8STreehugger Robot public:
20*7c3d14c8STreehugger Robot   Vector<int> virtual_v;
21*7c3d14c8STreehugger Robot   int virtual_a;
22*7c3d14c8STreehugger Robot   // Pointer to subclass member
23*7c3d14c8STreehugger Robot   int *intermediate_a_ptr;
24*7c3d14c8STreehugger Robot 
VirtualBaseVirtualBase25*7c3d14c8STreehugger Robot   VirtualBase() {
26*7c3d14c8STreehugger Robot     virtual_v.size = 1;
27*7c3d14c8STreehugger Robot     virtual_a = 9;
28*7c3d14c8STreehugger Robot   }
set_ptrVirtualBase29*7c3d14c8STreehugger Robot   void set_ptr(int *intermediate_a) {
30*7c3d14c8STreehugger Robot     this->intermediate_a_ptr = intermediate_a;
31*7c3d14c8STreehugger Robot   }
~VirtualBaseVirtualBase32*7c3d14c8STreehugger Robot   virtual ~VirtualBase() {
33*7c3d14c8STreehugger Robot     assert(__msan_test_shadow(&virtual_v, sizeof(virtual_v)) == -1);
34*7c3d14c8STreehugger Robot     assert(__msan_test_shadow(&virtual_a, sizeof(virtual_a)) == -1);
35*7c3d14c8STreehugger Robot     // Derived class member is poisoned
36*7c3d14c8STreehugger Robot     assert(__msan_test_shadow(intermediate_a_ptr,
37*7c3d14c8STreehugger Robot                               sizeof(*intermediate_a_ptr)) != -1);
38*7c3d14c8STreehugger Robot   }
39*7c3d14c8STreehugger Robot };
40*7c3d14c8STreehugger Robot 
41*7c3d14c8STreehugger Robot struct Intermediate : virtual public VirtualBase {
42*7c3d14c8STreehugger Robot public:
43*7c3d14c8STreehugger Robot   int intermediate_a;
44*7c3d14c8STreehugger Robot 
IntermediateIntermediate45*7c3d14c8STreehugger Robot   Intermediate() { intermediate_a = 5; }
~IntermediateIntermediate46*7c3d14c8STreehugger Robot   virtual ~Intermediate() {
47*7c3d14c8STreehugger Robot     assert(__msan_test_shadow(&this->intermediate_a,
48*7c3d14c8STreehugger Robot                               sizeof(this->intermediate_a)) == -1);
49*7c3d14c8STreehugger Robot     // Members inherited from VirtualBase unpoisoned
50*7c3d14c8STreehugger Robot     assert(__msan_test_shadow(&virtual_v, sizeof(virtual_v)) == -1);
51*7c3d14c8STreehugger Robot     assert(__msan_test_shadow(&virtual_a, sizeof(virtual_a)) == -1);
52*7c3d14c8STreehugger Robot     assert(__msan_test_shadow(intermediate_a_ptr,
53*7c3d14c8STreehugger Robot                               sizeof(*intermediate_a_ptr)) == -1);
54*7c3d14c8STreehugger Robot   }
55*7c3d14c8STreehugger Robot };
56*7c3d14c8STreehugger Robot 
57*7c3d14c8STreehugger Robot struct Base {
58*7c3d14c8STreehugger Robot   int base_a;
59*7c3d14c8STreehugger Robot   Vector<int> base_v;
60*7c3d14c8STreehugger Robot   double base_b;
61*7c3d14c8STreehugger Robot   // Pointers to subclass members
62*7c3d14c8STreehugger Robot   int *derived_a_ptr;
63*7c3d14c8STreehugger Robot   Vector<int> *derived_v1_ptr;
64*7c3d14c8STreehugger Robot   Vector<int> *derived_v2_ptr;
65*7c3d14c8STreehugger Robot   double *derived_b_ptr;
66*7c3d14c8STreehugger Robot   double *derived_c_ptr;
67*7c3d14c8STreehugger Robot 
BaseBase68*7c3d14c8STreehugger Robot   Base(int *derived_a, Vector<int> *derived_v1, Vector<int> *derived_v2,
69*7c3d14c8STreehugger Robot        double *derived_b, double *derived_c) {
70*7c3d14c8STreehugger Robot     base_a = 2;
71*7c3d14c8STreehugger Robot     base_v.size = 1;
72*7c3d14c8STreehugger Robot     base_b = 13.2324;
73*7c3d14c8STreehugger Robot     derived_a_ptr = derived_a;
74*7c3d14c8STreehugger Robot     derived_v1_ptr = derived_v1;
75*7c3d14c8STreehugger Robot     derived_v2_ptr = derived_v2;
76*7c3d14c8STreehugger Robot     derived_b_ptr = derived_b;
77*7c3d14c8STreehugger Robot     derived_c_ptr = derived_c;
78*7c3d14c8STreehugger Robot   }
~BaseBase79*7c3d14c8STreehugger Robot   virtual ~Base() {
80*7c3d14c8STreehugger Robot     assert(__msan_test_shadow(&base_a, sizeof(base_a)) == -1);
81*7c3d14c8STreehugger Robot     assert(__msan_test_shadow(&base_v, sizeof(base_v)) == -1);
82*7c3d14c8STreehugger Robot     assert(__msan_test_shadow(&base_b, sizeof(base_b)) == -1);
83*7c3d14c8STreehugger Robot     // Derived class members are poisoned
84*7c3d14c8STreehugger Robot     assert(__msan_test_shadow(derived_a_ptr, sizeof(*derived_a_ptr)) != -1);
85*7c3d14c8STreehugger Robot     assert(__msan_test_shadow(derived_v1_ptr, sizeof(*derived_v1_ptr)) != -1);
86*7c3d14c8STreehugger Robot     assert(__msan_test_shadow(derived_v2_ptr, sizeof(*derived_v2_ptr)) != -1);
87*7c3d14c8STreehugger Robot     assert(__msan_test_shadow(derived_b_ptr, sizeof(*derived_b_ptr)) != -1);
88*7c3d14c8STreehugger Robot     assert(__msan_test_shadow(derived_c_ptr, sizeof(*derived_c_ptr)) != -1);
89*7c3d14c8STreehugger Robot   }
90*7c3d14c8STreehugger Robot };
91*7c3d14c8STreehugger Robot 
92*7c3d14c8STreehugger Robot struct Derived : public Base, public Intermediate {
93*7c3d14c8STreehugger Robot   int derived_a;
94*7c3d14c8STreehugger Robot   Vector<int> derived_v1;
95*7c3d14c8STreehugger Robot   Vector<int> derived_v2;
96*7c3d14c8STreehugger Robot   double derived_b;
97*7c3d14c8STreehugger Robot   double derived_c;
98*7c3d14c8STreehugger Robot 
DerivedDerived99*7c3d14c8STreehugger Robot   Derived()
100*7c3d14c8STreehugger Robot       : Base(&derived_a, &derived_v1, &derived_v2, &derived_b, &derived_c) {
101*7c3d14c8STreehugger Robot     derived_a = 5;
102*7c3d14c8STreehugger Robot     derived_v1.size = 1;
103*7c3d14c8STreehugger Robot     derived_v2.size = 1;
104*7c3d14c8STreehugger Robot     derived_b = 7;
105*7c3d14c8STreehugger Robot     derived_c = 10;
106*7c3d14c8STreehugger Robot   }
~DerivedDerived107*7c3d14c8STreehugger Robot   ~Derived() {
108*7c3d14c8STreehugger Robot     assert(__msan_test_shadow(&derived_a, sizeof(derived_a)) == -1);
109*7c3d14c8STreehugger Robot     assert(__msan_test_shadow(&derived_v1, sizeof(derived_v1)) == -1);
110*7c3d14c8STreehugger Robot     assert(__msan_test_shadow(&derived_v2, sizeof(derived_v2)) == -1);
111*7c3d14c8STreehugger Robot     assert(__msan_test_shadow(&derived_b, sizeof(derived_b)) == -1);
112*7c3d14c8STreehugger Robot     assert(__msan_test_shadow(&derived_c, sizeof(derived_c)) == -1);
113*7c3d14c8STreehugger Robot   }
114*7c3d14c8STreehugger Robot };
115*7c3d14c8STreehugger Robot 
main()116*7c3d14c8STreehugger Robot int main() {
117*7c3d14c8STreehugger Robot   Derived *d = new Derived();
118*7c3d14c8STreehugger Robot   d->set_ptr(&d->intermediate_a);
119*7c3d14c8STreehugger Robot 
120*7c3d14c8STreehugger Robot   // Keep track of members of VirtualBase, since the virtual base table
121*7c3d14c8STreehugger Robot   // is inaccessible after destruction
122*7c3d14c8STreehugger Robot   Vector<int> *temp_virtual_v = &d->virtual_v;
123*7c3d14c8STreehugger Robot   int *temp_virtual_a = &d->virtual_a;
124*7c3d14c8STreehugger Robot   int **temp_intermediate_a_ptr = &d->intermediate_a_ptr;
125*7c3d14c8STreehugger Robot 
126*7c3d14c8STreehugger Robot   d->~Derived();
127*7c3d14c8STreehugger Robot   assert(__msan_test_shadow(&d->derived_a, sizeof(d->derived_a)) != -1);
128*7c3d14c8STreehugger Robot   assert(__msan_test_shadow(&d->derived_v1, sizeof(d->derived_v1)) != -1);
129*7c3d14c8STreehugger Robot   assert(__msan_test_shadow(&d->derived_v2, sizeof(d->derived_v2)) != -1);
130*7c3d14c8STreehugger Robot   assert(__msan_test_shadow(&d->derived_b, sizeof(d->derived_b)) != -1);
131*7c3d14c8STreehugger Robot   assert(__msan_test_shadow(&d->derived_c, sizeof(d->derived_c)) != -1);
132*7c3d14c8STreehugger Robot 
133*7c3d14c8STreehugger Robot   // Inherited from base
134*7c3d14c8STreehugger Robot   assert(__msan_test_shadow(&d->base_a, sizeof(d->base_a)) != -1);
135*7c3d14c8STreehugger Robot   assert(__msan_test_shadow(&d->base_v, sizeof(d->base_v)) != -1);
136*7c3d14c8STreehugger Robot   assert(__msan_test_shadow(&d->base_b, sizeof(d->base_b)) != -1);
137*7c3d14c8STreehugger Robot   assert(__msan_test_shadow(&d->derived_a_ptr, sizeof(d->derived_a_ptr)) != -1);
138*7c3d14c8STreehugger Robot   assert(__msan_test_shadow(&d->derived_v1_ptr, sizeof(d->derived_v1_ptr)) !=
139*7c3d14c8STreehugger Robot          -1);
140*7c3d14c8STreehugger Robot   assert(__msan_test_shadow(&d->derived_v2_ptr, sizeof(d->derived_v2_ptr)) !=
141*7c3d14c8STreehugger Robot          -1);
142*7c3d14c8STreehugger Robot   assert(__msan_test_shadow(&d->derived_b_ptr, sizeof(d->derived_b_ptr)) != -1);
143*7c3d14c8STreehugger Robot   assert(__msan_test_shadow(&d->derived_c_ptr, sizeof(d->derived_c_ptr)) != -1);
144*7c3d14c8STreehugger Robot 
145*7c3d14c8STreehugger Robot   // Inherited from intermediate
146*7c3d14c8STreehugger Robot   assert(__msan_test_shadow(temp_virtual_v, sizeof(*temp_virtual_v)) != -1);
147*7c3d14c8STreehugger Robot   assert(__msan_test_shadow(temp_virtual_a, sizeof(*temp_virtual_a)) != -1);
148*7c3d14c8STreehugger Robot   assert(__msan_test_shadow(temp_intermediate_a_ptr,
149*7c3d14c8STreehugger Robot                             sizeof(*temp_intermediate_a_ptr)) != -1);
150*7c3d14c8STreehugger Robot 
151*7c3d14c8STreehugger Robot   return 0;
152*7c3d14c8STreehugger Robot }
153