Refactor collection of call arguments in common code.

Add support for variadic collection functions. More to do
here.

llvm-svn: 89781
This commit is contained in:
Fariborz Jahanian 2009-11-24 18:29:37 +00:00
parent 0b11a3ef71
commit 835026e9f1
4 changed files with 75 additions and 48 deletions

View File

@ -1514,6 +1514,14 @@ public:
Expr **Args, unsigned NumArgs, Expr **Args, unsigned NumArgs,
SourceLocation RParenLoc); SourceLocation RParenLoc);
bool GatherArgumentsForCall(SourceLocation CallLoc,
FunctionDecl *FDecl,
const FunctionProtoType *Proto,
unsigned FirstProtoArg,
Expr **Args, unsigned NumArgs,
llvm::SmallVector<Expr *, 8> &AllArgs,
Expr *Fn = 0);
void DeconstructCallFunction(Expr *FnExpr, void DeconstructCallFunction(Expr *FnExpr,
llvm::SmallVectorImpl<NamedDecl*>& Fns, llvm::SmallVectorImpl<NamedDecl*>& Fns,
DeclarationName &Name, DeclarationName &Name,

View File

@ -2520,17 +2520,14 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
// C99 6.5.2.2p7 - the arguments are implicitly converted, as if by // C99 6.5.2.2p7 - the arguments are implicitly converted, as if by
// assignment, to the types of the corresponding parameter, ... // assignment, to the types of the corresponding parameter, ...
unsigned NumArgsInProto = Proto->getNumArgs(); unsigned NumArgsInProto = Proto->getNumArgs();
unsigned NumArgsToCheck = NumArgs;
bool Invalid = false; bool Invalid = false;
// If too few arguments are available (and we don't have default // If too few arguments are available (and we don't have default
// arguments for the remaining parameters), don't make the call. // arguments for the remaining parameters), don't make the call.
if (NumArgs < NumArgsInProto) { if (NumArgs < NumArgsInProto) {
if (!FDecl || NumArgs < FDecl->getMinRequiredArguments()) if (!FDecl || NumArgs < FDecl->getMinRequiredArguments())
return Diag(RParenLoc, diag::err_typecheck_call_too_few_args) return Diag(RParenLoc, diag::err_typecheck_call_too_few_args)
<< Fn->getType()->isBlockPointerType() << Fn->getSourceRange(); << Fn->getType()->isBlockPointerType() << Fn->getSourceRange();
// Use default arguments for missing arguments
NumArgsToCheck = NumArgsInProto;
Call->setNumArgs(Context, NumArgsInProto); Call->setNumArgs(Context, NumArgsInProto);
} }
@ -2545,25 +2542,49 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
Args[NumArgs-1]->getLocEnd()); Args[NumArgs-1]->getLocEnd());
// This deletes the extra arguments. // This deletes the extra arguments.
Call->setNumArgs(Context, NumArgsInProto); Call->setNumArgs(Context, NumArgsInProto);
Invalid = true; return true;
} }
NumArgsToCheck = NumArgsInProto;
} }
llvm::SmallVector<Expr *, 8> 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<Expr *, 8> &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). // 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); QualType ProtoArgType = Proto->getArgType(i);
Expr *Arg; Expr *Arg;
if (i < NumArgs) { if (ArgIx < NumArgs) {
Arg = Args[i]; Arg = Args[ArgIx++];
if (RequireCompleteType(Arg->getSourceRange().getBegin(), if (RequireCompleteType(Arg->getSourceRange().getBegin(),
ProtoArgType, ProtoArgType,
PDiag(diag::err_call_incomplete_argument) PDiag(diag::err_call_incomplete_argument)
<< Arg->getSourceRange())) << Arg->getSourceRange()))
return true; return true;
// Pass the argument. // Pass the argument.
if (PerformCopyInitialization(Arg, ProtoArgType, "passing")) if (PerformCopyInitialization(Arg, ProtoArgType, "passing"))
return true; return true;
@ -2572,35 +2593,33 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
Arg = MaybeBindToTemporary(Arg).takeAs<Expr>(); Arg = MaybeBindToTemporary(Arg).takeAs<Expr>();
} else { } else {
ParmVarDecl *Param = FDecl->getParamDecl(i); ParmVarDecl *Param = FDecl->getParamDecl(i);
OwningExprResult ArgExpr = OwningExprResult ArgExpr =
BuildCXXDefaultArgExpr(Call->getSourceRange().getBegin(), BuildCXXDefaultArgExpr(CallLoc, FDecl, Param);
FDecl, Param);
if (ArgExpr.isInvalid()) if (ArgExpr.isInvalid())
return true; return true;
Arg = ArgExpr.takeAs<Expr>(); Arg = ArgExpr.takeAs<Expr>();
} }
AllArgs.push_back(Arg);
Call->setArg(i, Arg);
} }
// If this is a variadic call, handle args passed through "...". // If this is a variadic call, handle args passed through "...".
if (Proto->isVariadic()) { if (Proto->isVariadic()) {
VariadicCallType CallType = VariadicFunction; VariadicCallType CallType = VariadicFunction;
if (Fn->getType()->isBlockPointerType()) if (Fn) {
CallType = VariadicBlock; // Block if (Fn->getType()->isBlockPointerType())
else if (isa<MemberExpr>(Fn)) CallType = VariadicBlock; // Block
CallType = VariadicMethod; else if (isa<MemberExpr>(Fn))
CallType = VariadicMethod;
}
// Promote the arguments (C99 6.5.2.2p7). // 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]; Expr *Arg = Args[i];
Invalid |= DefaultVariadicArgumentPromotion(Arg, CallType); Invalid |= DefaultVariadicArgumentPromotion(Arg, CallType);
Call->setArg(i, Arg); AllArgs.push_back(Arg);
} }
} }
return Invalid; return Invalid;
} }

