r217874 - Add support for putting constructors and destructos in explicit comdats.
David Blaikie
dblaikie at gmail.com
Tue Sep 16 09:40:23 PDT 2014
On Tue, Sep 16, 2014 at 8:18 AM, Rafael Espindola <
rafael.espindola at gmail.com> wrote:
> Author: rafael
> Date: Tue Sep 16 10:18:21 2014
> New Revision: 217874
>
> URL: http://llvm.org/viewvc/llvm-project?rev=217874&view=rev
> Log:
> Add support for putting constructors and destructos in explicit comdats.
>
> There are situations when clang knows that the C1 and C2 constructors
> or the D1 and D2 destructors are identical. We already optimize some
> of these cases, but cannot optimize it when the GlobalValue is
> weak_odr.
>
> The problem with weak_odr is that an old TU seeing the same code will
> have a C1 and a C2 comdat with the corresponding symbols. We cannot
> suddenly start putting the C2 symbol in the C1 comdat as we cannot
> guarantee that the linker will not pick a .o with only C1 in it.
>
> The solution implemented by GCC is to expand the ABI to have a comdat
> whose name uses a C5/D5 suffix and always has both symbols. That is
> what this patch implements.
>
I was sort of hoping this would happen - this change caused an XPASS on the
GDB buildbot (
http://lab.llvm.org:8011/builders/clang-x86_64-ubuntu-gdb-75/builds/17323 )
as it resolves PR14473.
I've updated the test case in r217882 & marked the bug as resolved. Thanks!
>
> Modified:
> cfe/trunk/include/clang/AST/Mangle.h
> cfe/trunk/include/clang/Basic/ABI.h
> cfe/trunk/lib/AST/ItaniumMangle.cpp
> cfe/trunk/lib/AST/MicrosoftMangle.cpp
> cfe/trunk/lib/CodeGen/CGClass.cpp
> cfe/trunk/lib/CodeGen/CodeGenModule.cpp
> cfe/trunk/lib/CodeGen/CodeGenModule.h
> cfe/trunk/lib/CodeGen/CodeGenTypes.h
> cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
> cfe/trunk/test/CodeGenCXX/ctor-dtor-alias.cpp
> cfe/trunk/test/CodeGenCXX/destructors.cpp
> cfe/trunk/test/CodeGenCXX/virtual-destructor-calls.cpp
>
> Modified: cfe/trunk/include/clang/AST/Mangle.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Mangle.h?rev=217874&r1=217873&r2=217874&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/AST/Mangle.h (original)
> +++ cfe/trunk/include/clang/AST/Mangle.h Tue Sep 16 10:18:21 2014
> @@ -156,6 +156,11 @@ public:
> virtual void mangleItaniumThreadLocalWrapper(const VarDecl *D,
> raw_ostream &) = 0;
>
> + virtual void mangleCXXCtorComdat(const CXXConstructorDecl *D,
> + raw_ostream &) = 0;
> + virtual void mangleCXXDtorComdat(const CXXDestructorDecl *D,
> + raw_ostream &) = 0;
> +
> static bool classof(const MangleContext *C) {
> return C->getKind() == MK_Itanium;
> }
>
> Modified: cfe/trunk/include/clang/Basic/ABI.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/ABI.h?rev=217874&r1=217873&r2=217874&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/ABI.h (original)
> +++ cfe/trunk/include/clang/Basic/ABI.h Tue Sep 16 10:18:21 2014
> @@ -24,14 +24,15 @@ namespace clang {
> enum CXXCtorType {
> Ctor_Complete, ///< Complete object ctor
> Ctor_Base, ///< Base object ctor
> - Ctor_CompleteAllocating ///< Complete object allocating ctor
> + Ctor_Comdat ///< The COMDAT used for ctors
> };
>
> /// \brief C++ destructor types.
> enum CXXDtorType {
> Dtor_Deleting, ///< Deleting dtor
> Dtor_Complete, ///< Complete object dtor
> - Dtor_Base ///< Base object dtor
> + Dtor_Base, ///< Base object dtor
> + Dtor_Comdat ///< The COMDAT used for dtors
> };
>
> /// \brief A return adjustment.
>
> Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=217874&r1=217873&r2=217874&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/AST/ItaniumMangle.cpp (original)
> +++ cfe/trunk/lib/AST/ItaniumMangle.cpp Tue Sep 16 10:18:21 2014
> @@ -150,6 +150,8 @@ public:
> void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type,
> raw_ostream &) override;
>
> + void mangleCXXCtorComdat(const CXXConstructorDecl *D, raw_ostream &)
> override;
> + void mangleCXXDtorComdat(const CXXDestructorDecl *D, raw_ostream &)
> override;
> void mangleStaticGuardVariable(const VarDecl *D, raw_ostream &)
> override;
> void mangleDynamicInitializer(const VarDecl *D, raw_ostream &Out)
> override;
> void mangleDynamicAtExitDestructor(const VarDecl *D,
> @@ -3249,8 +3251,8 @@ void CXXNameMangler::mangleFunctionParam
> void CXXNameMangler::mangleCXXCtorType(CXXCtorType T) {
> // <ctor-dtor-name> ::= C1 # complete object constructor
> // ::= C2 # base object constructor
> - // ::= C3 # complete object allocating constructor
> //
> + // In addition, C5 is a comdat name with C1 and C2 in it.
> switch (T) {
> case Ctor_Complete:
> Out << "C1";
> @@ -3258,8 +3260,8 @@ void CXXNameMangler::mangleCXXCtorType(C
> case Ctor_Base:
> Out << "C2";
> break;
> - case Ctor_CompleteAllocating:
> - Out << "C3";
> + case Ctor_Comdat:
> + Out << "C5";
> break;
> }
> }
> @@ -3269,6 +3271,7 @@ void CXXNameMangler::mangleCXXDtorType(C
> // ::= D1 # complete object destructor
> // ::= D2 # base object destructor
> //
> + // In addition, D5 is a comdat name with D1, D2 and, if virtual, D0 in
> it.
> switch (T) {
> case Dtor_Deleting:
> Out << "D0";
> @@ -3279,6 +3282,9 @@ void CXXNameMangler::mangleCXXDtorType(C
> case Dtor_Base:
> Out << "D2";
> break;
> + case Dtor_Comdat:
> + Out << "D5";
> + break;
> }
> }
>
> @@ -3689,6 +3695,18 @@ void ItaniumMangleContextImpl::mangleCXX
> Mangler.mangle(D);
> }
>
> +void ItaniumMangleContextImpl::mangleCXXCtorComdat(const
> CXXConstructorDecl *D,
> + raw_ostream &Out) {
> + CXXNameMangler Mangler(*this, Out, D, Ctor_Comdat);
> + Mangler.mangle(D);
> +}
> +
> +void ItaniumMangleContextImpl::mangleCXXDtorComdat(const
> CXXDestructorDecl *D,
> + raw_ostream &Out) {
> + CXXNameMangler Mangler(*this, Out, D, Dtor_Comdat);
> + Mangler.mangle(D);
> +}
> +
> void ItaniumMangleContextImpl::mangleThunk(const CXXMethodDecl *MD,
> const ThunkInfo &Thunk,
> raw_ostream &Out) {
>
> Modified: cfe/trunk/lib/AST/MicrosoftMangle.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/MicrosoftMangle.cpp?rev=217874&r1=217873&r2=217874&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/AST/MicrosoftMangle.cpp (original)
> +++ cfe/trunk/lib/AST/MicrosoftMangle.cpp Tue Sep 16 10:18:21 2014
> @@ -854,6 +854,8 @@ void MicrosoftCXXNameMangler::mangleCXXD
> // <operator-name> ::= ?_E # vector deleting destructor
> // FIXME: Add a vector deleting dtor type. It goes in the vtable, so
> we need
> // it.
> + case Dtor_Comdat:
> + llvm_unreachable("not expecting a COMDAT");
> }
> llvm_unreachable("Unsupported dtor type?");
> }
>
> Modified: cfe/trunk/lib/CodeGen/CGClass.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGClass.cpp?rev=217874&r1=217873&r2=217874&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGClass.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGClass.cpp Tue Sep 16 10:18:21 2014
> @@ -1292,6 +1292,9 @@ void CodeGenFunction::EmitDestructorBody
> // we'd introduce *two* handler blocks. In the Microsoft ABI, we
> // always delegate because we might not have a definition in this TU.
> switch (DtorType) {
> + case Dtor_Comdat:
> + llvm_unreachable("not expecting a COMDAT");
> +
> case Dtor_Deleting: llvm_unreachable("already handled deleting case");
>
> case Dtor_Complete:
>
> Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=217874&r1=217873&r2=217874&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Tue Sep 16 10:18:21 2014
> @@ -198,6 +198,10 @@ void CodeGenModule::createCUDARuntime()
> CUDARuntime = CreateNVCUDARuntime(*this);
> }
>
> +void CodeGenModule::addReplacement(StringRef Name, llvm::Constant *C) {
> + Replacements[Name] = C;
> +}
> +
> void CodeGenModule::applyReplacements() {
> for (ReplacementsTy::iterator I = Replacements.begin(),
> E = Replacements.end();
>
> Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=217874&r1=217873&r2=217874&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)
> +++ cfe/trunk/lib/CodeGen/CodeGenModule.h Tue Sep 16 10:18:21 2014
> @@ -1058,9 +1058,17 @@ public:
> void setFunctionDefinitionAttributes(const FunctionDecl *D,
> llvm::Function *F);
>
> -private:
> llvm::GlobalValue *GetGlobalValue(StringRef Ref);
>
> + /// Set attributes which are common to any form of a global definition
> (alias,
> + /// Objective-C method, function, global variable).
> + ///
> + /// NOTE: This should only be called for definitions.
> + void SetCommonAttributes(const Decl *D, llvm::GlobalValue *GV);
> +
> + void addReplacement(StringRef Name, llvm::Constant *C);
> +private:
> +
> llvm::Constant *
> GetOrCreateLLVMFunction(StringRef MangledName, llvm::Type *Ty,
> GlobalDecl D,
> bool ForVTable, bool DontDefer = false,
> @@ -1070,12 +1078,6 @@ private:
> llvm::PointerType *PTy,
> const VarDecl *D);
>
> - /// Set attributes which are common to any form of a global definition
> (alias,
> - /// Objective-C method, function, global variable).
> - ///
> - /// NOTE: This should only be called for definitions.
> - void SetCommonAttributes(const Decl *D, llvm::GlobalValue *GV);
> -
> void setNonAliasAttributes(const Decl *D, llvm::GlobalObject *GO);
>
> /// Set function attributes for a function declaration.
>
> Modified: cfe/trunk/lib/CodeGen/CodeGenTypes.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenTypes.h?rev=217874&r1=217873&r2=217874&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CodeGenTypes.h (original)
> +++ cfe/trunk/lib/CodeGen/CodeGenTypes.h Tue Sep 16 10:18:21 2014
> @@ -80,8 +80,8 @@ inline StructorType getFromCtorType(CXXC
> return StructorType::Complete;
> case Ctor_Base:
> return StructorType::Base;
> - case Ctor_CompleteAllocating:
> - llvm_unreachable("invalid enum");
> + case Ctor_Comdat:
> + llvm_unreachable("not expecting a COMDAT");
> }
> llvm_unreachable("not a CXXCtorType");
> }
> @@ -106,6 +106,8 @@ inline StructorType getFromDtorType(CXXD
> return StructorType::Complete;
> case Dtor_Base:
> return StructorType::Base;
> + case Dtor_Comdat:
> + llvm_unreachable("not expecting a COMDAT");
> }
> llvm_unreachable("not a CXXDtorType");
> }
>
> Modified: cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp?rev=217874&r1=217873&r2=217874&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp (original)
> +++ cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp Tue Sep 16 10:18:21 2014
> @@ -2999,35 +2999,102 @@ ItaniumCXXABI::RTTIUniquenessKind Itaniu
> return RUK_NonUniqueVisible;
> }
>
> -static void emitCXXConstructor(CodeGenModule &CGM,
> - const CXXConstructorDecl *ctor,
> - StructorType ctorType) {
> - if (!ctor->getParent()->getNumVBases() &&
> - (ctorType == StructorType::Complete || ctorType ==
> StructorType::Base)) {
> - // The complete constructor is equivalent to the base constructor
> - // for classes with no virtual bases. Try to emit it as an alias.
> - bool ProducedAlias = !CGM.TryEmitDefinitionAsAlias(
> - GlobalDecl(ctor, Ctor_Complete), GlobalDecl(ctor, Ctor_Base),
> true);
> - if (ctorType == StructorType::Complete && ProducedAlias)
> - return;
> +// Find out how to codegen the complete destructor and constructor
> +namespace {
> +enum class StructorCodegen { Emit, RAUW, Alias, COMDAT };
> +}
> +static StructorCodegen getCodegenToUse(CodeGenModule &CGM,
> + const CXXMethodDecl *MD) {
> + if (!CGM.getCodeGenOpts().CXXCtorDtorAliases)
> + return StructorCodegen::Emit;
> +
> + // The complete and base structors are not equivalent if there are any
> virtual
> + // bases, so emit separate functions.
> + if (MD->getParent()->getNumVBases())
> + return StructorCodegen::Emit;
> +
> + GlobalDecl AliasDecl;
> + if (const auto *DD = dyn_cast<CXXDestructorDecl>(MD)) {
> + AliasDecl = GlobalDecl(DD, Dtor_Complete);
> + } else {
> + const auto *CD = cast<CXXConstructorDecl>(MD);
> + AliasDecl = GlobalDecl(CD, Ctor_Complete);
> }
> + llvm::GlobalValue::LinkageTypes Linkage =
> CGM.getFunctionLinkage(AliasDecl);
> +
> + if (llvm::GlobalValue::isDiscardableIfUnused(Linkage))
> + return StructorCodegen::RAUW;
> +
> + // FIXME: Should we allow available_externally aliases?
> + if (!llvm::GlobalAlias::isValidLinkage(Linkage))
> + return StructorCodegen::RAUW;
>
> - CGM.codegenCXXStructor(ctor, ctorType);
> + if (llvm::GlobalValue::isWeakForLinker(Linkage))
> + return StructorCodegen::COMDAT;
> +
> + return StructorCodegen::Alias;
> }
>
> -static void emitCXXDestructor(CodeGenModule &CGM, const CXXDestructorDecl
> *dtor,
> - StructorType dtorType) {
> - // The complete destructor is equivalent to the base destructor for
> - // classes with no virtual bases, so try to emit it as an alias.
> - if (!dtor->getParent()->getNumVBases() &&
> - (dtorType == StructorType::Complete || dtorType ==
> StructorType::Base)) {
> - bool ProducedAlias = !CGM.TryEmitDefinitionAsAlias(
> - GlobalDecl(dtor, Dtor_Complete), GlobalDecl(dtor, Dtor_Base),
> true);
> - if (ProducedAlias) {
> - if (dtorType == StructorType::Complete)
> - return;
> - if (dtor->isVirtual())
> - CGM.getVTables().EmitThunks(GlobalDecl(dtor, Dtor_Complete));
> +static void emitConstructorDestructorAlias(CodeGenModule &CGM,
> + GlobalDecl AliasDecl,
> + GlobalDecl TargetDecl) {
> + llvm::GlobalValue::LinkageTypes Linkage =
> CGM.getFunctionLinkage(AliasDecl);
> +
> + StringRef MangledName = CGM.getMangledName(AliasDecl);
> + llvm::GlobalValue *Entry = CGM.GetGlobalValue(MangledName);
> + if (Entry && !Entry->isDeclaration())
> + return;
> +
> + auto *Aliasee =
> cast<llvm::GlobalValue>(CGM.GetAddrOfGlobal(TargetDecl));
> + llvm::PointerType *AliasType = Aliasee->getType();
> +
> + // Create the alias with no name.
> + auto *Alias = llvm::GlobalAlias::create(
> + AliasType->getElementType(), 0, Linkage, "", Aliasee,
> &CGM.getModule());
> +
> + // Switch any previous uses to the alias.
> + if (Entry) {
> + assert(Entry->getType() == AliasType &&
> + "declaration exists with different type");
> + Alias->takeName(Entry);
> + Entry->replaceAllUsesWith(Alias);
> + Entry->eraseFromParent();
> + } else {
> + Alias->setName(MangledName);
> + }
> +
> + // Finally, set up the alias with its proper name and attributes.
> + CGM.SetCommonAttributes(cast<NamedDecl>(AliasDecl.getDecl()), Alias);
> +}
> +
> +void ItaniumCXXABI::emitCXXStructor(const CXXMethodDecl *MD,
> + StructorType Type) {
> + auto *CD = dyn_cast<CXXConstructorDecl>(MD);
> + const CXXDestructorDecl *DD = CD ? nullptr :
> cast<CXXDestructorDecl>(MD);
> +
> + StructorCodegen CGType = getCodegenToUse(CGM, MD);
> +
> + if (Type == StructorType::Complete) {
> + GlobalDecl CompleteDecl;
> + GlobalDecl BaseDecl;
> + if (CD) {
> + CompleteDecl = GlobalDecl(CD, Ctor_Complete);
> + BaseDecl = GlobalDecl(CD, Ctor_Base);
> + } else {
> + CompleteDecl = GlobalDecl(DD, Dtor_Complete);
> + BaseDecl = GlobalDecl(DD, Dtor_Base);
> + }
> +
> + if (CGType == StructorCodegen::Alias || CGType ==
> StructorCodegen::COMDAT) {
> + emitConstructorDestructorAlias(CGM, CompleteDecl, BaseDecl);
> + return;
> + }
> +
> + if (CGType == StructorCodegen::RAUW) {
> + StringRef MangledName = CGM.getMangledName(CompleteDecl);
> + auto *Aliasee =
> cast<llvm::GlobalValue>(CGM.GetAddrOfGlobal(BaseDecl));
> + CGM.addReplacement(MangledName, Aliasee);
> + return;
> }
> }
>
> @@ -3035,17 +3102,20 @@ static void emitCXXDestructor(CodeGenMod
> // base class if there is exactly one non-virtual base class with a
> // non-trivial destructor, there are no fields with a non-trivial
> // destructor, and the body of the destructor is trivial.
> - if (dtorType == StructorType::Base &&
> !CGM.TryEmitBaseDestructorAsAlias(dtor))
> + if (DD && Type == StructorType::Base && CGType !=
> StructorCodegen::COMDAT &&
> + !CGM.TryEmitBaseDestructorAsAlias(DD))
> return;
>
> - CGM.codegenCXXStructor(dtor, dtorType);
> -}
> + llvm::Function *Fn = CGM.codegenCXXStructor(MD, Type);
>
> -void ItaniumCXXABI::emitCXXStructor(const CXXMethodDecl *MD,
> - StructorType Type) {
> - if (auto *CD = dyn_cast<CXXConstructorDecl>(MD)) {
> - emitCXXConstructor(CGM, CD, Type);
> - return;
> + if (CGType == StructorCodegen::COMDAT) {
> + SmallString<256> Buffer;
> + llvm::raw_svector_ostream Out(Buffer);
> + if (DD)
> + getMangleContext().mangleCXXDtorComdat(DD, Out);
> + else
> + getMangleContext().mangleCXXCtorComdat(CD, Out);
> + llvm::Comdat *C = CGM.getModule().getOrInsertComdat(Out.str());
> + Fn->setComdat(C);
> }
> - emitCXXDestructor(CGM, cast<CXXDestructorDecl>(MD), Type);
> }
>
> Modified: cfe/trunk/test/CodeGenCXX/ctor-dtor-alias.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/ctor-dtor-alias.cpp?rev=217874&r1=217873&r2=217874&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/CodeGenCXX/ctor-dtor-alias.cpp (original)
> +++ cfe/trunk/test/CodeGenCXX/ctor-dtor-alias.cpp Tue Sep 16 10:18:21 2014
> @@ -6,18 +6,23 @@
> // RUN: FileCheck --check-prefix=CHECK3 --input-file=%t %s
> // RUN: FileCheck --check-prefix=CHECK4 --input-file=%t %s
> // RUN: FileCheck --check-prefix=CHECK5 --input-file=%t %s
> +// RUN: FileCheck --check-prefix=CHECK6 --input-file=%t %s
>
> namespace test1 {
> -// test that we don't produce an alias when the destructor is weak_odr.
> The
> -// reason to avoid it that another TU might have no explicit template
> -// instantiation definition or declaration, causing it to to output only
> -// one of the destructors as linkonce_odr, producing a different comdat.
> +// Test that we produce the apropriate comdats when creating aliases to
> +// weak_odr constructors and destructors.
>
> -// CHECK1: define weak_odr void @_ZN5test16foobarIvEC2Ev
> -// CHECK1: define weak_odr void @_ZN5test16foobarIvEC1Ev
> +// CHECK1: @_ZN5test16foobarIvEC1Ev = weak_odr alias void {{.*}}
> @_ZN5test16foobarIvEC2Ev
> +// CHECK1: @_ZN5test16foobarIvED1Ev = weak_odr alias void
> (%"struct.test1::foobar"*)* @_ZN5test16foobarIvED2Ev
> +// CHECK1: define weak_odr void @_ZN5test16foobarIvEC2Ev({{.*}} comdat
> $_ZN5test16foobarIvEC5Ev
> +// CHECK1: define weak_odr void @_ZN5test16foobarIvED2Ev({{.*}} comdat
> $_ZN5test16foobarIvED5Ev
> +// CHECK1: define weak_odr void @_ZN5test16foobarIvED0Ev({{.*}} comdat
> $_ZN5test16foobarIvED5Ev
> +// CHECK1-NOT: comdat
>
> -template <typename T> struct foobar {
> +template <typename T>
> +struct foobar {
> foobar() {}
> + virtual ~foobar() {}
> };
>
> template struct foobar<void>;
> @@ -187,3 +192,38 @@ void
> fn1() {
> new C;
> }
> +
> +namespace test10 {
> +// Test that if a destructor is in a comdat, we don't try to emit is as an
> +// alias to a base class destructor.
> +struct bar {
> + ~bar();
> +};
> +bar::~bar() {
> +}
> +} // closing the namespace causes ~bar to be sent to CodeGen
> +namespace test10 {
> +template <typename T>
> +struct foo : public bar {
> + ~foo();
> +};
> +template <typename T>
> +foo<T>::~foo() {}
> +template class foo<int>;
> +// CHECK5: define weak_odr void @_ZN6test103fooIiED2Ev({{.*}} comdat
> $_ZN6test103fooIiED5Ev
> +}
> +
> +namespace test11 {
> +// Test that when we don't have to worry about COMDATs we produce an alias
> +// from complate to base and from base to base class base.
> +struct bar {
> + ~bar();
> +};
> +bar::~bar() {}
> +struct foo : public bar {
> + ~foo();
> +};
> +foo::~foo() {}
> +// CHECK6: @_ZN6test113fooD2Ev = alias {{.*}} @_ZN6test113barD2Ev
> +// CHECK6: @_ZN6test113fooD1Ev = alias {{.*}} @_ZN6test113fooD2Ev
> +}
>
> Modified: cfe/trunk/test/CodeGenCXX/destructors.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/destructors.cpp?rev=217874&r1=217873&r2=217874&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/CodeGenCXX/destructors.cpp (original)
> +++ cfe/trunk/test/CodeGenCXX/destructors.cpp Tue Sep 16 10:18:21 2014
> @@ -204,18 +204,14 @@ namespace test3 {
> // CHECK4: call void @_ZN5test312_GLOBAL__N_11DD0Ev(
> // CHECK4: ret void
>
> - // CHECK4-LABEL: define internal void
> @_ZThn8_N5test312_GLOBAL__N_11CD1Ev(
> - // CHECK4: getelementptr inbounds i8* {{.*}}, i64 -8
> - // CHECK4: call void @_ZN5test312_GLOBAL__N_11CD2Ev(
> - // CHECK4: ret void
> + // CHECK4-LABEL: declare void @_ZN5test31BD2Ev(
> + // CHECK4-LABEL: declare void @_ZN5test31AD2Ev(
>
> // CHECK4-LABEL: define internal void
> @_ZN5test312_GLOBAL__N_11CD2Ev(%"struct.test3::(anonymous namespace)::C"*
> %this) unnamed_addr
> // CHECK4: invoke void @_ZN5test31BD2Ev(
> // CHECK4: call void @_ZN5test31AD2Ev(
> // CHECK4: ret void
>
> - // CHECK4: declare void @_ZN5test31BD2Ev(
> - // CHECK4: declare void @_ZN5test31AD2Ev(
>
> // CHECK4-LABEL: define internal void
> @_ZN5test312_GLOBAL__N_11CD0Ev(%"struct.test3::(anonymous namespace)::C"*
> %this) unnamed_addr
> // CHECK4: invoke void @_ZN5test312_GLOBAL__N_11CD2Ev(
> @@ -226,6 +222,11 @@ namespace test3 {
> // CHECK4: call void @_ZdlPv({{.*}}) [[NUW]]
> // CHECK4: resume { i8*, i32 }
>
> + // CHECK4-LABEL: define internal void
> @_ZThn8_N5test312_GLOBAL__N_11CD1Ev(
> + // CHECK4: getelementptr inbounds i8* {{.*}}, i64 -8
> + // CHECK4: call void @_ZN5test312_GLOBAL__N_11CD2Ev(
> + // CHECK4: ret void
> +
> // CHECK4-LABEL: define internal void
> @_ZThn8_N5test312_GLOBAL__N_11CD0Ev(
> // CHECK4: getelementptr inbounds i8* {{.*}}, i64 -8
> // CHECK4: call void @_ZN5test312_GLOBAL__N_11CD0Ev(
>
> Modified: cfe/trunk/test/CodeGenCXX/virtual-destructor-calls.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/virtual-destructor-calls.cpp?rev=217874&r1=217873&r2=217874&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/CodeGenCXX/virtual-destructor-calls.cpp (original)
> +++ cfe/trunk/test/CodeGenCXX/virtual-destructor-calls.cpp Tue Sep 16
> 10:18:21 2014
> @@ -17,8 +17,8 @@ struct B : A {
> // CHECK: @_ZN1BD1Ev = alias {{.*}} @_ZN1BD2Ev
>
> // (aliases from C)
> -// CHECK: @_ZN1CD1Ev = alias {{.*}} @_ZN1CD2Ev
> // CHECK: @_ZN1CD2Ev = alias bitcast {{.*}} @_ZN1BD2Ev
> +// CHECK: @_ZN1CD1Ev = alias {{.*}} @_ZN1CD2Ev
>
> // Base dtor: actually calls A's base dtor.
> // CHECK-LABEL: define void @_ZN1BD2Ev(%struct.B* %this) unnamed_addr
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20140916/8b5a4eea/attachment.html>
More information about the cfe-commits
mailing list