aaron.ballman created this revision. aaron.ballman added reviewers: jyknight, hubert.reinterpretcast, delcypher, erichkeane, clang-language-wg. Herald added a project: All. aaron.ballman requested review of this revision. Herald added a project: clang.
This catches places where a function without a prototype is accidentally used, potentially passing an incorrect number of arguments, and is a follow-up to the work done in https://reviews.llvm.org/D122895 and described in the RFC (https://discourse.llvm.org/t/rfc-enabling-wstrict-prototypes-by-default-in-c). The diagnostic is grouped under the new `-Wdeprecated-non-prototypes` warning group and is enabled by default. The diagnostic is disabled if the function being called was implicitly declared (the user already gets an on-by-default warning about the creation of the implicit function declaration, so no need to warn them twice on the same line). Additionally, the diagnostic is disabled if the declaration of the function without a prototype was in a location where the user explicitly disabled deprecation warnings for functions without prototypes (this allows the provider of the API a way to disable the diagnostic at call sites because the lack of prototype is intentional). Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D123456 Files: clang/docs/ReleaseNotes.rst clang/include/clang/Basic/DiagnosticSemaKinds.td clang/lib/Sema/SemaExpr.cpp clang/test/Analysis/nullability.c clang/test/Analysis/svalbuilder-float-cast.c clang/test/Sema/warn-deprecated-non-prototype.c
Index: clang/test/Sema/warn-deprecated-non-prototype.c =================================================================== --- clang/test/Sema/warn-deprecated-non-prototype.c +++ clang/test/Sema/warn-deprecated-non-prototype.c @@ -36,7 +36,7 @@ void another(); // strict-warning {{a function declaration without a prototype is deprecated in all versions of C}} int main(void) { - another(1, 2); // OK for now + another(1, 2); // both-warning {{calling 'another' with arguments when the function has no prototype}} } void order1(); // expected-warning {{a function declaration without a prototype is deprecated in all versions of C and is not supported in C2x}} \ @@ -71,3 +71,47 @@ void blapp(int); void blapp() { } // both-warning {{a function declaration without a prototype is deprecated in all versions of C and is not supported in C2x}} \ // strict-warning {{a function declaration without a prototype is deprecated in all versions of C}} + +// Disable -Wdeprecated-non-prototype +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-non-prototype" +void depr_non_prot(); // strict-warning {{a function declaration without a prototype is deprecated in all versions of C}} +#pragma GCC diagnostic pop +// Reenable it. + +// Disable -Wstrict-prototypes +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-prototypes" +void strict_prot(); // OK +#pragma GCC diagnostic pop +// Reenable it. + +void calls(void) { + // Ensure that we diagnose calls to functions without a prototype, but only + // if they pass arguments. + never_defined(); // OK + never_defined(1); // both-warning {{calling 'never_defined' with arguments when the function has no prototype}} + + // Ensure that calls to builtins without a traditional prototype are not + // diagnosed. + (void)__builtin_isless(1.0, 1.0); // OK + + // Calling a function whose prototype was provided by a function with an + // identifier list is still fine. + func(1, 2); // OK + + // Ensure that a call through a function pointer is still diagnosed properly. + fp f; + f(); // OK + f(1, 2); // both-warning {{calling a function with arguments when the function has no prototype}} + + // Ensure that we don't diagnose when the diagnostic group is disabled. + depr_non_prot(1); // OK + strict_prot(1); // OK + + // Ensure we don't issue diagnostics if the function without a prototype was + // later given a prototype by a definintion. Also ensure we don't duplicate + // diagnostics if such a call is incorrect. + func(1, 2); // OK + func(1, 2, 3); // both-warning {{too many arguments in call to 'func'}} +} Index: clang/test/Analysis/svalbuilder-float-cast.c =================================================================== --- clang/test/Analysis/svalbuilder-float-cast.c +++ clang/test/Analysis/svalbuilder-float-cast.c @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker debug.ExprInspection -verify %s +// RUN: %clang_analyze_cc1 -analyzer-checker debug.ExprInspection -Wno-deprecated-non-prototype -verify %s void clang_analyzer_denote(int, const char *); void clang_analyzer_express(int); Index: clang/test/Analysis/nullability.c =================================================================== --- clang/test/Analysis/nullability.c +++ clang/test/Analysis/nullability.c @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -fblocks -analyzer-checker=core,nullability -verify %s +// RUN: %clang_analyze_cc1 -fblocks -analyzer-checker=core,nullability -Wno-deprecated-non-prototype -verify %s void it_takes_two(int a, int b); void function_pointer_arity_mismatch() { Index: clang/lib/Sema/SemaExpr.cpp =================================================================== --- clang/lib/Sema/SemaExpr.cpp +++ clang/lib/Sema/SemaExpr.cpp @@ -7047,6 +7047,23 @@ Proto = FDecl->getType()->getAs<FunctionProtoType>(); } + // If we still haven't found a prototype to use but there are arguments to + // the call, diagnose this as calling a function without a prototype. + // However, if we found a function declaration, check to see if the strict + // uses without a prototype warning was disabled where the function was + // declared. If so, we will silence the diagnostic here on the assumption + // that this interface is intentional and the user knows what they're doing. + // We will also silence the diagnostic if there is a function declaration + // but it was implicitly defined (the user already gets diagnostics about + // the creation of the implicit function declaration, so the additional + // warning is not helpful). + if (!Proto && !Args.empty() && + (!FDecl || (!FDecl->isImplicit() && + !Diags.isIgnored(diag::warn_strict_uses_without_prototype, + FDecl->getLocation())))) + Diag(LParenLoc, diag::warn_strict_uses_without_prototype) + << (bool)FDecl << FDecl; + // Promote the arguments (C99 6.5.2.2p6). for (unsigned i = 0, e = Args.size(); i != e; i++) { Expr *Arg = Args[i]; Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -5554,6 +5554,9 @@ InGroup<Sentinel>; def note_sentinel_here : Note< "%select{function|method|block}0 has been explicitly marked sentinel here">; +def warn_strict_uses_without_prototype : Warning< + "calling %select{a function|%1}0 with arguments when the function has no " + "prototype">, InGroup<DeprecatedNonPrototype>; def warn_missing_prototype : Warning< "no previous prototype for function %0">, InGroup<DiagGroup<"missing-prototypes">>, DefaultIgnore; Index: clang/docs/ReleaseNotes.rst =================================================================== --- clang/docs/ReleaseNotes.rst +++ clang/docs/ReleaseNotes.rst @@ -122,8 +122,13 @@ diagnostic remains off by default but is now enabled via ``-pedantic`` due to it being a deprecation warning. ``-Wdeprecated-non-prototype`` will diagnose cases where the deprecated declarations or definitions of a function without - a prototype will change behavior in C2x. This diagnostic is grouped under the - ``-Wstrict-prototypes`` warning group, but is enabled by default. + a prototype will change behavior in C2x. Additionally, it will diagnose calls + to a function without a prototype but arguments are provided, only so long as + the ``-Wdeprecated-non-prototype`` option is enabled at the function + declaration. (This allows a developer to locally disable the diagnostic for a + declaration without a prototype to silence the call-site diagnostics as + well.) This diagnostic is grouped under the ``-Wstrict-prototypes`` warning + group, but is enabled by default. Non-comprehensive list of changes in this release -------------------------------------------------
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits