1 // RUN: %clangxx_msan %s -O0 -fsanitize-memory-use-after-dtor -fsanitize-memory-track-origins -o %t && %run %t 2>&1 | FileCheck %s
2 // RUN: %clangxx_msan %s -O1 -fsanitize-memory-use-after-dtor -fsanitize-memory-track-origins -o %t && %run %t 2>&1 | FileCheck %s
3 // RUN: %clangxx_msan %s -O2 -fsanitize-memory-use-after-dtor -fsanitize-memory-track-origins -o %t && %run %t 2>&1 | FileCheck %s
4
5 #include <sanitizer/msan_interface.h>
6 #include <assert.h>
7
8 class Base {
9 public:
10 int b;
Base()11 Base() { b = 1; }
12 ~Base();
13 };
14
15 class TrivialBaseBefore {
16 public:
17 int tb0;
TrivialBaseBefore()18 TrivialBaseBefore() { tb0 = 1; }
19 };
20
21 class TrivialBaseAfter {
22 public:
23 int tb1;
TrivialBaseAfter()24 TrivialBaseAfter() { tb1 = 1; }
25 };
26
27 class Derived : public TrivialBaseBefore, public Base, public TrivialBaseAfter {
28 public:
29 int d;
Derived()30 Derived() { d = 1; }
31 ~Derived();
32 };
33
34 Derived *g;
35
~Base()36 Base::~Base() {
37 // ok to access its own members and earlier bases
38 assert(__msan_test_shadow(&g->tb0, sizeof(g->tb0)) == -1);
39 assert(__msan_test_shadow(&g->b, sizeof(g->b)) == -1);
40 // not ok to access others
41 assert(__msan_test_shadow(&g->tb1, sizeof(g->tb1)) == 0);
42 assert(__msan_test_shadow(&g->d, sizeof(g->d)) == 0);
43 }
44
~Derived()45 Derived::~Derived() {
46 // ok to access everything
47 assert(__msan_test_shadow(&g->tb0, sizeof(g->tb0)) == -1);
48 assert(__msan_test_shadow(&g->b, sizeof(g->b)) == -1);
49 assert(__msan_test_shadow(&g->tb1, sizeof(g->tb1)) == -1);
50 assert(__msan_test_shadow(&g->d, sizeof(g->d)) == -1);
51 }
52
main()53 int main() {
54 g = new Derived();
55 // ok to access everything
56 assert(__msan_test_shadow(&g->tb0, sizeof(g->tb0)) == -1);
57 assert(__msan_test_shadow(&g->b, sizeof(g->b)) == -1);
58 assert(__msan_test_shadow(&g->tb1, sizeof(g->tb1)) == -1);
59 assert(__msan_test_shadow(&g->d, sizeof(g->d)) == -1);
60
61 g->~Derived();
62 // not ok to access everything
63 assert(__msan_test_shadow(&g->tb0, sizeof(g->tb0)) == 0);
64 assert(__msan_test_shadow(&g->b, sizeof(g->b)) == 0);
65 assert(__msan_test_shadow(&g->tb1, sizeof(g->tb1)) == 0);
66 assert(__msan_test_shadow(&g->d, sizeof(g->d)) == 0);
67
68 __msan_print_shadow(&g->tb0, sizeof(g->tb0));
69 // CHECK: Member fields were destroyed
70 // CHECK: {{#0 0x.* in __sanitizer_dtor_callback}}
71 // CHECK: {{#1 0x.* in .*~Derived.*cpp:}}[[@LINE-56]]:
72 // CHECK: {{#2 0x.* in .*~Derived.*cpp:}}[[@LINE-21]]:
73
74 __msan_print_shadow(&g->b, sizeof(g->b));
75 // CHECK: Member fields were destroyed
76 // CHECK: {{#0 0x.* in __sanitizer_dtor_callback}}
77 // CHECK: {{#1 0x.* in .*~Base.*cpp:}}[[@LINE-67]]:
78 // CHECK: {{#2 0x.* in .*~Base.*cpp:}}[[@LINE-35]]:
79
80 __msan_print_shadow(&g->tb1, sizeof(g->tb1));
81 // CHECK: Member fields were destroyed
82 // CHECK: {{#0 0x.* in __sanitizer_dtor_callback}}
83 // CHECK: {{#1 0x.* in .*~Derived.*cpp:}}[[@LINE-62]]:
84 // CHECK: {{#2 0x.* in .*~Derived.*cpp:}}[[@LINE-33]]:
85
86 return 0;
87 }
88