diff options
author | Marco Antognini <marco.antognini@arm.com> | 2019-07-18 10:04:18 +0000 |
---|---|---|
committer | Marco Antognini <marco.antognini@arm.com> | 2019-07-18 10:04:18 +0000 |
commit | 83748cc5abc199a5219b0e7d9ba308984a8df613 (patch) | |
tree | 8abe72eb817fff18c645aec8d52fc22f610bf113 /clang/lib/CodeGen | |
parent | 46b55fa58dead05222211e327ed90ffab949040b (diff) | |
download | bcm5719-llvm-83748cc5abc199a5219b0e7d9ba308984a8df613.tar.gz bcm5719-llvm-83748cc5abc199a5219b0e7d9ba308984a8df613.zip |
[OpenCL] Improve destructor support in C++ for OpenCL
Summary:
This patch does mainly three things:
1. It fixes a false positive error detection in Sema that is similar to
D62156. The error happens when explicitly calling an overloaded
destructor for different address spaces.
2. It selects the correct destructor when multiple overloads for
address spaces are available.
3. It inserts the expected address space cast when invoking a
destructor, if needed, and therefore fixes a crash due to the unmet
assertion in llvm::CastInst::Create.
The following is a reproducer of the three issues:
struct MyType {
~MyType() {}
~MyType() __constant {}
};
__constant MyType myGlobal{};
kernel void foo() {
myGlobal.~MyType(); // 1 and 2.
// 1. error: cannot initialize object parameter of type
// '__generic MyType' with an expression of type '__constant MyType'
// 2. error: no matching member function for call to '~MyType'
}
kernel void bar() {
// 3. The implicit call to the destructor crashes due to:
// Assertion `castIsValid(op, S, Ty) && "Invalid cast!"' failed.
// in llvm::CastInst::Create.
MyType myLocal;
}
The added test depends on D62413 and covers a few more things than the
above reproducer.
Subscribers: yaxunl, Anastasia, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64569
llvm-svn: 366422
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r-- | clang/lib/CodeGen/CGCXXABI.h | 14 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGCall.cpp | 2 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGClass.cpp | 40 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGDecl.cpp | 21 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExprCXX.cpp | 31 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 13 | ||||
-rw-r--r-- | clang/lib/CodeGen/ItaniumCXXABI.cpp | 31 | ||||
-rw-r--r-- | clang/lib/CodeGen/MicrosoftCXXABI.cpp | 29 |
8 files changed, 116 insertions, 65 deletions
diff --git a/clang/lib/CodeGen/CGCXXABI.h b/clang/lib/CodeGen/CGCXXABI.h index 511bcd00d42..3a9c3b34743 100644 --- a/clang/lib/CodeGen/CGCXXABI.h +++ b/clang/lib/CodeGen/CGCXXABI.h @@ -378,7 +378,7 @@ public: virtual void EmitDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *DD, CXXDtorType Type, bool ForVirtualBase, bool Delegating, - Address This) = 0; + Address This, QualType ThisTy) = 0; /// Emits the VTable definitions required for the given record type. virtual void emitVTableDefinitions(CodeGenVTables &CGVT, @@ -421,11 +421,15 @@ public: llvm::Type *Ty, SourceLocation Loc) = 0; + using DeleteOrMemberCallExpr = + llvm::PointerUnion<const CXXDeleteExpr *, const CXXMemberCallExpr *>; + /// Emit the ABI-specific virtual destructor call. - virtual llvm::Value * - EmitVirtualDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *Dtor, - CXXDtorType DtorType, Address This, - const CXXMemberCallExpr *CE) = 0; + virtual llvm::Value *EmitVirtualDestructorCall(CodeGenFunction &CGF, + const CXXDestructorDecl *Dtor, + CXXDtorType DtorType, + Address This, + DeleteOrMemberCallExpr E) = 0; virtual void adjustCallArgsForDestructorThunk(CodeGenFunction &CGF, GlobalDecl GD, diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 5f1fb100748..cf8024550ee 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -3502,7 +3502,7 @@ struct DestroyUnpassedArg final : EHScopeStack::Cleanup { const CXXDestructorDecl *Dtor = Ty->getAsCXXRecordDecl()->getDestructor(); assert(!Dtor->isTrivial()); CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, /*for vbase*/ false, - /*Delegating=*/false, Addr); + /*Delegating=*/false, Addr, Ty); } else { CGF.callCStructDestructor(CGF.MakeAddrLValue(Addr, Ty)); } diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp index 9a9dd88810e..c8bb63c5c4b 100644 --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -491,12 +491,15 @@ namespace { cast<CXXMethodDecl>(CGF.CurCodeDecl)->getParent(); const CXXDestructorDecl *D = BaseClass->getDestructor(); + // We are already inside a destructor, so presumably the object being + // destroyed should have the expected type. + QualType ThisTy = D->getThisObjectType(); Address Addr = CGF.GetAddressOfDirectBaseInCompleteClass(CGF.LoadCXXThisAddress(), DerivedClass, BaseClass, BaseIsVirtual); CGF.EmitCXXDestructorCall(D, Dtor_Base, BaseIsVirtual, - /*Delegating=*/false, Addr); + /*Delegating=*/false, Addr, ThisTy); } }; @@ -1440,9 +1443,11 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) { if (DtorType == Dtor_Deleting) { RunCleanupsScope DtorEpilogue(*this); EnterDtorCleanups(Dtor, Dtor_Deleting); - if (HaveInsertPoint()) + if (HaveInsertPoint()) { + QualType ThisTy = Dtor->getThisObjectType(); EmitCXXDestructorCall(Dtor, Dtor_Complete, /*ForVirtualBase=*/false, - /*Delegating=*/false, LoadCXXThisAddress()); + /*Delegating=*/false, LoadCXXThisAddress(), ThisTy); + } return; } @@ -1473,8 +1478,9 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) { EnterDtorCleanups(Dtor, Dtor_Complete); if (!isTryBody) { + QualType ThisTy = Dtor->getThisObjectType(); EmitCXXDestructorCall(Dtor, Dtor_Base, /*ForVirtualBase=*/false, - /*Delegating=*/false, LoadCXXThisAddress()); + /*Delegating=*/false, LoadCXXThisAddress(), ThisTy); break; } @@ -2013,7 +2019,7 @@ void CodeGenFunction::destroyCXXObject(CodeGenFunction &CGF, const CXXDestructorDecl *dtor = record->getDestructor(); assert(!dtor->isTrivial()); CGF.EmitCXXDestructorCall(dtor, Dtor_Complete, /*for vbase*/ false, - /*Delegating=*/false, addr); + /*Delegating=*/false, addr, type); } void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, @@ -2363,8 +2369,11 @@ namespace { : Dtor(D), Addr(Addr), Type(Type) {} void Emit(CodeGenFunction &CGF, Flags flags) override { + // We are calling the destructor from within the constructor. + // Therefore, "this" should have the expected type. + QualType ThisTy = Dtor->getThisObjectType(); CGF.EmitCXXDestructorCall(Dtor, Type, /*ForVirtualBase=*/false, - /*Delegating=*/true, Addr); + /*Delegating=*/true, Addr, ThisTy); } }; } // end anonymous namespace @@ -2402,31 +2411,32 @@ CodeGenFunction::EmitDelegatingCXXConstructorCall(const CXXConstructorDecl *Ctor void CodeGenFunction::EmitCXXDestructorCall(const CXXDestructorDecl *DD, CXXDtorType Type, bool ForVirtualBase, - bool Delegating, - Address This) { + bool Delegating, Address This, + QualType ThisTy) { CGM.getCXXABI().EmitDestructorCall(*this, DD, Type, ForVirtualBase, - Delegating, This); + Delegating, This, ThisTy); } namespace { struct CallLocalDtor final : EHScopeStack::Cleanup { const CXXDestructorDecl *Dtor; Address Addr; + QualType Ty; - CallLocalDtor(const CXXDestructorDecl *D, Address Addr) - : Dtor(D), Addr(Addr) {} + CallLocalDtor(const CXXDestructorDecl *D, Address Addr, QualType Ty) + : Dtor(D), Addr(Addr), Ty(Ty) {} void Emit(CodeGenFunction &CGF, Flags flags) override { CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, /*ForVirtualBase=*/false, - /*Delegating=*/false, Addr); + /*Delegating=*/false, Addr, Ty); } }; } // end anonymous namespace void CodeGenFunction::PushDestructorCleanup(const CXXDestructorDecl *D, - Address Addr) { - EHStack.pushCleanup<CallLocalDtor>(NormalAndEHCleanup, D, Addr); + QualType T, Address Addr) { + EHStack.pushCleanup<CallLocalDtor>(NormalAndEHCleanup, D, Addr, T); } void CodeGenFunction::PushDestructorCleanup(QualType T, Address Addr) { @@ -2436,7 +2446,7 @@ void CodeGenFunction::PushDestructorCleanup(QualType T, Address Addr) { const CXXDestructorDecl *D = ClassDecl->getDestructor(); assert(D && D->isUsed() && "destructor not marked as used!"); - PushDestructorCleanup(D, Addr); + PushDestructorCleanup(D, T, Addr); } void CodeGenFunction::InitializeVTablePointer(const VPtr &Vptr) { diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index 19a9e75cc5a..6ad43cefc4d 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -480,11 +480,12 @@ namespace { template <class Derived> struct DestroyNRVOVariable : EHScopeStack::Cleanup { - DestroyNRVOVariable(Address addr, llvm::Value *NRVOFlag) - : NRVOFlag(NRVOFlag), Loc(addr) {} + DestroyNRVOVariable(Address addr, QualType type, llvm::Value *NRVOFlag) + : NRVOFlag(NRVOFlag), Loc(addr), Ty(type) {} llvm::Value *NRVOFlag; Address Loc; + QualType Ty; void Emit(CodeGenFunction &CGF, Flags flags) override { // Along the exceptions path we always execute the dtor. @@ -511,26 +512,24 @@ namespace { struct DestroyNRVOVariableCXX final : DestroyNRVOVariable<DestroyNRVOVariableCXX> { - DestroyNRVOVariableCXX(Address addr, const CXXDestructorDecl *Dtor, - llvm::Value *NRVOFlag) - : DestroyNRVOVariable<DestroyNRVOVariableCXX>(addr, NRVOFlag), - Dtor(Dtor) {} + DestroyNRVOVariableCXX(Address addr, QualType type, + const CXXDestructorDecl *Dtor, llvm::Value *NRVOFlag) + : DestroyNRVOVariable<DestroyNRVOVariableCXX>(addr, type, NRVOFlag), + Dtor(Dtor) {} const CXXDestructorDecl *Dtor; void emitDestructorCall(CodeGenFunction &CGF) { CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, /*ForVirtualBase=*/false, - /*Delegating=*/false, Loc); + /*Delegating=*/false, Loc, Ty); } }; struct DestroyNRVOVariableC final : DestroyNRVOVariable<DestroyNRVOVariableC> { DestroyNRVOVariableC(Address addr, llvm::Value *NRVOFlag, QualType Ty) - : DestroyNRVOVariable<DestroyNRVOVariableC>(addr, NRVOFlag), Ty(Ty) {} - - QualType Ty; + : DestroyNRVOVariable<DestroyNRVOVariableC>(addr, Ty, NRVOFlag) {} void emitDestructorCall(CodeGenFunction &CGF) { CGF.destroyNonTrivialCStruct(CGF, Loc, Ty); @@ -1940,7 +1939,7 @@ void CodeGenFunction::emitAutoVarTypeCleanup( if (emission.NRVOFlag) { assert(!type->isArrayType()); CXXDestructorDecl *dtor = type->getAsCXXRecordDecl()->getDestructor(); - EHStack.pushCleanup<DestroyNRVOVariableCXX>(cleanupKind, addr, dtor, + EHStack.pushCleanup<DestroyNRVOVariableCXX>(cleanupKind, addr, type, dtor, emission.NRVOFlag); return; } diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp index 8ad229fc0c3..5476d13b7c4 100644 --- a/clang/lib/CodeGen/CGExprCXX.cpp +++ b/clang/lib/CodeGen/CGExprCXX.cpp @@ -10,12 +10,13 @@ // //===----------------------------------------------------------------------===// -#include "CodeGenFunction.h" #include "CGCUDARuntime.h" #include "CGCXXABI.h" #include "CGDebugInfo.h" #include "CGObjCRuntime.h" +#include "CodeGenFunction.h" #include "ConstantEmitter.h" +#include "TargetInfo.h" #include "clang/Basic/CodeGenOptions.h" #include "clang/CodeGen/CGFunctionInfo.h" #include "llvm/IR/Intrinsics.h" @@ -90,12 +91,26 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorCall( } RValue CodeGenFunction::EmitCXXDestructorCall( - GlobalDecl Dtor, const CGCallee &Callee, llvm::Value *This, + GlobalDecl Dtor, const CGCallee &Callee, llvm::Value *This, QualType ThisTy, llvm::Value *ImplicitParam, QualType ImplicitParamTy, const CallExpr *CE) { + const CXXMethodDecl *DtorDecl = cast<CXXMethodDecl>(Dtor.getDecl()); + + assert(!ThisTy.isNull()); + assert(ThisTy->getAsCXXRecordDecl() == DtorDecl->getParent() && + "Pointer/Object mixup"); + + LangAS SrcAS = ThisTy.getAddressSpace(); + LangAS DstAS = DtorDecl->getMethodQualifiers().getAddressSpace(); + if (SrcAS != DstAS) { + QualType DstTy = DtorDecl->getThisType(); + llvm::Type *NewType = CGM.getTypes().ConvertType(DstTy); + This = getTargetHooks().performAddrSpaceCast(*this, This, SrcAS, DstAS, + NewType); + } + CallArgList Args; - commonEmitCXXMemberOrOperatorCall(*this, cast<CXXMethodDecl>(Dtor.getDecl()), - This, ImplicitParam, ImplicitParamTy, CE, - Args, nullptr); + commonEmitCXXMemberOrOperatorCall(*this, DtorDecl, This, ImplicitParam, + ImplicitParamTy, CE, Args, nullptr); return EmitCall(CGM.getTypes().arrangeCXXStructorDeclaration(Dtor), Callee, ReturnValueSlot(), Args); } @@ -345,7 +360,9 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr( Callee = CGCallee::forDirect(CGM.GetAddrOfFunction(GD, Ty), GD); } - EmitCXXDestructorCall(GD, Callee, This.getPointer(), + QualType ThisTy = + IsArrow ? Base->getType()->getPointeeType() : Base->getType(); + EmitCXXDestructorCall(GD, Callee, This.getPointer(), ThisTy, /*ImplicitParam=*/nullptr, /*ImplicitParamTy=*/QualType(), nullptr); } @@ -1883,7 +1900,7 @@ static void EmitObjectDelete(CodeGenFunction &CGF, CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, /*ForVirtualBase=*/false, /*Delegating=*/false, - Ptr); + Ptr, ElementType); else if (auto Lifetime = ElementType.getObjCLifetime()) { switch (Lifetime) { case Qualifiers::OCL_None: diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 06ef2dff7e9..c3060d1fb35 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -675,7 +675,8 @@ public: /// PushDestructorCleanup - Push a cleanup to call the /// complete-object variant of the given destructor on the object at /// the given address. - void PushDestructorCleanup(const CXXDestructorDecl *Dtor, Address Addr); + void PushDestructorCleanup(const CXXDestructorDecl *Dtor, QualType T, + Address Addr); /// PopCleanupBlock - Will pop the cleanup entry on the stack and /// process all branch fixups. @@ -2554,8 +2555,8 @@ public: static Destroyer destroyCXXObject; void EmitCXXDestructorCall(const CXXDestructorDecl *D, CXXDtorType Type, - bool ForVirtualBase, bool Delegating, - Address This); + bool ForVirtualBase, bool Delegating, Address This, + QualType ThisTy); void EmitNewArrayInitializer(const CXXNewExpr *E, QualType elementType, llvm::Type *ElementTy, Address NewPtr, @@ -3677,9 +3678,9 @@ public: llvm::Value *ImplicitParam, QualType ImplicitParamTy, const CallExpr *E, CallArgList *RtlArgs); - RValue EmitCXXDestructorCall(GlobalDecl Dtor, - const CGCallee &Callee, - llvm::Value *This, llvm::Value *ImplicitParam, + RValue EmitCXXDestructorCall(GlobalDecl Dtor, const CGCallee &Callee, + llvm::Value *This, QualType ThisTy, + llvm::Value *ImplicitParam, QualType ImplicitParamTy, const CallExpr *E); RValue EmitCXXMemberCallExpr(const CXXMemberCallExpr *E, ReturnValueSlot ReturnValue); diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index 7367ff37cf4..3b2413d960d 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -224,7 +224,8 @@ public: void EmitDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *DD, CXXDtorType Type, bool ForVirtualBase, - bool Delegating, Address This) override; + bool Delegating, Address This, + QualType ThisTy) override; void emitVTableDefinitions(CodeGenVTables &CGVT, const CXXRecordDecl *RD) override; @@ -261,9 +262,8 @@ public: llvm::Value *EmitVirtualDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *Dtor, - CXXDtorType DtorType, - Address This, - const CXXMemberCallExpr *CE) override; + CXXDtorType DtorType, Address This, + DeleteOrMemberCallExpr E) override; void emitVirtualInheritanceTables(const CXXRecordDecl *RD) override; @@ -1128,7 +1128,7 @@ void ItaniumCXXABI::emitVirtualObjectDelete(CodeGenFunction &CGF, // FIXME: Provide a source location here even though there's no // CXXMemberCallExpr for dtor call. CXXDtorType DtorType = UseGlobalDelete ? Dtor_Complete : Dtor_Deleting; - EmitVirtualDestructorCall(CGF, Dtor, DtorType, Ptr, /*CE=*/nullptr); + EmitVirtualDestructorCall(CGF, Dtor, DtorType, Ptr, DE); if (UseGlobalDelete) CGF.PopCleanupBlock(); @@ -1539,7 +1539,8 @@ CGCXXABI::AddedStructorArgs ItaniumCXXABI::addImplicitConstructorArgs( void ItaniumCXXABI::EmitDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *DD, CXXDtorType Type, bool ForVirtualBase, - bool Delegating, Address This) { + bool Delegating, Address This, + QualType ThisTy) { GlobalDecl GD(DD, Type); llvm::Value *VTT = CGF.GetVTTParameter(GD, ForVirtualBase, Delegating); QualType VTTTy = getContext().getPointerType(getContext().VoidPtrTy); @@ -1551,7 +1552,8 @@ void ItaniumCXXABI::EmitDestructorCall(CodeGenFunction &CGF, else Callee = CGCallee::forDirect(CGM.getAddrOfCXXStructor(GD), GD); - CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), VTT, VTTTy, nullptr); + CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), ThisTy, VTT, VTTTy, + nullptr); } void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT, @@ -1739,7 +1741,10 @@ CGCallee ItaniumCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF, llvm::Value *ItaniumCXXABI::EmitVirtualDestructorCall( CodeGenFunction &CGF, const CXXDestructorDecl *Dtor, CXXDtorType DtorType, - Address This, const CXXMemberCallExpr *CE) { + Address This, DeleteOrMemberCallExpr E) { + auto *CE = E.dyn_cast<const CXXMemberCallExpr *>(); + auto *D = E.dyn_cast<const CXXDeleteExpr *>(); + assert((CE != nullptr) ^ (D != nullptr)); assert(CE == nullptr || CE->arg_begin() == CE->arg_end()); assert(DtorType == Dtor_Deleting || DtorType == Dtor_Complete); @@ -1749,8 +1754,14 @@ llvm::Value *ItaniumCXXABI::EmitVirtualDestructorCall( llvm::FunctionType *Ty = CGF.CGM.getTypes().GetFunctionType(*FInfo); CGCallee Callee = CGCallee::forVirtual(CE, GD, This, Ty); - CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), nullptr, QualType(), - nullptr); + QualType ThisTy; + if (CE) + ThisTy = CE->getImplicitObjectArgument()->getType()->getPointeeType(); + else + ThisTy = D->getDestroyedType(); + + CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), ThisTy, nullptr, + QualType(), nullptr); return nullptr; } diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp index a91a949d024..fa34414de5d 100644 --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -258,7 +258,8 @@ public: void EmitDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *DD, CXXDtorType Type, bool ForVirtualBase, - bool Delegating, Address This) override; + bool Delegating, Address This, + QualType ThisTy) override; void emitVTableTypeMetadata(const VPtrInfo &Info, const CXXRecordDecl *RD, llvm::GlobalVariable *VTable); @@ -296,9 +297,8 @@ public: llvm::Value *EmitVirtualDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *Dtor, - CXXDtorType DtorType, - Address This, - const CXXMemberCallExpr *CE) override; + CXXDtorType DtorType, Address This, + DeleteOrMemberCallExpr E) override; void adjustCallArgsForDestructorThunk(CodeGenFunction &CGF, GlobalDecl GD, CallArgList &CallArgs) override { @@ -844,8 +844,7 @@ void MicrosoftCXXABI::emitVirtualObjectDelete(CodeGenFunction &CGF, // CXXMemberCallExpr for dtor call. bool UseGlobalDelete = DE->isGlobalDelete(); CXXDtorType DtorType = UseGlobalDelete ? Dtor_Complete : Dtor_Deleting; - llvm::Value *MDThis = - EmitVirtualDestructorCall(CGF, Dtor, DtorType, Ptr, /*CE=*/nullptr); + llvm::Value *MDThis = EmitVirtualDestructorCall(CGF, Dtor, DtorType, Ptr, DE); if (UseGlobalDelete) CGF.EmitDeleteCall(DE->getOperatorDelete(), MDThis, ElementType); } @@ -1569,7 +1568,8 @@ CGCXXABI::AddedStructorArgs MicrosoftCXXABI::addImplicitConstructorArgs( void MicrosoftCXXABI::EmitDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *DD, CXXDtorType Type, bool ForVirtualBase, - bool Delegating, Address This) { + bool Delegating, Address This, + QualType ThisTy) { // Use the base destructor variant in place of the complete destructor variant // if the class has no virtual bases. This effectively implements some of the // -mconstructor-aliases optimization, but as part of the MS C++ ABI. @@ -1591,7 +1591,7 @@ void MicrosoftCXXABI::EmitDestructorCall(CodeGenFunction &CGF, BaseDtorEndBB = EmitDtorCompleteObjectHandler(CGF); } - CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), + CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), ThisTy, /*ImplicitParam=*/nullptr, /*ImplicitParamTy=*/QualType(), nullptr); if (BaseDtorEndBB) { @@ -1900,7 +1900,10 @@ CGCallee MicrosoftCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF, llvm::Value *MicrosoftCXXABI::EmitVirtualDestructorCall( CodeGenFunction &CGF, const CXXDestructorDecl *Dtor, CXXDtorType DtorType, - Address This, const CXXMemberCallExpr *CE) { + Address This, DeleteOrMemberCallExpr E) { + auto *CE = E.dyn_cast<const CXXMemberCallExpr *>(); + auto *D = E.dyn_cast<const CXXDeleteExpr *>(); + assert((CE != nullptr) ^ (D != nullptr)); assert(CE == nullptr || CE->arg_begin() == CE->arg_end()); assert(DtorType == Dtor_Deleting || DtorType == Dtor_Complete); @@ -1917,8 +1920,14 @@ llvm::Value *MicrosoftCXXABI::EmitVirtualDestructorCall( llvm::IntegerType::getInt32Ty(CGF.getLLVMContext()), DtorType == Dtor_Deleting); + QualType ThisTy; + if (CE) + ThisTy = CE->getImplicitObjectArgument()->getType()->getPointeeType(); + else + ThisTy = D->getDestroyedType(); + This = adjustThisArgumentForVirtualFunctionCall(CGF, GD, This, true); - RValue RV = CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), + RValue RV = CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), ThisTy, ImplicitParam, Context.IntTy, CE); return RV.getScalarVal(); } |