aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/CodeGen/CGClass.cpp4
-rw-r--r--lib/Sema/SemaDeclCXX.cpp5
-rw-r--r--test/CodeGenCXX/union-dtor.cpp42
3 files changed, 49 insertions, 2 deletions
diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp
index 71cb13e9df..615a4daa86 100644
--- a/lib/CodeGen/CGClass.cpp
+++ b/lib/CodeGen/CGClass.cpp
@@ -980,6 +980,10 @@ void CodeGenFunction::EnterDtorCleanups(const CXXDestructorDecl *DD,
const CXXRecordDecl *ClassDecl = DD->getParent();
+ // Unions have no bases and do not call field destructors.
+ if (ClassDecl->isUnion())
+ return;
+
// The complete-destructor phase just destructs all the virtual bases.
if (DtorType == Dtor_Complete) {
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index b408f7f088..e75b79c609 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -2767,8 +2767,9 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl,
void
Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
CXXRecordDecl *ClassDecl) {
- // Ignore dependent contexts.
- if (ClassDecl->isDependentContext())
+ // Ignore dependent contexts. Also ignore unions, since their members never
+ // have destructors implicitly called.
+ if (ClassDecl->isDependentContext() || ClassDecl->isUnion())
return;
// FIXME: all the access-control diagnostics are positioned on the
diff --git a/test/CodeGenCXX/union-dtor.cpp b/test/CodeGenCXX/union-dtor.cpp
new file mode 100644
index 0000000000..a9d1f8e9bd
--- /dev/null
+++ b/test/CodeGenCXX/union-dtor.cpp
@@ -0,0 +1,42 @@
+// RUN: %clang_cc1 -std=c++0x %s -S -o - -emit-llvm | FileCheck %s
+
+// PR10304: destructors should not call destructors for variant members.
+
+template<bool b = false>
+struct Foo {
+ Foo() { static_assert(b, "Foo::Foo used"); }
+ ~Foo() { static_assert(b, "Foo::~Foo used"); }
+};
+
+struct Bar {
+ Bar();
+ ~Bar();
+};
+
+union FooBar {
+ FooBar() {}
+ ~FooBar() {}
+ Foo<> foo;
+ Bar bar;
+};
+
+struct Variant {
+ Variant() {}
+ ~Variant() {}
+ union {
+ Foo<> foo;
+ Bar bar;
+ };
+};
+
+FooBar foobar;
+Variant variant;
+
+// The ctor and dtor of Foo<> and Bar should not be mentioned in the resulting
+// code.
+//
+// CHECK-NOT: 3FooILb1EEC1
+// CHECK-NOT: 3BarC1
+//
+// CHECK-NOT: 3FooILb1EED1
+// CHECK-NOT: 3BarD1