On 5/29/26 4:06 AM, Jakub Jelinek wrote:
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.
OK.
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