diff options
80 files changed, 1249 insertions, 406 deletions
@@ -1,3 +1,7 @@ +2025-12-08 Nathan Myers <ncm@cantrip.org> + + * MAINTAINERS: add ncm + 2025-11-30 Jose E. Marchesi <jose.marchesi@oracle.com> * MAINTAINERS: Add Algol 68 subsystems. diff --git a/MAINTAINERS b/MAINTAINERS index 22d4172..53a35b9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -706,6 +706,7 @@ Christoph Müllner cmuellner <christoph.muellner@vrull.eu> Steven Munroe munroesj <munroesj52@gmail.com> Philippe De Muyter - <phdm@macqel.be> Joseph Myers jsm28 <josmyers@redhat.com> +Nathan Myers ncm <ncm@cantrip.org> Szabolcs Nagy nsz <nsz@gcc.gnu.org> Victor Do Nascimento victorldn <victor.donascimento@arm.com> Quentin Neill qneill <quentin.neill.gnu@gmail.com> diff --git a/contrib/ChangeLog b/contrib/ChangeLog index ea2d807..6683ddc 100644 --- a/contrib/ChangeLog +++ b/contrib/ChangeLog @@ -1,3 +1,13 @@ +2025-12-08 Joseph Myers <josmyers@redhat.com> + + * test_installed (--with-alt-cc=, --with-alt-cxx=) + (--with-compat-options=, --with-libiconv=): New options. + +2025-12-08 Jonathan Wakely <jwakely@redhat.com> + + * check_GNU_style_lib.py (check_GNU_style_file): Do not check + libstdc++ files. + 2025-12-06 Mark Zhuang <mark.zhuang@spacemit.com> * prepare-commit-msg: check --default-prefix diff --git a/contrib/check_GNU_style_lib.py b/contrib/check_GNU_style_lib.py index faf30c4..fccb3d6 100755 --- a/contrib/check_GNU_style_lib.py +++ b/contrib/check_GNU_style_lib.py @@ -285,6 +285,9 @@ def check_GNU_style_file(file, format): # Skip testsuite files if 'testsuite' in t or t.endswith('.py'): continue + # Libstdc++ does not use GNU style + if t.startswith('libstdc++-v3/'): + continue for hunk in pfile: delta = 0 diff --git a/contrib/test_installed b/contrib/test_installed index 77492ca..42c3f12 100755 --- a/contrib/test_installed +++ b/contrib/test_installed @@ -42,6 +42,7 @@ if test -f site.exp; then exit 1 fi +libiconv=-liconv while true; do case "$1" in --with-testsuite=*) testsuite=`echo "$1" | sed 's/[^=]*=//'`; shift;; @@ -51,6 +52,10 @@ while true; do --with-gcc=*) GCC_UNDER_TEST=`echo "$1" | sed 's/[^=]*=//'`; shift;; --with-g++=*) GXX_UNDER_TEST=`echo "$1" | sed 's/[^=]*=//'`; shift;; --with-gfortran=*) GFORTRAN_UNDER_TEST=`echo "$1" | sed 's/[^=]*=//'`; shift;; + --with-alt-cc=*) ALT_CC_UNDER_TEST=`echo "$1" | sed 's/[^=]*=//'`; shift;; + --with-alt-cxx=*) ALT_CXX_UNDER_TEST=`echo "$1" | sed 's/[^=]*=//'`; shift;; + --with-compat-options=*) COMPAT_OPTIONS=`echo "$1" | sed 's/[^=]*=//'`; shift;; + --with-libiconv=*) libiconv=`echo "$1" | sed 's/[^=]*=//'`; shift;; --without-gcc) GCC_UNDER_TEST=no; shift;; --without-g++) GXX_UNDER_TEST=no; shift;; --without-gfortran) GFORTRAN_UNDER_TEST=no; shift;; @@ -78,6 +83,10 @@ Supported arguments: --with-gcc=/some/dir/bin/gcc use specified gcc program [gcc] --with-g++=/some/dir/bin/g++ use specified g++ program [g++] --with-gfortran=/some/dir/bin/gfortran use specified gfortran program [gfortran] +--with-alt-cc=/some/compiler use specified alternative compiler in compat tests +--with-alt-cxx=/some/compiler use specified alternative compiler in compat tests +--with-compat-options=opts use specified COMPAT_OPTIONS in compat tests +--with-libiconv=linker-args use given arguments to link with iconv [-liconv] --without-gcc do not run gcc testsuite --without-g++ do not run g++ testsuite --without-gfortran do not run gfortran testsuite @@ -108,6 +117,7 @@ cat >site.exp <<EOF set rootme "." set tmpdir "${tmpdir-`${PWDCMD-pwd}`}" set srcdir "${testsuite-${srcdir}/gcc/testsuite}" +set libiconv "$libiconv" set CFLAGS "" set CXXFLAGS "" set GCC_UNDER_TEST "${GCC_UNDER_TEST-${prefix}${prefix+/bin/}gcc}" @@ -123,6 +133,15 @@ if test x${target} != x; then echo "set target_triplet $target" >> site.exp echo "set target_alias $target" >> site.exp fi +if test x"$ALT_CC_UNDER_TEST" != x; then + echo "set ALT_CC_UNDER_TEST \"${ALT_CC_UNDER_TEST}\"" >> site.exp +fi +if test x"$ALT_CXX_UNDER_TEST" != x; then + echo "set ALT_CXX_UNDER_TEST \"${ALT_CXX_UNDER_TEST}\"" >> site.exp +fi +if test x"$COMPAT_OPTIONS" != x; then + echo "set COMPAT_OPTIONS \"${COMPAT_OPTIONS}\"" >> site.exp +fi test x"${GCC_UNDER_TEST}" = x"no" || runtest --tool gcc ${1+"$@"} test x"${GXX_UNDER_TEST}" = x"no" || runtest --tool g++ ${1+"$@"} diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6c0c42e..e6da5b8 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,79 @@ +2025-12-08 Andrew Pinski <andrew.pinski@oss.qualcomm.com> + + PR tree-optimization/46555 + * tree-cfgcleanup.cc (execute_cleanup_cfg_post_optimizing): + Don't set todo to include cleanupcfg; do it manually. + Call make_forwarders_with_degenerate_phis if optimizing. + +2025-12-08 Andrew Pinski <andrew.pinski@oss.qualcomm.com> + + * tree-cfg.cc (make_forwarders_with_degenerate_phis): Add debug + dump. + +2025-12-08 Andrew Pinski <andrew.pinski@oss.qualcomm.com> + + * tree-ssa-dce.cc (sort_phi_args): Move to tree-cfg.cc. + (make_forwarders_with_degenerate_phis): Move to tree-cfg.cc. + (perform_tree_ssa_dce): Update for the updated return type + of make_forwarders_with_degenerate_phis. + * tree-cfg.cc (sort_phi_args): Moved from tree-ssa-dce.cc. + (make_forwarders_with_degenerate_phis): Moved from tree-ssa-dce.cc. + Update return type to bool and return true if an edge was split. + * tree-cfg.h (make_forwarders_with_degenerate_phis): New decl. + +2025-12-08 Eric Botcazou <ebotcazou@adacore.com> + + PR target/80881 + * config/mingw/winnt.cc (mingw_pe_unique_section): Put two dollar + signs for TLS sections after the prefix. + (mingw_pe_asm_named_section): Deal with all TLS sections uniformly. + +2025-12-08 Ezra Sitorus <Ezra.Sitorus@arm.com> + + * config/aarch64/aarch64-cores.def (AARCH64_CORE): Add C1-Nano, + C1-Pro, C1-Premium and C1-Ultra. + * config/aarch64/aarch64-tune.md: Regenerate. + * doc/invoke.texi: Document C1 cores. + +2025-12-08 Richard Biener <rguenther@suse.de> + + PR tree-optimization/123040 + * tree-ssa-sccvn.cc (vn_nary_build_or_lookup_1): Only insert + nary results. + +2025-12-08 Josef Melcr <josef.melcr@suse.com> + + PR ipa/122798 + * cgraph.cc (cgraph_edge::redirect_callee): Use + iterate_referring instead of referred_to_p. + * cgraphclones.cc (set_new_clone_decl_and_node_flags): Set local + to true iff the node does not have its address taken. + +2025-12-08 Richard Biener <rguenther@suse.de> + + PR tree-optimization/123038 + * tree-vect-patterns.cc (vect_recog_ctz_ffs_pattern): Reject + pattern for reductions when the call argument is used multiple + times. + +2025-12-08 Tamar Christina <tamar.christina@arm.com> + + PR target/123026 + * config/aarch64/aarch64-simd.md (reduc_sbool_ior_scal_<mode>, + reduc_sbool_and_scal_<mode>): Fix tmp operands[1] override. + +2025-12-08 Tamar Christina <tamar.christina@arm.com> + + PR tree-optimization/122868 + * tree-vect-stmts.cc (vectorizable_load): Move check for invariant loads + down into the loop. + +2025-12-08 H.J. Lu <hjl.tools@gmail.com> + + PR target/122343 + * config/i386/sse.md (*<avx512>_cmp<mode>3_dup_op): Don't allow + 2 volatile memory references. + 2025-12-07 Jason Merrill <jason@redhat.com> * config/darwin-c.cc (find_subframework_header): Use diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index f674ed1..4568345 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20251208 +20251209 diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 2067233..8b19deb 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,9 @@ +2025-12-08 Eric Botcazou <ebotcazou@adacore.com> + + PR ada/123037 + * rtinit.c [__MINGW32__]: Include <stdlib.h> and not <windows.h>. + * rtfinal.c [__MINGW32__]: Do not include <windows.h>. + 2025-12-07 Eric Botcazou <ebotcazou@adacore.com> PR ada/115349 diff --git a/gcc/ada/rtfinal.c b/gcc/ada/rtfinal.c index 88bbb0e..0bd3ce4 100644 --- a/gcc/ada/rtfinal.c +++ b/gcc/ada/rtfinal.c @@ -46,9 +46,7 @@ extern int __gnat_rt_init_count; /* see initialize.c */ #if defined (__MINGW32__) -#define WIN32_LEAN_AND_MEAN #include "mingw32.h" -#include <windows.h> extern CRITICAL_SECTION ProcListCS; extern HANDLE ProcListEvt; diff --git a/gcc/ada/rtinit.c b/gcc/ada/rtinit.c index 598550c..3b5af0d 100644 --- a/gcc/ada/rtinit.c +++ b/gcc/ada/rtinit.c @@ -70,9 +70,8 @@ int __gnat_rt_init_count = 0; and finalize properly the run-time. */ #if defined (__MINGW32__) -#define WIN32_LEAN_AND_MEAN +#include <stdlib.h> #include "mingw32.h" -#include <windows.h> extern void __gnat_init_float (void); diff --git a/gcc/cgraph.cc b/gcc/cgraph.cc index 3c21e17..1a7d499 100644 --- a/gcc/cgraph.cc +++ b/gcc/cgraph.cc @@ -1696,8 +1696,12 @@ cgraph_edge::redirect_callee (cgraph_node *n) old_ref->remove_reference (); ipa_ref *new_ref = caller->create_reference (n, IPA_REF_ADDR, call_stmt); new_ref->lto_stmt_uid = lto_stmt_uid; - if (!old_callee->referred_to_p ()) + /* If the last reference to OLD_CALLEE has been redirected, unset + address_taken. old_ref is only used as a placeholder when looking for + a different reference. */ + if (!old_callee->iterate_referring (0, old_ref)) old_callee->address_taken = 0; + n->mark_address_taken (); } if (!inline_failed) diff --git a/gcc/cgraphclones.cc b/gcc/cgraphclones.cc index 49f0e58..816fc53 100644 --- a/gcc/cgraphclones.cc +++ b/gcc/cgraphclones.cc @@ -176,7 +176,9 @@ set_new_clone_decl_and_node_flags (cgraph_node *new_node) DECL_IS_REPLACEABLE_OPERATOR (new_node->decl) = 0; new_node->externally_visible = 0; - new_node->local = 1; + /* Clones of callbacks might have their address taken, and thus cannot be + local. */ + new_node->local = !new_node->address_taken; new_node->lowered = true; new_node->semantic_interposition = 0; } diff --git a/gcc/config/aarch64/aarch64-cores.def b/gcc/config/aarch64/aarch64-cores.def index b86d80c..851594a 100644 --- a/gcc/config/aarch64/aarch64-cores.def +++ b/gcc/config/aarch64/aarch64-cores.def @@ -229,6 +229,11 @@ AARCH64_CORE("grace", grace, cortexa57, V9A, (I8MM, BF16, SVE2_BITPERM, SVE2_AES AARCH64_CORE("neoverse-v3", neoversev3, cortexa57, V9_2A, (SVE2_BITPERM, RNG, LS64, MEMTAG, PROFILE), neoversev3, 0x41, 0xd84, -1) AARCH64_CORE("neoverse-v3ae", neoversev3ae, cortexa57, V9_2A, (SVE2_BITPERM, RNG, LS64, MEMTAG, PROFILE), neoversev3ae, 0x41, 0xd83, -1) +AARCH64_CORE("c1-nano", c1nano, cortexa53, V9_3A, (MEMTAG, SVE2_BITPERM, F16FML, SME2, RCPC3), cortexa53, 0x41, 0xd8a, -1) +AARCH64_CORE("c1-pro", c1pro, cortexa57, V9_3A, (MEMTAG, SVE2_BITPERM, F16FML, PROFILE, SME2, RCPC3), neoversen3, 0x41, 0xd8b, -1) +AARCH64_CORE("c1-premium", c1premium, cortexa57, V9_3A, (MEMTAG, SVE2_BITPERM, F16FML, PROFILE, SME2, RCPC3), neoversev3, 0x41, 0xd90, -1) +AARCH64_CORE("c1-ultra", c1ultra, cortexa57, V9_3A, (MEMTAG, SVE2_BITPERM, F16FML, PROFILE, SME2, RCPC3), cortexx925, 0x41, 0xd8c, -1) + AARCH64_CORE("demeter", demeter, cortexa57, V9A, (I8MM, BF16, SVE2_BITPERM, RNG, MEMTAG, PROFILE), neoversev2, 0x41, 0xd4f, -1) /* NVIDIA ('N') cores. */ diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md index 3f9d5f6..c02ffd6 100644 --- a/gcc/config/aarch64/aarch64-simd.md +++ b/gcc/config/aarch64/aarch64-simd.md @@ -3544,10 +3544,10 @@ rtx reduc = gen_lowpart (V4SImode, tmp); rtx res = gen_reg_rtx (V4SImode); emit_insn (gen_aarch64_uminpv4si (res, reduc, reduc)); - emit_move_insn (tmp, gen_lowpart (<MODE>mode, res)); + tmp = gen_lowpart (<MODE>mode, res); } - rtx val = gen_reg_rtx (DImode); - emit_move_insn (val, gen_lowpart (DImode, tmp)); + + rtx val = force_lowpart_subreg (DImode, tmp, <MODE>mode); rtx cc_reg = aarch64_gen_compare_reg (EQ, val, constm1_rtx); rtx cmp = gen_rtx_fmt_ee (EQ, SImode, cc_reg, constm1_rtx); rtx tmp2 = gen_reg_rtx (SImode); @@ -3607,10 +3607,10 @@ rtx reduc = gen_lowpart (V4SImode, tmp); rtx res = gen_reg_rtx (V4SImode); emit_insn (gen_aarch64_umaxpv4si (res, reduc, reduc)); - emit_move_insn (tmp, gen_lowpart (<MODE>mode, res)); + tmp = gen_lowpart (<MODE>mode, res); } - rtx val = gen_reg_rtx (DImode); - emit_move_insn (val, gen_lowpart (DImode, tmp)); + + rtx val = force_lowpart_subreg (DImode, tmp, <MODE>mode); rtx cc_reg = aarch64_gen_compare_reg (NE, val, const0_rtx); rtx cmp = gen_rtx_fmt_ee (NE, SImode, cc_reg, const0_rtx); rtx tmp2 = gen_reg_rtx (SImode); diff --git a/gcc/config/aarch64/aarch64-tune.md b/gcc/config/aarch64/aarch64-tune.md index 292796c..d6f1bbc 100644 --- a/gcc/config/aarch64/aarch64-tune.md +++ b/gcc/config/aarch64/aarch64-tune.md @@ -1,5 +1,5 @@ ;; -*- buffer-read-only: t -*- ;; Generated automatically by gentune.sh from aarch64-cores.def (define_attr "tune" - "cortexa34,cortexa35,cortexa53,cortexa57,cortexa72,cortexa73,thunderx,thunderxt88,thunderxt88p1,octeontx,octeontxt81,octeontxt83,thunderxt81,thunderxt83,ampere1,ampere1a,ampere1b,ampere1c,emag,xgene1,falkor,qdf24xx,exynosm1,phecda,thunderx2t99p1,vulcan,thunderx2t99,cortexa55,cortexa75,cortexa76,cortexa76ae,cortexa77,cortexa78,cortexa78ae,cortexa78c,cortexa65,cortexa65ae,cortexx1,cortexx1c,neoversen1,ares,neoversee1,octeontx2,octeontx2t98,octeontx2t96,octeontx2t93,octeontx2f95,octeontx2f95n,octeontx2f95mm,a64fx,fujitsu_monaka,tsv110,thunderx3t110,neoversev1,zeus,neoverse512tvb,saphira,oryon1,cortexa57cortexa53,cortexa72cortexa53,cortexa73cortexa35,cortexa73cortexa53,cortexa75cortexa55,cortexa76cortexa55,cortexr82,cortexr82ae,applea12,applem1_0,applem1_1,applem1_2,applem1_3,applem2_0,applem2_1,applem2_2,applem2_3,applem3_0,applem3_1,applem3_2,applem4_0,applem4_1,applem4_2,cortexa510,cortexa520,cortexa520ae,cortexa710,cortexa715,cortexa720,cortexa720ae,cortexa725,cortexx2,cortexx3,cortexx4,cortexx925,neoversen2,cobalt100,neoversen3,neoversev2,grace,neoversev3,neoversev3ae,demeter,olympus,gb10,generic,generic_armv8_a,generic_armv9_a" + "cortexa34,cortexa35,cortexa53,cortexa57,cortexa72,cortexa73,thunderx,thunderxt88,thunderxt88p1,octeontx,octeontxt81,octeontxt83,thunderxt81,thunderxt83,ampere1,ampere1a,ampere1b,ampere1c,emag,xgene1,falkor,qdf24xx,exynosm1,phecda,thunderx2t99p1,vulcan,thunderx2t99,cortexa55,cortexa75,cortexa76,cortexa76ae,cortexa77,cortexa78,cortexa78ae,cortexa78c,cortexa65,cortexa65ae,cortexx1,cortexx1c,neoversen1,ares,neoversee1,octeontx2,octeontx2t98,octeontx2t96,octeontx2t93,octeontx2f95,octeontx2f95n,octeontx2f95mm,a64fx,fujitsu_monaka,tsv110,thunderx3t110,neoversev1,zeus,neoverse512tvb,saphira,oryon1,cortexa57cortexa53,cortexa72cortexa53,cortexa73cortexa35,cortexa73cortexa53,cortexa75cortexa55,cortexa76cortexa55,cortexr82,cortexr82ae,applea12,applem1_0,applem1_1,applem1_2,applem1_3,applem2_0,applem2_1,applem2_2,applem2_3,applem3_0,applem3_1,applem3_2,applem4_0,applem4_1,applem4_2,cortexa510,cortexa520,cortexa520ae,cortexa710,cortexa715,cortexa720,cortexa720ae,cortexa725,cortexx2,cortexx3,cortexx4,cortexx925,neoversen2,cobalt100,neoversen3,neoversev2,grace,neoversev3,neoversev3ae,c1nano,c1pro,c1premium,c1ultra,demeter,olympus,gb10,generic,generic_armv8_a,generic_armv9_a" (const (symbol_ref "((enum attr_tune) aarch64_tune)"))) diff --git a/gcc/config/mingw/winnt.cc b/gcc/config/mingw/winnt.cc index b51fd8e..fe2fb4c 100644 --- a/gcc/config/mingw/winnt.cc +++ b/gcc/config/mingw/winnt.cc @@ -446,8 +446,11 @@ mingw_pe_unique_section (tree decl, int reloc) prefix = ".text$"; else if (decl_readonly_section (decl, reloc)) prefix = ".rdata$"; + /* Note that we need two dollar signs for TLS sections + because they need to be ASCII-sorted before .tls$ZZZ + to be properly laid out by the GNU linker. */ else if (DECL_THREAD_LOCAL_P (decl)) - prefix = ".tls$"; + prefix = ".tls$$"; else prefix = ".data$"; len = strlen (name) + strlen (prefix); @@ -522,9 +525,6 @@ mingw_pe_asm_named_section (const char *name, unsigned int flags, *f++ = 'e'; #endif - if (strcmp (name, ".tls$") == 0) - *f++ = 'd'; - if ((flags & (SECTION_CODE | SECTION_WRITE)) == 0) /* readonly data */ { @@ -533,6 +533,8 @@ mingw_pe_asm_named_section (const char *name, unsigned int flags, } else { + if (startswith (name, ".tls$")) + *f++ = 'd'; if (flags & SECTION_CODE) *f++ = 'x'; if (flags & SECTION_WRITE) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 3ad8d16..b4c2b70 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,13 @@ +2025-12-08 Egas Ribeiro <egas.g.ribeiro@tecnico.ulisboa.pt> + + * pt.cc (tsubst_expr): Add TARGET_EXPR case with explanatory + comment and gcc_unreachable. + +2025-12-08 Egas Ribeiro <egas.g.ribeiro@tecnico.ulisboa.pt> + + PR c++/119343 + * pt.cc (resolve_nondeduced_context): Remove mark_used call. + 2025-12-06 Jakub Jelinek <jakub@redhat.com> * decl2.cc (is_late_template_attribute): Call lookup_attribute_spec diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index 74c862e..31081b3 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -19750,7 +19750,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags) } } - bool honor_interface = (!DECL_TEMPLATE_INSTANTIATION (decl1) + bool honor_interface = (!DECL_TEMPLOID_INSTANTIATION (decl1) /* Implicitly-defined methods (like the destructor for a class in which no destructor is explicitly declared) must not be defined @@ -19781,7 +19781,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags) else if (!finfo->interface_unknown && honor_interface) { if (DECL_DECLARED_INLINE_P (decl1) - || DECL_TEMPLATE_INSTANTIATION (decl1)) + || DECL_TEMPLOID_INSTANTIATION (decl1)) { DECL_EXTERNAL (decl1) = (finfo->interface_only @@ -19823,7 +19823,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags) DECL_EXTERNAL (decl1) = 0; if ((DECL_DECLARED_INLINE_P (decl1) - || DECL_TEMPLATE_INSTANTIATION (decl1)) + || DECL_TEMPLOID_INSTANTIATION (decl1)) && ! DECL_INTERFACE_KNOWN (decl1)) DECL_DEFER_OUTPUT (decl1) = 1; else diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc index 8ec9740..01bf26b 100644 --- a/gcc/cp/decl2.cc +++ b/gcc/cp/decl2.cc @@ -2510,7 +2510,7 @@ vague_linkage_p (tree decl) || (TREE_CODE (decl) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (decl)) || (DECL_LANG_SPECIFIC (decl) - && DECL_TEMPLATE_INSTANTIATION (decl)) + && DECL_TEMPLOID_INSTANTIATION (decl)) || (VAR_P (decl) && DECL_INLINE_VAR_P (decl))) return true; else if (DECL_FUNCTION_SCOPE_P (decl)) @@ -5850,8 +5850,7 @@ c_parse_final_cleanups (void) && !(header_module_p () && (DECL_DEFAULTED_FN (decl) || decl_tls_wrapper_p (decl))) /* Don't complain if the template was defined. */ - && !((DECL_TEMPLATE_INSTANTIATION (decl) - || DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (decl)) + && !(DECL_TEMPLOID_INSTANTIATION (decl) && DECL_INITIAL (DECL_TEMPLATE_RESULT (template_for_substitution (decl)))) && warning_at (DECL_SOURCE_LOCATION (decl), 0, diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 8498730..ce30b52 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -22562,6 +22562,11 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) in response to the saved STMT_IS_FULL_EXPR_P setting. */ gcc_unreachable (); + case TARGET_EXPR: + /* TARGET_EXPR represents temporary objects and should not appear in + templated trees. */ + gcc_unreachable (); + case OFFSET_REF: { /* We should only get here for an OFFSET_REF like A::m; a .* in a @@ -24816,8 +24821,6 @@ resolve_nondeduced_context (tree orig_expr, tsubst_flags_t complain) } if (good == 1) { - if (!mark_used (goodfn, complain) && !(complain & tf_error)) - return error_mark_node; expr = goodfn; if (baselink) expr = build_baselink (BASELINK_BINFO (baselink), diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc index 331db16..b32ab2f 100644 --- a/gcc/cp/semantics.cc +++ b/gcc/cp/semantics.cc @@ -5537,7 +5537,9 @@ expand_or_defer_fn_1 (tree fn) of the compilation. Until that point, we do not want the back end to output them -- but we do want it to see the bodies of these functions so that it can inline them as appropriate. */ - if (DECL_DECLARED_INLINE_P (fn) || DECL_IMPLICIT_INSTANTIATION (fn)) + if (DECL_DECLARED_INLINE_P (fn) + || DECL_IMPLICIT_INSTANTIATION (fn) + || DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (fn)) { if (DECL_INTERFACE_KNOWN (fn)) /* We've already made a decision as to how this function will diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index ac36fda..b89fbf8 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -22761,7 +22761,8 @@ performance of the code. Permissible values for this option are: @samp{cortex-a520}, @samp{cortex-a520ae}, @samp{cortex-a710}, @samp{cortex-a715}, @samp{cortex-a720}, @samp{cortex-a720ae}, @samp{ampere1}, @samp{ampere1a}, @samp{ampere1b}, @samp{ampere1c}, @samp{cobalt-100}, @samp{apple-m1}, -@samp{apple-m2}, @samp{apple-m3}, @samp{apple-m4} and @samp{native}. +@samp{apple-m2}, @samp{apple-m3}, @samp{apple-m4}, @samp{c1-nano}, +@samp{c1-pro}, @samp{c1-premium} @samp{c1-ultra} and @samp{native}. The values @samp{cortex-a57.cortex-a53}, @samp{cortex-a72.cortex-a53}, @samp{cortex-a73.cortex-a35}, @samp{cortex-a73.cortex-a53}, diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 724da5b..4fd2183 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,12 @@ +2025-12-08 Harald Anlauf <anlauf@gmx.de> + Steven G. Kargl <kargl@gcc.gnu.org> + + PR fortran/123025 + * decl.cc (match_char_length): Add a check for the + obsolete '*' style of character declarations in the + alternate branch of checking so we dont miss two + use cases: + 2025-12-06 Paul Thomas <pault@gcc.gnu.org> PR fortran/122693 diff --git a/gcc/fortran/decl.cc b/gcc/fortran/decl.cc index dfedb96..0e55171 100644 --- a/gcc/fortran/decl.cc +++ b/gcc/fortran/decl.cc @@ -1217,6 +1217,10 @@ match_char_length (gfc_expr **expr, bool *deferred, bool obsolescent_check) goto syntax; } + if (obsolescent_check + && !gfc_notify_std (GFC_STD_F95_OBS, "Old-style character length at %C")) + return MATCH_ERROR; + return MATCH_YES; syntax: diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e6918d4..f8a8fba 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,58 @@ +2025-12-08 Andrew Pinski <andrew.pinski@oss.qualcomm.com> + + PR tree-optimization/46555 + * gcc.dg/tree-ssa/pr46555.c: New test. + +2025-12-08 Harald Anlauf <anlauf@gmx.de> + Steven G. Kargl <kargl@gcc.gnu.org> + + PR fortran/123025 + * gfortran.dg/assumed_charlen_dummy.f90: These tests failed + with the change because of the default -pedantic option + used by the dg.exp mechanisms. Overide this default. + * gfortran.dg/automatic_char_len_1.f90: Ditto. + * gfortran.dg/entry_23.f: Ditto. + * gfortran.dg/finalize_59.f90: Dito. + * gfortran.dg/g77/f90-intrinsic-bit.f: Ditto. + * gfortran.dg/g77/f90-intrinsic-mathematical.f: Ditto. + * gfortran.dg/g77/f90-intrinsic-numeric.f: Ditto. + * gfortran.dg/g77/intrinsic-unix-bessel.f: Ditto. + * gfortran.dg/g77/intrinsic-unix-erf.f: Ditto. + * gfortran.dg/initialization_9.f90: Ditto. + * gfortran.dg/intrinsic_actual_4.f90: Ditto. + * gfortran.dg/namelist_assumed_char.f90: Ditto. + * gfortran.dg/pr15140.f90: Ditto. + +2025-12-08 Egas Ribeiro <egas.g.ribeiro@tecnico.ulisboa.pt> + + PR c++/119343 + * g++.dg/template/sfinae-deleted-pr119343.C: New test. + +2025-12-08 Eric Botcazou <ebotcazou@adacore.com> + + * gcc.dg/tls/data-sections-1.c: New test. + +2025-12-08 Richard Biener <rguenther@suse.de> + + PR tree-optimization/123040 + * g++.dg/torture/pr123040.C: New testcase. + +2025-12-08 Richard Biener <rguenther@suse.de> + + PR tree-optimization/123038 + * gcc.dg/vect/pr123038.c: New testcase. + +2025-12-08 Tamar Christina <tamar.christina@arm.com> + + PR target/123026 + * gcc.target/aarch64/pr123026.c: New test. + +2025-12-08 H.J. Lu <hjl.tools@gmail.com> + + PR target/122343 + * gcc.target/i386/avx2-vpcmpgtq-1.c: Compile with + -fno-fuse-ops-with-volatile-access. + 2025-12-07 Eric Botcazou <ebotcazou@adacore.com> * gnat.dg/reduce3.adb: New test. diff --git a/gcc/testsuite/g++.dg/modules/tpl-friend-22.C b/gcc/testsuite/g++.dg/modules/tpl-friend-22.C new file mode 100644 index 0000000..a77d1cb --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/tpl-friend-22.C @@ -0,0 +1,24 @@ +// PR c++/122819 +// { dg-do compile { target *-*-*gnu* } } +// { dg-additional-options "-fmodules" } + +export module M; + +template <typename T> struct S; +void foo(S<float>); + +template <typename T> struct S { + friend void foo(S) {} +}; + +void foo(S<double>); + +void use() { + foo(S<int>{}); + foo(S<float>{}); + foo(S<double>{}); +} + +// { dg-final { scan-assembler "_ZW1M3fooS_1SIiE,comdat" } } +// { dg-final { scan-assembler "_ZW1M3fooS_1SIfE,comdat" } } +// { dg-final { scan-assembler "_ZW1M3fooS_1SIdE,comdat" } } diff --git a/gcc/testsuite/g++.dg/template/sfinae-deleted-pr119343.C b/gcc/testsuite/g++.dg/template/sfinae-deleted-pr119343.C new file mode 100644 index 0000000..065ad60 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/sfinae-deleted-pr119343.C @@ -0,0 +1,31 @@ +// { dg-do compile { target c++11 } } +// PR c++/119343 - No SFINAE for deleted explicit specializations + +struct true_type { static constexpr bool value = true; }; +struct false_type { static constexpr bool value = false; }; + +struct X { + static void f()=delete; + template<int> static void g(); +}; +template<> void X::g<0>()=delete; +struct Y { + static void f(); + template<int> static void g(); +}; + +template<class T,class=void> +struct has_f : false_type {}; +template<class T> +struct has_f<T,decltype(void(T::f))> : true_type {}; + +static_assert(!has_f<X>::value, ""); +static_assert(has_f<Y>::value, ""); + +template<class T,class=void> +struct has_g0 : false_type {}; +template<class T> +struct has_g0<T,decltype(void(T::template g<0>))> : true_type {}; + +static_assert(!has_g0<X>::value, ""); +static_assert(has_g0<Y>::value, ""); diff --git a/gcc/testsuite/g++.dg/torture/pr123040.C b/gcc/testsuite/g++.dg/torture/pr123040.C new file mode 100644 index 0000000..3ba2d90 --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr123040.C @@ -0,0 +1,61 @@ +// { dg-do compile } + +template <int kBytes, typename From, typename To> +void CopyBytes(From from, To to) { + __builtin_memcpy(to, from, kBytes); +} +template <typename From, typename To> void CopySameSize(From *from, To to) { + CopyBytes<sizeof(From)>(from, to); +} +template <typename> using MakeUnsigned = char; +template <typename Lane, int N> struct Simd { + using T = Lane; + static constexpr int kPrivateLanes = N; + template <typename NewT> using Rebind = Simd<NewT, 0>; +}; +template <class D> using TFromD = D::T; +template <class T, class D> using Rebind = D::template Rebind<T>; +template <class D> using RebindToUnsigned = Rebind<MakeUnsigned<D>, D>; +template <typename T, int> struct Vec128 { + using PrivateT = T; + static constexpr int kPrivateN = 6; + T raw[16]; +}; +template <class V> using DFromV = Simd<typename V::PrivateT, V::kPrivateN>; +template <class D> Vec128<TFromD<D>, D::kPrivateLanes> Zero(D); +template <class D> using VFromD = decltype(Zero(D())); +template <class D, class VFrom> VFromD<D> BitCast(D, VFrom v) { + VFromD<D> to; + CopySameSize(&v, to.raw); + return to; +} +template <int N> Vec128<signed char, N> And(Vec128<signed char, N> b) { + Vec128<signed char, N> a; + DFromV<decltype(a)> d; + RebindToUnsigned<decltype(d)> du; + auto au(a); + auto bu = BitCast(du, b); + for (int i = 0; i < N; ++i) + au.raw[i] &= bu.raw[i]; + return au; +} +void Or(Vec128<signed char, 16>); +template <int N> void IfVecThenElse(Vec128<signed char, N> yes) { + Vec128 __trans_tmp_2 = And(yes); + Or(__trans_tmp_2); +} +template <int N> void IfThenElseZero(Vec128<signed char, N> yes) { + IfVecThenElse(yes); +} +Vec128<signed char, 16> Abs_a; +char MaskedAbs___trans_tmp_5; +void MaskedAbs() { + Vec128<signed char, 16> __trans_tmp_4; + for (int i = 0; i < 16; ++i) { + MaskedAbs___trans_tmp_5 = Abs_a.raw[i] ? -Abs_a.raw[i] : 0; + Abs_a.raw[i] = MaskedAbs___trans_tmp_5; + } + __trans_tmp_4 = Abs_a; + Vec128 __trans_tmp_3 = __trans_tmp_4; + IfThenElseZero(__trans_tmp_3); +} diff --git a/gcc/testsuite/gcc.dg/tls/data-sections-1.c b/gcc/testsuite/gcc.dg/tls/data-sections-1.c new file mode 100644 index 0000000..c829256 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tls/data-sections-1.c @@ -0,0 +1,14 @@ +/* { dg-do run } */ +/* { dg-require-effective-target tls_runtime } */ +/* { dg-options "-fdata-sections" } */ +/* { dg-add-options tls } */ + +__thread int i = 1; + +int main (void) +{ + if (i != 1) + __builtin_abort (); + + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr46555.c b/gcc/testsuite/gcc.dg/tree-ssa/pr46555.c new file mode 100644 index 0000000..d4de7c2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr46555.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized-details -fdump-rtl-pro_and_epilogue" } */ +/* PR tree-optimization/46555 */ +/* Here should not remove the forwarder block (or rather recreate it and not + remove it again). This improves expansion to RTL as there is one less copy + (or constant formation) in some cases. In this case we also get the ability + to shrink wrap the function. */ + +int h(void); +int f(int a, int b, int c) +{ + if (a) + return 2; + h(); + if (b) + return 2; + h(); + if (c) + return 2; + h(); + return 4; +} + +/* { dg-final { scan-tree-dump-times "New forwarder block for edge" 1 "optimized" } } */ +/* Make sure we only have a PHI with 2 arguments here, 2 and 4. */ +/* { dg-final { scan-tree-dump "PHI <2..., 4...>|PHI <4..., 2...>" "optimized" } } */ +/* Make sure we can shrink wrap the function now too. */ +/* { dg-final { scan-rtl-dump "Performing shrink-wrapping" "pro_and_epilogue" { target { { { i?86-*-* x86_64-*-* } && { ! ia32 } } || { powerpc*-*-* aarch64*-*-* riscv*-*-* arm*-*-* } } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/pr123038.c b/gcc/testsuite/gcc.dg/vect/pr123038.c new file mode 100644 index 0000000..bca831f --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr123038.c @@ -0,0 +1,8 @@ +/* { dg-do compile } */ + +unsigned char f(int b) +{ + for (int a = 0; a < 10; a += 1) + b = __builtin_ffs(b); + return b; +} diff --git a/gcc/testsuite/gcc.target/aarch64/pr123026.c b/gcc/testsuite/gcc.target/aarch64/pr123026.c new file mode 100644 index 0000000..4dcce8a --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/pr123026.c @@ -0,0 +1,21 @@ +/* { dg-do run } */ +/* { dg-additional-options "-O3 -march=armv8-a -std=c99" } */ + +#include <stdbool.h> + +int g; + +__attribute__ ((noipa)) void +foo(bool a) { + for (int i = 0; i < 4; i++) + if (!i || a) + g += 1; +} + +int main() +{ + foo(0); + if (g != 1) + __builtin_abort(); + return 0; +} diff --git a/gcc/testsuite/gcc.target/i386/avx2-vpcmpgtq-1.c b/gcc/testsuite/gcc.target/i386/avx2-vpcmpgtq-1.c index 7a98380..5e6f431 100644 --- a/gcc/testsuite/gcc.target/i386/avx2-vpcmpgtq-1.c +++ b/gcc/testsuite/gcc.target/i386/avx2-vpcmpgtq-1.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-mavx2 -O2" } */ +/* { dg-options "-mavx2 -O2 -fno-fuse-ops-with-volatile-access" } */ /* { dg-final { scan-assembler "vpcmpgtq\[ \\t\]+\[^\n\]*%ymm\[0-9\]" } } */ #include <immintrin.h> diff --git a/gcc/testsuite/gfortran.dg/assumed_charlen_dummy.f90 b/gcc/testsuite/gfortran.dg/assumed_charlen_dummy.f90 index 04f0b9f..2e0e77c 100644 --- a/gcc/testsuite/gfortran.dg/assumed_charlen_dummy.f90 +++ b/gcc/testsuite/gfortran.dg/assumed_charlen_dummy.f90 @@ -1,4 +1,5 @@ ! { dg-do compile } +! { dg-options " " } ! Test the fix for PR fortran/39893. ! Original testcase provided by Deji Akingunola. ! Reduced testcase provided by Dominique d'Humieres. diff --git a/gcc/testsuite/gfortran.dg/automatic_char_len_1.f90 b/gcc/testsuite/gfortran.dg/automatic_char_len_1.f90 index 3ccfcb7..7f102b7 100644 --- a/gcc/testsuite/gfortran.dg/automatic_char_len_1.f90 +++ b/gcc/testsuite/gfortran.dg/automatic_char_len_1.f90 @@ -1,4 +1,5 @@ ! { dg-do compile } +! { dg-options " " } ! PR18082 - Compiler would get stuck in loop, whilst treating ! the assignments. ! Test is one of PR cases. diff --git a/gcc/testsuite/gfortran.dg/entry_23.f b/gcc/testsuite/gfortran.dg/entry_23.f index ebc5f66..d10ea92 100644 --- a/gcc/testsuite/gfortran.dg/entry_23.f +++ b/gcc/testsuite/gfortran.dg/entry_23.f @@ -1,4 +1,5 @@ ! { dg-do run } +! { dg-options " " } ! PR 97799 - this used to segfault intermittently. ! Test case by George Hockney. PROGRAM MAIN diff --git a/gcc/testsuite/gfortran.dg/finalize_59.f90 b/gcc/testsuite/gfortran.dg/finalize_59.f90 index 8be5f71..e9e68d4 100644 --- a/gcc/testsuite/gfortran.dg/finalize_59.f90 +++ b/gcc/testsuite/gfortran.dg/finalize_59.f90 @@ -187,7 +187,7 @@ Program Cds_Principal Type(Uef_Vector) :: Cds_Mod_Les_materiaux Type (Cds_Materiau_Acier_EC) :: acier_ec Class (Cds_Materiau), pointer :: pt_materiau - Character *(8) :: nom_materiau + Character(len=8) :: nom_materiau !------------------------------------------------------------------------------------------------- CaLL Cds_Mod_Les_materiaux%Add (acier_ec) nom_materiau = "12345678" @@ -199,7 +199,7 @@ Function Get_Pt_Materiau_nom (vecteur, nom_materiau) ! Fonction : !-------------------- ! Parametres en entree - Character *(8), Intent (in) :: nom_materiau + Character(len=8), Intent (in) :: nom_materiau Type (Uef_Vector) , Intent (inout) :: vecteur ! Parametres en sortie diff --git a/gcc/testsuite/gfortran.dg/g77/f90-intrinsic-bit.f b/gcc/testsuite/gfortran.dg/g77/f90-intrinsic-bit.f index 0ce45de..2f03db1 100644 --- a/gcc/testsuite/gfortran.dg/g77/f90-intrinsic-bit.f +++ b/gcc/testsuite/gfortran.dg/g77/f90-intrinsic-bit.f @@ -1,4 +1,5 @@ c { dg-do run } +c { dg-options " " } c f90-intrinsic-bit.f c c Test Fortran 90 diff --git a/gcc/testsuite/gfortran.dg/g77/f90-intrinsic-mathematical.f b/gcc/testsuite/gfortran.dg/g77/f90-intrinsic-mathematical.f index d151fd0..f07336e 100644 --- a/gcc/testsuite/gfortran.dg/g77/f90-intrinsic-mathematical.f +++ b/gcc/testsuite/gfortran.dg/g77/f90-intrinsic-mathematical.f @@ -1,4 +1,5 @@ c { dg-do run } +c { dg-options " " } c f90-intrinsic-mathematical.f c c Test Fortran 90 intrinsic mathematical functions - Section 13.10.3 and diff --git a/gcc/testsuite/gfortran.dg/g77/f90-intrinsic-numeric.f b/gcc/testsuite/gfortran.dg/g77/f90-intrinsic-numeric.f index c8d7c56..c01efe6 100644 --- a/gcc/testsuite/gfortran.dg/g77/f90-intrinsic-numeric.f +++ b/gcc/testsuite/gfortran.dg/g77/f90-intrinsic-numeric.f @@ -1,4 +1,5 @@ c { dg-do run } +c { dg-options " " } c f90-intrinsic-numeric.f c c Test Fortran 90 intrinsic numeric functions - Section 13.10.2 and 13.13 diff --git a/gcc/testsuite/gfortran.dg/g77/intrinsic-unix-bessel.f b/gcc/testsuite/gfortran.dg/g77/intrinsic-unix-bessel.f index b388806..406a8e4 100644 --- a/gcc/testsuite/gfortran.dg/g77/intrinsic-unix-bessel.f +++ b/gcc/testsuite/gfortran.dg/g77/intrinsic-unix-bessel.f @@ -1,4 +1,5 @@ c { dg-do run } +c { dg-options " " } c intrinsic-unix-bessel.f c c Test Bessel function intrinsics. diff --git a/gcc/testsuite/gfortran.dg/g77/intrinsic-unix-erf.f b/gcc/testsuite/gfortran.dg/g77/intrinsic-unix-erf.f index 250519a..6ed9590 100644 --- a/gcc/testsuite/gfortran.dg/g77/intrinsic-unix-erf.f +++ b/gcc/testsuite/gfortran.dg/g77/intrinsic-unix-erf.f @@ -1,4 +1,5 @@ c { dg-do run } +c { dg-options " " } c intrinsic-unix-erf.f c c Test Bessel function intrinsics. diff --git a/gcc/testsuite/gfortran.dg/initialization_9.f90 b/gcc/testsuite/gfortran.dg/initialization_9.f90 index d904047..fe7ca63 100644 --- a/gcc/testsuite/gfortran.dg/initialization_9.f90 +++ b/gcc/testsuite/gfortran.dg/initialization_9.f90 @@ -1,4 +1,5 @@ ! { dg-do compile } +! { dg-options " " } ! ! PR fortran/31639 ! Contributed by Martin Michlmayr <tbm AT cyrius DOT com> diff --git a/gcc/testsuite/gfortran.dg/intrinsic_actual_4.f90 b/gcc/testsuite/gfortran.dg/intrinsic_actual_4.f90 index 4521c96..3358b4a 100644 --- a/gcc/testsuite/gfortran.dg/intrinsic_actual_4.f90 +++ b/gcc/testsuite/gfortran.dg/intrinsic_actual_4.f90 @@ -1,4 +1,5 @@ ! { dg-do run } +! { dg-options " " } ! Tests the fix for PR27900, in which an ICE would be caused because ! the actual argument LEN had no type. ! diff --git a/gcc/testsuite/gfortran.dg/namelist_assumed_char.f90 b/gcc/testsuite/gfortran.dg/namelist_assumed_char.f90 index b7d063c..25edf64 100644 --- a/gcc/testsuite/gfortran.dg/namelist_assumed_char.f90 +++ b/gcc/testsuite/gfortran.dg/namelist_assumed_char.f90 @@ -8,7 +8,7 @@ ! Add -std=f95, add bar() ! subroutine foo(c) - character*(*) c + character*(*) c ! { dg-warning "Old-style character length" } namelist /abc/ c ! { dg-error "nonconstant character length in namelist" } end subroutine diff --git a/gcc/testsuite/gfortran.dg/pr15140.f90 b/gcc/testsuite/gfortran.dg/pr15140.f90 index 80c08dd..7f9af4f 100644 --- a/gcc/testsuite/gfortran.dg/pr15140.f90 +++ b/gcc/testsuite/gfortran.dg/pr15140.f90 @@ -1,4 +1,5 @@ ! { dg-do run } +! { dg-options "-std=legacy" } ! PR 15140: we used to fail an assertion, because we don't use the ! argument of the subroutine directly, but instead use a copy of it. function M(NAMES) diff --git a/gcc/tree-cfg.cc b/gcc/tree-cfg.cc index 1d20e6a..f0a5e05 100644 --- a/gcc/tree-cfg.cc +++ b/gcc/tree-cfg.cc @@ -10173,6 +10173,224 @@ make_pass_fixup_cfg (gcc::context *ctxt) return new pass_fixup_cfg (ctxt); } + +/* Sort PHI argument values for make_forwarders_with_degenerate_phis. */ + +static int +sort_phi_args (const void *a_, const void *b_) +{ + auto *a = (const std::pair<edge, hashval_t> *) a_; + auto *b = (const std::pair<edge, hashval_t> *) b_; + hashval_t ha = a->second; + hashval_t hb = b->second; + if (ha < hb) + return -1; + else if (ha > hb) + return 1; + else if (a->first->dest_idx < b->first->dest_idx) + return -1; + else if (a->first->dest_idx > b->first->dest_idx) + return 1; + else + return 0; +} + +/* Look for a non-virtual PHIs and make a forwarder block when all PHIs + have the same argument on a set of edges. This is to not consider + control dependences of individual edges for same values but only for + the common set. Returns true if changed the CFG. */ + +bool +make_forwarders_with_degenerate_phis (function *fn) +{ + bool didsomething = false; + + basic_block bb; + FOR_EACH_BB_FN (bb, fn) + { + /* Only PHIs with three or more arguments have opportunities. */ + if (EDGE_COUNT (bb->preds) < 3) + continue; + /* Do not touch loop headers or blocks with abnormal predecessors. + ??? This is to avoid creating valid loops here, see PR103458. + We might want to improve things to either explicitely add those + loops or at least consider blocks with no backedges. */ + if (bb->loop_father->header == bb + || bb_has_abnormal_pred (bb)) + continue; + + /* Take one PHI node as template to look for identical + arguments. Build a vector of candidates forming sets + of argument edges with equal values. Note optimality + depends on the particular choice of the template PHI + since equal arguments are unordered leaving other PHIs + with more than one set of equal arguments within this + argument range unsorted. We'd have to break ties by + looking at other PHI nodes. */ + gphi_iterator gsi = gsi_start_nonvirtual_phis (bb); + if (gsi_end_p (gsi)) + continue; + gphi *phi = gsi.phi (); + auto_vec<std::pair<edge, hashval_t>, 8> args; + bool need_resort = false; + for (unsigned i = 0; i < gimple_phi_num_args (phi); ++i) + { + edge e = gimple_phi_arg_edge (phi, i); + /* Skip abnormal edges since we cannot redirect them. */ + if (e->flags & EDGE_ABNORMAL) + continue; + /* Skip loop exit edges when we are in loop-closed SSA form + since the forwarder we'd create does not have a PHI node. */ + if (loops_state_satisfies_p (LOOP_CLOSED_SSA) + && loop_exit_edge_p (e->src->loop_father, e)) + continue; + + tree arg = gimple_phi_arg_def (phi, i); + if (!CONSTANT_CLASS_P (arg) && TREE_CODE (arg) != SSA_NAME) + need_resort = true; + args.safe_push (std::make_pair (e, iterative_hash_expr (arg, 0))); + } + if (args.length () < 2) + continue; + args.qsort (sort_phi_args); + /* The above sorting can be different between -g and -g0, as e.g. decls + can have different uids (-g could have bigger gaps in between them). + So, only use that to determine which args are equal, then change + second from hash value to smallest dest_idx of the edges which have + equal argument and sort again. If all the phi arguments are + constants or SSA_NAME, there is no need for the second sort, the hash + values are stable in that case. */ + hashval_t hash = args[0].second; + args[0].second = args[0].first->dest_idx; + bool any_equal = false; + for (unsigned i = 1; i < args.length (); ++i) + if (hash == args[i].second + && operand_equal_p (PHI_ARG_DEF_FROM_EDGE (phi, args[i - 1].first), + PHI_ARG_DEF_FROM_EDGE (phi, args[i].first))) + { + args[i].second = args[i - 1].second; + any_equal = true; + } + else + { + hash = args[i].second; + args[i].second = args[i].first->dest_idx; + } + if (!any_equal) + continue; + if (need_resort) + args.qsort (sort_phi_args); + + /* From the candidates vector now verify true candidates for + forwarders and create them. */ + gphi *vphi = get_virtual_phi (bb); + unsigned start = 0; + while (start < args.length () - 1) + { + unsigned i; + for (i = start + 1; i < args.length (); ++i) + if (args[start].second != args[i].second) + break; + /* args[start]..args[i-1] are equal. */ + if (start != i - 1) + { + /* Check all PHI nodes for argument equality + except for vops. */ + bool equal = true; + gphi_iterator gsi2 = gsi; + gsi_next (&gsi2); + for (; !gsi_end_p (gsi2); gsi_next (&gsi2)) + { + gphi *phi2 = gsi2.phi (); + if (virtual_operand_p (gimple_phi_result (phi2))) + continue; + tree start_arg + = PHI_ARG_DEF_FROM_EDGE (phi2, args[start].first); + for (unsigned j = start + 1; j < i; ++j) + { + if (!operand_equal_p (start_arg, + PHI_ARG_DEF_FROM_EDGE + (phi2, args[j].first))) + { + /* Another PHI might have a shorter set of + equivalent args. Go for that. */ + i = j; + if (j == start + 1) + equal = false; + break; + } + } + if (!equal) + break; + } + if (equal) + { + /* If we are asked to forward all edges the block + has all degenerate PHIs. Do nothing in that case. */ + if (start == 0 + && i == args.length () + && args.length () == gimple_phi_num_args (phi)) + break; + /* Instead of using make_forwarder_block we are + rolling our own variant knowing that the forwarder + does not need PHI nodes apart from eventually + a virtual one. */ + auto_vec<tree, 8> vphi_args; + if (vphi) + { + vphi_args.reserve_exact (i - start); + for (unsigned j = start; j < i; ++j) + vphi_args.quick_push + (PHI_ARG_DEF_FROM_EDGE (vphi, args[j].first)); + } + free_dominance_info (fn, CDI_DOMINATORS); + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file, "New forwarder block for edge "); + fprintf (dump_file, "%d -> %d.\n", + args[start].first->src->index, + args[start].first->dest->index); + } + basic_block forwarder = split_edge (args[start].first); + profile_count count = profile_count::zero (); + bool irr = false; + for (unsigned j = start + 1; j < i; ++j) + { + edge e = args[j].first; + if (e->flags & EDGE_IRREDUCIBLE_LOOP) + irr = true; + redirect_edge_and_branch_force (e, forwarder); + redirect_edge_var_map_clear (e); + count += e->count (); + } + forwarder->count = count; + if (irr) + { + forwarder->flags |= BB_IRREDUCIBLE_LOOP; + single_succ_edge (forwarder)->flags + |= EDGE_IRREDUCIBLE_LOOP; + } + + if (vphi) + { + tree def = copy_ssa_name (vphi_args[0]); + gphi *vphi_copy = create_phi_node (def, forwarder); + for (unsigned j = start; j < i; ++j) + add_phi_arg (vphi_copy, vphi_args[j - start], + args[j].first, UNKNOWN_LOCATION); + SET_PHI_ARG_DEF + (vphi, single_succ_edge (forwarder)->dest_idx, def); + } + didsomething = true; + } + } + /* Continue searching for more opportunities. */ + start = i; + } + } + return didsomething; +} + /* Garbage collection support for edge_def. */ extern void gt_ggc_mx (tree&); diff --git a/gcc/tree-cfg.h b/gcc/tree-cfg.h index 520bb3a..2e01762 100644 --- a/gcc/tree-cfg.h +++ b/gcc/tree-cfg.h @@ -114,6 +114,7 @@ extern edge gimple_switch_edge (function *, gswitch *, unsigned); extern edge gimple_switch_default_edge (function *, gswitch *); extern bool cond_only_block_p (basic_block); extern void copy_phi_arg_into_existing_phi (edge, edge, bool = false); +extern bool make_forwarders_with_degenerate_phis (function *); /* Return true if the LHS of a call should be removed. */ diff --git a/gcc/tree-cfgcleanup.cc b/gcc/tree-cfgcleanup.cc index 872ded3..093fde9 100644 --- a/gcc/tree-cfgcleanup.cc +++ b/gcc/tree-cfgcleanup.cc @@ -1415,8 +1415,13 @@ execute_cleanup_cfg_post_optimizing (void) } maybe_remove_unreachable_handlers (); cleanup_dead_labels (); - if (group_case_labels ()) - todo |= TODO_cleanup_cfg; + if (group_case_labels () && cleanup_tree_cfg ()) + todo |= TODO_update_ssa; + + /* When optimizing undo the merging of forwarder blocks + that phis for better out of ssa expansion. */ + if (optimize) + make_forwarders_with_degenerate_phis (cfun); basic_block bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun)); gimple_stmt_iterator gsi = gsi_start_nondebug_after_labels_bb (bb); diff --git a/gcc/tree-ssa-dce.cc b/gcc/tree-ssa-dce.cc index 317a0d6..9a9f6f9 100644 --- a/gcc/tree-ssa-dce.cc +++ b/gcc/tree-ssa-dce.cc @@ -1940,214 +1940,6 @@ tree_dce_done (bool aggressive) worklist.release (); } -/* Sort PHI argument values for make_forwarders_with_degenerate_phis. */ - -static int -sort_phi_args (const void *a_, const void *b_) -{ - auto *a = (const std::pair<edge, hashval_t> *) a_; - auto *b = (const std::pair<edge, hashval_t> *) b_; - hashval_t ha = a->second; - hashval_t hb = b->second; - if (ha < hb) - return -1; - else if (ha > hb) - return 1; - else if (a->first->dest_idx < b->first->dest_idx) - return -1; - else if (a->first->dest_idx > b->first->dest_idx) - return 1; - else - return 0; -} - -/* Look for a non-virtual PHIs and make a forwarder block when all PHIs - have the same argument on a set of edges. This is to not consider - control dependences of individual edges for same values but only for - the common set. */ - -static unsigned -make_forwarders_with_degenerate_phis (function *fn) -{ - unsigned todo = 0; - - basic_block bb; - FOR_EACH_BB_FN (bb, fn) - { - /* Only PHIs with three or more arguments have opportunities. */ - if (EDGE_COUNT (bb->preds) < 3) - continue; - /* Do not touch loop headers or blocks with abnormal predecessors. - ??? This is to avoid creating valid loops here, see PR103458. - We might want to improve things to either explicitely add those - loops or at least consider blocks with no backedges. */ - if (bb->loop_father->header == bb - || bb_has_abnormal_pred (bb)) - continue; - - /* Take one PHI node as template to look for identical - arguments. Build a vector of candidates forming sets - of argument edges with equal values. Note optimality - depends on the particular choice of the template PHI - since equal arguments are unordered leaving other PHIs - with more than one set of equal arguments within this - argument range unsorted. We'd have to break ties by - looking at other PHI nodes. */ - gphi_iterator gsi = gsi_start_nonvirtual_phis (bb); - if (gsi_end_p (gsi)) - continue; - gphi *phi = gsi.phi (); - auto_vec<std::pair<edge, hashval_t>, 8> args; - bool need_resort = false; - for (unsigned i = 0; i < gimple_phi_num_args (phi); ++i) - { - edge e = gimple_phi_arg_edge (phi, i); - /* Skip abnormal edges since we cannot redirect them. */ - if (e->flags & EDGE_ABNORMAL) - continue; - /* Skip loop exit edges when we are in loop-closed SSA form - since the forwarder we'd create does not have a PHI node. */ - if (loops_state_satisfies_p (LOOP_CLOSED_SSA) - && loop_exit_edge_p (e->src->loop_father, e)) - continue; - - tree arg = gimple_phi_arg_def (phi, i); - if (!CONSTANT_CLASS_P (arg) && TREE_CODE (arg) != SSA_NAME) - need_resort = true; - args.safe_push (std::make_pair (e, iterative_hash_expr (arg, 0))); - } - if (args.length () < 2) - continue; - args.qsort (sort_phi_args); - /* The above sorting can be different between -g and -g0, as e.g. decls - can have different uids (-g could have bigger gaps in between them). - So, only use that to determine which args are equal, then change - second from hash value to smallest dest_idx of the edges which have - equal argument and sort again. If all the phi arguments are - constants or SSA_NAME, there is no need for the second sort, the hash - values are stable in that case. */ - hashval_t hash = args[0].second; - args[0].second = args[0].first->dest_idx; - bool any_equal = false; - for (unsigned i = 1; i < args.length (); ++i) - if (hash == args[i].second - && operand_equal_p (PHI_ARG_DEF_FROM_EDGE (phi, args[i - 1].first), - PHI_ARG_DEF_FROM_EDGE (phi, args[i].first))) - { - args[i].second = args[i - 1].second; - any_equal = true; - } - else - { - hash = args[i].second; - args[i].second = args[i].first->dest_idx; - } - if (!any_equal) - continue; - if (need_resort) - args.qsort (sort_phi_args); - - /* From the candidates vector now verify true candidates for - forwarders and create them. */ - gphi *vphi = get_virtual_phi (bb); - unsigned start = 0; - while (start < args.length () - 1) - { - unsigned i; - for (i = start + 1; i < args.length (); ++i) - if (args[start].second != args[i].second) - break; - /* args[start]..args[i-1] are equal. */ - if (start != i - 1) - { - /* Check all PHI nodes for argument equality. */ - bool equal = true; - gphi_iterator gsi2 = gsi; - gsi_next (&gsi2); - for (; !gsi_end_p (gsi2); gsi_next (&gsi2)) - { - gphi *phi2 = gsi2.phi (); - if (virtual_operand_p (gimple_phi_result (phi2))) - continue; - tree start_arg - = PHI_ARG_DEF_FROM_EDGE (phi2, args[start].first); - for (unsigned j = start + 1; j < i; ++j) - { - if (!operand_equal_p (start_arg, - PHI_ARG_DEF_FROM_EDGE - (phi2, args[j].first))) - { - /* Another PHI might have a shorter set of - equivalent args. Go for that. */ - i = j; - if (j == start + 1) - equal = false; - break; - } - } - if (!equal) - break; - } - if (equal) - { - /* If we are asked to forward all edges the block - has all degenerate PHIs. Do nothing in that case. */ - if (start == 0 - && i == args.length () - && args.length () == gimple_phi_num_args (phi)) - break; - /* Instead of using make_forwarder_block we are - rolling our own variant knowing that the forwarder - does not need PHI nodes apart from eventually - a virtual one. */ - auto_vec<tree, 8> vphi_args; - if (vphi) - { - vphi_args.reserve_exact (i - start); - for (unsigned j = start; j < i; ++j) - vphi_args.quick_push - (PHI_ARG_DEF_FROM_EDGE (vphi, args[j].first)); - } - free_dominance_info (fn, CDI_DOMINATORS); - basic_block forwarder = split_edge (args[start].first); - profile_count count = profile_count::zero (); - bool irr = false; - for (unsigned j = start + 1; j < i; ++j) - { - edge e = args[j].first; - if (e->flags & EDGE_IRREDUCIBLE_LOOP) - irr = true; - redirect_edge_and_branch_force (e, forwarder); - redirect_edge_var_map_clear (e); - count += e->count (); - } - forwarder->count = count; - if (irr) - { - forwarder->flags |= BB_IRREDUCIBLE_LOOP; - single_succ_edge (forwarder)->flags - |= EDGE_IRREDUCIBLE_LOOP; - } - - if (vphi) - { - tree def = copy_ssa_name (vphi_args[0]); - gphi *vphi_copy = create_phi_node (def, forwarder); - for (unsigned j = start; j < i; ++j) - add_phi_arg (vphi_copy, vphi_args[j - start], - args[j].first, UNKNOWN_LOCATION); - SET_PHI_ARG_DEF - (vphi, single_succ_edge (forwarder)->dest_idx, def); - } - todo |= TODO_cleanup_cfg; - } - } - /* Continue searching for more opportunities. */ - start = i; - } - } - return todo; -} /* Main routine to eliminate dead code. @@ -2174,8 +1966,8 @@ perform_tree_ssa_dce (bool aggressive) scev_initialize (); } - if (aggressive) - todo |= make_forwarders_with_degenerate_phis (cfun); + if (aggressive && make_forwarders_with_degenerate_phis (cfun)) + todo |= TODO_cleanup_cfg; calculate_dominance_info (CDI_DOMINATORS); diff --git a/gcc/tree-ssa-sccvn.cc b/gcc/tree-ssa-sccvn.cc index 09f92b2..0c519cf 100644 --- a/gcc/tree-ssa-sccvn.cc +++ b/gcc/tree-ssa-sccvn.cc @@ -2527,7 +2527,10 @@ vn_nary_build_or_lookup_1 (gimple_match_op *res_op, bool insert, else { tree val = vn_lookup_simplify_result (res_op); - if (!val && insert) + /* ??? In weird cases we can end up with internal-fn calls, + but this isn't expected so throw the result away. See + PR123040 for an example. */ + if (!val && insert && res_op->code.is_tree_code ()) { gimple_seq stmts = NULL; result = maybe_push_res_to_seq (res_op, &stmts); diff --git a/gcc/tree-vect-patterns.cc b/gcc/tree-vect-patterns.cc index 555986b..af64cb8 100644 --- a/gcc/tree-vect-patterns.cc +++ b/gcc/tree-vect-patterns.cc @@ -1914,6 +1914,9 @@ vect_recog_ctz_ffs_pattern (vec_info *vinfo, stmt_vec_info stmt_vinfo, && val_new == prec) || (ifnnew == IFN_POPCOUNT && ifn == IFN_CTZ)) { + if (vect_is_reduction (stmt_vinfo)) + return NULL; + /* .CTZ (X) = PREC - .CLZ ((X - 1) & ~X) .CTZ (X) = .POPCOUNT ((X - 1) & ~X). */ if (ifnnew == IFN_CLZ) @@ -1952,6 +1955,9 @@ vect_recog_ctz_ffs_pattern (vec_info *vinfo, stmt_vec_info stmt_vinfo, } else if (ifnnew == IFN_CLZ) { + if (vect_is_reduction (stmt_vinfo)) + return NULL; + /* .CTZ (X) = (PREC - 1) - .CLZ (X & -X) .FFS (X) = PREC - .CLZ (X & -X). */ sub = prec - (ifn == IFN_CTZ); @@ -1971,6 +1977,9 @@ vect_recog_ctz_ffs_pattern (vec_info *vinfo, stmt_vec_info stmt_vinfo, } else if (ifnnew == IFN_POPCOUNT) { + if (vect_is_reduction (stmt_vinfo)) + return NULL; + /* .CTZ (X) = PREC - .POPCOUNT (X | -X) .FFS (X) = (PREC + 1) - .POPCOUNT (X | -X). */ sub = prec + (ifn == IFN_FFS); @@ -1993,6 +2002,11 @@ vect_recog_ctz_ffs_pattern (vec_info *vinfo, stmt_vec_info stmt_vinfo, /* .FFS (X) = .CTZ (X) + 1. */ add = 1; val_cmp++; + + if (vect_is_reduction (stmt_vinfo) + && defined_at_zero + && (!defined_at_zero_new || val != val_cmp)) + return NULL; } /* Create B = .IFNNEW (A). */ diff --git a/gcc/tree-vect-stmts.cc b/gcc/tree-vect-stmts.cc index dc155dc..95f015f 100644 --- a/gcc/tree-vect-stmts.cc +++ b/gcc/tree-vect-stmts.cc @@ -9920,36 +9920,35 @@ vectorizable_load (vec_info *vinfo, bool hoist_p = (LOOP_VINFO_NO_DATA_DEPENDENCIES (loop_vinfo) && !nested_in_vect_loop); - /* It is unsafe to hoist a conditional load over the conditions that make - it valid. When early break this means that any invariant load can't be - hoisted unless it's in the loop header or if we know something else has - verified the load is valid to do. Alignment peeling would do this - since getting through the prologue means the load was done at least - once and so the vector main body is free to hoist it. However today - GCC will hoist the load above the PFA loop. As such that makes it - still invalid and so we can't allow it today. */ - auto stmt_bb - = gimple_bb (STMT_VINFO_STMT ( - vect_orig_stmt (SLP_TREE_SCALAR_STMTS (slp_node)[0]))); - if (LOOP_VINFO_EARLY_BREAKS (loop_vinfo) - && !DR_SCALAR_KNOWN_BOUNDS (dr_info) - && stmt_bb != loop->header) - { - if (LOOP_VINFO_PEELING_FOR_ALIGNMENT (loop_vinfo) - && dump_enabled_p ()) - dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, + bool uniform_p = true; + for (stmt_vec_info sinfo : SLP_TREE_SCALAR_STMTS (slp_node)) + { + /* It is unsafe to hoist a conditional load over the conditions that + make it valid. When early break this means that any invariant load + can't be hoisted unless it's in the loop header or if we know + something else has verified the load is valid to do. Alignment + peeling would do this since getting through the prologue means the + load was done at least once and so the vector main body is free to + hoist it. However today GCC will hoist the load above the PFA + loop. As such that makes it still invalid and so we can't allow it + today. */ + if (LOOP_VINFO_EARLY_BREAKS (loop_vinfo) + && !DR_SCALAR_KNOWN_BOUNDS (STMT_VINFO_DR_INFO (sinfo)) + && gimple_bb (STMT_VINFO_STMT (vect_orig_stmt (sinfo))) + != loop->header) + { + if (LOOP_VINFO_PEELING_FOR_ALIGNMENT (loop_vinfo) + && dump_enabled_p ()) + dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, "not hoisting invariant load due to early break" "constraints\n"); - else if (dump_enabled_p ()) - dump_printf_loc (MSG_NOTE, vect_location, + else if (dump_enabled_p ()) + dump_printf_loc (MSG_NOTE, vect_location, "not hoisting invariant load due to early break" "constraints\n"); - hoist_p = false; - } + hoist_p = false; + } - bool uniform_p = true; - for (stmt_vec_info sinfo : SLP_TREE_SCALAR_STMTS (slp_node)) - { hoist_p = hoist_p && hoist_defs_of_uses (sinfo->stmt, loop, false); if (sinfo != SLP_TREE_SCALAR_STMTS (slp_node)[0]) uniform_p = false; diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index c01d044..c2a99de 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,71 @@ +2025-12-08 Jonathan Wakely <jwakely@redhat.com> + + PR libstdc++/122946 + * include/bits/version.def (concepts): Set value to 202207. + * include/bits/version.h: Regenerate. + * include/std/concepts (__comparison_common_type_with_impl) + (__comparison_common_type_with): New helper concepts. + (equality_comparable_with): Use __comparison_common_type_with. + * libsupc++/compare (three_way_comparable_with): Likewise. + (__glibcxx_want_concepts): Define to get __cpp_lib_concepts + here. + * testsuite/std/concepts/concepts.compare/move_only.cc: New + test. + +2025-12-08 Jonathan Wakely <jwakely@redhat.com> + + * include/bits/intcmp.h: Replace all uses of + __is_standard_integer with __is_signed_or_unsigned_integer. + * include/bits/max_size_type.h: Fix outdated comment. + * include/bits/sat_arith.h: Replace all uses of + __is_standard_integer with __is_signed_or_unsigned_integer. + * include/c_compatibility/stdckdint.h: Replace all uses of the + __cv_unqual_signed_or_unsigned_integer_type concept with + __is_signed_or_unsigned_integer. + (__cv_unqual_signed_or_unsigned_integer_type): Remove. + * include/ext/numeric_traits.h: Fix outdated comment. + * include/std/charconv (from_chars): Replace use of + __is_standard_integer with __is_signed_or_unsigned_integer. + Do not enable for cv-qualified char. + * include/std/mdspan: Likewise. + * include/std/type_traits (__is_unsigned_integer): Include + unsigned __int128 in type list. + (__is_signed_integer): Include signed __int128 in type list. + (__is_standard_integer): Rename to ... + (__is_signed_or_unsigned_integer): ... this. + * testsuite/23_containers/mdspan/extents/ctor_ints.cc: Test + with 128-bit integers. + * testsuite/23_containers/mdspan/submdspan/strided_slice.cc: + Likewise. + * testsuite/20_util/integer_comparisons/extended.cc: New test. + * testsuite/26_numerics/saturation/extended.cc: New test. + * testsuite/26_numerics/stdckdint/extended.cc: New test. + +2025-12-08 Tomasz Kamiński <tkaminsk@redhat.com> + + PR libstdc++/112591 + * include/std/variant (_Variadic_union): Separate specializations for + for union of only trivially destructible types (true as first template + argument). Unconditionally define destructor for _Variadic_union<false, + _First, _Rest...>. + * testsuite/20_util/variant/87619.cc: Add limit for the template depth. + * testsuite/20_util/variant/112591.cc: New test. + +2025-12-08 Jonathan Wakely <jwakely@redhat.com> + + * include/bits/iterator_concepts.h: Remove diagnostic pragmas. + +2025-12-08 Jonathan Wakely <jwakely@redhat.com> + + * include/Makefile.am: Add new header. + * include/Makefile.in: Regenerate. + * include/std/latch: Include <bits/intcmp.h> instead of + <utility>. + * include/std/utility: Include <bits/intcmp.h>. + (cmp_equal, cmp_not_equal, cmp_less, cmp_greater) + (cmp_less_equal, cmp_greater_equal, in_range): Move to ... + * include/bits/intcmp.h: New file. + 2025-12-06 Jason Merrill <jason@redhat.com> * src/c++23/std.cc.in: Add more #if. diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am index 7d65c6f..847fc13 100644 --- a/libstdc++-v3/include/Makefile.am +++ b/libstdc++-v3/include/Makefile.am @@ -134,6 +134,7 @@ bits_freestanding = \ ${bits_srcdir}/enable_special_members.h \ ${bits_srcdir}/functexcept.h \ ${bits_srcdir}/functional_hash.h \ + ${bits_srcdir}/intcmp.h \ ${bits_srcdir}/invoke.h \ ${bits_srcdir}/iterator_concepts.h \ ${bits_srcdir}/max_size_type.h \ diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in index acf8ae9..1d6171b 100644 --- a/libstdc++-v3/include/Makefile.in +++ b/libstdc++-v3/include/Makefile.in @@ -492,6 +492,7 @@ bits_freestanding = \ ${bits_srcdir}/enable_special_members.h \ ${bits_srcdir}/functexcept.h \ ${bits_srcdir}/functional_hash.h \ + ${bits_srcdir}/intcmp.h \ ${bits_srcdir}/invoke.h \ ${bits_srcdir}/iterator_concepts.h \ ${bits_srcdir}/max_size_type.h \ diff --git a/libstdc++-v3/include/bits/intcmp.h b/libstdc++-v3/include/bits/intcmp.h new file mode 100644 index 0000000..bb9c7f2 --- /dev/null +++ b/libstdc++-v3/include/bits/intcmp.h @@ -0,0 +1,120 @@ +// Integer comparison functions -*- C++ -*- + +// Copyright (C) 2020-2025 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library 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. + +// This library 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/>. + +/** @file bits/intcmp.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{utility} + */ + +#ifndef _GLIBCXX_INTCMP_H +#define _GLIBCXX_INTCMP_H 1 + +#ifdef _GLIBCXX_SYSHDR +#pragma GCC system_header +#endif + +#include <bits/version.h> + +#ifdef __glibcxx_integer_comparison_functions // C++ >= 20 + +#include <type_traits> +#include <ext/numeric_traits.h> // __int_traits + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + template<typename _Tp, typename _Up> + constexpr bool + cmp_equal(_Tp __t, _Up __u) noexcept + { + static_assert(__is_signed_or_unsigned_integer<_Tp>::value); + static_assert(__is_signed_or_unsigned_integer<_Up>::value); + + if constexpr (is_signed_v<_Tp> == is_signed_v<_Up>) + return __t == __u; + else if constexpr (is_signed_v<_Tp>) + return __t >= 0 && make_unsigned_t<_Tp>(__t) == __u; + else + return __u >= 0 && __t == make_unsigned_t<_Up>(__u); + } + + template<typename _Tp, typename _Up> + constexpr bool + cmp_not_equal(_Tp __t, _Up __u) noexcept + { return !std::cmp_equal(__t, __u); } + + template<typename _Tp, typename _Up> + constexpr bool + cmp_less(_Tp __t, _Up __u) noexcept + { + static_assert(__is_signed_or_unsigned_integer<_Tp>::value); + static_assert(__is_signed_or_unsigned_integer<_Up>::value); + + if constexpr (is_signed_v<_Tp> == is_signed_v<_Up>) + return __t < __u; + else if constexpr (is_signed_v<_Tp>) + return __t < 0 || make_unsigned_t<_Tp>(__t) < __u; + else + return __u >= 0 && __t < make_unsigned_t<_Up>(__u); + } + + template<typename _Tp, typename _Up> + constexpr bool + cmp_greater(_Tp __t, _Up __u) noexcept + { return std::cmp_less(__u, __t); } + + template<typename _Tp, typename _Up> + constexpr bool + cmp_less_equal(_Tp __t, _Up __u) noexcept + { return !std::cmp_less(__u, __t); } + + template<typename _Tp, typename _Up> + constexpr bool + cmp_greater_equal(_Tp __t, _Up __u) noexcept + { return !std::cmp_less(__t, __u); } + + template<typename _Res, typename _Tp> + constexpr bool + in_range(_Tp __t) noexcept + { + static_assert(__is_signed_or_unsigned_integer<_Res>::value); + static_assert(__is_signed_or_unsigned_integer<_Tp>::value); + using __gnu_cxx::__int_traits; + + if constexpr (is_signed_v<_Tp> == is_signed_v<_Res>) + return __int_traits<_Res>::__min <= __t + && __t <= __int_traits<_Res>::__max; + else if constexpr (is_signed_v<_Tp>) + return __t >= 0 + && make_unsigned_t<_Tp>(__t) <= __int_traits<_Res>::__max; + else + return __t <= make_unsigned_t<_Res>(__int_traits<_Res>::__max); + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif // __glibcxx_integer_comparison_functions +#endif // _GLIBCXX_INTCMP_H diff --git a/libstdc++-v3/include/bits/iterator_concepts.h b/libstdc++-v3/include/bits/iterator_concepts.h index fd91b22..40ac808 100644 --- a/libstdc++-v3/include/bits/iterator_concepts.h +++ b/libstdc++-v3/include/bits/iterator_concepts.h @@ -39,9 +39,6 @@ #include <bits/ptr_traits.h> // to_address #include <bits/ranges_cmp.h> // identity, ranges::less -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpedantic" // __int128 - namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION @@ -1032,6 +1029,5 @@ namespace ranges #endif // C++20 library concepts _GLIBCXX_END_NAMESPACE_VERSION } // namespace std -#pragma GCC diagnostic pop #endif // C++20 #endif // _ITERATOR_CONCEPTS_H diff --git a/libstdc++-v3/include/bits/max_size_type.h b/libstdc++-v3/include/bits/max_size_type.h index a34b91a..537acee 100644 --- a/libstdc++-v3/include/bits/max_size_type.h +++ b/libstdc++-v3/include/bits/max_size_type.h @@ -44,10 +44,8 @@ // [iterator.concept.winc]) that are one bit wider than the widest supported // integer type. // -// The set of integer types we consider includes __int128 and unsigned __int128 -// (when they exist), even though they are really integer types only in GNU -// mode. This is to obtain a consistent ABI for these integer-class types -// across strict mode and GNU mode. +// The set of integer types we consider includes the extended integer types +// __int128 and unsigned __int128 (when they exist). namespace std _GLIBCXX_VISIBILITY(default) { diff --git a/libstdc++-v3/include/bits/sat_arith.h b/libstdc++-v3/include/bits/sat_arith.h index e036fc8..bce86d9 100644 --- a/libstdc++-v3/include/bits/sat_arith.h +++ b/libstdc++-v3/include/bits/sat_arith.h @@ -46,7 +46,7 @@ namespace std _GLIBCXX_VISIBILITY(default) _GLIBCXX_BEGIN_NAMESPACE_VERSION /// Add two integers, with saturation in case of overflow. - template<typename _Tp> requires __is_standard_integer<_Tp>::value + template<typename _Tp> requires __is_signed_or_unsigned_integer<_Tp>::value constexpr _Tp add_sat(_Tp __x, _Tp __y) noexcept { @@ -62,7 +62,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } /// Subtract one integer from another, with saturation in case of overflow. - template<typename _Tp> requires __is_standard_integer<_Tp>::value + template<typename _Tp> requires __is_signed_or_unsigned_integer<_Tp>::value constexpr _Tp sub_sat(_Tp __x, _Tp __y) noexcept { @@ -78,7 +78,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } /// Multiply two integers, with saturation in case of overflow. - template<typename _Tp> requires __is_standard_integer<_Tp>::value + template<typename _Tp> requires __is_signed_or_unsigned_integer<_Tp>::value constexpr _Tp mul_sat(_Tp __x, _Tp __y) noexcept { @@ -94,7 +94,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } /// Divide one integer by another, with saturation in case of overflow. - template<typename _Tp> requires __is_standard_integer<_Tp>::value + template<typename _Tp> requires __is_signed_or_unsigned_integer<_Tp>::value constexpr _Tp div_sat(_Tp __x, _Tp __y) noexcept { @@ -107,8 +107,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// Divide one integer by another, with saturation in case of overflow. template<typename _Res, typename _Tp> - requires __is_standard_integer<_Res>::value - && __is_standard_integer<_Tp>::value + requires __is_signed_or_unsigned_integer<_Res>::value + && __is_signed_or_unsigned_integer<_Tp>::value constexpr _Res saturate_cast(_Tp __x) noexcept { diff --git a/libstdc++-v3/include/bits/version.def b/libstdc++-v3/include/bits/version.def index 412b9ce..bbc8d38 100644 --- a/libstdc++-v3/include/bits/version.def +++ b/libstdc++-v3/include/bits/version.def @@ -879,8 +879,12 @@ ftms = { ftms = { name = concepts; + // 201806 P0898R3 Standard Library Concepts + // 201907 P1754R1 Rename concepts to standard_case for C++20 + // 202002 P1964R2 Wording for boolean-testable + // 202207 P2404R3 Move-only types for equality_comparable_with, etc. values = { - v = 202002; + v = 202207; cxxmin = 20; extra_cond = "__cpp_concepts >= 201907L"; }; diff --git a/libstdc++-v3/include/bits/version.h b/libstdc++-v3/include/bits/version.h index 2b96934..7ee9ae8 100644 --- a/libstdc++-v3/include/bits/version.h +++ b/libstdc++-v3/include/bits/version.h @@ -985,9 +985,9 @@ #if !defined(__cpp_lib_concepts) # if (__cplusplus >= 202002L) && (__cpp_concepts >= 201907L) -# define __glibcxx_concepts 202002L +# define __glibcxx_concepts 202207L # if defined(__glibcxx_want_all) || defined(__glibcxx_want_concepts) -# define __cpp_lib_concepts 202002L +# define __cpp_lib_concepts 202207L # endif # endif #endif /* !defined(__cpp_lib_concepts) */ diff --git a/libstdc++-v3/include/c_compatibility/stdckdint.h b/libstdc++-v3/include/c_compatibility/stdckdint.h index 1de2d18..5bdf4dc 100644 --- a/libstdc++-v3/include/c_compatibility/stdckdint.h +++ b/libstdc++-v3/include/c_compatibility/stdckdint.h @@ -40,15 +40,6 @@ namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) { #endif -/// @cond undocumented -namespace __detail -{ - template<typename _Tp> - concept __cv_unqual_signed_or_unsigned_integer_type - = std::same_as<_Tp, std::remove_cv_t<_Tp>> - && std::__is_standard_integer<_Tp>::value; -} -/// @endcond /** Checked integer arithmetic * @@ -71,10 +62,9 @@ template<typename _Tp1, typename _Tp2, typename _Tp3> inline bool ckd_add(_Tp1* __result, _Tp2 __a, _Tp3 __b) { - using __gnu_cxx::__detail::__cv_unqual_signed_or_unsigned_integer_type; - static_assert(__cv_unqual_signed_or_unsigned_integer_type<_Tp1>); - static_assert(__cv_unqual_signed_or_unsigned_integer_type<_Tp2>); - static_assert(__cv_unqual_signed_or_unsigned_integer_type<_Tp3>); + static_assert(std::__is_signed_or_unsigned_integer<_Tp1>::value); + static_assert(std::__is_signed_or_unsigned_integer<_Tp2>::value); + static_assert(std::__is_signed_or_unsigned_integer<_Tp3>::value); return __builtin_add_overflow(__a, __b, __result); } @@ -82,10 +72,9 @@ template<typename _Tp1, typename _Tp2, typename _Tp3> inline bool ckd_sub(_Tp1* __result, _Tp2 __a, _Tp3 __b) { - using __gnu_cxx::__detail::__cv_unqual_signed_or_unsigned_integer_type; - static_assert(__cv_unqual_signed_or_unsigned_integer_type<_Tp1>); - static_assert(__cv_unqual_signed_or_unsigned_integer_type<_Tp2>); - static_assert(__cv_unqual_signed_or_unsigned_integer_type<_Tp3>); + static_assert(std::__is_signed_or_unsigned_integer<_Tp1>::value); + static_assert(std::__is_signed_or_unsigned_integer<_Tp2>::value); + static_assert(std::__is_signed_or_unsigned_integer<_Tp3>::value); return __builtin_sub_overflow(__a, __b, __result); } @@ -93,15 +82,14 @@ template<typename _Tp1, typename _Tp2, typename _Tp3> inline bool ckd_mul(_Tp1* __result, _Tp2 __a, _Tp3 __b) { - using __gnu_cxx::__detail::__cv_unqual_signed_or_unsigned_integer_type; - static_assert(__cv_unqual_signed_or_unsigned_integer_type<_Tp1>); - static_assert(__cv_unqual_signed_or_unsigned_integer_type<_Tp2>); - static_assert(__cv_unqual_signed_or_unsigned_integer_type<_Tp3>); + static_assert(std::__is_signed_or_unsigned_integer<_Tp1>::value); + static_assert(std::__is_signed_or_unsigned_integer<_Tp2>::value); + static_assert(std::__is_signed_or_unsigned_integer<_Tp3>::value); return __builtin_mul_overflow(__a, __b, __result); } /// @} #ifndef _GLIBCXX_DOXYGEN -} +} // namespace __gnu_cxx using __gnu_cxx::ckd_add; using __gnu_cxx::ckd_sub; diff --git a/libstdc++-v3/include/ext/numeric_traits.h b/libstdc++-v3/include/ext/numeric_traits.h index 6786dc6..78cb8e3 100644 --- a/libstdc++-v3/include/ext/numeric_traits.h +++ b/libstdc++-v3/include/ext/numeric_traits.h @@ -48,7 +48,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // or is_signed, digits10, max_digits10, or max_exponent10 for floats. // Unlike __is_integer (and std::is_integral) this trait is true for - // non-standard built-in integer types such as __int128 and __int20. + // non-standard built-in integer types such as __int20. template<typename _Tp> struct __is_integer_nonstrict : public std::__is_integer<_Tp> diff --git a/libstdc++-v3/include/std/charconv b/libstdc++-v3/include/std/charconv index 8cf2c0b..47f5aaa 100644 --- a/libstdc++-v3/include/std/charconv +++ b/libstdc++-v3/include/std/charconv @@ -554,10 +554,10 @@ namespace __detail } // namespace __detail - /// std::from_chars for integral types. + /// std::from_chars for integer types. template<typename _Tp, - enable_if_t<__or_<__is_standard_integer<_Tp>, - is_same<char, remove_cv_t<_Tp>>>::value, int> = 0> + enable_if_t<__or_<__is_signed_or_unsigned_integer<_Tp>, + is_same<char, _Tp>>::value, int> = 0> _GLIBCXX23_CONSTEXPR from_chars_result from_chars(const char* __first, const char* __last, _Tp& __value, int __base = 10) diff --git a/libstdc++-v3/include/std/concepts b/libstdc++-v3/include/std/concepts index d9920a8..870b0a4 100644 --- a/libstdc++-v3/include/std/concepts +++ b/libstdc++-v3/include/std/concepts @@ -296,6 +296,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { { !static_cast<_Tp&&>(__t) } -> __boolean_testable_impl; }; } // namespace __detail + // [concept.comparisoncommontype], helpers for comparison common types + namespace __detail + { + template<typename _Tp, typename _Up, + typename _Cref = common_reference_t<const _Tp&, const _Up&>> + concept __comparison_common_type_with_impl + = same_as<common_reference_t<const _Tp&, const _Up&>, + common_reference_t<const _Up&, const _Tp&>> + && requires { + requires convertible_to<const _Tp&, const _Cref&> + || convertible_to<_Tp, const _Cref&>; + requires convertible_to<const _Up&, const _Cref&> + || convertible_to<_Up, const _Cref&>; + }; + + template<typename _Tp, typename _Up> + concept __comparison_common_type_with + = __comparison_common_type_with_impl<remove_cvref_t<_Tp>, + remove_cvref_t<_Up>>; + } // namespace __detail + // [concept.equalitycomparable], concept equality_comparable namespace __detail @@ -316,7 +337,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp, typename _Up> concept equality_comparable_with = equality_comparable<_Tp> && equality_comparable<_Up> - && common_reference_with<__detail::__cref<_Tp>, __detail::__cref<_Up>> + && __detail::__comparison_common_type_with<_Tp, _Up> && equality_comparable<common_reference_t<__detail::__cref<_Tp>, __detail::__cref<_Up>>> && __detail::__weakly_eq_cmp_with<_Tp, _Up>; diff --git a/libstdc++-v3/include/std/latch b/libstdc++-v3/include/std/latch index 9504df0..df126c6 100644 --- a/libstdc++-v3/include/std/latch +++ b/libstdc++-v3/include/std/latch @@ -41,7 +41,7 @@ #ifdef __cpp_lib_latch // C++ >= 20 && atomic_wait #include <bits/atomic_base.h> #include <ext/numeric_traits.h> -#include <utility> // cmp_equal, cmp_less_equal, etc. +#include <bits/intcmp.h> // cmp_equal, cmp_less_equal, etc. namespace std _GLIBCXX_VISIBILITY(default) { diff --git a/libstdc++-v3/include/std/mdspan b/libstdc++-v3/include/std/mdspan index 03cc4f0..981fa1c 100644 --- a/libstdc++-v3/include/std/mdspan +++ b/libstdc++-v3/include/std/mdspan @@ -352,11 +352,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _OffsetType, typename _ExtentType, typename _StrideType> struct strided_slice { - static_assert(__is_standard_integer<_OffsetType>::value + static_assert(__is_signed_or_unsigned_integer<_OffsetType>::value || __detail::__integral_constant_like<_OffsetType>); - static_assert(__is_standard_integer<_ExtentType>::value + static_assert(__is_signed_or_unsigned_integer<_ExtentType>::value || __detail::__integral_constant_like<_ExtentType>); - static_assert(__is_standard_integer<_StrideType>::value + static_assert(__is_signed_or_unsigned_integer<_StrideType>::value || __detail::__integral_constant_like<_StrideType>); using offset_type = _OffsetType; @@ -379,7 +379,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _IndexType, size_t... _Extents> class extents { - static_assert(__is_standard_integer<_IndexType>::value, + static_assert(__is_signed_or_unsigned_integer<_IndexType>::value, "IndexType must be a signed or unsigned integer type"); static_assert( (__mdspan::__valid_static_extent<_Extents, _IndexType> && ...), diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits index 7c157ea..3f0bcc4e 100644 --- a/libstdc++-v3/include/std/type_traits +++ b/libstdc++-v3/include/std/type_traits @@ -826,7 +826,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Check if a type is one of the signed integer types. __extension__ template<typename _Tp> - using __is_signed_integer = __is_one_of<__remove_cv_t<_Tp>, + using __is_signed_integer = __is_one_of<_Tp, signed char, signed short, signed int, signed long, signed long long #if defined(__GLIBCXX_TYPE_INT_N_0) @@ -841,12 +841,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #if defined(__GLIBCXX_TYPE_INT_N_3) , signed __GLIBCXX_TYPE_INT_N_3 #endif +#if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__ + , signed __int128 +#endif >; // Check if a type is one of the unsigned integer types. __extension__ template<typename _Tp> - using __is_unsigned_integer = __is_one_of<__remove_cv_t<_Tp>, + using __is_unsigned_integer = __is_one_of<_Tp, unsigned char, unsigned short, unsigned int, unsigned long, unsigned long long #if defined(__GLIBCXX_TYPE_INT_N_0) @@ -861,11 +864,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #if defined(__GLIBCXX_TYPE_INT_N_3) , unsigned __GLIBCXX_TYPE_INT_N_3 #endif +#if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__ + , unsigned __int128 +#endif >; // Check if a type is one of the signed or unsigned integer types. + // i.e. an integral type except bool, char, wchar_t, and charN_t. template<typename _Tp> - using __is_standard_integer + using __is_signed_or_unsigned_integer = __or_<__is_signed_integer<_Tp>, __is_unsigned_integer<_Tp>>; // __void_t (std::void_t for C++11) diff --git a/libstdc++-v3/include/std/utility b/libstdc++-v3/include/std/utility index 3ae1852..0f6dd82 100644 --- a/libstdc++-v3/include/std/utility +++ b/libstdc++-v3/include/std/utility @@ -78,7 +78,7 @@ #include <bits/utility.h> #if __cplusplus >= 202002L -#include <ext/numeric_traits.h> // __is_standard_integer, __int_traits +#include <bits/intcmp.h> #endif #if __cplusplus > 202302L @@ -129,76 +129,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION void as_const(const _Tp&&) = delete; #endif -#ifdef __cpp_lib_integer_comparison_functions // C++ >= 20 - template<typename _Tp, typename _Up> - constexpr bool - cmp_equal(_Tp __t, _Up __u) noexcept - { - static_assert(__is_standard_integer<_Tp>::value); - static_assert(__is_standard_integer<_Up>::value); - - if constexpr (is_signed_v<_Tp> == is_signed_v<_Up>) - return __t == __u; - else if constexpr (is_signed_v<_Tp>) - return __t >= 0 && make_unsigned_t<_Tp>(__t) == __u; - else - return __u >= 0 && __t == make_unsigned_t<_Up>(__u); - } - - template<typename _Tp, typename _Up> - constexpr bool - cmp_not_equal(_Tp __t, _Up __u) noexcept - { return !std::cmp_equal(__t, __u); } - - template<typename _Tp, typename _Up> - constexpr bool - cmp_less(_Tp __t, _Up __u) noexcept - { - static_assert(__is_standard_integer<_Tp>::value); - static_assert(__is_standard_integer<_Up>::value); - - if constexpr (is_signed_v<_Tp> == is_signed_v<_Up>) - return __t < __u; - else if constexpr (is_signed_v<_Tp>) - return __t < 0 || make_unsigned_t<_Tp>(__t) < __u; - else - return __u >= 0 && __t < make_unsigned_t<_Up>(__u); - } - - template<typename _Tp, typename _Up> - constexpr bool - cmp_greater(_Tp __t, _Up __u) noexcept - { return std::cmp_less(__u, __t); } - - template<typename _Tp, typename _Up> - constexpr bool - cmp_less_equal(_Tp __t, _Up __u) noexcept - { return !std::cmp_less(__u, __t); } - - template<typename _Tp, typename _Up> - constexpr bool - cmp_greater_equal(_Tp __t, _Up __u) noexcept - { return !std::cmp_less(__t, __u); } - - template<typename _Res, typename _Tp> - constexpr bool - in_range(_Tp __t) noexcept - { - static_assert(__is_standard_integer<_Res>::value); - static_assert(__is_standard_integer<_Tp>::value); - using __gnu_cxx::__int_traits; - - if constexpr (is_signed_v<_Tp> == is_signed_v<_Res>) - return __int_traits<_Res>::__min <= __t - && __t <= __int_traits<_Res>::__max; - else if constexpr (is_signed_v<_Tp>) - return __t >= 0 - && make_unsigned_t<_Tp>(__t) <= __int_traits<_Res>::__max; - else - return __t <= make_unsigned_t<_Res>(__int_traits<_Res>::__max); - } -#endif // __cpp_lib_integer_comparison_functions - #ifdef __cpp_lib_to_underlying // C++ >= 23 /// Convert an object of enumeration type to its underlying type. template<typename _Tp> diff --git a/libstdc++-v3/include/std/variant b/libstdc++-v3/include/std/variant index 2f44f97..f2f5583 100644 --- a/libstdc++-v3/include/std/variant +++ b/libstdc++-v3/include/std/variant @@ -393,8 +393,29 @@ namespace __variant _Variadic_union(in_place_index_t<_Np>, _Args&&...) = delete; }; - template<bool __trivially_destructible, typename _First, typename... _Rest> - union _Variadic_union<__trivially_destructible, _First, _Rest...> + template<typename _First, typename... _Rest> + union _Variadic_union<true, _First, _Rest...> + { + constexpr _Variadic_union() : _M_rest() { } + + template<typename... _Args> + constexpr + _Variadic_union(in_place_index_t<0>, _Args&&... __args) + : _M_first(in_place_index<0>, std::forward<_Args>(__args)...) + { } + + template<size_t _Np, typename... _Args> + constexpr + _Variadic_union(in_place_index_t<_Np>, _Args&&... __args) + : _M_rest(in_place_index<_Np-1>, std::forward<_Args>(__args)...) + { } + + _Uninitialized<_First> _M_first; + _Variadic_union<true, _Rest...> _M_rest; + }; + + template<typename _First, typename... _Rest> + union _Variadic_union<false, _First, _Rest...> { constexpr _Variadic_union() : _M_rest() { } @@ -410,24 +431,19 @@ namespace __variant : _M_rest(in_place_index<_Np-1>, std::forward<_Args>(__args)...) { } -#if __cpp_lib_variant >= 202106L _Variadic_union(const _Variadic_union&) = default; _Variadic_union(_Variadic_union&&) = default; _Variadic_union& operator=(const _Variadic_union&) = default; _Variadic_union& operator=(_Variadic_union&&) = default; - ~_Variadic_union() = default; - // If any alternative type is not trivially destructible then we need a // user-provided destructor that does nothing. The active alternative // will be destroyed by _Variant_storage::_M_reset() instead of here. - constexpr ~_Variadic_union() - requires (!__trivially_destructible) + _GLIBCXX20_CONSTEXPR ~_Variadic_union() { } -#endif _Uninitialized<_First> _M_first; - _Variadic_union<__trivially_destructible, _Rest...> _M_rest; + _Variadic_union<(is_trivially_destructible_v<_Rest> && ...), _Rest...> _M_rest; }; // _Never_valueless_alt is true for variant alternatives that can diff --git a/libstdc++-v3/libsupc++/compare b/libstdc++-v3/libsupc++/compare index 08f2b2b..5b4f47a 100644 --- a/libstdc++-v3/libsupc++/compare +++ b/libstdc++-v3/libsupc++/compare @@ -34,6 +34,7 @@ #pragma GCC system_header #endif +#define __glibcxx_want_concepts #define __glibcxx_want_three_way_comparison #define __glibcxx_want_type_order #include <bits/version.h> @@ -499,10 +500,8 @@ namespace std _GLIBCXX_VISIBILITY(default) template<typename _Tp, typename _Up, typename _Cat = partial_ordering> concept three_way_comparable_with - = three_way_comparable<_Tp, _Cat> - && three_way_comparable<_Up, _Cat> - && common_reference_with<const remove_reference_t<_Tp>&, - const remove_reference_t<_Up>&> + = three_way_comparable<_Tp, _Cat> && three_way_comparable<_Up, _Cat> + && __detail::__comparison_common_type_with<_Tp, _Up> && three_way_comparable< common_reference_t<const remove_reference_t<_Tp>&, const remove_reference_t<_Up>&>, _Cat> diff --git a/libstdc++-v3/testsuite/20_util/integer_comparisons/extended.cc b/libstdc++-v3/testsuite/20_util/integer_comparisons/extended.cc new file mode 100644 index 0000000..d862b16 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/integer_comparisons/extended.cc @@ -0,0 +1,60 @@ +// { dg-do compile { target c++20 } } + +#include <utility> + +template<typename T> +constexpr bool +test() +{ + using S = std::make_signed_t<T>; + using U = std::make_unsigned_t<T>; + + static_assert( std::cmp_less((S)-1, (U)1)); + static_assert( ! std::cmp_less((S)20, (U)10)); + static_assert( ! std::cmp_less((U)20, (S)10)); + + static_assert( std::cmp_greater((S)100, (U)1) ); + static_assert( std::cmp_greater((U)100, (S)1) ); + static_assert( ! std::cmp_greater((S)-100, (U)1) ); + + static_assert( std::cmp_less_equal((S)-1, (U)1)); + static_assert( std::cmp_less_equal((U)10, (S)10)); + static_assert( ! std::cmp_less_equal((U)-100, (S)-100)); + + static_assert( std::cmp_greater_equal((S)200, (U)2) ); + static_assert( std::cmp_greater_equal((U)2000, (S)2000) ); + static_assert( ! std::cmp_greater_equal((S)-100, (U)100) ); + + static_assert( std::cmp_equal((S)1, (U)1) ); + static_assert( ! std::cmp_equal((S)-2, (U)-2) ); + + static_assert( std::cmp_not_equal((S)-1, (U)-1) ); + static_assert( ! std::cmp_not_equal((S)100, (U)100) ); + + static_assert( std::in_range<S>((U)5) ); + static_assert( std::in_range<U>((S)5) ); + static_assert( ! std::in_range<S>((U)-5) ); + static_assert( ! std::in_range<U>((S)-5) ); + + return true; +} + +#ifdef __SIZEOF_INT128__ +static_assert(test<__int128>()); +#endif + +#ifdef __GLIBCXX_TYPE_INT_N_0 +static_assert(test<__GLIBCXX_TYPE_INT_N_0>()); +#endif + +#ifdef __GLIBCXX_TYPE_INT_N_1 +static_assert(test<__GLIBCXX_TYPE_INT_N_1>()); +#endif + +#ifdef __GLIBCXX_TYPE_INT_N_2 +static_assert(test<__GLIBCXX_TYPE_INT_N_2>()); +#endif + +#ifdef __GLIBCXX_TYPE_INT_N_3 +static_assert(test<__GLIBCXX_TYPE_INT_N_3>()); +#endif diff --git a/libstdc++-v3/testsuite/20_util/variant/112591.cc b/libstdc++-v3/testsuite/20_util/variant/112591.cc new file mode 100644 index 0000000..b1b07c4 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/variant/112591.cc @@ -0,0 +1,32 @@ +// { dg-do run { target c++17 } } + +#include <variant> +#include <testsuite_hooks.h> + +struct NonEmpty { int x; }; +struct TrivialEmpty {}; +struct NonTrivialEmpty { ~NonTrivialEmpty() {} }; + +template<typename T> +struct Compose : T +{ + std::variant<T, int> v; +}; + +template<typename T> +bool testAlias() +{ + Compose<T> c; + return static_cast<T*>(&c) == &std::get<T>(c.v); +} + +int main() +{ + VERIFY( !testAlias<NonEmpty>() ); + VERIFY( !testAlias<TrivialEmpty>() ); +#if __cplusplus >= 202002L + VERIFY( !testAlias<NonTrivialEmpty>() ); +#else + VERIFY( testAlias<NonTrivialEmpty>() ); +#endif +} diff --git a/libstdc++-v3/testsuite/20_util/variant/87619.cc b/libstdc++-v3/testsuite/20_util/variant/87619.cc index d988925..ac7dd46 100644 --- a/libstdc++-v3/testsuite/20_util/variant/87619.cc +++ b/libstdc++-v3/testsuite/20_util/variant/87619.cc @@ -16,6 +16,7 @@ // <http://www.gnu.org/licenses/>. // { dg-do compile { target c++17 } } +// { dg-options "-ftemplate-depth=270" } #include <variant> #include <utility> @@ -23,6 +24,7 @@ template<std::size_t I> struct S { + ~S() {} }; template <std::size_t... Is> diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_ints.cc b/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_ints.cc index d5f07c1..fdbcb70 100644 --- a/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_ints.cc +++ b/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_ints.cc @@ -16,6 +16,13 @@ static_assert(!std::is_constructible_v<std::extents<int, 1, dyn, 3>, int, int>); // Not constructible from non integer-like objects. static_assert(!std::is_constructible_v<std::extents<int, 1>, int, A>); +#ifdef __SIZEOF_INT128__ +static_assert(std::is_constructible_v<std::extents<__int128, 1, 2>, + __int128, unsigned __int128>); +static_assert(std::is_constructible_v<std::extents<unsigned __int128, 1, 2>, + unsigned int, int>); +#endif + // No implicit conversion from integer-like objects. template<typename Extent, typename... OExtents> constexpr bool diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/strided_slice.cc b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/strided_slice.cc index c43a821..6fa5aaa 100644 --- a/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/strided_slice.cc +++ b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/strided_slice.cc @@ -34,6 +34,9 @@ test_all() test_initializers(0, 1, 2); test_initializers(std::integral_constant<short, 0>{}, size_t{1}, std::cw<2>); test_initializers(-1, 2, 2); +#ifdef __SIZEOF_INT128__ + test_initializers((__int128)1, (unsigned __int128)-2, std::cw<(__int128)3>); +#endif return true; } diff --git a/libstdc++-v3/testsuite/26_numerics/saturation/extended.cc b/libstdc++-v3/testsuite/26_numerics/saturation/extended.cc new file mode 100644 index 0000000..fbef628 --- /dev/null +++ b/libstdc++-v3/testsuite/26_numerics/saturation/extended.cc @@ -0,0 +1,55 @@ +// { dg-do compile { target c++26 } } + +#include <numeric> +#include <limits> + +template<typename T> +constexpr bool +test() +{ + using S = std::make_signed_t<T>; + using U = std::make_unsigned_t<T>; + + constexpr S smax = std::numeric_limits<S>::max(); + constexpr S smin = std::numeric_limits<S>::min(); + constexpr U umax = std::numeric_limits<U>::max(); + + static_assert( std::add_sat(smax, (S)1) == smax ); + static_assert( std::add_sat(smin, (S)-2) == smin ); + static_assert( std::add_sat(umax, (U)3) == umax ); + + static_assert( std::sub_sat(smax, (S)-1) == smax ); + static_assert( std::sub_sat(smin, (S)2) == smin ); + static_assert( std::sub_sat((U)0, (U)3) == (U)0 ); + + static_assert( std::mul_sat((S)(smax >> 1), (S)3) == smax ); + static_assert( std::mul_sat((S)(smin >> 1), (S)5) == smin ); + static_assert( std::mul_sat((U)(umax >> 1), (U)7) == umax ); + + static_assert( std::div_sat(smax, (S)2) == (smax >> 1) ); + static_assert( std::div_sat(smin, (S)4) == (smin >> 2) ); + static_assert( std::div_sat(smin, (S)-1) == smax ); + static_assert( std::div_sat(umax, (U)8) == (umax >> 3) ); + + return true; +} + +#ifdef __SIZEOF_INT128__ +static_assert(test<__int128>()); +#endif + +#ifdef __GLIBCXX_TYPE_INT_N_0 +static_assert(test<__GLIBCXX_TYPE_INT_N_0>()); +#endif + +#ifdef __GLIBCXX_TYPE_INT_N_1 +static_assert(test<__GLIBCXX_TYPE_INT_N_1>()); +#endif + +#ifdef __GLIBCXX_TYPE_INT_N_2 +static_assert(test<__GLIBCXX_TYPE_INT_N_2>()); +#endif + +#ifdef __GLIBCXX_TYPE_INT_N_3 +static_assert(test<__GLIBCXX_TYPE_INT_N_3>()); +#endif diff --git a/libstdc++-v3/testsuite/26_numerics/stdckdint/extended.cc b/libstdc++-v3/testsuite/26_numerics/stdckdint/extended.cc new file mode 100644 index 0000000..efc0792 --- /dev/null +++ b/libstdc++-v3/testsuite/26_numerics/stdckdint/extended.cc @@ -0,0 +1,65 @@ +// { dg-do run { target c++26 } } + +#include <stdckdint.h> +#include <limits> +#include <testsuite_hooks.h> + +template<typename T> +void +test() +{ + using S = std::make_signed_t<T>; + using U = std::make_unsigned_t<T>; + + constexpr S smax = std::numeric_limits<S>::max(); + constexpr S smin = std::numeric_limits<S>::min(); + constexpr U umax = std::numeric_limits<U>::max(); + S sout{}; + U uout{}; + + VERIFY( ckd_add(&sout, smax, (S)1) ); + VERIFY( ! ckd_add(&uout, smax, (U)1) && uout == ((U)smax + (U)1) ); + VERIFY( ! ckd_add(&sout, smin, (S)99) && sout == (smin + 99) ); + VERIFY( ckd_add(&uout, smin, (S)99) ); + VERIFY( ckd_add(&sout, smin, (S)-2) ); + VERIFY( ckd_add(&uout, umax, (U)3) ); + VERIFY( ! ckd_add(&sout, (U)9, (U)3) && sout == 12 ); + + VERIFY( ckd_sub(&sout, smax, (S)-1) ); + VERIFY( ! ckd_sub(&uout, smax, (S)-1) && uout == ((U)smax + (U)1) ); + VERIFY( ckd_sub(&sout, smin, (S)2) ); + VERIFY( ! ckd_sub(&sout, smin, (S)-2) && sout == (smin + 2) ); + VERIFY( ! ckd_sub(&sout, (U)0, (U)3) && sout == -3 ); + VERIFY( ckd_sub(&uout, (U)0, (U)3) ); + + VERIFY( ! ckd_mul(&sout, (S)(smax >> 2), (S)3) && sout == (smax/4*3) ); + VERIFY( ckd_mul(&sout, (S)(smax >> 1), (S)3) ); + VERIFY( ! ckd_mul(&uout, (S)(smax >> 1), (S)3) ); + VERIFY( ckd_mul(&sout, (S)(smin >> 1), (S)5) ); + VERIFY( ! ckd_mul(&uout, (U)(umax >> 2), (U)3) ); + VERIFY( ckd_mul(&sout, (U)(umax >> 2), (U)3) ); + VERIFY( ckd_mul(&uout, (U)(umax >> 1), (U)7) ); +} + +int main() +{ +#ifdef __SIZEOF_INT128__ + test<__int128>(); +#endif + +#ifdef __GLIBCXX_TYPE_INT_N_0 + test<__GLIBCXX_TYPE_INT_N_0>(); +#endif + +#ifdef __GLIBCXX_TYPE_INT_N_1 + test<__GLIBCXX_TYPE_INT_N_1>(); +#endif + +#ifdef __GLIBCXX_TYPE_INT_N_2 + test<__GLIBCXX_TYPE_INT_N_2>(); +#endif + +#ifdef __GLIBCXX_TYPE_INT_N_3 + test<__GLIBCXX_TYPE_INT_N_3>(); +#endif +} diff --git a/libstdc++-v3/testsuite/std/concepts/concepts.compare/move_only.cc b/libstdc++-v3/testsuite/std/concepts/concepts.compare/move_only.cc new file mode 100644 index 0000000..01870d8 --- /dev/null +++ b/libstdc++-v3/testsuite/std/concepts/concepts.compare/move_only.cc @@ -0,0 +1,28 @@ +// { dg-do compile { target c++20 } } + +#include <concepts> +#include <compare> + +// P2404R3 Move-only types for equality_comparable_with, +// totally_ordered_with, and three_way_comparable_with + +// This was approved for C++23 but we treat it as a DR for C++20. + +#ifndef __cpp_lib_concepts +# error "Feature-test macro __cpp_lib_concepts is missing in <compare>" +#elif __cpp_lib_concepts < 202207L +# error "Feature-test macro __cpp_lib_concepts has wrong value in <compare>" +#endif + +struct MoveOnly +{ + MoveOnly(int); + MoveOnly(MoveOnly&&) = default; + auto operator<=>(const MoveOnly&) const = default; + std::strong_ordering operator<=>(int) const; + bool operator==(const MoveOnly&) const; +}; + +static_assert(std::equality_comparable_with<MoveOnly, int>); +static_assert(std::totally_ordered_with<MoveOnly, int>); +static_assert(std::three_way_comparable_with<MoveOnly, int>); |
