]> granicus.if.org Git - clang/commitdiff
Don't emit an internal destructor that is identical to an external one.
authorRafael Espindola <rafael.espindola@gmail.com>
Sat, 9 Nov 2013 01:57:21 +0000 (01:57 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Sat, 9 Nov 2013 01:57:21 +0000 (01:57 +0000)
It is not safe to emit alias to undefined (not supported by ELF or COFF), but
it is safe to rauw when the alias would have been internal or linkonce_odr.

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

lib/CodeGen/CGCXX.cpp
test/CodeGenCXX/ctor-dtor-alias.cpp

index f9b07d2386b6d5e720bf691ffa7c9ce2b708dc66..f79e079745cd3ee15a445c5ae55d64a8b72d3935 100644 (file)
@@ -82,18 +82,12 @@ bool CodeGenModule::TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D) {
   if (!UniqueBase)
     return true;
 
-  /// If we don't have a definition for the destructor yet, don't
-  /// emit.  We can't emit aliases to declarations; that's just not
-  /// how aliases work.
-  const CXXDestructorDecl *BaseD = UniqueBase->getDestructor();
-  if (!BaseD->isImplicit() && !BaseD->hasBody())
-    return true;
-
   // If the base is at a non-zero offset, give up.
   const ASTRecordLayout &ClassLayout = Context.getASTRecordLayout(Class);
   if (!ClassLayout.getBaseClassOffset(UniqueBase).isZero())
     return true;
 
+  const CXXDestructorDecl *BaseD = UniqueBase->getDestructor();
   return TryEmitDefinitionAsAlias(GlobalDecl(D, Dtor_Base),
                                   GlobalDecl(BaseD, Dtor_Base),
                                   false);
@@ -146,14 +140,20 @@ bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl,
     return false;
   }
 
-  // Don't create an alias to a linker weak symbol unless we know we can do
-  // that in every TU. This avoids producing different COMDATs in different
-  // TUs.
-  if (llvm::GlobalValue::isWeakForLinker(TargetLinkage)) {
-    if (!InEveryTU)
+  if (!InEveryTU) {
+    /// If we don't have a definition for the destructor yet, don't
+    /// emit.  We can't emit aliases to declarations; that's just not
+    /// how aliases work.
+    if (Ref->isDeclaration())
       return true;
 
-    assert(Linkage == TargetLinkage);
+    // Don't create an alias to a linker weak symbol unless we know we can do
+    // that in every TU. This avoids producing different COMDATs in different
+    // TUs.
+    if (llvm::GlobalValue::isWeakForLinker(TargetLinkage)) {
+      assert(Linkage == TargetLinkage);
+      return true;
+    }
   }
 
   // Create the alias with no name.
index 6e1c144e5de73b762d34cde8d3334c40124c9baa..745495ac68ff9f6b1ac1d039af317d48bbcba70b 100644 (file)
@@ -73,3 +73,18 @@ namespace test5 {
   }
   B X;
 }
+
+namespace test6 {
+  // Test that we use ~A directly, even when ~A is not defined. The symbol for
+  // ~B would have been internal and still contain a reference to ~A.
+  struct A {
+    virtual ~A();
+  };
+  namespace {
+  struct B : public A {
+    ~B() {}
+  };
+  }
+  B X;
+  // CHECK-DAG: call i32 @__cxa_atexit({{.*}}@_ZN5test61AD2Ev
+}