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

Reply via email to