While this syntax is not standard, there's a certain degree of consensus
within the C Committee that, if this was ever standardized, there's a
preference to have a single list of forward declarations of parameters.
This would allow eventually adding another semicolon in function
prototypes to separate a different feature.

So, make multiple lists of forward declarations of parameters
obsolescent, and produce a new diagnostic,
-Wmultiple-parameter-fwd-decl-lists, which diagnoses uses of this
obsolescent syntax.

Forward declarations of parameters are a rarely used feature, AFAIK, so
this shouldn't be problematic in -Wextra.  Eventually, we may want to
move this into a default diagnostic, and later an error.

Cc: Christopher Bazley <[email protected]>
Cc: Martin Uecker <[email protected]>
Signed-off-by: Alejandro Colomar <[email protected]>
---

Hi!

I've implemented this diagnostic to try to unify code using forward
declarations of parameters into a single syntax, where there's a single
list of forward declarations of parameters.

I have tested this by compiling the compiler and then compiling the
following test case:

        alx@debian:~/tmp$ cat fwd.c | nl
             1  //void f(int n, int n; int n);  // error
             2  void g(int n; int n; int n);
             3  void h(int n, int m; int n, int m);
             4  void i(int n; int n; int n; int n, int m);
        alx@debian:~/tmp$ /opt/local/gnu/gcc/fwd/bin/gcc -S 
-Wmultiple-parameter-fwd-decl-lists fwd.c 
        fwd.c:2:1: warning: More than one list of forward declarations of 
parameters are an obsolescent feature [-Wmultiple-parameter-fwd-decl-lists]
            2 | void g(int n; int n; int n);
              | ^~~~
        fwd.c:4:1: warning: More than one list of forward declarations of 
parameters are an obsolescent feature [-Wmultiple-parameter-fwd-decl-lists]
            4 | void i(int n; int n; int n; int n, int m);
              | ^~~~
        fwd.c:4:1: warning: More than one list of forward declarations of 
parameters are an obsolescent feature [-Wmultiple-parameter-fwd-decl-lists]

I haven't yet run regression tests, which is why this is still an RFC,
and not a PATCH.  I'll do that when I stay in a place for an entire day.

Also, I'll write changelogs once I've tested it and we agree this is
something we want.

WDYT?


Have a lovely day!
Alex


 gcc/c-family/c.opt                                |  4 ++++
 gcc/c/c-decl.cc                                   | 11 ++++++++---
 gcc/doc/extend.texi                               |  2 +-
 gcc/doc/invoke.texi                               | 13 ++++++++++++-
 gcc/testsuite/gcc.dg/Wold-style-fwd-declaration.c |  6 ++++++
 5 files changed, 31 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/Wold-style-fwd-declaration.c

diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 3f5e2f0874d..4fd8770b65c 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 77006cacdb7..69ded166f87 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -507,7 +507,7 @@ struct GTY((chain_next ("%h.outer"))) c_scope {
   /* 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;
+  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
@@ -6261,12 +6261,17 @@ mark_forward_parm_decls (void)
 {
   struct c_binding *b;
 
-  if (pedantic && !current_scope->warned_forward_parm_decls)
+  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 are 
an obsolescent feature");
+    }
+  if (pedantic && !current_scope->had_forward_parm_decls)
     {
       pedwarn (input_location, OPT_Wpedantic,
               "ISO C forbids forward parameter declarations");
-      current_scope->warned_forward_parm_decls = true;
     }
+  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 cc9005439a4..2cfc0542b89 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -675,7 +675,7 @@ 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
+parameter list.  They can be separated by commas, and 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
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 4bec80ac205..a5187e01d34 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -539,7 +539,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}
 
@@ -6664,6 +6666,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)}
@@ -10517,6 +10520,14 @@ 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,
+which is an obsolescent feature.
+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/Wold-style-fwd-declaration.c 
b/gcc/testsuite/gcc.dg/Wold-style-fwd-declaration.c
new file mode 100644
index 00000000000..756b612e597
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wold-style-fwd-declaration.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" } */

Range-diff against v0:
-:  ----------- > 1:  fd77f2ea556 c: Deprecate more than one list of forward 
declarations of parameters
-- 
2.50.1

Reply via email to