https://gcc.gnu.org/g:33c35b7f4c1894cb197903310b7b7bff19205f35

commit r16-4108-g33c35b7f4c1894cb197903310b7b7bff19205f35
Author: Alejandro Colomar <[email protected]>
Date:   Fri Sep 26 19:27:28 2025 +0000

    c, objc: Add -Wmultiple-parameter-fwd-decl-lists
    
    Warn about this:
    
            void f(int x; int x; int x);
    
    Add a new diagnostic, -Wmultiple-parameter-fwd-decl-lists, which
    diagnoses uses of this obsolescent syntax.
    
    Add this diagnostic in -Wextra.
    
    Forward declarations of parameters are very rarely used.  And functions
    that need two forward declaractions of parameters are also quite rare.
    This combination results in this code almost not existing in any code
    base, which makes adding this to -Wextra okay.  FWIW, I've tried finding
    such code using a code search engine, and didn't find any cases (but the
    regex for that isn't easy to writei, so I wouldn't trust it).
    
    gcc/c-family/ChangeLog:
    
            * c.opt: Add -Wmultiple-parameter-fwd-decl-lists
    
    gcc/c/ChangeLog:
    
            * c-decl.cc (c_scope): Rename {warned > had}_forward_parm_decls.
            (mark_forward_parm_decls): Add
            -Wmultiple-parameter-fwd-decl-lists.
    
    gcc/ChangeLog:
    
            * doc/extend.texi: Clarify documentation about lists of
            parameter forward declarations, and mention that more than one
            of them are unnecessary.
            * doc/invoke.texi: Document the new
            -Wmultiple-parameter-fwd-decl-lists.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.dg/Wmultiple-parameter-fwd-decl-lists.c: New test.
    
    Signed-off-by: Alejandro Colomar <[email protected]>

Diff:
---
 gcc/c-family/c.opt                                 |  4 ++++
 gcc/c/c-decl.cc                                    | 20 ++++++++---------
 gcc/doc/extend.texi                                | 25 +++++++++++++---------
 gcc/doc/invoke.texi                                | 12 ++++++++++-
 .../gcc.dg/Wmultiple-parameter-fwd-decl-lists.c    |  6 ++++++
 5 files changed, 46 insertions(+), 21 deletions(-)

diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 3f5e2f0874d9..4fd8770b65c3 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -1086,6 +1086,10 @@ Wmultiple-inheritance
 C++ ObjC++ Var(warn_multiple_inheritance) Warning
 Warn on direct multiple inheritance.
 
+Wmultiple-parameter-fwd-decl-lists
+C ObjC Var(warn_multiple_parameter_fwd_decl_lists) Warning EnabledBy(Wextra)
+Warn for multiple lists of forward declarations of function parameters.
+
 Wmultistatement-macros
 C ObjC C++ ObjC++ Var(warn_multistatement_macros) Warning LangEnabledBy(C ObjC 
C++ ObjC++,Wall)
 Warn about unsafe macros expanding to multiple statements used as a body of a 
