aaron.ballman updated this revision to Diff 421738.
aaron.ballman marked 2 inline comments as done.
aaron.ballman added a comment.

Updated based on review comments.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D123456/new/

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
+    // -Wdeprecated-non-prototype 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)
+          << (FDecl != nullptr) << 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

Reply via email to