59 changes: 44 additions & 15 deletions clang/test/CodeGenCXX/sanitize-dtor-zero-size-field.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ struct Struct {
static_assert(sizeof(Struct) == 24);
} // namespace T1
// CHECK-LABEL: define {{.*}} @_ZN5empty2T16StructD2Ev(
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 13)
// CHECK: [[GEP:%.+]] = getelementptr i8, {{.*}}, i64 8{{$}}
// CHECK: call void @__sanitizer_dtor_callback(i8* [[GEP]], i64 13)
// CHECK: call void @_ZN10NonTrivialD1Ev(
// CHECK-NEXT: ret void

namespace T2 {
Expand All @@ -57,8 +59,11 @@ struct Struct {
static_assert(sizeof(Struct) == 24);
} // namespace T2
// CHECK-LABEL: define {{.*}} @_ZN5empty2T26StructD2Ev(
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 8)
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 5)
// CHECK: [[GEP1:%.+]] = getelementptr i8, {{.*}}, i64 16{{$}}
// CHECK: call void @__sanitizer_dtor_callback(i8* [[GEP1]], i64 5)
// CHECK: call void @_ZN10NonTrivialD1Ev(
// CHECK: [[GEP2:%.+]] = getelementptr i8, {{.*}}, i64 0{{$}}
// CHECK: call void @__sanitizer_dtor_callback(i8* [[GEP2]], i64 8)
// CHECK-NEXT: ret void

namespace T3 {
Expand All @@ -71,8 +76,11 @@ struct Struct {
static_assert(sizeof(Struct) == 24);
} // namespace T3
// CHECK-LABEL: define {{.*}} @_ZN5empty2T36StructD2Ev(
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 12)
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 1)
// CHECK: [[GEP1:%.+]] = getelementptr i8, {{.*}}, i64 20{{$}}
// CHECK: call void @__sanitizer_dtor_callback(i8* [[GEP1]], i64 1)
// CHECK: call void @_ZN10NonTrivialD1Ev(
// CHECK: [[GEP2:%.+]] = getelementptr i8, {{.*}}, i64 0{{$}}
// CHECK: call void @__sanitizer_dtor_callback(i8* [[GEP2]], i64 12)
// CHECK-NEXT: ret void

namespace T4 {
Expand Down Expand Up @@ -100,6 +108,7 @@ static_assert(sizeof(Struct) == 24);
} // namespace T5
// CHECK-LABEL: define {{.*}} @_ZN5empty2T56StructD2Ev(
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 13)
// CHECK: call void @_ZN10NonTrivialD1Ev(
// CHECK-NEXT: ret void

namespace T6 {
Expand All @@ -114,6 +123,7 @@ static_assert(sizeof(Struct) == 24);
} // namespace T6
// CHECK-LABEL: define {{.*}} @_ZN5empty2T66StructD2Ev(
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 13)
// CHECK: call void @_ZN10NonTrivialD1Ev(
// CHECK-NEXT: ret void

namespace T7 {
Expand All @@ -127,8 +137,9 @@ struct Struct {
static_assert(sizeof(Struct) == 24);
} // namespace T7
// CHECK-LABEL: define {{.*}} @_ZN5empty2T76StructD2Ev(
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 8)
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 5)
// CHECK: call void @_ZN10NonTrivialD1Ev(
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 8)
// CHECK-NEXT: ret void

namespace T8 {
Expand All @@ -142,8 +153,8 @@ struct Struct {
static_assert(sizeof(Struct) == 24);
} // namespace T8
// CHECK-LABEL: define {{.*}} @_ZN5empty2T86StructD2Ev(
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 8)
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 5)
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 8)
// CHECK-NEXT: ret void

namespace T9 {
Expand All @@ -157,8 +168,8 @@ struct Struct {
static_assert(sizeof(Struct) == 24);
} // namespace T9
// CHECK-LABEL: define {{.*}} @_ZN5empty2T96StructD2Ev(
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 12)
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 1)
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 12)
// CHECK-NEXT: ret void

