Go to file
Jakub Jelinek 458773ac7b c++: Implement C++26 P1306R5 - Expansion statements [PR120776]
The following patch implements the C++26 P1306R5 - Expansion statements
paper.
When expansion statements are used outside of templates, the lowering
of the statement uses push_tinst_level_loc and instantiates the body
multiple times, otherwise when the new TEMPLATE_FOR_STMT statement is
being instantiated and !processing_template_decl, it instantiates the
body several times with just local_specialization_stack around each
iteration but with the original args.
Because the lowering of these statements is mostly about instantiation,
I've put the lowering code into pt.cc rather than semantics.cc.
Only destructuring expansion statements currently use in the patch
temporary lifetime extension which matches the proposed resolution of
https://cplusplus.github.io/CWG/issues/3043.html
I'm not sure what will CWG decide about that if there will be some
temporary lifetime extension for enumerating expansion statements and if
yes, under what exact rules (e.g. whether it extends all the temporaries
across one iteration of the body, or only if a reference is initialized
or nothing at all).  And for iterating expansion statements, I think I
don't understand the P2686R4 rules well yet, I think if the
expansion-initializer is used in static constexpr rvalue reference, then
it isn't needed, but not sure if it won't be needed if static would be
dropped (whether
struct S { constexpr S () : s (0) {} constexpr ~S () {} int s; };
struct T { const S &t, &u; };
void foo () { constexpr T t = { S {}, S {} }; use (t.t, t.u); }
is ok under P2686R4; though without constexpr before T I see S::~S () being
called after use, not at the end of the t declaration, so maybe it is
fine also without static).
As per
https://cplusplus.github.io/CWG/issues/3044.html
the patch uses build_int_cst (ptrdiff_type_node, i) to create second
operand of begin + i and doesn't lookup overloaded comma operator (note, I'm
actually not even creating a lambda there, just using TARGET_EXPRs).
I guess my preference would be dropping those 4 static keywords from
[stmt.expand] but the patch does use those for now and it won't be possible
to change that until the rest of P2686R4 is implemented.
As per
https://cplusplus.github.io/CWG/issues/3045.html
it treats sk_template_for like sk_for for the purpose of redeclaration of
vars in the body but doesn't yet reject [[fallthrough]]; in the expansion
stmt body (when not nested in another switch).
I'm not sure if cp_perform_range_for_lookup used in the patch is exactly
what we want for the https://eel.is/c++draft/stmt.expand#3.2
- it does finish_call_expr on the perform_koenig_lookup as well, shouldn't
for the decision whether it is iterating or destructing (i.e. tf_none)
just call perform_koenig_lookup and check if it found some
FUNCTION_DECL/OVERLOAD/TEMPLATE_DECL?
cp_decomp_size in the patch has tsubst_flags_t argument and attempts to be
SFINAE friendly, even when it isn't needed strictly for this patch.
This is with PR96185 __builtin_structured_binding_size implementation in
mind (to follow clang).
The new TEMPLATE_FOR_STMT statement is expected to be lowered to something
that doesn't use the statement at all, I've implemented break/continue
discovery in the body, so all I needed was to punt on TEMPLATE_FOR_STMT
in potential_constant_expression_1 so that we don't try to constant evaluate
it when it is still dependent (and cxx_eval_constant_expression rejects
it without any extra code).
I think only enumerating and iterating expansion statements can have zero
iteration, because for destructuring ones it doesn't use a structured
binding pack and so valid structured binding has to have at least one
iteration.  Though
https://cplusplus.github.io/CWG/issues/3048.html
could change that, this patch currently rejects it though.

2025-08-13  Jakub Jelinek  <jakub@redhat.com>

	PR c++/120776
gcc/c-family/
	* c-cppbuiltin.cc (c_cpp_builtins): Predefine
	__cpp_expansion_statements=202506L for C++26.
