From 4654241866c91fa312d7b26d5eb4afd070b5c602 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Mon, 25 Oct 2010 20:39:23 +0000 Subject: [PATCH] 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@117305 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaExpr.cpp | 47 +++++++++++++++++++++++++++++++--------- test/Sema/knr-def-call.c | 13 ++++++++++- 2 files changed, 49 insertions(+), 11 deletions(-) diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index ced383310f..793dc42759 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -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(); - if (!Proto || !(Proto->isVariadic() && NumArgs >= Def->param_size())) { + const FunctionProtoType *Proto + = Def->getType()->getAs(); + 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(); } // 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(); + + } else { + DefaultArgumentPromotion(Arg); + + if (RequireCompleteType(Arg->getSourceRange().getBegin(), + Arg->getType(), + PDiag(diag::err_call_incomplete_argument) + << Arg->getSourceRange())) + return ExprError(); + } + TheCall->setArg(i, Arg); } } diff --git a/test/Sema/knr-def-call.c b/test/Sema/knr-def-call.c index fd06cbf645..fc6cfbbd56 100644 --- a/test/Sema/knr-def-call.c +++ b/test/Sema/knr-def-call.c @@ -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'}} +} -- 2.40.0