virtual void EmitVirtualDestructorCall(CodeGenFunction &CGF,
const CXXDestructorDecl *Dtor,
CXXDtorType DtorType,
- SourceLocation CallLoc,
- llvm::Value *This) = 0;
+ llvm::Value *This,
+ const CXXMemberCallExpr *CE) = 0;
virtual void adjustCallArgsForDestructorThunk(CodeGenFunction &CGF,
GlobalDecl GD,
using namespace clang;
using namespace CodeGen;
-RValue CodeGenFunction::EmitCXXMemberCall(const CXXMethodDecl *MD,
- SourceLocation CallLoc,
- llvm::Value *Callee,
- ReturnValueSlot ReturnValue,
- llvm::Value *This,
- llvm::Value *ImplicitParam,
- QualType ImplicitParamTy,
- CallExpr::const_arg_iterator ArgBeg,
- CallExpr::const_arg_iterator ArgEnd) {
+RValue CodeGenFunction::EmitCXXMemberOrOperatorCall(
+ const CXXMethodDecl *MD, llvm::Value *Callee, ReturnValueSlot ReturnValue,
+ llvm::Value *This, llvm::Value *ImplicitParam, QualType ImplicitParamTy,
+ const CallExpr *CE) {
+ assert(CE == nullptr || isa<CXXMemberCallExpr>(CE) ||
+ isa<CXXOperatorCallExpr>(CE));
assert(MD->isInstance() &&
- "Trying to emit a member call expr on a static method!");
+ "Trying to emit a member or operator call expr on a static method!");
// C++11 [class.mfct.non-static]p2:
// If a non-static member function of a class X is called for an object that
// is not of type X, or of a type derived from X, the behavior is undefined.
+ SourceLocation CallLoc;
+ if (CE)
+ CallLoc = CE->getExprLoc();
EmitTypeCheck(isa<CXXConstructorDecl>(MD) ? TCK_ConstructorCall
: TCK_MemberCall,
CallLoc, This, getContext().getRecordType(MD->getParent()));
RequiredArgs required = RequiredArgs::forPrototypePlus(FPT, Args.size());
// And the rest of the call args.
+ CallExpr::const_arg_iterator ArgBeg, ArgEnd;
+ if (CE == nullptr) {
+ ArgBeg = ArgEnd = nullptr;
+ } else if (auto OCE = dyn_cast<CXXOperatorCallExpr>(CE)) {
+ // Special case: skip first argument of CXXOperatorCall (it is "this").
+ ArgBeg = OCE->arg_begin() + 1;
+ ArgEnd = OCE->arg_end();
+ } else {
+ ArgBeg = CE->arg_begin();
+ ArgEnd = CE->arg_end();
+ }
EmitCallArgs(Args, FPT, ArgBeg, ArgEnd);
return EmitCall(CGM.getTypes().arrangeCXXMethodCall(Args, FPT, required),
assert(ReturnValue.isNull() && "Destructor shouldn't have return value");
if (UseVirtualCall) {
CGM.getCXXABI().EmitVirtualDestructorCall(*this, Dtor, Dtor_Complete,
- CE->getExprLoc(), This);
+ This, CE);
} else {
if (getLangOpts().AppleKext &&
MD->isVirtual() &&
cast<CXXDestructorDecl>(DevirtualizedMethod);
Callee = CGM.GetAddrOfFunction(GlobalDecl(DDtor, Dtor_Complete), Ty);
}
- EmitCXXMemberCall(MD, CE->getExprLoc(), Callee, ReturnValue, This,
- /*ImplicitParam=*/nullptr, QualType(), nullptr,nullptr);
+ EmitCXXMemberOrOperatorCall(MD, Callee, ReturnValue, This,
+ /*ImplicitParam=*/nullptr, QualType(), CE);
}
return RValue::get(nullptr);
}
*this, MD, This, UseVirtualCall);
}
- return EmitCXXMemberCall(MD, CE->getExprLoc(), Callee, ReturnValue, This,
- /*ImplicitParam=*/nullptr, QualType(),
- CE->arg_begin(), CE->arg_end());
+ return EmitCXXMemberOrOperatorCall(MD, Callee, ReturnValue, This,
+ /*ImplicitParam=*/nullptr, QualType(), CE);
}
RValue
}
llvm::Value *Callee = EmitCXXOperatorMemberCallee(E, MD, This);
- return EmitCXXMemberCall(MD, E->getExprLoc(), Callee, ReturnValue, This,
- /*ImplicitParam=*/nullptr, QualType(),
- E->arg_begin() + 1, E->arg_end());
+ return EmitCXXMemberOrOperatorCall(MD, Callee, ReturnValue, This,
+ /*ImplicitParam=*/nullptr, QualType(), E);
}
RValue CodeGenFunction::EmitCUDAKernelCallExpr(const CUDAKernelCallExpr *E,
ElementType);
}
- // FIXME: Provide a source location here.
+ // 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,
- SourceLocation(), Ptr);
+ CGF.CGM.getCXXABI().EmitVirtualDestructorCall(CGF, Dtor, DtorType, Ptr,
+ nullptr);
if (UseGlobalDelete) {
CGF.PopCleanupBlock();
}
-
+
return;
}
}
CXXDtorType Type,
const CXXRecordDecl *RD);
- RValue EmitCXXMemberCall(const CXXMethodDecl *MD,
- SourceLocation CallLoc,
- llvm::Value *Callee,
- ReturnValueSlot ReturnValue,
- llvm::Value *This,
- llvm::Value *ImplicitParam,
- QualType ImplicitParamTy,
- CallExpr::const_arg_iterator ArgBeg,
- CallExpr::const_arg_iterator ArgEnd);
+ RValue
+ EmitCXXMemberOrOperatorCall(const CXXMethodDecl *MD, llvm::Value *Callee,
+ ReturnValueSlot ReturnValue, llvm::Value *This,
+ llvm::Value *ImplicitParam,
+ QualType ImplicitParamTy, const CallExpr *E);
RValue EmitCXXMemberCallExpr(const CXXMemberCallExpr *E,
ReturnValueSlot ReturnValue);
RValue EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E,
void EmitVirtualDestructorCall(CodeGenFunction &CGF,
const CXXDestructorDecl *Dtor,
- CXXDtorType DtorType, SourceLocation CallLoc,
- llvm::Value *This) override;
+ CXXDtorType DtorType, llvm::Value *This,
+ const CXXMemberCallExpr *CE) override;
void emitVirtualInheritanceTables(const CXXRecordDecl *RD) override;
if (!Callee)
Callee = CGM.GetAddrOfCXXDestructor(DD, Type);
- // FIXME: Provide a source location here.
- CGF.EmitCXXMemberCall(DD, SourceLocation(), Callee, ReturnValueSlot(), This,
- VTT, VTTTy, nullptr, nullptr);
+ CGF.EmitCXXMemberOrOperatorCall(DD, Callee, ReturnValueSlot(), This, VTT,
+ VTTTy, nullptr);
}
void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,
void ItaniumCXXABI::EmitVirtualDestructorCall(CodeGenFunction &CGF,
const CXXDestructorDecl *Dtor,
CXXDtorType DtorType,
- SourceLocation CallLoc,
- llvm::Value *This) {
+ llvm::Value *This,
+ const CXXMemberCallExpr *CE) {
+ assert(CE == nullptr || CE->arg_begin() == CE->arg_end());
assert(DtorType == Dtor_Deleting || DtorType == Dtor_Complete);
const CGFunctionInfo *FInfo
llvm::Value *Callee =
getVirtualFunctionPointer(CGF, GlobalDecl(Dtor, DtorType), This, Ty);
- CGF.EmitCXXMemberCall(Dtor, CallLoc, Callee, ReturnValueSlot(), This,
- /*ImplicitParam=*/nullptr, QualType(), nullptr,
- nullptr);
+ CGF.EmitCXXMemberOrOperatorCall(Dtor, Callee, ReturnValueSlot(), This,
+ /*ImplicitParam=*/nullptr, QualType(), CE);
}
void ItaniumCXXABI::emitVirtualInheritanceTables(const CXXRecordDecl *RD) {
void EmitVirtualDestructorCall(CodeGenFunction &CGF,
const CXXDestructorDecl *Dtor,
- CXXDtorType DtorType, SourceLocation CallLoc,
- llvm::Value *This) override;
+ CXXDtorType DtorType, llvm::Value *This,
+ const CXXMemberCallExpr *CE) override;
void adjustCallArgsForDestructorThunk(CodeGenFunction &CGF, GlobalDecl GD,
CallArgList &CallArgs) override {
This, false);
}
- // FIXME: Provide a source location here.
- CGF.EmitCXXMemberCall(DD, SourceLocation(), Callee, ReturnValueSlot(), This,
- /*ImplicitParam=*/nullptr,
- /*ImplicitParamTy=*/QualType(), nullptr, nullptr);
+ CGF.EmitCXXMemberOrOperatorCall(DD, Callee, ReturnValueSlot(), This,
+ /*ImplicitParam=*/nullptr,
+ /*ImplicitParamTy=*/QualType(), nullptr);
}
void MicrosoftCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,
void MicrosoftCXXABI::EmitVirtualDestructorCall(CodeGenFunction &CGF,
const CXXDestructorDecl *Dtor,
CXXDtorType DtorType,
- SourceLocation CallLoc,
- llvm::Value *This) {
+ llvm::Value *This,
+ const CXXMemberCallExpr *CE) {
+ assert(CE == nullptr || CE->arg_begin() == CE->arg_end());
assert(DtorType == Dtor_Deleting || DtorType == Dtor_Complete);
// We have only one destructor in the vftable but can get both behaviors
DtorType == Dtor_Deleting);
This = adjustThisArgumentForVirtualFunctionCall(CGF, GD, This, true);
- CGF.EmitCXXMemberCall(Dtor, CallLoc, Callee, ReturnValueSlot(), This,
- ImplicitParam, Context.IntTy, nullptr, nullptr);
+ CGF.EmitCXXMemberOrOperatorCall(Dtor, Callee, ReturnValueSlot(), This,
+ ImplicitParam, Context.IntTy, CE);
}
const VBTableGlobals &