r288896 - Implement the -Wstrict-prototypes warning

Alex Lorenz via cfe-commits cfe-commits at lists.llvm.org
Wed Dec 7 02:52:18 PST 2016


Author: arphaman
Date: Wed Dec  7 04:52:18 2016
New Revision: 288896

URL: http://llvm.org/viewvc/llvm-project?rev=288896&view=rev
Log:
Implement the -Wstrict-prototypes warning

This commit fixes PR20796. It implements the C only -Wstrict-prototypes warning.
Clang now emits a warning for function declarations which have no parameters
specified and for K&R function definitions with more than 0 parameters that are
not preceded by a previous prototype declaration.

The patch was originally submitted by Paul Titei!

rdar://15060615

Differential Revision: https://reviews.llvm.org/D16533

Added:
    cfe/trunk/test/Sema/warn-strict-prototypes.c
    cfe/trunk/test/Sema/warn-strict-prototypes.m
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaType.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=288896&r1=288895&r2=288896&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Dec  7 04:52:18 2016
@@ -4411,6 +4411,10 @@ def warn_missing_prototype : Warning<
   InGroup<DiagGroup<"missing-prototypes">>, DefaultIgnore;
 def note_declaration_not_a_prototype : Note<
   "this declaration is not a prototype; add 'void' to make it a prototype for a zero-parameter function">; 
+def warn_strict_prototypes : Warning<
+  "this %select{function declaration is not|"
+  "old-style function definition is not preceded by}0 a prototype">,
+  InGroup<DiagGroup<"strict-prototypes">>, DefaultIgnore;
 def warn_missing_variable_declarations : Warning<
   "no previous extern declaration for non-static variable %0">,
   InGroup<DiagGroup<"missing-variable-declarations">>, DefaultIgnore;

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=288896&r1=288895&r2=288896&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Dec  7 04:52:18 2016
@@ -11878,6 +11878,21 @@ Decl *Sema::ActOnFinishFunctionBody(Decl
                 << FixItHint::CreateInsertion(FTL.getRParenLoc(), "void");
         }
       }
