From: John McCall Date: Wed, 3 Mar 2010 03:40:11 +0000 (+0000) Subject: Don't emit derived-to-base destructor aliases if we don't have a definition X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9a70846c5ffd5ff5cce60de49cd7b312146bf502;p=clang Don't emit derived-to-base destructor aliases if we don't have a definition for the base destructor, because aliases to declarations aren't legal. Fixes PR 6471. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@97637 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp index cb8489d202..4889fc08f4 100644 --- a/lib/CodeGen/CGCXX.cpp +++ b/lib/CodeGen/CGCXX.cpp @@ -93,12 +93,18 @@ 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(getContext()); + if (!BaseD->isImplicit() && !BaseD->getBody()) + return true; + // If the base is at a non-zero offset, give up. const ASTRecordLayout &ClassLayout = Context.getASTRecordLayout(Class); if (ClassLayout.getBaseClassOffset(UniqueBase) != 0) return true; - const CXXDestructorDecl *BaseD = UniqueBase->getDestructor(getContext()); return TryEmitDefinitionAsAlias(GlobalDecl(D, Dtor_Base), GlobalDecl(BaseD, Dtor_Base)); } diff --git a/test/CodeGenCXX/destructors.cpp b/test/CodeGenCXX/destructors.cpp index accd1b3498..d40b174012 100644 --- a/test/CodeGenCXX/destructors.cpp +++ b/test/CodeGenCXX/destructors.cpp @@ -104,6 +104,10 @@ namespace test1 { struct Empty { }; // trivial destructor, empty struct NonEmpty { int x; }; // trivial destructor, non-empty + // There must be a definition in this translation unit for the alias + // optimization to apply. + A::~A() { delete m; } + struct M : A { ~M(); }; M::~M() {} // alias tested above @@ -133,3 +137,13 @@ namespace test1 { struct U : A, virtual B { ~U(); }; U::~U() {} // CHECK: define void @_ZN5test11UD2Ev } + +// PR6471 +namespace test2 { + struct A { ~A(); char ***m; }; + struct B : A { ~B(); }; + + B::~B() {} + // CHECK: define void @_ZN5test21BD2Ev + // CHECK: call void @_ZN5test21AD2Ev +}