[v5,1/1] c, objc: Add -Wmultiple-parameter-fwd-decl-lists
Commit Message
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.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 | 23 +++++++++++--------
gcc/doc/invoke.texi | 12 +++++++++-
.../Wmultiple-parameter-fwd-decl-lists.c | 6 +++++
5 files changed, 44 insertions(+), 17 deletions(-)
create mode 100644 gcc/testsuite/gcc.dg/Wmultiple-parameter-fwd-decl-lists.c
Comments
On Tue, Sep 16, 2025 at 08:53:04AM +0200, Alejandro Colomar wrote:
> 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.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 | 23 +++++++++++--------
> gcc/doc/invoke.texi | 12 +++++++++-
> .../Wmultiple-parameter-fwd-decl-lists.c | 6 +++++
> 5 files changed, 44 insertions(+), 17 deletions(-)
> create mode 100644 gcc/testsuite/gcc.dg/Wmultiple-parameter-fwd-decl-lists.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 62a0545947e..763ee6ab7e1 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");
> + 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..77116169331 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.
> +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.
> +Lists of parameter forward declarations are terminated by semicolons,
> +and parameters are separated within such lists by commas,
Maybe here I should say 's/parameters/parameter forward declarations/'.
> +just like in the regular parameter declaration list.
> +
> +You can write any number of such parameter forward declaration lists,
> +but using more than one is unnecessary.
> +The last semicolon 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.
>
> @node Zero Length
> @subsection Arrays of Length Zero
> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> index d0c13d4a24e..25e64dc5024 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,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 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" } */
> --
> 2.50.1
>
Hi Joseph,
Would you mind having a look at this patch?
On Tue, Sep 16, 2025 at 08:56:49AM +0200, Alejandro Colomar wrote:
> > diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
> > index 2922d9e9839..77116169331 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.
> > +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.
> > +Lists of parameter forward declarations are terminated by semicolons,
> > +and parameters are separated within such lists by commas,
>
> Maybe here I should say 's/parameters/parameter forward declarations/'.
And would you mind amending this, if possible? Or do you prefer me to
send a patch with that changed?
Have a lovely day!
Alex
>
> > +just like in the regular parameter declaration list.
> > +
> > +You can write any number of such parameter forward declaration lists,
> > +but using more than one is unnecessary.
> > +The last semicolon 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.
> >
> > @node Zero Length
> > @subsection Arrays of Length Zero
> > diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> > index d0c13d4a24e..25e64dc5024 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,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 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" } */
> > --
> > 2.50.1
> >
>
> --
> <https://www.alejandro-colomar.es>
> Use port 80 (that is, <...:80/>).
On Thu, 25 Sep 2025, Alejandro Colomar wrote:
> > Maybe here I should say 's/parameters/parameter forward declarations/'.
>
> And would you mind amending this, if possible? Or do you prefer me to
> send a patch with that changed?
If you want to propose some different patch, then send that patch. I took
the "Maybe" as indicating you hadn't decided what the patch should look
like and so it wasn't ready for review.
Hi Joseph,
On Thu, Sep 25, 2025 at 04:33:55PM +0000, Joseph Myers wrote:
> On Thu, 25 Sep 2025, Alejandro Colomar wrote:
>
> > > Maybe here I should say 's/parameters/parameter forward declarations/'.
> >
> > And would you mind amending this, if possible? Or do you prefer me to
> > send a patch with that changed?
>
> If you want to propose some different patch, then send that patch. I took
> the "Maybe" as indicating you hadn't decided what the patch should look
> like and so it wasn't ready for review.
I'll send a new patch. That will give me an opportunity to re-read the
documentation, and maybe improve it more. I'll send it in a few days.
Thanks!
Have a lovely day!
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");
+ 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)
@@ -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.
+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.
+Lists of parameter forward declarations are terminated by semicolons,
+and parameters are separated within such lists by commas,
+just like in the regular parameter declaration list.
+
+You can write any number of such parameter forward declaration lists,
+but using more than one is unnecessary.
+The last semicolon 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.
@node Zero Length
@subsection Arrays of Length Zero
@@ -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,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)}
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" } */