View File

@ -402,30 +402,17 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
UseGlobal, AllocType, ArraySize, PlaceArgs, UseGlobal, AllocType, ArraySize, PlaceArgs,
NumPlaceArgs, OperatorNew, OperatorDelete)) NumPlaceArgs, OperatorNew, OperatorDelete))
return ExprError(); return ExprError();
llvm::SmallVector<Expr *, 4> AllPlaceArgs; llvm::SmallVector<Expr *, 8> AllPlaceArgs;
if (OperatorNew) { if (OperatorNew) {
// Add default arguments, if any. // Add default arguments, if any.
const FunctionProtoType *Proto = const FunctionProtoType *Proto =
OperatorNew->getType()->getAs<FunctionProtoType>(); OperatorNew->getType()->getAs<FunctionProtoType>();
unsigned NumArgsInProto = Proto->getNumArgs(); bool Invalid = GatherArgumentsForCall(PlacementLParen, OperatorNew,
for (unsigned i = 1; i != NumArgsInProto; i++) { Proto, 1, PlaceArgs, NumPlaceArgs,
QualType ProtoArgType = Proto->getArgType(i); 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<Expr>();
AllPlaceArgs.push_back(Arg);
}
NumPlaceArgs = AllPlaceArgs.size(); NumPlaceArgs = AllPlaceArgs.size();
if (NumPlaceArgs > 0) if (NumPlaceArgs > 0)
PlaceArgs = &AllPlaceArgs[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, // 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 // too. This is checked on declaration and can be assumed. (It can't be
// asserted on, though, since invalid decls are left in there.) // 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. // FIXME: Passing word to diagnostic.
if (PerformCopyInitialization(Args[i], if (PerformCopyInitialization(Args[i],
FnDecl->getParamDecl(i)->getType(), FnDecl->getParamDecl(i)->getType(),

View File

@ -79,3 +79,14 @@ void t9() {
new bool(true); new bool(true);
new (&b) 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;
}