aboutsummaryrefslogtreecommitdiff
path: root/test/msan/dtor-multiple-inheritance-nontrivial-class-members.cc
diff options
context:
space:
mode:
Diffstat (limited to 'test/msan/dtor-multiple-inheritance-nontrivial-class-members.cc')
-rw-r--r--test/msan/dtor-multiple-inheritance-nontrivial-class-members.cc152
1 files changed, 152 insertions, 0 deletions
diff --git a/test/msan/dtor-multiple-inheritance-nontrivial-class-members.cc b/test/msan/dtor-multiple-inheritance-nontrivial-class-members.cc
new file mode 100644
index 000000000000..dd79e3cc6c5e
--- /dev/null
+++ b/test/msan/dtor-multiple-inheritance-nontrivial-class-members.cc
@@ -0,0 +1,152 @@
+// 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
+
+// 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
+
+// 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
+
+#include <sanitizer/msan_interface.h>
+#include <assert.h>
+
+template <class T> class Vector {
+public:
+ int size;
+ ~Vector() {
+ assert(__msan_test_shadow(&this->size, sizeof(this->size)) == -1);
+ }
+};
+
+struct VirtualBase {
+public:
+ Vector<int> virtual_v;
+ int virtual_a;
+ // Pointer to subclass member
+ int *intermediate_a_ptr;
+
+ VirtualBase() {
+ virtual_v.size = 1;
+ virtual_a = 9;
+ }
+ void set_ptr(int *intermediate_a) {
+ this->intermediate_a_ptr = intermediate_a;
+ }
+ virtual ~VirtualBase() {
+ assert(__msan_test_shadow(&virtual_v, sizeof(virtual_v)) == -1);
+ assert(__msan_test_shadow(&virtual_a, sizeof(virtual_a)) == -1);
+ // Derived class member is poisoned
+ assert(__msan_test_shadow(intermediate_a_ptr,
+ sizeof(*intermediate_a_ptr)) != -1);
+ }
+};
+
+struct Intermediate : virtual public VirtualBase {
+public:
+ int intermediate_a;
+
+ Intermediate() { intermediate_a = 5; }
+ virtual ~Intermediate() {
+ assert(__msan_test_shadow(&this->intermediate_a,
+ sizeof(this->intermediate_a)) == -1);
+ // Members inherited from VirtualBase unpoisoned
+ assert(__msan_test_shadow(&virtual_v, sizeof(virtual_v)) == -1);
+ assert(__msan_test_shadow(&virtual_a, sizeof(virtual_a)) == -1);
+ assert(__msan_test_shadow(intermediate_a_ptr,
+ sizeof(*intermediate_a_ptr)) == -1);
+ }
+};
+
+struct Base {
+ int base_a;
+ Vector<int> base_v;
+ double base_b;
+ // Pointers to subclass members
+ int *derived_a_ptr;
+ Vector<int> *derived_v1_ptr;
+ Vector<int> *derived_v2_ptr;
+ double *derived_b_ptr;
+ double *derived_c_ptr;
+
+ Base(int *derived_a, Vector<int> *derived_v1, Vector<int> *derived_v2,
+ double *derived_b, double *derived_c) {
+ base_a = 2;
+ base_v.size = 1;
+ base_b = 13.2324;
+ derived_a_ptr = derived_a;
+ derived_v1_ptr = derived_v1;
+ derived_v2_ptr = derived_v2;
+ derived_b_ptr = derived_b;
+ derived_c_ptr = derived_c;
+ }
+ virtual ~Base() {
+ assert(__msan_test_shadow(&base_a, sizeof(base_a)) == -1);
+ assert(__msan_test_shadow(&base_v, sizeof(base_v)) == -1);
+ assert(__msan_test_shadow(&base_b, sizeof(base_b)) == -1);
+ // Derived class members are poisoned
+ assert(__msan_test_shadow(derived_a_ptr, sizeof(*derived_a_ptr)) != -1);
+ assert(__msan_test_shadow(derived_v1_ptr, sizeof(*derived_v1_ptr)) != -1);
+ assert(__msan_test_shadow(derived_v2_ptr, sizeof(*derived_v2_ptr)) != -1);
+ assert(__msan_test_shadow(derived_b_ptr, sizeof(*derived_b_ptr)) != -1);
+ assert(__msan_test_shadow(derived_c_ptr, sizeof(*derived_c_ptr)) != -1);
+ }
+};
+
+struct Derived : public Base, public Intermediate {
+ int derived_a;
+ Vector<int> derived_v1;
+ Vector<int> derived_v2;
+ double derived_b;
+ double derived_c;
+
+ Derived()
+ : Base(&derived_a, &derived_v1, &derived_v2, &derived_b, &derived_c) {
+ derived_a = 5;
+ derived_v1.size = 1;
+ derived_v2.size = 1;
+ derived_b = 7;
+ derived_c = 10;
+ }
+ ~Derived() {
+ assert(__msan_test_shadow(&derived_a, sizeof(derived_a)) == -1);
+ assert(__msan_test_shadow(&derived_v1, sizeof(derived_v1)) == -1);
+ assert(__msan_test_shadow(&derived_v2, sizeof(derived_v2)) == -1);
+ assert(__msan_test_shadow(&derived_b, sizeof(derived_b)) == -1);
+ assert(__msan_test_shadow(&derived_c, sizeof(derived_c)) == -1);
+ }
+};
+
+int main() {
+ Derived *d = new Derived();
+ d->set_ptr(&d->intermediate_a);
+
+ // Keep track of members of VirtualBase, since the virtual base table
+ // is inaccessible after destruction
+ Vector<int> *temp_virtual_v = &d->virtual_v;
+ int *temp_virtual_a = &d->virtual_a;
+ int **temp_intermediate_a_ptr = &d->intermediate_a_ptr;
+
+ d->~Derived();
+ assert(__msan_test_shadow(&d->derived_a, sizeof(d->derived_a)) != -1);
+ assert(__msan_test_shadow(&d->derived_v1, sizeof(d->derived_v1)) != -1);
+ assert(__msan_test_shadow(&d->derived_v2, sizeof(d->derived_v2)) != -1);
+ assert(__msan_test_shadow(&d->derived_b, sizeof(d->derived_b)) != -1);
+ assert(__msan_test_shadow(&d->derived_c, sizeof(d->derived_c)) != -1);
+
+ // Inherited from base
+ assert(__msan_test_shadow(&d->base_a, sizeof(d->base_a)) != -1);
+ assert(__msan_test_shadow(&d->base_v, sizeof(d->base_v)) != -1);
+ assert(__msan_test_shadow(&d->base_b, sizeof(d->base_b)) != -1);
+ assert(__msan_test_shadow(&d->derived_a_ptr, sizeof(d->derived_a_ptr)) != -1);
+ assert(__msan_test_shadow(&d->derived_v1_ptr, sizeof(d->derived_v1_ptr)) !=
+ -1);
+ assert(__msan_test_shadow(&d->derived_v2_ptr, sizeof(d->derived_v2_ptr)) !=
+ -1);
+ assert(__msan_test_shadow(&d->derived_b_ptr, sizeof(d->derived_b_ptr)) != -1);
+ assert(__msan_test_shadow(&d->derived_c_ptr, sizeof(d->derived_c_ptr)) != -1);
+
+ // Inherited from intermediate
+ assert(__msan_test_shadow(temp_virtual_v, sizeof(*temp_virtual_v)) != -1);
+ assert(__msan_test_shadow(temp_virtual_a, sizeof(*temp_virtual_a)) != -1);
+ assert(__msan_test_shadow(temp_intermediate_a_ptr,
+ sizeof(*temp_intermediate_a_ptr)) != -1);
+
+ return 0;
+}