On 4 September 2014 14:41, Reid Kleckner <r...@google.com> wrote:
> I don't like calling arrangeCXXDtorDeclaration from ctor-related functions.
> It looks like a typo. In the past I've used 'structor' as the generic term
> for ctors and dtors. You can see it in the Itanium mangling code, but I
> don't think it's very widely used. Does that seem like a better
> nomenclature? Then we would probably have StructorType, etc.

The attached patches uses the Structor nomenclature.

> I'm excited to finally have this functionality, though. :)

+1 :-)

Cheers,
Rafael
diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp
index 545c5ef..583017c 100644
--- a/lib/CodeGen/CGCXX.cpp
+++ b/lib/CodeGen/CGCXX.cpp
@@ -213,7 +213,7 @@ void CodeGenModule::EmitCXXConstructor(const CXXConstructorDecl *ctor,
   }
 
   const CGFunctionInfo &fnInfo =
-    getTypes().arrangeCXXConstructorDeclaration(ctor, ctorType);
+      getTypes().arrangeCXXStructorDeclaration(ctor, getFromCtorType(ctorType));
 
   auto *fn = cast<llvm::Function>(
       GetAddrOfCXXConstructor(ctor, ctorType, &fnInfo, true));
@@ -225,26 +225,39 @@ void CodeGenModule::EmitCXXConstructor(const CXXConstructorDecl *ctor,
   SetLLVMFunctionAttributesForDefinition(ctor, fn);
 }
 
