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