https://gcc.gnu.org/g:1933adbc5446e5ae0282585498ac5f9f8e6c0bdc
commit r16-8501-g1933adbc5446e5ae0282585498ac5f9f8e6c0bdc Author: Jakub Jelinek <[email protected]> Date: Tue Apr 7 18:00:24 2026 +0200 c++: Implement mangling for partially instantiated C++26 pack indexing [PR124487] On Fri, Apr 03, 2026 at 05:56:08PM -0400, Jason Merrill wrote: > Regarding the TODO, the related case I was thinking about was > > > ::= sZ <template-param> # sizeof...(T), size of a template parameter pack > > ::= sP <template-arg>* E # sizeof...(T), size of a captured template parameter pack from an alias template > > ...but rather than follow the precedent of a different two-letter > abbreviation, I might use J...E to express the expanded pack, as in > <template-arg>. I've now suggested that on the ABI issue, as well. Here is a patch which implements it. 2026-04-07 Jakub Jelinek <[email protected]> PR c++/124487 * mangle.cc (write_type) <case PACK_INDEX_TYPE>: Handle even the case of partially substituted pack. (write_expression): Similarly for PACK_INDEX_EXPR. * g++.dg/cpp26/pack-indexing9.C: Remove dg-sorry/dg-bogus, add tests for mangled names and further test coverage. Reviewed-by: Jason Merrill <[email protected]> Diff: --- gcc/cp/mangle.cc | 35 ++++++++++++++++------------- gcc/testsuite/g++.dg/cpp26/pack-indexing9.C | 22 ++++++++++++++++-- 2 files changed, 40 insertions(+), 17 deletions(-) diff --git a/gcc/cp/mangle.cc b/gcc/cp/mangle.cc index 9eb09dcede75..d1301789ef4d 100644 --- a/gcc/cp/mangle.cc +++ b/gcc/cp/mangle.cc @@ -2745,16 +2745,19 @@ write_type (tree type) case PACK_INDEX_TYPE: /* https://github.com/itanium-cxx-abi/cxx-abi/issues/175. */ + write_string ("Dy"); if (TREE_CODE (PACK_INDEX_PACK (type)) == TREE_VEC) { - /* TODO: How should this be mangled when the pack is already - expanded? */ - sorry ("mangling type pack index"); - break; + write_char ('J'); + for (int i = 0; i < TREE_VEC_LENGTH (PACK_INDEX_PACK (type)); + ++i) + write_template_arg (TREE_VEC_ELT (PACK_INDEX_PACK (type), + i)); + write_char ('E'); } - write_string ("Dy"); - /* Dy rather than DyDp. */ - write_type (PACK_EXPANSION_PATTERN (PACK_INDEX_PACK (type))); + else + /* Dy rather than DyDp. */ + write_type (PACK_EXPANSION_PATTERN (PACK_INDEX_PACK (type))); write_expression (PACK_INDEX_INDEX (type)); break; @@ -3614,17 +3617,19 @@ write_expression (tree expr) else if (code == PACK_INDEX_EXPR) { /* https://github.com/itanium-cxx-abi/cxx-abi/issues/175. */ + write_string ("sy"); if (TREE_CODE (PACK_INDEX_PACK (expr)) == TREE_VEC) - /* TODO: How should this be mangled when the pack is already - expanded? */ - sorry ("mangling type pack index"); - else { - write_string ("sy"); - /* sy rather than sysp. */ - write_expression (PACK_EXPANSION_PATTERN (PACK_INDEX_PACK (expr))); - write_expression (PACK_INDEX_INDEX (expr)); + write_char ('J'); + for (int i = 0; i < TREE_VEC_LENGTH (PACK_INDEX_PACK (expr)); + ++i) + write_template_arg (TREE_VEC_ELT (PACK_INDEX_PACK (expr), i)); + write_char ('E'); } + else + /* sy rather than sysp. */ + write_expression (PACK_EXPANSION_PATTERN (PACK_INDEX_PACK (expr))); + write_expression (PACK_INDEX_INDEX (expr)); } else if (TREE_CODE (expr) == ALIGNOF_EXPR) { diff --git a/gcc/testsuite/g++.dg/cpp26/pack-indexing9.C b/gcc/testsuite/g++.dg/cpp26/pack-indexing9.C index afd8a2f9ed6b..ab5d2c7704df 100644 --- a/gcc/testsuite/g++.dg/cpp26/pack-indexing9.C +++ b/gcc/testsuite/g++.dg/cpp26/pack-indexing9.C @@ -4,24 +4,42 @@ // From <https://github.com/itanium-cxx-abi/cxx-abi/issues/175>. template <class... T> struct tuple { - template <unsigned I> T...[I] get(); // { dg-bogus "sorry, unimplemented: mangling" "" { xfail *-*-* } } + template <unsigned I> T...[I] get(); }; int g () { tuple<int> t; + // { dg-final { scan-assembler "_ZN5tupleIJiEE3getILj0EEEDyJiET_v" } } return t.get<0>(); } template<typename T, typename U> concept C = true; +template<typename T, auto U> concept D = true; template<typename ...T> struct A { - template<int I, typename ...U> void f(T...[I], U...[I]) requires C<T...[I], U...[I]>; // { dg-message "sorry, unimplemented: mangling" } + template<int I, typename ...U> void f(T...[I], U...[I]) requires C<T...[I], U...[I]>; + template<int I, auto ...U> void h(T...[I], decltype(U...[I])) requires D<T...[I], U...[I]>; }; void h () { A<char, int, double> a; + // { dg-final { scan-assembler "_ZN1AIJcidEE1fILi1EJiicEEEvDyJcidET_DyT0_T_Q1CIDyT_TL0__DyTL0_0_TL0__E" } } a.f<1, int, int, char>(1, 2); + // { dg-final { scan-assembler "_ZN1AIJcidEE1hILi1EJLi2ELl3ELj4EEEEvDyJcidET_DtsyT0_T_EQ1DIDyT_TL0__XsyTL0_0_TL0__EE" } } + a.h<1, 2, 3L, 4U>(1, 3L); +} + +template <auto... U> struct E { + template <unsigned I> decltype (U...[I]) get(); +}; + +int +i () +{ + E<1, 2L, 3U, 4LL> t; + // { dg-final { scan-assembler "_ZN1EIJLi1ELl2ELj3ELx4EEE3getILj2EEEDtsyJLi1ELl2ELj3ELx4EET_Ev" } } + return t.get<2>(); }
