[v3,1/1] c, objc: Deprecate more than one list of forward declarations of parameters

Message ID 83fbe0d41f3ac342f78537c8ceef6f512c387d88.1757582279.git.alx@kernel.org
State New
Headers
Series c, objc: Add -Wmultiple-parameter-fwd-decl-lists |

Commit Message

Alejandro Colomar Sept. 11, 2025, 9:20 a.m. UTC
  Warn about this:

	void f(int x; int x; int x);

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,
(and having more than one would be even rarer) so this shouldn't be
problematic in -Wextra.  Eventually, we may want to move this into
a default diagnostic, and later an error.

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/invoke.texi: Document the new
	-Wmultiple-parameter-fwd-decl-lists.

gcc/testsuite/ChangeLog:

	* gcc.gd/Wmultiple-parameter-fwd-decl-lists.c: New test.

Cc: Christopher Bazley <chris.bazley.wg14@gmail.com>
Cc: Martin Uecker <uecker@tugraz.at>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
---
 gcc/c-family/c.opt                               |  4 ++++
 gcc/c/c-decl.cc                                  | 16 +++++++++-------
 gcc/doc/extend.texi                              |  2 +-
 gcc/doc/invoke.texi                              | 13 ++++++++++++-
 .../gcc.dg/Wmultiple-parameter-fwd-decl-lists.c  |  6 ++++++
 5 files changed, 32 insertions(+), 9 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/Wmultiple-parameter-fwd-decl-lists.c
  

Comments

Joseph Myers Sept. 11, 2025, 3:42 p.m. UTC | #1
On Thu, 11 Sep 2025, Alejandro Colomar wrote:

> Warn about this:
> 
> 	void f(int x; int x; int x);
> 
> This would allow eventually adding another semicolon in function
> prototypes to separate a different feature.

I don't think that's a plausible future addition.  The small visual 
difference between comma and semicolon is one of the reasons people have 
given for objecting to this feature; adding extra features with multiple 
semicolons seems even more confusing, quite apart from being incompatible 
with the existing extension.

> 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.

I'm dubious of obsolescence here.  Restricting to a single forward 
declaration list is one of many possible design choices for a subset of 
the feature to consider for the standard; it's a reasonable subset choice, 
but hardly a unique one.  If the feature were accepted into C2y with that 
particular subset, my inclination would be that cases outside that subset 
(i.e. multiple forward declaration lists) would then (continue to) get a 
pedwarn-if-pedantic, rather than any stronger form of obsolescence such as 
warning with -Wextra.  Having an additional option for this particular 
case is reasonable enough; it's treating it as obsolesence or including it 
in -Wextra that seems questionable.
  
Alejandro Colomar Sept. 11, 2025, 9:08 p.m. UTC | #2
Hi Joseph,

On Thu, Sep 11, 2025 at 03:42:20PM +0000, Joseph Myers wrote:
> On Thu, 11 Sep 2025, Alejandro Colomar wrote:
> 
> > Warn about this:
> > 
> > 	void f(int x; int x; int x);
> > 
> > This would allow eventually adding another semicolon in function
> > prototypes to separate a different feature.
> 
> I don't think that's a plausible future addition.  The small visual 
> difference between comma and semicolon is one of the reasons people have 
> given for objecting to this feature; adding extra features with multiple 
> semicolons seems even more confusing, quite apart from being incompatible 
> with the existing extension.

Yeah, I also expect it to be unlikely for now.  I just wanted to leave
the door open, just in case we find it useful later.  To be clear,
I don't think it's useful in any way, though.

> > 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.
> 
> I'm dubious of obsolescence here.  Restricting to a single forward 
> declaration list is one of many possible design choices for a subset of 
> the feature to consider for the standard; it's a reasonable subset choice, 
> but hardly a unique one.  If the feature were accepted into C2y with that 
> particular subset, my inclination would be that cases outside that subset 
> (i.e. multiple forward declaration lists) would then (continue to) get a 
> pedwarn-if-pedantic, rather than any stronger form of obsolescence such as 
> warning with -Wextra.  Having an additional option for this particular 
> case is reasonable enough; it's treating it as obsolesence or including it 
> in -Wextra that seems questionable.

Okay, I can reword the commit message to remove any clues of
obsolescence.  We can consider obsolescence if/when we need to do it.

About -Wextra, I think it would be useful.  If people are going to start
using this slightly more often than until now (the Linux man-pages might
help with discovering this obscure feature, as it's now being used in
the SYNOPSIS section of some functions), then it would be useful for
them to remain on the preferred way to use this feature, and this
diagnostic would prevent any accidental use of semicolons to separate
forward declarations.

Anyway, I don't think we'll break much code in -Wextra (and to some
degree, -Wextra is already allowed to break a little bit).


Have a lovely night!
Alex
  

Patch

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 62a0545947e..12c7994c412 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
@@ -6269,12 +6269,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 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->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 2922d9e9839..2b92dee5cfd 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 d0c13d4a24e..b29d796d5e9 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}
 
@@ -6682,6 +6684,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)}
@@ -10535,6 +10538,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/Wmultiple-parameter-fwd-decl-lists.c b/gcc/testsuite/gcc.dg/Wmultiple-parameter-fwd-decl-lists.c
new file mode 100644
index 00000000000..c3edbf6a494
--- /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" } */