namespace T10 {
Expand All @@ -172,8 +183,8 @@ struct Struct {
static_assert(sizeof(Struct) == 24);
} // namespace T10
// CHECK-LABEL: define {{.*}} @_ZN5empty3T106StructD2Ev(
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 12)
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 1)
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 12)
// CHECK-NEXT: ret void

namespace T11 {
Expand Down Expand Up @@ -202,6 +213,7 @@ static_assert(sizeof(Struct) == 24);
} // namespace T12
} // namespace empty
// CHECK-LABEL: define {{.*}} @_ZN5empty3T126StructD2Ev(
// CHECK: call void @_ZN10NonTrivialD1Ev(
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 16)
// CHECK-NEXT: ret void

Expand All @@ -217,6 +229,7 @@ static_assert(sizeof(Struct) == 24);
} // namespace T1
// CHECK-LABEL: define {{.*}} @_ZN17empty_non_trivial2T16StructD2Ev(
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 13)
// CHECK: call void @_ZN10NonTrivialD1Ev(
// CHECK-NEXT: ret void

namespace T2 {
Expand All @@ -229,8 +242,8 @@ struct Struct {
static_assert(sizeof(Struct) == 24);
} // namespace T2
// CHECK-LABEL: define {{.*}} @_ZN17empty_non_trivial2T26StructD2Ev(
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 8)
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 5)
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 8)
// CHECK-NEXT: ret void

namespace T3 {
Expand All @@ -243,8 +256,8 @@ struct Struct {
static_assert(sizeof(Struct) == 24);
} // namespace T3
// CHECK-LABEL: define {{.*}} @_ZN17empty_non_trivial2T36StructD2Ev(
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 12)
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 1)
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 12)
// CHECK-NEXT: ret void

namespace T4 {
Expand Down Expand Up @@ -272,6 +285,8 @@ static_assert(sizeof(Struct) == 24);
} // namespace T5
// CHECK-LABEL: define {{.*}} @_ZN17empty_non_trivial2T56StructD2Ev(
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 13)
// CHECK: call void @_ZN10NonTrivialD1Ev(
// CHECK: call void @_ZN15EmptyNonTrivialD1Ev(
// CHECK-NEXT: ret void

namespace T6 {
Expand All @@ -286,6 +301,8 @@ static_assert(sizeof(Struct) == 24);
} // namespace T6
// CHECK-LABEL: define {{.*}} @_ZN17empty_non_trivial2T66StructD2Ev(
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 13)
// CHECK: call void @_ZN15EmptyNonTrivialD1Ev(
// CHECK: call void @_ZN10NonTrivialD1Ev(
// CHECK-NEXT: ret void

namespace T7 {
Expand All @@ -299,8 +316,10 @@ struct Struct {
static_assert(sizeof(Struct) == 24);
} // namespace T7
// CHECK-LABEL: define {{.*}} @_ZN17empty_non_trivial2T76StructD2Ev(
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 8)
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 5)
// CHECK: call void @_ZN15EmptyNonTrivialD1Ev(
// CHECK: call void @_ZN10NonTrivialD1Ev(
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 8)
// CHECK-NEXT: ret void

namespace T8 {
Expand All @@ -314,8 +333,10 @@ struct Struct {
static_assert(sizeof(Struct) == 24);
} // namespace T8
// CHECK-LABEL: define {{.*}} @_ZN17empty_non_trivial2T86StructD2Ev(
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 8)
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 5)
// CHECK: call void @_ZN10NonTrivialD1Ev(
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 8)
// CHECK: call void @_ZN15EmptyNonTrivialD1Ev(
// CHECK-NEXT: ret void

namespace T9 {
Expand All @@ -329,8 +350,10 @@ struct Struct {
static_assert(sizeof(Struct) == 24);
} // namespace T9
// CHECK-LABEL: define {{.*}} @_ZN17empty_non_trivial2T96StructD2Ev(
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 12)
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 1)
// CHECK: call void @_ZN15EmptyNonTrivialD1Ev(
// CHECK: call void @_ZN10NonTrivialD1Ev(
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 12)
// CHECK-NEXT: ret void

