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
