On 8/27/25 2:04 PM, Jakub Jelinek wrote:
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?
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