| // RUN: %clangxx_msan %s -O0 -fsanitize=memory -fsanitize-memory-use-after-dtor -o %t && MSAN_OPTIONS=poison_in_dtor=1 %run %t |
| |
| // RUN: %clangxx_msan %s -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -o %t && MSAN_OPTIONS=poison_in_dtor=1 %run %t |
| |
| // RUN: %clangxx_msan %s -O2 -fsanitize=memory -fsanitize-memory-use-after-dtor -o %t && MSAN_OPTIONS=poison_in_dtor=1 %run %t |
| |
| // RUN: %clangxx_msan %s -DCVPTR=1 -O2 -fsanitize=memory -fsanitize-memory-use-after-dtor -o %t && MSAN_OPTIONS=poison_in_dtor=1 not %run %t |
| |
| // RUN: %clangxx_msan %s -DEAVPTR=1 -O2 -fsanitize=memory -fsanitize-memory-use-after-dtor -o %t && MSAN_OPTIONS=poison_in_dtor=1 not %run %t |
| |
| // RUN: %clangxx_msan %s -DEDVPTR=1 -O2 -fsanitize=memory -fsanitize-memory-use-after-dtor -o %t && MSAN_OPTIONS=poison_in_dtor=1 not %run %t |
| |
| // Expected to quit due to invalid access when invoking |
| // function using vtable. |
| |
| class A { |
| public: |
| int x; |
| virtual ~A() { |
| // Should succeed |
| this->A_Foo(); |
| } |
| virtual void A_Foo() {} |
| }; |
| |
| class B : public virtual A { |
| public: |
| int y; |
| virtual ~B() {} |
| virtual void A_Foo() {} |
| }; |
| |
| class C : public B { |
| public: |
| int z; |
| ~C() {} |
| }; |
| |
| class D { |
| public: |
| int w; |
| ~D() {} |
| virtual void D_Foo() {} |
| }; |
| |
| class E : public virtual A, public virtual D { |
| public: |
| int u; |
| ~E() {} |
| void A_Foo() {} |
| }; |
| |
| int main() { |
| // Simple linear inheritance |
| C *c = new C(); |
| c->~C(); |
| // This fails |
| #ifdef CVPTR |
| c->A_Foo(); |
| #endif |
| |
| // Multiple inheritance, so has multiple vtables |
| E *e = new E(); |
| e->~E(); |
| // Both of these fail |
| #ifdef EAVPTR |
| e->A_Foo(); |
| #endif |
| #ifdef EDVPTR |
| e->D_Foo(); |
| #endif |
| } |