// 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> class Base { public: int *x_ptr; Base(int *y_ptr) { // store value of subclass member x_ptr = y_ptr; } virtual ~Base(); }; class Derived : public Base { public: int y; Derived():Base(&y) { y = 10; } ~Derived(); }; Base::~Base() { // ok access its own member assert(__msan_test_shadow(&this->x_ptr, sizeof(this->x_ptr)) == -1); // bad access subclass member assert(__msan_test_shadow(this->x_ptr, sizeof(*this->x_ptr)) != -1); } Derived::~Derived() { // ok to access its own members assert(__msan_test_shadow(&this->y, sizeof(this->y)) == -1); // ok access base class members assert(__msan_test_shadow(&this->x_ptr, sizeof(this->x_ptr)) == -1); } int main() { Derived *d = new Derived(); assert(__msan_test_shadow(&d->x_ptr, sizeof(d->x_ptr)) == -1); d->~Derived(); assert(__msan_test_shadow(&d->x_ptr, sizeof(d->x_ptr)) != -1); return 0; }