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

Attachment: signature.asc
Description: PGP signature

Reply via email to