On Thu, Mar 26, 2026 at 08:26:21PM +0100, Jakub Jelinek wrote: > The following patch implements the proposed resolution of > https://wg21.link/cwg3119 > Temporarily setting processing_template_decl around the > cp_parser_simple_declaration causes all kinds of ICEs and miscompilations, > this patch just sets in_expansion_stmt around it and allows the sb > pack in that case.
Reposting as no longer RFC PATCH. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2026-03-28 Jakub Jelinek <[email protected]> * parser.cc (cp_parser_expansion_statement): Temporarily set in_expansion_stmt to true around cp_parser_simple_declaration for range_decl. (cp_parser_decomposition_declaration): Don't reject structured binding packs if in_expansion_stmt is set. * g++.dg/cpp26/expansion-stmt34.C: New test. --- gcc/cp/parser.cc.jj 2026-03-23 11:26:45.807386878 +0100 +++ gcc/cp/parser.cc 2026-03-26 20:03:18.398967675 +0100 @@ -16601,6 +16601,8 @@ cp_parser_expansion_statement (cp_parser /* A colon is used in expansion-statement. */ parser->colon_corrects_to_scope_p = false; + in_expansion_stmt = true; + /* Parse the declaration. */ tree range_decl; cp_parser_simple_declaration (parser, @@ -16609,6 +16611,7 @@ cp_parser_expansion_statement (cp_parser if (range_decl == NULL_TREE) range_decl = error_mark_node; parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; + in_expansion_stmt = save_in_expansion_stmt; cp_parser_require (parser, CPP_COLON, RT_COLON); @@ -18249,7 +18252,7 @@ cp_parser_decomposition_declaration (cp_ if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS)) { location_t elloc = cp_lexer_peek_token (parser->lexer)->location; - if (!processing_template_decl) + if (!processing_template_decl && !in_expansion_stmt) error_at (elloc, "structured binding pack outside of template"); else if (pack != -1) error_at (elloc, --- gcc/testsuite/g++.dg/cpp26/expansion-stmt34.C.jj 2026-03-26 20:10:15.713887376 +0100 +++ gcc/testsuite/g++.dg/cpp26/expansion-stmt34.C 2026-03-26 20:15:42.434344130 +0100 @@ -0,0 +1,40 @@ +// CWG3119 - for-range-declaration of an expansion-statement as a templated +// entity. +// { dg-do run { target c++26 } } + +namespace std { + using size_t = decltype (sizeof 0); + template<typename T> struct tuple_size; + template<size_t, typename> struct tuple_element; +} +struct B { int a; long b; }; +struct C { char a; short b; int c; long d; long long e; float f; }; +struct E { char a; template <int I> char &get () { return a; } }; + +template <> struct std::tuple_size <E> { static const int value = 7; }; +template <std::size_t I> struct std::tuple_element <I, E> { using type = char; }; + +struct A +{ + B b; + C c; + int d[3]; + E e; +}; + +template <typename ...T> +int +foo (T... x) +{ + return sizeof... (x); +} + +int +main () +{ + int ret = 0; + template for (auto [...e] : A ()) + ret += foo (e...); + if (ret != 18) + __builtin_abort (); +} Jakub
