Index: include/clang/Basic/ABI.h =================================================================== --- include/clang/Basic/ABI.h +++ include/clang/Basic/ABI.h @@ -29,9 +29,10 @@ /// \brief C++ destructor types. enum CXXDtorType { - Dtor_Deleting, ///< Deleting dtor - Dtor_Complete, ///< Complete object dtor - Dtor_Base ///< Base object dtor + Dtor_Deleting, ///< Deleting dtor + Dtor_Complete, ///< Complete object dtor + Dtor_Base, ///< Base object dtor + Dtor_VectorDeleting ///< Vector deleting dtor }; /// \brief A return adjustment. Index: lib/AST/ItaniumMangle.cpp =================================================================== --- lib/AST/ItaniumMangle.cpp +++ lib/AST/ItaniumMangle.cpp @@ -3071,6 +3071,8 @@ case Dtor_Base: Out << "D2"; break; + case Dtor_VectorDeleting: + llvm_unreachable("Itanium ABI does not use vector deleting dtors"); } } Index: lib/AST/MicrosoftMangle.cpp =================================================================== --- lib/AST/MicrosoftMangle.cpp +++ lib/AST/MicrosoftMangle.cpp @@ -570,6 +570,9 @@ void MicrosoftCXXNameMangler::mangleCXXDtorType(CXXDtorType T) { switch (T) { + case Dtor_VectorDeleting: + Out << "?_E"; + return; case Dtor_Deleting: Out << "?_G"; return; @@ -1188,8 +1191,8 @@ // ::= @ # structors (they have no declared return type) if (IsStructor) { if (isa(D) && D == Structor && - StructorType == Dtor_Deleting) { - // The scalar deleting destructor takes an extra int argument. + (StructorType == Dtor_Deleting || StructorType == Dtor_VectorDeleting)){ + // The deleting destructors take an extra int argument. // However, the FunctionType generated has 0 arguments. // FIXME: This is a temporary hack. // Maybe should fix the FunctionType creation instead? Index: lib/AST/VTableBuilder.cpp =================================================================== --- lib/AST/VTableBuilder.cpp +++ lib/AST/VTableBuilder.cpp @@ -1304,7 +1304,7 @@ Components.push_back(VTableComponent::MakeCompleteDtor(DD)); Components.push_back(VTableComponent::MakeDeletingDtor(DD)); } else { - // Add the scalar deleting destructor. + // Add the vector deleting destructor. Components.push_back(VTableComponent::MakeDeletingDtor(DD)); } } else { @@ -1951,7 +1951,7 @@ if (IsComplete) Out << "() [complete]"; else if (isMicrosoftABI()) - Out << "() [scalar deleting]"; + Out << "() [vector deleting]"; else Out << "() [deleting]"; @@ -2143,8 +2143,9 @@ IndicesMap[VTables.getMethodVTableIndex(GlobalDecl(DD, Dtor_Deleting))] = MethodName + " [deleting]"; } else { - IndicesMap[VTables.getMethodVTableIndex(GlobalDecl(DD, Dtor_Deleting))] - = MethodName + " [scalar deleting]"; + IndicesMap[VTables.getMethodVTableIndex( + GlobalDecl(DD, Dtor_VectorDeleting))] + = MethodName + " [vector deleting]"; } } else { IndicesMap[VTables.getMethodVTableIndex(MD)] = MethodName; @@ -2276,9 +2277,9 @@ MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)] = getMethodVTableIndex(GlobalDecl(OverriddenDD, Dtor_Deleting)); } else { - // Add the scalar deleting destructor. - MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)] = - getMethodVTableIndex(GlobalDecl(OverriddenDD, Dtor_Deleting)); + // Add the vector deleting destructor. + MethodVTableIndices[GlobalDecl(DD, Dtor_VectorDeleting)] = + getMethodVTableIndex(GlobalDecl(OverriddenDD, Dtor_VectorDeleting)); } } else { MethodVTableIndices[MD] = getMethodVTableIndex(OverriddenMD); @@ -2305,7 +2306,8 @@ MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)] = CurrentIndex++; } else { // Add the scalar deleting dtor. - MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)] = CurrentIndex++; + MethodVTableIndices[GlobalDecl(DD, Dtor_VectorDeleting)] = + CurrentIndex++; } } else { // Add the entry. Index: lib/CodeGen/CGCXX.cpp =================================================================== --- lib/CodeGen/CGCXX.cpp +++ lib/CodeGen/CGCXX.cpp @@ -136,6 +136,18 @@ if (llvm::GlobalValue::isWeakForLinker(TargetLinkage)) return true; + EmitDefinitionAsAlias(AliasDecl, TargetDecl); + return false; +} + +/// Emit a definition as a global alias for another definition, unconditionally. +/// Use this function with care as it can produce invalid aliases. Generally +/// this function should be used only where there is an ABI requirement to emit +/// an alias. +void CodeGenModule::EmitDefinitionAsAlias(GlobalDecl AliasDecl, + GlobalDecl TargetDecl) { + llvm::GlobalValue::LinkageTypes Linkage = getFunctionLinkage(AliasDecl); + // Derive the type for the alias. llvm::PointerType *AliasType = getTypes().GetFunctionType(AliasDecl)->getPointerTo(); @@ -168,8 +180,6 @@ // Finally, set up the alias with its proper name and attributes. SetCommonAttributes(cast(AliasDecl.getDecl()), Alias); - - return false; } void CodeGenModule::EmitCXXConstructors(const CXXConstructorDecl *D) { @@ -263,6 +273,15 @@ if (dtorType == Dtor_Base && !TryEmitBaseDestructorAsAlias(dtor)) return; + // The Microsoft ABI requires that the vector deleting destructor + // be weak aliased to the scalar deleting destructor. + // TODO: emission of the vector deleting destructor (when required). + if (dtorType == Dtor_VectorDeleting) { + EmitDefinitionAsAlias(GlobalDecl(dtor, Dtor_VectorDeleting), + GlobalDecl(dtor, Dtor_Deleting)); + return; + } + const CGFunctionInfo &fnInfo = getTypes().arrangeCXXDestructor(dtor, dtorType); Index: lib/CodeGen/CGClass.cpp =================================================================== --- lib/CodeGen/CGClass.cpp +++ lib/CodeGen/CGClass.cpp @@ -1277,6 +1277,7 @@ // we'd introduce *two* handler blocks. switch (DtorType) { case Dtor_Deleting: llvm_unreachable("already handled deleting case"); + case Dtor_VectorDeleting: llvm_unreachable("TODO"); case Dtor_Complete: // Enter the cleanup scopes for virtual bases. Index: lib/CodeGen/CGVTables.cpp =================================================================== --- lib/CodeGen/CGVTables.cpp +++ lib/CodeGen/CGVTables.cpp @@ -554,7 +554,10 @@ GD = GlobalDecl(Component.getDestructorDecl(), Dtor_Complete); break; case VTableComponent::CK_DeletingDtorPointer: - GD = GlobalDecl(Component.getDestructorDecl(), Dtor_Deleting); + GD = GlobalDecl(Component.getDestructorDecl(), + CGM.getTarget().getCXXABI().isMicrosoft() + ? Dtor_VectorDeleting + : Dtor_Deleting); break; } Index: lib/CodeGen/CodeGenModule.h =================================================================== --- lib/CodeGen/CodeGenModule.h +++ lib/CodeGen/CodeGenModule.h @@ -1021,6 +1021,7 @@ bool TryEmitDefinitionAsAlias(GlobalDecl Alias, GlobalDecl Target); bool TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D); + void EmitDefinitionAsAlias(GlobalDecl Alias, GlobalDecl Target); void EmitNamespace(const NamespaceDecl *D); void EmitLinkageSpec(const LinkageSpecDecl *D); Index: lib/CodeGen/CodeGenModule.cpp =================================================================== --- lib/CodeGen/CodeGenModule.cpp +++ lib/CodeGen/CodeGenModule.cpp @@ -529,9 +529,14 @@ // In the Microsoft ABI, most destructor types are not emitted with the // definition, and must be emitted on demand. Give these linkonce_odr - // linkage. + // linkage, with the exception of vector deleting destructors, which get + // weak linkage because they may not necessarily be referenced in the + // translation unit which requires them to be emitted, and they may be + // overridden by other translation units. if (getTarget().getCXXABI().isMicrosoft() && isa(D)) { - if (GD.getDtorType() != Dtor_Base) + if (GD.getDtorType() == Dtor_VectorDeleting) + return llvm::Function::WeakAnyLinkage; + else if (GD.getDtorType() != Dtor_Base) return llvm::Function::LinkOnceODRLinkage; } Index: lib/CodeGen/MicrosoftCXXABI.cpp =================================================================== --- lib/CodeGen/MicrosoftCXXABI.cpp +++ lib/CodeGen/MicrosoftCXXABI.cpp @@ -263,7 +263,7 @@ // 'this' is already in place // TODO: 'for base' flag - if (Type == Dtor_Deleting) { + if (Type == Dtor_Deleting || Type == Dtor_VectorDeleting) { // The deleting destructors take an implicit int parameter. ArgTys.push_back(CGM.getContext().IntTy); } @@ -272,7 +272,8 @@ static bool IsDeletingDtor(GlobalDecl GD) { const CXXMethodDecl* MD = cast(GD.getDecl()); if (isa(MD)) { - return GD.getDtorType() == Dtor_Deleting; + return GD.getDtorType() == Dtor_Deleting || + GD.getDtorType() == Dtor_VectorDeleting; } return false; } @@ -371,9 +372,10 @@ // We have only one destructor in the vftable but can get both behaviors // by passing an implicit bool parameter. const CGFunctionInfo *FInfo - = &CGM.getTypes().arrangeCXXDestructor(Dtor, Dtor_Deleting); + = &CGM.getTypes().arrangeCXXDestructor(Dtor, Dtor_VectorDeleting); llvm::Type *Ty = CGF.CGM.getTypes().GetFunctionType(*FInfo); - llvm::Value *Callee = CGF.BuildVirtualCall(Dtor, Dtor_Deleting, This, Ty); + llvm::Value *Callee + = CGF.BuildVirtualCall(Dtor, Dtor_VectorDeleting, This, Ty); ASTContext &Context = CGF.getContext(); llvm::Value *ImplicitParam Index: test/CodeGenCXX/microsoft-abi-structors.cpp =================================================================== --- test/CodeGenCXX/microsoft-abi-structors.cpp +++ test/CodeGenCXX/microsoft-abi-structors.cpp @@ -246,6 +246,7 @@ // The emission of the ctor requires emission of the vtable and therefore // of the other dtor forms, despite not being defined in this TU. +// DTOR5: @"\01??_EA@bodyless_dtors@@UAEPAXI@Z" = alias weak void (%"struct.bodyless_dtors::A"*, i32)* @"\01??_GA@bodyless_dtors@@UAEPAXI@Z" // DTOR5: define linkonce_odr x86_thiscallcc void @"\01??_GA@bodyless_dtors@@UAEPAXI@Z"(%"struct.bodyless_dtors::A"* %this, i32 %flags) // DTORS: define linkonce_odr x86_thiscallcc void @"\01??_DA@bodyless_dtors@@UAE@XZ"(%"struct.bodyless_dtors::A"* %this) Index: test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp =================================================================== --- test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp +++ test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp @@ -37,10 +37,10 @@ struct C { // CHECK-C: Vtable for 'C' (2 entries) - // CHECK-C-NEXT: 0 | C::~C() [scalar deleting] + // CHECK-C-NEXT: 0 | C::~C() [vector deleting] // CHECK-C-NEXT: 1 | void C::f() // CHECK-C: VTable indices for 'C' (2 entries). - // CHECK-C-NEXT: 0 | C::~C() [scalar deleting] + // CHECK-C-NEXT: 0 | C::~C() [vector deleting] // CHECK-C-NEXT: 1 | void C::f() // Never used, so doesn't emit a vtable. virtual ~C(); @@ -52,7 +52,7 @@ struct D { // CHECK-D: Vtable for 'D' (2 entries) // CHECK-D-NEXT: 0 | void D::f() - // CHECK-D-NEXT: 1 | D::~D() [scalar deleting] + // CHECK-D-NEXT: 1 | D::~D() [vector deleting] // EMITS-VTABLE: @"\01??_7D@@6B@" = unnamed_addr constant [2 x i8*] virtual void f(); @@ -65,10 +65,10 @@ // CHECK-E-NEXT: 0 | void A::f() // CHECK-E-NEXT: 1 | void A::g() // CHECK-E-NEXT: 2 | void A::h() - // CHECK-E-NEXT: 3 | E::~E() [scalar deleting] + // CHECK-E-NEXT: 3 | E::~E() [vector deleting] // CHECK-E-NEXT: 4 | void E::i() // CHECK-E: VTable indices for 'E' (2 entries). - // CHECK-E-NEXT: 3 | E::~E() [scalar deleting] + // CHECK-E-NEXT: 3 | E::~E() [vector deleting] // CHECK-E-NEXT: 4 | void E::i() // Never used, so doesn't emit a vtable. @@ -83,10 +83,10 @@ // CHECK-F-NEXT: 1 | void A::g() // CHECK-F-NEXT: 2 | void A::h() // CHECK-F-NEXT: 3 | void F::i() - // CHECK-F-NEXT: 4 | F::~F() [scalar deleting] + // CHECK-F-NEXT: 4 | F::~F() [vector deleting] // CHECK-F: VTable indices for 'F' (2 entries). // CHECK-F-NEXT: 3 | void F::i() - // CHECK-F-NEXT: 4 | F::~F() [scalar deleting] + // CHECK-F-NEXT: 4 | F::~F() [vector deleting] // EMITS-VTABLE: @"\01??_7F@@6B@" = unnamed_addr constant [5 x i8*] virtual void i(); virtual ~F(); @@ -98,12 +98,12 @@ // CHECK-G-NEXT: 0 | void G::f() // CHECK-G-NEXT: 1 | void A::g() // CHECK-G-NEXT: 2 | void A::h() - // CHECK-G-NEXT: 3 | G::~G() [scalar deleting] + // CHECK-G-NEXT: 3 | G::~G() [vector deleting] // CHECK-G-NEXT: 4 | void E::i() // CHECK-G-NEXT: 5 | void G::j() // CHECK-G: VTable indices for 'G' (3 entries). // CHECK-G-NEXT: 0 | void G::f() - // CHECK-G-NEXT: 3 | G::~G() [scalar deleting] + // CHECK-G-NEXT: 3 | G::~G() [vector deleting] // CHECK-G-NEXT: 5 | void G::j() // Never used, so doesn't emit a vtable. virtual void f(); // overrides A::f()