On Wed, Aug 27, 2025 at 01:45:38PM +0200, Jason Merrill wrote: > > would be wrong. Guess > > if (DECL_CONTEXT (t) > > && !uses_template_parms (DECL_CONTEXT (t))) > > RETURN (t); > > would fix these ICEs, shall I go with that > > Sounds good.
The following passed bootstrap/regtest on x86_64-linux and i686-linux, ok? 2025-08-27 Jakub Jelinek <ja...@redhat.com> Jason Merrill <ja...@redhat.com> PR c++/121575 * pt.cc (tsubst_expr) <case PARM_DECL>: If DECL_CONTEXT (t) isn't a template return t for PARM_DECLs without local specialization. * g++.dg/cpp26/expansion-stmt20.C: New test. --- gcc/cp/pt.cc.jj 2025-08-25 16:29:07.122358976 +0200 +++ gcc/cp/pt.cc 2025-08-25 16:45:15.210314704 +0200 @@ -22321,6 +22321,11 @@ tsubst_expr (tree t, tree args, tsubst_f if (DECL_NAME (t) == this_identifier && current_class_ptr) RETURN (current_class_ptr); + /* Parameters of non-templates map to themselves (e.g. in + expansion statement body). */ + if (DECL_CONTEXT (t) && !uses_template_parms (DECL_CONTEXT (t))) + RETURN (t); + /* This can happen for a parameter name used later in a function declaration (such as in a late-specified return type). Just make a dummy decl, since it's only used for its type. */ --- gcc/testsuite/g++.dg/cpp26/expansion-stmt20.C.jj 2025-08-25 16:43:07.510020392 +0200 +++ gcc/testsuite/g++.dg/cpp26/expansion-stmt20.C 2025-08-25 16:43:07.510020392 +0200 @@ -0,0 +1,59 @@ +// PR c++/121575 +// { dg-do run { target c++11 } } +// { dg-options "" } + +struct A { int x, y; }; +int c; + +void +qux (A p) +{ + if (p.x != 1 || p.y != 3) + __builtin_abort (); + ++c; +} + +void +foo () +{ + A p { 1, 3 }; + template for (auto _ : {}) // { dg-warning "'template for' only available with" "" { target c++23_down } } + qux (p); + template for (auto _ : { 0 }) // { dg-warning "'template for' only available with" "" { target c++23_down } } + qux (p); +} + +void +bar (A p) +{ + template for (auto _ : {}) // { dg-warning "'template for' only available with" "" { target c++23_down } } + qux (p); + template for (auto _ : { 0, 1 }) // { dg-warning "'template for' only available with" "" { target c++23_down } } + qux (p); +} + +A +baz () +{ + A p { 1, 3 }; + template for (auto _ : {}) // { dg-warning "'template for' only available with" "" { target c++23_down } } + qux (p); + template for (auto _ : { 0, 1, 2 }) // { dg-warning "'template for' only available with" "" { target c++23_down } } + qux (p); + return p; +} + +int +main () +{ + foo (); + if (c != 1) + __builtin_abort (); + bar ({ 1, 3 }); + if (c != 3) + __builtin_abort (); + if (baz ().x != 1 || baz ().y != 3) + __builtin_abort (); + if (c != 9) + __builtin_abort (); +} Jakub