Index: cfe/trunk/include/clang/AST/Expr.h =================================================================== --- cfe/trunk/include/clang/AST/Expr.h +++ cfe/trunk/include/clang/AST/Expr.h @@ -2416,11 +2416,12 @@ // These versions of the constructor are for derived classes. CallExpr(const ASTContext &C, StmtClass SC, Expr *fn, ArrayRef preargs, ArrayRef args, QualType t, - ExprValueKind VK, SourceLocation rparenloc); + ExprValueKind VK, SourceLocation rparenloc, unsigned MinNumArgs = 0); CallExpr(const ASTContext &C, StmtClass SC, Expr *fn, ArrayRef 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!"); @@ -2438,11 +2439,14 @@ unsigned getNumPreArgs() const { return CallExprBits.NumPreArgs; } public: - CallExpr(const ASTContext& C, Expr *fn, ArrayRef 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 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(SubExprs[FN]); } Expr *getCallee() { return cast(SubExprs[FN]); } @@ -2488,10 +2492,18 @@ 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; Index: cfe/trunk/include/clang/AST/ExprCXX.h =================================================================== --- cfe/trunk/include/clang/AST/ExprCXX.h +++ cfe/trunk/include/clang/AST/ExprCXX.h @@ -98,8 +98,10 @@ 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. @@ -163,12 +165,13 @@ /// the object argument). class CXXMemberCallExpr : public CallExpr { public: - CXXMemberCallExpr(ASTContext &C, Expr *fn, ArrayRef args, - QualType t, ExprValueKind VK, SourceLocation RP) - : CallExpr(C, CXXMemberCallExprClass, fn, args, t, VK, RP) {} + CXXMemberCallExpr(ASTContext &C, Expr *fn, ArrayRef 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. /// @@ -206,12 +209,14 @@ public: CUDAKernelCallExpr(ASTContext &C, Expr *fn, CallExpr *Config, - ArrayRef args, QualType t, ExprValueKind VK, - SourceLocation RP) - : CallExpr(C, CUDAKernelCallExprClass, fn, Config, args, t, VK, RP) {} - - CUDAKernelCallExpr(ASTContext &C, EmptyShell Empty) - : CallExpr(C, CUDAKernelCallExprClass, END_PREARG, Empty) {} + ArrayRef args, QualType t, ExprValueKind VK, + SourceLocation RP, unsigned MinNumArgs = 0) + : CallExpr(C, CUDAKernelCallExprClass, fn, Config, args, t, VK, RP, + MinNumArgs) {} + + CUDAKernelCallExpr(ASTContext &C, unsigned NumArgs, EmptyShell Empty) + : CallExpr(C, CUDAKernelCallExprClass, /*NumPreArgs=*/END_PREARG, NumArgs, + Empty) {} const CallExpr *getConfig() const { return cast_or_null(getPreArg(CONFIG)); @@ -488,8 +493,10 @@ : 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 { Index: cfe/trunk/lib/AST/Expr.cpp =================================================================== --- cfe/trunk/lib/AST/Expr.cpp +++ cfe/trunk/lib/AST/Expr.cpp @@ -1222,14 +1222,17 @@ CallExpr::CallExpr(const ASTContext &C, StmtClass SC, Expr *fn, ArrayRef preargs, ArrayRef 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(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]); @@ -1239,32 +1242,33 @@ 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 args, QualType t, ExprValueKind VK, - SourceLocation rparenloc) - : CallExpr(C, SC, fn, ArrayRef(), args, t, VK, rparenloc) {} + SourceLocation rparenloc, unsigned MinNumArgs) + : CallExpr(C, SC, fn, ArrayRef(), args, t, VK, rparenloc, + MinNumArgs) {} CallExpr::CallExpr(const ASTContext &C, Expr *fn, ArrayRef args, - QualType t, ExprValueKind VK, SourceLocation rparenloc) - : CallExpr(C, CallExprClass, fn, ArrayRef(), 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(), 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; @@ -1308,35 +1312,6 @@ 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 { Index: cfe/trunk/lib/Sema/SemaExpr.cpp =================================================================== --- cfe/trunk/lib/Sema/SemaExpr.cpp +++ cfe/trunk/lib/Sema/SemaExpr.cpp @@ -4872,7 +4872,10 @@ 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 @@ -4913,7 +4916,7 @@ Diag(FDecl->getBeginLoc(), diag::note_callee_decl) << FDecl; // This deletes the extra arguments. - Call->setNumArgs(Context, NumParams); + Call->shrinkNumArgs(NumParams); return true; } } @@ -5580,16 +5583,50 @@ 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()) { + // C99 6.5.2.2p1 - "The expression that denotes the called function shall + // have type pointer to function". + FuncT = PT->getPointeeType()->getAs(); + if (!FuncT) + return ExprError(Diag(LParenLoc, diag::err_typecheck_call_not_function) + << Fn->getType() << Fn->getSourceRange()); + } else if (const BlockPointerType *BPT = + Fn->getType()->getAs()) { + FuncT = BPT->getPointeeType()->castAs(); + } 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(FuncT); + unsigned NumParams = Proto ? Proto->getNumParams() : 0; + CallExpr *TheCall; if (Config) - TheCall = - new (Context) CUDAKernelCallExpr(Context, Fn, cast(Config), - Args, ResultTy, VK_RValue, RParenLoc); + TheCall = new (Context) + CUDAKernelCallExpr(Context, Fn, cast(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 @@ -5600,39 +5637,16 @@ if (!Result.isUsable()) return ExprError(); TheCall = dyn_cast(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()) { - // C99 6.5.2.2p1 - "The expression that denotes the called function shall - // have type pointer to function". - FuncT = PT->getPointeeType()->getAs(); - if (!FuncT) - return ExprError(Diag(LParenLoc, diag::err_typecheck_call_not_function) - << Fn->getType() << Fn->getSourceRange()); - } else if (const BlockPointerType *BPT = - Fn->getType()->getAs()) { - FuncT = BPT->getPointeeType()->castAs(); - } 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 @@ -5661,7 +5675,6 @@ TheCall->setType(FuncT->getCallResultType(Context)); TheCall->setValueKind(Expr::getValueKindForType(FuncT->getReturnType())); - const FunctionProtoType *Proto = dyn_cast(FuncT); if (Proto) { if (ConvertArgumentsForCall(TheCall, Fn, FDecl, Proto, Args, RParenLoc, IsExecConfig)) Index: cfe/trunk/lib/Sema/SemaOverload.cpp =================================================================== --- cfe/trunk/lib/Sema/SemaOverload.cpp +++ cfe/trunk/lib/Sema/SemaOverload.cpp @@ -12836,7 +12836,8 @@ 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)) @@ -12986,9 +12987,11 @@ ResultType = ResultType.getNonLValueExprType(Context); assert(Method && "Member call to something that isn't a method?"); + const auto *Proto = Method->getType()->getAs(); 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(), @@ -13008,8 +13011,6 @@ } // Convert the rest of the arguments - const FunctionProtoType *Proto = - Method->getType()->getAs(); if (ConvertArgumentsForCall(TheCall, MemExpr, Method, Proto, Args, RParenLoc)) return ExprError(); Index: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp =================================================================== --- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp +++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp @@ -731,10 +731,11 @@ 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()); } @@ -2479,7 +2480,9 @@ 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: { @@ -3069,11 +3072,15 @@ } 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: @@ -3113,7 +3120,8 @@ 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: @@ -3283,7 +3291,8 @@ 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: