// These versions of the constructor are for derived classes.
CallExpr(const ASTContext &C, StmtClass SC, Expr *fn,
ArrayRef<Expr *> preargs, ArrayRef<Expr *> args, QualType t,
- ExprValueKind VK, SourceLocation rparenloc);
+ ExprValueKind VK, SourceLocation rparenloc, unsigned MinNumArgs = 0);
CallExpr(const ASTContext &C, StmtClass SC, Expr *fn, ArrayRef<Expr *> args,
- QualType t, ExprValueKind VK, SourceLocation rparenloc);
+ QualType t, ExprValueKind VK, SourceLocation rparenloc,
+ unsigned MinNumArgs = 0);
CallExpr(const ASTContext &C, StmtClass SC, unsigned NumPreArgs,
- EmptyShell Empty);
+ unsigned NumArgs, EmptyShell Empty);
Stmt *getPreArg(unsigned i) {
assert(i < getNumPreArgs() && "Prearg access out of range!");
unsigned getNumPreArgs() const { return CallExprBits.NumPreArgs; }
public:
- CallExpr(const ASTContext& C, Expr *fn, ArrayRef<Expr*> args, QualType t,
- ExprValueKind VK, SourceLocation rparenloc);
+ /// Build a call expression. MinNumArgs specifies the minimum number of
+ /// arguments. The actual number of arguments will be the greater of
+ /// args.size() and MinNumArgs.
+ CallExpr(const ASTContext &C, Expr *fn, ArrayRef<Expr *> args, QualType t,
+ ExprValueKind VK, SourceLocation rparenloc, unsigned MinNumArgs = 0);
/// Build an empty call expression.
- CallExpr(const ASTContext &C, StmtClass SC, EmptyShell Empty);
+ CallExpr(const ASTContext &C, unsigned NumArgs, EmptyShell Empty);
const Expr *getCallee() const { return cast<Expr>(SubExprs[FN]); }
Expr *getCallee() { return cast<Expr>(SubExprs[FN]); }
SubExprs[Arg+getNumPreArgs()+PREARGS_START] = ArgExpr;
}
- /// setNumArgs - This changes the number of arguments present in this call.
- /// Any orphaned expressions are deleted by this, and any new operands are set
- /// to null.
- void setNumArgs(const ASTContext& C, unsigned NumArgs);
+ /// Reduce the number of arguments in this call expression. This is used for
+ /// example during error recovery to drop extra arguments. There is no way
+ /// to perform the opposite because: 1.) We don't track how much storage
+ /// we have for the argument array 2.) This would potentially require growing
+ /// the argument array, something we cannot support since the arguments will
+ /// be stored in a trailing array in the future.
+ /// (TODO: update this comment when this is done).
+ void shrinkNumArgs(unsigned NewNumArgs) {
+ assert((NewNumArgs <= NumArgs) &&
+ "shrinkNumArgs cannot increase the number of arguments!");
+ NumArgs = NewNumArgs;
+ }
typedef ExprIterator arg_iterator;
typedef ConstExprIterator const_arg_iterator;
Range = getSourceRangeImpl();
}
- explicit CXXOperatorCallExpr(ASTContext& C, EmptyShell Empty)
- : CallExpr(C, CXXOperatorCallExprClass, Empty) {}
+ explicit CXXOperatorCallExpr(ASTContext &C, unsigned NumArgs,
+ EmptyShell Empty)
+ : CallExpr(C, CXXOperatorCallExprClass, /*NumPreArgs=*/0, NumArgs,
+ Empty) {}
/// Returns the kind of overloaded operator that this
/// expression refers to.
/// the object argument).
class CXXMemberCallExpr : public CallExpr {
public:
- CXXMemberCallExpr(ASTContext &C, Expr *fn, ArrayRef<Expr*> args,
- QualType t, ExprValueKind VK, SourceLocation RP)
- : CallExpr(C, CXXMemberCallExprClass, fn, args, t, VK, RP) {}
+ CXXMemberCallExpr(ASTContext &C, Expr *fn, ArrayRef<Expr *> args, QualType t,
+ ExprValueKind VK, SourceLocation RP,
+ unsigned MinNumArgs = 0)
+ : CallExpr(C, CXXMemberCallExprClass, fn, args, t, VK, RP, MinNumArgs) {}
- CXXMemberCallExpr(ASTContext &C, EmptyShell Empty)
- : CallExpr(C, CXXMemberCallExprClass, Empty) {}
+ CXXMemberCallExpr(ASTContext &C, unsigned NumArgs, EmptyShell Empty)
+ : CallExpr(C, CXXMemberCallExprClass, /*NumPreArgs=*/0, NumArgs, Empty) {}
/// Retrieves the implicit object argument for the member call.
///
public:
CUDAKernelCallExpr(ASTContext &C, Expr *fn, CallExpr *Config,
- ArrayRef<Expr*> args, QualType t, ExprValueKind VK,
- SourceLocation RP)
- : CallExpr(C, CUDAKernelCallExprClass, fn, Config, args, t, VK, RP) {}
+ ArrayRef<Expr *> args, QualType t, ExprValueKind VK,
+ SourceLocation RP, unsigned MinNumArgs = 0)
+ : CallExpr(C, CUDAKernelCallExprClass, fn, Config, args, t, VK, RP,
+ MinNumArgs) {}
- CUDAKernelCallExpr(ASTContext &C, EmptyShell Empty)
- : CallExpr(C, CUDAKernelCallExprClass, END_PREARG, Empty) {}
+ CUDAKernelCallExpr(ASTContext &C, unsigned NumArgs, EmptyShell Empty)
+ : CallExpr(C, CUDAKernelCallExprClass, /*NumPreArgs=*/END_PREARG, NumArgs,
+ Empty) {}
const CallExpr *getConfig() const {
return cast_or_null<CallExpr>(getPreArg(CONFIG));
: CallExpr(C, UserDefinedLiteralClass, Fn, Args, T, VK, LitEndLoc),
UDSuffixLoc(SuffixLoc) {}
- explicit UserDefinedLiteral(const ASTContext &C, EmptyShell Empty)
- : CallExpr(C, UserDefinedLiteralClass, Empty) {}
+ explicit UserDefinedLiteral(const ASTContext &C, unsigned NumArgs,
+ EmptyShell Empty)
+ : CallExpr(C, UserDefinedLiteralClass, /*NumPreArgs=*/0, NumArgs,
+ Empty) {}
/// The kind of literal operator which is invoked.
enum LiteralOperatorKind {
CallExpr::CallExpr(const ASTContext &C, StmtClass SC, Expr *fn,
ArrayRef<Expr *> preargs, ArrayRef<Expr *> args, QualType t,
- ExprValueKind VK, SourceLocation rparenloc)
+ ExprValueKind VK, SourceLocation rparenloc,
+ unsigned MinNumArgs)
: Expr(SC, t, VK, OK_Ordinary, fn->isTypeDependent(),
fn->isValueDependent(), fn->isInstantiationDependent(),
fn->containsUnexpandedParameterPack()),
- NumArgs(args.size()) {
-
+ RParenLoc(rparenloc) {
+ NumArgs = std::max<unsigned>(args.size(), MinNumArgs);
unsigned NumPreArgs = preargs.size();
- SubExprs = new (C) Stmt *[args.size()+PREARGS_START+NumPreArgs];
+ CallExprBits.NumPreArgs = NumPreArgs;
+
+ SubExprs = new (C) Stmt *[NumArgs + PREARGS_START + NumPreArgs];
SubExprs[FN] = fn;
for (unsigned i = 0; i != NumPreArgs; ++i) {
updateDependenciesFromArg(preargs[i]);
updateDependenciesFromArg(args[i]);
SubExprs[i+PREARGS_START+NumPreArgs] = args[i];
}
-
- CallExprBits.NumPreArgs = NumPreArgs;
- RParenLoc = rparenloc;
+ for (unsigned i = args.size(); i != NumArgs; ++i) {
+ SubExprs[i + PREARGS_START + NumPreArgs] = nullptr;
+ }
}
CallExpr::CallExpr(const ASTContext &C, StmtClass SC, Expr *fn,
ArrayRef<Expr *> args, QualType t, ExprValueKind VK,
- SourceLocation rparenloc)
- : CallExpr(C, SC, fn, ArrayRef<Expr *>(), args, t, VK, rparenloc) {}
+ SourceLocation rparenloc, unsigned MinNumArgs)
+ : CallExpr(C, SC, fn, ArrayRef<Expr *>(), args, t, VK, rparenloc,
+ MinNumArgs) {}
CallExpr::CallExpr(const ASTContext &C, Expr *fn, ArrayRef<Expr *> args,
- QualType t, ExprValueKind VK, SourceLocation rparenloc)
- : CallExpr(C, CallExprClass, fn, ArrayRef<Expr *>(), args, t, VK, rparenloc) {
-}
-
-CallExpr::CallExpr(const ASTContext &C, StmtClass SC, EmptyShell Empty)
- : CallExpr(C, SC, /*NumPreArgs=*/0, Empty) {}
+ QualType t, ExprValueKind VK, SourceLocation rparenloc,
+ unsigned MinNumArgs)
+ : CallExpr(C, CallExprClass, fn, ArrayRef<Expr *>(), args, t, VK,
+ rparenloc, MinNumArgs) {}
CallExpr::CallExpr(const ASTContext &C, StmtClass SC, unsigned NumPreArgs,
- EmptyShell Empty)
- : Expr(SC, Empty), SubExprs(nullptr), NumArgs(0) {
- // FIXME: Why do we allocate this?
- SubExprs = new (C) Stmt*[PREARGS_START+NumPreArgs]();
+ unsigned NumArgs, EmptyShell Empty)
+ : Expr(SC, Empty), NumArgs(NumArgs) {
CallExprBits.NumPreArgs = NumPreArgs;
+ SubExprs = new (C) Stmt *[NumArgs + PREARGS_START + NumPreArgs];
}
+CallExpr::CallExpr(const ASTContext &C, unsigned NumArgs, EmptyShell Empty)
+ : CallExpr(C, CallExprClass, /*NumPreArgs=*/0, NumArgs, Empty) {}
+
void CallExpr::updateDependenciesFromArg(Expr *Arg) {
if (Arg->isTypeDependent())
ExprBits.TypeDependent = true;
return nullptr;
}
-/// setNumArgs - This changes the number of arguments present in this call.
-/// Any orphaned expressions are deleted by this, and any new operands are set
-/// to null.
-void CallExpr::setNumArgs(const ASTContext& C, unsigned NumArgs) {
- // No change, just return.
- if (NumArgs == getNumArgs()) return;
-
- // If shrinking # arguments, just delete the extras and forgot them.
- if (NumArgs < getNumArgs()) {
- this->NumArgs = NumArgs;
- return;
- }
-
- // Otherwise, we are growing the # arguments. New an bigger argument array.
- unsigned NumPreArgs = getNumPreArgs();
- Stmt **NewSubExprs = new (C) Stmt*[NumArgs+PREARGS_START+NumPreArgs];
- // Copy over args.
- for (unsigned i = 0; i != getNumArgs()+PREARGS_START+NumPreArgs; ++i)
- NewSubExprs[i] = SubExprs[i];
- // Null out new args.
- for (unsigned i = getNumArgs()+PREARGS_START+NumPreArgs;
- i != NumArgs+PREARGS_START+NumPreArgs; ++i)
- NewSubExprs[i] = nullptr;
-
- if (SubExprs) C.Deallocate(SubExprs);
- SubExprs = NewSubExprs;
- this->NumArgs = NumArgs;
-}
-
/// getBuiltinCallee - If this is a call to a builtin, return the builtin ID. If
/// not, return 0.
unsigned CallExpr::getBuiltinCallee() const {
return true;
}
- Call->setNumArgs(Context, NumParams);
+ // We reserve space for the default arguments when we create
+ // the call expression, before calling ConvertArgumentsForCall.
+ assert((Call->getNumArgs() == NumParams) &&
+ "We should have reserved space for the default arguments before!");
}
// If too many are passed and not variadic, error on the extras and drop
Diag(FDecl->getBeginLoc(), diag::note_callee_decl) << FDecl;
// This deletes the extra arguments.
- Call->setNumArgs(Context, NumParams);
+ Call->shrinkNumArgs(NumParams);
return true;
}
}
return ExprError();
Fn = Result.get();
- // Make the call expr early, before semantic checks. This guarantees cleanup
- // of arguments and function on error.
+ // Check for a valid function type, but only if it is not a builtin which
+ // requires custom type checking. These will be handled by
+ // CheckBuiltinFunctionCall below just after creation of the call expression.
+ const FunctionType *FuncT = nullptr;
+ if (!BuiltinID || !Context.BuiltinInfo.hasCustomTypechecking(BuiltinID)) {
+ retry:
+ if (const PointerType *PT = Fn->getType()->getAs<PointerType>()) {
+ // C99 6.5.2.2p1 - "The expression that denotes the called function shall
+ // have type pointer to function".
+ FuncT = PT->getPointeeType()->getAs<FunctionType>();
+ if (!FuncT)
+ return ExprError(Diag(LParenLoc, diag::err_typecheck_call_not_function)
+ << Fn->getType() << Fn->getSourceRange());
+ } else if (const BlockPointerType *BPT =
+ Fn->getType()->getAs<BlockPointerType>()) {
+ FuncT = BPT->getPointeeType()->castAs<FunctionType>();
+ } else {
+ // Handle calls to expressions of unknown-any type.
+ if (Fn->getType() == Context.UnknownAnyTy) {
+ ExprResult rewrite = rebuildUnknownAnyFunction(*this, Fn);
+ if (rewrite.isInvalid()) return ExprError();
+ Fn = rewrite.get();
+ goto retry;
+ }
+
+ return ExprError(Diag(LParenLoc, diag::err_typecheck_call_not_function)
+ << Fn->getType() << Fn->getSourceRange());
+ }
+ }
+
+ // Get the number of parameters in the function prototype, if any.
+ // We will allocate space for max(Args.size(), NumParams) arguments
+ // in the call expression.
+ const auto *Proto = dyn_cast_or_null<FunctionProtoType>(FuncT);
+ unsigned NumParams = Proto ? Proto->getNumParams() : 0;
+
CallExpr *TheCall;
if (Config)
- TheCall =
- new (Context) CUDAKernelCallExpr(Context, Fn, cast<CallExpr>(Config),
- Args, ResultTy, VK_RValue, RParenLoc);
+ TheCall = new (Context)
+ CUDAKernelCallExpr(Context, Fn, cast<CallExpr>(Config), Args, ResultTy,
+ VK_RValue, RParenLoc, NumParams);
else
TheCall = new (Context)
- CallExpr(Context, Fn, Args, ResultTy, VK_RValue, RParenLoc);
+ CallExpr(Context, Fn, Args, ResultTy, VK_RValue, RParenLoc, NumParams);
if (!getLangOpts().CPlusPlus) {
// C cannot always handle TypoExpr nodes in builtin calls and direct
if (!Result.isUsable()) return ExprError();
TheCall = dyn_cast<CallExpr>(Result.get());
if (!TheCall) return Result;
- Args = llvm::makeArrayRef(TheCall->getArgs(), TheCall->getNumArgs());
+ // TheCall at this point has max(Args.size(), NumParams) arguments,
+ // with extra arguments nulled. We don't want to introduce nulled
+ // arguments in Args and so we only take the first Args.size() arguments.
+ Args = llvm::makeArrayRef(TheCall->getArgs(), Args.size());
}
- // Bail out early if calling a builtin with custom typechecking.
+ // Bail out early if calling a builtin with custom type checking.
if (BuiltinID && Context.BuiltinInfo.hasCustomTypechecking(BuiltinID))
return CheckBuiltinFunctionCall(FDecl, BuiltinID, TheCall);
- retry:
- const FunctionType *FuncT;
- if (const PointerType *PT = Fn->getType()->getAs<PointerType>()) {
- // C99 6.5.2.2p1 - "The expression that denotes the called function shall
- // have type pointer to function".
- FuncT = PT->getPointeeType()->getAs<FunctionType>();
- if (!FuncT)
- return ExprError(Diag(LParenLoc, diag::err_typecheck_call_not_function)
- << Fn->getType() << Fn->getSourceRange());
- } else if (const BlockPointerType *BPT =
- Fn->getType()->getAs<BlockPointerType>()) {
- FuncT = BPT->getPointeeType()->castAs<FunctionType>();
- } else {
- // Handle calls to expressions of unknown-any type.
- if (Fn->getType() == Context.UnknownAnyTy) {
- ExprResult rewrite = rebuildUnknownAnyFunction(*this, Fn);
- if (rewrite.isInvalid()) return ExprError();
- Fn = rewrite.get();
- TheCall->setCallee(Fn);
- goto retry;
- }
-
- return ExprError(Diag(LParenLoc, diag::err_typecheck_call_not_function)
- << Fn->getType() << Fn->getSourceRange());
- }
-
if (getLangOpts().CUDA) {
if (Config) {
// CUDA: Kernel calls must be to global functions
TheCall->setType(FuncT->getCallResultType(Context));
TheCall->setValueKind(Expr::getValueKindForType(FuncT->getReturnType()));
- const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FuncT);
if (Proto) {
if (ConvertArgumentsForCall(TheCall, Fn, FDecl, Proto, Args, RParenLoc,
IsExecConfig))
CXXMemberCallExpr *call
= new (Context) CXXMemberCallExpr(Context, MemExprE, Args,
- resultType, valueKind, RParenLoc);
+ resultType, valueKind, RParenLoc,
+ proto->getNumParams());
if (CheckCallReturnType(proto->getReturnType(), op->getRHS()->getBeginLoc(),
call, nullptr))
ResultType = ResultType.getNonLValueExprType(Context);
assert(Method && "Member call to something that isn't a method?");
+ const auto *Proto = Method->getType()->getAs<FunctionProtoType>();
CXXMemberCallExpr *TheCall =
new (Context) CXXMemberCallExpr(Context, MemExprE, Args,
- ResultType, VK, RParenLoc);
+ ResultType, VK, RParenLoc,
+ Proto->getNumParams());
// Check for a valid return type.
if (CheckCallReturnType(Method->getReturnType(), MemExpr->getMemberLoc(),
}
// Convert the rest of the arguments
- const FunctionProtoType *Proto =
- Method->getType()->getAs<FunctionProtoType>();
if (ConvertArgumentsForCall(TheCall, MemExpr, Method, Proto, Args,
RParenLoc))
return ExprError();
void ASTStmtReader::VisitCallExpr(CallExpr *E) {
VisitExpr(E);
- E->setNumArgs(Record.getContext(), Record.readInt());
+ unsigned NumArgs = Record.readInt();
+ assert((NumArgs == E->getNumArgs()) && "Wrong NumArgs!");
E->setRParenLoc(ReadSourceLocation());
E->setCallee(Record.readSubExpr());
- for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I)
+ for (unsigned I = 0; I != NumArgs; ++I)
E->setArg(I, Record.readSubExpr());
}
break;
case EXPR_CALL:
- S = new (Context) CallExpr(Context, Stmt::CallExprClass, Empty);
+ S = new (Context) CallExpr(
+ Context, /* NumArgs=*/Record[ASTStmtReader::NumExprFields + 0],
+ Empty);
break;
case EXPR_MEMBER: {
}
case EXPR_CXX_OPERATOR_CALL:
- S = new (Context) CXXOperatorCallExpr(Context, Empty);
+ S = new (Context) CXXOperatorCallExpr(
+ Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields + 0],
+ Empty);
break;
case EXPR_CXX_MEMBER_CALL:
- S = new (Context) CXXMemberCallExpr(Context, Empty);
+ S = new (Context) CXXMemberCallExpr(
+ Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields + 0],
+ Empty);
break;
case EXPR_CXX_CONSTRUCT:
break;
case EXPR_USER_DEFINED_LITERAL:
- S = new (Context) UserDefinedLiteral(Context, Empty);
+ S = new (Context) UserDefinedLiteral(
+ Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields + 0], Empty);
break;
case EXPR_CXX_STD_INITIALIZER_LIST:
break;
case EXPR_CUDA_KERNEL_CALL:
- S = new (Context) CUDAKernelCallExpr(Context, Empty);
+ S = new (Context) CUDAKernelCallExpr(
+ Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields + 0], Empty);
break;
case EXPR_ASTYPE: