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
8class Base {
9 public:
10 int b;
11 Base() { b = 1; }
12 ~Base();
13};
14
15class TrivialBaseBefore {
16public:
17 int tb0;
18 TrivialBaseBefore() { tb0 = 1; }
19};
20
21class TrivialBaseAfter {
22public:
23 int tb1;
24 TrivialBaseAfter() { tb1 = 1; }
25};
26
27class Derived : public TrivialBaseBefore, public Base, public TrivialBaseAfter {
28public:
29 int d;
30 Derived() { d = 1; }
31 ~Derived();
32};
33
34Derived *g;
35
36Base::~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
45Derived::~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
53int 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(x: &g->tb0, size: 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(x: &g->b, size: 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(x: &g->tb1, size: 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

source code of compiler-rt/test/msan/dtor-base-access.cpp