When we're calling a function that we know based on its K&R-style

function definition, we should still use a prototype to type-check and
convert the function arguments, if such a prototype exists. Fixes
PR8314.

llvm-svn: 117305
This commit is contained in:
Douglas Gregor 2010-10-25 20:39:23 +00:00
parent e137df2624
commit 8e09a72f13
2 changed files with 49 additions and 11 deletions

View File

@ -3836,24 +3836,51 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
// on our knowledge of the function definition.
const FunctionDecl *Def = 0;
if (FDecl->hasBody(Def) && NumArgs != Def->param_size()) {
const FunctionProtoType *Proto =
Def->getType()->getAs<FunctionProtoType>();
if (!Proto || !(Proto->isVariadic() && NumArgs >= Def->param_size())) {
const FunctionProtoType *Proto
= Def->getType()->getAs<FunctionProtoType>();
if (!Proto || !(Proto->isVariadic() && NumArgs >= Def->param_size()))
Diag(RParenLoc, diag::warn_call_wrong_number_of_arguments)
<< (NumArgs > Def->param_size()) << FDecl << Fn->getSourceRange();
}
}
// If the function we're calling isn't a function prototype, but we have
// a function prototype from a prior declaratiom, use that prototype.
if (!FDecl->hasPrototype())
Proto = FDecl->getType()->getAs<FunctionProtoType>();
}
// Promote the arguments (C99 6.5.2.2p6).
for (unsigned i = 0; i != NumArgs; i++) {
Expr *Arg = Args[i];
DefaultArgumentPromotion(Arg);
if (RequireCompleteType(Arg->getSourceRange().getBegin(),
Arg->getType(),
PDiag(diag::err_call_incomplete_argument)
<< Arg->getSourceRange()))
return ExprError();
if (Proto && i < Proto->getNumArgs()) {
if (RequireCompleteType(Arg->getSourceRange().getBegin(),
Arg->getType(),
PDiag(diag::err_call_incomplete_argument)
<< Arg->getSourceRange()))
return ExprError();
InitializedEntity Entity
= InitializedEntity::InitializeParameter(Context,
Proto->getArgType(i));
ExprResult ArgE = PerformCopyInitialization(Entity,
SourceLocation(),
Owned(Arg));
if (ArgE.isInvalid())
return true;
Arg = ArgE.takeAs<Expr>();
} else {
DefaultArgumentPromotion(Arg);
if (RequireCompleteType(Arg->getSourceRange().getBegin(),
Arg->getType(),
PDiag(diag::err_call_incomplete_argument)
<< Arg->getSourceRange()))
return ExprError();
}
TheCall->setArg(i, Arg);
}
}

View File

@ -1,4 +1,4 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
// RUN: %clang_cc1 -Wconversion -fsyntax-only -verify %s
// C DR #316, PR 3626.
void f0(a, b, c, d) int a,b,c,d; {}
@ -27,3 +27,14 @@ char *rindex(s, c)
{
return 0;
}
// PR8314
void proto(int);
void proto(x)
int x;
{
}
void use_proto() {
proto(42.0); // expected-warning{{implicit conversion turns floating-point number into integer: 'double' to 'int'}}
}