namespace T10 {
Expand All @@ -344,8 +367,10 @@ struct Struct {
static_assert(sizeof(Struct) == 24);
} // namespace T10
// CHECK-LABEL: define {{.*}} @_ZN17empty_non_trivial3T106StructD2Ev(
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 12)
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 1)
// CHECK: call void @_ZN10NonTrivialD1Ev(
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 12)
// CHECK: call void @_ZN15EmptyNonTrivialD1Ev(
// CHECK-NEXT: ret void

namespace T11 {
Expand All @@ -359,6 +384,8 @@ struct Struct {
static_assert(sizeof(Struct) == 24);
} // namespace T11
// CHECK-LABEL: define {{.*}} @_ZN17empty_non_trivial3T116StructD2Ev(
// CHECK: call void @_ZN15EmptyNonTrivialD1Ev(
// CHECK: call void @_ZN10NonTrivialD1Ev(
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 16)
// CHECK-NEXT: ret void

Expand All @@ -374,5 +401,7 @@ static_assert(sizeof(Struct) == 24);
} // namespace T12
} // namespace empty_non_trivial
// CHECK-LABEL: define {{.*}} @_ZN17empty_non_trivial3T126StructD2Ev(
// CHECK: call void @_ZN10NonTrivialD1Ev(
// CHECK: call void @__sanitizer_dtor_callback(i8* {{.*}}, i64 16)
// CHECK: call void @_ZN15EmptyNonTrivialD1Ev(
// CHECK: ret void
69 changes: 45 additions & 24 deletions compiler-rt/test/msan/dtor-base-access.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,41 +9,62 @@

class Base {
public:
int *x_ptr;
Base(int *y_ptr) {
// store value of subclass member
x_ptr = y_ptr;
}
virtual ~Base();
int b;
Base() { b = 1; }
~Base();
};

class Derived : public Base {
public:
int y;
Derived():Base(&y) {
y = 10;
}
class TrivialBaseBefore {
public:
int tb0;
TrivialBaseBefore() { tb0 = 1; }
};

class TrivialBaseAfter {
public:
int tb1;
TrivialBaseAfter() { tb1 = 1; }
};

class Derived : public TrivialBaseBefore, public Base, public TrivialBaseAfter {
public:
int d;
Derived() { d = 1; }
~Derived();
};

Derived *g;

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);
// ok to access its own members and earlier bases
assert(__msan_test_shadow(&g->tb0, sizeof(g->tb0)) == -1);
assert(__msan_test_shadow(&g->b, sizeof(g->b)) == -1);
// not ok to access others
assert(__msan_test_shadow(&g->tb1, sizeof(g->tb1)) == 0);
assert(__msan_test_shadow(&g->d, sizeof(g->d)) == 0);
}

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);
// ok to access everything
assert(__msan_test_shadow(&g->tb0, sizeof(g->tb0)) == -1);
assert(__msan_test_shadow(&g->b, sizeof(g->b)) == -1);
assert(__msan_test_shadow(&g->tb1, sizeof(g->tb1)) == -1);
assert(__msan_test_shadow(&g->d, sizeof(g->d)) == -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);
g = new Derived();
// ok to access everything
assert(__msan_test_shadow(&g->tb0, sizeof(g->tb0)) == -1);
assert(__msan_test_shadow(&g->b, sizeof(g->b)) == -1);
assert(__msan_test_shadow(&g->tb1, sizeof(g->tb1)) == -1);
assert(__msan_test_shadow(&g->d, sizeof(g->d)) == -1);

g->~Derived();
// not ok to access everything
assert(__msan_test_shadow(&g->tb0, sizeof(g->tb0)) == 0);
assert(__msan_test_shadow(&g->b, sizeof(g->b)) == 0);
assert(__msan_test_shadow(&g->tb1, sizeof(g->tb1)) == 0);
assert(__msan_test_shadow(&g->d, sizeof(g->d)) == 0);
return 0;
}