aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MAINTAINERS1
-rwxr-xr-xcontrib/download_prerequisites6
-rw-r--r--contrib/prerequisites.md56
-rw-r--r--contrib/prerequisites.sha5126
-rw-r--r--gcc/ChangeLog220
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/Makefile.in2
-rw-r--r--gcc/c-family/ChangeLog6
-rw-r--r--gcc/c-family/c-attribs.cc19
-rw-r--r--gcc/c-family/c-common.h2
-rw-r--r--gcc/c-family/c-cppbuiltin.cc2
-rw-r--r--gcc/c-family/c-opts.cc9
-rw-r--r--gcc/c-family/c.opt4
-rw-r--r--gcc/c-family/c.opt.urls3
-rw-r--r--gcc/c/ChangeLog42
-rw-r--r--gcc/c/c-decl.cc23
-rw-r--r--gcc/c/c-tree.h3
-rw-r--r--gcc/c/c-typeck.cc205
-rw-r--r--gcc/config/aarch64/aarch64.cc37
-rw-r--r--gcc/config/i386/i386.h34
-rw-r--r--gcc/config/i386/i386.md14
-rw-r--r--gcc/config/i386/predicates.md6
-rw-r--r--gcc/config/s390/s390.cc37
-rwxr-xr-xgcc/configure44
-rw-r--r--gcc/configure.ac29
-rw-r--r--gcc/cp/ChangeLog25
-rw-r--r--gcc/cp/constexpr.cc8
-rw-r--r--gcc/cp/decl.cc241
-rw-r--r--gcc/cp/lex.cc60
-rw-r--r--gcc/cp/parser.cc81
-rw-r--r--gcc/cp/pt.cc117
-rw-r--r--gcc/d/ChangeLog4
-rw-r--r--gcc/d/Make-lang.in2
-rw-r--r--gcc/doc/install.texi2
-rw-r--r--gcc/doc/invoke.texi9
-rw-r--r--gcc/simplify-rtx.cc12
-rw-r--r--gcc/testsuite/ChangeLog109
-rw-r--r--gcc/testsuite/g++.dg/DRs/dr2575.C51
-rw-r--r--gcc/testsuite/g++.dg/DRs/dr2576.C47
-rw-r--r--gcc/testsuite/g++.dg/DRs/dr2577-1.C40
-rw-r--r--gcc/testsuite/g++.dg/DRs/dr2577-2.C13
-rw-r--r--gcc/testsuite/g++.dg/DRs/dr2577-2.h1
-rw-r--r--gcc/testsuite/g++.dg/DRs/dr2577-3.C7
-rw-r--r--gcc/testsuite/g++.dg/DRs/dr2577-3.h1
-rw-r--r--gcc/testsuite/g++.dg/cpp26/constexpr-new3.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp26/decomp13.C52
-rw-r--r--gcc/testsuite/g++.dg/cpp26/decomp14.C474
-rw-r--r--gcc/testsuite/g++.dg/cpp26/decomp15.C474
-rw-r--r--gcc/testsuite/g++.dg/cpp26/decomp16.C240
-rw-r--r--gcc/testsuite/g++.dg/cpp26/decomp17.C28
-rw-r--r--gcc/testsuite/g++.dg/cpp26/decomp18.C109
-rw-r--r--gcc/testsuite/g++.dg/cpp26/decomp19.C46
-rw-r--r--gcc/testsuite/g++.dg/cpp26/decomp20.C53
-rw-r--r--gcc/testsuite/g++.dg/cpp26/decomp21.C103
-rw-r--r--gcc/testsuite/g++.dg/cpp26/feat-cxx26.C4
-rw-r--r--gcc/testsuite/g++.dg/modules/atom-preamble-3.C2
-rw-r--r--gcc/testsuite/g++.dg/opt/pr82577.C8
-rw-r--r--gcc/testsuite/g++.dg/template/sfinae17.C6
-rw-r--r--gcc/testsuite/g++.dg/warn/Wkeyword-macro-1.C112
-rw-r--r--gcc/testsuite/g++.dg/warn/Wkeyword-macro-10.C23
-rw-r--r--gcc/testsuite/g++.dg/warn/Wkeyword-macro-2.C112
-rw-r--r--gcc/testsuite/g++.dg/warn/Wkeyword-macro-3.C7
-rw-r--r--gcc/testsuite/g++.dg/warn/Wkeyword-macro-4.C112
-rw-r--r--gcc/testsuite/g++.dg/warn/Wkeyword-macro-5.C112
-rw-r--r--gcc/testsuite/g++.dg/warn/Wkeyword-macro-6.C7
-rw-r--r--gcc/testsuite/g++.dg/warn/Wkeyword-macro-7.C112
-rw-r--r--gcc/testsuite/g++.dg/warn/Wkeyword-macro-8.C112
-rw-r--r--gcc/testsuite/g++.dg/warn/Wkeyword-macro-9.C22
-rw-r--r--gcc/testsuite/gcc.dg/Wkeyword-macro-1.c62
-rw-r--r--gcc/testsuite/gcc.dg/Wkeyword-macro-2.c4
-rw-r--r--gcc/testsuite/gcc.dg/Wkeyword-macro-3.c62
-rw-r--r--gcc/testsuite/gcc.dg/Wkeyword-macro-4.c4
-rw-r--r--gcc/testsuite/gcc.dg/Wkeyword-macro-5.c47
-rw-r--r--gcc/testsuite/gcc.dg/Wkeyword-macro-6.c4
-rw-r--r--gcc/testsuite/gcc.dg/Wkeyword-macro-7.c47
-rw-r--r--gcc/testsuite/gcc.dg/Wkeyword-macro-8.c4
-rw-r--r--gcc/testsuite/gcc.dg/Wkeyword-macro-9.c15
-rw-r--r--gcc/testsuite/gcc.dg/torture/hardbool-ai.c7
-rw-r--r--gcc/testsuite/gcc.dg/torture/hardbool-vi.c5
-rw-r--r--gcc/testsuite/gcc.dg/torture/hardbool.c68
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-107.c29
-rw-r--r--gcc/testsuite/gcc.dg/vla-tert-1.c293
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sme/pr121414_1.c27
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr120718.c12
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/peel_ind_11.c20
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/peel_ind_11_run.c27
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/peel_ind_12.c21
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/peel_ind_12_run.c29
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/peel_ind_13.c24
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/peel_ind_13_run.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/pr90579.c7
-rw-r--r--gcc/testsuite/gcc.target/s390/bitint-1.c83
-rw-r--r--gcc/testsuite/gcc.target/s390/bitint-2.c32
-rw-r--r--gcc/testsuite/gcc.target/s390/bitint-3.c28
-rw-r--r--gcc/testsuite/gcc.target/s390/bitint-4.c71
-rw-r--r--gcc/tree-ssa-sccvn.cc22
-rw-r--r--gcc/tree-vect-data-refs.cc61
-rw-r--r--gcc/tree-vect-loop-manip.cc71
-rw-r--r--gcc/tree-vect-loop.cc8
-rw-r--r--gcc/tree-vect-stmts.cc103
-rw-r--r--gcc/tree-vectorizer.h9
-rw-r--r--libcpp/directives.cc21
-rw-r--r--libcpp/include/cpplib.h17
-rw-r--r--libcpp/macro.cc33
-rw-r--r--libgcc/ChangeLog6
-rw-r--r--libgcc/config.host2
-rw-r--r--libgcc/config/s390/libgcc-glibc.ver14
-rw-r--r--libgcc/config/s390/sfp-exceptions.c61
-rw-r--r--libgcc/config/s390/sfp-machine.h89
-rw-r--r--libgcc/config/s390/t-softfp2
-rw-r--r--libgfortran/ChangeLog7
-rw-r--r--libgomp/ChangeLog20
-rw-r--r--libiberty/ChangeLog5
-rw-r--r--libiberty/testsuite/test-doubly-linked-list.c13
-rw-r--r--libstdc++-v3/doc/html/manual/appendix_porting.html2
-rw-r--r--libstdc++-v3/doc/xml/manual/build_hacking.xml2
116 files changed, 5173 insertions, 366 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 6148ce0..bc607cb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -628,6 +628,7 @@ James Lemke jwlemke <jim@lemke.org>
Ilya Leoshkevich iii <iii@linux.ibm.com>
Kriang Lerdsuwanakij lerdsuwa <lerdsuwa@users.sourceforge.net>
Pan Li - <pan2.li@intel.com>
+Pengfei Li pfustc <pengfei.li2@arm.com>
Renlin Li renlin <renlin.li@arm.com>
Xinliang David Li davidxl <davidxl@google.com>
Kewen Lin linkw <linkw@gcc.gnu.org>
diff --git a/contrib/download_prerequisites b/contrib/download_prerequisites
index b83fcc9..a6d756c 100755
--- a/contrib/download_prerequisites
+++ b/contrib/download_prerequisites
@@ -27,9 +27,9 @@ version='(unversioned)'
# remember to also update the files `contrib/prerequisites.sha512` and
# `contrib/prerequisites.md5` with the new checksums.
-gmp='gmp-6.2.1.tar.bz2'
-mpfr='mpfr-4.1.0.tar.bz2'
-mpc='mpc-1.2.1.tar.gz'
+gmp='gmp-6.3.0.tar.bz2'
+mpfr='mpfr-4.2.2.tar.bz2'
+mpc='mpc-1.3.1.tar.gz'
isl='isl-0.24.tar.bz2'
gettext='gettext-0.22.tar.gz'
diff --git a/contrib/prerequisites.md5 b/contrib/prerequisites.md5
index 716a9ff..96b9802 100644
--- a/contrib/prerequisites.md5
+++ b/contrib/prerequisites.md5
@@ -1,5 +1,5 @@
-28971fc21cf028042d4897f02fd355ea gmp-6.2.1.tar.bz2
-44b892bc5a45bafb4294d134e13aad1d mpfr-4.1.0.tar.bz2
-9f16c976c25bb0f76b50be749cd7a3a8 mpc-1.2.1.tar.gz
+c1cd6ef33085e9cb818b9b08371f9000 gmp-6.3.0.tar.bz2
+afe8268360bc8702fbc8297d351c8b5e mpfr-4.2.2.tar.bz2
+5c9bc658c9fd0f940e8e3e0f09530c62 mpc-1.3.1.tar.gz
dd2f7b78e118c25bd96134a52aae7f4d isl-0.24.tar.bz2
c092102240f8f66134d22718421d5115 gettext-0.22.tar.gz
diff --git a/contrib/prerequisites.sha512 b/contrib/prerequisites.sha512
index f71398b..7a3e9c2 100644
--- a/contrib/prerequisites.sha512
+++ b/contrib/prerequisites.sha512
@@ -1,5 +1,5 @@
-8904334a3bcc5c896ececabc75cda9dec642e401fb5397c4992c4fabea5e962c9ce8bd44e8e4233c34e55c8010cc28db0545f5f750cbdbb5f00af538dc763be9 gmp-6.2.1.tar.bz2
-410208ee0d48474c1c10d3d4a59decd2dfa187064183b09358ec4c4666e34d74383128436b404123b831e585d81a9176b24c7ced9d913967c5fce35d4040a0b4 mpfr-4.1.0.tar.bz2
-3279f813ab37f47fdcc800e4ac5f306417d07f539593ca715876e43e04896e1d5bceccfb288ef2908a3f24b760747d0dbd0392a24b9b341bc3e12082e5c836ee mpc-1.2.1.tar.gz
+3b684c9bcb9ede2b7e54d0ba4c9764bfa17c20d4f3000017c553b6f1e135b536949580ff37341680c25dc236cfe0ba1db8cfdfe619ce013656189ef0871b89f8 gmp-6.3.0.tar.bz2
+0176e50808dcc07afbf5bc3e38bf9b7b21918e5f194aa0bfd860d99b00c470630aef149776c4be814a61c44269c3a5b9a4b0b1c0fcd4c9feb1459d8466452da8 mpfr-4.2.2.tar.bz2
+4bab4ef6076f8c5dfdc99d810b51108ced61ea2942ba0c1c932d624360a5473df20d32b300fc76f2ba4aa2a97e1f275c9fd494a1ba9f07c4cb2ad7ceaeb1ae97 mpc-1.3.1.tar.gz
aab3bddbda96b801d0f56d2869f943157aad52a6f6e6a61745edd740234c635c38231af20bc3f1a08d416a5e973a90e18249078ed8e4ae2f1d5de57658738e95 isl-0.24.tar.bz2
e2a58dde1cae3e6b79c03e7ef3d888f7577c1f4cba283b3b0f31123ceea8c33d7c9700e83de57104644de23e5f5c374868caa0e091f9c45edbbe87b98ee51c04 gettext-0.22.tar.gz
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index d975768..b600551 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,223 @@
+2025-08-06 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/96226
+ * config/i386/predicates.md (and_operator): New operator.
+ * config/i386/i386.md (splitter after *<rotate_insn><mode>3_mask):
+ Use and_operator to match AND RTX and use its mode
+ in the split pattern.
+
+2025-08-06 Gerald Pfeifer <gerald@pfeifer.com>
+
+ PR target/69374
+ * doc/install.texi (Prerequisites): Replace bzip2 by xz.
+
+2025-08-06 Yangyu Chen <cyy@cyyself.name>
+
+ * config/i386/i386.h (PTA_BDVER1):
+ Add missing PTA_POPCNT and PTA_LZCNT with PTA_ABM.
+ (PTA_ZNVER1): Ditto.
+ (PTA_BTVER1): Ditto.
+ (PTA_LUJIAZUI): Ditto.
+ (PTA_YONGFENG): Do not include extra PTA_LZCNT.
+
+2025-08-06 Sam James <sam@gentoo.org>
+
+ PR libstdc++/29286
+ * Makefile.in (ALIASING_FLAGS): Drop.
+ * configure: Regenerate.
+ * configure.ac: Drop -fno-strict-aliasing workaround for < GCC 4.3.
+
+2025-08-06 Richard Biener <rguenther@suse.de>
+
+ * tree-vect-data-refs.cc (vect_supportable_dr_alignment):
+ Prune dead code.
+
+2025-08-06 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/121231
+ PR c++/119688
+ PR c++/94511
+ * common.opt: Document additional ABI version 21 change.
+ * doc/invoke.texi: Likewise.
+
+2025-08-06 Richard Biener <rguenther@suse.de>
+
+ * tree-vectorizer.h (_slp_tree::gs_scale): New.
+ (_slp_tree::gs_base): Likewise.
+ (SLP_TREE_GS_SCALE): Likewise.
+ (SLP_TREE_GS_BASE): Likewise.
+ (vect_describe_gather_scatter_call): Declare.
+ * tree-vect-slp.cc (_slp_tree::_slp_tree): Initialize
+ new members.
+ (vect_build_slp_tree_2): Record gather/scatter base and scale.
+ (vect_get_and_check_slp_defs): For gather/scatter IFNs
+ describe the call to first_gs_info.
+ * tree-vect-data-refs.cc (vect_gather_scatter_fn_p): Add
+ mode of operation with fixed offset vector type.
+ (vect_describe_gather_scatter_call): Export.
+ * tree-vect-stmts.cc (get_load_store_type): Do not call
+ vect_check_gather_scatter to fill gs_info, instead populate
+ from the SLP tree. Check which of, IFN, decl or fallback
+ is supported and record that decision.
+
+2025-08-06 Richard Biener <rguenther@suse.de>
+
+ * tree-vect-stmts.cc (vectorizable_store): Build proper
+ alias + align pointer value for gather/scatter and SLP
+ and use it.
+ (vectorizable_load): Likewise.
+
+2025-08-06 Richard Biener <rguenther@suse.de>
+
+ * tree-vect-stmts.cc (check_load_store_for_partial_vectors):
+ Remove redundant gather/scatter target support check, instead
+ check the recorded ifns. Also allow legacy gather/scatter
+ with loop masking.
+
+2025-08-06 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/121413
+ * gimple-lower-bitint.cc (gimple_lower_bitint): Fix up last
+ commit, cast limb_prec to unsigned before comparison.
+
+2025-08-06 Yang Yujie <yangyujie@loongson.cn>
+
+ * match.pd: Preserve conversion to _BitInt before a VCE
+ if the _BitInt is extended.
+
+2025-08-06 Yang Yujie <yangyujie@loongson.cn>
+
+ * gimple-lower-bitint.cc (bitint_large_huge::lower_mergeable_stmt):
+ Zero-extend the partial limb of any unsigned _BitInt LHS assigned
+ with a widening sign-extension.
+
+2025-08-06 Yang Yujie <yangyujie@loongson.cn>
+
+ * gimple-lower-bitint.cc (bitint_large_huge::limb_access):
+ Add a parameter abi_load_p. If set, load a limb directly
+ in its actual precision without casting from m_limb_type.
+ (struct bitint_large_huge): Same.
+ (bitint_large_huge::handle_load): Use.
+
+2025-08-06 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/121413
+ * gimple-lower-bitint.cc (abi_limb_prec): New variable
+ (bitint_precision_kind): Initialize it.
+ (gimple_lower_bitint): Clear it at the start. For
+ min_prec > limb_prec descreased precision vars for
+ INTEGER_CST PHI arguments ensure min_prec is either
+ prec or multiple of abi_limb_prec.
+
+2025-08-06 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/121127
+ * gimple-lower-bitint.cc (bitint_large_huge::handle_operand_addr): For
+ uninitialized SSA_NAME, set *prec_stored to 0 rather than *prec.
+ Handle that case in narrowing casts. If prec_stored is non-NULL,
+ set *prec_stored to prec_stored_val.
+
+2025-08-06 Jakub Jelinek <jakub@redhat.com>
+
+ PR bootstrap/121386
+ * Makefile.in (gengtype-lex.cc): Append #define FLEX_SCANNER,
+ #include "system.h" and #undef FLEX_SCANNER to the prepended lines.
+ * gengtype-lex.l: Remove inclusion of config.h or bconfig.h, system.h
+ and definition of malloc/realloc from %{} section.
+
+2025-08-06 Kito Cheng <kito.cheng@sifive.com>
+
+ * config/riscv/arch-canonicalize: Read extension data from
+ riscv-ext*.def and adding unittest.
+
+2025-08-06 Kito Cheng <kito.cheng@sifive.com>
+
+ * common/config/riscv/riscv-common.cc (riscv_expand_arch):
+ Ignore `unset`.
+ * config/riscv/riscv.h (OPTION_DEFAULT_SPECS): Handle
+ `-march=unset`.
+ (ARCH_UNSET_CLEANUP_SPECS): New.
+ (DRIVER_SELF_SPECS): Handle -march=unset.
+ * doc/invoke.texi (RISC-V Options): Update documentation for
+ `-march=unset`.
+
+2025-08-06 Kwok Cheung Yeung <kcyeung@baylibre.com>
+
+ * gimplify.cc (remove_unused_omp_iterator_vars): Display unused
+ variable warning for 'to' and 'from' clauses.
+ (gimplify_scan_omp_clauses): Add argument for iterator loop sequence.
+ Gimplify the clause decl and size into the iterator loop if iterators
+ are used.
+ (gimplify_omp_workshare): Add argument for iterator loops sequence
+ in call to gimplify_scan_omp_clauses.
+ (gimplify_omp_target_update): Call remove_unused_omp_iterator_vars and
+ build_omp_iterators_loops. Add loop sequence as argument when calling
+ gimplify_scan_omp_clauses, gimplify_adjust_omp_clauses and building
+ the Gimple statement.
+ * tree-pretty-print.cc (dump_omp_clause): Call dump_omp_iterators
+ for to/from clauses with iterators.
+ * tree.cc (omp_clause_num_ops): Add extra operand for OMP_CLAUSE_FROM
+ and OMP_CLAUSE_TO.
+ * tree.h (OMP_CLAUSE_HAS_ITERATORS): Add check for OMP_CLAUSE_TO and
+ OMP_CLAUSE_FROM.
+ (OMP_CLAUSE_ITERATORS): Likewise.
+
+2025-08-06 Kwok Cheung Yeung <kcyeung@baylibre.com>
+ Andrew Stubbs <ams@baylibre.com>
+
+ * gimple-pretty-print.cc (dump_gimple_omp_target): Print expanded
+ iterator loops.
+ * gimple.cc (gimple_build_omp_target): Add argument for iterator
+ loops sequence. Initialize iterator loops field.
+ * gimple.def (GIMPLE_OMP_TARGET): Set GSS symbol to GSS_OMP_TARGET.
+ * gimple.h (gomp_target): Set GSS symbol to GSS_OMP_TARGET. Add extra
+ field for iterator loops.
+ (gimple_build_omp_target): Add argument for iterator loops sequence.
+ (gimple_omp_target_iterator_loops): New.
+ (gimple_omp_target_iterator_loops_ptr): New.
+ (gimple_omp_target_set_iterator_loops): New.
+ * gimplify.cc (find_var_decl): New.
+ (copy_omp_iterator): New.
+ (remap_omp_iterator_var_1): New.
+ (remap_omp_iterator_var): New.
+ (remove_unused_omp_iterator_vars): New.
+ (struct iterator_loop_info_t): New type.
+ (iterator_loop_info_map_t): New type.
+ (build_omp_iterators_loops): New.
+ (enter_omp_iterator_loop_context_1): New.
+ (enter_omp_iterator_loop_context): New.
+ (enter_omp_iterator_loop_context): New.
+ (exit_omp_iterator_loop_context): New.
+ (gimplify_adjust_omp_clauses): Add argument for iterator loop
+ sequence. Gimplify the clause decl and size into the iterator
+ loop if iterators are used.
+ (gimplify_omp_workshare): Call remove_unused_omp_iterator_vars and
+ build_omp_iterators_loops for OpenMP target expressions. Add
+ loop sequence as argument when calling gimplify_adjust_omp_clauses
+ and building the Gimple statement.
+ * gimplify.h (enter_omp_iterator_loop_context): New prototype.
+ (exit_omp_iterator_loop_context): New prototype.
+ * gsstruct.def (GSS_OMP_TARGET): New.
+ * omp-low.cc (lower_omp_map_iterator_expr): New.
+ (lower_omp_map_iterator_size): New.
+ (finish_omp_map_iterators): New.
+ (lower_omp_target): Add sorry if iterators used with deep mapping.
+ Call lower_omp_map_iterator_expr before assigning to sender ref.
+ Call lower_omp_map_iterator_size before setting the size. Insert
+ iterator loop sequence before the statements for the target clause.
+ * tree-nested.cc (convert_nonlocal_reference_stmt): Walk the iterator
+ loop sequence of OpenMP target statements.
+ (convert_local_reference_stmt): Likewise.
+ (convert_tramp_reference_stmt): Likewise.
+ * tree-pretty-print.cc (dump_omp_iterators): Dump extra iterator
+ information if present.
+ (dump_omp_clause): Call dump_omp_iterators for iterators in map
+ clauses.
+ * tree.cc (omp_clause_num_ops): Add operand for OMP_CLAUSE_MAP.
+ (walk_tree_1): Do not walk last operand of OMP_CLAUSE_MAP.
+ * tree.h (OMP_CLAUSE_HAS_ITERATORS): New.
+ (OMP_CLAUSE_ITERATORS): New.
+
2025-08-05 H.J. Lu <hjl.tools@gmail.com>
PR target/121410
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index cf43af9..d4024d7 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20250806
+20250807
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 3406517..cc79595 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -187,8 +187,6 @@ C_STRICT_WARN = @c_strict_warn@
NOEXCEPTION_FLAGS = @noexception_flags@
-ALIASING_FLAGS = @aliasing_flags@
-
# This is set by --disable-maintainer-mode (default) to "#"
# FIXME: 'MAINT' will always be set to an empty string, no matter if
# --disable-maintainer-mode is used or not. This is because the
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index c9ab153..2abe6df 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,9 @@
+2025-08-06 Alexandre Oliva <oliva@adacore.com>
+
+ * c-attribs.cc (handle_hardbool_attribute): Create distinct
+ enumeration types, with structural equality. Handle
+ base type qualifiers.
+
2025-08-02 Martin Uecker <uecker@tugraz.at>
* c-attribs.cc (handle_argspec_attribute): Update.
diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc
index a0d832b..041a004 100644
--- a/gcc/c-family/c-attribs.cc
+++ b/gcc/c-family/c-attribs.cc
@@ -1128,11 +1128,16 @@ handle_hardbool_attribute (tree *node, tree name, tree args,
}
tree orig = *node;
- *node = build_duplicate_type (orig);
+ /* Drop qualifiers from the base type. Keep attributes, so that, in the odd
+ chance attributes are applicable and relevant to the base type, if they
+ are specified first, or through a typedef, they wouldn't be dropped on the
+ floor here. */
+ tree unqual = build_qualified_type (orig, TYPE_UNQUALIFIED);
+ *node = build_distinct_type_copy (unqual);
TREE_SET_CODE (*node, ENUMERAL_TYPE);
- ENUM_UNDERLYING_TYPE (*node) = orig;
- TYPE_CANONICAL (*node) = TYPE_CANONICAL (orig);
+ ENUM_UNDERLYING_TYPE (*node) = unqual;
+ SET_TYPE_STRUCTURAL_EQUALITY (*node);
tree false_value;
if (args)
@@ -1191,7 +1196,13 @@ handle_hardbool_attribute (tree *node, tree name, tree args,
gcc_checking_assert (!TYPE_CACHED_VALUES_P (*node));
TYPE_VALUES (*node) = values;
- TYPE_NAME (*node) = orig;
+ TYPE_NAME (*node) = unqual;
+
+ if (TYPE_QUALS (orig) != TYPE_QUALS (*node))
+ {
+ *node = build_qualified_type (*node, TYPE_QUALS (orig));
+ TYPE_NAME (*node) = orig;
+ }
return NULL_TREE;
}
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 7c7e21d..009c8ef 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -747,7 +747,7 @@ enum cxx_dialect {
cxx26
};
-/* The C++ dialect being used. C++98 is the default. */
+/* The C++ dialect being used. C++17 is the default. */
extern enum cxx_dialect cxx_dialect;
/* Maximum template instantiation depth. This limit is rather
diff --git a/gcc/c-family/c-cppbuiltin.cc b/gcc/c-family/c-cppbuiltin.cc
index 4aea902..5476d10 100644
--- a/gcc/c-family/c-cppbuiltin.cc
+++ b/gcc/c-family/c-cppbuiltin.cc
@@ -1090,7 +1090,7 @@ c_cpp_builtins (cpp_reader *pfile)
cpp_define (pfile, "__cpp_constexpr_exceptions=202411L");
cpp_define (pfile, "__cpp_static_assert=202306L");
cpp_define (pfile, "__cpp_placeholder_variables=202306L");
- cpp_define (pfile, "__cpp_structured_bindings=202403L");
+ cpp_define (pfile, "__cpp_structured_bindings=202411L");
cpp_define (pfile, "__cpp_deleted_function=202403L");
cpp_define (pfile, "__cpp_variadic_friend=202403L");
cpp_define (pfile, "__cpp_pack_indexing=202311L");
diff --git a/gcc/c-family/c-opts.cc b/gcc/c-family/c-opts.cc
index c652e82..3fb12b9 100644
--- a/gcc/c-family/c-opts.cc
+++ b/gcc/c-family/c-opts.cc
@@ -959,6 +959,15 @@ c_common_post_options (const char **pfilename)
if (warn_enum_compare == -1)
warn_enum_compare = c_dialect_cxx () ? 1 : 0;
+ /* For C++26 default to -Wkeyword-macro if -Wpedantic. */
+ if (cxx_dialect >= cxx26 && pedantic)
+ {
+ SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+ warn_keyword_macro, 1);
+ if (warn_keyword_macro)
+ cpp_opts->cpp_warn_keyword_macro = warn_keyword_macro;
+ }
+
/* -Wpacked-bitfield-compat is on by default for the C languages. The
warning is issued in stor-layout.cc which is not part of the front-end so
we need to selectively turn it on here. */
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 12877eb..0ee2c30 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -964,6 +964,10 @@ Enum(warn_leading_whitespace_kind) String(tabs) Value(2)
EnumValue
Enum(warn_leading_whitespace_kind) String(blanks) Value(3)
+Wkeyword-macro
+C ObjC C++ ObjC++ CPP(cpp_warn_keyword_macro) CppReason(CPP_W_KEYWORD_MACRO) Var(warn_keyword_macro) Init(0) Warning
+Warn about defining or undefining macros with identifiers equal to keywords (or for C++ conditional keywords or standard attribute names).
+
Wleading-whitespace=
C ObjC C++ ObjC++ CPP(cpp_warn_leading_whitespace) CppReason(CPP_W_LEADING_WHITESPACE) Enum(warn_leading_whitespace_kind) Joined RejectNegative Var(warn_leading_whitespace) Init(0) Warning
Warn about leading whitespace style issues on lines except when in raw string literals.
diff --git a/gcc/c-family/c.opt.urls b/gcc/c-family/c.opt.urls
index 5c97593..6eb1178 100644
--- a/gcc/c-family/c.opt.urls
+++ b/gcc/c-family/c.opt.urls
@@ -508,6 +508,9 @@ UrlSuffix(gcc/Warning-Options.html#index-Winvalid-utf8)
Wjump-misses-init
UrlSuffix(gcc/Warning-Options.html#index-Wjump-misses-init)
+Wkeyword-macro
+UrlSuffix(gcc/Warning-Options.html#index-Wkeyword-macro)
+
Wleading-whitespace=
UrlSuffix(gcc/Warning-Options.html#index-Wleading-whitespace_003d)
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 464e5a1..2e5c896 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,45 @@
+2025-08-06 Alexandre Oliva <oliva@adacore.com>
+
+ * c-tree.h (C_BOOLEAN_TYPE_P): Cover hardbools as well.
+ * c-typeck.cc (convert_lvalue_to_rvalue): New overload and
+ wrapper.
+ (build_atomic_assign, build_modify_expr): Use it.
+ (build_asm_expr, handle_omp-array_sections_1): Simplify with
+ it.
+ (build_unary_op): Handle hardbools.
+
+2025-08-06 Martin Uecker <uecker@tugraz.at>
+
+ PR c/108931
+ * c-typeck.cc (composite_type_cond): Renamed from
+ composite_type with argument for condition
+ (composite_type): New function.
+ (composite_type_internal): Implement new logic.
+ (build_conditional_expr): Pass condition.
+ (common_pointer_type): Adapt.
+ (pointer_diff): Adapt.
+ (build_binary_op): Adapt.
+
+2025-08-06 Martin Uecker <uecker@tugraz.at>
+
+ PR c/121217
+ * c-typeck.cc (tagged_types_tu_compatible_p): Add check.
+
+2025-08-06 Kwok Cheung Yeung <kcyeung@baylibre.com>
+
+ * c-parser.cc (c_parser_omp_clause_from_to): Parse 'iterator' modifier.
+ * c-typeck.cc (c_finish_omp_clauses): Finish iterators for to/from
+ clauses.
+
+2025-08-06 Kwok Cheung Yeung <kcyeung@baylibre.com>
+ Andrew Stubbs <ams@baylibre.com>
+
+ * c-parser.cc (c_parser_omp_variable_list): Use location of the
+ map expression as the clause location.
+ (c_parser_omp_clause_map): Parse 'iterator' modifier.
+ * c-typeck.cc (c_finish_omp_clauses): Finish iterators. Apply
+ iterators to generated clauses.
+
2025-08-02 Martin Uecker <uecker@tugraz.at>
* c-decl.cc (get_parm_array_spec): Remove.
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 7850365..8e8bac6 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -4825,6 +4825,29 @@ c_init_decl_processing (void)
make_fname_decl = c_make_fname_decl;
start_fname_decls ();
+
+ if (warn_keyword_macro)
+ {
+ for (unsigned int i = 0; i < num_c_common_reswords; ++i)
+ /* For C register keywords which don't start with underscore
+ or start with just single underscore. Don't complain about
+ ObjC or Transactional Memory keywords. */
+ if (c_common_reswords[i].word[0] == '_'
+ && c_common_reswords[i].word[1] == '_')
+ continue;
+ else if (c_common_reswords[i].disable
+ & (D_TRANSMEM | D_OBJC | D_CXX_OBJC))
+ continue;
+ else
+ {
+ tree id = get_identifier (c_common_reswords[i].word);
+ if (C_IS_RESERVED_WORD (id)
+ && C_RID_CODE (id) != RID_CXX_COMPAT_WARN)
+ cpp_lookup (parse_in,
+ (const unsigned char *) IDENTIFIER_POINTER (id),
+ IDENTIFIER_LENGTH (id))->flags |= NODE_WARN;
+ }
+ }
}
/* Create the VAR_DECL at LOC for __FUNCTION__ etc. ID is the name to
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index bb0b113..dba94ab 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -163,7 +163,8 @@ along with GCC; see the file COPYING3. If not see
(TREE_CODE (TYPE) == BOOLEAN_TYPE \
|| (TREE_CODE (TYPE) == ENUMERAL_TYPE \
&& ENUM_UNDERLYING_TYPE (TYPE) != NULL_TREE \
- && TREE_CODE (ENUM_UNDERLYING_TYPE (TYPE)) == BOOLEAN_TYPE))
+ && (TREE_CODE (ENUM_UNDERLYING_TYPE (TYPE)) == BOOLEAN_TYPE \
+ || c_hardbool_type_attr (TYPE))))
/* Record parser information about an expression that is irrelevant
for code generation alongside a tree representing its value. */
diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index e0d0a44..7a95f72 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -641,7 +641,8 @@ struct composite_cache {
};
tree
-composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
+composite_type_internal (tree t1, tree t2, tree cond,
+ struct composite_cache* cache)
{
enum tree_code code1;
enum tree_code code2;
@@ -686,8 +687,8 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
{
tree pointed_to_1 = TREE_TYPE (t1);
tree pointed_to_2 = TREE_TYPE (t2);
- tree target = composite_type_internal (pointed_to_1,
- pointed_to_2, cache);
+ tree target = composite_type_internal (pointed_to_1, pointed_to_2,
+ cond, cache);
t1 = c_build_pointer_type_for_mode (target, TYPE_MODE (t1), false);
t1 = c_build_type_attribute_variant (t1, attributes);
return qualify_type (t1, t2);
@@ -695,25 +696,20 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
case ARRAY_TYPE:
{
- tree elt = composite_type_internal (TREE_TYPE (t1), TREE_TYPE (t2),
- cache);
- int quals;
- tree unqual_elt;
tree d1 = TYPE_DOMAIN (t1);
tree d2 = TYPE_DOMAIN (t2);
- bool d1_variable, d2_variable;
- bool d1_zero, d2_zero;
- bool t1_complete, t2_complete;
/* We should not have any type quals on arrays at all. */
gcc_assert (!TYPE_QUALS_NO_ADDR_SPACE (t1)
&& !TYPE_QUALS_NO_ADDR_SPACE (t2));
- t1_complete = COMPLETE_TYPE_P (t1);
- t2_complete = COMPLETE_TYPE_P (t2);
+ bool t1_complete = COMPLETE_TYPE_P (t1);
+ bool t2_complete = COMPLETE_TYPE_P (t2);
- d1_zero = d1 == NULL_TREE || !TYPE_MAX_VALUE (d1);
- d2_zero = d2 == NULL_TREE || !TYPE_MAX_VALUE (d2);
+ bool d1_zero = d1 == NULL_TREE || !TYPE_MAX_VALUE (d1);
+ bool d2_zero = d2 == NULL_TREE || !TYPE_MAX_VALUE (d2);
+
+ bool d1_variable, d2_variable;
d1_variable = (!d1_zero
&& (TREE_CODE (TYPE_MIN_VALUE (d1)) != INTEGER_CST
@@ -722,10 +718,8 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
&& (TREE_CODE (TYPE_MIN_VALUE (d2)) != INTEGER_CST
|| TREE_CODE (TYPE_MAX_VALUE (d2)) != INTEGER_CST));
- bool use1 = TYPE_DOMAIN (t1)
- && (d2_variable || d2_zero || !d1_variable);
- bool use2 = TYPE_DOMAIN (t2)
- && (d1_variable || d1_zero || !d2_variable);
+ bool use1 = d1 && (d2_variable || d2_zero || !d1_variable);
+ bool use2 = d2 && (d1_variable || d1_zero || !d2_variable);
/* If the first is an unspecified size pick the other one. */
if (d2_variable && c_type_unspecified_p (t1))
@@ -734,25 +728,53 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
use1 = false;
}
- /* Save space: see if the result is identical to one of the args. */
- if (elt == TREE_TYPE (t1) && use1)
- return c_build_type_attribute_variant (t1, attributes);
- if (elt == TREE_TYPE (t2) && use2)
- return c_build_type_attribute_variant (t2, attributes);
+ /* If both are VLAs but not unspecified and we are in the
+ conditional operator, we create a conditional to select
+ the size of the active branch. */
+ bool use0 = cond && d1_variable && !c_type_unspecified_p (t1)
+ && d2_variable && !c_type_unspecified_p (t2);
+
+ tree td;
+ tree elt = composite_type_internal (TREE_TYPE (t1), TREE_TYPE (t2),
+ cond, cache);
+
+ if (!use0)
+ {
+ /* Save space: see if the result is identical to one of the args. */
+ if (elt == TREE_TYPE (t1) && use1)
+ return c_build_type_attribute_variant (t1, attributes);
+ if (elt == TREE_TYPE (t2) && use2)
+ return c_build_type_attribute_variant (t2, attributes);
+
+ if (elt == TREE_TYPE (t1) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1))
+ return c_build_type_attribute_variant (t1, attributes);
+ if (elt == TREE_TYPE (t2) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1))
+ return c_build_type_attribute_variant (t2, attributes);
+
+ td = TYPE_DOMAIN (use1 ? t1 : t2);
+ }
+ else
+ {
+ /* Not used in C. */
+ gcc_assert (size_zero_node == TYPE_MIN_VALUE (d1));
+ gcc_assert (size_zero_node == TYPE_MIN_VALUE (d2));
+
+ tree d = fold_build3_loc (UNKNOWN_LOCATION, COND_EXPR, sizetype,
+ cond, TYPE_MAX_VALUE (d1),
+ TYPE_MAX_VALUE (d2));
- if (elt == TREE_TYPE (t1) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1))
- return c_build_type_attribute_variant (t1, attributes);
- if (elt == TREE_TYPE (t2) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1))
- return c_build_type_attribute_variant (t2, attributes);
+ td = build_index_type (d);
+ }
/* Merge the element types, and have a size if either arg has
one. We may have qualifiers on the element types. To set
up TYPE_MAIN_VARIANT correctly, we need to form the
composite of the unqualified types and add the qualifiers
back at the end. */
- quals = TYPE_QUALS (strip_array_types (elt));
- unqual_elt = c_build_qualified_type (elt, TYPE_UNQUALIFIED);
- t1 = c_build_array_type (unqual_elt, TYPE_DOMAIN (use1 ? t1 : t2));
+ int quals = TYPE_QUALS (strip_array_types (elt));
+ tree unqual_elt = c_build_qualified_type (elt, TYPE_UNQUALIFIED);
+
+ t1 = c_build_array_type (unqual_elt, td);
/* Check that a type which has a varying outermost dimension
got marked has having a variable size. */
@@ -819,7 +841,7 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
gcc_assert (DECL_NAME (a) == DECL_NAME (b));
gcc_checking_assert (!DECL_NAME (a) || comptypes (ta, tb));
- tree t = composite_type_internal (ta, tb, cache);
+ tree t = composite_type_internal (ta, tb, cond, cache);
tree f = build_decl (input_location, FIELD_DECL, DECL_NAME (a), t);
DECL_PACKED (f) = DECL_PACKED (a);
@@ -876,8 +898,8 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
/* Function types: prefer the one that specified arg types.
If both do, merge the arg types. Also merge the return types. */
{
- tree valtype = composite_type_internal (TREE_TYPE (t1),
- TREE_TYPE (t2), cache);
+ tree valtype = composite_type_internal (TREE_TYPE (t1), TREE_TYPE (t2),
+ cond, cache);
tree p1 = TYPE_ARG_TYPES (t1);
tree p2 = TYPE_ARG_TYPES (t2);
int len;
@@ -956,7 +978,7 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
{
TREE_VALUE (n) = composite_type_internal (TREE_TYPE (memb),
TREE_VALUE (p2),
- cache);
+ cond, cache);
pedwarn (input_location, OPT_Wpedantic,
"function types not truly compatible in ISO C");
goto parm_done;
@@ -979,14 +1001,14 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
TREE_VALUE (n)
= composite_type_internal (TREE_TYPE (memb),
TREE_VALUE (p1),
- cache);
+ cond, cache);
pedwarn (input_location, OPT_Wpedantic,
"function types not truly compatible in ISO C");
goto parm_done;
}
}
}
- TREE_VALUE (n) = composite_type_internal (mv1, mv2, cache);
+ TREE_VALUE (n) = composite_type_internal (mv1, mv2, cond, cache);
parm_done: ;
}
@@ -1001,18 +1023,25 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
}
tree
-composite_type (tree t1, tree t2)
+composite_type_cond (tree t1, tree t2, tree cond)
{
gcc_checking_assert (comptypes_check_for_composite (t1, t2));
struct composite_cache cache = { };
- tree n = composite_type_internal (t1, t2, &cache);
+ tree n = composite_type_internal (t1, t2, cond, &cache);
gcc_checking_assert (comptypes_check_for_composite (n, t1));
gcc_checking_assert (comptypes_check_for_composite (n, t2));
return n;
}
+
+tree
+composite_type (tree t1, tree t2)
+{
+ return composite_type_cond (t1, t2, NULL_TREE);
+}
+
/* Return the type of a conditional expression between pointers to
possibly differently qualified versions of compatible types.
@@ -1020,7 +1049,7 @@ composite_type (tree t1, tree t2)
true; if that isn't so, this may crash. */
static tree
-common_pointer_type (tree t1, tree t2)
+common_pointer_type (tree t1, tree t2, tree cond)
{
tree attributes;
unsigned target_quals;
@@ -1047,8 +1076,8 @@ common_pointer_type (tree t1, tree t2)
qualifiers of the two types' targets. */
tree pointed_to_1 = TREE_TYPE (t1);
tree pointed_to_2 = TREE_TYPE (t2);
- tree target = composite_type (TYPE_MAIN_VARIANT (pointed_to_1),
- TYPE_MAIN_VARIANT (pointed_to_2));
+ tree target = composite_type_cond (TYPE_MAIN_VARIANT (pointed_to_1),
+ TYPE_MAIN_VARIANT (pointed_to_2), cond);
/* Strip array types to get correct qualifier for pointers to arrays */
quals1 = TYPE_QUALS_NO_ADDR_SPACE (strip_array_types (pointed_to_1));
@@ -2651,6 +2680,20 @@ convert_lvalue_to_rvalue (location_t loc, struct c_expr exp,
return exp;
}
+/* Wrapper for the overload above, same arguments but for tree rather than
+ c_expr. This is important for hardbools to decay to bools. */
+
+static inline tree
+convert_lvalue_to_rvalue (location_t loc, tree val,
+ bool convert_p, bool read_p, bool for_init = false)
+{
+ struct c_expr expr;
+ memset (&expr, 0, sizeof (expr));
+ expr.value = val;
+ expr = convert_lvalue_to_rvalue (loc, expr, convert_p, read_p, for_init);
+ return expr.value;
+}
+
/* EXP is an expression of integer type. Apply the integer promotions
to it and return the promoted value. */
@@ -4929,7 +4972,7 @@ pointer_diff (location_t loc, tree op0, tree op1, tree *instrument_expr)
if (!addr_space_superset (as0, as1, &as_common))
gcc_unreachable ();
- common_type = common_pointer_type (TREE_TYPE (op0), TREE_TYPE (op1));
+ common_type = common_pointer_type (TREE_TYPE (op0), TREE_TYPE (op1), NULL_TREE);
op0 = convert (common_type, op0);
op1 = convert (common_type, op1);
}
@@ -5274,7 +5317,9 @@ cas_loop:
/* newval = old + val; */
if (rhs_type != rhs_semantic_type)
val = build1 (EXCESS_PRECISION_EXPR, nonatomic_rhs_semantic_type, val);
- rhs = build_binary_op (loc, modifycode, old, val, true);
+ rhs = build_binary_op (loc, modifycode,
+ convert_lvalue_to_rvalue (loc, old, true, true),
+ val, true);
if (TREE_CODE (rhs) == EXCESS_PRECISION_EXPR)
{
tree eptype = TREE_TYPE (rhs);
@@ -5730,7 +5775,48 @@ build_unary_op (location_t location, enum tree_code code, tree xarg,
goto return_build_unary_op;
}
- if (C_BOOLEAN_TYPE_P (TREE_TYPE (arg)))
+ tree true_res;
+ if (c_hardbool_type_attr (TREE_TYPE (arg), NULL, &true_res))
+ {
+ tree larg = stabilize_reference (arg);
+ tree sarg = save_expr (larg);
+ switch (code)
+ {
+ case PREINCREMENT_EXPR:
+ val = build2 (MODIFY_EXPR, TREE_TYPE (larg), larg, true_res);
+ val = build2 (COMPOUND_EXPR, TREE_TYPE (larg), sarg, val);
+ break;
+ case POSTINCREMENT_EXPR:
+ val = build2 (MODIFY_EXPR, TREE_TYPE (larg), larg, true_res);
+ val = build2 (COMPOUND_EXPR, TREE_TYPE (larg), val, sarg);
+ val = build2 (COMPOUND_EXPR, TREE_TYPE (larg), sarg, val);
+ break;
+ case PREDECREMENT_EXPR:
+ {
+ tree rarg = convert_lvalue_to_rvalue (location, sarg,
+ true, true);
+ rarg = invert_truthvalue_loc (location, rarg);
+ rarg = convert (TREE_TYPE (sarg), rarg);
+ val = build2 (MODIFY_EXPR, TREE_TYPE (larg), larg, rarg);
+ }
+ break;
+ case POSTDECREMENT_EXPR:
+ {
+ tree rarg = convert_lvalue_to_rvalue (location, sarg,
+ true, true);
+ rarg = invert_truthvalue_loc (location, rarg);
+ tree iarg = convert (TREE_TYPE (larg), rarg);
+ val = build2 (MODIFY_EXPR, TREE_TYPE (larg), larg, iarg);
+ val = build2 (COMPOUND_EXPR, TREE_TYPE (larg), val, sarg);
+ val = build2 (COMPOUND_EXPR, TREE_TYPE (larg), sarg, val);
+ }
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ TREE_SIDE_EFFECTS (val) = 1;
+ }
+ else if (C_BOOLEAN_TYPE_P (TREE_TYPE (arg)))
val = boolean_increment (code, arg);
else
val = build2 (code, TREE_TYPE (arg), arg, inc);
@@ -6383,7 +6469,10 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
addr_space_t as_common;
if (comp_target_types (colon_loc, type1, type2))
- result_type = common_pointer_type (type1, type2);
+ {
+ ifexp = save_expr (ifexp);
+ result_type = common_pointer_type (type1, type2, ifexp);
+ }
else if (null_pointer_constant_p (orig_op1))
result_type = type2;
else if (null_pointer_constant_p (orig_op2))
@@ -7340,8 +7429,10 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
clear_decl_read = true;
}
- newrhs = build_binary_op (location,
- modifycode, lhs, newrhs, true);
+ newrhs = build_binary_op (location, modifycode,
+ convert_lvalue_to_rvalue (location, lhs,
+ true, true),
+ newrhs, true);
if (clear_decl_read)
DECL_READ_P (lhs) = 0;
@@ -12733,11 +12824,9 @@ build_asm_expr (location_t loc, tree string, tree outputs, tree inputs,
}
else
{
- struct c_expr expr;
- memset (&expr, 0, sizeof (expr));
- expr.value = input;
- expr = convert_lvalue_to_rvalue (loc, expr, true, false);
- input = c_fully_fold (expr.value, false, NULL);
+ input = c_fully_fold (convert_lvalue_to_rvalue (loc, input,
+ true, false),
+ false, NULL);
if (input != error_mark_node && VOID_TYPE_P (TREE_TYPE (input)))
{
@@ -14393,7 +14482,7 @@ build_binary_op (location_t location, enum tree_code code,
Otherwise, the targets must be compatible
and both must be object or both incomplete. */
if (comp_target_types (location, type0, type1))
- result_type = common_pointer_type (type0, type1);
+ result_type = common_pointer_type (type0, type1, NULL_TREE);
else if (!addr_space_superset (as0, as1, &as_common))
{
error_at (location, "comparison of pointers to "
@@ -14532,7 +14621,7 @@ build_binary_op (location_t location, enum tree_code code,
if (comp_target_types (location, type0, type1))
{
- result_type = common_pointer_type (type0, type1);
+ result_type = common_pointer_type (type0, type1, NULL_TREE);
if (!COMPLETE_TYPE_P (TREE_TYPE (type0))
!= !COMPLETE_TYPE_P (TREE_TYPE (type1)))
pedwarn_c99 (location, OPT_Wpedantic,
@@ -15359,12 +15448,8 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
/* If the array section is pointer based and the pointer
itself is _Atomic qualified, we need to atomically load
the pointer. */
- c_expr expr;
- memset (&expr, 0, sizeof (expr));
- expr.value = ret;
- expr = convert_lvalue_to_rvalue (OMP_CLAUSE_LOCATION (c),
- expr, false, false);
- ret = expr.value;
+ ret = convert_lvalue_to_rvalue (OMP_CLAUSE_LOCATION (c),
+ ret, false, false);
}
return ret;
}
diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index d30c9c7..2dbaf4a 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -25435,20 +25435,41 @@ aarch64_asm_preferred_eh_data_format (int code ATTRIBUTE_UNUSED, int global)
return (global ? DW_EH_PE_indirect : 0) | DW_EH_PE_pcrel | type;
}
+/* Return true if function declaration FNDECL needs to be marked as
+ having a variant PCS. */
+
+static bool
+aarch64_is_variant_pcs (tree fndecl)
+{
+ /* Check for ABIs that preserve more registers than usual. */
+ arm_pcs pcs = (arm_pcs) fndecl_abi (fndecl).id ();
+ if (pcs == ARM_PCS_SIMD || pcs == ARM_PCS_SVE)
+ return true;
+
+ /* Check for ABIs that allow PSTATE.SM to be 1 on entry. */
+ tree fntype = TREE_TYPE (fndecl);
+ if (aarch64_fntype_pstate_sm (fntype) != AARCH64_ISA_MODE_SM_OFF)
+ return true;
+
+ /* Check for ABIs that require PSTATE.ZA to be 1 on entry, either because
+ of ZA or ZT0. */
+ if (aarch64_fntype_pstate_za (fntype) != 0)
+ return true;
+
+ return false;
+}
+
/* Output .variant_pcs for aarch64_vector_pcs function symbols. */
static void
aarch64_asm_output_variant_pcs (FILE *stream, const tree decl, const char* name)
{
- if (TREE_CODE (decl) == FUNCTION_DECL)
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ && aarch64_is_variant_pcs (decl))
{
- arm_pcs pcs = (arm_pcs) fndecl_abi (decl).id ();
- if (pcs == ARM_PCS_SIMD || pcs == ARM_PCS_SVE)
- {
- fprintf (stream, "\t.variant_pcs\t");
- assemble_name (stream, name);
- fprintf (stream, "\n");
- }
+ fprintf (stream, "\t.variant_pcs\t");
+ assemble_name (stream, name);
+ fprintf (stream, "\n");
}
}
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 791f3b9..49af963 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -2477,9 +2477,9 @@ constexpr wide_int_bitmask PTA_DIAMONDRAPIDS = PTA_GRANITERAPIDS_D
| PTA_MOVRS | PTA_AMX_MOVRS | PTA_USER_MSR;
constexpr wide_int_bitmask PTA_BDVER1 = PTA_64BIT | PTA_MMX | PTA_SSE
- | PTA_SSE2 | PTA_SSE3 | PTA_SSE4A | PTA_CX16 | PTA_ABM | PTA_SSSE3
- | PTA_SSE4_1 | PTA_SSE4_2 | PTA_AES | PTA_PCLMUL | PTA_AVX | PTA_FMA4
- | PTA_XOP | PTA_LWP | PTA_PRFCHW | PTA_FXSR | PTA_XSAVE;
+ | PTA_SSE2 | PTA_SSE3 | PTA_SSE4A | PTA_CX16 | PTA_POPCNT | PTA_LZCNT
+ | PTA_ABM | PTA_SSSE3 | PTA_SSE4_1 | PTA_SSE4_2 | PTA_AES | PTA_PCLMUL
+ | PTA_AVX | PTA_FMA4 | PTA_XOP | PTA_LWP | PTA_PRFCHW | PTA_FXSR | PTA_XSAVE;
constexpr wide_int_bitmask PTA_BDVER2 = PTA_BDVER1 | PTA_BMI | PTA_TBM
| PTA_F16C | PTA_FMA;
constexpr wide_int_bitmask PTA_BDVER3 = PTA_BDVER2 | PTA_XSAVEOPT
@@ -2487,13 +2487,13 @@ constexpr wide_int_bitmask PTA_BDVER3 = PTA_BDVER2 | PTA_XSAVEOPT
constexpr wide_int_bitmask PTA_BDVER4 = PTA_BDVER3 | PTA_AVX2 | PTA_BMI2
| PTA_RDRND | PTA_MOVBE | PTA_MWAITX;
-constexpr wide_int_bitmask PTA_ZNVER1 = PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2
- | PTA_SSE3 | PTA_SSE4A | PTA_CX16 | PTA_ABM | PTA_SSSE3 | PTA_SSE4_1
- | PTA_SSE4_2 | PTA_AES | PTA_PCLMUL | PTA_AVX | PTA_AVX2 | PTA_BMI | PTA_BMI2
- | PTA_F16C | PTA_FMA | PTA_PRFCHW | PTA_FXSR | PTA_XSAVE | PTA_XSAVEOPT
- | PTA_FSGSBASE | PTA_RDRND | PTA_MOVBE | PTA_MWAITX | PTA_ADX | PTA_RDSEED
- | PTA_CLZERO | PTA_CLFLUSHOPT | PTA_XSAVEC | PTA_XSAVES | PTA_SHA | PTA_LZCNT
- | PTA_POPCNT;
+constexpr wide_int_bitmask PTA_ZNVER1 = PTA_64BIT | PTA_MMX | PTA_SSE
+ | PTA_SSE2 | PTA_SSE3 | PTA_SSE4A | PTA_CX16 | PTA_POPCNT | PTA_LZCNT
+ | PTA_ABM | PTA_SSSE3 | PTA_SSE4_1 | PTA_SSE4_2 | PTA_AES | PTA_PCLMUL
+ | PTA_AVX | PTA_AVX2 | PTA_BMI | PTA_BMI2 | PTA_F16C | PTA_FMA | PTA_PRFCHW
+ | PTA_FXSR | PTA_XSAVE | PTA_XSAVEOPT | PTA_FSGSBASE | PTA_RDRND | PTA_MOVBE
+ | PTA_MWAITX | PTA_ADX | PTA_RDSEED | PTA_CLZERO | PTA_CLFLUSHOPT
+ | PTA_XSAVEC | PTA_XSAVES | PTA_SHA;
constexpr wide_int_bitmask PTA_ZNVER2 = PTA_ZNVER1 | PTA_CLWB | PTA_RDPID
| PTA_WBNOINVD;
constexpr wide_int_bitmask PTA_ZNVER3 = PTA_ZNVER2 | PTA_VAES | PTA_VPCLMULQDQ
@@ -2506,19 +2506,19 @@ constexpr wide_int_bitmask PTA_ZNVER5 = PTA_ZNVER4 | PTA_AVXVNNI
| PTA_MOVDIRI | PTA_MOVDIR64B | PTA_AVX512VP2INTERSECT | PTA_PREFETCHI;
constexpr wide_int_bitmask PTA_BTVER1 = PTA_64BIT | PTA_MMX | PTA_SSE
- | PTA_SSE2 | PTA_SSE3 | PTA_SSSE3 | PTA_SSE4A | PTA_ABM | PTA_CX16
- | PTA_PRFCHW | PTA_FXSR | PTA_XSAVE;
+ | PTA_SSE2 | PTA_SSE3 | PTA_SSSE3 | PTA_SSE4A | PTA_LZCNT | PTA_POPCNT
+ | PTA_ABM | PTA_CX16 | PTA_PRFCHW | PTA_FXSR | PTA_XSAVE;
constexpr wide_int_bitmask PTA_BTVER2 = PTA_BTVER1 | PTA_SSE4_1 | PTA_SSE4_2
| PTA_AES | PTA_PCLMUL | PTA_AVX | PTA_BMI | PTA_F16C | PTA_MOVBE
| PTA_XSAVEOPT;
constexpr wide_int_bitmask PTA_LUJIAZUI = PTA_64BIT | PTA_MMX | PTA_SSE
- | PTA_SSE2 | PTA_SSE3 | PTA_CX16 | PTA_ABM | PTA_SSSE3 | PTA_SSE4_1
- | PTA_SSE4_2 | PTA_AES | PTA_PCLMUL | PTA_BMI | PTA_BMI2 | PTA_PRFCHW
- | PTA_FXSR | PTA_XSAVE | PTA_XSAVEOPT | PTA_FSGSBASE | PTA_RDRND | PTA_MOVBE
- | PTA_ADX | PTA_RDSEED | PTA_POPCNT;
+ | PTA_SSE2 | PTA_SSE3 | PTA_CX16 | PTA_LZCNT | PTA_POPCNT | PTA_ABM
+ | PTA_SSSE3 | PTA_SSE4_1 | PTA_SSE4_2 | PTA_AES | PTA_PCLMUL | PTA_BMI
+ | PTA_BMI2 | PTA_PRFCHW | PTA_FXSR | PTA_XSAVE | PTA_XSAVEOPT | PTA_FSGSBASE
+ | PTA_RDRND | PTA_MOVBE | PTA_ADX | PTA_RDSEED;
constexpr wide_int_bitmask PTA_YONGFENG = PTA_LUJIAZUI | PTA_AVX | PTA_AVX2
- | PTA_F16C | PTA_FMA | PTA_SHA | PTA_LZCNT;
+ | PTA_F16C | PTA_FMA | PTA_SHA;
#ifndef GENERATOR_FILE
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 2b0dd66..6686f10 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -18298,17 +18298,17 @@
(any_rotate:SWI
(match_operand:SWI 1 "const_int_operand")
(subreg:QI
- (and
- (match_operand 2 "int248_register_operand")
- (match_operand 3 "const_int_operand")) 0)))]
+ (match_operator 4 "and_operator"
+ [(match_operand 2 "int248_register_operand")
+ (match_operand 3 "const_int_operand")]) 0)))]
"(INTVAL (operands[3]) & (GET_MODE_BITSIZE (<MODE>mode) - 1))
== GET_MODE_BITSIZE (<MODE>mode) - 1"
- [(set (match_dup 4) (match_dup 1))
+ [(set (match_dup 5) (match_dup 1))
(set (match_dup 0)
- (any_rotate:SWI (match_dup 4)
+ (any_rotate:SWI (match_dup 5)
(subreg:QI
- (and:SI (match_dup 2) (match_dup 3)) 0)))]
- "operands[4] = gen_reg_rtx (<MODE>mode);")
+ (match_op_dup 4 [(match_dup 2) (match_dup 3)]) 0)))]
+ "operands[5] = gen_reg_rtx (<MODE>mode);")
(define_insn_and_split "*<insn><mode>3_mask_1"
[(set (match_operand:SWI 0 "nonimmediate_operand")
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index 0f31090..175798c 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -1714,10 +1714,14 @@
(define_predicate "div_operator"
(match_code "div"))
-;; Return true if this is a and, ior or xor operation.
+;; Return true if this is an and, ior or xor operation.
(define_predicate "logic_operator"
(match_code "and,ior,xor"))
+;; Return true if this is an and operation.
+(define_predicate "and_operator"
+ (match_code "and"))
+
;; Return true if this is a plus, minus, and, ior or xor operation.
(define_predicate "plusminuslogic_operator"
(match_code "plus,minus,and,ior,xor"))
diff --git a/gcc/config/s390/s390.cc b/gcc/config/s390/s390.cc
index 012b6db..d044f9a 100644
--- a/gcc/config/s390/s390.cc
+++ b/gcc/config/s390/s390.cc
@@ -9239,15 +9239,12 @@ print_operand (FILE *file, rtx x, int code)
else if (code == 'h')
fprintf (file, HOST_WIDE_INT_PRINT_DEC,
((CONST_WIDE_INT_ELT (x, 0) & 0xffff) ^ 0x8000) - 0x8000);
+ /* Support arbitrary _BitInt constants in asm statements. */
+ else if (code == 0)
+ output_addr_const (file, x);
else
- {
- if (code == 0)
- output_operand_lossage ("invalid constant - try using "
- "an output modifier");
- else
- output_operand_lossage ("invalid constant for output modifier '%c'",
- code);
- }
+ output_operand_lossage ("invalid constant for output modifier '%c'",
+ code);
break;
case CONST_VECTOR:
switch (code)
@@ -18768,6 +18765,27 @@ s390_c_mode_for_floating_type (enum tree_index ti)
return default_mode_for_floating_type (ti);
}
+/* Return true if _BitInt(N) is supported and fill its details into *INFO. */
+
+bool
+s390_bitint_type_info (int n, struct bitint_info *info)
+{
+ if (!TARGET_64BIT)
+ return false;
+ if (n <= 8)
+ info->limb_mode = QImode;
+ else if (n <= 16)
+ info->limb_mode = HImode;
+ else if (n <= 32)
+ info->limb_mode = SImode;
+ else
+ info->limb_mode = DImode;
+ info->abi_limb_mode = info->limb_mode;
+ info->big_endian = true;
+ info->extended = true;
+ return true;
+}
+
/* Initialize GCC target structure. */
#undef TARGET_ASM_ALIGNED_HI_OP
@@ -19089,6 +19107,9 @@ s390_c_mode_for_floating_type (enum tree_index ti)
#undef TARGET_DOCUMENTATION_NAME
#define TARGET_DOCUMENTATION_NAME "S/390"
+#undef TARGET_C_BITINT_TYPE_INFO
+#define TARGET_C_BITINT_TYPE_INFO s390_bitint_type_info
+
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-s390.h"
diff --git a/gcc/configure b/gcc/configure
index bacdd29..cab9c75 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -872,7 +872,6 @@ c_strict_warn
strict_warn
c_loose_warn
loose_warn
-aliasing_flags
CPP
EGREP
GREP
@@ -7126,45 +7125,6 @@ $as_echo "#define HAVE_SWAP_IN_UTILITY 1" >>confdefs.h
fi
-# Check whether compiler is affected by placement new aliasing bug (PR 29286).
-# If the host compiler is affected by the bug, and we build with optimization
-# enabled (which happens e.g. when cross-compiling), the pool allocator may
-# get miscompiled. Use -fno-strict-aliasing to work around this problem.
-# Since there is no reliable feature check for the presence of this bug,
-# we simply use a GCC version number check. (This should never trigger for
-# stages 2 or 3 of a native bootstrap.)
-aliasing_flags=
-if test "$GCC" = yes; then
- saved_CXXFLAGS="$CXXFLAGS"
-
- # The following test compilation will succeed if and only if $CXX accepts
- # -fno-strict-aliasing *and* is older than GCC 4.3.
- CXXFLAGS="$CXXFLAGS -fno-strict-aliasing"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX is affected by placement new aliasing bug" >&5
-$as_echo_n "checking whether $CXX is affected by placement new aliasing bug... " >&6; }
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
-#error compiler not affected by placement new aliasing bug
-#endif
-
-_ACEOF
-if ac_fn_cxx_try_compile "$LINENO"; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }; aliasing_flags='-fno-strict-aliasing'
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
- CXXFLAGS="$saved_CXXFLAGS"
-fi
-
-
-
-
# ---------------------
# Warnings and checking
# ---------------------
@@ -21522,7 +21482,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 21525 "configure"
+#line 21485 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -21628,7 +21588,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 21631 "configure"
+#line 21591 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 2c43b38..ac1f0e9 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -563,35 +563,6 @@ if test $ac_cv_std_swap_in_utility = yes; then
[Define if <utility> defines std::swap.])
fi
-# Check whether compiler is affected by placement new aliasing bug (PR 29286).
-# If the host compiler is affected by the bug, and we build with optimization
-# enabled (which happens e.g. when cross-compiling), the pool allocator may
-# get miscompiled. Use -fno-strict-aliasing to work around this problem.
-# Since there is no reliable feature check for the presence of this bug,
-# we simply use a GCC version number check. (This should never trigger for
-# stages 2 or 3 of a native bootstrap.)
-aliasing_flags=
-if test "$GCC" = yes; then
- saved_CXXFLAGS="$CXXFLAGS"
-
- # The following test compilation will succeed if and only if $CXX accepts
- # -fno-strict-aliasing *and* is older than GCC 4.3.
- CXXFLAGS="$CXXFLAGS -fno-strict-aliasing"
- AC_MSG_CHECKING([whether $CXX is affected by placement new aliasing bug])
- AC_COMPILE_IFELSE([AC_LANG_SOURCE([
-#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
-#error compiler not affected by placement new aliasing bug
-#endif
-])],
- [AC_MSG_RESULT([yes]); aliasing_flags='-fno-strict-aliasing'],
- [AC_MSG_RESULT([no])])
-
- CXXFLAGS="$saved_CXXFLAGS"
-fi
-AC_SUBST(aliasing_flags)
-
-
-
# ---------------------
# Warnings and checking
# ---------------------
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index cb4ff09..8e9b8ea 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,28 @@
+2025-08-06 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/121231
+ PR c++/119688
+ PR c++/94511
+ * mangle.cc (write_expression): Write out implicit non-trailing
+ zeroes of a CONSTRUCTOR when the ABI version is at least 21.
+
+2025-08-06 Jason Merrill <jason@redhat.com>
+
+ * constexpr.cc (cxx_eval_indirect_ref): Improve diagnostic.
+
+2025-08-06 Kwok Cheung Yeung <kcyeung@baylibre.com>
+
+ * parser.cc (cp_parser_omp_clause_from_to): Parse 'iterator' modifier.
+ * semantics.cc (finish_omp_clauses): Finish iterators for to/from
+ clauses.
+
+2025-08-06 Kwok Cheung Yeung <kcyeung@baylibre.com>
+ Andrew Stubbs <ams@baylibre.com>
+
+ * parser.cc (cp_parser_omp_clause_map): Parse 'iterator' modifier.
+ * semantics.cc (finish_omp_clauses): Finish iterators. Apply
+ iterators to generated clauses.
+
2025-08-05 Jason Merrill <jason@redhat.com>
PR c++/121068
diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index b8ac454..eabf7f8 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -11615,12 +11615,14 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
}
return false;
}
+ tree ve = DECL_VALUE_EXPR (t);
/* Treat __PRETTY_FUNCTION__ inside a template function as
potentially-constant. */
- else if (DECL_PRETTY_FUNCTION_P (t)
- && DECL_VALUE_EXPR (t) == error_mark_node)
+ if (DECL_PRETTY_FUNCTION_P (t) && ve == error_mark_node)
return true;
- return RECUR (DECL_VALUE_EXPR (t), rval);
+ if (DECL_DECOMPOSITION_P (t) && TREE_CODE (ve) == TREE_VEC)
+ return RECUR (TREE_VEC_ELT (ve, 0), rval);
+ return RECUR (ve, rval);
}
if (want_rval
&& (now || !var_in_maybe_constexpr_fn (t))
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 8122fca..ab5b0c9 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -9748,7 +9748,7 @@ get_tuple_size (tree type)
/* Return std::tuple_element<I,TYPE>::type. */
static tree
-get_tuple_element_type (tree type, unsigned i)
+get_tuple_element_type (tree type, unsigned HOST_WIDE_INT i)
{
tree args = make_tree_vec (2);
TREE_VEC_ELT (args, 0) = build_int_cst (integer_type_node, i);
@@ -9764,7 +9764,7 @@ get_tuple_element_type (tree type, unsigned i)
/* Return e.get<i>() or get<i>(e). */
static tree
-get_tuple_decomp_init (tree decl, unsigned i)
+get_tuple_decomp_init (tree decl, unsigned HOST_WIDE_INT i)
{
tree targs = make_tree_vec (1);
TREE_VEC_ELT (targs, 0) = build_int_cst (integer_type_node, i);
@@ -9870,6 +9870,19 @@ cp_maybe_mangle_decomp (tree decl, cp_decomp *decomp)
}
}
+/* Append #i to DECL_NAME (decl). */
+
+static void
+set_sb_pack_name (tree decl, unsigned HOST_WIDE_INT i)
+{
+ tree name = DECL_NAME (decl);
+ size_t len = IDENTIFIER_LENGTH (name) + 22;
+ char *n = XALLOCAVEC (char, len);
+ snprintf (n, len, "%s#" HOST_WIDE_INT_PRINT_UNSIGNED,
+ IDENTIFIER_POINTER (name), i);
+ DECL_NAME (decl) = get_identifier (n);
+}
+
/* Finish a decomposition declaration. DECL is the underlying declaration
"e", FIRST is the head of a chain of decls for the individual identifiers
chained through DECL_CHAIN in reverse order and COUNT is the number of
@@ -9926,10 +9939,13 @@ cp_finish_decomp (tree decl, cp_decomp *decomp, bool test_p)
auto_vec<tree, 16> v;
v.safe_grow (count, true);
tree d = first;
+ int pack = -1;
for (unsigned int i = 0; i < count; i++, d = DECL_CHAIN (d))
{
v[count - i - 1] = d;
fit_decomposition_lang_decl (d, decl);
+ if (DECL_PACK_P (d))
+ pack = count - i - 1;
}
tree type = TREE_TYPE (decl);
@@ -9951,6 +9967,14 @@ cp_finish_decomp (tree decl, cp_decomp *decomp, bool test_p)
tree eltype = NULL_TREE;
unsigned HOST_WIDE_INT eltscnt = 0;
+ /* Structured binding packs when initializer is non-dependent should
+ have their DECL_VALUE_EXPR set to a TREE_VEC. First two elements
+ of that TREE_VEC are the base and index, what is normally represented
+ as DECL_VALUE_EXPR ARRAY_REF <base, index> where index is the index
+ of the pack first element. The remaining elements of the TREE_VEC
+ are VAR_DECLs for the pack elements. */
+ tree packv = NULL_TREE;
+
if (TREE_CODE (type) == ARRAY_TYPE)
{
tree nelts;
@@ -9969,7 +9993,7 @@ cp_finish_decomp (tree decl, cp_decomp *decomp, bool test_p)
goto error_out;
}
eltscnt = tree_to_uhwi (nelts);
- if (count != eltscnt)
+ if (pack != -1 ? count - 1 > eltscnt : count != eltscnt)
{
cnt_mismatch:
auto_diagnostic_group d;
@@ -9990,12 +10014,37 @@ cp_finish_decomp (tree decl, cp_decomp *decomp, bool test_p)
eltype = TREE_TYPE (type);
for (unsigned int i = 0; i < count; i++)
{
+ if ((unsigned) pack == i)
+ {
+ packv = make_tree_vec (eltscnt - count + 3);
+ for (unsigned HOST_WIDE_INT j = 0; j < eltscnt - count + 1; ++j)
+ {
+ tree t;
+ TREE_VEC_ELT (packv, j + 2) = t = copy_node (v[pack]);
+ set_sb_pack_name (t, j);
+ maybe_push_decl (t);
+ TREE_TYPE (t) = eltype;
+ layout_decl (t, 0);
+ if (!processing_template_decl)
+ {
+ tree a = unshare_expr (dexp);
+ a = build4 (ARRAY_REF, eltype, a, size_int (j + pack),
+ NULL_TREE, NULL_TREE);
+ SET_DECL_VALUE_EXPR (t, a);
+ DECL_HAS_VALUE_EXPR_P (t) = 1;
+ }
+ }
+ continue;
+ }
TREE_TYPE (v[i]) = eltype;
layout_decl (v[i], 0);
if (processing_template_decl)
continue;
tree t = unshare_expr (dexp);
- t = build4 (ARRAY_REF, eltype, t, size_int (i), NULL_TREE, NULL_TREE);
+ unsigned HOST_WIDE_INT j = i;
+ if (pack != -1 && (unsigned) pack < i)
+ j = i + eltscnt - count;
+ t = build4 (ARRAY_REF, eltype, t, size_int (j), NULL_TREE, NULL_TREE);
SET_DECL_VALUE_EXPR (v[i], t);
DECL_HAS_VALUE_EXPR_P (v[i]) = 1;
}
@@ -10004,17 +10053,41 @@ cp_finish_decomp (tree decl, cp_decomp *decomp, bool test_p)
else if (TREE_CODE (type) == COMPLEX_TYPE)
{
eltscnt = 2;
- if (count != eltscnt)
+ if (pack != -1 ? count - 1 > eltscnt : count != eltscnt)
goto cnt_mismatch;
eltype = cp_build_qualified_type (TREE_TYPE (type), TYPE_QUALS (type));
for (unsigned int i = 0; i < count; i++)
{
+ if ((unsigned) pack == i)
+ {
+ packv = make_tree_vec (eltscnt - count + 3);
+ for (unsigned HOST_WIDE_INT j = 0; j < eltscnt - count + 1; ++j)
+ {
+ tree t;
+ TREE_VEC_ELT (packv, j + 2) = t = copy_node (v[pack]);
+ set_sb_pack_name (t, j);
+ maybe_push_decl (t);
+ TREE_TYPE (t) = eltype;
+ layout_decl (t, 0);
+ if (!processing_template_decl)
+ {
+ tree a = build1 (pack + j ? IMAGPART_EXPR : REALPART_EXPR, eltype,
+ unshare_expr (dexp));
+ SET_DECL_VALUE_EXPR (t, a);
+ DECL_HAS_VALUE_EXPR_P (t) = 1;
+ }
+ }
+ continue;
+ }
TREE_TYPE (v[i]) = eltype;
layout_decl (v[i], 0);
if (processing_template_decl)
continue;
tree t = unshare_expr (dexp);
- t = build1 (i ? IMAGPART_EXPR : REALPART_EXPR, eltype, t);
+ unsigned HOST_WIDE_INT j = i;
+ if (pack != -1 && (unsigned) pack < i)
+ j = i + eltscnt - count;
+ t = build1 (j ? IMAGPART_EXPR : REALPART_EXPR, eltype, t);
SET_DECL_VALUE_EXPR (v[i], t);
DECL_HAS_VALUE_EXPR_P (v[i]) = 1;
}
@@ -10026,19 +10099,47 @@ cp_finish_decomp (tree decl, cp_decomp *decomp, bool test_p)
error_at (loc, "cannot decompose variable length vector %qT", type);
goto error_out;
}
- if (count != eltscnt)
+ if (pack != -1 ? count - 1 > eltscnt : count != eltscnt)
goto cnt_mismatch;
eltype = cp_build_qualified_type (TREE_TYPE (type), TYPE_QUALS (type));
for (unsigned int i = 0; i < count; i++)
{
+ if ((unsigned) pack == i)
+ {
+ packv = make_tree_vec (eltscnt - count + 3);
+ for (unsigned HOST_WIDE_INT j = 0; j < eltscnt - count + 1; ++j)
+ {
+ tree t;
+ TREE_VEC_ELT (packv, j + 2) = t = copy_node (v[pack]);
+ set_sb_pack_name (t, j);
+ maybe_push_decl (t);
+ TREE_TYPE (t) = eltype;
+ layout_decl (t, 0);
+ if (!processing_template_decl)
+ {
+ tree a = unshare_expr (dexp);
+ location_t loc = DECL_SOURCE_LOCATION (t);
+ tree s = size_int (j + pack);
+ convert_vector_to_array_for_subscript (loc, &a, s);
+ a = build4 (ARRAY_REF, eltype, a, s,
+ NULL_TREE, NULL_TREE);
+ SET_DECL_VALUE_EXPR (t, a);
+ DECL_HAS_VALUE_EXPR_P (t) = 1;
+ }
+ }
+ continue;
+ }
TREE_TYPE (v[i]) = eltype;
layout_decl (v[i], 0);
if (processing_template_decl)
continue;
tree t = unshare_expr (dexp);
+ unsigned HOST_WIDE_INT j = i;
+ if (pack != -1 && (unsigned) pack < i)
+ j = i + eltscnt - count;
convert_vector_to_array_for_subscript (DECL_SOURCE_LOCATION (v[i]),
- &t, size_int (i));
- t = build4 (ARRAY_REF, eltype, t, size_int (i), NULL_TREE, NULL_TREE);
+ &t, size_int (j));
+ t = build4 (ARRAY_REF, eltype, t, size_int (j), NULL_TREE, NULL_TREE);
SET_DECL_VALUE_EXPR (v[i], t);
DECL_HAS_VALUE_EXPR_P (v[i]) = 1;
}
@@ -10062,11 +10163,11 @@ cp_finish_decomp (tree decl, cp_decomp *decomp, bool test_p)
goto error_out;
}
eltscnt = tree_to_uhwi (tsize);
- if (count != eltscnt)
+ if (pack != -1 ? count - 1 > eltscnt : count != eltscnt)
goto cnt_mismatch;
- if (test_p)
+ if (test_p && eltscnt)
return true;
- if (!processing_template_decl && DECL_DECOMP_BASE (decl))
+ if (!processing_template_decl && DECL_DECOMP_BASE (decl) && eltscnt)
{
/* For structured bindings used in conditions we need to evaluate
the conversion of decl (aka e in the standard) to bool or
@@ -10096,16 +10197,70 @@ cp_finish_decomp (tree decl, cp_decomp *decomp, bool test_p)
location_t sloc = input_location;
location_t dloc = DECL_SOURCE_LOCATION (v[i]);
+ if ((unsigned) pack == i)
+ {
+ packv = make_tree_vec (eltscnt - count + 3);
+ for (unsigned HOST_WIDE_INT j = 0; j < eltscnt - count + 1; ++j)
+ {
+ tree t;
+ TREE_VEC_ELT (packv, j + 2) = t = copy_node (v[pack]);
+ set_sb_pack_name (t, j);
+ input_location = dloc;
+ tree init = get_tuple_decomp_init (decl, j + pack);
+ tree eltype = (init == error_mark_node ? error_mark_node
+ : get_tuple_element_type (type, j + pack));
+ input_location = sloc;
+
+ if (VOID_TYPE_P (eltype))
+ {
+ error ("%<std::tuple_element<%wu, %T>::type%> is "
+ "%<void%>", j + pack, type);
+ eltype = error_mark_node;
+ }
+ if (init == error_mark_node || eltype == error_mark_node)
+ {
+ inform (dloc, "in initialization of structured binding "
+ "pack %qD", v[pack]);
+ goto error_out;
+ }
+ if (j == 0
+ && !processing_template_decl
+ && TREE_STATIC (decl))
+ {
+ sorry_at (dloc, "mangling of structured binding pack "
+ "elements not implemented yet");
+ goto error_out;
+ }
+ maybe_push_decl (t);
+ /* Save the decltype away before reference collapse. */
+ hash_map_safe_put<hm_ggc> (decomp_type_table, t, eltype);
+ eltype = cp_build_reference_type (eltype, !lvalue_p (init));
+ TREE_TYPE (t) = eltype;
+ layout_decl (t, 0);
+ DECL_HAS_VALUE_EXPR_P (t) = 0;
+ if (!processing_template_decl)
+ {
+ copy_linkage (t, decl);
+ cp_finish_decl (t, init, /*constexpr*/false,
+ /*asm*/NULL_TREE, LOOKUP_NORMAL);
+ }
+ }
+ continue;
+ }
+
+ unsigned HOST_WIDE_INT j = i;
+ if (pack != -1 && (unsigned) pack < i)
+ j = i + eltscnt - count;
input_location = dloc;
- tree init = get_tuple_decomp_init (decl, i);
+ tree init = get_tuple_decomp_init (decl, j);
tree eltype = (init == error_mark_node ? error_mark_node
- : get_tuple_element_type (type, i));
+ : get_tuple_element_type (type, j));
input_location = sloc;
if (VOID_TYPE_P (eltype))
{
- error ("%<std::tuple_element<%u, %T>::type%> is %<void%>",
- i, type);
+ error ("%<std::tuple_element<%wu, %T>::type%> is %<void%>",
+ j, type);
eltype = error_mark_node;
}
if (init == error_mark_node || eltype == error_mark_node)
@@ -10159,6 +10314,12 @@ cp_finish_decomp (tree decl, cp_decomp *decomp, bool test_p)
goto error_out;
else if (btype == NULL_TREE)
{
+ if (pack == 0 && count == 1)
+ {
+ eltscnt = 0;
+ packv = make_tree_vec (2);
+ goto done;
+ }
error_at (loc, "cannot decompose class type %qT without non-static "
"data members", type);
goto error_out;
@@ -10170,7 +10331,7 @@ cp_finish_decomp (tree decl, cp_decomp *decomp, bool test_p)
continue;
else
eltscnt++;
- if (count != eltscnt)
+ if (pack != -1 ? count - 1 > eltscnt : count != eltscnt)
goto cnt_mismatch;
tree t = dexp;
if (type != btype)
@@ -10179,6 +10340,7 @@ cp_finish_decomp (tree decl, cp_decomp *decomp, bool test_p)
/*nonnull*/false, tf_warning_or_error);
type = btype;
}
+ unsigned HOST_WIDE_INT j = 0;
unsigned int i = 0;
for (tree field = TYPE_FIELDS (btype); field; field = TREE_CHAIN (field))
if (TREE_CODE (field) != FIELD_DECL
@@ -10191,6 +10353,32 @@ cp_finish_decomp (tree decl, cp_decomp *decomp, bool test_p)
NULL_TREE);
if (REFERENCE_REF_P (tt))
tt = TREE_OPERAND (tt, 0);
+ if (pack != -1 && j >= (unsigned) pack)
+ {
+ if (j == (unsigned) pack)
+ {
+ packv = make_tree_vec (eltscnt - count + 3);
+ i++;
+ }
+ if (j < (unsigned) pack + eltscnt - (count - 1))
+ {
+ tree t;
+ TREE_VEC_ELT (packv, j + 3 - i) = t = copy_node (v[pack]);
+ set_sb_pack_name (t, j + 1 - i);
+ maybe_push_decl (t);
+ TREE_TYPE (t) = TREE_TYPE (tt);
+ layout_decl (t, 0);
+ if (!processing_template_decl)
+ {
+ SET_DECL_VALUE_EXPR (t, tt);
+ DECL_HAS_VALUE_EXPR_P (t) = 1;
+ }
+ else
+ DECL_HAS_VALUE_EXPR_P (t) = 0;
+ j++;
+ continue;
+ }
+ }
TREE_TYPE (v[i]) = TREE_TYPE (tt);
layout_decl (v[i], 0);
if (!processing_template_decl)
@@ -10199,7 +10387,26 @@ cp_finish_decomp (tree decl, cp_decomp *decomp, bool test_p)
DECL_HAS_VALUE_EXPR_P (v[i]) = 1;
}
i++;
+ j++;
}
+ if (pack != -1 && j == (unsigned) pack)
+ {
+ gcc_checking_assert (eltscnt == count - 1);
+ packv = make_tree_vec (2);
+ }
+ }
+ done:
+ if (packv)
+ {
+ gcc_checking_assert (pack != -1);
+ TREE_VEC_ELT (packv, 0) = decl;
+ TREE_VEC_ELT (packv, 1) = size_int (pack);
+ SET_DECL_VALUE_EXPR (v[pack], packv);
+ DECL_HAS_VALUE_EXPR_P (v[pack]) = 1;
+ DECL_IGNORED_P (v[pack]) = 1;
+ if (!processing_template_decl)
+ for (unsigned int i = 0; i < TREE_VEC_LENGTH (packv) - 2U; ++i)
+ pushdecl (TREE_VEC_ELT (packv, 2 + i));
}
if (processing_template_decl)
{
diff --git a/gcc/cp/lex.cc b/gcc/cp/lex.cc
index 08a6348..b7d2ac6 100644
--- a/gcc/cp/lex.cc
+++ b/gcc/cp/lex.cc
@@ -368,6 +368,66 @@ cxx_init (void)
cxx_init_decl_processing ();
+ if (warn_keyword_macro)
+ {
+ for (unsigned int i = 0; i < num_c_common_reswords; ++i)
+ /* For C++ none of the keywords in [lex.key] starts with underscore,
+ don't register anything like that. Don't complain about
+ ObjC or Transactional Memory keywords. */
+ if (c_common_reswords[i].word[0] == '_')
+ continue;
+ else if (c_common_reswords[i].disable & (D_TRANSMEM | D_OBJC))
+ continue;
+ else
+ {
+ tree id = get_identifier (c_common_reswords[i].word);
+ if (IDENTIFIER_KEYWORD_P (id)
+ /* Don't register keywords with spaces. */
+ && IDENTIFIER_POINTER (id)[IDENTIFIER_LENGTH (id) - 1] != ' ')
+ cpp_lookup (parse_in,
+ (const unsigned char *) IDENTIFIER_POINTER (id),
+ IDENTIFIER_LENGTH (id))->flags |= NODE_WARN;
+ }
+ auto warn_on = [] (const char *name) {
+ cpp_lookup (parse_in, (const unsigned char *) name,
+ strlen (name))->flags |= NODE_WARN;
+ };
+ if (cxx_dialect >= cxx11)
+ {
+ warn_on ("final");
+ warn_on ("override");
+ warn_on ("noreturn");
+ if (cxx_dialect < cxx26)
+ warn_on ("carries_dependency");
+ }
+ if (cxx_dialect >= cxx14)
+ warn_on ("deprecated");
+ if (cxx_dialect >= cxx17)
+ {
+ warn_on ("fallthrough");
+ warn_on ("maybe_unused");
+ warn_on ("nodiscard");
+ }
+ if (cxx_dialect >= cxx20)
+ {
+ warn_on ("likely");
+ warn_on ("unlikely");
+ warn_on ("no_unique_address");
+ }
+ if (flag_modules)
+ {
+ warn_on ("import");
+ warn_on ("module");
+ }
+ if (cxx_dialect >= cxx23)
+ warn_on ("assume");
+ if (cxx_dialect >= cxx26)
+ {
+ warn_on ("replaceable_if_eligible");
+ warn_on ("trivially_relocatable_if_eligible");
+ }
+ }
+
if (c_common_init () == false)
{
input_location = saved_loc;
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index a8c54c7..743fd74 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -14672,13 +14672,23 @@ cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl,
tree v = DECL_VALUE_EXPR (range_decl);
/* For decomposition declaration get all of the corresponding
declarations out of the way. */
- if (TREE_CODE (v) == ARRAY_REF
- && DECL_DECOMPOSITION_P (TREE_OPERAND (v, 0)))
+ if ((TREE_CODE (v) == ARRAY_REF
+ && DECL_DECOMPOSITION_P (TREE_OPERAND (v, 0)))
+ || (TREE_CODE (v) == TREE_VEC
+ && DECL_DECOMPOSITION_P (TREE_VEC_ELT (v, 0))))
{
tree d = range_decl;
- range_decl = TREE_OPERAND (v, 0);
decomp = &decomp_d;
- decomp->count = tree_to_uhwi (TREE_OPERAND (v, 1)) + 1;
+ if (TREE_CODE (v) == ARRAY_REF)
+ {
+ range_decl = TREE_OPERAND (v, 0);
+ decomp->count = tree_to_uhwi (TREE_OPERAND (v, 1)) + 1;
+ }
+ else
+ {
+ range_decl = TREE_VEC_ELT (v, 0);
+ decomp->count = tree_to_uhwi (TREE_VEC_ELT (v, 1)) + 1;
+ }
decomp->decl = d;
bool seen_name_independent_decl = false;
for (unsigned int i = 0; i < decomp->count;
@@ -16843,7 +16853,7 @@ cp_parser_simple_declaration (cp_parser* parser,
}
/* Helper of cp_parser_simple_declaration, parse a decomposition declaration.
- decl-specifier-seq ref-qualifier [opt] [ identifier-list ]
+ decl-specifier-seq ref-qualifier [opt] [ sb-identifier-list ]
initializer ; */
static tree
@@ -16856,21 +16866,45 @@ cp_parser_decomposition_declaration (cp_parser *parser,
location_t loc = cp_lexer_peek_token (parser->lexer)->location;
cp_parser_require (parser, CPP_OPEN_SQUARE, RT_OPEN_SQUARE);
- /* Parse the identifier-list. */
+ /* Parse the sb-identifier-list. */
auto_vec<cp_expr, 10> v;
bool attr_diagnosed = false;
int first_attr = -1;
+ int pack = -1;
unsigned int cnt = 0;
if (!cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_SQUARE))
while (true)
{
+ if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
+ {
+ location_t elloc = cp_lexer_peek_token (parser->lexer)->location;
+ if (!processing_template_decl)
+ error_at (elloc, "structured binding pack outside of template");
+ else if (pack != -1)
+ error_at (elloc,
+ "multiple packs in structured binding declaration");
+ else
+ {
+ if (keyword == RID_MAX
+ && cxx_dialect >= cxx17
+ && cxx_dialect < cxx26)
+ pedwarn (elloc, OPT_Wc__26_extensions,
+ "structured binding packs only available with "
+ "%<-std=c++2c%> or %<-std=gnu++2c%>");
+ pack = cnt;
+ }
+ cp_lexer_consume_token (parser->lexer);
+ }
cp_expr e = cp_parser_identifier (parser);
if (e.get_value () == error_mark_node)
break;
tree attr = NULL_TREE;
if (cp_next_tokens_can_be_std_attribute_p (parser))
{
- if (cxx_dialect >= cxx17 && cxx_dialect < cxx26 && !attr_diagnosed)
+ if (keyword == RID_MAX
+ && cxx_dialect >= cxx17
+ && cxx_dialect < cxx26
+ && !attr_diagnosed)
{
pedwarn (cp_lexer_peek_token (parser->lexer)->location,
OPT_Wc__26_extensions,
@@ -16931,7 +16965,7 @@ cp_parser_decomposition_declaration (cp_parser *parser,
&pushed_scope);
tree orig_decl = decl;
- unsigned int i;
+ unsigned int i, j;
cp_expr e;
cp_decl_specifier_seq decl_specs;
clear_decl_specs (&decl_specs);
@@ -16939,6 +16973,7 @@ cp_parser_decomposition_declaration (cp_parser *parser,
if (decl_specifiers->storage_class == sc_static)
decl_specs.storage_class = sc_static;
tree prev = decl;
+ j = 0;
FOR_EACH_VEC_ELT (v, i, e)
{
if (i == 0)
@@ -16969,9 +17004,22 @@ cp_parser_decomposition_declaration (cp_parser *parser,
prev = decl2;
DECL_DECLARED_CONSTEXPR_P (decl2) = DECL_DECLARED_CONSTEXPR_P (decl);
DECL_DECLARED_CONSTINIT_P (decl2) = DECL_DECLARED_CONSTINIT_P (decl);
+ if (j == (unsigned) pack)
+ {
+ tree dtype = cxx_make_type (DECLTYPE_TYPE);
+ DECLTYPE_TYPE_EXPR (dtype) = decl2;
+ DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (dtype) = 1;
+ SET_TYPE_STRUCTURAL_EQUALITY (dtype);
+ tree type = cxx_make_type (TYPE_PACK_EXPANSION);
+ PACK_EXPANSION_PATTERN (type) = dtype;
+ SET_TYPE_STRUCTURAL_EQUALITY (type);
+ PACK_EXPANSION_PARAMETER_PACKS (type) = decl2;
+ TREE_TYPE (decl2) = type;
+ }
}
if (elt_pushed_scope)
pop_scope (elt_pushed_scope);
+ ++j;
}
if (v.is_empty ())
@@ -46300,6 +46348,14 @@ cp_convert_omp_range_for (tree &this_pre_body, tree &sl,
decomp->count = tree_to_uhwi (TREE_OPERAND (v, 1)) + 1;
decomp->decl = decl;
}
+ else if (TREE_CODE (v) == TREE_VEC
+ && DECL_DECOMPOSITION_P (TREE_VEC_ELT (v, 0)))
+ {
+ d = TREE_VEC_ELT (v, 0);
+ decomp = &decomp_d;
+ decomp->count = tree_to_uhwi (TREE_VEC_ELT (v, 1)) + 1;
+ decomp->decl = decl;
+ }
}
do_range_for_auto_deduction (d, init, decomp);
}
@@ -46423,6 +46479,15 @@ cp_convert_omp_range_for (tree &this_pre_body, tree &sl,
decomp->count = tree_to_uhwi (TREE_OPERAND (v, 1)) + 1;
decomp->decl = d;
}
+ else if (TREE_CODE (v) == TREE_VEC
+ && DECL_DECOMPOSITION_P (TREE_VEC_ELT (v, 0)))
+ {
+ tree d = orig_decl;
+ orig_decl = TREE_VEC_ELT (v, 0);
+ decomp = &decomp_d;
+ decomp->count = tree_to_uhwi (TREE_VEC_ELT (v, 1)) + 1;
+ decomp->decl = d;
+ }
}
tree auto_node = type_uses_auto (TREE_TYPE (orig_decl));
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index acfeb81..b6b13ed 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -13981,9 +13981,30 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
else if (is_capture_proxy (parm_pack))
{
arg_pack = retrieve_local_specialization (parm_pack);
+ if (DECL_DECOMPOSITION_P (arg_pack))
+ {
+ orig_arg = arg_pack;
+ goto expand_sb_pack;
+ }
if (DECL_PACK_P (arg_pack))
arg_pack = NULL_TREE;
}
+ else if (DECL_DECOMPOSITION_P (parm_pack))
+ {
+ orig_arg = retrieve_local_specialization (parm_pack);
+ expand_sb_pack:
+ gcc_assert (DECL_DECOMPOSITION_P (orig_arg));
+ if (TREE_TYPE (orig_arg) == error_mark_node)
+ return error_mark_node;
+ gcc_assert (DECL_HAS_VALUE_EXPR_P (orig_arg));
+ arg_pack = DECL_VALUE_EXPR (orig_arg);
+ tree vec = make_tree_vec (TREE_VEC_LENGTH (arg_pack) - 2);
+ if (TREE_VEC_LENGTH (vec))
+ memcpy (TREE_VEC_BEGIN (vec), &TREE_VEC_ELT (arg_pack, 2),
+ TREE_VEC_LENGTH (vec) * sizeof (tree));
+ arg_pack = make_node (NONTYPE_ARGUMENT_PACK);
+ ARGUMENT_PACK_ARGS (arg_pack) = vec;
+ }
else
{
int idx;
@@ -13996,7 +14017,8 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
arg_pack = NULL_TREE;
}
- orig_arg = arg_pack;
+ if (orig_arg == NULL_TREE)
+ orig_arg = arg_pack;
if (arg_pack && TREE_CODE (arg_pack) == ARGUMENT_PACK_SELECT)
arg_pack = ARGUMENT_PACK_SELECT_FROM_PACK (arg_pack);
@@ -14011,8 +14033,8 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
if (arg_pack)
{
- int my_len =
- TREE_VEC_LENGTH (ARGUMENT_PACK_ARGS (arg_pack));
+ int my_len
+ = TREE_VEC_LENGTH (ARGUMENT_PACK_ARGS (arg_pack));
/* Don't bother trying to do a partial substitution with
incomplete packs; we'll try again after deduction. */
@@ -14176,8 +14198,8 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
/* Update the corresponding argument. */
if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args))
- TREE_VEC_ELT (TREE_VEC_ELT (args, level -1 ), idx) =
- TREE_TYPE (pack);
+ TREE_VEC_ELT (TREE_VEC_ELT (args, level -1 ), idx)
+ = TREE_TYPE (pack);
else
TREE_VEC_ELT (args, idx) = TREE_TYPE (pack);
}
@@ -15921,7 +15943,10 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain,
tsubst_flags_t tcomplain = complain;
if (VAR_P (t))
tcomplain |= tf_tst_ok;
- type = tsubst (type, args, tcomplain, in_decl);
+ if (DECL_DECOMPOSITION_P (t) && DECL_PACK_P (t))
+ type = NULL_TREE;
+ else
+ type = tsubst (type, args, tcomplain, in_decl);
/* Substituting the type might have recursively instantiated this
same alias (c++/86171). */
if (use_spec_table && gen_tmpl && DECL_ALIAS_TEMPLATE_P (gen_tmpl)
@@ -15938,6 +15963,17 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain,
{
DECL_INITIALIZED_P (r) = 0;
DECL_TEMPLATE_INSTANTIATED (r) = 0;
+ if (DECL_DECOMPOSITION_P (t) && DECL_PACK_P (t))
+ {
+ tree dtype = cxx_make_type (DECLTYPE_TYPE);
+ DECLTYPE_TYPE_EXPR (dtype) = r;
+ DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (dtype) = 1;
+ SET_TYPE_STRUCTURAL_EQUALITY (dtype);
+ type = cxx_make_type (TYPE_PACK_EXPANSION);
+ PACK_EXPANSION_PATTERN (type) = dtype;
+ SET_TYPE_STRUCTURAL_EQUALITY (type);
+ PACK_EXPANSION_PARAMETER_PACKS (type) = r;
+ }
if (TREE_CODE (type) == FUNCTION_TYPE)
{
/* It may seem that this case cannot occur, since:
@@ -18555,13 +18591,17 @@ tsubst_omp_for_iterator (tree t, int i, tree declv, tree &orig_declv,
if (decl != error_mark_node && DECL_HAS_VALUE_EXPR_P (decl))
{
tree v = DECL_VALUE_EXPR (decl);
- if (TREE_CODE (v) == ARRAY_REF
- && DECL_DECOMPOSITION_P (TREE_OPERAND (v, 0)))
+ if ((TREE_CODE (v) == ARRAY_REF
+ && DECL_DECOMPOSITION_P (TREE_OPERAND (v, 0)))
+ || (TREE_CODE (v) == TREE_VEC
+ && DECL_DECOMPOSITION_P (TREE_VEC_ELT (v, 0))))
{
+ v = (TREE_CODE (v) == ARRAY_REF
+ ? TREE_OPERAND (v, 0) : TREE_VEC_ELT (v, 0));
cp_decomp decomp_d = { NULL_TREE, 0 };
- tree d = tsubst_decl (TREE_OPERAND (v, 0), args, complain);
+ tree d = tsubst_decl (v, args, complain);
maybe_push_decl (d);
- d = tsubst_decomp_names (d, TREE_OPERAND (v, 0), args, complain,
+ d = tsubst_decomp_names (d, v, args, complain,
in_decl, &decomp_d);
decomp = true;
if (d == error_mark_node)
@@ -21220,7 +21260,28 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
++c_inhibit_evaluation_warnings;
/* We only want to compute the number of arguments. */
if (PACK_EXPANSION_P (op))
- expanded = tsubst_pack_expansion (op, args, complain, in_decl);
+ {
+ expanded = NULL_TREE;
+ if (DECL_DECOMPOSITION_P (PACK_EXPANSION_PATTERN (op)))
+ {
+ tree d = PACK_EXPANSION_PATTERN (op);
+ if (DECL_HAS_VALUE_EXPR_P (d))
+ {
+ d = DECL_VALUE_EXPR (d);
+ if (TREE_CODE (d) == TREE_VEC)
+ {
+ tree b = TREE_VEC_ELT (d, 0);
+ if (!type_dependent_expression_p_push (b))
+ {
+ expanded = void_node;
+ len = TREE_VEC_LENGTH (d) - 2;
+ }
+ }
+ }
+ }
+ if (!expanded)
+ expanded = tsubst_pack_expansion (op, args, complain, in_decl);
+ }
else
expanded = tsubst_template_args (ARGUMENT_PACK_ARGS (op),
args, complain, in_decl);
@@ -29050,6 +29111,24 @@ value_dependent_expression_p (tree expression)
case SIZEOF_EXPR:
if (SIZEOF_EXPR_TYPE_P (expression))
return dependent_type_p (TREE_TYPE (TREE_OPERAND (expression, 0)));
+ if (tree p = TREE_OPERAND (expression, 0))
+ if (PACK_EXPANSION_P (p)
+ && DECL_DECOMPOSITION_P (PACK_EXPANSION_PATTERN (p)))
+ {
+ tree d = PACK_EXPANSION_PATTERN (p);
+ if (DECL_HAS_VALUE_EXPR_P (d))
+ {
+ d = DECL_VALUE_EXPR (d);
+ /* [temp.dep.constexpr]/4:
+ Expressions of the following form are value-dependent:
+ sizeof ... ( identifier )
+ unless the identifier is a structured binding pack whose
+ initializer is not dependent. */
+ if (TREE_CODE (d) == TREE_VEC
+ && !type_dependent_expression_p (TREE_VEC_ELT (d, 0)))
+ return false;
+ }
+ }
/* FALLTHRU */
case ALIGNOF_EXPR:
case TYPEID_EXPR:
@@ -29563,6 +29642,22 @@ instantiation_dependent_r (tree *tp, int *walk_subtrees,
tree op = TREE_OPERAND (*tp, 0);
if (code == SIZEOF_EXPR && SIZEOF_EXPR_TYPE_P (*tp))
op = TREE_TYPE (op);
+ else if (code == SIZEOF_EXPR
+ && PACK_EXPANSION_P (op)
+ && DECL_DECOMPOSITION_P (PACK_EXPANSION_PATTERN (op)))
+ {
+ tree d = PACK_EXPANSION_PATTERN (op);
+ if (DECL_HAS_VALUE_EXPR_P (d))
+ {
+ d = DECL_VALUE_EXPR (d);
+ if (TREE_CODE (d) == TREE_VEC
+ && !type_dependent_expression_p (TREE_VEC_ELT (d, 0)))
+ {
+ *walk_subtrees = 0;
+ return NULL_TREE;
+ }
+ }
+ }
if (TYPE_P (op))
{
if (dependent_type_p (op))
diff --git a/gcc/d/ChangeLog b/gcc/d/ChangeLog
index 4fe6418..1217b5d 100644
--- a/gcc/d/ChangeLog
+++ b/gcc/d/ChangeLog
@@ -1,3 +1,7 @@
+2025-08-06 Sam James <sam@gentoo.org>
+
+ * Make-lang.in (ALL_DFLAGS): Don't use ALIASING_FLAGS.
+
2025-07-25 David Malcolm <dmalcolm@redhat.com>
* d-diagnostic.cc: Likewise.
diff --git a/gcc/d/Make-lang.in b/gcc/d/Make-lang.in
index 2d444c9..0ddd524 100644
--- a/gcc/d/Make-lang.in
+++ b/gcc/d/Make-lang.in
@@ -61,7 +61,7 @@ WARN_DFLAGS = -Wall -Wdeprecated
NOEXCEPTION_DFLAGS = $(filter-out -fno-rtti, $(NOEXCEPTION_FLAGS))
ALL_DFLAGS = $(DFLAGS-$@) $(GDCFLAGS) -fversion=IN_GCC $(CHECKING_DFLAGS) \
- $(PICFLAG) $(ALIASING_FLAGS) $(NOEXCEPTION_DFLAGS) $(COVERAGE_FLAGS) \
+ $(PICFLAG) $(NOEXCEPTION_DFLAGS) $(COVERAGE_FLAGS) \
$(WARN_DFLAGS)
DCOMPILE.base = $(GDC) -c $(ALL_DFLAGS) -o $@
diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
index 64c1217..7423224 100644
--- a/gcc/doc/install.texi
+++ b/gcc/doc/install.texi
@@ -393,7 +393,7 @@ Note binutils 2.35 or newer is required for LTO to work correctly
with GNU libtool that includes doing a bootstrap with LTO enabled.
@item gzip version 1.2.4 (or later) or
-@itemx bzip2 version 1.0.2 (or later)
+@itemx xz version 5.0 (or later)
Necessary to uncompress GCC @command{tar} files when source code is
obtained via HTTPS mirror sites.
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 00468a7..33ae98c 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -388,6 +388,7 @@ Objective-C and Objective-C++ Dialects}.
-Winit-self -Winline -Wno-int-conversion -Wint-in-bool-context
-Wno-int-to-pointer-cast -Wno-invalid-memory-model
-Winvalid-pch -Winvalid-utf8 -Wno-unicode -Wjump-misses-init
+-Wkeyword-macro
-Wlarger-than=@var{byte-size} -Wleading-whitespace=@var{kind}
-Wlogical-not-parentheses -Wlogical-op
-Wlong-long -Wno-lto-type-mismatch -Wmain -Wmaybe-uninitialized
@@ -10399,6 +10400,14 @@ Do not warn if certain built-in macros are redefined. This suppresses
warnings for redefinition of @code{__TIMESTAMP__}, @code{__TIME__},
@code{__DATE__}, @code{__FILE__}, and @code{__BASE_FILE__}.
+@opindex Wkeyword-macro
+@opindex Wno-keyword-macro
+@item -Wkeyword-macro
+Warn if a keyword is defined as a macro or undefined.
+For C++ identifiers with special meaning or standard attribute identifiers
+are diagnosed as well. This warning is enabled by default for C++26
+if @code{-Wpedantic} and emits a pedwarn in that case.
+
@opindex Wfree-labels
@opindex Wno-free-labels
@item -Wfree-labels @r{(C and Objective-C only)}
diff --git a/gcc/simplify-rtx.cc b/gcc/simplify-rtx.cc
index c723a07..ee9c048 100644
--- a/gcc/simplify-rtx.cc
+++ b/gcc/simplify-rtx.cc
@@ -8460,14 +8460,10 @@ simplify_context::simplify_gen_subreg (machine_mode outermode, rtx op,
if (GET_CODE (op) == SUBREG
|| GET_CODE (op) == CONCAT
- || GET_MODE (op) == VOIDmode)
- return NULL_RTX;
-
- if (MODE_COMPOSITE_P (outermode)
- && (CONST_SCALAR_INT_P (op)
- || CONST_DOUBLE_AS_FLOAT_P (op)
- || CONST_FIXED_P (op)
- || GET_CODE (op) == CONST_VECTOR))
+ || CONST_SCALAR_INT_P (op)
+ || CONST_DOUBLE_AS_FLOAT_P (op)
+ || CONST_FIXED_P (op)
+ || GET_CODE (op) == CONST_VECTOR)
return NULL_RTX;
if (validate_subreg (outermode, innermode, op, byte))
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 1ac6084..df2c843 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,112 @@
+2025-08-06 Sam James <sam@gentoo.org>
+
+ * g++.dg/cpp26/constexpr-new3.C: Escape '[' and ']'.
+
+2025-08-06 Alexandre Oliva <oliva@adacore.com>
+
+ * gcc.dg/torture/hardbool-ai.c: New.
+ * gcc.dg/torture/hardbool-vi.c: New.
+ * gcc.dg/torture/hardbool.c: Handle NO_BITFIELDS.
+ (add1, preinc, postinc, sub1, predec, postdec): New.
+ (main): Exercise them.
+
+2025-08-06 Martin Uecker <uecker@tugraz.at>
+
+ PR c/108931
+ * gcc.dg/vla-tert-1.c: New test.
+
+2025-08-06 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/121231
+ PR c++/119688
+ PR c++/94511
+ * g++.dg/abi/mangle82.C: New test.
+ * g++.dg/cpp2a/nontype-class73.C: New test.
+
+2025-08-06 Jason Merrill <jason@redhat.com>
+
+ * g++.dg/cpp26/constexpr-new3.C: Tweak diagnostic.
+
+2025-08-06 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/vect/vect-gather-1.c: Adjust to hide N.
+
+2025-08-06 Tejas Belagod <tejas.belagod@arm.com>
+
+ * gcc.target/aarch64/sve/acle/general/cops.c: Fix test.
+
+2025-08-06 Yang Yujie <yangyujie@loongson.cn>
+
+ * gcc.dg/torture/bitint-84.c: New test.
+
+2025-08-06 Yang Yujie <yangyujie@loongson.cn>
+
+ * gcc.dg/torture/bitint-83.c: New test.
+
+2025-08-06 Yang Yujie <yangyujie@loongson.cn>
+
+ * gcc.dg/bitintext.h (BEXTC1): Define. Convert the copied
+ object back to the original type before comparison.
+ (BEXTC): Use BEXTC1 for both the signed and the unsigned case.
+
+2025-08-06 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/121413
+ * gcc.dg/torture/bitint-85.c: New test.
+
+2025-08-06 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/121127
+ * gcc.dg/bitint-125.c: New test.
+
+2025-08-06 Yuao Ma <c8ef@outlook.com>
+
+ * gfortran.dg/c_f_pointer_shape_tests_2.f03: Use the new driver.
+ * gfortran.dg/c_f_pointer_shape_tests_4.f03: Ditto.
+ * gfortran.dg/c_f_pointer_shape_tests_4_driver.c: Removed.
+ * gfortran.dg/c_f_pointer_shape_tests_2_driver.c: Renamed to ...
+ * gfortran.dg/c_f_pointer_shape_tests_driver.c: ... this; format
+ with gcc style.
+
+2025-08-06 Jakub Jelinek <jakub@redhat.com>
+
+ PR preprocessor/120778
+ * c-c++-common/cpp/comment-ff-1.c: New test.
+ * c-c++-common/cpp/comment-vtab-1.c: New test.
+
+2025-08-06 Martin Uecker <uecker@tugraz.at>
+
+ PR c/121217
+ * gcc.dg/pr121217.c: New test.
+
+2025-08-06 Kito Cheng <kito.cheng@sifive.com>
+
+ * gcc.target/riscv/arch-unset-1.c: New test.
+ * gcc.target/riscv/arch-unset-2.c: New test.
+ * gcc.target/riscv/arch-unset-3.c: New test.
+ * gcc.target/riscv/arch-unset-4.c: New test.
+ * gcc.target/riscv/arch-unset-5.c: New test.
+
+2025-08-06 Kwok Cheung Yeung <kcyeung@baylibre.com>
+
+ * c-c++-common/gomp/target-update-iterators-1.c: New.
+ * c-c++-common/gomp/target-update-iterators-2.c: New.
+ * c-c++-common/gomp/target-update-iterators-3.c: New.
+
+2025-08-06 Kwok Cheung Yeung <kcyeung@baylibre.com>
+ Andrew Stubbs <ams@baylibre.com>
+
+ * c-c++-common/gomp/map-6.c (foo): Amend expected error message.
+ * c-c++-common/gomp/target-map-iterators-1.c: New.
+ * c-c++-common/gomp/target-map-iterators-2.c: New.
+ * c-c++-common/gomp/target-map-iterators-3.c: New.
+ * c-c++-common/gomp/target-map-iterators-4.c: New.
+
+2025-08-06 Jerry DeLisle <jvdelisle@gcc.gnu.org>
+
+ PR libfortran/121234
+ * gfortran.dg/pr121234.f90: New test.
+
2025-08-05 Jason Merrill <jason@redhat.com>
PR c++/121068
diff --git a/gcc/testsuite/g++.dg/DRs/dr2575.C b/gcc/testsuite/g++.dg/DRs/dr2575.C
new file mode 100644
index 0000000..f350282
--- /dev/null
+++ b/gcc/testsuite/g++.dg/DRs/dr2575.C
@@ -0,0 +1,51 @@
+// DR 2575 - Undefined behavior when macro-replacing "defined" operator
+// { dg-do preprocess }
+// { dg-options "-pedantic-errors" }
+
+#define A defined
+#if !A(A) // { dg-error "this use of 'defined' may not be portable" }
+#error
+#endif
+#if A(B) // { dg-error "this use of 'defined' may not be portable" }
+#error
+#endif
+#if !A A // { dg-error "this use of 'defined' may not be portable" }
+#error
+#endif
+#if A B // { dg-error "this use of 'defined' may not be portable" }
+#error
+#endif
+#if defined A + B
+#else
+#error
+#endif
+#if defined +B // { dg-error "operator 'defined' requires an identifier" }
+#endif // { dg-error "missing binary operator before token 'B'" "" { target *-*-* } .-1 }
+#if defined 1 // { dg-error "operator 'defined' requires an identifier" }
+#endif
+#if defined // { dg-error "operator 'defined' requires an identifier" }
+#endif
+#if defined (A + B) // { dg-error "missing '\\\)' after 'defined'" }
+#endif // { dg-error "missing binary operator before token 'B'" "" { target *-*-* } .-1 }
+#if defined (+B) // { dg-error "operator 'defined' requires an identifier" }
+#endif // { dg-error "missing binary operator before token 'B'" "" { target *-*-* } .-1 }
+#if defined (1) // { dg-error "operator 'defined' requires an identifier" }
+#endif // { dg-error "missing '\\\(' in expression" "" { target *-*-* } .-1 }
+#if defined () // { dg-error "operator 'defined' requires an identifier" }
+#endif
+#if defined A, B // { dg-error "comma operator in operand of #if" }
+#endif
+#if defined (A), B // { dg-error "comma operator in operand of #if" }
+#endif
+#if (defined A), B // { dg-error "comma operator in operand of #if" }
+#endif
+#if defined (A, B) // { dg-error "missing '\\\)' after 'defined'" }
+#endif // { dg-error "missing binary operator before token 'B'" "" { target *-*-* } .-1 }
+#if defined (A) + B
+#else
+#error
+#endif
+#if (defined A) + B
+#else
+#error
+#endif
diff --git a/gcc/testsuite/g++.dg/DRs/dr2576.C b/gcc/testsuite/g++.dg/DRs/dr2576.C
new file mode 100644
index 0000000..ed53a08
--- /dev/null
+++ b/gcc/testsuite/g++.dg/DRs/dr2576.C
@@ -0,0 +1,47 @@
+// DR 2576 - Undefined behavior with macro-expanded #include directives
+// { dg-do preprocess }
+// { dg-options "-pedantic-errors" }
+
+#define A <cstddef>
+#include A
+#define B "cstddef"
+#include B
+#define C(x) #x
+#define D(x) C(x)
+#include D(cstddef)
+#include "cstddef" "" // { dg-error "extra tokens at end of '#include' directive" }
+#include "cstddef"".h" // { dg-error "extra tokens at end of '#include' directive" }
+#include // { dg-error "'#include' expects '\"FILENAME\"' or '<FILENAME>'" }
+#include E // { dg-error "'#include' expects '\"FILENAME\"' or '<FILENAME>'" }
+#include <cstddef
+ // { dg-error "missing terminating '>' character" "" { target *-*-* } .-1 }
+#include "cstddef
+ // { dg-error "missing terminating \" character" "" { target *-*-* } .-1 }
+ // { dg-error "'#include' expects '\"FILENAME\"' or '<FILENAME>'" "" { target *-*-* } .-2 }
+#define F cstddef
+#include F // { dg-error "'#include' expects '\"FILENAME\"' or '<FILENAME>'" }
+// There is implementation divergence on the following cases (G H through M N)
+// between e.g. GCC and clang++. clang++ fails on trying to include ' cstddef'
+// and 'cstd def' and 'stddef .h' and 'cstddef ' headers.
+// https://eel.is/c++draft/cpp.include#7.sentence-3 makes the whitespace
+// handling implementation defined and the way GCC handles it can allow
+// certain use cases which aren't otherwise possible. One can still
+// insert spaces into the <> filenames if it is from the same macro.
+#define G <
+#define H cstddef>
+#include G H
+#define I <cstd
+#define J def>
+#include I J
+#define K <stddef
+#define L .h>
+#include K L
+#define M <cstddef
+#define N >
+#include M N
+#define O <cstddef> <cstddef>
+#include O // { dg-error "extra tokens at end of '#include' directive" }
+#define P "cstddef" ""
+#include P // { dg-error "extra tokens at end of '#include' directive" }
+#define Q "cstddef"".h"
+#include Q // { dg-error "extra tokens at end of '#include' directive" }
diff --git a/gcc/testsuite/g++.dg/DRs/dr2577-1.C b/gcc/testsuite/g++.dg/DRs/dr2577-1.C
new file mode 100644
index 0000000..784b6a8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/DRs/dr2577-1.C
@@ -0,0 +1,40 @@
+// DR 2577 - Undefined behavior for preprocessing directives in macro arguments
+// { dg-do preprocess }
+// { dg-options "-pedantic-errors" }
+
+#define A(x)
+#define B(x, y)
+A(
+#if 1 // { dg-error "embedding a directive within macro arguments is not portable" }
+1
+#else // { dg-error "embedding a directive within macro arguments is not portable" }
+2
+#endif // { dg-error "embedding a directive within macro arguments is not portable" }
+)
+B(1,
+#line 234 // { dg-error "embedding a directive within macro arguments is not portable" }
+)
+#line 18
+A(
+#define C 1 // { dg-error "embedding a directive within macro arguments is not portable" }
+)
+A(
+#undef C // { dg-error "embedding a directive within macro arguments is not portable" }
+)
+B(42,
+# 234 "dr2577-1.C" // { dg-error "embedding a directive within macro arguments is not portable" }
+) // { dg-error "style of line directive is a GCC extension" "" { target *-*-* } .-1 }
+#line 28 "dr2577-1.C"
+B(
+#warning "foobar" // { dg-error "embedding a directive within macro arguments is not portable" }
+, 12) // { dg-error "'#warning' before C\\\+\\\+23 is a GCC extension" "" { target c++20_down } .-1 }
+ // { dg-warning "#warning \"foobar\"" "" { target *-*-* } .-2 }
+A(
+#pragma GCC diagnostics push // { dg-error "embedding a directive within macro arguments is not portable" }
+)
+B(5,
+#pragma GCC diagnostics pop // { dg-error "embedding a directive within macro arguments is not portable" }
+)
+A(
+#error foobar // { dg-error "embedding a directive within macro arguments is not portable" }
+) // { dg-error "#error foobar" "" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/g++.dg/DRs/dr2577-2.C b/gcc/testsuite/g++.dg/DRs/dr2577-2.C
new file mode 100644
index 0000000..e54006a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/DRs/dr2577-2.C
@@ -0,0 +1,13 @@
+// DR 2577 - Undefined behavior for preprocessing directives in macro arguments
+// { dg-do preprocess }
+// { dg-options "-pedantic-errors" }
+
+#define A(x, y, z) x + y + z
+int a = A(
+#include "dr2577-2.h" // { dg-error "embedding a directive within macro arguments is not portable" }
+,
+#include "dr2577-2.h"
+,
+#include "dr2577-2.h"
+);
+// { dg-error "unterminated argument list invoking macro 'A'" "" { target *-*-* } 0 }
diff --git a/gcc/testsuite/g++.dg/DRs/dr2577-2.h b/gcc/testsuite/g++.dg/DRs/dr2577-2.h
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/DRs/dr2577-2.h
@@ -0,0 +1 @@
+1
diff --git a/gcc/testsuite/g++.dg/DRs/dr2577-3.C b/gcc/testsuite/g++.dg/DRs/dr2577-3.C
new file mode 100644
index 0000000..6ebf419
--- /dev/null
+++ b/gcc/testsuite/g++.dg/DRs/dr2577-3.C
@@ -0,0 +1,7 @@
+// DR 2577 - Undefined behavior for preprocessing directives in macro arguments
+// { dg-do preprocess }
+// { dg-options "-pedantic-errors" }
+
+#define A(x) x
+int a = A(
+#include "dr2577-3.h" // { dg-error "embedding a directive within macro arguments is not portable" }
diff --git a/gcc/testsuite/g++.dg/DRs/dr2577-3.h b/gcc/testsuite/g++.dg/DRs/dr2577-3.h
new file mode 100644
index 0000000..5e36ce0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/DRs/dr2577-3.h
@@ -0,0 +1 @@
+1)
diff --git a/gcc/testsuite/g++.dg/cpp26/constexpr-new3.C b/gcc/testsuite/g++.dg/cpp26/constexpr-new3.C
index 7466199..c79060f 100644
--- a/gcc/testsuite/g++.dg/cpp26/constexpr-new3.C
+++ b/gcc/testsuite/g++.dg/cpp26/constexpr-new3.C
@@ -37,7 +37,7 @@ baz ()
{
std::allocator<int> a;
auto b = a.allocate (2);
- new (b) long (42); // { dg-error "accessing value of 'int [2]' object through a 'long int' glvalue in a constant expression" }
+ new (b) long (42); // { dg-error "accessing value of 'int \\\[2\\\]' object through a 'long int' glvalue in a constant expression" }
a.deallocate (b, 2);
return true;
}
diff --git a/gcc/testsuite/g++.dg/cpp26/decomp13.C b/gcc/testsuite/g++.dg/cpp26/decomp13.C
new file mode 100644
index 0000000..d01590f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp26/decomp13.C
@@ -0,0 +1,52 @@
+// P1061R10 - Structured Bindings can introduce a Pack
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+namespace std {
+ template<typename T> struct tuple_size;
+ template<int, typename> struct tuple_element;
+}
+
+struct S { int a, b, c, d; };
+struct T {
+ int a[5];
+ template <int I> int &get () { return a[I]; }
+};
+
+template<> struct std::tuple_size<T> { static const int value = 5; };
+template<int I> struct std::tuple_element<I,T> { using type = int; };
+
+template <int N>
+void
+foo ()
+{
+ auto [a, ...b, c] = S (); // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ auto [...d] = S (); // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ auto [...e, f, ...g, h] = S (); // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ // { dg-error "multiple packs in structured binding declaration" "" { target *-*-* } .-2 }
+ auto [i, j, k, l, ...m, n] = S (); // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ // { dg-error "6 names provided for structured binding" "" { target *-*-* } .-2 }
+ // { dg-message "while 'S' decomposes into 4 elements" "" { target *-*-* } .-3 }
+ auto [o, ...p, q, r, s] = S (); // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ auto [t, u, v, w, x, ...y, z] = T (); // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ // { dg-error "7 names provided for structured binding" "" { target *-*-* } .-2 }
+ // { dg-message "while 'T' decomposes into 5 elements" "" { target *-*-* } .-3 }
+ int aa[] = { 1, 2, 3 };
+ const auto & [ab, ...ac, ad, ae, af] = aa; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ // { dg-error "5 names provided for structured binding" "" { target *-*-* } .-2 }
+ // { dg-message "while 'const int \\\[3\\\]' decomposes into 3 elements" "" { target *-*-* } .-3 }
+}
+
+void
+bar ()
+{
+ auto [a, ...b, c, d] = S (); // { dg-error "structured binding pack outside of template" }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+}
diff --git a/gcc/testsuite/g++.dg/cpp26/decomp14.C b/gcc/testsuite/g++.dg/cpp26/decomp14.C
new file mode 100644
index 0000000..f626ec9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp26/decomp14.C
@@ -0,0 +1,474 @@
+// P1061R10 - Structured Bindings can introduce a Pack
+// { dg-do run { target c++11 } }
+// { dg-options "" }
+
+struct S {
+ int a; long long b; short c;
+ explicit operator bool () const noexcept { return true; }
+};
+namespace std {
+ template <typename T> struct tuple_size;
+ template <int, typename> struct tuple_element;
+}
+struct T {
+ short c; int a; long long b;
+ template <int I>
+ typename std::tuple_element<I, T>::type &get ();
+ template <int I>
+ typename std::tuple_element<I, const T>::type &get () const;
+ explicit operator bool () const noexcept { return false; }
+};
+template <>
+struct std::tuple_size<T> { static constexpr int value = 3; };
+template <>
+struct std::tuple_element<0, T> { typedef int type; };
+template <>
+struct std::tuple_element<1, T> { typedef long long type; };
+template <>
+struct std::tuple_element<2, T> { typedef short type; };
+template <>
+std::tuple_element<0, T>::type &T::get <0> () { return a; }
+template <>
+std::tuple_element<1, T>::type &T::get <1> () { return b; }
+template <>
+std::tuple_element<2, T>::type &T::get <2> () { return c; }
+template <>
+struct std::tuple_size<const T> { static constexpr int value = 3; };
+template <>
+struct std::tuple_element<0, const T> { typedef const int type; };
+template <>
+struct std::tuple_element<1, const T> { typedef const long long type; };
+template <>
+struct std::tuple_element<2, const T> { typedef const short type; };
+template <>
+std::tuple_element<0, const T>::type &T::get <0> () const { return a; }
+template <>
+std::tuple_element<1, const T>::type &T::get <1> () const { return b; }
+template <>
+std::tuple_element<2, const T>::type &T::get <2> () const { return c; }
+template <typename T, typename U>
+struct same_type { static const bool value = false; };
+template <typename T>
+struct same_type<T, T> { static const bool value = true; };
+
+int
+sum ()
+{
+ return 0;
+}
+
+template <typename T, typename ...A>
+T
+sum (T x, A... y)
+{
+ return x + sum (y...);
+}
+
+template <typename T>
+T
+square (T x)
+{
+ return x * x;
+}
+
+template <typename T>
+T &
+ref (T &x)
+{
+ return x;
+}
+
+using size_t = decltype (sizeof 0);
+
+template <int N>
+size_t
+foo ()
+{
+ S s = S { 1, 2, 3 };
+ auto [sa, sb, sc] = S { 1, 2, 3 }; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ static_assert (same_type <decltype (sa), int>::value, "");
+ static_assert (same_type <decltype (sb), long long>::value, "");
+ static_assert (same_type <decltype (sc), short>::value, "");
+ auto [sd, ...se] = S { 1, 2, 3 }; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ constexpr size_t ses = sizeof... (se);
+ static_assert (sizeof... (se) == 2, "");
+ static_assert (same_type <decltype (sd), int>::value, "");
+ static_assert (same_type <decltype (se...[0]), long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (se...[1]), short>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ const auto & [...sf [[]], sg] = s; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 }
+ static_assert (sizeof... (sf) == 2, "");
+ static_assert (same_type <decltype (sf...[0]), const int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (sf...[1]), const long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (sg), const short>::value, "");
+ auto [sh, si, sj [[]], ...sk] = S { 1, 2, 3 };// { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 }
+ static_assert (sizeof... (sk) == 0, "");
+ static_assert (same_type <decltype (sh), int>::value, "");
+ static_assert (same_type <decltype (si), long long>::value, "");
+ static_assert (same_type <decltype (sj), short>::value, "");
+ auto && [sl, ...sm [[maybe_unused]], sn] = s; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 }
+ static_assert (sizeof... (sm) == 1, "");
+ static_assert (same_type <decltype (sl), int>::value, "");
+ static_assert (same_type <decltype (sm...[0]), long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (sn), short>::value, "");
+ auto [...so] = S { 1, 2, 3 }; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ static_assert (sizeof... (so) == 3, "");
+ static_assert (same_type <decltype (so...[0]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (so...[1]), long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (so...[2]), short>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ auto [...sp, sq, sr, ss [[maybe_unused]]] = S { 1, 2, 3 };// { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 }
+ static_assert (sizeof... (sp) == 0, "");
+ static_assert (same_type <decltype (sq), int>::value, "");
+ static_assert (same_type <decltype (sr), long long>::value, "");
+ static_assert (same_type <decltype (ss), short>::value, "");
+ auto [st, ...su, sv, sw] = S { 1, 2, 3 };// { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ static_assert (sizeof... (su) == 0, "");
+ static_assert (same_type <decltype (st), int>::value, "");
+ static_assert (same_type <decltype (sv), long long>::value, "");
+ static_assert (same_type <decltype (sw), short>::value, "");
+ if (sa != 1 || sb != 2 || sc != 3
+ || sd != 1 || se...[0] != 2 || se...[1] != 3 // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ || sf...[0] != 1 || sf...[1] != 2 || sg != 3 // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ || sh != 1 || si != 2 || sj != 3
+ || sl != 1 || sm...[0] != 2 || sn != 3 // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ || so...[0] != 1 || so...[1] != 2 || so...[2] != 3// { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ || sq != 1 || sr != 2 || ss != 3
+ || st != 1 || sv != 2 || sw != 3
+ || sum (se...) != 5
+ || sum <decltype (se)...> (se...) != 5
+ || sum (square (square (se))...) != 97
+ || sum (sf...) != 3
+ || sum (sk...) != 0
+ || sum (sm...) != 2
+ || sum (so...) != 6
+ || sum <decltype (so)...> (so...) != 6
+ || sum (square (so)...) != 14
+ || sum (sp...) != 0
+ || sum (su...) != 0
+ || (se + ...) != 5 // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ || (... + sf) != 3 // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ || (0 + ... + sk) != 0 // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ || (sm + ... + 0) != 2 // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ || (so + ...) != 6 // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ || (sp + ... + 0) != 0 // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ || (0 + ... + su) != 0) // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ __builtin_abort ();
+ S s2[] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
+ int i = 0;
+ for (auto [sx, ...sy [[]]] : s2) // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ { // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 }
+ static_assert (sizeof... (sy) == 2, "");
+ static_assert (same_type <decltype (sx), int>::value, "");
+ static_assert (same_type <decltype (sy...[0]), long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (sy...[1]), short>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ if (sx != i * 3 + 1 || sum (sy...) != i * 6 + 5)
+ __builtin_abort ();
+ auto fn1 = [&] () { if (sum (sy...) != i * 6 + 5) __builtin_abort (); }; // { dg-warning "captured structured bindings are" "" { target c++17_down } }
+ fn1 ();
+ auto fn2 = [&sy..., &i] () { if (sum (sy...) != i * 6 + 5) __builtin_abort (); }; // { dg-warning "captured structured bindings are" "" { target c++17_down } }
+ fn2 ();
+ auto fn3 = [&...sy2 = sy, &i] () { if (sum (sy2...) != i * 6 + 5) __builtin_abort (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } }
+ fn3 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 }
+ auto fn4 = [&...sy3 = ref (sy), &i] () { if (sum (sy3...) != i * 6 + 5) __builtin_abort (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } }
+ fn4 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 }
+ auto fn5 = [=] () { if (sum (sy...) != i * 6 + 5) __builtin_abort (); }; // { dg-warning "captured structured bindings are" "" { target c++17_down } }
+ fn5 ();
+ auto fn6 = [sy..., i] () { if (sum (sy...) != i * 6 + 5) __builtin_abort (); }; // { dg-warning "captured structured bindings are" "" { target c++17_down } }
+ fn6 ();
+ auto fn7 = [...sy2 = sy, i] () { if (sum (sy2...) != i * 6 + 5) __builtin_abort (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } }
+ fn7 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 }
+ auto fn8 = [...sy3 = square (sy), i] () { if (sum (sy3...) != (i * 3 + 2) * (i * 3 + 2) + (i * 3 + 3) * (i * 3 + 3)) __builtin_abort (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } }
+ fn8 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 }
+ auto fn9 = [&] () { auto fn = [&] () { if (sum (sy...) != i * 6 + 5) __builtin_abort (); }; fn (); }; // { dg-warning "captured structured bindings are" "" { target c++17_down } }
+ fn9 ();
+ auto fn10 = [&sy..., &i] () { auto fn = [&] () { if (sum (sy...) != i * 6 + 5) __builtin_abort (); }; fn (); }; // { dg-warning "captured structured bindings are" "" { target c++17_down } }
+ fn10 ();
+ auto fn11 = [&] () { auto fn = [&...sy2 = sy, &i] () { if (sum (sy2...) != i * 6 + 5) __builtin_abort (); }; fn (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } }
+ fn11 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 }
+ // { dg-warning "captured structured bindings are" "" { target c++17_down } .-2 }
+ auto fn12 = [&sy..., &i] () { auto fn = [&...sy3 = ref (sy), &i] () { if (sum (sy3...) != i * 6 + 5) __builtin_abort (); }; fn (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } }
+ fn12 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 }
+ // { dg-warning "captured structured bindings are" "" { target c++17_down } .-2 }
+ auto fn13 = [=] () { auto fn = [=] () { if (sum (sy...) != i * 6 + 5) __builtin_abort (); }; fn (); }; // { dg-warning "captured structured bindings are" "" { target c++17_down } }
+ fn13 ();
+ auto fn14 = [sy..., i] () { auto fn = [=] () { if (sum (sy...) != i * 6 + 5) __builtin_abort (); }; fn (); }; // { dg-warning "captured structured bindings are" "" { target c++17_down } }
+ fn14 ();
+ auto fn15 = [=] () { auto fn = [...sy2 = sy, i] () { if (sum (sy2...) != i * 6 + 5) __builtin_abort (); }; fn (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } }
+ fn15 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 }
+ // { dg-warning "captured structured bindings are" "" { target c++17_down } .-2 }
+ auto fn16 = [&sy..., &i] () { auto fn = [...sy3 = square (sy), i] () { if (sum (sy3...) != (i * 3 + 2) * (i * 3 + 2) + (i * 3 + 3) * (i * 3 + 3)) __builtin_abort (); }; fn (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } }
+ fn16 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 }
+ // { dg-warning "captured structured bindings are" "" { target c++17_down } .-2 }
+ ++i;
+ }
+ i = 0;
+ for (auto [...sz] : s2) // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ { // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ static_assert (sizeof... (sz) == 3, "");
+ static_assert (same_type <decltype (sz...[0]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (sz...[1]), long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (sz...[2]), short>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ if (sum (sz...) != i * 9 + 6)
+ __builtin_abort ();
+ auto fn = [=] () { if (sum (sz...) != i * 9 + 6) __builtin_abort (); }; // { dg-warning "captured structured bindings are" "" { target c++17_down } }
+ fn ();
+ ++i;
+ }
+ if (auto [...sx, sy] = s) // { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+ {
+ static_assert (sizeof... (sx) == 2, "");
+ static_assert (same_type <decltype (sx...[0]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (sx...[1]), long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (sy), short>::value, "");
+ if (sum (sx...) != 3 || sy != 3)
+ __builtin_abort ();
+ }
+ else
+ __builtin_abort ();
+ T t = T { 3, 1, 2 };
+ auto [ta, tb, tc] = T { 3, 1, 2 }; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ static_assert (same_type <decltype (ta), int>::value, "");
+ static_assert (same_type <decltype (tb), long long>::value, "");
+ static_assert (same_type <decltype (tc), short>::value, "");
+ auto [td [[maybe_unused]], ...te] = T { 3, 1, 2 }; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 }
+ static_assert (sizeof... (te) == 2, "");
+ static_assert (same_type <decltype (td), int>::value, "");
+ static_assert (same_type <decltype (te...[0]), long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (te...[1]), short>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ auto [...tf [[maybe_unused]], tg] = T { 3, 1, 2 }; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 }
+ static_assert (sizeof... (tf) == 2, "");
+ static_assert (same_type <decltype (tf...[0]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (tf...[1]), long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (tg), short>::value, "");
+ const auto & [th, ti, tj, ...tk] = t; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ static_assert (sizeof... (tk) == 0, "");
+ static_assert (same_type <decltype (th), const int>::value, "");
+ static_assert (same_type <decltype (ti), const long long>::value, "");
+ static_assert (same_type <decltype (tj), const short>::value, "");
+ auto [tl [[]], ...tm [[]], tn [[]]] = T { 3, 1, 2 }; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 }
+ static_assert (sizeof... (tm) == 1, "");
+ static_assert (same_type <decltype (tl), int>::value, "");
+ static_assert (same_type <decltype (tm...[0]), long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (tn), short>::value, "");
+ auto && [...to] = t; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ static_assert (sizeof... (to) == 3, "");
+ static_assert (same_type <decltype (to...[0]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (to...[1]), long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (to...[2]), short>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ auto [...tp, tq [[]], tr, ts] = T { 3, 1, 2 };// { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 }
+ static_assert (sizeof... (tp) == 0, "");
+ static_assert (same_type <decltype (tq), int>::value, "");
+ static_assert (same_type <decltype (tr), long long>::value, "");
+ static_assert (same_type <decltype (ts), short>::value, "");
+ auto [tt, ...tu [[]], tv, tw] = T { 3, 1, 2 };// { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 }
+ static_assert (sizeof... (tu) == 0, "");
+ static_assert (same_type <decltype (tt), int>::value, "");
+ static_assert (same_type <decltype (tv), long long>::value, "");
+ static_assert (same_type <decltype (tw), short>::value, "");
+ if (ta != 1 || tb != 2 || tc != 3
+ || td != 1 || te...[0] != 2 || te...[1] != 3 // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ || tf...[0] != 1 || tf...[1] != 2 || tg != 3 // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ || th != 1 || ti != 2 || tj != 3
+ || tl != 1 || tm...[0] != 2 || tn != 3 // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ || to...[0] != 1 || to...[1] != 2 || to...[2] != 3// { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ || tq != 1 || tr != 2 || ts != 3
+ || tt != 1 || tv != 2 || tw != 3
+ || sum (te...) != 5
+ || sum <decltype (te)...> (te...) != 5
+ || sum (square (square (te))...) != 97
+ || sum (tf...) != 3
+ || sum (tk...) != 0
+ || sum (tm...) != 2
+ || sum (to...) != 6
+ || sum <decltype (to)...> (to...) != 6
+ || sum (square (to)...) != 14
+ || sum (tp...) != 0
+ || sum (tu...) != 0
+ || (te + ...) != 5 // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ || (... + tf) != 3 // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ || (0 + ... + tk) != 0 // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ || (tm + ... + 0) != 2 // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ || (to + ...) != 6 // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ || (tp + ... + 0) != 0 // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ || (0 + ... + tu) != 0) // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ __builtin_abort ();
+ T t2[] = { { 3, 1, 2 }, { 6, 4, 5 }, { 9, 7, 8 } };
+ i = 0;
+ for (auto [tx, ...ty] : t2) // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ { // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ static_assert (sizeof... (ty) == 2, "");
+ static_assert (same_type <decltype (tx), int>::value, "");
+ static_assert (same_type <decltype (ty...[0]), long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (ty...[1]), short>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ if (tx != i * 3 + 1 || sum (ty...) != i * 6 + 5)
+ __builtin_abort ();
+ auto fn1 = [&] () { if (sum (ty...) != i * 6 + 5) __builtin_abort (); };
+ fn1 ();
+ auto fn2 = [&ty..., &i] () { if (sum (ty...) != i * 6 + 5) __builtin_abort (); }; // { dg-warning "captured structured bindings are" "" { target c++17_down } }
+ fn2 ();
+ auto fn3 = [&...ty2 = ty, &i] () { if (sum (ty2...) != i * 6 + 5) __builtin_abort (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } }
+ fn3 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 }
+ auto fn4 = [&...ty3 = ref (ty), &i] () { if (sum (ty3...) != i * 6 + 5) __builtin_abort (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } }
+ fn4 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 }
+ auto fn5 = [=] () { if (sum (ty...) != i * 6 + 5) __builtin_abort (); };
+ fn5 ();
+ auto fn6 = [ty..., i] () { if (sum (ty...) != i * 6 + 5) __builtin_abort (); }; // { dg-warning "captured structured bindings are" "" { target c++17_down } }
+ fn6 ();
+ auto fn7 = [...ty2 = ty, i] () { if (sum (ty2...) != i * 6 + 5) __builtin_abort (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } }
+ fn7 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 }
+ auto fn8 = [...ty3 = square (ty), i] () { if (sum (ty3...) != (i * 3 + 2) * (i * 3 + 2) + (i * 3 + 3) * (i * 3 + 3)) __builtin_abort (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } }
+ fn8 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 }
+ auto fn9 = [&] () { auto fn = [&] () { if (sum (ty...) != i * 6 + 5) __builtin_abort (); }; fn (); };
+ fn9 ();
+ auto fn10 = [&ty..., &i] () { auto fn = [&] () { if (sum (ty...) != i * 6 + 5) __builtin_abort (); }; fn (); }; // { dg-warning "captured structured bindings are" "" { target c++17_down } }
+ fn10 ();
+ auto fn11 = [&] () { auto fn = [&...ty2 = ty, &i] () { if (sum (ty2...) != i * 6 + 5) __builtin_abort (); }; fn (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } }
+ fn11 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 }
+ auto fn12 = [&ty..., &i] () { auto fn = [&...ty3 = ref (ty), &i] () { if (sum (ty3...) != i * 6 + 5) __builtin_abort (); }; fn (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } }
+ fn12 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 }
+ // { dg-warning "captured structured bindings are" "" { target c++17_down } .-2 }
+ auto fn13 = [=] () { auto fn = [=] () { if (sum (ty...) != i * 6 + 5) __builtin_abort (); }; fn (); };
+ fn13 ();
+ auto fn14 = [ty..., i] () { auto fn = [=] () { if (sum (ty...) != i * 6 + 5) __builtin_abort (); }; fn (); }; // { dg-warning "captured structured bindings are" "" { target c++17_down } }
+ fn14 ();
+ auto fn15 = [=] () { auto fn = [...ty2 = ty, i] () { if (sum (ty2...) != i * 6 + 5) __builtin_abort (); }; fn (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } }
+ fn15 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 }
+ auto fn16 = [&ty..., &i] () { auto fn = [...ty3 = square (ty), i] () { if (sum (ty3...) != (i * 3 + 2) * (i * 3 + 2) + (i * 3 + 3) * (i * 3 + 3)) __builtin_abort (); }; fn (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } }
+ fn16 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 }
+ // { dg-warning "captured structured bindings are" "" { target c++17_down } .-2 }
+ ++i;
+ }
+ i = 0;
+ for (auto [...tz] : t2) // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ { // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ static_assert (sizeof... (tz) == 3, "");
+ static_assert (same_type <decltype (tz...[0]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (tz...[1]), long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (tz...[2]), short>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ if (sum (tz...) != i * 9 + 6)
+ __builtin_abort ();
+ auto fn = [=] () { if (sum (tz...) != i * 9 + 6) __builtin_abort (); };
+ fn ();
+ ++i;
+ }
+ if (auto [...tx [[maybe_unused]], ty] = t) // { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+ __builtin_abort ();
+ else
+ {
+ static_assert (sizeof... (tx) == 2, "");
+ static_assert (same_type <decltype (tx...[0]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (tx...[1]), long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (ty), short>::value, "");
+ if (sum (tx...) != 3 || ty != 3)
+ __builtin_abort ();
+ }
+ int a[3] = { 1, 2, 3 };
+ auto [aa, ab, ac] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ static_assert (same_type <decltype (aa), int>::value, "");
+ static_assert (same_type <decltype (ab), int>::value, "");
+ static_assert (same_type <decltype (ac), int>::value, "");
+ auto [ad [[maybe_unused]], ...ae [[maybe_unused]]] = a; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 }
+ static_assert (sizeof... (ae) == 2, "");
+ static_assert (same_type <decltype (ad), int>::value, "");
+ static_assert (same_type <decltype (ae...[0]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (ae...[1]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ auto [...af, ag] = a; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ static_assert (sizeof... (af) == 2, "");
+ static_assert (same_type <decltype (af...[0]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (af...[1]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (ag), int>::value, "");
+ auto [ah, ai [[]], aj, ...ak [[]]] = a; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 }
+ static_assert (sizeof... (ak) == 0, "");
+ static_assert (same_type <decltype (ah), int>::value, "");
+ static_assert (same_type <decltype (ai), int>::value, "");
+ static_assert (same_type <decltype (aj), int>::value, "");
+ auto [al, ...am [[]], an] = a;// { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 }
+ static_assert (sizeof... (am) == 1, "");
+ static_assert (same_type <decltype (al), int>::value, "");
+ static_assert (same_type <decltype (am...[0]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (an), int>::value, "");
+ const auto &[...ao] = a; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ static_assert (sizeof... (ao) == 3, "");
+ static_assert (same_type <decltype (ao...[0]), const int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (ao...[1]), const int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (ao...[2]), const int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ auto &&[...ap, aq, ar [[]], as] = a;// { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 }
+ static_assert (sizeof... (ap) == 0, "");
+ static_assert (same_type <decltype (aq), int>::value, "");
+ static_assert (same_type <decltype (ar), int>::value, "");
+ static_assert (same_type <decltype (as), int>::value, "");
+ auto [at, ...au, av, aw] = a; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ static_assert (sizeof... (au) == 0, "");
+ static_assert (same_type <decltype (at), int>::value, "");
+ static_assert (same_type <decltype (av), int>::value, "");
+ static_assert (same_type <decltype (aw), int>::value, "");
+ if (aa != 1 || ab != 2 || ac != 3
+ || ad != 1 || ae...[0] != 2 || ae...[1] != 3 // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ || af...[0] != 1 || af...[1] != 2 || ag != 3 // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ || ah != 1 || ai != 2 || aj != 3
+ || al != 1 || am...[0] != 2 || an != 3 // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ || ao...[0] != 1 || ao...[1] != 2 || ao...[2] != 3// { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ || aq != 1 || ar != 2 || as != 3
+ || at != 1 || av != 2 || aw != 3
+ || sum (ae...) != 5
+ || sum <decltype (ae)...> (ae...) != 5
+ || sum (square (square (ae))...) != 97
+ || sum (af...) != 3
+ || sum (ak...) != 0
+ || sum (am...) != 2
+ || sum (ao...) != 6
+ || sum <decltype (ao)...> (ao...) != 6
+ || sum (square (ao)...) != 14
+ || sum (ap...) != 0
+ || sum (au...) != 0
+ || (ae + ...) != 5 // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ || (... + af) != 3 // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ || (0 + ... + ak) != 0 // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ || (am + ... + 0) != 2 // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ || (ao + ...) != 6 // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ || (ap + ... + 0) != 0 // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ || (0 + ... + au) != 0) // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ __builtin_abort ();
+ return ses;
+}
+
+int
+main ()
+{
+ if (foo <0> () != 2)
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp26/decomp15.C b/gcc/testsuite/g++.dg/cpp26/decomp15.C
new file mode 100644
index 0000000..9bb55b3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp26/decomp15.C
@@ -0,0 +1,474 @@
+// P1061R10 - Structured Bindings can introduce a Pack
+// { dg-do run { target c++11 } }
+// { dg-options "" }
+
+struct S {
+ int a; long long b; short c;
+ explicit operator bool () const noexcept { return true; }
+};
+namespace std {
+ template <typename T> struct tuple_size;
+ template <int, typename> struct tuple_element;
+}
+struct T {
+ short c; int a; long long b;
+ template <int I>
+ typename std::tuple_element<I, T>::type &get ();
+ template <int I>
+ typename std::tuple_element<I, const T>::type &get () const;
+ explicit operator bool () const noexcept { return false; }
+};
+template <>
+struct std::tuple_size<T> { static constexpr int value = 3; };
+template <>
+struct std::tuple_element<0, T> { typedef int type; };
+template <>
+struct std::tuple_element<1, T> { typedef long long type; };
+template <>
+struct std::tuple_element<2, T> { typedef short type; };
+template <>
+std::tuple_element<0, T>::type &T::get <0> () { return a; }
+template <>
+std::tuple_element<1, T>::type &T::get <1> () { return b; }
+template <>
+std::tuple_element<2, T>::type &T::get <2> () { return c; }
+template <>
+struct std::tuple_size<const T> { static constexpr int value = 3; };
+template <>
+struct std::tuple_element<0, const T> { typedef const int type; };
+template <>
+struct std::tuple_element<1, const T> { typedef const long long type; };
+template <>
+struct std::tuple_element<2, const T> { typedef const short type; };
+template <>
+std::tuple_element<0, const T>::type &T::get <0> () const { return a; }
+template <>
+std::tuple_element<1, const T>::type &T::get <1> () const { return b; }
+template <>
+std::tuple_element<2, const T>::type &T::get <2> () const { return c; }
+template <typename T, typename U>
+struct same_type { static const bool value = false; };
+template <typename T>
+struct same_type<T, T> { static const bool value = true; };
+
+int
+sum ()
+{
+ return 0;
+}
+
+template <typename T, typename ...A>
+T
+sum (T x, A... y)
+{
+ return x + sum (y...);
+}
+
+template <typename T>
+T
+square (T x)
+{
+ return x * x;
+}
+
+template <typename T>
+T &
+ref (T &x)
+{
+ return x;
+}
+
+using size_t = decltype (sizeof 0);
+
+template <typename S, typename T, typename U>
+size_t
+foo ()
+{
+ S s = S { 1, 2, 3 };
+ auto [sa, sb, sc] = S { 1, 2, 3 }; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ static_assert (same_type <decltype (sa), int>::value, "");
+ static_assert (same_type <decltype (sb), long long>::value, "");
+ static_assert (same_type <decltype (sc), short>::value, "");
+ auto [sd, ...se] = S { 1, 2, 3 }; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ static_assert (sizeof... (se) == 2, "");
+ static_assert (same_type <decltype (sd), int>::value, "");
+ static_assert (same_type <decltype (se...[0]), long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (se...[1]), short>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ const auto & [...sf [[]], sg] = s; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 }
+ static_assert (sizeof... (sf) == 2, "");
+ static_assert (same_type <decltype (sf...[0]), const int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (sf...[1]), const long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (sg), const short>::value, "");
+ auto [sh, si, sj [[]], ...sk] = S { 1, 2, 3 };// { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 }
+ static_assert (sizeof... (sk) == 0, "");
+ static_assert (same_type <decltype (sh), int>::value, "");
+ static_assert (same_type <decltype (si), long long>::value, "");
+ static_assert (same_type <decltype (sj), short>::value, "");
+ auto && [sl, ...sm [[maybe_unused]], sn] = s; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 }
+ static_assert (sizeof... (sm) == 1, "");
+ static_assert (same_type <decltype (sl), int>::value, "");
+ static_assert (same_type <decltype (sm...[0]), long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (sn), short>::value, "");
+ auto [...so] = S { 1, 2, 3 }; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ static_assert (sizeof... (so) == 3, "");
+ static_assert (same_type <decltype (so...[0]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (so...[1]), long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (so...[2]), short>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ auto [...sp, sq, sr, ss [[maybe_unused]]] = S { 1, 2, 3 };// { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 }
+ static_assert (sizeof... (sp) == 0, "");
+ static_assert (same_type <decltype (sq), int>::value, "");
+ static_assert (same_type <decltype (sr), long long>::value, "");
+ static_assert (same_type <decltype (ss), short>::value, "");
+ auto [st, ...su, sv, sw] = S { 1, 2, 3 };// { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ static_assert (sizeof... (su) == 0, "");
+ static_assert (same_type <decltype (st), int>::value, "");
+ static_assert (same_type <decltype (sv), long long>::value, "");
+ static_assert (same_type <decltype (sw), short>::value, "");
+ if (sa != 1 || sb != 2 || sc != 3
+ || sd != 1 || se...[0] != 2 || se...[1] != 3 // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ || sf...[0] != 1 || sf...[1] != 2 || sg != 3 // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ || sh != 1 || si != 2 || sj != 3
+ || sl != 1 || sm...[0] != 2 || sn != 3 // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ || so...[0] != 1 || so...[1] != 2 || so...[2] != 3// { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ || sq != 1 || sr != 2 || ss != 3
+ || st != 1 || sv != 2 || sw != 3
+ || sum (se...) != 5
+ || sum <decltype (se)...> (se...) != 5
+ || sum (square (square (se))...) != 97
+ || sum (sf...) != 3
+ || sum (sk...) != 0
+ || sum (sm...) != 2
+ || sum (so...) != 6
+ || sum <decltype (so)...> (so...) != 6
+ || sum (square (so)...) != 14
+ || sum (sp...) != 0
+ || sum (su...) != 0
+ || (se + ...) != 5 // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ || (... + sf) != 3 // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ || (0 + ... + sk) != 0 // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ || (sm + ... + 0) != 2 // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ || (so + ...) != 6 // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ || (sp + ... + 0) != 0 // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ || (0 + ... + su) != 0) // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ __builtin_abort ();
+ S s2[] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
+ int i = 0;
+ for (auto [sx, ...sy [[]]] : s2) // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ { // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 }
+ static_assert (sizeof... (sy) == 2, "");
+ static_assert (same_type <decltype (sx), int>::value, "");
+ static_assert (same_type <decltype (sy...[0]), long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (sy...[1]), short>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ if (sx != i * 3 + 1 || sum (sy...) != i * 6 + 5)
+ __builtin_abort ();
+ auto fn1 = [&] () { if (sum (sy...) != i * 6 + 5) __builtin_abort (); }; // { dg-warning "captured structured bindings are" "" { target c++17_down } }
+ fn1 ();
+ auto fn2 = [&sy..., &i] () { if (sum (sy...) != i * 6 + 5) __builtin_abort (); }; // { dg-warning "captured structured bindings are" "" { target c++17_down } }
+ fn2 ();
+ auto fn3 = [&...sy2 = sy, &i] () { if (sum (sy2...) != i * 6 + 5) __builtin_abort (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } }
+ fn3 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 }
+ auto fn4 = [&...sy3 = ref (sy), &i] () { if (sum (sy3...) != i * 6 + 5) __builtin_abort (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } }
+ fn4 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 }
+ auto fn5 = [=] () { if (sum (sy...) != i * 6 + 5) __builtin_abort (); }; // { dg-warning "captured structured bindings are" "" { target c++17_down } }
+ fn5 ();
+ auto fn6 = [sy..., i] () { if (sum (sy...) != i * 6 + 5) __builtin_abort (); }; // { dg-warning "captured structured bindings are" "" { target c++17_down } }
+ fn6 ();
+ auto fn7 = [...sy2 = sy, i] () { if (sum (sy2...) != i * 6 + 5) __builtin_abort (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } }
+ fn7 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 }
+ auto fn8 = [...sy3 = square (sy), i] () { if (sum (sy3...) != (i * 3 + 2) * (i * 3 + 2) + (i * 3 + 3) * (i * 3 + 3)) __builtin_abort (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } }
+ fn8 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 }
+ auto fn9 = [&] () { auto fn = [&] () { if (sum (sy...) != i * 6 + 5) __builtin_abort (); }; fn (); }; // { dg-warning "captured structured bindings are" "" { target c++17_down } }
+ fn9 ();
+ auto fn10 = [&sy..., &i] () { auto fn = [&] () { if (sum (sy...) != i * 6 + 5) __builtin_abort (); }; fn (); }; // { dg-warning "captured structured bindings are" "" { target c++17_down } }
+ fn10 ();
+ auto fn11 = [&] () { auto fn = [&...sy2 = sy, &i] () { if (sum (sy2...) != i * 6 + 5) __builtin_abort (); }; fn (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } }
+ fn11 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 }
+ // { dg-warning "captured structured bindings are" "" { target c++17_down } .-2 }
+ auto fn12 = [&sy..., &i] () { auto fn = [&...sy3 = ref (sy), &i] () { if (sum (sy3...) != i * 6 + 5) __builtin_abort (); }; fn (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } }
+ fn12 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 }
+ // { dg-warning "captured structured bindings are" "" { target c++17_down } .-2 }
+ auto fn13 = [=] () { auto fn = [=] () { if (sum (sy...) != i * 6 + 5) __builtin_abort (); }; fn (); }; // { dg-warning "captured structured bindings are" "" { target c++17_down } }
+ fn13 ();
+ auto fn14 = [sy..., i] () { auto fn = [=] () { if (sum (sy...) != i * 6 + 5) __builtin_abort (); }; fn (); }; // { dg-warning "captured structured bindings are" "" { target c++17_down } }
+ fn14 ();
+ auto fn15 = [=] () { auto fn = [...sy2 = sy, i] () { if (sum (sy2...) != i * 6 + 5) __builtin_abort (); }; fn (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } }
+ fn15 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 }
+ // { dg-warning "captured structured bindings are" "" { target c++17_down } .-2 }
+ auto fn16 = [&sy..., &i] () { auto fn = [...sy3 = square (sy), i] () { if (sum (sy3...) != (i * 3 + 2) * (i * 3 + 2) + (i * 3 + 3) * (i * 3 + 3)) __builtin_abort (); }; fn (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } }
+ fn16 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 }
+ // { dg-warning "captured structured bindings are" "" { target c++17_down } .-2 }
+ ++i;
+ }
+ i = 0;
+ for (auto [...sz] : s2) // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ { // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ static_assert (sizeof... (sz) == 3, "");
+ static_assert (same_type <decltype (sz...[0]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (sz...[1]), long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (sz...[2]), short>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ if (sum (sz...) != i * 9 + 6)
+ __builtin_abort ();
+ auto fn = [=] () { if (sum (sz...) != i * 9 + 6) __builtin_abort (); }; // { dg-warning "captured structured bindings are" "" { target c++17_down } }
+ fn ();
+ ++i;
+ }
+ if (auto [...sx, sy] = s) // { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+ {
+ static_assert (sizeof... (sx) == 2, "");
+ static_assert (same_type <decltype (sx...[0]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (sx...[1]), long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (sy), short>::value, "");
+ if (sum (sx...) != 3 || sy != 3)
+ __builtin_abort ();
+ }
+ else
+ __builtin_abort ();
+ T t = T { 3, 1, 2 };
+ auto [ta, tb, tc] = T { 3, 1, 2 }; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ static_assert (same_type <decltype (ta), int>::value, "");
+ static_assert (same_type <decltype (tb), long long>::value, "");
+ static_assert (same_type <decltype (tc), short>::value, "");
+ auto [td [[maybe_unused]], ...te] = T { 3, 1, 2 }; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 }
+ static_assert (sizeof... (te) == 2, "");
+ static_assert (same_type <decltype (td), int>::value, "");
+ static_assert (same_type <decltype (te...[0]), long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (te...[1]), short>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ auto [...tf [[maybe_unused]], tg] = T { 3, 1, 2 }; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 }
+ static_assert (sizeof... (tf) == 2, "");
+ static_assert (same_type <decltype (tf...[0]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (tf...[1]), long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (tg), short>::value, "");
+ const auto & [th, ti, tj, ...tk] = t; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ static_assert (sizeof... (tk) == 0, "");
+ static_assert (same_type <decltype (th), const int>::value, "");
+ static_assert (same_type <decltype (ti), const long long>::value, "");
+ static_assert (same_type <decltype (tj), const short>::value, "");
+ auto [tl [[]], ...tm [[]], tn [[]]] = T { 3, 1, 2 }; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 }
+ static_assert (sizeof... (tm) == 1, "");
+ static_assert (same_type <decltype (tl), int>::value, "");
+ static_assert (same_type <decltype (tm...[0]), long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (tn), short>::value, "");
+ auto && [...to] = t; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ static_assert (sizeof... (to) == 3, "");
+ constexpr size_t tos = sizeof... (to);
+ static_assert (same_type <decltype (to...[0]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (to...[1]), long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (to...[2]), short>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ auto [...tp, tq [[]], tr, ts] = T { 3, 1, 2 };// { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 }
+ static_assert (sizeof... (tp) == 0, "");
+ static_assert (same_type <decltype (tq), int>::value, "");
+ static_assert (same_type <decltype (tr), long long>::value, "");
+ static_assert (same_type <decltype (ts), short>::value, "");
+ auto [tt, ...tu [[]], tv, tw] = T { 3, 1, 2 };// { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 }
+ static_assert (sizeof... (tu) == 0, "");
+ static_assert (same_type <decltype (tt), int>::value, "");
+ static_assert (same_type <decltype (tv), long long>::value, "");
+ static_assert (same_type <decltype (tw), short>::value, "");
+ if (ta != 1 || tb != 2 || tc != 3
+ || td != 1 || te...[0] != 2 || te...[1] != 3 // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ || tf...[0] != 1 || tf...[1] != 2 || tg != 3 // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ || th != 1 || ti != 2 || tj != 3
+ || tl != 1 || tm...[0] != 2 || tn != 3 // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ || to...[0] != 1 || to...[1] != 2 || to...[2] != 3// { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ || tq != 1 || tr != 2 || ts != 3
+ || tt != 1 || tv != 2 || tw != 3
+ || sum (te...) != 5
+ || sum <decltype (te)...> (te...) != 5
+ || sum (square (square (te))...) != 97
+ || sum (tf...) != 3
+ || sum (tk...) != 0
+ || sum (tm...) != 2
+ || sum (to...) != 6
+ || sum <decltype (to)...> (to...) != 6
+ || sum (square (to)...) != 14
+ || sum (tp...) != 0
+ || sum (tu...) != 0
+ || (te + ...) != 5 // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ || (... + tf) != 3 // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ || (0 + ... + tk) != 0 // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ || (tm + ... + 0) != 2 // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ || (to + ...) != 6 // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ || (tp + ... + 0) != 0 // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ || (0 + ... + tu) != 0) // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ __builtin_abort ();
+ T t2[] = { { 3, 1, 2 }, { 6, 4, 5 }, { 9, 7, 8 } };
+ i = 0;
+ for (auto [tx, ...ty] : t2) // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ { // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ static_assert (sizeof... (ty) == 2, "");
+ static_assert (same_type <decltype (tx), int>::value, "");
+ static_assert (same_type <decltype (ty...[0]), long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (ty...[1]), short>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ if (tx != i * 3 + 1 || sum (ty...) != i * 6 + 5)
+ __builtin_abort ();
+ auto fn1 = [&] () { if (sum (ty...) != i * 6 + 5) __builtin_abort (); };
+ fn1 ();
+ auto fn2 = [&ty..., &i] () { if (sum (ty...) != i * 6 + 5) __builtin_abort (); }; // { dg-warning "captured structured bindings are" "" { target c++17_down } }
+ fn2 ();
+ auto fn3 = [&...ty2 = ty, &i] () { if (sum (ty2...) != i * 6 + 5) __builtin_abort (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } }
+ fn3 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 }
+ auto fn4 = [&...ty3 = ref (ty), &i] () { if (sum (ty3...) != i * 6 + 5) __builtin_abort (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } }
+ fn4 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 }
+ auto fn5 = [=] () { if (sum (ty...) != i * 6 + 5) __builtin_abort (); };
+ fn5 ();
+ auto fn6 = [ty..., i] () { if (sum (ty...) != i * 6 + 5) __builtin_abort (); }; // { dg-warning "captured structured bindings are" "" { target c++17_down } }
+ fn6 ();
+ auto fn7 = [...ty2 = ty, i] () { if (sum (ty2...) != i * 6 + 5) __builtin_abort (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } }
+ fn7 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 }
+ auto fn8 = [...ty3 = square (ty), i] () { if (sum (ty3...) != (i * 3 + 2) * (i * 3 + 2) + (i * 3 + 3) * (i * 3 + 3)) __builtin_abort (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } }
+ fn8 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 }
+ auto fn9 = [&] () { auto fn = [&] () { if (sum (ty...) != i * 6 + 5) __builtin_abort (); }; fn (); };
+ fn9 ();
+ auto fn10 = [&ty..., &i] () { auto fn = [&] () { if (sum (ty...) != i * 6 + 5) __builtin_abort (); }; fn (); }; // { dg-warning "captured structured bindings are" "" { target c++17_down } }
+ fn10 ();
+ auto fn11 = [&] () { auto fn = [&...ty2 = ty, &i] () { if (sum (ty2...) != i * 6 + 5) __builtin_abort (); }; fn (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } }
+ fn11 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 }
+ auto fn12 = [&ty..., &i] () { auto fn = [&...ty3 = ref (ty), &i] () { if (sum (ty3...) != i * 6 + 5) __builtin_abort (); }; fn (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } }
+ fn12 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 }
+ // { dg-warning "captured structured bindings are" "" { target c++17_down } .-2 }
+ auto fn13 = [=] () { auto fn = [=] () { if (sum (ty...) != i * 6 + 5) __builtin_abort (); }; fn (); };
+ fn13 ();
+ auto fn14 = [ty..., i] () { auto fn = [=] () { if (sum (ty...) != i * 6 + 5) __builtin_abort (); }; fn (); }; // { dg-warning "captured structured bindings are" "" { target c++17_down } }
+ fn14 ();
+ auto fn15 = [=] () { auto fn = [...ty2 = ty, i] () { if (sum (ty2...) != i * 6 + 5) __builtin_abort (); }; fn (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } }
+ fn15 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 }
+ auto fn16 = [&ty..., &i] () { auto fn = [...ty3 = square (ty), i] () { if (sum (ty3...) != (i * 3 + 2) * (i * 3 + 2) + (i * 3 + 3) * (i * 3 + 3)) __builtin_abort (); }; fn (); }; // { dg-warning "pack init-capture only available with" "" { target c++17_down } }
+ fn16 (); // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 }
+ // { dg-warning "captured structured bindings are" "" { target c++17_down } .-2 }
+ ++i;
+ }
+ i = 0;
+ for (auto [...tz] : t2) // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ { // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ static_assert (sizeof... (tz) == 3, "");
+ static_assert (same_type <decltype (tz...[0]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (tz...[1]), long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (tz...[2]), short>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ if (sum (tz...) != i * 9 + 6)
+ __builtin_abort ();
+ auto fn = [=] () { if (sum (tz...) != i * 9 + 6) __builtin_abort (); };
+ fn ();
+ ++i;
+ }
+ if (auto [...tx [[maybe_unused]], ty] = t) // { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+ __builtin_abort ();
+ else
+ {
+ static_assert (sizeof... (tx) == 2, "");
+ static_assert (same_type <decltype (tx...[0]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (tx...[1]), long long>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (ty), short>::value, "");
+ if (sum (tx...) != 3 || ty != 3)
+ __builtin_abort ();
+ }
+ U a[3] = { 1, 2, 3 };
+ auto [aa, ab, ac] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ static_assert (same_type <decltype (aa), int>::value, "");
+ static_assert (same_type <decltype (ab), int>::value, "");
+ static_assert (same_type <decltype (ac), int>::value, "");
+ auto [ad [[maybe_unused]], ...ae [[maybe_unused]]] = a; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 }
+ static_assert (sizeof... (ae) == 2, "");
+ static_assert (same_type <decltype (ad), int>::value, "");
+ static_assert (same_type <decltype (ae...[0]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (ae...[1]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ auto [...af, ag] = a; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ static_assert (sizeof... (af) == 2, "");
+ static_assert (same_type <decltype (af...[0]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (af...[1]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (ag), int>::value, "");
+ auto [ah, ai [[]], aj, ...ak [[]]] = a; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 }
+ static_assert (sizeof... (ak) == 0, "");
+ static_assert (same_type <decltype (ah), int>::value, "");
+ static_assert (same_type <decltype (ai), int>::value, "");
+ static_assert (same_type <decltype (aj), int>::value, "");
+ auto [al, ...am [[]], an] = a;// { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 }
+ static_assert (sizeof... (am) == 1, "");
+ static_assert (same_type <decltype (al), int>::value, "");
+ static_assert (same_type <decltype (am...[0]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (an), int>::value, "");
+ const auto &[...ao] = a; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ static_assert (sizeof... (ao) == 3, "");
+ static_assert (same_type <decltype (ao...[0]), const int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (ao...[1]), const int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (ao...[2]), const int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ auto &&[...ap, aq, ar [[]], as] = a;// { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ // { dg-warning "structured bindings with attributed identifiers only available with" "" { target { c++17 && c++23_down } } .-2 }
+ static_assert (sizeof... (ap) == 0, "");
+ static_assert (same_type <decltype (aq), int>::value, "");
+ static_assert (same_type <decltype (ar), int>::value, "");
+ static_assert (same_type <decltype (as), int>::value, "");
+ auto [at, ...au, av, aw] = a; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ static_assert (sizeof... (au) == 0, "");
+ static_assert (same_type <decltype (at), int>::value, "");
+ static_assert (same_type <decltype (av), int>::value, "");
+ static_assert (same_type <decltype (aw), int>::value, "");
+ if (aa != 1 || ab != 2 || ac != 3
+ || ad != 1 || ae...[0] != 2 || ae...[1] != 3 // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ || af...[0] != 1 || af...[1] != 2 || ag != 3 // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ || ah != 1 || ai != 2 || aj != 3
+ || al != 1 || am...[0] != 2 || an != 3 // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ || ao...[0] != 1 || ao...[1] != 2 || ao...[2] != 3// { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ || aq != 1 || ar != 2 || as != 3
+ || at != 1 || av != 2 || aw != 3
+ || sum (ae...) != 5
+ || sum <decltype (ae)...> (ae...) != 5
+ || sum (square (square (ae))...) != 97
+ || sum (af...) != 3
+ || sum (ak...) != 0
+ || sum (am...) != 2
+ || sum (ao...) != 6
+ || sum <decltype (ao)...> (ao...) != 6
+ || sum (square (ao)...) != 14
+ || sum (ap...) != 0
+ || sum (au...) != 0
+ || (ae + ...) != 5 // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ || (... + af) != 3 // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ || (0 + ... + ak) != 0 // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ || (am + ... + 0) != 2 // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ || (ao + ...) != 6 // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ || (ap + ... + 0) != 0 // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ || (0 + ... + au) != 0) // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ __builtin_abort ();
+ return tos;
+}
+
+int
+main ()
+{
+ if (foo <S, T, int> () != 3)
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp26/decomp16.C b/gcc/testsuite/g++.dg/cpp26/decomp16.C
new file mode 100644
index 0000000..548f9af
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp26/decomp16.C
@@ -0,0 +1,240 @@
+// P1061R10 - Structured Bindings can introduce a Pack
+// { dg-do run { target c++11 } }
+// { dg-options "" }
+
+int
+sum ()
+{
+ return 0;
+}
+
+template <typename T, typename ...A>
+T
+sum (T x, A... y)
+{
+ return x + sum (y...);
+}
+
+template <typename T>
+T
+square (T x)
+{
+ return x * x;
+}
+
+template <typename T, typename U>
+struct same_type { static const bool value = false; };
+
+template <typename T>
+struct same_type<T, T> { static const bool value = true; };
+
+typedef int V __attribute__((vector_size (16 * sizeof (int))));
+
+template <int N>
+void
+foo ()
+{
+ V v = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
+ auto [...va] = v; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ static_assert (sizeof... (va) == 16, "");
+ static_assert (same_type <decltype (va...[5]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (va...[13]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ auto [vb, ...vc, vd, ve] = v; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ static_assert (sizeof... (vc) == 13, "");
+ static_assert (same_type <decltype (vb), int>::value, "");
+ static_assert (same_type <decltype (vc...[0]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (vc...[12]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (vd), int>::value, "");
+ static_assert (same_type <decltype (ve), int>::value, "");
+ auto [vf, vg, vh, vi, ...vj] = v; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ static_assert (sizeof... (vj) == 12, "");
+ static_assert (same_type <decltype (vf), int>::value, "");
+ static_assert (same_type <decltype (vg), int>::value, "");
+ static_assert (same_type <decltype (vh), int>::value, "");
+ static_assert (same_type <decltype (vi), int>::value, "");
+ static_assert (same_type <decltype (vj...[2]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (vj...[10]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ if (va...[13] != 14 // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ || sum (va...) != 8 * 17
+ || sum (square (va)...) != 1496
+ || vb != 1
+ || vc...[10] != 12 // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ || sum (vc...) != 15 * 7 - 1
+ || sum <decltype (vc)...> (vc...) != 15 * 7 - 1
+ || vd != 15 || ve != 16
+ || vf != 1 || vg != 2 || vh != 3 || vi != 4
+ || sum (vj...) != 8 * 17 - 10
+ || (va + ...) != 8 * 17 // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ || (... + vc) != 15 * 7 - 1 // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ || (0 + ... + vj) != 8 * 17 - 10) // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ __builtin_abort ();
+ V v2[3] = { v, v + 1, v + 2 };
+ int i = 0;
+ for (auto [vk, ...vl, vm] : v2) // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ { // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ static_assert (sizeof... (vl) == 14, "");
+ static_assert (same_type <decltype (vk), int>::value, "");
+ static_assert (same_type <decltype (vl...[1]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (vl...[9]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (vm), int>::value, "");
+ if (vk != i + 1 || sum (vl...) != i * 14 + 15 * 8 - 1 || vm != i + 16)
+ __builtin_abort ();
+ ++i;
+ }
+ _Complex double c = 1.0 + 2.0i;
+ auto [...ca] = c; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ static_assert (sizeof... (ca) == 2, "");
+ static_assert (same_type <decltype (ca...[0]), double>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (ca...[1]), double>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ auto [cb, ...cc, cd] = c; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ static_assert (sizeof... (cc) == 0, "");
+ static_assert (same_type <decltype (cb), double>::value, "");
+ static_assert (same_type <decltype (cd), double>::value, "");
+ auto [ce, ...cf] = c; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ static_assert (sizeof... (cf) == 1, "");
+ static_assert (same_type <decltype (ce), double>::value, "");
+ static_assert (same_type <decltype (cf...[0]), double>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ auto [...cg, ch] = c; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ static_assert (sizeof... (cg) == 1, "");
+ static_assert (same_type <decltype (cg...[0]), double>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (ch), double>::value, "");
+ if (ca...[0] != 1.0 || ca...[1] != 2.0// { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ || sum (ca...) != 3.0
+ || sum <decltype (ca)...> (ca...) != 3.0
+ || sum (square (square (square (ca)))...) != 257.0
+ || cb != 1.0 || cd != 2.0
+ || ce != 1.0 || cf...[0] != 2.0 // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ || sum (cf...) != 2.0
+ || cg...[0] != 1.0 || ch != 2.0 // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ || sum (cg...) != 1.0
+ || (ca + ...) != 3.0 // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ || (0.0 + ... + cc) != 0.0 // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ || (... + cf) != 2.0 // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ || (cg + ... + 0.0) != 1.0) // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ __builtin_abort ();
+ _Complex float c2[3] = { 1.0f + 2.0fi, 2.0f + 3.0fi, 3.0f + 4.0fi };
+ i = 0;
+ for (auto [...ci] : c2) // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ { // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ static_assert (sizeof... (ci) == 2, "");
+ static_assert (same_type <decltype (ci...[0]), float>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (ci...[1]), float>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ if (sum (ci...) != i * 2 + 3.0f)
+ __builtin_abort ();
+ ++i;
+ }
+}
+
+template <typename V, typename C, typename D>
+void
+bar ()
+{
+ V v = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
+ auto [...va] = v; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ static_assert (sizeof... (va) == 16, "");
+ static_assert (same_type <decltype (va...[5]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (va...[13]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ auto [vb, ...vc, vd, ve] = v; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ static_assert (sizeof... (vc) == 13, "");
+ static_assert (same_type <decltype (vb), int>::value, "");
+ static_assert (same_type <decltype (vc...[0]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (vc...[12]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (vd), int>::value, "");
+ static_assert (same_type <decltype (ve), int>::value, "");
+ auto [vf, vg, vh, vi, ...vj] = v; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ static_assert (sizeof... (vj) == 12, "");
+ static_assert (same_type <decltype (vf), int>::value, "");
+ static_assert (same_type <decltype (vg), int>::value, "");
+ static_assert (same_type <decltype (vh), int>::value, "");
+ static_assert (same_type <decltype (vi), int>::value, "");
+ static_assert (same_type <decltype (vj...[2]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (vj...[10]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ if (va...[13] != 14 // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ || sum (va...) != 8 * 17
+ || vb != 1
+ || vc...[10] != 12 // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ || sum (vc...) != 15 * 7 - 1
+ || sum <decltype (vc)...> (vc...) != 15 * 7 - 1
+ || vd != 15 || ve != 16
+ || vf != 1 || vg != 2 || vh != 3 || vi != 4
+ || sum (vj...) != 8 * 17 - 10
+ || (va + ...) != 8 * 17 // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ || (... + vc) != 15 * 7 - 1 // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ || (0 + ... + vj) != 8 * 17 - 10) // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ __builtin_abort ();
+ V v2[3] = { v, v + 1, v + 2 };
+ int i = 0;
+ for (auto [vk, ...vl, vm] : v2) // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ { // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ static_assert (sizeof... (vl) == 14, "");
+ static_assert (same_type <decltype (vk), int>::value, "");
+ static_assert (same_type <decltype (vl...[1]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (vl...[9]), int>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (vm), int>::value, "");
+ if (vk != i + 1 || sum (vl...) != i * 14 + 15 * 8 - 1 || vm != i + 16)
+ __builtin_abort ();
+ ++i;
+ }
+ C c = 1.0 + 2.0i;
+ auto [...ca] = c; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ static_assert (sizeof... (ca) == 2, "");
+ static_assert (same_type <decltype (ca...[0]), double>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (ca...[1]), double>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ auto [cb, ...cc, cd] = c; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ static_assert (sizeof... (cc) == 0, "");
+ static_assert (same_type <decltype (cb), double>::value, "");
+ static_assert (same_type <decltype (cd), double>::value, "");
+ auto [ce, ...cf] = c; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ static_assert (sizeof... (cf) == 1, "");
+ static_assert (same_type <decltype (ce), double>::value, "");
+ static_assert (same_type <decltype (cf...[0]), double>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ auto [...cg, ch] = c; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ static_assert (sizeof... (cg) == 1, "");
+ static_assert (same_type <decltype (cg...[0]), double>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (ch), double>::value, "");
+ if (ca...[0] != 1.0 || ca...[1] != 2.0// { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ || sum (ca...) != 3.0
+ || sum <decltype (ca)...> (ca...) != 3.0
+ || cb != 1.0 || cd != 2.0
+ || ce != 1.0 || cf...[0] != 2.0 // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ || sum (cf...) != 2.0
+ || cg...[0] != 1.0 || ch != 2.0 // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ || sum (cg...) != 1.0
+ || (ca + ...) != 3.0 // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ || (0.0 + ... + cc) != 0.0 // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ || (... + cf) != 2.0 // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ || (cg + ... + 0.0) != 1.0) // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+ __builtin_abort ();
+ D c2[3] = { 1.0f + 2.0fi, 2.0f + 3.0fi, 3.0f + 4.0fi };
+ i = 0;
+ for (auto [...ci] : c2) // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ { // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ static_assert (sizeof... (ci) == 2, "");
+ static_assert (same_type <decltype (ci...[0]), float>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ static_assert (same_type <decltype (ci...[1]), float>::value, ""); // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ if (sum (ci...) != i * 2 + 3.0f)
+ __builtin_abort ();
+ ++i;
+ }
+}
+
+int
+main ()
+{
+ foo <0> ();
+ bar <V, _Complex double, _Complex float> ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp26/decomp17.C b/gcc/testsuite/g++.dg/cpp26/decomp17.C
new file mode 100644
index 0000000..49ad0e2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp26/decomp17.C
@@ -0,0 +1,28 @@
+// P1061R10 - Structured Bindings can introduce a Pack
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+typedef int V __attribute__((vector_size (16 * sizeof (int))));
+
+template <int N>
+void
+foo ()
+{
+ V v = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
+ auto [va, vb, vc, vd, ...ve, vf, vg, vh, vi, vj, vk, vl, vm, vn, vo, vp, vq, vr] = v;
+ // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } .-1 }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-2 }
+ // { dg-error "18 names provided for structured binding" "" { target *-*-* } .-3 }
+ // { dg-message "while '__vector\\\(16\\\) int' decomposes into 16 elements" "" { target *-*-* } .-4 }
+ _Complex double c = 1.0 + 2.0i;
+ auto [...ca, cb, cc, cd] = c; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ // { dg-error "4 names provided for structured binding" "" { target *-*-* } .-2 }
+ // { dg-message "while '__complex__ double' decomposes into 2 elements" "" { target *-*-* } .-3 }
+}
+
+int
+main ()
+{
+ foo <0> ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp26/decomp18.C b/gcc/testsuite/g++.dg/cpp26/decomp18.C
new file mode 100644
index 0000000..86b9bf4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp26/decomp18.C
@@ -0,0 +1,109 @@
+// P1061R10 - Structured Bindings can introduce a Pack
+// { dg-do run { target c++11 } }
+// { dg-options "" }
+
+struct S { int a, b, c; };
+namespace std {
+ template <typename T> struct tuple_size;
+ template <int, typename> struct tuple_element;
+}
+struct T {
+ int a[3];
+ template <int I>
+ int &get () { return a[2 - I]; }
+};
+template <>
+struct std::tuple_size<T> { static constexpr int value = 3; };
+template <int N>
+struct std::tuple_element<N, T> { typedef int type; };
+
+template <int N>
+inline int
+foo ()
+{
+ static int a[4] = { N, N + 1, N + 2, N + 3 };
+ static auto [...aa] = a; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-2 }
+ aa...[1]++; // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ return (... + aa); // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+}
+
+template <int N>
+inline int
+bar ()
+{
+ static S s = { N, N + 1, N + 2 };
+ static auto [...sa] = s; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-2 }
+ sa...[1]++; // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ return (sa + ...); // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+}
+
+template <int N>
+inline int
+baz ()
+{
+ static T t = { { N, N + 1, N + 2 } };
+ static auto [ta, ...tb, tc, td] = t; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-2 }
+ tc++;
+ return ((ta + tc + td) + ... + tb); // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+}
+
+template <int N>
+inline int
+qux ()
+{
+ thread_local int a[4] = { N, N + 1, N + 2, N + 3 };
+ thread_local auto [...aa] = a; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ // { dg-warning "structured binding declaration can be 'thread_local' only in" "" { target c++17_down } .-2 }
+ aa...[1]++; // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ return (... + aa); // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+}
+
+template <int N>
+inline int
+freddy ()
+{
+ thread_local S s = { N, N + 1, N + 2 };
+ thread_local auto [...sa] = s; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ // { dg-warning "structured binding declaration can be 'thread_local' only in" "" { target c++17_down } .-2 }
+ sa...[1]++; // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ return (sa + ...); // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+}
+
+template <int N>
+inline int
+corge ()
+{
+ thread_local T t = { { N, N + 1, N + 2 } };
+ thread_local auto [ta, ...tb, tc, td] = t; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ // { dg-warning "structured binding declaration can be 'thread_local' only in" "" { target c++17_down } .-2 }
+ tc++;
+ return ((ta + tc + td) + ... + tb); // { dg-warning "fold-expressions only available with" "" { target c++14_down } }
+}
+
+int
+main ()
+{
+ if (foo <2> () != 15 || foo <2> () != 16 || foo <2> () != 17
+ || foo <42> () != 175 || foo <42> () != 176
+ || bar <5> () != 19 || bar <5> () != 20 || bar <5> () != 21
+ || bar <18> () != 58 || bar <18> () != 59
+ || baz <3> () != 13 || baz <3> () != 14 || baz <3> () != 15
+ || baz <22> () != 70 || baz <22> () != 71)
+ __builtin_abort ();
+ if (qux <2> () != 15 || qux <2> () != 16 || qux <2> () != 17
+ || qux <42> () != 175 || qux <42> () != 176
+ || freddy <5> () != 19 || freddy <5> () != 20 || freddy <5> () != 21
+ || freddy <18> () != 58 || freddy <18> () != 59
+ || corge <3> () != 13 || corge <3> () != 14 || corge <3> () != 15
+ || corge <22> () != 70 || corge <22> () != 71)
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp26/decomp19.C b/gcc/testsuite/g++.dg/cpp26/decomp19.C
new file mode 100644
index 0000000..b4d97a1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp26/decomp19.C
@@ -0,0 +1,46 @@
+// P1061R10 - Structured Bindings can introduce a Pack
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+namespace std {
+ template <typename T> struct tuple_size;
+ template <int, typename> struct tuple_element;
+}
+struct T {
+ int a[3];
+ template <int I>
+ int &get () { return a[2 - I]; }
+};
+template <>
+struct std::tuple_size<T> { static constexpr int value = 3; };
+template <int N>
+struct std::tuple_element<N, T> { typedef int type; };
+
+template <int N>
+inline void
+foo ()
+{
+ static T t = { { N, N + 1, N + 2 } };
+ static auto [ta, ...tb, tc] = t; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-2 }
+ // { dg-message "mangling of structured binding pack elements not implemented yet" "" { target *-*-* } .-3 }
+}
+
+template <int N>
+inline void
+bar ()
+{
+ thread_local T t = { { N, N + 1, N + 2 } };
+ thread_local auto [...ta] = t; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ // { dg-warning "structured binding declaration can be 'thread_local' only in" "" { target c++17_down } .-2 }
+ // { dg-message "mangling of structured binding pack elements not implemented yet" "" { target *-*-* } .-3 }
+}
+
+int
+main ()
+{
+ foo <0> ();
+ bar <0> ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp26/decomp20.C b/gcc/testsuite/g++.dg/cpp26/decomp20.C
new file mode 100644
index 0000000..5091e13
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp26/decomp20.C
@@ -0,0 +1,53 @@
+// P1061R10 - Structured Bindings can introduce a Pack
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+struct S {
+ explicit operator bool () const noexcept { return true; }
+};
+namespace std {
+ template <typename T> struct tuple_size;
+ template <int, typename> struct tuple_element;
+}
+int x;
+struct T {
+ template <int I>
+ int &get () { return x; }
+ explicit operator bool () const noexcept { return false; }
+};
+template <>
+struct std::tuple_size<T> { static constexpr int value = 0; };
+template <int N>
+struct std::tuple_element<N, T> { typedef int type; };
+
+template <int N>
+void
+foo ()
+{
+ int a[0] = {};
+ auto [...aa] = a; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ static_assert (sizeof... (aa) == 0, "");
+ S s = {};
+ auto [...sa] = s; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ static_assert (sizeof... (sa) == 0, "");
+ T t = {};
+ auto [...ta] = t; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ static_assert (sizeof... (ta) == 0, "");
+ if (auto [...sb] = s) // { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+ static_assert (sizeof... (sb) == 0, "");
+ else
+ __builtin_abort ();
+ if (auto [...tb] = t) // { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+ __builtin_abort ();
+ else
+ static_assert (sizeof... (tb) == 0, "");
+}
+
+int
+main ()
+{
+ foo <0> ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp26/decomp21.C b/gcc/testsuite/g++.dg/cpp26/decomp21.C
new file mode 100644
index 0000000..6baa8aa
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp26/decomp21.C
@@ -0,0 +1,103 @@
+// P1061R10 - Structured Bindings can introduce a Pack
+// { dg-do run { target c++11 } }
+// { dg-options "" }
+
+using size_t = decltype (sizeof 0);
+
+auto g () -> int (&)[4]
+{
+ static int a[4] = { 1, 2, 3, 4 };
+ return a;
+}
+
+template <size_t N>
+void
+h (int (&arr)[N])
+{
+ auto [a, ...b, c] = arr; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ static_assert (sizeof... (b) == 2, "");
+ auto &[f, ...g, h] = arr; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ static_assert (sizeof... (g) == 2, "");
+ if (&f != &arr[0] || &h != &arr[3]
+ || &g...[0] != &arr[1] || &g...[1] != &arr[2]) // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ __builtin_abort ();
+ auto &[...e] = arr; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ static_assert (sizeof ... (e) == 4, "");
+ if (&e...[0] != &arr[0] || &e...[3] != &arr[3]) // { dg-warning "pack indexing only available with" "" { target c++23_down } }
+ __builtin_abort ();
+}
+
+struct C { int x, y, z; };
+
+template <class T>
+void
+now_i_know_my ()
+{
+ auto [a, b, c] = C (); // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ auto [d, ...e] = C (); // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ static_assert (sizeof... (e) == 2, "");
+ auto [...f, g] = C (); // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ static_assert (sizeof... (f) == 2, "");
+ auto [h, i, j, ...k] = C (); // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ static_assert (sizeof... (k) == 0, "");
+// auto [l, m, n, o, ...p] = C ();
+}
+
+auto foo () -> int (&)[2]
+{
+ static int a[2] = { 1, 2 };
+ return a;
+}
+
+template <class T>
+void
+bar ()
+{
+ auto [...a] = foo (); // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ static_assert (sizeof... (a) == 2, "");
+ auto [b, c, ...d] = foo (); // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ static_assert (sizeof... (d) == 0, "");
+}
+
+struct D { };
+
+void
+baz (...)
+{
+ __builtin_abort ();
+}
+
+template <typename T>
+void
+qux ()
+{
+ D arr[1] = {};
+ auto [...e] = arr; // { dg-warning "structured binding packs only available with" "" { target { c++17 && c++23_down } } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ baz (e...);
+}
+
+int d;
+
+void
+baz (D)
+{
+ d = 1;
+}
+
+int
+main ()
+{
+ h (g ());
+ now_i_know_my <int> ();
+ bar <int> ();
+ qux <int> ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp26/feat-cxx26.C b/gcc/testsuite/g++.dg/cpp26/feat-cxx26.C
index cfc5f61..9284bc2 100644
--- a/gcc/testsuite/g++.dg/cpp26/feat-cxx26.C
+++ b/gcc/testsuite/g++.dg/cpp26/feat-cxx26.C
@@ -395,8 +395,8 @@
#ifndef __cpp_structured_bindings
# error "__cpp_structured_bindings"
-#elif __cpp_structured_bindings != 202403
-# error "__cpp_structured_bindings != 202403"
+#elif __cpp_structured_bindings != 202411
+# error "__cpp_structured_bindings != 202411"
#endif
#ifndef __cpp_template_template_args
diff --git a/gcc/testsuite/g++.dg/modules/atom-preamble-3.C b/gcc/testsuite/g++.dg/modules/atom-preamble-3.C
index 74dba7d..915fa74 100644
--- a/gcc/testsuite/g++.dg/modules/atom-preamble-3.C
+++ b/gcc/testsuite/g++.dg/modules/atom-preamble-3.C
@@ -1,4 +1,4 @@
-// { dg-additional-options "-fmodules-ts" }
+// { dg-additional-options "-fmodules-ts -Wno-keyword-macro" }
#define import import
import malcolm; // { dg-error "object-like macro" }
// { dg-error "failed to read" "" { target *-*-* } 0 }
diff --git a/gcc/testsuite/g++.dg/opt/pr82577.C b/gcc/testsuite/g++.dg/opt/pr82577.C
index 1a06897..8a4f36d 100644
--- a/gcc/testsuite/g++.dg/opt/pr82577.C
+++ b/gcc/testsuite/g++.dg/opt/pr82577.C
@@ -3,7 +3,9 @@
#if __cplusplus > 201500L
// register is no longer a keyword in C++17.
-#define register
+#define reg
+#else
+#define reg register
#endif
class a {
@@ -14,8 +16,8 @@ struct c {
int d;
a e;
} f;
-void fn1(register c *g) {
- register int *h;
+void fn1(reg c *g) {
+ reg int *h;
do
(h) = g->e.b() + (g)->d;
while (&f);
diff --git a/gcc/testsuite/g++.dg/template/sfinae17.C b/gcc/testsuite/g++.dg/template/sfinae17.C
index eb043cb..8628726 100644
--- a/gcc/testsuite/g++.dg/template/sfinae17.C
+++ b/gcc/testsuite/g++.dg/template/sfinae17.C
@@ -1,7 +1,7 @@
// The conversion from D* to B* is ambiguous, but that should not produce
// an error, it should remove the first f overload by SFINAE.
-#define static_assert(TEST,STR) \
+#define my_static_assert(TEST,STR) \
do { int ar[(TEST)?1:-1]; } while (0);
struct B {};
@@ -23,6 +23,6 @@ template <class T>
int main()
{
- static_assert(sizeof f<int>(0) == sizeof(two), "");
- static_assert(sizeof f<B *>(0) == sizeof(two), "");
+ my_static_assert(sizeof f<int>(0) == sizeof(two), "");
+ my_static_assert(sizeof f<B *>(0) == sizeof(two), "");
}
diff --git a/gcc/testsuite/g++.dg/warn/Wkeyword-macro-1.C b/gcc/testsuite/g++.dg/warn/Wkeyword-macro-1.C
new file mode 100644
index 0000000..f47de7a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wkeyword-macro-1.C
@@ -0,0 +1,112 @@
+// C++26 P2843R3 - Preprocessing is never undefined
+// [cpp.replace.general]/9
+// { dg-do preprocess }
+// { dg-options "-pedantic-errors" }
+// { dg-additional-options "-fmodules" { target c++20 } }
+
+// [lex.key]
+#define alignas 1 // { dg-error "keyword 'alignas' defined as macro" "" { target c++26 } }
+#define alignof 1 // { dg-error "keyword 'alignof' defined as macro" "" { target c++26 } }
+#define asm 1 // { dg-error "keyword 'asm' defined as macro" "" { target c++26 } }
+#define auto 1 // { dg-error "keyword 'auto' defined as macro" "" { target c++26 } }
+#define bool 1 // { dg-error "keyword 'bool' defined as macro" "" { target c++26 } }
+#define break 1 // { dg-error "keyword 'break' defined as macro" "" { target c++26 } }
+#define case 1 // { dg-error "keyword 'case' defined as macro" "" { target c++26 } }
+#define catch 1 // { dg-error "keyword 'catch' defined as macro" "" { target c++26 } }
+#define char 1 // { dg-error "keyword 'char' defined as macro" "" { target c++26 } }
+#define char16_t 1 // { dg-error "keyword 'char16_t' defined as macro" "" { target c++26 } }
+#define char32_t 1 // { dg-error "keyword 'char32_t' defined as macro" "" { target c++26 } }
+#define char8_t 1 // { dg-error "keyword 'char8_t' defined as macro" "" { target c++26 } }
+#define class 1 // { dg-error "keyword 'class' defined as macro" "" { target c++26 } }
+#define co_await 1 // { dg-error "keyword 'co_await' defined as macro" "" { target c++26 } }
+#define concept 1 // { dg-error "keyword 'concept' defined as macro" "" { target c++26 } }
+#define const 1 // { dg-error "keyword 'const' defined as macro" "" { target c++26 } }
+#define const_cast 1 // { dg-error "keyword 'const_cast' defined as macro" "" { target c++26 } }
+#define consteval 1 // { dg-error "keyword 'consteval' defined as macro" "" { target c++26 } }
+#define constexpr 1 // { dg-error "keyword 'constexpr' defined as macro" "" { target c++26 } }
+#define constinit 1 // { dg-error "keyword 'constinit' defined as macro" "" { target c++26 } }
+#define continue 1 // { dg-error "keyword 'continue' defined as macro" "" { target c++26 } }
+#define contract_assert 1
+#define co_return 1 // { dg-error "keyword 'co_return' defined as macro" "" { target c++26 } }
+#define co_yield 1 // { dg-error "keyword 'co_yield' defined as macro" "" { target c++26 } }
+#define decltype 1 // { dg-error "keyword 'decltype' defined as macro" "" { target c++26 } }
+#define default 1 // { dg-error "keyword 'default' defined as macro" "" { target c++26 } }
+#define delete 1 // { dg-error "keyword 'delete' defined as macro" "" { target c++26 } }
+#define do 1 // { dg-error "keyword 'do' defined as macro" "" { target c++26 } }
+#define double 1 // { dg-error "keyword 'double' defined as macro" "" { target c++26 } }
+#define dynamic_cast 1 // { dg-error "keyword 'dynamic_cast' defined as macro" "" { target c++26 } }
+#define else 1 // { dg-error "keyword 'else' defined as macro" "" { target c++26 } }
+#define enum 1 // { dg-error "keyword 'enum' defined as macro" "" { target c++26 } }
+#define explicit 1 // { dg-error "keyword 'explicit' defined as macro" "" { target c++26 } }
+#define export 1 // { dg-error "keyword 'export' defined as macro" "" { target c++26 } }
+#define extern 1 // { dg-error "keyword 'extern' defined as macro" "" { target c++26 } }
+#define false 1 // { dg-error "keyword 'false' defined as macro" "" { target c++26 } }
+#define float 1 // { dg-error "keyword 'float' defined as macro" "" { target c++26 } }
+#define for 1 // { dg-error "keyword 'for' defined as macro" "" { target c++26 } }
+#define friend 1 // { dg-error "keyword 'friend' defined as macro" "" { target c++26 } }
+#define goto 1 // { dg-error "keyword 'goto' defined as macro" "" { target c++26 } }
+#define if 1 // { dg-error "keyword 'if' defined as macro" "" { target c++26 } }
+#define inline 1 // { dg-error "keyword 'inline' defined as macro" "" { target c++26 } }
+#define int 1 // { dg-error "keyword 'int' defined as macro" "" { target c++26 } }
+#define long 1 // { dg-error "keyword 'long' defined as macro" "" { target c++26 } }
+#define mutable 1 // { dg-error "keyword 'mutable' defined as macro" "" { target c++26 } }
+#define namespace 1 // { dg-error "keyword 'namespace' defined as macro" "" { target c++26 } }
+#define new 1 // { dg-error "keyword 'new' defined as macro" "" { target c++26 } }
+#define noexcept 1 // { dg-error "keyword 'noexcept' defined as macro" "" { target c++26 } }
+#define nullptr 1 // { dg-error "keyword 'nullptr' defined as macro" "" { target c++26 } }
+#define operator 1 // { dg-error "keyword 'operator' defined as macro" "" { target c++26 } }
+#define private 1 // { dg-error "keyword 'private' defined as macro" "" { target c++26 } }
+#define protected 1 // { dg-error "keyword 'protected' defined as macro" "" { target c++26 } }
+#define public 1 // { dg-error "keyword 'public' defined as macro" "" { target c++26 } }
+#define register 1 // { dg-error "keyword 'register' defined as macro" "" { target c++26 } }
+#define reinterpret_cast 1 // { dg-error "keyword 'reinterpret_cast' defined as macro" "" { target c++26 } }
+#define requires 1 // { dg-error "keyword 'requires' defined as macro" "" { target c++26 } }
+#define return 1 // { dg-error "keyword 'return' defined as macro" "" { target c++26 } }
+#define short 1 // { dg-error "keyword 'short' defined as macro" "" { target c++26 } }
+#define signed 1 // { dg-error "keyword 'signed' defined as macro" "" { target c++26 } }
+#define sizeof 1 // { dg-error "keyword 'sizeof' defined as macro" "" { target c++26 } }
+#define static 1 // { dg-error "keyword 'static' defined as macro" "" { target c++26 } }
+#define static_assert 1 // { dg-error "keyword 'static_assert' defined as macro" "" { target c++26 } }
+#define static_cast 1 // { dg-error "keyword 'static_cast' defined as macro" "" { target c++26 } }
+#define struct 1 // { dg-error "keyword 'struct' defined as macro" "" { target c++26 } }
+#define switch 1 // { dg-error "keyword 'switch' defined as macro" "" { target c++26 } }
+#define template 1 // { dg-error "keyword 'template' defined as macro" "" { target c++26 } }
+#define this 1 // { dg-error "keyword 'this' defined as macro" "" { target c++26 } }
+#define thread_local 1 // { dg-error "keyword 'thread_local' defined as macro" "" { target c++26 } }
+#define throw 1 // { dg-error "keyword 'throw' defined as macro" "" { target c++26 } }
+#define true 1 // { dg-error "keyword 'true' defined as macro" "" { target c++26 } }
+#define try 1 // { dg-error "keyword 'try' defined as macro" "" { target c++26 } }
+#define typedef 1 // { dg-error "keyword 'typedef' defined as macro" "" { target c++26 } }
+#define typeid 1 // { dg-error "keyword 'typeid' defined as macro" "" { target c++26 } }
+#define typename 1 // { dg-error "keyword 'typename' defined as macro" "" { target c++26 } }
+#define union 1 // { dg-error "keyword 'union' defined as macro" "" { target c++26 } }
+#define unsigned 1 // { dg-error "keyword 'unsigned' defined as macro" "" { target c++26 } }
+#define using 1 // { dg-error "keyword 'using' defined as macro" "" { target c++26 } }
+#define virtual 1 // { dg-error "keyword 'virtual' defined as macro" "" { target c++26 } }
+#define void 1 // { dg-error "keyword 'void' defined as macro" "" { target c++26 } }
+#define volatile 1 // { dg-error "keyword 'volatile' defined as macro" "" { target c++26 } }
+#define wchar_t 1 // { dg-error "keyword 'wchar_t' defined as macro" "" { target c++26 } }
+#define while 1 // { dg-error "keyword 'while' defined as macro" "" { target c++26 } }
+
+// [lex.name]
+#define final 1 // { dg-error "keyword 'final' defined as macro" "" { target c++26 } }
+#define import 1 // { dg-error "keyword 'import' defined as macro" "" { target c++26 } }
+#define module 1 // { dg-error "keyword 'module' defined as macro" "" { target c++26 } }
+#define override 1 // { dg-error "keyword 'override' defined as macro" "" { target c++26 } }
+#define post 1
+#define pre 1
+#define replaceable_if_eligible 1 // { dg-error "keyword 'replaceable_if_eligible' defined as macro" "" { target c++26 } }
+#define trivially_relocatable_if_eligible 1 // { dg-error "keyword 'trivially_relocatable_if_eligible' defined as macro" "" { target c++26 } }
+
+// [dcl.attr]
+#define assume 1 // { dg-error "keyword 'assume' defined as macro" "" { target c++26 } }
+#define carries_dependency 1
+#define deprecated 1 // { dg-error "keyword 'deprecated' defined as macro" "" { target c++26 } }
+#define fallthrough 1 // { dg-error "keyword 'fallthrough' defined as macro" "" { target c++26 } }
+#define indeterminate 1
+#define likely 1 // { dg-error "keyword 'likely' defined as macro" "" { target c++26 } }
+#define maybe_unused 1 // { dg-error "keyword 'maybe_unused' defined as macro" "" { target c++26 } }
+#define nodiscard 1 // { dg-error "keyword 'nodiscard' defined as macro" "" { target c++26 } }
+#define noreturn 1 // { dg-error "keyword 'noreturn' defined as macro" "" { target c++26 } }
+#define no_unique_address 1 // { dg-error "keyword 'no_unique_address' defined as macro" "" { target c++26 } }
+#define unlikely 1 // { dg-error "keyword 'unlikely' defined as macro" "" { target c++26 } }
diff --git a/gcc/testsuite/g++.dg/warn/Wkeyword-macro-10.C b/gcc/testsuite/g++.dg/warn/Wkeyword-macro-10.C
new file mode 100644
index 0000000..e6fafcd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wkeyword-macro-10.C
@@ -0,0 +1,23 @@
+// C++26 P2843R3 - Preprocessing is never undefined
+// [cpp.replace.general]/9
+// { dg-do preprocess }
+// { dg-options "-Wkeyword-macro" }
+
+#undef for // { dg-warning "undefining keyword 'for'" }
+#define for for // { dg-warning "keyword 'for' defined as macro" }
+#undef for // { dg-warning "undefining keyword 'for'" }
+#define while do // { dg-warning "keyword 'while' defined as macro" }
+#define while do // { dg-warning "keyword 'while' defined as macro" }
+#define while for // { dg-warning "keyword 'while' defined as macro" }
+ // { dg-warning "'while' redefined" "" { target *-*-* } .-1 }
+#undef while // { dg-warning "undefining keyword 'while'" }
+#define while while // { dg-warning "keyword 'while' defined as macro" }
+#define private public // { dg-warning "keyword 'private' defined as macro" }
+#define inline // { dg-warning "keyword 'inline' defined as macro" }
+#undef inline // { dg-warning "undefining keyword 'inline'" }
+#define inline __inline__ __attribute__((__always_inline__)) // { dg-warning "keyword 'inline' defined as macro" }
+#define likely(a) a
+#undef likely // { dg-warning "undefining keyword 'likely'" "" { target c++20 } }
+#define unlikely(a, b, c) a + b + c
+#define unlikely(a, b, c) a + b + c
+#undef unlikely // { dg-warning "undefining keyword 'unlikely'" "" { target c++20 } }
diff --git a/gcc/testsuite/g++.dg/warn/Wkeyword-macro-2.C b/gcc/testsuite/g++.dg/warn/Wkeyword-macro-2.C
new file mode 100644
index 0000000..b1a9aa2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wkeyword-macro-2.C
@@ -0,0 +1,112 @@
+// C++26 P2843R3 - Preprocessing is never undefined
+// [cpp.replace.general]/9
+// { dg-do preprocess }
+// { dg-options "-pedantic" }
+// { dg-additional-options "-fmodules" { target c++20 } }
+
+// [lex.key]
+#define alignas 1 // { dg-warning "keyword 'alignas' defined as macro" "" { target c++26 } }
+#define alignof 1 // { dg-warning "keyword 'alignof' defined as macro" "" { target c++26 } }
+#define asm 1 // { dg-warning "keyword 'asm' defined as macro" "" { target c++26 } }
+#define auto 1 // { dg-warning "keyword 'auto' defined as macro" "" { target c++26 } }
+#define bool 1 // { dg-warning "keyword 'bool' defined as macro" "" { target c++26 } }
+#define break 1 // { dg-warning "keyword 'break' defined as macro" "" { target c++26 } }
+#define case 1 // { dg-warning "keyword 'case' defined as macro" "" { target c++26 } }
+#define catch 1 // { dg-warning "keyword 'catch' defined as macro" "" { target c++26 } }
+#define char 1 // { dg-warning "keyword 'char' defined as macro" "" { target c++26 } }
+#define char16_t 1 // { dg-warning "keyword 'char16_t' defined as macro" "" { target c++26 } }
+#define char32_t 1 // { dg-warning "keyword 'char32_t' defined as macro" "" { target c++26 } }
+#define char8_t 1 // { dg-warning "keyword 'char8_t' defined as macro" "" { target c++26 } }
+#define class 1 // { dg-warning "keyword 'class' defined as macro" "" { target c++26 } }
+#define co_await 1 // { dg-warning "keyword 'co_await' defined as macro" "" { target c++26 } }
+#define concept 1 // { dg-warning "keyword 'concept' defined as macro" "" { target c++26 } }
+#define const 1 // { dg-warning "keyword 'const' defined as macro" "" { target c++26 } }
+#define const_cast 1 // { dg-warning "keyword 'const_cast' defined as macro" "" { target c++26 } }
+#define consteval 1 // { dg-warning "keyword 'consteval' defined as macro" "" { target c++26 } }
+#define constexpr 1 // { dg-warning "keyword 'constexpr' defined as macro" "" { target c++26 } }
+#define constinit 1 // { dg-warning "keyword 'constinit' defined as macro" "" { target c++26 } }
+#define continue 1 // { dg-warning "keyword 'continue' defined as macro" "" { target c++26 } }
+#define contract_assert 1
+#define co_return 1 // { dg-warning "keyword 'co_return' defined as macro" "" { target c++26 } }
+#define co_yield 1 // { dg-warning "keyword 'co_yield' defined as macro" "" { target c++26 } }
+#define decltype 1 // { dg-warning "keyword 'decltype' defined as macro" "" { target c++26 } }
+#define default 1 // { dg-warning "keyword 'default' defined as macro" "" { target c++26 } }
+#define delete 1 // { dg-warning "keyword 'delete' defined as macro" "" { target c++26 } }
+#define do 1 // { dg-warning "keyword 'do' defined as macro" "" { target c++26 } }
+#define double 1 // { dg-warning "keyword 'double' defined as macro" "" { target c++26 } }
+#define dynamic_cast 1 // { dg-warning "keyword 'dynamic_cast' defined as macro" "" { target c++26 } }
+#define else 1 // { dg-warning "keyword 'else' defined as macro" "" { target c++26 } }
+#define enum 1 // { dg-warning "keyword 'enum' defined as macro" "" { target c++26 } }
+#define explicit 1 // { dg-warning "keyword 'explicit' defined as macro" "" { target c++26 } }
+#define export 1 // { dg-warning "keyword 'export' defined as macro" "" { target c++26 } }
+#define extern 1 // { dg-warning "keyword 'extern' defined as macro" "" { target c++26 } }
+#define false 1 // { dg-warning "keyword 'false' defined as macro" "" { target c++26 } }
+#define float 1 // { dg-warning "keyword 'float' defined as macro" "" { target c++26 } }
+#define for 1 // { dg-warning "keyword 'for' defined as macro" "" { target c++26 } }
+#define friend 1 // { dg-warning "keyword 'friend' defined as macro" "" { target c++26 } }
+#define goto 1 // { dg-warning "keyword 'goto' defined as macro" "" { target c++26 } }
+#define if 1 // { dg-warning "keyword 'if' defined as macro" "" { target c++26 } }
+#define inline 1 // { dg-warning "keyword 'inline' defined as macro" "" { target c++26 } }
+#define int 1 // { dg-warning "keyword 'int' defined as macro" "" { target c++26 } }
+#define long 1 // { dg-warning "keyword 'long' defined as macro" "" { target c++26 } }
+#define mutable 1 // { dg-warning "keyword 'mutable' defined as macro" "" { target c++26 } }
+#define namespace 1 // { dg-warning "keyword 'namespace' defined as macro" "" { target c++26 } }
+#define new 1 // { dg-warning "keyword 'new' defined as macro" "" { target c++26 } }
+#define noexcept 1 // { dg-warning "keyword 'noexcept' defined as macro" "" { target c++26 } }
+#define nullptr 1 // { dg-warning "keyword 'nullptr' defined as macro" "" { target c++26 } }
+#define operator 1 // { dg-warning "keyword 'operator' defined as macro" "" { target c++26 } }
+#define private 1 // { dg-warning "keyword 'private' defined as macro" "" { target c++26 } }
+#define protected 1 // { dg-warning "keyword 'protected' defined as macro" "" { target c++26 } }
+#define public 1 // { dg-warning "keyword 'public' defined as macro" "" { target c++26 } }
+#define register 1 // { dg-warning "keyword 'register' defined as macro" "" { target c++26 } }
+#define reinterpret_cast 1 // { dg-warning "keyword 'reinterpret_cast' defined as macro" "" { target c++26 } }
+#define requires 1 // { dg-warning "keyword 'requires' defined as macro" "" { target c++26 } }
+#define return 1 // { dg-warning "keyword 'return' defined as macro" "" { target c++26 } }
+#define short 1 // { dg-warning "keyword 'short' defined as macro" "" { target c++26 } }
+#define signed 1 // { dg-warning "keyword 'signed' defined as macro" "" { target c++26 } }
+#define sizeof 1 // { dg-warning "keyword 'sizeof' defined as macro" "" { target c++26 } }
+#define static 1 // { dg-warning "keyword 'static' defined as macro" "" { target c++26 } }
+#define static_assert 1 // { dg-warning "keyword 'static_assert' defined as macro" "" { target c++26 } }
+#define static_cast 1 // { dg-warning "keyword 'static_cast' defined as macro" "" { target c++26 } }
+#define struct 1 // { dg-warning "keyword 'struct' defined as macro" "" { target c++26 } }
+#define switch 1 // { dg-warning "keyword 'switch' defined as macro" "" { target c++26 } }
+#define template 1 // { dg-warning "keyword 'template' defined as macro" "" { target c++26 } }
+#define this 1 // { dg-warning "keyword 'this' defined as macro" "" { target c++26 } }
+#define thread_local 1 // { dg-warning "keyword 'thread_local' defined as macro" "" { target c++26 } }
+#define throw 1 // { dg-warning "keyword 'throw' defined as macro" "" { target c++26 } }
+#define true 1 // { dg-warning "keyword 'true' defined as macro" "" { target c++26 } }
+#define try 1 // { dg-warning "keyword 'try' defined as macro" "" { target c++26 } }
+#define typedef 1 // { dg-warning "keyword 'typedef' defined as macro" "" { target c++26 } }
+#define typeid 1 // { dg-warning "keyword 'typeid' defined as macro" "" { target c++26 } }
+#define typename 1 // { dg-warning "keyword 'typename' defined as macro" "" { target c++26 } }
+#define union 1 // { dg-warning "keyword 'union' defined as macro" "" { target c++26 } }
+#define unsigned 1 // { dg-warning "keyword 'unsigned' defined as macro" "" { target c++26 } }
+#define using 1 // { dg-warning "keyword 'using' defined as macro" "" { target c++26 } }
+#define virtual 1 // { dg-warning "keyword 'virtual' defined as macro" "" { target c++26 } }
+#define void 1 // { dg-warning "keyword 'void' defined as macro" "" { target c++26 } }
+#define volatile 1 // { dg-warning "keyword 'volatile' defined as macro" "" { target c++26 } }
+#define wchar_t 1 // { dg-warning "keyword 'wchar_t' defined as macro" "" { target c++26 } }
+#define while 1 // { dg-warning "keyword 'while' defined as macro" "" { target c++26 } }
+
+// [lex.name]
+#define final 1 // { dg-warning "keyword 'final' defined as macro" "" { target c++26 } }
+#define import 1 // { dg-warning "keyword 'import' defined as macro" "" { target c++26 } }
+#define module 1 // { dg-warning "keyword 'module' defined as macro" "" { target c++26 } }
+#define override 1 // { dg-warning "keyword 'override' defined as macro" "" { target c++26 } }
+#define post 1
+#define pre 1
+#define replaceable_if_eligible 1 // { dg-warning "keyword 'replaceable_if_eligible' defined as macro" "" { target c++26 } }
+#define trivially_relocatable_if_eligible 1 // { dg-warning "keyword 'trivially_relocatable_if_eligible' defined as macro" "" { target c++26 } }
+
+// [dcl.attr]
+#define assume 1 // { dg-warning "keyword 'assume' defined as macro" "" { target c++26 } }
+#define carries_dependency 1
+#define deprecated 1 // { dg-warning "keyword 'deprecated' defined as macro" "" { target c++26 } }
+#define fallthrough 1 // { dg-warning "keyword 'fallthrough' defined as macro" "" { target c++26 } }
+#define indeterminate 1
+#define likely 1 // { dg-warning "keyword 'likely' defined as macro" "" { target c++26 } }
+#define maybe_unused 1 // { dg-warning "keyword 'maybe_unused' defined as macro" "" { target c++26 } }
+#define nodiscard 1 // { dg-warning "keyword 'nodiscard' defined as macro" "" { target c++26 } }
+#define noreturn 1 // { dg-warning "keyword 'noreturn' defined as macro" "" { target c++26 } }
+#define no_unique_address 1 // { dg-warning "keyword 'no_unique_address' defined as macro" "" { target c++26 } }
+#define unlikely 1 // { dg-warning "keyword 'unlikely' defined as macro" "" { target c++26 } }
diff --git a/gcc/testsuite/g++.dg/warn/Wkeyword-macro-3.C b/gcc/testsuite/g++.dg/warn/Wkeyword-macro-3.C
new file mode 100644
index 0000000..8576b64
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wkeyword-macro-3.C
@@ -0,0 +1,7 @@
+// C++26 P2843R3 - Preprocessing is never undefined
+// [cpp.replace.general]/9
+// { dg-do preprocess }
+// { dg-options "" }
+// { dg-additional-options "-fmodules" { target c++20 } }
+
+#include "Wkeyword-macro-1.C"
diff --git a/gcc/testsuite/g++.dg/warn/Wkeyword-macro-4.C b/gcc/testsuite/g++.dg/warn/Wkeyword-macro-4.C
new file mode 100644
index 0000000..9ff974d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wkeyword-macro-4.C
@@ -0,0 +1,112 @@
+// C++26 P2843R3 - Preprocessing is never undefined
+// [cpp.replace.general]/9
+// { dg-do preprocess }
+// { dg-options "-pedantic-errors" }
+// { dg-additional-options "-fmodules" { target c++20 } }
+
+// [lex.key]
+#undef alignas // { dg-error "undefining keyword 'alignas'" "" { target c++26 } }
+#undef alignof // { dg-error "undefining keyword 'alignof'" "" { target c++26 } }
+#undef asm // { dg-error "undefining keyword 'asm'" "" { target c++26 } }
+#undef auto // { dg-error "undefining keyword 'auto'" "" { target c++26 } }
+#undef bool // { dg-error "undefining keyword 'bool'" "" { target c++26 } }
+#undef break // { dg-error "undefining keyword 'break'" "" { target c++26 } }
+#undef case // { dg-error "undefining keyword 'case'" "" { target c++26 } }
+#undef catch // { dg-error "undefining keyword 'catch'" "" { target c++26 } }
+#undef char // { dg-error "undefining keyword 'char'" "" { target c++26 } }
+#undef char16_t // { dg-error "undefining keyword 'char16_t'" "" { target c++26 } }
+#undef char32_t // { dg-error "undefining keyword 'char32_t'" "" { target c++26 } }
+#undef char8_t // { dg-error "undefining keyword 'char8_t'" "" { target c++26 } }
+#undef class // { dg-error "undefining keyword 'class'" "" { target c++26 } }
+#undef co_await // { dg-error "undefining keyword 'co_await'" "" { target c++26 } }
+#undef concept // { dg-error "undefining keyword 'concept'" "" { target c++26 } }
+#undef const // { dg-error "undefining keyword 'const'" "" { target c++26 } }
+#undef const_cast // { dg-error "undefining keyword 'const_cast'" "" { target c++26 } }
+#undef consteval // { dg-error "undefining keyword 'consteval'" "" { target c++26 } }
+#undef constexpr // { dg-error "undefining keyword 'constexpr'" "" { target c++26 } }
+#undef constinit // { dg-error "undefining keyword 'constinit'" "" { target c++26 } }
+#undef continue // { dg-error "undefining keyword 'continue'" "" { target c++26 } }
+#undef contract_assert
+#undef co_return // { dg-error "undefining keyword 'co_return'" "" { target c++26 } }
+#undef co_yield // { dg-error "undefining keyword 'co_yield'" "" { target c++26 } }
+#undef decltype // { dg-error "undefining keyword 'decltype'" "" { target c++26 } }
+#undef default // { dg-error "undefining keyword 'default'" "" { target c++26 } }
+#undef delete // { dg-error "undefining keyword 'delete'" "" { target c++26 } }
+#undef do // { dg-error "undefining keyword 'do'" "" { target c++26 } }
+#undef double // { dg-error "undefining keyword 'double'" "" { target c++26 } }
+#undef dynamic_cast // { dg-error "undefining keyword 'dynamic_cast'" "" { target c++26 } }
+#undef else // { dg-error "undefining keyword 'else'" "" { target c++26 } }
+#undef enum // { dg-error "undefining keyword 'enum'" "" { target c++26 } }
+#undef explicit // { dg-error "undefining keyword 'explicit'" "" { target c++26 } }
+#undef export // { dg-error "undefining keyword 'export'" "" { target c++26 } }
+#undef extern // { dg-error "undefining keyword 'extern'" "" { target c++26 } }
+#undef false // { dg-error "undefining keyword 'false'" "" { target c++26 } }
+#undef float // { dg-error "undefining keyword 'float'" "" { target c++26 } }
+#undef for // { dg-error "undefining keyword 'for'" "" { target c++26 } }
+#undef friend // { dg-error "undefining keyword 'friend'" "" { target c++26 } }
+#undef goto // { dg-error "undefining keyword 'goto'" "" { target c++26 } }
+#undef if // { dg-error "undefining keyword 'if'" "" { target c++26 } }
+#undef inline // { dg-error "undefining keyword 'inline'" "" { target c++26 } }
+#undef int // { dg-error "undefining keyword 'int'" "" { target c++26 } }
+#undef long // { dg-error "undefining keyword 'long'" "" { target c++26 } }
+#undef mutable // { dg-error "undefining keyword 'mutable'" "" { target c++26 } }
+#undef namespace // { dg-error "undefining keyword 'namespace'" "" { target c++26 } }
+#undef new // { dg-error "undefining keyword 'new'" "" { target c++26 } }
+#undef noexcept // { dg-error "undefining keyword 'noexcept'" "" { target c++26 } }
+#undef nullptr // { dg-error "undefining keyword 'nullptr'" "" { target c++26 } }
+#undef operator // { dg-error "undefining keyword 'operator'" "" { target c++26 } }
+#undef private // { dg-error "undefining keyword 'private'" "" { target c++26 } }
+#undef protected // { dg-error "undefining keyword 'protected'" "" { target c++26 } }
+#undef public // { dg-error "undefining keyword 'public'" "" { target c++26 } }
+#undef register // { dg-error "undefining keyword 'register'" "" { target c++26 } }
+#undef reinterpret_cast // { dg-error "undefining keyword 'reinterpret_cast'" "" { target c++26 } }
+#undef requires // { dg-error "undefining keyword 'requires'" "" { target c++26 } }
+#undef return // { dg-error "undefining keyword 'return'" "" { target c++26 } }
+#undef short // { dg-error "undefining keyword 'short'" "" { target c++26 } }
+#undef signed // { dg-error "undefining keyword 'signed'" "" { target c++26 } }
+#undef sizeof // { dg-error "undefining keyword 'sizeof'" "" { target c++26 } }
+#undef static // { dg-error "undefining keyword 'static'" "" { target c++26 } }
+#undef static_assert // { dg-error "undefining keyword 'static_assert'" "" { target c++26 } }
+#undef static_cast // { dg-error "undefining keyword 'static_cast'" "" { target c++26 } }
+#undef struct // { dg-error "undefining keyword 'struct'" "" { target c++26 } }
+#undef switch // { dg-error "undefining keyword 'switch'" "" { target c++26 } }
+#undef template // { dg-error "undefining keyword 'template'" "" { target c++26 } }
+#undef this // { dg-error "undefining keyword 'this'" "" { target c++26 } }
+#undef thread_local // { dg-error "undefining keyword 'thread_local'" "" { target c++26 } }
+#undef throw // { dg-error "undefining keyword 'throw'" "" { target c++26 } }
+#undef true // { dg-error "undefining keyword 'true'" "" { target c++26 } }
+#undef try // { dg-error "undefining keyword 'try'" "" { target c++26 } }
+#undef typedef // { dg-error "undefining keyword 'typedef'" "" { target c++26 } }
+#undef typeid // { dg-error "undefining keyword 'typeid'" "" { target c++26 } }
+#undef typename // { dg-error "undefining keyword 'typename'" "" { target c++26 } }
+#undef union // { dg-error "undefining keyword 'union'" "" { target c++26 } }
+#undef unsigned // { dg-error "undefining keyword 'unsigned'" "" { target c++26 } }
+#undef using // { dg-error "undefining keyword 'using'" "" { target c++26 } }
+#undef virtual // { dg-error "undefining keyword 'virtual'" "" { target c++26 } }
+#undef void // { dg-error "undefining keyword 'void'" "" { target c++26 } }
+#undef volatile // { dg-error "undefining keyword 'volatile'" "" { target c++26 } }
+#undef wchar_t // { dg-error "undefining keyword 'wchar_t'" "" { target c++26 } }
+#undef while // { dg-error "undefining keyword 'while'" "" { target c++26 } }
+
+// [lex.name]
+#undef final // { dg-error "undefining keyword 'final'" "" { target c++26 } }
+#undef import // { dg-error "undefining keyword 'import'" "" { target c++26 } }
+#undef module // { dg-error "undefining keyword 'module'" "" { target c++26 } }
+#undef override // { dg-error "undefining keyword 'override'" "" { target c++26 } }
+#undef post
+#undef pre
+#undef replaceable_if_eligible // { dg-error "undefining keyword 'replaceable_if_eligible'" "" { target c++26 } }
+#undef trivially_relocatable_if_eligible // { dg-error "undefining keyword 'trivially_relocatable_if_eligible'" "" { target c++26 } }
+
+// [dcl.attr]
+#undef assume // { dg-error "undefining keyword 'assume'" "" { target c++26 } }
+#undef carries_dependency
+#undef deprecated // { dg-error "undefining keyword 'deprecated'" "" { target c++26 } }
+#undef fallthrough // { dg-error "undefining keyword 'fallthrough'" "" { target c++26 } }
+#undef indeterminate
+#undef likely // { dg-error "undefining keyword 'likely'" "" { target c++26 } }
+#undef maybe_unused // { dg-error "undefining keyword 'maybe_unused'" "" { target c++26 } }
+#undef nodiscard // { dg-error "undefining keyword 'nodiscard'" "" { target c++26 } }
+#undef noreturn // { dg-error "undefining keyword 'noreturn'" "" { target c++26 } }
+#undef no_unique_address // { dg-error "undefining keyword 'no_unique_address'" "" { target c++26 } }
+#undef unlikely // { dg-error "undefining keyword 'unlikely'" "" { target c++26 } }
diff --git a/gcc/testsuite/g++.dg/warn/Wkeyword-macro-5.C b/gcc/testsuite/g++.dg/warn/Wkeyword-macro-5.C
new file mode 100644
index 0000000..657797b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wkeyword-macro-5.C
@@ -0,0 +1,112 @@
+// C++26 P2843R3 - Preprocessing is never undefined
+// [cpp.replace.general]/9
+// { dg-do preprocess }
+// { dg-options "-pedantic" }
+// { dg-additional-options "-fmodules" { target c++20 } }
+
+// [lex.key]
+#undef alignas // { dg-warning "undefining keyword 'alignas'" "" { target c++26 } }
+#undef alignof // { dg-warning "undefining keyword 'alignof'" "" { target c++26 } }
+#undef asm // { dg-warning "undefining keyword 'asm'" "" { target c++26 } }
+#undef auto // { dg-warning "undefining keyword 'auto'" "" { target c++26 } }
+#undef bool // { dg-warning "undefining keyword 'bool'" "" { target c++26 } }
+#undef break // { dg-warning "undefining keyword 'break'" "" { target c++26 } }
+#undef case // { dg-warning "undefining keyword 'case'" "" { target c++26 } }
+#undef catch // { dg-warning "undefining keyword 'catch'" "" { target c++26 } }
+#undef char // { dg-warning "undefining keyword 'char'" "" { target c++26 } }
+#undef char16_t // { dg-warning "undefining keyword 'char16_t'" "" { target c++26 } }
+#undef char32_t // { dg-warning "undefining keyword 'char32_t'" "" { target c++26 } }
+#undef char8_t // { dg-warning "undefining keyword 'char8_t'" "" { target c++26 } }
+#undef class // { dg-warning "undefining keyword 'class'" "" { target c++26 } }
+#undef co_await // { dg-warning "undefining keyword 'co_await'" "" { target c++26 } }
+#undef concept // { dg-warning "undefining keyword 'concept'" "" { target c++26 } }
+#undef const // { dg-warning "undefining keyword 'const'" "" { target c++26 } }
+#undef const_cast // { dg-warning "undefining keyword 'const_cast'" "" { target c++26 } }
+#undef consteval // { dg-warning "undefining keyword 'consteval'" "" { target c++26 } }
+#undef constexpr // { dg-warning "undefining keyword 'constexpr'" "" { target c++26 } }
+#undef constinit // { dg-warning "undefining keyword 'constinit'" "" { target c++26 } }
+#undef continue // { dg-warning "undefining keyword 'continue'" "" { target c++26 } }
+#undef contract_assert
+#undef co_return // { dg-warning "undefining keyword 'co_return'" "" { target c++26 } }
+#undef co_yield // { dg-warning "undefining keyword 'co_yield'" "" { target c++26 } }
+#undef decltype // { dg-warning "undefining keyword 'decltype'" "" { target c++26 } }
+#undef default // { dg-warning "undefining keyword 'default'" "" { target c++26 } }
+#undef delete // { dg-warning "undefining keyword 'delete'" "" { target c++26 } }
+#undef do // { dg-warning "undefining keyword 'do'" "" { target c++26 } }
+#undef double // { dg-warning "undefining keyword 'double'" "" { target c++26 } }
+#undef dynamic_cast // { dg-warning "undefining keyword 'dynamic_cast'" "" { target c++26 } }
+#undef else // { dg-warning "undefining keyword 'else'" "" { target c++26 } }
+#undef enum // { dg-warning "undefining keyword 'enum'" "" { target c++26 } }
+#undef explicit // { dg-warning "undefining keyword 'explicit'" "" { target c++26 } }
+#undef export // { dg-warning "undefining keyword 'export'" "" { target c++26 } }
+#undef extern // { dg-warning "undefining keyword 'extern'" "" { target c++26 } }
+#undef false // { dg-warning "undefining keyword 'false'" "" { target c++26 } }
+#undef float // { dg-warning "undefining keyword 'float'" "" { target c++26 } }
+#undef for // { dg-warning "undefining keyword 'for'" "" { target c++26 } }
+#undef friend // { dg-warning "undefining keyword 'friend'" "" { target c++26 } }
+#undef goto // { dg-warning "undefining keyword 'goto'" "" { target c++26 } }
+#undef if // { dg-warning "undefining keyword 'if'" "" { target c++26 } }
+#undef inline // { dg-warning "undefining keyword 'inline'" "" { target c++26 } }
+#undef int // { dg-warning "undefining keyword 'int'" "" { target c++26 } }
+#undef long // { dg-warning "undefining keyword 'long'" "" { target c++26 } }
+#undef mutable // { dg-warning "undefining keyword 'mutable'" "" { target c++26 } }
+#undef namespace // { dg-warning "undefining keyword 'namespace'" "" { target c++26 } }
+#undef new // { dg-warning "undefining keyword 'new'" "" { target c++26 } }
+#undef noexcept // { dg-warning "undefining keyword 'noexcept'" "" { target c++26 } }
+#undef nullptr // { dg-warning "undefining keyword 'nullptr'" "" { target c++26 } }
+#undef operator // { dg-warning "undefining keyword 'operator'" "" { target c++26 } }
+#undef private // { dg-warning "undefining keyword 'private'" "" { target c++26 } }
+#undef protected // { dg-warning "undefining keyword 'protected'" "" { target c++26 } }
+#undef public // { dg-warning "undefining keyword 'public'" "" { target c++26 } }
+#undef register // { dg-warning "undefining keyword 'register'" "" { target c++26 } }
+#undef reinterpret_cast // { dg-warning "undefining keyword 'reinterpret_cast'" "" { target c++26 } }
+#undef requires // { dg-warning "undefining keyword 'requires'" "" { target c++26 } }
+#undef return // { dg-warning "undefining keyword 'return'" "" { target c++26 } }
+#undef short // { dg-warning "undefining keyword 'short'" "" { target c++26 } }
+#undef signed // { dg-warning "undefining keyword 'signed'" "" { target c++26 } }
+#undef sizeof // { dg-warning "undefining keyword 'sizeof'" "" { target c++26 } }
+#undef static // { dg-warning "undefining keyword 'static'" "" { target c++26 } }
+#undef static_assert // { dg-warning "undefining keyword 'static_assert'" "" { target c++26 } }
+#undef static_cast // { dg-warning "undefining keyword 'static_cast'" "" { target c++26 } }
+#undef struct // { dg-warning "undefining keyword 'struct'" "" { target c++26 } }
+#undef switch // { dg-warning "undefining keyword 'switch'" "" { target c++26 } }
+#undef template // { dg-warning "undefining keyword 'template'" "" { target c++26 } }
+#undef this // { dg-warning "undefining keyword 'this'" "" { target c++26 } }
+#undef thread_local // { dg-warning "undefining keyword 'thread_local'" "" { target c++26 } }
+#undef throw // { dg-warning "undefining keyword 'throw'" "" { target c++26 } }
+#undef true // { dg-warning "undefining keyword 'true'" "" { target c++26 } }
+#undef try // { dg-warning "undefining keyword 'try'" "" { target c++26 } }
+#undef typedef // { dg-warning "undefining keyword 'typedef'" "" { target c++26 } }
+#undef typeid // { dg-warning "undefining keyword 'typeid'" "" { target c++26 } }
+#undef typename // { dg-warning "undefining keyword 'typename'" "" { target c++26 } }
+#undef union // { dg-warning "undefining keyword 'union'" "" { target c++26 } }
+#undef unsigned // { dg-warning "undefining keyword 'unsigned'" "" { target c++26 } }
+#undef using // { dg-warning "undefining keyword 'using'" "" { target c++26 } }
+#undef virtual // { dg-warning "undefining keyword 'virtual'" "" { target c++26 } }
+#undef void // { dg-warning "undefining keyword 'void'" "" { target c++26 } }
+#undef volatile // { dg-warning "undefining keyword 'volatile'" "" { target c++26 } }
+#undef wchar_t // { dg-warning "undefining keyword 'wchar_t'" "" { target c++26 } }
+#undef while // { dg-warning "undefining keyword 'while'" "" { target c++26 } }
+
+// [lex.name]
+#undef final // { dg-warning "undefining keyword 'final'" "" { target c++26 } }
+#undef import // { dg-warning "undefining keyword 'import'" "" { target c++26 } }
+#undef module // { dg-warning "undefining keyword 'module'" "" { target c++26 } }
+#undef override // { dg-warning "undefining keyword 'override'" "" { target c++26 } }
+#undef post
+#undef pre
+#undef replaceable_if_eligible // { dg-warning "undefining keyword 'replaceable_if_eligible'" "" { target c++26 } }
+#undef trivially_relocatable_if_eligible // { dg-warning "undefining keyword 'trivially_relocatable_if_eligible'" "" { target c++26 } }
+
+// [dcl.attr]
+#undef assume // { dg-warning "undefining keyword 'assume'" "" { target c++26 } }
+#undef carries_dependency
+#undef deprecated // { dg-warning "undefining keyword 'deprecated'" "" { target c++26 } }
+#undef fallthrough // { dg-warning "undefining keyword 'fallthrough'" "" { target c++26 } }
+#undef indeterminate
+#undef likely // { dg-warning "undefining keyword 'likely'" "" { target c++26 } }
+#undef maybe_unused // { dg-warning "undefining keyword 'maybe_unused'" "" { target c++26 } }
+#undef nodiscard // { dg-warning "undefining keyword 'nodiscard'" "" { target c++26 } }
+#undef noreturn // { dg-warning "undefining keyword 'noreturn'" "" { target c++26 } }
+#undef no_unique_address // { dg-warning "undefining keyword 'no_unique_address'" "" { target c++26 } }
+#undef unlikely // { dg-warning "undefining keyword 'unlikely'" "" { target c++26 } }
diff --git a/gcc/testsuite/g++.dg/warn/Wkeyword-macro-6.C b/gcc/testsuite/g++.dg/warn/Wkeyword-macro-6.C
new file mode 100644
index 0000000..881df8b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wkeyword-macro-6.C
@@ -0,0 +1,7 @@
+// C++26 P2843R3 - Preprocessing is never undefined
+// [cpp.replace.general]/9
+// { dg-do preprocess }
+// { dg-options "" }
+// { dg-additional-options "-fmodules" { target c++20 } }
+
+#include "Wkeyword-macro-4.C"
diff --git a/gcc/testsuite/g++.dg/warn/Wkeyword-macro-7.C b/gcc/testsuite/g++.dg/warn/Wkeyword-macro-7.C
new file mode 100644
index 0000000..30a2c8d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wkeyword-macro-7.C
@@ -0,0 +1,112 @@
+// C++26 P2843R3 - Preprocessing is never undefined
+// [cpp.replace.general]/9
+// { dg-do preprocess }
+// { dg-options "-Wkeyword-macro" }
+// { dg-additional-options "-fmodules" { target c++20 } }
+
+// [lex.key]
+#define alignas 1 // { dg-warning "keyword 'alignas' defined as macro" "" { target c++11 } }
+#define alignof 1 // { dg-warning "keyword 'alignof' defined as macro" "" { target c++11 } }
+#define asm 1 // { dg-warning "keyword 'asm' defined as macro" }
+#define auto 1 // { dg-warning "keyword 'auto' defined as macro" }
+#define bool 1 // { dg-warning "keyword 'bool' defined as macro" }
+#define break 1 // { dg-warning "keyword 'break' defined as macro" }
+#define case 1 // { dg-warning "keyword 'case' defined as macro" }
+#define catch 1 // { dg-warning "keyword 'catch' defined as macro" }
+#define char 1 // { dg-warning "keyword 'char' defined as macro" }
+#define char16_t 1 // { dg-warning "keyword 'char16_t' defined as macro" "" { target c++11 } }
+#define char32_t 1 // { dg-warning "keyword 'char32_t' defined as macro" "" { target c++11 } }
+#define char8_t 1 // { dg-warning "keyword 'char8_t' defined as macro" "" { target c++20 } }
+#define class 1 // { dg-warning "keyword 'class' defined as macro" }
+#define co_await 1 // { dg-warning "keyword 'co_await' defined as macro" "" { target c++20 } }
+#define concept 1 // { dg-warning "keyword 'concept' defined as macro" "" { target c++20 } }
+#define const 1 // { dg-warning "keyword 'const' defined as macro" }
+#define const_cast 1 // { dg-warning "keyword 'const_cast' defined as macro" }
+#define consteval 1 // { dg-warning "keyword 'consteval' defined as macro" "" { target c++20 } }
+#define constexpr 1 // { dg-warning "keyword 'constexpr' defined as macro" "" { target c++11 } }
+#define constinit 1 // { dg-warning "keyword 'constinit' defined as macro" "" { target c++20 } }
+#define continue 1 // { dg-warning "keyword 'continue' defined as macro" }
+#define contract_assert 1
+#define co_return 1 // { dg-warning "keyword 'co_return' defined as macro" "" { target c++20 } }
+#define co_yield 1 // { dg-warning "keyword 'co_yield' defined as macro" "" { target c++20 } }
+#define decltype 1 // { dg-warning "keyword 'decltype' defined as macro" "" { target c++11 } }
+#define default 1 // { dg-warning "keyword 'default' defined as macro" }
+#define delete 1 // { dg-warning "keyword 'delete' defined as macro" }
+#define do 1 // { dg-warning "keyword 'do' defined as macro" }
+#define double 1 // { dg-warning "keyword 'double' defined as macro" }
+#define dynamic_cast 1 // { dg-warning "keyword 'dynamic_cast' defined as macro" }
+#define else 1 // { dg-warning "keyword 'else' defined as macro" }
+#define enum 1 // { dg-warning "keyword 'enum' defined as macro" }
+#define explicit 1 // { dg-warning "keyword 'explicit' defined as macro" }
+#define export 1 // { dg-warning "keyword 'export' defined as macro" }
+#define extern 1 // { dg-warning "keyword 'extern' defined as macro" }
+#define false 1 // { dg-warning "keyword 'false' defined as macro" }
+#define float 1 // { dg-warning "keyword 'float' defined as macro" }
+#define for 1 // { dg-warning "keyword 'for' defined as macro" }
+#define friend 1 // { dg-warning "keyword 'friend' defined as macro" }
+#define goto 1 // { dg-warning "keyword 'goto' defined as macro" }
+#define if 1 // { dg-warning "keyword 'if' defined as macro" }
+#define inline 1 // { dg-warning "keyword 'inline' defined as macro" }
+#define int 1 // { dg-warning "keyword 'int' defined as macro" }
+#define long 1 // { dg-warning "keyword 'long' defined as macro" }
+#define mutable 1 // { dg-warning "keyword 'mutable' defined as macro" }
+#define namespace 1 // { dg-warning "keyword 'namespace' defined as macro" }
+#define new 1 // { dg-warning "keyword 'new' defined as macro" }
+#define noexcept 1 // { dg-warning "keyword 'noexcept' defined as macro" "" { target c++11 } }
+#define nullptr 1 // { dg-warning "keyword 'nullptr' defined as macro" "" { target c++11 } }
+#define operator 1 // { dg-warning "keyword 'operator' defined as macro" }
+#define private 1 // { dg-warning "keyword 'private' defined as macro" }
+#define protected 1 // { dg-warning "keyword 'protected' defined as macro" }
+#define public 1 // { dg-warning "keyword 'public' defined as macro" }
+#define register 1 // { dg-warning "keyword 'register' defined as macro" }
+#define reinterpret_cast 1 // { dg-warning "keyword 'reinterpret_cast' defined as macro" }
+#define requires 1 // { dg-warning "keyword 'requires' defined as macro" "" { target c++20 } }
+#define return 1 // { dg-warning "keyword 'return' defined as macro" }
+#define short 1 // { dg-warning "keyword 'short' defined as macro" }
+#define signed 1 // { dg-warning "keyword 'signed' defined as macro" }
+#define sizeof 1 // { dg-warning "keyword 'sizeof' defined as macro" }
+#define static 1 // { dg-warning "keyword 'static' defined as macro" }
+#define static_assert 1 // { dg-warning "keyword 'static_assert' defined as macro" "" { target c++11 } }
+#define static_cast 1 // { dg-warning "keyword 'static_cast' defined as macro" }
+#define struct 1 // { dg-warning "keyword 'struct' defined as macro" }
+#define switch 1 // { dg-warning "keyword 'switch' defined as macro" }
+#define template 1 // { dg-warning "keyword 'template' defined as macro" }
+#define this 1 // { dg-warning "keyword 'this' defined as macro" }
+#define thread_local 1 // { dg-warning "keyword 'thread_local' defined as macro" "" { target c++11 } }
+#define throw 1 // { dg-warning "keyword 'throw' defined as macro" }
+#define true 1 // { dg-warning "keyword 'true' defined as macro" }
+#define try 1 // { dg-warning "keyword 'try' defined as macro" }
+#define typedef 1 // { dg-warning "keyword 'typedef' defined as macro" }
+#define typeid 1 // { dg-warning "keyword 'typeid' defined as macro" }
+#define typename 1 // { dg-warning "keyword 'typename' defined as macro" }
+#define union 1 // { dg-warning "keyword 'union' defined as macro" }
+#define unsigned 1 // { dg-warning "keyword 'unsigned' defined as macro" }
+#define using 1 // { dg-warning "keyword 'using' defined as macro" }
+#define virtual 1 // { dg-warning "keyword 'virtual' defined as macro" }
+#define void 1 // { dg-warning "keyword 'void' defined as macro" }
+#define volatile 1 // { dg-warning "keyword 'volatile' defined as macro" }
+#define wchar_t 1 // { dg-warning "keyword 'wchar_t' defined as macro" }
+#define while 1 // { dg-warning "keyword 'while' defined as macro" }
+
+// [lex.name]
+#define final 1 // { dg-warning "keyword 'final' defined as macro" "" { target c++11 } }
+#define import 1 // { dg-warning "keyword 'import' defined as macro" "" { target c++20 } }
+#define module 1 // { dg-warning "keyword 'module' defined as macro" "" { target c++20 } }
+#define override 1 // { dg-warning "keyword 'override' defined as macro" "" { target c++11 } }
+#define post 1
+#define pre 1
+#define replaceable_if_eligible 1 // { dg-warning "keyword 'replaceable_if_eligible' defined as macro" "" { target c++26 } }
+#define trivially_relocatable_if_eligible 1 // { dg-warning "keyword 'trivially_relocatable_if_eligible' defined as macro" "" { target c++26 } }
+
+// [dcl.attr]
+#define assume 1 // { dg-warning "keyword 'assume' defined as macro" "" { target c++23 } }
+#define carries_dependency 1 // { dg-warning "keyword 'carries_dependency' defined as macro" "" { target { c++11 && c++23_down } } }
+#define deprecated 1 // { dg-warning "keyword 'deprecated' defined as macro" "" { target c++14 } }
+#define fallthrough 1 // { dg-warning "keyword 'fallthrough' defined as macro" "" { target c++17 } }
+#define indeterminate 1
+#define likely 1 // { dg-warning "keyword 'likely' defined as macro" "" { target c++20 } }
+#define maybe_unused 1 // { dg-warning "keyword 'maybe_unused' defined as macro" "" { target c++17 } }
+#define nodiscard 1 // { dg-warning "keyword 'nodiscard' defined as macro" "" { target c++17 } }
+#define noreturn 1 // { dg-warning "keyword 'noreturn' defined as macro" "" { target c++11 } }
+#define no_unique_address 1 // { dg-warning "keyword 'no_unique_address' defined as macro" "" { target c++20 } }
+#define unlikely 1 // { dg-warning "keyword 'unlikely' defined as macro" "" { target c++20 } }
diff --git a/gcc/testsuite/g++.dg/warn/Wkeyword-macro-8.C b/gcc/testsuite/g++.dg/warn/Wkeyword-macro-8.C
new file mode 100644
index 0000000..7dcc377
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wkeyword-macro-8.C
@@ -0,0 +1,112 @@
+// C++26 P2843R3 - Preprocessing is never undefined
+// [cpp.replace.general]/9
+// { dg-do preprocess }
+// { dg-options "-Wkeyword-macro" }
+// { dg-additional-options "-fmodules" { target c++20 } }
+
+// [lex.key]
+#undef alignas // { dg-warning "undefining keyword 'alignas'" "" { target c++11 } }
+#undef alignof // { dg-warning "undefining keyword 'alignof'" "" { target c++11 } }
+#undef asm // { dg-warning "undefining keyword 'asm'" }
+#undef auto // { dg-warning "undefining keyword 'auto'" }
+#undef bool // { dg-warning "undefining keyword 'bool'" }
+#undef break // { dg-warning "undefining keyword 'break'" }
+#undef case // { dg-warning "undefining keyword 'case'" }
+#undef catch // { dg-warning "undefining keyword 'catch'" }
+#undef char // { dg-warning "undefining keyword 'char'" }
+#undef char16_t // { dg-warning "undefining keyword 'char16_t'" "" { target c++11 } }
+#undef char32_t // { dg-warning "undefining keyword 'char32_t'" "" { target c++11 } }
+#undef char8_t // { dg-warning "undefining keyword 'char8_t'" "" { target c++20 } }
+#undef class // { dg-warning "undefining keyword 'class'" }
+#undef co_await // { dg-warning "undefining keyword 'co_await'" "" { target c++20 } }
+#undef concept // { dg-warning "undefining keyword 'concept'" "" { target c++20 } }
+#undef const // { dg-warning "undefining keyword 'const'" }
+#undef const_cast // { dg-warning "undefining keyword 'const_cast'" }
+#undef consteval // { dg-warning "undefining keyword 'consteval'" "" { target c++20 } }
+#undef constexpr // { dg-warning "undefining keyword 'constexpr'" "" { target c++11 } }
+#undef constinit // { dg-warning "undefining keyword 'constinit'" "" { target c++20 } }
+#undef continue // { dg-warning "undefining keyword 'continue'" }
+#undef contract_assert
+#undef co_return // { dg-warning "undefining keyword 'co_return'" "" { target c++20 } }
+#undef co_yield // { dg-warning "undefining keyword 'co_yield'" "" { target c++20 } }
+#undef decltype // { dg-warning "undefining keyword 'decltype'" "" { target c++11 } }
+#undef default // { dg-warning "undefining keyword 'default'" }
+#undef delete // { dg-warning "undefining keyword 'delete'" }
+#undef do // { dg-warning "undefining keyword 'do'" }
+#undef double // { dg-warning "undefining keyword 'double'" }
+#undef dynamic_cast // { dg-warning "undefining keyword 'dynamic_cast'" }
+#undef else // { dg-warning "undefining keyword 'else'" }
+#undef enum // { dg-warning "undefining keyword 'enum'" }
+#undef explicit // { dg-warning "undefining keyword 'explicit'" }
+#undef export // { dg-warning "undefining keyword 'export'" }
+#undef extern // { dg-warning "undefining keyword 'extern'" }
+#undef false // { dg-warning "undefining keyword 'false'" }
+#undef float // { dg-warning "undefining keyword 'float'" }
+#undef for // { dg-warning "undefining keyword 'for'" }
+#undef friend // { dg-warning "undefining keyword 'friend'" }
+#undef goto // { dg-warning "undefining keyword 'goto'" }
+#undef if // { dg-warning "undefining keyword 'if'" }
+#undef inline // { dg-warning "undefining keyword 'inline'" }
+#undef int // { dg-warning "undefining keyword 'int'" }
+#undef long // { dg-warning "undefining keyword 'long'" }
+#undef mutable // { dg-warning "undefining keyword 'mutable'" }
+#undef namespace // { dg-warning "undefining keyword 'namespace'" }
+#undef new // { dg-warning "undefining keyword 'new'" }
+#undef noexcept // { dg-warning "undefining keyword 'noexcept'" "" { target c++11 } }
+#undef nullptr // { dg-warning "undefining keyword 'nullptr'" "" { target c++11 } }
+#undef operator // { dg-warning "undefining keyword 'operator'" }
+#undef private // { dg-warning "undefining keyword 'private'" }
+#undef protected // { dg-warning "undefining keyword 'protected'" }
+#undef public // { dg-warning "undefining keyword 'public'" }
+#undef register // { dg-warning "undefining keyword 'register'" }
+#undef reinterpret_cast // { dg-warning "undefining keyword 'reinterpret_cast'" }
+#undef requires // { dg-warning "undefining keyword 'requires'" "" { target c++20 } }
+#undef return // { dg-warning "undefining keyword 'return'" }
+#undef short // { dg-warning "undefining keyword 'short'" }
+#undef signed // { dg-warning "undefining keyword 'signed'" }
+#undef sizeof // { dg-warning "undefining keyword 'sizeof'" }
+#undef static // { dg-warning "undefining keyword 'static'" }
+#undef static_assert // { dg-warning "undefining keyword 'static_assert'" "" { target c++11 } }
+#undef static_cast // { dg-warning "undefining keyword 'static_cast'" }
+#undef struct // { dg-warning "undefining keyword 'struct'" }
+#undef switch // { dg-warning "undefining keyword 'switch'" }
+#undef template // { dg-warning "undefining keyword 'template'" }
+#undef this // { dg-warning "undefining keyword 'this'" }
+#undef thread_local // { dg-warning "undefining keyword 'thread_local'" "" { target c++11 } }
+#undef throw // { dg-warning "undefining keyword 'throw'" }
+#undef true // { dg-warning "undefining keyword 'true'" }
+#undef try // { dg-warning "undefining keyword 'try'" }
+#undef typedef // { dg-warning "undefining keyword 'typedef'" }
+#undef typeid // { dg-warning "undefining keyword 'typeid'" }
+#undef typename // { dg-warning "undefining keyword 'typename'" }
+#undef union // { dg-warning "undefining keyword 'union'" }
+#undef unsigned // { dg-warning "undefining keyword 'unsigned'" }
+#undef using // { dg-warning "undefining keyword 'using'" }
+#undef virtual // { dg-warning "undefining keyword 'virtual'" }
+#undef void // { dg-warning "undefining keyword 'void'" }
+#undef volatile // { dg-warning "undefining keyword 'volatile'" }
+#undef wchar_t // { dg-warning "undefining keyword 'wchar_t'" }
+#undef while // { dg-warning "undefining keyword 'while'" }
+
+// [lex.name]
+#undef final // { dg-warning "undefining keyword 'final'" "" { target c++11 } }
+#undef import // { dg-warning "undefining keyword 'import'" "" { target c++20 } }
+#undef module // { dg-warning "undefining keyword 'module'" "" { target c++20 } }
+#undef override // { dg-warning "undefining keyword 'override'" "" { target c++11 } }
+#undef post
+#undef pre
+#undef replaceable_if_eligible // { dg-warning "undefining keyword 'replaceable_if_eligible'" "" { target c++26 } }
+#undef trivially_relocatable_if_eligible // { dg-warning "undefining keyword 'trivially_relocatable_if_eligible'" "" { target c++26 } }
+
+// [dcl.attr]
+#undef assume // { dg-warning "undefining keyword 'assume'" "" { target c++23 } }
+#undef carries_dependency // { dg-warning "undefining keyword 'carries_dependency'" "" { target { c++11 && c++23_down } } }
+#undef deprecated // { dg-warning "undefining keyword 'deprecated'" "" { target c++14 } }
+#undef fallthrough // { dg-warning "undefining keyword 'fallthrough'" "" { target c++17 } }
+#undef indeterminate
+#undef likely // { dg-warning "undefining keyword 'likely'" "" { target c++20 } }
+#undef maybe_unused // { dg-warning "undefining keyword 'maybe_unused'" "" { target c++17 } }
+#undef nodiscard // { dg-warning "undefining keyword 'nodiscard'" "" { target c++17 } }
+#undef noreturn // { dg-warning "undefining keyword 'noreturn'" "" { target c++11 } }
+#undef no_unique_address // { dg-warning "undefining keyword 'no_unique_address'" "" { target c++20 } }
+#undef unlikely // { dg-warning "undefining keyword 'unlikely'" "" { target c++20 } }
diff --git a/gcc/testsuite/g++.dg/warn/Wkeyword-macro-9.C b/gcc/testsuite/g++.dg/warn/Wkeyword-macro-9.C
new file mode 100644
index 0000000..741cdee
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wkeyword-macro-9.C
@@ -0,0 +1,22 @@
+// C++26 P2843R3 - Preprocessing is never undefined
+// [cpp.replace.general]/9
+// { dg-do preprocess }
+// { dg-options "-pedantic-errors" }
+
+#undef for // { dg-error "undefining keyword 'for'" "" { target c++26 } }
+#define for for // { dg-error "keyword 'for' defined as macro" "" { target c++26 } }
+#undef for // { dg-error "undefining keyword 'for'" "" { target c++26 } }
+#define while do // { dg-error "keyword 'while' defined as macro" "" { target c++26 } }
+#define while do // { dg-error "keyword 'while' defined as macro" "" { target c++26 } }
+#define while for // { dg-error "keyword 'while' defined as macro" "" { target c++26 } }
+ // { dg-error "'while' redefined" "" { target *-*-* } .-1 }
+#undef while // { dg-error "undefining keyword 'while'" "" { target c++26 } }
+#define while while // { dg-error "keyword 'while' defined as macro" "" { target c++26 } }
+#define private public // { dg-error "keyword 'private' defined as macro" "" { target c++26 } }
+#define inline // { dg-error "keyword 'inline' defined as macro" "" { target c++26 } }
+#undef inline // { dg-error "undefining keyword 'inline'" "" { target c++26 } }
+#define inline __inline__ __attribute__((__always_inline__)) // { dg-error "keyword 'inline' defined as macro" "" { target c++26 } }
+#define likely(a) a
+#undef likely // { dg-error "undefining keyword 'likely'" "" { target c++26 } }
+#define unlikely(a, b, c) a + b + c
+#define unlikely(a, b, c) a + b + c
diff --git a/gcc/testsuite/gcc.dg/Wkeyword-macro-1.c b/gcc/testsuite/gcc.dg/Wkeyword-macro-1.c
new file mode 100644
index 0000000..0b2d78f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wkeyword-macro-1.c
@@ -0,0 +1,62 @@
+// { dg-do preprocess }
+// { dg-options "-Wkeyword-macro -std=c23" }
+
+#define _Alignas 1 // { dg-warning "keyword '_Alignas' defined as macro" }
+#define _Alignof 1 // { dg-warning "keyword '_Alignof' defined as macro" }
+#define _Atomic 1 // { dg-warning "keyword '_Atomic' defined as macro" }
+#define _BitInt 1 // { dg-warning "keyword '_BitInt' defined as macro" }
+#define _Bool 1 // { dg-warning "keyword '_Bool' defined as macro" }
+#define _Complex 1 // { dg-warning "keyword '_Complex' defined as macro" }
+#define _Decimal128 1 // { dg-warning "keyword '_Decimal128' defined as macro" }
+#define _Decimal32 1 // { dg-warning "keyword '_Decimal32' defined as macro" }
+#define _Decimal64 1 // { dg-warning "keyword '_Decimal64' defined as macro" }
+#define _Generic 1 // { dg-warning "keyword '_Generic' defined as macro" }
+#define _Imaginary 1 // { dg-warning "keyword '_Imaginary' defined as macro" }
+#define _Noreturn 1 // { dg-warning "keyword '_Noreturn' defined as macro" }
+#define _Static_assert 1 // { dg-warning "keyword '_Static_assert' defined as macro" }
+#define _Thread_local 1 // { dg-warning "keyword '_Thread_local' defined as macro" }
+#define alignas 1 // { dg-warning "keyword 'alignas' defined as macro" }
+#define alignof 1 // { dg-warning "keyword 'alignof' defined as macro" }
+#define auto 1 // { dg-warning "keyword 'auto' defined as macro" }
+#define bool 1 // { dg-warning "keyword 'bool' defined as macro" }
+#define break 1 // { dg-warning "keyword 'break' defined as macro" }
+#define case 1 // { dg-warning "keyword 'case' defined as macro" }
+#define char 1 // { dg-warning "keyword 'char' defined as macro" }
+#define const 1 // { dg-warning "keyword 'const' defined as macro" }
+#define constexpr 1 // { dg-warning "keyword 'constexpr' defined as macro" }
+#define continue 1 // { dg-warning "keyword 'continue' defined as macro" }
+#define default 1 // { dg-warning "keyword 'default' defined as macro" }
+#define do 1 // { dg-warning "keyword 'do' defined as macro" }
+#define double 1 // { dg-warning "keyword 'double' defined as macro" }
+#define else 1 // { dg-warning "keyword 'else' defined as macro" }
+#define enum 1 // { dg-warning "keyword 'enum' defined as macro" }
+#define extern 1 // { dg-warning "keyword 'extern' defined as macro" }
+#define false 1 // { dg-warning "keyword 'false' defined as macro" }
+#define float 1 // { dg-warning "keyword 'float' defined as macro" }
+#define for 1 // { dg-warning "keyword 'for' defined as macro" }
+#define goto 1 // { dg-warning "keyword 'goto' defined as macro" }
+#define if 1 // { dg-warning "keyword 'if' defined as macro" }
+#define inline 1 // { dg-warning "keyword 'inline' defined as macro" }
+#define int 1 // { dg-warning "keyword 'int' defined as macro" }
+#define long 1 // { dg-warning "keyword 'long' defined as macro" }
+#define nullptr 1 // { dg-warning "keyword 'nullptr' defined as macro" }
+#define register 1 // { dg-warning "keyword 'register' defined as macro" }
+#define restrict 1 // { dg-warning "keyword 'restrict' defined as macro" }
+#define return 1 // { dg-warning "keyword 'return' defined as macro" }
+#define short 1 // { dg-warning "keyword 'short' defined as macro" }
+#define signed 1 // { dg-warning "keyword 'signed' defined as macro" }
+#define sizeof 1 // { dg-warning "keyword 'sizeof' defined as macro" }
+#define static 1 // { dg-warning "keyword 'static' defined as macro" }
+#define static_assert 1 // { dg-warning "keyword 'static_assert' defined as macro" }
+#define struct 1 // { dg-warning "keyword 'struct' defined as macro" }
+#define switch 1 // { dg-warning "keyword 'switch' defined as macro" }
+#define thread_local 1 // { dg-warning "keyword 'thread_local' defined as macro" }
+#define true 1 // { dg-warning "keyword 'true' defined as macro" }
+#define typedef 1 // { dg-warning "keyword 'typedef' defined as macro" }
+#define typeof 1 // { dg-warning "keyword 'typeof' defined as macro" }
+#define typeof_unqual 1 // { dg-warning "keyword 'typeof_unqual' defined as macro" }
+#define union 1 // { dg-warning "keyword 'union' defined as macro" }
+#define unsigned 1 // { dg-warning "keyword 'unsigned' defined as macro" }
+#define void 1 // { dg-warning "keyword 'void' defined as macro" }
+#define volatile 1 // { dg-warning "keyword 'volatile' defined as macro" }
+#define while 1 // { dg-warning "keyword 'while' defined as macro" }
diff --git a/gcc/testsuite/gcc.dg/Wkeyword-macro-2.c b/gcc/testsuite/gcc.dg/Wkeyword-macro-2.c
new file mode 100644
index 0000000..329a55a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wkeyword-macro-2.c
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-std=c23" }
+
+#include "Wkeyword-macro-1.c"
diff --git a/gcc/testsuite/gcc.dg/Wkeyword-macro-3.c b/gcc/testsuite/gcc.dg/Wkeyword-macro-3.c
new file mode 100644
index 0000000..f631b8e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wkeyword-macro-3.c
@@ -0,0 +1,62 @@
+// { dg-do preprocess }
+// { dg-options "-Wkeyword-macro -std=c23" }
+
+#undef _Alignas // { dg-warning "undefining keyword '_Alignas'" }
+#undef _Alignof // { dg-warning "undefining keyword '_Alignof'" }
+#undef _Atomic // { dg-warning "undefining keyword '_Atomic'" }
+#undef _BitInt // { dg-warning "undefining keyword '_BitInt'" }
+#undef _Bool // { dg-warning "undefining keyword '_Bool'" }
+#undef _Complex // { dg-warning "undefining keyword '_Complex'" }
+#undef _Decimal128 // { dg-warning "undefining keyword '_Decimal128'" }
+#undef _Decimal32 // { dg-warning "undefining keyword '_Decimal32'" }
+#undef _Decimal64 // { dg-warning "undefining keyword '_Decimal64'" }
+#undef _Generic // { dg-warning "undefining keyword '_Generic'" }
+#undef _Imaginary // { dg-warning "undefining keyword '_Imaginary'" }
+#undef _Noreturn // { dg-warning "undefining keyword '_Noreturn'" }
+#undef _Static_assert // { dg-warning "undefining keyword '_Static_assert'" }
+#undef _Thread_local // { dg-warning "undefining keyword '_Thread_local'" }
+#undef alignas // { dg-warning "undefining keyword 'alignas'" }
+#undef alignof // { dg-warning "undefining keyword 'alignof'" }
+#undef auto // { dg-warning "undefining keyword 'auto'" }
+#undef bool // { dg-warning "undefining keyword 'bool'" }
+#undef break // { dg-warning "undefining keyword 'break'" }
+#undef case // { dg-warning "undefining keyword 'case'" }
+#undef char // { dg-warning "undefining keyword 'char'" }
+#undef const // { dg-warning "undefining keyword 'const'" }
+#undef constexpr // { dg-warning "undefining keyword 'constexpr'" }
+#undef continue // { dg-warning "undefining keyword 'continue'" }
+#undef default // { dg-warning "undefining keyword 'default'" }
+#undef do // { dg-warning "undefining keyword 'do'" }
+#undef double // { dg-warning "undefining keyword 'double'" }
+#undef else // { dg-warning "undefining keyword 'else'" }
+#undef enum // { dg-warning "undefining keyword 'enum'" }
+#undef extern // { dg-warning "undefining keyword 'extern'" }
+#undef false // { dg-warning "undefining keyword 'false'" }
+#undef float // { dg-warning "undefining keyword 'float'" }
+#undef for // { dg-warning "undefining keyword 'for'" }
+#undef goto // { dg-warning "undefining keyword 'goto'" }
+#undef if // { dg-warning "undefining keyword 'if'" }
+#undef inline // { dg-warning "undefining keyword 'inline'" }
+#undef int // { dg-warning "undefining keyword 'int'" }
+#undef long // { dg-warning "undefining keyword 'long'" }
+#undef nullptr // { dg-warning "undefining keyword 'nullptr'" }
+#undef register // { dg-warning "undefining keyword 'register'" }
+#undef restrict // { dg-warning "undefining keyword 'restrict'" }
+#undef return // { dg-warning "undefining keyword 'return'" }
+#undef short // { dg-warning "undefining keyword 'short'" }
+#undef signed // { dg-warning "undefining keyword 'signed'" }
+#undef sizeof // { dg-warning "undefining keyword 'sizeof'" }
+#undef static // { dg-warning "undefining keyword 'static'" }
+#undef static_assert // { dg-warning "undefining keyword 'static_assert'" }
+#undef struct // { dg-warning "undefining keyword 'struct'" }
+#undef switch // { dg-warning "undefining keyword 'switch'" }
+#undef thread_local // { dg-warning "undefining keyword 'thread_local'" }
+#undef true // { dg-warning "undefining keyword 'true'" }
+#undef typedef // { dg-warning "undefining keyword 'typedef'" }
+#undef typeof // { dg-warning "undefining keyword 'typeof'" }
+#undef typeof_unqual // { dg-warning "undefining keyword 'typeof_unqual'" }
+#undef union // { dg-warning "undefining keyword 'union'" }
+#undef unsigned // { dg-warning "undefining keyword 'unsigned'" }
+#undef void // { dg-warning "undefining keyword 'void'" }
+#undef volatile // { dg-warning "undefining keyword 'volatile'" }
+#undef while // { dg-warning "undefining keyword 'while'" }
diff --git a/gcc/testsuite/gcc.dg/Wkeyword-macro-4.c b/gcc/testsuite/gcc.dg/Wkeyword-macro-4.c
new file mode 100644
index 0000000..796d654
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wkeyword-macro-4.c
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-std=c23" }
+
+#include "Wkeyword-macro-3.c"
diff --git a/gcc/testsuite/gcc.dg/Wkeyword-macro-5.c b/gcc/testsuite/gcc.dg/Wkeyword-macro-5.c
new file mode 100644
index 0000000..c61a1ce
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wkeyword-macro-5.c
@@ -0,0 +1,47 @@
+// { dg-do preprocess }
+// { dg-options "-Wkeyword-macro -std=c17" }
+
+#define _Alignas 1 // { dg-warning "keyword '_Alignas' defined as macro" }
+#define _Alignof 1 // { dg-warning "keyword '_Alignof' defined as macro" }
+#define _Atomic 1 // { dg-warning "keyword '_Atomic' defined as macro" }
+#define _Bool 1 // { dg-warning "keyword '_Bool' defined as macro" }
+#define _Complex 1 // { dg-warning "keyword '_Complex' defined as macro" }
+#define _Generic 1 // { dg-warning "keyword '_Generic' defined as macro" }
+#define _Imaginary 1 // { dg-warning "keyword '_Imaginary' defined as macro" }
+#define _Noreturn 1 // { dg-warning "keyword '_Noreturn' defined as macro" }
+#define _Static_assert 1 // { dg-warning "keyword '_Static_assert' defined as macro" }
+#define _Thread_local 1 // { dg-warning "keyword '_Thread_local' defined as macro" }
+#define auto 1 // { dg-warning "keyword 'auto' defined as macro" }
+#define break 1 // { dg-warning "keyword 'break' defined as macro" }
+#define case 1 // { dg-warning "keyword 'case' defined as macro" }
+#define char 1 // { dg-warning "keyword 'char' defined as macro" }
+#define const 1 // { dg-warning "keyword 'const' defined as macro" }
+#define continue 1 // { dg-warning "keyword 'continue' defined as macro" }
+#define default 1 // { dg-warning "keyword 'default' defined as macro" }
+#define do 1 // { dg-warning "keyword 'do' defined as macro" }
+#define double 1 // { dg-warning "keyword 'double' defined as macro" }
+#define else 1 // { dg-warning "keyword 'else' defined as macro" }
+#define enum 1 // { dg-warning "keyword 'enum' defined as macro" }
+#define extern 1 // { dg-warning "keyword 'extern' defined as macro" }
+#define float 1 // { dg-warning "keyword 'float' defined as macro" }
+#define for 1 // { dg-warning "keyword 'for' defined as macro" }
+#define goto 1 // { dg-warning "keyword 'goto' defined as macro" }
+#define if 1 // { dg-warning "keyword 'if' defined as macro" }
+#define inline 1 // { dg-warning "keyword 'inline' defined as macro" }
+#define int 1 // { dg-warning "keyword 'int' defined as macro" }
+#define long 1 // { dg-warning "keyword 'long' defined as macro" }
+#define register 1 // { dg-warning "keyword 'register' defined as macro" }
+#define restrict 1 // { dg-warning "keyword 'restrict' defined as macro" }
+#define return 1 // { dg-warning "keyword 'return' defined as macro" }
+#define short 1 // { dg-warning "keyword 'short' defined as macro" }
+#define signed 1 // { dg-warning "keyword 'signed' defined as macro" }
+#define sizeof 1 // { dg-warning "keyword 'sizeof' defined as macro" }
+#define static 1 // { dg-warning "keyword 'static' defined as macro" }
+#define struct 1 // { dg-warning "keyword 'struct' defined as macro" }
+#define switch 1 // { dg-warning "keyword 'switch' defined as macro" }
+#define typedef 1 // { dg-warning "keyword 'typedef' defined as macro" }
+#define union 1 // { dg-warning "keyword 'union' defined as macro" }
+#define unsigned 1 // { dg-warning "keyword 'unsigned' defined as macro" }
+#define void 1 // { dg-warning "keyword 'void' defined as macro" }
+#define volatile 1 // { dg-warning "keyword 'volatile' defined as macro" }
+#define while 1 // { dg-warning "keyword 'while' defined as macro" }
diff --git a/gcc/testsuite/gcc.dg/Wkeyword-macro-6.c b/gcc/testsuite/gcc.dg/Wkeyword-macro-6.c
new file mode 100644
index 0000000..760ece6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wkeyword-macro-6.c
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-std=c17" }
+
+#include "Wkeyword-macro-5.c"
diff --git a/gcc/testsuite/gcc.dg/Wkeyword-macro-7.c b/gcc/testsuite/gcc.dg/Wkeyword-macro-7.c
new file mode 100644
index 0000000..dc146d4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wkeyword-macro-7.c
@@ -0,0 +1,47 @@
+// { dg-do preprocess }
+// { dg-options "-Wkeyword-macro -std=c17" }
+
+#undef _Alignas // { dg-warning "undefining keyword '_Alignas'" }
+#undef _Alignof // { dg-warning "undefining keyword '_Alignof'" }
+#undef _Atomic // { dg-warning "undefining keyword '_Atomic'" }
+#undef _Bool // { dg-warning "undefining keyword '_Bool'" }
+#undef _Complex // { dg-warning "undefining keyword '_Complex'" }
+#undef _Generic // { dg-warning "undefining keyword '_Generic'" }
+#undef _Imaginary // { dg-warning "undefining keyword '_Imaginary'" }
+#undef _Noreturn // { dg-warning "undefining keyword '_Noreturn'" }
+#undef _Static_assert // { dg-warning "undefining keyword '_Static_assert'" }
+#undef _Thread_local // { dg-warning "undefining keyword '_Thread_local'" }
+#undef auto // { dg-warning "undefining keyword 'auto'" }
+#undef break // { dg-warning "undefining keyword 'break'" }
+#undef case // { dg-warning "undefining keyword 'case'" }
+#undef char // { dg-warning "undefining keyword 'char'" }
+#undef const // { dg-warning "undefining keyword 'const'" }
+#undef continue // { dg-warning "undefining keyword 'continue'" }
+#undef default // { dg-warning "undefining keyword 'default'" }
+#undef do // { dg-warning "undefining keyword 'do'" }
+#undef double // { dg-warning "undefining keyword 'double'" }
+#undef else // { dg-warning "undefining keyword 'else'" }
+#undef enum // { dg-warning "undefining keyword 'enum'" }
+#undef extern // { dg-warning "undefining keyword 'extern'" }
+#undef float // { dg-warning "undefining keyword 'float'" }
+#undef for // { dg-warning "undefining keyword 'for'" }
+#undef goto // { dg-warning "undefining keyword 'goto'" }
+#undef if // { dg-warning "undefining keyword 'if'" }
+#undef inline // { dg-warning "undefining keyword 'inline'" }
+#undef int // { dg-warning "undefining keyword 'int'" }
+#undef long // { dg-warning "undefining keyword 'long'" }
+#undef register // { dg-warning "undefining keyword 'register'" }
+#undef restrict // { dg-warning "undefining keyword 'restrict'" }
+#undef return // { dg-warning "undefining keyword 'return'" }
+#undef short // { dg-warning "undefining keyword 'short'" }
+#undef signed // { dg-warning "undefining keyword 'signed'" }
+#undef sizeof // { dg-warning "undefining keyword 'sizeof'" }
+#undef static // { dg-warning "undefining keyword 'static'" }
+#undef struct // { dg-warning "undefining keyword 'struct'" }
+#undef switch // { dg-warning "undefining keyword 'switch'" }
+#undef typedef // { dg-warning "undefining keyword 'typedef'" }
+#undef union // { dg-warning "undefining keyword 'union'" }
+#undef unsigned // { dg-warning "undefining keyword 'unsigned'" }
+#undef void // { dg-warning "undefining keyword 'void'" }
+#undef volatile // { dg-warning "undefining keyword 'volatile'" }
+#undef while // { dg-warning "undefining keyword 'while'" }
diff --git a/gcc/testsuite/gcc.dg/Wkeyword-macro-8.c b/gcc/testsuite/gcc.dg/Wkeyword-macro-8.c
new file mode 100644
index 0000000..b209f40
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wkeyword-macro-8.c
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-std=c17" }
+
+#include "Wkeyword-macro-7.c"
diff --git a/gcc/testsuite/gcc.dg/Wkeyword-macro-9.c b/gcc/testsuite/gcc.dg/Wkeyword-macro-9.c
new file mode 100644
index 0000000..5d6b650
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wkeyword-macro-9.c
@@ -0,0 +1,15 @@
+// { dg-do preprocess }
+// { dg-options "-Wkeyword-macro" }
+
+#undef for // { dg-warning "undefining keyword 'for'" }
+#define for for // { dg-warning "keyword 'for' defined as macro" }
+#undef for // { dg-warning "undefining keyword 'for'" }
+#define while do // { dg-warning "keyword 'while' defined as macro" }
+#define while do // { dg-warning "keyword 'while' defined as macro" }
+#define while for // { dg-warning "keyword 'while' defined as macro" }
+ // { dg-warning "'while' redefined" "" { target *-*-* } .-1 }
+#undef while // { dg-warning "undefining keyword 'while'" }
+#define while while // { dg-warning "keyword 'while' defined as macro" }
+#define inline // { dg-warning "keyword 'inline' defined as macro" }
+#undef inline // { dg-warning "undefining keyword 'inline'" }
+#define inline __inline__ __attribute__((__always_inline__)) // { dg-warning "keyword 'inline' defined as macro" }
diff --git a/gcc/testsuite/gcc.dg/torture/hardbool-ai.c b/gcc/testsuite/gcc.dg/torture/hardbool-ai.c
new file mode 100644
index 0000000..97569a6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/hardbool-ai.c
@@ -0,0 +1,7 @@
+/* { dg-do run } */
+
+#define basetype _Atomic int
+
+#define NO_BITFIELDS 1
+
+#include "hardbool.c"
diff --git a/gcc/testsuite/gcc.dg/torture/hardbool-vi.c b/gcc/testsuite/gcc.dg/torture/hardbool-vi.c
new file mode 100644
index 0000000..898d395
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/hardbool-vi.c
@@ -0,0 +1,5 @@
+/* { dg-do run } */
+
+#define basetype volatile int
+
+#include "hardbool.c"
diff --git a/gcc/testsuite/gcc.dg/torture/hardbool.c b/gcc/testsuite/gcc.dg/torture/hardbool.c
index 0168495..ed0c598 100644
--- a/gcc/testsuite/gcc.dg/torture/hardbool.c
+++ b/gcc/testsuite/gcc.dg/torture/hardbool.c
@@ -21,8 +21,12 @@ typedef unsigned char __attribute__ ((__hardbool__ (1, 0))) zbool;
struct hs {
hbool a[2];
+#ifndef NO_BITFIELDS
hbool x:2;
hbool y:5;
+#else
+ hbool x, y;
+#endif
zbool z:1;
};
@@ -57,6 +61,30 @@ int ghs(hbool s) {
int t = (hbool)2;
+hbool add1(hbool *s) {
+ return *s += 1;
+}
+
+hbool preinc(hbool *s) {
+ return ++*s;
+}
+
+hbool postinc(hbool *s) {
+ return (*s)++;
+}
+
+hbool sub1(hbool *s) {
+ return *s -= 1;
+}
+
+hbool predec(hbool *s) {
+ return --*s;
+}
+
+hbool postdec(hbool *s) {
+ return (*s)--;
+}
+
void check_pfalse (hbool *p)
{
assert (!*p);
@@ -114,5 +142,43 @@ int main () {
check_vtrue (h2 (2));
check_vtrue (h2 (1));
check_vfalse (h2 (0));
-}
+ hbool v;
+ v = 0;
+ check_vtrue (add1 (&v));
+ assert (v);
+ v = 0;
+ check_vtrue (preinc (&v));
+ assert (v);
+ v = 0;
+ check_vfalse (postinc (&v));
+ assert (v);
+ v = 0;
+ check_vtrue (sub1 (&v));
+ assert (v);
+ v = 0;
+ check_vtrue (predec (&v));
+ assert (v);
+ v = 0;
+ check_vfalse (postdec (&v));
+ assert (v);
+
+ v = 1;
+ check_vtrue (add1 (&v));
+ assert (v);
+ v = 1;
+ check_vtrue (preinc (&v));
+ assert (v);
+ v = 1;
+ check_vtrue (postinc (&v));
+ assert (v);
+ v = 1;
+ check_vfalse (sub1 (&v));
+ assert (!v);
+ v = 1;
+ check_vfalse (predec (&v));
+ assert (!v);
+ v = 1;
+ check_vtrue (postdec (&v));
+ assert (!v);
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-107.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-107.c
new file mode 100644
index 0000000..f80baf3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-107.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-optimized" } */
+
+struct vec_char_16
+{
+ unsigned char raw[2];
+};
+
+static inline struct vec_char_16
+Dup128VecFromValues(unsigned char t0, unsigned char t1)
+{
+ struct vec_char_16 result;
+ result.raw[0] = t0;
+ result.raw[1] = t1;
+ return result;
+}
+
+int f(unsigned char t0, unsigned char t1)
+{
+ struct vec_char_16 a = Dup128VecFromValues(t0, t1);
+ struct vec_char_16 b;
+ __builtin_memcpy(&b, &a, sizeof(a));
+ return b.raw[0] + b.raw[1];
+}
+
+/* Ideally we'd optimize this at FRE1 time but we only replace
+ the loads from b.raw[] with BIT_FIELD_REFs which get optimized
+ only later in the next FRE. */
+/* { dg-final { scan-tree-dump-not "MEM" "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/vla-tert-1.c b/gcc/testsuite/gcc.dg/vla-tert-1.c
new file mode 100644
index 0000000..dfbb2e6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vla-tert-1.c
@@ -0,0 +1,293 @@
+/* { dg-do run }
+ * { dg-options "-std=c99" }
+ * */
+
+
+// For the conditional operator and variably modified types,
+// verify that the size expression on the selected branch
+// is evaluated and the correct result is returned.
+
+
+// keep track which side was evaluated.
+static int fc[2] = { 0 };
+
+static int f(int s, int c)
+{
+ fc[c]++;
+ return s;
+}
+
+
+int main()
+{
+ // two VLAs, constant condition
+
+ fc[0] = fc[1] = 0;
+
+ if (5 != sizeof(*(1 ? (char(*)[ f(5, 0) ])0 : (char(*)[ f(3, 1) ])0)))
+ __builtin_abort();
+
+ if ((1 != fc[0]) || (0 != fc[1]))
+ __builtin_abort();
+
+ fc[0] = fc[1] = 0;
+
+ if (3 != sizeof(*(0 ? (char(*)[ f(5, 0) ])0 : (char(*)[ f(3, 1) ])0)))
+ __builtin_abort(); // fails
+
+ if ((0 != fc[0]) || (1 != fc[1]))
+ __builtin_abort(); // fails
+
+ // two VLAs
+
+ int c = 0;
+ fc[0] = fc[1] = 0;
+
+ if (3 != sizeof(*(c ? (char(*)[ f(5, 0) ])0 : (char(*)[ f(3, 1) ])0)))
+ __builtin_abort(); // fails
+
+ if ((0 != fc[0]) || (1 != fc[1]))
+ __builtin_abort();
+
+ c = 1;
+ fc[0] = fc[1] = 0;
+
+ if (5 != sizeof(*(c ? (char(*)[ f(5, 0) ])0 : (char(*)[ f(3, 1) ])0)))
+ __builtin_abort();
+
+ if ((1 != fc[0]) || (0 != fc[1]))
+ __builtin_abort();
+
+ // VLA + array of unknown size, VLA side is evaluated, defined
+
+ c = 0;
+ fc[0] = fc[1] = 0;
+
+ if (3 != sizeof(*(c ? (char(*)[ ])0 : (char(*)[ f(3, 1) ])0)))
+ __builtin_abort();
+
+ if ((0 != fc[0]) || (1 != fc[1]))
+ __builtin_abort();
+
+ c = 1;
+ fc[0] = fc[1] = 0;
+
+ if (5 != sizeof(*(c ? (char(*)[ f(5, 0) ])0 : (char(*)[ ])0)))
+ __builtin_abort();
+
+ if ((1 != fc[0]) || (0 != fc[1]))
+ __builtin_abort();
+
+ // VLA + array of unknown size, VLA side is not evaluated
+
+ c = 1;
+ fc[0] = fc[1] = 0;
+
+ sizeof(*(c ? (char(*)[ ])0 : (char(*)[ f(3, 1) ])0));
+
+ if ((0 != fc[0]) || (0 != fc[1]))
+ __builtin_abort();
+
+ // without sizeof
+
+ fc[0] = fc[1] = 0;
+
+ (c ? (char(*)[ ])0 : (char(*)[ f(3, 1) ])0);
+
+ if ((0 != fc[0]) || (0 != fc[1]))
+ __builtin_abort();
+
+ c = 0;
+ fc[0] = fc[1] = 0;
+
+ sizeof(*(c ? (char(*)[ f(5, 0) ])0 : (char(*)[ ])0));
+
+ if ((0 != fc[0]) || (0 != fc[1]))
+ __builtin_abort();
+
+ // without sizeof
+
+ fc[0] = fc[1] = 0;
+
+ (c ? (char(*)[ f(5, 0) ])0 : (char(*)[ ])0);
+
+ if ((0 != fc[0]) || (0 != fc[1]))
+ __builtin_abort();
+
+
+ // VLA + array of known size, VLA side is evaluated
+
+ c = 0;
+ fc[0] = fc[1] = 0;
+
+ if (3 != sizeof(*(c ? (char(*)[3])0 : (char(*)[ f(3, 1) ])0)))
+ __builtin_abort();
+
+ // sizeof is not evaluated because not a VLA
+ if ((0 != fc[0]) || (0 != fc[1]))
+ __builtin_abort();
+
+ c = 0;
+ fc[0] = fc[1] = 0;
+
+ // without sizeof
+
+ (c ? (char(*)[3])0 : (char(*)[ f(3, 1) ])0);
+
+ if ((0 != fc[0]) || (1 != fc[1]))
+ __builtin_abort();
+
+ c = 1;
+ fc[0] = fc[1] = 0;
+
+ if (5 != sizeof(*(c ? (char(*)[ f(5, 0) ])0 : (char(*)[5])0)))
+ __builtin_abort();
+
+ // sizeof is not evaluated because not a VLA
+ if ((0 != fc[0]) || (0 != fc[1]))
+ __builtin_abort();
+
+ // without sizeof
+
+ fc[0] = fc[1] = 0;
+
+ (c ? (char(*)[ f(5, 0) ])0 : (char(*)[ 5 ])0);
+
+ if ((1 != fc[0]) || (0 != fc[1]))
+ __builtin_abort();
+
+ // VLA + array of known size, VLA side is not evaluated
+
+ c = 0;
+ fc[0] = fc[1] = 0;
+
+ if (3 != sizeof(*(c ? (char(*)[ f(3, 0) ])0 : (char(*)[ 3 ])0)))
+ __builtin_abort();
+
+ if ((0 != fc[0]) || (0 != fc[1]))
+ __builtin_abort();
+
+ c = 1;
+ fc[0] = fc[1] = 0;
+
+ if (5 != sizeof(*(c ? (char(*)[ 5 ])0 : (char(*)[ f(5, 1) ])0)))
+ __builtin_abort();
+
+ if ((0 != fc[0]) || (0 != fc[1]))
+ __builtin_abort();
+
+ // VM type on one side, null pointer on the other side
+
+ c = 0;
+ fc[0] = fc[1] = 0;
+
+ if (3 != sizeof(*(c ? (void*)0 : (char(*)[ f(3, 1) ])0)))
+ __builtin_abort();
+
+ if ((0 != fc[0]) || (1 != fc[1]))
+ __builtin_abort();
+
+ c = 1;
+ fc[0] = fc[1] = 0;
+
+ if (5 != sizeof(*(c ? (char(*)[ f(5, 0) ])0 : (void*)0)))
+ __builtin_abort();
+
+ if ((1 != fc[0]) || (0 != fc[1]))
+ __builtin_abort();
+
+#if 0
+ // these cases are not fixable
+ // VM types on one side, null pointer on the other side
+ c = 1;
+ fc[0] = fc[1] = 0;
+
+ if (3 != sizeof(*(c ? (void*)0 : (char(*)[ f(3, 1) ])0)))
+ __builtin_abort();
+
+ if ((0 != fc[0]) || (1 != fc[1]))
+ __builtin_abort();
+
+ c = 0;
+ fc[0] = fc[1] = 0;
+
+ if (5 != sizeof(*(c ? (char(*)[ f(5, 0) ])0 : (void*)0)))
+ __builtin_abort();
+
+ if ((1 != fc[0]) || (0 != fc[1]))
+ __builtin_abort();
+#endif
+
+ // VLA + void*
+ void* p = 0;
+ c = 0;
+ fc[0] = fc[1] = 0;
+
+ if (1 != sizeof(*(c ? p : (char(*)[ f(3, 1) ])0)))
+ __builtin_abort();
+
+ // not a VLA or evaluated
+ if ((0 != fc[0]) || (0 != fc[1]))
+ __builtin_abort();
+
+ // .. without sizeof
+
+ (c ? p : (char(*)[ f(3, 1) ])0);
+
+ if ((0 != fc[0]) || (1 != fc[1]))
+ __builtin_abort();
+
+ c = 1;
+ fc[0] = fc[1] = 0;
+
+ if (1 != sizeof(*(c ? (char(*)[ f(5, 0) ])0 : p)))
+ __builtin_abort();
+
+ // not a VLA
+ if ((0 != fc[0]) || (0 != fc[1]))
+ __builtin_abort();
+
+ // .. without sizeof
+
+ (c ? (char(*)[ f(5, 0) ])0 : p);
+
+ if ((1 != fc[0]) || (0 != fc[1]))
+ __builtin_abort();
+
+ // VLA + void*, VLA side not evaluated
+
+ c = 1;
+ fc[0] = fc[1] = 0;
+
+ if (1 != sizeof(*(c ? p : (char(*)[ f(3, 1) ])0)))
+ __builtin_abort();
+
+ if ((0 != fc[0]) || (0 != fc[1]))
+ __builtin_abort();
+
+ // .. without sizeof
+
+ (c ? p : (char(*)[ f(3, 1) ])0);
+
+ if ((0 != fc[0]) || (0 != fc[1]))
+ __builtin_abort();
+
+ c = 0;
+ fc[0] = fc[1] = 0;
+
+ if (1 != sizeof(*(c ? (char(*)[ f(5, 0) ])0 : p)))
+ __builtin_abort();
+
+ if ((0 != fc[0]) || (0 != fc[1]))
+ __builtin_abort();
+
+ // .. without sizeof
+
+ (c ? (char(*)[ f(5, 0) ])0 : p);
+
+ if ((0 != fc[0]) || (0 != fc[1]))
+ __builtin_abort();
+
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.target/aarch64/sme/pr121414_1.c b/gcc/testsuite/gcc.target/aarch64/sme/pr121414_1.c
new file mode 100644
index 0000000..ad8600f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sme/pr121414_1.c
@@ -0,0 +1,27 @@
+#pragma GCC target "+sme2"
+
+void f1() __arm_streaming_compatible {}
+void f2() __arm_streaming {}
+void f3() __arm_in("za") {}
+void f4() __arm_out("za") {}
+void f5() __arm_inout("za") {}
+void f6() __arm_in("zt0") {}
+void f7() __arm_out("zt0") {}
+void f8() __arm_inout("zt0") {}
+
+__arm_locally_streaming void g1() {}
+__arm_new("za") void g2() {}
+__arm_new("zt0") void g3() {}
+
+/* { dg-final { scan-assembler {\t\.variant_pcs\tf1\n} } } */
+/* { dg-final { scan-assembler {\t\.variant_pcs\tf2\n} } } */
+/* { dg-final { scan-assembler {\t\.variant_pcs\tf3\n} } } */
+/* { dg-final { scan-assembler {\t\.variant_pcs\tf4\n} } } */
+/* { dg-final { scan-assembler {\t\.variant_pcs\tf5\n} } } */
+/* { dg-final { scan-assembler {\t\.variant_pcs\tf6\n} } } */
+/* { dg-final { scan-assembler {\t\.variant_pcs\tf7\n} } } */
+/* { dg-final { scan-assembler {\t\.variant_pcs\tf8\n} } } */
+
+/* { dg-final { scan-assembler-not {\t\.variant_pcs\tg1\n} } } */
+/* { dg-final { scan-assembler-not {\t\.variant_pcs\tg2\n} } } */
+/* { dg-final { scan-assembler-not {\t\.variant_pcs\tg3\n} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr120718.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr120718.c
new file mode 100644
index 0000000..9ca0938
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr120718.c
@@ -0,0 +1,12 @@
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+typedef int __attribute__((vector_size(8))) v2si;
+typedef struct { int x; int y; } A;
+void bar(A a);
+void foo()
+{
+ A a;
+ *(v2si *)&a = (v2si){0, (int)svcntd_pat(SV_ALL)};
+ bar(a);
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_11.c b/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_11.c
new file mode 100644
index 0000000..feb7ee7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_11.c
@@ -0,0 +1,20 @@
+/* Peeling for alignment with masking in VLA modes. */
+/* { dg-do compile } */
+/* { dg-options "-Ofast -msve-vector-bits=scalable --param aarch64-autovec-preference=sve-only -fdump-tree-vect-details" } */
+
+#define START 3
+#define END 510
+
+int __attribute__((noipa))
+foo (int *a) {
+ for (signed int i = START; i < END; ++i) {
+ if (a[i] != 0)
+ return i;
+ }
+ return -1;
+}
+
+/* { dg-final { scan-tree-dump "LOOP VECTORIZED" "vect" } } */
+/* { dg-final { scan-tree-dump "pfa_iv_offset" "vect" } } */
+/* { dg-final { scan-tree-dump "Alignment of access forced using peeling" "vect" } } */
+/* { dg-final { scan-assembler {\tnot\tp[0-7]\.b, p[0-7]/z, p.*\n} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_11_run.c b/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_11_run.c
new file mode 100644
index 0000000..b4c267f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_11_run.c
@@ -0,0 +1,27 @@
+/* Peeling for alignment with masking in VLA modes. */
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-Ofast -msve-vector-bits=scalable --param aarch64-autovec-preference=sve-only" } */
+
+#include "peel_ind_11.c"
+#include <stdio.h>
+#include <stdlib.h>
+
+#define N 512
+
+int __attribute__ ((optimize (1)))
+main (void)
+{
+ for (int k = 5; k < 30; k++) {
+ int *a = (int *) malloc (sizeof(int) * N);
+
+ /* Set only one non-zero element for test. */
+ for (int i = 5; i < 30; i++)
+ a[i] = (i == k ? 1 : 0);
+
+ int res = foo (a);
+ asm volatile ("");
+ if (res != k) {
+ __builtin_abort ();
+ }
+ }
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_12.c b/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_12.c
new file mode 100644
index 0000000..260482a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_12.c
@@ -0,0 +1,21 @@
+/* Peeling for alignment with masking together with versioning in VLA modes. */
+/* { dg-do compile } */
+/* { dg-options "-Ofast -msve-vector-bits=scalable --param aarch64-autovec-preference=sve-only -fdump-tree-vect-details" } */
+
+#define START 5
+#define END 509
+
+int __attribute__((noipa))
+foo (int *restrict a, int * restrict b) {
+ for (signed int i = START; i < END; ++i) {
+ if (a[i] != b[i])
+ return i;
+ }
+ return -1;
+}
+
+/* { dg-final { scan-tree-dump "LOOP VECTORIZED" "vect" } } */
+/* { dg-final { scan-tree-dump "pfa_iv_offset" "vect" } } */
+/* { dg-final { scan-tree-dump "Both peeling and versioning will be applied" "vect" } } */
+/* { dg-final { scan-assembler {\tnot\tp[0-7]\.b, p[0-7]/z, p.*\n} } } */
+/* { dg-final { scan-assembler {\teor\t.*\n} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_12_run.c b/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_12_run.c
new file mode 100644
index 0000000..ba978fe
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_12_run.c
@@ -0,0 +1,29 @@
+/* Peeling for alignment with masking together with versioning in VLA modes. */
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-Ofast -msve-vector-bits=scalable --param aarch64-autovec-preference=sve-only" } */
+
+#include "peel_ind_12.c"
+#include <stdio.h>
+#include <stdlib.h>
+
+#define N 512
+
+int __attribute__ ((optimize (1)))
+main (void) {
+ for (int k = 5; k < 50; k++) {
+ int *a = (int *) malloc (sizeof(int) * N);
+ int *b = (int *) malloc (sizeof(int) * N);
+
+ /* Set only one place of different values for test. */
+ for (int i = 5; i < 50; i++) {
+ a[i] = (i == k ? 1 : 0);
+ b[i] = 0;
+ }
+
+ int res = foo (a, b);
+ asm volatile ("");
+ if (res != k) {
+ __builtin_abort ();
+ }
+ }
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_13.c b/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_13.c
new file mode 100644
index 0000000..730e33e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_13.c
@@ -0,0 +1,24 @@
+/* Known inbounds DR in VLA modes. */
+/* { dg-do compile } */
+/* { dg-options "-Ofast -msve-vector-bits=scalable --param aarch64-autovec-preference=sve-only -fdump-tree-vect-details" } */
+
+#define N 512
+#define START 5
+#define END 509
+
+int x[N] __attribute__((aligned(32)));
+
+int __attribute__((noipa))
+foo (void)
+{
+ for (signed int i = START; i < END; ++i)
+ {
+ if (x[i] == 0)
+ return i;
+ }
+ return -1;
+}
+
+/* { dg-final { scan-tree-dump "LOOP VECTORIZED" "vect" } } */
+/* { dg-final { scan-tree-dump-not "pfa_iv_offset" "vect" } } */
+/* { dg-final { scan-tree-dump-not "Alignment of access forced using peeling" "vect" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_13_run.c b/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_13_run.c
new file mode 100644
index 0000000..83352a8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_13_run.c
@@ -0,0 +1,15 @@
+/* Known inbounds DR in VLA modes. */
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-Ofast -msve-vector-bits=scalable --param aarch64-autovec-preference=sve-only" } */
+
+#include "peel_ind_13.c"
+
+int __attribute__ ((optimize (1)))
+main (void)
+{
+ int res = foo ();
+ asm volatile ("");
+ if (res != START)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr90579.c b/gcc/testsuite/gcc.target/i386/pr90579.c
index ab48a44..bd2fd33 100644
--- a/gcc/testsuite/gcc.target/i386/pr90579.c
+++ b/gcc/testsuite/gcc.target/i386/pr90579.c
@@ -16,8 +16,5 @@ loop (int k, double x)
return t;
}
-/* Verify we end up with scalar loads from r for the final sum. */
-/* { dg-final { scan-assembler "vaddsd\tr\\\+40" } } */
-/* { dg-final { scan-assembler "vaddsd\tr\\\+32" } } */
-/* { dg-final { scan-assembler "vaddsd\tr\\\+24" } } */
-/* { dg-final { scan-assembler "vaddsd\tr\\\+16" } } */
+/* Verify we end up with no loads from r. */
+/* { dg-final { scan-assembler-not "v\[ma\]\[^\t \]+\tr" } } */
diff --git a/gcc/testsuite/gcc.target/s390/bitint-1.c b/gcc/testsuite/gcc.target/s390/bitint-1.c
new file mode 100644
index 0000000..8bdf2ae
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/bitint-1.c
@@ -0,0 +1,83 @@
+/* { dg-do compile { target bitint } } */
+/* { dg-options "-O2 -march=z9-109" } */
+/* { dg-final { check-function-bodies "**" "" "" } } */
+
+/* Verify calling convention. */
+
+static_assert (sizeof (_BitInt(5)) == 1);
+static_assert (sizeof (_BitInt(9)) == 2);
+static_assert (sizeof (_BitInt(17)) == 4);
+static_assert (sizeof (_BitInt(33)) == 8);
+
+/*
+** bitint5_zero_extend_call:
+** lghi %r2,22
+** jg bitint5_zero_extend@PLT
+*/
+
+void bitint5_zero_extend (unsigned _BitInt(5) x);
+void bitint5_zero_extend_call (void) { bitint5_zero_extend (22wbu); }
+
+/*
+** bitint5_sign_extend_call:
+** lghi %r2,-10
+** jg bitint5_sign_extend@PLT
+*/
+
+void bitint5_sign_extend (_BitInt(5) x);
+void bitint5_sign_extend_call (void) { bitint5_sign_extend (-10wb); }
+
+/*
+** bitint9_zero_extend_call:
+** lghi %r2,422
+** jg bitint9_zero_extend@PLT
+*/
+
+void bitint9_zero_extend (unsigned _BitInt(9) x);
+void bitint9_zero_extend_call (void) { bitint9_zero_extend (422wbu); }
+
+/*
+** bitint9_sign_extend_call:
+** lghi %r2,-90
+** jg bitint9_sign_extend@PLT
+*/
+
+void bitint9_sign_extend (_BitInt(9) x);
+void bitint9_sign_extend_call (void) { bitint9_sign_extend (-90wb); }
+
+/*
+** bitint17_zero_extend_call:
+** lgfi %r2,108198
+** jg bitint17_zero_extend@PLT
+*/
+
+void bitint17_zero_extend (unsigned _BitInt(17) x);
+void bitint17_zero_extend_call (void) { bitint17_zero_extend (108198wbu); }
+
+/*
+** bitint17_sign_extend_call:
+** lghi %r2,-22874
+** jg bitint17_sign_extend@PLT
+*/
+
+void bitint17_sign_extend (_BitInt(17) x);
+void bitint17_sign_extend_call (void) { bitint17_sign_extend (-22874wb); }
+
+/*
+** bitint33_zero_extend_call:
+** llihl %r2,1
+** oilf %r2,2795939494
+** jg bitint33_zero_extend@PLT
+*/
+
+void bitint33_zero_extend (unsigned _BitInt(33) x);
+void bitint33_zero_extend_call (void) { bitint33_zero_extend (7090906790wbu); }
+
+/*
+** bitint33_sign_extend_call:
+** lgfi %r2,-1499027802
+** jg bitint33_sign_extend@PLT
+*/
+
+void bitint33_sign_extend (_BitInt(33) x);
+void bitint33_sign_extend_call (void) { bitint33_sign_extend (-1499027802wb); }
diff --git a/gcc/testsuite/gcc.target/s390/bitint-2.c b/gcc/testsuite/gcc.target/s390/bitint-2.c
new file mode 100644
index 0000000..9b0e6b9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/bitint-2.c
@@ -0,0 +1,32 @@
+/* { dg-do run { target bitint } } */
+/* { dg-options "-std=c23" } */
+
+/* Verify calling convention. */
+
+static_assert (sizeof (_BitInt(65)) == 16);
+
+[[gnu::noipa]] void
+bitint65_zero_extend (unsigned _BitInt(65) x)
+{
+ static const char y[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0xBA, 0xDC, 0x0F, 0xFE, 0xE0, 0xDD, 0xF0, 0x0D};
+ if (__builtin_memcmp (&x, y, 16) != 0)
+ __builtin_abort ();
+}
+
+[[gnu::noipa]] void
+bitint65_sign_extend (signed _BitInt(65) x)
+{
+ static const char y[16] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xBA, 0xDC, 0x0F, 0xFE, 0xE0, 0xDD, 0xF0, 0x0D};
+ if (__builtin_memcmp (&x, y, 16) != 0)
+ __builtin_abort ();
+}
+
+int
+main (void)
+{
+ bitint65_zero_extend (0x1BADC0FFEE0DDF00Dwbu);
+ bitint65_sign_extend (0x1BADC0FFEE0DDF00Dwb);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/s390/bitint-3.c b/gcc/testsuite/gcc.target/s390/bitint-3.c
new file mode 100644
index 0000000..9132028
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/bitint-3.c
@@ -0,0 +1,28 @@
+/* { dg-do compile { target bitint } } */
+/* { dg-options "-march=z9-109 -fdump-rtl-expand" } */
+
+/* Verify calling convention. */
+
+/* { dg-final { scan-rtl-dump-times "zero_extend:DI.*reg:QI" 1 "expand" } } */
+void bitint5_zero_extend (unsigned _BitInt(5) x);
+void bitint5_zero_extend_call (unsigned _BitInt(5) x) { bitint5_zero_extend (x + 1); }
+
+/* { dg-final { scan-rtl-dump-times "sign_extend:DI.*reg:QI" 1 "expand" } } */
+void bitint5_sign_extend (_BitInt(5) x);
+void bitint5_sign_extend_call (_BitInt(5) x) { bitint5_sign_extend (x + 1); }
+
+/* { dg-final { scan-rtl-dump-times "zero_extend:DI.*reg:HI" 1 "expand" } } */
+void bitint9_zero_extend (unsigned _BitInt(9) x);
+void bitint9_zero_extend_call (unsigned _BitInt(9) x) { bitint9_zero_extend (x + 1); }
+
+/* { dg-final { scan-rtl-dump-times "sign_extend:DI.*reg:HI" 1 "expand" } } */
+void bitint9_sign_extend (_BitInt(9) x);
+void bitint9_sign_extend_call (_BitInt(9) x) { bitint9_sign_extend (x + 1); }
+
+/* { dg-final { scan-rtl-dump-times "zero_extend:DI.*reg:SI" 1 "expand" } } */
+void bitint17_zero_extend (unsigned _BitInt(17) x);
+void bitint17_zero_extend_call (unsigned _BitInt(17) x) { bitint17_zero_extend (x + 1); }
+
+/* { dg-final { scan-rtl-dump-times "sign_extend:DI.*reg:SI" 1 "expand" } } */
+void bitint17_sign_extend (_BitInt(17) x);
+void bitint17_sign_extend_call (_BitInt(17) x) { bitint17_sign_extend (x + 1); }
diff --git a/gcc/testsuite/gcc.target/s390/bitint-4.c b/gcc/testsuite/gcc.target/s390/bitint-4.c
new file mode 100644
index 0000000..dce72d8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/bitint-4.c
@@ -0,0 +1,71 @@
+/* { dg-do compile { target bitint } } */
+/* { dg-options "-march=z9-109 -O2" } */
+/* { dg-final { check-function-bodies "**" "" "" } } */
+
+/* Verify calling convention. */
+
+struct s_bitint5 {
+ short a;
+ unsigned _BitInt(5) b;
+ char c;
+};
+
+static_assert (sizeof (struct s_bitint5) == 4);
+
+/*
+** s_bitint5_call:
+** iilf %r2,2758168
+** jg s_bitint5@PLT
+*/
+
+void s_bitint5 (struct s_bitint5 x);
+void s_bitint5_call (void) { s_bitint5 ((struct s_bitint5){42, 22wbu, 24}); }
+
+struct s_bitint9 {
+ short a;
+ unsigned _BitInt(9) b;
+};
+
+static_assert (sizeof (struct s_bitint9) == 4);
+
+/*
+** s_bitint9_call:
+** iilf %r2,2752934
+** jg s_bitint9@PLT
+*/
+
+void s_bitint9 (struct s_bitint9 x);
+void s_bitint9_call (void) { s_bitint9 ((struct s_bitint9){42, 422wbu}); }
+
+struct s_bitint17 {
+ int a;
+ unsigned _BitInt(17) b;
+};
+
+static_assert (sizeof (struct s_bitint17) == 8);
+
+/*
+** s_bitint17_call:
+** llihl %r2,42
+** oilf %r2,108198
+** jg s_bitint17@PLT
+*/
+
+void s_bitint17 (struct s_bitint17 x);
+void s_bitint17_call (void) { s_bitint17 ((struct s_bitint17){42, 108198wbu}); }
+
+struct s_bitint33 {
+ unsigned _BitInt(33) b;
+};
+
+static_assert (sizeof (struct s_bitint33) == 8);
+
+/*
+** s_bitint33_call:
+** llihl %r2,1
+** oilf %r2,2795939494
+** jg s_bitint33@PLT
+*/
+
+void s_bitint33 (struct s_bitint33 x);
+void s_bitint33_call (void) { s_bitint33 ((struct s_bitint33){7090906790wbu}); }
diff --git a/gcc/tree-ssa-sccvn.cc b/gcc/tree-ssa-sccvn.cc
index 00315d1..1c113f8 100644
--- a/gcc/tree-ssa-sccvn.cc
+++ b/gcc/tree-ssa-sccvn.cc
@@ -5633,6 +5633,28 @@ visit_nary_op (tree lhs, gassign *stmt)
}
}
break;
+ case BIT_FIELD_REF:
+ if (TREE_CODE (TREE_OPERAND (rhs1, 0)) == SSA_NAME)
+ {
+ tree op0 = TREE_OPERAND (rhs1, 0);
+ gassign *ass = dyn_cast <gassign *> (SSA_NAME_DEF_STMT (op0));
+ if (ass
+ && !gimple_has_volatile_ops (ass)
+ && vn_get_stmt_kind (ass) == VN_REFERENCE)
+ {
+ tree last_vuse = gimple_vuse (ass);
+ tree op = build3 (BIT_FIELD_REF, TREE_TYPE (rhs1),
+ gimple_assign_rhs1 (ass),
+ TREE_OPERAND (rhs1, 1), TREE_OPERAND (rhs1, 2));
+ tree result = vn_reference_lookup (op, gimple_vuse (ass),
+ default_vn_walk_kind,
+ NULL, true, &last_vuse);
+ if (result
+ && useless_type_conversion_p (type, TREE_TYPE (result)))
+ return set_ssa_val_to (lhs, result);
+ }
+ }
+ break;
case TRUNC_DIV_EXPR:
if (TYPE_UNSIGNED (type))
break;
diff --git a/gcc/tree-vect-data-refs.cc b/gcc/tree-vect-data-refs.cc
index a9d4aae..a3d3b3e 100644
--- a/gcc/tree-vect-data-refs.cc
+++ b/gcc/tree-vect-data-refs.cc
@@ -1448,17 +1448,20 @@ vect_compute_data_ref_alignment (vec_info *vinfo, dr_vec_info *dr_info,
if (loop_vinfo
&& dr_safe_speculative_read_required (stmt_info))
{
- poly_uint64 vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
- auto vectype_size
+ /* The required target alignment must be a power-of-2 value and is
+ computed as the product of vector element size, VF and group size.
+ We compute the constant part first as VF may be a variable. For
+ variable VF, the power-of-2 check of VF is deferred to runtime. */
+ auto align_factor_c
= TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (vectype)));
- poly_uint64 new_alignment = vf * vectype_size;
- /* If we have a grouped access we require that the alignment be N * elem. */
if (STMT_VINFO_GROUPED_ACCESS (stmt_info))
- new_alignment *= DR_GROUP_SIZE (DR_GROUP_FIRST_ELEMENT (stmt_info));
+ align_factor_c *= DR_GROUP_SIZE (DR_GROUP_FIRST_ELEMENT (stmt_info));
+
+ poly_uint64 vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
+ poly_uint64 new_alignment = vf * align_factor_c;
- unsigned HOST_WIDE_INT target_alignment;
- if (new_alignment.is_constant (&target_alignment)
- && pow2p_hwi (target_alignment))
+ if ((vf.is_constant () && pow2p_hwi (new_alignment.to_constant ()))
+ || (!vf.is_constant () && pow2p_hwi (align_factor_c)))
{
if (dump_enabled_p ())
{
@@ -1467,7 +1470,7 @@ vect_compute_data_ref_alignment (vec_info *vinfo, dr_vec_info *dr_info,
dump_dec (MSG_NOTE, new_alignment);
dump_printf (MSG_NOTE, " bytes.\n");
}
- vector_alignment = target_alignment;
+ vector_alignment = new_alignment;
}
}
@@ -2438,6 +2441,7 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
- The cost of peeling (the extra runtime checks, the increase
in code size). */
+ poly_uint64 vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
FOR_EACH_VEC_ELT (datarefs, i, dr)
{
dr_vec_info *dr_info = loop_vinfo->lookup_dr (dr);
@@ -2446,9 +2450,18 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
stmt_vec_info stmt_info = dr_info->stmt;
tree vectype = STMT_VINFO_VECTYPE (stmt_info);
- do_peeling
- = vector_alignment_reachable_p (dr_info,
- LOOP_VINFO_VECT_FACTOR (loop_vinfo));
+
+ /* With variable VF, unsafe speculative read can be avoided for known
+ inbounds DRs as long as partial vectors are used. */
+ if (!vf.is_constant ()
+ && dr_safe_speculative_read_required (stmt_info)
+ && DR_SCALAR_KNOWN_BOUNDS (dr_info))
+ {
+ dr_set_safe_speculative_read_required (stmt_info, false);
+ LOOP_VINFO_MUST_USE_PARTIAL_VECTORS_P (loop_vinfo) = true;
+ }
+
+ do_peeling = vector_alignment_reachable_p (dr_info, vf);
if (do_peeling)
{
if (known_alignment_for_access_p (dr_info, vectype))
@@ -2488,7 +2501,6 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
poly_uint64 nscalars = npeel_tmp;
if (unlimited_cost_model (LOOP_VINFO_LOOP (loop_vinfo)))
{
- poly_uint64 vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
unsigned group_size = 1;
if (STMT_SLP_TYPE (stmt_info)
&& STMT_VINFO_GROUPED_ACCESS (stmt_info))
@@ -2911,14 +2923,12 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
2) there is at least one unsupported misaligned data ref with an unknown
misalignment, and
3) all misaligned data refs with a known misalignment are supported, and
- 4) the number of runtime alignment checks is within reason.
- 5) the vectorization factor is a constant. */
+ 4) the number of runtime alignment checks is within reason. */
do_versioning
= (optimize_loop_nest_for_speed_p (loop)
&& !loop->inner /* FORNOW */
- && loop_cost_model (loop) > VECT_COST_MODEL_CHEAP)
- && LOOP_VINFO_VECT_FACTOR (loop_vinfo).is_constant ();
+ && loop_cost_model (loop) > VECT_COST_MODEL_CHEAP);
if (do_versioning)
{
@@ -2965,25 +2975,22 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
?? We could actually unroll the loop to achieve the required
overall step alignment, and forcing the alignment could be
done by doing some iterations of the non-vectorized loop. */
- if (!multiple_p (LOOP_VINFO_VECT_FACTOR (loop_vinfo)
- * DR_STEP_ALIGNMENT (dr),
+ if (!multiple_p (vf * DR_STEP_ALIGNMENT (dr),
DR_TARGET_ALIGNMENT (dr_info)))
{
do_versioning = false;
break;
}
- /* The rightmost bits of an aligned address must be zeros.
- Construct the mask needed for this test. For example,
- GET_MODE_SIZE for the vector mode V4SI is 16 bytes so the
- mask must be 15 = 0xf. */
- gcc_assert (DR_TARGET_ALIGNMENT (dr_info).is_constant ());
- int mask = DR_TARGET_ALIGNMENT (dr_info).to_constant () - 1;
+ /* Use "mask = DR_TARGET_ALIGNMENT - 1" to test rightmost address
+ bits for runtime alignment check. For example, for 16 bytes
+ target alignment the mask is 15 = 0xf. */
+ poly_uint64 mask = DR_TARGET_ALIGNMENT (dr_info) - 1;
/* FORNOW: use the same mask to test all potentially unaligned
references in the loop. */
- if (LOOP_VINFO_PTR_MASK (loop_vinfo)
- && LOOP_VINFO_PTR_MASK (loop_vinfo) != mask)
+ if (maybe_ne (LOOP_VINFO_PTR_MASK (loop_vinfo), 0U)
+ && maybe_ne (LOOP_VINFO_PTR_MASK (loop_vinfo), mask))
{
do_versioning = false;
break;
diff --git a/gcc/tree-vect-loop-manip.cc b/gcc/tree-vect-loop-manip.cc
index 6c1b26a..566308f 100644
--- a/gcc/tree-vect-loop-manip.cc
+++ b/gcc/tree-vect-loop-manip.cc
@@ -2454,10 +2454,7 @@ get_misalign_in_elems (gimple **seq, loop_vec_info loop_vinfo)
else
{
tree vla = build_int_cst (type, target_align);
- tree vla_align = fold_build2 (BIT_AND_EXPR, type, vla,
- fold_build2 (MINUS_EXPR, type,
- build_int_cst (type, 0), vla));
- target_align_minus_1 = fold_build2 (MINUS_EXPR, type, vla_align,
+ target_align_minus_1 = fold_build2 (MINUS_EXPR, type, vla,
build_int_cst (type, 1));
}
@@ -3840,7 +3837,7 @@ vect_create_cond_for_align_checks (loop_vec_info loop_vinfo,
const vec<stmt_vec_info> &may_misalign_stmts
= LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo);
stmt_vec_info stmt_info;
- int mask = LOOP_VINFO_PTR_MASK (loop_vinfo);
+ poly_uint64 mask = LOOP_VINFO_PTR_MASK (loop_vinfo);
tree mask_cst;
unsigned int i;
tree int_ptrsize_type;
@@ -3852,9 +3849,7 @@ vect_create_cond_for_align_checks (loop_vec_info loop_vinfo,
tree ptrsize_zero;
tree part_cond_expr;
- /* Check that mask is one less than a power of 2, i.e., mask is
- all zeros followed by all ones. */
- gcc_assert ((mask != 0) && ((mask & (mask+1)) == 0));
+ gcc_assert (known_ne (mask, 0U));
int_ptrsize_type = signed_type_for (ptr_type_node);
@@ -3962,6 +3957,62 @@ vect_create_cond_for_align_checks (loop_vec_info loop_vinfo,
chain_cond_expr (cond_expr, part_cond_expr);
}
+/* Function vect_create_cond_for_vla_spec_read.
+
+ Create a conditional expression that represents the run-time checks with
+ max speculative read amount in VLA modes. We check two things:
+ 1) if the max speculative read amount exceeds the min page size
+ 2) if the VF is power-of-2 - done by checking the max read amount instead
+
+ Input:
+ COND_EXPR - input conditional expression. New conditions will be chained
+ with logical AND operation.
+ LOOP_VINFO - field LOOP_VINFO_MAX_SPEC_READ_AMOUNT contains the max
+ possible speculative read amount in VLA modes.
+
+ Output:
+ COND_EXPR - conditional expression.
+
+ The returned COND_EXPR is the conditional expression to be used in the
+ if statement that controls which version of the loop gets executed at
+ runtime. */
+
+static void
+vect_create_cond_for_vla_spec_read (loop_vec_info loop_vinfo, tree *cond_expr)
+{
+ poly_uint64 read_amount_poly = LOOP_VINFO_MAX_SPEC_READ_AMOUNT (loop_vinfo);
+ tree amount = build_int_cst (long_unsigned_type_node, read_amount_poly);
+
+ /* Both the read amount and the VF must be variants, and the read amount must
+ be a constant power-of-2 multiple of the VF. */
+ unsigned HOST_WIDE_INT multiple;
+ gcc_assert (!read_amount_poly.is_constant ()
+ && !LOOP_VINFO_VECT_FACTOR (loop_vinfo).is_constant ()
+ && constant_multiple_p (read_amount_poly,
+ LOOP_VINFO_VECT_FACTOR (loop_vinfo),
+ &multiple)
+ && pow2p_hwi (multiple));
+
+ tree cst_ul_zero = build_int_cstu (long_unsigned_type_node, 0U);
+ tree cst_ul_one = build_int_cstu (long_unsigned_type_node, 1U);
+ tree cst_ul_pagesize = build_int_cstu (long_unsigned_type_node,
+ (unsigned long) param_min_pagesize);
+
+ /* Create an expression of "amount & (amount - 1) == 0". */
+ tree amount_m1 = fold_build2 (MINUS_EXPR, long_unsigned_type_node,
+ amount, cst_ul_one);
+ tree amount_and_expr = fold_build2 (BIT_AND_EXPR, long_unsigned_type_node,
+ amount, amount_m1);
+ tree powof2_cond_expr = fold_build2 (EQ_EXPR, boolean_type_node,
+ amount_and_expr, cst_ul_zero);
+ chain_cond_expr (cond_expr, powof2_cond_expr);
+
+ /* Create an expression of "amount <= cst_ul_pagesize". */
+ tree pagesize_cond_expr = fold_build2 (LE_EXPR, boolean_type_node,
+ amount, cst_ul_pagesize);
+ chain_cond_expr (cond_expr, pagesize_cond_expr);
+}
+
/* If LOOP_VINFO_CHECK_UNEQUAL_ADDRS contains <A1, B1>, ..., <An, Bn>,
create a tree representation of: (&A1 != &B1) && ... && (&An != &Bn).
Set *COND_EXPR to a tree that is true when both the original *COND_EXPR
@@ -4087,6 +4138,7 @@ vect_loop_versioning (loop_vec_info loop_vinfo,
gimple_seq gimplify_stmt_list = NULL;
tree scalar_loop_iters = LOOP_VINFO_NITERSM1 (loop_vinfo);
bool version_align = LOOP_REQUIRES_VERSIONING_FOR_ALIGNMENT (loop_vinfo);
+ bool version_spec_read = LOOP_REQUIRES_VERSIONING_FOR_SPEC_READ (loop_vinfo);
bool version_alias = LOOP_REQUIRES_VERSIONING_FOR_ALIAS (loop_vinfo);
bool version_niter = LOOP_REQUIRES_VERSIONING_FOR_NITERS (loop_vinfo);
poly_uint64 versioning_threshold
@@ -4145,6 +4197,9 @@ vect_loop_versioning (loop_vec_info loop_vinfo,
vect_create_cond_for_align_checks (loop_vinfo, &cond_expr,
&cond_expr_stmt_list);
+ if (version_spec_read)
+ vect_create_cond_for_vla_spec_read (loop_vinfo, &cond_expr);
+
if (version_alias)
{
vect_create_cond_for_unequal_addrs (loop_vinfo, &cond_expr);
diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc
index 85f3e90..55a8495 100644
--- a/gcc/tree-vect-loop.cc
+++ b/gcc/tree-vect-loop.cc
@@ -1009,6 +1009,7 @@ _loop_vec_info::_loop_vec_info (class loop *loop_in, vec_info_shared *shared)
unaligned_dr (NULL),
peeling_for_alignment (0),
ptr_mask (0),
+ max_spec_read_amount (0),
nonlinear_iv (false),
ivexpr_map (NULL),
scan_map (NULL),
@@ -10141,7 +10142,12 @@ vectorizable_induction (loop_vec_info loop_vinfo,
if (peel_mul)
{
if (!step_mul)
- step_mul = peel_mul;
+ {
+ gcc_assert (!nunits.is_constant ());
+ step_mul = gimple_build (&init_stmts,
+ MINUS_EXPR, step_vectype,
+ build_zero_cst (step_vectype), peel_mul);
+ }
else
step_mul = gimple_build (&init_stmts,
MINUS_EXPR, step_vectype,
diff --git a/gcc/tree-vect-stmts.cc b/gcc/tree-vect-stmts.cc
index a6f4db4..dbeb8bd 100644
--- a/gcc/tree-vect-stmts.cc
+++ b/gcc/tree-vect-stmts.cc
@@ -2400,70 +2400,26 @@ get_load_store_type (vec_info *vinfo, stmt_vec_info stmt_info,
/* We can only peel for loops, of course. */
gcc_checking_assert (loop_vinfo);
+ poly_uint64 vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
+ poly_uint64 read_amount
+ = vf * TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (vectype)));
+ if (STMT_VINFO_GROUPED_ACCESS (stmt_info))
+ read_amount *= DR_GROUP_SIZE (DR_GROUP_FIRST_ELEMENT (stmt_info));
+
auto target_alignment
= DR_TARGET_ALIGNMENT (STMT_VINFO_DR_INFO (stmt_info));
- unsigned HOST_WIDE_INT target_align;
-
- bool group_aligned = false;
- if (target_alignment.is_constant (&target_align)
- && nunits.is_constant ())
- {
- poly_uint64 vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
- auto vectype_size
- = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (vectype)));
- poly_uint64 required_alignment = vf * vectype_size;
- /* If we have a grouped access we require that the alignment be N * elem. */
- if (STMT_VINFO_GROUPED_ACCESS (stmt_info))
- required_alignment *=
- DR_GROUP_SIZE (DR_GROUP_FIRST_ELEMENT (stmt_info));
- if (!multiple_p (target_alignment, required_alignment))
- {
- if (dump_enabled_p ())
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "desired alignment %wu not met. Instead got %wu "
- "for DR alignment at %G",
- required_alignment.to_constant (),
- target_align, STMT_VINFO_STMT (stmt_info));
- return false;
- }
-
- if (!pow2p_hwi (target_align))
- {
- if (dump_enabled_p ())
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "non-power-of-two vector alignment %wd "
- "for DR alignment at %G",
- target_align, STMT_VINFO_STMT (stmt_info));
- return false;
- }
-
- /* For VLA we have to insert a runtime check that the vector loads
- per iterations don't exceed a page size. For now we can use
- POLY_VALUE_MAX as a proxy as we can't peel for VLA. */
- if (known_gt (required_alignment, (unsigned)param_min_pagesize))
+ if (!multiple_p (target_alignment, read_amount))
+ {
+ if (dump_enabled_p ())
{
- if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "alignment required for correctness (");
- dump_dec (MSG_MISSED_OPTIMIZATION, required_alignment);
- dump_printf (MSG_NOTE, ") may exceed page size\n");
- }
- return false;
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "desired alignment not met, target was ");
+ dump_dec (MSG_NOTE, target_alignment);
+ dump_printf (MSG_NOTE, " previously, but read amount is ");
+ dump_dec (MSG_NOTE, read_amount);
+ dump_printf (MSG_NOTE, " at %G.\n", STMT_VINFO_STMT (stmt_info));
}
-
- group_aligned = true;
- }
-
- /* There are multiple loads that have a misalignment that we couldn't
- align. We would need LOOP_VINFO_MUST_USE_PARTIAL_VECTORS_P to
- vectorize. */
- if (!group_aligned)
- {
- if (inbounds)
- LOOP_VINFO_MUST_USE_PARTIAL_VECTORS_P (loop_vinfo) = true;
- else
- return false;
+ return false;
}
/* When using a group access the first element may be aligned but the
@@ -2485,6 +2441,33 @@ get_load_store_type (vec_info *vinfo, stmt_vec_info stmt_info,
STMT_VINFO_STMT (stmt_info));
return false;
}
+
+ /* Reject vectorization if we know the read mount per vector iteration
+ exceeds the min page size. */
+ if (known_gt (read_amount, (unsigned) param_min_pagesize))
+ {
+ if (dump_enabled_p ())
+ {
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "alignment required for correctness (");
+ dump_dec (MSG_MISSED_OPTIMIZATION, read_amount);
+ dump_printf (MSG_NOTE, ") may exceed page size.\n");
+ }
+ return false;
+ }
+
+ if (!vf.is_constant ())
+ {
+ /* For VLA modes, we need a runtime check to ensure any speculative
+ read amount does not exceed the page size. Here we record the max
+ possible read amount for the check. */
+ if (maybe_gt (read_amount,
+ LOOP_VINFO_MAX_SPEC_READ_AMOUNT (loop_vinfo)))
+ LOOP_VINFO_MAX_SPEC_READ_AMOUNT (loop_vinfo) = read_amount;
+
+ /* For VLA modes, we must use partial vectors. */
+ LOOP_VINFO_MUST_USE_PARTIAL_VECTORS_P (loop_vinfo) = true;
+ }
}
if (*alignment_support_scheme == dr_unaligned_unsupported)
diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
index 9653496..041cff8 100644
--- a/gcc/tree-vectorizer.h
+++ b/gcc/tree-vectorizer.h
@@ -919,7 +919,10 @@ public:
int peeling_for_alignment;
/* The mask used to check the alignment of pointers or arrays. */
- int ptr_mask;
+ poly_uint64 ptr_mask;
+
+ /* The maximum speculative read amount in VLA modes for runtime check. */
+ poly_uint64 max_spec_read_amount;
/* Indicates whether the loop has any non-linear IV. */
bool nonlinear_iv;
@@ -1155,6 +1158,7 @@ public:
#define LOOP_VINFO_RGROUP_IV_TYPE(L) (L)->rgroup_iv_type
#define LOOP_VINFO_PARTIAL_VECTORS_STYLE(L) (L)->partial_vector_style
#define LOOP_VINFO_PTR_MASK(L) (L)->ptr_mask
+#define LOOP_VINFO_MAX_SPEC_READ_AMOUNT(L) (L)->max_spec_read_amount
#define LOOP_VINFO_LOOP_NEST(L) (L)->shared->loop_nest
#define LOOP_VINFO_DATAREFS(L) (L)->shared->datarefs
#define LOOP_VINFO_DDRS(L) (L)->shared->ddrs
@@ -1209,6 +1213,8 @@ public:
#define LOOP_REQUIRES_VERSIONING_FOR_ALIGNMENT(L) \
((L)->may_misalign_stmts.length () > 0)
+#define LOOP_REQUIRES_VERSIONING_FOR_SPEC_READ(L) \
+ (maybe_gt ((L)->max_spec_read_amount, 0U))
#define LOOP_REQUIRES_VERSIONING_FOR_ALIAS(L) \
((L)->comp_alias_ddrs.length () > 0 \
|| (L)->check_unequal_addrs.length () > 0 \
@@ -1219,6 +1225,7 @@ public:
(LOOP_VINFO_SIMD_IF_COND (L))
#define LOOP_REQUIRES_VERSIONING(L) \
(LOOP_REQUIRES_VERSIONING_FOR_ALIGNMENT (L) \
+ || LOOP_REQUIRES_VERSIONING_FOR_SPEC_READ (L) \
|| LOOP_REQUIRES_VERSIONING_FOR_ALIAS (L) \
|| LOOP_REQUIRES_VERSIONING_FOR_NITERS (L) \
|| LOOP_REQUIRES_VERSIONING_FOR_SIMD_IF_COND (L))
diff --git a/libcpp/directives.cc b/libcpp/directives.cc
index 4d06caa..47fb8fb 100644
--- a/libcpp/directives.cc
+++ b/libcpp/directives.cc
@@ -734,13 +734,30 @@ do_undef (cpp_reader *pfile)
if (pfile->cb.undef)
pfile->cb.undef (pfile, pfile->directive_line, node);
+ /* Handle -Wkeyword-macro registered identifiers. */
+ bool diagnosed = false;
+ if (CPP_OPTION (pfile, cpp_warn_keyword_macro) && cpp_keyword_p (node))
+ {
+ if (CPP_OPTION (pfile, cpp_pedantic)
+ && CPP_OPTION (pfile, cplusplus)
+ && CPP_OPTION (pfile, lang) >= CLK_GNUCXX26)
+ cpp_pedwarning (pfile, CPP_W_KEYWORD_MACRO,
+ "undefining keyword %qs", NODE_NAME (node));
+ else
+ cpp_warning (pfile, CPP_W_KEYWORD_MACRO,
+ "undefining keyword %qs", NODE_NAME (node));
+ diagnosed = true;
+ }
/* 6.10.3.5 paragraph 2: [#undef] is ignored if the specified
identifier is not currently defined as a macro name. */
if (cpp_macro_p (node))
{
if (node->flags & NODE_WARN)
- cpp_error (pfile, CPP_DL_WARNING,
- "undefining %qs", NODE_NAME (node));
+ {
+ if (!diagnosed)
+ cpp_error (pfile, CPP_DL_WARNING,
+ "undefining %qs", NODE_NAME (node));
+ }
else if (cpp_builtin_macro_p (node)
&& CPP_OPTION (pfile, warn_builtin_macro_redefined))
cpp_warning (pfile, CPP_W_BUILTIN_MACRO_REDEFINED,
diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h
index 75efdcd..bbd88e5 100644
--- a/libcpp/include/cpplib.h
+++ b/libcpp/include/cpplib.h
@@ -620,6 +620,9 @@ struct cpp_options
/* True if -finput-charset= option has been used explicitly. */
bool cpp_input_charset_explicit;
+ /* True if -Wkeyword-macro. */
+ bool cpp_warn_keyword_macro;
+
/* -Wleading-whitespace= value. */
unsigned char cpp_warn_leading_whitespace;
@@ -757,7 +760,8 @@ enum cpp_warning_reason {
CPP_W_HEADER_GUARD,
CPP_W_PRAGMA_ONCE_OUTSIDE_HEADER,
CPP_W_LEADING_WHITESPACE,
- CPP_W_TRAILING_WHITESPACE
+ CPP_W_TRAILING_WHITESPACE,
+ CPP_W_KEYWORD_MACRO
};
/* Callback for header lookup for HEADER, which is the name of a
@@ -1250,6 +1254,17 @@ inline bool cpp_fun_like_macro_p (cpp_hashnode *node)
return cpp_user_macro_p (node) && node->value.macro->fun_like;
}
+/* Return true for nodes marked for -Wkeyword-macro diagnostics. */
+inline bool cpp_keyword_p (cpp_hashnode *node)
+{
+ /* As keywords are marked identifiers which don't start with underscore
+ or start with underscore followed by capital letter (except for
+ _Pragma). */
+ return ((node->flags & NODE_WARN)
+ && (NODE_NAME (node)[0] != '_'
+ || (NODE_NAME (node)[1] != '_' && NODE_NAME (node)[1] != 'P')));
+}
+
extern const unsigned char *cpp_macro_definition (cpp_reader *, cpp_hashnode *);
extern const unsigned char *cpp_macro_definition (cpp_reader *, cpp_hashnode *,
const cpp_macro *);
diff --git a/libcpp/macro.cc b/libcpp/macro.cc
index 158c821..a47e1fe 100644
--- a/libcpp/macro.cc
+++ b/libcpp/macro.cc
@@ -3411,7 +3411,11 @@ warn_of_redefinition (cpp_reader *pfile, cpp_hashnode *node,
{
/* Some redefinitions need to be warned about regardless. */
if (node->flags & NODE_WARN)
- return true;
+ {
+ /* Ignore NODE_WARN on -Wkeyword-macro registered identifiers though. */
+ if (!CPP_OPTION (pfile, cpp_warn_keyword_macro) || !cpp_keyword_p (node))
+ return true;
+ }
/* Suppress warnings for builtins that lack the NODE_WARN flag,
unless Wbuiltin-macro-redefined. */
@@ -3949,6 +3953,25 @@ _cpp_create_definition (cpp_reader *pfile, cpp_hashnode *node,
if (name_loc)
macro->line = name_loc;
+ /* Handle -Wkeyword-macro registered identifiers. */
+ if (CPP_OPTION (pfile, cpp_warn_keyword_macro) && cpp_keyword_p (node))
+ {
+ if (macro->fun_like
+ && CPP_OPTION (pfile, cplusplus)
+ && (strcmp ((const char *) NODE_NAME (node), "likely") == 0
+ || strcmp ((const char *) NODE_NAME (node), "unlikely") == 0))
+ /* likely and unlikely can be defined as function-like macros. */;
+ else if (CPP_OPTION (pfile, cpp_pedantic)
+ && CPP_OPTION (pfile, cplusplus)
+ && CPP_OPTION (pfile, lang) >= CLK_GNUCXX26)
+ cpp_pedwarning_with_line (pfile, CPP_W_KEYWORD_MACRO, macro->line, 0,
+ "keyword %qs defined as macro",
+ NODE_NAME (node));
+ else
+ cpp_warning_with_line (pfile, CPP_W_KEYWORD_MACRO, macro->line, 0,
+ "keyword %qs defined as macro",
+ NODE_NAME (node));
+ }
if (cpp_macro_p (node))
{
if (CPP_OPTION (pfile, warn_unused_macros))
@@ -3957,12 +3980,12 @@ _cpp_create_definition (cpp_reader *pfile, cpp_hashnode *node,
if (warn_of_redefinition (pfile, node, macro))
{
const enum cpp_warning_reason reason
- = (cpp_builtin_macro_p (node) && !(node->flags & NODE_WARN))
- ? CPP_W_BUILTIN_MACRO_REDEFINED : CPP_W_NONE;
+ = (cpp_builtin_macro_p (node) && !(node->flags & NODE_WARN)
+ ? CPP_W_BUILTIN_MACRO_REDEFINED : CPP_W_NONE);
bool warned
- = cpp_pedwarning_with_line (pfile, reason, macro->line, 0,
- "%qs redefined", NODE_NAME (node));
+ = cpp_pedwarning_with_line (pfile, reason, macro->line, 0,
+ "%qs redefined", NODE_NAME (node));
if (warned && cpp_user_macro_p (node))
cpp_error_with_line (pfile, CPP_DL_NOTE, node->value.macro->line,
diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog
index 0962ddf..882117d 100644
--- a/libgcc/ChangeLog
+++ b/libgcc/ChangeLog
@@ -1,3 +1,9 @@
+2025-08-06 Jakub Jelinek <jakub@redhat.com>
+
+ PR libgcc/121397
+ * enable-execute-stack-mprotect.c (check_enabling): Remove useless
+ forward declaration.
+
2025-07-31 Wilco Dijkstra <wilco.dijkstra@arm.com>
* config/aarch64/cpuinfo.c (__init_cpu_features_constructor):
diff --git a/libgcc/config.host b/libgcc/config.host
index d36f0e3..92acdd0 100644
--- a/libgcc/config.host
+++ b/libgcc/config.host
@@ -1397,6 +1397,8 @@ s390x-*-linux*)
tmake_file="${tmake_file} s390/t-crtstuff s390/t-linux t-stack s390/t-stack-s390"
if test "${host_address}" = 32; then
tmake_file="${tmake_file} s390/32/t-floattodi"
+ else
+ tmake_file="${tmake_file} s390/t-softfp t-softfp"
fi
md_unwind_header=s390/linux-unwind.h
;;
diff --git a/libgcc/config/s390/libgcc-glibc.ver b/libgcc/config/s390/libgcc-glibc.ver
index 86c55a0..00375b3 100644
--- a/libgcc/config/s390/libgcc-glibc.ver
+++ b/libgcc/config/s390/libgcc-glibc.ver
@@ -114,3 +114,17 @@ GCC_4.1.0 {
__floatditf
%endif
}
+
+%ifdef __s390x__
+%inherit GCC_16.0.0 GCC_4.1.0
+GCC_16.0.0 {
+ __mulbitint3
+ __divmodbitint4
+ __fixsfbitint
+ __fixdfbitint
+ __fixtfbitint
+ __floatbitintsf
+ __floatbitintdf
+ __floatbitinttf
+}
+%endif
diff --git a/libgcc/config/s390/sfp-exceptions.c b/libgcc/config/s390/sfp-exceptions.c
new file mode 100644
index 0000000..a2fc5dd
--- /dev/null
+++ b/libgcc/config/s390/sfp-exceptions.c
@@ -0,0 +1,61 @@
+/* Copyright (C) 2001-2025 Free Software Foundation, Inc.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ GCC is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "sfp-machine.h"
+
+#define __math_force_eval_div(x, y) \
+ do { asm ("" : "+f" (x)); asm volatile ("" : : "f" (x / y)); } while (0)
+
+void
+__sfp_handle_exceptions (int _fex)
+{
+ if (_fex & FP_EX_INVALID)
+ {
+ float x = 0.0f;
+ __math_force_eval_div (x, x);
+ }
+ if (_fex & FP_EX_DIVZERO)
+ {
+ float x = 1.0f;
+ float y = 0.0f;
+ __math_force_eval_div (x, y);
+ }
+ if (_fex & FP_EX_OVERFLOW)
+ {
+ float x = __FLT_MAX__;
+ asm ("" : "+f" (x));
+ asm volatile ("" : : "f" (x + x));
+ }
+ if (_fex & FP_EX_UNDERFLOW)
+ {
+ float x = __FLT_MIN__;
+ asm ("" : "+f" (x));
+ asm volatile ("" : : "f" (x * x));
+ }
+ if (_fex & FP_EX_INEXACT)
+ {
+ float x = 1.0f;
+ float y = 3.0f;
+ __math_force_eval_div (x, y);
+ }
+}
diff --git a/libgcc/config/s390/sfp-machine.h b/libgcc/config/s390/sfp-machine.h
new file mode 100644
index 0000000..960bad7
--- /dev/null
+++ b/libgcc/config/s390/sfp-machine.h
@@ -0,0 +1,89 @@
+/* Copyright (C) 2001-2025 Free Software Foundation, Inc.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ GCC is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#if ! __s390x__
+# error "soft-fp implemented for s390x only"
+#endif
+
+#define _FP_W_TYPE_SIZE 64
+#define _FP_W_TYPE unsigned long long
+#define _FP_WS_TYPE signed long long
+#define _FP_I_TYPE long long
+
+typedef int TItype __attribute__ ((mode (TI)));
+typedef unsigned int UTItype __attribute__ ((mode (TI)));
+#define TI_BITS (__CHAR_BIT__ * (int) sizeof (TItype))
+
+#define _FP_NANFRAC_H ((_FP_QNANBIT_H << 1) - 1)
+#define _FP_NANFRAC_S ((_FP_QNANBIT_S << 1) - 1)
+#define _FP_NANFRAC_D ((_FP_QNANBIT_D << 1) - 1)
+#define _FP_NANFRAC_Q ((_FP_QNANBIT_Q << 1) - 1), -1
+
+#define _FP_NANSIGN_H 0
+#define _FP_NANSIGN_S 0
+#define _FP_NANSIGN_D 0
+#define _FP_NANSIGN_Q 0
+
+#define _FP_KEEPNANFRACP 1
+#define _FP_QNANNEGATEDP 0
+
+#define FP_EX_INVALID 0x01
+#define FP_EX_DIVZERO 0x02
+#define FP_EX_OVERFLOW 0x04
+#define FP_EX_UNDERFLOW 0x08
+#define FP_EX_INEXACT 0x10
+#define FP_EX_ALL \
+ (FP_EX_INVALID | FP_EX_DIVZERO | FP_EX_OVERFLOW \
+ | FP_EX_UNDERFLOW | FP_EX_INEXACT)
+
+void __sfp_handle_exceptions (int);
+
+#define FP_HANDLE_EXCEPTIONS \
+ do { \
+ if (__builtin_expect (_fex, 0)) \
+ __sfp_handle_exceptions (_fex); \
+ } while (0)
+
+#define _FP_TININESS_AFTER_ROUNDING 0
+
+#define FP_RND_NEAREST 0x0
+#define FP_RND_ZERO 0x1
+#define FP_RND_PINF 0x2
+#define FP_RND_MINF 0x3
+#define FP_RND_MASK 0x3
+
+#define _FP_DECL_EX \
+ unsigned int _fpcr __attribute__ ((unused)) = FP_RND_NEAREST
+
+#define FP_INIT_ROUNDMODE \
+ do { \
+ __asm__ __volatile__ ("stfpc %0" \
+ : "=m" (_fpcr)); \
+ } while (0)
+
+#define FP_ROUNDMODE (_fpcr & FP_RND_MASK)
+
+#define __LITTLE_ENDIAN 1234
+#define __BIG_ENDIAN 4321
+
+#define __BYTE_ORDER __BIG_ENDIAN
diff --git a/libgcc/config/s390/t-softfp b/libgcc/config/s390/t-softfp
new file mode 100644
index 0000000..724b15e
--- /dev/null
+++ b/libgcc/config/s390/t-softfp
@@ -0,0 +1,2 @@
+LIB2ADD += $(srcdir)/config/s390/sfp-exceptions.c
+softfp_extras := fixtfbitint floatbitinttf
diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog
index ea41616..440a32a 100644
--- a/libgfortran/ChangeLog
+++ b/libgfortran/ChangeLog
@@ -1,3 +1,10 @@
+2025-08-06 Jerry DeLisle <jvdelisle@gcc.gnu.org>
+
+ PR libfortran/121234
+ * io/list_read.c (read_character): Add checks to bypass eating
+ semicolons when reading strings with decimal mode 'point'
+ (list_formatted_read_scalar): Likewise.
+
2025-07-30 Yuao Ma <c8ef@outlook.com>
* gfortran.map: Add split symbol.
diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog
index 2689f3e..722da76 100644
--- a/libgomp/ChangeLog
+++ b/libgomp/ChangeLog
@@ -1,3 +1,23 @@
+2025-08-06 Kwok Cheung Yeung <kcyeung@baylibre.com>
+
+ * target.c (gomp_update): Call gomp_merge_iterator_maps. Free
+ allocated variables.
+ * testsuite/libgomp.c-c++-common/target-update-iterators-1.c: New.
+ * testsuite/libgomp.c-c++-common/target-update-iterators-2.c: New.
+ * testsuite/libgomp.c-c++-common/target-update-iterators-3.c: New.
+
+2025-08-06 Kwok Cheung Yeung <kcyeung@baylibre.com>
+ Andrew Stubbs <ams@baylibre.com>
+
+ * target.c (kind_to_name): New.
+ (gomp_merge_iterator_maps): New.
+ (gomp_map_vars_internal): Call gomp_merge_iterator_maps. Copy
+ address of only the first iteration to target vars. Free allocated
+ variables.
+ * testsuite/libgomp.c-c++-common/target-map-iterators-1.c: New.
+ * testsuite/libgomp.c-c++-common/target-map-iterators-2.c: New.
+ * testsuite/libgomp.c-c++-common/target-map-iterators-3.c: New.
+
2025-07-21 Thomas Schwinge <tschwinge@baylibre.com>
PR target/119853
diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog
index cf90917..b072d0b 100644
--- a/libiberty/ChangeLog
+++ b/libiberty/ChangeLog
@@ -1,3 +1,8 @@
+2025-08-06 Matthieu Longo <matthieu.longo@arm.com>
+
+ * testsuite/test-doubly-linked-list.c: disable debug logging on
+ stdout.
+
2025-07-09 Matthieu Longo <matthieu.longo@arm.com>
* Makefile.in: Add new header.
diff --git a/libiberty/testsuite/test-doubly-linked-list.c b/libiberty/testsuite/test-doubly-linked-list.c
index 1e1fc63..93fe19a 100644
--- a/libiberty/testsuite/test-doubly-linked-list.c
+++ b/libiberty/testsuite/test-doubly-linked-list.c
@@ -155,19 +155,26 @@ bool check(const char *op,
bool success = true;
bool res;
- l_print (wrapper->first);
+#define DUMP_LIST 0
+
+ if (DUMP_LIST)
+ l_print (wrapper->first);
+
res = run_test (expect, wrapper, false);
printf ("%s: test-linked-list::%s: check forward conformity\n",
res ? "PASS": "FAIL", op);
success &= res;
- l_reverse_print (wrapper->last);
+ if (DUMP_LIST)
+ l_reverse_print (wrapper->last);
+
res = run_test (expect, wrapper, true);
printf ("%s: test-linked-list::%s: check backward conformity\n",
res ? "PASS": "FAIL", op);
success &= res;
- printf("\n");
+ if (DUMP_LIST)
+ printf("\n");
return success;
}
diff --git a/libstdc++-v3/doc/html/manual/appendix_porting.html b/libstdc++-v3/doc/html/manual/appendix_porting.html
index 887fa50..7b63613 100644
--- a/libstdc++-v3/doc/html/manual/appendix_porting.html
+++ b/libstdc++-v3/doc/html/manual/appendix_porting.html
@@ -26,7 +26,7 @@ Support for C++11 dialect.
</a></span></dt><dt><span class="section"><a href="backwards.html#backwards.third.iterator_type">
<code class="code">Container::iterator_type</code> is not necessarily <code class="code">Container::value_type*</code>
</a></span></dt></dl></dd></dl></dd></dl></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="appendix.porting.build_hacking"></a>Configure and Build Hacking</h2></div></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a id="build_hacking.prereq"></a>Prerequisites</h3></div></div></div><p>
- As noted <a class="link" href="http://gcc.gnu.org/install/prerequisites.html" target="_top">previously</a>,
+ As noted <a class="link" href="https://gcc.gnu.org/install/prerequisites.html" target="_top">previously</a>,
certain other tools are necessary for hacking on files that
control configure (<code class="code">configure.ac</code>,
<code class="code">acinclude.m4</code>) and make
diff --git a/libstdc++-v3/doc/xml/manual/build_hacking.xml b/libstdc++-v3/doc/xml/manual/build_hacking.xml
index 20de49f..4c044d9 100644
--- a/libstdc++-v3/doc/xml/manual/build_hacking.xml
+++ b/libstdc++-v3/doc/xml/manual/build_hacking.xml
@@ -17,7 +17,7 @@
<section xml:id="build_hacking.prereq"><info><title>Prerequisites</title></info>
<para>
- As noted <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://gcc.gnu.org/install/prerequisites.html">previously</link>,
+ As noted <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="https://gcc.gnu.org/install/prerequisites.html">previously</link>,
certain other tools are necessary for hacking on files that
control configure (<code>configure.ac</code>,
<code>acinclude.m4</code>) and make