gcc/cp/
	* cp-tree.def: Implement C++26 P1306R5 - Expansion statements.
	(TEMPLATE_FOR_STMT): New tree code.
	* cp-tree.h (struct saved_scope): Add expansion_stmt.
	(in_expansion_stmt): Define.
	(TEMPLATE_FOR_DECL, TEMPLATE_FOR_EXPR, TEMPLATE_FOR_BODY,
	TEMPLATE_FOR_SCOPE, TEMPLATE_FOR_INIT_STMT): Define.
	(struct tinst_level): Adjust comment.
	(cp_decomp_size, finish_expansion_stmt, do_pushlevel,
	cp_build_range_for_decls, build_range_temp,
	cp_perform_range_for_lookup, begin_template_for_scope): Declare.
	(finish_range_for_stmt): Remove declaration.
	* cp-objcp-common.cc (cp_common_init_ts): Handle TEMPLATE_FOR_STMT.
	* name-lookup.h (enum scope_kind): Add sk_template_for enumerator.
	(struct cp_binding_level): Enlarge kind bitfield from 4 to 5 bits.
	Adjust comment with remaining space bits.
	* name-lookup.cc (check_local_shadow): Handle sk_template_for like
	sk_for.
	(cp_binding_level_descriptor): Add entry for sk_template_for.
	(begin_scope): Handle sk_template_for.
	* parser.h (IN_EXPANSION_STMT): Define.
	* parser.cc (cp_debug_parser): Print IN_EXPANSION_STMT bit.
	(cp_parser_lambda_expression): Temporarily clear in_expansion_stmt.
	(cp_parser_statement): Handle RID_TEMPLATE followed by RID_FOR for
	C++11.
	(cp_parser_label_for_labeled_statement): Complain about named labels
	inside of expansion stmt body.
	(cp_hide_range_decl): New function.
	(cp_parser_range_for): Use it.  Adjust do_range_for_auto_deduction
	caller.  Remove second template argument from auto_vecs bindings and
	names.
	(build_range_temp): No longer static.
	(do_range_for_auto_deduction): Add expansion_stmt argument.
	(cp_build_range_for_decls): New function.
	(cp_convert_range_for): Use it.  Call cp_perform_range_for_lookup
	rather than cp_parser_perform_range_for_lookup.
	(cp_parser_perform_range_for_lookup): Rename to ...
	(cp_perform_range_for_lookup): ... this.  No longer static.  Add
	complain argument and handle it.
	(cp_parser_range_for_member_function): Rename to ...
	(cp_range_for_member_function): ... this.
	(cp_parser_expansion_statement): New function.
	(cp_parser_jump_statement): Handle IN_EXPANSION_STMT.
	(cp_convert_omp_range_for): Adjust do_range_for_auto_deduction caller.
	Call cp_perform_range_for_lookup rather than
	cp_parser_perform_range_for_lookup.
	* error.cc (print_instantiation_full_context): Handle tldcl being
	TEMPLATE_FOR_STMT.
	(print_instantiation_partial_context_line): Likewise.
	* constexpr.cc (potential_constant_expression_1): Handle
	TEMPLATE_FOR_STMT.
	* decl.cc (poplevel_named_label_1): Use obl instead of bl->level_chain.
	(finish_case_label): Diagnose case labels inside of template for.
	(find_decomp_class_base): Add complain argument, don't diagnose
	anything and just return error_mark_node if tf_none, adjust recursive
	call.
	(cp_decomp_size): New function.
	(cp_finish_decomp): Adjust find_decomp_class_base caller.
	* semantics.cc (do_pushlevel): No longer static.
	(begin_template_for_scope): New function.
	* pt.cc (push_tinst_level_loc): Handle TEMPLATE_FOR_STMT.
	(reopen_tinst_level): Likewise.
	(tsubst_stmt): Handle TEMPLATE_FOR_STMT.
	(struct expansion_stmt_bc): New type.
	(expansion_stmt_find_bc_r, finish_expansion_stmt): New functions.
	* decl2.cc (decl_dependent_p): Return true for current function's decl
	if in_expansion_stmt.
	* call.cc (extend_ref_init_temps): Don't extend_all_temps if
	TREE_STATIC (decl).
	* cxx-pretty-print.cc (cxx_pretty_printer::statement): Handle
	TEMPLATE_FOR_STMT.
