From: Jakub Jelinek Date: Mon, 6 Apr 2026 21:10:46 +0000 (+0200) Subject: c++: Fix up handling of for-range-decls of expansion stmt [PR124488] X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a96d7250389d05ab8f8a68c2c3cfad3c709a6cb4;p=thirdparty%2Fgcc.git 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 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) : Set DECL_DEPENDENT_INIT_P on decl. * g++.dg/cpp26/expansion-stmt33.C: New test. Reviewed-by: Jason Merrill --- diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 518858fc776..3a8d56dc146 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 d83ff031d77..673da9a19b4 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 00000000000..c7f79efb3a5 --- /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; +}