forked from OSchip/llvm-project
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:
parent
0b11a3ef71
commit
835026e9f1
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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(),
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue