https://gcc.gnu.org/g:d3f638f4dfe67f50ba298890258ef6466705f0fa

commit r16-5781-gd3f638f4dfe67f50ba298890258ef6466705f0fa
Author: Jakub Jelinek <[email protected]>
Date:   Sun Nov 30 15:52:27 2025 +0100

    c++: Fix error recovery in cp_hide_range_decl [PR122465]
    
    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).
    
    The fix tweaks cp_parser_simple_declaration, such that it stores 
error_mark_node
    instead of NULL_TREE into *maybe_range_for_decl in the erroneous cases.
    
    2025-11-30  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.

Diff:
---
 gcc/cp/parser.cc                      | 20 ++++++++++----------
 gcc/testsuite/g++.dg/cpp0x/pr122465.C | 10 ++++++++++
 2 files changed, 20 insertions(+), 10 deletions(-)

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 786212713dbc..4289f47e1b23 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -17086,8 +17086,9 @@ cp_parser_block_declaration (cp_parser *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,
@@ -17139,7 +17140,7 @@ cp_parser_simple_declaration (cp_parser* parser,
       && !decl_specifiers.any_specifiers_p)
     {
       cp_parser_error (parser, "expected declaration");
-      goto done;
+      goto error_out;
     }
 
   /* If the next two tokens are both identifiers, the code is
@@ -17155,7 +17156,7 @@ cp_parser_simple_declaration (cp_parser* 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);
@@ -17180,11 +17181,7 @@ cp_parser_simple_declaration (cp_parser* 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
          {
@@ -17263,7 +17260,7 @@ cp_parser_simple_declaration (cp_parser* 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)
        {
@@ -17401,6 +17398,9 @@ cp_parser_simple_declaration (cp_parser* parser,
       if (comma_loc != UNKNOWN_LOCATION)
        error_at (comma_loc,
                  "multiple declarations in range-based %<for%> loop");
+    error_out:
+      if (maybe_range_for_decl && *maybe_range_for_decl == NULL_TREE)
+       *maybe_range_for_decl = error_mark_node;
     }
 
  done:
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr122465.C 
b/gcc/testsuite/g++.dg/cpp0x/pr122465.C
new file mode 100644
index 000000000000..b8de3d417b40
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/pr122465.C
@@ -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" }
+    ;
+}

Reply via email to