See <https://wg21.link/P1061R10>.
Created attachment 61223 [details] gcc16-pr117783-wip.patch My current WIP. It can already handle something like struct S { int a, b; long long c; unsigned d; }; template <typename ... T> void baz (T ...x) { } template <typename T> long long foo () { auto [a, ...b, c] = T {}; auto [...d] = T {}; baz (d...); return ((a + c) + ... + b); } int bar () { return foo <S> (); } Not really sure about mangling though. LLVM mangles struct S { int a, b; long long c; unsigned d; }; template <typename ... T> void baz (T ...x) { } template <typename T> long long foo () { auto [a, ...b, c] = T {}; auto [...d] = T {}; baz (d...); return ((a + c) + ... + b); } int bar () { return foo <S> (); } as _ZZ3fooILi0EEvvEDC1a1bE and _ZZ3fooILi42EEvvEDC1a1bE (and so will this patch), not really sure if the mangling shouldn't include something to say which of those if any is a structured binding pack. Another question is for struct S { int a, b, c, d, e; }; int c[6]; struct B { template<int I> int &get () { return c[I]; } } b; namespace std { template<typename T> struct tuple_size; template<int, typename> struct tuple_element; } template<> struct std::tuple_size<B> { static constexpr int value = 6; }; template<int I> struct std::tuple_element<I,B> { typedef int type; }; template <int N> inline void foo () { static auto [a, ...c, d] = b; ++a; ++d; } void bar () { foo <0> (); foo <42> (); } where I see LLVM using _ZZ3fooILi0EEvvE1c _ZGVZ3fooILi0EEvvE1c _ZZ3fooILi0EEvvE1c.1 _ZGVZ3fooILi0EEvvE1c.2 _ZZ3fooILi0EEvvE1c.3 _ZGVZ3fooILi0EEvvE1c.4 etc. That just can't be right.
Filed https://github.com/itanium-cxx-abi/cxx-abi/issues/200
Created attachment 61241 [details] gcc16-pr117783-wip.patch Further progress.
Created attachment 61257 [details] gcc16-pr117783-wip.patch Further progress.
The master branch has been updated by Jakub Jelinek <jakub@gcc.gnu.org>: https://gcc.gnu.org/g:dff57d76ad3c78cedaf2f8caa1686acb5059303d commit r16-3069-gdff57d76ad3c78cedaf2f8caa1686acb5059303d Author: Jakub Jelinek <jakub@redhat.com> Date: Thu Aug 7 16:38:51 2025 +0200 c++: Implement C++26 P1061R10 - Structured Bindings can introduce a Pack [PR117783] The following patch implements the C++26 P1061R10 - Structured Bindings can introduce a Pack paper. One thing unresolved in the patch is mangling, I've raised https://github.com/itanium-cxx-abi/cxx-abi/issues/200 for that but no comments there yet. One question is if it is ok not to mention the fact that there is a structured binding pack in the mangling of the structured bindings but more important is in case of std::tuple* we might need to mangle individual structured binding pack elements separately (each might need an exported name for the var itself and perhaps its guard variable as well). The patch just uses the normal mangling for the whole structured bindings and emits sorry if we need to mangle the structured binding pack elements. The patch just marks the structured binding pack specially (considered e.g. using some bit on it, but in the end I'm identifying it using a made up type which causes DECL_PACK_P to be true; it is kind of self-referential solution, because the type on the pack mentions the DECL_DECOMPOSITION_P VAR_DECL on which the type is attached as its pack, so it needs to be handled carefully during instantiation to avoid infinite recursion, but it is the type that should be used if something else actually needs to use the same type as the structured binding pack, e.g. a capture proxy), and stores the pack elements when actually processed through cp_finish_decomp with non-dependent initializer into a TREE_VEC used as DECL_VALUE_EXPR of the pack; though because several spots use the DECL_VALUE_EXPR and assume it is ARRAY_REF from which they can find out the base variable and the index, it stores the base variable and index in the first 2 TREE_VEC elts and has the structured binding elements only after that. https://eel.is/c++draft/temp.dep.expr#3.6 says the packs are type dependent regardless of whether the initializer of the structured binding is type dependent or not, so I hope having a dependent type on the structured binding VAR_DECL is ok. The paper also has an exception for sizeof... which is then not value dependent when the structured bindings are initialized with non-dependent initializer: https://eel.is/c++draft/temp.dep.constexpr#4 The patch special cases that in 3 spots (I've been wondering if e.g. during parsing I couldn't just fold the sizeof... to the INTEGER_CST right away, but guess I'd need to repeat that also during partial instantiation). And one thing still unresolved is debug info, I've just added DECL_IGNORED_P on the structured binding pack VAR_DECL because there were ICEs with -g for now, hope it can be fixed incrementally but am not sure what exactly we should emit in the debug info for that. Speaking of which, I see DW_TAG_GNU_template_parameter_pack DW_TAG_GNU_formal_parameter_pack etc. DIEs emitted regardless of DWARF version, shouldn't we try to upstream those into DWARF 6 or check what other compilers emit for the packs? And bet we'd need DW_TAG_GNU_structured_binding_pack as well. 2025-08-07 Jakub Jelinek <jakub@redhat.com> PR c++/117783 gcc/c-family/ * c-cppbuiltin.cc (c_cpp_builtins): Change __cpp_structured_bindings predefined value for C++26 from 202403L to 202411L. gcc/cp/ * parser.cc: Implement C++26 P1061R10 - Structured Bindings can introduce a Pack. (cp_parser_range_for): Also handle TREE_VEC as DECL_VALUE_EXPR instead of ARRAY_REF. (cp_parser_decomposition_declaration): Use sb-identifier-list instead of identifier-list in comments. Parse structured bindings with structured binding pack. Don't emit pedwarn about structured binding attributes in structured bindings inside of a condition. (cp_convert_omp_range_for): Also handle TREE_VEC as DECL_VALUE_EXPR instead of ARRAY_REF. * decl.cc (get_tuple_element_type): Change i argument type from unsigned to unsigned HOST_WIDE_INT. (get_tuple_decomp_init): Likewise. (set_sb_pack_name): New function. (cp_finish_decomp): Handle structured binding packs. * pt.cc (tsubst_pack_expansion): Handle structured binding packs and capture proxies for them. Formatting fixes. (tsubst_decl): For structured binding packs don't tsubst TREE_TYPE first, instead recreate the type after r is created. (tsubst_omp_for_iterator): Also handle TREE_VEC as DECL_VALUE_EXPR instead of ARRAY_REF. (tsubst_expr): Handle sizeof... on non-dependent structure binding packs. (value_dependent_expression_p): Return false for sizeof... on non-dependent structure binding packs. (instantiation_dependent_r): Don't recurse on sizeof... on non-dependent structure binding packs. * constexpr.cc (potential_constant_expression_1): Also handle TREE_VEC on DECL_VALUE_EXPR of structure binding packs. gcc/testsuite/ * g++.dg/cpp26/decomp13.C: New test. * g++.dg/cpp26/decomp14.C: New test. * g++.dg/cpp26/decomp15.C: New test. * g++.dg/cpp26/decomp16.C: New test. * g++.dg/cpp26/decomp17.C: New test. * g++.dg/cpp26/decomp18.C: New test. * g++.dg/cpp26/decomp19.C: New test. * g++.dg/cpp26/decomp20.C: New test. * g++.dg/cpp26/decomp21.C: New test. * g++.dg/cpp26/feat-cxx26.C (__cpp_structured_bindings): Expect 202411 rather than 202403.
Implemented for 16+.
The master branch has been updated by Jakub Jelinek <jakub@gcc.gnu.org>: https://gcc.gnu.org/g:5274f490fa72830aafd278bc752145f1225b08e0 commit r16-3121-g5274f490fa72830aafd278bc752145f1225b08e0 Author: Jakub Jelinek <jakub@redhat.com> Date: Mon Aug 11 08:54:57 2025 +0200 c++: Implement mangling for structured binding packs [PR117783] On Wed, Aug 06, 2025 at 11:53:55AM -0700, Jason Merrill wrote: > The Clang mangling of the underlying variable seems fine, just mentioning > the bound names; we can't get mangling collisions between pack and non-pack > versions of the same name. > > But It looks like they use .N discriminators for the individual elements, > which is wrong because . is reserved for implementation details. But I'd > think it should be fine to use [<discriminator>] instead. If you want the whole structured bindings to be mangled normally as if the pack isn't a pack and the individual vars of the structured binding pack mangled as multiple occurrences of the named entities, the following patch does that. 2025-08-11 Jakub Jelinek <jakub@redhat.com> PR c++/117783 * decl.cc (cp_finish_decomp): Don't sorry on tuple static structured bindings with a pack, instead temporarily reset DECL_NAME of the individual vars in the pack to the name of the pack for cp_finish_decl time and force mangling. * g++.dg/cpp26/decomp19.C: Don't expect sorry on tuple static structured bindings with a pack. * g++.dg/cpp26/decomp26.C: New test.
The master branch has been updated by Jakub Jelinek <jakub@gcc.gnu.org>: https://gcc.gnu.org/g:b7e4b5e862fcb12cfeaa3bee4e8c77098201d5f4 commit r16-3122-gb7e4b5e862fcb12cfeaa3bee4e8c77098201d5f4 Author: Jakub Jelinek <jakub@redhat.com> Date: Mon Aug 11 09:02:38 2025 +0200 c++: Fix up handling of name independent structured binding packs [PR117783] I've realized I haven't added testsuite coverage for name independent structured binding packs. And the auto [i, ..._, j] = T {}; auto [k, ..._, l] = T {}; case shows a problem with that. The elements of the structured binding pack have #i appended to their names, so for the _ case e.g. _#0, _#1 etc. (to print something useful in diagnostics, perhaps debug info later on). The above is valid though as long as one doesn't use _ (which is ambiguous), but we were emitting errors on redeclaration of _#0, _#1 etc. The following patch uses DECL_NAME (decl) = NULL_TREE; for the name independent decl case so that the false positive redeclaration errors aren't emitted. 2025-08-11 Jakub Jelinek <jakub@redhat.com> PR c++/117783 * decl.cc (set_sb_pack_name): For name independent decls just clear DECL_NAME instead of appending #i to it. * g++.dg/cpp26/name-independent-decl11.C: New test.