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 <[email protected]>
> Cc: Martin Uecker <[email protected]>
> Signed-off-by: Alejandro Colomar <[email protected]>
> ---
> 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
>
--
<https://www.alejandro-colomar.es>
Use port 80 (that is, <...:80/>).
signature.asc
Description: PGP signature
