]> granicus.if.org Git - clang/commitdiff
PR10304: Do not call destructors for data members from union destructors. Prior to...
authorRichard Smith <richard-llvm@metafoo.co.uk>
Sun, 18 Sep 2011 12:11:43 +0000 (12:11 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Sun, 18 Sep 2011 12:11:43 +0000 (12:11 +0000)
has no effect since any such destructors must be trivial, and in C++11 such destructors must not
be called.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@139997 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGClass.cpp
lib/Sema/SemaDeclCXX.cpp
test/CodeGenCXX/union-dtor.cpp [new file with mode: 0644]

index 71cb13e9df3da2417cb3cbe4bb61de6e8e73dccb..615a4daa869704b4cdd0dacaa5b8e1ae5ff031e2 100644 (file)
@@ -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) {
 
index b408f7f0882f0b0fb8ca65b30095ebd21cfa147a..e75b79c609564147c7e6baf4acf467c773df9c5f 100644 (file)
@@ -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 (file)
index 0000000..a9d1f8e
--- /dev/null
@@ -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