gcc/testsuite/
	* g++.dg/cpp1z/decomp64.C: New test.
	* g++.dg/cpp26/expansion-stmt1.C: New test.
	* g++.dg/cpp26/expansion-stmt2.C: New test.
	* g++.dg/cpp26/expansion-stmt3.C: New test.
	* g++.dg/cpp26/expansion-stmt4.C: New test.
	* g++.dg/cpp26/expansion-stmt5.C: New test.
	* g++.dg/cpp26/expansion-stmt6.C: New test.
	* g++.dg/cpp26/expansion-stmt7.C: New test.
	* g++.dg/cpp26/expansion-stmt8.C: New test.
	* g++.dg/cpp26/expansion-stmt9.C: New test.
	* g++.dg/cpp26/expansion-stmt10.C: New test.
	* g++.dg/cpp26/expansion-stmt11.C: New test.
	* g++.dg/cpp26/expansion-stmt12.C: New test.
	* g++.dg/cpp26/expansion-stmt13.C: New test.
	* g++.dg/cpp26/expansion-stmt14.C: New test.
	* g++.dg/cpp26/expansion-stmt15.C: New test.
	* g++.dg/cpp26/expansion-stmt16.C: New test.
	* g++.dg/cpp26/expansion-stmt17.C: New test.
	* g++.dg/cpp26/expansion-stmt18.C: New test.
	* g++.dg/cpp26/expansion-stmt19.C: New test.
	* g++.dg/cpp26/feat-cxx26.C: Add __cpp_expansion_statements
	tests.
