[v3,1/1] c, objc: Deprecate more than one list of forward declarations of parameters
Commit Message
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
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.
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
@@ -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.
@@ -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)
@@ -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
@@ -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)}
new file mode 100644
@@ -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" } */