diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 1df1ec681e06..3b3b41ba217c 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -1514,6 +1514,14 @@ public: Expr **Args, unsigned NumArgs, SourceLocation RParenLoc); + bool GatherArgumentsForCall(SourceLocation CallLoc, + FunctionDecl *FDecl, + const FunctionProtoType *Proto, + unsigned FirstProtoArg, + Expr **Args, unsigned NumArgs, + llvm::SmallVector &AllArgs, + Expr *Fn = 0); + void DeconstructCallFunction(Expr *FnExpr, llvm::SmallVectorImpl& Fns, DeclarationName &Name, diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index b5dffdced6d2..9d7a42172c41 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2520,17 +2520,14 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, // C99 6.5.2.2p7 - the arguments are implicitly converted, as if by // assignment, to the types of the corresponding parameter, ... unsigned NumArgsInProto = Proto->getNumArgs(); - unsigned NumArgsToCheck = NumArgs; bool Invalid = false; - + // If too few arguments are available (and we don't have default // arguments for the remaining parameters), don't make the call. if (NumArgs < NumArgsInProto) { if (!FDecl || NumArgs < FDecl->getMinRequiredArguments()) return Diag(RParenLoc, diag::err_typecheck_call_too_few_args) << Fn->getType()->isBlockPointerType() << Fn->getSourceRange(); - // Use default arguments for missing arguments - NumArgsToCheck = NumArgsInProto; Call->setNumArgs(Context, NumArgsInProto); } @@ -2545,25 +2542,49 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, Args[NumArgs-1]->getLocEnd()); // This deletes the extra arguments. Call->setNumArgs(Context, NumArgsInProto); - Invalid = true; + return true; } - NumArgsToCheck = NumArgsInProto; } + llvm::SmallVector AllArgs; + Invalid = GatherArgumentsForCall(Call->getSourceRange().getBegin(), FDecl, + Proto, 0, Args, NumArgs, AllArgs, Fn); + if (Invalid) + return true; + unsigned TotalNumArgs = AllArgs.size(); + for (unsigned i = 0; i < TotalNumArgs; ++i) + Call->setArg(i, AllArgs[i]); + + return false; +} +bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, + FunctionDecl *FDecl, + const FunctionProtoType *Proto, + unsigned FirstProtoArg, + Expr **Args, unsigned NumArgs, + llvm::SmallVector &AllArgs, + Expr *Fn) { + unsigned NumArgsInProto = Proto->getNumArgs(); + unsigned NumArgsToCheck = NumArgs; + bool Invalid = false; + if (NumArgs != NumArgsInProto) + // Use default arguments for missing arguments + NumArgsToCheck = NumArgsInProto; + unsigned ArgIx = 0; // Continue to check argument types (even if we have too few/many args). - for (unsigned i = 0; i != NumArgsToCheck; i++) { + for (unsigned i = FirstProtoArg; i != NumArgsToCheck; i++) { QualType ProtoArgType = Proto->getArgType(i); - + Expr *Arg; - if (i < NumArgs) { - Arg = Args[i]; - + if (ArgIx < NumArgs) { + Arg = Args[ArgIx++]; + if (RequireCompleteType(Arg->getSourceRange().getBegin(), ProtoArgType, PDiag(diag::err_call_incomplete_argument) - << Arg->getSourceRange())) + << Arg->getSourceRange())) return true; - + // Pass the argument. if (PerformCopyInitialization(Arg, ProtoArgType, "passing")) return true; @@ -2572,35 +2593,33 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, Arg = MaybeBindToTemporary(Arg).takeAs(); } else { ParmVarDecl *Param = FDecl->getParamDecl(i); - + OwningExprResult ArgExpr = - BuildCXXDefaultArgExpr(Call->getSourceRange().getBegin(), - FDecl, Param); + BuildCXXDefaultArgExpr(CallLoc, FDecl, Param); if (ArgExpr.isInvalid()) return true; - + Arg = ArgExpr.takeAs(); } - - Call->setArg(i, Arg); + AllArgs.push_back(Arg); } - + // If this is a variadic call, handle args passed through "...". if (Proto->isVariadic()) { VariadicCallType CallType = VariadicFunction; - if (Fn->getType()->isBlockPointerType()) - CallType = VariadicBlock; // Block - else if (isa(Fn)) - CallType = VariadicMethod; - + if (Fn) { + if (Fn->getType()->isBlockPointerType()) + CallType = VariadicBlock; // Block + else if (isa(Fn)) + CallType = VariadicMethod; + } // Promote the arguments (C99 6.5.2.2p7). - for (unsigned i = NumArgsInProto; i < NumArgs; i++) { + for (unsigned i = ArgIx; i < NumArgs; i++) { Expr *Arg = Args[i]; Invalid |= DefaultVariadicArgumentPromotion(Arg, CallType); - Call->setArg(i, Arg); + AllArgs.push_back(Arg); } } - return Invalid; } diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 6cf2cc6ef987..4aa928a43696 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -402,30 +402,17 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, UseGlobal, AllocType, ArraySize, PlaceArgs, NumPlaceArgs, OperatorNew, OperatorDelete)) return ExprError(); - llvm::SmallVector AllPlaceArgs; + llvm::SmallVector AllPlaceArgs; if (OperatorNew) { // Add default arguments, if any. const FunctionProtoType *Proto = OperatorNew->getType()->getAs(); - unsigned NumArgsInProto = Proto->getNumArgs(); - for (unsigned i = 1; i != NumArgsInProto; i++) { - QualType ProtoArgType = Proto->getArgType(i); + bool Invalid = GatherArgumentsForCall(PlacementLParen, OperatorNew, + Proto, 1, PlaceArgs, NumPlaceArgs, + AllPlaceArgs); + if (Invalid) + return ExprError(); - Expr *Arg; - if (i <= NumPlaceArgs) { - AllPlaceArgs.push_back(PlaceArgs[i-1]); - continue; - } - ParmVarDecl *Param = OperatorNew->getParamDecl(i); - - OwningExprResult ArgExpr = - BuildCXXDefaultArgExpr(StartLoc, OperatorNew, Param); - if (ArgExpr.isInvalid()) - return ExprError(); - - Arg = ArgExpr.takeAs(); - AllPlaceArgs.push_back(Arg); - } NumPlaceArgs = AllPlaceArgs.size(); if (NumPlaceArgs > 0) PlaceArgs = &AllPlaceArgs[0]; @@ -630,7 +617,9 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range, // The first argument is size_t, and the first parameter must be size_t, // too. This is checked on declaration and can be assumed. (It can't be // asserted on, though, since invalid decls are left in there.) - for (unsigned i = 0; i < NumArgs; ++i) { + // Whatch out for variadic allocator function. + unsigned NumArgsInFnDecl = FnDecl->getNumParams(); + for (unsigned i = 0; (i < NumArgs && i < NumArgsInFnDecl); ++i) { // FIXME: Passing word to diagnostic. if (PerformCopyInitialization(Args[i], FnDecl->getParamDecl(i)->getType(), diff --git a/clang/test/CodeGenCXX/new.cpp b/clang/test/CodeGenCXX/new.cpp index ddf1f9b3c904..f2121a6079b8 100644 --- a/clang/test/CodeGenCXX/new.cpp +++ b/clang/test/CodeGenCXX/new.cpp @@ -79,3 +79,14 @@ void t9() { new bool(true); new (&b) bool(true); } + +struct A { + void* operator new(__typeof(sizeof(int)), int, float, ...); + A(); +}; + +A* t10() { + // CHECK: @_ZN1AnwEmifz + return new(1, 2, 3.45, 100) A; +} +