+
+      // GNU warning -Wstrict-prototypes
+      //   Warn if K&R function is defined without a previous declaration.
+      //   This warning is issued only if the definition itself does not provide
+      //   a prototype. Only K&R definitions do not provide a prototype.
+      //   An empty list in a function declarator that is part of a definition
+      //   of that function specifies that the function has no parameters
+      //   (C99 6.7.5.3p14)
+      if (!FD->hasWrittenPrototype() && FD->getNumParams() > 0 &&
+          !LangOpts.CPlusPlus) {
+        TypeSourceInfo *TI = FD->getTypeSourceInfo();
+        TypeLoc TL = TI->getTypeLoc();
+        FunctionTypeLoc FTL = TL.castAs<FunctionTypeLoc>();
+        Diag(FTL.getLParenLoc(), diag::warn_strict_prototypes) << 1;
+      }
     }
 
     if (auto *MD = dyn_cast<CXXMethodDecl>(FD)) {

Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=288896&r1=288895&r2=288896&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Wed Dec  7 04:52:18 2016
@@ -4320,6 +4320,19 @@ static TypeSourceInfo *GetFullTypeForDec
       if (FTI.isAmbiguous)
         warnAboutAmbiguousFunction(S, D, DeclType, T);
 
+      // GNU warning -Wstrict-prototypes
+      //   Warn if a function declaration is without a prototype.
+      //   This warning is issued for all kinds of unprototyped function
+      //   declarations (i.e. function type typedef, function pointer etc.)
+      //   C99 6.7.5.3p14:
+      //   The empty list in a function declarator that is not part of a
+      //   definition of that function specifies that no information
+      //   about the number or types of the parameters is supplied.
+      if (D.getFunctionDefinitionKind() == FDK_Declaration &&
+          FTI.NumParams == 0 && !LangOpts.CPlusPlus)
+        S.Diag(DeclType.Loc, diag::warn_strict_prototypes)
+            << 0 << FixItHint::CreateInsertion(FTI.getRParenLoc(), "void");
+
       FunctionType::ExtInfo EI(getCCForDeclaratorChunk(S, D, FTI, chunkIndex));
 
       if (!FTI.NumParams && !FTI.isVariadic && !LangOpts.CPlusPlus) {

Added: cfe/trunk/test/Sema/warn-strict-prototypes.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/warn-strict-prototypes.c?rev=288896&view=auto
==============================================================================
--- cfe/trunk/test/Sema/warn-strict-prototypes.c (added)
+++ cfe/trunk/test/Sema/warn-strict-prototypes.c Wed Dec  7 04:52:18 2016
@@ -0,0 +1,62 @@
+// RUN: %clang_cc1 -fsyntax-only -Wstrict-prototypes -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wstrict-prototypes -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
+
+// function declaration with unspecified params
+void foo1(); // expected-warning {{this function declaration is not a prototype}}
+             // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:11}:"void"
+// function declaration with 0 params
+void foo2(void);
+
+// function definition with 0 params(for both cases),
+// valid according to 6.7.5.3/14
+void foo1() {}
+void foo2(void) {}
+
+// function type typedef unspecified params
+typedef void foo3(); // expected-warning {{this function declaration is not a prototype}}
+                     // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:19-[[@LINE-1]]:19}:"void"
+
+// global fp unspecified params
+void (*foo4)(); // expected-warning {{this function declaration is not a prototype}}
+                // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:14-[[@LINE-1]]:14}:"void"
+
+// struct member fp unspecified params
+struct { void (*foo5)(); } s; // expected-warning {{this function declaration is not a prototype}}
+                              // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:23-[[@LINE-1]]:23}:"void"
+
+// param fp unspecified params
+void bar2(void (*foo6)()) { // expected-warning {{this function declaration is not a prototype}}
+                            // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:24-[[@LINE-1]]:24}:"void"
+  // local fp unspecified params
+  void (*foo7)() = 0; // expected-warning {{this function declaration is not a prototype}}
+                      // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:16-[[@LINE-1]]:16}:"void"
+  // array fp unspecified params
+  void (*foo8[2])() = {0}; // expected-warning {{this function declaration is not a prototype}}
+                           // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:19-[[@LINE-1]]:19}:"void"
+}
+
+// function type cast using using an anonymous function declaration
+void bar3(void) {
+  // casting function w/out prototype to unspecified params function type
+  (void)(void(*)()) foo1; // expected-warning {{this function declaration is not a prototype}}
+                          // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:18-[[@LINE-1]]:18}:"void"
+  // .. specified params
+  (void)(void(*)(void)) foo1;
+}
+
+// K&R function definition not preceded by full prototype
+int foo9(a, b) // expected-warning {{old-style function definition is not preceded by a prototype}}
+  int a, b;
+{
+  return a + b;
+}
+
+// Function declaration with no types
+void foo10(); // expected-warning {{this function declaration is not a prototype}}
+              // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:12-[[@LINE-1]]:12}:"void"
+// K&R function definition with incomplete param list declared
+void foo10(p, p2) void *p; {} // expected-warning {{old-style function definition is not preceded by a prototype}}
+
+// K&R function definition with previous prototype declared is not diagnosed.
+void foo11(int p, int p2);
+void foo11(p, p2) int p; int p2; {}

Added: cfe/trunk/test/Sema/warn-strict-prototypes.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/warn-strict-prototypes.m?rev=288896&view=auto
==============================================================================
--- cfe/trunk/test/Sema/warn-strict-prototypes.m (added)
+++ cfe/trunk/test/Sema/warn-strict-prototypes.m Wed Dec  7 04:52:18 2016
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -fsyntax-only -Wstrict-prototypes -verify -fblocks %s
+
+ at interface Foo
+
+ at property (nonatomic, copy) void (^noProtoBlock)(); // expected-warning {{this function declaration is not a prototype}}
+ at property (nonatomic, copy) void (^block)(void); // no warning
+
+- doStuff:(void (^)()) completionHandler; // expected-warning {{this function declaration is not a prototype}}
+- doOtherStuff:(void (^)(void)) completionHandler; // no warning
+
+ at end
+
+void foo() {
+  void (^block)() = // expected-warning {{this function declaration is not a prototype}}
+                    ^void(int arg) { // no warning
+  };
+  void (^block2)(void) = // no warning
+                         ^void() { // expected-warning {{this function declaration is not a prototype}}
+  };
+}




More information about the cfe-commits mailing list