On Mon, Jan 26, 2026 at 11:04:05AM +0800, Jason Merrill wrote:
> > +  recursed = true;
> >     print_ring[ring_counter] = xstrdup (lang_decl_name (decl, v, 
> > translate));
> > +  recursed = false;
> >     uid_ring[ring_counter] = DECL_UID (decl);
> >     trans_ring[ring_counter] = translate;
> >     return print_ring[ring_counter];
> 
> Would it instead make sense to use a local automatic copy of "ring_counter"
> so that recursive modifications don't change which element we access here?

We'd need to move the free call after that and I'd be afraid we would risk
having duplicate entries in the cache (which is something the function would
ICE on), because the checking which cache element to use has been done
before perhaps multiple entries of the cache were changed.

But I think we could just move the lang_decl_name call earlier before we
decide in which cache element to cache it.  I can't rule out that the call
would recursively add the same function to the cache, so I've repeated the
search (which is not expensive, PRINT_RING_SIZE is just 4).

2026-01-26  Jakub Jelinek  <[email protected]>

        PR c++/123578
        * tree.cc (cxx_printable_name_internal): Call lang_decl_name before
        finding the slot to cache it in and repeat search in the cache
        after the call.

        * g++.dg/cpp2a/pr123578.C: New test.

--- gcc/cp/tree.cc.jj   2026-01-24 09:55:14.411592954 +0100
+++ gcc/cp/tree.cc      2026-01-26 14:28:07.031283312 +0100
@@ -2859,6 +2859,15 @@ cxx_printable_name_internal (tree decl,
       /* yes, so return it.  */
       return print_ring[i];
 
+  const char *ret = lang_decl_name (decl, v, translate);
+
+  /* The lang_decl_name call could have called this function recursively,
+     so check again.  */
+  for (i = 0; i < PRINT_RING_SIZE; i++)
+    if (uid_ring[i] == DECL_UID (decl) && translate == trans_ring[i])
+      /* yes, so return it.  */
+      return print_ring[i];
+
   if (++ring_counter == PRINT_RING_SIZE)
     ring_counter = 0;
 
@@ -2878,7 +2887,7 @@ cxx_printable_name_internal (tree decl,
 
   free (print_ring[ring_counter]);
 
-  print_ring[ring_counter] = xstrdup (lang_decl_name (decl, v, translate));
+  print_ring[ring_counter] = xstrdup (ret);
   uid_ring[ring_counter] = DECL_UID (decl);
   trans_ring[ring_counter] = translate;
   return print_ring[ring_counter];
--- gcc/testsuite/g++.dg/cpp2a/pr123578.C.jj    2026-01-26 14:14:19.391980298 
+0100
+++ gcc/testsuite/g++.dg/cpp2a/pr123578.C       2026-01-26 14:14:19.391980298 
+0100
@@ -0,0 +1,9 @@
+// PR c++/123578
+// { dg-do compile { target c++20 } }
+// { dg-options "-fdump-tree-all" }
+
+namespace {
+  template <typename>
+  struct A { A (decltype ([] { return 0; } ())) {} };
+  A <int> b = 0;
+}


        Jakub

Reply via email to