clause such as if, else, while, switch, or for.
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index b122e82bfc47..7e4c7c2ac3f6 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -504,10 +504,8 @@ struct GTY((chain_next ("%h.outer"))) c_scope {
      if these appears in a function definition.  */
   BOOL_BITFIELD had_vla_unspec : 1;
 
-  /* True if we already complained about forward parameter decls
-     in this scope.  This prevents double warnings on
-     foo (int a; int b; ...)  */
-  BOOL_BITFIELD warned_forward_parm_decls : 1;
+  /* True if we parsed a list of forward parameter decls in this scope.  */
+  BOOL_BITFIELD had_forward_parm_decls : 1;
 
   /* True if this is the outermost block scope of a function body.
      This scope contains the parameters, the local variables declared
@@ -6269,12 +6267,14 @@ mark_forward_parm_decls (void)
 {
   struct c_binding *b;
 
-  if (pedantic && !current_scope->warned_forward_parm_decls)
-    {
-      pedwarn (input_location, OPT_Wpedantic,
-              "ISO C forbids forward parameter declarations");
-      current_scope->warned_forward_parm_decls = true;
-    }
+  if (current_scope->had_forward_parm_decls)
+    warning_at (input_location, OPT_Wmultiple_parameter_fwd_decl_lists,
+               "more than one list of forward declarations of parameters");
+  if (pedantic && !current_scope->had_forward_parm_decls)
+    pedwarn (input_location, OPT_Wpedantic,
+            "ISO C forbids forward parameter declarations");
+
+  current_scope->had_forward_parm_decls = true;
 
   for (b = current_scope->bindings; b; b = b->prev)
     if (TREE_CODE (b->decl) == PARM_DECL)
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 7f01f2cb7b88..384211f8b6dc 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -670,16 +670,21 @@ tester (int len; char data[len][len], int len)
 @end smallexample
 
 @cindex parameter forward declaration
-The @samp{int len} before the semicolon is a @dfn{parameter forward
-declaration}, and it serves the purpose of making the name @code{len}
-known when the declaration of @code{data} is parsed.
-
-You can write any number of such parameter forward declarations in the
-parameter list.  They can be separated by commas or semicolons, but the
-last one must end with a semicolon, which is followed by the ``real''
-parameter declarations.  Each forward declaration must match a ``real''
-declaration in parameter name and data type.  ISO C99 does not support
-parameter forward declarations.
+The @samp{int len} before the semicolon
+is a @dfn{parameter forward declaration},
+and it serves the purpose of making the name @code{len} known
+when the declaration of @code{data} is parsed.
+
+Lists of parameter forward declarations are terminated by semicolons,
+and parameter forward declarations are separated within such lists by commas,
+just like in the regular list of parameter declarations.
+
+You can write any number of lists of parameter forward declaration,
+but using more than one is unnecessary.
+The last semicolon is followed by the list of parameter declarations.
+Each parameter forward declaration must match
+a parameter declaration in parameter name and data type.
+ISO C99 does not support parameter forward declarations.
 
 @node Zero Length
 @subsection Arrays of Length Zero
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index cea83f62c5f0..99607a09b89c 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -540,7 +540,9 @@ Objective-C and Objective-C++ Dialects}.
 @gccoptlist{-Wbad-function-cast -Wdeprecated-non-prototype -Wfree-labels
 -Wmissing-declarations -Wmissing-parameter-name -Wmissing-parameter-type
 -Wdeclaration-missing-parameter-type -Wmissing-prototypes
--Wmissing-variable-declarations -Wnested-externs -Wold-style-declaration
+-Wmissing-variable-declarations
+-Wmultiple-parameter-fwd-decl-lists
+-Wnested-externs -Wold-style-declaration
 -Wold-style-definition -Wstrict-prototypes -Wtraditional
 -Wtraditional-conversion -Wdeclaration-after-statement -Wpointer-sign}
 
@@ -6683,6 +6685,7 @@ name is still supported, but the newer name is more 
descriptive.)
 -Wmissing-parameter-name @r{(C/ObjC only)}
 -Wmissing-parameter-type @r{(C/ObjC only)}
 -Wold-style-declaration @r{(C/ObjC only)}
+-Wmultiple-parameter-fwd-decl-lists @r{(C/ObjC only)}
 -Woverride-init @r{(C/ObjC only)}
 -Wredundant-move @r{(C++ and Objective-C++ only)}
 -Wshift-negative-value @r{(in C++11 to C++17 and in C99 and newer)}
@@ -10536,6 +10539,13 @@ is not considered an old-style definition in C23 mode, 
because it is
 equivalent to @samp{(void)} in that case, but is considered an
 old-style definition for older standards.
 
+@opindex Wmultiple-parameter-fwd-decl-lists
+@opindex Wno-multiple-parameter-fwd-decl-lists
+@item -Wmultiple-parameter-fwd-decl-lists @r{(C and Objective-C only)}
+Warn if more than one list of forward declarations of parameters
+appears in a function prototype.
+This warning is also enabled by @option{-Wextra}.
+
 @opindex Wdeprecated-non-prototype
 @opindex Wno-deprecated-non-prototype
 @item -Wdeprecated-non-prototype @r{(C and Objective-C only)}
diff --git a/gcc/testsuite/gcc.dg/Wmultiple-parameter-fwd-decl-lists.c 
b/gcc/testsuite/gcc.dg/Wmultiple-parameter-fwd-decl-lists.c
new file mode 100644
index 000000000000..c3edbf6a4940
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wmultiple-parameter-fwd-decl-lists.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-Wmultiple-parameter-fwd-decl-lists" } */
+
+void f(int n, int m; int n, int m);
+void g(int n; int m; int n, int m); /* { dg-warning "more than one list of 
forward declarations" } */
+void h(int n; int n; int n); /* { dg-warning "more than one list of forward 
declarations" } */

Reply via email to