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