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,
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,
llvm::SmallVectorImpl<NamedDecl*>& Fns,
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
// 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<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).
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<Expr>();
} 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<Expr>();
}
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<MemberExpr>(Fn))
CallType = VariadicMethod;
if (Fn) {
if (Fn->getType()->isBlockPointerType())
CallType = VariadicBlock; // Block
else if (isa<MemberExpr>(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;
}

View File

@ -402,30 +402,17 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
UseGlobal, AllocType, ArraySize, PlaceArgs,
NumPlaceArgs, OperatorNew, OperatorDelete))
return ExprError();
llvm::SmallVector<Expr *, 4> AllPlaceArgs;
llvm::SmallVector<Expr *, 8> AllPlaceArgs;
if (OperatorNew) {
// Add default arguments, if any.
const FunctionProtoType *Proto =
OperatorNew->getType()->getAs<FunctionProtoType>();
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<Expr>();
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(),

View File

@ -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;
}