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

commit r16-8483-ga96d7250389d05ab8f8a68c2c3cfad3c709a6cb4
Author: Jakub Jelinek <[email protected]>
Date:   Mon Apr 6 23:10:46 2026 +0200

    c++: Fix up handling of for-range-decls of expansion stmt [PR124488]
    
    The following testcase is rejected, because we don't set all the needed
    flags on range_decl in cp_parser_expansion_statement.  During parsing
    of the expansion stmt body, it should be treated as if there is a decl
    with value dependent initializer in a template, because the value it will
    have is yet to be determined (and possibly different in each instantiation
    of the body).
    For such decls, cp_finish_decl normally conservatively sets
    DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (because it might be initialized
    by constant expression) and for non-references also sets TREE_CONSTANT
    if decl_maybe_constant_var_p.  Furthermore, those have a value dependent
    initializer and DECL_DEPENDENT_INIT_P is set on those too.
    
    The following patch arranges all of that for the range_decl.
    
    2026-04-06  Jakub Jelinek  <[email protected]>
    
            PR c++/124488
            * parser.cc (cp_parser_expansion_statement): Set
            DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P, DECL_DEPENDENT_INIT_P and
            if maybe constant non-reference TREE_CONSTANT on range_decl.
            * pt.cc (tsubst_stmt) <case TEMPLATE_FOR_STMT>: Set
            DECL_DEPENDENT_INIT_P on decl.
    
            * g++.dg/cpp26/expansion-stmt33.C: New test.
    
    Reviewed-by: Jason Merrill <[email protected]>

Diff:
---
 gcc/cp/parser.cc                              | 14 ++++++++++++++
 gcc/cp/pt.cc                                  |  5 +++++
 gcc/testsuite/g++.dg/cpp26/expansion-stmt33.C | 17 +++++++++++++++++
 3 files changed, 36 insertions(+)

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 518858fc7760..3a8d56dc1465 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -16685,6 +16685,20 @@ cp_parser_expansion_statement (cp_parser* parser, bool 
*if_p)
   TEMPLATE_FOR_EXPR (r) = expansion_init;
   TEMPLATE_FOR_BODY (r) = do_pushlevel (sk_block);
 
+  /* We don't know yet if range_decl will be initialized by constant
+     expression or not.  */
+  if (VAR_P (range_decl))
+    {
+      DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (range_decl) = 1;
+      if (decl_maybe_constant_var_p (range_decl)
+         /* FIXME setting TREE_CONSTANT on refs breaks the back end.  */
+         && !TYPE_REF_P (TREE_TYPE (range_decl)))
+       TREE_CONSTANT (range_decl) = true;
+      /* Make it value dependent.  */
+      retrofit_lang_decl (range_decl);
+      SET_DECL_DEPENDENT_INIT_P (range_decl, 1);
+    }
+
   /* Parse the body of the expansion-statement.  */
   parser->in_statement = IN_EXPANSION_STMT;
   bool prev = note_iteration_stmt_body_start ();
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index d83ff031d77b..673da9a19b40 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -19776,6 +19776,11 @@ tsubst_stmt (tree t, tree args, tsubst_flags_t 
complain, tree in_decl)
              orig_decl = TREE_VEC_ELT (orig_decl, 0);
            tree decl = tsubst (orig_decl, args, complain, in_decl);
            maybe_push_decl (decl);
+           if (VAR_P (decl))
+             {
+               retrofit_lang_decl (decl);
+               SET_DECL_DEPENDENT_INIT_P (decl, 1);
+             }
 
            cp_decomp decomp_d, *decomp = NULL;
            if (DECL_DECOMPOSITION_P (decl))
diff --git a/gcc/testsuite/g++.dg/cpp26/expansion-stmt33.C 
b/gcc/testsuite/g++.dg/cpp26/expansion-stmt33.C
new file mode 100644
index 000000000000..c7f79efb3a56
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp26/expansion-stmt33.C
@@ -0,0 +1,17 @@
+// PR c++/124488
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+void
+foo ()
+{
+  template for (constexpr int a : { 42 })      // { dg-warning "'template for' 
only available with" "" { target c++23_down } }
+    auto b = [] () { return a; };
+}
+
+void
+bar (int x)
+{
+  template for (const int a : { 42, ++x, 5 })  // { dg-warning "'template for' 
only available with" "" { target c++23_down } }
+    const int b = a;
+}

Reply via email to