diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 28a941765931..0a53a65e138f 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1177,6 +1177,8 @@ def err_typecheck_call_too_few_args : Error< "too few arguments to %select{function|block|method}0 call">; def err_typecheck_call_too_many_args : Error< "too many arguments to %select{function|block|method}0 call">; +def warn_call_wrong_number_of_arguments : Warning< + "too %select{few|many}0 arguments in call to %1">; def err_deleted_function_use : Error<"attempt to use a deleted function">; def warn_cannot_pass_non_pod_arg_to_vararg : Warning< "cannot pass object of non-POD type %0 through variadic " diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 1540f0a00922..b3c8be49c981 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2368,6 +2368,15 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc, } else { assert(isa(FuncT) && "Unknown FunctionType!"); + if (FDecl) { + // Check if we have too few/too many template arguments, based + // on our knowledge of the function definition. + const FunctionDecl *Def = 0; + if (FDecl->getBody(Def) && NumArgs != Def->param_size()) + Diag(RParenLoc, diag::warn_call_wrong_number_of_arguments) + << (NumArgs > Def->param_size()) << FDecl << Fn->getSourceRange(); + } + // Promote the arguments (C99 6.5.2.2p6). for (unsigned i = 0; i != NumArgs; i++) { Expr *Arg = Args[i]; diff --git a/clang/test/Sema/arg-duplicate.c b/clang/test/Sema/arg-duplicate.c index 82b2992af342..e40a964234d9 100644 --- a/clang/test/Sema/arg-duplicate.c +++ b/clang/test/Sema/arg-duplicate.c @@ -9,6 +9,6 @@ int f3(y, x, } void f4(void) { - f3 (1, 1, 2, 3, 4); + f3 (1, 1, 2, 3, 4); // expected-warning{{too many arguments}} } diff --git a/clang/test/Sema/function.c b/clang/test/Sema/function.c index aec76a26ebd9..e604d0e1ea14 100644 --- a/clang/test/Sema/function.c +++ b/clang/test/Sema/function.c @@ -27,7 +27,7 @@ int t9(int a, ); // expected-error {{expected parameter declarator}} // PR2042 void t10(){} -void t11(){t10(1);} +void t11(){t10(1);} // expected-warning{{too many arguments}} // PR3208 void t12(int) {} // expected-error{{parameter name omitted}} diff --git a/clang/test/Sema/knr-def-call.c b/clang/test/Sema/knr-def-call.c index 0e562d7c7e7b..6b033fc3a21f 100644 --- a/clang/test/Sema/knr-def-call.c +++ b/clang/test/Sema/knr-def-call.c @@ -2,10 +2,14 @@ // C DR #316, PR 3626. void f0(a, b, c, d) int a,b,c,d; {} -void t0(void) { f0(1); } +void t0(void) { + f0(1); // expected-warning{{too few arguments}} +} void f1(a, b) int a, b; {} -void t1(void) { f1(1, 2, 3); } +void t1(void) { + f1(1, 2, 3); // expected-warning{{too many arguments}} +} void f2(float); // expected-note{{previous declaration is here}} void f2(x) float x; { } // expected-warning{{promoted type 'double' of K&R function parameter is not compatible with the parameter type 'float' declared in a previous prototype}}