2025-08-13 22:10:18 +02:00
.forgejo top-level: Add pull request template for Forgejo 2024-10-23 19:45:09 +01:00
.github
INSTALL
c++tools Daily bump. 2025-06-03 00:18:06 +00:00
config Daily bump. 2025-08-11 00:16:52 +00:00
contrib Daily bump. 2025-08-08 00:18:50 +00:00
fixincludes Daily bump. 2024-07-12 00:17:52 +00:00
gcc c++: Implement C++26 P1306R5 - Expansion statements [PR120776] 2025-08-13 22:10:18 +02:00
gnattools Daily bump. 2025-06-23 00:16:33 +00:00
gotools
include Daily bump. 2025-07-10 00:20:18 +00:00
libada Update copyright years. 2025-01-02 11:59:57 +01:00
libatomic Daily bump. 2025-08-01 00:20:20 +00:00
libbacktrace Daily bump. 2025-04-11 00:17:32 +00:00
libcc1 Daily bump. 2025-07-26 00:19:51 +00:00
libcody Update Copyright year in ChangeLog files 2025-01-02 11:13:18 +01:00
libcpp Daily bump. 2025-08-11 00:16:52 +00:00
libdecnumber Update copyright years. 2025-01-02 11:59:57 +01:00
libffi Daily bump. 2024-10-26 00:19:39 +00:00
libgcc LoongArch: Add support for _BitInt [PR117599] 2025-08-13 11:01:55 +08:00
libgcobol Regenerate libgcobol/configure 2025-08-13 17:53:27 +02:00
libgfortran Daily bump. 2025-08-07 00:20:46 +00:00
libgm2 Daily bump. 2025-07-24 00:20:56 +00:00
libgo runtime: avoid libc memmove and memclr 2025-07-08 15:49:16 -07:00
libgomp Daily bump. 2025-08-07 00:20:46 +00:00
libgrust Daily bump. 2025-08-06 00:21:26 +00:00
libiberty Daily bump. 2025-08-07 00:20:46 +00:00
libitm Daily bump. 2025-05-10 00:17:59 +00:00
libobjc Update copyright years. 2025-01-02 11:59:57 +01:00
libphobos Daily bump. 2025-07-02 00:19:39 +00:00
libquadmath Daily bump. 2025-04-10 00:18:06 +00:00
libsanitizer [sanitizer_common] Remove reference to obsolete termio ioctls (#138822) 2025-07-30 23:29:52 +01:00
libssp Update copyright years. 2025-01-02 11:59:57 +01:00
libstdc++-v3 Daily bump. 2025-08-11 00:16:52 +00:00
libvtv Daily bump. 2025-05-10 00:17:59 +00:00
lto-plugin Daily bump. 2025-03-07 00:17:19 +00:00
maintainer-scripts Daily bump. 2025-07-05 00:19:48 +00:00
zlib Daily bump. 2025-08-01 00:20:20 +00:00
.b4-config Add config file so b4 uses inbox.sourceware.org automatically 2024-07-28 11:13:16 +01:00
.dir-locals.el dir-locals: apply our C settings in C++ also 2024-07-31 20:38:27 +02:00
.gitattributes
.gitignore Rust: Move 'libformat_parser' build into the GCC build directory 2025-08-05 16:36:43 +02:00
ABOUT-NLS
COPYING
COPYING.LIB
COPYING.RUNTIME
COPYING3
COPYING3.LIB
ChangeLog Daily bump. 2025-08-09 00:19:57 +00:00
ChangeLog.jit
ChangeLog.tree-ssa
MAINTAINERS Update my maintainer entry email 2025-08-08 17:37:08 +00:00
Makefile.def [AUTOFDO] Fix autogen remake issue 2025-05-29 08:47:19 +10:00
Makefile.in Ada: Introduce GNATMAKE_FOR_BUILD Makefile variable 2025-06-23 00:11:19 +02:00
Makefile.tpl Ada: Introduce GNATMAKE_FOR_BUILD Makefile variable 2025-06-23 00:11:19 +02:00
README
SECURITY.txt Remove Debian from SECURITY.txt 2024-11-19 12:27:33 +01:00
ar-lib
compile
config-ml.in Remove extra argument from subst macro 2025-03-13 07:26:04 +01:00
config.guess
config.rpath
config.sub
configure Ada: Introduce GNATMAKE_FOR_BUILD Makefile variable 2025-06-23 00:11:19 +02:00
configure.ac Ada: Introduce GNATMAKE_FOR_BUILD Makefile variable 2025-06-23 00:11:19 +02:00
depcomp
install-sh
libtool-ldflags
libtool.m4
ltgcc.m4
ltmain.sh ltmain.sh: allow more flags at link-time 2024-09-25 19:05:24 +01:00
ltoptions.m4
ltsugar.m4
ltversion.m4
lt~obsolete.m4
missing
mkdep
mkinstalldirs
move-if-change
multilib.am
symlink-tree
test-driver
ylwrap

README

This directory contains the GNU Compiler Collection (GCC).

The GNU Compiler Collection is free software.  See the files whose
names start with COPYING for copying permission.  The manuals, and
some of the runtime libraries, are under different terms; see the
individual source files for details.

The directory INSTALL contains copies of the installation information
as HTML and plain text.  The source of this information is
gcc/doc/install.texi.  The installation information includes details
of what is included in the GCC sources and what files GCC installs.

See the file gcc/doc/gcc.texi (together with other files that it
includes) for usage and porting information.  An online readable
version of the manual is in the files gcc/doc/gcc.info*.

See http://gcc.gnu.org/bugs/ for how to report bugs usefully.

Copyright years on GCC source files may be listed using range
notation, e.g., 1987-2012, indicating that every year in the range,
inclusive, is a copyrightable year that could otherwise be listed
individually.