Refactor collection of call arguments in common code.
Add support for variadic collection functions. More to do
here.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@89781 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index b5dffdc..9d7a421 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -2520,17 +2520,14 @@
// 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 @@
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 @@
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;
}