On Thu, May 28, 2026 at 04:18:31PM -0400, Jason Merrill wrote: > On 5/28/26 4:00 PM, Jakub Jelinek wrote: > > On Wed, May 27, 2026 at 06:19:33PM -0400, Jason Merrill wrote: > > > On 5/25/26 11:15 AM, Jakub Jelinek wrote: > > > > Hi! > > > > > > > > The following testcase ICEs, because we decide to mangle the (for the > > > > time > > > > being as workaround static constexpr variables created for expansion > > > > statements). And if there is more than one in the same function and we > > > > mangle both, we ICE because they mangle the same. > > > > > > > > The problem is that cp_finish_decl does not > > > > determine_local_discriminator > > > > for DECL_ARTIFICIAL vars. > > > > > > Would it make sense to change that? > > > > My understanding is that the DECL_ARTIFICIAL check is there probably to > > avoid calling those functions for guard variables. > > And there is no flag exactly for guard vars. > > I don't see why calling determine_local_discriminator would be a problem for > guard vars, and removing the DECL_ARTIFICIAL check doesn't seem to regress > anything for me.
Perhaps it is a small waste of compile time/memory, but guess the guard var names are unique and so will not actually lead to assignment of discriminators. Following passed bootstrap/regtest on x86_64-linux and i686-linux. 2026-05-29 Jakub Jelinek <[email protected]> PR c++/125123 * parser.cc (cp_build_range_for_decls): If range_temp or begin are static, set DECL_IGNORED_P on it. * pt.cc (finish_expansion_stmt): Similarly for iter. * decl.cc (cp_finish_decl): Call determine_local_discriminator etc. also for DECL_ARTIFICIAL TREE_STATIC vars. * g++.dg/cpp26/expansion-stmt42.C: New test. --- gcc/cp/parser.cc.jj 2026-05-23 01:23:05.072826742 +0200 +++ gcc/cp/parser.cc 2026-05-25 12:48:42.070467582 +0200 @@ -16063,6 +16063,7 @@ cp_build_range_for_decls (location_t loc DECL_INTERFACE_KNOWN (range_temp) = 1; DECL_DECLARED_CONSTEXPR_P (range_temp) = 1; TREE_READONLY (range_temp) = 1; + DECL_IGNORED_P (range_temp) = 1; } } else @@ -16092,8 +16096,9 @@ cp_build_range_for_decls (location_t loc TREE_STATIC (begin) = 1; DECL_DECLARED_CONSTEXPR_P (begin) = 1; TREE_READONLY (begin) = 1; + DECL_IGNORED_P (begin) = 1; } pushdecl (begin); cp_finish_decl (begin, begin_expr, /*is_constant_init*/false, NULL_TREE, LOOKUP_ONLYCONVERTING); --- gcc/cp/pt.cc.jj 2026-05-23 10:23:20.669068142 +0200 +++ gcc/cp/pt.cc 2026-05-25 12:48:00.390139881 +0200 @@ -33701,8 +33701,9 @@ finish_expansion_stmt (tree expansion_st TREE_STATIC (iter) = 1; DECL_DECLARED_CONSTEXPR_P (iter) = 1; TREE_READONLY (iter) = 1; + DECL_IGNORED_P (iter) = 1; } pushdecl (iter); cp_finish_decl (iter, iter_init, /*is_constant_init*/false, NULL_TREE, LOOKUP_ONLYCONVERTING); init = build_x_indirect_ref (loc, iter, RO_UNARY_STAR, NULL_TREE, --- gcc/cp/decl.cc.jj 2026-05-26 11:40:04.935274356 +0200 +++ gcc/cp/decl.cc 2026-05-28 22:21:26.406685208 +0200 @@ -9887,9 +9887,7 @@ cp_finish_decl (tree decl, tree init, bo require a guard variable, and since the mangled name of the guard variable will depend on the mangled name of this variable. */ - if (DECL_FUNCTION_SCOPE_P (decl) - && TREE_STATIC (decl) - && !DECL_ARTIFICIAL (decl)) + if (DECL_FUNCTION_SCOPE_P (decl) && TREE_STATIC (decl)) { /* The variable holding an anonymous union will have had its discriminator set in finish_anon_union, after which it's --- gcc/testsuite/g++.dg/cpp26/expansion-stmt42.C.jj 2026-05-25 12:50:46.111466801 +0200 +++ gcc/testsuite/g++.dg/cpp26/expansion-stmt42.C 2026-05-25 12:53:47.616539126 +0200 @@ -0,0 +1,22 @@ +// PR c++/125123 +// { dg-do compile { target c++20 } } +// { dg-options "-g" } + +struct A +{ + int a[2]; + constexpr int const *begin () const { return a; } + constexpr int const *end () const { return a + 2; } +}; + +template <typename T> +requires true +void +foo () +{ + template for (constexpr int i : A { 0, 1 }) // { dg-warning "'template for' only available with" "" { target c++23_down } } + ; + template for (constexpr int i : A { 0, 1 }) // { dg-warning "'template for' only available with" "" { target c++23_down } } + ; +} +template void foo <void> (); Jakub