-llvm::GlobalValue *
-CodeGenModule::GetAddrOfCXXConstructor(const CXXConstructorDecl *ctor,
-                                       CXXCtorType ctorType,
-                                       const CGFunctionInfo *fnInfo,
-                                       bool DontDefer) {
-  GlobalDecl GD(ctor, ctorType);
-  
-  StringRef name = getMangledName(GD);
-  if (llvm::GlobalValue *existing = GetGlobalValue(name))
-    return existing;
+llvm::GlobalValue *CodeGenModule::getAddrOfCXXStructor(
+    const CXXMethodDecl *MD, StructorType Type, const CGFunctionInfo *FnInfo,
+    llvm::FunctionType *FnType, bool DontDefer) {
+  GlobalDecl GD;
+  if (auto *CD = dyn_cast<CXXConstructorDecl>(MD)) {
+    GD = GlobalDecl(CD, toCXXCtorType(Type));
+  } else {
+    auto *DD = dyn_cast<CXXDestructorDecl>(MD);
+    GD = GlobalDecl(DD, toCXXDtorType(Type));
+  }
 
-  if (!fnInfo)
-    fnInfo = &getTypes().arrangeCXXConstructorDeclaration(ctor, ctorType);
+  StringRef Name = getMangledName(GD);
+  if (llvm::GlobalValue *Existing = GetGlobalValue(Name))
+    return Existing;
 
-  llvm::FunctionType *fnType = getTypes().GetFunctionType(*fnInfo);
-  return cast<llvm::Function>(GetOrCreateLLVMFunction(name, fnType, GD,
+  if (!FnType) {
+    if (!FnInfo)
+      FnInfo = &getTypes().arrangeCXXStructorDeclaration(MD, Type);
+    FnType = getTypes().GetFunctionType(*FnInfo);
+  }
+
+  return cast<llvm::Function>(GetOrCreateLLVMFunction(Name, FnType, GD,
                                                       /*ForVTable=*/false,
                                                       DontDefer));
 }
 
+llvm::GlobalValue *CodeGenModule::GetAddrOfCXXConstructor(
+    const CXXConstructorDecl *ctor, CXXCtorType ctorType,
+    const CGFunctionInfo *fnInfo, bool DontDefer) {
+  return getAddrOfCXXStructor(ctor, getFromCtorType(ctorType), fnInfo, nullptr,
+                              DontDefer);
+}
+
 void CodeGenModule::EmitCXXDestructor(const CXXDestructorDecl *dtor,
                                       CXXDtorType dtorType) {
   // The complete destructor is equivalent to the base destructor for
@@ -270,7 +283,7 @@ void CodeGenModule::EmitCXXDestructor(const CXXDestructorDecl *dtor,
     return;
 
   const CGFunctionInfo &fnInfo =
-    getTypes().arrangeCXXDestructor(dtor, dtorType);
+      getTypes().arrangeCXXStructorDeclaration(dtor, getFromDtorType(dtorType));
 
   auto *fn = cast<llvm::Function>(
       GetAddrOfCXXDestructor(dtor, dtorType, &fnInfo, nullptr, true));
@@ -288,19 +301,8 @@ CodeGenModule::GetAddrOfCXXDestructor(const CXXDestructorDecl *dtor,
                                       const CGFunctionInfo *fnInfo,
                                       llvm::FunctionType *fnType,
                                       bool DontDefer) {
-  GlobalDecl GD(dtor, dtorType);
-
-  StringRef name = getMangledName(GD);
-  if (llvm::GlobalValue *existing = GetGlobalValue(name))
-    return existing;
-
-  if (!fnType) {
-    if (!fnInfo) fnInfo = &getTypes().arrangeCXXDestructor(dtor, dtorType);
-    fnType = getTypes().GetFunctionType(*fnInfo);
-  }
-  return cast<llvm::Function>(GetOrCreateLLVMFunction(name, fnType, GD,
-                                                      /*ForVTable=*/false,
-                                                      DontDefer));
+  return getAddrOfCXXStructor(dtor, getFromDtorType(dtorType), fnInfo, fnType,
+                              DontDefer);
 }
 
 static llvm::Value *BuildAppleKextVirtualCall(CodeGenFunction &CGF,
@@ -360,8 +362,8 @@ CodeGenFunction::BuildAppleKextVirtualDestructorCall(
   // -O does that. But need to support -O0 as well.
   if (MD->isVirtual() && Type != Dtor_Base) {
     // Compute the function type we're calling.
-    const CGFunctionInfo &FInfo =
-      CGM.getTypes().arrangeCXXDestructor(DD, Dtor_Complete);
+    const CGFunctionInfo &FInfo = CGM.getTypes().arrangeCXXStructorDeclaration(
+        DD, StructorType::Complete);
     llvm::Type *Ty = CGM.getTypes().GetFunctionType(FInfo);
     return ::BuildAppleKextVirtualCall(*this, GlobalDecl(DD, Type), Ty, RD);
   }
diff --git a/lib/CodeGen/CGCXXABI.h b/lib/CodeGen/CGCXXABI.h
index 39813fd..fe33179 100644
--- a/lib/CodeGen/CGCXXABI.h
+++ b/lib/CodeGen/CGCXXABI.h
@@ -241,20 +241,6 @@ public:
                                                  const CXXRecordDecl *ClassDecl,
                                         const CXXRecordDecl *BaseClassDecl) = 0;
 
-  /// Build the signature of the given constructor variant by adding
-  /// any required parameters.  For convenience, ArgTys has been initialized
-  /// with the type of 'this' and ResTy has been initialized with the type of
-  /// 'this' if HasThisReturn(GlobalDecl(Ctor, T)) is true or 'void' otherwise
-  /// (although both may be changed by the ABI).
-  ///
-  /// If there are ever any ABIs where the implicit parameters are
-  /// intermixed with the formal parameters, we can address those
-  /// then.
-  virtual void BuildConstructorSignature(const CXXConstructorDecl *Ctor,
-                                         CXXCtorType T,
-                                         CanQualType &ResTy,
-                               SmallVectorImpl<CanQualType> &ArgTys) = 0;
-
   virtual llvm::BasicBlock *EmitCtorCompleteObjectHandler(CodeGenFunction &CGF,
                                                           const CXXRecordDecl *RD);
 
@@ -267,15 +253,11 @@ public:
   /// Emit constructor variants required by this ABI.
   virtual void EmitCXXConstructors(const CXXConstructorDecl *D) = 0;
 
-  /// Build the signature of the given destructor variant by adding
-  /// any required parameters.  For convenience, ArgTys has been initialized
-  /// with the type of 'this' and ResTy has been initialized with the type of
-  /// 'this' if HasThisReturn(GlobalDecl(Dtor, T)) is true or 'void' otherwise
-  /// (although both may be changed by the ABI).
-  virtual void BuildDestructorSignature(const CXXDestructorDecl *Dtor,
-                                        CXXDtorType T,
-                                        CanQualType &ResTy,
-                               SmallVectorImpl<CanQualType> &ArgTys) = 0;
+  /// Build the signature of the given constructor or destructor variant by
+  /// adding any required parameters.  For convenience, ArgTys has been
+  /// initialized with the type of 'this'.
+  virtual void buildStructorSignature(const CXXMethodDecl *MD, StructorType T,
+                                      SmallVectorImpl<CanQualType> &ArgTys) = 0;
 
   /// Returns true if the given destructor type should be emitted as a linkonce
   /// delegating thunk, regardless of whether the dtor is defined in this TU or
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp
index ce16d3b..cc4a02e 100644
--- a/lib/CodeGen/CGCall.cpp
+++ b/lib/CodeGen/CGCall.cpp
@@ -181,30 +181,35 @@ CodeGenTypes::arrangeCXXMethodDeclaration(const CXXMethodDecl *MD) {
   return arrangeFreeFunctionType(prototype);
 }
 
-/// Arrange the argument and result information for a declaration
-/// or definition to the given constructor variant.
 const CGFunctionInfo &
-CodeGenTypes::arrangeCXXConstructorDeclaration(const CXXConstructorDecl *D,
-                                               CXXCtorType ctorKind) {
+CodeGenTypes::arrangeCXXStructorDeclaration(const CXXMethodDecl *MD,
+                                            StructorType Type) {
+
   SmallVector<CanQualType, 16> argTypes;
-  argTypes.push_back(GetThisType(Context, D->getParent()));
+  argTypes.push_back(GetThisType(Context, MD->getParent()));
 
-  GlobalDecl GD(D, ctorKind);
-  CanQualType resultType =
-    TheCXXABI.HasThisReturn(GD) ? argTypes.front() : Context.VoidTy;
+  GlobalDecl GD;
+  if (auto *CD = dyn_cast<CXXConstructorDecl>(MD)) {
+    GD = GlobalDecl(CD, toCXXCtorType(Type));
+  } else {
+    auto *DD = dyn_cast<CXXDestructorDecl>(MD);
+    GD = GlobalDecl(DD, toCXXDtorType(Type));
+  }
 
-  CanQual<FunctionProtoType> FTP = GetFormalType(D);
+  CanQual<FunctionProtoType> FTP = GetFormalType(MD);
 
   // Add the formal parameters.
   for (unsigned i = 0, e = FTP->getNumParams(); i != e; ++i)
     argTypes.push_back(FTP->getParamType(i));
 
-  TheCXXABI.BuildConstructorSignature(D, ctorKind, resultType, argTypes);
+  TheCXXABI.buildStructorSignature(MD, Type, argTypes);
 
   RequiredArgs required =
-      (D->isVariadic() ? RequiredArgs(argTypes.size()) : RequiredArgs::All);
+      (MD->isVariadic() ? RequiredArgs(argTypes.size()) : RequiredArgs::All);
 
   FunctionType::ExtInfo extInfo = FTP->getExtInfo();
+  CanQualType resultType =
+      TheCXXABI.HasThisReturn(GD) ? argTypes.front() : Context.VoidTy;
   return arrangeLLVMFunctionInfo(resultType, true, argTypes, extInfo, required);
 }
 
@@ -229,30 +234,6 @@ CodeGenTypes::arrangeCXXConstructorCall(const CallArgList &args,
   return arrangeLLVMFunctionInfo(ResultType, true, ArgTypes, Info, Required);
 }
 
-/// Arrange the argument and result information for a declaration,
-/// definition, or call to the given destructor variant.  It so
-/// happens that all three cases produce the same information.
-const CGFunctionInfo &
-CodeGenTypes::arrangeCXXDestructor(const CXXDestructorDecl *D,
-                                   CXXDtorType dtorKind) {
-  SmallVector<CanQualType, 2> argTypes;
-  argTypes.push_back(GetThisType(Context, D->getParent()));
-
-  GlobalDecl GD(D, dtorKind);
-  CanQualType resultType =
-    TheCXXABI.HasThisReturn(GD) ? argTypes.front() : Context.VoidTy;
-
-  TheCXXABI.BuildDestructorSignature(D, dtorKind, resultType, argTypes);
-
-  CanQual<FunctionProtoType> FTP = GetFormalType(D);
-  assert(FTP->getNumParams() == 0 && "dtor with formal parameters");
-  assert(FTP->isVariadic() == 0 && "dtor with formal parameters");
-
-  FunctionType::ExtInfo extInfo = FTP->getExtInfo();
-  return arrangeLLVMFunctionInfo(resultType, true, argTypes, extInfo,
-                                 RequiredArgs::All);
-}
-
 /// Arrange the argument and result information for the declaration or
 /// definition of the given function.
 const CGFunctionInfo &
@@ -324,10 +305,10 @@ CodeGenTypes::arrangeGlobalDeclaration(GlobalDecl GD) {
   const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
 
   if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD))
-    return arrangeCXXConstructorDeclaration(CD, GD.getCtorType());
+    return arrangeCXXStructorDeclaration(CD, getFromCtorType(GD.getCtorType()));
 
   if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(FD))
-    return arrangeCXXDestructor(DD, GD.getDtorType());
+    return arrangeCXXStructorDeclaration(DD, getFromDtorType(GD.getDtorType()));
 
   return arrangeFunctionDeclaration(FD);
 }
@@ -1029,7 +1010,8 @@ llvm::Type *CodeGenTypes::GetFunctionTypeForVTable(GlobalDecl GD) {
     
   const CGFunctionInfo *Info;
   if (isa<CXXDestructorDecl>(MD))
-    Info = &arrangeCXXDestructor(cast<CXXDestructorDecl>(MD), GD.getDtorType());
+    Info =
+        &arrangeCXXStructorDeclaration(MD, getFromDtorType(GD.getDtorType()));
   else
     Info = &arrangeCXXMethodDeclaration(MD);
   return GetFunctionType(*Info);
diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp
index 5a033de..3277b41 100644
--- a/lib/CodeGen/CGClass.cpp
+++ b/lib/CodeGen/CGClass.cpp
@@ -1758,7 +1758,8 @@ CodeGenFunction::EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor,
   }
 
   llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(Ctor, CtorType);
-  EmitCall(CGM.getTypes().arrangeCXXConstructorDeclaration(Ctor, CtorType),
+  EmitCall(CGM.getTypes()
+               .arrangeCXXStructorDeclaration(Ctor, getFromCtorType(CtorType)),
            Callee, ReturnValueSlot(), DelegateArgs, Ctor);
 }
 
diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp
index db876b1..937a043 100644
--- a/lib/CodeGen/CGExprCXX.cpp
+++ b/lib/CodeGen/CGExprCXX.cpp
@@ -170,11 +170,11 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE,
   const CXXMethodDecl *CalleeDecl = DevirtualizedMethod ? DevirtualizedMethod : MD;
   const CGFunctionInfo *FInfo = nullptr;
   if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(CalleeDecl))
-    FInfo = &CGM.getTypes().arrangeCXXDestructor(Dtor,
-                                                 Dtor_Complete);
+    FInfo = &CGM.getTypes().arrangeCXXStructorDeclaration(
+        Dtor, StructorType::Complete);
   else if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(CalleeDecl))
-    FInfo = &CGM.getTypes().arrangeCXXConstructorDeclaration(Ctor,
-                                                             Ctor_Complete);
+    FInfo = &CGM.getTypes().arrangeCXXStructorDeclaration(
+        Ctor, StructorType::Complete);
   else
     FInfo = &CGM.getTypes().arrangeCXXMethodDeclaration(CalleeDecl);
 
diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h
index 985e536..452553f 100644
--- a/lib/CodeGen/CodeGenModule.h
+++ b/lib/CodeGen/CodeGenModule.h
@@ -803,6 +803,13 @@ public:
   QualType getObjCFastEnumerationStateType();
   
   /// Return the address of the constructor of the given type.
+
+  llvm::GlobalValue *
+  getAddrOfCXXStructor(const CXXMethodDecl *MD, StructorType Type,
+                       const CGFunctionInfo *FnInfo = nullptr,
+                       llvm::FunctionType *FnType = nullptr,
+                       bool DontDefer = false);
+
   llvm::GlobalValue *
   GetAddrOfCXXConstructor(const CXXConstructorDecl *ctor, CXXCtorType ctorType,
                           const CGFunctionInfo *fnInfo = nullptr,
diff --git a/lib/CodeGen/CodeGenTypes.h b/lib/CodeGen/CodeGenTypes.h
index b1c9dad..088fb69 100644
--- a/lib/CodeGen/CodeGenTypes.h
+++ b/lib/CodeGen/CodeGenTypes.h
@@ -56,6 +56,56 @@ class CGRecordLayout;
 class CodeGenModule;
 class RequiredArgs;
 
+enum class StructorType {
+  Complete, // constructor or destructor
+  Base,     // constructor or destructor
+  Deleting  // destructor only
+};
+
+inline CXXCtorType toCXXCtorType(StructorType T) {
+  switch (T) {
+  case StructorType::Complete:
+    return Ctor_Complete;
+  case StructorType::Base:
+    return Ctor_Base;
+  case StructorType::Deleting:
+    llvm_unreachable("foo");
+  }
+}
+
+inline StructorType getFromCtorType(CXXCtorType T) {
+  switch (T) {
+  case Ctor_Complete:
+    return StructorType::Complete;
+  case Ctor_Base:
+    return StructorType::Base;
+  case Ctor_CompleteAllocating:
+    llvm_unreachable("foo");
+  }
+}
+
+inline CXXDtorType toCXXDtorType(StructorType T) {
+  switch (T) {
+  case StructorType::Complete:
+    return Dtor_Complete;
+  case StructorType::Base:
+    return Dtor_Base;
+  case StructorType::Deleting:
+    return Dtor_Deleting;
+  }
+}
+
+inline StructorType getFromDtorType(CXXDtorType T) {
+  switch (T) {
+  case Dtor_Deleting:
+    return StructorType::Deleting;
+  case Dtor_Complete:
+    return StructorType::Complete;
+  case Dtor_Base:
+    return StructorType::Base;
+  }
+}
+
 /// CodeGenTypes - This class organizes the cross-module state that is used
 /// while lowering AST types to LLVM types.
 class CodeGenTypes {
@@ -185,16 +235,12 @@ public:
                                                         QualType receiverType);
 
   const CGFunctionInfo &arrangeCXXMethodDeclaration(const CXXMethodDecl *MD);
-  const CGFunctionInfo &arrangeCXXConstructorDeclaration(
-                                                    const CXXConstructorDecl *D,
-                                                    CXXCtorType Type);
+  const CGFunctionInfo &arrangeCXXStructorDeclaration(const CXXMethodDecl *MD,
+                                                      StructorType Type);
   const CGFunctionInfo &arrangeCXXConstructorCall(const CallArgList &Args,
                                                   const CXXConstructorDecl *D,
                                                   CXXCtorType CtorKind,
                                                   unsigned ExtraArgs);
-  const CGFunctionInfo &arrangeCXXDestructor(const CXXDestructorDecl *D,
-                                             CXXDtorType Type);
-
   const CGFunctionInfo &arrangeFreeFunctionCall(const CallArgList &Args,
                                                 const FunctionType *Ty);
   const CGFunctionInfo &arrangeFreeFunctionCall(QualType ResTy,
diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp
index f861af3..60b6ecd 100644
--- a/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/lib/CodeGen/ItaniumCXXABI.cpp
@@ -138,15 +138,10 @@ public:
                               const CXXRecordDecl *ClassDecl,
                               const CXXRecordDecl *BaseClassDecl) override;
 
-  void BuildConstructorSignature(const CXXConstructorDecl *Ctor,
-                                 CXXCtorType T, CanQualType &ResTy,
-                                 SmallVectorImpl<CanQualType> &ArgTys) override;
-
   void EmitCXXConstructors(const CXXConstructorDecl *D) override;
 
-  void BuildDestructorSignature(const CXXDestructorDecl *Dtor,
-                                CXXDtorType T, CanQualType &ResTy,
-                                SmallVectorImpl<CanQualType> &ArgTys) override;
+  void buildStructorSignature(const CXXMethodDecl *MD, StructorType T,
+                              SmallVectorImpl<CanQualType> &ArgTys) override;
 
   bool useThunkForDtorVariant(const CXXDestructorDecl *Dtor,
                               CXXDtorType DT) const override {
@@ -1066,23 +1061,6 @@ ItaniumCXXABI::GetVirtualBaseClassOffset(CodeGenFunction &CGF,
   return VBaseOffset;
 }
 
-/// The generic ABI passes 'this', plus a VTT if it's initializing a
-/// base subobject.
-void
-ItaniumCXXABI::BuildConstructorSignature(const CXXConstructorDecl *Ctor,
-                                         CXXCtorType Type, CanQualType &ResTy,
-                                         SmallVectorImpl<CanQualType> &ArgTys) {
-  ASTContext &Context = getContext();
-
-  // All parameters are already in place except VTT, which goes after 'this'.
-  // These are Clang types, so we don't need to worry about sret yet.
-
-  // Check if we need to add a VTT parameter (which has type void **).
-  if (Type == Ctor_Base && Ctor->getParent()->getNumVBases() != 0)
-    ArgTys.insert(ArgTys.begin() + 1,
-                  Context.getPointerType(Context.VoidPtrTy));
-}
-
 void ItaniumCXXABI::EmitCXXConstructors(const CXXConstructorDecl *D) {
   // Just make sure we're in sync with TargetCXXABI.
   assert(CGM.getTarget().getCXXABI().hasConstructorVariants());
@@ -1099,20 +1077,18 @@ void ItaniumCXXABI::EmitCXXConstructors(const CXXConstructorDecl *D) {
   }
 }
 
-/// The generic ABI passes 'this', plus a VTT if it's destroying a
-/// base subobject.
-void ItaniumCXXABI::BuildDestructorSignature(const CXXDestructorDecl *Dtor,
-                                             CXXDtorType Type,
-                                             CanQualType &ResTy,
-                                SmallVectorImpl<CanQualType> &ArgTys) {
+void
+ItaniumCXXABI::buildStructorSignature(const CXXMethodDecl *MD, StructorType T,
+                                      SmallVectorImpl<CanQualType> &ArgTys) {
   ASTContext &Context = getContext();
 
-  // 'this' parameter is already there, as well as 'this' return if
-  // HasThisReturn(GlobalDecl(Dtor, Type)) is true
+  // All parameters are already in place except VTT, which goes after 'this'.
+  // These are Clang types, so we don't need to worry about sret yet.
 
   // Check if we need to add a VTT parameter (which has type void **).
-  if (Type == Dtor_Base && Dtor->getParent()->getNumVBases() != 0)
-    ArgTys.push_back(Context.getPointerType(Context.VoidPtrTy));
+  if (T == StructorType::Base && MD->getParent()->getNumVBases() != 0)
+    ArgTys.insert(ArgTys.begin() + 1,
+                  Context.getPointerType(Context.VoidPtrTy));
 }
 
 void ItaniumCXXABI::EmitCXXDestructors(const CXXDestructorDecl *D) {
@@ -1346,8 +1322,8 @@ void ItaniumCXXABI::EmitVirtualDestructorCall(CodeGenFunction &CGF,
   assert(CE == nullptr || CE->arg_begin() == CE->arg_end());
   assert(DtorType == Dtor_Deleting || DtorType == Dtor_Complete);
 
-  const CGFunctionInfo *FInfo
-    = &CGM.getTypes().arrangeCXXDestructor(Dtor, DtorType);
+  const CGFunctionInfo *FInfo = &CGM.getTypes().arrangeCXXStructorDeclaration(
+      Dtor, getFromDtorType(DtorType));
   llvm::Type *Ty = CGF.CGM.getTypes().GetFunctionType(*FInfo);
   llvm::Value *Callee =
       getVirtualFunctionPointer(CGF, GlobalDecl(Dtor, DtorType), This, Ty);
diff --git a/lib/CodeGen/MicrosoftCXXABI.cpp b/lib/CodeGen/MicrosoftCXXABI.cpp
index 134f0b7..b3074de 100644
--- a/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -89,10 +89,6 @@ public:
                             const CXXRecordDecl *ClassDecl,
                             const CXXRecordDecl *BaseClassDecl) override;
 
-  void BuildConstructorSignature(const CXXConstructorDecl *Ctor,
-                                 CXXCtorType Type, CanQualType &ResTy,
-                                 SmallVectorImpl<CanQualType> &ArgTys) override;
-
   llvm::BasicBlock *
   EmitCtorCompleteObjectHandler(CodeGenFunction &CGF,
                                 const CXXRecordDecl *RD) override;
@@ -134,10 +130,8 @@ public:
   // lacks a definition for the destructor, non-base destructors must always
   // delegate to or alias the base destructor.
 
-  void BuildDestructorSignature(const CXXDestructorDecl *Dtor,
-                                CXXDtorType Type,
-                                CanQualType &ResTy,
-                                SmallVectorImpl<CanQualType> &ArgTys) override;
+  void buildStructorSignature(const CXXMethodDecl *MD, StructorType T,
+                              SmallVectorImpl<CanQualType> &ArgTys) override;
 
   /// Non-base dtors should be emitted as delegating thunks in this ABI.
   bool useThunkForDtorVariant(const CXXDestructorDecl *Dtor,
@@ -785,23 +779,6 @@ bool MicrosoftCXXABI::classifyReturnType(CGFunctionInfo &FI) const {
   return false;
 }
 
-void MicrosoftCXXABI::BuildConstructorSignature(
-    const CXXConstructorDecl *Ctor, CXXCtorType Type, CanQualType &ResTy,
-    SmallVectorImpl<CanQualType> &ArgTys) {
-
-  // All parameters are already in place except is_most_derived, which goes
-  // after 'this' if it's variadic and last if it's not.
-
-  const CXXRecordDecl *Class = Ctor->getParent();
-  const FunctionProtoType *FPT = Ctor->getType()->castAs<FunctionProtoType>();
-  if (Class->getNumVBases()) {
-    if (FPT->isVariadic())
-      ArgTys.insert(ArgTys.begin() + 1, CGM.getContext().IntTy);
-    else
-      ArgTys.push_back(CGM.getContext().IntTy);
-  }
-}
-
 llvm::BasicBlock *
 MicrosoftCXXABI::EmitCtorCompleteObjectHandler(CodeGenFunction &CGF,
                                                const CXXRecordDecl *RD) {
@@ -910,18 +887,29 @@ void MicrosoftCXXABI::EmitVBPtrStores(CodeGenFunction &CGF,
   }
 }
 
-void MicrosoftCXXABI::BuildDestructorSignature(const CXXDestructorDecl *Dtor,
-                                               CXXDtorType Type,
-                                               CanQualType &ResTy,
+void
+MicrosoftCXXABI::buildStructorSignature(const CXXMethodDecl *MD, StructorType T,
                                         SmallVectorImpl<CanQualType> &ArgTys) {
-  // 'this' is already in place
-
   // TODO: 'for base' flag
-
-  if (Type == Dtor_Deleting) {
+  if (T == StructorType::Deleting) {
     // The scalar deleting destructor takes an implicit int parameter.
     ArgTys.push_back(CGM.getContext().IntTy);
   }
+  auto *CD = dyn_cast<CXXConstructorDecl>(MD);
+  if (!CD)
+    return;
+
+  // All parameters are already in place except is_most_derived, which goes
+  // after 'this' if it's variadic and last if it's not.
+
+  const CXXRecordDecl *Class = CD->getParent();
+  const FunctionProtoType *FPT = CD->getType()->castAs<FunctionProtoType>();
+  if (Class->getNumVBases()) {
+    if (FPT->isVariadic())
+      ArgTys.insert(ArgTys.begin() + 1, CGM.getContext().IntTy);
+    else
+      ArgTys.push_back(CGM.getContext().IntTy);
+  }
 }
 
 void MicrosoftCXXABI::EmitCXXDestructors(const CXXDestructorDecl *D) {
@@ -1387,8 +1375,8 @@ void MicrosoftCXXABI::EmitVirtualDestructorCall(CodeGenFunction &CGF,
   // We have only one destructor in the vftable but can get both behaviors
   // by passing an implicit int parameter.
   GlobalDecl GD(Dtor, Dtor_Deleting);
-  const CGFunctionInfo *FInfo =
-      &CGM.getTypes().arrangeCXXDestructor(Dtor, Dtor_Deleting);
+  const CGFunctionInfo *FInfo = &CGM.getTypes().arrangeCXXStructorDeclaration(
+      Dtor, StructorType::Deleting);
   llvm::Type *Ty = CGF.CGM.getTypes().GetFunctionType(*FInfo);
   llvm::Value *Callee = getVirtualFunctionPointer(CGF, GD, This, Ty);
 
diff --git a/include/clang/AST/Mangle.h b/include/clang/AST/Mangle.h
index a8d1199..9423582 100644
--- a/include/clang/AST/Mangle.h
+++ b/include/clang/AST/Mangle.h
@@ -111,6 +111,8 @@ public:
                              raw_ostream &) = 0;
   virtual void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type,
                              raw_ostream &) = 0;
+  virtual void mangleCXXCtorComdat(const CXXConstructorDecl *D, raw_ostream &);
+  virtual void mangleCXXDtorComdat(const CXXDestructorDecl *D, raw_ostream &);
   virtual void mangleStringLiteral(const StringLiteral *SL, raw_ostream &) = 0;
 
   void mangleGlobalBlock(const BlockDecl *BD,
diff --git a/include/clang/Basic/ABI.h b/include/clang/Basic/ABI.h
index a3aad4b..fcb6b21 100644
--- a/include/clang/Basic/ABI.h
+++ b/include/clang/Basic/ABI.h
@@ -27,6 +27,8 @@ enum CXXCtorType {
     Ctor_CompleteAllocating ///< Complete object allocating ctor
 };
 
+enum CXXCtorComdatType { Ctor_Comdat = Ctor_CompleteAllocating + 1 };
+
 /// \brief C++ destructor types.
 enum CXXDtorType {
     Dtor_Deleting, ///< Deleting dtor
@@ -34,6 +36,8 @@ enum CXXDtorType {
     Dtor_Base      ///< Base object dtor
 };
 
+enum CXXDtorComdatType { Dtor_Comdat = Dtor_Base + 1 };
+
 /// \brief A return adjustment.
 struct ReturnAdjustment {
   /// \brief The non-virtual adjustment from the derived object to its
diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp
index 486fab3..3698508 100644
--- a/lib/AST/ItaniumMangle.cpp
+++ b/lib/AST/ItaniumMangle.cpp
@@ -149,7 +149,8 @@ public:
                      raw_ostream &) override;
   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,
@@ -261,13 +262,13 @@ public:
                   !isa<CXXConstructorDecl>(D)));
   }
   CXXNameMangler(ItaniumMangleContextImpl &C, raw_ostream &Out_,
-                 const CXXConstructorDecl *D, CXXCtorType Type)
-    : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type),
-      SeqID(0) { }
+                 const CXXConstructorDecl *D, unsigned Type)
+      : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type),
+        SeqID(0) {}
   CXXNameMangler(ItaniumMangleContextImpl &C, raw_ostream &Out_,
-                 const CXXDestructorDecl *D, CXXDtorType Type)
-    : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type),
-      SeqID(0) { }
+                 const CXXDestructorDecl *D, unsigned Type)
+      : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type),
+        SeqID(0) {}
 
 #if MANGLE_CHECKER
   ~CXXNameMangler() {
@@ -374,8 +375,8 @@ private:
                         DeclarationName name,
                         unsigned knownArity);
   void mangleExpression(const Expr *E, unsigned Arity = UnknownArity);
-  void mangleCXXCtorType(CXXCtorType T);
-  void mangleCXXDtorType(CXXDtorType T);
+  void mangleCXXCtorType(unsigned T);
+  void mangleCXXDtorType(unsigned T);
 
   void mangleTemplateArgs(const ASTTemplateArgumentListInfo &TemplateArgs);
   void mangleTemplateArgs(const TemplateArgument *TemplateArgs,
@@ -1188,7 +1189,7 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
     if (ND == Structor)
       // If the named decl is the C++ constructor we're mangling, use the type
       // we were given.
-      mangleCXXCtorType(static_cast<CXXCtorType>(StructorType));
+      mangleCXXCtorType(StructorType);
     else
       // Otherwise, use the complete constructor name. This is relevant if a
       // class with a constructor is declared within a constructor.
@@ -1199,7 +1200,7 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
     if (ND == Structor)
       // If the named decl is the C++ destructor we're mangling, use the type we
       // were given.
-      mangleCXXDtorType(static_cast<CXXDtorType>(StructorType));
+      mangleCXXDtorType(StructorType);
     else
       // Otherwise, use the complete destructor name. This is relevant if a
       // class with a destructor is declared within a destructor.
@@ -3246,12 +3247,15 @@ void CXXNameMangler::mangleFunctionParam(const ParmVarDecl *parm) {
   Out << '_';
 }
 
-void CXXNameMangler::mangleCXXCtorType(CXXCtorType T) {
+void CXXNameMangler::mangleCXXCtorType(unsigned 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) {
+  default:
+    llvm_unreachable("unsupported type");
   case Ctor_Complete:
     Out << "C1";
     break;
@@ -3261,15 +3265,21 @@ void CXXNameMangler::mangleCXXCtorType(CXXCtorType T) {
   case Ctor_CompleteAllocating:
     Out << "C3";
     break;
+  case Ctor_Comdat:
+    Out << "C5";
+    break;
   }
 }
 
-void CXXNameMangler::mangleCXXDtorType(CXXDtorType T) {
+void CXXNameMangler::mangleCXXDtorType(unsigned T) {
   // <ctor-dtor-name> ::= D0  # deleting destructor
   //                  ::= D1  # complete object destructor
   //                  ::= D2  # base object destructor
   //
+  // In addition, C5 is a comdat name with C1 and C2 in it.
   switch (T) {
+  default:
+    llvm_unreachable("unsupported type");
   case Dtor_Deleting:
     Out << "D0";
     break;
@@ -3279,6 +3289,9 @@ void CXXNameMangler::mangleCXXDtorType(CXXDtorType T) {
   case Dtor_Base:
     Out << "D2";
     break;
+  case Dtor_Comdat:
+    Out << "D6";
+    break;
   }
 }
 
@@ -3689,6 +3702,18 @@ void ItaniumMangleContextImpl::mangleCXXDtor(const CXXDestructorDecl *D,
   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) {
diff --git a/lib/AST/Mangle.cpp b/lib/AST/Mangle.cpp
index fdc00e3..bbc72a4 100644
--- a/lib/AST/Mangle.cpp
+++ b/lib/AST/Mangle.cpp
@@ -90,6 +90,16 @@ static StdOrFastCC getStdOrFastCallMangling(const ASTContext &Context,
   }
 }
 
+void MangleContext::mangleCXXCtorComdat(const CXXConstructorDecl *D,
+                                        raw_ostream &Out) {
+  llvm_unreachable("Should not be used by this mangling");
+}
+
+void MangleContext::mangleCXXDtorComdat(const CXXDestructorDecl *D,
+                                        raw_ostream &Out) {
+  llvm_unreachable("Should not be used by this mangling");
+}
+
 bool MangleContext::shouldMangleDeclName(const NamedDecl *D) {
   const ASTContext &ASTContext = getASTContext();
 
diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp
index 583017c..94801c6 100644
--- a/lib/CodeGen/CGCXX.cpp
+++ b/lib/CodeGen/CGCXX.cpp
@@ -102,16 +102,14 @@ bool CodeGenModule::TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D) {
     return true;
 
   return TryEmitDefinitionAsAlias(GlobalDecl(D, Dtor_Base),
-                                  GlobalDecl(BaseD, Dtor_Base),
-                                  false);
+                                  GlobalDecl(BaseD, Dtor_Base));
 }
 
 /// Try to emit a definition as a global alias for another definition.
 /// If \p InEveryTU is true, we know that an equivalent alias can be produced
 /// in every translation unit.
 bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl,
-                                             GlobalDecl TargetDecl,
-                                             bool InEveryTU) {
+                                             GlobalDecl TargetDecl) {
   if (!getCodeGenOpts().CXXCtorDtorAliases)
     return true;
 
@@ -160,13 +158,11 @@ bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl,
     return false;
   }
 
-  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;
-  }
+  /// 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;
 
   // Don't create an alias to a linker weak symbol. This avoids producing
   // different COMDATs in different TUs. Another option would be to
@@ -196,33 +192,95 @@ bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl,
   return false;
 }
 
-void CodeGenModule::EmitCXXConstructor(const CXXConstructorDecl *ctor,
-                                       CXXCtorType ctorType) {
-  if (!getTarget().getCXXABI().hasConstructorVariants()) {
-    // If there are no constructor variants, always emit the complete destructor.
-    ctorType = Ctor_Complete;
-  } else if (!ctor->getParent()->getNumVBases() &&
-             (ctorType == Ctor_Complete || ctorType == Ctor_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 =
-        !TryEmitDefinitionAsAlias(GlobalDecl(ctor, Ctor_Complete),
-                                  GlobalDecl(ctor, Ctor_Base), true);
-    if (ctorType == Ctor_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 constructor is equivalent to the base constructor
+  // for classes with no virtual bases.
+  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);
 
-  const CGFunctionInfo &fnInfo =
-      getTypes().arrangeCXXStructorDeclaration(ctor, getFromCtorType(ctorType));
+  if (llvm::GlobalValue::isDiscardableIfUnused(Linkage))
+    return StructorCodegen::RAUW;
 
-  auto *fn = cast<llvm::Function>(
-      GetAddrOfCXXConstructor(ctor, ctorType, &fnInfo, true));
-  setFunctionLinkage(GlobalDecl(ctor, ctorType), fn);
+  // FIXME: Should we allow available_externally aliases?
+  if (!llvm::GlobalAlias::isValidLinkage(Linkage))
+    return StructorCodegen::RAUW;
 
-  CodeGenFunction(*this).GenerateCode(GlobalDecl(ctor, ctorType), fn, fnInfo);
+  if (llvm::GlobalValue::isWeakForLinker(Linkage))
+    return StructorCodegen::COMDAT;
 
-  setFunctionDefinitionAttributes(ctor, fn);
-  SetLLVMFunctionAttributesForDefinition(ctor, fn);
+  return StructorCodegen::Alias;
+}
+
+void CodeGenModule::emitConstructorDestructorAlias(GlobalDecl AliasDecl,
+                                                   GlobalDecl TargetDecl) {
+  llvm::GlobalValue::LinkageTypes Linkage = getFunctionLinkage(AliasDecl);
+
+  StringRef MangledName = getMangledName(AliasDecl);
+  llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
+  if (Entry && !Entry->isDeclaration())
+    return;
+
+  auto *Aliasee = cast<llvm::GlobalValue>(GetAddrOfGlobal(TargetDecl));
+  llvm::PointerType *AliasType = Aliasee->getType();
+
+  // Create the alias with no name.
+  auto *Alias = llvm::GlobalAlias::create(AliasType->getElementType(), 0,
+                                          Linkage, "", Aliasee, &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.
+  SetCommonAttributes(cast<NamedDecl>(AliasDecl.getDecl()), Alias);
+}
+
+llvm::Function *CodeGenModule::codegenCXXStructor(const CXXMethodDecl *MD,
+                                                  StructorType Type) {
+  const CGFunctionInfo &FnInfo =
+      getTypes().arrangeCXXStructorDeclaration(MD, Type);
+  auto *Fn = cast<llvm::Function>(
+      getAddrOfCXXStructor(MD, Type, &FnInfo, nullptr, true));
+  if (!Fn->isDeclaration())
+    return Fn;
+
+  GlobalDecl GD;
+  if (const auto *DD = dyn_cast<CXXDestructorDecl>(MD)) {
+    GD = GlobalDecl(DD, toCXXDtorType(Type));
+  } else {
+    const auto *CD = cast<CXXConstructorDecl>(MD);
+    GD = GlobalDecl(CD, toCXXCtorType(Type));
+  }
+
+  setFunctionLinkage(GD, Fn);
+  CodeGenFunction(*this).GenerateCode(GD, Fn, FnInfo);
+  setFunctionDefinitionAttributes(MD, Fn);
+  SetLLVMFunctionAttributesForDefinition(MD, Fn);
+  return Fn;
 }
 
 llvm::GlobalValue *CodeGenModule::getAddrOfCXXStructor(
@@ -258,20 +316,57 @@ llvm::GlobalValue *CodeGenModule::GetAddrOfCXXConstructor(
                               DontDefer);
 }
 
-void CodeGenModule::EmitCXXDestructor(const CXXDestructorDecl *dtor,
-                                      CXXDtorType 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 == Dtor_Complete || dtorType == Dtor_Base)) {
-    bool ProducedAlias =
-        !TryEmitDefinitionAsAlias(GlobalDecl(dtor, Dtor_Complete),
-                                  GlobalDecl(dtor, Dtor_Base), true);
-    if (ProducedAlias) {
-      if (dtorType == Dtor_Complete)
-        return;
-      if (dtor->isVirtual())
-        getVTables().EmitThunks(GlobalDecl(dtor, Dtor_Complete));
+void CodeGenModule::emitCXXStructor(const CXXMethodDecl *MD,
+                                    StructorType Type) {
+  if (Type == StructorType::Deleting) {
+    codegenCXXStructor(MD, StructorType::Deleting);
+    return;
+  }
+  assert(Type == StructorType::Complete || Type == StructorType::Base);
+
+  auto *CD = dyn_cast<CXXConstructorDecl>(MD);
+  const CXXDestructorDecl *DD = nullptr;
+  if (CD) {
+    // If there are no constructor variants, always emit the complete
+    // destructor.
+    if (!getTarget().getCXXABI().hasConstructorVariants()) {
+      codegenCXXStructor(CD, StructorType::Complete);
+      return;
+    }
+  } else {
+    DD = cast<CXXDestructorDecl>(MD);
+  }
+
+  StructorCodegen CompleteCG = getCodegenToUse(*this, MD);
+  if (CompleteCG == StructorCodegen::COMDAT) {
+    // Make sure both are emitted.
+    if (Type == StructorType::Complete)
+      getAddrOfCXXStructor(MD, StructorType::Base);
+    else
+      getAddrOfCXXStructor(MD, StructorType::Complete);
+  }
+
+  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 (CompleteCG == StructorCodegen::Alias ||
+        CompleteCG == StructorCodegen::COMDAT) {
+      emitConstructorDestructorAlias(CompleteDecl, BaseDecl);
+      return;
+    }
+    if (CompleteCG == StructorCodegen::RAUW) {
+      StringRef MangledName = getMangledName(CompleteDecl);
+      auto *Aliasee = cast<llvm::GlobalValue>(GetAddrOfGlobal(BaseDecl));
+      Replacements[MangledName] = Aliasee;
+      return;
     }
   }
 
@@ -279,20 +374,24 @@ void CodeGenModule::EmitCXXDestructor(const CXXDestructorDecl *dtor,
   // 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 == Dtor_Base && !TryEmitBaseDestructorAsAlias(dtor))
+  // FIXME: not if COMDAT...
+  if (DD && Type == StructorType::Base &&
+      CompleteCG != StructorCodegen::COMDAT &&
+      !TryEmitBaseDestructorAsAlias(DD))
     return;
 
-  const CGFunctionInfo &fnInfo =
-      getTypes().arrangeCXXStructorDeclaration(dtor, getFromDtorType(dtorType));
-
-  auto *fn = cast<llvm::Function>(
-      GetAddrOfCXXDestructor(dtor, dtorType, &fnInfo, nullptr, true));
-  setFunctionLinkage(GlobalDecl(dtor, dtorType), fn);
-
-  CodeGenFunction(*this).GenerateCode(GlobalDecl(dtor, dtorType), fn, fnInfo);
-
-  setFunctionDefinitionAttributes(dtor, fn);
-  SetLLVMFunctionAttributesForDefinition(dtor, fn);
+  llvm::Function *Fn = codegenCXXStructor(MD, Type);
+
+  if (CompleteCG == StructorCodegen::COMDAT) {
+    SmallString<256> Buffer;
+    llvm::raw_svector_ostream Out(Buffer);
+    if (DD)
+      ABI->getMangleContext().mangleCXXDtorComdat(DD, Out);
+    else
+      ABI->getMangleContext().mangleCXXCtorComdat(CD, Out);
+    llvm::Comdat *C = TheModule.getOrInsertComdat(Out.str());
+    Fn->setComdat(C);
+  }
 }
 
 llvm::GlobalValue *
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index aaadbd4..8ef3baa 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -1066,7 +1066,7 @@ void CodeGenModule::EmitDeferred() {
     // Stop if we're out of both deferred v-tables and deferred declarations.
     if (DeferredDeclsToEmit.empty()) break;
 
-    DeferredGlobal &G = DeferredDeclsToEmit.back();
+    const DeferredGlobal &G = DeferredDeclsToEmit.back();
     GlobalDecl D = G.GD;
     llvm::GlobalValue *GV = G.GV;
     DeferredDeclsToEmit.pop_back();
@@ -1404,9 +1404,9 @@ void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD, llvm::GlobalValue *GV) {
       // Make sure to emit the definition(s) before we emit the thunks.
       // This is necessary for the generation of certain thunks.
       if (const auto *CD = dyn_cast<CXXConstructorDecl>(Method))
-        EmitCXXConstructor(CD, GD.getCtorType());
+        emitCXXStructor(CD, getFromCtorType(GD.getCtorType()));
       else if (const auto *DD = dyn_cast<CXXDestructorDecl>(Method))
-        EmitCXXDestructor(DD, GD.getDtorType());
+        emitCXXStructor(DD, getFromDtorType(GD.getDtorType()));
       else
         EmitGlobalFunctionDefinition(GD, GV);
 
diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h
index 452553f..e99c483 100644
--- a/lib/CodeGen/CodeGenModule.h
+++ b/lib/CodeGen/CodeGenModule.h
@@ -320,7 +320,7 @@ class CodeGenModule : public CodeGenTypeCache {
   /// referenced. These get code generated when the module is done.
   struct DeferredGlobal {
     DeferredGlobal(llvm::GlobalValue *GV, GlobalDecl GD) : GV(GV), GD(GD) {}
-    llvm::AssertingVH<llvm::GlobalValue> GV;
+    llvm::TrackingVH<llvm::GlobalValue> GV;
     GlobalDecl GD;
   };
   std::vector<DeferredGlobal> DeferredDeclsToEmit;
@@ -1097,19 +1097,19 @@ private:
   
   // C++ related functions.
 
-  bool TryEmitDefinitionAsAlias(GlobalDecl Alias, GlobalDecl Target,
-                                bool InEveryTU);
+  bool TryEmitDefinitionAsAlias(GlobalDecl Alias, GlobalDecl Target);
   bool TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D);
 
+  void emitConstructorDestructorAlias(GlobalDecl Alias, GlobalDecl Target);
+
   void EmitNamespace(const NamespaceDecl *D);
   void EmitLinkageSpec(const LinkageSpecDecl *D);
   void CompleteDIClassType(const CXXMethodDecl* D);
 
-  /// Emit a single constructor with the given type from a C++ constructor Decl.
-  void EmitCXXConstructor(const CXXConstructorDecl *D, CXXCtorType Type);
+  void emitCXXStructor(const CXXMethodDecl *MD, StructorType Type);
 
-  /// Emit a single destructor with the given type from a C++ destructor Decl.
-  void EmitCXXDestructor(const CXXDestructorDecl *D, CXXDtorType Type);
+  llvm::Function *codegenCXXStructor(const CXXMethodDecl *MD,
+                                     StructorType Type);
 
   /// \brief Emit the function that initializes C++ thread_local variables.
   void EmitCXXThreadLocalInitFunc();
diff --git a/test/CodeGenCXX/ctor-dtor-alias.cpp b/test/CodeGenCXX/ctor-dtor-alias.cpp
index 8be5494..40388c7 100644
--- a/test/CodeGenCXX/ctor-dtor-alias.cpp
+++ b/test/CodeGenCXX/ctor-dtor-alias.cpp
@@ -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.
-
-// CHECK1: define weak_odr void @_ZN5test16foobarIvEC2Ev
-// CHECK1: define weak_odr void @_ZN5test16foobarIvEC1Ev
-
-template <typename T> struct foobar {
+// Test that we produce the apropriate comdats when creating aliases to
+// weak_odr constructors and destructors.
+
+// 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 $_ZN5test16foobarIvED6Ev
+// CHECK1: define weak_odr void @_ZN5test16foobarIvED0Ev(
+// CHECK1-NOT: comdat
+
+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 $_ZN6test103fooIiED6Ev
+}
+
+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
+}
diff --git a/test/CodeGenCXX/destructors.cpp b/test/CodeGenCXX/destructors.cpp
index 0bfc8ec..bc9a683 100644
--- a/test/CodeGenCXX/destructors.cpp
+++ b/test/CodeGenCXX/destructors.cpp
@@ -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(
diff --git a/test/CodeGenCXX/virtual-destructor-calls.cpp b/test/CodeGenCXX/virtual-destructor-calls.cpp
index 3e7fa82..f0e3dc5 100644
--- a/test/CodeGenCXX/virtual-destructor-calls.cpp
+++ b/test/CodeGenCXX/virtual-destructor-calls.cpp
@@ -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@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to