Skip to content

[opaque pointer types] Fix the CallInfo passed to EmitCall in some edge cases. #2

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 36 additions & 15 deletions clang/lib/CodeGen/CGCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,17 @@ unsigned CodeGenTypes::ClangCallConvToLLVMCallConv(CallingConv CC) {
}

/// Derives the 'this' type for codegen purposes, i.e. ignoring method CVR
/// qualification.
static CanQualType GetThisType(ASTContext &Context, const CXXRecordDecl *RD,
const CXXMethodDecl *MD) {
QualType RecTy = Context.getTagDeclType(RD)->getCanonicalTypeInternal();
/// qualification. Either or both of RD and MD may be null. A null RD indicates
/// that there is no meaningful 'this' type, and a null MD can occur when
/// calling a method pointer.
CanQualType CodeGenTypes::DeriveThisType(const CXXRecordDecl *RD,
const CXXMethodDecl *MD) {
QualType RecTy;
if (RD)
RecTy = Context.getTagDeclType(RD)->getCanonicalTypeInternal();
else
RecTy = Context.VoidTy;

if (MD)
RecTy = Context.getAddrSpaceQualType(RecTy, MD->getMethodQualifiers().getAddressSpace());
return Context.getPointerType(CanQualType::CreateUnsafe(RecTy));
Expand Down Expand Up @@ -235,7 +242,7 @@ static CallingConv getCallingConventionForDecl(const Decl *D, bool IsWindows) {

/// Arrange the argument and result information for a call to an
/// unknown C++ non-static member function of the given abstract type.
/// (Zero value of RD means we don't have any meaningful "this" argument type,
/// (A null RD means we don't have any meaningful "this" argument type,
/// so fall back to a generic pointer type).
/// The member function must be an ordinary function, i.e. not a
/// constructor or destructor.
Expand All @@ -246,10 +253,7 @@ CodeGenTypes::arrangeCXXMethodType(const CXXRecordDecl *RD,
SmallVector<CanQualType, 16> argTypes;

// Add the 'this' pointer.
if (RD)
argTypes.push_back(GetThisType(Context, RD, MD));
else
argTypes.push_back(Context.VoidPtrTy);
argTypes.push_back(DeriveThisType(RD, MD));

return ::arrangeLLVMFunctionInfo(
*this, true, argTypes,
Expand Down Expand Up @@ -303,7 +307,7 @@ CodeGenTypes::arrangeCXXStructorDeclaration(const CXXMethodDecl *MD,

SmallVector<CanQualType, 16> argTypes;
SmallVector<FunctionProtoType::ExtParameterInfo, 16> paramInfos;
argTypes.push_back(GetThisType(Context, MD->getParent(), MD));
argTypes.push_back(DeriveThisType(MD->getParent(), MD));

bool PassParams = true;

Expand Down Expand Up @@ -403,8 +407,11 @@ CodeGenTypes::arrangeCXXConstructorCall(const CallArgList &args,
unsigned TotalPrefixArgs = 1 + ExtraPrefixArgs;

CanQual<FunctionProtoType> FPT = GetFormalType(D);
RequiredArgs Required =
RequiredArgs::forPrototypePlus(FPT, TotalPrefixArgs + ExtraSuffixArgs);
RequiredArgs Required = PassProtoArgs
? RequiredArgs::forPrototypePlus(
FPT, TotalPrefixArgs + ExtraSuffixArgs)
: RequiredArgs::All;

GlobalDecl GD(D, CtorKind);
CanQualType ResultType = TheCXXABI.HasThisReturn(GD)
? ArgTypes.front()
Expand Down Expand Up @@ -530,7 +537,7 @@ const CGFunctionInfo &
CodeGenTypes::arrangeUnprototypedMustTailThunk(const CXXMethodDecl *MD) {
assert(MD->isVirtual() && "only methods have thunks");
CanQual<FunctionProtoType> FTP = GetFormalType(MD);
CanQualType ArgTys[] = { GetThisType(Context, MD->getParent(), MD) };
CanQualType ArgTys[] = {DeriveThisType(MD->getParent(), MD)};
return arrangeLLVMFunctionInfo(Context.VoidTy, /*instanceMethod=*/false,
/*chainCall=*/false, ArgTys,
FTP->getExtInfo(), {}, RequiredArgs(1));
Expand All @@ -544,7 +551,7 @@ CodeGenTypes::arrangeMSCtorClosure(const CXXConstructorDecl *CD,
CanQual<FunctionProtoType> FTP = GetFormalType(CD);
SmallVector<CanQualType, 2> ArgTys;
const CXXRecordDecl *RD = CD->getParent();
ArgTys.push_back(GetThisType(Context, RD, CD));
ArgTys.push_back(DeriveThisType(RD, CD));
if (CT == Ctor_CopyingClosure)
ArgTys.push_back(*FTP->param_type_begin());
if (RD->getNumVBases() > 0)
Expand Down Expand Up @@ -577,7 +584,7 @@ arrangeFreeFunctionLikeCall(CodeGenTypes &CGT,
// extra prefix plus the arguments in the prototype.
if (const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(fnType)) {
if (proto->isVariadic())
required = RequiredArgs(proto->getNumParams() + numExtraRequiredArgs);
required = RequiredArgs::forPrototypePlus(proto, numExtraRequiredArgs);

if (proto->hasExtParameterInfos())
addExtParameterInfosForCall(paramInfos, proto, numExtraRequiredArgs,
Expand Down Expand Up @@ -802,6 +809,8 @@ CGFunctionInfo *CGFunctionInfo::create(unsigned llvmCC,
ArrayRef<CanQualType> argTypes,
RequiredArgs required) {
assert(paramInfos.empty() || paramInfos.size() == argTypes.size());
assert(!required.allowsOptionalArgs() ||
required.getNumRequiredArgs() <= argTypes.size());

void *buffer =
operator new(totalSizeToAlloc<ArgInfo, ExtParameterInfo>(
Expand Down Expand Up @@ -3817,6 +3826,18 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
const ABIArgInfo &RetAI = CallInfo.getReturnInfo();

llvm::FunctionType *IRFuncTy = Callee.getFunctionType();
if (!(CallInfo.isVariadic() && CallInfo.getArgStruct())) {
// For an inalloca varargs function, we don't expect CallInfo to match the
// function pointer's type, because the inalloca arg will have the extra
// varargs fields in it. We bitcast to type derived from CallInfo, below.
llvm::FunctionType *IRFuncTyFromInfo = getTypes().GetFunctionType(CallInfo);
if (IRFuncTy != IRFuncTyFromInfo) {
fprintf(stderr, "Function types -- from ptr vs from CallInfo:\n");
IRFuncTy->dump();
IRFuncTyFromInfo->dump();
assert(IRFuncTy == IRFuncTyFromInfo);
}
}

// 1. Set up the arguments.

Expand Down
30 changes: 14 additions & 16 deletions clang/lib/CodeGen/CGExprCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,11 @@ commonEmitCXXMemberOrOperatorCall(CodeGenFunction &CGF, const CXXMethodDecl *MD,
isa<CXXOperatorCallExpr>(CE));
assert(MD->isInstance() &&
"Trying to emit a member or operator call expr on a static method!");
ASTContext &C = CGF.getContext();

// Push the this ptr.
const CXXRecordDecl *RD =
CGF.CGM.getCXXABI().getThisArgumentTypeForMethod(MD);
Args.add(RValue::get(This),
RD ? C.getPointerType(C.getTypeDeclType(RD)) : C.VoidPtrTy);
Args.add(RValue::get(This), CGF.getTypes().DeriveThisType(RD, MD));

// If there is an implicit parameter (e.g. VTT), emit it.
if (ImplicitParam) {
Expand Down Expand Up @@ -326,9 +324,6 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr(
CallLoc, This.getPointer(), C.getRecordType(CalleeDecl->getParent()),
/*Alignment=*/CharUnits::Zero(), SkippedChecks);

// FIXME: Uses of 'MD' past this point need to be audited. We may need to use
// 'CalleeDecl' instead.

// C++ [class.virtual]p12:
// Explicit qualification with the scope operator (5.1) suppresses the
// virtual call mechanism.
Expand All @@ -337,7 +332,7 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr(
// because then we know what the type is.
bool UseVirtualCall = CanUseVirtualCall && !DevirtualizedMethod;

if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(MD)) {
if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(CalleeDecl)) {
assert(CE->arg_begin() == CE->arg_end() &&
"Destructor shouldn't have explicit parameters");
assert(ReturnValue.isNull() && "Destructor shouldn't have return value");
Expand All @@ -347,26 +342,29 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr(
cast<CXXMemberCallExpr>(CE));
} else {
CGCallee Callee;
if (getLangOpts().AppleKext && MD->isVirtual() && HasQualifier)
Callee = BuildAppleKextVirtualCall(MD, Qualifier, Ty);
if (getLangOpts().AppleKext && Dtor->isVirtual() && HasQualifier)
Callee = BuildAppleKextVirtualCall(Dtor, Qualifier, Ty);
else if (!DevirtualizedMethod)
Callee = CGCallee::forDirect(
CGM.getAddrOfCXXStructor(Dtor, StructorType::Complete, FInfo, Ty),
GlobalDecl(Dtor, Dtor_Complete));
else {
const CXXDestructorDecl *DDtor =
cast<CXXDestructorDecl>(DevirtualizedMethod);
Callee = CGCallee::forDirect(
CGM.GetAddrOfFunction(GlobalDecl(DDtor, Dtor_Complete), Ty),
GlobalDecl(DDtor, Dtor_Complete));
CGM.GetAddrOfFunction(GlobalDecl(Dtor, Dtor_Complete), Ty),
GlobalDecl(Dtor, Dtor_Complete));
}
EmitCXXMemberOrOperatorCall(
CalleeDecl, Callee, ReturnValue, This.getPointer(),
/*ImplicitParam=*/nullptr, QualType(), CE, nullptr);

EmitCXXDestructorCall(Dtor, Callee, This.getPointer(),
/*ImplicitParam=*/nullptr,
/*ImplicitParamTy=*/QualType(), nullptr,
getFromDtorType(Dtor_Complete));
}
return RValue::get(nullptr);
}

// FIXME: Uses of 'MD' past this point need to be audited. We may need to use
// 'CalleeDecl' instead.

CGCallee Callee;
if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(MD)) {
Callee = CGCallee::forDirect(
Expand Down
6 changes: 3 additions & 3 deletions clang/lib/CodeGen/CGObjC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1051,9 +1051,9 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl,
// FIXME: We shouldn't need to get the function info here, the
// runtime already should have computed it to build the function.
llvm::CallBase *CallInstruction;
RValue RV = EmitCall(
getTypes().arrangeBuiltinFunctionCall(propType, args),
callee, ReturnValueSlot(), args, &CallInstruction);
RValue RV = EmitCall(getTypes().arrangeBuiltinFunctionCall(
getContext().getObjCIdType(), args),
callee, ReturnValueSlot(), args, &CallInstruction);
if (llvm::CallInst *call = dyn_cast<llvm::CallInst>(CallInstruction))
call->setTailCall();

Expand Down
4 changes: 4 additions & 0 deletions clang/lib/CodeGen/CodeGenTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,10 @@ class CodeGenTypes {
/// Convert clang calling convention to LLVM callilng convention.
unsigned ClangCallConvToLLVMCallConv(CallingConv CC);

/// Derives the 'this' type for codegen purposes, i.e. ignoring method CVR
/// qualification.
CanQualType DeriveThisType(const CXXRecordDecl *RD, const CXXMethodDecl *MD);

/// ConvertType - Convert type T into a llvm::Type.
llvm::Type *ConvertType(QualType T);

Expand Down
10 changes: 4 additions & 6 deletions clang/lib/CodeGen/ItaniumCXXABI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1566,9 +1566,8 @@ void ItaniumCXXABI::EmitDestructorCall(CodeGenFunction &CGF,
Callee = CGCallee::forDirect(
CGM.getAddrOfCXXStructor(DD, getFromDtorType(Type)), GD);

CGF.EmitCXXMemberOrOperatorCall(DD, Callee, ReturnValueSlot(),
This.getPointer(), VTT, VTTTy,
nullptr, nullptr);
CGF.EmitCXXDestructorCall(DD, Callee, This.getPointer(), VTT, VTTTy, nullptr,
getFromDtorType(Type));
}

void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,
Expand Down Expand Up @@ -1766,9 +1765,8 @@ llvm::Value *ItaniumCXXABI::EmitVirtualDestructorCall(
CGCallee Callee =
CGCallee::forVirtual(CE, GlobalDecl(Dtor, DtorType), This, Ty);

CGF.EmitCXXMemberOrOperatorCall(Dtor, Callee, ReturnValueSlot(),
This.getPointer(), /*ImplicitParam=*/nullptr,
QualType(), CE, nullptr);
CGF.EmitCXXDestructorCall(Dtor, Callee, This.getPointer(), nullptr,
QualType(), nullptr, getFromDtorType(DtorType));
return nullptr;
}

Expand Down
6 changes: 4 additions & 2 deletions clang/lib/Sema/SemaOpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10747,7 +10747,8 @@ buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range,
return D;
return nullptr;
}))
return SemaRef.BuildDeclRefExpr(VD, Ty, VK_LValue, Loc);
return SemaRef.BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(),
VK_LValue, Loc);
if (auto *VD = filterLookupForUDR<ValueDecl *>(
Lookups, [&SemaRef, Ty, Loc](ValueDecl *D) -> ValueDecl * {
if (!D->isInvalidDecl() &&
Expand All @@ -10765,7 +10766,8 @@ buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range,
/*DiagID=*/0) !=
Sema::AR_inaccessible) {
SemaRef.BuildBasePathArray(Paths, BasePath);
return SemaRef.BuildDeclRefExpr(VD, Ty, VK_LValue, Loc);
return SemaRef.BuildDeclRefExpr(
VD, VD->getType().getNonReferenceType(), VK_LValue, Loc);
}
}
}
Expand Down
4 changes: 1 addition & 3 deletions clang/test/CodeGenObjC/getter-property-mismatch.m
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,4 @@ @implementation CalDAVAddManagedAttachmentsTaskGroup

// CHECK: [[CALL:%.*]] = tail call i8* @objc_getProperty
// CHECK: [[ONE:%.*]] = bitcast i8* [[CALL:%.*]] to [[T1:%.*]]*
// CHECK: [[TWO:%.*]] = bitcast [[T1]]* [[ONE]] to [[T2:%.*]]*
// CHECK: ret [[T2]]* [[TWO]]

// CHECK: ret [[T1]]* [[ONE]]