summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r--clang/lib/CodeGen/CGCXXABI.h24
-rw-r--r--clang/lib/CodeGen/CGCall.cpp14
-rw-r--r--clang/lib/CodeGen/CGExprCXX.cpp79
-rw-r--r--clang/lib/CodeGen/CGVTables.cpp14
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.cpp2
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.h8
-rw-r--r--clang/lib/CodeGen/ItaniumCXXABI.cpp70
-rw-r--r--clang/lib/CodeGen/MicrosoftCXXABI.cpp78
8 files changed, 175 insertions, 114 deletions
diff --git a/clang/lib/CodeGen/CGCXXABI.h b/clang/lib/CodeGen/CGCXXABI.h
index 9782ff3bf36..9739f064478 100644
--- a/clang/lib/CodeGen/CGCXXABI.h
+++ b/clang/lib/CodeGen/CGCXXABI.h
@@ -93,6 +93,8 @@ public:
/// when called virtually, and code generation does not support the case.
virtual bool HasThisReturn(GlobalDecl GD) const { return false; }
+ virtual bool hasMostDerivedReturn(GlobalDecl GD) const { return false; }
+
/// If the C++ ABI requires the given type be returned in a particular way,
/// this method sets RetAI and returns true.
virtual bool classifyReturnType(CGFunctionInfo &FI) const = 0;
@@ -207,14 +209,11 @@ protected:
CharUnits getMemberPointerPathAdjustment(const APValue &MP);
public:
- /// Adjust the given non-null pointer to an object of polymorphic
- /// type to point to the complete object.
- ///
- /// The IR type of the result should be a pointer but is otherwise
- /// irrelevant.
- virtual llvm::Value *adjustToCompleteObject(CodeGenFunction &CGF,
- llvm::Value *ptr,
- QualType type) = 0;
+ virtual void emitVirtualObjectDelete(CodeGenFunction &CGF,
+ const FunctionDecl *OperatorDelete,
+ llvm::Value *Ptr, QualType ElementType,
+ bool UseGlobalDelete,
+ const CXXDestructorDecl *Dtor) = 0;
virtual llvm::Constant *getAddrOfRTTIDescriptor(QualType Ty) = 0;
@@ -359,11 +358,10 @@ public:
llvm::Type *Ty) = 0;
/// Emit the ABI-specific virtual destructor call.
- virtual void EmitVirtualDestructorCall(CodeGenFunction &CGF,
- const CXXDestructorDecl *Dtor,
- CXXDtorType DtorType,
- llvm::Value *This,
- const CXXMemberCallExpr *CE) = 0;
+ virtual llvm::Value *
+ EmitVirtualDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *Dtor,
+ CXXDtorType DtorType, llvm::Value *This,
+ const CXXMemberCallExpr *CE) = 0;
virtual void adjustCallArgsForDestructorThunk(CodeGenFunction &CGF,
GlobalDecl GD,
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index ffa28c17694..b31cdf3a909 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -214,8 +214,11 @@ CodeGenTypes::arrangeCXXStructorDeclaration(const CXXMethodDecl *MD,
(MD->isVariadic() ? RequiredArgs(argTypes.size()) : RequiredArgs::All);
FunctionType::ExtInfo extInfo = FTP->getExtInfo();
- CanQualType resultType =
- TheCXXABI.HasThisReturn(GD) ? argTypes.front() : Context.VoidTy;
+ CanQualType resultType = TheCXXABI.HasThisReturn(GD)
+ ? argTypes.front()
+ : TheCXXABI.hasMostDerivedReturn(GD)
+ ? CGM.getContext().VoidPtrTy
+ : Context.VoidTy;
return arrangeLLVMFunctionInfo(resultType, true, argTypes, extInfo, required);
}
@@ -233,8 +236,11 @@ CodeGenTypes::arrangeCXXConstructorCall(const CallArgList &args,
CanQual<FunctionProtoType> FPT = GetFormalType(D);
RequiredArgs Required = RequiredArgs::forPrototypePlus(FPT, 1 + ExtraArgs);
GlobalDecl GD(D, CtorKind);
- CanQualType ResultType =
- TheCXXABI.HasThisReturn(GD) ? ArgTypes.front() : Context.VoidTy;
+ CanQualType ResultType = TheCXXABI.HasThisReturn(GD)
+ ? ArgTypes.front()
+ : TheCXXABI.hasMostDerivedReturn(GD)
+ ? CGM.getContext().VoidPtrTy
+ : Context.VoidTy;
FunctionType::ExtInfo Info = FPT->getExtInfo();
return arrangeLLVMFunctionInfo(ResultType, true, ArgTypes, Info, Required);
diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp
index 483966fce20..f81edb62225 100644
--- a/clang/lib/CodeGen/CGExprCXX.cpp
+++ b/clang/lib/CodeGen/CGExprCXX.cpp
@@ -24,10 +24,10 @@
using namespace clang;
using namespace CodeGen;
-RValue CodeGenFunction::EmitCXXMemberOrOperatorCall(
- const CXXMethodDecl *MD, llvm::Value *Callee, ReturnValueSlot ReturnValue,
- llvm::Value *This, llvm::Value *ImplicitParam, QualType ImplicitParamTy,
- const CallExpr *CE) {
+static RequiredArgs commonEmitCXXMemberOrOperatorCall(
+ CodeGenFunction &CGF, const CXXMethodDecl *MD, llvm::Value *Callee,
+ ReturnValueSlot ReturnValue, llvm::Value *This, llvm::Value *ImplicitParam,
+ QualType ImplicitParamTy, const CallExpr *CE, CallArgList &Args) {
assert(CE == nullptr || isa<CXXMemberCallExpr>(CE) ||
isa<CXXOperatorCallExpr>(CE));
assert(MD->isInstance() &&
@@ -39,14 +39,13 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorCall(
SourceLocation CallLoc;
if (CE)
CallLoc = CE->getExprLoc();
- EmitTypeCheck(isa<CXXConstructorDecl>(MD) ? TCK_ConstructorCall
- : TCK_MemberCall,
- CallLoc, This, getContext().getRecordType(MD->getParent()));
-
- CallArgList Args;
+ CGF.EmitTypeCheck(
+ isa<CXXConstructorDecl>(MD) ? CodeGenFunction::TCK_ConstructorCall
+ : CodeGenFunction::TCK_MemberCall,
+ CallLoc, This, CGF.getContext().getRecordType(MD->getParent()));
// Push the this ptr.
- Args.add(RValue::get(This), MD->getThisType(getContext()));
+ Args.add(RValue::get(This), MD->getThisType(CGF.getContext()));
// If there is an implicit parameter (e.g. VTT), emit it.
if (ImplicitParam) {
@@ -60,18 +59,40 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorCall(
if (CE) {
// Special case: skip first argument of CXXOperatorCall (it is "this").
unsigned ArgsToSkip = isa<CXXOperatorCallExpr>(CE) ? 1 : 0;
- EmitCallArgs(Args, FPT, CE->arg_begin() + ArgsToSkip, CE->arg_end(),
- CE->getDirectCallee());
+ CGF.EmitCallArgs(Args, FPT, CE->arg_begin() + ArgsToSkip, CE->arg_end(),
+ CE->getDirectCallee());
} else {
assert(
FPT->getNumParams() == 0 &&
"No CallExpr specified for function with non-zero number of arguments");
}
+ return required;
+}
+RValue CodeGenFunction::EmitCXXMemberOrOperatorCall(
+ const CXXMethodDecl *MD, llvm::Value *Callee, ReturnValueSlot ReturnValue,
+ llvm::Value *This, llvm::Value *ImplicitParam, QualType ImplicitParamTy,
+ const CallExpr *CE) {
+ const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>();
+ CallArgList Args;
+ RequiredArgs required = commonEmitCXXMemberOrOperatorCall(
+ *this, MD, Callee, ReturnValue, This, ImplicitParam, ImplicitParamTy, CE,
+ Args);
return EmitCall(CGM.getTypes().arrangeCXXMethodCall(Args, FPT, required),
Callee, ReturnValue, Args, MD);
}
+RValue CodeGenFunction::EmitCXXStructorCall(
+ const CXXMethodDecl *MD, llvm::Value *Callee, ReturnValueSlot ReturnValue,
+ llvm::Value *This, llvm::Value *ImplicitParam, QualType ImplicitParamTy,
+ const CallExpr *CE, StructorType Type) {
+ CallArgList Args;
+ commonEmitCXXMemberOrOperatorCall(*this, MD, Callee, ReturnValue, This,
+ ImplicitParam, ImplicitParamTy, CE, Args);
+ return EmitCall(CGM.getTypes().arrangeCXXStructorDeclaration(MD, Type),
+ Callee, ReturnValue, Args, MD);
+}
+
static CXXRecordDecl *getCXXRecord(const Expr *E) {
QualType T = E->getType();
if (const PointerType *PTy = T->getAs<PointerType>())
@@ -1389,6 +1410,14 @@ namespace {
};
}
+void
+CodeGenFunction::pushCallObjectDeleteCleanup(const FunctionDecl *OperatorDelete,
+ llvm::Value *CompletePtr,
+ QualType ElementType) {
+ EHStack.pushCleanup<CallObjectDelete>(NormalAndEHCleanup, CompletePtr,
+ OperatorDelete, ElementType);
+}
+
/// Emit the code for deleting a single object.
static void EmitObjectDelete(CodeGenFunction &CGF,
const FunctionDecl *OperatorDelete,
@@ -1404,30 +1433,8 @@ static void EmitObjectDelete(CodeGenFunction &CGF,
Dtor = RD->getDestructor();
if (Dtor->isVirtual()) {
- if (UseGlobalDelete) {
- // If we're supposed to call the global delete, make sure we do so
- // even if the destructor throws.
-
- // Derive the complete-object pointer, which is what we need
- // to pass to the deallocation function.
- llvm::Value *completePtr =
- CGF.CGM.getCXXABI().adjustToCompleteObject(CGF, Ptr, ElementType);
-
- CGF.EHStack.pushCleanup<CallObjectDelete>(NormalAndEHCleanup,
- completePtr, OperatorDelete,
- ElementType);
- }
-
- // FIXME: Provide a source location here even though there's no
- // CXXMemberCallExpr for dtor call.
- CXXDtorType DtorType = UseGlobalDelete ? Dtor_Complete : Dtor_Deleting;
- CGF.CGM.getCXXABI().EmitVirtualDestructorCall(CGF, Dtor, DtorType, Ptr,
- nullptr);
-
- if (UseGlobalDelete) {
- CGF.PopCleanupBlock();
- }
-
+ CGF.CGM.getCXXABI().emitVirtualObjectDelete(
+ CGF, OperatorDelete, Ptr, ElementType, UseGlobalDelete, Dtor);
return;
}
}
diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp
index 51c29fe1717..54f7eb06a15 100644
--- a/clang/lib/CodeGen/CGVTables.cpp
+++ b/clang/lib/CodeGen/CGVTables.cpp
@@ -200,8 +200,11 @@ void CodeGenFunction::StartThunk(llvm::Function *Fn, GlobalDecl GD,
const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
QualType ThisType = MD->getThisType(getContext());
const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
- QualType ResultType =
- CGM.getCXXABI().HasThisReturn(GD) ? ThisType : FPT->getReturnType();
+ QualType ResultType = CGM.getCXXABI().HasThisReturn(GD)
+ ? ThisType
+ : CGM.getCXXABI().hasMostDerivedReturn(GD)
+ ? CGM.getContext().VoidPtrTy
+ : FPT->getReturnType();
FunctionArgList FunctionArgs;
// Create the implicit 'this' parameter declaration.
@@ -278,8 +281,11 @@ void CodeGenFunction::EmitCallAndReturnForThunk(llvm::Value *Callee,
#endif
// Determine whether we have a return value slot to use.
- QualType ResultType =
- CGM.getCXXABI().HasThisReturn(CurGD) ? ThisType : FPT->getReturnType();
+ QualType ResultType = CGM.getCXXABI().HasThisReturn(CurGD)
+ ? ThisType
+ : CGM.getCXXABI().hasMostDerivedReturn(CurGD)
+ ? CGM.getContext().VoidPtrTy
+ : FPT->getReturnType();
ReturnValueSlot Slot;
if (!ResultType->isVoidType() &&
CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect &&
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index e2bf11e0379..16a0b4af09b 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -822,6 +822,8 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
if (MD && MD->isInstance()) {
if (CGM.getCXXABI().HasThisReturn(GD))
ResTy = MD->getThisType(getContext());
+ else if (CGM.getCXXABI().hasMostDerivedReturn(GD))
+ ResTy = CGM.getContext().VoidPtrTy;
CGM.getCXXABI().buildThisParam(*this, Args);
}
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 5faf2accebc..2c7783234b9 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -1136,6 +1136,9 @@ public:
void pushLifetimeExtendedDestroy(CleanupKind kind, llvm::Value *addr,
QualType type, Destroyer *destroyer,
bool useEHCleanupForArray);
+ void pushCallObjectDeleteCleanup(const FunctionDecl *OperatorDelete,
+ llvm::Value *CompletePtr,
+ QualType ElementType);
void pushStackRestore(CleanupKind kind, llvm::Value *SPMem);
void emitDestroy(llvm::Value *addr, QualType type, Destroyer *destroyer,
bool useEHCleanupForArray);
@@ -2319,6 +2322,11 @@ public:
ReturnValueSlot ReturnValue, llvm::Value *This,
llvm::Value *ImplicitParam,
QualType ImplicitParamTy, const CallExpr *E);
+ RValue EmitCXXStructorCall(const CXXMethodDecl *MD, llvm::Value *Callee,
+ ReturnValueSlot ReturnValue, llvm::Value *This,
+ llvm::Value *ImplicitParam,
+ QualType ImplicitParamTy, const CallExpr *E,
+ StructorType Type);
RValue EmitCXXMemberCallExpr(const CXXMemberCallExpr *E,
ReturnValueSlot ReturnValue);
RValue EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E,
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index eb5fbab4381..93d5ff13ecb 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -106,8 +106,11 @@ public:
llvm::Value *Addr,
const MemberPointerType *MPT) override;
- llvm::Value *adjustToCompleteObject(CodeGenFunction &CGF, llvm::Value *ptr,
- QualType type) override;
+ void emitVirtualObjectDelete(CodeGenFunction &CGF,
+ const FunctionDecl *OperatorDelete,
+ llvm::Value *Ptr, QualType ElementType,
+ bool UseGlobalDelete,
+ const CXXDestructorDecl *Dtor) override;
void EmitFundamentalRTTIDescriptor(QualType Type);
void EmitFundamentalRTTIDescriptors();
@@ -187,10 +190,11 @@ public:
llvm::Value *This,
llvm::Type *Ty) override;
- void EmitVirtualDestructorCall(CodeGenFunction &CGF,
- const CXXDestructorDecl *Dtor,
- CXXDtorType DtorType, llvm::Value *This,
- const CXXMemberCallExpr *CE) override;
+ llvm::Value *EmitVirtualDestructorCall(CodeGenFunction &CGF,
+ const CXXDestructorDecl *Dtor,
+ CXXDtorType DtorType,
+ llvm::Value *This,
+ const CXXMemberCallExpr *CE) override;
void emitVirtualInheritanceTables(const CXXRecordDecl *RD) override;
@@ -847,21 +851,38 @@ bool ItaniumCXXABI::isZeroInitializable(const MemberPointerType *MPT) {
/// The Itanium ABI always places an offset to the complete object
/// at entry -2 in the vtable.
-llvm::Value *ItaniumCXXABI::adjustToCompleteObject(CodeGenFunction &CGF,
- llvm::Value *ptr,
- QualType type) {
- // Grab the vtable pointer as an intptr_t*.
- llvm::Value *vtable = CGF.GetVTablePtr(ptr, CGF.IntPtrTy->getPointerTo());
-
- // Track back to entry -2 and pull out the offset there.
- llvm::Value *offsetPtr =
- CGF.Builder.CreateConstInBoundsGEP1_64(vtable, -2, "complete-offset.ptr");
- llvm::LoadInst *offset = CGF.Builder.CreateLoad(offsetPtr);
- offset->setAlignment(CGF.PointerAlignInBytes);
+void ItaniumCXXABI::emitVirtualObjectDelete(
+ CodeGenFunction &CGF, const FunctionDecl *OperatorDelete, llvm::Value *Ptr,
+ QualType ElementType, bool UseGlobalDelete, const CXXDestructorDecl *Dtor) {
+ if (UseGlobalDelete) {
+ // Derive the complete-object pointer, which is what we need
+ // to pass to the deallocation function.
+
+ // Grab the vtable pointer as an intptr_t*.
+ llvm::Value *VTable = CGF.GetVTablePtr(Ptr, CGF.IntPtrTy->getPointerTo());
+
+ // Track back to entry -2 and pull out the offset there.
+ llvm::Value *OffsetPtr = CGF.Builder.CreateConstInBoundsGEP1_64(
+ VTable, -2, "complete-offset.ptr");
+ llvm::LoadInst *Offset = CGF.Builder.CreateLoad(OffsetPtr);
+ Offset->setAlignment(CGF.PointerAlignInBytes);
+
+ // Apply the offset.
+ llvm::Value *CompletePtr = CGF.Builder.CreateBitCast(Ptr, CGF.Int8PtrTy);
+ CompletePtr = CGF.Builder.CreateInBoundsGEP(CompletePtr, Offset);
+
+ // If we're supposed to call the global delete, make sure we do so
+ // even if the destructor throws.
+ CGF.pushCallObjectDeleteCleanup(OperatorDelete, CompletePtr, ElementType);
+ }
- // Apply the offset.
- ptr = CGF.Builder.CreateBitCast(ptr, CGF.Int8PtrTy);
- return CGF.Builder.CreateInBoundsGEP(ptr, offset);
+ // 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);
+
+ if (UseGlobalDelete)
+ CGF.PopCleanupBlock();
}
static llvm::Constant *getItaniumDynamicCastFn(CodeGenFunction &CGF) {
@@ -1333,11 +1354,9 @@ llvm::Value *ItaniumCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
return CGF.Builder.CreateLoad(VFuncPtr);
}
-void ItaniumCXXABI::EmitVirtualDestructorCall(CodeGenFunction &CGF,
- const CXXDestructorDecl *Dtor,
- CXXDtorType DtorType,
- llvm::Value *This,
- const CXXMemberCallExpr *CE) {
+llvm::Value *ItaniumCXXABI::EmitVirtualDestructorCall(
+ CodeGenFunction &CGF, const CXXDestructorDecl *Dtor, CXXDtorType DtorType,
+ llvm::Value *This, const CXXMemberCallExpr *CE) {
assert(CE == nullptr || CE->arg_begin() == CE->arg_end());
assert(DtorType == Dtor_Deleting || DtorType == Dtor_Complete);
@@ -1349,6 +1368,7 @@ void ItaniumCXXABI::EmitVirtualDestructorCall(CodeGenFunction &CGF,
CGF.EmitCXXMemberOrOperatorCall(Dtor, Callee, ReturnValueSlot(), This,
/*ImplicitParam=*/nullptr, QualType(), CE);
+ return nullptr;
}
void ItaniumCXXABI::emitVirtualInheritanceTables(const CXXRecordDecl *RD) {
diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
index 9e5bbd130bb..49907c965d3 100644
--- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -43,6 +43,7 @@ public:
CompleteObjectLocatorType(nullptr) {}
bool HasThisReturn(GlobalDecl GD) const override;
+ bool hasMostDerivedReturn(GlobalDecl GD) const override;
bool classifyReturnType(CGFunctionInfo &FI) const override;
@@ -65,9 +66,11 @@ public:
StringRef GetPureVirtualCallName() override { return "_purecall"; }
StringRef GetDeletedVirtualCallName() override { return "_purecall"; }
- llvm::Value *adjustToCompleteObject(CodeGenFunction &CGF,
- llvm::Value *ptr,
- QualType type) override;
+ void emitVirtualObjectDelete(CodeGenFunction &CGF,
+ const FunctionDecl *OperatorDelete,
+ llvm::Value *Ptr, QualType ElementType,
+ bool UseGlobalDelete,
+ const CXXDestructorDecl *Dtor) override;
llvm::GlobalVariable *getMSCompleteObjectLocator(const CXXRecordDecl *RD,
const VPtrInfo *Info);
@@ -211,10 +214,11 @@ public:
llvm::Value *This,
llvm::Type *Ty) override;
- void EmitVirtualDestructorCall(CodeGenFunction &CGF,
- const CXXDestructorDecl *Dtor,
- CXXDtorType DtorType, llvm::Value *This,
- const CXXMemberCallExpr *CE) override;
+ llvm::Value *EmitVirtualDestructorCall(CodeGenFunction &CGF,
+ const CXXDestructorDecl *Dtor,
+ CXXDtorType DtorType,
+ llvm::Value *This,
+ const CXXMemberCallExpr *CE) override;
void adjustCallArgsForDestructorThunk(CodeGenFunction &CGF, GlobalDecl GD,
CallArgList &CallArgs) override {
@@ -641,11 +645,16 @@ MicrosoftCXXABI::getRecordArgABI(const CXXRecordDecl *RD) const {
llvm_unreachable("invalid enum");
}
-llvm::Value *MicrosoftCXXABI::adjustToCompleteObject(CodeGenFunction &CGF,
- llvm::Value *ptr,
- QualType type) {
- // FIXME: implement
- return ptr;
+void MicrosoftCXXABI::emitVirtualObjectDelete(
+ CodeGenFunction &CGF, const FunctionDecl *OperatorDelete, llvm::Value *Ptr,
+ QualType ElementType, bool UseGlobalDelete, const CXXDestructorDecl *Dtor) {
+ // FIXME: Provide a source location here even though there's no
+ // CXXMemberCallExpr for dtor call.
+ CXXDtorType DtorType = UseGlobalDelete ? Dtor_Complete : Dtor_Deleting;
+ llvm::Value *MDThis =
+ EmitVirtualDestructorCall(CGF, Dtor, DtorType, Ptr, /*CE=*/nullptr);
+ if (UseGlobalDelete)
+ CGF.EmitDeleteCall(OperatorDelete, MDThis, ElementType);
}
/// \brief Gets the offset to the virtual base that contains the vfptr for
@@ -795,6 +804,15 @@ bool MicrosoftCXXABI::HasThisReturn(GlobalDecl GD) const {
return isa<CXXConstructorDecl>(GD.getDecl());
}
+static bool isDeletingDtor(GlobalDecl GD) {
+ return isa<CXXDestructorDecl>(GD.getDecl()) &&
+ GD.getDtorType() == Dtor_Deleting;
+}
+
+bool MicrosoftCXXABI::hasMostDerivedReturn(GlobalDecl GD) const {
+ return isDeletingDtor(GD);
+}
+
bool MicrosoftCXXABI::classifyReturnType(CGFunctionInfo &FI) const {
const CXXRecordDecl *RD = FI.getReturnType()->getAsCXXRecordDecl();
if (!RD)
@@ -1059,14 +1077,6 @@ llvm::Value *MicrosoftCXXABI::adjustThisArgumentForVirtualFunctionCall(
return This;
}
-static bool IsDeletingDtor(GlobalDecl GD) {
- const CXXMethodDecl* MD = cast<CXXMethodDecl>(GD.getDecl());
- if (isa<CXXDestructorDecl>(MD)) {
- return GD.getDtorType() == Dtor_Deleting;
- }
- return false;
-}
-
void MicrosoftCXXABI::addImplicitStructorParams(CodeGenFunction &CGF,
QualType &ResTy,
FunctionArgList &Params) {
@@ -1087,7 +1097,7 @@ void MicrosoftCXXABI::addImplicitStructorParams(CodeGenFunction &CGF,
else
Params.push_back(IsMostDerived);
getStructorImplicitParamDecl(CGF) = IsMostDerived;
- } else if (IsDeletingDtor(CGF.CurGD)) {
+ } else if (isDeletingDtor(CGF.CurGD)) {
ImplicitParamDecl *ShouldDelete
= ImplicitParamDecl::Create(Context, nullptr,
CGF.CurGD.getDecl()->getLocation(),
@@ -1133,6 +1143,9 @@ void MicrosoftCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
/// HasThisReturn only specifies a contract, not the implementation
if (HasThisReturn(CGF.CurGD))
CGF.Builder.CreateStore(getThisValue(CGF), CGF.ReturnValue);
+ else if (hasMostDerivedReturn(CGF.CurGD))
+ CGF.Builder.CreateStore(CGF.EmitCastToVoidPtr(getThisValue(CGF)),
+ CGF.ReturnValue);
const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl());
if (isa<CXXConstructorDecl>(MD) && MD->getParent()->getNumVBases()) {
@@ -1144,7 +1157,7 @@ void MicrosoftCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
"is_most_derived");
}
- if (IsDeletingDtor(CGF.CurGD)) {
+ if (isDeletingDtor(CGF.CurGD)) {
assert(getStructorImplicitParamDecl(CGF) &&
"no implicit parameter for a deleting destructor?");
getStructorImplicitParamValue(CGF)
@@ -1192,9 +1205,10 @@ void MicrosoftCXXABI::EmitDestructorCall(CodeGenFunction &CGF,
This, false);
}
- CGF.EmitCXXMemberOrOperatorCall(DD, Callee, ReturnValueSlot(), This,
- /*ImplicitParam=*/nullptr,
- /*ImplicitParamTy=*/QualType(), nullptr);
+ CGF.EmitCXXStructorCall(DD, Callee, ReturnValueSlot(), This,
+ /*ImplicitParam=*/nullptr,
+ /*ImplicitParamTy=*/QualType(), nullptr,
+ getFromDtorType(Type));
}
void MicrosoftCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,
@@ -1402,11 +1416,9 @@ llvm::Value *MicrosoftCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
return Builder.CreateLoad(VFuncPtr);
}
-void MicrosoftCXXABI::EmitVirtualDestructorCall(CodeGenFunction &CGF,
- const CXXDestructorDecl *Dtor,
- CXXDtorType DtorType,
- llvm::Value *This,
- const CXXMemberCallExpr *CE) {
+llvm::Value *MicrosoftCXXABI::EmitVirtualDestructorCall(
+ CodeGenFunction &CGF, const CXXDestructorDecl *Dtor, CXXDtorType DtorType,
+ llvm::Value *This, const CXXMemberCallExpr *CE) {
assert(CE == nullptr || CE->arg_begin() == CE->arg_end());
assert(DtorType == Dtor_Deleting || DtorType == Dtor_Complete);
@@ -1424,8 +1436,10 @@ void MicrosoftCXXABI::EmitVirtualDestructorCall(CodeGenFunction &CGF,
DtorType == Dtor_Deleting);
This = adjustThisArgumentForVirtualFunctionCall(CGF, GD, This, true);
- CGF.EmitCXXMemberOrOperatorCall(Dtor, Callee, ReturnValueSlot(), This,
- ImplicitParam, Context.IntTy, CE);
+ RValue RV = CGF.EmitCXXStructorCall(Dtor, Callee, ReturnValueSlot(), This,
+ ImplicitParam, Context.IntTy, CE,
+ StructorType::Deleting);
+ return RV.getScalarVal();
}
const VBTableGlobals &
OpenPOWER on IntegriCloud