On 11/20/25 5:31 PM, Jakub Jelinek wrote:
On Thu, Nov 20, 2025 at 10:46:21AM +0530, Jason Merrill wrote:
The following testcase shows that range_decl in cp_hide_range_decl is
sometimes also NULL_TREE and not just error_mark_node, and the function
IMHO should treat both the same, not try to hide anything in that case
because it doesn't know what should be hidden.  This ICEs during
error recovery since something like cp_hide_range_decl has been introduced
(earlier it wasn't called that way).

This seems like cp_parser_simple_declaration is violating its comment:

If the intent was a decl or error_mark_node as the comment says, then
it wouldn't start with
   if (maybe_range_for_decl)
     *maybe_range_for_decl = NULL_TREE;
Furthermore, I think it would be really weird to set *maybe_range_for_decl
to error_mark_node in the non-erroneous cases, the name of the argument
includes maybe_ prefix.

I think it is just fine to set *maybe_range_for_decl to error_mark_node
in the erroneous cases, basically make sure that if it is followed by
CPP_COLON (i.e. when cp_parser_init_statement is going to return true)
then it will never be NULL.

Here is a patch which does that, so far tested with
GXX_TESTSUITE_STDS=98,11,14,17,20,23,26 make -j32 -k check-g++ check-obj-c++
in gcc/ and libstdc++-v3 make check, ok for trunk if it passes full
bootstrap/regtest?

2025-11-20  Jakub Jelinek  <[email protected]>

        PR c++/122465
        * parser.cc (cp_parser_simple_declaration): Adjust function comment.
        Set *maybe_range_for_decl to error_mark_node instead of keeping it
        NULL_TREE in error cases or when followed by CPP_COLON.

        * g++.dg/cpp0x/pr122465.C: New test.

--- gcc/cp/parser.cc.jj 2025-11-20 11:19:13.583211387 +0100
+++ gcc/cp/parser.cc    2025-11-20 12:02:19.051259722 +0100
@@ -17032,8 +17032,9 @@ cp_parser_block_declaration (cp_parser *
If MAYBE_RANGE_FOR_DECL is not NULL, the pointed tree will be set to the
     parsed declaration if it is an uninitialized single declarator not followed
-   by a `;', or to error_mark_node otherwise. Either way, the trailing `;',
-   if present, will not be consumed.  */
+   by a `;', or to NULL_TREE when not followed by `:' or to error_mark_node
+   otherwise.  Either way, the trailing `;', if present, will not be
+   consumed.  */
static void
  cp_parser_simple_declaration (cp_parser* parser,
@@ -17085,6 +17086,9 @@ cp_parser_simple_declaration (cp_parser*
        && !decl_specifiers.any_specifiers_p)
      {
        cp_parser_error (parser, "expected declaration");
+    error_out:
+      if (maybe_range_for_decl && *maybe_range_for_decl == NULL_TREE)
+       *maybe_range_for_decl = error_mark_node;
        goto done;

Instead of putting error_out: here...

      }
@@ -17101,7 +17105,7 @@ cp_parser_simple_declaration (cp_parser*
         looking at a declaration.  */
        cp_parser_commit_to_tentative_parse (parser);
        /* Give up.  */
-      goto done;
+      goto error_out;
      }
cp_parser_maybe_commit_to_declaration (parser, &decl_specifiers);
@@ -17126,11 +17130,7 @@ cp_parser_simple_declaration (cp_parser*
        if (token->type == CPP_SEMICOLON)
          goto finish;
        else if (maybe_range_for_decl)
-         {
-           if (*maybe_range_for_decl == NULL_TREE)
-             *maybe_range_for_decl = error_mark_node;
-           goto finish;
-         }
+         goto finish;
        /* Anything else is an error.  */
        else
          {
@@ -17209,7 +17209,7 @@ cp_parser_simple_declaration (cp_parser*
         statement is treated as a declaration-statement until proven
         otherwise.)  */
        if (cp_parser_error_occurred (parser))
-       goto done;
+       goto error_out;
if (auto_specifier_p && cxx_dialect >= cxx14)
        {
@@ -17347,6 +17347,8 @@ cp_parser_simple_declaration (cp_parser*
        if (comma_loc != UNKNOWN_LOCATION)
        error_at (comma_loc,
                  "multiple declarations in range-based %<for%> loop");

...how about putting it here?

+      if (*maybe_range_for_decl == NULL_TREE)
+       *maybe_range_for_decl = error_mark_node;
      }
done:
--- gcc/testsuite/g++.dg/cpp0x/pr122465.C.jj    2025-11-20 11:19:04.978706617 
+0100
+++ gcc/testsuite/g++.dg/cpp0x/pr122465.C       2025-11-20 12:06:11.387942293 
+0100
@@ -0,0 +1,10 @@
+// PR c++/122465
+// { dg-do compile { target c++11 } }
+
+void
+foo ()
+{
+  int x = 0;
+  for (const T i = { i } : x)  // { dg-error "'T' does not name a type" }
+    ;
+}


        Jakub


Reply via email to