On 5/11/26 8:25 PM, Marek Polacek wrote:
On Wed, May 06, 2026 at 04:15:03PM -0400, Jason Merrill wrote:
On 5/5/26 9:19 PM, Marek Polacek wrote:
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

Additionally tested with the "Optimization only" checks disabled
to see if it isn't hiding any errors.

-- >8 --
In

    void fn (int i = sizeof (i)) {}

the i in sizeof should refer to the parameter ([basic.scope.pdecl]) and
since the second i is not evaluated, the code is valid per
[dcl.fct.default]/9: A parameter shall not appear as a potentially
evaluated expression in a default argument.

To make this work, we have to defer parsing of the default argument
until we've done grokdeclarator + pushdecl on i.

How about doing that by moving grokdeclarator/pushdecl into
cp_parser_parameter_declaration rather than mess with DEFERRED_PARSE?

Looks like I actually can do that.  I just have to pass the decl back
to _parameter_declaration_list, otherwise the pending_decls handling
could become ugly.  But it seems better than the DEFERRED_PARSE
approach.

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

-- >8 --
In

   void fn (int i = sizeof (i)) {}

the i in sizeof should refer to the parameter ([basic.scope.pdecl]) and
since the second i is not evaluated, the code is valid per
[dcl.fct.default]/9: A parameter shall not appear as a potentially
evaluated expression in a default argument.

This patch fixes this by moving the grokdeclarator call from
_parameter_declaration_list to _parameter_declaration and maybe calling
pushdecl before parsing the default argument.

        PR c++/50479
        PR c++/62244

gcc/cp/ChangeLog:

        * parser.cc (cp_parser_parameter_declaration_list): Move the
        grokdeclarator call and setting DECL_SOURCE_LOCATION to...
        (cp_parser_parameter_declaration): ...here.  New tree parameter.
        Set it.  Call pushdecl for a named decl with a default argument.

gcc/testsuite/ChangeLog:

        * g++.dg/reflect/parm1.C: Uncomment code.
        * g++.dg/parse/defarg22.C: New test.
        * g++.dg/parse/defarg23.C: New test.
        * g++.dg/parse/defarg24.C: New test.
        * g++.dg/parse/defarg25.C: New test.
        * g++.dg/parse/defarg26.C: New test.
---
  gcc/cp/parser.cc                      | 63 +++++++++++++++++----------
  gcc/testsuite/g++.dg/parse/defarg22.C | 16 +++++++
  gcc/testsuite/g++.dg/parse/defarg23.C | 36 +++++++++++++++
  gcc/testsuite/g++.dg/parse/defarg24.C | 12 +++++
  gcc/testsuite/g++.dg/parse/defarg25.C | 22 ++++++++++
  gcc/testsuite/g++.dg/parse/defarg26.C | 18 ++++++++
  gcc/testsuite/g++.dg/reflect/parm1.C  |  5 +--
  7 files changed, 146 insertions(+), 26 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/parse/defarg22.C
  create mode 100644 gcc/testsuite/g++.dg/parse/defarg23.C
  create mode 100644 gcc/testsuite/g++.dg/parse/defarg24.C
  create mode 100644 gcc/testsuite/g++.dg/parse/defarg25.C
  create mode 100644 gcc/testsuite/g++.dg/parse/defarg26.C

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index d128de771b5..66126115e61 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -2785,7 +2785,7 @@ static tree cp_parser_parameter_declaration_clause
  static tree cp_parser_parameter_declaration_list
    (cp_parser *, cp_parser_flags, auto_vec<tree> *);
  static cp_parameter_declarator *cp_parser_parameter_declaration
-  (cp_parser *, cp_parser_flags, bool, bool *);
+  (cp_parser *, cp_parser_flags, bool, bool *, tree * = nullptr);
  static tree cp_parser_default_argument
    (cp_parser *, bool);
  static void cp_parser_function_body
@@ -28301,24 +28301,7 @@ cp_parser_parameter_declaration_list (cp_parser* 
parser,
        parameter
        = cp_parser_parameter_declaration (parser, flags,
                                           /*template_parm_p=*/false,
-                                          &parenthesized_p);
-
-      /* We don't know yet if the enclosing context is unavailable or 
deprecated,
-        so wait and deal with it in grokparms if appropriate.  */
-      deprecated_state = UNAVAILABLE_DEPRECATED_SUPPRESS;
-
-      if (parameter && !cp_parser_error_occurred (parser))
-       {
-         decl = grokdeclarator (parameter->declarator,
-                                &parameter->decl_specifiers,
-                                PARM,
-                                parameter->default_argument != NULL_TREE,
-                                &parameter->decl_specifiers.attributes);
-         if (decl != error_mark_node && parameter->loc != UNKNOWN_LOCATION)
-           DECL_SOURCE_LOCATION (decl) = parameter->loc;
-       }
-
-      deprecated_state = DEPRECATED_NORMAL;
+                                          &parenthesized_p, &decl);
/* If a parse error occurred parsing the parameter declaration,
         then the entire parameter-declaration-list is erroneous.  */
@@ -28361,7 +28344,10 @@ cp_parser_parameter_declaration_list (cp_parser* 
parser,
                   return false;
                 }())
            pending_decls->safe_push (decl);
-         else
+         /* If we saw a default argument, we've already pushed this decl.
+            (An ill-formed default argument should have been parsed to
+            error_mark_node.)  */
+         else if (!parameter->default_argument)
            decl = pushdecl (decl);
        }
@@ -28474,6 +28460,9 @@ cp_parser_parameter_declaration_list (cp_parser* parser,
     token encountered during the parsing of the assignment-expression
     is not interpreted as a greater-than operator.)
+ If DECL is non-null, we are called from cp_parser_parameter_declaration_list
+   and will perform grokdeclarator here; DECL will be set to the result.

Let's call this DECLP for clarity. This should also mention that it will call pushdecl if there is a default argument. OK with those tweaks.

Jason

Reply via email to