From 6e84e92f72f0634cf9f43767444d48dcf99c0121 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Sat, 9 Nov 2013 01:57:21 +0000 Subject: [PATCH] Don't emit an internal destructor that is identical to an external one. 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 | 26 +++++++++++++------------- test/CodeGenCXX/ctor-dtor-alias.cpp | 15 +++++++++++++++ 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp index f9b07d2386..f79e079745 100644 --- a/lib/CodeGen/CGCXX.cpp +++ b/lib/CodeGen/CGCXX.cpp @@ -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. diff --git a/test/CodeGenCXX/ctor-dtor-alias.cpp b/test/CodeGenCXX/ctor-dtor-alias.cpp index 6e1c144e5d..745495ac68 100644 --- a/test/CodeGenCXX/ctor-dtor-alias.cpp +++ b/test/CodeGenCXX/ctor-dtor-alias.cpp @@ -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 +} -- 2.40.0