diff options
784 files changed, 20060 insertions, 8152 deletions
@@ -1,3 +1,7 @@ +2025-07-07 Tamar Christina <tamar.christina@arm.com> + + * MAINTAINERS: Add myself to AArch64 pot. + 2025-07-04 Andrew Pinski <quic_apinski@quicinc.com> * MAINTAINERS: Replace tabs with spaces. diff --git a/MAINTAINERS b/MAINTAINERS index f2ad650..2cd2ec6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -57,6 +57,7 @@ docs, and the testsuite related to that. aarch64 ldp/stp Alex Coplan <alex.coplan@arm.com> aarch64 port Richard Earnshaw <richard.earnshaw@arm.com> aarch64 port Richard Sandiford <richard.sandiford@arm.com> +aarch64 port Tamar Christina <tamar.christina@arm.com> aarch64 port Kyrylo Tkachov <ktkachov@nvidia.com> alpha port Richard Henderson <rth@gcc.gnu.org> amdgcn port Julian Brown <julian@codesourcery.com> diff --git a/contrib/ChangeLog b/contrib/ChangeLog index ce9dfec..a4f8bb3 100644 --- a/contrib/ChangeLog +++ b/contrib/ChangeLog @@ -1,3 +1,22 @@ +2025-07-08 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * prepare-commit-msg: Force default git prefixes. + +2025-07-07 Martin Jambor <mjambor@suse.cz> + + * filter-clang-warnings.py (skip_warning): Also ignore + -Woverloaded-shift-op-parentheses, -Wunused-function, + -Wunneeded-internal-declaration, -Wvla-cxx-extension', and + -Wunused-command-line-argument everywhere and a warning about + m_logical_loc_mgr in diagnostic-path-output.cc. Adjust gimple-match + and generic-match "filenames." Ignore -Wnontrivial-memcall warnings + in wide-int.h, all warnings about unused stuff in files under + m2/gm2-compiler-boot, all -Wunused-private-field in rust FE, in + analyzer/ana-state-to-diagnostic-state.h and c-family/c-format.cc, all + Warnings in avr-mmcu.texi, install.texi and libgccjit.texi and all + -Wc23-extensions warnings in libiberty/sha1.c. Ignore + -Wunused-parameter in analyzer/sm.cc. Reorder entries. + 2025-06-29 Filip Kastl <fkastl@suse.cz> * mklog.py: In 'main()', specify variable 'root' as global. diff --git a/contrib/filter-clang-warnings.py b/contrib/filter-clang-warnings.py index 2ea7c71..b1b881e 100755 --- a/contrib/filter-clang-warnings.py +++ b/contrib/filter-clang-warnings.py @@ -41,22 +41,43 @@ def skip_warning(filename, message): '-Wignored-attributes', '-Wgnu-zero-variadic-macro-arguments', '-Wformat-security', '-Wundefined-internal', '-Wunknown-warning-option', '-Wc++20-extensions', - '-Wbitwise-instead-of-logical', 'egrep is obsolescent'], + '-Wbitwise-instead-of-logical', 'egrep is obsolescent', + '-Woverloaded-shift-op-parentheses', + '-Wunused-function', '-Wunneeded-internal-declaration', + '-Wvla-cxx-extension', '-Wunused-command-line-argument'], + + 'diagnostic-path-output.cc': ['m_logical_loc_mgr'], + 'fold-const-call.cc': ['-Wreturn-type'], + 'gimple-match': ['-Wunused-', '-Wtautological-compare'], + 'generic-match': ['-Wunused-', '-Wtautological-compare'], + 'genautomata.cc': ['-Wstring-plus-int'], + # Perhaps revisit when ATTR_FNSPEC_DECONST_WATERMARK ifdef case is + # made default or removed: + 'ipa-strub.cc': ['-Wunused-but-set-variable'], 'insn-modes.cc': ['-Wshift-count-overflow'], 'insn-emit.cc': ['-Wtautological-compare'], 'insn-attrtab.cc': ['-Wparentheses-equality'], - 'gimple-match.cc': ['-Wunused-', '-Wtautological-compare'], - 'generic-match.cc': ['-Wunused-', '-Wtautological-compare'], + 'omp-builtins.def': ['-Wc++11-narrowing'], + 'wide-int.h': ['-Wnontrivial-memcall'], 'i386.md': ['-Wparentheses-equality', '-Wtautological-compare', '-Wtautological-overlap-compare'], 'sse.md': ['-Wparentheses-equality', '-Wtautological-compare', '-Wconstant-logical-operand'], 'mmx.md': ['-Wtautological-compare'], - 'genautomata.cc': ['-Wstring-plus-int'], - 'fold-const-call.cc': ['-Wreturn-type'], - 'gfortran.texi': [''], - 'libtool': [''], 'lex.cc': ['-Wc++20-attribute-extensions'], + # Perhaps remove once PR 120960 is resolved: + 'analyzer/ana-state-to-diagnostic-state.h': ['-Wunused-private-field'], + 'analyzer/sm.cc': ['-Wunused-parameter'], + 'c-family/c-format.cc': ['-Wunused-private-field'], + 'm2/gm2-compiler-boot': ['-Wunused-'], + # Rust peopel promised to clean these warnings too + 'rust/': ['-Wunused-private-field'], + 'libiberty/sha1.c': ['-Wc23-extensions'], + 'avr-mmcu.texi': [''], + 'gfortran.texi': [''], + 'install.texi': [''], + 'libgccjit.texi': [''], + 'libtool': [''] } for name, ignore in ignores.items(): diff --git a/contrib/prepare-commit-msg b/contrib/prepare-commit-msg index 1b87877..75d1025 100755 --- a/contrib/prepare-commit-msg +++ b/contrib/prepare-commit-msg @@ -78,4 +78,4 @@ else tee="cat" fi -git $cmd | $tee | git gcc-mklog -c "$COMMIT_MSG_FILE" +git $cmd --default-prefix | $tee | git gcc-mklog -c "$COMMIT_MSG_FILE" diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 319b756..0ac20fd 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,402 @@ +2025-07-09 Richard Sandiford <richard.sandiford@arm.com> + + * config/aarch64/aarch64.cc (aarch64_simd_valid_imm): Account + for FLOAT_WORDS_BIG_ENDIAN when building a floating-point value. + +2025-07-09 Jan Hubicka <hubicka@ucw.cz> + + * auto-profile.cc (afdo_adjust_guessed_profile): Add forgotten + if (dump_file) guard. + +2025-07-09 Richard Sandiford <richard.sandiford@arm.com> + + * config/aarch64/aarch64.cc (aarch64_sve_index_series_p): New + function, split out from... + (aarch64_simd_valid_imm): ...here. Account for the different + SVE and Advanced SIMD element orders on big-endian targets. + Check each vector in a structure mode. + +2025-07-09 Richard Sandiford <richard.sandiford@arm.com> + + * read-rtl-function.cc (function_reader::read_rtx_operand_r): Use + hard_regno_nregs to work out REG_NREGS for hard registers. + +2025-07-09 Pan Li <pan2.li@intel.com> + + * config/riscv/riscv-v.cc (expand_vx_binary_vec_vec_dup): Add + new case SS_MINUS. + * config/riscv/riscv.cc (riscv_rtx_costs): Ditto. + * config/riscv/vector-iterators.md: Add new op ss_minus. + +2025-07-09 Richard Sandiford <richard.sandiford@arm.com> + + * ext-dce.cc (ext_dce_process_uses): Apply is_constant directly + to the subreg_lsb. + +2025-07-09 Jan Dubiec <jdx@o2.pl> + + PR target/109286 + * config.gcc: Include elfos.h before h8300/h8300.h. + * config/h8300/h8300.h (INIT_SECTION_ASM_OP): Override + default version from elfos.h. + (FINI_SECTION_ASM_OP): Ditto. + (ASM_DECLARE_FUNCTION_NAME): Ditto. + (ASM_GENERATE_INTERNAL_LABEL): Macro removed because it was + being overridden in elfos.h anyway. + (ASM_OUTPUT_SKIP): Ditto. + +2025-07-09 Icen Zeyada <Icen.Zeyada2@arm.com> + + PR tree-optimization/119196 + * match.pd: Allow scalar optimizations with bitwise AND/OR/XOR to apply to vectors. + +2025-07-09 Icen Zeyada <Icen.Zeyada2@arm.com> + + PR tree-optimization/119196 + * match.pd: Merge multiple vec_cond_expr in a single one for + bit_and, bit_ior and bit_xor. + +2025-07-09 Jeff Law <jlaw@ventanamicro.com> + + PR target/120642 + * config/riscv/riscv-avlprop.cc (pass_avlprop::execute): Do not do + constant AVL propagation for xtheadvector. + +2025-07-09 Richard Biener <rguenther@suse.de> + + * tree-vect-loop.cc (vectorizable_reduction): Get the + output vector type from slp_for_stmt_info. + * tree-vect-stmts.cc (vect_analyze_stmt): Bail out earlier + for PURE_SLP_STMT when doing loop stmt analysis. + +2025-07-09 Jan Hubicka <hubicka@ucw.cz> + + * auto-profile.cc (struct scale): New structure. + (add_scale): Also record weights. + (afdo_adjust_guessed_profile): Compute robust average + of scales and cap by max count in function. + +2025-07-09 Jan Hubicka <hubicka@ucw.cz> + + * tree-inline.cc (initialize_cfun): Use num and den for scaling. + +2025-07-09 Jan Hubicka <hubicka@ucw.cz> + + * auto-profile.cc (get_original_name): Fix loop walking the + suffixes. + +2025-07-09 Christophe Lyon <christophe.lyon@linaro.org> + + * config/arm/arm_neon.h: Remove useless push/pop pragmas. + +2025-07-09 Tamar Christina <tamar.christina@arm.com> + + PR tree-optimization/120922 + * tree-vect-loop-manip.cc (vect_gen_vector_loop_niters): Support range + for partial vectors. + +2025-07-09 Tamar Christina <tamar.christina@arm.com> + + PR tree-optimization/120922 + * tree-vect-loop-manip.cc (vect_gen_vector_loop_niters): Don't set range + for partial vectors. + +2025-07-08 Takayuki 'January June' Suwa <jjsuwa_sys3175@yahoo.co.jp> + + * config/xtensa/xtensa.cc (xtensa_b4const_or_zero): + Remove. + (xtensa_b4const): Add a case where the value is 0, and rename + to xtensa_b4const_or_zero. + (xtensa_rtx_costs): Fix to also consider the result of + xtensa_b4constu(). + +2025-07-08 Stefan Schulze Frielinghaus <stefansf@gcc.gnu.org> + + * config/s390/s390.md (stack_protect_get_tpsi): New insn. + (stack_protect_get_tpdi): New insn. + (stack_protect_set): Use new insn. + (stack_protect_test): Use new insn. + +2025-07-08 Robin Dapp <rdapp@ventanamicro.com> + + PR target/120461 + * config/riscv/riscv-v.cc (emit_vlmax_insn_lra): Do not emit + vsetivli for XTHeadVector. + +2025-07-08 Robin Dapp <rdapp@ventanamicro.com> + + PR target/113829 + * config/riscv/riscv-vector-builtins.cc (registered_function::overloaded_hash): + Skip non-type arguments. + +2025-07-08 Andreas Schwab <schwab@suse.de> + + PR target/120995 + * config/riscv/sync.md (zacas_atomic_cas_value_strong<mode>): + Allow op3 to be zero. + +2025-07-08 Richard Biener <rguenther@suse.de> + + * config/i386/x86-tune.def (X86_TUNE_AVX512_MASKED_EPILOGUES): + New tunable, default on for m_ZNVER4 and m_ZNVER5. + * config/i386/i386.cc (ix86_vector_costs::finish_cost): With + X86_TUNE_AVX512_MASKED_EPILOGUES and when the main loop + had a vectorization factor > 2 use a masked epilogue when + possible and when not obviously problematic. + +2025-07-08 Richard Biener <rguenther@suse.de> + + * tree-vectorizer.h (vector_costs::suggested_epilogue_mode): + Add masked output parameter and return m_masked_epilogue. + (vector_costs::m_masked_epilogue): New tristate flag. + (vector_costs::vector_costs): Initialize m_masked_epilogue. + * tree-vect-loop.cc (vect_analyze_loop_1): Pass in masked + flag to optionally initialize can_use_partial_vectors_p. + (vect_analyze_loop): For epilogues also get whether to use + a masked epilogue for this loop from the target and use + that for the first epilogue mode we try. + +2025-07-08 Richard Biener <rguenther@suse.de> + + PR tree-optimization/120358 + * tree-ssa-structalias.cc (get_constraint_for_1): Adjust + pruning of sub-variables according to the imprecise + known start offset. + +2025-07-08 Alexandre Oliva <oliva@adacore.com> + + * config/vxworks-dummy.h (TARGET_VXWORKS_VAROFF): New. + (TARGET_VXWORKS_GOTTPIC): New. + * config/vxworks.h (TARGET_VXWORKS_VAROFF): Override. + (TARGET_VXWORKS_GOTTPIC): Likewise. + * config/i386/i386.cc (output_set_got): Disable VxWorks6 GOT + sequence on VxWorks7. + (legitimize_pic_address): Accept relative addressing of + labels on VxWorks7. + (ix86_delegitimize_address_1): Likewise. + (ix86_output_addr_diff_elt): Likewise. + * config/i386/i386.md (tablejump): Likewise. + (set_got, set_got_labelled): Set no-red-zone flag on VxWorks7. + * config/i386/predicates.md (gotoff_operand): Test + TARGET_VXWORKS_VAROFF. + +2025-07-08 Alexandre Oliva <oliva@adacore.com> + + * config.gcc (vxworks-dummy.h): Add to aarch64-*-* as well. + +2025-07-07 Qing Zhao <qing.zhao@oracle.com> + + Revert: + 2025-07-07 Qing Zhao <qing.zhao@oracle.com> + + * doc/extend.texi: Extend counted_by attribute to pointer fields in + structures. Add one more requirement to pointers with counted_by + attribute. + +2025-07-07 Qing Zhao <qing.zhao@oracle.com> + + Revert: + 2025-07-01 Qing Zhao <qing.zhao@oracle.com> + + * tree-object-size.cc (access_with_size_object_size): Update comments + for pointers with .ACCESS_WITH_SIZE. + (collect_object_sizes_for): Propagate size info through GIMPLE_ASSIGN + for pointers with .ACCESS_WITH_SIZE. + +2025-07-07 Martin Jambor <mjambor@suse.cz> + + * value-range.h (class irange): Mark member function verify_range + with override. + (class prange): Mark member function verify_range with final override. + (class frange): Mark member function verify_range with override. + +2025-07-07 H.J. Lu <hjl.tools@gmail.com> + + PR target/120888 + * config/xtensa/xtensa.cc (xtensa_promote_function_mode): New. + (TARGET_PROMOTE_FUNCTION_MODE): Use. + (TARGET_PROMOTE_PROTOTYPES): Removed. + +2025-07-07 Juergen Christ <jchrist@linux.ibm.com> + + * config/s390/s390.md: Update UNSPECs + * config/s390/vector.md (fmax<mode>3): New expander. + (fmin<mode>3): New expander. + * config/s390/vx-builtins.md (*fmin<mode>): New insn. + (vfmin<mode>): Redefined to use new insn. + (*fmax<mode>): New insn. + (vfmax<mode>): Redefined to use new insn. + +2025-07-07 Jason Merrill <jason@redhat.com> + + PR c++/120917 + * doc/invoke.texi: Add -Wno-abbreviated-auto-in-template-arg. + +2025-07-07 Kyrylo Tkachov <ktkachov@nvidia.com> + + * config/aarch64/aarch64.md (popcountti2): Add TARGET_SVE path. + +2025-07-07 Richard Biener <rguenther@suse.de> + + PR tree-optimization/120817 + * tree-ssa-dse.cc (initialize_ao_ref_for_dse): Use + ao_ref_init_from_ptr_and_range with unknown size for + .MASK_STORE and .MASK_LEN_STORE. + +2025-07-07 Pan Li <pan2.li@intel.com> + + * config/riscv/riscv-protos.h (riscv_expand_usmul): Add new func + decl. + * config/riscv/riscv.cc (riscv_expand_xmode_usmul): Add new func + to expand Xmode SAT_MUL. + (riscv_expand_non_xmode_usmul): Ditto but for non-Xmode. + (riscv_expand_usmul): Add new func to implment SAT_MUL. + * config/riscv/riscv.md (usmul<mode>3): Add new pattern to match + standard name usmul. + +2025-07-07 Pan Li <pan2.li@intel.com> + + * match.pd: Add new match pattern for unsigned SAT_MUL. + * tree-ssa-math-opts.cc (gimple_unsigned_integer_sat_mul): + new decl for pattern match func. + (match_unsigned_saturation_mul): Add new func to match unsigned + SAT_MUL. + (math_opts_dom_walker::after_dom_children): Try to match + unsigned SAT_MUL on NOP. + +2025-07-07 Pan Li <pan2.li@intel.com> + + * internal-fn.cc (commutative_binary_fn_p): Add new case + for SAT_MUL. + * internal-fn.def (SAT_MUL): Add new IFN_SAT_MUL. + * optabs.def (OPTAB_NL): Remove fixed point limitation. + +2025-07-07 Juergen Christ <jchrist@linux.ibm.com> + + * config/s390/s390.md: Removed unused unspecs. + * config/s390/vector.md (avg<mode>3_ceil): New expander. + (uavg<mode>3_ceil): New expander. + (smul<mode>3_highpart): New expander. + (umul<mode>3_highpart): New expander. + * config/s390/vx-builtins.md (vec_umulh<mode>): Remove unspec. + (vec_smulh<mode>): Remove unspec. + +2025-07-07 Spencer Abson <spencer.abson@arm.com> + + * config/aarch64/aarch64-sve.md (vec_cmp<mode><vpred>): Extend + to handle partial FP modes. + (@aarch64_pred_fcm<cmp_op><mode>): Likewise. + (@aarch64_pred_fcmuo<mode>): Likewise. + (*one_cmpl<mode>3): Rename to... + (@aarch64_pred_one_cmpl<mode>_z): ... this. + * config/aarch64/aarch64.cc (aarch64_emit_sve_fp_cond): Allow the + target and governing predicates to have different modes. + (aarch64_emit_sve_or_fp_conds): Likewise. + (aarch64_emit_sve_invert_fp_cond): Likewise. + (aarch64_expand_sve_vec_cmp_float): Likewise. + +2025-07-07 Richard Sandiford <richard.sandiford@arm.com> + + PR tree-optimization/118891 + * tree-vect-stmts.cc (supportable_widening_operation): Swap the + hi and lo internal functions on big-endian targets. + +2025-07-07 Richard Sandiford <richard.sandiford@arm.com> + + * ext-dce.cc (ext_dce_process_uses): Apply is_constant directly + to the subreg_lsb. + +2025-07-07 Richard Sandiford <richard.sandiford@arm.com> + + * config/aarch64/aarch64-sve.md (@aarch64_sve_set_neonq_<mode>): + Use %Z instead of lowpart_subreg. Tweak formatting. + +2025-07-07 Richard Sandiford <richard.sandiford@arm.com> + + PR target/118891 + * config/aarch64/aarch64.cc (aarch64_expand_vector_init): Fix the + ZIP1 operand order for big-endian targets. + +2025-07-07 Jan Hubicka <hubicka@ucw.cz> + + * tree-ssa-live.cc (dump_scope_block): Print discriminators + of inlined functions. + +2025-07-07 H.J. Lu <hjl.tools@gmail.com> + + PR target/120670 + PR target/120683 + * config/i386/i386-expand.cc (expand_set_or_cpymem_via_loop): + Don't generate the loop if the loop count is 1. + (expand_cpymem_epilogue): Use move_by_pieces. + (setmem_epilogue_gen_val): New. + (expand_setmem_epilogue): Use store_by_pieces. + (expand_small_cpymem_or_setmem): Choose cpymem mode from MOVE_MAX. + For memset with vector and the size is smaller than the vector + size, first try the narrower vector, otherwise, use the scalar + value. + (promote_duplicated_reg): Duplicate the scalar value for vector. + (ix86_expand_set_or_cpymem): Always expand vector-version of + memset for vector_loop. Use misaligned prologue if alignment + isn't needed and destination isn't aligned. Always initialize + vec_promoted_val from the promoted scalar value for vector_loop. + +2025-07-07 Andrew Pinski <quic_apinski@quicinc.com> + + PR middle-end/120709 + * builtins.cc (expand_builtin_crc_table_based): Error out + instead of asserting the 3rd argument is an integer constant. + * internal-fn.cc (expand_crc_optab_fn): Likewise. + * doc/extend.texi (crc): Document requirement of the poly argument + being a constant. + +2025-07-06 Georg-Johann Lay <avr@gjlay.de> + + * config/avr/avr-mcus.def: -mmcu= takes lower case MCU names. + * doc/avr-mmcu.texi: Rebuild. + +2025-07-06 Georg-Johann Lay <avr@gjlay.de> + + * config/avr/avr-mcus.def (avr32da28S, avr32da32S, avr32da48S) + (avr64da28S, avr64da32S, avr64da48S avr64da64S) + (avr128da28S, avr128da32S, avr128da48S, avr128da64S): Add devices. + * doc/avr-mmcu.texi: Rebuild. + +2025-07-06 Andrew Pinski <quic_apinski@quicinc.com> + + PR tree-optimization/120951 + * tree-call-cdce.cc (use_internal_fn): For non-call exceptions + with EQ_EXPR can throw for floating point types, then create + the EQ_EXPR seperately. + +2025-07-06 Andrew Pinski <quic_apinski@quicinc.com> + + PR middle-end/120921 + * tree-cfg.cc (verify_gimple_assign_single): Reject constant and address expression LHS. + For non-empty vector constructors, make sure the LHS is an is_gimple_reg. + +2025-07-06 Jan Hubicka <hubicka@ucw.cz> + + * auto-profile.cc + (autofdo_source_profile::read): Scale cutoff. + (read_autofdo_file): Initialize cutoff + * coverage.cc (read_counts_file): Initialize cutoff to 1. + * gcov-io.h (struct gcov_summary): Add cutoff field. + * ipa-inline.cc (inline_small_functions): mac_count can be non-zero + also with auto_profile. + * lto-cgraph.cc (output_profile_summary): Write cutoff + and sum_max. + (input_profile_summary): Read cutoff and sum max. + (merge_profile_summaries): Initialize and scale global cutoffs + and sum max. + * profile-count.cc: Include profile.h + (profile_count::force_nonzero): move here from ...; use cutoff. + * profile-count.h: (profile_count::force_nonzero): ... here. + +2025-07-06 Jan Hubicka <hubicka@ucw.cz> + + * profile-count.cc (profile_count::operator*): fix overflow check. + 2025-07-05 Alexandre Oliva <oliva@adacore.com> * config/rs6000/vxworks.h (SUBTARGET_DRIVER_SELF_SPECS): diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 0f0154f..12032ce 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20250706 +20250710 diff --git a/gcc/ada/libgnarl/s-taskin.ads b/gcc/ada/libgnarl/s-taskin.ads index d68e199..dbf2e7b 100644 --- a/gcc/ada/libgnarl/s-taskin.ads +++ b/gcc/ada/libgnarl/s-taskin.ads @@ -390,7 +390,7 @@ package System.Tasking is System_Domain : Dispatching_Domain_Access; -- All processors belong to default system dispatching domain at start up. -- We use a pointer which creates the actual variable for the reasons - -- explained bellow in Dispatching_Domain_Tasks. + -- explained below in Dispatching_Domain_Tasks. Dispatching_Domains_Frozen : Boolean := False; -- True when the main procedure has been called. Hence, no new dispatching diff --git a/gcc/ada/par-load.adb b/gcc/ada/par-load.adb index 96fa7e8..4a97f14 100644 --- a/gcc/ada/par-load.adb +++ b/gcc/ada/par-load.adb @@ -83,7 +83,7 @@ procedure Load is -- withed units and the second round handles Ada 2005 limited-withed units. -- This is required to allow the low-level circuitry that detects circular -- dependencies of units the correct notification of errors (see comment - -- bellow). This variable is used to indicate that the second round is + -- below). This variable is used to indicate that the second round is -- required. function Same_File_Name_Except_For_Case diff --git a/gcc/auto-profile.cc b/gcc/auto-profile.cc index a970eb8..5226e455 100644 --- a/gcc/auto-profile.cc +++ b/gcc/auto-profile.cc @@ -53,6 +53,7 @@ along with GCC; see the file COPYING3. If not see #include "auto-profile.h" #include "tree-pretty-print.h" #include "gimple-pretty-print.h" +#include "output.h" /* The following routines implements AutoFDO optimization. @@ -430,7 +431,8 @@ public: void set_call_location (location_t l) { - gcc_checking_assert (call_location_ == UNKNOWN_LOCATION); + gcc_checking_assert (call_location_ == UNKNOWN_LOCATION + && l != UNKNOWN_LOCATION); call_location_= l; } @@ -622,9 +624,11 @@ get_original_name (const char *name, bool alloc = true) } /* Suffixes of clones that compiler generates after auto-profile. */ const char *suffixes[] = {"isra", "constprop", "lto_priv", "part", "cold"}; - for (unsigned i = 0; i < sizeof (suffixes); ++i) + for (unsigned i = 0; i < sizeof (suffixes) / sizeof (const char *); ++i) { - if (strncmp (next_dot + 1, suffixes[i], strlen (suffixes[i])) == 0) + int len = strlen (suffixes[i]); + if (len == last_dot - next_dot - 1 + && strncmp (next_dot + 1, suffixes[i], strlen (suffixes[i])) == 0) { *next_dot = 0; return get_original_name (ret, false); @@ -683,6 +687,26 @@ dump_afdo_loc (FILE *f, unsigned loc) fprintf (f, "%i", loc >> 16); } +/* Return assembler name as in symbol table and DW_AT_linkage_name. */ + +static const char * +raw_symbol_name (const char *asmname) +{ + /* If we start supporting user_label_prefixes, add_linkage_attr will also + need to be fixed. */ + if (strlen (user_label_prefix)) + sorry ("auto-profile is not supported for targets with user label prefix"); + return asmname + (asmname[0] == '*'); +} + +/* Convenience wrapper that looks up assembler name. */ + +static const char * +raw_symbol_name (tree decl) +{ + return raw_symbol_name (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))); +} + /* Dump STACK to F. */ static void @@ -693,7 +717,7 @@ dump_inline_stack (FILE *f, inline_stack *stack) { fprintf (f, "%s%s:", first ? "" : "; ", - IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (p.decl))); + raw_symbol_name (p.decl)); dump_afdo_loc (f, p.afdo_loc); first = false; } @@ -815,7 +839,7 @@ string_table::get_index (const char *name) const int string_table::get_index_by_decl (tree decl) const { - const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); + const char *name = raw_symbol_name (decl); int ret = get_index (name); if (ret != -1) return ret; @@ -878,10 +902,9 @@ function_instance::~function_instance () cgraph_node * function_instance::get_cgraph_node () { - for (symtab_node *n = cgraph_node::get_for_asmname - (get_identifier - (afdo_string_table->get_name (name ()))); - n; n = n->next_sharing_asm_name) + const char *sname = afdo_string_table->get_name (name ()); + symtab_node *n = cgraph_node::get_for_asmname (get_identifier (sname)); + for (;n; n = n->next_sharing_asm_name) if (cgraph_node *cn = dyn_cast <cgraph_node *> (n)) if (cn->definition && cn->has_gimple_body_p ()) return cn; @@ -919,10 +942,10 @@ function_instance::get_function_instance_by_decl (unsigned lineno, dump_printf_loc (MSG_NOTE | MSG_PRIORITY_INTERNALS, dump_user_location_t::from_location_t (location), "auto-profile has mismatched function name %s" - " instaed of %s at loc %i:%i", + " insteed of %s at loc %i:%i", afdo_string_table->get_name (iter.first.second), - IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)), - lineno << 16, + raw_symbol_name (decl), + lineno >> 16, lineno & 65535); } @@ -1125,10 +1148,13 @@ function_instance::offline_if_in_set (name_index_set &seen, Return non-zero if it correspons and 2 if renaming was done. */ static int -match_with_target (gimple *stmt, function_instance *inlined_fn, cgraph_node *n) +match_with_target (cgraph_node *n, + gimple *stmt, + function_instance *inlined_fn, + cgraph_node *orig_callee) { - const char *symbol_name = IDENTIFIER_POINTER - (DECL_ASSEMBLER_NAME (n->decl)); + cgraph_node *callee = orig_callee->ultimate_alias_target (); + const char *symbol_name = raw_symbol_name (callee->decl); const char *name = afdo_string_table->get_name (inlined_fn->name ()); if (strcmp (name, symbol_name)) { @@ -1142,8 +1168,8 @@ match_with_target (gimple *stmt, function_instance *inlined_fn, cgraph_node *n) in_suffix = true; } /* Accept dwarf names and stripped suffixes. */ - if (!strcmp (lang_hooks.dwarf_name (n->decl, 0), - afdo_string_table->get_name (inlined_fn->name ())) + if (!strcmp (lang_hooks.dwarf_name (callee->decl, 0), + afdo_string_table->get_name (inlined_fn->name ())) || (!name[i] && symbol_name[i] == '.') || in_suffix) { @@ -1157,10 +1183,14 @@ match_with_target (gimple *stmt, function_instance *inlined_fn, cgraph_node *n) inlined_fn->set_name (index); return 2; } - warning_at (gimple_location (stmt), OPT_Wauto_profile, - "auto-profile contains inlined " - "function with symbol name %s instead of symbol name %s", - name, symbol_name); + /* Only warn about declarations. It is possible that the function is + declared as alias in other module and we inlined cross-module. */ + if (callee->definition + && warning (OPT_Wauto_profile, + "auto-profile of %q+F contains inlined " + "function with symbol name %s instead of symbol name %s", + n->decl, name, symbol_name)) + inform (gimple_location (stmt), "corresponding call"); return 0; } return 1; @@ -1203,13 +1233,14 @@ function_instance::lookup_count (location_t loc, inline_stack &stack, if (stack.length ()) { int c = pos_counts.count (stack[0].afdo_loc); - if (c > 1) - warning_at (loc, OPT_Wauto_profile, - "duplicated count information" - " in auto-profile of %q+F" - " with relative location %i discriminator %i", - node->decl, stack[0].afdo_loc >> 16, - stack[0].afdo_loc & 65535); + if (c > 1 + && warning (OPT_Wauto_profile, + "duplicated count information" + " in auto-profile of %q+F" + " with relative location %i discriminator %i", + node->decl, stack[0].afdo_loc >> 16, + stack[0].afdo_loc & 65535)) + inform (loc, "corresponding source location"); if (c) return &pos_counts[stack[0].afdo_loc]; } @@ -1271,6 +1302,7 @@ function_instance::match (cgraph_node *node, hash_set<const count_info *> counts; hash_set<const count_info *> targets; hash_set<const function_instance *> functions; + hash_set<const function_instance *> functions_to_offline; /* We try to fill in lost disciminator if there is unique call with given line number. This map is used to record them. */ @@ -1374,20 +1406,23 @@ function_instance::match (cgraph_node *node, inlined_fn_nodisc = iter.second; cnodis++; } - if (c > 1 || cnodis > 1) - warning_at (gimple_location (stmt), OPT_Wauto_profile, - "duplicated callsite in auto-profile of %q+F" - " with relative location %i, discriminator %i", - node->decl, stack[0].afdo_loc >> 16, - stack[0].afdo_loc & 65535); - if (inlined_fn && info && info->targets.size ()) - warning_at (gimple_location (stmt), OPT_Wauto_profile, - "both call targets and inline callsite" - " information is present in auto-profile" - " of function %q+F with relative location" - " %i, discriminator %i", - node->decl, stack[0].afdo_loc >> 16, - stack[0].afdo_loc & 65535); + if ((c > 1 || (!c && cnodis > 1)) + && warning (OPT_Wauto_profile, + "duplicated callsite in auto-profile of %q+F" + " with relative location %i," + " discriminator %i", + node->decl, stack[0].afdo_loc >> 16, + stack[0].afdo_loc & 65535)) + inform (gimple_location (stmt), "corresponding call"); + if (inlined_fn && info && info->targets.size () + && warning (OPT_Wauto_profile, + "both call targets and inline callsite" + " information is present in auto-profile" + " of function %q+F with relative location" + " %i, discriminator %i", + node->decl, stack[0].afdo_loc >> 16, + stack[0].afdo_loc & 65535)) + inform (gimple_location (stmt), "corresponding call"); tree callee = gimple_call_fndecl (stmt); cgraph_node *callee_node; unsigned int loc = stack[0].afdo_loc; @@ -1420,11 +1455,17 @@ function_instance::match (cgraph_node *node, if (lineno_to_call.get (stack[0].afdo_loc >> 16)->length () == 1) { - warning_at (gimple_location (stmt), OPT_Wauto_profile, - "auto-profile of %q+F seem to contain" - " lost discriminator %i for call at" - " relative location %i", - node->decl, loc & 65535, loc >> 16); + if (warning (OPT_Wauto_profile, + "auto-profile of %q+F seem to contain" + " lost discriminator %i for" + " call of %s at relative location %i", + node->decl, + loc & 65535, + afdo_string_table->get_name + (inlined_fn_nodisc->name ()), + loc >> 16)) + inform (gimple_location (stmt), + "corresponding call"); inlined_fn = inlined_fn_nodisc; if (dump_file) fprintf (dump_file, " Lost discriminator %i\n", @@ -1435,11 +1476,10 @@ function_instance::match (cgraph_node *node, } if (callee && (callee_node = cgraph_node::get (callee))) { - callee_node = callee_node->ultimate_alias_target (); if (inlined_fn) { int old_name = inlined_fn->name (); - int r = match_with_target (stmt, inlined_fn, + int r = match_with_target (node, stmt, inlined_fn, callee_node); if (r == 2) { @@ -1456,6 +1496,8 @@ function_instance::match (cgraph_node *node, } if (r) functions.add (inlined_fn); + else + functions_to_offline.add (inlined_fn); } if (info && info->targets.size () > 1) @@ -1473,19 +1515,24 @@ function_instance::match (cgraph_node *node, { if (inlined_fn && inlined_fn->get_call_location () - != UNKNOWN_LOCATION - && warning_at (gimple_location (stmt), - OPT_Wauto_profile, - "%q+F contains two calls of the same" - " relative location +%i," - " discrimnator %i," - " that leads to lost auto-profile", - node->decl, - loc << 16, - loc & 65535)) + != UNKNOWN_LOCATION) { - inform (inlined_fn->get_call_location (), - "location of the earlier call"); + if (warning (OPT_Wauto_profile, + "function contains two calls of the same" + " relative location +%i," + " discrimnator %i," + " that leads to lost auto-profile", + loc >> 16, + loc & 65535)) + { + inform (gimple_location (stmt), + "location of the first call"); + inform (inlined_fn->get_call_location (), + "location of the second call"); + } + if (dump_file) + fprintf (dump_file, + " Duplicated call location\n"); inlined_fn = NULL; } if (inlined_fn) @@ -1559,11 +1606,18 @@ function_instance::match (cgraph_node *node, (DECL_STRUCT_FUNCTION (node->decl)->function_end_locus, node->decl); unsigned int start_location = get_combined_location (DECL_STRUCT_FUNCTION (node->decl)->function_start_locus, node->decl); + /* When outputting code to builtins location we use line number 0. + craeate_gcov is stupid and hapilly computes offsets across files. + Silently ignore it. */ + unsigned int zero_location + = ((unsigned)(1-DECL_SOURCE_LINE (node->decl))) << 16; for (position_count_map::const_iterator iter = pos_counts.begin (); iter != pos_counts.end ();) if (!counts.contains (&iter->second)) { - if (iter->first != end_location && iter->first != start_location + if (iter->first != end_location + && iter->first != start_location + && (iter->first & 65535) != zero_location && iter->first) { if (!warned) @@ -1601,28 +1655,42 @@ function_instance::match (cgraph_node *node, iter != callsites.end ();) if (!functions.contains (iter->second)) { - if (!warned) - warned = warning_at (DECL_SOURCE_LOCATION (node->decl), - OPT_Wauto_profile, - "auto-profile of %q+F contains extra callsites", - node->decl); - if (warned) - inform (DECL_SOURCE_LOCATION (node->decl), - "call of %s with relative location +%i, discriminator %i", - afdo_string_table->get_name (iter->first.second), - iter->first.first >> 16, iter->first.first & 65535); - if ((iter->first.first >> 16) > (end_location >> 16) && warned) - inform (DECL_SOURCE_LOCATION (node->decl), - "location is after end of function"); - warned = true; function_instance *f = iter->second; - if (dump_file) + /* If we did not see the corresponding statement, warn. */ + if (!functions_to_offline.contains (iter->second)) + { + if (!warned) + warned = warning_at (DECL_SOURCE_LOCATION (node->decl), + OPT_Wauto_profile, + "auto-profile of %q+F contains" + " extra callsites", + node->decl); + if (warned) + inform (DECL_SOURCE_LOCATION (node->decl), + "call of %s with total count %" PRId64 + ", relative location +%i, discriminator %i", + afdo_string_table->get_name (iter->first.second), + iter->second->total_count (), + iter->first.first >> 16, iter->first.first & 65535); + if ((iter->first.first >> 16) > (end_location >> 16) && warned) + inform (DECL_SOURCE_LOCATION (node->decl), + "location is after end of function"); + if (dump_file) + { + fprintf (dump_file, + "Offlining inline with no corresponding gimple stmt "); + f->dump_inline_stack (dump_file); + fprintf (dump_file, "\n"); + } + } + else if (dump_file) { fprintf (dump_file, - "Offlining inline with no corresponding gimple stmt "); + "Offlining mismatched inline "); f->dump_inline_stack (dump_file); fprintf (dump_file, "\n"); } + warned = true; callsites.erase (iter); offline (f, new_functions); iter = callsites.begin (); @@ -1921,7 +1989,7 @@ autofdo_source_profile::offline_external_functions () FOR_EACH_DEFINED_FUNCTION (node) { const char *name - = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl)); + = raw_symbol_name (node->decl); const char *dwarf_name = lang_hooks.dwarf_name (node->decl, 0); int index = afdo_string_table->get_index (name); @@ -2103,8 +2171,7 @@ walk_block (tree fn, function_instance *s, tree block) fprintf (dump_file, ":"); dump_afdo_loc (dump_file, loc); fprintf (dump_file, " %s\n", - IDENTIFIER_POINTER - (DECL_ASSEMBLER_NAME (BLOCK_ABSTRACT_ORIGIN (block)))); + raw_symbol_name (BLOCK_ABSTRACT_ORIGIN (block))); } return; } @@ -2462,7 +2529,7 @@ autofdo_source_profile::get_callsite_total_count ( { if (dump_file) fprintf (dump_file, "Mismatched name of callee %s and profile %s\n", - IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (edge->callee->decl)), + raw_symbol_name (edge->callee->decl), afdo_string_table->get_name (s->name ())); return 0; } @@ -2556,8 +2623,7 @@ autofdo_source_profile::get_function_instance_by_inline_stack ( { if (dump_file) fprintf (dump_file, "No offline instance for %s\n", - IDENTIFIER_POINTER - (DECL_ASSEMBLER_NAME (stack[stack.length () - 1].decl))); + raw_symbol_name (stack[stack.length () - 1].decl)); return NULL; } function_instance *s = iter->second; @@ -2579,8 +2645,7 @@ autofdo_source_profile::get_function_instance_by_inline_stack ( "auto-profile has no inlined function instance " "for inlined call of %s at relative " " locaction +%i, discriminator %i\n", - IDENTIFIER_POINTER - (DECL_ASSEMBLER_NAME (stack[i - 1].decl)), + raw_symbol_name (stack[i - 1].decl), stack[i].afdo_loc >> 16, stack[i].afdo_loc & 65535); return NULL; @@ -3304,10 +3369,22 @@ cmp (const void *a, const void *b) return 0; } +/* To scalle a connected component of graph we collect desired scales of + basic blocks on the boundary and then compute a robust average. */ + +struct scale +{ + /* Scale descired. */ + sreal scale; + /* Weight for averaging computed from execution count of the edge + scale originates from. */ + uint64_t weight; +}; + /* Add scale ORIG/ANNOTATED to SCALES. */ static void -add_scale (vec <sreal> *scales, profile_count annotated, profile_count orig) +add_scale (vec <scale> *scales, profile_count annotated, profile_count orig) { if (dump_file) { @@ -3316,15 +3393,15 @@ add_scale (vec <sreal> *scales, profile_count annotated, profile_count orig) annotated.dump (dump_file); fprintf (dump_file, "\n"); } - if (orig.nonzero_p ()) + if (orig.force_nonzero () == orig) { sreal scale = annotated.guessed_local () .to_sreal_scale (orig); if (dump_file) - fprintf (dump_file, " adding scale %.16f\n", - scale.to_double ()); - scales->safe_push (scale); + fprintf (dump_file, " adding scale %.16f, weight %" PRId64 "\n", + scale.to_double (), annotated.value () + 1); + scales->safe_push ({scale, annotated.value () + 1}); } } @@ -3370,7 +3447,7 @@ afdo_adjust_guessed_profile (bb_set *annotated_bb) /* Basic blocks of connected component currently processed. */ auto_vec <basic_block, 20> bbs (n_basic_blocks_for_fn (cfun)); /* Scale factors found. */ - auto_vec <sreal, 20> scales; + auto_vec <scale, 20> scales; auto_vec <basic_block, 20> stack (n_basic_blocks_for_fn (cfun)); basic_block seed_bb; @@ -3382,9 +3459,15 @@ afdo_adjust_guessed_profile (bb_set *annotated_bb) >=2 is an id of the component BB belongs to. */ auto_vec <unsigned int, 20> component; component.safe_grow (last_basic_block_for_fn (cfun)); + profile_count max_count_in_fn = profile_count::zero (); FOR_ALL_BB_FN (seed_bb, cfun) - component[seed_bb->index] - = is_bb_annotated (seed_bb, *annotated_bb) ? 1 : 0; + if (is_bb_annotated (seed_bb, *annotated_bb)) + { + component[seed_bb->index] = 1; + max_count_in_fn = max_count_in_fn.max (seed_bb->count); + } + else + component[seed_bb->index] = 0; FOR_ALL_BB_FN (seed_bb, cfun) if (!component[seed_bb->index]) { @@ -3507,12 +3590,15 @@ afdo_adjust_guessed_profile (bb_set *annotated_bb) profile_count annotated_count = e->dest->count; profile_count out_count = profile_count::zero (); bool ok = true; + for (edge e2: e->dest->preds) if (AFDO_EINFO (e2)->is_annotated ()) annotated_count -= AFDO_EINFO (e2)->get_count (); - else if (component[e->src->index] == component_id) - out_count += e->count (); - else if (e->probability.nonzero_p ()) + else if (component[e2->src->index] == component_id) + out_count += e2->count (); + else if (is_bb_annotated (e2->src, *annotated_bb)) + annotated_count -= e2->count (); + else if (e2->probability.nonzero_p ()) { ok = false; break; @@ -3559,7 +3645,47 @@ afdo_adjust_guessed_profile (bb_set *annotated_bb) } gcc_checking_assert (scales.length ()); scales.qsort (cmp); - scale_bbs (bbs, scales[scales.length () / 2]); + + uint64_t overall_weight = 0; + for (scale &e : scales) + overall_weight += e.weight; + + uint64_t cummulated = 0, weight_sum = 0; + sreal scale_sum = 0; + for (scale &e : scales) + { + uint64_t prev = cummulated; + cummulated += e.weight; + if (cummulated >= overall_weight / 4 + && prev <= 3 * overall_weight / 4) + { + scale_sum += e.scale * e.weight; + weight_sum += e.weight; + if (dump_file) + fprintf (dump_file, " accounting scale %.16f, weight %" PRId64 "\n", + e.scale.to_double (), e.weight); + } + else if (dump_file) + fprintf (dump_file, " ignoring scale %.16f, weight %" PRId64 "\n", + e.scale.to_double (), e.weight); + } + sreal scale = scale_sum / (sreal)weight_sum; + + /* Avoid scaled regions to have very large counts. + Otherwise they may dominate ipa-profile's histogram computing cutoff + of hot basic blocks. */ + if (max_count * scale > max_count_in_fn.guessed_local ()) + { + if (dump_file) + { + fprintf (dump_file, "Scaling by %.16f produces max count ", + scale.to_double ()); + (max_count * scale).dump (dump_file); + fprintf (dump_file, " that exceeds max count in fn; capping\n"); + } + scale = max_count_in_fn.guessed_local ().to_sreal_scale (max_count); + } + scale_bbs (bbs, scale); } } diff --git a/gcc/builtins.cc b/gcc/builtins.cc index a2ce372..7f580a3 100644 --- a/gcc/builtins.cc +++ b/gcc/builtins.cc @@ -7799,11 +7799,17 @@ expand_builtin_crc_table_based (internal_fn fn, scalar_mode crc_mode, rtx op1 = expand_normal (rhs1); rtx op2 = expand_normal (rhs2); - gcc_assert (TREE_CODE (rhs3) == INTEGER_CST); - rtx op3 = gen_int_mode (TREE_INT_CST_LOW (rhs3), crc_mode); + rtx op3; + if (TREE_CODE (rhs3) != INTEGER_CST) + { + error ("third argument to %<crc%> builtins must be a constant"); + op3 = const0_rtx; + } + else + op3 = convert_to_mode (crc_mode, expand_normal (rhs3), 0); if (CONST_INT_P (op2)) - op2 = gen_int_mode (INTVAL (op2), crc_mode); + op2 = convert_to_mode (crc_mode, op2, 0); if (fn == IFN_CRC) expand_crc_table_based (target, op1, op2, op3, data_mode); diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index bef9a0e..54dcb52 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,37 @@ +2025-07-07 Qing Zhao <qing.zhao@oracle.com> + + Revert: + 2025-07-01 Qing Zhao <qing.zhao@oracle.com> + + * c-attribs.cc (handle_counted_by_attribute): Accept counted_by + attribute for pointer fields. + +2025-07-07 Qing Zhao <qing.zhao@oracle.com> + + Revert: + 2025-07-01 Qing Zhao <qing.zhao@oracle.com> + + * c-gimplify.cc (is_address_with_access_with_size): New function. + (ubsan_walk_array_refs_r): Instrument an INDIRECT_REF whose base + address is .ACCESS_WITH_SIZE or an address computation whose base + address is .ACCESS_WITH_SIZE. + * c-ubsan.cc (ubsan_instrument_bounds_pointer_address): New function. + (struct factor_t): New structure. + (get_factors_from_mul_expr): New function. + (get_index_from_offset): New function. + (get_index_from_pointer_addr_expr): New function. + (is_instrumentable_pointer_array_address): New function. + (ubsan_array_ref_instrumented_p): Change prototype. + Handle MEM_REF in addtional to ARRAY_REF. + (ubsan_maybe_instrument_array_ref): Handle MEM_REF in addtional + to ARRAY_REF. + +2025-07-07 Jason Merrill <jason@redhat.com> + + PR c++/120917 + * c.opt: Add -Wno-abbreviated-auto-in-template-arg. + * c.opt.urls: Regenerate. + 2025-07-04 Jakub Jelinek <jakub@redhat.com> PR c/120837 diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc index ea04ed7..5d7a31f 100644 --- a/gcc/c-family/c-attribs.cc +++ b/gcc/c-family/c-attribs.cc @@ -2906,53 +2906,22 @@ handle_counted_by_attribute (tree *node, tree name, " declaration %q+D", name, decl); *no_add_attrs = true; } - /* This attribute only applies to a field with array type or pointer type. */ - else if (TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE - && TREE_CODE (TREE_TYPE (decl)) != POINTER_TYPE) + /* This attribute only applies to field with array type. */ + else if (TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE) { error_at (DECL_SOURCE_LOCATION (decl), - "%qE attribute is not allowed for a non-array" - " or non-pointer field", name); + "%qE attribute is not allowed for a non-array field", + name); *no_add_attrs = true; } /* This attribute only applies to a C99 flexible array member type. */ - else if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE - && !c_flexible_array_member_type_p (TREE_TYPE (decl))) + else if (! c_flexible_array_member_type_p (TREE_TYPE (decl))) { error_at (DECL_SOURCE_LOCATION (decl), "%qE attribute is not allowed for a non-flexible" " array member field", name); *no_add_attrs = true; } - /* This attribute cannot be applied to a pointer to void type. */ - else if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE - && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == VOID_TYPE) - { - error_at (DECL_SOURCE_LOCATION (decl), - "%qE attribute is not allowed for a pointer to void", - name); - *no_add_attrs = true; - } - /* This attribute cannot be applied to a pointer to function type. */ - else if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE - && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == FUNCTION_TYPE) - { - error_at (DECL_SOURCE_LOCATION (decl), - "%qE attribute is not allowed for a pointer to" - " function", name); - *no_add_attrs = true; - } - /* This attribute cannot be applied to a pointer to structure or union - with flexible array member. */ - else if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE - && RECORD_OR_UNION_TYPE_P (TREE_TYPE (TREE_TYPE (decl))) - && TYPE_INCLUDES_FLEXARRAY (TREE_TYPE (TREE_TYPE (decl)))) - { - error_at (DECL_SOURCE_LOCATION (decl), - "%qE attribute is not allowed for a pointer to" - " structure or union with flexible array member", name); - *no_add_attrs = true; - } /* The argument should be an identifier. */ else if (TREE_CODE (argval) != IDENTIFIER_NODE) { @@ -2961,8 +2930,7 @@ handle_counted_by_attribute (tree *node, tree name, *no_add_attrs = true; } /* Issue error when there is a counted_by attribute with a different - field as the argument for the same flexible array member or - pointer field. */ + field as the argument for the same flexible array member field. */ else if (old_counted_by != NULL_TREE) { tree old_fieldname = TREE_VALUE (TREE_VALUE (old_counted_by)); diff --git a/gcc/c-family/c-cppbuiltin.cc b/gcc/c-family/c-cppbuiltin.cc index 459fd86..0c84020 100644 --- a/gcc/c-family/c-cppbuiltin.cc +++ b/gcc/c-family/c-cppbuiltin.cc @@ -1087,6 +1087,7 @@ c_cpp_builtins (cpp_reader *pfile) { /* Set feature test macros for C++26. */ cpp_define (pfile, "__cpp_constexpr=202406L"); + cpp_define (pfile, "__cpp_constexpr_exceptions=202411L"); cpp_define (pfile, "__cpp_static_assert=202306L"); cpp_define (pfile, "__cpp_placeholder_variables=202306L"); cpp_define (pfile, "__cpp_structured_bindings=202403L"); diff --git a/gcc/c-family/c-gimplify.cc b/gcc/c-family/c-gimplify.cc index e905059..c6fb764 100644 --- a/gcc/c-family/c-gimplify.cc +++ b/gcc/c-family/c-gimplify.cc @@ -66,20 +66,6 @@ along with GCC; see the file COPYING3. If not see walk back up, we check that they fit our constraints, and copy them into temporaries if not. */ - -/* Check whether TP is an address computation whose base is a call to - .ACCESS_WITH_SIZE. */ - -static bool -is_address_with_access_with_size (tree tp) -{ - if (TREE_CODE (tp) == POINTER_PLUS_EXPR - && (TREE_CODE (TREE_OPERAND (tp, 0)) == INDIRECT_REF) - && (is_access_with_size_p (TREE_OPERAND (TREE_OPERAND (tp, 0), 0)))) - return true; - return false; -} - /* Callback for c_genericize. */ static tree @@ -135,20 +121,6 @@ ubsan_walk_array_refs_r (tree *tp, int *walk_subtrees, void *data) walk_tree (&TREE_OPERAND (*tp, 1), ubsan_walk_array_refs_r, pset, pset); walk_tree (&TREE_OPERAND (*tp, 0), ubsan_walk_array_refs_r, pset, pset); } - else if (TREE_CODE (*tp) == INDIRECT_REF - && is_address_with_access_with_size (TREE_OPERAND (*tp, 0))) - { - ubsan_maybe_instrument_array_ref (&TREE_OPERAND (*tp, 0), false); - /* Make sure ubsan_maybe_instrument_array_ref is not called again on - the POINTER_PLUS_EXPR, so ensure it is not walked again and walk - its subtrees manually. */ - tree aref = TREE_OPERAND (*tp, 0); - pset->add (aref); - *walk_subtrees = 0; - walk_tree (&TREE_OPERAND (aref, 0), ubsan_walk_array_refs_r, pset, pset); - } - else if (is_address_with_access_with_size (*tp)) - ubsan_maybe_instrument_array_ref (tp, true); return NULL_TREE; } diff --git a/gcc/c-family/c-ubsan.cc b/gcc/c-family/c-ubsan.cc index 38514a4..a4dc310 100644 --- a/gcc/c-family/c-ubsan.cc +++ b/gcc/c-family/c-ubsan.cc @@ -397,8 +397,7 @@ get_bound_from_access_with_size (tree call) return NULL_TREE; tree ref_to_size = CALL_EXPR_ARG (call, 1); - unsigned int class_of_size = TREE_INT_CST_LOW (CALL_EXPR_ARG (call, 2)); - tree type = TREE_TYPE (CALL_EXPR_ARG (call, 3)); + tree type = TREE_TYPE (TREE_TYPE (CALL_EXPR_ARG (call, 2))); tree size = fold_build2 (MEM_REF, type, unshare_expr (ref_to_size), build_int_cst (ptr_type_node, 0)); /* If size is negative value, treat it as zero. */ @@ -410,12 +409,7 @@ get_bound_from_access_with_size (tree call) build_zero_cst (type), size); } - /* Only when class_of_size is 1, i.e, the number of the elements of - the object type, return the size. */ - if (class_of_size != 1) - return NULL_TREE; - else - size = fold_convert (sizetype, size); + size = fold_convert (sizetype, size); return size; } @@ -554,322 +548,38 @@ ubsan_instrument_bounds (location_t loc, tree array, tree *index, *index, bound); } - -/* Instrument array bounds for the pointer array address which is - an INDIRECT_REF to the call to .ACCESS_WITH_SIZE. We create special - builtin, that gets expanded in the sanopt pass, and make an array - dimention of it. POINTER_ADDR is the pointer array's base address. - *INDEX is an index to the array. - IGNORE_OFF_BY_ONE is true if the POINTER_ADDR is not inside an - INDIRECT_REF. - Return NULL_TREE if no instrumentation is emitted. */ - -tree -ubsan_instrument_bounds_pointer_address (location_t loc, tree pointer_addr, - tree *index, - bool ignore_off_by_one) -{ - gcc_assert (TREE_CODE (pointer_addr) == INDIRECT_REF); - tree call = TREE_OPERAND (pointer_addr, 0); - if (!is_access_with_size_p (call)) - return NULL_TREE; - tree bound = get_bound_from_access_with_size (call); - - if (ignore_off_by_one) - bound = fold_build2 (PLUS_EXPR, TREE_TYPE (bound), bound, - build_int_cst (TREE_TYPE (bound), - 1)); - - /* Don't emit instrumentation in the most common cases. */ - tree idx = NULL_TREE; - if (TREE_CODE (*index) == INTEGER_CST) - idx = *index; - else if (TREE_CODE (*index) == BIT_AND_EXPR - && TREE_CODE (TREE_OPERAND (*index, 1)) == INTEGER_CST) - idx = TREE_OPERAND (*index, 1); - if (idx - && TREE_CODE (bound) == INTEGER_CST - && tree_int_cst_sgn (idx) >= 0 - && tree_int_cst_lt (idx, bound)) - return NULL_TREE; - - *index = save_expr (*index); - - /* Create an array_type for the corresponding pointer array. */ - tree itype = build_range_type (sizetype, size_zero_node, NULL_TREE); - /* The array's element type can be get from the return type of the call to - .ACCESS_WITH_SIZE. */ - tree element_type = TREE_TYPE (TREE_TYPE (TREE_TYPE (call))); - tree array_type = build_array_type (element_type, itype); - /* Create a "(T *) 0" tree node to describe the array type. */ - tree zero_with_type = build_int_cst (build_pointer_type (array_type), 0); - return build_call_expr_internal_loc (loc, IFN_UBSAN_BOUNDS, - void_type_node, 3, zero_with_type, - *index, bound); -} - -/* This structure is to combine a factor with its parent and its position - * in its parent tree. */ -struct factor_t -{ - tree factor; - tree parent; /* the parent tree of this factor. */ - int pos; /* the position of this factor in its parent tree. */ -}; - -/* for a multiply expression like: - ((long unsigned int) m * (long unsigned int) SAVE_EXPR <n>) * 4 - - locate all the factors, the parents of the factor and the position of - the factor in its parent, and put them to VEC_FACTORS. */ - -static void -get_factors_from_mul_expr (tree mult_expr, tree parent, - int pos, auto_vec<factor_t> *vec_factors) -{ - struct factor_t mult_factor = {0, 0, -1}; - mult_factor.factor = mult_expr; - mult_factor.parent = parent; - mult_factor.pos = pos; - - while (CONVERT_EXPR_CODE_P (TREE_CODE (mult_expr))) - { - mult_factor.parent = mult_expr; - mult_factor.pos = 0; - mult_expr = TREE_OPERAND (mult_expr, 0); - mult_factor.factor = mult_expr; - } - if (TREE_CODE (mult_expr) != MULT_EXPR) - vec_factors->safe_push (mult_factor); - else - { - get_factors_from_mul_expr (TREE_OPERAND (mult_expr, 0), mult_expr, - 0, vec_factors); - get_factors_from_mul_expr (TREE_OPERAND (mult_expr, 1), mult_expr, - 1, vec_factors); - } -} - -/* Given an OFFSET expression, and the ELEMENT_SIZE, - get the index expression from OFFSET and return it. - For example: - OFFSET: - ((long unsigned int) m * (long unsigned int) SAVE_EXPR <n>) * 4 - ELEMENT_SIZE: - (sizetype) SAVE_EXPR <n> * 4 - get the index as (long unsigned int) m, and return it. - The INDEX_P holds the pointer to the parent tree of the index, - INDEX_N holds the position of the index in its parent. */ - -static tree -get_index_from_offset (tree offset, tree *index_p, - int *index_n, tree element_size) -{ - if (TREE_CODE (offset) != MULT_EXPR) - return NULL_TREE; - - auto_vec<factor_t> e_factors, o_factors; - get_factors_from_mul_expr (element_size, NULL, -1, &e_factors); - get_factors_from_mul_expr (offset, *index_p, *index_n, &o_factors); - - if (e_factors.is_empty () || o_factors.is_empty ()) - return NULL_TREE; - - bool all_found = true; - for (unsigned i = 0; i < e_factors.length (); i++) - { - factor_t e_size_factor = e_factors[i]; - bool found = false; - for (unsigned j = 0; j < o_factors.length ();) - { - factor_t o_exp_factor = o_factors[j]; - if (operand_equal_p (e_size_factor.factor, o_exp_factor.factor)) - { - o_factors.unordered_remove (j); - found = true; - break; - } - else - j++; - } - if (!found) - all_found = false; - } - - if (!all_found) - return NULL_TREE; - - if (o_factors.length () != 1) - return NULL_TREE; - - *index_p = o_factors[0].parent; - *index_n = o_factors[0].pos; - return o_factors[0].factor; -} - -/* For an pointer + offset computation expression, such as, - *.ACCESS_WITH_SIZE (p->c, &p->b, 1, 0, -1, 0B) - + (sizetype) ((long unsigned int) index * 4 - Return the index of this pointer array reference, - set the parent tree of INDEX to *INDEX_P. - set the operand position of the INDEX in the parent tree to *INDEX_N. - If failed, return NULL_TREE. */ - -static tree -get_index_from_pointer_addr_expr (tree pointer, tree *index_p, int *index_n) -{ - *index_p = NULL_TREE; - *index_n = -1; - if (TREE_CODE (TREE_OPERAND (pointer, 0)) != INDIRECT_REF) - return NULL_TREE; - tree call = TREE_OPERAND (TREE_OPERAND (pointer, 0), 0); - if (!is_access_with_size_p (call)) - return NULL_TREE; - - /* Get the pointee type of the call to .ACCESS_WITH_SIZE. - This should be the element type of the pointer array. */ - tree pointee_type = TREE_TYPE (TREE_TYPE (TREE_TYPE (call))); - tree pointee_size = TYPE_SIZE_UNIT (pointee_type); - - tree index_exp = TREE_OPERAND (pointer, 1); - *index_p = pointer; - *index_n = 1; - - if (!(TREE_CODE (index_exp) != MULT_EXPR - && tree_int_cst_equal (pointee_size, integer_one_node))) - { - while (CONVERT_EXPR_CODE_P (TREE_CODE (index_exp))) - { - *index_p = index_exp; - *index_n = 0; - index_exp = TREE_OPERAND (index_exp, 0); - } - index_exp = get_index_from_offset (index_exp, index_p, - index_n, pointee_size); - - if (!index_exp) - return NULL_TREE; - } - - while (CONVERT_EXPR_CODE_P (TREE_CODE (index_exp))) - { - *index_p = index_exp; - *index_n = 0; - index_exp = TREE_OPERAND (index_exp, 0); - } - - return index_exp; -} - -/* Return TRUE when the EXPR is a pointer array address that could be - instrumented. - We only instrument an address computation similar as the following: - *.ACCESS_WITH_SIZE (p->c, &p->b, 1, 0, -1, 0B) - + (sizetype) ((long unsigned int) index * 4) - if the EXPR is instrumentable, return TRUE and - set the index to *INDEX. - set the *.ACCESS_WITH_SIZE to *BASE. - set the parent tree of INDEX to *INDEX_P. - set the operand position of the INDEX in the parent tree to INDEX_N. */ - -static bool -is_instrumentable_pointer_array_address (tree expr, tree *base, - tree *index, tree *index_p, - int *index_n) -{ - /* For a poiner array address as: - (*.ACCESS_WITH_SIZE (p->c, &p->b, 1, 0, -1, 0B) - + (sizetype) ((long unsigned int) index * 4) - op0 is the call to *.ACCESS_WITH_SIZE; - op1 is the index. */ - if (TREE_CODE (expr) != POINTER_PLUS_EXPR) - return false; - - tree op0 = TREE_OPERAND (expr, 0); - if (TREE_CODE (op0) != INDIRECT_REF) - return false; - if (!is_access_with_size_p (TREE_OPERAND (op0, 0))) - return false; - tree op1 = get_index_from_pointer_addr_expr (expr, index_p, index_n); - if (op1 != NULL_TREE) - { - *base = op0; - *index = op1; - return true; - } - return false; -} - -/* Return true iff T is an array or an indirect reference that was - instrumented by SANITIZE_BOUNDS. */ +/* Return true iff T is an array that was instrumented by SANITIZE_BOUNDS. */ bool -ubsan_array_ref_instrumented_p (tree t) +ubsan_array_ref_instrumented_p (const_tree t) { - if (TREE_CODE (t) != ARRAY_REF - && TREE_CODE (t) != MEM_REF) + if (TREE_CODE (t) != ARRAY_REF) return false; - bool is_array = (TREE_CODE (t) == ARRAY_REF); - tree op0 = NULL_TREE; - tree op1 = NULL_TREE; - tree index_p = NULL_TREE; - int index_n = 0; - if (is_array) - { - op1 = TREE_OPERAND (t, 1); - return TREE_CODE (op1) == COMPOUND_EXPR - && TREE_CODE (TREE_OPERAND (op1, 0)) == CALL_EXPR - && CALL_EXPR_FN (TREE_OPERAND (op1, 0)) == NULL_TREE - && CALL_EXPR_IFN (TREE_OPERAND (op1, 0)) == IFN_UBSAN_BOUNDS; - } - else if (is_instrumentable_pointer_array_address (t, &op0, &op1, - &index_p, &index_n)) - return TREE_CODE (op1) == COMPOUND_EXPR - && TREE_CODE (TREE_OPERAND (op1, 0)) == CALL_EXPR - && CALL_EXPR_FN (TREE_OPERAND (op1, 0)) == NULL_TREE - && CALL_EXPR_IFN (TREE_OPERAND (op1, 0)) == IFN_UBSAN_BOUNDS; - - return false; + tree op1 = TREE_OPERAND (t, 1); + return TREE_CODE (op1) == COMPOUND_EXPR + && TREE_CODE (TREE_OPERAND (op1, 0)) == CALL_EXPR + && CALL_EXPR_FN (TREE_OPERAND (op1, 0)) == NULL_TREE + && CALL_EXPR_IFN (TREE_OPERAND (op1, 0)) == IFN_UBSAN_BOUNDS; } -/* Instrument an ARRAY_REF or an address computation whose base address is - a call to .ACCESS_WITH_SIZE, if it hasn't already been instrumented. - IGNORE_OFF_BY_ONE is true if the ARRAY_REF is inside a ADDR_EXPR, or the - address computation is not inside a INDIRECT_REF. */ +/* Instrument an ARRAY_REF, if it hasn't already been instrumented. + IGNORE_OFF_BY_ONE is true if the ARRAY_REF is inside a ADDR_EXPR. */ void ubsan_maybe_instrument_array_ref (tree *expr_p, bool ignore_off_by_one) { - tree e = NULL_TREE; - tree op0 = NULL_TREE; - tree op1 = NULL_TREE; - tree index_p = NULL_TREE; /* the parent tree of INDEX. */ - int index_n = 0; /* the operand position of INDEX in the parent tree. */ - if (!ubsan_array_ref_instrumented_p (*expr_p) && sanitize_flags_p (SANITIZE_BOUNDS | SANITIZE_BOUNDS_STRICT) && current_function_decl != NULL_TREE) { - if (TREE_CODE (*expr_p) == ARRAY_REF) - { - op0 = TREE_OPERAND (*expr_p, 0); - op1 = TREE_OPERAND (*expr_p, 1); - index_p = *expr_p; - index_n = 1; - e = ubsan_instrument_bounds (EXPR_LOCATION (*expr_p), op0, - &op1, ignore_off_by_one); - } - else if (is_instrumentable_pointer_array_address (*expr_p, &op0, &op1, - &index_p, &index_n)) - e = ubsan_instrument_bounds_pointer_address (EXPR_LOCATION (*expr_p), - op0, &op1, - ignore_off_by_one); - - /* Replace the original INDEX with the instrumented INDEX. */ + tree op0 = TREE_OPERAND (*expr_p, 0); + tree op1 = TREE_OPERAND (*expr_p, 1); + tree e = ubsan_instrument_bounds (EXPR_LOCATION (*expr_p), op0, &op1, + ignore_off_by_one); if (e != NULL_TREE) - TREE_OPERAND (index_p, index_n) - = build2 (COMPOUND_EXPR, TREE_TYPE (op1), e, op1); + TREE_OPERAND (*expr_p, 1) = build2 (COMPOUND_EXPR, TREE_TYPE (op1), + e, op1); } } diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index 8af466d..6a55e71 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -397,6 +397,10 @@ Wassign-intercept ObjC ObjC++ Var(warn_assign_intercept) Warning Warn whenever an Objective-C assignment is being intercepted by the garbage collector. +Wabbreviated-auto-in-template-arg +C++ ObjC++ Warning Var(warn_abbev_auto_targ) Init(1) +Diagnose a placeholder type in a template argument in a function parameter type. + Wbad-function-cast C ObjC Var(warn_bad_function_cast) Warning Warn about casting functions to incompatible types. diff --git a/gcc/c-family/c.opt.urls b/gcc/c-family/c.opt.urls index 65d1221..401e6e7 100644 --- a/gcc/c-family/c.opt.urls +++ b/gcc/c-family/c.opt.urls @@ -139,6 +139,9 @@ UrlSuffix(gcc/Warning-Options.html#index-Warray-parameter) Wassign-intercept UrlSuffix(gcc/Objective-C-and-Objective-C_002b_002b-Dialect-Options.html#index-Wassign-intercept) +Wabbreviated-auto-in-template-arg +UrlSuffix(gcc/C_002b_002b-Dialect-Options.html#index-Wabbreviated-auto-in-template-arg) + Wbad-function-cast UrlSuffix(gcc/Warning-Options.html#index-Wbad-function-cast) diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index cb69b8c..dcef284 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,20 @@ +2025-07-07 Qing Zhao <qing.zhao@oracle.com> + + Revert: + 2025-07-07 Qing Zhao <qing.zhao@oracle.com> + + * c-decl.cc (verify_counted_by_attribute): Change the 2nd argument + to a vector of fields with counted_by attribute. Verify all fields + in this vector. + (finish_struct): Collect all the fields with counted_by attribute + to a vector and pass this vector to verify_counted_by_attribute. + * c-typeck.cc (build_counted_by_ref): Handle pointers with counted_by. + Add one more argument, issue error when the pointee type is a structure + or union including a flexible array member. + (build_access_with_size_for_counted_by): Handle pointers with counted_by. + (handle_counted_by_for_component_ref): Call build_counted_by_ref + with the new prototype. + 2025-07-01 Qing Zhao <qing.zhao@oracle.com> * c-decl.cc (verify_counted_by_attribute): Change the 2nd argument diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc index 7e1c197..8bbd6eb 100644 --- a/gcc/c/c-decl.cc +++ b/gcc/c/c-decl.cc @@ -9432,62 +9432,56 @@ c_update_type_canonical (tree t) } } -/* Verify the argument of the counted_by attribute of each of the - FIELDS_WITH_COUNTED_BY is a valid field of the containing structure, - STRUCT_TYPE, Report error and remove the corresponding attribute - when it's not. */ +/* Verify the argument of the counted_by attribute of the flexible array + member FIELD_DECL is a valid field of the containing structure, + STRUCT_TYPE, Report error and remove this attribute when it's not. */ static void -verify_counted_by_attribute (tree struct_type, - auto_vec<tree> *fields_with_counted_by) +verify_counted_by_attribute (tree struct_type, tree field_decl) { - for (tree field_decl : *fields_with_counted_by) - { - tree attr_counted_by = lookup_attribute ("counted_by", - DECL_ATTRIBUTES (field_decl)); + tree attr_counted_by = lookup_attribute ("counted_by", + DECL_ATTRIBUTES (field_decl)); - if (!attr_counted_by) - continue; + if (!attr_counted_by) + return; + + /* If there is an counted_by attribute attached to the field, + verify it. */ - /* If there is an counted_by attribute attached to the field, - verify it. */ + tree fieldname = TREE_VALUE (TREE_VALUE (attr_counted_by)); - tree fieldname = TREE_VALUE (TREE_VALUE (attr_counted_by)); + /* Verify the argument of the attrbute is a valid field of the + containing structure. */ - /* Verify the argument of the attrbute is a valid field of the - containing structure. */ + tree counted_by_field = lookup_field (struct_type, fieldname); - tree counted_by_field = lookup_field (struct_type, fieldname); + /* Error when the field is not found in the containing structure and + remove the corresponding counted_by attribute from the field_decl. */ + if (!counted_by_field) + { + error_at (DECL_SOURCE_LOCATION (field_decl), + "argument %qE to the %<counted_by%> attribute" + " is not a field declaration in the same structure" + " as %qD", fieldname, field_decl); + DECL_ATTRIBUTES (field_decl) + = remove_attribute ("counted_by", DECL_ATTRIBUTES (field_decl)); + } + else + /* Error when the field is not with an integer type. */ + { + while (TREE_CHAIN (counted_by_field)) + counted_by_field = TREE_CHAIN (counted_by_field); + tree real_field = TREE_VALUE (counted_by_field); - /* Error when the field is not found in the containing structure and - remove the corresponding counted_by attribute from the field_decl. */ - if (!counted_by_field) + if (!INTEGRAL_TYPE_P (TREE_TYPE (real_field))) { error_at (DECL_SOURCE_LOCATION (field_decl), "argument %qE to the %<counted_by%> attribute" - " is not a field declaration in the same structure" - " as %qD", fieldname, field_decl); + " is not a field declaration with an integer type", + fieldname); DECL_ATTRIBUTES (field_decl) = remove_attribute ("counted_by", DECL_ATTRIBUTES (field_decl)); } - else - /* Error when the field is not with an integer type. */ - { - while (TREE_CHAIN (counted_by_field)) - counted_by_field = TREE_CHAIN (counted_by_field); - tree real_field = TREE_VALUE (counted_by_field); - - if (!INTEGRAL_TYPE_P (TREE_TYPE (real_field))) - { - error_at (DECL_SOURCE_LOCATION (field_decl), - "argument %qE to the %<counted_by%> attribute" - " is not a field declaration with an integer type", - fieldname); - DECL_ATTRIBUTES (field_decl) - = remove_attribute ("counted_by", - DECL_ATTRIBUTES (field_decl)); - } - } } } @@ -9562,7 +9556,7 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes, until now.) */ bool saw_named_field = false; - auto_vec<tree> fields_with_counted_by; + tree counted_by_fam_field = NULL_TREE; for (x = fieldlist; x; x = DECL_CHAIN (x)) { /* Whether this field is the last field of the structure or union. @@ -9643,16 +9637,9 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes, record it here and do more verification later after the whole structure is complete. */ if (lookup_attribute ("counted_by", DECL_ATTRIBUTES (x))) - fields_with_counted_by.safe_push (x); + counted_by_fam_field = x; } - if (TREE_CODE (TREE_TYPE (x)) == POINTER_TYPE) - /* If there is a counted_by attribute attached to this field, - record it here and do more verification later after the - whole structure is complete. */ - if (lookup_attribute ("counted_by", DECL_ATTRIBUTES (x))) - fields_with_counted_by.safe_push (x); - if (pedantic && TREE_CODE (t) == RECORD_TYPE && flexible_array_type_p (TREE_TYPE (x))) pedwarn (DECL_SOURCE_LOCATION (x), OPT_Wpedantic, @@ -9951,8 +9938,8 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes, struct_parse_info->struct_types.safe_push (t); } - if (fields_with_counted_by.length () > 0) - verify_counted_by_attribute (t, &fields_with_counted_by); + if (counted_by_fam_field) + verify_counted_by_attribute (t, counted_by_fam_field); return t; } diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc index 7948106..9a5eb0d 100644 --- a/gcc/c/c-typeck.cc +++ b/gcc/c/c-typeck.cc @@ -2922,8 +2922,8 @@ should_suggest_deref_p (tree datum_type) /* For a SUBDATUM field of a structure or union DATUM, generate a REF to the object that represents its counted_by per the attribute counted_by - attached to this field if it's a flexible array member or a pointer - field, otherwise return NULL_TREE. + attached to this field if it's a flexible array member field, otherwise + return NULL_TREE. Set COUNTED_BY_TYPE to the TYPE of the counted_by field. For example, if: @@ -2941,34 +2941,18 @@ should_suggest_deref_p (tree datum_type) */ static tree -build_counted_by_ref (location_t loc, tree datum, tree subdatum, - tree *counted_by_type) +build_counted_by_ref (tree datum, tree subdatum, tree *counted_by_type) { tree type = TREE_TYPE (datum); - tree sub_type = TREE_TYPE (subdatum); - if (!c_flexible_array_member_type_p (sub_type) - && TREE_CODE (sub_type) != POINTER_TYPE) + if (!c_flexible_array_member_type_p (TREE_TYPE (subdatum))) return NULL_TREE; - tree element_type = TREE_TYPE (sub_type); - tree attr_counted_by = lookup_attribute ("counted_by", DECL_ATTRIBUTES (subdatum)); tree counted_by_ref = NULL_TREE; *counted_by_type = NULL_TREE; if (attr_counted_by) { - /* Issue error when the element_type is a structure or - union including a flexible array member. */ - if (RECORD_OR_UNION_TYPE_P (element_type) - && TYPE_INCLUDES_FLEXARRAY (element_type)) - { - error_at (loc, - "%<counted_by%> attribute is not allowed for a pointer to" - " structure or union with flexible array member"); - return error_mark_node; - } - tree field_id = TREE_VALUE (TREE_VALUE (attr_counted_by)); counted_by_ref = build_component_ref (UNKNOWN_LOCATION, @@ -2991,29 +2975,28 @@ build_counted_by_ref (location_t loc, tree datum, tree subdatum, } /* Given a COMPONENT_REF REF with the location LOC, the corresponding - COUNTED_BY_REF, and the COUNTED_BY_TYPE, generate the corresponding - call to the internal function .ACCESS_WITH_SIZE. - - Generate an INDIRECT_REF to a call to the internal function - .ACCESS_WITH_SIZE. + COUNTED_BY_REF, and the COUNTED_BY_TYPE, generate an INDIRECT_REF + to a call to the internal function .ACCESS_WITH_SIZE. REF to: - (*.ACCESS_WITH_SIZE (REF, COUNTED_BY_REF, 1, (TYPE_OF_SIZE)0, -1, - (TYPE_OF_ARRAY *)0)) + (*.ACCESS_WITH_SIZE (REF, COUNTED_BY_REF, (* TYPE_OF_SIZE)0, + TYPE_SIZE_UNIT for element) NOTE: The return type of this function is the POINTER type pointing - to the original flexible array type or the original pointer type. - Then the type of the INDIRECT_REF is the original flexible array type - or the original pointer type. + to the original flexible array type. + Then the type of the INDIRECT_REF is the original flexible array type. + + The type of the first argument of this function is a POINTER type + to the original flexible array type. - The 4th argument of the call is a constant 0 with the TYPE of the - object pointed by COUNTED_BY_REF. + The 3rd argument of the call is a constant 0 with the pointer TYPE whose + pointee type is the TYPE of the object pointed by COUNTED_BY_REF. - The 6th argument of the call is a constant 0 of the same TYPE as - the return type of the call. + The 4th argument of the call is the TYPE_SIZE_UNIT of the element TYPE + of the array. */ static tree @@ -3021,29 +3004,26 @@ build_access_with_size_for_counted_by (location_t loc, tree ref, tree counted_by_ref, tree counted_by_type) { - gcc_assert (c_flexible_array_member_type_p (TREE_TYPE (ref)) - || TREE_CODE (TREE_TYPE (ref)) == POINTER_TYPE); - bool is_fam = c_flexible_array_member_type_p (TREE_TYPE (ref)); - tree first_param = is_fam ? array_to_pointer_conversion (loc, ref) - : build_unary_op (loc, ADDR_EXPR, ref, false); - - /* The result type of the call is a pointer to the original type - of the ref. */ + gcc_assert (c_flexible_array_member_type_p (TREE_TYPE (ref))); + /* The result type of the call is a pointer to the flexible array type. */ tree result_type = c_build_pointer_type (TREE_TYPE (ref)); - first_param = c_fully_fold (first_param, false, NULL); + tree element_size = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ref))); + + tree first_param + = c_fully_fold (array_to_pointer_conversion (loc, ref), false, NULL); tree second_param = c_fully_fold (counted_by_ref, false, NULL); + tree third_param = build_int_cst (build_pointer_type (counted_by_type), 0); tree call = build_call_expr_internal_loc (loc, IFN_ACCESS_WITH_SIZE, - result_type, 6, + result_type, 4, first_param, second_param, - build_int_cst (integer_type_node, 1), - build_int_cst (counted_by_type, 0), - build_int_cst (integer_type_node, -1), - build_int_cst (result_type, 0)); - /* Wrap the call with an INDIRECT_REF with the original type of the ref. */ + third_param, + element_size); + + /* Wrap the call with an INDIRECT_REF with the flexible array type. */ call = build1 (INDIRECT_REF, TREE_TYPE (ref), call); SET_EXPR_LOCATION (call, loc); return call; @@ -3061,7 +3041,7 @@ handle_counted_by_for_component_ref (location_t loc, tree ref) tree datum = TREE_OPERAND (ref, 0); tree subdatum = TREE_OPERAND (ref, 1); tree counted_by_type = NULL_TREE; - tree counted_by_ref = build_counted_by_ref (loc, datum, subdatum, + tree counted_by_ref = build_counted_by_ref (datum, subdatum, &counted_by_type); if (counted_by_ref) ref = build_access_with_size_for_counted_by (loc, ref, diff --git a/gcc/cfgexpand.cc b/gcc/cfgexpand.cc index 33649d4..a656cce 100644 --- a/gcc/cfgexpand.cc +++ b/gcc/cfgexpand.cc @@ -5358,6 +5358,8 @@ expand_debug_expr (tree exp) return simplify_gen_binary (MULT, mode, op0, op1); case RDIV_EXPR: + gcc_assert (FLOAT_MODE_P (mode)); + /* Fall through. */ case TRUNC_DIV_EXPR: case EXACT_DIV_EXPR: if (unsignedp) diff --git a/gcc/cgraphunit.cc b/gcc/cgraphunit.cc index fa54a59..8e8d855 100644 --- a/gcc/cgraphunit.cc +++ b/gcc/cgraphunit.cc @@ -63,7 +63,7 @@ along with GCC; see the file COPYING3. If not see final assembler is generated. This is done in the following way. Note that with link time optimization the process is split into three stages (compile time, linktime analysis and parallel linktime as - indicated bellow). + indicated below). Compile time: diff --git a/gcc/cobol/ChangeLog b/gcc/cobol/ChangeLog index 4b05399..6c3e1bd 100644 --- a/gcc/cobol/ChangeLog +++ b/gcc/cobol/ChangeLog @@ -1,3 +1,81 @@ +2025-07-09 Robert Dubner <rdubner@symas.com> + James K. Lowden <jklowden@cobolworx.com> + + PR cobol/120765 + PR cobol/119337 + PR cobol/120794 + * Make-lang.in: Take control of the .cc.o rule. + * cbldiag.h (error_msg_direct): New declaration. + (gcc_location_dump): Forward declaration. + (location_dump): Use gcc_location_dump. + * cdf.y: Change some tokens. + * gcobc: Change dialect handling. + * genapi.cc (parser_call_targets_dump): Temporarily remove from service. + (parser_compile_dcls): Combine temporary arrays. + (get_binary_value_from_float): Apply const to one parameter. + (depending_on_value): Localize a boolean variable. + (normal_normal_compare): Likewise. + (cobol_compare): Eliminate cppcheck warning. + (combined_name): Apply const to an input parameter. + (parser_perform): Apply const to a variable. + (parser_accept): Improve handling of special_name_t parameter and + the exception conditions. + (parser_display): Improve handling of speciat_name_t parameter; use the + os_filename[] string when appropriate. + (program_end_stuff): Rename shadowing variable. + (parser_division): Consolidate temporary char[] arrays. + (parser_file_start): Apply const to a parameter. + (inspect_replacing): Likewise. + (parser_program_hierarchy): Rename shadowing variable. + (mh_identical): Apply const to parameters. + (float_type_of): Likewise. + (picky_memcpy): Likewise. + (mh_numeric_display): Likewise. + (mh_little_endian): Likewise. + (mh_source_is_group): Apply static to a variable it. + (move_helper): Quiet a cppcheck warning. + * genapi.h (parser_accept): Add exceptions to declaration. + (parser_accept_under_discussion): Add declaration. + (parser_display): Change to std::vector; add exceptions to declaration. + * lexio.cc (cdf_source_format): Improve source code location handling. + (source_format_t::infer): Likewise. + (is_fixed_format): Likewise. + (is_reference_format): Likewise. + (left_margin): Likewise. + (right_margin): Likewise. + (cobol_set_indicator_column): Likewise. + (include_debug): Likewise. + (continues_at): Likewise. + (indicated): Likewise. + (check_source_format_directive): Likewise. + (cdftext::free_form_reference_format): Likewise. + * parse.y: Tokens; program and function names; DISPLAY and ACCEPT + handling. + * parse_ante.h (class tokenset_t): Removed. + (class current_tokens_t): Removed. + (field_of): Removed. + * scan.l: Token handling. + * scan_ante.h (level_found): Comment. + * scan_post.h (start_condition_str): Remove cast author_state:. + * symbols.cc (symbols_update): Change error message. + (symbol_table_init): Correct and reorder entries. + (symbol_unresolved_file_key): New function definition. + (cbl_file_key_t::deforward): Change error message. + * symbols.h (symbol_unresolved_file_key): New declaration. + (keyword_tok): New function. + (redefined_token): New function. + (class current_tokens_t): New class. + * symfind.cc (symbol_match): Revise error message. + * token_names.h: Reorder and change numbers in comments. + * util.cc (class cdf_directives_t): New class. + (cobol_set_indicator_column): New function. + (cdf_source_format): New function. + (gcc_location_set_impl): Improve column handling in token_location. + (gcc_location_dump): New function. + (class temp_loc_t): Modify constructor. + (error_msg_direct): New function. + * util.h (class source_format_t): New class. + 2025-07-01 James K. Lowden <jklowden@cobolworx.com> * Make-lang.in: Use && instead of semicolon between commands. diff --git a/gcc/cobol/Make-lang.in b/gcc/cobol/Make-lang.in index e884212..ee494b8 100644 --- a/gcc/cobol/Make-lang.in +++ b/gcc/cobol/Make-lang.in @@ -384,3 +384,23 @@ cobol.stagefeedback: stagefeedback-start selftest-cobol: lang_checks += check-cobol + +# +# Front-end specific flags: Originally done for the COBOL front end, this +# scripting applies CXXFLAGS_FOR_COBOL only to compilations of source code in the +# gcc/cobol source code tree. Both forms can be used: +# +# CXXFLAGS_FOR_COBOL=xxx ../configure --enable-languages=.... +# and +# make <gcc> CXXFLAGS_FOR_COBOL=yyy +# +# The second form overrides the first. +# +# To apply this feature to other front ends, look for and clone lines +# containing "CXXFLAGS_FOR_COBOL" in configure.ac, Makefile.tbl, and Makefile.def. +# + +cobol/%.o: cobol/%.cc + @echo $(COMPILE) $(CXXFLAGS_FOR_COBOL) $< + $(COMPILE) $(CXXFLAGS_FOR_COBOL) $< + $(POSTCOMPILE) diff --git a/gcc/cobol/cbldiag.h b/gcc/cobol/cbldiag.h index 548b0f2..49dc44b 100644 --- a/gcc/cobol/cbldiag.h +++ b/gcc/cobol/cbldiag.h @@ -82,6 +82,10 @@ struct YDFLTYPE void error_msg( const YYLTYPE& loc, const char gmsgid[], ... ) ATTRIBUTE_GCOBOL_DIAG(2, 3); +// an error that uses token_location, not yylloc +void error_msg_direct( const char gmsgid[], ... ) + ATTRIBUTE_GCOBOL_DIAG(1, 2); + void dialect_error( const YYLTYPE& loc, const char term[], const char dialect[] ); @@ -104,16 +108,20 @@ void dbgmsg( const char fmt[], ... ) ATTRIBUTE_PRINTF_1; void gcc_location_set( const YYLTYPE& loc ); +void gcc_location_dump(); + // tree.h defines yy_flex_debug as a macro because options.h #if ! defined(yy_flex_debug) template <typename LOC> static void location_dump( const char func[], int line, const char tag[], const LOC& loc) { extern int yy_flex_debug; // cppcheck-suppress shadowVariable - if( yy_flex_debug && gcobol_getenv("update_location") ) + if( yy_flex_debug && gcobol_getenv("update_location") ) { fprintf(stderr, "%s:%d: %s location (%d,%d) to (%d,%d)\n", func, line, tag, loc.first_line, loc.first_column, loc.last_line, loc.last_column); + gcc_location_dump(); + } } #endif // defined(yy_flex_debug) diff --git a/gcc/cobol/cdf.y b/gcc/cobol/cdf.y index 3344271..840eb50 100644 --- a/gcc/cobol/cdf.y +++ b/gcc/cobol/cdf.y @@ -105,14 +105,14 @@ void input_file_status_notify(); using std::map; - static map<std::string, cdfval_t> dictionary; - #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-function" static bool cdfval_add( const char name[], const cdfval_t& value, bool override = false ) { + cdf_values_t& dictionary( cdf_dictionary() ); + if( scanner_parsing() ) { if( ! override ) { if( dictionary.find(name) != dictionary.end() ) return false; @@ -123,6 +123,8 @@ void input_file_status_notify(); } static void cdfval_off( const char name[] ) { + cdf_values_t& dictionary( cdf_dictionary() ); + if( scanner_parsing() ) { auto p = dictionary.find(name); if( p == dictionary.end() ) { @@ -159,6 +161,8 @@ exception_turn_t exception_turn; bool apply_cdf_turn( const exception_turn_t& turn ) { + cbl_enabled_exceptions_t& enabled_exceptions( cdf_enabled_exceptions() ); + for( auto elem : turn.exception_files() ) { std::set<size_t> files(elem.second.begin(), elem.second.end()); enabled_exceptions.turn_on_off(turn.enabled, @@ -204,15 +208,17 @@ apply_cdf_turn( const exception_turn_t& turn ) { %type <file> filename %type <files> filenames -%token BY 478 +%type <number> cdf_stackable + +%token BY 486 %token COPY 362 %token CDF_DISPLAY 384 ">>DISPLAY" -%token IN 597 +%token IN 605 %token NAME 286 %token NUMSTR 305 "numeric literal" -%token OF 678 -%token PSEUDOTEXT 713 -%token REPLACING 735 +%token OF 686 +%token PSEUDOTEXT 721 +%token REPLACING 743 %token LITERAL 298 %token SUPPRESS 376 @@ -227,25 +233,32 @@ apply_cdf_turn( const exception_turn_t& turn ) { %token CDF_WHEN 389 ">>WHEN" %token CDF_END_EVALUATE 390 ">>END-EVALUATE" -%token AS 460 CONSTANT 361 DEFINED 363 +%token ALL 450 +%token CALL_CONVENTION 391 ">>CALL-CONVENTION" +%token COBOL_WORDS 380 ">>COBOL-WORDS" +%token CDF_PUSH 394 ">>PUSH" +%token CDF_POP 395 ">>POP" +%token SOURCE_FORMAT 396 ">>SOURCE FORMAT" + +%token AS 468 CONSTANT 361 DEFINED 363 %type <boolean> DEFINED -%token OTHER 690 PARAMETER_kw 368 "PARAMETER" -%token OFF 679 OVERRIDE 369 -%token THRU 931 -%token TRUE_kw 805 "True" +%token OTHER 698 PARAMETER_kw 368 "PARAMETER" +%token OFF 687 OVERRIDE 369 +%token THRU 939 +%token TRUE_kw 813 "True" -%token CALL_COBOL 391 "CALL" -%token CALL_VERBATIM 392 "CALL (as C)" +%token CALL_COBOL 392 "CALL" +%token CALL_VERBATIM 393 "CALL (as C)" -%token TURN 807 CHECKING 488 LOCATION 641 ON 681 WITH 833 +%token TURN 815 CHECKING 496 LOCATION 649 ON 689 WITH 841 -%left OR 932 -%left AND 933 -%right NOT 934 -%left '<' '>' '=' NE 935 LE 936 GE 937 +%left OR 940 +%left AND 941 +%right NOT 942 +%left '<' '>' '=' NE 943 LE 944 GE 945 %left '-' '+' %left '*' '/' -%right NEG 939 +%right NEG 947 %define api.prefix {ydf} %define api.token.prefix{YDF_} @@ -277,6 +290,8 @@ complete: cdf_define | cdf_display | cdf_turn | cdf_call_convention + | cdf_push + | cdf_pop ; /* @@ -328,6 +343,7 @@ cdf_define: CDF_DEFINE cdf_constant NAME as cdf_expr[value] override } if( !cdfval_add( $NAME, cdfval_t($value), $override) ) { error_msg(@NAME, "name already in dictionary: %s", $NAME); + cdf_values_t& dictionary( cdf_dictionary() ); const cdfval_t& entry = dictionary[$NAME]; if( entry.filename ) { error_msg(@NAME, "%s previously defined in %s:%d", @@ -357,7 +373,7 @@ cdf_define: CDF_DEFINE cdf_constant NAME as cdf_expr[value] override * available regardless. */ { - if( 0 == dictionary.count($NAME) ) { + if( 0 == cdf_dictionary().count($NAME) ) { yywarn("CDF: '%s' is defined AS PARAMETER " "but was not defined", $NAME); } @@ -400,6 +416,35 @@ cdf_call_convention: } ; +cdf_push: CDF_PUSH cdf_stackable { + switch( $cdf_stackable ) { + case YDF_ALL: cdf_push(); break; + case YDF_CALL_CONVENTION: cdf_push_call_convention(); break; + case YDF_CDF_DEFINE: cdf_push_dictionary(); break; + case YDF_COBOL_WORDS: cdf_push_current_tokens(); break; + case YDF_SOURCE_FORMAT: cdf_push_source_format(); break; + default: gcc_unreachable(); + } + } + ; +cdf_pop: CDF_POP cdf_stackable { + switch( $cdf_stackable ) { + case YDF_ALL: cdf_pop(); break; + case YDF_CALL_CONVENTION: cdf_pop_call_convention(); break; + case YDF_CDF_DEFINE: cdf_pop_dictionary(); break; + case YDF_COBOL_WORDS: cdf_pop_current_tokens(); break; + case YDF_SOURCE_FORMAT: cdf_pop_source_format(); break; + default: gcc_unreachable(); + } + } + ; + +cdf_stackable: ALL { $$ = YDF_ALL; } + | CALL_CONVENTION { $$ = YDF_CALL_CONVENTION; } + | COBOL_WORDS { $$ = YDF_COBOL_WORDS; } + | CDF_DEFINE { $$ = YDF_CDF_DEFINE; } + | SOURCE_FORMAT { $$ = YDF_SOURCE_FORMAT; } + ; except_names: except_name | except_names except_name @@ -471,6 +516,7 @@ cdf_eval_obj: cdf_cond_expr cdf_cond_expr: BOOL | NAME DEFINED { + cdf_values_t& dictionary( cdf_dictionary() ); auto p = dictionary.find($1); bool found = p != dictionary.end(); if( !$DEFINED ) found = ! found; @@ -552,6 +598,7 @@ cdf_expr: cdf_expr '+' cdf_expr { $$ = $1(@1) + $3(@3); } ; cdf_factor: NAME { + cdf_values_t& dictionary( cdf_dictionary() ); auto that = dictionary.find($1); if( that != dictionary.end() ) { $$ = that->second; @@ -651,6 +698,7 @@ name_any: namelit name_one: NAME { + cdf_values_t& dictionary( cdf_dictionary() ); cdf_arg_t arg = { YDF_NAME, $1 }; auto p = dictionary.find($1); @@ -665,6 +713,7 @@ name_one: NAME namelit: name { + cdf_values_t& dictionary( cdf_dictionary() ); cdf_arg_t arg = { YDF_NAME, $1 }; auto p = dictionary.find($1); @@ -745,6 +794,7 @@ location_set( const YYLTYPE& loc ) { bool // used by cobol1.cc defined_cmd( const char arg[] ) { + cdf_values_t& dictionary( cdf_dictionary() ); cdfval_t value(1); char *name = xstrdup(arg); @@ -868,6 +918,7 @@ static int ydflex(void) { bool cdf_value( const char name[], const cdfval_t& value ) { + cdf_values_t& dictionary( cdf_dictionary() ); auto p = dictionary.find(name); if( p != dictionary.end() ) return false; @@ -878,6 +929,7 @@ cdf_value( const char name[], const cdfval_t& value ) { const cdfval_t * cdf_value( const char name[] ) { + cdf_values_t& dictionary( cdf_dictionary() ); auto p = dictionary.find(name); if( p == dictionary.end() ) return NULL; diff --git a/gcc/cobol/cdfval.h b/gcc/cobol/cdfval.h index 465bdbb..cc474a2 100644 --- a/gcc/cobol/cdfval.h +++ b/gcc/cobol/cdfval.h @@ -126,4 +126,8 @@ cdf_value( const char name[] ); bool cdf_value( const char name[], const cdfval_t& value ); +typedef std::map<std::string, cdfval_t> cdf_values_t; + +cdf_values_t& cdf_dictionary(); + #endif diff --git a/gcc/cobol/dts.h b/gcc/cobol/dts.h index aa3fa58..e12b979 100644 --- a/gcc/cobol/dts.h +++ b/gcc/cobol/dts.h @@ -86,18 +86,24 @@ namespace dts { #if __cpp_exceptions static const char msg[] = "input not NUL-terminated"; throw std::domain_error( msg ); -#else - // eoinput terminates input - eoinput = strchr(input, '\0'); // cppcheck-suppress uselessAssignmentPtrArg #endif } auto ncm = re.size(); cm.resize(ncm); std::vector <regmatch_t> cms(ncm); - int erc = regexec( &re, input, ncm, cms.data(), 0 ); if( erc != 0 ) return false; +#if __cpp_exceptions + // This is not correct at all, but current use depends on current behavior. + // The following line is excluded from the GCC build, which is compiled + // without __cpp_exceptions. parse_copy_directive (for one) depends on + // regex_search returning true even if the match is beyond eoinput. + if( eoinput < cm[0].second ) return false; + // Correct behavior would return match only between input and eoinput. + // Because regex(3) uses a NUL terminator, it may match text between + // eoinput and the NUL. +#endif std::transform( cms.begin(), cms.end(), cm.begin(), [input]( const regmatch_t& m ) { return csub_match( input, m ); diff --git a/gcc/cobol/except.cc b/gcc/cobol/except.cc index 60b8416..e42aea2 100644 --- a/gcc/cobol/except.cc +++ b/gcc/cobol/except.cc @@ -84,8 +84,6 @@ cbl_enabled_exception_t::dump( int i ) const { file ); } -cbl_enabled_exceptions_t enabled_exceptions; - void cbl_enabled_exceptions_t::dump() const { extern int yydebug; diff --git a/gcc/cobol/gcobc b/gcc/cobol/gcobc index 01c75dd..fa9f609 100755 --- a/gcc/cobol/gcobc +++ b/gcc/cobol/gcobc @@ -125,25 +125,24 @@ $0 recognizes the following GnuCOBOL cobc compilation options: -std=mvs -std=mvs-strict -std=mf -std=mf-strict -std=cobol85 -std=cobol2002 -std=cobol2014 - Options that are the same in gcobol and cobc are passed through verbatim. - Options that have no analog in gcobol produce a warning message. - To produce this message, use -HELP. +Options that are the same in gcobol and cobc are passed through verbatim. +Options that have no analog in gcobol produce a warning message. +To produce this message, use -HELP. To see the constructed cobc command-line, use -echo. To override the default cobc, set the "cobc" environment variable. By default, gcobc invokes the gcobol the same directory the gcobc resides. To override, set the gcobol environment variable. - EOF - } +EOF +} -dialect="gnu" +dialect="mf gnu" out_set="" first="" - # - # Simply iterate over the command-line tokens. We can't use getopts - # here because it's not designed for single-dash words (e.g. -shared). # - +# Iterate over the command-line tokens. We can't use getopts here +# because it's not designed for single-dash words (e.g. -shared). +# for opt in "$@" do if [ "$skip_arg" ] @@ -441,11 +440,13 @@ do -std=mvs | -std=mvs-strict | -std=ibm | -std=ibm-strict) dialect=ibm ;; -std=mf | -std=mf-strict) dialect=mf - ;; - -std=default) dialect=gnu # that's GnuCOBOL's default and GCC's dialect for GnuCOBOL - ;; - -std=cobol*) dialect="" # GCC COBOL targets COBOL2024 "mostly backward to COBOL85" - ;; + ;; + # GnuCOBOL's default and GCC's dialect for GnuCOBOL + -std=default) dialect=gnu + ;; + # GCC COBOL targets COBOL2024 "mostly backward to COBOL85" + -std=cobol*) dialect="" + ;; -std=*) dialect="" warn "$opt (unkown dialect)" @@ -480,7 +481,8 @@ do opts="$opts /dev/stdin" ;; - *) if [ -z "$output_name" ] # first non-option argument is source file name + # First file name argument is default output filename. + *) if [ -z "$output_name" -a -e "$opt" ] then output_name=$(basename "${opt%.*}") case $mode in @@ -512,6 +514,11 @@ fi # To override the default gcobol, set the "gcobol" environment variable. gcobol="${gcobol:-${0%/*}/gcobol}" +if [ "$dialect" ] +then + dialect=$(echo $dialect | sed -E 's/[[:alnum:]]+/-dialect &/g') +fi + if [ "$echo" ] then echo $gcobol $mode $opts @@ -523,4 +530,4 @@ then set -x fi -exec $gcobol $mode $opts +exec $gcobol $mode $dialect $opts diff --git a/gcc/cobol/gcobol.1 b/gcc/cobol/gcobol.1 index 6db5400..ebb833c 100644 --- a/gcc/cobol/gcobol.1 +++ b/gcc/cobol/gcobol.1 @@ -587,6 +587,21 @@ statement, regardless of compile-time constants. .. . .Ss Implemented Exception Conditions +By default, per ISO, no EC is enabled. Implemented ECs may be enabled +on the command line or via the +.Sy TURN +directive. Any attempt to enable an EC that is not implemented is +treated as an error. +.Pp +An enabled EC not handled by a +.Sy DECLARATIVE +is written to the system log and to standard error. (The authors +intend to make that an option.) A fatal EC not handled with +.Sy RESUME +ends with a call to +.Xr abort 3 +and process termination. +.Pp Not all Exception Conditions are implemented. Any attempt to enable an EC that that is not implemented produces a warning message. The following are implemented: @@ -913,11 +928,90 @@ or has no effect; the two are interchangeable. .. . -.Ss Compiler-Directing Facility (CDF) +.Sh COMPILER-DIRECTING FACILITY The CDF should be used with caution because no comprehensive test -suite has been identified. +suite has been identified. . -.Ss Conditional Compilation +.Ss CDF Text Manipulation +.Bl -tag -width >>DEFINE +.It Sy COPY Ar copybook Li Oo OF|BY Ar library Oc Oo Sy REPLACING ... Oc +If +.Ar copybook +is a literal, it treated a literal filename, which either does or does not exist. If +.Ar copybook +is a \*[lang] word, +.Nm +looks first for an environment variable named +.Va copybook +and, if found, uses the contents of that variable as the name of the +copybook file. If that file does not exist, it continues looking for +a file named one of: +.sp +.Bl -bullet -compact -offset 5n +.It +.Pa copybook +(literally) +.It +.Pa copybook.cpy +.It +.Pa copybook.CPY +.It +.Pa copybook.cbl +.It +.Pa copybook.CBL +.It +.Pa copybook.cob +.It +.Pa copybook.COB +.El +.sp +in that order. It looks first in the same directory as the source +code file, and then in any +.Ar copybook-path +named with the +.Fl I +option. +. +.\" FIXME: need escape mechanism for directories with ':' in the name. +.Ar copybook-path +may (like the shell's +.Ev PATH +variable) be a colon-separated list. +The +.Fl I +option may occur multiple times on the command line. Each successive +.Ar copybook-path +is concatenated to previous ones. +Relative paths (having no leading +.Ql / Ns +\&) +are searched relative to the compiler's current working directory. +.Pp +For example, +.D1 \& +.D1 Fl I Li /usr/local/include:include +.D1 \& +searches first the directory where the \*[lang] program is found, next in +.Pa /usr/local/include , +and finally in an +.Pa include +subdirectory of the directory from which +.Nm +was invoked. +.Pp +For the +.Sy REPLACING +phrase, both the modern pseudo-text and the \*[lang]/85 forms are +recognized. (The older forms are used in the NIST CCVS/85 test suite.) +.It Sy REPLACE ... +.Nm +supports the full ISO +.Sy REPLACE +syntax. +.El +. +.Ss CDF Directives +.\"Bl -tag -width >>PROPAGATE .Bl -tag -width >>DEFINE .It >> Ns Sy DEFINE Ar name Sy AS Bro Ar expression Li | Sy PARAMETER Brc Op Sy OVERRIDE Define @@ -959,10 +1053,6 @@ is supported. Boolean literals are not supported. . .It >> Ns Sy EVALUATE Not implemented. -.El -. -.Ss Other CDF Directives -.Bl -tag -width >>PROPAGATE .It >> Ns Sy CALL-CONVENTION Ar convention .Ar convention may be one of: @@ -1036,6 +1126,24 @@ Not implemented. Not implemented. .It >> Ns Sy PROPAGATE Not implemented. +.It >> Ns Sy PUSH Ar directive +.It >> Ns Sy POP Ar directive +With +.Sy PUSH , +push CDF state onto a stack. +With +.Sy POP , +return to the prior pushed state. +.Ar directive +may be one of +.Bl -tag -compact +.It Sy CALL-CONVENTION +.It Sy COBOL-WORDS +.It Sy DEFINE +.It Sy SOURCE FORMAT +.It Sy TURN +.El +. .It >> Ns Sy TURN Oo .Ar ec Oo Ar file Li ... Oc ... .Oc Sy CHECKING Bro Oo Sy ON Oc Oo Oo Sy WITH Oc Sy LOCATION Oc | Sy OFF Brc @@ -1087,76 +1195,6 @@ the directive must appear before To test a feature-set variable, use .Dl >>IF Ar feature Li DEFINED . -.Ss Copybooks -.Nm -supports the CDF -.Sy COPY -statement, with or without its -.Sy REPLACING -component. For any statement -.sp -.D1 COPY Ar copybook -.sp -.Nm -looks first for an environment variable named -.Va copybook -and, if found, uses the contents of that variable as the name of the -copybook file. If that file does not exist, it continues looking for -a file named one of: -.sp -.Bl -bullet -compact -offset 5n -.It -.Pa copybook -(literally) -.It -.Pa copybook.cpy -.It -.Pa copybook.CPY -.It -.Pa copybook.cbl -.It -.Pa copybook.CBL -.It -.Pa copybook.cob -.It -.Pa copybook.COB -.El -.sp -in that order. It looks first in the same directory as the source -code file, and then in any -.Ar copybook-path -named with the -.Fl I -option. -. -.\" FIXME: need escape mechanism for directories with ':' in the name. -.Ar copybook-path -may (like the shell's -.Ev PATH -variable) be a colon-separated list. -. -The -.Fl I -option may occur multiple times on the command line. Each successive -.Ar copybook-path -is concatenated to previous ones. -Relative paths (having no leading -.Ql / Ns -\&) -are searched relative to the compiler's current working directory. -.Pp -For example, -.D1 \& -.D1 Fl I Li /usr/local/include:include -.D1 \& -searches first the directory where the \*[lang] program is found, next in -.Pa /usr/local/include , -and finally in an -.Pa include -subdirectory of the directory from which -.Nm -was invoked. -. .Ss Intrinsic functions .Nm implements all intrinsic functions defined by \*[isostd], plus a few diff --git a/gcc/cobol/genapi.cc b/gcc/cobol/genapi.cc index 8017788..3c4e9a9 100644 --- a/gcc/cobol/genapi.cc +++ b/gcc/cobol/genapi.cc @@ -766,8 +766,9 @@ parser_call_target_convention( tree func ) void parser_call_targets_dump() { - dbgmsg( "call targets for #" HOST_SIZE_T_PRINT_UNSIGNED, + dbgmsg( "call targets for #" HOST_SIZE_T_PRINT_UNSIGNED " NOT dumping", (fmt_size_t)current_program_index() ); + return; // not currently working for( const auto& elem : call_targets ) { const auto& k = elem.first; const auto& v = elem.second; @@ -1034,14 +1035,13 @@ parser_compile_dcls( const std::vector<uint64_t>& dcls ) return NULL_TREE; } - char ach[32]; + char ach[64]; static int counter = 1; sprintf(ach, "_dcls_table_%d", counter++); tree retval = array_of_long_long(ach, dcls); SHOW_IF_PARSE(nullptr) { SHOW_PARSE_HEADER - char ach[64]; snprintf(ach, sizeof(ach), " Size is %lu; retval is %p", gb4(dcls.size()), as_voidp(retval)); SHOW_PARSE_TEXT(ach); @@ -1050,7 +1050,6 @@ parser_compile_dcls( const std::vector<uint64_t>& dcls ) TRACE1 { TRACE1_HEADER - char ach[64]; snprintf(ach, sizeof(ach), " Size is %lu; retval is %p", gb4(dcls.size()), as_voidp(retval)); TRACE1_TEXT_ABC("", ach, ""); @@ -1167,7 +1166,7 @@ parser_statement_begin( const cbl_name_t statement_name, // the execution time of a program doing two-billion simple adds in an inner // loop dropped from 3.8 seconds to 0.175 seconds. - bool exception_processing = enabled_exceptions.size() ; + bool exception_processing = cdf_enabled_exceptions().size() ; if( !exception_processing ) { @@ -1588,7 +1587,7 @@ parser_initialize(const cbl_refer_t& refer, bool like_parser_symbol_add) static void get_binary_value_from_float(tree value, - cbl_refer_t &dest, + const cbl_refer_t &dest, cbl_field_t *source, tree source_offset ) @@ -1682,6 +1681,7 @@ depending_on_value(tree depending_on, cbl_field_t *current_sizer) // gg_assign(occurs_lower, build_int_cst_type(LONG, current_sizer->occurs.bounds.lower)); // gg_assign(occurs_upper, build_int_cst_type(LONG, current_sizer->occurs.bounds.upper)); + gcc_assert(current_sizer); if( current_sizer->occurs.depending_on ) { get_depending_on_value_from_odo(depending_on, current_sizer); @@ -1825,16 +1825,12 @@ normal_normal_compare(bool debugging, NULL_TREE); } - bool needs_adjusting; if( !left_intermediate && !right_intermediate ) { // Yay! Both sides have fixed rdigit values. - // Flag needs_adjusting as false, because we are going to do it here: - needs_adjusting = false; int adjust = get_scaled_rdigits(left_side_ref->field) - get_scaled_rdigits(right_side_ref->field); - if( adjust > 0 ) { // We need to make right_side bigger to match the scale of left_side @@ -1849,6 +1845,7 @@ normal_normal_compare(bool debugging, else { // At least one side is right_intermediate + bool needs_adjusting; tree adjust; if( !left_intermediate && right_intermediate ) @@ -2357,7 +2354,7 @@ cobol_compare( tree return_int, build_int_cst_type(INT, rightflags), integer_zero_node, NULL_TREE)); - compared = true; + // compared = true; // Commented out to quiet cppcheck } // gg_printf(" result is %d\n", return_int, NULL_TREE); @@ -2563,7 +2560,7 @@ get_string_from(cbl_field_t *field) } static char * -combined_name(cbl_label_t *label) +combined_name(const cbl_label_t *label) { // This routine returns a pointer to a static, so make sure you use the result // before calling the routine again @@ -2578,7 +2575,7 @@ combined_name(cbl_label_t *label) if( label->parent ) { // It's possible for implicit - cbl_label_t *section_label = cbl_label_of(symbol_at(label->parent)); + const cbl_label_t *section_label = cbl_label_of(symbol_at(label->parent)); sect_name = section_label->name; } } @@ -3315,7 +3312,7 @@ parser_perform(cbl_label_t *label, bool suppress_nexting) char ach[256]; if( label->type == LblParagraph ) { - cbl_label_t *section_label = cbl_label_of(symbol_at(label->parent)); + const cbl_label_t *section_label = cbl_label_of(symbol_at(label->parent)); para_name = label->name; sect_name = section_label->name; sprintf(ach, @@ -4339,67 +4336,182 @@ psa_FldBlob(struct cbl_field_t *var ) } void -parser_accept( struct cbl_refer_t refer, - enum special_name_t special_e ) +parser_accept(struct cbl_refer_t tgt, + special_name_t special_e, + cbl_label_t *error, + cbl_label_t *not_error ) { - Analyze(); SHOW_PARSE { SHOW_PARSE_HEADER - SHOW_PARSE_REF(" ", refer); + if( error ) + { + SHOW_PARSE_LABEL(" error ", error) + } + if( not_error ) + { + SHOW_PARSE_LABEL(" not_error ", not_error) + } SHOW_PARSE_END } - TRACE1 - { - TRACE1_HEADER - TRACE1_END - } - - /* - enum special_name_t - { - SYSIN_e, - SYSIPT_e, - SYSOUT_e, - SYSLIST_e, - SYSLST_e, - SYSPUNCH_e, - SYSPCH_e, - CONSOLE_e, - C01_e, C02_e, C03_e, C04_e, C05_e, C06_e, - C07_e, C08_e, C09_e, C10_e, C11_e, C12_e, - CSP_e, - S01_e, S02_e, S03_e, S04_e, S05_e, - AFP_5A_e, - }; - */ // The ISO spec describes the valid special names for ACCEPT as implementation // dependent. We are following IBM's lead. tree environment = build_int_cst_type(INT, special_e); - switch( special_e ) + const char *function_to_call = NULL; + + switch(special_e) { + case STDIN_e: case CONSOLE_e: case SYSIPT_e: case SYSIN_e: - break; - default: - dbgmsg("%s(): We don't know what to do with special_name_t %d,", __func__, special_e); - dbgmsg("%s(): so we are ignoring it.", __func__); - yywarn("unrecognized SPECIAL NAME ignored"); + // This is ordinary input from from the stdin: + gg_call(VOID, + "__gg__accept", + environment, + gg_get_address_of(tgt.field->var_decl_node), + refer_offset(tgt), + refer_size_dest(tgt), + NULL_TREE); return; break; - } - gg_call(VOID, - "__gg__accept", - environment, - gg_get_address_of(refer.field->var_decl_node), - refer_offset(refer), - refer_size_dest(refer), - NULL_TREE); + case C01_e: + case C02_e: + case C03_e: + case C04_e: + case C05_e: + case C06_e: + case C07_e: + case C08_e: + case C09_e: + case C10_e: + case C11_e: + case C12_e: + case CSP_e: + case S01_e: + case S02_e: + case S03_e: + case S04_e: + case S05_e: + case AFP_5A_e: + case STDOUT_e: + case SYSOUT_e: + case SYSLIST_e: + case SYSLST_e: + case STDERR_e: + case SYSPUNCH_e: + case SYSPCH_e: + case SYSERR_e: + cbl_internal_error("Not valid for ACCEPT statement."); + break; + + case ARG_NUM_e: + // This ACCEPT statement wants the number of argv values: + gg_call(VOID, + "__gg__get_argc", + gg_get_address_of(tgt.field->var_decl_node), + refer_offset(tgt), + refer_size_source(tgt), + NULL_TREE); + return; + break; + + case ENV_NAME_e: + // This fetches the environment name set by DISPLAY... UPON ENV_NAME_e + gg_call(VOID, + "__gg__get_env_name", + gg_get_address_of(tgt.field->var_decl_node), + refer_offset(tgt), + refer_size_source(tgt), + NULL_TREE); + return; + break; + + case ENV_VALUE_e: + // This fetches the environment value associated with the previously + // esablished name + function_to_call = "__gg__get_env_value"; + break; + + case ARG_VALUE_e: + // We are fetching the variable whose index was established by a prior + // DISPLAY UPON ARGUMENT-NUMBER. After the fetch, the value will be + // incremented by one. + function_to_call = "__gg__accept_arg_value"; + break; + } + if( function_to_call ) + { + tree erf = gg_define_int(); + gg_assign(erf, + gg_call_expr( INT, + function_to_call, + gg_get_address_of(tgt.field->var_decl_node), + refer_offset(tgt), + refer_size_dest(tgt), + NULL_TREE)); + if( error ) + { + // There is an ON EXCEPTION phrase: + IF( erf, ne_op, integer_zero_node ) + { + SHOW_PARSE + { + SHOW_PARSE_INDENT + SHOW_PARSE_TEXT("Laying down GOTO error->INTO for_argv") + SHOW_PARSE_LABEL(" ", error) + } + gg_append_statement( error->structs.arith_error->into.go_to ); + } + ELSE + { + } + ENDIF + } + if( not_error ) + { + // There is an NOT ON EXCEPTION phrase: + IF( erf, eq_op, integer_zero_node ) + { + SHOW_PARSE + { + SHOW_PARSE_INDENT + SHOW_PARSE_TEXT("Laying down GOTO not_error->INTO for_argv") + SHOW_PARSE_LABEL(" ", not_error) + } + gg_append_statement( not_error->structs.arith_error->into.go_to ); + } + ELSE + { + } + ENDIF + } + if( error ) + { + SHOW_PARSE + { + SHOW_PARSE_INDENT + SHOW_PARSE_TEXT("Laying down LABEL error->bottom") + SHOW_PARSE_LABEL(" ", error) + } + gg_append_statement( error->structs.arith_error->bottom.label ); + } + if( not_error ) + { + SHOW_PARSE + { + SHOW_PARSE_INDENT + SHOW_PARSE_TEXT("Laying down LABEL not_error->bottom") + SHOW_PARSE_LABEL(" ", not_error) + SHOW_PARSE_END + } + gg_append_statement( not_error->structs.arith_error->bottom.label ); + } + } } // TODO: update documentation. @@ -5250,22 +5362,29 @@ parser_display_field(cbl_field_t *field) DISPLAY_NO_ADVANCE); } -/* - * The first parameter to parser_display is the "device" upon which to display - * the data. Besides normal devices, these may include elements that define the - * Unix command line and environment: - * 1. ARG_NUM_e, the ARGUMENT-NUMBER - * 2. ARG_VALUE_e, the ARGUMENT-VALUE - * 3. ENV_NAME_e, the ENVIRONMENT-NAME - * 4. ENV_VALUE_e, the ENVIRONMENT-VALUE - * that need special care and feeding. - */ void parser_display( const struct cbl_special_name_t *upon, - struct cbl_refer_t refs[], - size_t n, - bool advance ) + std::vector<cbl_refer_t> refs, + bool advance, + cbl_label_t *not_error, + cbl_label_t *error ) { + const size_t n = refs.size(); + /* + * The first parameter to parser_display is the "device" upon which to display + * the data. Besides normal devices, these may include elements that define the + * Unix command line and environment: + * 1. ARG_NUM_e, the ARGUMENT-NUMBER + * 2. ARG_VALUE_e, the ARGUMENT-VALUE + * 3. ENV_NAME_e, the ENVIRONMENT-NAME + * 4. ENV_VALUE_e, the ENVIRONMENT-VALUE + * that need special care and feeding. + */ + + // At the present time, I am not sure what not_error and error are for + gcc_assert(!not_error); + gcc_assert(!error); + Analyze(); SHOW_PARSE { @@ -5274,7 +5393,7 @@ parser_display( const struct cbl_special_name_t *upon, for(size_t i=0; i<n; i++) { SHOW_PARSE_INDENT - SHOW_PARSE_REF("", refs[i]); + SHOW_PARSE_REF("", refs.at(i)); } if( advance ) { @@ -5306,23 +5425,81 @@ parser_display( const struct cbl_special_name_t *upon, { switch(upon->id) { + // See table 5 in the IBM Cobol For Linux x86 1.2 document. + + case STDIN_e: + case SYSIN_e: + case SYSIPT_e: + cbl_internal_error("Attempting to send to an input device."); + break; + + case C01_e: + case C02_e: + case C03_e: + case C04_e: + case C05_e: + case C06_e: + case C07_e: + case C08_e: + case C09_e: + case C10_e: + case C11_e: + case C12_e: + case CSP_e: + case S01_e: + case S02_e: + case S03_e: + case S04_e: + case S05_e: + case AFP_5A_e: + case ARG_VALUE_e: + cbl_internal_error("Not valid for DISPLAY statement."); + break; + case STDOUT_e: - case SYSOUT_e: - case SYSLIST_e: - case SYSLST_e: case CONSOLE_e: + // These are inarguably stdout gg_assign(file_descriptor, integer_one_node); break; case STDERR_e: + case SYSERR_e: + // These are inarguably stderr + gg_assign(file_descriptor, integer_two_node); + break; + + case SYSOUT_e: + case SYSLIST_e: + case SYSLST_e: case SYSPUNCH_e: case SYSPCH_e: - gg_assign(file_descriptor, integer_two_node); + // In the 21st century, when there are no longer valid assumptions to + // be made about the existence of line printers, and where things + // formerly-ubiquitous card punches no longer exist, there is a need + // for the possibility of assigning these "devices" to externally- + // determined Unix gadgetry in /dev: + gg_assign(file_descriptor, + gg_call_expr( INT, + "__gg__get_file_descriptor", + gg_string_literal(upon->os_filename), + NULL_TREE)); + needs_closing = true; break; + case ARG_NUM_e: + // Set the index number for a subsequent ACCEPT FROM ARG_VALUE_e + gg_call(VOID, + "__gg__set_arg_num", + gg_get_address_of(refs[0].field->var_decl_node), + refer_offset(refs[0]), + refer_size_source(refs[0]), + NULL_TREE); + return; + break; + case ENV_NAME_e: - // This Part I of the slightly absurd method of using DISPLAY...UPON - // to fetch, or set, environment variables. + // Establish the name of an environment variable for later use with + // in either DISPLAY UPON or ACCEPT FROM gg_call(VOID, "__gg__set_env_name", gg_get_address_of(refs[0].field->var_decl_node), @@ -5332,19 +5509,16 @@ parser_display( const struct cbl_special_name_t *upon, return; break; - default: - if( upon->os_filename[0] ) - { - tree topen = gg_open( gg_string_literal(upon->os_filename), - build_int_cst_type(INT, O_APPEND|O_WRONLY)); - gg_assign(file_descriptor, topen); - needs_closing = true; - } - else - { - fprintf(stderr, "We don't know what to do in parser_display\n"); - gcc_unreachable(); - } + case ENV_VALUE_e: + // Set the contents of the environment variable named with ENV_NAME_e + gg_call(VOID, + "__gg__set_env_value", + gg_get_address_of(refs[0].field->var_decl_node), + refer_offset(refs[0]), + refer_size_source(refs[0]), + NULL_TREE); + return; + break; } } else @@ -5359,12 +5533,9 @@ parser_display( const struct cbl_special_name_t *upon, } CHECK_FIELD(refs[n-1].field); parser_display_internal(file_descriptor, refs[n-1], advance ? DISPLAY_ADVANCE : DISPLAY_NO_ADVANCE); - if( needs_closing ) { - tree tclose = gg_close(file_descriptor); - // We are ignoring the close() return value - gg_append_statement(tclose); + gg_close(file_descriptor); } cursor_at_sol = advance; @@ -6240,12 +6411,12 @@ program_end_stuff(cbl_refer_t refer, ec_type_t ec) tree array_type = build_array_type_nelts(UCHAR, returner->data.capacity); - tree retval = gg_define_variable(array_type, vs_static); - gg_memcpy(gg_get_address_of(retval), + tree array = gg_define_variable(array_type, vs_static); + gg_memcpy(gg_get_address_of(array), member(returner->var_decl_node, "data"), member(returner->var_decl_node, "capacity")); - tree actual = gg_cast(COBOL_FUNCTION_RETURN_TYPE, gg_get_address_of(retval)); + tree actual = gg_cast(COBOL_FUNCTION_RETURN_TYPE, gg_get_address_of(array)); restore_local_variables(); gg_return(actual); @@ -6876,7 +7047,6 @@ parser_division(cbl_division_t division, // expected formal parameter and tacks it onto the end of the // function's arguments chain. - char ach[2*sizeof(cbl_name_t)]; sprintf(ach, "_p_%s", args[i].refer.field->name); size_t nbytes = 0; @@ -9947,8 +10117,8 @@ parser_file_start(struct cbl_file_t *file, // A key has a number of fields for(size_t ifield=0; ifield<file->keys[key_number].nfield; ifield++) { - size_t field_index = file->keys[key_number].fields[ifield]; - cbl_field_t *field = cbl_field_of(symbol_at(field_index)); + size_t nfield = file->keys[key_number].fields[ifield]; + cbl_field_t *field = cbl_field_of(symbol_at(nfield)); combined_length += field->data.capacity; } gg_assign(length, build_int_cst_type(SIZE_T, combined_length)); @@ -9975,7 +10145,7 @@ parser_file_start(struct cbl_file_t *file, static void inspect_tally(bool backward, - cbl_refer_t identifier_1, + const cbl_refer_t &identifier_1, cbl_inspect_opers_t& identifier_2) { Analyze(); @@ -10175,8 +10345,8 @@ inspect_tally(bool backward, static void inspect_replacing(int backward, - cbl_refer_t identifier_1, - cbl_inspect_opers_t& operations) + const cbl_refer_t &identifier_1, + cbl_inspect_opers_t &operations) { Analyze(); // This is an INSPECT FORMAT 2 @@ -12066,6 +12236,8 @@ parser_file_merge( cbl_file_t *workfile, ELSE ENDIF + cbl_enabled_exceptions_t& enabled_exceptions( cdf_enabled_exceptions() ); + for(size_t i=0; i<ninputs; i++) { if( process_this_exception(ec_sort_merge_file_open_e) ) @@ -13510,9 +13682,9 @@ parser_program_hierarchy( const cbl_prog_hier_t& hier ) // are also accessible by us. Go find them. std::vector<const hier_node *>uncles; find_uncles(nodes[i], uncles); - for( size_t i=0; i<uncles.size(); i++ ) + for( size_t j=0; j<uncles.size(); j++ ) { - const hier_node *uncle = uncles[i]; + const hier_node *uncle = uncles[j]; if( map_of_sets[caller].find(uncle->name) == map_of_sets[caller].end() ) { // We have a COMMON uncle or sibling we haven't seen before. @@ -13550,7 +13722,6 @@ parser_program_hierarchy( const cbl_prog_hier_t& hier ) if( callers.find(caller) == callers.end() ) { // We haven't seen this caller before - callers.insert(caller); char ach[3*sizeof(cbl_name_t)]; tree names_table_type = build_array_type_nelts(CHAR_P, mol->second.size()+1); @@ -13617,6 +13788,8 @@ parser_program_hierarchy( const cbl_prog_hier_t& hier ) (fmt_size_t)caller); tree accessible_programs_decl = gg_trans_unit_var_decl(ach); gg_assign( accessible_programs_decl, gg_get_address_of(the_constructed_table) ); + + callers.insert(caller); } } } @@ -13734,7 +13907,7 @@ parser_check_fatal_exception() // in its innermost loop had an execution time of 19.5 seconds. By putting in // the if() statement, that was reduced to 3.8 seconds. - if( enabled_exceptions.size() || sv_is_i_o ) + if( cdf_enabled_exceptions().size() || sv_is_i_o ) { gg_call(VOID, "__gg__check_fatal_exception", @@ -13883,8 +14056,8 @@ conditional_abs(tree source, const cbl_field_t *field) static bool mh_identical(cbl_refer_t &destref, - cbl_refer_t &sourceref, - TREEPLET &tsource) + const cbl_refer_t &sourceref, + const TREEPLET &tsource) { // Check to see if the two variables are identical types, thus allowing // for a simple byte-for-byte copy of the data areas: @@ -14224,7 +14397,7 @@ float_type_of(const cbl_field_t *field) } static tree -float_type_of(cbl_refer_t *refer) +float_type_of(const cbl_refer_t *refer) { return float_type_of(refer->field); } @@ -14456,7 +14629,7 @@ picky_memset(tree &dest_p, unsigned char value, size_t length) } static void -picky_memcpy(tree &dest_p, tree &source_p, size_t length) +picky_memcpy(tree &dest_p, const tree &source_p, size_t length) { if( length ) { @@ -14476,8 +14649,8 @@ picky_memcpy(tree &dest_p, tree &source_p, size_t length) static bool mh_numeric_display( cbl_refer_t &destref, - cbl_refer_t &sourceref, - TREEPLET &tsource, + const cbl_refer_t &sourceref, + const TREEPLET &tsource, tree size_error) { bool moved = false; @@ -14965,8 +15138,8 @@ mh_numeric_display( cbl_refer_t &destref, static bool mh_little_endian( cbl_refer_t &destref, - cbl_refer_t &sourceref, - TREEPLET &tsource, + const cbl_refer_t &sourceref, + const TREEPLET &tsource, bool check_for_error, tree size_error) { @@ -15037,8 +15210,8 @@ mh_little_endian( cbl_refer_t &destref, static bool mh_source_is_group( cbl_refer_t &destref, - cbl_refer_t &sourceref, - TREEPLET &tsrc) + const cbl_refer_t &sourceref, + const TREEPLET &tsrc) { bool retval = false; if( sourceref.field->type == FldGroup && !(destref.field->attr & rjust_e) ) @@ -15103,7 +15276,7 @@ move_helper(tree size_error, // This is an INT { // We are creating a copy of the original destination in case we clobber it // and have to restore it because of a computational error. - bool first_time = true; + static bool first_time = true; static size_t stash_size = 1024; if( first_time ) { @@ -15341,7 +15514,7 @@ move_helper(tree size_error, // This is an INT gg_attribute_bit_clear(destref.field, refmod_e); } - moved = true; + // moved = true; // commented out to quiet cppcheck } if( restore_on_error ) diff --git a/gcc/cobol/genapi.h b/gcc/cobol/genapi.h index 36d947b..ab76856 100644 --- a/gcc/cobol/genapi.h +++ b/gcc/cobol/genapi.h @@ -52,10 +52,13 @@ void parser_division( cbl_division_t division, void parser_enter_program(const char *funcname, bool is_function, int *retval); void parser_leave_program(); -void parser_accept( cbl_refer_t refer, special_name_t special_e); +void parser_accept( cbl_refer_t refer, special_name_t special_e, + cbl_label_t *error, cbl_label_t *not_error ); void parser_accept_exception( cbl_label_t *name ); void parser_accept_exception_end( cbl_label_t *name ); +void parser_accept_under_discussion(struct cbl_refer_t tgt, special_name_t special, + cbl_label_t *error, cbl_label_t *not_error ); void parser_accept_envar( cbl_refer_t refer, cbl_refer_t envar, cbl_label_t *error, cbl_label_t *not_error ); void parser_set_envar( cbl_refer_t envar, cbl_refer_t refer ); @@ -263,8 +266,10 @@ void parser_exit_program(void); // exits back to COBOL only, else continue void parser_display( const struct cbl_special_name_t *upon, - struct cbl_refer_t args[], size_t n, - bool advance = DISPLAY_ADVANCE ); + std::vector<cbl_refer_t> args, + bool advance = DISPLAY_ADVANCE, + cbl_label_t *not_error = nullptr, + cbl_label_t *compute_error = nullptr ); void parser_display_field(cbl_field_t *fld); diff --git a/gcc/cobol/genutil.cc b/gcc/cobol/genutil.cc index 1d921a3..e09b1bf 100644 --- a/gcc/cobol/genutil.cc +++ b/gcc/cobol/genutil.cc @@ -307,6 +307,8 @@ get_and_check_refstart_and_reflen( tree refstart,// LONG returned value tree reflen, // LONG returned value cbl_refer_t &refer) { + cbl_enabled_exceptions_t& enabled_exceptions( cdf_enabled_exceptions() ); + if( !enabled_exceptions.match(ec_bound_ref_mod_e) ) { // This is normal operation -- no exception checking. Thus, we won't @@ -458,6 +460,7 @@ get_depending_on_value_from_odo(tree retval, cbl_field_t *odo) declarative with a RESUME NEXT STATEMENT, or before the default_condition processing can do a controlled exit. */ + cbl_enabled_exceptions_t& enabled_exceptions( cdf_enabled_exceptions() ); cbl_field_t *depending_on; depending_on = cbl_field_of(symbol_at(odo->occurs.depending_on)); @@ -601,6 +604,7 @@ get_data_offset(cbl_refer_t &refer, } else { + cbl_enabled_exceptions_t& enabled_exceptions( cdf_enabled_exceptions() ); if( !enabled_exceptions.match(ec_bound_subscript_e) ) { // With no exception testing, just pick up the value @@ -657,6 +661,8 @@ get_data_offset(cbl_refer_t &refer, // Although we strictly don't need to look at the ODO value at this point, // we do want it checked for the purposes of ec-bound-odo + cbl_enabled_exceptions_t& enabled_exceptions( cdf_enabled_exceptions() ); + if( enabled_exceptions.match(ec_bound_odo_e) ) { if( parent->occurs.depending_on ) @@ -1669,6 +1675,7 @@ set_exception_code_func(ec_type_t ec, int /*line*/, int from_raise_statement) bool process_this_exception(ec_type_t ec) { + cbl_enabled_exceptions_t& enabled_exceptions( cdf_enabled_exceptions() ); bool retval; if( enabled_exceptions.match(ec) || !skip_exception_processing ) { diff --git a/gcc/cobol/lexio.cc b/gcc/cobol/lexio.cc index 2d9fb72..0aebe52 100644 --- a/gcc/cobol/lexio.cc +++ b/gcc/cobol/lexio.cc @@ -38,29 +38,24 @@ extern int yy_flex_debug; -static struct { - bool first_file, explicitly; - int column, right_margin; - bool inference_pending() { - bool tf = first_file && !explicitly; - first_file = false; - return tf; - } - inline bool is_fixed() const { return column == 7; } - inline bool is_reffmt() const { return is_fixed() && right_margin == 73; } - inline bool is_free() const { return ! is_fixed(); } - - const char * description() const { - if( is_reffmt() ) return "REFERENCE"; - if( is_fixed() ) return "FIXED"; - if( is_free() ) return "FREE"; - gcc_unreachable(); - } -} indicator = { true, false, 0, 0 }; +source_format_t& cdf_source_format(); + +void +source_format_t::infer( const char *bol, bool want_reference_format ) { + if( bol ) { + left = 7; + if( want_reference_format ) { + right = 73; + } + } + dbgmsg("%s:%d: %s format detected", __func__, __LINE__, + description()); +} + // public source format test functions -bool is_fixed_format() { return indicator.is_fixed(); } -bool is_reference_format() { return indicator.is_reffmt(); } +bool is_fixed_format() { return cdf_source_format().is_fixed(); } +bool is_reference_format() { return cdf_source_format().is_reffmt(); } static bool debug_mode = false; @@ -76,11 +71,10 @@ static bool debug_mode = false; */ static inline int left_margin() { - return indicator.column == 0? indicator.column : indicator.column - 1; + return cdf_source_format().left_margin(); } static inline int right_margin() { - return indicator.right_margin == 0? - indicator.right_margin : indicator.right_margin - 1; + return cdf_source_format().right_margin(); } /* @@ -89,18 +83,9 @@ static inline int right_margin() { * When setting back to 0 (free), the right margin is also reset to 0. */ void -cobol_set_indicator_column( int column ) -{ - indicator.explicitly = true; - if( column == 0 ) indicator.right_margin = 0; - if( column < 0 ) { - column = -column; - indicator.right_margin = 73; - } - indicator.column = column; -} +cobol_set_indicator_column( int column ); -bool include_debug() { return indicator.column == 7 && debug_mode; } +bool include_debug() { return is_fixed_format() && debug_mode; } bool set_debug( bool tf ) { return debug_mode = tf && is_fixed_format(); } static bool nonblank( const char ch ) { return !isblank(ch); } @@ -114,7 +99,7 @@ start_of_line( char *bol, char *eol ) { static inline char * continues_at( char *bol, char *eol ) { - if( indicator.column == 0 ) return NULL; // cannot continue in free format + if( cdf_source_format().is_free() ) return NULL; // cannot continue in free format bol += left_margin(); if( *bol != '-' ) return NULL; // not a continuation line return start_of_line(++bol, eol); @@ -124,7 +109,7 @@ continues_at( char *bol, char *eol ) { // NULL means no indicator column or tested value not present. static inline char * indicated( char *bol, const char *eol, char ch = '\0' ) { - if( indicator.column == 0 && *bol != '*' ) { + if( cdf_source_format().left_margin() == 0 && *bol != '*' ) { return NULL; // no indicator column in free format, except for comments } gcc_assert(bol != NULL); @@ -336,7 +321,69 @@ recognize_replacements( filespan_t mfile, std::list<replace_t>& pending_replacem } static void +check_push_pop_directive( filespan_t& mfile ) { + char eol = '\0'; + const char *p = std::find(mfile.cur, mfile.eol, '>'); + if( ! (p < mfile.eol && p[1] == *p ) ) return; + + const char pattern[] = + ">>[[:blank:]]*(push|pop)[[:blank:]]+" + "(" + "all|" + "call-convention|" + "cobol-words|" + "define|" + "source[[:blank:]]+format|" + "turn" + ")"; + static regex re(pattern, extended_icase); + + // show contents of marked subexpressions within each match + cmatch cm; + + std::swap(*mfile.eol, eol); // see implementation for excuses + bool ok = regex_search(p, const_cast<const char *>(mfile.eol), cm, re); + std::swap(*mfile.eol, eol); + + if( ok ) { + gcc_assert(cm.size() > 1); + bool push = TOUPPER(cm[1].first[1]) == 'U'; + switch( TOUPPER(cm[2].first[0]) ) { + case 'A': // ALL + push? cdf_push() : cdf_pop(); + break; + case 'C': + switch( TOUPPER(cm[2].first[1]) ) { + case 'A': // CALL-CONVENTION + push? cdf_push_call_convention() : cdf_pop_call_convention(); + break; + case 'O': // COBOL-WORDS + push? cdf_push_current_tokens() : cdf_pop_current_tokens(); + break; + default: + gcc_unreachable(); + } + break; + case 'D': // DEFINE + push? cdf_push_dictionary() : cdf_pop_dictionary(); + break; + case 'S': // SOURCE FORMAT + push? cdf_push_source_format() : cdf_pop_source_format(); + break; + case 'T': // TURN + push? cdf_push_enabled_exceptions() : cdf_pop_enabled_exceptions(); + break; + default: + gcc_unreachable(); + } + erase_line(const_cast<char*>(cm[0].first), + const_cast<char*>(cm[0].second)); + } +} + +static void check_source_format_directive( filespan_t& mfile ) { + char eol = '\0'; const char *p = std::find(mfile.cur, mfile.eol, '>'); if( ! (p < mfile.eol && p[1] == *p ) ) return; @@ -349,7 +396,12 @@ check_source_format_directive( filespan_t& mfile ) { // show contents of marked subexpressions within each match cmatch cm; - if( regex_search(p, const_cast<const char *>(mfile.eol), cm, re) ) { + + std::swap(*mfile.eol, eol); // see implementation for excuses + bool ok = regex_search(p, const_cast<const char *>(mfile.eol), cm, re); + std::swap(*mfile.eol, eol); + + if( ok ) { gcc_assert(cm.size() > 1); switch( cm[3].length() ) { case 4: @@ -365,11 +417,11 @@ check_source_format_directive( filespan_t& mfile ) { dbgmsg( "%s:%d: %s format set, on line " HOST_SIZE_T_PRINT_UNSIGNED, __func__, __LINE__, - indicator.column == 7? "FIXED" : "FREE", + cdf_source_format().description(), (fmt_size_t)mfile.lineno() ); - char *bol = indicator.is_fixed()? mfile.cur : const_cast<char*>(cm[0].first); + char *bol = cdf_source_format().is_fixed()? mfile.cur : const_cast<char*>(cm[0].first); + gcc_assert(cm[0].second <= mfile.eol); erase_line(bol, const_cast<char*>(cm[0].second)); - mfile.cur = const_cast<char*>(cm[0].second); } } @@ -1695,20 +1747,15 @@ cdftext::free_form_reference_format( int input ) { /* * Infer source code format. */ - if( indicator.inference_pending() ) { + if( cdf_source_format().inference_pending() ) { const char *bol = valid_sequence_area(mfile.data, mfile.eodata); if( bol ) { - indicator.column = 7; - if( infer_reference_format(bol, mfile.eodata) ) { - indicator.right_margin = 73; - } + cdf_source_format().infer( bol, infer_reference_format(bol, mfile.eodata) ); } - - dbgmsg("%s:%d: %s format detected", __func__, __LINE__, - indicator.description()); } while( mfile.next_line() ) { + check_push_pop_directive(mfile); check_source_format_directive(mfile); remove_inline_comment(mfile.cur, mfile.eol); diff --git a/gcc/cobol/parse.y b/gcc/cobol/parse.y index 74637c9..83bffdf 100644 --- a/gcc/cobol/parse.y +++ b/gcc/cobol/parse.y @@ -45,6 +45,7 @@ }; enum accept_func_t { + accept_e, accept_done_e, accept_command_line_e, accept_envar_e, @@ -349,7 +350,7 @@ %token <string> SECTION %token <number> STANDARD_ALPHABET "STANDARD ALPHABET" %token <string> SWITCH -%token <string> UPSI +%token <string> UPSI %token <number> ZERO /* environment names */ @@ -385,7 +386,10 @@ CDF_EVALUATE ">>EVALUATE" CDF_WHEN ">>WHEN" CDF_END_EVALUATE ">>END-EVALUATE" + CALL_CONVENTION ">>CALL-CONVENTION" CALL_COBOL "CALL" CALL_VERBATIM "CALL (as C)" + CDF_PUSH ">>PUSH" CDF_POP ">>POP" + SOURCE_FORMAT ">>SOURCE FORMAT" IF THEN ELSE SENTENCE @@ -399,7 +403,10 @@ STRING_kw "STRING" STOP SUBTRACT START UNSTRING WRITE WHEN - ABS ACCESS ACOS ACTUAL ADVANCING AFTER ALL + ARGUMENT_NUMBER ARGUMENT_VALUE + ENVIRONMENT_NAME ENVIRONMENT_VALUE + + ABS ACCESS ACOS ACTUAL ADVANCING AFTER ALL ALLOCATE ALPHABET ALPHABETIC ALPHABETIC_LOWER "ALPHABETIC-LOWER" ALPHABETIC_UPPER "ALPHABETIC-UPPER" @@ -793,6 +800,7 @@ %type <error_clauses> io_invalids read_eofs write_eops %type <boolean> io_invalid read_eof write_eop global is_global anycase backward + end_display %type <number> mistake globally first_last %type <io_mode> io_mode @@ -848,7 +856,7 @@ declarative_list_t* dcl_list_t; isym_list_t* isym_list; struct { radix_t radix; char *string; } numstr; - struct { int token; literal_t name; } prog_end; + struct { YYLTYPE loc; int token; literal_t name; } prog_end; struct { int token; special_name_t id; } special_type; struct { cbl_field_type_t type; uint32_t capacity; bool signable; } computational; @@ -902,7 +910,7 @@ struct refer_pair_t { cbl_refer_t *first, *second; } refer2; struct { refer_collection_t *inputs; refer_pair_t into; } str_body; - struct { accept_func_t func; cbl_refer_t *into, *from; } accept_func; + struct { accept_func_t func; cbl_refer_t *into, *from; special_name_t special;} accept_func; struct unstring_into_t *uns_into; struct unstring_tgt_list_t *uns_tgts; struct unstring_tgt_t *uns_tgt; @@ -1464,16 +1472,16 @@ cobol_words: cobol_words1 | cobol_words cobol_words1 ; cobol_words1: COBOL_WORDS EQUATE NAME[keyword] WITH NAME[name] { - if( ! tokens.equate(@keyword, $keyword, $name) ) { YYERROR; } + if( ! cdf_tokens.equate(@keyword, $keyword, $name) ) { YYERROR; } } | COBOL_WORDS UNDEFINE NAME[keyword] { - if( ! tokens.undefine(@keyword, $keyword) ) { YYERROR; } + if( ! cdf_tokens.undefine(@keyword, $keyword) ) { YYERROR; } } | COBOL_WORDS SUBSTITUTE NAME[keyword] BY NAME[name] { - if( ! tokens.substitute(@keyword, $keyword, $name) ) { YYERROR; } + if( ! cdf_tokens.substitute(@keyword, $keyword, $name) ) { YYERROR; } } | COBOL_WORDS RESERVE NAME[name] { - if( ! tokens.reserve(@name, $name) ) { YYERROR; } + if( ! cdf_tokens.reserve(@name, $name) ) { YYERROR; } } ; @@ -1513,7 +1521,7 @@ program_as: %empty { static const literal_t empty {}; $$ = empty; } | AS LITERAL { $$ = $2; } ; -function_id: FUNCTION '.' NAME program_as program_attrs[attr] '.' +function_id: FUNCTION NAME program_as program_attrs[attr] '.' { internal_ebcdic_lock(); current_division = identification_div_e; @@ -1547,7 +1555,7 @@ function_id: FUNCTION '.' NAME program_as program_attrs[attr] '.' current.udf_add(current_program_index()); if( nparse_error > 0 ) YYABORT; } - | FUNCTION '.' NAME program_as is PROTOTYPE '.' + | FUNCTION NAME program_as is PROTOTYPE '.' { cbl_unimplemented("FUNCTION PROTOTYPE"); } @@ -1838,7 +1846,7 @@ select: SELECT optional NAME[name] select_clauses[clauses] '.' cbl_file_t *file = $clauses.file; file->optional = $optional; - file->line = yylineno; + file->line = @name.first_line; if( !namcpy(@clauses, file->name, $name) ) YYERROR; if( ! ($clauses.clauses & assign_clause_e) ) { @@ -1911,7 +1919,7 @@ select: SELECT optional NAME[name] select_clauses[clauses] '.' cbl_file_t file = protofile; file.optional = $optional; - file.line = yylineno; + file.line = @name.first_line; if( !namcpy(@name, file.name, $name) ) YYERROR; if( file_add(@name, &file) == NULL ) YYERROR; @@ -2473,7 +2481,7 @@ special_name: dev_mnemonic | CLASS NAME is domains { struct cbl_field_t field = { 0, - FldClass, FldInvalid, 0, 0, 0, 0, nonarray, yylineno, "", + FldClass, FldInvalid, 0, 0, 0, 0, nonarray, @NAME.first_line, "", 0, cbl_field_t::linkage_t(), {}, NULL }; if( !namcpy(@NAME, field.name, $2) ) YYERROR; @@ -2604,6 +2612,10 @@ device_name: SYSIN { $$.token = SYSIN; $$.id = SYSIN_e; } | STDIN { $$.token = STDIN; $$.id = STDIN_e; } | STDOUT { $$.token = STDOUT; $$.id = STDOUT_e; } | STDERR { $$.token = STDERR; $$.id = STDERR_e; } + /* These cannot be both ctx_name and here. * + /* ARGUMENT_NUMBER { $$.token=0; $$.id = ARG_NUM_e; } */ + /* ENVIRONMENT_NAME { $$.token=0; $$.id = ENV_NAME_e; } */ + /* ENVIRONMENT_VALUE { $$.token=0; $$.id = ENV_VALUE_e; } */ ; alphabet_name: STANDARD_ALPHABET { $$ = alphabet_add(@1, ASCII_e); } @@ -3164,7 +3176,7 @@ depending: %empty assert(e->type == SymField); odo = symbol_index(e); } else { - e = symbol_field_forward_add(PROGRAM, 0, $NAME, yylineno); + e = symbol_field_forward_add(PROGRAM, 0, $NAME, @NAME.first_line); if( !e ) YYERROR; symbol_field_location( symbol_index(e), @NAME ); odo = field_index(cbl_field_of(e)); @@ -3364,7 +3376,7 @@ level_name: LEVEL ctx_name } struct cbl_field_t field = { 0, FldInvalid, FldInvalid, 0, 0, 0, capacity_cast($1), - nonarray, yylineno, "", + nonarray, @ctx_name.first_line, "", 0, cbl_field_t::linkage_t(), {}, NULL }; if( !namcpy(@ctx_name, field.name, $2) ) YYERROR; @@ -3389,7 +3401,7 @@ level_name: LEVEL ctx_name } struct cbl_field_t field = { 0, FldInvalid, FldInvalid, 0, 0, 0, capacity_cast($1), - nonarray, yylineno, "", + nonarray, @LEVEL.first_line, "", 0, {}, {}, NULL }; $$ = field_add(@1, &field); @@ -3527,7 +3539,7 @@ data_descr1: level_name } struct cbl_field_t field = { 0, FldLiteralA, FldInvalid, constant_e, 0, 0, 78, nonarray, - yylineno, "", 0, {}, *$data, NULL }; + @name.first_line, "", 0, {}, *$data, NULL }; if( !namcpy(@name, field.name, $name) ) YYERROR; if( field.data.initial ) { field.attr |= quoted_e; @@ -3550,7 +3562,7 @@ data_descr1: level_name | LEVEL88 NAME /* VALUE */ NULLPTR { struct cbl_field_t field = { 0, - FldClass, FldInvalid, 0, 0, 0, 88, nonarray, yylineno, "", + FldClass, FldInvalid, 0, 0, 0, 88, nonarray, @NAME.first_line, "", 0, cbl_field_t::linkage_t(), {}, NULL }; if( !namcpy(@NAME, field.name, $2) ) YYERROR; @@ -3576,7 +3588,7 @@ data_descr1: level_name | LEVEL88 NAME VALUE domains { struct cbl_field_t field = { 0, - FldClass, FldInvalid, 0, 0, 0, 88, nonarray, yylineno, "", + FldClass, FldInvalid, 0, 0, 0, 88, nonarray, @NAME.first_line, "", 0, cbl_field_t::linkage_t(), {}, NULL }; if( !namcpy(@NAME, field.name, $2) ) YYERROR; @@ -4606,7 +4618,7 @@ justified_clause: is JUSTIFIED redefines_clause: REDEFINES NAME[orig] { - struct symbol_elem_t *e = field_of($orig); + struct symbol_elem_t *e = symbol_field(PROGRAM, 0, $orig); if( !e ) { error_msg(@2, "REDEFINES target not defined"); YYERROR; @@ -4906,6 +4918,7 @@ by_value_arg: scalar declaratives: %empty | DECLARATIVES '.' <label>{ + cbl_enabled_exceptions_t& enabled_exceptions( cdf_enabled_exceptions() ); current.enabled_exception_cache = enabled_exceptions; enabled_exceptions.clear(); current.doing_declaratives(true); @@ -4924,6 +4937,7 @@ declaratives: %empty * forward reference, because we haven't yet begun to parse * nondeclarative procedures. */ + cbl_enabled_exceptions_t& enabled_exceptions( cdf_enabled_exceptions() ); parser_label_label($label); enabled_exceptions = current.enabled_exception_cache; current.enabled_exception_cache.clear(); @@ -5068,9 +5082,8 @@ statement: error { /* * ISO defines ON EXCEPTION only for Format 3 (screen). We - * implement extensions defined by MF and Fujitsu (and us) to - * use ACCEPT to interact with the command line and the - * environment. + * implement extensions defined by MF and Fujitsu to use ACCEPT + * to interact with the command line and the environment. * * ISO ACCEPT and some others are implemented in accept_body, * before the parser sees any ON EXCEPTION. In those cases @@ -5085,6 +5098,9 @@ accept: accept_body end_accept { switch( $accept_body.func ) { case accept_done_e: break; + case accept_e: + parser_accept(*$1.into, $1.special, nullptr, nullptr); + break; case accept_command_line_e: if( $1.from->field == NULL ) { // take next command-line arg parser_accept_command_line(*$1.into, argi, NULL, NULL); @@ -5108,6 +5124,9 @@ accept: accept_body end_accept { error_msg(@ec, "ON EXCEPTION valid only " "with ENVIRONMENT or COMMAND-LINE(n)"); break; + case accept_e: + parser_accept(*$1.into, $1.special, $ec.on_error, $ec.not_error); + break; case accept_command_line_e: if( $1.from->field == NULL ) { // take next command-line arg parser_accept_command_line(*$1.into, argi, @@ -5139,7 +5158,7 @@ end_accept: %empty %prec ACCEPT accept_body: accept_refer { $$.func = accept_done_e; - parser_accept(*$1, CONSOLE_e); + parser_accept(*$1, CONSOLE_e, nullptr, nullptr); } | accept_refer FROM DATE { @@ -5198,29 +5217,15 @@ accept_body: accept_refer } | accept_refer FROM acceptable { - cbl_field_t *argc = register_find("_ARGI"); - switch( $acceptable->id ) { - case ARG_NUM_e: - $$.func = accept_command_line_e; - $$.into = $1; - $$.from = new_reference(argc); - break; - case ARG_VALUE_e: - $$.func = accept_command_line_e; - $$.into = $1; - $$.from = cbl_refer_t::empty(); - break; - default: - $$.func = accept_done_e; - parser_accept( *$1, $acceptable->id ); - } + $$.func = accept_e; + $$.into = $1; + $$.special = $acceptable->id; } | accept_refer FROM ENVIRONMENT envar { $$.func = accept_envar_e; $$.into = $1; $$.from = $envar; - //// parser_accept_envar( *$1, *$envar ); } | accept_refer FROM COMMAND_LINE { @@ -5232,7 +5237,6 @@ accept_body: accept_refer $$.func = accept_command_line_e; $$.into = $1; $$.from = $expr; - //// parser_accept_command_line(*$1, $expr->field ); } | accept_refer FROM COMMAND_LINE_COUNT { $$.func = accept_done_e; @@ -5285,7 +5289,7 @@ accept_except: EXCEPTION { $$.not_error = NULL; $$.on_error = label_add(LblArith, - uniq_label("accept"), yylineno); + uniq_label("accept"), @1.first_line); if( !$$.on_error ) YYERROR; parser_accept_exception( $$.on_error ); @@ -5320,15 +5324,54 @@ acceptable: device_name error_msg(@NAME, "no such special name '%s'", $NAME); YYERROR; } + if( ENV_NAME_e == *special_type ) { + error_msg(@NAME, "cannot ACCEPT FROM %qs", $NAME); + YYERROR; + } // Add the name now, as a convenience. - cbl_special_name_t special = { 0, *special_type }; + int token = 0; + switch(*special_type) { + case ARG_NUM_e: token = ARGUMENT_NUMBER; break; + case ARG_VALUE_e: token = ARGUMENT_VALUE; break; + case ENV_VALUE_e: token = ENVIRONMENT_VALUE; break; + + case ENV_NAME_e: + default: + error_msg(@NAME, "cannot ACCEPT FROM %qs", $NAME); + YYERROR; + break; + } + cbl_special_name_t special = { token, *special_type }; namcpy(@NAME, special.name, $NAME); symbol_elem_t *e = symbol_special_add(PROGRAM, &special); $$ = cbl_special_name_of(e); + cbl_special_name_t& unused(*$$); + assert(unused.id); } assert($$); } + | ENVIRONMENT_VALUE { + // Add the name now, as a convenience. + cbl_special_name_t special = + { ENVIRONMENT_VALUE, ENV_VALUE_e, "ENVIRONMENT-VALUE" }; + symbol_elem_t *e = symbol_special_add(PROGRAM, &special); + $$ = cbl_special_name_of(e); + } + | ARGUMENT_NUMBER { + // Add the name now, as a convenience. + cbl_special_name_t special = + { ARGUMENT_NUMBER, ARG_NUM_e, "ARGUMENT-NUMBER" }; + symbol_elem_t *e = symbol_special_add(PROGRAM, &special); + $$ = cbl_special_name_of(e); + } + | ARGUMENT_VALUE { + // Add the name now, as a convenience. + cbl_special_name_t special = + { ARGUMENT_VALUE, ARG_VALUE_e, "ARGUMENT-VALUE" }; + symbol_elem_t *e = symbol_special_add(PROGRAM, &special); + $$ = cbl_special_name_of(e); + } ; add: add_impl end_add { ast_add($1); } @@ -5558,46 +5601,18 @@ compute_expr: '=' { } ; -display: disp_body end_display +display: disp_body end_display[advance] { - std::vector <cbl_refer_t> args($1.vargs->args.size()); - std::copy( $1.vargs->args.begin(), $1.vargs->args.end(), args.begin() ); - if( $1.special && $1.special->id == ARG_NUM_e ) { - if( $1.vargs->args.size() != 1 ) { - error_msg(@1, "ARGUMENT-NUMBER can be set to only one value"); - } - const cbl_refer_t& src( $1.vargs->args.front() ); - cbl_field_t *dst = register_find("_ARGI"); - parser_move( dst, src ); - } else { - parser_display($1.special, - args.empty()? NULL : args.data(), args.size(), - DISPLAY_ADVANCE); - } - current.declaratives_evaluate(); - } - | disp_body NO ADVANCING end_display - { - std::vector <cbl_refer_t> args($1.vargs->args.size()); - std::copy( $1.vargs->args.begin(), $1.vargs->args.end(), args.begin() ); - - if( $1.special && $1.special->id == ARG_NUM_e ) { - if( $1.vargs->args.size() != 1 ) { - error_msg(@1, "ARGUMENT-NUMBER can be set to only one value"); - } - const cbl_refer_t& src( $1.vargs->args.front() ); - cbl_field_t *dst = register_find("_ARGI"); - parser_move( dst, src ); - } else { - parser_display($1.special, - args.empty()? NULL : args.data(), args.size(), - DISPLAY_NO_ADVANCE); - } + std::vector <cbl_refer_t> args($1.vargs->args.begin(), + $1.vargs->args.end()); + parser_display($1.special, args, $advance); current.declaratives_evaluate(); } ; -end_display: %empty - | END_DISPLAY +end_display: %empty { $$ = DISPLAY_ADVANCE; } + | END_DISPLAY { $$ = DISPLAY_ADVANCE; } + | NO ADVANCING { $$ = DISPLAY_NO_ADVANCE; } + | NO ADVANCING END_DISPLAY { $$ = DISPLAY_NO_ADVANCE; } ; disp_body: disp_vargs[vargs] { @@ -5628,14 +5643,48 @@ disp_upon: device_name { error_msg(@NAME, "no such special name '%s'", $NAME); YYERROR; } - // Add the name now, as a convenience. - cbl_special_name_t special = { 0, *special_type }; + // Add the name now, as a convenience. + // These may come through as a NAME, depending on how scanned. + int token = 0; + switch(*special_type) { + case ARG_NUM_e: token = ARGUMENT_NUMBER; break; + case ENV_NAME_e: token = ENVIRONMENT_NAME; break; + case ENV_VALUE_e: token = ENVIRONMENT_VALUE; break; + + case ARG_VALUE_e: + default: + error_msg(@NAME, "cannot DISPLAY UPON %qs", $NAME); + YYERROR; + break; + } + cbl_special_name_t special = { token, *special_type }; namcpy(@NAME, special.name, $NAME); e = symbol_special_add(PROGRAM, &special); } $$ = cbl_special_name_of(e); } + | ARGUMENT_NUMBER { + // Add the name now, as a convenience. + cbl_special_name_t special = + { ARGUMENT_NUMBER, ARG_NUM_e, "ARGUMENT-NUMBER" }; + symbol_elem_t *e = symbol_special_add(PROGRAM, &special); + $$ = cbl_special_name_of(e); + } + | ENVIRONMENT_NAME { + // Add the name now, as a convenience. + cbl_special_name_t special = + { ENVIRONMENT_NAME, ENV_NAME_e, "ENVIRONMENT-NAME" }; + symbol_elem_t *e = symbol_special_add(PROGRAM, &special); + $$ = cbl_special_name_of(e); + } + | ENVIRONMENT_VALUE { + // Add the name now, as a convenience. + cbl_special_name_t special = + { ENVIRONMENT_VALUE, ENV_VALUE_e, "ENVIRONMENT-VALUE" }; + symbol_elem_t *e = symbol_special_add(PROGRAM, &special); + $$ = cbl_special_name_of(e); + } ; divide: divide_impl end_divide { ast_divide($1); } @@ -5733,14 +5782,14 @@ end_program: end_program1[end] '.' gcc_unreachable(); } if( !matches ) { - error_msg(@end, "END %s %s does not match " + error_msg($end.loc, "END %s %s does not match " "%<IDENTIFICATION DIVISION %s%>", token_name, name, prog->name); YYERROR; } if( 0 != strcasecmp(prog->name, name) ) { - error_msg(@end, "END PROGRAM '%s' does not match PROGRAM-ID '%s'", + error_msg($end.loc, "END PROGRAM '%s' does not match PROGRAM-ID '%s'", name, prog->name); YYERROR; } @@ -5773,20 +5822,24 @@ end_program: end_program1[end] '.' ; end_program1: END_PROGRAM namestr[name] { + $$.loc = @name; $$.token = END_PROGRAM; $$.name = $name; } | END_FUNCTION namestr[name] { + $$.loc = @name; $$.token = END_FUNCTION; $$.name = $name; } | END_PROGRAM '.' // error { + $$.loc = @1; $$.token = END_PROGRAM; } | END_FUNCTION '.' // error { + $$.loc = @1; $$.token = END_FUNCTION; } ; @@ -6622,7 +6675,7 @@ name: qname auto name = names.front(); names.pop_front(); auto e = symbol_field_forward_add(PROGRAM, parent, - name, yylineno); + name, @1.first_line); if( !e ) YYERROR; symbol_field_location( symbol_index(e), @qname ); parent = symbol_index(e); @@ -6652,6 +6705,10 @@ ctx_name: NAME context_word: APPLY { static char s[] ="APPLY"; $$ = s; } // screen description entry + | ARGUMENT_NUMBER { static char s[] ="ARGUMENT-NUMBER"; + $$ = s; } // Display Upon / Accept From + | ARGUMENT_VALUE { static char s[] ="ARGUMENT-VALUE"; + $$ = s; } // Accept From | ARITHMETIC { static char s[] ="ARITHMETIC"; $$ = s; } // OPTIONS paragraph | ATTRIBUTE { static char s[] ="ATTRIBUTE"; @@ -6688,6 +6745,10 @@ context_word: APPLY { static char s[] ="APPLY"; $$ = s; } // ERASE clause in a screen description entry | ENTRY_CONVENTION { static char s[] ="ENTRY-CONVENTION"; $$ = s; } // OPTIONS paragraph + | ENVIRONMENT_NAME { static char s[] ="ENVIRONMENT-NAME"; + $$ = s; } // Display Upon + | ENVIRONMENT_VALUE { static char s[] ="ENVIRONMENT-VALUE"; + $$ = s; } // Display Upon / Accept From | ERASE { static char s[] ="ERASE"; $$ = s; } // screen description entry | EXPANDS { static char s[] ="EXPANDS"; @@ -7036,9 +7097,9 @@ arith_err: SIZE_ERROR *ptgt = $1 == NOT? current.compute_not_error() : current.compute_on_error(); } else { - *ptgt = label_add(LblArith, uniq_label("arith"), yylineno); + *ptgt = label_add(LblArith, uniq_label("arith"), @1.first_line); } - (*ptgt)->lain = yylineno; + (*ptgt)->lain = @1.first_line; parser_arith_error( *ptgt ); } ; @@ -8754,12 +8815,12 @@ search_1_body: name[table] search_varying[varying] cbl_name_t label_name; auto len = snprintf(label_name, sizeof(label_name), - "linear_search_%d", yylineno); + "linear_search_%d", @1.first_line); if( ! (0 < len && len < int(sizeof(label_name))) ) { gcc_unreachable(); } cbl_label_t *name = label_add( LblSearch, - label_name, yylineno ); + label_name, @1.first_line ); auto varying($varying); if( index == varying ) varying = NULL; parser_lsearch_start( name, $table, index, varying ); @@ -8812,9 +8873,9 @@ search_binary: SEARCH ALL search_2_body search_2_cases search_2_body: name[table] { statement_begin(@$, SEARCH); - char *label_name = xasprintf("binary_search_%d", yylineno); + char *label_name = xasprintf("binary_search_%d", @1.first_line); cbl_label_t *name = label_add( LblSearch, - label_name, yylineno ); + label_name, @1.first_line ); parser_bsearch_start( name, $table ); search_alloc(name); } @@ -9759,7 +9820,7 @@ call_except: EXCEPTION { $$.not_error = NULL; $$.on_error = label_add(LblArith, - uniq_label("call"), yylineno); + uniq_label("call"), @1.first_line); if( !$$.on_error ) YYERROR; parser_call_exception( $$.on_error ); @@ -9772,7 +9833,7 @@ call_except: EXCEPTION { $$.not_error = NULL; $$.on_error = label_add(LblArith, - uniq_label("call"), yylineno); + uniq_label("call"), @1.first_line); if( !$$.on_error ) YYERROR; parser_call_exception( $$.on_error ); @@ -9828,7 +9889,7 @@ go_to: GOTO labels[args] } for( auto& label : $args->elems ) { - label->used = yylineno; + label->used = @2.first_line; } cbl_label_t *arg = $args->elems.front(); parser_goto( cbl_refer_t(), 1, &arg ); @@ -9840,7 +9901,7 @@ go_to: GOTO labels[args] std::vector <cbl_label_t *> args($args->elems.size()); std::copy($args->elems.begin(), $args->elems.end(), args.begin()); for( auto& label : $args->elems ) { - label->used = yylineno; + label->used = @2.first_line; } parser_goto( *$value, args.size(), args.data() ); } @@ -9860,7 +9921,7 @@ resume: RESUME NEXT STATEMENT { statement_begin(@1, RESUME); parser_clear_exception(); - $tgt->used = yylineno; + $tgt->used = @1.first_line; parser_goto( cbl_refer_t(), 1, &$tgt ); } ; @@ -10035,7 +10096,7 @@ on_overflow: OVERFLOW_kw { $$.not_error = NULL; $$.on_error = label_add(LblString, - uniq_label("string"), yylineno); + uniq_label("string"), @1.first_line); if( !$$.on_error ) YYERROR; parser_string_overflow( $$.on_error ); @@ -11377,6 +11438,7 @@ void ast_call( const YYLTYPE& loc, cbl_refer_t name, const cbl_refer_t& returnin */ static bool possible_ec() { + cbl_enabled_exceptions_t& enabled_exceptions( cdf_enabled_exceptions() ); bool format_1 = current.declaratives.has_format_1(); bool enabled = 0xFF < (current.declaratives.status() @@ -11399,6 +11461,7 @@ possible_ec() { */ static void statement_epilog( int token ) { + cbl_enabled_exceptions_t& enabled_exceptions( cdf_enabled_exceptions() ); if( possible_ec() && token != CONTINUE ) { if( enabled_exceptions.size() ) { current.declaratives_evaluate(); @@ -11461,9 +11524,11 @@ keyword_str( int token ) { return ascii; } - return tokens.name_of(token); + return cdf_tokens.name_of(token); } +bool iso_cobol_word( const std::string& name, bool include_context ); + /* * Return the token for the Cobol name, unless it is a function name. The * lexer uses keyword_tok to determine if what appears to be a NAME is in fact @@ -11474,15 +11539,14 @@ keyword_str( int token ) { */ // tokens.h is generated as needed from parse.h with tokens.h.gen -tokenset_t::tokenset_t() { +current_tokens_t::tokenset_t::tokenset_t() { #include "token_names.h" } -bool iso_cobol_word( const std::string& name, bool include_context ); // Look up the lowercase form of a keyword, excluding some CDF names. int -tokenset_t::find( const cbl_name_t name, bool include_intrinsics ) { +current_tokens_t::tokenset_t::find( const cbl_name_t name, bool include_intrinsics ) { static const cbl_name_t non_names[] = { // including CDF NAMES, and "SWITCH" "CHECKING", "LIST", "LOCATION", "MAP", "SWITCH", }, * const eonames = non_names + COUNT_OF(non_names); @@ -11532,7 +11596,7 @@ tokenset_t::find( const cbl_name_t name, bool include_intrinsics ) { int keyword_tok( const char * text, bool include_intrinsics ) { - return tokens.find(text, include_intrinsics); + return cdf_tokens.find(text, include_intrinsics); } static inline size_t @@ -13074,7 +13138,7 @@ cobol_dialect_set( cbl_dialect_t dialect ) { break; case dialect_gnu_e: if( 0 == (cbl_dialects & dialect) ) { // first time - tokens.equate(YYLTYPE(), "BINARY-DOUBLE", "BINARY-C-LONG"); + cdf_tokens.equate(YYLTYPE(), "BINARY-DOUBLE", "BINARY-C-LONG"); } break; } diff --git a/gcc/cobol/parse_ante.h b/gcc/cobol/parse_ante.h index 105afe9..fa06e6c 100644 --- a/gcc/cobol/parse_ante.h +++ b/gcc/cobol/parse_ante.h @@ -935,165 +935,11 @@ teed_up_names() { return name_queue_t::namelist_of( name_queue.peek() ); } -class tokenset_t { - // token_names is initialized from a generated header file. - std::vector<const char *>token_names; // position indicates token value - std::map <std::string, int> tokens; // aliases - std::set<std::string> cobol_words; // Anything in COBOL-WORDS may appear only once. - public: - static std::string - lowercase( const cbl_name_t name ) { - cbl_name_t lname; - std::transform(name, name + strlen(name) + 1, lname, ftolower); - return lname; - } - static std::string - uppercase( const cbl_name_t name ) { - cbl_name_t uname; - std::transform(name, name + strlen(name) + 1, uname, ftoupper); - return uname; - } - - public: - tokenset_t(); - int find( const cbl_name_t name, bool include_intrinsics ); - - bool equate( const YYLTYPE& loc, int token, - const cbl_name_t name, const cbl_name_t verb = "EQUATE") { - auto lname( lowercase(name) ); - auto cw = cobol_words.insert(lname); - if( ! cw.second ) { - error_msg(loc, "COBOL-WORDS %s: %s may appear but once", verb, name); - return false; - } - auto p = tokens.find(lowercase(name)); - bool fOK = p == tokens.end(); - if( fOK ) { // name not already in use - tokens[lname] = token; - dbgmsg("%s:%d: %d has alias %s", __func__, __LINE__, token, name); - } else { - error_msg(loc, "%s: %s already defined as a token", verb, name); - } - return fOK; - } - bool undefine( const YYLTYPE& loc, - const cbl_name_t name, const cbl_name_t verb = "UNDEFINE" ) { - auto lname( lowercase(name) ); - auto cw = cobol_words.insert(lname); - if( ! cw.second ) { - error_msg(loc, "COBOL-WORDS %s: %s may appear but once", verb, name); - return false; - } - - // Do not erase generic, multi-type tokens COMPUTATIONAL and BINARY_INTEGER. - if( binary_integer_usage_of(name) ) { - dbgmsg("%s:%d: generic %s remains valid as a token", __func__, __LINE__, name); - return true; - } - - auto p = tokens.find(lname); - bool fOK = p != tokens.end(); - if( fOK ) { // name in use - tokens.erase(p); - } else { - error_msg(loc, "%s: %s not defined as a token", verb, name); - } - dbgmsg("%s:%d: %s removed as a valid token name", __func__, __LINE__, name); - return fOK; - } - - bool substitute( const YYLTYPE& loc, - const cbl_name_t extant, int token, const cbl_name_t name ) { - return - equate( loc, token, name, "SUBSTITUTE" ) - && - undefine( loc, extant, "SUBSTITUTE" ); - } - bool reserve( const YYLTYPE& loc, const cbl_name_t name ) { - auto lname( lowercase(name) ); - auto cw = cobol_words.insert(lname); - if( ! cw.second ) { - error_msg(loc, "COBOL-WORDS RESERVE: %s may appear but once", name); - return false; - } - tokens[lname] = -42; - return true; - } - int redefined_as( const cbl_name_t name ) { - auto lname( lowercase(name) ); - if( cobol_words.find(lname) != cobol_words.end() ) { - auto p = tokens.find(lname); - if( p != tokens.end() ) { - return p->second; - } - } - return 0; - } - const char * name_of( int tok ) const { - tok -= (255 + 3); - gcc_assert(0 <= tok && size_t(tok) < token_names.size()); - return tok < 0? "???" : token_names[tok]; - } -}; - -class current_tokens_t { - tokenset_t tokens; - public: - current_tokens_t() {} - int find( const cbl_name_t name, bool include_intrinsics ) { - return tokens.find(name, include_intrinsics); - } - bool equate( const YYLTYPE& loc, const cbl_name_t keyword, const cbl_name_t alias ) { - int token; - if( 0 == (token = binary_integer_usage_of(keyword)) ) { - if( 0 == (token = keyword_tok(keyword)) ) { - error_msg(loc, "EQUATE %s: not a valid token", keyword); - return false; - } - } - auto name = keyword_alias_add(tokens.uppercase(keyword), - tokens.uppercase(alias)); - if( name != keyword ) { - error_msg(loc, "EQUATE: %s is already an alias for %s", alias, name.c_str()); - return false; - } - return tokens.equate(loc, token, alias); - } - bool undefine( const YYLTYPE& loc, cbl_name_t keyword ) { - return tokens.undefine(loc, keyword); - } - bool substitute( const YYLTYPE& loc, const cbl_name_t keyword, const cbl_name_t alias ) { - int token; - if( 0 == (token = binary_integer_usage_of(keyword)) ) { - if( 0 == (token = keyword_tok(keyword)) ) { - error_msg(loc, "SUBSTITUTE %s: not a valid token", keyword); - return false; - } - } - auto name = keyword_alias_add(tokens.uppercase(keyword), - tokens.uppercase(alias)); - if( name != keyword ) { - error_msg(loc, "SUBSTITUTE: %s is already an alias for %s", alias, name.c_str()); - return false; - } - - dbgmsg("%s:%d: %s (%d) will have alias %s", __func__, __LINE__, keyword, token, alias); - return tokens.substitute(loc, keyword, token, alias); - } - bool reserve( const YYLTYPE& loc, const cbl_name_t name ) { - return tokens.reserve(loc, name); - } - int redefined_as( const cbl_name_t name ) { - return tokens.redefined_as(name); - } - const char * name_of( int tok ) const { - return tokens.name_of(tok); - } -} tokens; +#define cdf_tokens cdf_current_tokens() int redefined_token( const cbl_name_t name ) { - return tokens.redefined_as(name); + return cdf_tokens.redefined_as(name); } struct file_list_t { @@ -1475,7 +1321,6 @@ class prog_descr_t { } } } locale; - cbl_call_convention_t call_convention; cbl_options_t options; explicit prog_descr_t( size_t isymbol ) @@ -1484,9 +1329,7 @@ class prog_descr_t { , paragraph(NULL) , section(NULL) , collating_sequence(NULL) - { - call_convention = current_call_convention(); - } + {} std::set<std::string> external_targets() { std::set<std::string> externals; @@ -1575,24 +1418,13 @@ static cbl_label_t * implicit_section(); class program_stack_t : protected std::stack<prog_descr_t> { struct pending_t { - cbl_call_convention_t call_convention; bool initial; - pending_t() - : call_convention(cbl_call_convention_t(0)) - , initial(false) - {} + pending_t() : initial(false) {} } pending; public: - cbl_call_convention_t - pending_call_convention( cbl_call_convention_t convention ) { - return pending.call_convention = convention; - } bool pending_initial() { return pending.initial = true; } void push( prog_descr_t descr ) { - cbl_call_convention_t call_convention = cbl_call_cobol_e; - if( !empty() ) call_convention = top().call_convention; - descr.call_convention = call_convention; std::stack<prog_descr_t>& me(*this); me.push(descr); } @@ -1618,9 +1450,6 @@ class program_stack_t : protected std::stack<prog_descr_t> { } void apply_pending() { - if( size() == 1 && 0 != pending.call_convention ) { - top().call_convention = pending.call_convention; - } if( pending.initial ) { auto e = symbol_at(top().program_index); auto prog(cbl_label_of(e)); @@ -2027,19 +1856,6 @@ static class current_t { return programs.top().options.default_round = mode; } - cbl_call_convention_t - call_convention() { - return programs.empty()? cbl_call_cobol_e : programs.top().call_convention; - } - cbl_call_convention_t - call_convention( cbl_call_convention_t convention) { - if( programs.empty() ) { - return programs.pending_call_convention(convention); - } - auto& prog( programs.top() ); - return prog.call_convention = convention; - } - const char * locale() { return programs.empty()? NULL : programs.top().locale.os_name; @@ -2137,6 +1953,7 @@ static class current_t { * ISO, in new_program. */ std::set<std::string> end_program() { + cbl_enabled_exceptions_t& enabled_exceptions( cdf_enabled_exceptions() ); if( enabled_exceptions.size() ) { declaratives_evaluate(); } @@ -2427,15 +2244,6 @@ current_rounded_mode( cbl_round_t rounded) { #endif static cbl_round_t current_rounded_mode( int token ); -cbl_call_convention_t -current_call_convention() { - return current.call_convention(); -} -cbl_call_convention_t -current_call_convention( cbl_call_convention_t convention) { - return current.call_convention(convention); -} - size_t program_level() { return current.program_level(); } static size_t constant_index( int token ); @@ -2909,17 +2717,6 @@ group_attr( const cbl_field_t * field ) { return p->attr; } -static struct symbol_elem_t * -field_of( const char F[], int L, const char name[] ) { - struct symbol_elem_t *e = symbol_field(PROGRAM, 0, name); - if( !e ) { - cbl_internal_error("%s:%d: no symbol '%s' found", F, L, name); - } - assert( procedure_div_e != current_division ); - return e; -} -#define field_of( F ) field_of(__func__, __LINE__, (F)) - static struct cbl_field_t * field_add( const YYLTYPE& loc, cbl_field_t *field ) { switch(current_data_section) { diff --git a/gcc/cobol/scan.l b/gcc/cobol/scan.l index 2fc4aea..8b5dc25 100644 --- a/gcc/cobol/scan.l +++ b/gcc/cobol/scan.l @@ -83,6 +83,8 @@ NONWORD [^[:alnum:]$_-]+ SPC [[:space:]]+ OSPC [[:space:]]* +BLANK [[:blank:]]+ +OBLANK [[:blank:]]* EOL \r?\n BLANK_EOL [[:blank:]]*{EOL} BLANK_OEOL [[:blank:]]*{EOL}? @@ -160,7 +162,7 @@ COMMA [,;][[:blank:]]* ISNT (IS{SPC})?NOT -COMMENTARY DATE-COMPILED|DATE-WRITTEN|INSTALLATION|SECURITY +COMMENTARY AUTHOR|DATE-COMPILED|DATE-WRITTEN|INSTALLATION|SECURITY SORT_MERGE SORT(-MERGE)? @@ -182,7 +184,7 @@ LINE_DIRECTIVE ^[#]line{SPC}[[:alnum:]]+{SPC}[""''].+\n %x procedure_div ident_state addr_of function classify %x program_id_state comment_entries -%x author_state date_state field_level field_state dot_state +%x date_state field_level field_state dot_state %x numeric_state name_state %x quoted1 quoted2 quoteq %x picture picture_count integer_count @@ -238,30 +240,23 @@ WORKING-STORAGE{SPC}SECTION { yy_push_state(field_state); return WORKING_STORAGE_SECT; } LOCAL-STORAGE{SPC}SECTION { - yy_push_state(field_state); - return LOCAL_STORAGE_SECT; } -WORKING-STORAGE { - return WORKING_STORAGE; } -LOCAL-STORAGE { - return LOCAL_STORAGE; } -SCREEN { - return SCREEN; } + yy_push_state(field_state); + return LOCAL_STORAGE_SECT; } +WORKING-STORAGE { return WORKING_STORAGE; } +LOCAL-STORAGE { return LOCAL_STORAGE; } +SCREEN { return SCREEN; } LINKAGE{SPC}SECTION { yy_push_state(field_state); return LINKAGE_SECT; } -FUNCTION-ID { yy_push_state(ident_state); - yy_push_state(program_id_state); - yy_push_state(name_state); return FUNCTION; } - -PROGRAM-ID { yy_push_state(ident_state); - yy_push_state(program_id_state); - yy_push_state(name_state); return PROGRAM_ID; } +FUNCTION-ID{OSPC}{DOTSEP}? { yy_push_state(ident_state); + yy_push_state(program_id_state); + yy_push_state(name_state); return FUNCTION; } -PROGRAM-ID/{DOTEOL} { yy_push_state(ident_state); - yy_push_state(name_state); - yy_push_state(dot_state); return PROGRAM_ID; } +PROGRAM-ID{OSPC}{DOTSEP}? { yy_push_state(ident_state); + yy_push_state(program_id_state); + yy_push_state(name_state); return PROGRAM_ID; } PROCEDURE{SPC}DIVISION { yy_push_state(procedure_div); return PROCEDURE_DIV; } @@ -272,30 +267,18 @@ PROCEDURE{SPC}DIVISION { yy_push_state(procedure_div); } <ident_state>{ + {BLANK_OEOL} ID(ENTIFICATION)?{SPC}DIVISION { myless(0); yy_pop_state(); } + (ENVIRONMENT|DATA|PROCEDURE){SPC}DIVISION { + myless(0); yy_pop_state(); } + OPTIONS { myless(0); yy_pop_state(); } + AS{SPC}[""] { yy_push_state(quoted2); return AS; } AS{SPC}[''] { yy_push_state(quoted1); return AS; } IS { pop_return IS; } - OPTIONS { yy_pop_state(); myless(0); } - [[:blank:]]*(ENVIRONMENT|DATA|PROCEDURE){SPC}DIVISION/[[:space:].] { - yy_pop_state(); myless(0); } - [[:blank:]]*AUTHOR[[:blank:].]+{EOL}? { - // Might not have an EOL, but stop on one. - yy_push_state(author_state); } - - {DOTEOL} - {COMMENTARY} { BEGIN(comment_entries); } } -<author_state>{ - [[:blank:]]+ - ^{BLANK_EOL} - [^\r\n]+ { yy_pop_state(); - yylval.string = xstrdup(yytext); - } -} - <INITIAL>{ COBOL { return COBOL; } @@ -307,6 +290,15 @@ PROCEDURE{SPC}DIVISION { yy_push_state(procedure_div); yy_push_state(field_state); yy_set_bol(1); myless(0); } + + END{SPC}PROGRAM { yy_push_state(name_state); + return program_level() > 1? + END_SUBPROGRAM : END_PROGRAM; } + + END{SPC}FUNCTION { yy_push_state(name_state); + return program_level() > 1? + END_SUBPROGRAM /*invalid*/ : + END_FUNCTION; } } <INITIAL,procedure_div,cdf_state>{ @@ -444,6 +436,11 @@ STDOUT { return STDOUT; } STDERR { return STDERR; } SYSERR { return STDERR; } +ARGUMENT-NUMBER { return ARGUMENT_NUMBER; } +ARGUMENT-VALUE { return ARGUMENT_VALUE; } +ENVIRONMENT-NAME { return ENVIRONMENT_NAME; } +ENVIRONMENT-VALUE { return ENVIRONMENT_VALUE; } + CANCEL { return CANCEL; } COMMIT { return COMMIT; } COMMON { return COMMON; } @@ -541,7 +538,7 @@ SECTION{SPC}[+-]?{INTEGERZ}/{OSPC}{DOTSEP} { auto eotext = yytext + yyleng; auto p = std::find_if(yytext, eotext, fisspace); p = std::find_if(p, eotext, nonspace); - yylval.string = p; + yylval.string = xstrdup(p); return SECTION; } @@ -1384,45 +1381,36 @@ USE({SPC}FOR)? { return USE; } } <program_id_state>{ - ^[[:blank:]]+ - ^{BLANK_EOL} + {BLANK_OEOL} (IS)?[[:space:]] + AS/{SPC} { myless(0); yy_pop_state(); } /* => ident_state */ - COMMON/[.]|{SPC}[[:alnum:].] { return COMMON; } - INITIAL/[.]|{SPC}[[:alnum:].] { return INITIAL_kw; } - RECURSIVE { return RECURSIVE; } - PROGRAM/[.]|{SPC}[[:alnum:].] { return PROGRAM_kw; } - - INITIAL { pop_return INITIAL_kw; } - COMMON { pop_return COMMON; } - PROGRAM { pop_return PROGRAM; } + INITIAL { return INITIAL_kw; } + COMMON { return COMMON; } + RECURSIVE { return RECURSIVE; } + PROGRAM { return PROGRAM_kw; } - AS/{SPC} { myless(0); yy_pop_state(); } /* => ident_state */ - [[:blank:]]*{DOTSEP}[[:blank:].]+{EOL} { pop_return '.'; } - {DOTEOL} { pop_return '.'; } + {DOTSEP} { pop_return '.'; } } -<name_state>{ - ^[[:blank:]]+ - ^{BLANK_EOL} - {NAME} | - {NAME}/{OSPC}[.] { yy_pop_state(); - yylval.string = xstrdup(yytext); return NAME; } +<name_state>{ /* Either pop from here, or let the quoted state pop */ + {BLANK_OEOL} + {NAME} { yy_pop_state(); + yylval.string = xstrdup(yytext); + return NAME; + } Z?[''] { yylval.literal.set_prefix(yytext, yyleng-1); - yy_push_state(quoted1); } + BEGIN(quoted1); } Z?[""] { yylval.literal.set_prefix(yytext, yyleng-1); - yy_push_state(quoted2); } - - [.]/[[:blank:]]+. { return *yytext; } + BEGIN(quoted2); } - [[:blank:]]*{DOTSEP}[[:blank:].]+{EOL} { - yy_pop_state(); myless(0); } - {DOTEOL} { yy_pop_state(); myless(0); } + . { myless(0); yy_pop_state(); + /* Should not happen for valid inputs. */ } } <dot_state>{ [[:blank:]]*[.][[:blank:].]+{EOL} { pop_return '.'; } - [[:blank:]]*[.] { pop_return '.'; } + [[:blank:]]*[.]+ { pop_return '.'; } } <date_state>{ @@ -1645,9 +1633,9 @@ B-SHIFT-RC FUNCTION { yy_push_state(function); return FUNCTION; } - SECTION{OSPC}[.]{SPC}/USE[[:space:]] { yylval.string = NULL; return SECTION; } + SECTION{OSPC}[.]+{SPC}/USE[[:space:]] { yylval.string = NULL; return SECTION; } - [.]({SPC}(EJECT|SKIP[123]))*{SPC}EXIT{OSPC}/{DOTSEP} { + [.]+({SPC}(EJECT|SKIP[123]))*{SPC}EXIT{OSPC}/{DOTSEP} { // EXIT format-1 is a "continue" statement } {NAME}/{OSPC}{DOTSEP} { @@ -2073,49 +2061,62 @@ BASIS { yy_push_state(basis); return BASIS; } if( include_debug() ) myless(7); } } - ^[ ]*>>{OSPC}IF { yy_push_state(cdf_state); return CDF_IF; } - ^[ ]*>>{OSPC}ELSE { return CDF_ELSE; } - ^[ ]*>>{OSPC}END-IF { return CDF_END_IF; } + ^[ ]*>>{OBLANK}IF { yy_push_state(cdf_state); return CDF_IF; } + ^[ ]*>>{OBLANK}ELSE { return CDF_ELSE; } + ^[ ]*>>{OBLANK}END-IF { return CDF_END_IF; } - ^[ ]*[$]{OSPC}IF { if( ! dialect_mf() ) { + ^[ ]*[$]{OBLANK}IF { if( ! dialect_mf() ) { dialect_error(yylloc, yytext, "mf"); } yy_push_state(cdf_state); return CDF_IF; } - ^[ ]*[$]{OSPC}ELSE { if( ! dialect_mf() ) { + ^[ ]*[$]{OBLANK}ELSE { if( ! dialect_mf() ) { dialect_error(yylloc, yytext, "mf"); } return CDF_ELSE; } - ^[ ]*[$]{OSPC}END { if( ! dialect_mf() ) { + ^[ ]*[$]{OBLANK}END { if( ! dialect_mf() ) { dialect_error(yylloc, yytext, "mf"); } return CDF_END_IF; } - ^[ ]*[$]{OSPC}SET({SPC}CONSTANT)? { + ^[ ]*[$]{OBLANK}SET({SPC}CONSTANT)? { if( ! dialect_mf() ) dialect_error(yylloc, yytext, "mf"); yy_push_state(cdf_state); return CDF_DEFINE; } - ^[ ]*>>{OSPC}EVALUATE { return CDF_EVALUATE; } - ^[ ]*>>{OSPC}WHEN { return CDF_WHEN; } - ^[ ]*>>{OSPC}END-EVALUATE { return CDF_END_EVALUATE; } + ^[ ]*>>{OBLANK}EVALUATE { return CDF_EVALUATE; } + ^[ ]*>>{OBLANK}WHEN { return CDF_WHEN; } + ^[ ]*>>{OBLANK}END-EVALUATE { return CDF_END_EVALUATE; } + + ^[ ]*>>{OBLANK}CALL-CONVENTION{BLANK}C { return CALL_VERBATIM; } + ^[ ]*>>{OBLANK}CALL-CONVENTION{BLANK}COBOL { return CALL_COBOL; } + ^[ ]*>>{OBLANK}CALL-CONVENTION{BLANK}VERBATIM { return CALL_VERBATIM; } + + ^[ ]*>>{OBLANK}DEFINE { yy_push_state(cdf_state); return CDF_DEFINE; } + ^[ ]*>>{OBLANK}DISPLAY { return CDF_DISPLAY; } + ^[ ]*>>{OBLANK}TURN { yy_push_state(exception); return TURN; } + ^[ ]*>>{OBLANK}COBOL-WORDS { yy_push_state(cobol_words); return COBOL_WORDS; } - ^[ ]*>>{OSPC}CALL-CONVENTION{SPC}C { return CALL_VERBATIM; } - ^[ ]*>>{OSPC}CALL-CONVENTION{SPC}COBOL { return CALL_COBOL; } - ^[ ]*>>{OSPC}CALL-CONVENTION{SPC}VERBATIM { return CALL_VERBATIM; } + ^[ ]*>>{OBLANK}SOURCE{BLANK}FORMAT { return SOURCE_FORMAT; } - ^[ ]*>>{OSPC}DEFINE { yy_push_state(cdf_state); return CDF_DEFINE; } - ^[ ]*>>{OSPC}DISPLAY { return CDF_DISPLAY; } - ^[ ]*>>{OSPC}TURN { yy_push_state(exception); return TURN; } - ^[ ]*>>{OSPC}COBOL-WORDS { yy_push_state(cobol_words); return COBOL_WORDS; } + ^[ ]*>>{OBLANK}PUSH { return CDF_PUSH; } + ^[ ]*>>{OBLANK}POP { return CDF_POP; } - ^[ ]*>>{OSPC}{NAME} { + ^[ ]*>>{OBLANK}{NAME} { error_msg(yylloc, "unknown CDF token: %s", yytext); } + OTHER { return OTHER; } OVERRIDE { return OVERRIDE; } PARAMETER { return PARAMETER_kw; } THRU { return THRU; } TRUE { return TRUE_kw; } + + ALL { return ALL; } + CALL-CONVENTION { return CALL_CONVENTION; } + COBOL-WORDS { return COBOL_WORDS; } + DEFINE { return CDF_DEFINE; } + SOURCE{BLANK}FORMAT { return SOURCE_FORMAT; } + } <cobol_words>{ @@ -2165,7 +2166,7 @@ BASIS { yy_push_state(basis); return BASIS; } <*>OR { return OR; } <*>AND { return AND; } -<*>{DOTSEP}[[:blank:].]+$ { return '.'; } +<*>{DOTSEP} { return '.'; } <*>[().=*/+&-] { return *yytext; } <*>[[:blank:]]+ <*>\r?\n @@ -2369,7 +2370,7 @@ BASIS { yy_push_state(basis); return BASIS; } POINTER { return POINTER; } POSITIVE { return POSITIVE; } PROCEDURE { return PROCEDURE; } - PROGRAM { return PROGRAM; } + PROGRAM { return PROGRAM_kw; } PROGRAM-ID { return PROGRAM_ID; } PROPERTY { return PROPERTY; } PROTOTYPE { return PROTOTYPE; } @@ -2411,7 +2412,7 @@ BASIS { yy_push_state(basis); return BASIS; } SCREEN { return SCREEN; } SD { return SD; } SEARCH { return SEARCH; } - SECTION { return SECTION; } + SECTION { yylval.string = NULL; return SECTION; } SELECT { return SELECT; } SENTENCE { return SENTENCE; } SEPARATE { return SEPARATE; } diff --git a/gcc/cobol/scan_ante.h b/gcc/cobol/scan_ante.h index ea304ba..6960739 100644 --- a/gcc/cobol/scan_ante.h +++ b/gcc/cobol/scan_ante.h @@ -356,6 +356,10 @@ static void level_found() { if( scanner_normal() ) parsing.need_level(false); } +/* + * Trim the scanned location by the amount about to re-scanned. + * Must be a macro because it expands yyless. + */ #define myless(N) \ do { \ auto n(N); \ diff --git a/gcc/cobol/scan_post.h b/gcc/cobol/scan_post.h index a273da9..7cf2b98 100644 --- a/gcc/cobol/scan_post.h +++ b/gcc/cobol/scan_post.h @@ -34,7 +34,6 @@ start_condition_str( int sc ) { switch(sc) { case INITIAL: state = "INITIAL"; break; case addr_of: state = "addr_of"; break; - case author_state: state = "author_state"; break; case basis: state = "basis"; break; case bool_state: state = "bool_state"; break; case cdf_state: state = "cdf_state"; break; @@ -159,6 +158,8 @@ is_cdf_token( int token ) { case CDF_DISPLAY: case CDF_IF: case CDF_ELSE: case CDF_END_IF: case CDF_EVALUATE: case CDF_WHEN: case CDF_END_EVALUATE: + case CDF_PUSH: + case CDF_POP: return true; case CALL_COBOL: case CALL_VERBATIM: diff --git a/gcc/cobol/symbols.cc b/gcc/cobol/symbols.cc index 089c9c1..4b34729 100644 --- a/gcc/cobol/symbols.cc +++ b/gcc/cobol/symbols.cc @@ -1768,8 +1768,8 @@ symbols_update( size_t first, bool parsed_ok ) { if( e == symbols_end() ) { // no field redefines the file's default record auto file = cbl_file_of(symbol_at(field->parent)); - ERROR_FIELD(field, "line %d: %s lacks a file description", - file->line, file->name); + ERROR_FIELD(field, "%s lacks a file description", + file->name); return 0; } } @@ -2180,14 +2180,22 @@ symbol_table_init(void) { } static symbol_elem_t environs[] = { + { symbol_elem_t{ 0, cbl_special_name_t{0, CONSOLE_e, "CONSOLE", 0, "/dev/stdout"}} }, // stdout in DISPLAY; stdin in ACCEPT + + { symbol_elem_t{ 0, cbl_special_name_t{0, STDIN_e, "STDIN", 0, "/dev/stdin"}} }, { symbol_elem_t{ 0, cbl_special_name_t{0, SYSIN_e, "SYSIN", 0, "/dev/stdin"}} }, - { symbol_elem_t{ 0, cbl_special_name_t{0, SYSIPT_e, "SYSIPT", 0, "/dev/stdout"}} }, + { symbol_elem_t{ 0, cbl_special_name_t{0, SYSIPT_e, "SYSIPT", 0, "/dev/stdin"}} }, + + { symbol_elem_t{ 0, cbl_special_name_t{0, STDOUT_e, "STDOUT", 0, "/dev/stdout"}} }, { symbol_elem_t{ 0, cbl_special_name_t{0, SYSOUT_e, "SYSOUT", 0, "/dev/stdout"}} }, { symbol_elem_t{ 0, cbl_special_name_t{0, SYSLIST_e, "SYSLIST", 0, "/dev/stdout"}} }, { symbol_elem_t{ 0, cbl_special_name_t{0, SYSLST_e, "SYSLST", 0, "/dev/stdout"}} }, + { symbol_elem_t{ 0, cbl_special_name_t{0, SYSPUNCH_e, "SYSPUNCH", 0, "/dev/stderr"}} }, { symbol_elem_t{ 0, cbl_special_name_t{0, SYSPCH_e, "SYSPCH", 0, "/dev/stderr"}} }, - { symbol_elem_t{ 0, cbl_special_name_t{0, CONSOLE_e, "CONSOLE", 0, "/dev/stdout"}} }, + { symbol_elem_t{ 0, cbl_special_name_t{0, STDERR_e, "STDERR", 0, "/dev/stderr"}} }, + { symbol_elem_t{ 0, cbl_special_name_t{0, SYSERR_e, "SYSERR", 0, "/dev/stderr"}} }, + { symbol_elem_t{ 0, cbl_special_name_t{0, C01_e, "C01", 0, "/dev/null"}} }, { symbol_elem_t{ 0, cbl_special_name_t{0, C02_e, "C02", 0, "/dev/null"}} }, { symbol_elem_t{ 0, cbl_special_name_t{0, C03_e, "C03", 0, "/dev/null"}} }, @@ -2207,10 +2215,6 @@ symbol_table_init(void) { { symbol_elem_t{ 0, cbl_special_name_t{0, S04_e, "S04", 0, "/dev/null"}} }, { symbol_elem_t{ 0, cbl_special_name_t{0, S05_e, "S05", 0, "/dev/null"}} }, { symbol_elem_t{ 0, cbl_special_name_t{0, AFP_5A_e, "AFP-5A", 0, "/dev/null"}} }, - { symbol_elem_t{ 0, cbl_special_name_t{0, STDIN_e, "STDIN", 0, "/dev/stdin"}} }, - { symbol_elem_t{ 0, cbl_special_name_t{0, STDOUT_e, "STDOUT", 0, "/dev/stdout"}} }, - { symbol_elem_t{ 0, cbl_special_name_t{0, STDERR_e, "STDERR", 0, "/dev/stderr"}} }, - { symbol_elem_t{ 0, cbl_special_name_t{0, SYSERR_e, "SYSERR", 0, "/dev/stderr"}} }, }; struct symbol_elem_t *p = table.elems + table.nelem; @@ -4345,6 +4349,26 @@ cbl_occurs_t::subscript_ok( const cbl_field_t *subscript ) const { return bounds.lower <= (size_t)sub && (size_t)sub <= bounds.upper; } +const cbl_field_t * +symbol_unresolved_file_key( const cbl_file_t * file, + const cbl_name_t key_field_name ) { + const symbol_elem_t *file_sym = symbol_elem_of(file); + size_t program = file_sym->program; + for( const symbol_elem_t *e = file_sym - 1; e->program == program; e-- ) { + if( e->type == SymFile ) break; + if( e->type == SymField ) { + auto f = cbl_field_of(e); + if( f->type == FldLiteralA ) break; + if( f->type == FldForward ) { + if( 0 == strcmp(key_field_name, f->name) ) { + return f; + } + } + } + } + return nullptr; +} + cbl_file_key_t:: cbl_file_key_t( cbl_name_t name, const std::list<cbl_field_t *>& fields, @@ -4486,7 +4510,7 @@ cbl_file_key_t::deforward( size_t ifile ) { if( ifield == fwd ) { ERROR_FIELD(field, "line %d: %s of %s " "is not defined", - file->line, field->name, file->name); + field->line, field->name, file->name); return ifield; } @@ -4515,9 +4539,13 @@ cbl_file_key_t::deforward( size_t ifile ) { // looked-up field must have same file as parent if( ! (parent != NULL && symbol_index(symbol_elem_of(parent)) == ifile) ) { - ERROR_FIELD(field, "line %d: %s of %s " - "is not defined in file description", - file->line, field->name, file->name); + const cbl_field_t *undefined = + symbol_unresolved_file_key(file, field->name); + int lineno = undefined? undefined->line : file->line; + ERROR_FIELD(undefined? undefined : field, + "line %d: %s of %s " + "is not defined in file description", + lineno, field->name, file->name); } return ifield; } ); diff --git a/gcc/cobol/symbols.h b/gcc/cobol/symbols.h index 0b72b5c..c3de0aa 100644 --- a/gcc/cobol/symbols.h +++ b/gcc/cobol/symbols.h @@ -1894,6 +1894,10 @@ const cbl_label_t * symbol_program_local( const char called[] ); bool redefine_field( cbl_field_t *field ); +const cbl_field_t * +symbol_unresolved_file_key( const cbl_file_t * file, + const cbl_name_t key_field_name ); + static inline struct cbl_section_t * cbl_section_of( struct symbol_elem_t *e ) { assert(e && e->type == SymDataSection); @@ -2387,9 +2391,169 @@ enum cbl_call_convention_t { cbl_call_cobol_e = 'N', // native }; +int keyword_tok( const char * text, bool include_intrinsics = false ); +int redefined_token( const cbl_name_t name ); + +class current_tokens_t { + class tokenset_t { + // token_names is initialized from a generated header file. + std::vector<const char *>token_names; // position indicates token value + std::map <std::string, int> tokens; // aliases + std::set<std::string> cobol_words; // Anything in COBOL-WORDS may appear only once. + public: + static std::string + lowercase( const cbl_name_t name ) { + cbl_name_t lname; + std::transform(name, name + strlen(name) + 1, lname, ftolower); + return lname; + } + static std::string + uppercase( const cbl_name_t name ) { + cbl_name_t uname; + std::transform(name, name + strlen(name) + 1, uname, ftoupper); + return uname; + } + + public: + tokenset_t(); + int find( const cbl_name_t name, bool include_intrinsics ); + + bool equate( const YYLTYPE& loc, int token, + const cbl_name_t name, const cbl_name_t verb = "EQUATE") { + auto lname( lowercase(name) ); + auto cw = cobol_words.insert(lname); + if( ! cw.second ) { + error_msg(loc, "COBOL-WORDS %s: %s may appear but once", verb, name); + return false; + } + auto p = tokens.find(lowercase(name)); + bool fOK = p == tokens.end(); + if( fOK ) { // name not already in use + tokens[lname] = token; + dbgmsg("%s:%d: %d has alias %s", __func__, __LINE__, token, name); + } else { + error_msg(loc, "%s: %s already defined as a token", verb, name); + } + return fOK; + } + bool undefine( const YYLTYPE& loc, + const cbl_name_t name, const cbl_name_t verb = "UNDEFINE" ) { + auto lname( lowercase(name) ); + auto cw = cobol_words.insert(lname); + if( ! cw.second ) { + error_msg(loc, "COBOL-WORDS %s: %s may appear but once", verb, name); + return false; + } + + // Do not erase generic, multi-type tokens COMPUTATIONAL and BINARY_INTEGER. + if( binary_integer_usage_of(name) ) { + dbgmsg("%s:%d: generic %s remains valid as a token", __func__, __LINE__, name); + return true; + } + + auto p = tokens.find(lname); + bool fOK = p != tokens.end(); + if( fOK ) { // name in use + tokens.erase(p); + } else { + error_msg(loc, "%s: %s not defined as a token", verb, name); + } + dbgmsg("%s:%d: %s removed as a valid token name", __func__, __LINE__, name); + return fOK; + } + + bool substitute( const YYLTYPE& loc, + const cbl_name_t extant, int token, const cbl_name_t name ) { + return + equate( loc, token, name, "SUBSTITUTE" ) + && + undefine( loc, extant, "SUBSTITUTE" ); + } + bool reserve( const YYLTYPE& loc, const cbl_name_t name ) { + auto lname( lowercase(name) ); + auto cw = cobol_words.insert(lname); + if( ! cw.second ) { + error_msg(loc, "COBOL-WORDS RESERVE: %s may appear but once", name); + return false; + } + tokens[lname] = -42; + return true; + } + int redefined_as( const cbl_name_t name ) { + auto lname( lowercase(name) ); + if( cobol_words.find(lname) != cobol_words.end() ) { + auto p = tokens.find(lname); + if( p != tokens.end() ) { + return p->second; + } + } + return 0; + } + const char * name_of( int tok ) const { + tok -= (255 + 3); + gcc_assert(0 <= tok && size_t(tok) < token_names.size()); + return tok < 0? "???" : token_names[tok]; + } + }; + + tokenset_t tokens; + public: + current_tokens_t() {} + int find( const cbl_name_t name, bool include_intrinsics ) { + return tokens.find(name, include_intrinsics); + } + bool equate( const YYLTYPE& loc, const cbl_name_t keyword, const cbl_name_t alias ) { + int token; + if( 0 == (token = binary_integer_usage_of(keyword)) ) { + if( 0 == (token = keyword_tok(keyword)) ) { + error_msg(loc, "EQUATE %s: not a valid token", keyword); + return false; + } + } + auto name = keyword_alias_add(tokens.uppercase(keyword), + tokens.uppercase(alias)); + if( name != keyword ) { + error_msg(loc, "EQUATE: %s is already an alias for %s", alias, name.c_str()); + return false; + } + return tokens.equate(loc, token, alias); + } + bool undefine( const YYLTYPE& loc, cbl_name_t keyword ) { + return tokens.undefine(loc, keyword); + } + bool substitute( const YYLTYPE& loc, const cbl_name_t keyword, const cbl_name_t alias ) { + int token; + if( 0 == (token = binary_integer_usage_of(keyword)) ) { + if( 0 == (token = keyword_tok(keyword)) ) { + error_msg(loc, "SUBSTITUTE %s: not a valid token", keyword); + return false; + } + } + auto name = keyword_alias_add(tokens.uppercase(keyword), + tokens.uppercase(alias)); + if( name != keyword ) { + error_msg(loc, "SUBSTITUTE: %s is already an alias for %s", alias, name.c_str()); + return false; + } + + dbgmsg("%s:%d: %s (%d) will have alias %s", __func__, __LINE__, keyword, token, alias); + return tokens.substitute(loc, keyword, token, alias); + } + bool reserve( const YYLTYPE& loc, const cbl_name_t name ) { + return tokens.reserve(loc, name); + } + int redefined_as( const cbl_name_t name ) { + return tokens.redefined_as(name); + } + const char * name_of( int tok ) const { + return tokens.name_of(tok); + } +}; + cbl_call_convention_t current_call_convention(); +current_tokens_t& cdf_current_tokens(); -cbl_call_convention_t +void current_call_convention( cbl_call_convention_t convention); class procref_base_t { @@ -2433,9 +2597,6 @@ public: int line_number() const { return line; } }; -int keyword_tok( const char * text, bool include_intrinsics = false ); -int redefined_token( const cbl_name_t name ); - void procedure_definition_add( size_t program, const cbl_label_t *procedure ); void procedure_reference_add( const char *sect, const char *para, int line, size_t context ); diff --git a/gcc/cobol/symfind.cc b/gcc/cobol/symfind.cc index 39df2a0..c04bb0f 100644 --- a/gcc/cobol/symfind.cc +++ b/gcc/cobol/symfind.cc @@ -504,7 +504,7 @@ symbol_match( size_t program, const std::list<const char *>& names ) { } auto inserted = output.insert(*p); if( ! inserted.second ) { - yyerror("%s is not a unique reference", key.name); + error_msg_direct("%s is not a unique reference", key.name); } } return output; diff --git a/gcc/cobol/token_names.h b/gcc/cobol/token_names.h index 4b24fc6..ca51510 100644 --- a/gcc/cobol/token_names.h +++ b/gcc/cobol/token_names.h @@ -1,5 +1,5 @@ // generated by ./token_names.h.gen ../../build/gcc/cobol/parse.h -// Thu May 8 18:53:33 EDT 2025 +// Tue Jul 8 19:21:28 EDT 2025 tokens = { { "identification", IDENTIFICATION_DIV }, // 258 { "environment", ENVIRONMENT_DIV }, // 259 @@ -137,558 +137,566 @@ tokens = { { "cdf-evaluate", CDF_EVALUATE }, // 388 { "cdf-when", CDF_WHEN }, // 389 { "cdf-end-evaluate", CDF_END_EVALUATE }, // 390 - { "call-cobol", CALL_COBOL }, // 391 - { "call-verbatim", CALL_VERBATIM }, // 392 - { "if", IF }, // 393 - { "then", THEN }, // 394 - { "else", ELSE }, // 395 - { "sentence", SENTENCE }, // 396 - { "accept", ACCEPT }, // 397 - { "add", ADD }, // 398 - { "alter", ALTER }, // 399 - { "call", CALL }, // 400 - { "cancel", CANCEL }, // 401 - { "close", CLOSE }, // 402 - { "compute", COMPUTE }, // 403 - { "continue", CONTINUE }, // 404 - { "delete", DELETE }, // 405 - { "display", DISPLAY }, // 406 - { "divide", DIVIDE }, // 407 - { "evaluate", EVALUATE }, // 408 - { "exit", EXIT }, // 409 - { "filler", FILLER_kw }, // 410 - { "goback", GOBACK }, // 411 - { "goto", GOTO }, // 412 - { "initialize", INITIALIZE }, // 413 - { "inspect", INSPECT }, // 414 - { "merge", MERGE }, // 415 - { "move", MOVE }, // 416 - { "multiply", MULTIPLY }, // 417 - { "open", OPEN }, // 418 - { "paragraph", PARAGRAPH }, // 419 - { "read", READ }, // 420 - { "release", RELEASE }, // 421 - { "return", RETURN }, // 422 - { "rewrite", REWRITE }, // 423 - { "search", SEARCH }, // 424 - { "set", SET }, // 425 - { "select", SELECT }, // 426 - { "sort", SORT }, // 427 - { "sort-merge", SORT_MERGE }, // 428 - { "string", STRING_kw }, // 429 - { "stop", STOP }, // 430 - { "subtract", SUBTRACT }, // 431 - { "start", START }, // 432 - { "unstring", UNSTRING }, // 433 - { "write", WRITE }, // 434 - { "when", WHEN }, // 435 - { "abs", ABS }, // 436 - { "access", ACCESS }, // 437 - { "acos", ACOS }, // 438 - { "actual", ACTUAL }, // 439 - { "advancing", ADVANCING }, // 440 - { "after", AFTER }, // 441 - { "all", ALL }, // 442 - { "allocate", ALLOCATE }, // 443 - { "alphabet", ALPHABET }, // 444 - { "alphabetic", ALPHABETIC }, // 445 - { "alphabetic-lower", ALPHABETIC_LOWER }, // 446 - { "alphabetic-upper", ALPHABETIC_UPPER }, // 447 - { "alphanumeric", ALPHANUMERIC }, // 448 - { "alphanumeric-edited", ALPHANUMERIC_EDITED }, // 449 - { "also", ALSO }, // 450 - { "alternate", ALTERNATE }, // 451 - { "annuity", ANNUITY }, // 452 - { "anum", ANUM }, // 453 - { "any", ANY }, // 454 - { "anycase", ANYCASE }, // 455 - { "apply", APPLY }, // 456 - { "are", ARE }, // 457 - { "area", AREA }, // 458 - { "areas", AREAS }, // 459 - { "as", AS }, // 460 - { "ascending", ASCENDING }, // 461 - { "activating", ACTIVATING }, // 462 - { "asin", ASIN }, // 463 - { "assign", ASSIGN }, // 464 - { "at", AT }, // 465 - { "atan", ATAN }, // 466 - { "based", BASED }, // 467 - { "baseconvert", BASECONVERT }, // 468 - { "before", BEFORE }, // 469 - { "binary", BINARY }, // 470 - { "bit", BIT }, // 471 - { "bit-of", BIT_OF }, // 472 - { "bit-to-char", BIT_TO_CHAR }, // 473 - { "blank", BLANK }, // 474 - { "block", BLOCK_kw }, // 475 - { "boolean-of-integer", BOOLEAN_OF_INTEGER }, // 476 - { "bottom", BOTTOM }, // 477 - { "by", BY }, // 478 - { "byte", BYTE }, // 479 - { "byte-length", BYTE_LENGTH }, // 480 - { "cf", CF }, // 481 - { "ch", CH }, // 482 - { "changed", CHANGED }, // 483 - { "char", CHAR }, // 484 - { "char-national", CHAR_NATIONAL }, // 485 - { "character", CHARACTER }, // 486 - { "characters", CHARACTERS }, // 487 - { "checking", CHECKING }, // 488 - { "class", CLASS }, // 489 - { "cobol", COBOL }, // 490 - { "code", CODE }, // 491 - { "code-set", CODESET }, // 492 - { "collating", COLLATING }, // 493 - { "column", COLUMN }, // 494 - { "combined-datetime", COMBINED_DATETIME }, // 495 - { "comma", COMMA }, // 496 - { "command-line", COMMAND_LINE }, // 497 - { "command-line-count", COMMAND_LINE_COUNT }, // 498 - { "commit", COMMIT }, // 499 - { "common", COMMON }, // 500 - { "concat", CONCAT }, // 501 - { "condition", CONDITION }, // 502 - { "configuration", CONFIGURATION_SECT }, // 503 - { "contains", CONTAINS }, // 504 - { "content", CONTENT }, // 505 - { "control", CONTROL }, // 506 - { "controls", CONTROLS }, // 507 - { "convert", CONVERT }, // 508 - { "converting", CONVERTING }, // 509 - { "corresponding", CORRESPONDING }, // 510 - { "cos", COS }, // 511 - { "count", COUNT }, // 512 - { "currency", CURRENCY }, // 513 - { "current", CURRENT }, // 514 - { "current-date", CURRENT_DATE }, // 515 - { "data", DATA }, // 516 - { "date", DATE }, // 517 - { "date-compiled", DATE_COMPILED }, // 518 - { "date-of-integer", DATE_OF_INTEGER }, // 519 - { "date-to-yyyymmdd", DATE_TO_YYYYMMDD }, // 520 - { "date-written", DATE_WRITTEN }, // 521 - { "day", DAY }, // 522 - { "day-of-integer", DAY_OF_INTEGER }, // 523 - { "day-of-week", DAY_OF_WEEK }, // 524 - { "day-to-yyyyddd", DAY_TO_YYYYDDD }, // 525 - { "dbcs", DBCS }, // 526 - { "de", DE }, // 527 - { "debugging", DEBUGGING }, // 528 - { "decimal-point", DECIMAL_POINT }, // 529 - { "declaratives", DECLARATIVES }, // 530 - { "default", DEFAULT }, // 531 - { "delimited", DELIMITED }, // 532 - { "delimiter", DELIMITER }, // 533 - { "depending", DEPENDING }, // 534 - { "descending", DESCENDING }, // 535 - { "detail", DETAIL }, // 536 - { "direct", DIRECT }, // 537 - { "direct-access", DIRECT_ACCESS }, // 538 - { "down", DOWN }, // 539 - { "duplicates", DUPLICATES }, // 540 - { "dynamic", DYNAMIC }, // 541 - { "e", E }, // 542 - { "ebcdic", EBCDIC }, // 543 - { "ec", EC }, // 544 - { "egcs", EGCS }, // 545 - { "entry", ENTRY }, // 546 - { "environment", ENVIRONMENT }, // 547 - { "equal", EQUAL }, // 548 - { "every", EVERY }, // 549 - { "examine", EXAMINE }, // 550 - { "exhibit", EXHIBIT }, // 551 - { "exp", EXP }, // 552 - { "exp10", EXP10 }, // 553 - { "extend", EXTEND }, // 554 - { "external", EXTERNAL }, // 555 - { "exception-file", EXCEPTION_FILE }, // 556 - { "exception-file-n", EXCEPTION_FILE_N }, // 557 - { "exception-location", EXCEPTION_LOCATION }, // 558 - { "exception-location-n", EXCEPTION_LOCATION_N }, // 559 - { "exception-statement", EXCEPTION_STATEMENT }, // 560 - { "exception-status", EXCEPTION_STATUS }, // 561 - { "factorial", FACTORIAL }, // 562 - { "false", FALSE_kw }, // 563 - { "fd", FD }, // 564 - { "file-control", FILE_CONTROL }, // 565 - { "file", FILE_KW }, // 566 - { "file-limit", FILE_LIMIT }, // 567 - { "final", FINAL }, // 568 - { "finally", FINALLY }, // 569 - { "find-string", FIND_STRING }, // 570 - { "first", FIRST }, // 571 - { "fixed", FIXED }, // 572 - { "footing", FOOTING }, // 573 - { "for", FOR }, // 574 - { "formatted-current-date", FORMATTED_CURRENT_DATE }, // 575 - { "formatted-date", FORMATTED_DATE }, // 576 - { "formatted-datetime", FORMATTED_DATETIME }, // 577 - { "formatted-time", FORMATTED_TIME }, // 578 - { "form-overflow", FORM_OVERFLOW }, // 579 - { "free", FREE }, // 580 - { "fraction-part", FRACTION_PART }, // 581 - { "from", FROM }, // 582 - { "function", FUNCTION }, // 583 - { "generate", GENERATE }, // 584 - { "giving", GIVING }, // 585 - { "global", GLOBAL }, // 586 - { "go", GO }, // 587 - { "group", GROUP }, // 588 - { "heading", HEADING }, // 589 - { "hex", HEX }, // 590 - { "hex-of", HEX_OF }, // 591 - { "hex-to-char", HEX_TO_CHAR }, // 592 - { "high-values", HIGH_VALUES }, // 593 - { "highest-algebraic", HIGHEST_ALGEBRAIC }, // 594 - { "hold", HOLD }, // 595 - { "ibm-360", IBM_360 }, // 596 - { "in", IN }, // 597 - { "include", INCLUDE }, // 598 - { "index", INDEX }, // 599 - { "indexed", INDEXED }, // 600 - { "indicate", INDICATE }, // 601 - { "initial", INITIAL_kw }, // 602 - { "initiate", INITIATE }, // 603 - { "input", INPUT }, // 604 - { "installation", INSTALLATION }, // 605 - { "interface", INTERFACE }, // 606 - { "integer", INTEGER }, // 607 - { "integer-of-boolean", INTEGER_OF_BOOLEAN }, // 608 - { "integer-of-date", INTEGER_OF_DATE }, // 609 - { "integer-of-day", INTEGER_OF_DAY }, // 610 - { "integer-of-formatted-date", INTEGER_OF_FORMATTED_DATE }, // 611 - { "integer-part", INTEGER_PART }, // 612 - { "into", INTO }, // 613 - { "intrinsic", INTRINSIC }, // 614 - { "invoke", INVOKE }, // 615 - { "i-o", IO }, // 616 - { "i-o-control", IO_CONTROL }, // 617 - { "is", IS }, // 618 - { "isnt", ISNT }, // 619 - { "kanji", KANJI }, // 620 - { "key", KEY }, // 621 - { "label", LABEL }, // 622 - { "last", LAST }, // 623 - { "leading", LEADING }, // 624 - { "left", LEFT }, // 625 - { "length", LENGTH }, // 626 - { "length-of", LENGTH_OF }, // 627 - { "limit", LIMIT }, // 628 - { "limits", LIMITS }, // 629 - { "line", LINE }, // 630 - { "lines", LINES }, // 631 - { "line-counter", LINE_COUNTER }, // 632 - { "linage", LINAGE }, // 633 - { "linkage", LINKAGE }, // 634 - { "locale", LOCALE }, // 635 - { "locale-compare", LOCALE_COMPARE }, // 636 - { "locale-date", LOCALE_DATE }, // 637 - { "locale-time", LOCALE_TIME }, // 638 - { "locale-time-from-seconds", LOCALE_TIME_FROM_SECONDS }, // 639 - { "local-storage", LOCAL_STORAGE }, // 640 - { "location", LOCATION }, // 641 - { "lock", LOCK }, // 642 - { "lock-on", LOCK_ON }, // 643 - { "log", LOG }, // 644 - { "log10", LOG10 }, // 645 - { "lower-case", LOWER_CASE }, // 646 - { "low-values", LOW_VALUES }, // 647 - { "lowest-algebraic", LOWEST_ALGEBRAIC }, // 648 - { "lparen", LPAREN }, // 649 - { "manual", MANUAL }, // 650 - { "maxx", MAXX }, // 651 - { "mean", MEAN }, // 652 - { "median", MEDIAN }, // 653 - { "midrange", MIDRANGE }, // 654 - { "minn", MINN }, // 655 - { "multiple", MULTIPLE }, // 656 - { "mod", MOD }, // 657 - { "mode", MODE }, // 658 - { "module-name", MODULE_NAME }, // 659 - { "named", NAMED }, // 660 - { "nat", NAT }, // 661 - { "national", NATIONAL }, // 662 - { "national-edited", NATIONAL_EDITED }, // 663 - { "national-of", NATIONAL_OF }, // 664 - { "native", NATIVE }, // 665 - { "nested", NESTED }, // 666 - { "next", NEXT }, // 667 - { "no", NO }, // 668 - { "note", NOTE }, // 669 - { "nulls", NULLS }, // 670 - { "null", NULLS }, // 670 - { "nullptr", NULLPTR }, // 671 - { "numeric", NUMERIC }, // 672 - { "numeric-edited", NUMERIC_EDITED }, // 673 - { "numval", NUMVAL }, // 674 - { "numval-c", NUMVAL_C }, // 675 - { "numval-f", NUMVAL_F }, // 676 - { "occurs", OCCURS }, // 677 - { "of", OF }, // 678 - { "off", OFF }, // 679 - { "omitted", OMITTED }, // 680 - { "on", ON }, // 681 - { "only", ONLY }, // 682 - { "optional", OPTIONAL }, // 683 - { "options", OPTIONS }, // 684 - { "ord", ORD }, // 685 - { "order", ORDER }, // 686 - { "ord-max", ORD_MAX }, // 687 - { "ord-min", ORD_MIN }, // 688 - { "organization", ORGANIZATION }, // 689 - { "other", OTHER }, // 690 - { "otherwise", OTHERWISE }, // 691 - { "output", OUTPUT }, // 692 - { "packed-decimal", PACKED_DECIMAL }, // 693 - { "padding", PADDING }, // 694 - { "page", PAGE }, // 695 - { "page-counter", PAGE_COUNTER }, // 696 - { "pf", PF }, // 697 - { "ph", PH }, // 698 - { "pi", PI }, // 699 - { "pic", PIC }, // 700 - { "picture", PICTURE }, // 701 - { "plus", PLUS }, // 702 - { "present-value", PRESENT_VALUE }, // 703 - { "print-switch", PRINT_SWITCH }, // 704 - { "procedure", PROCEDURE }, // 705 - { "procedures", PROCEDURES }, // 706 - { "proceed", PROCEED }, // 707 - { "process", PROCESS }, // 708 - { "program-id", PROGRAM_ID }, // 709 - { "program", PROGRAM_kw }, // 710 - { "property", PROPERTY }, // 711 - { "prototype", PROTOTYPE }, // 712 - { "pseudotext", PSEUDOTEXT }, // 713 - { "quotes", QUOTES }, // 714 - { "quote", QUOTES }, // 714 - { "random", RANDOM }, // 715 - { "random-seed", RANDOM_SEED }, // 716 - { "range", RANGE }, // 717 - { "raise", RAISE }, // 718 - { "raising", RAISING }, // 719 - { "rd", RD }, // 720 - { "record", RECORD }, // 721 - { "recording", RECORDING }, // 722 - { "records", RECORDS }, // 723 - { "recursive", RECURSIVE }, // 724 - { "redefines", REDEFINES }, // 725 - { "reel", REEL }, // 726 - { "reference", REFERENCE }, // 727 - { "relative", RELATIVE }, // 728 - { "rem", REM }, // 729 - { "remainder", REMAINDER }, // 730 - { "remarks", REMARKS }, // 731 - { "removal", REMOVAL }, // 732 - { "renames", RENAMES }, // 733 - { "replace", REPLACE }, // 734 - { "replacing", REPLACING }, // 735 - { "report", REPORT }, // 736 - { "reporting", REPORTING }, // 737 - { "reports", REPORTS }, // 738 - { "repository", REPOSITORY }, // 739 - { "rerun", RERUN }, // 740 - { "reserve", RESERVE }, // 741 - { "restricted", RESTRICTED }, // 742 - { "resume", RESUME }, // 743 - { "reverse", REVERSE }, // 744 - { "reversed", REVERSED }, // 745 - { "rewind", REWIND }, // 746 - { "rf", RF }, // 747 - { "rh", RH }, // 748 - { "right", RIGHT }, // 749 - { "rounded", ROUNDED }, // 750 - { "run", RUN }, // 751 - { "same", SAME }, // 752 - { "screen", SCREEN }, // 753 - { "sd", SD }, // 754 - { "seconds-from-formatted-time", SECONDS_FROM_FORMATTED_TIME }, // 755 - { "seconds-past-midnight", SECONDS_PAST_MIDNIGHT }, // 756 - { "security", SECURITY }, // 757 - { "separate", SEPARATE }, // 758 - { "sequence", SEQUENCE }, // 759 - { "sequential", SEQUENTIAL }, // 760 - { "sharing", SHARING }, // 761 - { "simple-exit", SIMPLE_EXIT }, // 762 - { "sign", SIGN }, // 763 - { "sin", SIN }, // 764 - { "size", SIZE }, // 765 - { "smallest-algebraic", SMALLEST_ALGEBRAIC }, // 766 - { "source", SOURCE }, // 767 - { "source-computer", SOURCE_COMPUTER }, // 768 - { "special-names", SPECIAL_NAMES }, // 769 - { "sqrt", SQRT }, // 770 - { "stack", STACK }, // 771 - { "standard", STANDARD }, // 772 - { "standard-1", STANDARD_1 }, // 773 - { "standard-deviation", STANDARD_DEVIATION }, // 774 - { "standard-compare", STANDARD_COMPARE }, // 775 - { "status", STATUS }, // 776 - { "strong", STRONG }, // 777 - { "substitute", SUBSTITUTE }, // 778 - { "sum", SUM }, // 779 - { "symbol", SYMBOL }, // 780 - { "symbolic", SYMBOLIC }, // 781 - { "synchronized", SYNCHRONIZED }, // 782 - { "tally", TALLY }, // 783 - { "tallying", TALLYING }, // 784 - { "tan", TAN }, // 785 - { "terminate", TERMINATE }, // 786 - { "test", TEST }, // 787 - { "test-date-yyyymmdd", TEST_DATE_YYYYMMDD }, // 788 - { "test-day-yyyyddd", TEST_DAY_YYYYDDD }, // 789 - { "test-formatted-datetime", TEST_FORMATTED_DATETIME }, // 790 - { "test-numval", TEST_NUMVAL }, // 791 - { "test-numval-c", TEST_NUMVAL_C }, // 792 - { "test-numval-f", TEST_NUMVAL_F }, // 793 - { "than", THAN }, // 794 - { "time", TIME }, // 795 - { "times", TIMES }, // 796 - { "to", TO }, // 797 - { "top", TOP }, // 798 - { "top-level", TOP_LEVEL }, // 799 - { "tracks", TRACKS }, // 800 - { "track-area", TRACK_AREA }, // 801 - { "trailing", TRAILING }, // 802 - { "transform", TRANSFORM }, // 803 - { "trim", TRIM }, // 804 - { "true", TRUE_kw }, // 805 - { "try", TRY }, // 806 - { "turn", TURN }, // 807 - { "type", TYPE }, // 808 - { "typedef", TYPEDEF }, // 809 - { "ulength", ULENGTH }, // 810 - { "unbounded", UNBOUNDED }, // 811 - { "unit", UNIT }, // 812 - { "units", UNITS }, // 813 - { "unit-record", UNIT_RECORD }, // 814 - { "until", UNTIL }, // 815 - { "up", UP }, // 816 - { "upon", UPON }, // 817 - { "upos", UPOS }, // 818 - { "upper-case", UPPER_CASE }, // 819 - { "usage", USAGE }, // 820 - { "using", USING }, // 821 - { "usubstr", USUBSTR }, // 822 - { "usupplementary", USUPPLEMENTARY }, // 823 - { "utility", UTILITY }, // 824 - { "uuid4", UUID4 }, // 825 - { "uvalid", UVALID }, // 826 - { "uwidth", UWIDTH }, // 827 - { "value", VALUE }, // 828 - { "variance", VARIANCE }, // 829 - { "varying", VARYING }, // 830 - { "volatile", VOLATILE }, // 831 - { "when-compiled", WHEN_COMPILED }, // 832 - { "with", WITH }, // 833 - { "working-storage", WORKING_STORAGE }, // 834 - { "xml", XML }, // 835 - { "xmlgenerate", XMLGENERATE }, // 836 - { "xmlparse", XMLPARSE }, // 837 - { "year-to-yyyy", YEAR_TO_YYYY }, // 838 - { "yyyyddd", YYYYDDD }, // 839 - { "yyyymmdd", YYYYMMDD }, // 840 - { "arithmetic", ARITHMETIC }, // 841 - { "attribute", ATTRIBUTE }, // 842 - { "auto", AUTO }, // 843 - { "automatic", AUTOMATIC }, // 844 - { "away-from-zero", AWAY_FROM_ZERO }, // 845 - { "background-color", BACKGROUND_COLOR }, // 846 - { "bell", BELL }, // 847 - { "binary-encoding", BINARY_ENCODING }, // 848 - { "blink", BLINK }, // 849 - { "capacity", CAPACITY }, // 850 - { "center", CENTER }, // 851 - { "classification", CLASSIFICATION }, // 852 - { "cycle", CYCLE }, // 853 - { "decimal-encoding", DECIMAL_ENCODING }, // 854 - { "entry-convention", ENTRY_CONVENTION }, // 855 - { "eol", EOL }, // 856 - { "eos", EOS }, // 857 - { "erase", ERASE }, // 858 - { "expands", EXPANDS }, // 859 - { "float-binary", FLOAT_BINARY }, // 860 - { "float-decimal", FLOAT_DECIMAL }, // 861 - { "foreground-color", FOREGROUND_COLOR }, // 862 - { "forever", FOREVER }, // 863 - { "full", FULL }, // 864 - { "highlight", HIGHLIGHT }, // 865 - { "high-order-left", HIGH_ORDER_LEFT }, // 866 - { "high-order-right", HIGH_ORDER_RIGHT }, // 867 - { "ignoring", IGNORING }, // 868 - { "implements", IMPLEMENTS }, // 869 - { "initialized", INITIALIZED }, // 870 - { "intermediate", INTERMEDIATE }, // 871 - { "lc-all", LC_ALL_kw }, // 872 - { "lc-collate", LC_COLLATE_kw }, // 873 - { "lc-ctype", LC_CTYPE_kw }, // 874 - { "lc-messages", LC_MESSAGES_kw }, // 875 - { "lc-monetary", LC_MONETARY_kw }, // 876 - { "lc-numeric", LC_NUMERIC_kw }, // 877 - { "lc-time", LC_TIME_kw }, // 878 - { "lowlight", LOWLIGHT }, // 879 - { "nearest-away-from-zero", NEAREST_AWAY_FROM_ZERO }, // 880 - { "nearest-even", NEAREST_EVEN }, // 881 - { "nearest-toward-zero", NEAREST_TOWARD_ZERO }, // 882 - { "none", NONE }, // 883 - { "normal", NORMAL }, // 884 - { "numbers", NUMBERS }, // 885 - { "prefixed", PREFIXED }, // 886 - { "previous", PREVIOUS }, // 887 - { "prohibited", PROHIBITED }, // 888 - { "relation", RELATION }, // 889 - { "required", REQUIRED }, // 890 - { "reverse-video", REVERSE_VIDEO }, // 891 - { "rounding", ROUNDING }, // 892 - { "seconds", SECONDS }, // 893 - { "secure", SECURE }, // 894 - { "short", SHORT }, // 895 - { "signed", SIGNED_kw }, // 896 - { "standard-binary", STANDARD_BINARY }, // 897 - { "standard-decimal", STANDARD_DECIMAL }, // 898 - { "statement", STATEMENT }, // 899 - { "step", STEP }, // 900 - { "structure", STRUCTURE }, // 901 - { "toward-greater", TOWARD_GREATER }, // 902 - { "toward-lesser", TOWARD_LESSER }, // 903 - { "truncation", TRUNCATION }, // 904 - { "ucs-4", UCS_4 }, // 905 - { "underline", UNDERLINE }, // 906 - { "unsigned", UNSIGNED_kw }, // 907 - { "utf-16", UTF_16 }, // 908 - { "utf-8", UTF_8 }, // 909 - { "address", ADDRESS }, // 910 - { "end-accept", END_ACCEPT }, // 911 - { "end-add", END_ADD }, // 912 - { "end-call", END_CALL }, // 913 - { "end-compute", END_COMPUTE }, // 914 - { "end-delete", END_DELETE }, // 915 - { "end-display", END_DISPLAY }, // 916 - { "end-divide", END_DIVIDE }, // 917 - { "end-evaluate", END_EVALUATE }, // 918 - { "end-multiply", END_MULTIPLY }, // 919 - { "end-perform", END_PERFORM }, // 920 - { "end-read", END_READ }, // 921 - { "end-return", END_RETURN }, // 922 - { "end-rewrite", END_REWRITE }, // 923 - { "end-search", END_SEARCH }, // 924 - { "end-start", END_START }, // 925 - { "end-string", END_STRING }, // 926 - { "end-subtract", END_SUBTRACT }, // 927 - { "end-unstring", END_UNSTRING }, // 928 - { "end-write", END_WRITE }, // 929 - { "end-if", END_IF }, // 930 - { "thru", THRU }, // 931 - { "through", THRU }, // 931 - { "or", OR }, // 932 - { "and", AND }, // 933 - { "not", NOT }, // 934 - { "ne", NE }, // 935 - { "le", LE }, // 936 - { "ge", GE }, // 937 - { "pow", POW }, // 938 - { "neg", NEG }, // 939 + { "call-convention", CALL_CONVENTION }, // 391 + { "call-cobol", CALL_COBOL }, // 392 + { "call-verbatim", CALL_VERBATIM }, // 393 + { "cdf-push", CDF_PUSH }, // 394 + { "cdf-pop", CDF_POP }, // 395 + { "source-format", SOURCE_FORMAT }, // 396 + { "if", IF }, // 397 + { "then", THEN }, // 398 + { "else", ELSE }, // 399 + { "sentence", SENTENCE }, // 400 + { "accept", ACCEPT }, // 401 + { "add", ADD }, // 402 + { "alter", ALTER }, // 403 + { "call", CALL }, // 404 + { "cancel", CANCEL }, // 405 + { "close", CLOSE }, // 406 + { "compute", COMPUTE }, // 407 + { "continue", CONTINUE }, // 408 + { "delete", DELETE }, // 409 + { "display", DISPLAY }, // 410 + { "divide", DIVIDE }, // 411 + { "evaluate", EVALUATE }, // 412 + { "exit", EXIT }, // 413 + { "filler", FILLER_kw }, // 414 + { "goback", GOBACK }, // 415 + { "goto", GOTO }, // 416 + { "initialize", INITIALIZE }, // 417 + { "inspect", INSPECT }, // 418 + { "merge", MERGE }, // 419 + { "move", MOVE }, // 420 + { "multiply", MULTIPLY }, // 421 + { "open", OPEN }, // 422 + { "paragraph", PARAGRAPH }, // 423 + { "read", READ }, // 424 + { "release", RELEASE }, // 425 + { "return", RETURN }, // 426 + { "rewrite", REWRITE }, // 427 + { "search", SEARCH }, // 428 + { "set", SET }, // 429 + { "select", SELECT }, // 430 + { "sort", SORT }, // 431 + { "sort-merge", SORT_MERGE }, // 432 + { "string", STRING_kw }, // 433 + { "stop", STOP }, // 434 + { "subtract", SUBTRACT }, // 435 + { "start", START }, // 436 + { "unstring", UNSTRING }, // 437 + { "write", WRITE }, // 438 + { "when", WHEN }, // 439 + { "argument-number", ARGUMENT_NUMBER }, // 440 + { "argument-value", ARGUMENT_VALUE }, // 441 + { "environment-name", ENVIRONMENT_NAME }, // 442 + { "environment-value", ENVIRONMENT_VALUE }, // 443 + { "abs", ABS }, // 444 + { "access", ACCESS }, // 445 + { "acos", ACOS }, // 446 + { "actual", ACTUAL }, // 447 + { "advancing", ADVANCING }, // 448 + { "after", AFTER }, // 449 + { "all", ALL }, // 450 + { "allocate", ALLOCATE }, // 451 + { "alphabet", ALPHABET }, // 452 + { "alphabetic", ALPHABETIC }, // 453 + { "alphabetic-lower", ALPHABETIC_LOWER }, // 454 + { "alphabetic-upper", ALPHABETIC_UPPER }, // 455 + { "alphanumeric", ALPHANUMERIC }, // 456 + { "alphanumeric-edited", ALPHANUMERIC_EDITED }, // 457 + { "also", ALSO }, // 458 + { "alternate", ALTERNATE }, // 459 + { "annuity", ANNUITY }, // 460 + { "anum", ANUM }, // 461 + { "any", ANY }, // 462 + { "anycase", ANYCASE }, // 463 + { "apply", APPLY }, // 464 + { "are", ARE }, // 465 + { "area", AREA }, // 466 + { "areas", AREAS }, // 467 + { "as", AS }, // 468 + { "ascending", ASCENDING }, // 469 + { "activating", ACTIVATING }, // 470 + { "asin", ASIN }, // 471 + { "assign", ASSIGN }, // 472 + { "at", AT }, // 473 + { "atan", ATAN }, // 474 + { "based", BASED }, // 475 + { "baseconvert", BASECONVERT }, // 476 + { "before", BEFORE }, // 477 + { "binary", BINARY }, // 478 + { "bit", BIT }, // 479 + { "bit-of", BIT_OF }, // 480 + { "bit-to-char", BIT_TO_CHAR }, // 481 + { "blank", BLANK }, // 482 + { "block", BLOCK_kw }, // 483 + { "boolean-of-integer", BOOLEAN_OF_INTEGER }, // 484 + { "bottom", BOTTOM }, // 485 + { "by", BY }, // 486 + { "byte", BYTE }, // 487 + { "byte-length", BYTE_LENGTH }, // 488 + { "cf", CF }, // 489 + { "ch", CH }, // 490 + { "changed", CHANGED }, // 491 + { "char", CHAR }, // 492 + { "char-national", CHAR_NATIONAL }, // 493 + { "character", CHARACTER }, // 494 + { "characters", CHARACTERS }, // 495 + { "checking", CHECKING }, // 496 + { "class", CLASS }, // 497 + { "cobol", COBOL }, // 498 + { "code", CODE }, // 499 + { "code-set", CODESET }, // 500 + { "collating", COLLATING }, // 501 + { "column", COLUMN }, // 502 + { "combined-datetime", COMBINED_DATETIME }, // 503 + { "comma", COMMA }, // 504 + { "command-line", COMMAND_LINE }, // 505 + { "command-line-count", COMMAND_LINE_COUNT }, // 506 + { "commit", COMMIT }, // 507 + { "common", COMMON }, // 508 + { "concat", CONCAT }, // 509 + { "condition", CONDITION }, // 510 + { "configuration", CONFIGURATION_SECT }, // 511 + { "contains", CONTAINS }, // 512 + { "content", CONTENT }, // 513 + { "control", CONTROL }, // 514 + { "controls", CONTROLS }, // 515 + { "convert", CONVERT }, // 516 + { "converting", CONVERTING }, // 517 + { "corresponding", CORRESPONDING }, // 518 + { "cos", COS }, // 519 + { "count", COUNT }, // 520 + { "currency", CURRENCY }, // 521 + { "current", CURRENT }, // 522 + { "current-date", CURRENT_DATE }, // 523 + { "data", DATA }, // 524 + { "date", DATE }, // 525 + { "date-compiled", DATE_COMPILED }, // 526 + { "date-of-integer", DATE_OF_INTEGER }, // 527 + { "date-to-yyyymmdd", DATE_TO_YYYYMMDD }, // 528 + { "date-written", DATE_WRITTEN }, // 529 + { "day", DAY }, // 530 + { "day-of-integer", DAY_OF_INTEGER }, // 531 + { "day-of-week", DAY_OF_WEEK }, // 532 + { "day-to-yyyyddd", DAY_TO_YYYYDDD }, // 533 + { "dbcs", DBCS }, // 534 + { "de", DE }, // 535 + { "debugging", DEBUGGING }, // 536 + { "decimal-point", DECIMAL_POINT }, // 537 + { "declaratives", DECLARATIVES }, // 538 + { "default", DEFAULT }, // 539 + { "delimited", DELIMITED }, // 540 + { "delimiter", DELIMITER }, // 541 + { "depending", DEPENDING }, // 542 + { "descending", DESCENDING }, // 543 + { "detail", DETAIL }, // 544 + { "direct", DIRECT }, // 545 + { "direct-access", DIRECT_ACCESS }, // 546 + { "down", DOWN }, // 547 + { "duplicates", DUPLICATES }, // 548 + { "dynamic", DYNAMIC }, // 549 + { "e", E }, // 550 + { "ebcdic", EBCDIC }, // 551 + { "ec", EC }, // 552 + { "egcs", EGCS }, // 553 + { "entry", ENTRY }, // 554 + { "environment", ENVIRONMENT }, // 555 + { "equal", EQUAL }, // 556 + { "every", EVERY }, // 557 + { "examine", EXAMINE }, // 558 + { "exhibit", EXHIBIT }, // 559 + { "exp", EXP }, // 560 + { "exp10", EXP10 }, // 561 + { "extend", EXTEND }, // 562 + { "external", EXTERNAL }, // 563 + { "exception-file", EXCEPTION_FILE }, // 564 + { "exception-file-n", EXCEPTION_FILE_N }, // 565 + { "exception-location", EXCEPTION_LOCATION }, // 566 + { "exception-location-n", EXCEPTION_LOCATION_N }, // 567 + { "exception-statement", EXCEPTION_STATEMENT }, // 568 + { "exception-status", EXCEPTION_STATUS }, // 569 + { "factorial", FACTORIAL }, // 570 + { "false", FALSE_kw }, // 571 + { "fd", FD }, // 572 + { "file-control", FILE_CONTROL }, // 573 + { "file", FILE_KW }, // 574 + { "file-limit", FILE_LIMIT }, // 575 + { "final", FINAL }, // 576 + { "finally", FINALLY }, // 577 + { "find-string", FIND_STRING }, // 578 + { "first", FIRST }, // 579 + { "fixed", FIXED }, // 580 + { "footing", FOOTING }, // 581 + { "for", FOR }, // 582 + { "formatted-current-date", FORMATTED_CURRENT_DATE }, // 583 + { "formatted-date", FORMATTED_DATE }, // 584 + { "formatted-datetime", FORMATTED_DATETIME }, // 585 + { "formatted-time", FORMATTED_TIME }, // 586 + { "form-overflow", FORM_OVERFLOW }, // 587 + { "free", FREE }, // 588 + { "fraction-part", FRACTION_PART }, // 589 + { "from", FROM }, // 590 + { "function", FUNCTION }, // 591 + { "generate", GENERATE }, // 592 + { "giving", GIVING }, // 593 + { "global", GLOBAL }, // 594 + { "go", GO }, // 595 + { "group", GROUP }, // 596 + { "heading", HEADING }, // 597 + { "hex", HEX }, // 598 + { "hex-of", HEX_OF }, // 599 + { "hex-to-char", HEX_TO_CHAR }, // 600 + { "high-values", HIGH_VALUES }, // 601 + { "highest-algebraic", HIGHEST_ALGEBRAIC }, // 602 + { "hold", HOLD }, // 603 + { "ibm-360", IBM_360 }, // 604 + { "in", IN }, // 605 + { "include", INCLUDE }, // 606 + { "index", INDEX }, // 607 + { "indexed", INDEXED }, // 608 + { "indicate", INDICATE }, // 609 + { "initial", INITIAL_kw }, // 610 + { "initiate", INITIATE }, // 611 + { "input", INPUT }, // 612 + { "installation", INSTALLATION }, // 613 + { "interface", INTERFACE }, // 614 + { "integer", INTEGER }, // 615 + { "integer-of-boolean", INTEGER_OF_BOOLEAN }, // 616 + { "integer-of-date", INTEGER_OF_DATE }, // 617 + { "integer-of-day", INTEGER_OF_DAY }, // 618 + { "integer-of-formatted-date", INTEGER_OF_FORMATTED_DATE }, // 619 + { "integer-part", INTEGER_PART }, // 620 + { "into", INTO }, // 621 + { "intrinsic", INTRINSIC }, // 622 + { "invoke", INVOKE }, // 623 + { "i-o", IO }, // 624 + { "i-o-control", IO_CONTROL }, // 625 + { "is", IS }, // 626 + { "isnt", ISNT }, // 627 + { "kanji", KANJI }, // 628 + { "key", KEY }, // 629 + { "label", LABEL }, // 630 + { "last", LAST }, // 631 + { "leading", LEADING }, // 632 + { "left", LEFT }, // 633 + { "length", LENGTH }, // 634 + { "length-of", LENGTH_OF }, // 635 + { "limit", LIMIT }, // 636 + { "limits", LIMITS }, // 637 + { "line", LINE }, // 638 + { "lines", LINES }, // 639 + { "line-counter", LINE_COUNTER }, // 640 + { "linage", LINAGE }, // 641 + { "linkage", LINKAGE }, // 642 + { "locale", LOCALE }, // 643 + { "locale-compare", LOCALE_COMPARE }, // 644 + { "locale-date", LOCALE_DATE }, // 645 + { "locale-time", LOCALE_TIME }, // 646 + { "locale-time-from-seconds", LOCALE_TIME_FROM_SECONDS }, // 647 + { "local-storage", LOCAL_STORAGE }, // 648 + { "location", LOCATION }, // 649 + { "lock", LOCK }, // 650 + { "lock-on", LOCK_ON }, // 651 + { "log", LOG }, // 652 + { "log10", LOG10 }, // 653 + { "lower-case", LOWER_CASE }, // 654 + { "low-values", LOW_VALUES }, // 655 + { "lowest-algebraic", LOWEST_ALGEBRAIC }, // 656 + { "lparen", LPAREN }, // 657 + { "manual", MANUAL }, // 658 + { "maxx", MAXX }, // 659 + { "mean", MEAN }, // 660 + { "median", MEDIAN }, // 661 + { "midrange", MIDRANGE }, // 662 + { "minn", MINN }, // 663 + { "multiple", MULTIPLE }, // 664 + { "mod", MOD }, // 665 + { "mode", MODE }, // 666 + { "module-name", MODULE_NAME }, // 667 + { "named", NAMED }, // 668 + { "nat", NAT }, // 669 + { "national", NATIONAL }, // 670 + { "national-edited", NATIONAL_EDITED }, // 671 + { "national-of", NATIONAL_OF }, // 672 + { "native", NATIVE }, // 673 + { "nested", NESTED }, // 674 + { "next", NEXT }, // 675 + { "no", NO }, // 676 + { "note", NOTE }, // 677 + { "nulls", NULLS }, // 678 + { "null", NULLS }, // 678 + { "nullptr", NULLPTR }, // 679 + { "numeric", NUMERIC }, // 680 + { "numeric-edited", NUMERIC_EDITED }, // 681 + { "numval", NUMVAL }, // 682 + { "numval-c", NUMVAL_C }, // 683 + { "numval-f", NUMVAL_F }, // 684 + { "occurs", OCCURS }, // 685 + { "of", OF }, // 686 + { "off", OFF }, // 687 + { "omitted", OMITTED }, // 688 + { "on", ON }, // 689 + { "only", ONLY }, // 690 + { "optional", OPTIONAL }, // 691 + { "options", OPTIONS }, // 692 + { "ord", ORD }, // 693 + { "order", ORDER }, // 694 + { "ord-max", ORD_MAX }, // 695 + { "ord-min", ORD_MIN }, // 696 + { "organization", ORGANIZATION }, // 697 + { "other", OTHER }, // 698 + { "otherwise", OTHERWISE }, // 699 + { "output", OUTPUT }, // 700 + { "packed-decimal", PACKED_DECIMAL }, // 701 + { "padding", PADDING }, // 702 + { "page", PAGE }, // 703 + { "page-counter", PAGE_COUNTER }, // 704 + { "pf", PF }, // 705 + { "ph", PH }, // 706 + { "pi", PI }, // 707 + { "pic", PIC }, // 708 + { "picture", PICTURE }, // 709 + { "plus", PLUS }, // 710 + { "present-value", PRESENT_VALUE }, // 711 + { "print-switch", PRINT_SWITCH }, // 712 + { "procedure", PROCEDURE }, // 713 + { "procedures", PROCEDURES }, // 714 + { "proceed", PROCEED }, // 715 + { "process", PROCESS }, // 716 + { "program-id", PROGRAM_ID }, // 717 + { "program", PROGRAM_kw }, // 718 + { "property", PROPERTY }, // 719 + { "prototype", PROTOTYPE }, // 720 + { "pseudotext", PSEUDOTEXT }, // 721 + { "quotes", QUOTES }, // 722 + { "quote", QUOTES }, // 722 + { "random", RANDOM }, // 723 + { "random-seed", RANDOM_SEED }, // 724 + { "range", RANGE }, // 725 + { "raise", RAISE }, // 726 + { "raising", RAISING }, // 727 + { "rd", RD }, // 728 + { "record", RECORD }, // 729 + { "recording", RECORDING }, // 730 + { "records", RECORDS }, // 731 + { "recursive", RECURSIVE }, // 732 + { "redefines", REDEFINES }, // 733 + { "reel", REEL }, // 734 + { "reference", REFERENCE }, // 735 + { "relative", RELATIVE }, // 736 + { "rem", REM }, // 737 + { "remainder", REMAINDER }, // 738 + { "remarks", REMARKS }, // 739 + { "removal", REMOVAL }, // 740 + { "renames", RENAMES }, // 741 + { "replace", REPLACE }, // 742 + { "replacing", REPLACING }, // 743 + { "report", REPORT }, // 744 + { "reporting", REPORTING }, // 745 + { "reports", REPORTS }, // 746 + { "repository", REPOSITORY }, // 747 + { "rerun", RERUN }, // 748 + { "reserve", RESERVE }, // 749 + { "restricted", RESTRICTED }, // 750 + { "resume", RESUME }, // 751 + { "reverse", REVERSE }, // 752 + { "reversed", REVERSED }, // 753 + { "rewind", REWIND }, // 754 + { "rf", RF }, // 755 + { "rh", RH }, // 756 + { "right", RIGHT }, // 757 + { "rounded", ROUNDED }, // 758 + { "run", RUN }, // 759 + { "same", SAME }, // 760 + { "screen", SCREEN }, // 761 + { "sd", SD }, // 762 + { "seconds-from-formatted-time", SECONDS_FROM_FORMATTED_TIME }, // 763 + { "seconds-past-midnight", SECONDS_PAST_MIDNIGHT }, // 764 + { "security", SECURITY }, // 765 + { "separate", SEPARATE }, // 766 + { "sequence", SEQUENCE }, // 767 + { "sequential", SEQUENTIAL }, // 768 + { "sharing", SHARING }, // 769 + { "simple-exit", SIMPLE_EXIT }, // 770 + { "sign", SIGN }, // 771 + { "sin", SIN }, // 772 + { "size", SIZE }, // 773 + { "smallest-algebraic", SMALLEST_ALGEBRAIC }, // 774 + { "source", SOURCE }, // 775 + { "source-computer", SOURCE_COMPUTER }, // 776 + { "special-names", SPECIAL_NAMES }, // 777 + { "sqrt", SQRT }, // 778 + { "stack", STACK }, // 779 + { "standard", STANDARD }, // 780 + { "standard-1", STANDARD_1 }, // 781 + { "standard-deviation", STANDARD_DEVIATION }, // 782 + { "standard-compare", STANDARD_COMPARE }, // 783 + { "status", STATUS }, // 784 + { "strong", STRONG }, // 785 + { "substitute", SUBSTITUTE }, // 786 + { "sum", SUM }, // 787 + { "symbol", SYMBOL }, // 788 + { "symbolic", SYMBOLIC }, // 789 + { "synchronized", SYNCHRONIZED }, // 790 + { "tally", TALLY }, // 791 + { "tallying", TALLYING }, // 792 + { "tan", TAN }, // 793 + { "terminate", TERMINATE }, // 794 + { "test", TEST }, // 795 + { "test-date-yyyymmdd", TEST_DATE_YYYYMMDD }, // 796 + { "test-day-yyyyddd", TEST_DAY_YYYYDDD }, // 797 + { "test-formatted-datetime", TEST_FORMATTED_DATETIME }, // 798 + { "test-numval", TEST_NUMVAL }, // 799 + { "test-numval-c", TEST_NUMVAL_C }, // 800 + { "test-numval-f", TEST_NUMVAL_F }, // 801 + { "than", THAN }, // 802 + { "time", TIME }, // 803 + { "times", TIMES }, // 804 + { "to", TO }, // 805 + { "top", TOP }, // 806 + { "top-level", TOP_LEVEL }, // 807 + { "tracks", TRACKS }, // 808 + { "track-area", TRACK_AREA }, // 809 + { "trailing", TRAILING }, // 810 + { "transform", TRANSFORM }, // 811 + { "trim", TRIM }, // 812 + { "true", TRUE_kw }, // 813 + { "try", TRY }, // 814 + { "turn", TURN }, // 815 + { "type", TYPE }, // 816 + { "typedef", TYPEDEF }, // 817 + { "ulength", ULENGTH }, // 818 + { "unbounded", UNBOUNDED }, // 819 + { "unit", UNIT }, // 820 + { "units", UNITS }, // 821 + { "unit-record", UNIT_RECORD }, // 822 + { "until", UNTIL }, // 823 + { "up", UP }, // 824 + { "upon", UPON }, // 825 + { "upos", UPOS }, // 826 + { "upper-case", UPPER_CASE }, // 827 + { "usage", USAGE }, // 828 + { "using", USING }, // 829 + { "usubstr", USUBSTR }, // 830 + { "usupplementary", USUPPLEMENTARY }, // 831 + { "utility", UTILITY }, // 832 + { "uuid4", UUID4 }, // 833 + { "uvalid", UVALID }, // 834 + { "uwidth", UWIDTH }, // 835 + { "value", VALUE }, // 836 + { "variance", VARIANCE }, // 837 + { "varying", VARYING }, // 838 + { "volatile", VOLATILE }, // 839 + { "when-compiled", WHEN_COMPILED }, // 840 + { "with", WITH }, // 841 + { "working-storage", WORKING_STORAGE }, // 842 + { "xml", XML }, // 843 + { "xmlgenerate", XMLGENERATE }, // 844 + { "xmlparse", XMLPARSE }, // 845 + { "year-to-yyyy", YEAR_TO_YYYY }, // 846 + { "yyyyddd", YYYYDDD }, // 847 + { "yyyymmdd", YYYYMMDD }, // 848 + { "arithmetic", ARITHMETIC }, // 849 + { "attribute", ATTRIBUTE }, // 850 + { "auto", AUTO }, // 851 + { "automatic", AUTOMATIC }, // 852 + { "away-from-zero", AWAY_FROM_ZERO }, // 853 + { "background-color", BACKGROUND_COLOR }, // 854 + { "bell", BELL }, // 855 + { "binary-encoding", BINARY_ENCODING }, // 856 + { "blink", BLINK }, // 857 + { "capacity", CAPACITY }, // 858 + { "center", CENTER }, // 859 + { "classification", CLASSIFICATION }, // 860 + { "cycle", CYCLE }, // 861 + { "decimal-encoding", DECIMAL_ENCODING }, // 862 + { "entry-convention", ENTRY_CONVENTION }, // 863 + { "eol", EOL }, // 864 + { "eos", EOS }, // 865 + { "erase", ERASE }, // 866 + { "expands", EXPANDS }, // 867 + { "float-binary", FLOAT_BINARY }, // 868 + { "float-decimal", FLOAT_DECIMAL }, // 869 + { "foreground-color", FOREGROUND_COLOR }, // 870 + { "forever", FOREVER }, // 871 + { "full", FULL }, // 872 + { "highlight", HIGHLIGHT }, // 873 + { "high-order-left", HIGH_ORDER_LEFT }, // 874 + { "high-order-right", HIGH_ORDER_RIGHT }, // 875 + { "ignoring", IGNORING }, // 876 + { "implements", IMPLEMENTS }, // 877 + { "initialized", INITIALIZED }, // 878 + { "intermediate", INTERMEDIATE }, // 879 + { "lc-all", LC_ALL_kw }, // 880 + { "lc-collate", LC_COLLATE_kw }, // 881 + { "lc-ctype", LC_CTYPE_kw }, // 882 + { "lc-messages", LC_MESSAGES_kw }, // 883 + { "lc-monetary", LC_MONETARY_kw }, // 884 + { "lc-numeric", LC_NUMERIC_kw }, // 885 + { "lc-time", LC_TIME_kw }, // 886 + { "lowlight", LOWLIGHT }, // 887 + { "nearest-away-from-zero", NEAREST_AWAY_FROM_ZERO }, // 888 + { "nearest-even", NEAREST_EVEN }, // 889 + { "nearest-toward-zero", NEAREST_TOWARD_ZERO }, // 890 + { "none", NONE }, // 891 + { "normal", NORMAL }, // 892 + { "numbers", NUMBERS }, // 893 + { "prefixed", PREFIXED }, // 894 + { "previous", PREVIOUS }, // 895 + { "prohibited", PROHIBITED }, // 896 + { "relation", RELATION }, // 897 + { "required", REQUIRED }, // 898 + { "reverse-video", REVERSE_VIDEO }, // 899 + { "rounding", ROUNDING }, // 900 + { "seconds", SECONDS }, // 901 + { "secure", SECURE }, // 902 + { "short", SHORT }, // 903 + { "signed", SIGNED_kw }, // 904 + { "standard-binary", STANDARD_BINARY }, // 905 + { "standard-decimal", STANDARD_DECIMAL }, // 906 + { "statement", STATEMENT }, // 907 + { "step", STEP }, // 908 + { "structure", STRUCTURE }, // 909 + { "toward-greater", TOWARD_GREATER }, // 910 + { "toward-lesser", TOWARD_LESSER }, // 911 + { "truncation", TRUNCATION }, // 912 + { "ucs-4", UCS_4 }, // 913 + { "underline", UNDERLINE }, // 914 + { "unsigned", UNSIGNED_kw }, // 915 + { "utf-16", UTF_16 }, // 916 + { "utf-8", UTF_8 }, // 917 + { "address", ADDRESS }, // 918 + { "end-accept", END_ACCEPT }, // 919 + { "end-add", END_ADD }, // 920 + { "end-call", END_CALL }, // 921 + { "end-compute", END_COMPUTE }, // 922 + { "end-delete", END_DELETE }, // 923 + { "end-display", END_DISPLAY }, // 924 + { "end-divide", END_DIVIDE }, // 925 + { "end-evaluate", END_EVALUATE }, // 926 + { "end-multiply", END_MULTIPLY }, // 927 + { "end-perform", END_PERFORM }, // 928 + { "end-read", END_READ }, // 929 + { "end-return", END_RETURN }, // 930 + { "end-rewrite", END_REWRITE }, // 931 + { "end-search", END_SEARCH }, // 932 + { "end-start", END_START }, // 933 + { "end-string", END_STRING }, // 934 + { "end-subtract", END_SUBTRACT }, // 935 + { "end-unstring", END_UNSTRING }, // 936 + { "end-write", END_WRITE }, // 937 + { "end-if", END_IF }, // 938 + { "thru", THRU }, // 939 + { "through", THRU }, // 939 + { "or", OR }, // 940 + { "and", AND }, // 941 + { "not", NOT }, // 942 + { "ne", NE }, // 943 + { "le", LE }, // 944 + { "ge", GE }, // 945 + { "pow", POW }, // 946 + { "neg", NEG }, // 947 }; // cppcheck-suppress useInitializationList @@ -826,553 +834,561 @@ token_names = { "CDF-EVALUATE", // 130 (388) "CDF-WHEN", // 131 (389) "CDF-END-EVALUATE", // 132 (390) - "CALL-COBOL", // 133 (391) - "CALL-VERBATIM", // 134 (392) - "IF", // 135 (393) - "THEN", // 136 (394) - "ELSE", // 137 (395) - "SENTENCE", // 138 (396) - "ACCEPT", // 139 (397) - "ADD", // 140 (398) - "ALTER", // 141 (399) - "CALL", // 142 (400) - "CANCEL", // 143 (401) - "CLOSE", // 144 (402) - "COMPUTE", // 145 (403) - "CONTINUE", // 146 (404) - "DELETE", // 147 (405) - "DISPLAY", // 148 (406) - "DIVIDE", // 149 (407) - "EVALUATE", // 150 (408) - "EXIT", // 151 (409) - "FILLER", // 152 (410) - "GOBACK", // 153 (411) - "GOTO", // 154 (412) - "INITIALIZE", // 155 (413) - "INSPECT", // 156 (414) - "MERGE", // 157 (415) - "MOVE", // 158 (416) - "MULTIPLY", // 159 (417) - "OPEN", // 160 (418) - "PARAGRAPH", // 161 (419) - "READ", // 162 (420) - "RELEASE", // 163 (421) - "RETURN", // 164 (422) - "REWRITE", // 165 (423) - "SEARCH", // 166 (424) - "SET", // 167 (425) - "SELECT", // 168 (426) - "SORT", // 169 (427) - "SORT-MERGE", // 170 (428) - "STRING", // 171 (429) - "STOP", // 172 (430) - "SUBTRACT", // 173 (431) - "START", // 174 (432) - "UNSTRING", // 175 (433) - "WRITE", // 176 (434) - "WHEN", // 177 (435) - "ABS", // 178 (436) - "ACCESS", // 179 (437) - "ACOS", // 180 (438) - "ACTUAL", // 181 (439) - "ADVANCING", // 182 (440) - "AFTER", // 183 (441) - "ALL", // 184 (442) - "ALLOCATE", // 185 (443) - "ALPHABET", // 186 (444) - "ALPHABETIC", // 187 (445) - "ALPHABETIC-LOWER", // 188 (446) - "ALPHABETIC-UPPER", // 189 (447) - "ALPHANUMERIC", // 190 (448) - "ALPHANUMERIC-EDITED", // 191 (449) - "ALSO", // 192 (450) - "ALTERNATE", // 193 (451) - "ANNUITY", // 194 (452) - "ANUM", // 195 (453) - "ANY", // 196 (454) - "ANYCASE", // 197 (455) - "APPLY", // 198 (456) - "ARE", // 199 (457) - "AREA", // 200 (458) - "AREAS", // 201 (459) - "AS", // 202 (460) - "ASCENDING", // 203 (461) - "ACTIVATING", // 204 (462) - "ASIN", // 205 (463) - "ASSIGN", // 206 (464) - "AT", // 207 (465) - "ATAN", // 208 (466) - "BASED", // 209 (467) - "BASECONVERT", // 210 (468) - "BEFORE", // 211 (469) - "BINARY", // 212 (470) - "BIT", // 213 (471) - "BIT-OF", // 214 (472) - "BIT-TO-CHAR", // 215 (473) - "BLANK", // 216 (474) - "BLOCK", // 217 (475) - "BOOLEAN-OF-INTEGER", // 218 (476) - "BOTTOM", // 219 (477) - "BY", // 220 (478) - "BYTE", // 221 (479) - "BYTE-LENGTH", // 222 (480) - "CF", // 223 (481) - "CH", // 224 (482) - "CHANGED", // 225 (483) - "CHAR", // 226 (484) - "CHAR-NATIONAL", // 227 (485) - "CHARACTER", // 228 (486) - "CHARACTERS", // 229 (487) - "CHECKING", // 230 (488) - "CLASS", // 231 (489) - "COBOL", // 232 (490) - "CODE", // 233 (491) - "CODE-SET", // 234 (492) - "COLLATING", // 235 (493) - "COLUMN", // 236 (494) - "COMBINED-DATETIME", // 237 (495) - "COMMA", // 238 (496) - "COMMAND-LINE", // 239 (497) - "COMMAND-LINE-COUNT", // 240 (498) - "COMMIT", // 241 (499) - "COMMON", // 242 (500) - "CONCAT", // 243 (501) - "CONDITION", // 244 (502) - "CONFIGURATION", // 245 (503) - "CONTAINS", // 246 (504) - "CONTENT", // 247 (505) - "CONTROL", // 248 (506) - "CONTROLS", // 249 (507) - "CONVERT", // 250 (508) - "CONVERTING", // 251 (509) - "CORRESPONDING", // 252 (510) - "COS", // 253 (511) - "COUNT", // 254 (512) - "CURRENCY", // 255 (513) - "CURRENT", // 256 (514) - "CURRENT-DATE", // 257 (515) - "DATA", // 258 (516) - "DATE", // 259 (517) - "DATE-COMPILED", // 260 (518) - "DATE-OF-INTEGER", // 261 (519) - "DATE-TO-YYYYMMDD", // 262 (520) - "DATE-WRITTEN", // 263 (521) - "DAY", // 264 (522) - "DAY-OF-INTEGER", // 265 (523) - "DAY-OF-WEEK", // 266 (524) - "DAY-TO-YYYYDDD", // 267 (525) - "DBCS", // 268 (526) - "DE", // 269 (527) - "DEBUGGING", // 270 (528) - "DECIMAL-POINT", // 271 (529) - "DECLARATIVES", // 272 (530) - "DEFAULT", // 273 (531) - "DELIMITED", // 274 (532) - "DELIMITER", // 275 (533) - "DEPENDING", // 276 (534) - "DESCENDING", // 277 (535) - "DETAIL", // 278 (536) - "DIRECT", // 279 (537) - "DIRECT-ACCESS", // 280 (538) - "DOWN", // 281 (539) - "DUPLICATES", // 282 (540) - "DYNAMIC", // 283 (541) - "E", // 284 (542) - "EBCDIC", // 285 (543) - "EC", // 286 (544) - "EGCS", // 287 (545) - "ENTRY", // 288 (546) - "ENVIRONMENT", // 289 (547) - "EQUAL", // 290 (548) - "EVERY", // 291 (549) - "EXAMINE", // 292 (550) - "EXHIBIT", // 293 (551) - "EXP", // 294 (552) - "EXP10", // 295 (553) - "EXTEND", // 296 (554) - "EXTERNAL", // 297 (555) - "EXCEPTION-FILE", // 298 (556) - "EXCEPTION-FILE-N", // 299 (557) - "EXCEPTION-LOCATION", // 300 (558) - "EXCEPTION-LOCATION-N", // 301 (559) - "EXCEPTION-STATEMENT", // 302 (560) - "EXCEPTION-STATUS", // 303 (561) - "FACTORIAL", // 304 (562) - "FALSE", // 305 (563) - "FD", // 306 (564) - "FILE-CONTROL", // 307 (565) - "FILE", // 308 (566) - "FILE-LIMIT", // 309 (567) - "FINAL", // 310 (568) - "FINALLY", // 311 (569) - "FIND-STRING", // 312 (570) - "FIRST", // 313 (571) - "FIXED", // 314 (572) - "FOOTING", // 315 (573) - "FOR", // 316 (574) - "FORMATTED-CURRENT-DATE", // 317 (575) - "FORMATTED-DATE", // 318 (576) - "FORMATTED-DATETIME", // 319 (577) - "FORMATTED-TIME", // 320 (578) - "FORM-OVERFLOW", // 321 (579) - "FREE", // 322 (580) - "FRACTION-PART", // 323 (581) - "FROM", // 324 (582) - "FUNCTION", // 325 (583) - "GENERATE", // 326 (584) - "GIVING", // 327 (585) - "GLOBAL", // 328 (586) - "GO", // 329 (587) - "GROUP", // 330 (588) - "HEADING", // 331 (589) - "HEX", // 332 (590) - "HEX-OF", // 333 (591) - "HEX-TO-CHAR", // 334 (592) - "HIGH-VALUES", // 335 (593) - "HIGHEST-ALGEBRAIC", // 336 (594) - "HOLD", // 337 (595) - "IBM-360", // 338 (596) - "IN", // 339 (597) - "INCLUDE", // 340 (598) - "INDEX", // 341 (599) - "INDEXED", // 342 (600) - "INDICATE", // 343 (601) - "INITIAL", // 344 (602) - "INITIATE", // 345 (603) - "INPUT", // 346 (604) - "INSTALLATION", // 347 (605) - "INTERFACE", // 348 (606) - "INTEGER", // 349 (607) - "INTEGER-OF-BOOLEAN", // 350 (608) - "INTEGER-OF-DATE", // 351 (609) - "INTEGER-OF-DAY", // 352 (610) - "INTEGER-OF-FORMATTED-DATE", // 353 (611) - "INTEGER-PART", // 354 (612) - "INTO", // 355 (613) - "INTRINSIC", // 356 (614) - "INVOKE", // 357 (615) - "I-O", // 358 (616) - "I-O-CONTROL", // 359 (617) - "IS", // 360 (618) - "ISNT", // 361 (619) - "KANJI", // 362 (620) - "KEY", // 363 (621) - "LABEL", // 364 (622) - "LAST", // 365 (623) - "LEADING", // 366 (624) - "LEFT", // 367 (625) - "LENGTH", // 368 (626) - "LENGTH-OF", // 369 (627) - "LIMIT", // 370 (628) - "LIMITS", // 371 (629) - "LINE", // 372 (630) - "LINES", // 373 (631) - "LINE-COUNTER", // 374 (632) - "LINAGE", // 375 (633) - "LINKAGE", // 376 (634) - "LOCALE", // 377 (635) - "LOCALE-COMPARE", // 378 (636) - "LOCALE-DATE", // 379 (637) - "LOCALE-TIME", // 380 (638) - "LOCALE-TIME-FROM-SECONDS", // 381 (639) - "LOCAL-STORAGE", // 382 (640) - "LOCATION", // 383 (641) - "LOCK", // 384 (642) - "LOCK-ON", // 385 (643) - "LOG", // 386 (644) - "LOG10", // 387 (645) - "LOWER-CASE", // 388 (646) - "LOW-VALUES", // 389 (647) - "LOWEST-ALGEBRAIC", // 390 (648) - "LPAREN", // 391 (649) - "MANUAL", // 392 (650) - "MAXX", // 393 (651) - "MEAN", // 394 (652) - "MEDIAN", // 395 (653) - "MIDRANGE", // 396 (654) - "MINN", // 397 (655) - "MULTIPLE", // 398 (656) - "MOD", // 399 (657) - "MODE", // 400 (658) - "MODULE-NAME", // 401 (659) - "NAMED", // 402 (660) - "NAT", // 403 (661) - "NATIONAL", // 404 (662) - "NATIONAL-EDITED", // 405 (663) - "NATIONAL-OF", // 406 (664) - "NATIVE", // 407 (665) - "NESTED", // 408 (666) - "NEXT", // 409 (667) - "NO", // 410 (668) - "NOTE", // 411 (669) - "NULLS", // 412 (670) - "NULLPTR", // 413 (671) - "NUMERIC", // 414 (672) - "NUMERIC-EDITED", // 415 (673) - "NUMVAL", // 416 (674) - "NUMVAL-C", // 417 (675) - "NUMVAL-F", // 418 (676) - "OCCURS", // 419 (677) - "OF", // 420 (678) - "OFF", // 421 (679) - "OMITTED", // 422 (680) - "ON", // 423 (681) - "ONLY", // 424 (682) - "OPTIONAL", // 425 (683) - "OPTIONS", // 426 (684) - "ORD", // 427 (685) - "ORDER", // 428 (686) - "ORD-MAX", // 429 (687) - "ORD-MIN", // 430 (688) - "ORGANIZATION", // 431 (689) - "OTHER", // 432 (690) - "OTHERWISE", // 433 (691) - "OUTPUT", // 434 (692) - "PACKED-DECIMAL", // 435 (693) - "PADDING", // 436 (694) - "PAGE", // 437 (695) - "PAGE-COUNTER", // 438 (696) - "PF", // 439 (697) - "PH", // 440 (698) - "PI", // 441 (699) - "PIC", // 442 (700) - "PICTURE", // 443 (701) - "PLUS", // 444 (702) - "PRESENT-VALUE", // 445 (703) - "PRINT-SWITCH", // 446 (704) - "PROCEDURE", // 447 (705) - "PROCEDURES", // 448 (706) - "PROCEED", // 449 (707) - "PROCESS", // 450 (708) - "PROGRAM-ID", // 451 (709) - "PROGRAM", // 452 (710) - "PROPERTY", // 453 (711) - "PROTOTYPE", // 454 (712) - "PSEUDOTEXT", // 455 (713) - "QUOTES", // 456 (714) - "RANDOM", // 457 (715) - "RANDOM-SEED", // 458 (716) - "RANGE", // 459 (717) - "RAISE", // 460 (718) - "RAISING", // 461 (719) - "RD", // 462 (720) - "RECORD", // 463 (721) - "RECORDING", // 464 (722) - "RECORDS", // 465 (723) - "RECURSIVE", // 466 (724) - "REDEFINES", // 467 (725) - "REEL", // 468 (726) - "REFERENCE", // 469 (727) - "RELATIVE", // 470 (728) - "REM", // 471 (729) - "REMAINDER", // 472 (730) - "REMARKS", // 473 (731) - "REMOVAL", // 474 (732) - "RENAMES", // 475 (733) - "REPLACE", // 476 (734) - "REPLACING", // 477 (735) - "REPORT", // 478 (736) - "REPORTING", // 479 (737) - "REPORTS", // 480 (738) - "REPOSITORY", // 481 (739) - "RERUN", // 482 (740) - "RESERVE", // 483 (741) - "RESTRICTED", // 484 (742) - "RESUME", // 485 (743) - "REVERSE", // 486 (744) - "REVERSED", // 487 (745) - "REWIND", // 488 (746) - "RF", // 489 (747) - "RH", // 490 (748) - "RIGHT", // 491 (749) - "ROUNDED", // 492 (750) - "RUN", // 493 (751) - "SAME", // 494 (752) - "SCREEN", // 495 (753) - "SD", // 496 (754) - "SECONDS-FROM-FORMATTED-TIME", // 497 (755) - "SECONDS-PAST-MIDNIGHT", // 498 (756) - "SECURITY", // 499 (757) - "SEPARATE", // 500 (758) - "SEQUENCE", // 501 (759) - "SEQUENTIAL", // 502 (760) - "SHARING", // 503 (761) - "SIMPLE-EXIT", // 504 (762) - "SIGN", // 505 (763) - "SIN", // 506 (764) - "SIZE", // 507 (765) - "SMALLEST-ALGEBRAIC", // 508 (766) - "SOURCE", // 509 (767) - "SOURCE-COMPUTER", // 510 (768) - "SPECIAL-NAMES", // 511 (769) - "SQRT", // 512 (770) - "STACK", // 513 (771) - "STANDARD", // 514 (772) - "STANDARD-1", // 515 (773) - "STANDARD-DEVIATION", // 516 (774) - "STANDARD-COMPARE", // 517 (775) - "STATUS", // 518 (776) - "STRONG", // 519 (777) - "SUBSTITUTE", // 520 (778) - "SUM", // 521 (779) - "SYMBOL", // 522 (780) - "SYMBOLIC", // 523 (781) - "SYNCHRONIZED", // 524 (782) - "TALLY", // 525 (783) - "TALLYING", // 526 (784) - "TAN", // 527 (785) - "TERMINATE", // 528 (786) - "TEST", // 529 (787) - "TEST-DATE-YYYYMMDD", // 530 (788) - "TEST-DAY-YYYYDDD", // 531 (789) - "TEST-FORMATTED-DATETIME", // 532 (790) - "TEST-NUMVAL", // 533 (791) - "TEST-NUMVAL-C", // 534 (792) - "TEST-NUMVAL-F", // 535 (793) - "THAN", // 536 (794) - "TIME", // 537 (795) - "TIMES", // 538 (796) - "TO", // 539 (797) - "TOP", // 540 (798) - "TOP-LEVEL", // 541 (799) - "TRACKS", // 542 (800) - "TRACK-AREA", // 543 (801) - "TRAILING", // 544 (802) - "TRANSFORM", // 545 (803) - "TRIM", // 546 (804) - "TRUE", // 547 (805) - "TRY", // 548 (806) - "TURN", // 549 (807) - "TYPE", // 550 (808) - "TYPEDEF", // 551 (809) - "ULENGTH", // 552 (810) - "UNBOUNDED", // 553 (811) - "UNIT", // 554 (812) - "UNITS", // 555 (813) - "UNIT-RECORD", // 556 (814) - "UNTIL", // 557 (815) - "UP", // 558 (816) - "UPON", // 559 (817) - "UPOS", // 560 (818) - "UPPER-CASE", // 561 (819) - "USAGE", // 562 (820) - "USING", // 563 (821) - "USUBSTR", // 564 (822) - "USUPPLEMENTARY", // 565 (823) - "UTILITY", // 566 (824) - "UUID4", // 567 (825) - "UVALID", // 568 (826) - "UWIDTH", // 569 (827) - "VALUE", // 570 (828) - "VARIANCE", // 571 (829) - "VARYING", // 572 (830) - "VOLATILE", // 573 (831) - "WHEN-COMPILED", // 574 (832) - "WITH", // 575 (833) - "WORKING-STORAGE", // 576 (834) - "XML", // 577 (835) - "XMLGENERATE", // 578 (836) - "XMLPARSE", // 579 (837) - "YEAR-TO-YYYY", // 580 (838) - "YYYYDDD", // 581 (839) - "YYYYMMDD", // 582 (840) - "ARITHMETIC", // 583 (841) - "ATTRIBUTE", // 584 (842) - "AUTO", // 585 (843) - "AUTOMATIC", // 586 (844) - "AWAY-FROM-ZERO", // 587 (845) - "BACKGROUND-COLOR", // 588 (846) - "BELL", // 589 (847) - "BINARY-ENCODING", // 590 (848) - "BLINK", // 591 (849) - "CAPACITY", // 592 (850) - "CENTER", // 593 (851) - "CLASSIFICATION", // 594 (852) - "CYCLE", // 595 (853) - "DECIMAL-ENCODING", // 596 (854) - "ENTRY-CONVENTION", // 597 (855) - "EOL", // 598 (856) - "EOS", // 599 (857) - "ERASE", // 600 (858) - "EXPANDS", // 601 (859) - "FLOAT-BINARY", // 602 (860) - "FLOAT-DECIMAL", // 603 (861) - "FOREGROUND-COLOR", // 604 (862) - "FOREVER", // 605 (863) - "FULL", // 606 (864) - "HIGHLIGHT", // 607 (865) - "HIGH-ORDER-LEFT", // 608 (866) - "HIGH-ORDER-RIGHT", // 609 (867) - "IGNORING", // 610 (868) - "IMPLEMENTS", // 611 (869) - "INITIALIZED", // 612 (870) - "INTERMEDIATE", // 613 (871) - "LC-ALL", // 614 (872) - "LC-COLLATE", // 615 (873) - "LC-CTYPE", // 616 (874) - "LC-MESSAGES", // 617 (875) - "LC-MONETARY", // 618 (876) - "LC-NUMERIC", // 619 (877) - "LC-TIME", // 620 (878) - "LOWLIGHT", // 621 (879) - "NEAREST-AWAY-FROM-ZERO", // 622 (880) - "NEAREST-EVEN", // 623 (881) - "NEAREST-TOWARD-ZERO", // 624 (882) - "NONE", // 625 (883) - "NORMAL", // 626 (884) - "NUMBERS", // 627 (885) - "PREFIXED", // 628 (886) - "PREVIOUS", // 629 (887) - "PROHIBITED", // 630 (888) - "RELATION", // 631 (889) - "REQUIRED", // 632 (890) - "REVERSE-VIDEO", // 633 (891) - "ROUNDING", // 634 (892) - "SECONDS", // 635 (893) - "SECURE", // 636 (894) - "SHORT", // 637 (895) - "SIGNED", // 638 (896) - "STANDARD-BINARY", // 639 (897) - "STANDARD-DECIMAL", // 640 (898) - "STATEMENT", // 641 (899) - "STEP", // 642 (900) - "STRUCTURE", // 643 (901) - "TOWARD-GREATER", // 644 (902) - "TOWARD-LESSER", // 645 (903) - "TRUNCATION", // 646 (904) - "UCS-4", // 647 (905) - "UNDERLINE", // 648 (906) - "UNSIGNED", // 649 (907) - "UTF-16", // 650 (908) - "UTF-8", // 651 (909) - "ADDRESS", // 652 (910) - "END-ACCEPT", // 653 (911) - "END-ADD", // 654 (912) - "END-CALL", // 655 (913) - "END-COMPUTE", // 656 (914) - "END-DELETE", // 657 (915) - "END-DISPLAY", // 658 (916) - "END-DIVIDE", // 659 (917) - "END-EVALUATE", // 660 (918) - "END-MULTIPLY", // 661 (919) - "END-PERFORM", // 662 (920) - "END-READ", // 663 (921) - "END-RETURN", // 664 (922) - "END-REWRITE", // 665 (923) - "END-SEARCH", // 666 (924) - "END-START", // 667 (925) - "END-STRING", // 668 (926) - "END-SUBTRACT", // 669 (927) - "END-UNSTRING", // 670 (928) - "END-WRITE", // 671 (929) - "END-IF", // 672 (930) - "THRU", // 673 (931) - "OR", // 674 (932) - "AND", // 675 (933) - "NOT", // 676 (934) - "NE", // 677 (935) - "LE", // 678 (936) - "GE", // 679 (937) - "POW", // 680 (938) - "NEG", // 681 (939) + "CALL-CONVENTION", // 133 (391) + "CALL-COBOL", // 134 (392) + "CALL-VERBATIM", // 135 (393) + "CDF-PUSH", // 136 (394) + "CDF-POP", // 137 (395) + "SOURCE-FORMAT", // 138 (396) + "IF", // 139 (397) + "THEN", // 140 (398) + "ELSE", // 141 (399) + "SENTENCE", // 142 (400) + "ACCEPT", // 143 (401) + "ADD", // 144 (402) + "ALTER", // 145 (403) + "CALL", // 146 (404) + "CANCEL", // 147 (405) + "CLOSE", // 148 (406) + "COMPUTE", // 149 (407) + "CONTINUE", // 150 (408) + "DELETE", // 151 (409) + "DISPLAY", // 152 (410) + "DIVIDE", // 153 (411) + "EVALUATE", // 154 (412) + "EXIT", // 155 (413) + "FILLER", // 156 (414) + "GOBACK", // 157 (415) + "GOTO", // 158 (416) + "INITIALIZE", // 159 (417) + "INSPECT", // 160 (418) + "MERGE", // 161 (419) + "MOVE", // 162 (420) + "MULTIPLY", // 163 (421) + "OPEN", // 164 (422) + "PARAGRAPH", // 165 (423) + "READ", // 166 (424) + "RELEASE", // 167 (425) + "RETURN", // 168 (426) + "REWRITE", // 169 (427) + "SEARCH", // 170 (428) + "SET", // 171 (429) + "SELECT", // 172 (430) + "SORT", // 173 (431) + "SORT-MERGE", // 174 (432) + "STRING", // 175 (433) + "STOP", // 176 (434) + "SUBTRACT", // 177 (435) + "START", // 178 (436) + "UNSTRING", // 179 (437) + "WRITE", // 180 (438) + "WHEN", // 181 (439) + "ARGUMENT-NUMBER", // 182 (440) + "ARGUMENT-VALUE", // 183 (441) + "ENVIRONMENT-NAME", // 184 (442) + "ENVIRONMENT-VALUE", // 185 (443) + "ABS", // 186 (444) + "ACCESS", // 187 (445) + "ACOS", // 188 (446) + "ACTUAL", // 189 (447) + "ADVANCING", // 190 (448) + "AFTER", // 191 (449) + "ALL", // 192 (450) + "ALLOCATE", // 193 (451) + "ALPHABET", // 194 (452) + "ALPHABETIC", // 195 (453) + "ALPHABETIC-LOWER", // 196 (454) + "ALPHABETIC-UPPER", // 197 (455) + "ALPHANUMERIC", // 198 (456) + "ALPHANUMERIC-EDITED", // 199 (457) + "ALSO", // 200 (458) + "ALTERNATE", // 201 (459) + "ANNUITY", // 202 (460) + "ANUM", // 203 (461) + "ANY", // 204 (462) + "ANYCASE", // 205 (463) + "APPLY", // 206 (464) + "ARE", // 207 (465) + "AREA", // 208 (466) + "AREAS", // 209 (467) + "AS", // 210 (468) + "ASCENDING", // 211 (469) + "ACTIVATING", // 212 (470) + "ASIN", // 213 (471) + "ASSIGN", // 214 (472) + "AT", // 215 (473) + "ATAN", // 216 (474) + "BASED", // 217 (475) + "BASECONVERT", // 218 (476) + "BEFORE", // 219 (477) + "BINARY", // 220 (478) + "BIT", // 221 (479) + "BIT-OF", // 222 (480) + "BIT-TO-CHAR", // 223 (481) + "BLANK", // 224 (482) + "BLOCK", // 225 (483) + "BOOLEAN-OF-INTEGER", // 226 (484) + "BOTTOM", // 227 (485) + "BY", // 228 (486) + "BYTE", // 229 (487) + "BYTE-LENGTH", // 230 (488) + "CF", // 231 (489) + "CH", // 232 (490) + "CHANGED", // 233 (491) + "CHAR", // 234 (492) + "CHAR-NATIONAL", // 235 (493) + "CHARACTER", // 236 (494) + "CHARACTERS", // 237 (495) + "CHECKING", // 238 (496) + "CLASS", // 239 (497) + "COBOL", // 240 (498) + "CODE", // 241 (499) + "CODE-SET", // 242 (500) + "COLLATING", // 243 (501) + "COLUMN", // 244 (502) + "COMBINED-DATETIME", // 245 (503) + "COMMA", // 246 (504) + "COMMAND-LINE", // 247 (505) + "COMMAND-LINE-COUNT", // 248 (506) + "COMMIT", // 249 (507) + "COMMON", // 250 (508) + "CONCAT", // 251 (509) + "CONDITION", // 252 (510) + "CONFIGURATION", // 253 (511) + "CONTAINS", // 254 (512) + "CONTENT", // 255 (513) + "CONTROL", // 256 (514) + "CONTROLS", // 257 (515) + "CONVERT", // 258 (516) + "CONVERTING", // 259 (517) + "CORRESPONDING", // 260 (518) + "COS", // 261 (519) + "COUNT", // 262 (520) + "CURRENCY", // 263 (521) + "CURRENT", // 264 (522) + "CURRENT-DATE", // 265 (523) + "DATA", // 266 (524) + "DATE", // 267 (525) + "DATE-COMPILED", // 268 (526) + "DATE-OF-INTEGER", // 269 (527) + "DATE-TO-YYYYMMDD", // 270 (528) + "DATE-WRITTEN", // 271 (529) + "DAY", // 272 (530) + "DAY-OF-INTEGER", // 273 (531) + "DAY-OF-WEEK", // 274 (532) + "DAY-TO-YYYYDDD", // 275 (533) + "DBCS", // 276 (534) + "DE", // 277 (535) + "DEBUGGING", // 278 (536) + "DECIMAL-POINT", // 279 (537) + "DECLARATIVES", // 280 (538) + "DEFAULT", // 281 (539) + "DELIMITED", // 282 (540) + "DELIMITER", // 283 (541) + "DEPENDING", // 284 (542) + "DESCENDING", // 285 (543) + "DETAIL", // 286 (544) + "DIRECT", // 287 (545) + "DIRECT-ACCESS", // 288 (546) + "DOWN", // 289 (547) + "DUPLICATES", // 290 (548) + "DYNAMIC", // 291 (549) + "E", // 292 (550) + "EBCDIC", // 293 (551) + "EC", // 294 (552) + "EGCS", // 295 (553) + "ENTRY", // 296 (554) + "ENVIRONMENT", // 297 (555) + "EQUAL", // 298 (556) + "EVERY", // 299 (557) + "EXAMINE", // 300 (558) + "EXHIBIT", // 301 (559) + "EXP", // 302 (560) + "EXP10", // 303 (561) + "EXTEND", // 304 (562) + "EXTERNAL", // 305 (563) + "EXCEPTION-FILE", // 306 (564) + "EXCEPTION-FILE-N", // 307 (565) + "EXCEPTION-LOCATION", // 308 (566) + "EXCEPTION-LOCATION-N", // 309 (567) + "EXCEPTION-STATEMENT", // 310 (568) + "EXCEPTION-STATUS", // 311 (569) + "FACTORIAL", // 312 (570) + "FALSE", // 313 (571) + "FD", // 314 (572) + "FILE-CONTROL", // 315 (573) + "FILE", // 316 (574) + "FILE-LIMIT", // 317 (575) + "FINAL", // 318 (576) + "FINALLY", // 319 (577) + "FIND-STRING", // 320 (578) + "FIRST", // 321 (579) + "FIXED", // 322 (580) + "FOOTING", // 323 (581) + "FOR", // 324 (582) + "FORMATTED-CURRENT-DATE", // 325 (583) + "FORMATTED-DATE", // 326 (584) + "FORMATTED-DATETIME", // 327 (585) + "FORMATTED-TIME", // 328 (586) + "FORM-OVERFLOW", // 329 (587) + "FREE", // 330 (588) + "FRACTION-PART", // 331 (589) + "FROM", // 332 (590) + "FUNCTION", // 333 (591) + "GENERATE", // 334 (592) + "GIVING", // 335 (593) + "GLOBAL", // 336 (594) + "GO", // 337 (595) + "GROUP", // 338 (596) + "HEADING", // 339 (597) + "HEX", // 340 (598) + "HEX-OF", // 341 (599) + "HEX-TO-CHAR", // 342 (600) + "HIGH-VALUES", // 343 (601) + "HIGHEST-ALGEBRAIC", // 344 (602) + "HOLD", // 345 (603) + "IBM-360", // 346 (604) + "IN", // 347 (605) + "INCLUDE", // 348 (606) + "INDEX", // 349 (607) + "INDEXED", // 350 (608) + "INDICATE", // 351 (609) + "INITIAL", // 352 (610) + "INITIATE", // 353 (611) + "INPUT", // 354 (612) + "INSTALLATION", // 355 (613) + "INTERFACE", // 356 (614) + "INTEGER", // 357 (615) + "INTEGER-OF-BOOLEAN", // 358 (616) + "INTEGER-OF-DATE", // 359 (617) + "INTEGER-OF-DAY", // 360 (618) + "INTEGER-OF-FORMATTED-DATE", // 361 (619) + "INTEGER-PART", // 362 (620) + "INTO", // 363 (621) + "INTRINSIC", // 364 (622) + "INVOKE", // 365 (623) + "I-O", // 366 (624) + "I-O-CONTROL", // 367 (625) + "IS", // 368 (626) + "ISNT", // 369 (627) + "KANJI", // 370 (628) + "KEY", // 371 (629) + "LABEL", // 372 (630) + "LAST", // 373 (631) + "LEADING", // 374 (632) + "LEFT", // 375 (633) + "LENGTH", // 376 (634) + "LENGTH-OF", // 377 (635) + "LIMIT", // 378 (636) + "LIMITS", // 379 (637) + "LINE", // 380 (638) + "LINES", // 381 (639) + "LINE-COUNTER", // 382 (640) + "LINAGE", // 383 (641) + "LINKAGE", // 384 (642) + "LOCALE", // 385 (643) + "LOCALE-COMPARE", // 386 (644) + "LOCALE-DATE", // 387 (645) + "LOCALE-TIME", // 388 (646) + "LOCALE-TIME-FROM-SECONDS", // 389 (647) + "LOCAL-STORAGE", // 390 (648) + "LOCATION", // 391 (649) + "LOCK", // 392 (650) + "LOCK-ON", // 393 (651) + "LOG", // 394 (652) + "LOG10", // 395 (653) + "LOWER-CASE", // 396 (654) + "LOW-VALUES", // 397 (655) + "LOWEST-ALGEBRAIC", // 398 (656) + "LPAREN", // 399 (657) + "MANUAL", // 400 (658) + "MAXX", // 401 (659) + "MEAN", // 402 (660) + "MEDIAN", // 403 (661) + "MIDRANGE", // 404 (662) + "MINN", // 405 (663) + "MULTIPLE", // 406 (664) + "MOD", // 407 (665) + "MODE", // 408 (666) + "MODULE-NAME", // 409 (667) + "NAMED", // 410 (668) + "NAT", // 411 (669) + "NATIONAL", // 412 (670) + "NATIONAL-EDITED", // 413 (671) + "NATIONAL-OF", // 414 (672) + "NATIVE", // 415 (673) + "NESTED", // 416 (674) + "NEXT", // 417 (675) + "NO", // 418 (676) + "NOTE", // 419 (677) + "NULLS", // 420 (678) + "NULLPTR", // 421 (679) + "NUMERIC", // 422 (680) + "NUMERIC-EDITED", // 423 (681) + "NUMVAL", // 424 (682) + "NUMVAL-C", // 425 (683) + "NUMVAL-F", // 426 (684) + "OCCURS", // 427 (685) + "OF", // 428 (686) + "OFF", // 429 (687) + "OMITTED", // 430 (688) + "ON", // 431 (689) + "ONLY", // 432 (690) + "OPTIONAL", // 433 (691) + "OPTIONS", // 434 (692) + "ORD", // 435 (693) + "ORDER", // 436 (694) + "ORD-MAX", // 437 (695) + "ORD-MIN", // 438 (696) + "ORGANIZATION", // 439 (697) + "OTHER", // 440 (698) + "OTHERWISE", // 441 (699) + "OUTPUT", // 442 (700) + "PACKED-DECIMAL", // 443 (701) + "PADDING", // 444 (702) + "PAGE", // 445 (703) + "PAGE-COUNTER", // 446 (704) + "PF", // 447 (705) + "PH", // 448 (706) + "PI", // 449 (707) + "PIC", // 450 (708) + "PICTURE", // 451 (709) + "PLUS", // 452 (710) + "PRESENT-VALUE", // 453 (711) + "PRINT-SWITCH", // 454 (712) + "PROCEDURE", // 455 (713) + "PROCEDURES", // 456 (714) + "PROCEED", // 457 (715) + "PROCESS", // 458 (716) + "PROGRAM-ID", // 459 (717) + "PROGRAM", // 460 (718) + "PROPERTY", // 461 (719) + "PROTOTYPE", // 462 (720) + "PSEUDOTEXT", // 463 (721) + "QUOTES", // 464 (722) + "RANDOM", // 465 (723) + "RANDOM-SEED", // 466 (724) + "RANGE", // 467 (725) + "RAISE", // 468 (726) + "RAISING", // 469 (727) + "RD", // 470 (728) + "RECORD", // 471 (729) + "RECORDING", // 472 (730) + "RECORDS", // 473 (731) + "RECURSIVE", // 474 (732) + "REDEFINES", // 475 (733) + "REEL", // 476 (734) + "REFERENCE", // 477 (735) + "RELATIVE", // 478 (736) + "REM", // 479 (737) + "REMAINDER", // 480 (738) + "REMARKS", // 481 (739) + "REMOVAL", // 482 (740) + "RENAMES", // 483 (741) + "REPLACE", // 484 (742) + "REPLACING", // 485 (743) + "REPORT", // 486 (744) + "REPORTING", // 487 (745) + "REPORTS", // 488 (746) + "REPOSITORY", // 489 (747) + "RERUN", // 490 (748) + "RESERVE", // 491 (749) + "RESTRICTED", // 492 (750) + "RESUME", // 493 (751) + "REVERSE", // 494 (752) + "REVERSED", // 495 (753) + "REWIND", // 496 (754) + "RF", // 497 (755) + "RH", // 498 (756) + "RIGHT", // 499 (757) + "ROUNDED", // 500 (758) + "RUN", // 501 (759) + "SAME", // 502 (760) + "SCREEN", // 503 (761) + "SD", // 504 (762) + "SECONDS-FROM-FORMATTED-TIME", // 505 (763) + "SECONDS-PAST-MIDNIGHT", // 506 (764) + "SECURITY", // 507 (765) + "SEPARATE", // 508 (766) + "SEQUENCE", // 509 (767) + "SEQUENTIAL", // 510 (768) + "SHARING", // 511 (769) + "SIMPLE-EXIT", // 512 (770) + "SIGN", // 513 (771) + "SIN", // 514 (772) + "SIZE", // 515 (773) + "SMALLEST-ALGEBRAIC", // 516 (774) + "SOURCE", // 517 (775) + "SOURCE-COMPUTER", // 518 (776) + "SPECIAL-NAMES", // 519 (777) + "SQRT", // 520 (778) + "STACK", // 521 (779) + "STANDARD", // 522 (780) + "STANDARD-1", // 523 (781) + "STANDARD-DEVIATION", // 524 (782) + "STANDARD-COMPARE", // 525 (783) + "STATUS", // 526 (784) + "STRONG", // 527 (785) + "SUBSTITUTE", // 528 (786) + "SUM", // 529 (787) + "SYMBOL", // 530 (788) + "SYMBOLIC", // 531 (789) + "SYNCHRONIZED", // 532 (790) + "TALLY", // 533 (791) + "TALLYING", // 534 (792) + "TAN", // 535 (793) + "TERMINATE", // 536 (794) + "TEST", // 537 (795) + "TEST-DATE-YYYYMMDD", // 538 (796) + "TEST-DAY-YYYYDDD", // 539 (797) + "TEST-FORMATTED-DATETIME", // 540 (798) + "TEST-NUMVAL", // 541 (799) + "TEST-NUMVAL-C", // 542 (800) + "TEST-NUMVAL-F", // 543 (801) + "THAN", // 544 (802) + "TIME", // 545 (803) + "TIMES", // 546 (804) + "TO", // 547 (805) + "TOP", // 548 (806) + "TOP-LEVEL", // 549 (807) + "TRACKS", // 550 (808) + "TRACK-AREA", // 551 (809) + "TRAILING", // 552 (810) + "TRANSFORM", // 553 (811) + "TRIM", // 554 (812) + "TRUE", // 555 (813) + "TRY", // 556 (814) + "TURN", // 557 (815) + "TYPE", // 558 (816) + "TYPEDEF", // 559 (817) + "ULENGTH", // 560 (818) + "UNBOUNDED", // 561 (819) + "UNIT", // 562 (820) + "UNITS", // 563 (821) + "UNIT-RECORD", // 564 (822) + "UNTIL", // 565 (823) + "UP", // 566 (824) + "UPON", // 567 (825) + "UPOS", // 568 (826) + "UPPER-CASE", // 569 (827) + "USAGE", // 570 (828) + "USING", // 571 (829) + "USUBSTR", // 572 (830) + "USUPPLEMENTARY", // 573 (831) + "UTILITY", // 574 (832) + "UUID4", // 575 (833) + "UVALID", // 576 (834) + "UWIDTH", // 577 (835) + "VALUE", // 578 (836) + "VARIANCE", // 579 (837) + "VARYING", // 580 (838) + "VOLATILE", // 581 (839) + "WHEN-COMPILED", // 582 (840) + "WITH", // 583 (841) + "WORKING-STORAGE", // 584 (842) + "XML", // 585 (843) + "XMLGENERATE", // 586 (844) + "XMLPARSE", // 587 (845) + "YEAR-TO-YYYY", // 588 (846) + "YYYYDDD", // 589 (847) + "YYYYMMDD", // 590 (848) + "ARITHMETIC", // 591 (849) + "ATTRIBUTE", // 592 (850) + "AUTO", // 593 (851) + "AUTOMATIC", // 594 (852) + "AWAY-FROM-ZERO", // 595 (853) + "BACKGROUND-COLOR", // 596 (854) + "BELL", // 597 (855) + "BINARY-ENCODING", // 598 (856) + "BLINK", // 599 (857) + "CAPACITY", // 600 (858) + "CENTER", // 601 (859) + "CLASSIFICATION", // 602 (860) + "CYCLE", // 603 (861) + "DECIMAL-ENCODING", // 604 (862) + "ENTRY-CONVENTION", // 605 (863) + "EOL", // 606 (864) + "EOS", // 607 (865) + "ERASE", // 608 (866) + "EXPANDS", // 609 (867) + "FLOAT-BINARY", // 610 (868) + "FLOAT-DECIMAL", // 611 (869) + "FOREGROUND-COLOR", // 612 (870) + "FOREVER", // 613 (871) + "FULL", // 614 (872) + "HIGHLIGHT", // 615 (873) + "HIGH-ORDER-LEFT", // 616 (874) + "HIGH-ORDER-RIGHT", // 617 (875) + "IGNORING", // 618 (876) + "IMPLEMENTS", // 619 (877) + "INITIALIZED", // 620 (878) + "INTERMEDIATE", // 621 (879) + "LC-ALL", // 622 (880) + "LC-COLLATE", // 623 (881) + "LC-CTYPE", // 624 (882) + "LC-MESSAGES", // 625 (883) + "LC-MONETARY", // 626 (884) + "LC-NUMERIC", // 627 (885) + "LC-TIME", // 628 (886) + "LOWLIGHT", // 629 (887) + "NEAREST-AWAY-FROM-ZERO", // 630 (888) + "NEAREST-EVEN", // 631 (889) + "NEAREST-TOWARD-ZERO", // 632 (890) + "NONE", // 633 (891) + "NORMAL", // 634 (892) + "NUMBERS", // 635 (893) + "PREFIXED", // 636 (894) + "PREVIOUS", // 637 (895) + "PROHIBITED", // 638 (896) + "RELATION", // 639 (897) + "REQUIRED", // 640 (898) + "REVERSE-VIDEO", // 641 (899) + "ROUNDING", // 642 (900) + "SECONDS", // 643 (901) + "SECURE", // 644 (902) + "SHORT", // 645 (903) + "SIGNED", // 646 (904) + "STANDARD-BINARY", // 647 (905) + "STANDARD-DECIMAL", // 648 (906) + "STATEMENT", // 649 (907) + "STEP", // 650 (908) + "STRUCTURE", // 651 (909) + "TOWARD-GREATER", // 652 (910) + "TOWARD-LESSER", // 653 (911) + "TRUNCATION", // 654 (912) + "UCS-4", // 655 (913) + "UNDERLINE", // 656 (914) + "UNSIGNED", // 657 (915) + "UTF-16", // 658 (916) + "UTF-8", // 659 (917) + "ADDRESS", // 660 (918) + "END-ACCEPT", // 661 (919) + "END-ADD", // 662 (920) + "END-CALL", // 663 (921) + "END-COMPUTE", // 664 (922) + "END-DELETE", // 665 (923) + "END-DISPLAY", // 666 (924) + "END-DIVIDE", // 667 (925) + "END-EVALUATE", // 668 (926) + "END-MULTIPLY", // 669 (927) + "END-PERFORM", // 670 (928) + "END-READ", // 671 (929) + "END-RETURN", // 672 (930) + "END-REWRITE", // 673 (931) + "END-SEARCH", // 674 (932) + "END-START", // 675 (933) + "END-STRING", // 676 (934) + "END-SUBTRACT", // 677 (935) + "END-UNSTRING", // 678 (936) + "END-WRITE", // 679 (937) + "END-IF", // 680 (938) + "THRU", // 681 (939) + "OR", // 682 (940) + "AND", // 683 (941) + "NOT", // 684 (942) + "NE", // 685 (943) + "LE", // 686 (944) + "GE", // 687 (945) + "POW", // 688 (946) + "NEG", // 689 (947) }; diff --git a/gcc/cobol/udf/stored-char-length.cbl b/gcc/cobol/udf/stored-char-length.cbl index 9ab3b14..66889d0 100644 --- a/gcc/cobol/udf/stored-char-length.cbl +++ b/gcc/cobol/udf/stored-char-length.cbl @@ -1,3 +1,6 @@ + >> PUSH source format + >>SOURCE format is fixed + * This function is in public domain. * Contributed by James K. Lowden of Cobolworx in August 2024 @@ -13,3 +16,4 @@ to Output-Value. End Function STORED-CHAR-LENGTH. + >> pop source format
\ No newline at end of file diff --git a/gcc/cobol/util.cc b/gcc/cobol/util.cc index 23f605d..c85b4cb 100644 --- a/gcc/cobol/util.cc +++ b/gcc/cobol/util.cc @@ -34,29 +34,32 @@ * header files. */ -#include "cobol-system.h" -#include "coretypes.h" -#include "tree.h" +#include <cobol-system.h> +#include <coretypes.h> +#include <tree.h> #undef yy_flex_debug #include <langinfo.h> -#include "coretypes.h" -#include "version.h" -#include "demangle.h" -#include "intl.h" -#include "backtrace.h" -#include "diagnostic.h" -#include "diagnostic-color.h" -#include "diagnostic-url.h" -#include "diagnostic-metadata.h" -#include "diagnostic-path.h" -#include "edit-context.h" -#include "selftest.h" -#include "selftest-diagnostic.h" -#include "opts.h" +#include <coretypes.h> +#include <version.h> +#include <demangle.h> +#include <intl.h> +#include <backtrace.h> +#include <diagnostic.h> +#include <diagnostic-color.h> +#include <diagnostic-url.h> +#include <diagnostic-metadata.h> +#include <diagnostic-path.h> +#include <edit-context.h> +#include <selftest.h> +#include <selftest-diagnostic.h> +#include <opts.h> + #include "util.h" + #include "cbldiag.h" +#include "cdfval.h" #include "lexio.h" #include "../../libgcobol/ec.h" @@ -111,6 +114,159 @@ gb4( size_t input ) { return input; } +/* + * Most CDF Directives -- those that have state -- can be pushed and popped. + * This class maintains stacks of them, with each stack having a "default + * value" that may be updated, without push/pop, via a CDF directive or + * command-line option. A push to a stack pushes the default value onto it; a + * pop copies the top of the stack to the default value. + * + * Supported: + * CALL-CONVENTION + * COBOL-WORDS + * DEFINE + * DISPLAY + * IF + * POP + * PUSH + * SOURCE FORMAT + * TURN + * not supported + * EVALUATE + * FLAG-02 + * FLAG-14 + * LEAP-SECOND + * LISTING + * PAGE + * PROPAGATE + * REF-MOD-ZERO-LENGTH + * + * >>PUSH ALL calls the class's push() method. + * >>POP ALL calls the class's pop() method. + */ +class cdf_directives_t +{ + template <typename T> + class cdf_stack_t : private std::stack<T> { + T default_value; + const T& top() const { return std::stack<T>::top(); } + bool empty() const { return std::stack<T>::empty(); } + public: + void value( const T& value ) { + T& output( empty()? default_value : std::stack<T>::top() ); + output = value; + dbgmsg("cdf_directives_t::%s: %s", __func__, str(output).c_str()); + } + T& value() { + return empty()? default_value : std::stack<T>::top(); + } + void push() { + std::stack<T>::push(value()); + dbgmsg("cdf_directives_t::%s: %s", __func__, str(top()).c_str()); + } + void pop() { + if( empty() ) { + error_msg(YYLTYPE(), "CDF stack empty"); + return; + } + default_value = top(); + std::stack<T>::pop(); + dbgmsg("cdf_directives_t::%s: %s", __func__, str(default_value).c_str()); + } + protected: + static std::string str(cbl_call_convention_t arg) { + char output[2] = { static_cast<char>(arg) }; + return std::string("call-convention ") + output; + } + static std::string str(current_tokens_t) { + return "<cobol-words>"; + } + static std::string str(cdf_values_t) { + return "<dictionary>"; + } + static std::string str(source_format_t arg) { + return arg.description(); + } + static std::string str(cbl_enabled_exceptions_t) { + return "<enabled_exceptions>"; + } + + }; + + public: + cdf_stack_t<cbl_call_convention_t> call_convention; + cdf_stack_t<current_tokens_t> cobol_words; + cdf_stack_t<cdf_values_t> dictionary; // DEFINE + cdf_stack_t<source_format_t> source_format; + cdf_stack_t<cbl_enabled_exceptions_t> enabled_exceptions; + + cdf_directives_t() { + call_convention.value() = cbl_call_cobol_e; + } + + void push() { + call_convention.push(); + cobol_words.push(); + dictionary.push(); + source_format.push(); + enabled_exceptions.push(); + } + void pop() { + call_convention.pop(); + cobol_words.pop(); + dictionary.pop(); + source_format.pop(); + enabled_exceptions.pop(); + } +}; +static cdf_directives_t cdf_directives; + +void +current_call_convention( cbl_call_convention_t convention) { + cdf_directives.call_convention.value(convention); +} +cbl_call_convention_t +current_call_convention() { + return cdf_directives.call_convention.value(); +} + +current_tokens_t& +cdf_current_tokens() { + return cdf_directives.cobol_words.value(); +} + +cdf_values_t& +cdf_dictionary() { + return cdf_directives.dictionary.value(); +} + +void +cobol_set_indicator_column( int column ) { + cdf_directives.source_format.value().indicator_column_set(column); +} +source_format_t& cdf_source_format() { + return cdf_directives.source_format.value(); +} + +cbl_enabled_exceptions_t& +cdf_enabled_exceptions() { + return cdf_directives.enabled_exceptions.value(); +} + +void cdf_push() { cdf_directives.push(); } +void cdf_push_call_convention() { cdf_directives.call_convention.push(); } +void cdf_push_current_tokens() { cdf_directives.cobol_words.push(); } +void cdf_push_dictionary() { cdf_directives.dictionary.push(); } +void cdf_push_enabled_exceptions() { cdf_directives.enabled_exceptions.push(); } +void cdf_push_source_format() { cdf_directives.source_format.push(); } + +void cdf_pop() { cdf_directives.pop(); } +void cdf_pop_call_convention() { cdf_directives.call_convention.pop(); } +void cdf_pop_current_tokens() { cdf_directives.cobol_words.pop(); } +void cdf_pop_dictionary() { cdf_directives.dictionary.pop(); } +void cdf_pop_enabled_exceptions() { cdf_directives.enabled_exceptions.pop(); } +void cdf_pop_source_format() { cdf_directives.source_format.pop(); } + const char * symbol_type_str( enum symbol_type_t type ) { @@ -1927,7 +2083,8 @@ location_t location_from_lineno() { return token_location; } template <typename LOC> static void gcc_location_set_impl( const LOC& loc ) { - token_location = linemap_line_start( line_table, loc.last_line, 80 ); + // Set the position to the first line & column in the location. + token_location = linemap_line_start( line_table, loc.first_line, 80 ); token_location = linemap_position_for_column( line_table, loc.first_column); location_dump(__func__, __LINE__, "parser", loc); } @@ -1972,6 +2129,11 @@ verify_format( const char gmsgid[] ) { static const diagnostic_option_id option_zero; size_t parse_error_inc(); +void gcc_location_dump() { + linemap_dump_location( line_table, token_location, stderr ); +} + + void ydferror( const char gmsgid[], ... ) ATTRIBUTE_GCOBOL_DIAG(1, 2); void @@ -2008,10 +2170,7 @@ class temp_loc_t { gcc_location_set(loc); } explicit temp_loc_t( const YDFLTYPE& loc) : orig(token_location) { - YYLTYPE lloc = { - loc.first_line, loc.first_column, - loc.last_line, loc.last_column }; - gcc_location_set(lloc); + gcc_location_set(loc); } ~temp_loc_t() { if( orig != token_location ) { @@ -2057,6 +2216,17 @@ void error_msg( const YDFLTYPE& loc, const char gmsgid[], ... ) { ERROR_MSG_BODY } +void error_msg_direct( const char gmsgid[], ... ) { + verify_format(gmsgid); + parse_error_inc(); + auto_diagnostic_group d; + va_list ap; + va_start (ap, gmsgid); + auto ret = emit_diagnostic_valist( DK_ERROR, token_location, + option_zero, gmsgid, &ap ); + va_end (ap); +} + void yyerror( const char gmsgid[], ... ) { temp_loc_t looker; diff --git a/gcc/cobol/util.h b/gcc/cobol/util.h index 165915a..d07b669 100644 --- a/gcc/cobol/util.h +++ b/gcc/cobol/util.h @@ -59,5 +59,70 @@ as_voidp( P p ) { return static_cast<const void *>(p); } +/* + * The default source format, whether free or fixed, is determined + * heuristically by examining the PROGRAM-ID line, if it exists, in the first + * input file. If that file does not have such a line, the default is free + * format. Else the format is set to fixed if anything appears on that line + * that would prohibit parsing it as free format, + */ +class source_format_t { + bool first_file, explicitly; + int left, right; +public: + source_format_t() + : first_file(true), explicitly(false), left(0), right(0) + {} + void indicator_column_set( int column ) { + explicitly = true; + if( column == 0 ) right = 0; + if( column < 0 ) { + column = -column; + right = 73; + } + left = column; + } + + bool inference_pending() { + bool tf = first_file && !explicitly; + first_file = false; + return tf; + } + + void infer( const char *bol, bool want_reference_format ); + + inline bool is_fixed() const { return left == 7; } + inline bool is_reffmt() const { return is_fixed() && right == 73; } + inline bool is_free() const { return ! is_fixed(); } + + const char * description() const { + if( is_reffmt() ) return "REFERENCE"; + if( is_fixed() ) return "FIXED"; + if( is_free() ) return "FREE"; + gcc_unreachable(); + } + + inline int left_margin() { + return left == 0? left : left - 1; + } + inline int right_margin() { + return right == 0? right : right - 1; + } +}; + + +void cdf_push(); +void cdf_push_call_convention(); +void cdf_push_current_tokens(); +void cdf_push_dictionary(); +void cdf_push_enabled_exceptions(); +void cdf_push_source_format(); + +void cdf_pop(); +void cdf_pop_call_convention(); +void cdf_pop_current_tokens(); +void cdf_pop_dictionary(); +void cdf_pop_source_format(); +void cdf_pop_enabled_exceptions(); #endif diff --git a/gcc/config.gcc b/gcc/config.gcc index a6f6efe..8ed1113 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -1847,11 +1847,11 @@ moxie-*-moxiebox*) ;; h8300-*-elf*) tmake_file="h8300/t-h8300" - tm_file="h8300/h8300.h elfos.h newlib-stdint.h h8300/elf.h" + tm_file="elfos.h h8300/h8300.h newlib-stdint.h h8300/elf.h" ;; h8300-*-linux*) tmake_file="${tmake_file} h8300/t-h8300 h8300/t-linux" - tm_file="h8300/h8300.h elfos.h gnu-user.h linux.h glibc-stdint.h h8300/linux.h" + tm_file="elfos.h h8300/h8300.h gnu-user.h linux.h glibc-stdint.h h8300/linux.h" ;; hppa*64*-*-linux*) target_cpu_default="MASK_PA_11|MASK_PA_20" @@ -5894,7 +5894,7 @@ esac # distinguish VxWorks variants such as VxWorks 7 or 64). case ${target} in -arm*-*-* | i[34567]86-*-* | mips*-*-* | powerpc*-*-* | sh*-*-* \ +aarch64*-*-* | arm*-*-* | i[34567]86-*-* | mips*-*-* | powerpc*-*-* | sh*-*-* \ | sparc*-*-* | x86_64-*-*) tm_file="vxworks-dummy.h ${tm_file}" ;; diff --git a/gcc/config/aarch64/aarch64-sve-builtins-sve2.cc b/gcc/config/aarch64/aarch64-sve-builtins-sve2.cc index d9922de..abe21a8 100644 --- a/gcc/config/aarch64/aarch64-sve-builtins-sve2.cc +++ b/gcc/config/aarch64/aarch64-sve-builtins-sve2.cc @@ -316,7 +316,8 @@ public: expand (function_expander &e) const override { e.prepare_gather_address_operands (1, false); - return e.use_exact_insn (CODE_FOR_aarch64_gather_ld1q); + auto icode = code_for_aarch64_gather_ld1q (e.tuple_mode (0)); + return e.use_exact_insn (icode); } }; @@ -722,7 +723,7 @@ public: expand (function_expander &e) const override { rtx data = e.args.last (); - e.args.last () = force_lowpart_subreg (VNx2DImode, data, GET_MODE (data)); + e.args.last () = aarch64_sve_reinterpret (VNx2DImode, data); e.prepare_gather_address_operands (1, false); return e.use_exact_insn (CODE_FOR_aarch64_scatter_st1q); } diff --git a/gcc/config/aarch64/aarch64-sve.md b/gcc/config/aarch64/aarch64-sve.md index 4aecb3a..6b5113e 100644 --- a/gcc/config/aarch64/aarch64-sve.md +++ b/gcc/config/aarch64/aarch64-sve.md @@ -3966,7 +3966,7 @@ ) ;; Predicated predicate inverse. -(define_insn "*one_cmpl<mode>3" +(define_insn "@aarch64_pred_one_cmpl<mode>_z" [(set (match_operand:PRED_ALL 0 "register_operand" "=Upa") (and:PRED_ALL (not:PRED_ALL (match_operand:PRED_ALL 2 "register_operand" "Upa")) @@ -8637,8 +8637,8 @@ (define_expand "vec_cmp<mode><vpred>" [(set (match_operand:<VPRED> 0 "register_operand") (match_operator:<VPRED> 1 "comparison_operator" - [(match_operand:SVE_FULL_F 2 "register_operand") - (match_operand:SVE_FULL_F 3 "aarch64_simd_reg_or_zero")]))] + [(match_operand:SVE_F 2 "register_operand") + (match_operand:SVE_F 3 "aarch64_simd_reg_or_zero")]))] "TARGET_SVE" { aarch64_expand_sve_vec_cmp_float (operands[0], GET_CODE (operands[1]), @@ -8651,10 +8651,10 @@ (define_insn "@aarch64_pred_fcm<cmp_op><mode>" [(set (match_operand:<VPRED> 0 "register_operand") (unspec:<VPRED> - [(match_operand:<VPRED> 1 "register_operand") + [(match_operand:<VPRED> 1 "aarch64_predicate_operand") (match_operand:SI 2 "aarch64_sve_ptrue_flag") - (match_operand:SVE_FULL_F 3 "register_operand") - (match_operand:SVE_FULL_F 4 "aarch64_simd_reg_or_zero")] + (match_operand:SVE_F 3 "register_operand") + (match_operand:SVE_F 4 "aarch64_simd_reg_or_zero")] SVE_COND_FP_CMP_I0))] "TARGET_SVE" {@ [ cons: =0 , 1 , 3 , 4 ] @@ -8667,10 +8667,10 @@ (define_insn "@aarch64_pred_fcmuo<mode>" [(set (match_operand:<VPRED> 0 "register_operand" "=Upa") (unspec:<VPRED> - [(match_operand:<VPRED> 1 "register_operand" "Upl") + [(match_operand:<VPRED> 1 "aarch64_predicate_operand" "Upl") (match_operand:SI 2 "aarch64_sve_ptrue_flag") - (match_operand:SVE_FULL_F 3 "register_operand" "w") - (match_operand:SVE_FULL_F 4 "register_operand" "w")] + (match_operand:SVE_F 3 "register_operand" "w") + (match_operand:SVE_F 4 "register_operand" "w")] UNSPEC_COND_FCMUO))] "TARGET_SVE" "fcmuo\t%0.<Vetype>, %1/z, %3.<Vetype>, %4.<Vetype>" @@ -11437,16 +11437,12 @@ (define_insn "@aarch64_sve_set_neonq_<mode>" [(set (match_operand:SVE_FULL 0 "register_operand" "=w") - (unspec:SVE_FULL - [(match_operand:SVE_FULL 1 "register_operand" "w") - (match_operand:<V128> 2 "register_operand" "w") - (match_operand:<VPRED> 3 "register_operand" "Upl")] - UNSPEC_SET_NEONQ))] + (unspec:SVE_FULL + [(match_operand:SVE_FULL 1 "register_operand" "w") + (match_operand:<V128> 2 "register_operand" "w") + (match_operand:<VPRED> 3 "register_operand" "Upl")] + UNSPEC_SET_NEONQ))] "TARGET_SVE && BYTES_BIG_ENDIAN" - { - operands[2] = lowpart_subreg (<MODE>mode, operands[2], - GET_MODE (operands[2])); - return "sel\t%0.<Vetype>, %3, %2.<Vetype>, %1.<Vetype>"; - } + "sel\t%0.<Vetype>, %3, %Z2.<Vetype>, %1.<Vetype>" ) diff --git a/gcc/config/aarch64/aarch64-sve2.md b/gcc/config/aarch64/aarch64-sve2.md index 62524f3..660901d 100644 --- a/gcc/config/aarch64/aarch64-sve2.md +++ b/gcc/config/aarch64/aarch64-sve2.md @@ -334,12 +334,21 @@ ;; - LD1Q (SVE2p1) ;; ------------------------------------------------------------------------- -;; Model this as operating on the largest valid element size, which is DI. -;; This avoids having to define move patterns & more for VNx1TI, which would -;; be difficult without a non-gather form of LD1Q. -(define_insn "aarch64_gather_ld1q" - [(set (match_operand:VNx2DI 0 "register_operand") - (unspec:VNx2DI +;; For little-endian targets, it would be enough to use a single pattern, +;; with a subreg to bitcast the result to whatever mode is needed. +;; However, on big-endian targets, the bitcast would need to be an +;; aarch64_sve_reinterpret instruction. That would interact badly +;; with the "&" and "?" constraints in this pattern: if the result +;; of the reinterpret needs to be in the same register as the index, +;; the RA would tend to prefer to allocate a separate register for the +;; intermediate (uncast) result, even if the reinterpret prefers tying. +;; +;; The index is logically VNx1DI rather than VNx2DI, but introducing +;; and using VNx1DI would just create more bitcasting. The ACLE intrinsic +;; uses svuint64_t, which corresponds to VNx2DI. +(define_insn "@aarch64_gather_ld1q<mode>" + [(set (match_operand:SVE_FULL 0 "register_operand") + (unspec:SVE_FULL [(match_operand:VNx2BI 1 "register_operand") (match_operand:DI 2 "aarch64_reg_or_zero") (match_operand:VNx2DI 3 "register_operand") @@ -1628,7 +1637,7 @@ "TARGET_SVE2" {@ [ cons: =0 , %1 , 2 ; attrs: movprfx ] [ w , 0 , w ; * ] nbsl\t%0.d, %0.d, %2.d, %0.d - [ ?&w , w , w ; yes ] movprfx\t%0, %1\;nbsl\t%0.d, %0.d, %2.d, %0.d + [ ?&w , w , w ; yes ] movprfx\t%0, %1\;nbsl\t%0.d, %0.d, %2.d, %1.d } "&& !CONSTANT_P (operands[3])" { diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc index f3ce3a1..10b8ed5 100644 --- a/gcc/config/aarch64/aarch64.cc +++ b/gcc/config/aarch64/aarch64.cc @@ -17932,7 +17932,7 @@ aarch64_vector_costs::add_stmt_cost (int count, vect_cost_for_stmt kind, /* Do one-time initialization based on the vinfo. */ loop_vec_info loop_vinfo = dyn_cast<loop_vec_info> (m_vinfo); - if (!m_analyzed_vinfo) + if (!m_analyzed_vinfo && !m_costing_for_scalar) { if (loop_vinfo) analyze_loop_vinfo (loop_vinfo); @@ -23074,6 +23074,58 @@ aarch64_sve_index_immediate_p (rtx base_or_step) && IN_RANGE (INTVAL (base_or_step), -16, 15)); } +/* Return true if SERIES is a constant vector that can be loaded using + an immediate SVE INDEX, considering both SVE and Advanced SIMD modes. + When returning true, store the base in *BASE_OUT and the step + in *STEP_OUT. */ + +static bool +aarch64_sve_index_series_p (rtx series, rtx *base_out, rtx *step_out) +{ + rtx base, step; + if (!const_vec_series_p (series, &base, &step) + || !CONST_INT_P (base) + || !CONST_INT_P (step)) + return false; + + auto mode = GET_MODE (series); + auto elt_mode = as_a<scalar_int_mode> (GET_MODE_INNER (mode)); + unsigned int vec_flags = aarch64_classify_vector_mode (mode); + if (BYTES_BIG_ENDIAN && (vec_flags & VEC_ADVSIMD)) + { + /* On big-endian targets, architectural lane 0 holds the last element + for Advanced SIMD and the first element for SVE; see the comment at + the head of aarch64-sve.md for details. This means that, from an SVE + point of view, an Advanced SIMD series goes from the last element to + the first. */ + auto i = GET_MODE_NUNITS (mode).to_constant () - 1; + base = gen_int_mode (UINTVAL (base) + i * UINTVAL (step), elt_mode); + step = gen_int_mode (-UINTVAL (step), elt_mode); + } + + if (!aarch64_sve_index_immediate_p (base) + || !aarch64_sve_index_immediate_p (step)) + return false; + + /* If the mode spans multiple registers, check that each subseries is + in range. */ + unsigned int nvectors = aarch64_ldn_stn_vectors (mode); + if (nvectors != 1) + { + unsigned int nunits; + if (!GET_MODE_NUNITS (mode).is_constant (&nunits)) + return false; + nunits /= nvectors; + for (unsigned int i = 1; i < nvectors; ++i) + if (!IN_RANGE (INTVAL (base) + i * nunits * INTVAL (step), -16, 15)) + return false; + } + + *base_out = base; + *step_out = step; + return true; +} + /* Return true if X is a valid immediate for the SVE ADD and SUB instructions when applied to mode MODE. Negate X first if NEGATE_P is true. */ @@ -23522,13 +23574,8 @@ aarch64_simd_valid_imm (rtx op, simd_immediate_info *info, n_elts = CONST_VECTOR_NPATTERNS (op); else if (which == AARCH64_CHECK_MOV && TARGET_SVE - && const_vec_series_p (op, &base, &step)) + && aarch64_sve_index_series_p (op, &base, &step)) { - gcc_assert (GET_MODE_CLASS (mode) == MODE_VECTOR_INT); - if (!aarch64_sve_index_immediate_p (base) - || !aarch64_sve_index_immediate_p (step)) - return false; - if (info) { /* Get the corresponding container mode. E.g. an INDEX on V2SI @@ -23640,6 +23687,8 @@ aarch64_simd_valid_imm (rtx op, simd_immediate_info *info, long int as_long_ints[2]; as_long_ints[0] = ival & 0xFFFFFFFF; as_long_ints[1] = (ival >> 32) & 0xFFFFFFFF; + if (imode == DImode && FLOAT_WORDS_BIG_ENDIAN) + std::swap (as_long_ints[0], as_long_ints[1]); REAL_VALUE_TYPE r; real_from_target (&r, as_long_ints, fmode); @@ -24830,6 +24879,13 @@ aarch64_expand_vector_init (rtx target, rtx vals) emit_insn (rec_seq); } + /* The two halves should (by induction) be individually endian-correct. + However, in the memory layout provided by VALS, the nth element of + HALVES[0] comes immediately before the nth element HALVES[1]. + This means that, on big-endian targets, the nth element of HALVES[0] + is more significant than the nth element HALVES[1]. */ + if (BYTES_BIG_ENDIAN) + std::swap (halves[0], halves[1]); rtvec v = gen_rtvec (2, halves[0], halves[1]); rtx_insn *zip1_insn = emit_set_insn (target, gen_rtx_UNSPEC (mode, v, UNSPEC_ZIP1)); @@ -26745,7 +26801,6 @@ aarch64_evpc_hvla (struct expand_vec_perm_d *d) machine_mode vmode = d->vmode; if (!TARGET_SVE2p1 || !TARGET_NON_STREAMING - || BYTES_BIG_ENDIAN || d->vec_flags != VEC_SVE_DATA || GET_MODE_UNIT_BITSIZE (vmode) > 64) return false; @@ -27300,7 +27355,7 @@ aarch64_emit_sve_fp_cond (rtx target, rtx_code code, rtx pred, bool known_ptrue_p, rtx op0, rtx op1) { rtx flag = gen_int_mode (known_ptrue_p, SImode); - rtx unspec = gen_rtx_UNSPEC (GET_MODE (pred), + rtx unspec = gen_rtx_UNSPEC (GET_MODE (target), gen_rtvec (4, pred, flag, op0, op1), aarch64_unspec_cond_code (code)); emit_set_insn (target, unspec); @@ -27319,10 +27374,10 @@ static void aarch64_emit_sve_or_fp_conds (rtx target, rtx_code code1, rtx_code code2, rtx pred, bool known_ptrue_p, rtx op0, rtx op1) { - machine_mode pred_mode = GET_MODE (pred); - rtx tmp1 = gen_reg_rtx (pred_mode); + machine_mode target_mode = GET_MODE (target); + rtx tmp1 = gen_reg_rtx (target_mode); aarch64_emit_sve_fp_cond (tmp1, code1, pred, known_ptrue_p, op0, op1); - rtx tmp2 = gen_reg_rtx (pred_mode); + rtx tmp2 = gen_reg_rtx (target_mode); aarch64_emit_sve_fp_cond (tmp2, code2, pred, known_ptrue_p, op0, op1); aarch64_emit_binop (target, ior_optab, tmp1, tmp2); } @@ -27339,8 +27394,7 @@ static void aarch64_emit_sve_invert_fp_cond (rtx target, rtx_code code, rtx pred, bool known_ptrue_p, rtx op0, rtx op1) { - machine_mode pred_mode = GET_MODE (pred); - rtx tmp = gen_reg_rtx (pred_mode); + rtx tmp = gen_reg_rtx (GET_MODE (target)); aarch64_emit_sve_fp_cond (tmp, code, pred, known_ptrue_p, op0, op1); aarch64_emit_unop (target, one_cmpl_optab, tmp); } @@ -27352,10 +27406,25 @@ aarch64_emit_sve_invert_fp_cond (rtx target, rtx_code code, rtx pred, void aarch64_expand_sve_vec_cmp_float (rtx target, rtx_code code, rtx op0, rtx op1) { - machine_mode pred_mode = GET_MODE (target); machine_mode data_mode = GET_MODE (op0); + rtx pred = aarch64_sve_fp_pred (data_mode, nullptr); - rtx ptrue = aarch64_ptrue_reg (pred_mode); + /* The governing and destination modes. */ + machine_mode pred_mode = GET_MODE (pred); + machine_mode target_mode = GET_MODE (target); + + /* For partial vector modes, the choice of predicate mode depends + on whether we need to suppress exceptions for inactive elements. + If we do need to suppress exceptions, the predicate mode matches + the element size rather than the container size and the predicate + marks the upper bits in each container as inactive. The predicate + is then a ptrue wrt TARGET_MODE but not wrt PRED_MODE. It is the + latter which matters here. + + If we don't need to suppress exceptions, the predicate mode matches + the container size, PRED_MODE == TARGET_MODE, and the predicate is + thus a ptrue wrt both TARGET_MODE and PRED_MODE. */ + bool known_ptrue_p = pred_mode == target_mode; switch (code) { case UNORDERED: @@ -27369,12 +27438,13 @@ aarch64_expand_sve_vec_cmp_float (rtx target, rtx_code code, rtx op0, rtx op1) case EQ: case NE: /* There is native support for the comparison. */ - aarch64_emit_sve_fp_cond (target, code, ptrue, true, op0, op1); + aarch64_emit_sve_fp_cond (target, code, pred, known_ptrue_p, op0, op1); return; case LTGT: /* This is a trapping operation (LT or GT). */ - aarch64_emit_sve_or_fp_conds (target, LT, GT, ptrue, true, op0, op1); + aarch64_emit_sve_or_fp_conds (target, LT, GT, + pred, known_ptrue_p, op0, op1); return; case UNEQ: @@ -27383,7 +27453,7 @@ aarch64_expand_sve_vec_cmp_float (rtx target, rtx_code code, rtx op0, rtx op1) /* This would trap for signaling NaNs. */ op1 = force_reg (data_mode, op1); aarch64_emit_sve_or_fp_conds (target, UNORDERED, EQ, - ptrue, true, op0, op1); + pred, known_ptrue_p, op0, op1); return; } /* fall through */ @@ -27393,11 +27463,19 @@ aarch64_expand_sve_vec_cmp_float (rtx target, rtx_code code, rtx op0, rtx op1) case UNGE: if (flag_trapping_math) { - /* Work out which elements are ordered. */ - rtx ordered = gen_reg_rtx (pred_mode); op1 = force_reg (data_mode, op1); - aarch64_emit_sve_invert_fp_cond (ordered, UNORDERED, - ptrue, true, op0, op1); + + /* Work out which elements are unordered. */ + rtx uo_tmp = gen_reg_rtx (target_mode); + aarch64_emit_sve_fp_cond (uo_tmp, UNORDERED, + pred, known_ptrue_p, op0, op1); + + /* Invert the result. Governered by PRED so that we only + flip the active bits. */ + rtx ordered = gen_reg_rtx (pred_mode); + uo_tmp = gen_lowpart (pred_mode, uo_tmp); + emit_insn (gen_aarch64_pred_one_cmpl_z (pred_mode, ordered, + pred, uo_tmp)); /* Test the opposite condition for the ordered elements, then invert the result. */ @@ -27422,7 +27500,8 @@ aarch64_expand_sve_vec_cmp_float (rtx target, rtx_code code, rtx op0, rtx op1) /* There is native support for the inverse comparison. */ code = reverse_condition_maybe_unordered (code); - aarch64_emit_sve_invert_fp_cond (target, code, ptrue, true, op0, op1); + aarch64_emit_sve_invert_fp_cond (target, code, + pred, known_ptrue_p, op0, op1); } /* Return true if: diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index 509ef4c..27efc91 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -5771,6 +5771,19 @@ (match_operand:TI 1 "register_operand")] "TARGET_SIMD && !TARGET_CSSC" { + /* For SVE we can do popcount on DImode chunks of the TImode argument + and then use a cheap ADDP reduction. The SVE CNT instruction requires + materializing a PTRUE so don't do this if optimizing for size. */ + if (TARGET_SVE && !optimize_function_for_size_p (cfun)) + { + rtx v = gen_reg_rtx (V2DImode); + rtx v1 = gen_reg_rtx (V2DImode); + emit_move_insn (v, gen_lowpart (V2DImode, operands[1])); + rtx p = aarch64_ptrue_reg (VNx2BImode, 16); + emit_insn (gen_aarch64_pred_popcountv2di (v1, p, v)); + emit_insn (gen_reduc_plus_scal_v2di (operands[0], v1)); + DONE; + } rtx v = gen_reg_rtx (V16QImode); rtx v1 = gen_reg_rtx (V16QImode); emit_move_insn (v, gen_lowpart (V16QImode, operands[1])); diff --git a/gcc/config/arm/arm_neon.h b/gcc/config/arm/arm_neon.h index cba50de..105385f 100644 --- a/gcc/config/arm/arm_neon.h +++ b/gcc/config/arm/arm_neon.h @@ -20938,11 +20938,6 @@ vbfdotq_lane_f32 (float32x4_t __r, bfloat16x8_t __a, bfloat16x4_t __b, return __builtin_neon_vbfdot_lanev4bfv4sf (__r, __a, __b, __index); } -#pragma GCC pop_options - -#pragma GCC push_options -#pragma GCC target ("arch=armv8.2-a+bf16") - typedef struct bfloat16x4x2_t { bfloat16x4_t val[2]; diff --git a/gcc/config/h8300/h8300.h b/gcc/config/h8300/h8300.h index 6b2dd65..8018b63 100644 --- a/gcc/config/h8300/h8300.h +++ b/gcc/config/h8300/h8300.h @@ -610,6 +610,12 @@ struct cum_arg #define DATA_SECTION_ASM_OP "\t.section .data" #define BSS_SECTION_ASM_OP "\t.section .bss" +/* Override default definitions from elfos.h. */ +#undef INIT_SECTION_ASM_OP +#define INIT_SECTION_ASM_OP "\t.section\t.init,\"ax\"" +#undef FINI_SECTION_ASM_OP +#define FINI_SECTION_ASM_OP "\t.section\t.fini,\"ax\"" + #undef DO_GLOBAL_CTORS_BODY #define DO_GLOBAL_CTORS_BODY \ { \ @@ -647,19 +653,11 @@ struct cum_arg /* Globalizing directive for a label. */ #define GLOBAL_ASM_OP "\t.global " +/* Override default definition from elfos.h. */ +#undef ASM_DECLARE_FUNCTION_NAME #define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \ ASM_OUTPUT_FUNCTION_LABEL (FILE, NAME, DECL) -/* This is how to store into the string LABEL - the symbol_ref name of an internal numbered label where - PREFIX is the class of label and NUM is the number within the class. - This is suitable for output with `assemble_name'. - - N.B.: The h8300.md branch_true and branch_false patterns also know - how to generate internal labels. */ -#define ASM_GENERATE_INTERNAL_LABEL(LABEL, PREFIX, NUM) \ - sprintf (LABEL, "*.%s%lu", PREFIX, (unsigned long)(NUM)) - /* This is how to output an insn to push a register on the stack. It need not be very fast code. */ @@ -690,9 +688,6 @@ struct cum_arg if ((LOG) != 0) \ fprintf (FILE, "\t.align %d\n", (LOG)) -#define ASM_OUTPUT_SKIP(FILE, SIZE) \ - fprintf (FILE, "\t.space %d\n", (int)(SIZE)) - /* This says how to output an assembler line to define a global common symbol. */ diff --git a/gcc/config/i386/i386-expand.cc b/gcc/config/i386/i386-expand.cc index 83076ad..8f15c1c 100644 --- a/gcc/config/i386/i386-expand.cc +++ b/gcc/config/i386/i386-expand.cc @@ -7899,7 +7899,8 @@ expand_set_or_cpymem_via_loop (rtx destmem, rtx srcmem, rtx count, machine_mode mode, int unroll, int expected_size, bool issetmem) { - rtx_code_label *out_label, *top_label; + rtx_code_label *out_label = nullptr; + rtx_code_label *top_label = nullptr; rtx iter, tmp; machine_mode iter_mode = counter_mode (count); int piece_size_n = GET_MODE_SIZE (mode) * unroll; @@ -7907,9 +7908,19 @@ expand_set_or_cpymem_via_loop (rtx destmem, rtx srcmem, rtx piece_size_mask = GEN_INT (~((GET_MODE_SIZE (mode) * unroll) - 1)); rtx size; int i; + int loop_count; - top_label = gen_label_rtx (); - out_label = gen_label_rtx (); + if (expected_size != -1 && CONST_INT_P (count)) + loop_count = INTVAL (count) / GET_MODE_SIZE (mode) / unroll; + else + loop_count = -1; + + /* Don't generate the loop if the loop count is 1. */ + if (loop_count != 1) + { + top_label = gen_label_rtx (); + out_label = gen_label_rtx (); + } iter = gen_reg_rtx (iter_mode); size = expand_simple_binop (iter_mode, AND, count, piece_size_mask, @@ -7923,7 +7934,8 @@ expand_set_or_cpymem_via_loop (rtx destmem, rtx srcmem, } emit_move_insn (iter, const0_rtx); - emit_label (top_label); + if (loop_count != 1) + emit_label (top_label); tmp = convert_modes (Pmode, iter_mode, iter, true); @@ -7991,21 +8003,25 @@ expand_set_or_cpymem_via_loop (rtx destmem, rtx srcmem, if (tmp != iter) emit_move_insn (iter, tmp); - emit_cmp_and_jump_insns (iter, size, LT, NULL_RTX, iter_mode, - true, top_label); - if (expected_size != -1) + if (loop_count != 1) { - expected_size /= GET_MODE_SIZE (mode) * unroll; - if (expected_size == 0) - predict_jump (0); - else if (expected_size > REG_BR_PROB_BASE) - predict_jump (REG_BR_PROB_BASE - 1); + emit_cmp_and_jump_insns (iter, size, LT, NULL_RTX, iter_mode, + true, top_label); + if (expected_size != -1) + { + expected_size /= GET_MODE_SIZE (mode) * unroll; + if (expected_size == 0) + predict_jump (0); + else if (expected_size > REG_BR_PROB_BASE) + predict_jump (REG_BR_PROB_BASE - 1); + else + predict_jump (REG_BR_PROB_BASE + - (REG_BR_PROB_BASE + expected_size / 2) + / expected_size); + } else - predict_jump (REG_BR_PROB_BASE - (REG_BR_PROB_BASE + expected_size / 2) - / expected_size); + predict_jump (REG_BR_PROB_BASE * 80 / 100); } - else - predict_jump (REG_BR_PROB_BASE * 80 / 100); iter = ix86_zero_extend_to_Pmode (iter); tmp = expand_simple_binop (Pmode, PLUS, destptr, iter, destptr, true, OPTAB_LIB_WIDEN); @@ -8018,7 +8034,8 @@ expand_set_or_cpymem_via_loop (rtx destmem, rtx srcmem, if (tmp != srcptr) emit_move_insn (srcptr, tmp); } - emit_label (out_label); + if (loop_count != 1) + emit_label (out_label); } /* Divide COUNTREG by SCALE. */ @@ -8221,19 +8238,11 @@ expand_cpymem_epilogue (rtx destmem, rtx srcmem, rtx src, dest; if (CONST_INT_P (count)) { - HOST_WIDE_INT countval = INTVAL (count); - HOST_WIDE_INT epilogue_size = countval % max_size; - int i; - - /* For now MAX_SIZE should be a power of 2. This assert could be - relaxed, but it'll require a bit more complicated epilogue - expanding. */ - gcc_assert ((max_size & (max_size - 1)) == 0); - for (i = max_size; i >= 1; i >>= 1) - { - if (epilogue_size & i) - destmem = emit_memmov (destmem, &srcmem, destptr, srcptr, i); - } + unsigned HOST_WIDE_INT countval = UINTVAL (count); + unsigned HOST_WIDE_INT epilogue_size = countval % max_size; + unsigned int destalign = MEM_ALIGN (destmem); + move_by_pieces (destmem, srcmem, epilogue_size, destalign, + RETURN_BEGIN); return; } if (max_size > 8) @@ -8394,6 +8403,81 @@ expand_setmem_epilogue_via_loop (rtx destmem, rtx destptr, rtx value, 1, max_size / 2, true); } +/* Callback routine for store_by_pieces. Return the RTL of a register + containing GET_MODE_SIZE (MODE) bytes in the RTL register op_p which + is a word or a word vector register. If PREV_P isn't nullptr, it + has the RTL info from the previous iteration. */ + +static rtx +setmem_epilogue_gen_val (void *op_p, void *prev_p, HOST_WIDE_INT, + fixed_size_mode mode) +{ + rtx target; + by_pieces_prev *prev = (by_pieces_prev *) prev_p; + if (prev) + { + rtx prev_op = prev->data; + if (prev_op) + { + machine_mode prev_mode = GET_MODE (prev_op); + if (prev_mode == mode) + return prev_op; + if (VECTOR_MODE_P (prev_mode) + && VECTOR_MODE_P (mode) + && GET_MODE_INNER (prev_mode) == GET_MODE_INNER (mode)) + { + target = gen_rtx_SUBREG (mode, prev_op, 0); + return target; + } + } + } + + rtx op = (rtx) op_p; + machine_mode op_mode = GET_MODE (op); + + gcc_assert (op_mode == word_mode + || (VECTOR_MODE_P (op_mode) + && GET_MODE_INNER (op_mode) == word_mode)); + + if (VECTOR_MODE_P (mode)) + { + gcc_assert (GET_MODE_INNER (mode) == QImode); + + unsigned int op_size = GET_MODE_SIZE (op_mode); + unsigned int size = GET_MODE_SIZE (mode); + unsigned int nunits = op_size / GET_MODE_SIZE (QImode); + machine_mode vec_mode + = mode_for_vector (QImode, nunits).require (); + target = gen_reg_rtx (vec_mode); + op = gen_rtx_SUBREG (vec_mode, op, 0); + emit_move_insn (target, op); + if (op_size == size) + return target; + + rtx tmp = gen_reg_rtx (mode); + target = gen_rtx_SUBREG (mode, target, 0); + emit_move_insn (tmp, target); + return tmp; + } + + target = gen_reg_rtx (word_mode); + if (VECTOR_MODE_P (op_mode)) + { + op = gen_rtx_SUBREG (word_mode, op, 0); + emit_move_insn (target, op); + } + else + target = op; + + if (mode == word_mode) + return target; + + rtx tmp = gen_reg_rtx (mode); + target = gen_rtx_SUBREG (mode, target, 0); + emit_move_insn (tmp, target); + return tmp; +} + /* Output code to set at most count & (max_size - 1) bytes starting by DEST. */ static void expand_setmem_epilogue (rtx destmem, rtx destptr, rtx value, rtx vec_value, @@ -8403,24 +8487,12 @@ expand_setmem_epilogue (rtx destmem, rtx destptr, rtx value, rtx vec_value, if (CONST_INT_P (count)) { - HOST_WIDE_INT countval = INTVAL (count); - HOST_WIDE_INT epilogue_size = countval % max_size; - int i; - - /* For now MAX_SIZE should be a power of 2. This assert could be - relaxed, but it'll require a bit more complicated epilogue - expanding. */ - gcc_assert ((max_size & (max_size - 1)) == 0); - for (i = max_size; i >= 1; i >>= 1) - { - if (epilogue_size & i) - { - if (vec_value && i > GET_MODE_SIZE (GET_MODE (value))) - destmem = emit_memset (destmem, destptr, vec_value, i); - else - destmem = emit_memset (destmem, destptr, value, i); - } - } + unsigned HOST_WIDE_INT countval = UINTVAL (count); + unsigned HOST_WIDE_INT epilogue_size = countval % max_size; + unsigned int destalign = MEM_ALIGN (destmem); + store_by_pieces (destmem, epilogue_size, setmem_epilogue_gen_val, + vec_value ? vec_value : value, destalign, true, + RETURN_BEGIN); return; } if (max_size > 32) @@ -8552,6 +8624,7 @@ expand_small_cpymem_or_setmem (rtx destmem, rtx srcmem, rtx_code_label *label = ix86_expand_aligntest (count, size, false); machine_mode mode = int_mode_for_size (size * BITS_PER_UNIT, 1).else_blk (); rtx modesize; + rtx scalar_value = value; int n; /* If we do not have vector value to copy, we must reduce size. */ @@ -8571,11 +8644,57 @@ expand_small_cpymem_or_setmem (rtx destmem, rtx srcmem, { /* Choose appropriate vector mode. */ if (size >= 32) - mode = TARGET_AVX ? V32QImode : TARGET_SSE ? V16QImode : DImode; + switch (MOVE_MAX) + { + case 64: + if (size >= 64) + { + mode = V64QImode; + break; + } + /* FALLTHRU */ + case 32: + mode = V32QImode; + break; + case 16: + mode = V16QImode; + break; + case 8: + mode = DImode; + break; + default: + gcc_unreachable (); + } else if (size >= 16) mode = TARGET_SSE ? V16QImode : DImode; srcmem = change_address (srcmem, mode, srcptr); } + if (issetmem && vec_value && GET_MODE_SIZE (mode) > size) + { + /* For memset with vector and the size is smaller than the vector + size, first try the narrower vector, otherwise, use the + original value. */ + machine_mode inner_mode = GET_MODE_INNER (mode); + unsigned int nunits = size / GET_MODE_SIZE (inner_mode); + if (nunits > 1) + { + mode = mode_for_vector (GET_MODE_INNER (mode), + nunits).require (); + value = gen_rtx_SUBREG (mode, value, 0); + } + else + { + scalar_int_mode smode + = smallest_int_mode_for_size (size * BITS_PER_UNIT).require (); + gcc_assert (GET_MODE_SIZE (GET_MODE (scalar_value)) + >= GET_MODE_SIZE (smode)); + mode = smode; + if (GET_MODE (scalar_value) == mode) + value = scalar_value; + else + value = gen_rtx_SUBREG (mode, scalar_value, 0); + } + } destmem = change_address (destmem, mode, destptr); modesize = GEN_INT (GET_MODE_SIZE (mode)); gcc_assert (GET_MODE_SIZE (mode) <= size); @@ -9179,13 +9298,26 @@ decide_alignment (int align, static rtx promote_duplicated_reg (machine_mode mode, rtx val) { + if (val == const0_rtx) + return copy_to_mode_reg (mode, CONST0_RTX (mode)); + machine_mode valmode = GET_MODE (val); + if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT) + { + /* Duplicate the scalar value for integer vector. */ + gcc_assert ((val == const0_rtx || val == constm1_rtx) + || GET_MODE_INNER (mode) == valmode); + rtx dup = gen_reg_rtx (mode); + bool ok = ix86_expand_vector_init_duplicate (false, mode, dup, + val); + gcc_assert (ok); + return dup; + } + rtx tmp; int nops = mode == DImode ? 3 : 2; - gcc_assert (mode == SImode || mode == DImode || val == const0_rtx); - if (val == const0_rtx) - return copy_to_mode_reg (mode, CONST0_RTX (mode)); + gcc_assert (mode == SImode || mode == DImode); if (CONST_INT_P (val)) { HOST_WIDE_INT v = INTVAL (val) & 255; @@ -9413,11 +9545,6 @@ ix86_expand_set_or_cpymem (rtx dst, rtx src, rtx count_exp, rtx val_exp, return false; gcc_assert (alg != no_stringop); - /* For now vector-version of memset is generated only for memory zeroing, as - creating of promoted vector value is very cheap in this case. */ - if (issetmem && alg == vector_loop && val_exp != const0_rtx) - alg = unrolled_loop; - if (!count) count_exp = copy_to_mode_reg (GET_MODE (count_exp), count_exp); destreg = ix86_copy_addr_to_reg (XEXP (dst, 0)); @@ -9510,20 +9637,41 @@ ix86_expand_set_or_cpymem (rtx dst, rtx src, rtx count_exp, rtx val_exp, && ((desired_align > align && !align_bytes) || (!count && epilogue_size_needed > 1))); + /* Destination is aligned after the misaligned prologue. */ + bool aligned_dstmem = misaligned_prologue_used; + + if (noalign && !misaligned_prologue_used) + { + /* Also use misaligned prologue if alignment isn't needed and + destination isn't aligned. Since alignment isn't needed, + the destination after prologue won't be aligned. */ + aligned_dstmem = (GET_MODE_ALIGNMENT (move_mode) + <= MEM_ALIGN (dst)); + if (!aligned_dstmem) + misaligned_prologue_used = true; + } + /* Do the cheap promotion to allow better CSE across the main loop and epilogue (ie one load of the big constant in the front of all code. For now the misaligned move sequences do not have fast path without broadcasting. */ - if (issetmem && ((CONST_INT_P (val_exp) || misaligned_prologue_used))) + if (issetmem + && (alg == vector_loop + || CONST_INT_P (val_exp) + || misaligned_prologue_used)) { if (alg == vector_loop) { - gcc_assert (val_exp == const0_rtx); - vec_promoted_val = promote_duplicated_reg (move_mode, val_exp); promoted_val = promote_duplicated_reg_to_size (val_exp, GET_MODE_SIZE (word_mode), desired_align, align); + /* Duplicate the promoted scalar value if not 0 nor -1. */ + vec_promoted_val + = promote_duplicated_reg (move_mode, + (val_exp == const0_rtx + || val_exp == constm1_rtx) + ? val_exp : promoted_val); } else { @@ -9548,7 +9696,8 @@ ix86_expand_set_or_cpymem (rtx dst, rtx src, rtx count_exp, rtx val_exp, if (!issetmem) src = change_address (src, BLKmode, srcreg); dst = change_address (dst, BLKmode, destreg); - set_mem_align (dst, desired_align * BITS_PER_UNIT); + if (aligned_dstmem) + set_mem_align (dst, desired_align * BITS_PER_UNIT); epilogue_size_needed = 0; if (need_zero_guard && min_size < (unsigned HOST_WIDE_INT) size_needed) diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc index b64175d..ad7360e 100644 --- a/gcc/config/i386/i386.cc +++ b/gcc/config/i386/i386.cc @@ -6526,7 +6526,7 @@ output_set_got (rtx dest, rtx label) xops[0] = dest; - if (TARGET_VXWORKS_RTP && flag_pic) + if (TARGET_VXWORKS_GOTTPIC && TARGET_VXWORKS_RTP && flag_pic) { /* Load (*VXWORKS_GOTT_BASE) into the PIC register. */ xops[2] = gen_rtx_MEM (Pmode, @@ -12245,7 +12245,7 @@ legitimize_pic_address (rtx orig, rtx reg) else if ((GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (addr) == 0) /* We can't always use @GOTOFF for text labels on VxWorks, see gotoff_operand. */ - || (TARGET_VXWORKS_RTP && GET_CODE (addr) == LABEL_REF)) + || (TARGET_VXWORKS_VAROFF && GET_CODE (addr) == LABEL_REF)) { #if TARGET_PECOFF rtx tmp = legitimize_pe_coff_symbol (addr, true); @@ -13472,7 +13472,7 @@ ix86_delegitimize_address_1 (rtx x, bool base_term_p) else if (base_term_p && pic_offset_table_rtx && !TARGET_MACHO - && !TARGET_VXWORKS_RTP) + && !TARGET_VXWORKS_VAROFF) { rtx tmp = gen_rtx_SYMBOL_REF (Pmode, GOT_SYMBOL_NAME); tmp = gen_rtx_MINUS (Pmode, copy_rtx (addend), tmp); @@ -15872,7 +15872,7 @@ ix86_output_addr_diff_elt (FILE *file, int value, int rel) gcc_assert (!TARGET_64BIT); #endif /* We can't use @GOTOFF for text labels on VxWorks; see gotoff_operand. */ - if (TARGET_64BIT || TARGET_VXWORKS_RTP) + if (TARGET_64BIT || TARGET_VXWORKS_VAROFF) fprintf (file, "%s%s%d-%s%d\n", directive, LPREFIX, value, LPREFIX, rel); #if TARGET_MACHO @@ -26295,6 +26295,65 @@ ix86_vector_costs::finish_cost (const vector_costs *scalar_costs) && LOOP_VINFO_VECT_FACTOR (loop_vinfo).to_constant () >= 16) m_suggested_epilogue_mode = V8QImode; + /* When X86_TUNE_AVX512_MASKED_EPILOGUES is enabled try to use + a masked epilogue if that doesn't seem detrimental. */ + if (loop_vinfo + && !LOOP_VINFO_EPILOGUE_P (loop_vinfo) + && LOOP_VINFO_VECT_FACTOR (loop_vinfo).to_constant () > 2 + && ix86_tune_features[X86_TUNE_AVX512_MASKED_EPILOGUES] + && !OPTION_SET_P (param_vect_partial_vector_usage)) + { + bool avoid = false; + if (LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo) + && LOOP_VINFO_PEELING_FOR_ALIGNMENT (loop_vinfo) >= 0) + { + unsigned int peel_niter + = LOOP_VINFO_PEELING_FOR_ALIGNMENT (loop_vinfo); + if (LOOP_VINFO_PEELING_FOR_GAPS (loop_vinfo)) + peel_niter += 1; + /* When we know the number of scalar iterations of the epilogue, + avoid masking when a single vector epilog iteration handles + it in full. */ + if (pow2p_hwi ((LOOP_VINFO_INT_NITERS (loop_vinfo) - peel_niter) + % LOOP_VINFO_VECT_FACTOR (loop_vinfo).to_constant ())) + avoid = true; + } + if (!avoid && loop_outer (loop_outer (LOOP_VINFO_LOOP (loop_vinfo)))) + for (auto ddr : LOOP_VINFO_DDRS (loop_vinfo)) + { + if (DDR_ARE_DEPENDENT (ddr) == chrec_known) + ; + else if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know) + ; + else + { + int loop_depth + = index_in_loop_nest (LOOP_VINFO_LOOP (loop_vinfo)->num, + DDR_LOOP_NEST (ddr)); + if (DDR_NUM_DIST_VECTS (ddr) == 1 + && DDR_DIST_VECTS (ddr)[0][loop_depth] == 0) + { + /* Avoid the case when there's an outer loop that might + traverse a multi-dimensional array with the inner + loop just executing the masked epilogue with a + read-write where the next outer iteration might + read from the masked part of the previous write, + 'n' filling half a vector. + for (j = 0; j < m; ++j) + for (i = 0; i < n; ++i) + a[j][i] = c * a[j][i]; */ + avoid = true; + break; + } + } + } + if (!avoid) + { + m_suggested_epilogue_mode = loop_vinfo->vector_mode; + m_masked_epilogue = 1; + } + } + vector_costs::finish_cost (scalar_costs); } diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 21b9f5c..5825aca 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -20102,7 +20102,7 @@ /* We can't use @GOTOFF for text labels on VxWorks; see gotoff_operand. */ - if (TARGET_64BIT || TARGET_VXWORKS_RTP) + if (TARGET_64BIT || TARGET_VXWORKS_VAROFF) { code = PLUS; op0 = operands[0]; @@ -20970,7 +20970,7 @@ (clobber (reg:CC FLAGS_REG))])] "!TARGET_64BIT" { - if (flag_pic && !TARGET_VXWORKS_RTP) + if (flag_pic && !TARGET_VXWORKS_GOTTPIC) ix86_pc_thunk_call_expanded = true; }) @@ -20991,7 +20991,7 @@ (clobber (reg:CC FLAGS_REG))])] "!TARGET_64BIT" { - if (flag_pic && !TARGET_VXWORKS_RTP) + if (flag_pic && !TARGET_VXWORKS_GOTTPIC) ix86_pc_thunk_call_expanded = true; }) diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md index 1bd63b2..3afaf83 100644 --- a/gcc/config/i386/predicates.md +++ b/gcc/config/i386/predicates.md @@ -664,8 +664,9 @@ ;; same segment as the GOT. Unfortunately, the flexibility of linker ;; scripts means that we can't be sure of that in general, so assume ;; @GOTOFF is not valid on VxWorks, except with the large code model. +;; The comments above seem to apply only to VxWorks releases before 7. (define_predicate "gotoff_operand" - (and (ior (not (match_test "TARGET_VXWORKS_RTP")) + (and (ior (not (match_test "TARGET_VXWORKS_VAROFF")) (match_test "ix86_cmodel == CM_LARGE") (match_test "ix86_cmodel == CM_LARGE_PIC")) (match_operand 0 "local_symbolic_operand"))) diff --git a/gcc/config/i386/x86-tune.def b/gcc/config/i386/x86-tune.def index 91cdca7..a86cbad 100644 --- a/gcc/config/i386/x86-tune.def +++ b/gcc/config/i386/x86-tune.def @@ -31,7 +31,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see - Updating ix86_issue_rate and ix86_adjust_cost in i386.md - possibly updating ia32_multipass_dfa_lookahead, ix86_sched_reorder and ix86_sched_init_global if those tricks are needed. - - Tunning the flags bellow. Those are split into sections and each + - tuning flags below; those are split into sections and each section is very roughly ordered by importance. */ /*****************************************************************************/ @@ -639,6 +639,11 @@ DEF_TUNE (X86_TUNE_AVX512_STORE_BY_PIECES, "avx512_store_by_pieces", DEF_TUNE (X86_TUNE_AVX512_TWO_EPILOGUES, "avx512_two_epilogues", m_ZNVER4 | m_ZNVER5) +/* X86_TUNE_AVX512_MAKED_EPILOGUES: Use two masked vector epilogues + when fit. */ +DEF_TUNE (X86_TUNE_AVX512_MASKED_EPILOGUES, "avx512_masked_epilogues", + m_ZNVER4 | m_ZNVER5) + /*****************************************************************************/ /*****************************************************************************/ /* Historical relics: tuning flags that helps a specific old CPU designs */ diff --git a/gcc/config/riscv/constraints.md b/gcc/config/riscv/constraints.md index ccab1a2..5ecaa19 100644 --- a/gcc/config/riscv/constraints.md +++ b/gcc/config/riscv/constraints.md @@ -237,10 +237,11 @@ (and (match_code "const_vector") (match_test "rtx_equal_p (op, riscv_vector::gen_scalar_move_mask (GET_MODE (op)))"))) -(define_memory_constraint "Wdm" +(define_constraint "Wdm" "Vector duplicate memory operand" - (and (match_code "mem") - (match_code "reg" "0"))) + (and (match_test "strided_load_broadcast_p ()") + (and (match_code "mem") + (match_code "reg" "0")))) ;; Vendor ISA extension constraints. diff --git a/gcc/config/riscv/predicates.md b/gcc/config/riscv/predicates.md index 8baad2f..1f9a6b5 100644 --- a/gcc/config/riscv/predicates.md +++ b/gcc/config/riscv/predicates.md @@ -617,7 +617,7 @@ ;; The scalar operand can be directly broadcast by RVV instructions. (define_predicate "direct_broadcast_operand" - (match_test "riscv_vector::can_be_broadcasted_p (op)")) + (match_test "riscv_vector::can_be_broadcast_p (op)")) ;; A CONST_INT operand that has exactly two bits cleared. (define_predicate "const_nottwobits_operand" diff --git a/gcc/config/riscv/riscv-avlprop.cc b/gcc/config/riscv/riscv-avlprop.cc index bb4aceb..3031c29 100644 --- a/gcc/config/riscv/riscv-avlprop.cc +++ b/gcc/config/riscv/riscv-avlprop.cc @@ -508,7 +508,7 @@ pass_avlprop::execute (function *fn) simplify_replace_vlmax_avl (rinsn, prop.second); } - if (rvv_vector_bits == RVV_VECTOR_BITS_ZVL) + if (rvv_vector_bits == RVV_VECTOR_BITS_ZVL && !TARGET_XTHEADVECTOR) { /* Simplify VLMAX AVL into immediate AVL. E.g. Simplify this following case: diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h index a033120..a41c4c2 100644 --- a/gcc/config/riscv/riscv-protos.h +++ b/gcc/config/riscv/riscv-protos.h @@ -137,6 +137,7 @@ extern void riscv_expand_usadd (rtx, rtx, rtx); extern void riscv_expand_ssadd (rtx, rtx, rtx); extern void riscv_expand_ussub (rtx, rtx, rtx); extern void riscv_expand_sssub (rtx, rtx, rtx); +extern void riscv_expand_usmul (rtx, rtx, rtx); extern void riscv_expand_ustrunc (rtx, rtx); extern void riscv_expand_sstrunc (rtx, rtx); extern int riscv_register_move_cost (machine_mode, reg_class_t, reg_class_t); @@ -603,6 +604,7 @@ void emit_vlmax_vsetvl (machine_mode, rtx); void emit_hard_vlmax_vsetvl (machine_mode, rtx); void emit_vlmax_insn (unsigned, unsigned, rtx *); void emit_nonvlmax_insn (unsigned, unsigned, rtx *, rtx); +void emit_avltype_insn (unsigned, unsigned, rtx *, avl_type, rtx = nullptr); void emit_vlmax_insn_lra (unsigned, unsigned, rtx *, rtx); enum vlmul_type get_vlmul (machine_mode); rtx get_vlmax_rtx (machine_mode); @@ -759,7 +761,7 @@ uint8_t get_sew (rtx_insn *); enum vlmul_type get_vlmul (rtx_insn *); int count_regno_occurrences (rtx_insn *, unsigned int); bool imm_avl_p (machine_mode); -bool can_be_broadcasted_p (rtx); +bool can_be_broadcast_p (rtx); bool gather_scatter_valid_offset_p (machine_mode); HOST_WIDE_INT estimated_poly_value (poly_int64, unsigned int); bool whole_reg_to_reg_move_p (rtx *, machine_mode, int); @@ -812,6 +814,7 @@ extern const char *th_output_move (rtx, rtx); extern bool th_print_operand_address (FILE *, machine_mode, rtx); #endif +extern bool strided_load_broadcast_p (void); extern bool riscv_use_divmod_expander (void); void riscv_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree, int); extern bool diff --git a/gcc/config/riscv/riscv-selftests.cc b/gcc/config/riscv/riscv-selftests.cc index 34d01ac..9ca1ffe 100644 --- a/gcc/config/riscv/riscv-selftests.cc +++ b/gcc/config/riscv/riscv-selftests.cc @@ -342,9 +342,13 @@ run_broadcast_selftests (void) expand_vector_broadcast (mode, mem); \ insn = get_last_insn (); \ src = SET_SRC (PATTERN (insn)); \ - ASSERT_TRUE (MEM_P (XEXP (src, 0))); \ - ASSERT_TRUE ( \ - rtx_equal_p (src, gen_rtx_VEC_DUPLICATE (mode, XEXP (src, 0)))); \ + if (strided_load_broadcast_p ()) \ + { \ + ASSERT_TRUE (MEM_P (XEXP (src, 0))); \ + ASSERT_TRUE ( \ + rtx_equal_p (src, \ + gen_rtx_VEC_DUPLICATE (mode, XEXP (src, 0)))); \ + } \ end_sequence (); \ /* Test vmv.v.x or vfmv.v.f. */ \ start_sequence (); \ diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc index a5ab8dd..242ac08 100644 --- a/gcc/config/riscv/riscv-v.cc +++ b/gcc/config/riscv/riscv-v.cc @@ -408,7 +408,7 @@ emit_vlmax_insn_lra (unsigned icode, unsigned insn_flags, rtx *ops, rtx vl) gcc_assert (!can_create_pseudo_p ()); machine_mode mode = GET_MODE (ops[0]); - if (imm_avl_p (mode)) + if (imm_avl_p (mode) && !TARGET_XTHEADVECTOR) { /* Even though VL is a real hardreg already allocated since it is post-RA now, we still gain benefits that we emit @@ -437,6 +437,26 @@ emit_nonvlmax_insn (unsigned icode, unsigned insn_flags, rtx *ops, rtx vl) e.emit_insn ((enum insn_code) icode, ops); } +/* Emit either a VLMAX insn or a non-VLMAX insn depending on TYPE. For a + non-VLMAX insn, the length must be specified in VL. */ + +void +emit_avltype_insn (unsigned icode, unsigned insn_flags, rtx *ops, + avl_type type, rtx vl) +{ + if (type != avl_type::VLMAX && vl != NULL_RTX) + { + insn_expander<RVV_INSN_OPERANDS_MAX> e (insn_flags, false); + e.set_vl (vl); + e.emit_insn ((enum insn_code) icode, ops); + } + else + { + insn_expander<RVV_INSN_OPERANDS_MAX> e (insn_flags, true); + e.emit_insn ((enum insn_code) icode, ops); + } +} + /* Return true if the vector duplicated by a super element which is the fusion of consecutive elements. @@ -2144,21 +2164,40 @@ sew64_scalar_helper (rtx *operands, rtx *scalar_op, rtx vl, return false; } + bool avoid_strided_broadcast = false; if (CONST_INT_P (*scalar_op)) { if (maybe_gt (GET_MODE_SIZE (scalar_mode), GET_MODE_SIZE (Pmode))) - *scalar_op = force_const_mem (scalar_mode, *scalar_op); + { + if (strided_load_broadcast_p ()) + *scalar_op = force_const_mem (scalar_mode, *scalar_op); + else + avoid_strided_broadcast = true; + } else *scalar_op = force_reg (scalar_mode, *scalar_op); } rtx tmp = gen_reg_rtx (vector_mode); - rtx ops[] = {tmp, *scalar_op}; - if (type == VLMAX) - emit_vlmax_insn (code_for_pred_broadcast (vector_mode), UNARY_OP, ops); + if (!avoid_strided_broadcast) + { + rtx ops[] = {tmp, *scalar_op}; + emit_avltype_insn (code_for_pred_broadcast (vector_mode), UNARY_OP, ops, + type, vl); + } else - emit_nonvlmax_insn (code_for_pred_broadcast (vector_mode), UNARY_OP, ops, - vl); + { + /* Load scalar as V1DI and broadcast via vrgather.vi. */ + rtx tmp1 = gen_reg_rtx (V1DImode); + emit_move_insn (tmp1, lowpart_subreg (V1DImode, *scalar_op, + scalar_mode)); + tmp1 = lowpart_subreg (vector_mode, tmp1, V1DImode); + + rtx ops[] = {tmp, tmp1, CONST0_RTX (Pmode)}; + emit_vlmax_insn (code_for_pred_gather_scalar (vector_mode), + BINARY_OP, ops); + } + emit_vector_func (operands, tmp); return true; @@ -5586,6 +5625,7 @@ expand_vx_binary_vec_vec_dup (rtx op_0, rtx op_1, rtx op_2, case US_PLUS: case US_MINUS: case SS_PLUS: + case SS_MINUS: icode = code_for_pred_scalar (code, mode); break; default: @@ -5768,9 +5808,9 @@ count_regno_occurrences (rtx_insn *rinsn, unsigned int regno) return count; } -/* Return true if the OP can be directly broadcasted. */ +/* Return true if the OP can be directly broadcast. */ bool -can_be_broadcasted_p (rtx op) +can_be_broadcast_p (rtx op) { machine_mode mode = GET_MODE (op); /* We don't allow RA (register allocation) reload generate @@ -5782,7 +5822,8 @@ can_be_broadcasted_p (rtx op) return false; if (satisfies_constraint_K (op) || register_operand (op, mode) - || satisfies_constraint_Wdm (op) || rtx_equal_p (op, CONST0_RTX (mode))) + || (strided_load_broadcast_p () && satisfies_constraint_Wdm (op)) + || rtx_equal_p (op, CONST0_RTX (mode))) return true; return can_create_pseudo_p () && nonmemory_operand (op, mode); diff --git a/gcc/config/riscv/riscv-vector-builtins.cc b/gcc/config/riscv/riscv-vector-builtins.cc index f652a12..8810af0 100644 --- a/gcc/config/riscv/riscv-vector-builtins.cc +++ b/gcc/config/riscv/riscv-vector-builtins.cc @@ -4977,6 +4977,12 @@ registered_function::overloaded_hash () const for (unsigned int i = 0; i < argument_types.length (); i++) { type = argument_types[i]; + + /* If we're passed something entirely unreasonable, just ignore here. + We'll warn later anyway. */ + if (TREE_CODE_CLASS (TREE_CODE (type)) != tcc_type) + continue; + unsigned_p = POINTER_TYPE_P (type) ? TYPE_UNSIGNED (TREE_TYPE (type)) : TYPE_UNSIGNED (type); mode_p = POINTER_TYPE_P (type) ? TYPE_MODE (TREE_TYPE (type)) diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index ecdb61e..a4428f0 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -283,6 +283,10 @@ enum riscv_fusion_pairs RISCV_FUSE_AUIPC_LD = (1 << 7), RISCV_FUSE_LDPREINCREMENT = (1 << 8), RISCV_FUSE_ALIGNED_STD = (1 << 9), + RISCV_FUSE_CACHE_ALIGNED_STD = (1 << 10), + RISCV_FUSE_BFEXT = (1 << 11), + RISCV_FUSE_EXPANDED_LD = (1 << 12), + RISCV_FUSE_B_ALUI = (1 << 13), }; /* Costs of various operations on the different architectures. */ @@ -302,6 +306,7 @@ struct riscv_tune_param bool vector_unaligned_access; bool use_divmod_expansion; bool overlap_op_by_pieces; + bool use_zero_stride_load; bool speculative_sched_vsetvl; unsigned int fusible_ops; const struct cpu_vector_cost *vec_costs; @@ -465,6 +470,7 @@ static const struct riscv_tune_param generic_tune_info = { false, /* vector_unaligned_access */ false, /* use_divmod_expansion */ false, /* overlap_op_by_pieces */ + true, /* use_zero_stride_load */ false, /* speculative_sched_vsetvl */ RISCV_FUSE_NOTHING, /* fusible_ops */ NULL, /* vector cost */ @@ -488,6 +494,7 @@ static const struct riscv_tune_param rocket_tune_info = { false, /* vector_unaligned_access */ false, /* use_divmod_expansion */ false, /* overlap_op_by_pieces */ + true, /* use_zero_stride_load */ false, /* speculative_sched_vsetvl */ RISCV_FUSE_NOTHING, /* fusible_ops */ NULL, /* vector cost */ @@ -511,6 +518,7 @@ static const struct riscv_tune_param sifive_7_tune_info = { false, /* vector_unaligned_access */ false, /* use_divmod_expansion */ false, /* overlap_op_by_pieces */ + true, /* use_zero_stride_load */ false, /* speculative_sched_vsetvl */ RISCV_FUSE_NOTHING, /* fusible_ops */ NULL, /* vector cost */ @@ -534,6 +542,7 @@ static const struct riscv_tune_param sifive_p400_tune_info = { false, /* vector_unaligned_access */ false, /* use_divmod_expansion */ false, /* overlap_op_by_pieces */ + true, /* use_zero_stride_load */ false, /* speculative_sched_vsetvl */ RISCV_FUSE_LUI_ADDI | RISCV_FUSE_AUIPC_ADDI, /* fusible_ops */ &generic_vector_cost, /* vector cost */ @@ -557,6 +566,7 @@ static const struct riscv_tune_param sifive_p600_tune_info = { false, /* vector_unaligned_access */ false, /* use_divmod_expansion */ false, /* overlap_op_by_pieces */ + true, /* use_zero_stride_load */ false, /* speculative_sched_vsetvl */ RISCV_FUSE_LUI_ADDI | RISCV_FUSE_AUIPC_ADDI, /* fusible_ops */ &generic_vector_cost, /* vector cost */ @@ -580,6 +590,7 @@ static const struct riscv_tune_param thead_c906_tune_info = { false, /* vector_unaligned_access */ false, /* use_divmod_expansion */ false, /* overlap_op_by_pieces */ + true, /* use_zero_stride_load */ false, /* speculative_sched_vsetvl */ RISCV_FUSE_NOTHING, /* fusible_ops */ NULL, /* vector cost */ @@ -603,6 +614,7 @@ static const struct riscv_tune_param xiangshan_nanhu_tune_info = { false, /* vector_unaligned_access */ false, /* use_divmod_expansion */ false, /* overlap_op_by_pieces */ + true, /* use_zero_stride_load */ false, /* speculative_sched_vsetvl */ RISCV_FUSE_ZEXTW | RISCV_FUSE_ZEXTH, /* fusible_ops */ NULL, /* vector cost */ @@ -626,6 +638,7 @@ static const struct riscv_tune_param generic_ooo_tune_info = { true, /* vector_unaligned_access */ false, /* use_divmod_expansion */ true, /* overlap_op_by_pieces */ + true, /* use_zero_stride_load */ false, /* speculative_sched_vsetvl */ RISCV_FUSE_NOTHING, /* fusible_ops */ &generic_vector_cost, /* vector cost */ @@ -649,6 +662,7 @@ static const struct riscv_tune_param tt_ascalon_d8_tune_info = { true, /* vector_unaligned_access */ true, /* use_divmod_expansion */ true, /* overlap_op_by_pieces */ + true, /* use_zero_stride_load */ false, /* speculative_sched_vsetvl */ RISCV_FUSE_NOTHING, /* fusible_ops */ &generic_vector_cost, /* vector cost */ @@ -672,6 +686,7 @@ static const struct riscv_tune_param optimize_size_tune_info = { false, /* vector_unaligned_access */ false, /* use_divmod_expansion */ false, /* overlap_op_by_pieces */ + true, /* use_zero_stride_load */ false, /* speculative_sched_vsetvl */ RISCV_FUSE_NOTHING, /* fusible_ops */ NULL, /* vector cost */ @@ -695,6 +710,7 @@ static const struct riscv_tune_param mips_p8700_tune_info = { false, /* vector_unaligned_access */ true, /* use_divmod_expansion */ false, /* overlap_op_by_pieces */ + true, /* use_zero_stride_load */ false, /* speculative_sched_vsetvl */ RISCV_FUSE_NOTHING, /* fusible_ops */ NULL, /* vector cost */ @@ -3998,6 +4014,7 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN case US_PLUS: case US_MINUS: case SS_PLUS: + case SS_MINUS: *total = get_vector_binary_rtx_cost (op, scalar2vr_cost); break; default: @@ -10204,6 +10221,81 @@ riscv_fusion_enabled_p(enum riscv_fusion_pairs op) return tune_param->fusible_ops & op; } +/* Matches an add: + (set (reg:DI rd) (plus:SI (reg:SI rs1) (reg:SI rs2))) */ + +static bool +riscv_set_is_add (rtx set) +{ + return (GET_CODE (SET_SRC (set)) == PLUS + && REG_P (XEXP (SET_SRC (set), 0)) + && REG_P (XEXP (SET_SRC (set), 1)) + && REG_P (SET_DEST (set))); +} + +/* Matches an addi: + (set (reg:DI rd) (plus:SI (reg:SI rs1) (const_int imm))) */ + +static bool +riscv_set_is_addi (rtx set) +{ + return (GET_CODE (SET_SRC (set)) == PLUS + && REG_P (XEXP (SET_SRC (set), 0)) + && CONST_INT_P (XEXP (SET_SRC (set), 1)) + && REG_P (SET_DEST (set))); +} + +/* Matches an add.uw: + (set (reg:DI rd) + (plus:DI (zero_extend:DI (reg:SI rs1)) (reg:DI rs2))) */ + +static bool +riscv_set_is_adduw (rtx set) +{ + return (GET_CODE (SET_SRC (set)) == PLUS + && GET_CODE (XEXP (SET_SRC (set), 0)) == ZERO_EXTEND + && REG_P (XEXP (XEXP (SET_SRC (set), 0), 0)) + && REG_P (XEXP (SET_SRC (set), 1)) + && REG_P (SET_DEST (set))); +} + +/* Matches a shNadd: + (set (reg:DI rd) + (plus:DI (ashift:DI (reg:DI rs1) (const_int N)) (reg:DI rS2)) */ + +static bool +riscv_set_is_shNadd (rtx set) +{ + return (GET_CODE (SET_SRC (set)) == PLUS + && GET_CODE (XEXP (SET_SRC (set), 0)) == ASHIFT + && REG_P (XEXP (XEXP (SET_SRC (set), 0), 0)) + && CONST_INT_P (XEXP (XEXP (SET_SRC (set), 0), 1)) + && (INTVAL (XEXP (XEXP (SET_SRC (set), 0), 1)) == 1 + || INTVAL (XEXP (XEXP (SET_SRC (set), 0), 1)) == 2 + || INTVAL (XEXP (XEXP (SET_SRC (set), 0), 1)) == 3) + && REG_P (SET_DEST (set))); +} + +/* Matches a shNadd.uw: + (set (reg:DI rd) + (plus:DI (and:DI (ashift:DI (reg:DI rs1) (const_int N)) + (const_int N)) + (reg:DI rs2)) */ + +static bool +riscv_set_is_shNadduw (rtx set) +{ + return (GET_CODE (SET_SRC (set)) == PLUS + && GET_CODE (XEXP (SET_SRC (set), 0)) == AND + && GET_CODE (XEXP (XEXP (SET_SRC (set), 0), 0)) == ASHIFT + && REG_P (XEXP (XEXP (XEXP (SET_SRC (set), 0), 0), 0)) + && CONST_INT_P (XEXP (XEXP (XEXP (SET_SRC (set), 0), 0), 1)) + && (INTVAL (XEXP (XEXP (XEXP (SET_SRC (set), 0), 0), 1)) == 1 + || INTVAL (XEXP (XEXP (XEXP (SET_SRC (set), 0), 0), 1)) == 2 + || INTVAL (XEXP (XEXP (XEXP (SET_SRC (set), 0), 0), 1)) == 3) + && REG_P (SET_DEST (set))); +} + /* Implement TARGET_SCHED_MACRO_FUSION_PAIR_P. Return true if PREV and CURR should be kept together during scheduling. */ @@ -10333,6 +10425,139 @@ riscv_macro_fusion_pair_p (rtx_insn *prev, rtx_insn *curr) } } + if (simple_sets_p && riscv_fusion_enabled_p (RISCV_FUSE_EXPANDED_LD) + && (sched1 || prev_dest_regno == curr_dest_regno)) + { + /* For the "expanded add/load fusion" family we have 2 main + categories: memory loads with displacement (i.e. with imm offset) + and loads without displacement (i.e. with offset = x0). + + For loads without displacement we'll need: + - add + ld (done in RISCV_FUSE_LDINDEXED) + - addi + ld (done in RISCV_FUSE_LDPREINCREMENT) + - shNadd + ld + - add.uw + lw + - shNadd.uw + lw + + For loads with displacement/immediates: + with lw with immediate): + - add + ld with displacement + - addi + ld with displacement + - shNadd + ld with displacement + - add.uw + lw with displacement + - shNadd.uw + lw with displacement */ + + /* We're trying to match a curr_set ld with displacement: + prev (add|addi) = (set (reg:DI rd) (...)) + curr (ld) == (set (reg:DI rD) + (mem:DI (plus:DI (reg:DI rD) (const_int IMM12)))) */ + if (MEM_P (SET_SRC (curr_set)) + && SCALAR_INT_MODE_P (GET_MODE (SET_DEST (curr_set))) + && GET_CODE (XEXP (SET_SRC (curr_set), 0)) == PLUS + && REGNO (XEXP (XEXP (SET_SRC (curr_set), 0), 0)) == prev_dest_regno) + { + if (riscv_set_is_add (prev_set)) + { + if (dump_file) + fprintf (dump_file, "RISCV_FUSE_EXPANDED_LD\n"); + return true; + } + + if (riscv_set_is_addi (prev_set)) + { + if (dump_file) + fprintf (dump_file, "RISCV_FUSE_EXPANDED_LD\n"); + return true; + } + + if (riscv_set_is_shNadd (prev_set)) + { + if (dump_file) + fprintf (dump_file, "RISCV_FUSE_EXPANDED_LD\n"); + return true; + } + } + + /* We're trying to match a ld without displacement: + prev (addi|shNadd) = (reg:DI rD) (...)) + curr (ld) == (set (reg:DI rD) + (mem:DI (reg:DI rD))) */ + if (MEM_P (SET_SRC (curr_set)) + && SCALAR_INT_MODE_P (GET_MODE (SET_DEST (curr_set))) + && REG_P (XEXP (SET_SRC (curr_set), 0)) + && REGNO (XEXP (SET_SRC (curr_set), 0)) == prev_dest_regno) + { + if (riscv_set_is_addi (prev_set)) + { + if (dump_file) + fprintf (dump_file, "RISCV_FUSE_EXPANDED_LD\n"); + return true; + } + + if (riscv_set_is_shNadd (prev_set)) + { + if (dump_file) + fprintf (dump_file, "RISCV_FUSE_EXPANDED_LD\n"); + return true; + } + } + + /* We're trying to match a curr_set lw with displacement: + prev (add.uw|shNadd.uw) = (set (reg:DI rd) (...)) + curr (lw) == (set (reg:DI rd) + (any_extend:DI (mem:SUBX (plus:DI ((reg:DI rd) + (const_int IMM)))) */ + if ((GET_CODE (SET_SRC (curr_set)) == SIGN_EXTEND + || (GET_CODE (SET_SRC (curr_set)) == ZERO_EXTEND)) + && MEM_P (XEXP (SET_SRC (curr_set), 0)) + && SCALAR_INT_MODE_P (GET_MODE (SET_DEST (curr_set))) + && GET_CODE (XEXP (XEXP (SET_SRC (curr_set), 0), 0)) == PLUS + && REG_P (XEXP (XEXP (XEXP (SET_SRC (curr_set), 0), 0),0)) + && (REGNO (XEXP (XEXP (XEXP (SET_SRC (curr_set), 0), 0),0)) + == prev_dest_regno)) + { + if (riscv_set_is_adduw (prev_set)) + { + if (dump_file) + fprintf (dump_file, "RISCV_FUSE_EXPANDED_LD\n"); + return true; + } + + if (riscv_set_is_shNadduw (prev_set)) + { + if (dump_file) + fprintf (dump_file, "RISCV_FUSE_EXPANDED_LD\n"); + return true; + } + } + + /* We're trying to match a curr_set lw without displacement: + prev (add.uw|shNadd.uw) = (set (reg:DI rd) (...)) + curr (ld|lh|lw) == (set (reg:DI rd) + (any_extend:DI (mem:SUBX (reg:DI rsd)))) */ + if ((GET_CODE (SET_SRC (curr_set)) == SIGN_EXTEND + || (GET_CODE (SET_SRC (curr_set)) == ZERO_EXTEND)) + && MEM_P (XEXP (SET_SRC (curr_set), 0)) + && SCALAR_INT_MODE_P (GET_MODE (SET_DEST (curr_set))) + && REG_P (XEXP (XEXP (SET_SRC (curr_set), 0), 0)) + && REGNO (XEXP (XEXP (SET_SRC (curr_set), 0), 0)) == prev_dest_regno) + { + if (riscv_set_is_adduw (prev_set)) + { + if (dump_file) + fprintf (dump_file, "RISCV_FUSE_EXPANDED_LD\n"); + return true; + } + + if (riscv_set_is_shNadduw (prev_set)) + { + if (dump_file) + fprintf (dump_file, "RISCV_FUSE_EXPANDED_LD\n"); + return true; + } + } + } + if (simple_sets_p && riscv_fusion_enabled_p (RISCV_FUSE_LDPREINCREMENT) && (sched1 || prev_dest_regno == curr_dest_regno)) { @@ -10473,7 +10698,7 @@ riscv_macro_fusion_pair_p (rtx_insn *prev, rtx_insn *curr) } } - if (simple_sets_p && riscv_fusion_enabled_p (RISCV_FUSE_ALIGNED_STD)) + if (simple_sets_p && riscv_fusion_enabled_p (RISCV_FUSE_CACHE_ALIGNED_STD)) { /* We are trying to match the following: prev (sd) == (set (mem (plus (reg sp|fp) (const_int))) @@ -10527,6 +10752,175 @@ riscv_macro_fusion_pair_p (rtx_insn *prev, rtx_insn *curr) } } + /* More general form of the RISCV_FUSE_CACHE_ALIGNED_STD. The + major difference is the dependency on the stores being opposite + halves of a cache line is dropped. Instead the lowest address + needs 2X the alignment of the object and the higher address + immediately followed the first object. */ + if (simple_sets_p && riscv_fusion_enabled_p (RISCV_FUSE_ALIGNED_STD)) + { + /* We are trying to match the following: + prev (sd) == (set (mem (plus (reg rS1) (const_int))) + (reg rS2)) + curr (sd) == (set (mem (plus (reg rS1) (const_int))) + (reg rS3)) */ + + if (MEM_P (SET_DEST (prev_set)) + && SCALAR_INT_MODE_P (GET_MODE (SET_DEST (curr_set))) + && MEM_P (SET_DEST (curr_set)) + /* Stores must have the same width */ + && GET_MODE (SET_DEST (curr_set)) == GET_MODE (SET_DEST (prev_set))) + { + rtx base_prev, base_curr, offset_prev, offset_curr; + unsigned mode_size; + + extract_base_offset_in_addr (SET_DEST (prev_set), + &base_prev, &offset_prev); + extract_base_offset_in_addr (SET_DEST (curr_set), + &base_curr, &offset_curr); + + /* Proceed only if we find both bases, both bases + are registers and bases are the same register. */ + if (base_prev != NULL_RTX && base_curr != NULL_RTX + && REG_P (base_prev) && REG_P (base_curr) + && REGNO (base_prev) == REGNO (base_curr)) + { + machine_mode mode = GET_MODE (SET_DEST (curr_set)); + mode_size = estimated_poly_value (GET_MODE_SIZE (mode)); + + HOST_WIDE_INT offset_prev_int = INTVAL (offset_prev); + HOST_WIDE_INT offset_curr_int = INTVAL (offset_curr); + + /* Get the smaller offset into OFFSET_PREV_INT. */ + if (offset_prev_int > offset_curr_int) + std::swap (offset_prev_int, offset_curr_int); + + /* We've normalized, so we need to check that the lower + address is aligned to 2X the size of the object. The + higher address must be the lower address plus the + size of the object. */ + if (((offset_prev_int % (2 * mode_size)) == 0) + && offset_prev_int + mode_size == offset_curr_int) + { + if (dump_file) + fprintf (dump_file, "RISCV_FUSE_ALIGNED_STD\n"); + return true; + } + } + } + } + + if (simple_sets_p && riscv_fusion_enabled_p (RISCV_FUSE_BFEXT) + && (sched1 || prev_dest_regno == curr_dest_regno)) + { + /* We are trying to match the following: + prev (slli) == (set (reg:DI rD) + (ashift:DI (reg:DI rS) (const_int))) + curr (srli) == (set (reg:DI rD) + (lshiftrt:DI (reg:DI rD) (const_int))) */ + + if (GET_CODE (SET_SRC (prev_set)) == ASHIFT + && (GET_CODE (SET_SRC (curr_set)) == LSHIFTRT + || GET_CODE (SET_SRC (curr_set)) == ASHIFTRT) + && REG_P (SET_DEST (prev_set)) + && REG_P (SET_DEST (curr_set)) + && REGNO (XEXP (SET_SRC (curr_set), 0)) == prev_dest_regno + && CONST_INT_P (XEXP (SET_SRC (prev_set), 1)) + && CONST_INT_P (XEXP (SET_SRC (curr_set), 1))) + { + if (dump_file) + fprintf (dump_file, "RISCV_FUSE_BFEXT\n"); + return true; + } + } + + if (simple_sets_p && riscv_fusion_enabled_p (RISCV_FUSE_B_ALUI) + && (sched1 || prev_dest_regno == curr_dest_regno)) + { + /* We are trying to match the following: + prev (orc.b) == (set (reg rD) + (unspec (reg rS1))) + curr (not) == (set (reg rD2) (not (reg rD))) */ + + if (GET_CODE (SET_SRC (prev_set)) == UNSPEC + && GET_CODE (SET_SRC (curr_set)) == NOT + && XINT (SET_SRC (prev_set), 1) == UNSPEC_ORC_B + && REG_P (SET_DEST (prev_set)) + && REG_P (SET_DEST (curr_set)) + && REG_P (XEXP (SET_SRC (curr_set), 0)) + && REGNO (XEXP (SET_SRC (curr_set), 0)) == prev_dest_regno) + { + if (dump_file) + fprintf (dump_file, "RISCV_FUSE_B_ALUI\n"); + return true; + } + + /* We are trying to match the following: + prev (ctz) == (set (reg rD) (ctz (reg rS1))) + curr (andi) == (set (reg rD) + (and (reg rD) (const_int 63))) */ + + if (GET_CODE (SET_SRC (prev_set)) == CTZ + && GET_CODE (SET_SRC (curr_set)) == AND + && CONST_INT_P (XEXP (SET_SRC (curr_set), 1)) + && INTVAL (XEXP (SET_SRC (curr_set), 1)) == 63 + && REG_P (SET_DEST (prev_set)) + && REG_P (SET_DEST (curr_set)) + && REG_P (XEXP (SET_SRC (curr_set), 0)) + && REGNO (XEXP (SET_SRC (curr_set), 0)) == prev_dest_regno) + { + if (dump_file) + fprintf (dump_file, "RISCV_FUSE_B_ALUI\n"); + return true; + } + + /* We are trying to match the following: + prev (sub) == (set (reg rD) + (minus (const_int 0) (reg rS2)) + curr (max) == (set (reg rD) + (smax (reg rD) (reg rS2))) */ + + if (GET_CODE (SET_SRC (prev_set)) == MINUS + && (XEXP (SET_SRC (prev_set), 0) + == CONST0_RTX (GET_MODE (SET_SRC (prev_set)))) + && CONST_INT_P (XEXP (SET_SRC (prev_set), 0)) + && GET_CODE (SET_SRC (curr_set)) == SMAX + && REG_P (SET_DEST (prev_set)) + && REG_P (SET_DEST (curr_set)) + && REG_P (XEXP (SET_SRC (curr_set), 0)) + && REGNO (XEXP (SET_SRC (curr_set), 0)) == prev_dest_regno + && REG_P (XEXP (SET_SRC (prev_set), 1)) + && REG_P (XEXP (SET_SRC (curr_set), 1)) + && (REGNO (XEXP (SET_SRC (prev_set), 1)) + == REGNO (XEXP (SET_SRC (curr_set), 1)))) + { + if (dump_file) + fprintf (dump_file, "RISCV_FUSE_B_ALUI\n"); + return true; + } + + /* We are trying to match the following: + prev (neg) == (set (reg rD) (neg (reg rS1))) + curr (max) == (set (reg rD) + (smax (reg rD) (reg rS1))) */ + + if (GET_CODE (SET_SRC (prev_set)) == NEG + && GET_CODE (SET_SRC (curr_set)) == SMAX + && REG_P (SET_DEST (prev_set)) + && REG_P (SET_DEST (curr_set)) + && REG_P (XEXP (SET_SRC (curr_set), 0)) + && REGNO (XEXP (SET_SRC (curr_set), 0)) == prev_dest_regno + && REG_P (XEXP (SET_SRC (prev_set), 0)) + && REG_P (XEXP (SET_SRC (curr_set), 1)) + && (REGNO (XEXP (SET_SRC (prev_set), 0)) + == REGNO (XEXP (SET_SRC (curr_set), 1)))) + { + if (dump_file) + fprintf (dump_file, "RISCV_FUSE_B_ALUI\n"); + return true; + } + } + return false; } @@ -12383,6 +12777,14 @@ riscv_lshift_subword (machine_mode mode ATTRIBUTE_UNUSED, rtx value, rtx shift, gen_lowpart (QImode, shift))); } +/* Return TRUE if we should use the zero stride load, FALSE otherwise. */ + +bool +strided_load_broadcast_p () +{ + return tune_param->use_zero_stride_load; +} + /* Return TRUE if we should use the divmod expander, FALSE otherwise. This allows the behavior to be tuned for specific implementations as well as when optimizing for size. */ @@ -13347,6 +13749,88 @@ riscv_expand_sssub (rtx dest, rtx x, rtx y) emit_move_insn (dest, gen_lowpart (mode, xmode_dest)); } +/* Implement the Xmode usmul. + + b = SAT_MUL (a, b); + => + _1 = a * b; + _2 = mulhu (a, b); + _overflow_p = _2 == 0; + _mask = - _overflow_p; + b = _1 | _mask; + */ + +static void +riscv_expand_xmode_usmul (rtx dest, rtx x, rtx y) +{ + machine_mode mode = GET_MODE (dest); + + gcc_assert (mode == Xmode); + + rtx mul = gen_reg_rtx (Xmode); + rtx mulhu = gen_reg_rtx (Xmode); + rtx overflow_p = gen_reg_rtx (Xmode); + + riscv_emit_binary (MULT, mul, x, y); + + if (TARGET_64BIT) + emit_insn (gen_usmuldi3_highpart (mulhu, x, y)); + else + emit_insn (gen_usmulsi3_highpart (mulhu, x, y)); + + riscv_emit_binary (NE, overflow_p, mulhu, CONST0_RTX (Xmode)); + riscv_emit_unary (NEG, overflow_p, overflow_p); + riscv_emit_binary (IOR, dest, mul, overflow_p); +} + +/* Implement the non-Xmode usmul. + + b = SAT_MUL (a, b); + => + _1 = a * b; + _max = (T)-1 + _overflow_p = _1 > _max; + _mask = - _overflow_p; + b = _1 | _mask; + */ + +static void +riscv_expand_non_xmode_usmul (rtx dest, rtx x, rtx y) +{ + machine_mode mode = GET_MODE (dest); + unsigned bitsize = GET_MODE_BITSIZE (mode).to_constant (); + + gcc_assert (mode != Xmode); + + rtx xmode_x = riscv_extend_to_xmode_reg (x, mode, ZERO_EXTEND); + rtx xmode_y = riscv_extend_to_xmode_reg (y, mode, ZERO_EXTEND); + rtx xmode_mul = gen_reg_rtx (Xmode); + rtx mul_max = gen_reg_rtx (Xmode); + rtx overflow_p = gen_reg_rtx (Xmode); + + uint64_t max = ((uint64_t)1 << bitsize) - 1; + + emit_move_insn (mul_max, GEN_INT (max)); + riscv_emit_binary (MULT, xmode_mul, xmode_x, xmode_y); + + riscv_emit_binary (LTU, overflow_p, mul_max, xmode_mul); + riscv_emit_unary (NEG, overflow_p, overflow_p); + riscv_emit_binary (IOR, xmode_mul, xmode_mul, overflow_p); + + emit_move_insn (dest, gen_lowpart (mode, xmode_mul)); +} + +/* Implements the unsigned saturation mult standard name usmul for int mode. */ + +void +riscv_expand_usmul (rtx dest, rtx x, rtx y) +{ + if (GET_MODE (dest) == Xmode) + return riscv_expand_xmode_usmul (dest, x, y) ; + else + return riscv_expand_non_xmode_usmul (dest, x, y); +} + /* Implement the unsigned saturation truncation for int mode. b = SAT_TRUNC (a); diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md index f5ec0c5..c6661f5 100644 --- a/gcc/config/riscv/riscv.md +++ b/gcc/config/riscv/riscv.md @@ -4634,6 +4634,17 @@ } ) +(define_expand "usmul<mode>3" + [(match_operand:ANYI 0 "register_operand") + (match_operand:ANYI 1 "register_operand") + (match_operand:ANYI 2 "register_operand")] + "" + { + riscv_expand_usmul (operands[0], operands[1], operands[2]); + DONE; + } +) + (define_expand "ustrunc<mode><anyi_double_truncated>2" [(match_operand:<ANYI_DOUBLE_TRUNCATED> 0 "register_operand") (match_operand:ANYI_DOUBLE_TRUNC 1 "register_operand")] diff --git a/gcc/config/riscv/sync.md b/gcc/config/riscv/sync.md index a75ea68..50ec8b3 100644 --- a/gcc/config/riscv/sync.md +++ b/gcc/config/riscv/sync.md @@ -627,7 +627,7 @@ (match_operand:SHORT 1 "memory_operand" "+A")) ;; memory (set (match_dup 1) (unspec_volatile:SHORT [(match_operand:SHORT 2 "register_operand" "0") ;; expected_val - (match_operand:SHORT 3 "register_operand" "rJ") ;; desired_val + (match_operand:SHORT 3 "reg_or_0_operand" "rJ") ;; desired_val (match_operand:SI 4 "const_int_operand") ;; mod_s (match_operand:SI 5 "const_int_operand")] ;; mod_f UNSPEC_COMPARE_AND_SWAP))] diff --git a/gcc/config/riscv/vector-iterators.md b/gcc/config/riscv/vector-iterators.md index fd0959c..e60e3a8 100644 --- a/gcc/config/riscv/vector-iterators.md +++ b/gcc/config/riscv/vector-iterators.md @@ -4042,7 +4042,8 @@ ]) (define_code_iterator any_int_binop_no_shift_v_vdup [ - plus minus and ior xor mult div udiv mod umod smax umax smin umin us_plus us_minus ss_plus + plus minus and ior xor mult div udiv mod umod smax umax smin umin us_plus + us_minus ss_plus ss_minus ]) (define_code_iterator any_int_binop_no_shift_vdup_v [ diff --git a/gcc/config/riscv/vector.md b/gcc/config/riscv/vector.md index 6753b01..c5b23b3 100644 --- a/gcc/config/riscv/vector.md +++ b/gcc/config/riscv/vector.md @@ -1580,8 +1580,22 @@ "&& 1" [(const_int 0)] { - riscv_vector::emit_vlmax_insn (code_for_pred_broadcast (<MODE>mode), - riscv_vector::UNARY_OP, operands); + if (!strided_load_broadcast_p () + && TARGET_ZVFHMIN && !TARGET_ZVFH && <VEL>mode == HFmode) + { + /* For Float16, reinterpret as HImode, broadcast and reinterpret + back. */ + poly_uint64 nunits = GET_MODE_NUNITS (<MODE>mode); + machine_mode vmodehi + = riscv_vector::get_vector_mode (HImode, nunits).require (); + rtx ops[] = {lowpart_subreg (vmodehi, operands[0], <MODE>mode), + lowpart_subreg (HImode, operands[1], HFmode)}; + riscv_vector::emit_vlmax_insn (code_for_pred_broadcast (vmodehi), + riscv_vector::UNARY_OP, ops); + } + else + riscv_vector::emit_vlmax_insn (code_for_pred_broadcast (<MODE>mode), + riscv_vector::UNARY_OP, operands); DONE; } [(set_attr "type" "vector")] @@ -1783,7 +1797,7 @@ [(set_attr "type" "vsetvl") (set_attr "mode" "SI")]) -;; This pattern use to combine bellow two insns and then further remove +;; This pattern use to combine below two insns and then further remove ;; unnecessary sign_extend operations: ;; (set (reg:DI 134 [ _1 ]) ;; (unspec:DI [ @@ -2171,7 +2185,7 @@ } } else if (GET_MODE_BITSIZE (<VEL>mode) > GET_MODE_BITSIZE (Pmode) - && (immediate_operand (operands[3], Pmode) + && (immediate_operand (operands[3], Pmode) || (CONST_POLY_INT_P (operands[3]) && known_ge (rtx_to_poly_int64 (operands[3]), 0U) && known_le (rtx_to_poly_int64 (operands[3]), GET_MODE_SIZE (<MODE>mode))))) @@ -2224,12 +2238,7 @@ "(register_operand (operands[3], <VEL>mode) || CONST_POLY_INT_P (operands[3])) && GET_MODE_BITSIZE (<VEL>mode) > GET_MODE_BITSIZE (Pmode)" - [(set (match_dup 0) - (if_then_else:V_VLSI (unspec:<VM> [(match_dup 1) (match_dup 4) - (match_dup 5) (match_dup 6) (match_dup 7) - (reg:SI VL_REGNUM) (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE) - (vec_duplicate:V_VLSI (match_dup 3)) - (match_dup 2)))] + [(const_int 0)] { gcc_assert (can_create_pseudo_p ()); if (CONST_POLY_INT_P (operands[3])) @@ -2238,12 +2247,6 @@ emit_move_insn (tmp, operands[3]); operands[3] = tmp; } - rtx m = assign_stack_local (<VEL>mode, GET_MODE_SIZE (<VEL>mode), - GET_MODE_ALIGNMENT (<VEL>mode)); - m = validize_mem (m); - emit_move_insn (m, operands[3]); - m = gen_rtx_MEM (<VEL>mode, force_reg (Pmode, XEXP (m, 0))); - operands[3] = m; /* For SEW = 64 in RV32 system, we expand vmv.s.x: andi a2,a2,1 @@ -2254,6 +2257,35 @@ operands[4] = riscv_vector::gen_avl_for_scalar_move (operands[4]); operands[1] = CONSTM1_RTX (<VM>mode); } + + /* If the target doesn't want a strided-load broadcast we go with a regular + V1DImode load and a broadcast gather. */ + if (strided_load_broadcast_p ()) + { + rtx mem = assign_stack_local (<VEL>mode, GET_MODE_SIZE (<VEL>mode), + GET_MODE_ALIGNMENT (<VEL>mode)); + mem = validize_mem (mem); + emit_move_insn (mem, operands[3]); + mem = gen_rtx_MEM (<VEL>mode, force_reg (Pmode, XEXP (mem, 0))); + + emit_insn + (gen_pred_broadcast<mode> + (operands[0], operands[1], operands[2], mem, + operands[4], operands[5], operands[6], operands[7])); + } + else + { + rtx tmp = gen_reg_rtx (V1DImode); + emit_move_insn (tmp, lowpart_subreg (V1DImode, operands[3], + <VEL>mode)); + tmp = lowpart_subreg (<MODE>mode, tmp, V1DImode); + + emit_insn + (gen_pred_gather<mode>_scalar + (operands[0], operands[1], operands[2], tmp, CONST0_RTX (Pmode), + operands[4], operands[5], operands[6], operands[7])); + } + DONE; } [(set_attr "type" "vimov,vimov,vlds,vlds,vlds,vlds,vimovxv,vimovxv") (set_attr "mode" "<MODE>")]) @@ -2293,9 +2325,9 @@ (reg:SI VL_REGNUM) (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE) (vec_duplicate:V_VLSF_ZVFHMIN - (match_operand:<VEL> 3 "direct_broadcast_operand" "Wdm, Wdm, Wdm, Wdm")) + (match_operand:<VEL> 3 "direct_broadcast_operand" " A, A, A, A")) (match_operand:V_VLSF_ZVFHMIN 2 "vector_merge_operand" " vu, 0, vu, 0")))] - "TARGET_VECTOR" + "TARGET_VECTOR && strided_load_broadcast_p ()" "@ vlse<sew>.v\t%0,%3,zero,%1.t vlse<sew>.v\t%0,%3,zero,%1.t diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index 97a4bdf..02bc149 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -139,9 +139,6 @@ UNSPEC_LCBB ; Vector - UNSPEC_VEC_SMULT_HI - UNSPEC_VEC_UMULT_HI - UNSPEC_VEC_SMULT_LO UNSPEC_VEC_SMULT_EVEN UNSPEC_VEC_UMULT_EVEN UNSPEC_VEC_SMULT_ODD @@ -241,9 +238,6 @@ UNSPEC_VEC_MSUM - UNSPEC_VEC_VFMIN - UNSPEC_VEC_VFMAX - UNSPEC_VEC_VBLEND UNSPEC_VEC_VEVAL UNSPEC_VEC_VGEM @@ -256,6 +250,9 @@ UNSPEC_NNPA_VCFN_V8HI UNSPEC_NNPA_VCNF_V8HI + + UNSPEC_FMAX + UNSPEC_FMIN ]) ;; @@ -311,6 +308,9 @@ UNSPECV_SPLIT_STACK_CALL UNSPECV_OSC_BREAK + + ; Stack Protector + UNSPECV_SP_GET_TP ]) ;; @@ -368,6 +368,9 @@ (VR23_REGNUM 45) (VR24_REGNUM 46) (VR31_REGNUM 53) + ; Access registers + (AR0_REGNUM 36) + (AR1_REGNUM 37) ]) ; Rounding modes for binary floating point numbers @@ -11927,15 +11930,43 @@ ; Stack Protector Patterns ; +; Insns stack_protect_get_tp{si,di} are similar to *get_tp_{31,64} but still +; distinct in the sense that they force recomputation of the thread pointer +; instead of potentially reloading it from stack. + +(define_insn_and_split "stack_protect_get_tpsi" + [(set (match_operand:SI 0 "register_operand" "=d") + (unspec_volatile:SI [(const_int 0)] UNSPECV_SP_GET_TP))] + "" + "#" + "&& reload_completed" + [(set (match_dup 0) (reg:SI AR0_REGNUM))]) + +(define_insn_and_split "stack_protect_get_tpdi" + [(set (match_operand:DI 0 "register_operand" "=d") + (unspec_volatile:DI [(const_int 0)] UNSPECV_SP_GET_TP))] + "" + "#" + "&& reload_completed" + [(set (match_dup 1) (reg:SI AR0_REGNUM)) + (set (match_dup 0) (ashift:DI (match_dup 0) (const_int 32))) + (set (strict_low_part (match_dup 1)) (reg:SI AR1_REGNUM))] + "operands[1] = gen_rtx_REG (SImode, REGNO (operands[0]));") + (define_expand "stack_protect_set" [(set (match_operand 0 "memory_operand" "") (match_operand 1 "memory_operand" ""))] "" { #ifdef TARGET_THREAD_SSP_OFFSET + rtx tp = gen_reg_rtx (Pmode); + if (TARGET_64BIT) + emit_insn (gen_stack_protect_get_tpdi (tp)); + else + emit_insn (gen_stack_protect_get_tpsi (tp)); operands[1] - = gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, s390_get_thread_pointer (), - GEN_INT (TARGET_THREAD_SSP_OFFSET))); + = gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, tp, + GEN_INT (TARGET_THREAD_SSP_OFFSET))); #endif if (TARGET_64BIT) emit_insn (gen_stack_protect_setdi (operands[0], operands[1])); @@ -11961,9 +11992,14 @@ { rtx cc_reg, test; #ifdef TARGET_THREAD_SSP_OFFSET + rtx tp = gen_reg_rtx (Pmode); + if (TARGET_64BIT) + emit_insn (gen_stack_protect_get_tpdi (tp)); + else + emit_insn (gen_stack_protect_get_tpsi (tp)); operands[1] - = gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, s390_get_thread_pointer (), - GEN_INT (TARGET_THREAD_SSP_OFFSET))); + = gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, tp, + GEN_INT (TARGET_THREAD_SSP_OFFSET))); #endif if (TARGET_64BIT) emit_insn (gen_stack_protect_testdi (operands[0], operands[1])); diff --git a/gcc/config/s390/vector.md b/gcc/config/s390/vector.md index 7251a76..26753c0 100644 --- a/gcc/config/s390/vector.md +++ b/gcc/config/s390/vector.md @@ -89,6 +89,13 @@ (define_mode_iterator VF_HW [(V4SF "TARGET_VXE") V2DF (V1TF "TARGET_VXE") (TF "TARGET_VXE")]) +; FP scalar and vector modes +(define_mode_iterator VFT_BFP [SF DF + (V1SF "TARGET_VXE") (V2SF "TARGET_VXE") (V4SF "TARGET_VXE") + V1DF V2DF + (V1TF "TARGET_VXE") (TF "TARGET_VXE")]) + + (define_mode_iterator V_8 [V1QI]) (define_mode_iterator V_16 [V2QI V1HI]) (define_mode_iterator V_32 [V4QI V2HI V1SI V1SF]) @@ -3576,3 +3583,47 @@ ; vec_unpacks_float_lo ; vec_unpacku_float_hi ; vec_unpacku_float_lo + +(define_expand "avg<mode>3_ceil" + [(set (match_operand:VIT_HW_VXE3_T 0 "register_operand") + (unspec:VIT_HW_VXE3_T [(match_operand:VIT_HW_VXE3_T 1 "register_operand") + (match_operand:VIT_HW_VXE3_T 2 "register_operand")] + UNSPEC_VEC_AVG))] + "TARGET_VX") + +(define_expand "uavg<mode>3_ceil" + [(set (match_operand:VIT_HW_VXE3_T 0 "register_operand") + (unspec:VIT_HW_VXE3_T [(match_operand:VIT_HW_VXE3_T 1 "register_operand") + (match_operand:VIT_HW_VXE3_T 2 "register_operand")] + UNSPEC_VEC_AVGU))] + "TARGET_VX") + +(define_expand "smul<mode>3_highpart" + [(set (match_operand:VIT_HW_VXE3_DT 0 "register_operand") + (smul_highpart:VIT_HW_VXE3_DT (match_operand:VIT_HW_VXE3_DT 1 "register_operand") + (match_operand:VIT_HW_VXE3_DT 2 "register_operand")))] + "TARGET_VX") + +(define_expand "umul<mode>3_highpart" + [(set (match_operand:VIT_HW_VXE3_DT 0 "register_operand") + (umul_highpart:VIT_HW_VXE3_DT (match_operand:VIT_HW_VXE3_DT 1 "register_operand") + (match_operand:VIT_HW_VXE3_DT 2 "register_operand")))] + "TARGET_VX") + +; fmax +(define_expand "fmax<mode>3" + [(set (match_operand:VFT_BFP 0 "register_operand") + (unspec:VFT_BFP [(match_operand:VFT_BFP 1 "register_operand") + (match_operand:VFT_BFP 2 "register_operand") + (const_int 4)] + UNSPEC_FMAX))] + "TARGET_VXE") + +; fmin +(define_expand "fmin<mode>3" + [(set (match_operand:VFT_BFP 0 "register_operand") + (unspec:VFT_BFP [(match_operand:VFT_BFP 1 "register_operand") + (match_operand:VFT_BFP 2 "register_operand") + (const_int 4)] + UNSPEC_FMIN))] + "TARGET_VXE") diff --git a/gcc/config/s390/vx-builtins.md b/gcc/config/s390/vx-builtins.md index a7bb7ff..9b89b13 100644 --- a/gcc/config/s390/vx-builtins.md +++ b/gcc/config/s390/vx-builtins.md @@ -982,20 +982,18 @@ ; vmhb, vmhh, vmhf, vmhg, vmhq (define_insn "vec_smulh<mode>" - [(set (match_operand:VIT_HW_VXE3_DT 0 "register_operand" "=v") - (unspec:VIT_HW_VXE3_DT [(match_operand:VIT_HW_VXE3_DT 1 "register_operand" "v") - (match_operand:VIT_HW_VXE3_DT 2 "register_operand" "v")] - UNSPEC_VEC_SMULT_HI))] + [(set (match_operand:VIT_HW_VXE3_DT 0 "register_operand" "=v") + (smul_highpart:VIT_HW_VXE3_DT (match_operand:VIT_HW_VXE3_DT 1 "register_operand" "v") + (match_operand:VIT_HW_VXE3_DT 2 "register_operand" "v")))] "TARGET_VX" "vmh<bhfgq>\t%v0,%v1,%v2" [(set_attr "op_type" "VRR")]) ; vmlhb, vmlhh, vmlhf, vmlhg, vmlhq (define_insn "vec_umulh<mode>" - [(set (match_operand:VIT_HW_VXE3_DT 0 "register_operand" "=v") - (unspec:VIT_HW_VXE3_DT [(match_operand:VIT_HW_VXE3_DT 1 "register_operand" "v") - (match_operand:VIT_HW_VXE3_DT 2 "register_operand" "v")] - UNSPEC_VEC_UMULT_HI))] + [(set (match_operand:VIT_HW_VXE3_DT 0 "register_operand" "=v") + (umul_highpart:VIT_HW_VXE3_DT (match_operand:VIT_HW_VXE3_DT 1 "register_operand" "v") + (match_operand:VIT_HW_VXE3_DT 2 "register_operand" "v")))] "TARGET_VX" "vmlh<bhfgq>\t%v0,%v1,%v2" [(set_attr "op_type" "VRR")]) @@ -2136,23 +2134,22 @@ "<vw>fche<sdx>bs\t%v2,%v0,%v1" [(set_attr "op_type" "VRR")]) - (define_insn "vfmin<mode>" - [(set (match_operand:VF_HW 0 "register_operand" "=v") - (unspec:VF_HW [(match_operand:VF_HW 1 "register_operand" "v") - (match_operand:VF_HW 2 "register_operand" "v") - (match_operand:QI 3 "const_mask_operand" "C")] - UNSPEC_VEC_VFMIN))] + [(set (match_operand:VFT_BFP 0 "register_operand" "=v") + (unspec:VFT_BFP [(match_operand:VFT_BFP 1 "register_operand" "v") + (match_operand:VFT_BFP 2 "register_operand" "v") + (match_operand:QI 3 "const_mask_operand" "C")] + UNSPEC_FMIN))] "TARGET_VXE" "<vw>fmin<sdx>b\t%v0,%v1,%v2,%b3" [(set_attr "op_type" "VRR")]) (define_insn "vfmax<mode>" - [(set (match_operand:VF_HW 0 "register_operand" "=v") - (unspec:VF_HW [(match_operand:VF_HW 1 "register_operand" "v") - (match_operand:VF_HW 2 "register_operand" "v") - (match_operand:QI 3 "const_mask_operand" "C")] - UNSPEC_VEC_VFMAX))] + [(set (match_operand:VFT_BFP 0 "register_operand" "=v") + (unspec:VFT_BFP [(match_operand:VFT_BFP 1 "register_operand" "v") + (match_operand:VFT_BFP 2 "register_operand" "v") + (match_operand:QI 3 "const_mask_operand" "C")] + UNSPEC_FMAX))] "TARGET_VXE" "<vw>fmax<sdx>b\t%v0,%v1,%v2,%b3" [(set_attr "op_type" "VRR")]) diff --git a/gcc/config/vxworks-dummy.h b/gcc/config/vxworks-dummy.h index 494799d..516728c 100644 --- a/gcc/config/vxworks-dummy.h +++ b/gcc/config/vxworks-dummy.h @@ -40,9 +40,21 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #define TARGET_VXWORKS_RTP false #endif +/* True if offsets between different segments may vary, so we must avoid + cross-segment GOT- and PC-relative address computations. */ +#ifndef TARGET_VXWORKS_VAROFF +#define TARGET_VXWORKS_VAROFF false +#endif + /* The symbol that points to an RTP's table of GOTs. */ #define VXWORKS_GOTT_BASE (gcc_unreachable (), "") /* The symbol that holds the index of the current module's GOT in VXWORKS_GOTT_BASE. */ #define VXWORKS_GOTT_INDEX (gcc_unreachable (), "") + +/* True if PIC relies on the GOTT_* symbols above. As of VxWorks7, they are no + longer used. */ +#ifndef TARGET_VXWORKS_GOTTPIC +#define TARGET_VXWORKS_GOTTPIC false +#endif diff --git a/gcc/config/vxworks.h b/gcc/config/vxworks.h index 204a8e0..d2b6025 100644 --- a/gcc/config/vxworks.h +++ b/gcc/config/vxworks.h @@ -159,6 +159,18 @@ extern void vxworks_driver_init (unsigned int *, struct cl_decoded_option **); Earlier versions did not, not even for RTPS. */ #define VXWORKS_HAVE_TLS TARGET_VXWORKS7 +/* RTP segments could be loaded with varying offsets, so cross-segment offsets + could not be assumed to be constant. This rules out some PC- and + GOT-relative addressing. */ +#undef TARGET_VXWORKS_VAROFF +#define TARGET_VXWORKS_VAROFF (!TARGET_VXWORKS7 && TARGET_VXWORKS_RTP) + +/* GOTT_BASE and GOTT_INDEX symbols are only used by some ports up to VxWorks6. + This macro is only used by i386 so far. Other ports seem to keep on using + GOTTPIC from VxWorks7 on, but they don't test this macro. */ +#undef TARGET_VXWORKS_GOTTPIC +#define TARGET_VXWORKS_GOTTPIC (!TARGET_VXWORKS7) + /* On Vx6 and previous, the libraries to pick up depends on the architecture, so cannot be defined for all archs at once. On Vx7, a VSB is always needed and its structure is fixed and does not depend on the arch. We can thus diff --git a/gcc/config/xtensa/xtensa.cc b/gcc/config/xtensa/xtensa.cc index 92a2364..b75cec1 100644 --- a/gcc/config/xtensa/xtensa.cc +++ b/gcc/config/xtensa/xtensa.cc @@ -159,6 +159,10 @@ static void xtensa_asm_trampoline_template (FILE *); static void xtensa_trampoline_init (rtx, tree, rtx); static bool xtensa_output_addr_const_extra (FILE *, rtx); static bool xtensa_cannot_force_const_mem (machine_mode, rtx); +static machine_mode xtensa_promote_function_mode (const_tree, + machine_mode, + int *, const_tree, + int); static reg_class_t xtensa_preferred_reload_class (rtx, reg_class_t); static reg_class_t xtensa_preferred_output_reload_class (rtx, reg_class_t); @@ -235,9 +239,7 @@ static HARD_REG_SET xtensa_zero_call_used_regs (HARD_REG_SET); #define TARGET_EXPAND_BUILTIN_VA_START xtensa_va_start #undef TARGET_PROMOTE_FUNCTION_MODE -#define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote -#undef TARGET_PROMOTE_PROTOTYPES -#define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true +#define TARGET_PROMOTE_FUNCTION_MODE xtensa_promote_function_mode #undef TARGET_RETURN_IN_MEMORY #define TARGET_RETURN_IN_MEMORY xtensa_return_in_memory @@ -421,12 +423,13 @@ xtensa_uimm8x4 (HOST_WIDE_INT v) } -static bool -xtensa_b4const (HOST_WIDE_INT v) +bool +xtensa_b4const_or_zero (HOST_WIDE_INT v) { switch (v) { case -1: + case 0: case 1: case 2: case 3: @@ -449,15 +452,6 @@ xtensa_b4const (HOST_WIDE_INT v) bool -xtensa_b4const_or_zero (HOST_WIDE_INT v) -{ - if (v == 0) - return true; - return xtensa_b4const (v); -} - - -bool xtensa_b4constu (HOST_WIDE_INT v) { switch (v) @@ -4510,7 +4504,8 @@ xtensa_rtx_costs (rtx x, machine_mode mode, int outer_code, } break; case COMPARE: - if ((INTVAL (x) == 0) || xtensa_b4const (INTVAL (x))) + if (xtensa_b4const_or_zero (INTVAL (x)) + || xtensa_b4constu (INTVAL (x))) { *total = 0; return true; @@ -4801,6 +4796,19 @@ xtensa_insn_cost (rtx_insn *insn, bool speed) return pattern_cost (PATTERN (insn), speed); } +/* Worker function for TARGET_PROMOTE_FUNCTION_MODE. */ + +static machine_mode +xtensa_promote_function_mode (const_tree type, machine_mode mode, + int *punsignedp, const_tree, int) +{ + if (GET_MODE_CLASS (mode) == MODE_INT + && GET_MODE_SIZE (mode) < GET_MODE_SIZE (SImode)) + return SImode; + + return promote_mode (type, mode, punsignedp); +} + /* Worker function for TARGET_RETURN_IN_MEMORY. */ static bool diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 23511a0..79873a2 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,82 @@ +2025-07-09 Jason Merrill <jason@redhat.com> + + PR c++/121012 + PR c++/120917 + * parser.cc (cp_parser_lambda_expression): Clear + parser->in_template_argument_list_p. + +2025-07-09 Jason Merrill <jason@redhat.com> + + PR c++/121008 + PR c++/113563 + * semantics.cc (finish_this_expr): Do check current_class_ref for + non-lambda. + +2025-07-09 Marek Polacek <polacek@redhat.com> + + PR c++/119838 + * parser.cc (cp_parser_nested_name_specifier_opt): New global_p + parameter. Look for "template" when global_p is true. + (cp_parser_simple_type_specifier): Pass global_p to + cp_parser_nested_name_specifier_opt. + +2025-07-08 Marek Polacek <polacek@redhat.com> + Andrew Pinski <quic_apinski@quicinc.com> + + PR c++/83469 + PR c++/93809 + * cp-tree.h (UNION_TYPE_P): Define. + (TYPENAME_IS_UNION_P): Define. + * decl.cc (struct typename_info): Add union_p field. + (struct typename_hasher::equal): Compare union_p field. + (build_typename_type): Use ti.union_p for union_type. Set + TYPENAME_IS_UNION_P. + * error.cc (dump_type) <case TYPENAME_TYPE>: Handle + TYPENAME_IS_UNION_P. + * module.cc (trees_out::type_node): Likewise. + * parser.cc (cp_parser_check_class_key): Allow typename key for union + types and allow union keyword for typename types. + * pt.cc (tsubst) <case TYPENAME_TYPE>: Don't conflate unions with + class_type. For TYPENAME_IS_CLASS_P, check NON_UNION_CLASS_TYPE_P + rather than CLASS_TYPE_P. Add TYPENAME_IS_UNION_P handling. + +2025-07-08 Jakub Jelinek <jakub@redhat.com> + + PR c++/117784 + * decl.cc: Implement part of C++26 P2686R4 - constexpr structured + bindings. + (cp_finish_decl): Pedwarn for C++23 and older on constinit on + structured bindings except for static/thread_local where it uses + earlier error. + (grokdeclarator): Pedwarn on constexpr structured bindings for + C++23 and older instead of emitting error always, don't clear + constexpr_p in that case. + * parser.cc (cp_parser_decomposition_declaration): Copy over + DECL_DECLARED_CONSTEXPR_P and DECL_DECLARED_CONSTINIT_P flags. + +2025-07-07 Alfie Richards <alfie.richards@arm.com> + + PR c++/119498 + * decl.cc (duplicate_decls): Change logic to not always exclude FMV + annotated functions in cases of return type non-ambiguation. + +2025-07-07 Jason Merrill <jason@redhat.com> + + PR c++/120917 + * parser.cc (cp_parser_simple_type_specifier): Attach + auto in targ in parameter to -Wabbreviated-auto-in-template-arg. + (cp_parser_placeholder_type_specifier): Diagnose constrained auto in + template arg. + +2025-07-07 Jakub Jelinek <jakub@redhat.com> + + PR c++/84009 + * parser.cc (cp_parser_decomposition_declaration): Pedwarn + on thread_local, __thread or static in decl_specifiers for + for-range-declaration. + (cp_parser_init_declarator): Likewise, and also for extern + or register. + 2025-07-04 Jason Merrill <jason@redhat.com> PR c++/120575 diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc index 2c3ef3d..2629625 100644 --- a/gcc/cp/call.cc +++ b/gcc/cp/call.cc @@ -1723,6 +1723,56 @@ involves_qualification_conversion_p (tree to, tree from) return false; } +/* Return true if HANDLER is a match for exception object with EXCEPT_TYPE as + per [except.handle]/3. */ + +bool +handler_match_for_exception_type (tree handler, tree except_type) +{ + tree handler_type = HANDLER_TYPE (handler); + if (handler_type == NULL_TREE) + return true; /* ... */ + if (same_type_ignoring_top_level_qualifiers_p (handler_type, except_type)) + return true; + if (CLASS_TYPE_P (except_type) && CLASS_TYPE_P (handler_type)) + { + base_kind b_kind; + tree binfo = lookup_base (except_type, handler_type, ba_check, &b_kind, + tf_none); + if (binfo && binfo != error_mark_node) + return true; + } + if (TYPE_PTR_P (handler_type) || TYPE_PTRDATAMEM_P (handler_type)) + { + if (TREE_CODE (except_type) == NULLPTR_TYPE) + return true; + if ((TYPE_PTR_P (handler_type) && TYPE_PTR_P (except_type)) + || (TYPE_PTRDATAMEM_P (handler_type) + && TYPE_PTRDATAMEM_P (except_type))) + { + conversion *conv + = standard_conversion (handler_type, except_type, NULL_TREE, + /*c_cast_p=*/false, 0, tf_none); + if (conv && !conv->bad_p) + { + for (conversion *t = conv; t; t = next_conversion (t)) + switch (t->kind) + { + case ck_ptr: + case ck_fnptr: + case ck_qual: + case ck_identity: + break; + default: + return false; + } + return true; + } + } + } + return false; +} + /* A reference of the indicated TYPE is being bound directly to the expression represented by the implicit conversion sequence CONV. Return a conversion sequence for this binding. */ diff --git a/gcc/cp/class.cc b/gcc/cp/class.cc index 9a41c00..151ee2b 100644 --- a/gcc/cp/class.cc +++ b/gcc/cp/class.cc @@ -7452,7 +7452,7 @@ determine_key_method (tree type) && ! DECL_DECLARED_INLINE_P (method) && ! DECL_PURE_VIRTUAL_P (method)) { - CLASSTYPE_KEY_METHOD (type) = method; + SET_CLASSTYPE_KEY_METHOD (type, method); break; } diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc index f9066bc..eb19784 100644 --- a/gcc/cp/constexpr.cc +++ b/gcc/cp/constexpr.cc @@ -1184,6 +1184,10 @@ public: /* Heap VAR_DECLs created during the evaluation of the outermost constant expression. */ auto_vec<tree, 16> heap_vars; + /* Vector of caught exceptions, including exceptions still not active at + the start of a handler (those are immediately followed up by HANDLER_TYPE + until __cxa_begin_catch finishes). */ + auto_vec<tree, 2> caught_exceptions; /* Cleanups that need to be evaluated at the end of CLEANUP_POINT_EXPR. */ vec<tree> *cleanups; /* If non-null, only allow modification of existing values of the variables @@ -1191,10 +1195,13 @@ public: hash_set<tree> *modifiable; /* Number of heap VAR_DECL deallocations. */ unsigned heap_dealloc_count; + /* Number of uncaught exceptions. */ + unsigned uncaught_exceptions; + /* Constructor. */ constexpr_global_ctx () : constexpr_ops_count (0), cleanups (NULL), modifiable (nullptr), - heap_dealloc_count (0) {} + heap_dealloc_count (0), uncaught_exceptions (0) {} bool is_outside_lifetime (tree t) { @@ -1308,6 +1315,48 @@ struct constexpr_ctx { mce_value manifestly_const_eval; }; +/* Predicates for the meaning of *jump_target. */ + +static bool +returns (tree *jump_target) +{ + return *jump_target && TREE_CODE (*jump_target) == RETURN_EXPR; +} + +static bool +breaks (tree *jump_target) +{ + return (*jump_target + && ((TREE_CODE (*jump_target) == LABEL_DECL + && LABEL_DECL_BREAK (*jump_target)) + || TREE_CODE (*jump_target) == BREAK_STMT + || TREE_CODE (*jump_target) == EXIT_EXPR)); +} + +static bool +continues (tree *jump_target) +{ + return (*jump_target + && ((TREE_CODE (*jump_target) == LABEL_DECL + && LABEL_DECL_CONTINUE (*jump_target)) + || TREE_CODE (*jump_target) == CONTINUE_STMT)); +} + +static bool +switches (tree *jump_target) +{ + return *jump_target && TREE_CODE (*jump_target) == INTEGER_CST; +} + +static bool +throws (tree *jump_target) +{ + /* void_node is for use in potential_constant_expression_1, otherwise + it should an artificial VAR_DECL created by constant evaluation + of __cxa_allocate_exception (). */ + return (*jump_target && (VAR_P (*jump_target) || *jump_target == void_node)); +} + /* True if the constexpr relaxations afforded by P2280R4 for unknown references and objects are in effect. */ @@ -1543,13 +1592,672 @@ enum value_cat { }; static tree cxx_eval_constant_expression (const constexpr_ctx *, tree, - value_cat, bool *, bool *, tree * = NULL); + value_cat, bool *, bool *, tree *); static tree cxx_eval_bare_aggregate (const constexpr_ctx *, tree, - value_cat, bool *, bool *); + value_cat, bool *, bool *, tree *); static tree cxx_fold_indirect_ref (const constexpr_ctx *, location_t, tree, tree, - bool * = NULL); + bool *, tree *); static tree find_heap_var_refs (tree *, int *, void *); +/* For exception object EXC if it has class type and usable what () method + which returns cv char * return the xmalloced string literal which it returns + if possible, otherwise return NULL. */ + +static char * +exception_what_str (const constexpr_ctx *ctx, tree exc) +{ + tree type = strip_array_types (TREE_TYPE (exc)); + if (!CLASS_TYPE_P (type)) + return NULL; + tree std_exception = lookup_qualified_name (std_node, "exception", + LOOK_want::NORMAL, false); + if (TREE_CODE (std_exception) != TYPE_DECL) + return NULL; + if (!CLASS_TYPE_P (TREE_TYPE (std_exception))) + return NULL; + base_kind b_kind; + tree binfo = lookup_base (type, TREE_TYPE (std_exception), ba_check, &b_kind, + tf_none); + if (binfo == NULL_TREE || binfo == error_mark_node) + return NULL; + if (type != TREE_TYPE (exc)) + exc = build4 (ARRAY_REF, type, exc, size_zero_node, NULL, NULL); + tree call + = finish_class_member_access_expr (exc, get_identifier ("what"), false, + tf_none); + if (call == error_mark_node) + return NULL; + releasing_vec what_args; + call = finish_call_expr (call, &what_args, false, false, tf_none); + if (call == error_mark_node) + return NULL; + if (TREE_CODE (TREE_TYPE (call)) != POINTER_TYPE + || !INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (call))) + || !COMPLETE_TYPE_P (TREE_TYPE (TREE_TYPE (call))) + || !tree_int_cst_equal (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (call))), + TYPE_SIZE_UNIT (char_type_node)) + || TYPE_PRECISION (TREE_TYPE (TREE_TYPE (call))) != BITS_PER_UNIT) + return NULL; + if (!potential_constant_expression (call)) + return NULL; + bool non_constant_p = false, overflow_p = false; + tree jmp_target = NULL; + tree ptr = cxx_eval_constant_expression (ctx, call, vc_prvalue, + &non_constant_p, &overflow_p, + &jmp_target); + if (throws (&jmp_target) || non_constant_p) + return NULL; + if (reduced_constant_expression_p (ptr)) + if (const char *msg = c_getstr (ptr)) + return xstrdup (msg); + auto_vec <char, 32> v; + for (unsigned i = 0; i < INT_MAX; ++i) + { + tree t = call; + if (i) + t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (ptr), ptr, size_int (i)); + t = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (t)), t); + non_constant_p = false; + overflow_p = false; + jmp_target = NULL; + tree t2 = cxx_eval_constant_expression (ctx, t, vc_prvalue, + &non_constant_p, &overflow_p, + &jmp_target); + if (throws (&jmp_target) + || non_constant_p + || !tree_fits_shwi_p (t2)) + return NULL; + char c = tree_to_shwi (t2); + v.safe_push (c); + if (c == '\0') + break; + } + return xstrdup (v.address ()); +} + +/* Diagnose constant expression evaluation encountering call to + std::terminate due to exception EXC. */ + +static void +diagnose_std_terminate (location_t loc, const constexpr_ctx *ctx, tree exc) +{ + tree type = strip_array_types (TREE_TYPE (exc)); + if (char *str = exception_what_str (ctx, exc)) + { + error_at (loc, "%qs called after throwing an exception of type %qT; " + "%<what()%>: %qs", "std::terminate", type, str); + free (str); + } + else + { + if (type != TREE_TYPE (exc)) + exc = build4 (ARRAY_REF, type, exc, size_zero_node, NULL, NULL); + bool non_constant_p = false, overflow_p = false; + tree jmp_target = NULL; + tree val = cxx_eval_constant_expression (ctx, exc, vc_prvalue, + &non_constant_p, &overflow_p, + &jmp_target); + gcc_assert (!throws (&jmp_target) && !non_constant_p); + if (reduced_constant_expression_p (val)) + error_at (loc, "%qs called after throwing an exception %qE", + "std::terminate", val); + else + error_at (loc, "%qs called after throwing an exception of type %qT", + "std::terminate", type); + } +} + +/* Diagnose constant expression evaluation encountering call to + uncaught exception EXC. */ + +static void +diagnose_uncaught_exception (location_t loc, const constexpr_ctx *ctx, tree exc) +{ + tree type = strip_array_types (TREE_TYPE (exc)); + if (char *str = exception_what_str (ctx, exc)) + { + error_at (loc, "uncaught exception of type %qT; %<what()%>: %qs", type, str); + free (str); + } + else + { + if (type != TREE_TYPE (exc)) + exc = build4 (ARRAY_REF, type, exc, size_zero_node, NULL, NULL); + bool non_constant_p = false, overflow_p = false; + tree jmp_target = NULL; + tree val = cxx_eval_constant_expression (ctx, exc, vc_prvalue, + &non_constant_p, &overflow_p, + &jmp_target); + gcc_assert (!throws (&jmp_target) && !non_constant_p); + if (reduced_constant_expression_p (val)) + error_at (loc, "uncaught exception %qE", val); + else + error_at (loc, "uncaught exception of type %qT", type); + } +} + +/* Kinds of __cxa_* functions (and a few other EH related ones) we handle as + magic constexpr functions for C++26. */ + +enum cxa_builtin { + CXA_NONE = 0, + CXA_ALLOCATE_EXCEPTION = 1, + CXA_FREE_EXCEPTION = 2, + CXA_THROW = 3, + CXA_BEGIN_CATCH = 4, + CXA_END_CATCH = 5, + CXA_RETHROW = 6, + CXA_GET_EXCEPTION_PTR = 7, + CXA_BAD_CAST = 8, + CXA_BAD_TYPEID = 9, + CXA_THROW_BAD_ARRAY_NEW_LENGTH = 10, + STD_UNCAUGHT_EXCEPTIONS = 11, + STD_CURRENT_EXCEPTION = 12, + STD_RETHROW_EXCEPTION = 13, + BUILTIN_EH_PTR_ADJUST_REF = 14 +}; + +/* Return cxa_builtin if FNDECL is a __cxa_* function handled as + magic constexpr function for C++26. Return CXA_NONE otherwise. */ + +static enum cxa_builtin +cxx_cxa_builtin_fn_p (tree fndecl) +{ + if (cxx_dialect < cxx26) + return CXA_NONE; + if (DECL_LANGUAGE (fndecl) != lang_c) + { + if (!decl_in_std_namespace_p (fndecl)) + return CXA_NONE; + if (id_equal (DECL_NAME (fndecl), "uncaught_exceptions")) + return STD_UNCAUGHT_EXCEPTIONS; + if (id_equal (DECL_NAME (fndecl), "current_exception")) + return STD_CURRENT_EXCEPTION; + if (id_equal (DECL_NAME (fndecl), "rethrow_exception")) + return STD_RETHROW_EXCEPTION; + return CXA_NONE; + } + if (!startswith (IDENTIFIER_POINTER (DECL_NAME (fndecl)), "__cxa_")) + return CXA_NONE; + if (id_equal (DECL_NAME (fndecl), "__cxa_allocate_exception")) + return CXA_ALLOCATE_EXCEPTION; + if (id_equal (DECL_NAME (fndecl), "__cxa_free_exception")) + return CXA_FREE_EXCEPTION; + if (id_equal (DECL_NAME (fndecl), "__cxa_throw")) + return CXA_THROW; + if (id_equal (DECL_NAME (fndecl), "__cxa_begin_catch")) + return CXA_BEGIN_CATCH; + if (id_equal (DECL_NAME (fndecl), "__cxa_end_catch")) + return CXA_END_CATCH; + if (id_equal (DECL_NAME (fndecl), "__cxa_rethrow")) + return CXA_RETHROW; + if (id_equal (DECL_NAME (fndecl), "__cxa_get_exception_ptr")) + return CXA_GET_EXCEPTION_PTR; + if (id_equal (DECL_NAME (fndecl), "__cxa_bad_cast")) + return CXA_BAD_CAST; + if (id_equal (DECL_NAME (fndecl), "__cxa_bad_typeid")) + return CXA_BAD_TYPEID; + if (id_equal (DECL_NAME (fndecl), "__cxa_throw_bad_array_new_length")) + return CXA_THROW_BAD_ARRAY_NEW_LENGTH; + return CXA_NONE; +} + +/* Helper function for cxx_eval_cxa_builtin_fn. + Check if ARG is a valid first argument of __cxa_throw or + __cxa_free_exception or __builtin_eh_ptr_adjust_ref. Return NULL_TREE if + not, otherwise return the artificial __cxa_allocate_exception allocated + VAR_DECL. FREE_EXC is true for __cxa_free_exception, false otherwise. */ + +static tree +cxa_check_throw_arg (tree arg, bool free_exc) +{ + STRIP_NOPS (arg); + if (TREE_CODE (arg) != ADDR_EXPR) + return NULL_TREE; + arg = TREE_OPERAND (arg, 0); + if (!VAR_P (arg) + || !DECL_ARTIFICIAL (arg) + || ((!free_exc || DECL_NAME (arg) != heap_uninit_identifier) + && DECL_NAME (arg) != heap_identifier) + || !DECL_LANG_SPECIFIC (arg)) + return NULL_TREE; + return arg; +} + +/* Helper function for cxx_eval_cxa_builtin_fn. + "Allocate" on the constexpr heap an exception object of TYPE + with REFCOUNT. */ + +static tree +cxa_allocate_exception (location_t loc, const constexpr_ctx *ctx, tree type, + tree refcount) +{ + tree var = build_decl (loc, VAR_DECL, heap_uninit_identifier, type); + DECL_ARTIFICIAL (var) = 1; + retrofit_lang_decl (var); + DECL_EXCEPTION_REFCOUNT (var) = refcount; + ctx->global->heap_vars.safe_push (var); + return var; +} + +/* Evaluate various __cxa_* calls as magic constexpr builtins for + C++26 constexpr exception support (P3068R5). */ + +static tree +cxx_eval_cxa_builtin_fn (const constexpr_ctx *ctx, tree call, + enum cxa_builtin kind, tree fndecl, + bool *non_constant_p, bool *overflow_p, + tree *jump_target) +{ + int nargs = call_expr_nargs (call); + location_t loc = cp_expr_loc_or_input_loc (call); + tree args[4], arg; + if (nargs > 4) + { + invalid_nargs: + if (!ctx->quiet) + error_at (loc, "call to %qD function with incorrect" + "number of arguments", fndecl); + *non_constant_p = true; + return call; + } + if ((kind == CXA_BEGIN_CATCH || kind == CXA_GET_EXCEPTION_PTR) + && nargs == 1 + && (arg = CALL_EXPR_ARG (call, 0)) + && TREE_CODE (arg) == CALL_EXPR + && call_expr_nargs (arg) == 1 + && integer_zerop (CALL_EXPR_ARG (arg, 0))) + if (tree fun = get_function_named_in_call (arg)) + if (fndecl_built_in_p (fun, BUILT_IN_EH_POINTER)) + { + if (ctx->global->caught_exceptions.length () < 2) + { + no_caught_exceptions: + if (!ctx->quiet) + error_at (loc, "%qD called with no caught exceptions pending", + fndecl); + *non_constant_p = true; + return call; + } + /* Both __cxa_get_exception_ptr (__builtin_eh_pointer (0)) + and __cxa_begin_catch (__builtin_eh_pointer (0)) calls expect + ctx->global->caught_exceptions vector to end with + __cxa_allocate_exception created artificial VAR_DECL (the + exception object) followed by handler type, pushed by TRY_BLOCK + evaluation. The only difference between the functions is that + __cxa_begin_catch pops the handler type from the vector and keeps + the VAR_DECL last and decreases uncaught_exceptions. The + VAR_DECL after __cxa_begin_catch serves as the current exception + and is then popped in __cxa_end_catch evaluation. */ + tree handler_type = ctx->global->caught_exceptions.last (); + if (handler_type && VAR_P (handler_type)) + goto no_caught_exceptions; + unsigned idx = ctx->global->caught_exceptions.length () - 2; + arg = ctx->global->caught_exceptions[idx]; + gcc_assert (VAR_P (arg)); + if (kind == CXA_BEGIN_CATCH) + { + ctx->global->caught_exceptions.pop (); + --ctx->global->uncaught_exceptions; + } + if (handler_type == NULL_TREE) + /* Used for catch (...). Just return void. */ + return void_node; + else if (POINTER_TYPE_P (handler_type)) + { + /* Used for catch of a pointer. */ + if (TREE_CODE (TREE_TYPE (arg)) == ARRAY_TYPE) + arg = build4 (ARRAY_REF, TREE_TYPE (TREE_TYPE (arg)), arg, + size_zero_node, NULL_TREE, NULL_TREE); + arg = cp_convert (handler_type, arg, + ctx->quiet ? tf_none : tf_warning_or_error); + if (arg == error_mark_node) + { + *non_constant_p = true; + return call; + } + } + else + { + /* Used for catch of a non-pointer type. */ + tree exc_type = strip_array_types (TREE_TYPE (arg)); + tree exc_ptr_type = build_pointer_type (exc_type); + arg = build_fold_addr_expr_with_type (arg, exc_ptr_type); + if (CLASS_TYPE_P (handler_type)) + { + tree ptr_type = build_pointer_type (handler_type); + arg = cp_convert (ptr_type, arg, + ctx->quiet ? tf_none + : tf_warning_or_error); + if (arg == error_mark_node) + { + *non_constant_p = true; + return call; + } + } + } + return cxx_eval_constant_expression (ctx, arg, vc_prvalue, + non_constant_p, overflow_p, + jump_target); + } + for (int i = 0; i < nargs; ++i) + { + args[i] = cxx_eval_constant_expression (ctx, CALL_EXPR_ARG (call, i), + vc_prvalue, non_constant_p, + overflow_p, jump_target); + if (*non_constant_p) + return call; + if (*jump_target) + return NULL_TREE; + } + switch (kind) + { + case CXA_ALLOCATE_EXCEPTION: + if (nargs != 1) + goto invalid_nargs; + if (!tree_fits_uhwi_p (args[0])) + { + if (!ctx->quiet) + error_at (loc, "cannot allocate exception: size not constant"); + *non_constant_p = true; + return call; + } + else + { + tree type = build_array_type_nelts (char_type_node, + tree_to_uhwi (args[0])); + tree var = cxa_allocate_exception (loc, ctx, type, size_zero_node); + ctx->global->put_value (var, NULL_TREE); + return fold_convert (ptr_type_node, build_address (var)); + } + case CXA_FREE_EXCEPTION: + if (nargs != 1) + goto invalid_nargs; + arg = cxa_check_throw_arg (args[0], true); + if (arg == NULL_TREE) + { + invalid_ptr: + if (!ctx->quiet) + error_at (loc, "first argument to %qD function not result of " + "%<__cxa_allocate_exception%>", fndecl); + *non_constant_p = true; + return call; + } + DECL_NAME (arg) = heap_deleted_identifier; + ctx->global->destroy_value (arg); + ctx->global->heap_dealloc_count++; + return void_node; + case CXA_THROW: + if (nargs != 3) + goto invalid_nargs; + arg = cxa_check_throw_arg (args[0], false); + if (arg == NULL_TREE) + goto invalid_ptr; + DECL_EXCEPTION_REFCOUNT (arg) + = size_binop (PLUS_EXPR, DECL_EXCEPTION_REFCOUNT (arg), + size_one_node); + ++ctx->global->uncaught_exceptions; + *jump_target = arg; + return void_node; + case CXA_BEGIN_CATCH: + case CXA_GET_EXCEPTION_PTR: + goto invalid_nargs; + case CXA_END_CATCH: + if (nargs != 0) + goto invalid_nargs; + if (ctx->global->caught_exceptions.is_empty ()) + { + no_active_exc: + if (!ctx->quiet) + error_at (loc, "%qD called with no caught exceptions active", + fndecl); + *non_constant_p = true; + return call; + } + else + { + arg = ctx->global->caught_exceptions.pop (); + if (arg == NULL_TREE || !VAR_P (arg)) + goto no_active_exc; + free_except: + DECL_EXCEPTION_REFCOUNT (arg) + = size_binop (MINUS_EXPR, DECL_EXCEPTION_REFCOUNT (arg), + size_one_node); + if (integer_zerop (DECL_EXCEPTION_REFCOUNT (arg))) + { + if (type_build_dtor_call (TREE_TYPE (arg))) + { + tree cleanup + = cxx_maybe_build_cleanup (arg, (ctx->quiet ? tf_none + : tf_warning_or_error)); + if (cleanup == error_mark_node) + *non_constant_p = true; + tree jmp_target = NULL_TREE; + cxx_eval_constant_expression (ctx, cleanup, vc_discard, + non_constant_p, overflow_p, + &jmp_target); + if (throws (&jmp_target)) + *jump_target = jmp_target; + } + DECL_NAME (arg) = heap_deleted_identifier; + ctx->global->destroy_value (arg); + ctx->global->heap_dealloc_count++; + } + } + return void_node; + case CXA_RETHROW: + if (nargs != 0) + goto invalid_nargs; + unsigned idx; + FOR_EACH_VEC_ELT_REVERSE (ctx->global->caught_exceptions, idx, arg) + if (arg == NULL_TREE || !VAR_P (arg)) + --idx; + else + break; + if (arg == NULL_TREE) + { + if (!ctx->quiet) + error_at (loc, "%qD called with no caught exceptions active", + fndecl); + *non_constant_p = true; + return call; + } + DECL_EXCEPTION_REFCOUNT (arg) + = size_binop (PLUS_EXPR, DECL_EXCEPTION_REFCOUNT (arg), size_one_node); + ++ctx->global->uncaught_exceptions; + *jump_target = arg; + return void_node; + case CXA_BAD_CAST: + case CXA_BAD_TYPEID: + case CXA_THROW_BAD_ARRAY_NEW_LENGTH: + if (nargs != 0) + goto invalid_nargs; + else + { + tree name; + switch (kind) + { + case CXA_BAD_CAST: + name = get_identifier ("bad_cast"); + break; + case CXA_BAD_TYPEID: + name = get_identifier ("bad_typeid"); + break; + case CXA_THROW_BAD_ARRAY_NEW_LENGTH: + name = get_identifier ("bad_array_new_length"); + break; + default: + gcc_unreachable (); + } + tree decl = lookup_qualified_name (std_node, name); + if (TREE_CODE (decl) != TYPE_DECL + || !CLASS_TYPE_P (TREE_TYPE (decl)) + || !type_build_ctor_call (TREE_TYPE (decl))) + { + if (!ctx->quiet) + error_at (loc, "%qD called without %<std::%D%> being defined", + fndecl, name); + *non_constant_p = true; + return call; + } + tree type = TREE_TYPE (decl); + tree var = cxa_allocate_exception (loc, ctx, type, size_one_node); + tree ctor + = build_special_member_call (var, complete_ctor_identifier, + NULL, type, LOOKUP_NORMAL, + ctx->quiet ? tf_none + : tf_warning_or_error); + if (ctor == error_mark_node) + { + *non_constant_p = true; + return call; + } + if (TREE_CONSTANT (ctor)) + ctx->global->put_value (var, ctor); + else + { + ctx->global->put_value (var, NULL_TREE); + cxx_eval_constant_expression (ctx, ctor, vc_discard, + non_constant_p, overflow_p, + jump_target); + if (*non_constant_p) + return call; + if (throws (jump_target)) + return NULL_TREE; + } + ++ctx->global->uncaught_exceptions; + *jump_target = var; + } + return void_node; + case STD_UNCAUGHT_EXCEPTIONS: + if (nargs != 0) + goto invalid_nargs; + /* Similarly to __builtin_is_constant_evaluated (), we don't + want to give a definite answer during mce_unknown evaluation, + because that might prevent evaluation later on when some + exceptions might be uncaught. But unlike that, we don't + want to constant fold it even during cp_fold, because at runtime + std::uncaught_exceptions () might still be non-zero. */ + if (ctx->manifestly_const_eval != mce_true) + { + *non_constant_p = true; + return call; + } + return build_int_cst (integer_type_node, + ctx->global->uncaught_exceptions); + case STD_CURRENT_EXCEPTION: + if (nargs != 0) + goto invalid_nargs; + else + { + tree name = get_identifier ("exception_ptr"); + tree decl = lookup_qualified_name (std_node, name); + tree fld; + if (TREE_CODE (decl) != TYPE_DECL + || !CLASS_TYPE_P (TREE_TYPE (decl)) + || !COMPLETE_TYPE_P (TREE_TYPE (decl)) + || !(fld = next_aggregate_field (TYPE_FIELDS (TREE_TYPE (decl)))) + || DECL_ARTIFICIAL (fld) + || TREE_CODE (TREE_TYPE (fld)) != POINTER_TYPE + || next_aggregate_field (DECL_CHAIN (fld)) + || !tree_int_cst_equal (TYPE_SIZE (TREE_TYPE (decl)), + TYPE_SIZE (TREE_TYPE (fld)))) + { + if (!ctx->quiet) + error_at (loc, "%qD called without supportable %qs", + fndecl, "std::exception_ptr"); + *non_constant_p = true; + return call; + } + FOR_EACH_VEC_ELT_REVERSE (ctx->global->caught_exceptions, idx, arg) + if (arg == NULL_TREE || !VAR_P (arg)) + --idx; + else + break; + /* Similarly to __builtin_is_constant_evaluated (), we don't + want to give a definite answer during mce_unknown evaluation, + because that might prevent evaluation later on when some + exceptions might be current. But unlike that, we don't + want to constant fold it to null even during cp_fold, because + at runtime std::current_exception () might still be non-null. */ + if (ctx->manifestly_const_eval != mce_true && arg == NULL_TREE) + { + *non_constant_p = true; + return call; + } + if (arg == NULL_TREE) + arg = build_zero_cst (TREE_TYPE (fld)); + else + { + DECL_EXCEPTION_REFCOUNT (arg) + = size_binop (PLUS_EXPR, DECL_EXCEPTION_REFCOUNT (arg), + size_one_node); + arg = fold_convert (ptr_type_node, build_address (arg)); + } + return build_constructor_single (TREE_TYPE (decl), fld, arg); + } + case STD_RETHROW_EXCEPTION: + if (nargs != 1) + goto invalid_nargs; + if (TYPE_REF_P (TREE_TYPE (args[0]))) + { + arg = args[0]; + STRIP_NOPS (arg); + if (TREE_CODE (arg) == ADDR_EXPR) + { + args[0] + = cxx_eval_constant_expression (ctx, TREE_OPERAND (arg, 0), + vc_prvalue, non_constant_p, + overflow_p, jump_target); + if (*non_constant_p) + return call; + if (*jump_target) + return NULL_TREE; + } + } + if (TREE_CODE (args[0]) != CONSTRUCTOR + || CONSTRUCTOR_NELTS (args[0]) != 1) + { + invalid_std_rethrow: + if (!ctx->quiet) + error_at (loc, "%qD called with unexpected %qs argument", + fndecl, "std::exception_ptr"); + *non_constant_p = true; + return void_node; + } + arg = cxa_check_throw_arg (CONSTRUCTOR_ELT (args[0], 0)->value, false); + if (arg == NULL_TREE) + goto invalid_std_rethrow; + DECL_EXCEPTION_REFCOUNT (arg) + = size_binop (PLUS_EXPR, DECL_EXCEPTION_REFCOUNT (arg), size_one_node); + ++ctx->global->uncaught_exceptions; + *jump_target = arg; + return void_node; + case BUILTIN_EH_PTR_ADJUST_REF: + if (nargs != 2) + goto invalid_nargs; + arg = cxa_check_throw_arg (args[0], false); + if (arg == NULL_TREE) + goto invalid_ptr; + if (integer_onep (args[1])) + DECL_EXCEPTION_REFCOUNT (arg) + = size_binop (PLUS_EXPR, DECL_EXCEPTION_REFCOUNT (arg), + size_one_node); + else if (integer_minus_onep (args[1])) + goto free_except; + else + { + if (!ctx->quiet) + error_at (loc, "%qD called with second argument " + "other than 1 or -1", fndecl); + *non_constant_p = true; + } + return void_node; + default: + gcc_unreachable (); + } +} + /* Attempt to evaluate T which represents a call to a builtin function. We assume here that all builtin functions evaluate to scalar types represented by _CST nodes. */ @@ -1557,7 +2265,8 @@ static tree find_heap_var_refs (tree *, int *, void *); static tree cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun, value_cat lval, - bool *non_constant_p, bool *overflow_p) + bool *non_constant_p, bool *overflow_p, + tree *jump_target) { const int nargs = call_expr_nargs (t); tree *args = (tree *) alloca (nargs * sizeof (tree)); @@ -1603,6 +2312,12 @@ cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun, return fold_builtin_source_location (t); } + if (fndecl_built_in_p (fun, CP_BUILT_IN_EH_PTR_ADJUST_REF, + BUILT_IN_FRONTEND)) + return cxx_eval_cxa_builtin_fn (ctx, t, BUILTIN_EH_PTR_ADJUST_REF, + fun, non_constant_p, overflow_p, + jump_target); + int strops = 0; int strret = 0; if (fndecl_built_in_p (fun, BUILT_IN_NORMAL)) @@ -1677,8 +2392,14 @@ cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun, || potential_constant_expression (arg)) { bool dummy1 = false, dummy2 = false; + tree jmp_target = NULL_TREE; arg = cxx_eval_constant_expression (&new_ctx, arg, vc_prvalue, - &dummy1, &dummy2); + &dummy1, &dummy2, &jmp_target); + if (jmp_target) + { + *jump_target = jmp_target; + return NULL_TREE; + } } if (bi_const_p) @@ -1767,7 +2488,8 @@ cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun, } return cxx_eval_constant_expression (&new_ctx, new_call, lval, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); } /* TEMP is the constant value of a temporary object of type TYPE. Adjust @@ -1882,7 +2604,8 @@ addr_of_non_const_var (tree *tp, int *walk_subtrees, void *data) static tree cxx_bind_parameters_in_call (const constexpr_ctx *ctx, tree t, tree fun, tree orig_fun, bool *non_constant_p, - bool *overflow_p, bool *non_constant_args) + bool *overflow_p, bool *non_constant_args, + tree *jump_target) { int nargs = call_expr_nargs (t); tree parms = DECL_ARGUMENTS (fun); @@ -1958,14 +2681,16 @@ cxx_bind_parameters_in_call (const constexpr_ctx *ctx, tree t, tree fun, /* Undo convert_for_arg_passing work here. */ x = convert_from_reference (x); arg = cxx_eval_constant_expression (ctx, x, vc_glvalue, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); } else /* Normally we would strip a TARGET_EXPR in an initialization context such as this, but here we do the elision differently: we keep the TARGET_EXPR, and use its CONSTRUCTOR as the value of the parm. */ arg = cxx_eval_constant_expression (ctx, x, vc_prvalue, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); /* Check we aren't dereferencing a null pointer when calling a non-static member function, which is undefined behaviour. */ if (i == 0 && DECL_OBJECT_MEMBER_FUNCTION_P (fun) @@ -1983,6 +2708,8 @@ cxx_bind_parameters_in_call (const constexpr_ctx *ctx, tree t, tree fun, /* Don't VERIFY_CONSTANT here. */ if (*non_constant_p && ctx->quiet) break; + if (*jump_target) + break; /* Just discard ellipsis args after checking their constantitude. */ if (!parms) continue; @@ -2094,9 +2821,10 @@ fold_operand (tree e, const constexpr_ctx *ctx) if (ctx) { bool new_non_constant_p = false, new_overflow_p = false; + tree jmp_target = NULL_TREE; e = cxx_eval_constant_expression (ctx, e, vc_prvalue, &new_non_constant_p, - &new_overflow_p); + &new_overflow_p, &jmp_target); } else e = fold_non_dependent_expr (e, tf_none, /*manifestly_const_eval=*/true); @@ -2183,7 +2911,7 @@ cxx_eval_assert (const constexpr_ctx *ctx, tree arg, const char *msg, if (*non_constant_p) return true; - tree eval; + tree eval, jmp_target = NULL_TREE; if (!evaluated) { if (!potential_rvalue_constant_expression (arg)) @@ -2196,12 +2924,15 @@ cxx_eval_assert (const constexpr_ctx *ctx, tree arg, const char *msg, modifiable_tracker ms (new_ctx.global); eval = cxx_eval_constant_expression (&new_ctx, arg, vc_prvalue, &new_non_constant_p, - &new_overflow_p); + &new_overflow_p, &jmp_target); } else eval = cxx_eval_constant_expression (ctx, arg, vc_prvalue, non_constant_p, - overflow_p); + overflow_p, &jmp_target); + if (jmp_target) + return true; + if (!*non_constant_p && integer_zerop (eval)) { if (!ctx->quiet) @@ -2233,7 +2964,8 @@ cxx_eval_assert (const constexpr_ctx *ctx, tree arg, const char *msg, static tree cxx_eval_internal_function (const constexpr_ctx *ctx, tree t, value_cat lval, - bool *non_constant_p, bool *overflow_p) + bool *non_constant_p, bool *overflow_p, + tree *jump_target) { enum tree_code opcode = ERROR_MARK; @@ -2266,13 +2998,15 @@ cxx_eval_internal_function (const constexpr_ctx *ctx, tree t, case IFN_LAUNDER: return cxx_eval_constant_expression (ctx, CALL_EXPR_ARG (t, 0), vc_prvalue, non_constant_p, - overflow_p); + overflow_p, jump_target); case IFN_VEC_CONVERT: { tree arg = cxx_eval_constant_expression (ctx, CALL_EXPR_ARG (t, 0), vc_prvalue, non_constant_p, - overflow_p); + overflow_p, jump_target); + if (*jump_target) + return NULL_TREE; if (TREE_CODE (arg) == VECTOR_CST) if (tree r = fold_const_call (CFN_VEC_CONVERT, TREE_TYPE (t), arg)) return r; @@ -2290,10 +3024,13 @@ cxx_eval_internal_function (const constexpr_ctx *ctx, tree t, /* Evaluate constant arguments using OPCODE and return a complex number containing the result and the overflow bit. */ tree arg0 = cxx_eval_constant_expression (ctx, CALL_EXPR_ARG (t, 0), lval, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); tree arg1 = cxx_eval_constant_expression (ctx, CALL_EXPR_ARG (t, 1), lval, - non_constant_p, overflow_p); - + non_constant_p, overflow_p, + jump_target); + if (*jump_target) + return NULL_TREE; if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST) { location_t loc = cp_expr_loc_or_input_loc (t); @@ -2566,7 +3303,8 @@ get_component_with_type (tree path, tree type, tree stop) static tree cxx_eval_dynamic_cast_fn (const constexpr_ctx *ctx, tree call, - bool *non_constant_p, bool *overflow_p) + bool *non_constant_p, bool *overflow_p, + tree *jump_target) { /* T will be something like __dynamic_cast ((B*) b, &_ZTI1B, &_ZTI1D, 8) @@ -2585,19 +3323,26 @@ cxx_eval_dynamic_cast_fn (const constexpr_ctx *ctx, tree call, /* TYPE can only be either T* or T&. We can't know which of these it is by looking at TYPE, but OBJ will be "(T*) x" in the first case, - and something like "(T*)(T&)(T*) x" in the second case. */ - bool reference_p = false; + and something like "(T*)(T&)(T*) x" in the second case. + This is true for the reference cases in C++ < 26 or when exceptions + aren't enabled, in that case we should diagnose errors. For C++26 + with exceptions we should silently evaluate to null pointer and + let the callers call __cxa_bad_cast () later to throw an exception. */ + bool fail_for_non_constant_p = false; while (CONVERT_EXPR_P (obj) || TREE_CODE (obj) == SAVE_EXPR) { - reference_p |= TYPE_REF_P (TREE_TYPE (obj)); + if (cxx_dialect < cxx26 || !flag_exceptions) + fail_for_non_constant_p |= TYPE_REF_P (TREE_TYPE (obj)); obj = TREE_OPERAND (obj, 0); } /* Evaluate the object so that we know its dynamic type. */ obj = cxx_eval_constant_expression (ctx, obj, vc_prvalue, non_constant_p, - overflow_p); + overflow_p, jump_target); if (*non_constant_p) return call; + if (*jump_target) + return NULL_TREE; /* For dynamic_cast from classes with virtual bases we can get something like (virt_base *)(&d + 16) as OBJ. Try to convert that into @@ -2609,7 +3354,7 @@ cxx_eval_dynamic_cast_fn (const constexpr_ctx *ctx, tree call, if (TREE_CODE (objo) == POINTER_PLUS_EXPR) { objo = cxx_fold_indirect_ref (ctx, loc, TREE_TYPE (TREE_TYPE (obj)), - obj); + obj, NULL, jump_target); if (objo) obj = build_fold_addr_expr (objo); } @@ -2625,7 +3370,7 @@ cxx_eval_dynamic_cast_fn (const constexpr_ctx *ctx, tree call, ? TREE_OPERAND (obj, 1) : obj)) if (TREE_CODE (t) != FIELD_DECL || !DECL_FIELD_IS_BASE (t)) { - if (reference_p) + if (fail_for_non_constant_p) { if (!ctx->quiet) { @@ -2647,9 +3392,12 @@ cxx_eval_dynamic_cast_fn (const constexpr_ctx *ctx, tree call, constructor or destructor's class. */ tree vtable = build_vfield_ref (obj, objtype); vtable = cxx_eval_constant_expression (ctx, vtable, vc_prvalue, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); if (*non_constant_p) return call; + if (*jump_target) + return NULL_TREE; /* With -fsanitize=vptr, we initialize all vtable pointers to null, so it's possible that we got a null pointer now. */ if (integer_zerop (vtable)) @@ -2681,7 +3429,7 @@ cxx_eval_dynamic_cast_fn (const constexpr_ctx *ctx, tree call, /* If not accessible, give an error. */ if (t == error_mark_node) { - if (reference_p) + if (fail_for_non_constant_p) { if (!ctx->quiet) { @@ -2714,7 +3462,7 @@ cxx_eval_dynamic_cast_fn (const constexpr_ctx *ctx, tree call, obj = get_component_with_type (obj, mdtype, NULL_TREE); if (obj == error_mark_node) { - if (reference_p) + if (fail_for_non_constant_p) { if (!ctx->quiet) { @@ -2736,7 +3484,7 @@ cxx_eval_dynamic_cast_fn (const constexpr_ctx *ctx, tree call, tree binfo = lookup_base (mdtype, type, ba_check, &b_kind, tf_none); if (!binfo || binfo == error_mark_node) { - if (reference_p) + if (fail_for_non_constant_p) { if (!ctx->quiet) { @@ -2832,7 +3580,7 @@ replace_decl (tree *tp, tree decl, tree replacement) static tree cxx_eval_thunk_call (const constexpr_ctx *ctx, tree t, tree thunk_fndecl, value_cat lval, - bool *non_constant_p, bool *overflow_p) + bool *non_constant_p, bool *overflow_p, tree *jump_target) { tree function = THUNK_TARGET (thunk_fndecl); @@ -2875,7 +3623,8 @@ cxx_eval_thunk_call (const constexpr_ctx *ctx, tree t, tree thunk_fndecl, new_call, offset); return cxx_eval_constant_expression (ctx, new_call, lval, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); } /* If OBJECT is of const class type, evaluate it to a CONSTRUCTOR and set @@ -2885,7 +3634,7 @@ cxx_eval_thunk_call (const constexpr_ctx *ctx, tree t, tree thunk_fndecl, static void cxx_set_object_constness (const constexpr_ctx *ctx, tree object, bool readonly_p, bool *non_constant_p, - bool *overflow_p) + bool *overflow_p, tree *jump_target) { if (CLASS_TYPE_P (TREE_TYPE (object)) && CP_TYPE_CONST_P (TREE_TYPE (object))) @@ -2893,8 +3642,11 @@ cxx_set_object_constness (const constexpr_ctx *ctx, tree object, /* Subobjects might not be stored in ctx->global->values but we can get its CONSTRUCTOR by evaluating *this. */ tree e = cxx_eval_constant_expression (ctx, object, vc_prvalue, - non_constant_p, overflow_p); - if (TREE_CODE (e) == CONSTRUCTOR && !*non_constant_p) + non_constant_p, overflow_p, + jump_target); + if (!*non_constant_p + && !throws (jump_target) + && TREE_CODE (e) == CONSTRUCTOR) TREE_READONLY (e) = readonly_p; } } @@ -2906,20 +3658,25 @@ cxx_set_object_constness (const constexpr_ctx *ctx, tree object, static tree cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, value_cat lval, - bool *non_constant_p, bool *overflow_p) + bool *non_constant_p, bool *overflow_p, + tree *jump_target) { location_t loc = cp_expr_loc_or_input_loc (t); tree fun = get_function_named_in_call (t); if (fun == NULL_TREE) return cxx_eval_internal_function (ctx, t, lval, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); if (TREE_CODE (fun) != FUNCTION_DECL) { /* Might be a constexpr function pointer. */ fun = cxx_eval_constant_expression (ctx, fun, vc_prvalue, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); + if (*jump_target) + return NULL_TREE; STRIP_NOPS (fun); if (TREE_CODE (fun) == ADDR_EXPR) fun = TREE_OPERAND (fun, 0); @@ -2971,9 +3728,12 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, if (fndecl_built_in_p (fun)) return cxx_eval_builtin_function_call (ctx, t, fun, - lval, non_constant_p, overflow_p); + lval, non_constant_p, overflow_p, + jump_target); if (DECL_THUNK_P (fun)) - return cxx_eval_thunk_call (ctx, t, fun, lval, non_constant_p, overflow_p); + return cxx_eval_thunk_call (ctx, t, fun, lval, non_constant_p, overflow_p, + jump_target); + bool non_constexpr_call = false; if (!maybe_constexpr_fn (fun)) { if (TREE_CODE (t) == CALL_EXPR @@ -2988,7 +3748,10 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, { tree arg = CALL_EXPR_ARG (t, i); arg = cxx_eval_constant_expression (ctx, arg, vc_prvalue, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); + if (*jump_target) + return NULL_TREE; /* Deleting a non-constant pointer has a better error message below. */ if (new_op_p || i != 0) @@ -3103,7 +3866,10 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, { tree arg = CALL_EXPR_ARG (t, i); arg = cxx_eval_constant_expression (ctx, arg, vc_prvalue, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); + if (*jump_target) + return NULL_TREE; if (i == 1) arg1 = arg; else @@ -3113,16 +3879,31 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, return arg1; } else if (cxx_dynamic_cast_fn_p (fun)) - return cxx_eval_dynamic_cast_fn (ctx, t, non_constant_p, overflow_p); + return cxx_eval_dynamic_cast_fn (ctx, t, non_constant_p, overflow_p, + jump_target); + else if (enum cxa_builtin kind = cxx_cxa_builtin_fn_p (fun)) + return cxx_eval_cxa_builtin_fn (ctx, t, kind, fun, + non_constant_p, overflow_p, + jump_target); - if (!ctx->quiet) + /* Calls to non-constexpr functions can be diagnosed right away + before C++26, though in C++26 evaluation of the arguments might + throw and if caught it could be still constant expression. + So for C++26 this is diagnosed only after + cxx_bind_parameters_in_call. */ + if (cxx_dialect >= cxx26) + non_constexpr_call = true; + else { - if (!lambda_static_thunk_p (fun)) - error_at (loc, "call to non-%<constexpr%> function %qD", fun); - explain_invalid_constexpr_fn (fun); + if (!ctx->quiet) + { + if (!lambda_static_thunk_p (fun)) + error_at (loc, "call to non-%<constexpr%> function %qD", fun); + explain_invalid_constexpr_fn (fun); + } + *non_constant_p = true; + return t; } - *non_constant_p = true; - return t; } constexpr_ctx new_ctx = *ctx; @@ -3158,7 +3939,8 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, constexpr_call new_call; new_call.bindings = cxx_bind_parameters_in_call (ctx, t, fun, orig_fun, non_constant_p, - overflow_p, &non_constant_args); + overflow_p, &non_constant_args, + jump_target); /* We build up the bindings list before we know whether we already have this call cached. If we don't end up saving these bindings, ggc_free them when @@ -3172,8 +3954,21 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, void preserve () { bindings = NULL; } } fb (new_call.bindings); + if (*jump_target) + return NULL_TREE; if (*non_constant_p) return t; + if (non_constexpr_call) + { + if (!ctx->quiet) + { + if (!lambda_static_thunk_p (fun)) + error_at (loc, "call to non-%<constexpr%> function %qD", fun); + explain_invalid_constexpr_fn (fun); + } + *non_constant_p = true; + return t; + } /* We can't defer instantiating the function any longer. */ if (!DECL_INITIAL (fun) @@ -3246,7 +4041,9 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, new_obj = TREE_VEC_ELT (new_call.bindings, 0); bool empty_base = false; new_obj = cxx_fold_indirect_ref (ctx, loc, DECL_CONTEXT (fun), new_obj, - &empty_base); + &empty_base, jump_target); + if (*jump_target) + return NULL_TREE; /* If we're initializing an empty class, don't set constness, because cxx_fold_indirect_ref will return the wrong object to set constness of. */ @@ -3395,7 +4192,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, semantics are no longer in effect; see [class.dtor]p5. */ if (new_obj && DECL_DESTRUCTOR_P (fun)) cxx_set_object_constness (ctx, new_obj, /*readonly_p=*/false, - non_constant_p, overflow_p); + non_constant_p, overflow_p, jump_target); /* If this is a constructor, we are beginning the lifetime of the object we are initializing. */ @@ -3409,16 +4206,25 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, build_constructor (TREE_TYPE (new_obj), NULL)); cxx_eval_constant_expression (ctx, activate, - lval, non_constant_p, overflow_p); + lval, non_constant_p, overflow_p, + jump_target); ggc_free (activate); + if (*jump_target) + return NULL_TREE; } - tree jump_target = NULL_TREE; + tree jmp_target = NULL_TREE; cxx_eval_constant_expression (&call_ctx, body, vc_discard, non_constant_p, overflow_p, - &jump_target); + &jmp_target); - if (DECL_CONSTRUCTOR_P (fun)) + if (!*non_constant_p && throws (&jmp_target)) + { + result = NULL_TREE; + cacheable = false; + *jump_target = jmp_target; + } + else if (DECL_CONSTRUCTOR_P (fun)) /* This can be null for a subobject constructor call, in which case what we care about is the initialization side-effects rather than the value. We could get at the @@ -3446,7 +4252,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, marking the CONSTRUCTOR TREE_READONLY. */ if (new_obj && DECL_CONSTRUCTOR_P (fun)) cxx_set_object_constness (ctx, new_obj, /*readonly_p=*/true, - non_constant_p, overflow_p); + non_constant_p, overflow_p, jump_target); /* Remove the parms/result from the values map. */ destroy_value_checked (ctx, res, non_constant_p); @@ -3506,7 +4312,13 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, cacheable = false; result = cxx_eval_constant_expression (ctx, result, lval, non_constant_p, - overflow_p); + overflow_p, + jump_target); + if (*jump_target) + { + cacheable = false; + result = NULL_TREE; + } } } @@ -3864,12 +4676,16 @@ cxx_eval_check_shift_p (location_t loc, const constexpr_ctx *ctx, static tree cxx_eval_unary_expression (const constexpr_ctx *ctx, tree t, bool /*lval*/, - bool *non_constant_p, bool *overflow_p) + bool *non_constant_p, bool *overflow_p, + tree *jump_target) { tree r; tree orig_arg = TREE_OPERAND (t, 0); tree arg = cxx_eval_constant_expression (ctx, orig_arg, vc_prvalue, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); + if (*jump_target) + return NULL_TREE; VERIFY_CONSTANT (arg); location_t loc = EXPR_LOCATION (t); enum tree_code code = TREE_CODE (t); @@ -3893,7 +4709,7 @@ cxx_eval_unary_expression (const constexpr_ctx *ctx, tree t, static tree cxx_fold_pointer_plus_expression (const constexpr_ctx *ctx, tree t, tree lhs, tree rhs, bool *non_constant_p, - bool *overflow_p) + bool *overflow_p, tree *jump_target) { STRIP_NOPS (lhs); if (TREE_CODE (lhs) != ADDR_EXPR) @@ -3915,9 +4731,12 @@ cxx_fold_pointer_plus_expression (const constexpr_ctx *ctx, tree t, t = fold_convert_loc (loc, ssizetype, TREE_OPERAND (lhs, 1)); tree nelts = array_type_nelts_top (TREE_TYPE (TREE_OPERAND (lhs, 0))); nelts = cxx_eval_constant_expression (ctx, nelts, vc_prvalue, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); if (*non_constant_p) return NULL_TREE; + if (*jump_target) + return NULL_TREE; /* Don't fold an out-of-bound access. */ if (!tree_int_cst_le (t, nelts)) return NULL_TREE; @@ -3937,7 +4756,8 @@ cxx_fold_pointer_plus_expression (const constexpr_ctx *ctx, tree t, t = cp_build_addr_expr (t, tf_warning_or_error); t = cp_fold_convert (orig_type, t); return cxx_eval_constant_expression (ctx, t, vc_prvalue, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); } return NULL_TREE; @@ -3981,22 +4801,29 @@ cxx_maybe_fold_addr_pointer_plus (tree t) static tree cxx_eval_binary_expression (const constexpr_ctx *ctx, tree t, value_cat lval, - bool *non_constant_p, bool *overflow_p) + bool *non_constant_p, bool *overflow_p, + tree *jump_target) { tree r = NULL_TREE; tree orig_lhs = TREE_OPERAND (t, 0); tree orig_rhs = TREE_OPERAND (t, 1); tree lhs, rhs; lhs = cxx_eval_constant_expression (ctx, orig_lhs, vc_prvalue, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); /* Don't VERIFY_CONSTANT here, it's unnecessary and will break pointer subtraction. */ if (*non_constant_p) return t; + if (*jump_target) + return NULL_TREE; rhs = cxx_eval_constant_expression (ctx, orig_rhs, vc_prvalue, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); if (*non_constant_p) return t; + if (*jump_target) + return NULL_TREE; location_t loc = EXPR_LOCATION (t); enum tree_code code = TREE_CODE (t); @@ -4052,13 +4879,17 @@ cxx_eval_binary_expression (const constexpr_ctx *ctx, tree t, return t; } else if (code == POINTER_PLUS_EXPR) - r = cxx_fold_pointer_plus_expression (ctx, t, lhs, rhs, non_constant_p, - overflow_p); + { + r = cxx_fold_pointer_plus_expression (ctx, t, lhs, rhs, non_constant_p, + overflow_p, jump_target); + if (*jump_target) + return NULL_TREE; + } else if (code == SPACESHIP_EXPR) { r = genericize_spaceship (loc, type, lhs, rhs); return cxx_eval_constant_expression (ctx, r, lval, non_constant_p, - overflow_p); + overflow_p, jump_target); } if (r == NULL_TREE) @@ -4117,7 +4948,10 @@ cxx_eval_conditional_expression (const constexpr_ctx *ctx, tree t, { tree val = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0), vc_prvalue, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); + if (*jump_target) + return NULL_TREE; VERIFY_CONSTANT (val); if (TREE_CODE (t) == IF_STMT && IF_STMT_CONSTEVAL_P (t)) { @@ -4178,19 +5012,29 @@ cxx_eval_conditional_expression (const constexpr_ctx *ctx, tree t, static tree cxx_eval_vector_conditional_expression (const constexpr_ctx *ctx, tree t, - bool *non_constant_p, bool *overflow_p) + bool *non_constant_p, bool *overflow_p, + tree *jump_target) { tree arg1 = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0), vc_prvalue, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); + if (*jump_target) + return NULL_TREE; VERIFY_CONSTANT (arg1); tree arg2 = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 1), vc_prvalue, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); + if (*jump_target) + return NULL_TREE; VERIFY_CONSTANT (arg2); tree arg3 = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 2), vc_prvalue, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); + if (*jump_target) + return NULL_TREE; VERIFY_CONSTANT (arg3); location_t loc = EXPR_LOCATION (t); tree type = TREE_TYPE (t); @@ -4578,7 +5422,8 @@ diag_array_subscript (location_t loc, const constexpr_ctx *ctx, tree array, tree static tree get_array_or_vector_nelts (const constexpr_ctx *ctx, tree type, - bool *non_constant_p, bool *overflow_p) + bool *non_constant_p, bool *overflow_p, + tree *jump_target) { tree nelts; if (TREE_CODE (type) == ARRAY_TYPE) @@ -4595,7 +5440,8 @@ get_array_or_vector_nelts (const constexpr_ctx *ctx, tree type, /* For VLAs, the number of elements won't be an integer constant. */ nelts = cxx_eval_constant_expression (ctx, nelts, vc_prvalue, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); return nelts; } @@ -4626,13 +5472,17 @@ extract_string_elt (tree string, unsigned chars_per_elt, unsigned index) static tree eval_and_check_array_index (const constexpr_ctx *ctx, tree t, bool allow_one_past, - bool *non_constant_p, bool *overflow_p) + bool *non_constant_p, bool *overflow_p, + tree *jump_target) { location_t loc = cp_expr_loc_or_input_loc (t); tree ary = TREE_OPERAND (t, 0); t = TREE_OPERAND (t, 1); tree index = cxx_eval_constant_expression (ctx, t, vc_prvalue, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); + if (*jump_target) + return NULL_TREE; VERIFY_CONSTANT (index); if (!tree_fits_shwi_p (index) @@ -4644,7 +5494,9 @@ eval_and_check_array_index (const constexpr_ctx *ctx, } tree nelts = get_array_or_vector_nelts (ctx, TREE_TYPE (ary), non_constant_p, - overflow_p); + overflow_p, jump_target); + if (*jump_target) + return NULL_TREE; VERIFY_CONSTANT (nelts); if (allow_one_past ? !tree_int_cst_le (index, nelts) @@ -4664,14 +5516,18 @@ eval_and_check_array_index (const constexpr_ctx *ctx, static tree cxx_eval_array_reference (const constexpr_ctx *ctx, tree t, value_cat lval, - bool *non_constant_p, bool *overflow_p) + bool *non_constant_p, bool *overflow_p, + tree *jump_target) { tree oldary = TREE_OPERAND (t, 0); tree ary = cxx_eval_constant_expression (ctx, oldary, lval, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); if (*non_constant_p) return t; + if (*jump_target) + return NULL_TREE; if (!lval && TREE_CODE (ary) == VIEW_CONVERT_EXPR && VECTOR_TYPE_P (TREE_TYPE (TREE_OPERAND (ary, 0))) @@ -4681,9 +5537,12 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree t, tree oldidx = TREE_OPERAND (t, 1); tree index = eval_and_check_array_index (ctx, t, lval, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); if (*non_constant_p) return t; + if (*jump_target) + return NULL_TREE; if (lval && ary == oldary && index == oldidx) return t; @@ -4801,7 +5660,7 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree t, ctx = &new_ctx; } t = cxx_eval_constant_expression (ctx, val, lval, non_constant_p, - overflow_p); + overflow_p, jump_target); if (new_ctor && t != ctx->ctor) free_constructor (ctx->ctor); return t; @@ -4813,7 +5672,8 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree t, static tree cxx_eval_component_reference (const constexpr_ctx *ctx, tree t, value_cat lval, - bool *non_constant_p, bool *overflow_p) + bool *non_constant_p, bool *overflow_p, + tree *jump_target) { unsigned HOST_WIDE_INT i; tree field; @@ -4822,9 +5682,12 @@ cxx_eval_component_reference (const constexpr_ctx *ctx, tree t, tree orig_whole = TREE_OPERAND (t, 0); tree whole = cxx_eval_constant_expression (ctx, orig_whole, lval, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); if (*non_constant_p) return t; + if (*jump_target) + return NULL_TREE; if (INDIRECT_REF_P (whole) && integer_zerop (TREE_OPERAND (whole, 0))) { @@ -4933,7 +5796,8 @@ cxx_eval_component_reference (const constexpr_ctx *ctx, tree t, value = build_value_init (TREE_TYPE (t), tf_warning_or_error); return cxx_eval_constant_expression (ctx, value, lval, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); } /* Subroutine of cxx_eval_constant_expression. @@ -4943,7 +5807,8 @@ cxx_eval_component_reference (const constexpr_ctx *ctx, tree t, static tree cxx_eval_bit_field_ref (const constexpr_ctx *ctx, tree t, value_cat lval, - bool *non_constant_p, bool *overflow_p) + bool *non_constant_p, bool *overflow_p, + tree *jump_target) { tree orig_whole = TREE_OPERAND (t, 0); tree retval, fldval, utype, mask; @@ -4951,10 +5816,13 @@ cxx_eval_bit_field_ref (const constexpr_ctx *ctx, tree t, HOST_WIDE_INT istart, isize; tree whole = cxx_eval_constant_expression (ctx, orig_whole, lval, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); tree start, field, value; unsigned HOST_WIDE_INT i; + if (*jump_target) + return NULL_TREE; if (whole == orig_whole) return t; /* Don't VERIFY_CONSTANT here; we only want to check that we got a @@ -5235,7 +6103,7 @@ clear_uchar_or_std_byte_in_mask (location_t loc, tree t, unsigned char *mask) static tree cxx_eval_bit_cast (const constexpr_ctx *ctx, tree t, bool *non_constant_p, - bool *overflow_p) + bool *overflow_p, tree *jump_target) { if (check_bit_cast_type (ctx, EXPR_LOCATION (t), TREE_TYPE (t), TREE_TYPE (t)) @@ -5249,9 +6117,12 @@ cxx_eval_bit_cast (const constexpr_ctx *ctx, tree t, bool *non_constant_p, } tree op = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0), vc_prvalue, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); if (*non_constant_p) return t; + if (*jump_target) + return NULL_TREE; location_t loc = EXPR_LOCATION (t); if (BITS_PER_UNIT != 8 || CHAR_BIT != 8) @@ -5329,8 +6200,9 @@ cxx_eval_bit_cast (const constexpr_ctx *ctx, tree t, bool *non_constant_p, if (CHECKING_P) { tree e = cxx_eval_bare_aggregate (ctx, r, vc_prvalue, - non_constant_p, overflow_p); - gcc_checking_assert (e == r); + non_constant_p, overflow_p, + jump_target); + gcc_checking_assert (e == r && !*jump_target); r = e; } } @@ -5371,19 +6243,24 @@ cxx_eval_bit_cast (const constexpr_ctx *ctx, tree t, bool *non_constant_p, static tree cxx_eval_logical_expression (const constexpr_ctx *ctx, tree t, tree bailout_value, tree continue_value, - bool *non_constant_p, bool *overflow_p) + bool *non_constant_p, bool *overflow_p, + tree *jump_target) { tree r; tree lhs = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0), vc_prvalue, non_constant_p, - overflow_p); + overflow_p, jump_target); + if (*jump_target) + return NULL_TREE; VERIFY_CONSTANT (lhs); if (tree_int_cst_equal (lhs, bailout_value)) return lhs; gcc_assert (tree_int_cst_equal (lhs, continue_value)); r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 1), vc_prvalue, non_constant_p, - overflow_p); + overflow_p, jump_target); + if (*jump_target) + return NULL_TREE; VERIFY_CONSTANT (r); return r; } @@ -5540,7 +6417,8 @@ verify_ctor_sanity (const constexpr_ctx *ctx, tree type) static tree cxx_eval_bare_aggregate (const constexpr_ctx *ctx, tree t, value_cat lval, - bool *non_constant_p, bool *overflow_p) + bool *non_constant_p, bool *overflow_p, + tree *jump_target) { vec<constructor_elt, va_gc> *v = CONSTRUCTOR_ELTS (t); bool changed = false; @@ -5593,7 +6471,10 @@ cxx_eval_bare_aggregate (const constexpr_ctx *ctx, tree t, get_or_insert_ctor_field (ctx->ctor, index); tree elt = cxx_eval_constant_expression (&new_ctx, value, lval, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); + if (*jump_target) + return NULL_TREE; /* Don't VERIFY_CONSTANT here. */ if (ctx->quiet && *non_constant_p) break; @@ -5683,7 +6564,8 @@ cxx_eval_bare_aggregate (const constexpr_ctx *ctx, tree t, static tree cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree atype, tree init, bool value_init, value_cat lval, - bool *non_constant_p, bool *overflow_p) + bool *non_constant_p, bool *overflow_p, + tree *jump_target) { tree elttype = TREE_TYPE (atype); verify_ctor_sanity (ctx, atype); @@ -5694,7 +6576,7 @@ cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree atype, tree init, if (init && TREE_CODE (init) == CONSTRUCTOR) return cxx_eval_bare_aggregate (ctx, init, lval, - non_constant_p, overflow_p); + non_constant_p, overflow_p, jump_target); /* For the default constructor, build up a call to the default constructor of the element type. We only need to handle class types @@ -5731,7 +6613,9 @@ cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree atype, tree init, } tree nelts = get_array_or_vector_nelts (ctx, atype, non_constant_p, - overflow_p); + overflow_p, jump_target); + if (*jump_target) + return NULL_TREE; unsigned HOST_WIDE_INT max = tree_to_uhwi (nelts); for (i = 0; i < max; ++i) { @@ -5757,9 +6641,9 @@ cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree atype, tree init, } else eltinit = cp_build_array_ref (input_location, init, idx, complain); - eltinit = cxx_eval_vec_init_1 (&new_ctx, elttype, eltinit, value_init, - lval, - non_constant_p, overflow_p); + eltinit = cxx_eval_vec_init_1 (&new_ctx, elttype, eltinit, + value_init, lval, non_constant_p, + overflow_p, jump_target); } else if (pre_init) { @@ -5773,7 +6657,8 @@ cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree atype, tree init, /* Clarify what object is being initialized (118285). */ eltinit = build2 (INIT_EXPR, elttype, new_ctx.object, eltinit); eltinit = cxx_eval_constant_expression (&new_ctx, eltinit, lval, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); reuse = i == 0; } else @@ -5789,8 +6674,11 @@ cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree atype, tree init, /* Clarify what object is being initialized (118285). */ eltinit = build2 (INIT_EXPR, elttype, new_ctx.object, eltinit); eltinit = cxx_eval_constant_expression (&new_ctx, eltinit, lval, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); } + if (*jump_target) + return NULL_TREE; if (*non_constant_p) break; if (no_slot) @@ -5840,7 +6728,7 @@ cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree atype, tree init, static tree cxx_eval_vec_init (const constexpr_ctx *ctx, tree t, value_cat lval, - bool *non_constant_p, bool *overflow_p) + bool *non_constant_p, bool *overflow_p, tree *jump_target) { tree atype = TREE_TYPE (t); tree init = VEC_INIT_EXPR_INIT (t); @@ -5872,10 +6760,10 @@ cxx_eval_vec_init (const constexpr_ctx *ctx, tree t, } init = expand_vec_init_expr (ctx->object, t, complain); return cxx_eval_constant_expression (ctx, init, lval, non_constant_p, - overflow_p); + overflow_p, jump_target); } tree r = cxx_eval_vec_init_1 (ctx, atype, init, value_init, - lval, non_constant_p, overflow_p); + lval, non_constant_p, overflow_p, jump_target); if (*non_constant_p) return t; else @@ -5904,14 +6792,16 @@ same_type_ignoring_tlq_and_bounds_p (tree type1, tree type2) otherwise return NULL_TREE. */ static tree -cxx_union_active_member (const constexpr_ctx *ctx, tree t) +cxx_union_active_member (const constexpr_ctx *ctx, tree t, tree *jump_target) { constexpr_ctx new_ctx = *ctx; new_ctx.quiet = true; bool non_constant_p = false, overflow_p = false; tree ctor = cxx_eval_constant_expression (&new_ctx, t, vc_prvalue, &non_constant_p, - &overflow_p); + &overflow_p, jump_target); + if (*jump_target) + return NULL_TREE; if (TREE_CODE (ctor) == CONSTRUCTOR && CONSTRUCTOR_NELTS (ctor) == 1 && CONSTRUCTOR_ELT (ctor, 0)->index @@ -5924,7 +6814,8 @@ cxx_union_active_member (const constexpr_ctx *ctx, tree t) static tree cxx_fold_indirect_ref_1 (const constexpr_ctx *ctx, location_t loc, tree type, - tree op, unsigned HOST_WIDE_INT off, bool *empty_base) + tree op, unsigned HOST_WIDE_INT off, bool *empty_base, + tree *jump_target) { tree optype = TREE_TYPE (op); unsigned HOST_WIDE_INT const_nunits; @@ -5941,7 +6832,8 @@ cxx_fold_indirect_ref_1 (const constexpr_ctx *ctx, location_t loc, tree type, than pointer type. */ if (tree ret = cxx_fold_indirect_ref_1 (ctx, loc, strip_array_types (optype), - op, off, empty_base)) + op, off, empty_base, + jump_target)) return fold_convert (type, ret); } else if (TREE_CODE (optype) == COMPLEX_TYPE @@ -5987,7 +6879,7 @@ cxx_fold_indirect_ref_1 (const constexpr_ctx *ctx, location_t loc, tree type, op = build4_loc (loc, ARRAY_REF, TREE_TYPE (optype), op, index, NULL_TREE, NULL_TREE); return cxx_fold_indirect_ref_1 (ctx, loc, type, op, rem, - empty_base); + empty_base, jump_target); } } /* ((foo *)&struct_with_foo_field)[x] => COMPONENT_REF */ @@ -5996,7 +6888,7 @@ cxx_fold_indirect_ref_1 (const constexpr_ctx *ctx, location_t loc, tree type, { if (TREE_CODE (optype) == UNION_TYPE) /* For unions prefer the currently active member. */ - if (tree field = cxx_union_active_member (ctx, op)) + if (tree field = cxx_union_active_member (ctx, op, jump_target)) { unsigned HOST_WIDE_INT el_sz = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (field))); @@ -6005,7 +6897,8 @@ cxx_fold_indirect_ref_1 (const constexpr_ctx *ctx, location_t loc, tree type, tree cop = build3 (COMPONENT_REF, TREE_TYPE (field), op, field, NULL_TREE); if (tree ret = cxx_fold_indirect_ref_1 (ctx, loc, type, cop, - off, empty_base)) + off, empty_base, + jump_target)) return ret; } } @@ -6050,7 +6943,8 @@ cxx_fold_indirect_ref_1 (const constexpr_ctx *ctx, location_t loc, tree type, op, field, NULL_TREE); if (tree ret = cxx_fold_indirect_ref_1 (ctx, loc, type, cop, off - upos, - empty_base)) + empty_base, + jump_target)) return ret; } } @@ -6070,7 +6964,7 @@ cxx_fold_indirect_ref_1 (const constexpr_ctx *ctx, location_t loc, tree type, static tree cxx_fold_indirect_ref (const constexpr_ctx *ctx, location_t loc, tree type, - tree op0, bool *empty_base /* = NULL*/) + tree op0, bool *empty_base, tree *jump_target) { tree sub = op0; tree subtype; @@ -6152,7 +7046,8 @@ cxx_fold_indirect_ref (const constexpr_ctx *ctx, location_t loc, tree type, tree off = integer_zero_node; canonicalize_obj_off (op, off); return cxx_fold_indirect_ref_1 (ctx, loc, type, op, - tree_to_uhwi (off), empty_base); + tree_to_uhwi (off), empty_base, + jump_target); } } else if (TREE_CODE (sub) == POINTER_PLUS_EXPR @@ -6167,7 +7062,8 @@ cxx_fold_indirect_ref (const constexpr_ctx *ctx, location_t loc, tree type, tree obj = TREE_OPERAND (op00, 0); canonicalize_obj_off (obj, off); return cxx_fold_indirect_ref_1 (ctx, loc, type, obj, - tree_to_uhwi (off), empty_base); + tree_to_uhwi (off), empty_base, + jump_target); } } /* *(foo *)fooarrptr => (*fooarrptr)[0] */ @@ -6177,7 +7073,10 @@ cxx_fold_indirect_ref (const constexpr_ctx *ctx, location_t loc, tree type, tree type_domain; tree min_val = size_zero_node; tree newsub - = cxx_fold_indirect_ref (ctx, loc, TREE_TYPE (subtype), sub, NULL); + = cxx_fold_indirect_ref (ctx, loc, TREE_TYPE (subtype), sub, NULL, + jump_target); + if (*jump_target) + return NULL_TREE; if (newsub) sub = newsub; else @@ -6195,7 +7094,8 @@ cxx_fold_indirect_ref (const constexpr_ctx *ctx, location_t loc, tree type, static tree cxx_eval_indirect_ref (const constexpr_ctx *ctx, tree t, value_cat lval, - bool *non_constant_p, bool *overflow_p) + bool *non_constant_p, bool *overflow_p, + tree *jump_target) { tree orig_op0 = TREE_OPERAND (t, 0); bool empty_base = false; @@ -6213,13 +7113,17 @@ cxx_eval_indirect_ref (const constexpr_ctx *ctx, tree t, /* First try to simplify it directly. */ tree r = cxx_fold_indirect_ref (ctx, EXPR_LOCATION (t), TREE_TYPE (t), - orig_op0, &empty_base); + orig_op0, &empty_base, jump_target); + if (*jump_target) + return NULL_TREE; if (!r) { /* If that didn't work, evaluate the operand first. */ tree op0 = cxx_eval_constant_expression (ctx, orig_op0, vc_prvalue, non_constant_p, - overflow_p); + overflow_p, jump_target); + if (*jump_target) + return NULL_TREE; /* Don't VERIFY_CONSTANT here. */ if (*non_constant_p) return t; @@ -6233,7 +7137,9 @@ cxx_eval_indirect_ref (const constexpr_ctx *ctx, tree t, } r = cxx_fold_indirect_ref (ctx, EXPR_LOCATION (t), TREE_TYPE (t), op0, - &empty_base); + &empty_base, jump_target); + if (*jump_target) + return NULL_TREE; if (r == NULL_TREE) { /* We couldn't fold to a constant value. Make sure it's not @@ -6263,7 +7169,10 @@ cxx_eval_indirect_ref (const constexpr_ctx *ctx, tree t, } r = cxx_eval_constant_expression (ctx, r, - lval, non_constant_p, overflow_p); + lval, non_constant_p, overflow_p, + jump_target); + if (*jump_target) + return NULL_TREE; if (*non_constant_p) return t; @@ -6373,7 +7282,8 @@ non_const_var_error (location_t loc, tree r, bool fundef_p) static tree cxx_eval_trinary_expression (const constexpr_ctx *ctx, tree t, value_cat lval, - bool *non_constant_p, bool *overflow_p) + bool *non_constant_p, bool *overflow_p, + tree *jump_target) { int i; tree args[3]; @@ -6383,7 +7293,10 @@ cxx_eval_trinary_expression (const constexpr_ctx *ctx, tree t, { args[i] = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, i), lval, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); + if (*jump_target) + return NULL_TREE; VERIFY_CONSTANT (args[i]); } @@ -6505,7 +7418,8 @@ modifying_const_object_p (tree_code code, tree obj, bool mutable_p) static tree cxx_eval_store_expression (const constexpr_ctx *ctx, tree t, value_cat lval, - bool *non_constant_p, bool *overflow_p) + bool *non_constant_p, bool *overflow_p, + tree *jump_target) { constexpr_ctx new_ctx = *ctx; @@ -6531,7 +7445,10 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t, if (!SCALAR_TYPE_P (type)) new_ctx.ctor = new_ctx.object = NULL_TREE; init = cxx_eval_constant_expression (&new_ctx, init, vc_prvalue, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); + if (*jump_target) + return NULL_TREE; if (*non_constant_p) return t; } @@ -6543,8 +7460,11 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t, as a whole; otherwise, only evaluate the innermost piece to avoid building up unnecessary *_REFs. */ target = cxx_eval_constant_expression (ctx, target, lval, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); evaluated = true; + if (*jump_target) + return NULL_TREE; if (*non_constant_p) return t; } @@ -6570,7 +7490,10 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t, if (TREE_CODE (probe) == ARRAY_REF) { elt = eval_and_check_array_index (ctx, probe, false, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); + if (*jump_target) + return NULL_TREE; if (*non_constant_p) return t; } @@ -6627,8 +7550,11 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t, break; } probe = cxx_eval_constant_expression (ctx, probe, vc_glvalue, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); evaluated = true; + if (*jump_target) + return NULL_TREE; if (*non_constant_p) return t; } @@ -6972,7 +7898,10 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t, if (tree tinit = TARGET_EXPR_INITIAL (init)) init = tinit; init = cxx_eval_constant_expression (&new_ctx, init, vc_prvalue, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); + if (*jump_target) + return NULL_TREE; /* The hash table might have moved since the get earlier, and the initializer might have mutated the underlying CONSTRUCTORs, so we must recompute VALP. */ @@ -7098,7 +8027,8 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t, static tree cxx_eval_increment_expression (const constexpr_ctx *ctx, tree t, value_cat lval, - bool *non_constant_p, bool *overflow_p) + bool *non_constant_p, bool *overflow_p, + tree *jump_target) { enum tree_code code = TREE_CODE (t); tree type = TREE_TYPE (t); @@ -7112,12 +8042,18 @@ cxx_eval_increment_expression (const constexpr_ctx *ctx, tree t, /* The operand as an lvalue. */ op = cxx_eval_constant_expression (ctx, op, vc_glvalue, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); + if (*jump_target) + return NULL_TREE; /* The operand as an rvalue. */ tree val = cxx_eval_constant_expression (ctx, op, vc_prvalue, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); + if (*jump_target) + return NULL_TREE; /* Don't VERIFY_CONSTANT if this might be dealing with a pointer to a local array in a constexpr function. */ bool ptr = INDIRECT_TYPE_P (TREE_TYPE (val)); @@ -7156,8 +8092,11 @@ cxx_eval_increment_expression (const constexpr_ctx *ctx, tree t, tree store = build2_loc (cp_expr_loc_or_loc (t, input_location), MODIFY_EXPR, type, op, mod); mod = cxx_eval_constant_expression (ctx, store, lval, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); ggc_free (store); + if (*jump_target) + return NULL_TREE; if (*non_constant_p) return t; @@ -7171,42 +8110,6 @@ cxx_eval_increment_expression (const constexpr_ctx *ctx, tree t, return val; } -/* Predicates for the meaning of *jump_target. */ - -static bool -returns (tree *jump_target) -{ - return *jump_target - && TREE_CODE (*jump_target) == RETURN_EXPR; -} - -static bool -breaks (tree *jump_target) -{ - return *jump_target - && ((TREE_CODE (*jump_target) == LABEL_DECL - && LABEL_DECL_BREAK (*jump_target)) - || TREE_CODE (*jump_target) == BREAK_STMT - || TREE_CODE (*jump_target) == EXIT_EXPR); -} - -static bool -continues (tree *jump_target) -{ - return *jump_target - && ((TREE_CODE (*jump_target) == LABEL_DECL - && LABEL_DECL_CONTINUE (*jump_target)) - || TREE_CODE (*jump_target) == CONTINUE_STMT); - -} - -static bool -switches (tree *jump_target) -{ - return *jump_target - && TREE_CODE (*jump_target) == INTEGER_CST; -} - /* Subroutine of cxx_eval_statement_list. Determine whether the statement STMT matches *jump_target. If we're looking for a case label and we see the default label, note it in ctx->css_state. */ @@ -7254,6 +8157,11 @@ label_matches (const constexpr_ctx *ctx, tree *jump_target, tree stmt) breaks (jump_target) or continues (jump_target). */ break; + case VAR_DECL: + /* Uncaught exception. This is handled by TRY_BLOCK evaluation + and other places by testing throws (jump_target). */ + break; + default: gcc_unreachable (); } @@ -7268,15 +8176,9 @@ cxx_eval_statement_list (const constexpr_ctx *ctx, tree t, bool *non_constant_p, bool *overflow_p, tree *jump_target) { - tree local_target; /* In a statement-expression we want to return the last value. For empty statement expression return void_node. */ tree r = void_node; - if (!jump_target) - { - local_target = NULL_TREE; - jump_target = &local_target; - } for (tree_stmt_iterator i = tsi_start (t); !tsi_end_p (i); ++i) { tree stmt = *i; @@ -7304,18 +8206,11 @@ cxx_eval_statement_list (const constexpr_ctx *ctx, tree t, jump_target); if (*non_constant_p) break; - if (returns (jump_target) || breaks (jump_target)) + if (returns (jump_target) + || breaks (jump_target) + || throws (jump_target)) break; } - if (*jump_target && jump_target == &local_target) - { - /* We aren't communicating the jump to our caller, so give up. We don't - need to support evaluation of jumps out of statement-exprs. */ - if (!ctx->quiet) - error_at (cp_expr_loc_or_input_loc (r), - "statement is not a constant expression"); - *non_constant_p = true; - } return r; } @@ -7327,13 +8222,6 @@ cxx_eval_loop_expr (const constexpr_ctx *ctx, tree t, bool *non_constant_p, bool *overflow_p, tree *jump_target) { - tree local_target; - if (!jump_target) - { - local_target = NULL_TREE; - jump_target = &local_target; - } - tree body, cond = NULL_TREE, expr = NULL_TREE; tree cond_prep = NULL_TREE, cond_cleanup = NULL_TREE; unsigned cond_cleanup_depth = 0; @@ -7389,7 +8277,7 @@ cxx_eval_loop_expr (const constexpr_ctx *ctx, tree t, tree c; FOR_EACH_VEC_ELT_REVERSE (cleanups, i, c) cxx_eval_constant_expression (ctx, c, vc_discard, non_constant_p, - overflow_p); + overflow_p, jump_target); } if (cond_prep) for (tree decl = BIND_EXPR_VARS (cond_prep); @@ -7484,7 +8372,8 @@ cxx_eval_loop_expr (const constexpr_ctx *ctx, tree t, if (*non_constant_p || returns (jump_target) || breaks (jump_target) - || continues (jump_target)) + || continues (jump_target) + || throws (jump_target)) { depth = 1; break; @@ -7531,6 +8420,7 @@ cxx_eval_loop_expr (const constexpr_ctx *ctx, tree t, && !breaks (jump_target) && !continues (jump_target) && (!switches (jump_target) || count == 0) + && !throws (jump_target) && !*non_constant_p); cleanup_cond (); @@ -7549,7 +8439,10 @@ cxx_eval_switch_expr (const constexpr_ctx *ctx, tree t, tree cond = TREE_CODE (t) == SWITCH_STMT ? SWITCH_STMT_COND (t) : SWITCH_COND (t); cond = cxx_eval_constant_expression (ctx, cond, vc_prvalue, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); + if (*jump_target) + return NULL_TREE; VERIFY_CONSTANT (cond); if (TREE_CODE (cond) != INTEGER_CST) { @@ -7682,7 +8575,8 @@ maybe_warn_about_constant_value (location_t loc, tree decl) static tree build_new_constexpr_heap_type (const constexpr_ctx *ctx, tree elt_type, tree cookie_size, tree full_size, tree arg_size, - bool *non_constant_p, bool *overflow_p) + bool *non_constant_p, bool *overflow_p, + tree *jump_target) { gcc_assert (cookie_size == NULL_TREE || tree_fits_uhwi_p (cookie_size)); gcc_assert (tree_fits_uhwi_p (full_size)); @@ -7718,13 +8612,17 @@ build_new_constexpr_heap_type (const constexpr_ctx *ctx, tree elt_type, if (integer_zerop (op0)) arg_size = cxx_eval_constant_expression (ctx, op1, vc_prvalue, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); else if (integer_zerop (op1)) arg_size = cxx_eval_constant_expression (ctx, op0, vc_prvalue, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); else arg_size = NULL_TREE; + if (*jump_target) + return NULL_TREE; } else arg_size = NULL_TREE; @@ -7745,6 +8643,38 @@ build_new_constexpr_heap_type (const constexpr_ctx *ctx, tree elt_type, return build_new_constexpr_heap_type (elt_type, cookie_size, itype2); } +/* Handle the case when a cleanup of some expression throws. JMP_TARGET + indicates whether the cleanup threw or not, *JUMP_TARGET indicates whether + the expression which needed the cleanup threw. If both threw, diagnose + it and return NULL, otherwise return R. If only the cleanup threw, set + *JUMP_TARGET to the exception object from the cleanup. */ + +static tree +merge_jump_target (location_t loc, const constexpr_ctx *ctx, tree r, + bool *non_constant_p, tree *jump_target, tree jmp_target) +{ + if (!throws (&jmp_target)) + return r; + if (throws (jump_target)) + { + /* [except.throw]/9 - If the exception handling mechanism + handling an uncaught exception directly invokes a function + that exits via an exception, the function std::terminate is + invoked. */ + if (!ctx->quiet) + { + auto_diagnostic_group d; + diagnose_std_terminate (loc, ctx, *jump_target); + inform (loc, "destructor exited with an exception"); + } + *non_constant_p = true; + *jump_target = NULL_TREE; + return NULL_TREE; + } + *jump_target = jmp_target; + return r; +} + /* Attempt to reduce the expression T to a constant value. On failure, issue diagnostic and return error_mark_node. */ /* FIXME unify with c_fully_fold */ @@ -7754,9 +8684,9 @@ static tree cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, value_cat lval, bool *non_constant_p, bool *overflow_p, - tree *jump_target /* = NULL */) + tree *jump_target) { - if (jump_target && *jump_target) + if (*jump_target) { /* If we are jumping, ignore all statements/expressions except those that could have LABEL_EXPR or CASE_LABEL_EXPR in their bodies. */ @@ -7880,7 +8810,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, r = convert_from_reference (r); } return cxx_eval_constant_expression (ctx, r, lval, non_constant_p, - overflow_p); + overflow_p, jump_target); } /* fall through */ case CONST_DECL: @@ -7958,7 +8888,10 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, r = v; if (TREE_ADDRESSABLE (TREE_TYPE (t))) r = cxx_eval_constant_expression (ctx, r, vc_prvalue, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); + if (*jump_target) + return NULL_TREE; } else if (lval) /* Defer in case this is only used for its type. */; @@ -7991,7 +8924,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, case CALL_EXPR: case AGGR_INIT_EXPR: r = cxx_eval_call_expression (ctx, t, lval, - non_constant_p, overflow_p); + non_constant_p, overflow_p, jump_target); break; case DECL_EXPR: @@ -8055,7 +8988,10 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, if (tree init = DECL_INITIAL (r)) { init = cxx_eval_constant_expression (ctx, init, vc_prvalue, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); + if (*jump_target) + return NULL_TREE; /* Don't share a CONSTRUCTOR that might be changed. */ init = unshare_constructor (init); /* Remember that a constant object's constructor has already @@ -8125,9 +9061,12 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, /* Pass vc_prvalue because this indicates initialization of a temporary. */ r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 1), vc_prvalue, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); if (*non_constant_p) break; + if (*jump_target) + return NULL_TREE; if (!is_complex) { r = unshare_constructor (r); @@ -8135,8 +9074,15 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, r = adjust_temp_type (type, r); ctx->global->put_value (slot, r); } - if (TARGET_EXPR_CLEANUP (t) && !CLEANUP_EH_ONLY (t)) - ctx->global->cleanups->safe_push (TARGET_EXPR_CLEANUP (t)); + if (TARGET_EXPR_CLEANUP (t) + && (!CLEANUP_EH_ONLY (t) || cxx_dialect >= cxx26)) + { + ctx->global->cleanups->safe_push (TARGET_EXPR_CLEANUP (t)); + /* Mark CLEANUP_EH_ONLY cleanups by pushing NULL_TREE after + them. */ + if (CLEANUP_EH_ONLY (t)) + ctx->global->cleanups->safe_push (NULL_TREE); + } if (ctx->save_exprs) ctx->save_exprs->safe_push (slot); if (lval) @@ -8150,33 +9096,28 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, case MODIFY_EXPR: gcc_assert (jump_target == NULL || *jump_target == NULL_TREE); r = cxx_eval_store_expression (ctx, t, lval, - non_constant_p, overflow_p); + non_constant_p, overflow_p, jump_target); break; case SCOPE_REF: r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 1), lval, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); break; case RETURN_EXPR: if (TREE_OPERAND (t, 0) != NULL_TREE) r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0), lval, - non_constant_p, overflow_p); - /* FALLTHRU */ + non_constant_p, overflow_p, + jump_target); + if (!throws (jump_target)) + *jump_target = t; + break; case BREAK_STMT: case CONTINUE_STMT: - if (jump_target) - *jump_target = t; - else - { - /* Can happen with ({ return true; }) && false; passed to - maybe_constant_value. There is nothing to jump over in this - case, and the bug will be diagnosed later. */ - gcc_assert (ctx->quiet); - *non_constant_p = true; - } + *jump_target = t; break; case SAVE_EXPR: @@ -8185,9 +9126,10 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, r = v; else { - r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0), vc_prvalue, - non_constant_p, overflow_p); - if (*non_constant_p) + r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0), + vc_prvalue, non_constant_p, + overflow_p, jump_target); + if (*non_constant_p || *jump_target) break; ctx->global->put_value (t, r); if (ctx->save_exprs) @@ -8195,16 +9137,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, } break; - case TRY_CATCH_EXPR: - if (TREE_OPERAND (t, 0) == NULL_TREE) - { - r = void_node; - break; - } - /* FALLTHRU */ case NON_LVALUE_EXPR: - case TRY_BLOCK: - case MUST_NOT_THROW_EXPR: case EXPR_STMT: case EH_SPEC_BLOCK: r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0), @@ -8213,6 +9146,42 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, jump_target); break; + case TRY_BLOCK: + r = cxx_eval_constant_expression (ctx, TRY_STMTS (t), lval, + non_constant_p, overflow_p, + jump_target); + if (!*non_constant_p && throws (jump_target)) + if (tree h = TRY_HANDLERS (t)) + { + tree type = strip_array_types (TREE_TYPE (*jump_target)); + if (TREE_CODE (h) == STATEMENT_LIST) + { + for (tree stmt : tsi_range (h)) + if (TREE_CODE (stmt) == HANDLER + && handler_match_for_exception_type (stmt, type)) + { + h = stmt; + break; + } + if (TREE_CODE (h) == STATEMENT_LIST) + h = NULL_TREE; + } + else if (TREE_CODE (h) != HANDLER + || !handler_match_for_exception_type (h, type)) + h = NULL_TREE; + if (h) + { + gcc_assert (VAR_P (*jump_target)); + ctx->global->caught_exceptions.safe_push (*jump_target); + ctx->global->caught_exceptions.safe_push (HANDLER_TYPE (h)); + *jump_target = NULL_TREE; + r = cxx_eval_constant_expression (ctx, HANDLER_BODY (h), + vc_discard, non_constant_p, + overflow_p, jump_target); + } + } + break; + case CLEANUP_POINT_EXPR: { auto_vec<tree, 2> cleanups; @@ -8230,47 +9199,132 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, ctx->global->cleanups = prev_cleanups; unsigned int i; - tree cleanup; + tree cleanup, jmp_target = NULL_TREE; + bool eh = throws (jump_target); /* Evaluate the cleanups. */ FOR_EACH_VEC_ELT_REVERSE (cleanups, i, cleanup) - cxx_eval_constant_expression (&new_ctx, cleanup, vc_discard, - non_constant_p, overflow_p); + if (cleanup == NULL_TREE) + { + /* NULL_TREE cleanup is a marker that before it is + CLEANUP_EH_ONLY cleanup. Skip the cleanup before it + if the body didn't throw. */ + if (!eh) + --i; + } + else + cxx_eval_constant_expression (&new_ctx, cleanup, vc_discard, + non_constant_p, overflow_p, + &jmp_target); /* Forget SAVE_EXPRs and TARGET_EXPRs created by this full-expression. */ for (tree save_expr : save_exprs) destroy_value_checked (ctx, save_expr, non_constant_p); + if (throws (&jmp_target)) + *jump_target = jmp_target; } break; + case MUST_NOT_THROW_EXPR: + r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0), + lval, + non_constant_p, overflow_p, + jump_target); + if (throws (jump_target)) + { + /* [except.handle]/7 - If the search for a handler exits the + function body of a function with a non-throwing exception + specification, the function std::terminate is invoked. */ + if (!ctx->quiet) + { + auto_diagnostic_group d; + diagnose_std_terminate (loc, ctx, *jump_target); + if (MUST_NOT_THROW_NOEXCEPT_P (t) + && ctx->call + && ctx->call->fundef) + inform (loc, "uncaught exception exited from %<noexcept%> " + "function %qD", + ctx->call->fundef->decl); + else if (MUST_NOT_THROW_THROW_P (t)) + inform (loc, "destructor exited with an exception after " + "initializing the exception object"); + else if (MUST_NOT_THROW_CATCH_P (t)) + inform (loc, "constructor exited with another exception while " + "entering handler"); + } + *non_constant_p = true; + *jump_target = NULL_TREE; + r = NULL_TREE; + } + break; + + case TRY_CATCH_EXPR: + if (TREE_OPERAND (t, 0) == NULL_TREE) + { + r = void_node; + break; + } + r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0), lval, + non_constant_p, overflow_p, + jump_target); + if (!*non_constant_p && throws (jump_target)) + { + tree jmp_target = NULL_TREE; + cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 1), vc_discard, + non_constant_p, overflow_p, + &jmp_target); + r = merge_jump_target (loc, ctx, r, non_constant_p, jump_target, + jmp_target); + } + break; + case TRY_FINALLY_EXPR: r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0), lval, non_constant_p, overflow_p, jump_target); if (!*non_constant_p) - /* Also evaluate the cleanup. */ - cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 1), vc_discard, - non_constant_p, overflow_p); + { + tree jmp_target = NULL_TREE; + /* Also evaluate the cleanup. */ + if (TREE_CODE (TREE_OPERAND (t, 1)) == EH_ELSE_EXPR + && throws (jump_target)) + cxx_eval_constant_expression (ctx, + TREE_OPERAND (TREE_OPERAND (t, 1), + 1), vc_discard, + non_constant_p, overflow_p, + &jmp_target); + else + cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 1), vc_discard, + non_constant_p, overflow_p, + &jmp_target); + r = merge_jump_target (loc, ctx, r, non_constant_p, jump_target, + jmp_target); + } break; case EH_ELSE_EXPR: /* Evaluate any cleanup that applies to non-EH exits. */ cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0), vc_discard, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); - /* We do not have constexpr exceptions yet, so skip the EH path. */ + /* The EH path is handled in TRY_FINALLY_EXPR handling above. */ break; case CLEANUP_STMT: r = cxx_eval_constant_expression (ctx, CLEANUP_BODY (t), lval, non_constant_p, overflow_p, jump_target); - if (!CLEANUP_EH_ONLY (t) && !*non_constant_p) + if ((!CLEANUP_EH_ONLY (t) || throws (jump_target)) && !*non_constant_p) { iloc_sentinel ils (loc); + tree jmp_target = NULL_TREE; /* Also evaluate the cleanup. */ cxx_eval_constant_expression (ctx, CLEANUP_EXPR (t), vc_discard, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + &jmp_target); + r = merge_jump_target (loc, ctx, r, non_constant_p, jump_target, + jmp_target); } break; @@ -8280,14 +9334,18 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, case MEM_REF: case INDIRECT_REF: r = cxx_eval_indirect_ref (ctx, t, lval, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); break; case ADDR_EXPR: { tree oldop = TREE_OPERAND (t, 0); tree op = cxx_eval_constant_expression (ctx, oldop, vc_glvalue, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); + if (*jump_target) + return NULL_TREE; /* Don't VERIFY_CONSTANT here. */ if (*non_constant_p) return t; @@ -8307,7 +9365,10 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, if (lval) { r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0), lval, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); + if (*jump_target) + return NULL_TREE; if (r == error_mark_node) ; else if (r == TREE_OPERAND (t, 0) || lval == vc_discard) @@ -8328,7 +9389,8 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, case FIXED_CONVERT_EXPR: case VEC_DUPLICATE_EXPR: r = cxx_eval_unary_expression (ctx, t, lval, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); break; case SIZEOF_EXPR: @@ -8366,6 +9428,8 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, cxx_eval_constant_expression (ctx, op0, vc_discard, non_constant_p, overflow_p, jump_target); + if (*jump_target) + return NULL_TREE; if (*non_constant_p) return t; op1 = TREE_OPERAND (t, 1); @@ -8418,7 +9482,8 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, case RANGE_EXPR: case COMPLEX_EXPR: r = cxx_eval_binary_expression (ctx, t, lval, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); break; /* fold can introduce non-IF versions of these; still treat them as @@ -8427,19 +9492,22 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, case TRUTH_ANDIF_EXPR: r = cxx_eval_logical_expression (ctx, t, boolean_false_node, boolean_true_node, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); break; case TRUTH_OR_EXPR: case TRUTH_ORIF_EXPR: r = cxx_eval_logical_expression (ctx, t, boolean_true_node, boolean_false_node, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); break; case ARRAY_REF: r = cxx_eval_array_reference (ctx, t, lval, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); break; case COMPONENT_REF: @@ -8454,17 +9522,19 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, return t; } r = cxx_eval_component_reference (ctx, t, lval, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); break; case BIT_FIELD_REF: r = cxx_eval_bit_field_ref (ctx, t, lval, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); break; case COND_EXPR: case IF_STMT: - if (jump_target && *jump_target) + if (*jump_target) { tree orig_jump = *jump_target; tree arg = ((TREE_CODE (t) != IF_STMT || TREE_OPERAND (t, 1)) @@ -8502,7 +9572,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, break; case VEC_COND_EXPR: r = cxx_eval_vector_conditional_expression (ctx, t, non_constant_p, - overflow_p); + overflow_p, jump_target); break; case CONSTRUCTOR: @@ -8514,7 +9584,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, return t; } r = cxx_eval_bare_aggregate (ctx, t, lval, - non_constant_p, overflow_p); + non_constant_p, overflow_p, jump_target); break; case VEC_INIT_EXPR: @@ -8524,12 +9594,13 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, or xvalue of the same type, meaning direct-initialization from the corresponding member. */ r = cxx_eval_vec_init (ctx, t, lval, - non_constant_p, overflow_p); + non_constant_p, overflow_p, jump_target); break; case VEC_PERM_EXPR: r = cxx_eval_trinary_expression (ctx, t, lval, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); break; case PAREN_EXPR: @@ -8537,7 +9608,8 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, /* A PAREN_EXPR resulting from __builtin_assoc_barrier has no effect in constant expressions since it's unaffected by -fassociative-math. */ r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0), lval, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); break; case NOP_EXPR: @@ -8561,7 +9633,10 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, ? vc_discard : tcode == VIEW_CONVERT_EXPR ? lval : vc_prvalue, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); + if (*jump_target) + return NULL_TREE; if (*non_constant_p) return t; tree type = TREE_TYPE (t); @@ -8618,7 +9693,10 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, { if (integer_zerop (sop)) return build_int_cst (type, 0); - r = cxx_fold_indirect_ref (ctx, loc, TREE_TYPE (type), sop); + r = cxx_fold_indirect_ref (ctx, loc, TREE_TYPE (type), sop, + NULL, jump_target); + if (*jump_target) + return NULL_TREE; if (r) { r = build1 (ADDR_EXPR, type, r); @@ -8745,10 +9823,14 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, if (cxx_replaceable_global_alloc_fn (fun) && IDENTIFIER_NEW_OP_P (DECL_NAME (fun))) arg_size = CALL_EXPR_ARG (oldop, 0); - TREE_TYPE (var) + tree new_type = build_new_constexpr_heap_type (ctx, elt_type, cookie_size, var_size, arg_size, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); + if (*jump_target) + return NULL_TREE; + TREE_TYPE (var) = new_type; TREE_TYPE (TREE_OPERAND (op, 0)) = build_pointer_type (TREE_TYPE (var)); } @@ -8787,7 +9869,10 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, tree op = cxx_eval_constant_expression (ctx, oldop, lval, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); + if (*jump_target) + return NULL_TREE; if (*non_constant_p) return t; r = fold_convert (TREE_TYPE (t), op); @@ -8824,14 +9909,20 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, case PREDECREMENT_EXPR: case POSTDECREMENT_EXPR: return cxx_eval_increment_expression (ctx, t, - lval, non_constant_p, overflow_p); + lval, non_constant_p, overflow_p, + jump_target); + case THROW_EXPR: + if (cxx_dialect >= cxx26) + return cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0), lval, + non_constant_p, overflow_p, + jump_target); + /* FALLTHROUGH */ case LAMBDA_EXPR: case NEW_EXPR: case VEC_NEW_EXPR: case DELETE_EXPR: case VEC_DELETE_EXPR: - case THROW_EXPR: case MODOP_EXPR: /* GCC internal stuff. */ case VA_ARG_EXPR: @@ -8845,7 +9936,8 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, case OBJ_TYPE_REF: /* Virtual function lookup. We don't need to do anything fancy. */ return cxx_eval_constant_expression (ctx, OBJ_TYPE_REF_EXPR (t), - lval, non_constant_p, overflow_p); + lval, non_constant_p, overflow_p, + jump_target); case PLACEHOLDER_EXPR: /* Use of the value or address of the current object. */ @@ -8855,7 +9947,8 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, return ctor; else return cxx_eval_constant_expression (ctx, ctor, lval, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); } /* A placeholder without a referent. We can get here when checking whether NSDMIs are noexcept, or in massage_init_elt; @@ -8868,7 +9961,10 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, { tree cond = TREE_OPERAND (t, 0); cond = cxx_eval_constant_expression (ctx, cond, vc_prvalue, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); + if (*jump_target) + return NULL_TREE; VERIFY_CONSTANT (cond); if (integer_nonzerop (cond)) *jump_target = t; @@ -8980,7 +10076,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, *non_constant_p = true; return t; } - r = cxx_eval_bit_cast (ctx, t, non_constant_p, overflow_p); + r = cxx_eval_bit_cast (ctx, t, non_constant_p, overflow_p, jump_target); break; case OMP_PARALLEL: @@ -9299,8 +10395,34 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant, if (manifestly_const_eval == mce_true) instantiate_constexpr_fns (r); + tree jmp_target = NULL_TREE; r = cxx_eval_constant_expression (&ctx, r, vc_prvalue, - &non_constant_p, &overflow_p); + &non_constant_p, &overflow_p, + &jmp_target); + if (throws (&jmp_target) && !non_constant_p) + { + if (!ctx.quiet) + diagnose_uncaught_exception (input_location, &ctx, jmp_target); + non_constant_p = true; + jmp_target = NULL_TREE; + r = t; + } + else if (!non_constant_p && jmp_target) + { + non_constant_p = true; + if (!ctx.quiet) + { + if (breaks (&jmp_target)) + error ("%<break%> outside of a loop or %<switch%>"); + else if (continues (&jmp_target)) + error ("%<continue%> outside of a loop"); + else if (returns (&jmp_target)) + error ("%<return%> in a statement expression"); + else + gcc_unreachable (); + } + r = t; + } /* If we got a non-simple TARGET_EXPR, the initializer was a sequence of statements, and the result ought to be stored in ctx.ctor. */ @@ -9309,15 +10431,31 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant, unsigned int i; tree cleanup; + jmp_target = NULL_TREE; /* Evaluate the cleanups. */ FOR_EACH_VEC_ELT_REVERSE (cleanups, i, cleanup) - cxx_eval_constant_expression (&ctx, cleanup, vc_discard, - &non_constant_p, &overflow_p); + if (cleanup == NULL_TREE) + /* NULL_TREE cleanup is a marker that before it is + CLEANUP_EH_ONLY cleanup. Skip the cleanup before it. */ + --i; + else + cxx_eval_constant_expression (&ctx, cleanup, vc_discard, + &non_constant_p, &overflow_p, + &jmp_target); + if (throws (&jmp_target) && !non_constant_p) + { + if (!ctx.quiet) + diagnose_uncaught_exception (input_location, &ctx, jmp_target); + non_constant_p = true; + r = t; + } /* Mutable logic is a bit tricky: we want to allow initialization of constexpr variables with mutable members, but we can't copy those members to another constexpr variable. */ - if (TREE_CODE (r) == CONSTRUCTOR && CONSTRUCTOR_MUTABLE_POISON (r)) + if (!non_constant_p + && TREE_CODE (r) == CONSTRUCTOR + && CONSTRUCTOR_MUTABLE_POISON (r)) { if (!allow_non_constant) error ("%qE is not a constant expression because it refers to " @@ -9335,8 +10473,13 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant, { if (!allow_non_constant && !non_constant_p) { - error ("%qE is not a constant expression because it refers to " - "a result of %<operator new%>", t); + if (DECL_LANG_SPECIFIC (heap_var)) + error ("%qE is not a constant expression because it refers to " + "exception object allocated with " + "%<__cxa_allocate_exception%>", t); + else + error ("%qE is not a constant expression because it refers to " + "a result of %<operator new%>", t); inform (DECL_SOURCE_LOCATION (heap_var), "allocated here"); } r = t; @@ -9917,6 +11060,24 @@ cxx_constant_init (tree t, tree decl) return maybe_constant_init_1 (t, decl, false, mce_true); } +/* Return true if CALL_EXPR T might throw during constant evaluation. */ + +static bool +callee_might_throw (tree t) +{ + if (cxx_dialect < cxx26 || !flag_exceptions) + return false; + tree callee = cp_get_callee (t); + if (callee == NULL_TREE) + return false; + tree callee_fn = cp_get_fndecl_from_callee (callee, false); + return (!flag_enforce_eh_specs + || type_dependent_expression_p (callee) + || !POINTER_TYPE_P (TREE_TYPE (callee)) + || (!type_noexcept_p (TREE_TYPE (TREE_TYPE (callee))) + && (callee_fn == NULL_TREE || !TREE_NOTHROW (callee_fn)))); +} + #if 0 /* FIXME see ADDR_EXPR section in potential_constant_expression_1. */ /* Return true if the object referred to by REF has automatic or thread @@ -9949,11 +11110,13 @@ struct check_for_return_continue_data { hash_set<tree> *pset; tree continue_stmt; tree break_stmt; + bool could_throw; }; /* Helper function for potential_constant_expression_1 SWITCH_STMT handling, called through cp_walk_tree. Return the first RETURN_EXPR found, or note - the first CONTINUE_STMT and/or BREAK_STMT if RETURN_EXPR is not found. */ + the first CONTINUE_STMT and/or BREAK_STMT if RETURN_EXPR is not found. + For C++26 also note presence of possibly throwing calls. */ static tree check_for_return_continue (tree *tp, int *walk_subtrees, void *data) { @@ -10038,6 +11201,13 @@ check_for_return_continue (tree *tp, int *walk_subtrees, void *data) case CONSTRUCTOR: break; + case AGGR_INIT_EXPR: + case CALL_EXPR: + /* In C++26 a function could throw. */ + if (callee_might_throw (t)) + d->could_throw = true; + break; + default: if (!EXPR_P (t)) *walk_subtrees = 0; @@ -10243,8 +11413,27 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, || TREE_CODE (t) != CALL_EXPR || current_function_decl == NULL_TREE || !is_std_construct_at (current_function_decl)) - && !cxx_dynamic_cast_fn_p (fun)) + && !cxx_dynamic_cast_fn_p (fun) + && !cxx_cxa_builtin_fn_p (fun)) { + /* In C++26 evaluation of the function arguments might + throw and in that case it is irrelevant whether + fun is constexpr or not. */ + if (cxx_dialect >= cxx26) + for (; i < nargs; ++i) + { + tree x = get_nth_callarg (t, i); + bool rv = processing_template_decl ? any : rval; + bool sub_now = false; + if (!potential_constant_expression_1 (x, rv, strict, + sub_now, + fundef_p, + flags, + jump_target)) + return false; + if (throws (jump_target)) + return true; + } if ((flags & tf_error) && constexpr_error (loc, fundef_p, "call to non-%<constexpr%> " @@ -10289,7 +11478,12 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, sub_now, fundef_p, flags, jump_target)) return false; + if (throws (jump_target)) + return true; } + /* In C++26 a function could throw. */ + if (*jump_target == NULL_TREE && callee_might_throw (t)) + *jump_target = void_node; return true; } @@ -10512,11 +11706,13 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, a return. */ hash_set<tree> pset; check_for_return_continue_data data = { &pset, NULL_TREE, - NULL_TREE }; + NULL_TREE, false }; if (tree ret_expr = cp_walk_tree (&FOR_BODY (t), check_for_return_continue, &data, &pset)) *jump_target = ret_expr; + if (data.could_throw) + *jump_target = void_node; return true; } } @@ -10556,11 +11752,13 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, a return. */ hash_set<tree> pset; check_for_return_continue_data data = { &pset, NULL_TREE, - NULL_TREE }; + NULL_TREE, false }; if (tree ret_expr = cp_walk_tree (&WHILE_BODY (t), check_for_return_continue, &data, &pset)) *jump_target = ret_expr; + if (data.could_throw) + *jump_target = void_node; return true; } if (!RECUR (WHILE_BODY (t), any)) @@ -10584,7 +11782,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, { hash_set<tree> pset; check_for_return_continue_data data = { &pset, NULL_TREE, - NULL_TREE }; + NULL_TREE, false }; if (tree ret_expr = cp_walk_tree (&SWITCH_STMT_BODY (t), check_for_return_continue, &data, &pset)) @@ -10593,6 +11791,8 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, else if (data.continue_stmt) /* The switch can't return, but might continue. */ *jump_target = data.continue_stmt; + if (data.could_throw) + *jump_target = void_node; } return true; @@ -10622,7 +11822,6 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, case DYNAMIC_CAST_EXPR: case PSEUDO_DTOR_EXPR: - case THROW_EXPR: case OMP_PARALLEL: case OMP_TASK: case OMP_FOR: @@ -10678,6 +11877,11 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, constant. */ return true; + case THROW_EXPR: + if (cxx_dialect < cxx26) + goto fail; + return RECUR (TREE_OPERAND (t, 0), rval); + case ASM_EXPR: if (flags & tf_error) inline_asm_in_constexpr_error (loc, fundef_p); @@ -10806,6 +12010,22 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, case CLEANUP_POINT_EXPR: case MUST_NOT_THROW_EXPR: case TRY_CATCH_EXPR: + /* Even for C++26 handle TRY_BLOCK conservatively, if we detect the + body could throw, even with catch (...) among handlers we'd need + to analyze them in detail if they couldn't rethrow it. More + importantly though, throws (jump_target) is just conservative, + and there could be e.g. + try + { + possibly_throwing_fn (args); + break; + } + catch (...) + { + } + or continue or return instead of break. So, clearing *jump_target + because we see catch (...) handler might mean we missed break + etc. */ case TRY_BLOCK: case EH_SPEC_BLOCK: case EXPR_STMT: @@ -11047,9 +12267,9 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, want_rval, strict, now, fundef_p, tf_none, &this_jump_target)) { - if (returns (&this_jump_target)) + if (returns (&this_jump_target) || throws (&this_jump_target)) *jump_target = this_jump_target; - else if (!returns (jump_target)) + else if (!returns (jump_target) && !throws (jump_target)) { if (breaks (&this_jump_target) || continues (&this_jump_target)) @@ -11061,7 +12281,8 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, couldn't return, break or continue. */ hash_set<tree> pset; check_for_return_continue_data data = { &pset, NULL_TREE, - NULL_TREE }; + NULL_TREE, + false }; if (tree ret_expr = cp_walk_tree (&TREE_OPERAND (t, 2), check_for_return_continue, &data, @@ -11074,6 +12295,8 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, else if (data.break_stmt) *jump_target = data.break_stmt; } + if (data.could_throw) + *jump_target = void_node; } } return true; diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc index ce69bd6..882a943 100644 --- a/gcc/cp/cp-gimplify.cc +++ b/gcc/cp/cp-gimplify.cc @@ -889,6 +889,12 @@ cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) (EXPR_LOCATION (*expr_p), call_expr_nargs (*expr_p), &CALL_EXPR_ARG (*expr_p, 0)); break; + case CP_BUILT_IN_EH_PTR_ADJUST_REF: + error_at (EXPR_LOCATION (*expr_p), + "%qs used outside of constant expressions", + "__builtin_eh_ptr_adjust_ref"); + *expr_p = void_node; + break; default: break; } diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 1b893e2..9081628 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -452,6 +452,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX]; contract_semantic (in ASSERTION_, PRECONDITION_, POSTCONDITION_STMT) RETURN_EXPR_LOCAL_ADDR_P (in RETURN_EXPR) PACK_INDEX_PARENTHESIZED_P (in PACK_INDEX_*) + MUST_NOT_THROW_NOEXCEPT_P (in MUST_NOT_THROW_EXPR) 1: IDENTIFIER_KIND_BIT_1 (in IDENTIFIER_NODE) TI_PENDING_TEMPLATE_FLAG. TEMPLATE_PARMS_FOR_INLINE. @@ -472,6 +473,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX]; BIND_EXPR_VEC_DTOR (in BIND_EXPR) ATOMIC_CONSTR_EXPR_FROM_CONCEPT_P (in ATOMIC_CONSTR) STATIC_INIT_DECOMP_BASE_P (in the TREE_LIST for {static,tls}_aggregates) + MUST_NOT_THROW_THROW_P (in MUST_NOT_THROW_EXPR) 2: IDENTIFIER_KIND_BIT_2 (in IDENTIFIER_NODE) ICS_THIS_FLAG (in _CONV) DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (in VAR_DECL) @@ -493,6 +495,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX]; contract_semantic (in ASSERTION_, PRECONDITION_, POSTCONDITION_STMT) STATIC_INIT_DECOMP_NONBASE_P (in the TREE_LIST for {static,tls}_aggregates) + MUST_NOT_THROW_CATCH_P (in MUST_NOT_THROW_EXPR) 3: IMPLICIT_RVALUE_P (in NON_LVALUE_EXPR or STATIC_CAST_EXPR) ICS_BAD_FLAG (in _CONV) FN_TRY_BLOCK_P (in TRY_BLOCK) @@ -506,6 +509,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX]; LAMBDA_EXPR_STATIC_P (in LAMBDA_EXPR) TARGET_EXPR_ELIDING_P (in TARGET_EXPR) contract_semantic (in ASSERTION_, PRECONDITION_, POSTCONDITION_STMT) + TYPENAME_IS_UNION_P (in TYPENAME_TYPE) 4: IDENTIFIER_MARKED (IDENTIFIER_NODEs) TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR, CALL_EXPR, or FIELD_DECL). @@ -2354,6 +2358,10 @@ enum languages { lang_c, lang_cplusplus }; #define NON_UNION_CLASS_TYPE_P(T) \ (TREE_CODE (T) == RECORD_TYPE && TYPE_LANG_FLAG_5 (T)) +/* Nonzero if T is a class type and is a union. */ +#define UNION_TYPE_P(T) \ + (TREE_CODE (T) == UNION_TYPE && TYPE_LANG_FLAG_5 (T)) + /* Keep these checks in ascending code order. */ #define RECORD_OR_UNION_CODE_P(T) \ ((T) == RECORD_TYPE || (T) == UNION_TYPE) @@ -2511,11 +2519,11 @@ struct GTY(()) lang_type { vec<tree, va_gc> *pure_virtuals; tree friend_classes; vec<tree, va_gc> * GTY((reorder ("resort_type_member_vec"))) members; + /* CLASSTYPE_KEY_METHOD for TYPE_POLYMORPHIC_P types, CLASSTYPE_LAMBDA_EXPR + otherwise. */ tree key_method; tree decl_list; tree befriending_classes; - /* FIXME reuse another field? */ - tree lambda_expr; union maybe_objc_info { /* If not c_dialect_objc, this part is not even allocated. */ char GTY((tag ("0"))) non_objc; @@ -2638,7 +2646,13 @@ struct GTY(()) lang_type { /* The member function with which the vtable will be emitted: the first noninline non-pure-virtual member function. NULL_TREE if there is no key function or if this is a class template */ -#define CLASSTYPE_KEY_METHOD(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->key_method) +#define CLASSTYPE_KEY_METHOD(NODE) \ + (TYPE_POLYMORPHIC_P (NODE) \ + ? LANG_TYPE_CLASS_CHECK (NODE)->key_method \ + : NULL_TREE) +#define SET_CLASSTYPE_KEY_METHOD(NODE, VALUE) \ + (gcc_checking_assert (TYPE_POLYMORPHIC_P (NODE)), \ + LANG_TYPE_CLASS_CHECK (NODE)->key_method = (VALUE)) /* Vector of members. During definition, it is unordered and only member functions are present. After completion it is sorted and @@ -2770,7 +2784,12 @@ struct GTY(()) lang_type { /* The associated LAMBDA_EXPR that made this class. */ #define CLASSTYPE_LAMBDA_EXPR(NODE) \ - (LANG_TYPE_CLASS_CHECK (NODE)->lambda_expr) + (TYPE_POLYMORPHIC_P (NODE) \ + ? NULL_TREE \ + : LANG_TYPE_CLASS_CHECK (NODE)->key_method) +#define SET_CLASSTYPE_LAMBDA_EXPR(NODE, VALUE) \ + (gcc_checking_assert (!TYPE_POLYMORPHIC_P (NODE)), \ + LANG_TYPE_CLASS_CHECK (NODE)->key_method = (VALUE)) /* The extra mangling scope for this closure type. */ #define LAMBDA_TYPE_EXTRA_SCOPE(NODE) \ (LAMBDA_EXPR_EXTRA_SCOPE (CLASSTYPE_LAMBDA_EXPR (NODE))) @@ -3011,6 +3030,8 @@ struct GTY(()) lang_decl_min { In a lambda-capture proxy VAR_DECL, this is DECL_CAPTURED_VARIABLE. In a function-scope TREE_STATIC VAR_DECL or IMPLICIT_TYPEDEF_P TYPE_DECL, this is DECL_DISCRIMINATOR. + In constexpr exception artificial VAR_DECL, this is + DECL_EXCEPTION_REFCOUNT. In a DECL_LOCAL_DECL_P decl, this is the namespace decl it aliases. Otherwise, in a class-scope DECL, this is DECL_ACCESS. */ tree access; @@ -4465,6 +4486,23 @@ get_vec_init_expr (tree t) #define MUST_NOT_THROW_COND(NODE) \ TREE_OPERAND (MUST_NOT_THROW_EXPR_CHECK (NODE), 1) +/* Reasons why MUST_NOT_THROW_EXPR has been created. */ + +/* Indicates MUST_NOT_THROW_EXPR has been created to wrap body of + a noexcept function. */ +#define MUST_NOT_THROW_NOEXCEPT_P(NODE) \ + TREE_LANG_FLAG_0 (MUST_NOT_THROW_EXPR_CHECK (NODE)) + +/* Indicates MUST_NOT_THROW_EXPR has been created to wrap construction of + exception object during throw. */ +#define MUST_NOT_THROW_THROW_P(NODE) \ + TREE_LANG_FLAG_1 (MUST_NOT_THROW_EXPR_CHECK (NODE)) + +/* Indicates MUST_NOT_THROW_EXPR has been created to wrap construction of + handler parameter during catch. */ +#define MUST_NOT_THROW_CATCH_P(NODE) \ + TREE_LANG_FLAG_2 (MUST_NOT_THROW_EXPR_CHECK (NODE)) + /* The TYPE_MAIN_DECL for a class template type is a TYPE_DECL, not a TEMPLATE_DECL. This macro determines whether or not a given class type is really a template type, as opposed to an instantiation or @@ -4485,11 +4523,14 @@ get_vec_init_expr (tree t) #define TYPENAME_IS_ENUM_P(NODE) \ (TREE_LANG_FLAG_0 (TYPENAME_TYPE_CHECK (NODE))) -/* True if a TYPENAME_TYPE was declared as a "class", "struct", or - "union". */ +/* True if a TYPENAME_TYPE was declared as a "class" or "struct". */ #define TYPENAME_IS_CLASS_P(NODE) \ (TREE_LANG_FLAG_1 (TYPENAME_TYPE_CHECK (NODE))) +/* True if a TYPENAME_TYPE was declared as a "union". */ +#define TYPENAME_IS_UNION_P(NODE) \ + (TREE_LANG_FLAG_3 (TYPENAME_TYPE_CHECK (NODE))) + /* True if a TYPENAME_TYPE is in the process of being resolved. */ #define TYPENAME_IS_RESOLVING_P(NODE) \ (TREE_LANG_FLAG_2 (TYPENAME_TYPE_CHECK (NODE))) @@ -4504,7 +4545,7 @@ get_vec_init_expr (tree t) #define TYPE_CONTAINS_VPTR_P(NODE) \ (TYPE_POLYMORPHIC_P (NODE) || CLASSTYPE_VBASECLASSES (NODE)) -/* Nonzero if NODE is a FUNCTION_DECL or VARIABLE_DECL (for a decl +/* Nonzero if NODE is a FUNCTION_DECL or VAR_DECL (for a decl with namespace scope) declared in a local scope. */ #define DECL_LOCAL_DECL_P(NODE) \ DECL_LANG_FLAG_0 (VAR_OR_FUNCTION_DECL_CHECK (NODE)) @@ -5145,6 +5186,10 @@ get_vec_init_expr (tree t) protected_access_node will appear in the DECL_ACCESS for the node. */ #define DECL_ACCESS(NODE) (LANG_DECL_MIN_CHECK (NODE)->access) +/* In artificial VAR_DECL created by cxa_allocate_exception + this is reference count. */ +#define DECL_EXCEPTION_REFCOUNT(NODE) (LANG_DECL_MIN_CHECK (NODE)->access) + /* Nonzero if the FUNCTION_DECL is a global constructor. */ #define DECL_GLOBAL_CTOR_P(NODE) \ (LANG_DECL_FN_CHECK (NODE)->global_ctor_p) @@ -6805,6 +6850,7 @@ enum cp_built_in_function { CP_BUILT_IN_IS_CORRESPONDING_MEMBER, CP_BUILT_IN_IS_POINTER_INTERCONVERTIBLE_WITH_CLASS, CP_BUILT_IN_SOURCE_LOCATION, + CP_BUILT_IN_EH_PTR_ADJUST_REF, CP_BUILT_IN_LAST }; @@ -6985,6 +7031,7 @@ extern bool type_has_extended_temps (tree); extern tree strip_top_quals (tree); extern bool reference_related_p (tree, tree); extern bool reference_compatible_p (tree, tree); +extern bool handler_match_for_exception_type (tree, tree); extern int remaining_arguments (tree); extern tree build_implicit_conv_flags (tree, tree, int); extern tree perform_implicit_conversion (tree, tree, tsubst_flags_t); diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index 83c8e28..843f0e4 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -2014,8 +2014,10 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden) } /* For function versions, params and types match, but they are not ambiguous. */ - else if ((!DECL_FUNCTION_VERSIONED (newdecl) - && !DECL_FUNCTION_VERSIONED (olddecl)) + else if (((!DECL_FUNCTION_VERSIONED (newdecl) + && !DECL_FUNCTION_VERSIONED (olddecl)) + || !same_type_p (fndecl_declared_return_type (newdecl), + fndecl_declared_return_type (olddecl))) /* Let constrained hidden friends coexist for now, we'll check satisfaction later. */ && !member_like_constrained_friend_p (newdecl) @@ -4368,6 +4370,7 @@ struct typename_info { tree template_id; bool enum_p; bool class_p; + bool union_p; }; struct typename_hasher : ggc_ptr_hash<tree_node> @@ -4406,7 +4409,8 @@ struct typename_hasher : ggc_ptr_hash<tree_node> && TYPE_CONTEXT (t1) == t2->scope && TYPENAME_TYPE_FULLNAME (t1) == t2->template_id && TYPENAME_IS_ENUM_P (t1) == t2->enum_p - && TYPENAME_IS_CLASS_P (t1) == t2->class_p); + && TYPENAME_IS_CLASS_P (t1) == t2->class_p + && TYPENAME_IS_UNION_P (t1) == t2->union_p); } }; @@ -4430,9 +4434,8 @@ build_typename_type (tree context, tree name, tree fullname, ti.name = name; ti.template_id = fullname; ti.enum_p = tag_type == enum_type; - ti.class_p = (tag_type == class_type - || tag_type == record_type - || tag_type == union_type); + ti.class_p = (tag_type == class_type || tag_type == record_type); + ti.union_p = tag_type == union_type; hashval_t hash = typename_hasher::hash (&ti); /* See if we already have this type. */ @@ -4448,6 +4451,7 @@ build_typename_type (tree context, tree name, tree fullname, TYPENAME_TYPE_FULLNAME (t) = ti.template_id; TYPENAME_IS_ENUM_P (t) = ti.enum_p; TYPENAME_IS_CLASS_P (t) = ti.class_p; + TYPENAME_IS_UNION_P (t) = ti.union_p; /* Build the corresponding TYPE_DECL. */ tree d = build_decl (input_location, TYPE_DECL, name, t); @@ -5078,6 +5082,18 @@ cxx_init_decl_processing (void) BUILT_IN_FRONTEND, NULL, NULL_TREE); set_call_expr_flags (decl, ECF_CONST | ECF_NOTHROW | ECF_LEAF); + if (cxx_dialect >= cxx26) + { + tree void_ptrintftype + = build_function_type_list (void_type_node, ptr_type_node, + integer_type_node, NULL_TREE); + decl = add_builtin_function ("__builtin_eh_ptr_adjust_ref", + void_ptrintftype, + CP_BUILT_IN_EH_PTR_ADJUST_REF, + BUILT_IN_FRONTEND, NULL, NULL_TREE); + set_call_expr_flags (decl, ECF_NOTHROW | ECF_LEAF); + } + integer_two_node = build_int_cst (NULL_TREE, 2); /* Guess at the initial static decls size. */ @@ -9172,6 +9188,10 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, if (decomp) { + if (DECL_DECLARED_CONSTINIT_P (decl) && cxx_dialect < cxx26) + pedwarn (DECL_SOURCE_LOCATION (decl), OPT_Wc__26_extensions, + "%<constinit%> can be applied to structured binding " + "only with %<-std=c++2c%> or %<-std=gnu++2c%>"); cp_maybe_mangle_decomp (decl, decomp); if (TREE_STATIC (decl) && !DECL_FUNCTION_SCOPE_P (decl)) { @@ -13619,9 +13639,10 @@ grokdeclarator (const cp_declarator *declarator, if (typedef_p) error_at (declspecs->locations[ds_typedef], "structured binding declaration cannot be %qs", "typedef"); - if (constexpr_p && !concept_p) - error_at (declspecs->locations[ds_constexpr], "structured " - "binding declaration cannot be %qs", "constexpr"); + if (constexpr_p && !concept_p && cxx_dialect < cxx26) + pedwarn (declspecs->locations[ds_constexpr], OPT_Wc__26_extensions, + "structured binding declaration can be %qs only with " + "%<-std=c++2c%> or %<-std=gnu++2c%>", "constexpr"); if (consteval_p) error_at (declspecs->locations[ds_consteval], "structured " "binding declaration cannot be %qs", "consteval"); @@ -13632,8 +13653,11 @@ grokdeclarator (const cp_declarator *declarator, declspecs->gnu_thread_keyword_p ? "__thread" : "thread_local"); if (concept_p) - error_at (declspecs->locations[ds_concept], - "structured binding declaration cannot be %qs", "concept"); + { + error_at (declspecs->locations[ds_concept], + "structured binding declaration cannot be %qs", "concept"); + constexpr_p = 0; + } /* [dcl.struct.bind] "A cv that includes volatile is deprecated." */ if (type_quals & TYPE_QUAL_VOLATILE) warning_at (declspecs->locations[ds_volatile], OPT_Wvolatile, @@ -13688,7 +13712,6 @@ grokdeclarator (const cp_declarator *declarator, "%<auto%> type %qT", type); inlinep = 0; typedef_p = 0; - constexpr_p = 0; consteval_p = 0; concept_p = 0; if (storage_class != sc_static) @@ -17266,7 +17289,7 @@ xref_tag (enum tag_types tag_code, tree name, if (IDENTIFIER_LAMBDA_P (name)) /* Mark it as a lambda type right now. Our caller will correct the value. */ - CLASSTYPE_LAMBDA_EXPR (t) = error_mark_node; + SET_CLASSTYPE_LAMBDA_EXPR (t, error_mark_node); t = pushtag (name, t, how); } else diff --git a/gcc/cp/error.cc b/gcc/cp/error.cc index abeb028..eb2ff33 100644 --- a/gcc/cp/error.cc +++ b/gcc/cp/error.cc @@ -810,6 +810,7 @@ dump_type (cxx_pretty_printer *pp, tree t, int flags) pp_cxx_ws_string (pp, TYPENAME_IS_ENUM_P (t) ? "enum" : TYPENAME_IS_CLASS_P (t) ? "class" + : TYPENAME_IS_UNION_P (t) ? "union" : "typename"); dump_typename (pp, t, flags); break; diff --git a/gcc/cp/except.cc b/gcc/cp/except.cc index a9d8e2f..a7f35e4 100644 --- a/gcc/cp/except.cc +++ b/gcc/cp/except.cc @@ -367,6 +367,8 @@ initialize_handler_parm (tree decl, tree exp) MUST_NOT_THROW_EXPR. */ init = fold_build_cleanup_point_expr (TREE_TYPE (init), init); init = build_must_not_throw_expr (init, NULL_TREE); + if (init && TREE_CODE (init) == MUST_NOT_THROW_EXPR) + MUST_NOT_THROW_CATCH_P (init) = 1; } decl = pushdecl (decl); @@ -523,6 +525,7 @@ begin_eh_spec_block (void) r = build_stmt (spec_location, MUST_NOT_THROW_EXPR, NULL_TREE, NULL_TREE); TREE_SIDE_EFFECTS (r) = 1; + MUST_NOT_THROW_NOEXCEPT_P (r) = 1; } else r = build_stmt (spec_location, EH_SPEC_BLOCK, NULL_TREE, NULL_TREE); @@ -614,6 +617,7 @@ wrap_cleanups_r (tree *tp, int *walk_subtrees, void * /*data*/) { cleanup = build2 (MUST_NOT_THROW_EXPR, void_type_node, cleanup, NULL_TREE); + MUST_NOT_THROW_THROW_P (cleanup) = 1; TARGET_EXPR_CLEANUP (exp) = cleanup; } @@ -712,6 +716,11 @@ build_throw (location_t loc, tree exp, tsubst_flags_t complain) allocate_expr = do_allocate_exception (temp_type); if (allocate_expr == error_mark_node) return error_mark_node; + /* Copy ptr inside of the CLEANUP_POINT_EXPR + added below to a TARGET_EXPR slot added outside of it, + otherwise during constant evaluation of throw expression + we'd diagnose accessing ptr outside of its lifetime. */ + tree ptr_copy = get_internal_target_expr (null_pointer_node); allocate_expr = get_internal_target_expr (allocate_expr); ptr = TARGET_EXPR_SLOT (allocate_expr); TARGET_EXPR_CLEANUP (allocate_expr) = do_free_exception (ptr); @@ -763,10 +772,17 @@ build_throw (location_t loc, tree exp, tsubst_flags_t complain) /* Prepend the allocation. */ exp = build2 (COMPOUND_EXPR, TREE_TYPE (exp), allocate_expr, exp); + exp = build2 (COMPOUND_EXPR, void_type_node, exp, + build2 (MODIFY_EXPR, void_type_node, + TARGET_EXPR_SLOT (ptr_copy), ptr)); + ptr = TARGET_EXPR_SLOT (ptr_copy); + /* Force all the cleanups to be evaluated here so that we don't have to do them during unwinding. */ exp = build1 (CLEANUP_POINT_EXPR, void_type_node, exp); + exp = build2 (COMPOUND_EXPR, TREE_TYPE (exp), ptr_copy, exp); + throw_type = build_eh_type_type (prepare_eh_type (TREE_TYPE (object))); cleanup = NULL_TREE; diff --git a/gcc/cp/lambda.cc b/gcc/cp/lambda.cc index 182cffa..525e8ef 100644 --- a/gcc/cp/lambda.cc +++ b/gcc/cp/lambda.cc @@ -150,7 +150,7 @@ begin_lambda_type (tree lambda) /* Cross-reference the expression and the type. */ LAMBDA_EXPR_CLOSURE (lambda) = type; - CLASSTYPE_LAMBDA_EXPR (type) = lambda; + SET_CLASSTYPE_LAMBDA_EXPR (type, lambda); /* In C++17, assume the closure is literal; we'll clear the flag later if necessary. */ diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index c8e79f3..689319a 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -9619,6 +9619,8 @@ trees_out::type_node (tree type) tag_type = enum_type; else if (TYPENAME_IS_CLASS_P (type)) tag_type = class_type; + else if (TYPENAME_IS_UNION_P (type)) + tag_type = union_type; u (int (tag_type)); } } @@ -13391,13 +13393,19 @@ trees_in::read_class_def (tree defn, tree maybe_template) if (TYPE_LANG_SPECIFIC (type)) { - CLASSTYPE_LAMBDA_EXPR (type) = lambda; + if (!TYPE_POLYMORPHIC_P (type)) + SET_CLASSTYPE_LAMBDA_EXPR (type, lambda); + else + gcc_checking_assert (lambda == NULL_TREE); CLASSTYPE_MEMBER_VEC (type) = member_vec; CLASSTYPE_PURE_VIRTUALS (type) = pure_virts; CLASSTYPE_VCALL_INDICES (type) = vcall_indices; - CLASSTYPE_KEY_METHOD (type) = key_method; + if (TYPE_POLYMORPHIC_P (type)) + SET_CLASSTYPE_KEY_METHOD (type, key_method); + else + gcc_checking_assert (key_method == NULL_TREE); CLASSTYPE_VBASECLASSES (type) = vbase_vec; diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index cac74e3..21bec72c 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -2519,7 +2519,7 @@ static cp_expr cp_parser_id_expression static cp_expr cp_parser_unqualified_id (cp_parser *, bool, bool, bool, bool); static tree cp_parser_nested_name_specifier_opt - (cp_parser *, bool, bool, bool, bool, bool = false); + (cp_parser *, bool, bool, bool, bool, bool = false, bool = false); static tree cp_parser_nested_name_specifier (cp_parser *, bool, bool, bool, bool); static tree cp_parser_qualifying_entity @@ -3091,8 +3091,8 @@ static cp_token *cp_parser_require_keyword (cp_parser *, enum rid, required_token); static bool cp_parser_token_starts_function_definition_p (cp_token *); -static bool cp_parser_next_token_starts_class_definition_p - (cp_parser *); +static bool cp_parser_nth_token_starts_class_definition_p + (cp_parser *, size_t); static bool cp_parser_next_token_ends_template_argument_p (cp_parser *); static bool cp_parser_nth_token_starts_template_argument_list_p @@ -7242,18 +7242,22 @@ check_template_keyword_in_nested_name_spec (tree name) nested-name-specifier template [opt] simple-template-id :: PARSER->SCOPE should be set appropriately before this function is - called. TYPENAME_KEYWORD_P is TRUE if the `typename' keyword is in - effect. TYPE_P is TRUE if we non-type bindings should be ignored - in name lookups. + called. TYPENAME_KEYWORD_P is true if the `typename' keyword is in + effect. TYPE_P is true if we non-type bindings should be ignored + in name lookups. TEMPLATE_KEYWORD_P is true if the `template' keyword + was seen. GLOBAL_P is true if `::' has already been parsed. + TODO: This function doesn't handle the C++14 change to make `::' + a nested-name-specifier by itself. If it did, GLOBAL_P could probably + go. Sets PARSER->SCOPE to the class (TYPE) or namespace (NAMESPACE_DECL) specified by the nested-name-specifier, or leaves it unchanged if there is no nested-name-specifier. Returns the new scope iff there is a nested-name-specifier, or NULL_TREE otherwise. - If CHECK_DEPENDENCY_P is FALSE, names are looked up in dependent scopes. + If CHECK_DEPENDENCY_P is false, names are looked up in dependent scopes. - If IS_DECLARATION is TRUE, the nested-name-specifier is known to be + If IS_DECLARATION is true, the nested-name-specifier is known to be part of a declaration and/or decl-specifier. */ static tree @@ -7262,7 +7266,8 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser, bool check_dependency_p, bool type_p, bool is_declaration, - bool template_keyword_p /* = false */) + bool template_keyword_p /* = false */, + bool global_p /* = false */) { bool success = false; cp_token_position start = 0; @@ -7310,8 +7315,9 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser, /* Spot cases that cannot be the beginning of a nested-name-specifier. On the second and subsequent times - through the loop, we look for the `template' keyword. */ - if (success && token->keyword == RID_TEMPLATE) + (or the first, if '::' has already been parsed) through the + loop, we look for the `template' keyword. */ + if ((success || global_p) && token->keyword == RID_TEMPLATE) ; /* A template-id can start a nested-name-specifier. */ else if (token->type == CPP_TEMPLATE_ID) @@ -7359,8 +7365,11 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser, cp_parser_parse_tentatively (parser); /* Look for the optional `template' keyword, if this isn't the - first time through the loop. */ - if (success) + first time through the loop, or if we've already parsed '::'; + this is then the + nested-name-specifier template [opt] simple-template-id :: + production. */ + if (success || global_p) { template_keyword_p = cp_parser_optional_template_keyword (parser); /* DR1710: "In a qualified-id used as the name in @@ -11829,6 +11838,7 @@ cp_parser_lambda_expression (cp_parser* parser) bool auto_is_implicit_function_template_parm_p = parser->auto_is_implicit_function_template_parm_p; bool saved_omp_array_section_p = parser->omp_array_section_p; + bool saved_in_targ = parser->in_template_argument_list_p; parser->num_template_parameter_lists = 0; parser->in_statement = 0; @@ -11838,6 +11848,7 @@ cp_parser_lambda_expression (cp_parser* parser) parser->implicit_template_scope = 0; parser->auto_is_implicit_function_template_parm_p = false; parser->omp_array_section_p = false; + parser->in_template_argument_list_p = false; /* Inside the lambda, outside unevaluated context do not apply. */ cp_evaluated ev; @@ -11892,6 +11903,7 @@ cp_parser_lambda_expression (cp_parser* parser) parser->auto_is_implicit_function_template_parm_p = auto_is_implicit_function_template_parm_p; parser->omp_array_section_p = saved_omp_array_section_p; + parser->in_template_argument_list_p = saved_in_targ; } /* This lambda shouldn't have any proxies left at this point. */ @@ -16870,7 +16882,11 @@ cp_parser_decomposition_declaration (cp_parser *parser, decl = error_mark_node; } else - prev = decl2; + { + prev = decl2; + DECL_DECLARED_CONSTEXPR_P (decl2) = DECL_DECLARED_CONSTEXPR_P (decl); + DECL_DECLARED_CONSTINIT_P (decl2) = DECL_DECLARED_CONSTINIT_P (decl); + } if (elt_pushed_scope) pop_scope (elt_pushed_scope); } @@ -16919,6 +16935,15 @@ cp_parser_decomposition_declaration (cp_parser *parser, /* Ensure DECL_VALUE_EXPR is created for all the decls but the underlying DECL. */ cp_finish_decomp (decl, &decomp); + if (decl_spec_seq_has_spec_p (decl_specifiers, ds_thread)) + pedwarn (decl_specifiers->locations[ds_thread], + 0, "for-range-declaration cannot be %qs", + decl_specifiers->gnu_thread_keyword_p + ? "__thread" : "thread_local"); + else if (decl_specifiers->storage_class == sc_static) + pedwarn (decl_specifiers->locations[ds_storage_class], + 0, "for-range-declaration cannot be %qs", + "static"); } if (pushed_scope) @@ -21012,9 +21037,6 @@ cp_parser_simple_type_specifier (cp_parser* parser, "only available with " "%<-std=c++14%> or %<-std=gnu++14%>"); } - else if (parser->in_template_argument_list_p) - error_at (token->location, - "use of %<auto%> in template argument"); else if (!flag_concepts) pedwarn (token->location, OPT_Wc__20_extensions, "use of %<auto%> in parameter declaration " @@ -21024,6 +21046,11 @@ cp_parser_simple_type_specifier (cp_parser* parser, "use of %<auto%> in parameter declaration " "only available with " "%<-std=c++14%> or %<-std=gnu++14%>"); + + if (parser->in_template_argument_list_p) + permerror_opt (token->location, + OPT_Wabbreviated_auto_in_template_arg, + "use of %<auto%> in template argument"); } else type = make_auto (); @@ -21152,7 +21179,9 @@ cp_parser_simple_type_specifier (cp_parser* parser, /*typename_keyword_p=*/false, /*check_dependency_p=*/true, /*type_p=*/false, - /*is_declaration=*/false) + /*is_declaration=*/false, + /*template_keyword_p=*/false, + global_p) != NULL_TREE); /* If we have seen a nested-name-specifier, and the next token is `template', then we are using the template-id production. */ @@ -21470,6 +21499,10 @@ cp_parser_placeholder_type_specifier (cp_parser *parser, location_t loc, error_at (loc, "cannot declare a parameter with %<decltype(auto)%>"); return error_mark_node; } + if (parser->in_template_argument_list_p) + permerror_opt (placeholder->location, + OPT_Wabbreviated_auto_in_template_arg, + "use of %<auto%> in template argument"); tree parm = build_constrained_parameter (con, proto, args); return synthesize_implicit_template_parm (parser, parm); } @@ -21998,7 +22031,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser, bool template_p = (template_parm_lists_apply - && (cp_parser_next_token_starts_class_definition_p (parser) + && (cp_parser_nth_token_starts_class_definition_p (parser, 1) || cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))); /* An unqualified name was used to reference this type, so there were no qualifying templates. */ @@ -24162,7 +24195,26 @@ cp_parser_init_declarator (cp_parser* parser, && token->type != CPP_SEMICOLON) { if (maybe_range_for_decl && *maybe_range_for_decl != error_mark_node) - range_for_decl_p = true; + { + range_for_decl_p = true; + if (decl_spec_seq_has_spec_p (decl_specifiers, ds_thread)) + pedwarn (decl_specifiers->locations[ds_thread], + 0, "for-range-declaration cannot be %qs", + decl_specifiers->gnu_thread_keyword_p + ? "__thread" : "thread_local"); + else if (decl_specifiers->storage_class == sc_static) + pedwarn (decl_specifiers->locations[ds_storage_class], + 0, "for-range-declaration cannot be %qs", + "static"); + else if (decl_specifiers->storage_class == sc_extern) + pedwarn (decl_specifiers->locations[ds_storage_class], + 0, "for-range-declaration cannot be %qs", + "extern"); + else if (decl_specifiers->storage_class == sc_register) + pedwarn (decl_specifiers->locations[ds_storage_class], + 0, "for-range-declaration cannot be %qs", + "register"); + } else { if (!maybe_range_for_decl) @@ -28016,6 +28068,64 @@ cp_parser_class_specifier (cp_parser* parser) return type; } +/* Parse an (optional) class-property-specifier-seq. + + class-property-specifier-seq: + class-property-specifier class-property-specifier-seq [opt] + + class-property-specifier: + final + + Returns a bitmask representing the class-property-specifiers. */ + +static cp_virt_specifiers +cp_parser_class_property_specifier_seq_opt (cp_parser *parser) +{ + cp_virt_specifiers virt_specifiers = VIRT_SPEC_UNSPECIFIED; + + while (true) + { + cp_token *token; + cp_virt_specifiers virt_specifier; + + /* Peek at the next token. */ + token = cp_lexer_peek_token (parser->lexer); + /* See if it's a class-property-specifier. */ + if (token->type != CPP_NAME) + break; + if (id_equal (token->u.value, "final")) + { + /* For C++98, quietly ignore final in e.g. + struct S final = 24; */ + if (cxx_dialect == cxx98 + && virt_specifiers == VIRT_SPEC_UNSPECIFIED + && !cp_parser_nth_token_starts_class_definition_p (parser, 2) + && !cp_lexer_nth_token_is (parser->lexer, 2, CPP_NAME)) + break; + maybe_warn_cpp0x (CPP0X_OVERRIDE_CONTROLS); + virt_specifier = VIRT_SPEC_FINAL; + } + else if (id_equal (token->u.value, "__final")) + virt_specifier = VIRT_SPEC_FINAL; + else + break; + + if (virt_specifiers & virt_specifier) + { + gcc_rich_location richloc (token->location); + richloc.add_fixit_remove (); + error_at (&richloc, "duplicate %qD specifier", token->u.value); + cp_lexer_purge_token (parser->lexer); + } + else + { + cp_lexer_consume_token (parser->lexer); + virt_specifiers |= virt_specifier; + } + } + return virt_specifiers; +} + /* Parse a class-head. class-head: @@ -28206,18 +28316,16 @@ cp_parser_class_head (cp_parser* parser, pop_deferring_access_checks (); if (id) - { - cp_parser_check_for_invalid_template_id (parser, id, - class_key, - type_start_token->location); - } - virt_specifiers = cp_parser_virt_specifier_seq_opt (parser); + cp_parser_check_for_invalid_template_id (parser, id, + class_key, + type_start_token->location); + virt_specifiers = cp_parser_class_property_specifier_seq_opt (parser); /* If it's not a `:' or a `{' then we can't really be looking at a class-head, since a class-head only appears as part of a class-specifier. We have to detect this situation before calling xref_tag, since that has irreversible side-effects. */ - if (!cp_parser_next_token_starts_class_definition_p (parser)) + if (!cp_parser_nth_token_starts_class_definition_p (parser, 1)) { cp_parser_error (parser, "expected %<{%> or %<:%>"); type = error_mark_node; @@ -28227,13 +28335,6 @@ cp_parser_class_head (cp_parser* parser, /* At this point, we're going ahead with the class-specifier, even if some other problem occurs. */ cp_parser_commit_to_tentative_parse (parser); - if (virt_specifiers & VIRT_SPEC_OVERRIDE) - { - cp_parser_error (parser, - "cannot specify %<override%> for a class"); - type = error_mark_node; - goto out; - } /* Issue the error about the overly-qualified name now. */ if (qualified_p) { @@ -35602,15 +35703,15 @@ cp_parser_token_starts_function_definition_p (cp_token* token) || token->keyword == RID_RETURN); } -/* Returns TRUE iff the next token is the ":" or "{" beginning a class +/* Returns TRUE iff the Nth token is the ":" or "{" beginning a class definition. */ static bool -cp_parser_next_token_starts_class_definition_p (cp_parser *parser) +cp_parser_nth_token_starts_class_definition_p (cp_parser *parser, size_t n) { cp_token *token; - token = cp_lexer_peek_token (parser->lexer); + token = cp_lexer_peek_nth_token (parser->lexer, n); return (token->type == CPP_OPEN_BRACE || (token->type == CPP_COLON && !parser->colon_doesnt_start_class_def_p)); @@ -35890,7 +35991,9 @@ cp_parser_check_class_key (cp_parser *parser, location_t key_loc, return; bool seen_as_union = TREE_CODE (type) == UNION_TYPE; - if (seen_as_union != (class_key == union_type)) + if (class_key != typename_type + && TREE_CODE (type) != TYPENAME_TYPE + && seen_as_union != (class_key == union_type)) { auto_diagnostic_group d; if (permerror (input_location, "%qs tag used in naming %q#T", diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 3362a6f..8f3822c 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -17250,13 +17250,14 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) return error_mark_node; } - /* FIXME: TYPENAME_IS_CLASS_P conflates 'class' vs 'struct' vs 'union' - tags. TYPENAME_TYPE should probably remember the exact tag that - was written. */ + /* FIXME: TYPENAME_IS_CLASS_P conflates 'class' vs 'struct' tags. + TYPENAME_TYPE should probably remember the exact tag that + was written for -Wmismatched-tags. */ enum tag_types tag_type - = TYPENAME_IS_CLASS_P (t) ? class_type - : TYPENAME_IS_ENUM_P (t) ? enum_type - : typename_type; + = (TYPENAME_IS_CLASS_P (t) ? class_type + : TYPENAME_IS_UNION_P (t) ? union_type + : TYPENAME_IS_ENUM_P (t) ? enum_type + : typename_type); tsubst_flags_t tcomplain = complain | tf_keep_type_decl; tcomplain |= tst_ok_flag | qualifying_scope_flag; f = make_typename_type (ctx, f, tag_type, tcomplain); @@ -17278,10 +17279,18 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) else return error_mark_node; } - else if (TYPENAME_IS_CLASS_P (t) && !CLASS_TYPE_P (f)) + else if (TYPENAME_IS_CLASS_P (t) && !NON_UNION_CLASS_TYPE_P (f)) { if (complain & tf_error) - error ("%qT resolves to %qT, which is not a class type", + error ("%qT resolves to %qT, which is not a non-union " + "class type", t, f); + else + return error_mark_node; + } + else if (TYPENAME_IS_UNION_P (t) && !UNION_TYPE_P (f)) + { + if (complain & tf_error) + error ("%qT resolves to %qT, which is not a union type", t, f); else return error_mark_node; @@ -20138,7 +20147,14 @@ tsubst_stmt (tree t, tree args, tsubst_flags_t complain, tree in_decl) { tree op0 = RECUR (TREE_OPERAND (t, 0)); tree cond = RECUR (MUST_NOT_THROW_COND (t)); - RETURN (build_must_not_throw_expr (op0, cond)); + stmt = build_must_not_throw_expr (op0, cond); + if (stmt && TREE_CODE (stmt) == MUST_NOT_THROW_EXPR) + { + MUST_NOT_THROW_NOEXCEPT_P (stmt) = MUST_NOT_THROW_NOEXCEPT_P (t); + MUST_NOT_THROW_THROW_P (stmt) = MUST_NOT_THROW_THROW_P (t); + MUST_NOT_THROW_CATCH_P (stmt) = MUST_NOT_THROW_CATCH_P (t); + } + RETURN (stmt); } case EXPR_PACK_EXPANSION: diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc index 28baf7b..b57547c 100644 --- a/gcc/cp/semantics.cc +++ b/gcc/cp/semantics.cc @@ -3605,11 +3605,13 @@ finish_this_expr (void) { tree result = NULL_TREE; - if (current_class_type && LAMBDA_TYPE_P (current_class_type)) + if (current_class_ref && !LAMBDA_TYPE_P (TREE_TYPE (current_class_ref))) + result = current_class_ptr; + else if (current_class_type && LAMBDA_TYPE_P (current_class_type)) result = (lambda_expr_this_capture (CLASSTYPE_LAMBDA_EXPR (current_class_type), /*add*/true)); - else if (current_class_ptr) - result = current_class_ptr; + else + gcc_checking_assert (!current_class_ptr); if (result) /* The keyword 'this' is a prvalue expression. */ diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc index 5863b68..accce0e 100644 --- a/gcc/cp/tree.cc +++ b/gcc/cp/tree.cc @@ -488,6 +488,7 @@ builtin_valid_in_constant_expr_p (const_tree decl) case CP_BUILT_IN_SOURCE_LOCATION: case CP_BUILT_IN_IS_CORRESPONDING_MEMBER: case CP_BUILT_IN_IS_POINTER_INTERCONVERTIBLE_WITH_CLASS: + case CP_BUILT_IN_EH_PTR_ADJUST_REF: return true; default: break; diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 70adf2d..8c29e24 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -7138,11 +7138,9 @@ The @code{aligned} attribute can also be used for functions @cindex @code{counted_by} variable attribute @item counted_by (@var{count}) The @code{counted_by} attribute may be attached to the C99 flexible array -member, or a pointer field of a structure. It indicates that the number -of the elements of the array that is held by the flexible array member -field, or is pointed to by the pointer field, is given by the field -"@var{count}" in the same structure as the flexible array member or the -pointer field. +member of a structure. It indicates that the number of the elements of the +array is given by the field "@var{count}" in the same structure as the +flexible array member. This attribute is available only in C for now. In C++ this attribute is ignored. @@ -7163,22 +7161,8 @@ struct P @{ @end smallexample @noindent -specifies that the @code{array} is a flexible array member whose number -of elements is given by the field @code{count} in the same structure. - -@smallexample -struct PP @{ - size_t count2; - char other1; - char *array2 __attribute__ ((counted_by (count2))); - int other2; -@} *pp; -@end smallexample - -@noindent -specifies that the @code{array2} is an array that is pointed by the -pointer field, and its number of elements is given by the field -@code{count2} in the same structure. +specifies that the @code{array} is a flexible array member whose number of +elements is given by the field @code{count} in the same structure. The field that represents the number of the elements should have an integer type. Otherwise, the compiler reports an error and ignores @@ -7187,12 +7171,6 @@ the attribute. When the field that represents the number of the elements is assigned a negative integer value, the compiler treats the value as zero. -The @code{counted_by} attribute is not allowed for a pointer to @code{void}, -a pointer to function, or a pointer to a structure or union that includes -a flexible array member. However, it is allowed for a pointer to -non-void incomplete structure or union types, as long as the type could -be completed before the first reference to the pointer. - An explicit @code{counted_by} annotation defines a relationship between two objects, @code{p->array} and @code{p->count}, and there are the following requirements on the relationship between this pair: @@ -7208,13 +7186,6 @@ available all the time. This relationship must hold even after any of these related objects are updated during the program. @end itemize -In addition to the above requirements, there is one more requirement -between this pair if and only if @code{p->array} is an array that is -pointed by the pointer field: - -@code{p->array} and @code{p->count} can only be changed by changing the -whole structure at the same time. - It's the programmer's responsibility to make sure the above requirements to be kept all the time. Otherwise the compiler reports warnings and the results of the array bound sanitizer and the @@ -7236,8 +7207,6 @@ In the above, @code{ref1} uses @code{val1} as the number of the elements in @code{p->array}, and @code{ref2} uses @code{val2} as the number of elements in @code{p->array}. -Note, however, the above feature is not valid for the pointer field. - @cindex @code{alloc_size} variable attribute @item alloc_size (@var{position}) @itemx alloc_size (@var{position-1}, @var{position-2}) @@ -15553,7 +15522,7 @@ are 128-bit. Only supported on targets when 128-bit types are supported. Returns the calculated 8-bit bit-reversed CRC using the initial CRC (8-bit), data (8-bit) and the polynomial (8-bit). @var{crc} is the initial CRC, @var{data} is the data and -@var{poly} is the polynomial without leading 1. +@var{poly} is the polynomial without leading 1. @var{poly} is required to be a compile-time constant. Table-based or clmul-based CRC may be used for the calculation, depending on the target architecture. @enddefbuiltin @@ -15608,7 +15577,7 @@ is 32-bit. Returns the calculated 8-bit bit-forward CRC using the initial CRC (8-bit), data (8-bit) and the polynomial (8-bit). @var{crc} is the initial CRC, @var{data} is the data and -@var{poly} is the polynomial without leading 1. +@var{poly} is the polynomial without leading 1. @var{poly} is required to be a compile-time constant. Table-based or clmul-based CRC may be used for the calculation, depending on the target architecture. @enddefbuiltin diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 7640e7d..74f5ee2 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -3816,6 +3816,23 @@ Warn when a type with an ABI tag is used in a context that does not have that ABI tag. See @ref{C++ Attributes} for more information about ABI tags. +@opindex Wabbreviated-auto-in-template-arg +@opindex Wno-abbreviated-auto-in-template-arg +@item -Wno-abbreviated-auto-in-template-arg +Disable the error for an @code{auto} placeholder type used within a +template argument list to declare a C++20 abbreviated function +template, e.g. + +@smallexample +void f(S<auto>); +@end smallexample + +This feature was proposed in the Concepts TS, but was not adopted into +C++20; in the standard, a placeholder in a parameter declaration must +appear as a decl-specifier. The error can also be reduced to a +warning by @option{-fpermissive} or +@option{-Wno-error=abbreviated-auto-in-template-arg}. + @opindex Wcomma-subscript @opindex Wno-comma-subscript @item -Wcomma-subscript @r{(C++ and Objective-C++ only)} @@ -6443,6 +6460,7 @@ only by this flag, but it also downgrades some C and C++ diagnostics that have their own flag: @gccoptlist{ +-Wabbreviated-auto-in-template-arg @r{(C++ and Objective-C++ only)} -Wdeclaration-missing-parameter-type @r{(C and Objective-C only)} -Wimplicit-function-declaration @r{(C and Objective-C only)} -Wimplicit-int @r{(C and Objective-C only)} diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi index 6c5586e..85fb810 100644 --- a/gcc/doc/sourcebuild.texi +++ b/gcc/doc/sourcebuild.texi @@ -2373,6 +2373,12 @@ whether it does so by default). @itemx aarch64_sve1024_hw @itemx aarch64_sve2048_hw Like @code{aarch64_sve_hw}, but also test for an exact hardware vector length. +@item aarch64_sve2_hw +AArch64 target that is able to generate and execute SVE2 code (regardless of +whether it does so by default). +@item aarch64_sve2p1_hw +AArch64 target that is able to generate and execute SVE2.1 code (regardless of +whether it does so by default). @item aarch64_fjcvtzs_hw AArch64 target that is able to generate and execute armv8.3-a FJCVTZS diff --git a/gcc/ext-dce.cc b/gcc/ext-dce.cc index afe7afe..67ec92a 100644 --- a/gcc/ext-dce.cc +++ b/gcc/ext-dce.cc @@ -651,9 +651,8 @@ ext_dce_process_uses (rtx_insn *insn, rtx obj, /* ?!? How much of this should mirror SET handling, potentially being shared? */ - if (SUBREG_P (dst) && SUBREG_BYTE (dst).is_constant ()) + if (SUBREG_P (dst) && subreg_lsb (dst).is_constant (&bit)) { - bit = subreg_lsb (dst).to_constant (); if (bit >= HOST_BITS_PER_WIDE_INT) bit = HOST_BITS_PER_WIDE_INT - 1; dst = SUBREG_REG (dst); @@ -758,7 +757,7 @@ ext_dce_process_uses (rtx_insn *insn, rtx obj, and process the inner object. */ if (paradoxical_subreg_p (y)) y = XEXP (y, 0); - else if (SUBREG_P (y) && SUBREG_BYTE (y).is_constant ()) + else if (SUBREG_P (y) && subreg_lsb (y).is_constant (&bit)) { /* If !TRULY_NOOP_TRUNCATION_MODES_P, the mode change performed by Y would normally need to be a @@ -775,8 +774,6 @@ ext_dce_process_uses (rtx_insn *insn, rtx obj, GET_MODE (SUBREG_REG (y)))))) break; - bit = subreg_lsb (y).to_constant (); - /* If this is a wide object (more bits than we can fit in a HOST_WIDE_INT), then just break from the SET context. That will cause the iterator to walk down diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index ea366b1..168c475 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,14 @@ +2025-07-08 Andre Vehreschild <vehre@gcc.gnu.org> + + PR fortran/120637 + * class.cc (finalize_component): Return true, when a finalizable + component was detect and do not free it. + +2025-07-07 Mikael Morin <mikael@gcc.gnu.org> + + * trans-intrinsic.cc (conv_intrinsic_move_alloc): Add pre and + post code for the FROM and TO arguments. + 2025-07-04 Martin Jambor <mjambor@suse.cz> * io.cc (format_asterisk): Add a brace around static initialization diff --git a/gcc/fortran/class.cc b/gcc/fortran/class.cc index df18601..a1c6faf 100644 --- a/gcc/fortran/class.cc +++ b/gcc/fortran/class.cc @@ -1034,7 +1034,7 @@ comp_is_finalizable (gfc_component *comp) of calling the appropriate finalizers, coarray deregistering, and deallocation of allocatable subcomponents. */ -static void +static bool finalize_component (gfc_expr *expr, gfc_symbol *derived, gfc_component *comp, gfc_symbol *stat, gfc_symbol *fini_coarray, gfc_code **code, gfc_namespace *sub_ns) @@ -1044,14 +1044,14 @@ finalize_component (gfc_expr *expr, gfc_symbol *derived, gfc_component *comp, gfc_was_finalized *f; if (!comp_is_finalizable (comp)) - return; + return false; /* If this expression with this component has been finalized already in this namespace, there is nothing to do. */ for (f = sub_ns->was_finalized; f; f = f->next) { if (f->e == expr && f->c == comp) - return; + return false; } e = gfc_copy_expr (expr); @@ -1208,8 +1208,6 @@ finalize_component (gfc_expr *expr, gfc_symbol *derived, gfc_component *comp, final_wrap->ext.actual->next->next = gfc_get_actual_arglist (); final_wrap->ext.actual->next->next->expr = fini_coarray_expr; - - if (*code) { (*code)->next = final_wrap; @@ -1221,11 +1219,14 @@ finalize_component (gfc_expr *expr, gfc_symbol *derived, gfc_component *comp, else { gfc_component *c; + bool ret = false; for (c = comp->ts.u.derived->components; c; c = c->next) - finalize_component (e, comp->ts.u.derived, c, stat, fini_coarray, code, - sub_ns); - gfc_free_expr (e); + ret |= finalize_component (e, comp->ts.u.derived, c, stat, fini_coarray, + code, sub_ns); + /* Only free the expression, if it has never been used. */ + if (!ret) + gfc_free_expr (e); } /* Record that this was finalized already in this namespace. */ @@ -1234,6 +1235,7 @@ finalize_component (gfc_expr *expr, gfc_symbol *derived, gfc_component *comp, sub_ns->was_finalized->e = expr; sub_ns->was_finalized->c = comp; sub_ns->was_finalized->next = f; + return true; } @@ -2314,6 +2316,7 @@ finish_assumed_rank: { gfc_symbol *stat; gfc_code *block = NULL; + gfc_expr *ptr_expr; if (!ptr) { @@ -2359,14 +2362,15 @@ finish_assumed_rank: sub_ns); block = block->next; + ptr_expr = gfc_lval_expr_from_sym (ptr); for (comp = derived->components; comp; comp = comp->next) { if (comp == derived->components && derived->attr.extension && ancestor_wrapper && ancestor_wrapper->expr_type != EXPR_NULL) continue; - finalize_component (gfc_lval_expr_from_sym (ptr), derived, comp, - stat, fini_coarray, &block, sub_ns); + finalize_component (ptr_expr, derived, comp, stat, fini_coarray, + &block, sub_ns); if (!last_code->block->next) last_code->block->next = block; } diff --git a/gcc/fortran/trans-intrinsic.cc b/gcc/fortran/trans-intrinsic.cc index f1bfd3e..be98427 100644 --- a/gcc/fortran/trans-intrinsic.cc +++ b/gcc/fortran/trans-intrinsic.cc @@ -13101,6 +13101,8 @@ conv_intrinsic_move_alloc (gfc_code *code) } gfc_conv_expr_descriptor (&to_se, to_expr); gfc_conv_expr_descriptor (&from_se, from_expr); + gfc_add_block_to_block (&block, &to_se.pre); + gfc_add_block_to_block (&block, &from_se.pre); /* For coarrays, call SYNC ALL if TO is already deallocated as MOVE_ALLOC is an image control "statement", cf. IR F08/0040 in 12-006A. */ @@ -13174,6 +13176,9 @@ conv_intrinsic_move_alloc (gfc_code *code) if (fin_label) gfc_add_expr_to_block (&block, build1_v (LABEL_EXPR, fin_label)); + gfc_add_block_to_block (&block, &to_se.post); + gfc_add_block_to_block (&block, &from_se.post); + return gfc_finish_block (&block); } diff --git a/gcc/gimple-ssa-sccopy.cc b/gcc/gimple-ssa-sccopy.cc index 341bae4..e65f532 100644 --- a/gcc/gimple-ssa-sccopy.cc +++ b/gcc/gimple-ssa-sccopy.cc @@ -78,7 +78,7 @@ along with GCC; see the file COPYING3. If not see To find all three types of copy statements we use an algorithm based on strongly-connected components (SCCs) in dataflow graph. The algorithm was - introduced in an article from 2013[1]. We describe the algorithm bellow. + introduced in an article from 2013[1]. We describe the algorithm below. To identify SCCs we implement the Robert Tarjan's SCC algorithm. For the SCC computation we wrap potential copy statements in the 'vertex' struct. diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index b6fdf72..99bf24c 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -f5c453aa726ebb509e7b8cb20df7734f0e411404 +c4d7bfb9895efc196b04f18f5da77fd99b39212a The first line of this file holds the git revision number of the last merge done from the gofrontend repository. diff --git a/gcc/graphite.h b/gcc/graphite.h index 66d4db6..9cb3513 100644 --- a/gcc/graphite.h +++ b/gcc/graphite.h @@ -155,7 +155,7 @@ struct poly_dr The OpenScop access function is printed as follows: | 1 # The number of disjunct components in a union of access functions. - | R C O I L P # Described bellow. + | R C O I L P # Described below. | a s0 s1 i j k 1 | 1 0 0 0 0 0 -5 = 0 | 0 1 0 -1 0 0 0 = 0 diff --git a/gcc/internal-fn.cc b/gcc/internal-fn.cc index 3f4ac93..044bdc2 100644 --- a/gcc/internal-fn.cc +++ b/gcc/internal-fn.cc @@ -3442,25 +3442,23 @@ expand_DEFERRED_INIT (internal_fn, gcall *stmt) } /* Expand the IFN_ACCESS_WITH_SIZE function: - ACCESS_WITH_SIZE (REF_TO_OBJ, REF_TO_SIZE, CLASS_OF_SIZE, - TYPE_OF_SIZE, ACCESS_MODE) + ACCESS_WITH_SIZE (REF_TO_OBJ, REF_TO_SIZE, + TYPE_OF_SIZE + ACCESS_MODE, TYPE_SIZE_UNIT for element) which returns the REF_TO_OBJ same as the 1st argument; 1st argument REF_TO_OBJ: The reference to the object; 2nd argument REF_TO_SIZE: The reference to the size of the object, - 3rd argument CLASS_OF_SIZE: The size referenced by the REF_TO_SIZE represents - 0: the number of bytes. - 1: the number of the elements of the object type; - 4th argument TYPE_OF_SIZE: A constant 0 with its TYPE being the same as the TYPE - of the object referenced by REF_TO_SIZE - 5th argument ACCESS_MODE: - -1: Unknown access semantics - 0: none - 1: read_only - 2: write_only - 3: read_write - 6th argument: A constant 0 with the pointer TYPE to the original flexible - array type. + 3rd argument TYPE_OF_SIZE + ACCESS_MODE: An integer constant with a pointer + TYPE. + The pointee TYPE of the pointer TYPE is the TYPE of the object referenced + by REF_TO_SIZE. + The integer constant value represents the ACCESS_MODE: + 0: none + 1: read_only + 2: write_only + 3: read_write + + 4th argument: The TYPE_SIZE_UNIT of the element TYPE of the array. Both the return type and the type of the first argument of this function have been converted from the incomplete array type to @@ -4031,9 +4029,14 @@ expand_crc_optab_fn (internal_fn fn, gcall *stmt, convert_optab optab) rtx dest = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE); rtx crc = expand_normal (rhs1); rtx data = expand_normal (rhs2); - gcc_assert (TREE_CODE (rhs3) == INTEGER_CST); - rtx polynomial = gen_rtx_CONST_INT (TYPE_MODE (result_type), - TREE_INT_CST_LOW (rhs3)); + rtx polynomial; + if (TREE_CODE (rhs3) != INTEGER_CST) + { + error ("third argument to %<crc%> builtins must be a constant"); + polynomial = const0_rtx; + } + else + polynomial = convert_to_mode (TYPE_MODE (result_type), expand_normal (rhs3), 0); /* Use target specific expansion if it exists. Otherwise, generate table-based CRC. */ @@ -4423,6 +4426,7 @@ commutative_binary_fn_p (internal_fn fn) case IFN_ADD_OVERFLOW: case IFN_MUL_OVERFLOW: case IFN_SAT_ADD: + case IFN_SAT_MUL: case IFN_VEC_WIDEN_PLUS: case IFN_VEC_WIDEN_PLUS_LO: case IFN_VEC_WIDEN_PLUS_HI: diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def index 8edfa35..d2480a1 100644 --- a/gcc/internal-fn.def +++ b/gcc/internal-fn.def @@ -282,6 +282,7 @@ DEF_INTERNAL_SIGNED_OPTAB_FN (MULHRS, ECF_CONST | ECF_NOTHROW, first, DEF_INTERNAL_SIGNED_OPTAB_FN (SAT_ADD, ECF_CONST, first, ssadd, usadd, binary) DEF_INTERNAL_SIGNED_OPTAB_FN (SAT_SUB, ECF_CONST, first, sssub, ussub, binary) +DEF_INTERNAL_SIGNED_OPTAB_FN (SAT_MUL, ECF_CONST, first, ssmul, usmul, binary) DEF_INTERNAL_SIGNED_OPTAB_FN (SAT_TRUNC, ECF_CONST, first, sstrunc, ustrunc, unary_convert) @@ -524,7 +525,7 @@ DEF_INTERNAL_FN (DEFERRED_INIT, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL) /* A function to associate the access size and access mode information with the corresponding reference to an object. It only reads from the - 2nd argument. */ + 2nd and the 4th arguments. */ DEF_INTERNAL_FN (ACCESS_WITH_SIZE, ECF_PURE | ECF_LEAF | ECF_NOTHROW, NULL) /* DIM_SIZE and DIM_POS return the size of a particular compute diff --git a/gcc/ipa-devirt.cc b/gcc/ipa-devirt.cc index 532e25e..18cb5a8 100644 --- a/gcc/ipa-devirt.cc +++ b/gcc/ipa-devirt.cc @@ -1763,7 +1763,7 @@ add_type_duplicate (odr_type val, tree type) } /* One base is polymorphic and the other not. This ought to be diagnosed earlier, but do not ICE in the - checking bellow. */ + checking below. */ else if (TYPE_BINFO (type1) && polymorphic_type_binfo_p (TYPE_BINFO (type1)) != polymorphic_type_binfo_p (TYPE_BINFO (type2))) diff --git a/gcc/ipa-inline-transform.cc b/gcc/ipa-inline-transform.cc index 07a1024..9d759d2 100644 --- a/gcc/ipa-inline-transform.cc +++ b/gcc/ipa-inline-transform.cc @@ -331,7 +331,7 @@ inline_call (struct cgraph_edge *e, bool update_original, int estimated_growth = 0; if (! update_overall_summary) estimated_growth = estimate_edge_growth (e); - /* This is used only for assert bellow. */ + /* This is used only for assert below. */ #if 0 bool predicated = inline_edge_summary (e)->predicate != NULL; #endif diff --git a/gcc/ipa-polymorphic-call.cc b/gcc/ipa-polymorphic-call.cc index 7b105f1..09316de 100644 --- a/gcc/ipa-polymorphic-call.cc +++ b/gcc/ipa-polymorphic-call.cc @@ -1353,7 +1353,7 @@ record_known_type (struct type_change_info *tci, tree type, HOST_WIDE_INT offset /* If we found a constructor of type that is not polymorphic or that may contain the type in question as a field (not as base), - restrict to the inner class first to make type matching bellow + restrict to the inner class first to make type matching below happier. */ if (type && (offset diff --git a/gcc/ipa-reference.cc b/gcc/ipa-reference.cc index 2d8e62f..975341c 100644 --- a/gcc/ipa-reference.cc +++ b/gcc/ipa-reference.cc @@ -732,7 +732,7 @@ get_read_write_all_from_node (struct cgraph_node *node, /* Skip edges from and to nodes without ipa_reference enabled. Ignore not available symbols. This leave them out of strongly connected components and makes them easy to skip in the - propagation loop bellow. */ + propagation loop below. */ static bool ignore_edge_p (cgraph_edge *e) diff --git a/gcc/loop-unroll.cc b/gcc/loop-unroll.cc index 6149cec..c80a6cb 100644 --- a/gcc/loop-unroll.cc +++ b/gcc/loop-unroll.cc @@ -1185,7 +1185,7 @@ decide_unroll_stupid (class loop *loop, int flags) /* Do not unroll loops with branches inside -- it increases number of mispredicts. - TODO: this heuristic needs tunning; call inside the loop body + TODO: this heuristic needs tuning; call inside the loop body is also relatively good reason to not unroll. */ if (num_loop_branches (loop) > 1) { diff --git a/gcc/match.pd b/gcc/match.pd index 10c2b97..67b33ee 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -3583,6 +3583,37 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) || (wi::eq_p (int_cst_1, itype_max) && wi::eq_p (int_cst_2, limit_1))) && wi::eq_p (int_cst_3, otype_max))))))) +/* Saturation mult for unsigned integer. */ +(if (INTEGRAL_TYPE_P (type) && TYPE_UNSIGNED (type)) + (match (unsigned_integer_sat_mul @0 @1) + /* SAT_U_MUL (X, Y) = { + WT x = (WT)a * (WT)b; + T max = -1; + if (x > (WT)(max)) + return max; + else + return (T)x; + } + while WT is uint128_t, T is uint8_t, uint16_t, uint32_t or uint64_t. */ + (convert@4 (min (widen_mult:c@3 (convert@5 (convert @0)) + (convert@6 (convert @1))) + INTEGER_CST@2)) + (if (types_match (type, @0, @1) && types_match (type, @4)) + (with + { + unsigned prec = TYPE_PRECISION (type); + unsigned widen_prec = TYPE_PRECISION (TREE_TYPE (@3)); + unsigned cvt5_prec = TYPE_PRECISION (TREE_TYPE (@5)); + unsigned cvt6_prec = TYPE_PRECISION (TREE_TYPE (@6)); + unsigned hw_int_prec = sizeof (HOST_WIDE_INT) * 8; + wide_int c2 = wi::to_wide (@2); + wide_int max = wi::mask (prec, false, widen_prec); + bool c2_is_max_p = wi::eq_p (c2, max); + bool widen_mult_p = cvt5_prec == cvt6_prec && hw_int_prec == cvt5_prec; + } + (if (widen_prec > prec && c2_is_max_p && widen_mult_p))))) +) + /* The boundary condition for case 10: IMM = 1: SAT_U_SUB = X >= IMM ? (X - IMM) : 0. simplify (X != 0 ? X + ~0 : 0) to X - (X != 0). */ @@ -3685,6 +3716,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (if ((TREE_CODE (@1) == INTEGER_CST && TREE_CODE (@2) == INTEGER_CST) || ((INTEGRAL_TYPE_P (TREE_TYPE (@1)) + || (VECTOR_TYPE_P (TREE_TYPE (@1)) + && expand_vec_cmp_expr_p (TREE_TYPE (@1), type, code2)) || POINTER_TYPE_P (TREE_TYPE (@1))) && bitwise_equal_p (@1, @2))) (with @@ -3723,27 +3756,39 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (if (code1 == EQ_EXPR && val) @3) (if (code1 == EQ_EXPR && !val) { constant_boolean_node (false, type); }) (if (code1 == NE_EXPR && !val && allbits) @4) - (if (code1 == NE_EXPR + (if ((code1 == NE_EXPR && code2 == GE_EXPR && cmp == 0 && allbits) + && ((VECTOR_BOOLEAN_TYPE_P (type) + && expand_vec_cmp_expr_p (TREE_TYPE (@1), type, GT_EXPR)) + || !VECTOR_TYPE_P (TREE_TYPE (@1)))) (gt @c0 (convert @1))) - (if (code1 == NE_EXPR + (if ((code1 == NE_EXPR && code2 == LE_EXPR && cmp == 0 && allbits) + && ((VECTOR_BOOLEAN_TYPE_P (type) + && expand_vec_cmp_expr_p (TREE_TYPE (@1), type, LT_EXPR)) + || !VECTOR_TYPE_P (TREE_TYPE (@1)))) (lt @c0 (convert @1))) /* (a != (b+1)) & (a > b) -> a > (b+1) */ - (if (code1 == NE_EXPR + (if ((code1 == NE_EXPR && code2 == GT_EXPR && one_after && allbits) + && ((VECTOR_BOOLEAN_TYPE_P (type) + && expand_vec_cmp_expr_p (TREE_TYPE (@1), type, GT_EXPR)) + || !VECTOR_TYPE_P (TREE_TYPE (@1)))) (gt @c0 (convert @1))) /* (a != (b-1)) & (a < b) -> a < (b-1) */ - (if (code1 == NE_EXPR + (if ((code1 == NE_EXPR && code2 == LT_EXPR && one_before && allbits) + && ((VECTOR_BOOLEAN_TYPE_P (type) + && expand_vec_cmp_expr_p (TREE_TYPE (@1), type, LT_EXPR)) + || !VECTOR_TYPE_P (TREE_TYPE (@1)))) (lt @c0 (convert @1))) ) ) @@ -3762,6 +3807,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (if ((TREE_CODE (@1) == INTEGER_CST && TREE_CODE (@2) == INTEGER_CST) || ((INTEGRAL_TYPE_P (TREE_TYPE (@1)) + || (VECTOR_TYPE_P (TREE_TYPE (@1)) + && expand_vec_cmp_expr_p (TREE_TYPE (@1), type, code2)) || POINTER_TYPE_P (TREE_TYPE (@1))) && operand_equal_p (@1, @2))) (with @@ -3812,6 +3859,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (if ((TREE_CODE (@1) == INTEGER_CST && TREE_CODE (@2) == INTEGER_CST) || ((INTEGRAL_TYPE_P (TREE_TYPE (@1)) + || (VECTOR_TYPE_P (TREE_TYPE (@1))) || POINTER_TYPE_P (TREE_TYPE (@1))) && bitwise_equal_p (@1, @2))) (with @@ -3853,24 +3901,36 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (if (code1 == EQ_EXPR && code2 == GT_EXPR && cmp == 0 - && allbits) + && allbits + && ((VECTOR_BOOLEAN_TYPE_P (type) + && expand_vec_cmp_expr_p (TREE_TYPE (@1), type, GE_EXPR)) + || !VECTOR_TYPE_P (TREE_TYPE (@1)))) (ge @c0 @2)) (if (code1 == EQ_EXPR && code2 == LT_EXPR && cmp == 0 - && allbits) + && allbits + && ((VECTOR_BOOLEAN_TYPE_P (type) + && expand_vec_cmp_expr_p (TREE_TYPE (@1), type, LE_EXPR)) + || !VECTOR_TYPE_P (TREE_TYPE (@1)))) (le @c0 @2)) /* (a == (b-1)) | (a >= b) -> a >= (b-1) */ (if (code1 == EQ_EXPR && code2 == GE_EXPR && one_before - && allbits) + && allbits + && ((VECTOR_BOOLEAN_TYPE_P (type) + && expand_vec_cmp_expr_p (TREE_TYPE (@1), type, GE_EXPR)) + || !VECTOR_TYPE_P (TREE_TYPE (@1)))) (ge @c0 (convert @1))) /* (a == (b+1)) | (a <= b) -> a <= (b-1) */ (if (code1 == EQ_EXPR && code2 == LE_EXPR && one_after - && allbits) + && allbits + && ((VECTOR_BOOLEAN_TYPE_P (type) + && expand_vec_cmp_expr_p (TREE_TYPE (@1), type, LE_EXPR)) + || !VECTOR_TYPE_P (TREE_TYPE (@1)))) (le @c0 (convert @1))) ) ) @@ -3935,7 +3995,10 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) rcmp (ne le gt ne lt ge) (simplify (op:c (cmp1:c @0 @1) (cmp2 @0 @1)) - (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) || POINTER_TYPE_P (TREE_TYPE (@0))) + (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) + || POINTER_TYPE_P (TREE_TYPE (@0)) + || (VECTOR_TYPE_P (TREE_TYPE (@1)) + && expand_vec_cmp_expr_p (TREE_TYPE (@0), type, rcmp))) (rcmp @0 @1))))) /* Optimize (a CMP b) == (a CMP b) */ @@ -3944,7 +4007,10 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) rcmp (eq gt le eq ge lt) (simplify (eq:c (cmp1:c @0 @1) (cmp2 @0 @1)) - (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) || POINTER_TYPE_P (TREE_TYPE (@0))) + (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) + || POINTER_TYPE_P (TREE_TYPE (@0)) + || (VECTOR_TYPE_P (TREE_TYPE (@0)) + && expand_vec_cmp_expr_p (TREE_TYPE (@0), type, rcmp))) (rcmp @0 @1)))) /* (type)([0,1]@a != 0) -> (type)a @@ -5950,6 +6016,15 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) && !expand_vec_cond_expr_p (TREE_TYPE (@1), TREE_TYPE (@0))))) (vec_cond @0 (op! @1 @3) (op! @2 @4)))) +/* (@0 ? @2 : @3) lop (@1 ? @2 : @3) --> (@0 lop @1) ? @2 : @3. */ +(for lop (bit_and bit_ior bit_xor) + (simplify + (lop + (vec_cond @0 integer_minus_onep@2 integer_zerop@3) + (vec_cond @1 @2 @3)) + (if (target_supports_op_p (TREE_TYPE (@0), lop, optab_vector)) + (vec_cond (lop @0 @1) @2 @3)))) + /* (c ? a : b) op d --> c ? (a op d) : (b op d) */ (simplify (op (vec_cond:s @0 @1 @2) @3) @@ -11604,4 +11679,4 @@ and, && VECTOR_TYPE_P (type) && direct_internal_fn_supported_p (IFN_AVG_CEIL, type, OPTIMIZE_FOR_BOTH)) (IFN_AVG_CEIL @0 @2))) -#endif +#endif
\ No newline at end of file diff --git a/gcc/optabs-tree.cc b/gcc/optabs-tree.cc index 6dfe8ee..9308a6d 100644 --- a/gcc/optabs-tree.cc +++ b/gcc/optabs-tree.cc @@ -82,6 +82,8 @@ optab_for_tree_code (enum tree_code code, const_tree type, return unknown_optab; /* FALLTHRU */ case RDIV_EXPR: + gcc_assert (FLOAT_TYPE_P (type)); + /* FALLTHRU */ case TRUNC_DIV_EXPR: case EXACT_DIV_EXPR: if (TYPE_SATURATING (type)) diff --git a/gcc/optabs.def b/gcc/optabs.def index 0c1435d..87a8b85 100644 --- a/gcc/optabs.def +++ b/gcc/optabs.def @@ -134,8 +134,8 @@ OPTAB_NX(smul_optab, "mul$P$a3") OPTAB_NX(smul_optab, "mul$F$a3") OPTAB_VL(smulv_optab, "mulv$I$a3", MULT, "mul", '3', gen_intv_fp_libfunc) OPTAB_VX(smulv_optab, "mul$F$a3") -OPTAB_NL(ssmul_optab, "ssmul$Q$a3", SS_MULT, "ssmul", '3', gen_signed_fixed_libfunc) -OPTAB_NL(usmul_optab, "usmul$Q$a3", US_MULT, "usmul", '3', gen_unsigned_fixed_libfunc) +OPTAB_NL(ssmul_optab, "ssmul$a3", SS_MULT, "ssmul", '3', gen_signed_fixed_libfunc) +OPTAB_NL(usmul_optab, "usmul$a3", US_MULT, "usmul", '3', gen_unsigned_fixed_libfunc) OPTAB_NL(sdiv_optab, "div$a3", DIV, "div", '3', gen_int_fp_signed_fixed_libfunc) OPTAB_VL(sdivv_optab, "divv$I$a3", DIV, "divv", '3', gen_int_libfunc) OPTAB_VX(sdivv_optab, "div$F$a3") diff --git a/gcc/profile-count.h b/gcc/profile-count.h index 20c03a2..c893aec 100644 --- a/gcc/profile-count.h +++ b/gcc/profile-count.h @@ -597,7 +597,7 @@ public: There are two exceptions - edges leading to noreturn edges and edges predicted by number of iterations heuristics are predicted well. This macro should be able to distinguish those, but at the moment it simply check for - noreturn heuristic that is only one giving probability over 99% or bellow + noreturn heuristic that is only one giving probability over 99% or below 1%. In future we might want to propagate reliability information across the CFG if we find this information useful on multiple places. */ bool probably_reliable_p () const diff --git a/gcc/read-rtl-function.cc b/gcc/read-rtl-function.cc index fb9c955..1f08c50 100644 --- a/gcc/read-rtl-function.cc +++ b/gcc/read-rtl-function.cc @@ -1065,7 +1065,10 @@ function_reader::read_rtx_operand_r (rtx x) if (regno == -1) fatal_at (loc, "unrecognized register: '%s'", name.string); - set_regno_raw (x, regno, 1); + int nregs = 1; + if (HARD_REGISTER_NUM_P (regno)) + nregs = hard_regno_nregs (regno, GET_MODE (x)); + set_regno_raw (x, regno, nregs); /* Consolidate singletons. */ x = consolidate_singletons (x); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e234630..7cb2440 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,489 @@ +2025-07-09 Jason Merrill <jason@redhat.com> + + PR c++/120243 + * g++.dg/coroutines/torture/pr120243-unhandled-1.C: New test. + * g++.dg/coroutines/torture/pr120243-unhandled-2.C: New test. + +2025-07-09 Jason Merrill <jason@redhat.com> + + PR c++/121012 + PR c++/120917 + * g++.dg/cpp2a/lambda-targ17.C: New test. + +2025-07-09 Jason Merrill <jason@redhat.com> + + PR c++/121008 + PR c++/113563 + * g++.dg/cpp2a/lambda-uneval28.C: New test. + +2025-07-09 Marek Polacek <polacek@redhat.com> + + PR c++/119838 + * g++.dg/parse/template32.C: New test. + +2025-07-09 Richard Sandiford <richard.sandiford@arm.com> + + * gcc.dg/rtl/aarch64/vec-series-1.c: New test. + * gcc.dg/rtl/aarch64/vec-series-2.c: Likewise. + * gcc.target/aarch64/sve/acle/general/dupq_2.c: Fix expected + output for this big-endian test. + * gcc.target/aarch64/sve/acle/general/dupq_4.c: Likewise. + * gcc.target/aarch64/sve/vec_init_3.c: Restrict to little-endian + targets and add more tests. + * gcc.target/aarch64/sve/vec_init_4.c: New big-endian version + of vec_init_3.c. + +2025-07-09 Pan Li <pan2.li@intel.com> + + * gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i16.c: Add asm check. + * gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i32.c: Ditto. + * gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i64.c: Ditto. + * gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i8.c: Ditto. + * gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i16.c: Ditto. + * gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i32.c: Ditto. + * gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i64.c: Ditto. + * gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i8.c: Ditto. + * gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i16.c: Ditto. + * gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i32.c: Ditto. + * gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i64.c: Ditto. + * gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i8.c: Ditto. + +2025-07-09 Pan Li <pan2.li@intel.com> + + * gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i16.c: Add asm check. + * gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i32.c: Ditto. + * gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i64.c: Ditto. + * gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i8.c: Ditto. + * gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i16.c: Ditto. + * gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i32.c: Ditto. + * gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i64.c: Ditto. + * gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i8.c: Ditto. + * gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i16.c: Ditto. + * gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i32.c: Ditto. + * gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i64.c: Ditto. + * gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i8.c: Ditto. + * gcc.target/riscv/rvv/autovec/vx_vf/vx_binary.h: Add test + helper macros. + * gcc.target/riscv/rvv/autovec/vx_vf/vx_binary_data.h: Add test + data for run test. + * gcc.target/riscv/rvv/autovec/vx_vf/vx_vssub-run-1-i16.c: New test. + * gcc.target/riscv/rvv/autovec/vx_vf/vx_vssub-run-1-i32.c: New test. + * gcc.target/riscv/rvv/autovec/vx_vf/vx_vssub-run-1-i64.c: New test. + * gcc.target/riscv/rvv/autovec/vx_vf/vx_vssub-run-1-i8.c: New test. + +2025-07-09 Paul-Antoine Arras <parras@baylibre.com> + + * gcc.target/riscv/rvv/autovec/vx_vf/vf_mulop_run.h: Set + MAX_RELATIVE_DIFF depending on type. + * gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmacc-run-1-f16.c: Enable zvfh. + * gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmadd-run-1-f16.c: Likewise. + * gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmsac-run-1-f16.c: Likewise. + * gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmsub-run-1-f16.c: Likewise. + * gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmacc-run-1-f16.c: Likewise. + * gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmadd-run-1-f16.c: Likewise. + * gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmsac-run-1-f16.c: Likewise. + * gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmsub-run-1-f16.c: Likewise. + +2025-07-09 Ciyan Pan <panciyan@eswincomputing.com> + + * gcc.target/riscv/rvv/autovec/sat/vec_sat_arith.h: Add vec_sat_u_sub_fmt wrap define. + * gcc.target/riscv/rvv/autovec/sat/vec_sat_data.h: Add vec_sat_u_sub test data. + * gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-1-u16.c: Remove test data. + * gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-1-u32.c: Remove test data. + * gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-1-u64.c: Remove test data. + * gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-1-u8.c: Remove test data. + * gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-10-u16.c: Remove test data. + * gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-10-u32.c: Remove test data. + * gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-10-u64.c: Remove test data. + * gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-10-u8.c: Remove test data. + * gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-2-u16.c: Remove test data. + * gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-2-u32.c: Remove test data. + * gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-2-u64.c: Remove test data. + * gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-2-u8.c: Remove test data. + * gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-3-u16.c: Remove test data. + * gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-3-u32.c: Remove test data. + * gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-3-u64.c: Remove test data. + * gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-3-u8.c: Remove test data. + * gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-4-u16.c: Remove test data. + * gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-4-u32.c: Remove test data. + * gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-4-u64.c: Remove test data. + * gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-4-u8.c: Remove test data. + * gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-5-u16.c: Remove test data. + * gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-5-u32.c: Remove test data. + * gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-5-u64.c: Remove test data. + * gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-5-u8.c: Remove test data. + * gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-6-u16.c: Remove test data. + * gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-6-u32.c: Remove test data. + * gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-6-u64.c: Remove test data. + * gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-6-u8.c: Remove test data. + * gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-7-u16.c: Remove test data. + * gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-7-u32.c: Remove test data. + * gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-7-u64.c: Remove test data. + * gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-7-u8.c: Remove test data. + * gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-8-u16.c: Remove test data. + * gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-8-u32.c: Remove test data. + * gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-8-u64.c: Remove test data. + * gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-8-u8.c: Remove test data. + * gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-9-u16.c: Remove test data. + * gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-9-u32.c: Remove test data. + * gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-9-u64.c: Remove test data. + * gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-9-u8.c: Remove test data. + +2025-07-09 Richard Sandiford <richard.sandiford@arm.com> + + * gcc.target/aarch64/pr118348_1.c: Require fstack_protector. + * gcc.target/aarch64/pr118348_2.c: Likewise. + +2025-07-09 Icen Zeyada <Icen.Zeyada2@arm.com> + + * gcc.target/aarch64/vector-compare-5.c: Add new test for vector compare simplification. + +2025-07-09 Jeff Law <jlaw@ventanamicro.com> + + PR target/120642 + * gcc.target/riscv/rvv/xtheadvector/pr120642.c: New test. + +2025-07-09 Richard Biener <rguenther@suse.de> + + PR testsuite/120093 + * gcc.dg/vect/pr101145.c: Use noipa instead of noinline + attribute. + +2025-07-09 Juergen Christ <jchrist@linux.ibm.com> + + * gcc.target/s390/vector/pattern-avg-1.c: Fix on -m31. + * gcc.target/s390/vector/pattern-mulh-1.c: Fix on -m31. + * gcc.target/s390/vector/pattern-mulh-2.c: Fix on -m31. + +2025-07-09 Thomas Schwinge <tschwinge@baylibre.com> + + * gcc.dg/builtin-dynamic-object-size-pr120780.c: Fix 'main' function. + +2025-07-09 Tamar Christina <tamar.christina@arm.com> + + PR tree-optimization/120922 + * gcc.dg/vect/pr120922.c: New test. + +2025-07-09 Pan Li <pan2.li@intel.com> + + * gcc.target/riscv/sat/sat_arith.h: Add xlen check for + uint128_t. + * gcc.target/riscv/sat/sat_u_mul-run-1-u16-from-u128.c: Enable + run test for rv64 only. + * gcc.target/riscv/sat/sat_u_mul-run-1-u32-from-u128.c: Ditto. + * gcc.target/riscv/sat/sat_u_mul-run-1-u64-from-u128.c: Ditto. + * gcc.target/riscv/sat/sat_u_mul-run-1-u8-from-u128.c: Ditto. + +2025-07-08 Marek Polacek <polacek@redhat.com> + Andrew Pinski <quic_apinski@quicinc.com> + + PR c++/83469 + PR c++/93809 + * g++.dg/template/error45.C: Adjust dg-error. + * g++.dg/warn/Wredundant-tags-3.C: Remove xfail. + * g++.dg/parse/union1.C: New test. + * g++.dg/parse/union2.C: New test. + * g++.dg/parse/union3.C: New test. + * g++.dg/parse/union4.C: New test. + * g++.dg/parse/union5.C: New test. + * g++.dg/parse/union6.C: New test. + +2025-07-08 Takayuki 'January June' Suwa <jjsuwa_sys3175@yahoo.co.jp> + + * gcc.target/xtensa/BGEUI-BLTUI-32k-64k.c: New. + +2025-07-08 Jakub Jelinek <jakub@redhat.com> + + PR c++/117784 + * g++.dg/cpp1z/decomp3.C (test): For constexpr structured binding + initialize from constexpr var instead of non-constexpr and expect + just a pedwarn for C++23 and older instead of error always. + * g++.dg/cpp26/decomp9.C (foo): Likewise. + * g++.dg/cpp26/decomp22.C: New test. + * g++.dg/cpp26/decomp23.C: New test. + * g++.dg/cpp26/decomp24.C: New test. + * g++.dg/cpp26/decomp25.C: New test. + +2025-07-08 Stefan Schulze Frielinghaus <stefansf@gcc.gnu.org> + + * gcc.target/s390/stack-protector-guard-tls-1.c: New test. + +2025-07-08 Richard Biener <rguenther@suse.de> + + * gcc.dg/guality/guality.h (guality_main): Declare noipa. + (guality_check): Likewise. + +2025-07-08 Robin Dapp <rdapp@ventanamicro.com> + + PR target/120461 + * gcc.target/riscv/rvv/xtheadvector/pr120461.c: New test. + +2025-07-08 Robin Dapp <rdapp@ventanamicro.com> + + PR target/113829 + * gcc.target/riscv/rvv/base/pr113829.c: New test. + +2025-07-08 Andreas Schwab <schwab@suse.de> + + PR target/120995 + * gcc.target/riscv/amo/zabha-zacas-atomic-cas.c: New test. + +2025-07-08 Jason Merrill <jason@redhat.com> + + * g++.dg/cpp1y/lambda-generic-variadic.C: Change to 'compile'. + +2025-07-08 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + + * gcc.target/i386/memcpy-pr120683-1.c (dg-options): Add + -fasynchronous-unwind-tables -fdwarf2-cfi-asm. + * gcc.target/i386/memcpy-pr120683-2.c: Likewise. + * gcc.target/i386/memcpy-pr120683-3.c: Likewise. + * gcc.target/i386/memcpy-pr120683-4.c: Likewise. + * gcc.target/i386/memcpy-pr120683-5.c: Likewise. + * gcc.target/i386/memcpy-pr120683-6.c: Likewise. + * gcc.target/i386/memcpy-pr120683-7.c: Likewise. + * gcc.target/i386/memcpy-strategy-12.c: Likewise. + * gcc.target/i386/memset-pr120683-1.c: Likewise. + * gcc.target/i386/memset-pr120683-10.c: Likewise. + * gcc.target/i386/memset-pr120683-11.c: Likewise. + * gcc.target/i386/memset-pr120683-12.c: Likewise. + * gcc.target/i386/memset-pr120683-13.c: Likewise. + * gcc.target/i386/memset-pr120683-14.c: Likewise. + * gcc.target/i386/memset-pr120683-15.c: Likewise. + * gcc.target/i386/memset-pr120683-16.c: Likewise. + * gcc.target/i386/memset-pr120683-17.c: Likewise. + * gcc.target/i386/memset-pr120683-18.c: Likewise. + * gcc.target/i386/memset-pr120683-19.c: Likewise. + * gcc.target/i386/memset-pr120683-2.c: Likewise. + * gcc.target/i386/memset-pr120683-20.c: Likewise. + * gcc.target/i386/memset-pr120683-21.c: Likewise. + * gcc.target/i386/memset-pr120683-22.c: Likewise. + * gcc.target/i386/memset-pr120683-23.c: Likewise. + * gcc.target/i386/memset-pr120683-3.c: Likewise. + * gcc.target/i386/memset-pr120683-4.c: Likewise. + * gcc.target/i386/memset-pr120683-5.c: Likewise. + * gcc.target/i386/memset-pr120683-6.c: Likewise. + * gcc.target/i386/memset-pr120683-7.c: Likewise. + * gcc.target/i386/memset-pr120683-8.c: Likewise. + * gcc.target/i386/memset-pr120683-9.c: Likewise. + +2025-07-08 Juergen Christ <jchrist@linux.ibm.com> + + * gcc.target/s390/vector/pattern-avg-1.c: Split test. + * gcc.target/s390/vector/pattern-mulh-1.c: Split test. + * gcc.target/s390/vector/pattern-avg-2.c: New test. + * gcc.target/s390/vector/pattern-mulh-2.c: New test. + +2025-07-08 Richard Biener <rguenther@suse.de> + + * gcc.target/i386/vect-mask-epilogue-1.c: New testcase. + * gcc.target/i386/vect-mask-epilogue-2.c: Likewise. + * gcc.target/i386/vect-epilogues-3.c: Adjust. + +2025-07-08 Andre Vehreschild <vehre@gcc.gnu.org> + + PR fortran/120637 + * gfortran.dg/asan/finalize_1.f90: New test. + +2025-07-08 Jeff Law <jlaw@ventanamicro.com> + + * gcc.dg/torture/pr120654.c: Use __builtin variants of malloc and free. + +2025-07-08 Jeff Law <jlaw@ventanamicro.com> + + * gcc.target/riscv/amo/zalrsc-rvwmo-amo-add-int.c: Adjust expected + output. + * gcc.target/riscv/amo/zalrsc-ztso-amo-add-int.c: Likewise. + +2025-07-07 Qing Zhao <qing.zhao@oracle.com> + + Revert: + 2025-07-07 Qing Zhao <qing.zhao@oracle.com> + + * gcc.dg/flex-array-counted-by.c: Update test. + * gcc.dg/pointer-counted-by-1.c: New test. + * gcc.dg/pointer-counted-by-2.c: New test. + * gcc.dg/pointer-counted-by-3.c: New test. + * gcc.dg/pointer-counted-by.c: New test. + +2025-07-07 Qing Zhao <qing.zhao@oracle.com> + + Revert: + 2025-07-07 Qing Zhao <qing.zhao@oracle.com> + + * gcc.dg/pointer-counted-by-4-char.c: New test. + * gcc.dg/pointer-counted-by-4-float.c: New test. + * gcc.dg/pointer-counted-by-4-struct.c: New test. + * gcc.dg/pointer-counted-by-4-union.c: New test. + * gcc.dg/pointer-counted-by-4.c: New test. + * gcc.dg/pointer-counted-by-5.c: New test. + * gcc.dg/pointer-counted-by-6.c: New test. + * gcc.dg/pointer-counted-by-7.c: New test. + +2025-07-07 Qing Zhao <qing.zhao@oracle.com> + + Revert: + 2025-07-07 Qing Zhao <qing.zhao@oracle.com> + + * gcc.dg/ubsan/pointer-counted-by-bounds-2.c: New test. + * gcc.dg/ubsan/pointer-counted-by-bounds-3.c: New test. + * gcc.dg/ubsan/pointer-counted-by-bounds-4.c: New test. + * gcc.dg/ubsan/pointer-counted-by-bounds-5.c: New test. + * gcc.dg/ubsan/pointer-counted-by-bounds.c: New test. + +2025-07-07 H.J. Lu <hjl.tools@gmail.com> + + PR testsuite/120881 + * lib/scanasm.exp (check-function-bodies): Allow "^[0-9]+:". + +2025-07-07 H.J. Lu <hjl.tools@gmail.com> + + PR target/120888 + * gcc.target/xtensa/pr120888-1.c: New test. + * gcc.target/xtensa/pr120888-2.c: Likewise. + +2025-07-07 Juergen Christ <jchrist@linux.ibm.com> + + * gcc.target/s390/fminmax-1.c: New test. + * gcc.target/s390/fminmax-2.c: New test. + +2025-07-07 Tamar Christina <tamar.christina@arm.com> + + PR tree-optimization/120817 + * gcc.dg/vect/pr120817.c: Add SVE HW check. + +2025-07-07 Alfie Richards <alfie.richards@arm.com> + + PR c++/119498 + * g++.target/aarch64/pr119498.C: New test. + +2025-07-07 Jason Merrill <jason@redhat.com> + + PR c++/120917 + * g++.dg/concepts/auto7a.C: Add diagnostic. + * g++.dg/concepts/auto7b.C: New test. + * g++.dg/concepts/auto7c.C: New test. + * g++.dg/cpp1y/pr85076.C: Expect 'auto' error. + * g++.dg/concepts/pr67249.C: Likewise. + * g++.dg/cpp1y/lambda-generic-variadic.C: Likewise. + * g++.dg/cpp2a/concepts-pr67210.C: Likewise. + * g++.dg/concepts/pr67249a.C: New test. + * g++.dg/cpp1y/lambda-generic-variadic-a.C: New test. + * g++.dg/cpp2a/concepts-pr67210a.C: New test. + +2025-07-07 Kyrylo Tkachov <ktkachov@nvidia.com> + + * gcc.target/aarch64/popcnt9.c: Add +nosve to target pragma. + * gcc.target/aarch64/popcnt13.c: New test. + +2025-07-07 Richard Biener <rguenther@suse.de> + + PR tree-optimization/120817 + * gcc.dg/vect/pr120817.c: New testcase. + +2025-07-07 Pan Li <pan2.li@intel.com> + + * gcc.target/riscv/sat/sat_arith.h: Add test helper macros. + * gcc.target/riscv/sat/sat_arith_data.h: Add test data for + run test. + * gcc.target/riscv/sat/sat_u_mul-1-u16-from-u128.c: New test. + * gcc.target/riscv/sat/sat_u_mul-1-u32-from-u128.c: New test. + * gcc.target/riscv/sat/sat_u_mul-1-u64-from-u128.c: New test. + * gcc.target/riscv/sat/sat_u_mul-1-u8-from-u128.c: New test. + * gcc.target/riscv/sat/sat_u_mul-run-1-u16-from-u128.c: New test. + * gcc.target/riscv/sat/sat_u_mul-run-1-u32-from-u128.c: New test. + * gcc.target/riscv/sat/sat_u_mul-run-1-u64-from-u128.c: New test. + * gcc.target/riscv/sat/sat_u_mul-run-1-u8-from-u128.c: New test. + +2025-07-07 Eric Botcazou <ebotcazou@adacore.com> + + * ada/acats-3/tests/c9/c94001c.ada: Tweak delay statements. + * ada/acats-4/tests/c9/c94001c.ada: Likewise. + * ada/acats-4/tests/c9/c94006a.ada: Likewise. + * ada/acats-4/tests/c9/c94008c.ada: Likewise. + * ada/acats-4/tests/c9/c951002.a: Likewise. + * ada/acats-4/tests/c9/c954a01.a: Likewise. + * ada/acats-4/tests/c9/c940005.a: Tweak duration constants. + * ada/acats-4/tests/c9/c940007.a: Likewise. + * ada/acats-4/tests/c9/c96001a.ada: Likewise. + +2025-07-07 Juergen Christ <jchrist@linux.ibm.com> + + * gcc.target/s390/vector/pattern-avg-1.c: New test. + * gcc.target/s390/vector/pattern-mulh-1.c: New test. + +2025-07-07 Spencer Abson <spencer.abson@arm.com> + + * gcc.target/aarch64/sve/unpacked_fcm_1.c: New test. + * gcc.target/aarch64/sve/unpacked_fcm_2.c: Likewise. + +2025-07-07 H.J. Lu <hjl.tools@gmail.com> + + PR target/120670 + PR target/120683 + * gcc.target/i386/auto-init-padding-9.c: Updated. + * gcc.target/i386/memcpy-strategy-12.c: Likewise. + * gcc.target/i386/memset-strategy-25.c: Likewise. + * gcc.target/i386/memset-strategy-29.c: Likewise. + * gcc.target/i386/memset-strategy-30.c: Likewise. + * gcc.target/i386/memset-strategy-31.c: Likewise. + * gcc.target/i386/memcpy-pr120683-1.c: New test. + * gcc.target/i386/memcpy-pr120683-2.c: Likewise. + * gcc.target/i386/memcpy-pr120683-3.c: Likewise. + * gcc.target/i386/memcpy-pr120683-4.c: Likewise. + * gcc.target/i386/memcpy-pr120683-5.c: Likewise. + * gcc.target/i386/memcpy-pr120683-6.c: Likewise. + * gcc.target/i386/memcpy-pr120683-7.c: Likewise. + * gcc.target/i386/memset-pr120683-1.c: Likewise. + * gcc.target/i386/memset-pr120683-2.c: Likewise. + * gcc.target/i386/memset-pr120683-3.c: Likewise. + * gcc.target/i386/memset-pr120683-4.c: Likewise. + * gcc.target/i386/memset-pr120683-5.c: Likewise. + * gcc.target/i386/memset-pr120683-6.c: Likewise. + * gcc.target/i386/memset-pr120683-7.c: Likewise. + * gcc.target/i386/memset-pr120683-8.c: Likewise. + * gcc.target/i386/memset-pr120683-9.c: Likewise. + * gcc.target/i386/memset-pr120683-10.c: Likewise. + * gcc.target/i386/memset-pr120683-11.c: Likewise. + * gcc.target/i386/memset-pr120683-12.c: Likewise. + * gcc.target/i386/memset-pr120683-13.c: Likewise. + * gcc.target/i386/memset-pr120683-14.c: Likewise. + * gcc.target/i386/memset-pr120683-15.c: Likewise. + * gcc.target/i386/memset-pr120683-16.c: Likewise. + * gcc.target/i386/memset-pr120683-17.c: Likewise. + * gcc.target/i386/memset-pr120683-18.c: Likewise. + * gcc.target/i386/memset-pr120683-19.c: Likewise. + * gcc.target/i386/memset-pr120683-20.c: Likewise. + * gcc.target/i386/memset-pr120683-21.c: Likewise. + * gcc.target/i386/memset-pr120683-22.c: Likewise. + * gcc.target/i386/memset-pr120683-23.c: Likewise. + +2025-07-07 Jakub Jelinek <jakub@redhat.com> + + PR c++/84009 + * g++.dg/cpp0x/range-for40.C: New test. + * g++.dg/cpp0x/range-for41.C: New test. + * g++.dg/cpp0x/range-for42.C: New test. + * g++.dg/cpp0x/range-for43.C: New test. + +2025-07-07 Mikael Morin <mikael@gcc.gnu.org> + + * gfortran.dg/move_alloc_20.f03: New test. + +2025-07-07 Andrew Pinski <quic_apinski@quicinc.com> + + PR middle-end/120709 + * gcc.dg/crc-non-cst-poly-1.c: New test. + +2025-07-06 Andrew Pinski <quic_apinski@quicinc.com> + + PR tree-optimization/120951 + * gcc.dg/torture/pr120951-1.c: New test. + +2025-07-06 Jan Hubicka <hubicka@ucw.cz> + + * gcc.dg/tree-prof/clone-merge-1.c: + 2025-07-04 Vineet Gupta <vineetg@rivosinc.com> PR target/118241 diff --git a/gcc/testsuite/ada/acats-3/tests/c9/c94001c.ada b/gcc/testsuite/ada/acats-3/tests/c9/c94001c.ada index 0cc14f4..df38f99 100644 --- a/gcc/testsuite/ada/acats-3/tests/c9/c94001c.ada +++ b/gcc/testsuite/ada/acats-3/tests/c9/c94001c.ada @@ -211,7 +211,7 @@ BEGIN BEGIN -- (E) WHILE NOT(OUT_TSK'TERMINATED) AND DELAY_COUNT < 60 LOOP - DELAY 1.0; + DELAY 1.0 * Impdef.One_Long_Second; DELAY_COUNT := DELAY_COUNT + 1; END LOOP; IF DELAY_COUNT = 60 THEN @@ -254,7 +254,7 @@ BEGIN BEGIN WHILE NOT(OUT_TSK'TERMINATED) AND DELAY_COUNT < 60 LOOP - DELAY 1.0; + DELAY 1.0 * Impdef.One_Long_Second; DELAY_COUNT := DELAY_COUNT + 1; END LOOP; IF DELAY_COUNT = 60 THEN diff --git a/gcc/testsuite/ada/acats-4/tests/c9/c940005.a b/gcc/testsuite/ada/acats-4/tests/c9/c940005.a index adb58b1..47a97bf 100644 --- a/gcc/testsuite/ada/acats-4/tests/c9/c940005.a +++ b/gcc/testsuite/ada/acats-4/tests/c9/c940005.a @@ -85,7 +85,7 @@ begin -- In reality one would expect a time of 5 to 10 seconds. In -- the interests of speeding up the test suite a shorter time -- is used - Pulse_Time_Delta : constant duration := ImpDef.Switch_To_New_Task; + Pulse_Time_Delta : constant duration := ImpDef.Long_Switch_To_New_Task; -- control over stopping tasks protected Control is diff --git a/gcc/testsuite/ada/acats-4/tests/c9/c940007.a b/gcc/testsuite/ada/acats-4/tests/c9/c940007.a index c678463..41e80f4 100644 --- a/gcc/testsuite/ada/acats-4/tests/c9/c940007.a +++ b/gcc/testsuite/ada/acats-4/tests/c9/c940007.a @@ -90,7 +90,7 @@ begin -- In reality one would expect a time of 5 to 10 seconds. In -- the interests of speeding up the test suite a shorter time -- is used - Pulse_Time_Delta : constant duration := ImpDef.Switch_To_New_Task; + Pulse_Time_Delta : constant duration := ImpDef.Long_Switch_To_New_Task; -- control over stopping tasks diff --git a/gcc/testsuite/ada/acats-4/tests/c9/c94001c.ada b/gcc/testsuite/ada/acats-4/tests/c9/c94001c.ada index 0cc14f4..df38f99 100644 --- a/gcc/testsuite/ada/acats-4/tests/c9/c94001c.ada +++ b/gcc/testsuite/ada/acats-4/tests/c9/c94001c.ada @@ -211,7 +211,7 @@ BEGIN BEGIN -- (E) WHILE NOT(OUT_TSK'TERMINATED) AND DELAY_COUNT < 60 LOOP - DELAY 1.0; + DELAY 1.0 * Impdef.One_Long_Second; DELAY_COUNT := DELAY_COUNT + 1; END LOOP; IF DELAY_COUNT = 60 THEN @@ -254,7 +254,7 @@ BEGIN BEGIN WHILE NOT(OUT_TSK'TERMINATED) AND DELAY_COUNT < 60 LOOP - DELAY 1.0; + DELAY 1.0 * Impdef.One_Long_Second; DELAY_COUNT := DELAY_COUNT + 1; END LOOP; IF DELAY_COUNT = 60 THEN diff --git a/gcc/testsuite/ada/acats-4/tests/c9/c94006a.ada b/gcc/testsuite/ada/acats-4/tests/c9/c94006a.ada index 6b9c85f..cac5fc6 100644 --- a/gcc/testsuite/ada/acats-4/tests/c9/c94006a.ada +++ b/gcc/testsuite/ada/acats-4/tests/c9/c94006a.ada @@ -28,6 +28,7 @@ -- TBN 9/17/86 -- PWN 01/31/95 REMOVED PRAGMA PRIORITY FOR ADA 9X. +with Impdef; WITH REPORT; USE REPORT; WITH SYSTEM; USE SYSTEM; PROCEDURE C94006A IS @@ -41,7 +42,7 @@ PROCEDURE C94006A IS SELECT ACCEPT E; OR - DELAY 30.0; + DELAY 30.0 * Impdef.One_Long_Second; END SELECT; END TT; diff --git a/gcc/testsuite/ada/acats-4/tests/c9/c94008c.ada b/gcc/testsuite/ada/acats-4/tests/c9/c94008c.ada index 6d10e25..fb2eee9 100644 --- a/gcc/testsuite/ada/acats-4/tests/c9/c94008c.ada +++ b/gcc/testsuite/ada/acats-4/tests/c9/c94008c.ada @@ -33,6 +33,7 @@ -- JBG 8/29/86 ELIMINATED SHARED VARIABLES; ADDED GENERIC UNIT -- PWN 11/30/94 REMOVED PRAGMA PRIORITY INSTANCES FOR ADA 9X. +with Impdef; WITH REPORT; USE REPORT; WITH SYSTEM; USE SYSTEM; PROCEDURE C94008C IS @@ -198,10 +199,10 @@ BEGIN -- C94008C OR WHEN ENTER_TERMINATE => TERMINATE; END SELECT; - DELAY 10.0; + DELAY 10.0 * Impdef.One_Second; IF TERMINATE_COUNT.GET /= 1 THEN - DELAY 20.0; + DELAY 20.0 * Impdef.One_Long_Second; END IF; IF TERMINATE_COUNT.GET /= 1 THEN @@ -239,10 +240,10 @@ BEGIN -- C94008C BEGIN - DELAY 10.0; -- WAIT FOR T1, T2, AND T3 TO GET TO SELECT STMTS. + DELAY 10.0 * Impdef.One_Second; -- WAIT FOR T1, T2, AND T3 TO GET TO SELECT STMTS. IF TERMINATE_COUNT.GET /= 3 THEN - DELAY 20.0; + DELAY 20.0 * Impdef.One_Long_Second; END IF; IF TERMINATE_COUNT.GET /= 3 THEN diff --git a/gcc/testsuite/ada/acats-4/tests/c9/c951002.a b/gcc/testsuite/ada/acats-4/tests/c9/c951002.a index 8ccb2d0..65b696c 100644 --- a/gcc/testsuite/ada/acats-4/tests/c9/c951002.a +++ b/gcc/testsuite/ada/acats-4/tests/c9/c951002.a @@ -278,14 +278,14 @@ begin -- Wait until the message is queued on the entry before starting -- the Credit_Task while not Hold.TC_Message_is_Queued loop - delay ImpDef.Minimum_Task_Switch; + delay ImpDef.Long_Minimum_Task_Switch; end loop; -- Credit_Task.TC_Start; -- Ensure the first part of the test is complete before continuing while not (Credit_Message'terminated and Credit_Task'terminated) loop - delay ImpDef.Minimum_Task_Switch; + delay ImpDef.Long_Minimum_Task_Switch; end loop; --====================================================== @@ -298,12 +298,12 @@ begin -- for it to reach the accept statement and call Hold.Set_DB_Overload -- before starting Debit_Message -- - delay ImpDef.Switch_To_New_Task; + delay ImpDef.Long_Switch_To_New_Task; Debit_Message.TC_Start; while not Debit_Task'terminated loop - delay ImpDef.Minimum_Task_Switch; + delay ImpDef.Long_Minimum_Task_Switch; end loop; Hold.Clear_DB_Overload; -- Allow completion diff --git a/gcc/testsuite/ada/acats-4/tests/c9/c954a01.a b/gcc/testsuite/ada/acats-4/tests/c9/c954a01.a index 34f48b2..3ea545a 100644 --- a/gcc/testsuite/ada/acats-4/tests/c9/c954a01.a +++ b/gcc/testsuite/ada/acats-4/tests/c9/c954a01.a @@ -148,7 +148,7 @@ package body C954A01_0 is -- Printer server abstraction. end select; -- Allow other tasks to get control - delay ImpDef.Minimum_Task_Switch; + delay ImpDef.Long_Minimum_Task_Switch; end loop; @@ -175,7 +175,7 @@ use F954A00; procedure C954A01 is - Long_Enough : constant Duration := ImpDef.Switch_To_New_Task; + Long_Enough : constant Duration := ImpDef.Long_Switch_To_New_Task; --==============================================-- diff --git a/gcc/testsuite/ada/acats-4/tests/c9/c96001a.ada b/gcc/testsuite/ada/acats-4/tests/c9/c96001a.ada index 74374b9..f958ea1 100644 --- a/gcc/testsuite/ada/acats-4/tests/c9/c96001a.ada +++ b/gcc/testsuite/ada/acats-4/tests/c9/c96001a.ada @@ -36,6 +36,7 @@ -- RJW 11/13/87 ADDED CODE WHICH ALLOWS TEST TO REPORT "PASSED" -- IF TICK > DURATION'SMALL. +with Impdef; WITH CALENDAR; USE CALENDAR; WITH SYSTEM; USE SYSTEM; WITH REPORT; USE REPORT; @@ -50,7 +51,7 @@ BEGIN --------------------------------------------- DECLARE -- (A) - X : DURATION := 5.0; + X : DURATION := 5.0 * Impdef.One_Second; OLD_TIME : TIME; LAPSE : DURATION; BEGIN -- (A) @@ -138,8 +139,8 @@ BEGIN --------------------------------------------- DECLARE -- (E) - INC1 : DURATION := 2.0; - INC2 : DURATION := 3.0; + INC1 : DURATION := 2.0 * Impdef.One_Second; + INC2 : DURATION := 3.0 * Impdef.One_Second; OLD_TIME : TIME; LAPSE : DURATION; BEGIN -- (E) diff --git a/gcc/testsuite/g++.dg/concepts/auto7a.C b/gcc/testsuite/g++.dg/concepts/auto7a.C index 88868f4..f36038d 100644 --- a/gcc/testsuite/g++.dg/concepts/auto7a.C +++ b/gcc/testsuite/g++.dg/concepts/auto7a.C @@ -2,6 +2,7 @@ template <class T> struct A { }; void f(A<auto> a) { } // { dg-error "auto. in template argument" } +// { dg-message "in parameter declaration" "" { target c++17_down } .-1 } int main() { f(A<int>()); diff --git a/gcc/testsuite/g++.dg/concepts/auto7b.C b/gcc/testsuite/g++.dg/concepts/auto7b.C new file mode 100644 index 0000000..874192c --- /dev/null +++ b/gcc/testsuite/g++.dg/concepts/auto7b.C @@ -0,0 +1,10 @@ +// PR c++/120917 +// { dg-do compile { target c++14 } } +// { dg-additional-options "-fconcepts -Wno-abbreviated-auto-in-template-arg" } + +template <class T> struct A { }; +void f(A<auto> a) { } +int main() +{ + f(A<int>()); +} diff --git a/gcc/testsuite/g++.dg/concepts/auto7c.C b/gcc/testsuite/g++.dg/concepts/auto7c.C new file mode 100644 index 0000000..5b16027 --- /dev/null +++ b/gcc/testsuite/g++.dg/concepts/auto7c.C @@ -0,0 +1,12 @@ +// { dg-do compile { target c++17 } } +// { dg-additional-options -fconcepts } + +template <class T> +concept True = true; + +template <class T> struct A { }; +void f(A<True auto> a) { } // { dg-error "use of .auto. in template argument" } +int main() +{ + f(A<int>()); +} diff --git a/gcc/testsuite/g++.dg/concepts/pr67249.C b/gcc/testsuite/g++.dg/concepts/pr67249.C index e0f8d5a..e97183d 100644 --- a/gcc/testsuite/g++.dg/concepts/pr67249.C +++ b/gcc/testsuite/g++.dg/concepts/pr67249.C @@ -4,4 +4,4 @@ template<class T> concept C1 = true; template<class A, class B> struct Pair {}; // We used to test "Pair<auto, C1 >". -void f(Pair<C1 auto, C1 auto>); +void f(Pair<C1 auto, C1 auto>); // { dg-error "auto" } diff --git a/gcc/testsuite/g++.dg/concepts/pr67249a.C b/gcc/testsuite/g++.dg/concepts/pr67249a.C new file mode 100644 index 0000000..cb5d90e --- /dev/null +++ b/gcc/testsuite/g++.dg/concepts/pr67249a.C @@ -0,0 +1,7 @@ +// { dg-do compile { target c++17 } } +// { dg-options "-fconcepts -Wno-abbreviated-auto-in-template-arg" } + +template<class T> concept C1 = true; +template<class A, class B> struct Pair {}; +// We used to test "Pair<auto, C1 >". +void f(Pair<C1 auto, C1 auto>); diff --git a/gcc/testsuite/g++.dg/coroutines/torture/pr120243-unhandled-1.C b/gcc/testsuite/g++.dg/coroutines/torture/pr120243-unhandled-1.C new file mode 100644 index 0000000..16bfef1 --- /dev/null +++ b/gcc/testsuite/g++.dg/coroutines/torture/pr120243-unhandled-1.C @@ -0,0 +1,33 @@ +// PR c++/120243 +// { dg-do run } + +#include <coroutine> + +struct coro { + struct promise_type { + promise_type() = default; + + std::suspend_never initial_suspend() const noexcept { return {}; } + std::suspend_never final_suspend() const noexcept { return {}; } + + void unhandled_exception() { throw; } + + coro get_return_object() { return {}; } + void return_void() {} + + }; +}; + +int main() { + auto c = []() -> coro { + throw "hello"; + __builtin_abort(); + co_return; + }; + try { + c(); + } + catch(...) { + __builtin_printf("Caught!\n"); + } +} diff --git a/gcc/testsuite/g++.dg/coroutines/torture/pr120243-unhandled-2.C b/gcc/testsuite/g++.dg/coroutines/torture/pr120243-unhandled-2.C new file mode 100644 index 0000000..614c4ec --- /dev/null +++ b/gcc/testsuite/g++.dg/coroutines/torture/pr120243-unhandled-2.C @@ -0,0 +1,34 @@ +// PR c++/120243 +// { dg-do run } + +#include <coroutine> + +struct coro { + struct promise_type { + promise_type() = default; + + std::suspend_always initial_suspend() const noexcept { return {}; } + std::suspend_always final_suspend() const noexcept { return {}; } + + void unhandled_exception() { throw; } + + coro get_return_object() { return {std::coroutine_handle<promise_type>::from_promise(*this)}; } + void return_void() {} + }; + + std::coroutine_handle<promise_type> h; +}; + +int main() { + auto c = []() -> coro { + throw "hello"; + __builtin_abort(); + co_return; + }; + try { + c().h.resume(); + } + catch(...) { + __builtin_printf("Caught!\n"); + } +} diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ellipsis2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ellipsis2.C index b6a5323..c473257 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ellipsis2.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ellipsis2.C @@ -9,4 +9,6 @@ struct A constexpr int ellipsis(...) { return 1; } -static_assert(ellipsis(A().empty()), "Error"); // { dg-error "non-constant condition|empty" } +static_assert(ellipsis(A().empty()), "Error"); // { dg-error "non-constant condition" } +// { dg-error "call to non-'constexpr' function 'bool A::empty\\\(\\\)'" "" { target c++23_down } .-1 } +// { dg-error "temporary of non-literal type 'A' in a constant expression" "" { target c++26 } .-2 } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-throw.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-throw.C index 9c49fa4..9abf4a3 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-throw.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-throw.C @@ -2,8 +2,8 @@ // Explicit { dg-require-effective-target exceptions_enabled } to avoid verify compiler messages FAILs for '-fno-exceptions'. constexpr int may_throw(bool decide) { - return decide ? 42 : throw -1; // { dg-error "throw" } + return decide ? 42 : throw -1; // { dg-error "throw" "" { target c++23_down } } } -constexpr int x = may_throw(false); // { dg-message "may_throw" } -constexpr int y = may_throw(true); +constexpr int x = may_throw(false); // { dg-message "may_throw" "" { target c++23_down } } +constexpr int y = may_throw(true); // { dg-error "uncaught exception '-1'" "" { target c++26 } .-1 } diff --git a/gcc/testsuite/g++.dg/cpp0x/duplicate1.C b/gcc/testsuite/g++.dg/cpp0x/duplicate1.C index 1545e1c..4e85edc 100644 --- a/gcc/testsuite/g++.dg/cpp0x/duplicate1.C +++ b/gcc/testsuite/g++.dg/cpp0x/duplicate1.C @@ -6,7 +6,7 @@ struct A virtual void foo() const; }; -struct B final final : A /* { dg-error "duplicate virt-specifier" } +struct B final final : A /* { dg-error "duplicate 'final' specifier" } { dg-begin-multiline-output "" } struct B final final : A ^~~~~ diff --git a/gcc/testsuite/g++.dg/cpp0x/final1.C b/gcc/testsuite/g++.dg/cpp0x/final1.C new file mode 100644 index 0000000..1d64095 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/final1.C @@ -0,0 +1,11 @@ +// PR c++/120628 +// { dg-do compile { target c++98_only } } + +namespace A { + struct B {}; + struct B final = {}; +} +namespace C { + struct D { D (int, int); }; + struct D final (42, 0); +} diff --git a/gcc/testsuite/g++.dg/cpp0x/final2.C b/gcc/testsuite/g++.dg/cpp0x/final2.C new file mode 100644 index 0000000..d8d5866 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/final2.C @@ -0,0 +1,26 @@ +// PR c++/120628 +// { dg-do compile } +// { dg-options "" } +// { dg-additional-options "-pedantic" { target c++14 } } + +namespace U { + struct A {}; + struct A final = {}; +} +namespace V { + template <int N> + struct B {}; + template <int N> + struct B<N> final = {}; // { dg-warning "variable templates only available with" "" { target c++11_down } } +} +struct C { + struct D {}; + static D foo (); + struct D final = foo (); // { dg-warning "non-static data member initializers only available with" "" { target c++98_only } } +}; +namespace W { + struct E { struct F {}; }; + struct E::F final = {}; +} +template <int N> +struct V::B<N> final = {}; // { dg-warning "variable templates only available with" "" { target c++11_down } } diff --git a/gcc/testsuite/g++.dg/cpp0x/override2.C b/gcc/testsuite/g++.dg/cpp0x/override2.C index ab4dec4..d7f542e 100644 --- a/gcc/testsuite/g++.dg/cpp0x/override2.C +++ b/gcc/testsuite/g++.dg/cpp0x/override2.C @@ -23,9 +23,9 @@ struct D5 : B3<D5> {}; struct D6 : B4<D6> {}; // { dg-error "cannot derive from 'final' base" } -struct B6 final final {}; // { dg-error "duplicate virt-specifier" } +struct B6 final final {}; // { dg-error "duplicate 'final' specifier" } -struct B7 override {}; // { dg-error "cannot specify 'override' for a class" } +struct B7 override {}; // { dg-error "variable 'B7 override' has initializer but incomplete type" } namespace N { @@ -45,7 +45,7 @@ int main() struct B2 final; // { dg-error "redeclaration" } struct B2 override; // { dg-message "previously declared here" } struct B2 final {}; // { dg-error "redefinition" } - struct B2 override {}; // { dg-error "cannot specify 'override' for a class" } + struct B2 override {}; // { dg-error "redeclaration of 'main\\\(\\\)::B2 override'" } B2 override{}; // { dg-error "redeclaration" } struct foo final {}; // { dg-message "previous definition" } struct foo final {}; // { dg-error "redefinition" } diff --git a/gcc/testsuite/g++.dg/cpp0x/override5.C b/gcc/testsuite/g++.dg/cpp0x/override5.C new file mode 100644 index 0000000..3382c14 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/override5.C @@ -0,0 +1,26 @@ +// PR c++/120569 +// { dg-do compile } +// { dg-options "" } +// { dg-additional-options "-pedantic" { target c++14 } } + +namespace U { + struct A {}; + struct A override {}; // { dg-warning "extended initializer lists only available with" "" { target c++98_only } } +} +namespace V { + template <int N> + struct B {}; + template <int N> + struct B<N> override {}; // { dg-warning "extended initializer lists only available with" "" { target c++98_only } } +} // { dg-warning "variable templates only available with" "" { target c++11_down } .-1 } +struct C { + struct D {}; + struct D override {}; // { dg-warning "extended initializer lists only available with" "" { target c++98_only } } +}; // { dg-warning "non-static data member initializers only available with" "" { target c++98_only } .-1 } +namespace W { + struct E { struct F {}; }; + struct E::F override {}; // { dg-warning "extended initializer lists only available with" "" { target c++98_only } } +} +template <int N> +struct V::B<N> override {}; // { dg-warning "extended initializer lists only available with" "" { target c++98_only } } + // { dg-warning "variable templates only available with" "" { target c++11_down } .-1 } diff --git a/gcc/testsuite/g++.dg/cpp0x/override6.C b/gcc/testsuite/g++.dg/cpp0x/override6.C new file mode 100644 index 0000000..601e91d --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/override6.C @@ -0,0 +1,26 @@ +// PR c++/120628 +// { dg-do compile } +// { dg-options "" } +// { dg-additional-options "-pedantic" { target c++14 } } + +namespace U { + struct A {}; + struct A override = {}; +} +namespace V { + template <int N> + struct B {}; + template <int N> + struct B<N> override = {}; // { dg-warning "variable templates only available with" "" { target c++11_down } } +} +struct C { + struct D {}; + static D foo (); + struct D override = foo (); // { dg-warning "non-static data member initializers only available with" "" { target c++98_only } } +}; +namespace W { + struct E { struct F {}; }; + struct E::F override = {}; +} +template <int N> +struct V::B<N> override = {}; // { dg-warning "variable templates only available with" "" { target c++11_down } } diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for40.C b/gcc/testsuite/g++.dg/cpp0x/range-for40.C new file mode 100644 index 0000000..dea4a2a --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/range-for40.C @@ -0,0 +1,41 @@ +// PR c++/84009 +// { dg-do compile { target c++11 } } + +int z[64]; + +void +foo () +{ + for (static auto a : z) // { dg-error "for-range-declaration cannot be 'static'" } + ; + for (thread_local auto a : z) // { dg-error "for-range-declaration cannot be 'thread_local'" } + ; + for (__thread auto a : z) // { dg-error "for-range-declaration cannot be '__thread'" } + ; // { dg-error "function-scope 'a' implicitly auto and declared '__thread'" "" { target *-*-* } .-1 } + for (register auto a : z) // { dg-error "for-range-declaration cannot be 'register'" } + ; // { dg-error "does not allow 'register' storage class specifier" "" { target c++17 } .-1 } + for (extern auto a : z) // { dg-error "for-range-declaration cannot be 'extern'" } + ; // { dg-error "'a' has both 'extern' and initializer" "" { target *-*-* } .-1 } + for (mutable auto a : z) // { dg-error "non-member 'a' cannot be declared 'mutable'" } + ; + for (virtual auto a : z) // { dg-error "'virtual' outside class declaration" } + ; + for (explicit auto a : z) // { dg-error "'explicit' outside class declaration" } + ; + for (friend auto a : z) // { dg-error "'friend' used outside of class" } + ; + for (typedef auto a : z) // { dg-error "typedef declared 'auto'" } + ; // { dg-error "typedef 'a' is initialized \\\(use 'decltype' instead\\\)" "" { target *-*-* } .-1 } +#if __cplusplus >= 202002L + for (consteval auto a : z) // { dg-error "a variable cannot be declared 'consteval'" "" { target c++20 } } + ; + for (constinit auto a : z) // { dg-error "'constinit' can only be applied to a variable with static or thread storage duration" "" { target c++20 } } + ; +#endif + for (inline auto a : z) // { dg-error "'inline' specifier invalid for variable 'a' declared at block scope" } + ; + for (struct S { int a; } a : z) // { dg-error "types may not be defined in a for-range-declaration" } + ; // { dg-error "conversion from 'int' to non-scalar type 'foo\\\(\\\)::S' requested" "" { target *-*-* } .-1 } + for (enum E { E0 } a : z) // { dg-error "types may not be defined in a for-range-declaration" } + ; // { dg-error "invalid conversion from 'int' to 'foo\\\(\\\)::E'" "" { target *-*-* } .-1 } +} diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for41.C b/gcc/testsuite/g++.dg/cpp0x/range-for41.C new file mode 100644 index 0000000..d690365 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/range-for41.C @@ -0,0 +1,42 @@ +// PR c++/84009 +// { dg-do compile { target c++11 } } +// { dg-options "" } + +int z[64]; + +void +foo () +{ + for (static auto a : z) // { dg-warning "for-range-declaration cannot be 'static'" } + ; + for (thread_local auto a : z) // { dg-warning "for-range-declaration cannot be 'thread_local'" } + ; + for (__thread auto a : z) // { dg-warning "for-range-declaration cannot be '__thread'" } + ; // { dg-warning "function-scope 'a' implicitly auto and declared '__thread'" "" { target *-*-* } .-1 } + for (register auto a : z) // { dg-warning "for-range-declaration cannot be 'register'" } + ; // { dg-warning "does not allow 'register' storage class specifier" "" { target c++17 } .-1 } + for (extern auto a : z) // { dg-warning "for-range-declaration cannot be 'extern'" } + ; // { dg-error "'a' has both 'extern' and initializer" "" { target *-*-* } .-1 } + for (mutable auto a : z) // { dg-error "non-member 'a' cannot be declared 'mutable'" } + ; + for (virtual auto a : z) // { dg-error "'virtual' outside class declaration" } + ; + for (explicit auto a : z) // { dg-error "'explicit' outside class declaration" } + ; + for (friend auto a : z) // { dg-error "'friend' used outside of class" } + ; + for (typedef auto a : z) // { dg-error "typedef declared 'auto'" } + ; // { dg-error "typedef 'a' is initialized \\\(use 'decltype' instead\\\)" "" { target *-*-* } .-1 } +#if __cplusplus >= 202002L + for (consteval auto a : z) // { dg-error "a variable cannot be declared 'consteval'" "" { target c++20 } } + ; + for (constinit auto a : z) // { dg-error "'constinit' can only be applied to a variable with static or thread storage duration" "" { target c++20 } } + ; +#endif + for (inline auto a : z) // { dg-error "'inline' specifier invalid for variable 'a' declared at block scope" } + ; + for (struct S { int a; } a : z) // { dg-error "types may not be defined in a for-range-declaration" } + ; // { dg-error "conversion from 'int' to non-scalar type 'foo\\\(\\\)::S' requested" "" { target *-*-* } .-1 } + for (enum E { E0 } a : z) // { dg-error "types may not be defined in a for-range-declaration" } + ; // { dg-error "invalid conversion from 'int' to 'foo\\\(\\\)::E'" "" { target *-*-* } .-1 } +} diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for42.C b/gcc/testsuite/g++.dg/cpp0x/range-for42.C new file mode 100644 index 0000000..a5d94fc --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/range-for42.C @@ -0,0 +1,41 @@ +// PR c++/84009 +// { dg-do compile { target c++11 } } + +struct S { int y; } z[64]; + +void +foo () +{ + for (static auto [ a ] : z) // { dg-error "for-range-declaration cannot be 'static'" } + ; // { dg-error "structured binding declaration can be 'static' only in" "" { target c++17_down } .-1 } + // { dg-error "structured bindings only available with" "" { target c++14_down } .-2 } + for (thread_local auto [ a ] : z) // { dg-error "for-range-declaration cannot be 'thread_local'" } + ; // { dg-error "structured binding declaration can be 'thread_local' only in" "" { target c++17_down } .-1 } + // { dg-error "structured bindings only available with" "" { target c++14_down } .-2 } + for (__thread auto [ a ] : z) // { dg-error "for-range-declaration cannot be '__thread'" } + ; // { dg-error "function-scope 'structured binding' implicitly auto and declared '__thread'" "" { target *-*-* } .-1 } + // { dg-error "structured binding declaration can be '__thread' only in" "" { target c++17_down } .-2 } + // { dg-error "structured bindings only available with" "" { target c++14_down } .-3 } + for (register auto [ a ] : z) // { dg-error "structured binding declaration cannot be 'register'" } + ; // { dg-error "structured bindings only available with" "" { target c++14_down } .-1 } + for (extern auto [ a ] : z) // { dg-error "structured binding declaration cannot be 'extern'" } + ; // { dg-error "structured bindings only available with" "" { target c++14_down } .-1 } + for (mutable auto [ a ] : z) // { dg-error "structured binding declaration cannot be 'mutable'" } + ; // { dg-error "structured bindings only available with" "" { target c++14_down } .-1 } + for (virtual auto [ a ] : z) // { dg-error "'virtual' outside class declaration" } + ; // { dg-error "structured bindings only available with" "" { target c++14_down } .-1 } + for (explicit auto [ a ] : z) // { dg-error "'explicit' outside class declaration" } + ; // { dg-error "structured bindings only available with" "" { target c++14_down } .-1 } + for (friend auto [ a ] : z) // { dg-error "'friend' used outside of class" } + ; // { dg-error "structured bindings only available with" "" { target c++14_down } .-1 } + for (typedef auto [ a ] : z) // { dg-error "structured binding declaration cannot be 'typedef'" } + ; // { dg-error "structured bindings only available with" "" { target c++14_down } .-1 } +#if __cplusplus >= 202002L + for (consteval auto [ a ] : z) // { dg-error "structured binding declaration cannot be 'consteval'" "" { target c++20 } } + ; + for (constinit auto [ a ] : z) // { dg-error "'constinit' can only be applied to a variable with static or thread storage duration" "" { target c++20 } } + ; +#endif + for (inline auto [ a ] : z) // { dg-error "structured binding declaration cannot be 'inline'" } + ; // { dg-error "structured bindings only available with" "" { target c++14_down } .-1 } +} diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for43.C b/gcc/testsuite/g++.dg/cpp0x/range-for43.C new file mode 100644 index 0000000..77060e3 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/range-for43.C @@ -0,0 +1,42 @@ +// PR c++/84009 +// { dg-do compile { target c++11 } } +// { dg-options "" } + +struct S { int y; } z[64]; + +void +foo () +{ + for (static auto [ a ] : z) // { dg-warning "for-range-declaration cannot be 'static'" } + ; // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-1 } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-2 } + for (thread_local auto [ a ] : z) // { dg-warning "for-range-declaration cannot be 'thread_local'" } + ; // { dg-warning "structured binding declaration can be 'thread_local' only in" "" { target c++17_down } .-1 } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-2 } + for (__thread auto [ a ] : z) // { dg-warning "for-range-declaration cannot be '__thread'" } + ; // { dg-warning "function-scope 'structured binding' implicitly auto and declared '__thread'" "" { target *-*-* } .-1 } + // { dg-warning "structured binding declaration can be '__thread' only in" "" { target c++17_down } .-2 } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-3 } + for (register auto [ a ] : z) // { dg-error "structured binding declaration cannot be 'register'" } + ; // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + for (extern auto [ a ] : z) // { dg-error "structured binding declaration cannot be 'extern'" } + ; // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + for (mutable auto [ a ] : z) // { dg-error "structured binding declaration cannot be 'mutable'" } + ; // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + for (virtual auto [ a ] : z) // { dg-error "'virtual' outside class declaration" } + ; // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + for (explicit auto [ a ] : z) // { dg-error "'explicit' outside class declaration" } + ; // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + for (friend auto [ a ] : z) // { dg-error "'friend' used outside of class" } + ; // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } + for (typedef auto [ a ] : z) // { dg-error "structured binding declaration cannot be 'typedef'" } + ; // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } +#if __cplusplus >= 202002L + for (consteval auto [ a ] : z) // { dg-error "structured binding declaration cannot be 'consteval'" "" { target c++20 } } + ; + for (constinit auto [ a ] : z) // { dg-error "'constinit' can only be applied to a variable with static or thread storage duration" "" { target c++20 } } + ; +#endif + for (inline auto [ a ] : z) // { dg-error "structured binding declaration cannot be 'inline'" } + ; // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } +} diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-84192.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-84192.C index f7439d8..18efd23 100644 --- a/gcc/testsuite/g++.dg/cpp1y/constexpr-84192.C +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-84192.C @@ -12,7 +12,7 @@ void f2 () { for (;;) - constexpr bool b = ({ break; false; }) && false; // { dg-error "is not a constant expression" } + constexpr bool b = ({ break; false; }) && false; // { dg-error "'break' outside of a loop or 'switch'" } } constexpr bool diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-throw.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-throw.C index b5fa6ca..75e2fb8 100644 --- a/gcc/testsuite/g++.dg/cpp1y/constexpr-throw.C +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-throw.C @@ -27,8 +27,8 @@ constexpr int fun(int n) { case 0: return 1; default: - throw; // { dg-error "not a constant expression" } - } + throw; // { dg-error "not a constant expression" "" { target c++23_down } } + } // { dg-error "'void __cxa_rethrow\\\(\\\)' called with no caught exceptions active" "" { target c++26 } .-1 } } static_assert(fun(0), ""); diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic-a.C b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic-a.C new file mode 100644 index 0000000..557ecb9 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic-a.C @@ -0,0 +1,15 @@ +// Basic generic lambda test +// { dg-do run { target c++14 } } +// { dg-additional-options -Wno-abbreviated-auto-in-template-arg } + +template <typename T, typename U> struct pair {}; +template <typename... T> struct tuple {}; + +int main() +{ + auto a = [] (auto, pair<auto,auto> v) { return sizeof (v); }; + auto b = [] (auto, pair<pair<auto,auto>,auto>... v) { return sizeof... (v); }; + + a(1, pair<int, float>()); + b(2, pair<pair<short,char>, double>(), pair<pair<float,long>, int>()); +} diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic.C b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic.C index 6d2d250..6ef8652 100644 --- a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic.C +++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic.C @@ -1,13 +1,13 @@ // Basic generic lambda test -// { dg-do run { target c++14 } } +// { dg-do compile { target c++14 } } template <typename T, typename U> struct pair {}; template <typename... T> struct tuple {}; int main() { - auto a = [] (auto, pair<auto,auto> v) { return sizeof (v); }; - auto b = [] (auto, pair<pair<auto,auto>,auto>... v) { return sizeof... (v); }; + auto a = [] (auto, pair<auto,auto> v) { return sizeof (v); }; // { dg-error "auto" } + auto b = [] (auto, pair<pair<auto,auto>,auto>... v) { return sizeof... (v); }; // { dg-error "auto" } a(1, pair<int, float>()); b(2, pair<pair<short,char>, double>(), pair<pair<float,long>, int>()); diff --git a/gcc/testsuite/g++.dg/cpp1y/pr85076.C b/gcc/testsuite/g++.dg/cpp1y/pr85076.C index 6d54dea..b68143b 100644 --- a/gcc/testsuite/g++.dg/cpp1y/pr85076.C +++ b/gcc/testsuite/g++.dg/cpp1y/pr85076.C @@ -3,4 +3,4 @@ template<typename> struct A*; // { dg-error "expected unqualified-id before" } -auto a = [](A<auto>) {}; // { dg-error "is not a template|has incomplete type" } +auto a = [](A<auto>) {}; // { dg-error "is not a template|has incomplete type|auto" } diff --git a/gcc/testsuite/g++.dg/cpp1z/constexpr-asm-5.C b/gcc/testsuite/g++.dg/cpp1z/constexpr-asm-5.C index 35beb27..2c69b3b 100644 --- a/gcc/testsuite/g++.dg/cpp1z/constexpr-asm-5.C +++ b/gcc/testsuite/g++.dg/cpp1z/constexpr-asm-5.C @@ -18,7 +18,7 @@ struct H { short size () const { return 0; } constexpr const char *data () const { return ""; } }; struct I { constexpr signed char size () const { return 0; } const char *data () const { return ""; } }; -struct J { constexpr int size () const { return j ? throw 1 : 0; } // { dg-error "expression '<throw-expression>' is not a constant expression" } +struct J { constexpr int size () const { return j ? throw 1 : 0; } // { dg-error "expression '<throw-expression>' is not a constant expression" "" { target c++23_down } } constexpr const char *data () const { return ""; }; constexpr J (int x) : j (x) {} int j; }; @@ -114,6 +114,7 @@ foo () asm ((J (0))); asm ("" :: (J (1)) (1)); // { dg-error "constexpr string 'size\\\(\\\)' must be a constant expression" } + // { dg-error "uncaught exception '1'" "" { target c++26 } .-1 } asm ((M {})); #if __cpp_constexpr_dynamic_alloc >= 201907L asm ((N {})); // { dg-error "constexpr string 'data\\\(\\\)\\\[0\\\]' must be a constant expression" "" { target c++20 } } @@ -188,6 +189,7 @@ bar () asm ((J (0))); asm ("" :: (J (1)) (1)); // { dg-error "constexpr string 'size\\\(\\\)' must be a constant expression" } + // { dg-error "uncaught exception '1'" "" { target c++26 } .-1 } asm ((M {})); #if __cpp_constexpr_dynamic_alloc >= 201907L asm ((N {})); // { dg-error "constexpr string 'data\\\(\\\)\\\[0\\\]' must be a constant expression" "" { target c++20 } } @@ -272,7 +274,7 @@ namespace NN #if __cplusplus >= 201402L struct J { static constexpr int size () { return 0; } - static constexpr const char *data (int x = 0) { if (x) return nullptr; else throw 1; } }; // { dg-error "expression '<throw-expression>' is not a constant expression" "" { target c++14 } } + static constexpr const char *data (int x = 0) { if (x) return nullptr; else throw 1; } }; // { dg-error "expression '<throw-expression>' is not a constant expression" "" { target { c++14 && c++23_down } } } #endif #if __cpp_if_consteval >= 202106L struct K { @@ -284,12 +286,12 @@ namespace NN static constexpr const char *data () { if consteval { return "test"; } else { throw 1; } } }; struct M { - static constexpr int size () { if consteval { throw 1; } else { return 4; } } // { dg-error "expression '<throw-expression>' is not a constant expression" "" { target c++23 } } + static constexpr int size () { if consteval { throw 1; } else { return 4; } } // { dg-error "expression '<throw-expression>' is not a constant expression" "" { target c++23_only } } static constexpr const char *data () { return "test"; } }; struct N { static constexpr int size () { return 4; } - static constexpr const char *data () { if consteval { throw 1; } else { return "test"; } } // { dg-error "expression '<throw-expression>' is not a constant expression" "" { target c++23 } } + static constexpr const char *data () { if consteval { throw 1; } else { return "test"; } } // { dg-error "expression '<throw-expression>' is not a constant expression" "" { target c++23_only } } }; #endif struct O { constexpr int operator () () const { return 12; } }; @@ -318,12 +320,15 @@ namespace NN asm ((I {})); #if __cplusplus >= 201402L asm ((J {})); // { dg-error "constexpr string 'data\\\(\\\)' must be a core constant expression" "" { target c++14 } } + // { dg-error "uncaught exception '1'" "" { target c++26 } .-1 } #endif #if __cpp_if_consteval >= 202106L asm ((K {})); asm ((L {})); asm ((M {})); // { dg-error "constexpr string 'size\\\(\\\)' must be a constant expression" "" { target c++23 } } + // { dg-error "uncaught exception '1'" "" { target c++26 } .-1 } asm ((N {})); // { dg-error "constexpr string 'data\\\(\\\)\\\[0\\\]' must be a constant expression" "" { target c++23 } } + // { dg-error "uncaught exception '1'" "" { target c++26 } .-1 } #endif asm ((Q {})); asm ((R {})); @@ -348,12 +353,15 @@ namespace NN asm ((I {})); #if __cplusplus >= 201402L asm ((J {})); // { dg-error "constexpr string 'data\\\(\\\)' must be a core constant expression" "" { target c++14 } } + // { dg-error "uncaught exception '1'" "" { target c++26 } .-1 } #endif #if __cpp_if_consteval >= 202106L asm ((K {})); asm ((L {})); asm ((M {})); // { dg-error "constexpr string 'size\\\(\\\)' must be a constant expression" "" { target c++23 } } + // { dg-error "uncaught exception '1'" "" { target c++26 } .-1 } asm ((N {})); // { dg-error "constexpr string 'data\\\(\\\)\\\[0\\\]' must be a constant expression" "" { target c++23 } } + // { dg-error "uncaught exception '1'" "" { target c++26 } .-1 } #endif asm ((Q {})); asm ((R {})); diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp3.C b/gcc/testsuite/g++.dg/cpp1z/decomp3.C index a9b23b0..202edc3 100644 --- a/gcc/testsuite/g++.dg/cpp1z/decomp3.C +++ b/gcc/testsuite/g++.dg/cpp1z/decomp3.C @@ -19,7 +19,8 @@ test (A &b, B c) // { dg-error "expected primary-expression before 'decltype'" "" { target c++11_down } .-2 } auto & & && & [ m, n, o ] = b; // { dg-error "multiple ref-qualifiers" } // { dg-warning "structured bindings only available with '-std=c..17' or '-std=gnu..17'" "" { target c++14_down } .-1 } - constexpr auto [ p ] = c; // { dg-error "structured binding declaration cannot be 'constexpr'" } + constexpr B c2 = { 42 }; + constexpr auto [ p ] = c2; // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } } // { dg-warning "structured bindings only available with '-std=c..17' or '-std=gnu..17'" "" { target c++14_down } .-1 } friend auto [ q ] = c; // { dg-error "'friend' used outside of class" } // { dg-warning "structured bindings only available with '-std=c..17' or '-std=gnu..17'" "" { target c++14_down } .-1 } diff --git a/gcc/testsuite/g++.dg/cpp26/constexpr-eh1.C b/gcc/testsuite/g++.dg/cpp26/constexpr-eh1.C new file mode 100644 index 0000000..9eed3aa --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp26/constexpr-eh1.C @@ -0,0 +1,140 @@ +// C++26 P3068R5 - Allowing exception throwing in constant-evaluation +// { dg-do compile { target c++26 } } +// { dg-require-effective-target exceptions_enabled } + +struct S { + constexpr S () : s (new int (0)) {} + constexpr S (int x) : s (new int (x)) {} + constexpr S (const S &x) : s (new int (*x.s)) {} + constexpr ~S () { delete s; } + int *s; +}; +struct T : public S { + constexpr T () : S () {} + constexpr T (int x) : S (x) {} + constexpr T (const T &x) : S (*x.s) {} + constexpr ~T () {} +}; +struct U : public T { + constexpr U () : T () {} + constexpr U (int x) : T (x) {} + constexpr U (const U &x) : T (*x.s) {} + constexpr ~U () {} +}; +struct V : public T { + constexpr V () : T () {} + constexpr V (int x) : T (x) {} + constexpr V (const U &x) : T (*x.s) {} + constexpr ~V () {} +}; + +template <typename X> +constexpr int +foo (X x) +{ + try { throw x; } + catch (int &a) { return 42 + a; } + catch (const unsigned b) { return 43 + b; } + catch (const long &c) { return 44 + c; } + catch (bool d) { return 45 + d; } + catch (const U &e) { return 46 + *e.s; } + catch (const T &f) { return 47 + *f.s; } + catch (S g) { return 48 + *g.s; } + catch (int *const &h) { return 49; } + catch (long long *) { return 50; } + catch (const S *const &) { return 51; } + catch (...) { return 52; } +} + +template <typename X> +constexpr int +bar (const X &x) +{ + throw x; +} + +template <typename X> +constexpr int +baz (const X &x) +{ + try + { + try { bar (x); } + catch (int &a) { a += 80; throw; } + catch (long b) { b += 80; throw; } + catch (U &c) { c.s[0] += 82; throw; } + catch (V d) { d.s[0] += 83; throw; } + } + catch (int a) { return 42 + a; } + catch (const long &b) { return 43 + b; } + catch (S &c) { return 44 + c.s[0]; } + catch (long long d) { return 45 + d; } + catch (...) { return -1; } +} + +constexpr int +qux (int x, bool y = true) +{ + try + { + switch (x) + { + case 0: throw 42; break; + case 1: x = y ? throw 43 : 5; break; + case 2: x = -(throw 44, 6); break; + case 3: x = x + (throw 45, 7); break; + case 4: x = (throw 46, 8) + x; break; + case 5: x = (throw 47, y) ? 4 : 5; break; + case 6: x += (throw 48, y); break; + case 7: x = (double) (throw 49, y); break; + case 8: x = foo ((throw 50, x)); break; + default: break; + } + } + catch (int a) { return a; } + return -1; +} + +constexpr int +corge () +{ + try { throw 0; } + catch (int *const &h) { return 49; } + catch (long long *) { return 50; } + catch (const S *const &) { return 51; } + catch (...) { return 52; } +} + +static_assert (foo (12) == 54); +static_assert (foo (12U) == 55); +static_assert (foo (12L) == 56); +static_assert (foo (false) == 45); +static_assert (foo (true) == 46); +static_assert (foo (U (12)) == 58); +static_assert (foo (T (20)) == 67); +static_assert (foo (S (30)) == 78); +static_assert (foo (nullptr) == 49); +static_assert (foo ((int *)nullptr) == 49); +static_assert (foo ((long long *)nullptr) == 50); +static_assert (foo ((const S *)nullptr) == 51); +static_assert (foo ((const T *)nullptr) == 51); +static_assert (foo ((const U *)nullptr) == 51); +static_assert (foo (12ULL) == 52); +static_assert (baz (5) == 127); +static_assert (baz (6L) == 49); +static_assert (baz (U (25)) == 151); +static_assert (baz (V (26)) == 70); +static_assert (baz (T (27)) == 71); +static_assert (baz (S (28)) == 72); +static_assert (baz (7LL) == 52); +static_assert (baz (8ULL) == -1); +static_assert (qux (0) == 42); +static_assert (qux (1) == 43); +static_assert (qux (2) == 44); +static_assert (qux (3) == 45); +static_assert (qux (4) == 46); +static_assert (qux (5) == 47); +static_assert (qux (6) == 48); +static_assert (qux (7) == 49); +static_assert (qux (8) == 50); +static_assert (corge () == 52); diff --git a/gcc/testsuite/g++.dg/cpp26/constexpr-eh10.C b/gcc/testsuite/g++.dg/cpp26/constexpr-eh10.C new file mode 100644 index 0000000..a86cc4d --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp26/constexpr-eh10.C @@ -0,0 +1,110 @@ +// C++26 P3068R5 - Allowing exception throwing in constant-evaluation +// { dg-do compile { target c++26 } } +// { dg-require-effective-target exceptions_enabled } + +struct S { +}; +struct T { + constexpr ~T () noexcept (false) { throw S {}; } +}; +struct U { + int u; +}; +struct V { + int v; + constexpr V (int x) + try : v { x } + { + if (v > 42) + throw U { 42 }; + } + catch (U &u) + { + --u.u; + } +}; +struct W { + constexpr ~W () { ++w; } + int &w; +}; +struct X : public V { + constexpr X (int x) + try : V(x) + { + } + catch (U &u) + { + --u.u; + } +}; + +constexpr int +foo (bool x) +{ + try + { + T t; // { dg-error "'std::terminate' called after throwing an exception '42'" } + if (x) // { dg-message "destructor exited with an exception" "" { target *-*-* } .-1 } + throw 42; + return 10; + } + catch (S) + { + return 11; + } +} + +constexpr int +bar () +{ + V v { 42 }; + try + { + V w { 43 }; + } + catch (const U &u) + { + if (u.u == 41) + return 44; + } + return -1; +} + +constexpr int +baz () +{ + int i = 42; + try + { + W w { i }; + throw S (); + } + catch (...) + { + if (i == 43) + return 42; + } + return -1; +} + +constexpr int +qux () +{ + X v { 42 }; + try + { + X w { 43 }; + } + catch (const U &u) + { + if (u.u == 40) + return 48; + } + return -1; +} + +static_assert (foo (false) == 11); +constexpr int a = foo (true); // { dg-message "in 'constexpr' expansion of" } +static_assert (bar () == 44); +static_assert (baz () == 42); +static_assert (qux () == 48); diff --git a/gcc/testsuite/g++.dg/cpp26/constexpr-eh11.C b/gcc/testsuite/g++.dg/cpp26/constexpr-eh11.C new file mode 100644 index 0000000..287e066 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp26/constexpr-eh11.C @@ -0,0 +1,69 @@ +// C++26 P3068R5 - Allowing exception throwing in constant-evaluation +// { dg-do compile { target c++26 } } +// { dg-require-effective-target exceptions_enabled } + +struct A { + explicit constexpr A (int x) noexcept : a (x) {} + constexpr virtual int foo () const noexcept { return a; } + constexpr virtual ~A () {} + int a; +}; +struct B : public A { + explicit constexpr B (int x) noexcept : A (x) {} + constexpr int foo () const noexcept override { return a | 0x10; } +}; +struct C : public A { + explicit constexpr C (int x) noexcept : A (x) {} +}; +struct D : public A { + explicit constexpr D (int x) noexcept : A (x) {} +}; +struct E { + constexpr E () noexcept : e (0) {} + explicit constexpr E (int x) noexcept : e (x) {} + int e; +}; +struct F : public E, public B { + explicit constexpr F (int x) noexcept : B (x) {} +}; +struct G : public E, public C { + explicit constexpr G (int x) noexcept : C (x) {} +}; +struct H : public E, public D { + explicit constexpr H (int x) noexcept : D (x) {} +}; + +consteval int +bar (void (*fn) ()) +{ + try + { + fn (); + } + catch (C &a) + { + return a.foo () | 0x20; + } + catch (const C &b) // { dg-warning "exception of type 'C' will be caught by earlier handler" } + { + return b.foo () | 0x60; + } + catch (A &c) + { + return c.foo (); + } + catch (const A &d) // { dg-warning "exception of type 'A' will be caught by earlier handler" } + { + return d.foo () | 0x40; + } + return -1; +} + +static_assert (bar ([] { throw A { 1 }; }) == 1); +static_assert (bar ([] { throw B { 2 }; }) == 0x12); +static_assert (bar ([] { throw C { 3 }; }) == 0x23); +static_assert (bar ([] { throw D { 4 }; }) == 4); +constexpr int a = bar ([] { throw E { 5 }; }); // { dg-error "uncaught exception 'E\\\{5\\\}'" } +static_assert (bar ([] { throw F { 6 }; }) == 0x16); +static_assert (bar ([] { throw G { 7 }; }) == 0x27); +static_assert (bar ([] { throw H { 8 }; }) == 8); diff --git a/gcc/testsuite/g++.dg/cpp26/constexpr-eh12.C b/gcc/testsuite/g++.dg/cpp26/constexpr-eh12.C new file mode 100644 index 0000000..4a85f15 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp26/constexpr-eh12.C @@ -0,0 +1,74 @@ +// C++26 P3068R5 - Allowing exception throwing in constant-evaluation +// { dg-do compile { target c++26 } } +// { dg-require-effective-target exceptions_enabled } + +struct A { + explicit constexpr A (int x) noexcept : a (x) {} + constexpr virtual int foo () const noexcept { return a; } + constexpr virtual ~A () {} + int a; +}; +struct B : public A { + explicit constexpr B (int x) noexcept : A (x) {} + constexpr int foo () const noexcept override { return a | 0x10; } +}; +struct C : public A { + explicit constexpr C (int x) noexcept : A (x) {} +}; +struct D : public A { + explicit constexpr D (int x) noexcept : A (x) {} +}; +struct E { + constexpr E () noexcept : e (0) {} + explicit constexpr E (int x) noexcept : e (x) {} + int e; +}; +struct F : public E, public B { + explicit constexpr F (int x) noexcept : B (x) {} +}; +struct G : public E, public C { + explicit constexpr G (int x) noexcept : C (x) {} +}; +struct H : public E, public D { + explicit constexpr H (int x) noexcept : D (x) {} +}; + +consteval int +bar (void (*fn) ()) +{ + int r = 0; + try + { + fn (); + } + catch (C *a) + { + r = a->foo () | 0x20; + delete a; + } + catch (const C *b) + { + r = b->foo () | 0x60; + delete b; + } + catch (A *c) + { + r = c->foo (); + delete c; + } + catch (const A *d) + { + r = d->foo () | 0x40; + delete d; + } + return r; +} + +static_assert (bar ([] { throw new A { 1 }; }) == 1); +static_assert (bar ([] { throw new B { 2 }; }) == 0x12); +static_assert (bar ([] { throw new C { 3 }; }) == 0x23); +static_assert (bar ([] { throw new D { 4 }; }) == 4); +constexpr int a = bar ([] { throw new E { 5 }; }); // { dg-error "uncaught exception of type 'E\\\*'" } +static_assert (bar ([] { throw new F { 6 }; }) == 0x16); +static_assert (bar ([] { throw new G { 7 }; }) == 0x27); +static_assert (bar ([] { throw new H { 8 }; }) == 8); diff --git a/gcc/testsuite/g++.dg/cpp26/constexpr-eh13.C b/gcc/testsuite/g++.dg/cpp26/constexpr-eh13.C new file mode 100644 index 0000000..d62771c --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp26/constexpr-eh13.C @@ -0,0 +1,36 @@ +// C++26 P3068R5 - Allowing exception throwing in constant-evaluation +// { dg-do compile { target c++26 } } +// { dg-require-effective-target exceptions_enabled } + +template <typename T> +consteval T +foo (T x) +{ + try + { + throw &x; + } + catch (void *ptr) // { dg-message "for type 'void\\\*'" } + { + return *static_cast<T *> (ptr) | 0x10; + } + catch (const void *ptr) // { dg-message "for type 'const void\\\*'" } + { + return *static_cast<const T *> (ptr) | 0x20; + } + catch (T *ptr) // { dg-warning "exception of type 'T\\\*' will be caught by earlier handler" } + { // { dg-warning "exception of type 'int\\\*' will be caught by earlier handler" "" { target *-*-* } .-1 } + return *ptr | 0x30; // { dg-warning "exception of type 'long long unsigned int\\\*' will be caught by earlier handler" "" { target *-*-* } .-2 } + } + catch (const T *ptr) + { + return *ptr | 0x40; + } + catch (...) + { + return -1; + } +} + +static_assert (foo (1) == 0x11); +static_assert (foo (2ULL) == 0x12ULL); diff --git a/gcc/testsuite/g++.dg/cpp26/constexpr-eh14.C b/gcc/testsuite/g++.dg/cpp26/constexpr-eh14.C new file mode 100644 index 0000000..3e52f2b --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp26/constexpr-eh14.C @@ -0,0 +1,42 @@ +// C++26 P3068R5 - Allowing exception throwing in constant-evaluation +// { dg-do compile { target c++26 } } +// { dg-require-effective-target exceptions_enabled } + +template <typename T> +constexpr T +foo (T x, auto... y) +{ + const T z[] = { x, y... }; + try + { + throw z; + } + catch (const T (&a)[4]) + { + return T (); + } + catch (const T *b) + { + return b[0]; + } + catch (...) + { + return T (); + } +} + +void +bar () +{ +} + +void +baz () +{ +} + +static_assert (foo (42, 43, 44, 45, 46) == 42); +static_assert (foo (43U, 44U, 45U, 46U) == 43U); +static_assert (foo (44LL, 45LL) == 44LL); +static_assert (foo (bar, baz, bar, baz) == bar); +static_assert (foo (baz, bar) == baz); diff --git a/gcc/testsuite/g++.dg/cpp26/constexpr-eh15.C b/gcc/testsuite/g++.dg/cpp26/constexpr-eh15.C new file mode 100644 index 0000000..3dea461 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp26/constexpr-eh15.C @@ -0,0 +1,39 @@ +// C++26 P3068R5 - Allowing exception throwing in constant-evaluation +// { dg-do compile { target c++26 } } +// { dg-require-effective-target exceptions_enabled } + +int +foo (int x, int y) +{ + return x + y; +} + +constexpr int +bar (int x) +{ + if (x < 0) + throw x; + return x; +} + +constexpr int +baz (int x, int y) +{ + return foo (bar (x), bar (y)); +} + +constexpr int +qux (int x, int y) +{ + try + { + return baz (x, y); + } + catch (int) + { + return 42; + } +} + +static_assert (qux (12, -1) == 42); +static_assert (qux (-7, 12) == 42); diff --git a/gcc/testsuite/g++.dg/cpp26/constexpr-eh2.C b/gcc/testsuite/g++.dg/cpp26/constexpr-eh2.C new file mode 100644 index 0000000..8bd6b6f --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp26/constexpr-eh2.C @@ -0,0 +1,112 @@ +// C++26 P3068R5 - Allowing exception throwing in constant-evaluation +// { dg-do compile { target c++26 } } +// { dg-require-effective-target exceptions_enabled } + +struct S { + constexpr S () : s (0) {} + constexpr S (int x) : s (x) { if (x == 42) throw 42; } + constexpr S (const S &x) : s (x.s) {} + constexpr ~S () noexcept (false) { if (s == 41) throw 41; } + constexpr const char *what () const noexcept { return "S"; } + int s; +}; +struct T : public S { + constexpr T () {} + constexpr T (int x) : S (x) {} + constexpr T (const T &x) : S (x.s) {} + constexpr ~T () {} + constexpr const char *what () const noexcept { return "T"; } +}; +struct U { + constexpr U () : u (0) {} + constexpr U (int x) : u (x) {} + constexpr U (const S &x) : u (0) {} + constexpr U (const U &x) : u (x.u) { if (u == 42) throw 43; } + constexpr ~U () {} + constexpr const char *what () const noexcept { return "U"; } + int u; +}; + +constexpr int +foo (int x) +{ + if (x == 1) + throw 43; + return x; +} + +constexpr int +bar (int x) noexcept // { dg-error "'std::terminate' called" } +{ // { dg-message "uncaught exception exited from 'noexcept' function 'constexpr int bar\\\(int\\\)'" "" { target *-*-* } .-1 } + return foo (x); +} + +constexpr int +baz (int x) +{ + switch (x) + { + case 0: throw 1; break; + case 1: try { x = bar (x); } catch (...) {} break; // { dg-message "in 'constexpr' expansion of" } + case 2: throw S (2); break; + case 3: try { throw S (42); } catch (int a) { if (a != 42) throw -1; } break; + case 4: try { S s (41); throw 2; } catch (...) {} break; // { dg-error "'std::terminate' called" } + case 5: return 5; // { dg-message "destructor exited with an exception" "" { target *-*-* } .-1 } + case 6: + try + { + throw S (5); + } + catch (const T &) {} + catch (int) {} + catch (const bool &) {} + catch (const T **const &) {} + break; + case 7: try { constexpr int y = foo (2); } catch (...) {} break; + case 8: + try + { + try + { + throw U (); + } + catch (U &u) + { + u.u = 42; + throw; + } + } + catch (U u) // { dg-error "'std::terminate' called" } + { // { dg-message "constructor exited with another exception while entering handler" "" { target *-*-* } .-1 } + } + break; + case 9: + try + { + throw U (S (41)); // { dg-error "'std::terminate' called" } + } // { dg-message "destructor exited with an exception" "" { target *-*-* } .-1 } + catch (...) + { + } + break; + } + return -1; +} + +constexpr int +qux (int x) +{ + try { constexpr int y = foo (1); } catch (...) {} // { dg-error "uncaught exception" } + return 0; +} + +constexpr int a = baz (0); // { dg-error "uncaught exception" } +constexpr int b = baz (1); // { dg-message "in 'constexpr' expansion of" } +constexpr int c = baz (2); // { dg-error "uncaught exception" } +constexpr int d = baz (3); +constexpr int e = baz (4); // { dg-message "in 'constexpr' expansion of" } +constexpr int f = baz (5); +constexpr int g = baz (6); // { dg-error "uncaught exception" } +constexpr int h = baz (7); +constexpr int i = baz (8); // { dg-message "in 'constexpr' expansion of" } +constexpr int j = baz (9); // { dg-message "in 'constexpr' expansion of" } diff --git a/gcc/testsuite/g++.dg/cpp26/constexpr-eh3.C b/gcc/testsuite/g++.dg/cpp26/constexpr-eh3.C new file mode 100644 index 0000000..f844d11 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp26/constexpr-eh3.C @@ -0,0 +1,442 @@ +// C++26 P3068R5 - Allowing exception throwing in constant-evaluation +// { dg-do compile { target c++26 } } +// { dg-require-effective-target exceptions_enabled } + +#include <exception> +#include <new> +#include <typeinfo> + +constexpr std::exception a; +constexpr const char *b = a.what (); +constexpr std::bad_exception c; +constexpr const char *d = c.what (); +constexpr std::bad_alloc e; +constexpr const char *f = e.what (); +constexpr std::bad_array_new_length g; +constexpr const char *h = g.what (); +constexpr std::bad_cast i; +constexpr const char *j = i.what (); +constexpr std::bad_typeid k; +constexpr const char *l = k.what (); +constexpr std::exception_ptr m = nullptr; +static_assert (m == nullptr); +constexpr std::exception_ptr n = std::current_exception (); +static_assert (n == nullptr); +constexpr std::exception_ptr o; +static_assert (o == nullptr); +constexpr std::nested_exception p; +static_assert (p.nested_ptr () == nullptr); + +struct A { virtual ~A () {} }; +struct B { virtual void b (); }; +struct C { virtual void c (); }; +struct D : private B { virtual void d (); }; +struct E { virtual void e (); }; +struct F : D, E, private C { virtual void f (); }; +struct G { constexpr G () { if (std::uncaught_exceptions () != 0) asm (""); } }; +struct H { constexpr H () : h (0) {} constexpr ~H () { if (std::uncaught_exceptions () != h) asm (""); } int h; }; +struct I : std::nested_exception { }; +struct J { virtual ~J () noexcept = default; }; +struct K final { }; +struct L : J, std::nested_exception { }; +struct M { }; +struct N : I, L { }; +struct O : private std::nested_exception { }; + +constexpr int +foo (int x) +{ + if (std::uncaught_exceptions () != 0) + return -1; + switch (x) + { + case 0: + try + { + const std::type_info &s = typeid (*(A *) 0); + return -1; + } + catch (const std::bad_typeid &x) + { + if (std::uncaught_exceptions () != 0) + return -1; + const char *p = x.what (); + return 1; + } + catch (...) + { + return -1; + } + break; + case 1: + try + { + static constexpr F f; + D &d = dynamic_cast<D &>((B &) f); + return -1; + } + catch (std::bad_cast x) + { + const char *p = x.what (); + return 2; + } + catch (...) + { + return -1; + } + break; + case 2: + try + { + H h; + h.h = 1; + if (std::current_exception () != nullptr) + return -1; + throw G (); + } + catch (const G &g) + { + if (std::uncaught_exceptions () != 0) + return -1; + if (std::current_exception () == nullptr) + return -1; + return 3; + } + catch (...) + { + return -1; + } + break; + case 3: + try + { + decltype (sizeof 0) x = -64; + char (*a)[2] = new char[x][2]; + delete[] a; + } + catch (std::bad_array_new_length x) + { + return 4; + } + break; + case 4: + try + { + int y = -1; + int *a = new int[y]; + delete[] a; + } + catch (const std::bad_array_new_length &) + { + return 5; + } + break; + case 5: + try + { + int z = 1; + int *a = new int[z]{1, 2, 3}; + delete[] a; + } + catch (std::bad_array_new_length &) + { + return 6; + } + break; + case 6: + { + std::exception_ptr b, d; + if (b != nullptr || d != nullptr) + return -1; + try + { + throw 1; + } + catch (int a) + { + if (a != 1) + return -1; + b = std::current_exception (); + if (b == nullptr) + return -1; + try + { + throw 2L; + } + catch (long int c) + { + if (c != 2L) + return -1; + d = std::current_exception (); + if (d == nullptr || b == d) + return -1; + } + if (std::current_exception () != b) + return -1; + } + if (std::current_exception () != nullptr) + return -1; + try + { + std::rethrow_exception (d); + } + catch (long int &e) + { + if (e != 2L) + return -1; + try + { + std::rethrow_exception (b); + } + catch (const int &f) + { + if (f != 1) + return -1; + try + { + std::rethrow_exception (d); + } + catch (const long int g) + { + if (g != 2L) + return -1; + try + { + std::rethrow_exception (b); + } + catch (int h) + { + if (h != 1) + return -1; + std::exception_ptr i (b); + std::exception_ptr j; + if (j != nullptr || i == nullptr || i != b || bool (j)) + return -1; + j = i; + if (j != b || !bool (j)) + return -1; + j = nullptr; + std::swap (i, j); + if (j == nullptr || j != b || i != nullptr) + return -1; + } + } + } + } + return 7; + } + case 7: + { + std::exception_ptr a = std::make_exception_ptr (42); + std::exception_ptr b = std::make_exception_ptr (std::exception ()); + std::exception_ptr c + = std::make_exception_ptr (std::bad_array_new_length ()); + try + { + std::rethrow_exception (a); + } + catch (int d) + { + if (d != 42) + return -1; + try + { + std::rethrow_exception (b); + } + catch (const std::exception &e) + { + const char *f = e.what (); + try + { + std::rethrow_exception (c); + } + catch (const std::bad_alloc &g) + { + try + { + throw; + } + catch (const std::bad_array_new_length &h) + { + const char *i = h.what (); + const char *j = g.what (); + } + } + } + } + return 8; + } + case 8: + { + std::nested_exception a; + if (a.nested_ptr () != nullptr) + return -1; + try + { + std::nested_exception b; + if (b.nested_ptr () != nullptr) + return -1; + throw 42; + } + catch (...) + { + std::nested_exception c; + if (c.nested_ptr () != std::current_exception ()) + return -1; + std::nested_exception d = c; + if (d.nested_ptr () != c.nested_ptr ()) + return -1; + c = d; + try + { + c.rethrow_nested (); + } + catch (const int &e) + { + if (e != 42) + return -1; + } + } + return 9; + } + case 9: + try + { + std::throw_with_nested (I ()); + } + catch (const std::nested_exception &a) + { + if (a.nested_ptr () != nullptr) + return -1; + try + { + throw; + } + catch (const I &) + { + return 10; + } + } + return -1; + case 10: + try + { + std::throw_with_nested (J ()); + } + catch (const std::nested_exception &a) + { + if (a.nested_ptr () != nullptr) + return -1; + try + { + throw; + } + catch (const J &) + { + return 11; + } + } + return -1; + case 11: + try + { + std::throw_with_nested (K ()); + } + catch (const std::nested_exception &) + { + return -1; + } + catch (const K &) + { + return 12; + } + return -1; + case 12: + try + { + throw 42; + } + catch (...) + { + I a; + try + { + std::rethrow_if_nested (a); + } + catch (const int &b) + { + if (b == 42) + return 13; + } + } + return -1; + case 13: + try + { + throw J (); + } + catch (const J &a) + { + std::rethrow_if_nested (a); + return 14; + } + return -1; + case 14: + try + { + throw 42; + } + catch (...) + { + try + { + throw L (); + } + catch (const J &a) + { + try + { + std::rethrow_if_nested (a); + } + catch (const int &b) + { + if (b == 42) + return 15; + } + } + } + return -1; + case 15: + { + std::rethrow_if_nested (1); + M m; + std::rethrow_if_nested (m); + N n; + std::rethrow_if_nested (n); + O o; + std::rethrow_if_nested (o); + return 16; + } + default: + break; + } + return -1; +} + +static_assert (foo (0) == 1); +static_assert (foo (1) == 2); +static_assert (foo (2) == 3); +static_assert (foo (3) == 4); +static_assert (foo (4) == 5); +static_assert (foo (5) == 6); +static_assert (foo (6) == 7); +static_assert (foo (7) == 8); +static_assert (foo (8) == 9); +static_assert (foo (9) == 10); +static_assert (foo (10) == 11); +static_assert (foo (11) == 12); +static_assert (foo (12) == 13); +static_assert (foo (13) == 14); +static_assert (foo (14) == 15); +static_assert (foo (15) == 16); +static_assert (std::uncaught_exceptions () == 0); diff --git a/gcc/testsuite/g++.dg/cpp26/constexpr-eh4.C b/gcc/testsuite/g++.dg/cpp26/constexpr-eh4.C new file mode 100644 index 0000000..24118ca --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp26/constexpr-eh4.C @@ -0,0 +1,72 @@ +// C++26 P3068R5 - Allowing exception throwing in constant-evaluation +// { dg-do compile { target c++26 } } +// { dg-require-effective-target exceptions_enabled } + +struct A { virtual ~A () {} }; +struct B { virtual void b (); }; +struct C { virtual void c (); }; +struct D : private B { virtual void d (); }; +struct E { virtual void e (); }; +struct F : D, E, private C { virtual void f (); }; + +constexpr int +foo (int x) +{ + switch (x) + { + case 1: + try + { + static constexpr F f; + D &d = dynamic_cast<D &>((B &) f); // { dg-error "called without 'std::bad_cast' being defined" } + return -1; + } + catch (...) + { + return -1; + } + break; + case 3: + try + { + decltype (sizeof 0) x = -64; + char (*a)[2] = new char[x][2]; // { dg-error "called without 'std::bad_array_new_length' being defined" } + delete[] a; + } + catch (...) + { + return -1; + } + break; + case 4: + try + { + int y = -1; + int *a = new int[y]; // { dg-error "called without 'std::bad_array_new_length' being defined" } + delete[] a; + } + catch (...) + { + return -1; + } + break; + case 5: + try + { + int z = 1; + int *a = new int[z]{1, 2, 3}; // { dg-error "called without 'std::bad_array_new_length' being defined" } + delete[] a; + } + catch (...) + { + return -1; + } + break; + } + return -1; +} + +constexpr int a = foo (1); // { dg-message "in 'constexpr' expansion of" } +constexpr int b = foo (3); // { dg-message "in 'constexpr' expansion of" } +constexpr int c = foo (4); // { dg-message "in 'constexpr' expansion of" } +constexpr int d = foo (5); // { dg-message "in 'constexpr' expansion of" } diff --git a/gcc/testsuite/g++.dg/cpp26/constexpr-eh5.C b/gcc/testsuite/g++.dg/cpp26/constexpr-eh5.C new file mode 100644 index 0000000..512aa34 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp26/constexpr-eh5.C @@ -0,0 +1,55 @@ +// C++26 P3068R5 - Allowing exception throwing in constant-evaluation +// { dg-do compile { target c++26 } } +// { dg-require-effective-target exceptions_enabled } + +constexpr void +foo () +{ + throw 1; +} + +void +bar () +{ +} + +constexpr void +baz () +{ + foo (); + bar (); +} + +constexpr void +qux () +{ + if consteval { + throw 2; + } + bar (); +} + +constexpr bool +corge () +{ + try + { + baz (); + } + catch (int a) + { + if (a != 1) + return false; + try + { + qux (); + } + catch (int b) + { + return b == 2; + } + } + return false; +} + +static_assert (corge ()); diff --git a/gcc/testsuite/g++.dg/cpp26/constexpr-eh6.C b/gcc/testsuite/g++.dg/cpp26/constexpr-eh6.C new file mode 100644 index 0000000..6fd9462 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp26/constexpr-eh6.C @@ -0,0 +1,134 @@ +// C++26 P3068R5 - Allowing exception throwing in constant-evaluation +// { dg-do compile { target c++26 } } +// { dg-require-effective-target exceptions_enabled } + +struct S { + constexpr S () : s (0) {} + constexpr S (int x) : s (x) {} + constexpr S (const S &x) : s (x.s) {} + constexpr ~S () {} + int s; +}; +struct T { + constexpr T () : t (0) {} + constexpr T (int x) : t (x) {} + constexpr T (const T &x) : t (x.t) {} + constexpr ~T () {} + int t; +}; +struct U : public S, public T { + constexpr U () : S (0), T (0) {} + constexpr U (int x, int y) : S (x), T (y) {} + constexpr U (const U &x) : S (x.s), T (x.t) {} + constexpr ~U () {} +}; + +constexpr bool +foo () +{ + try + { + throw U (1, 2); + } + catch (const U &x) + { + if (x.s != 1 || x.t != 2) + return false; + try + { + throw; + } + catch (const S &y) + { + if (y.s != 1) + return false; + try + { + throw; + } + catch (const T &z) + { + if (z.t != 2) + return false; + return true; + } + } + } + return false; +} + +constexpr bool +bar () +{ + try + { + throw U (1, 2); + } + catch (U &x) + { + if (x.s != 1 || x.t != 2) + return false; + try + { + x.s = 3; + x.t = 4; + throw; + } + catch (S &y) + { + if (y.s != 3) + return false; + try + { + throw; + } + catch (T &z) + { + if (z.t != 4) + return false; + return true; + } + } + } + return false; +} + +constexpr bool +baz () +{ + try + { + throw U (1, 2); + } + catch (U x) + { + if (x.s != 1 || x.t != 2) + return false; + try + { + x.s = 3; + x.t = 4; + throw; + } + catch (S y) + { + if (y.s != 1) + return false; + try + { + throw; + } + catch (T z) + { + if (z.t != 2) + return false; + return true; + } + } + } + return false; +} + +static_assert (foo ()); +static_assert (bar ()); +static_assert (baz ()); diff --git a/gcc/testsuite/g++.dg/cpp26/constexpr-eh7.C b/gcc/testsuite/g++.dg/cpp26/constexpr-eh7.C new file mode 100644 index 0000000..6bdf0c3 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp26/constexpr-eh7.C @@ -0,0 +1,151 @@ +// C++26 P3068R5 - Allowing exception throwing in constant-evaluation +// { dg-do compile { target c++26 } } +// { dg-require-effective-target exceptions_enabled } + +constexpr char p[] = "hello"; +constexpr const char *q[] = { &p[0], &p[3] }; +constexpr const char *const *r = &q[0]; +const char *s[] = { &p[0], &p[3] }; +constexpr const char **t = &s[0]; + +constexpr bool +foo () +{ + try + { + throw t; + } + catch (const char **const &x) + { + if (x != t) + return false; + try + { + throw; + } + catch (const char **&y) + { + if (y != t) + return false; + try + { + throw; + } + catch (const char **z) + { + if (z != t) + return false; + try + { + throw; + } + catch (const char *const *const &v) + { + if (v != (const char *const *) t) + return false; + try + { + throw; + } + catch (const char *const *w) + { + if (w != (const char *const *) t) + return false; + return true; + } + } + } + } + } + return false; +} + +constexpr bool +bar () +{ + try + { + throw nullptr; + } + catch (const char **const &x) + { + if (x != nullptr) + return false; + try + { + throw; + } + catch (const char **&y) + { + if (y != nullptr) + return false; + try + { + throw; + } + catch (const char **z) + { + if (z != nullptr) + return false; + try + { + throw; + } + catch (const char *const *const &v) + { + if (v != nullptr) + return false; + try + { + throw; + } + catch (const char *const *w) + { + if (w != nullptr) + return false; + return true; + } + } + } + } + } + return false; +} + +constexpr bool +baz () +{ + try + { + throw r; + } + catch (const char *const *const &x) + { + if (x != r || **x != 'h') + return false; + try + { + throw; + } + catch (const char *const *&y) + { + if (y != r || **y != 'h') + return false; + try + { + throw; + } + catch (const char *const *z) + { + if (z != r || **z != 'h') + return false; + return true; + } + } + } + return false; +} + +static_assert (foo ()); +static_assert (bar ()); +static_assert (baz ()); diff --git a/gcc/testsuite/g++.dg/cpp26/constexpr-eh8.C b/gcc/testsuite/g++.dg/cpp26/constexpr-eh8.C new file mode 100644 index 0000000..2560364 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp26/constexpr-eh8.C @@ -0,0 +1,36 @@ +// C++26 P3068R5 - Allowing exception throwing in constant-evaluation +// { dg-do compile { target c++26 } } +// { dg-require-effective-target exceptions_enabled } + +#include <exception> + +constexpr std::exception_ptr +foo () +{ + try + { + throw 42; + } + catch (...) + { + return std::current_exception (); + } +} + +constexpr bool +bar () +{ + try + { + std::rethrow_exception (foo ()); + } + catch (const int &a) + { + return a == 42; + } + return false; +} + +static_assert (bar ()); +constexpr std::exception_ptr a = foo (); // { dg-error "is not a constant expression because it refers to exception object allocated with '__cxa_allocate_exception'" } +constexpr std::exception_ptr b = std::make_exception_ptr (42ULL); // { dg-error "is not a constant expression because it refers to exception object allocated with '__cxa_allocate_exception'" } diff --git a/gcc/testsuite/g++.dg/cpp26/constexpr-eh9.C b/gcc/testsuite/g++.dg/cpp26/constexpr-eh9.C new file mode 100644 index 0000000..fd39fe0 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp26/constexpr-eh9.C @@ -0,0 +1,127 @@ +// C++26 P3068R5 - Allowing exception throwing in constant-evaluation +// { dg-do compile { target c++26 } } +// { dg-require-effective-target exceptions_enabled } + +namespace std +{ + struct exception + { + constexpr exception () noexcept { } + constexpr virtual ~exception () noexcept {} + constexpr exception (const exception &) = default; + constexpr exception &operator= (const exception &) = default; + constexpr exception (exception &&) = default; + constexpr exception &operator= (exception &&) = default; + constexpr virtual const char *what () const noexcept + { return "std::exception"; } + }; +} + +struct S : public std::exception { + constexpr S () : s (0) {} + constexpr S (int x) : s (x) {} + constexpr S (const S &x) : s (x.s) {} + constexpr virtual ~S () {} + constexpr virtual const char *what () noexcept { return "this is S"; } + int s; +}; +struct T : public std::exception { + constexpr T () : s (new char[1]), t (0) { s[0] = '\0'; } + constexpr T (const char *p, int q) : s (new char[q + 1]), t (q) + { + for (int i = 0; i <= t; ++i) + s[i] = p[i]; + } + constexpr T (const T &x) : s (new char[x.t + 1]), t (x.t) + { + for (int i = 0; i <= t; ++i) + s[i] = x.s[i]; + } + constexpr virtual ~T () { delete[] s; } + constexpr virtual const char *what () noexcept { return s; } + char *s; + int t; +}; +struct U { + constexpr U () : x (0), y (0), z (0) {} + constexpr U (int a, long b, unsigned long long c) : x (a), y (b), z (c) {} + constexpr U (const U &u) = default; + int x; + long y; + unsigned long long z; +}; +struct V { + constexpr V () : v (0) {} + constexpr V (int x) : v (x) {} + constexpr V (const V &x) : v (x.v) {} + constexpr virtual ~V () {} + constexpr virtual const char *what () noexcept { return "this is V"; } + int v; +}; + +constexpr int +foo (int x) +{ + if (x == 1) + throw S (42); + else if (x == 2) + throw T ("hello, world", sizeof ("hello, world") - 1); + else if (x == 3) + throw U (1, -2L, 42ULL); + else if (x == 4) + throw 42; + else if (x == 5) + throw 1.0; + else if (x == 6) + throw V (42); + else + return 42; +} + +constexpr int +bar (int x) noexcept +// { dg-error "'std::terminate' called after throwing an exception of type 'S'; 'what\\\(\\\)': 'this is S'" "" { target *-*-* } .-1 } +// { dg-message "uncaught exception exited from 'noexcept' function 'constexpr int bar\\\(int\\\)'" "" { target *-*-* } .-2 } +// { dg-error "'std::terminate' called after throwing an exception of type 'T'; 'what\\\(\\\)': 'hello, world'" "" { target *-*-* } .-3 } +// { dg-error "'std::terminate' called after throwing an exception 'U\\\{1, -2, 42\\\}'" "" { target *-*-* } .-4 } +// { dg-error "'std::terminate' called after throwing an exception '42'" "" { target *-*-* } .-5 } +// { dg-error "'std::terminate' called after throwing an exception '1\\\.0e\\\+0'" "" { target *-*-* } .-6 } +// { dg-error "'std::terminate' called after throwing an exception 'V\\\{\[^\n\r]*42\\\}" "" { target *-*-* } .-7 } +{ + return foo (x); +} + +constexpr int +baz (int x) +{ + try + { + return foo (x); + } + catch (...) + { + return -1; + } +} + +static_assert (bar (0) == 42); +constexpr int a = bar (1); // { dg-message "in 'constexpr' expansion of" } +constexpr int b = bar (2); // { dg-message "in 'constexpr' expansion of" } +constexpr int c = bar (3); // { dg-message "in 'constexpr' expansion of" } +constexpr int d = bar (4); // { dg-message "in 'constexpr' expansion of" } +constexpr int e = bar (5); // { dg-message "in 'constexpr' expansion of" } +constexpr int f = bar (6); // { dg-message "in 'constexpr' expansion of" } +static_assert (baz (0) == 42); +static_assert (baz (1) == -1); +static_assert (baz (2) == -1); +static_assert (baz (3) == -1); +static_assert (baz (4) == -1); +static_assert (baz (5) == -1); +static_assert (baz (6) == -1); +static_assert (foo (0) == 42); +constexpr int g = foo (1); // { dg-error "uncaught exception of type 'S'; 'what\\\(\\\)': 'this is S'" } +constexpr int h = foo (2); // { dg-error "uncaught exception of type 'T'; 'what\\\(\\\)': 'hello, world'" } +constexpr int i = foo (3); // { dg-error "uncaught exception 'U\\\{1, -2, 42\\\}'" } +constexpr int j = foo (4); // { dg-error "uncaught exception '42'" } +constexpr int k = foo (5); // { dg-error "uncaught exception '1\\\.0e\\\+0'" } +constexpr int l = foo (6); // { dg-error "uncaught exception 'V\\\{\[^\n\r]*42\\\}'" } diff --git a/gcc/testsuite/g++.dg/cpp26/decomp22.C b/gcc/testsuite/g++.dg/cpp26/decomp22.C new file mode 100644 index 0000000..576a93b --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp26/decomp22.C @@ -0,0 +1,66 @@ +// C++26 P2686R4 - constexpr structured bindings +// { dg-do compile { target c++11 } } +// { dg-options "" } + +namespace std { + template <typename T> struct tuple_size; + template <int, typename> struct tuple_element; +} + +struct A { + int i, j; + template <int I> constexpr const int &get () const { return I == 1 ? j : i; } +}; + +template <> struct std::tuple_size <const A> { static const int value = 3; }; +template <int I> struct std::tuple_element <I, const A> { using type = const int; }; + +constexpr struct B { + int i, j; + long long k, l; +} a[3] = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } }; + +constexpr auto [ b, c, d ] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 } +#if __cpp_constinit >= 201907 +constinit auto [ e, f, g ] = a; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } } +#endif +constexpr auto [ h, i, j, k ] = a[1]; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 } +#if __cpp_constinit >= 201907 +constinit auto [ l, m, n, o ] = a[2]; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } } +#endif +constexpr auto & [ p, q, r ] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 } +#if __cpp_constinit >= 201907 +constinit auto & [ s, t, u ] = a; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } } +#endif +constexpr auto & [ v, w, x, y ] = a[1]; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 } +#if __cpp_constinit >= 201907 +constinit auto & [ aa, ab, ac, ad ] = a[2]; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } } +#endif +static_assert (b.i == 1 && b.l == 4 && c.j == 6 && c.k == 7 && d.i == 9 && d.k == 11, ""); +static_assert (h == 5 && i == 6 && j == 7 && k == 8, ""); +static_assert (p.i == 1 && p.l == 4 && q.j == 6 && q.k == 7 && r.i == 9 && r.k == 11, ""); +static_assert (&p.i == &a[0].i && &p.l == &a[0].l && &q.j == &a[1].j, ""); +static_assert (&q.k == &a[1].k && &r.i == &a[2].i && &r.k == &a[2].k, ""); +static_assert (v == 5 && w == 6 && x == 7 && y == 8, ""); +static_assert (&v == &a[1].i && &w == &a[1].j && &x == &a[1].k && &y == &a[1].l, ""); + +constexpr A z = { 42, -42 }; +constexpr auto [ ae, af, ag ] = z; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 } +#if __cpp_constinit >= 201907 +constinit const auto [ ah, ai, aj ] = z; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } } +#endif +constexpr auto & [ ak, al, am ] = z; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 } +#if __cpp_constinit >= 201907 +constinit auto & [ an, ao, ap ] = z; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } } +#endif +static_assert (ae == 42 && af == -42 && ag == 42, ""); +static_assert (&af == &ae + 1 && &ag == &ae, ""); +static_assert (&ae != &z.i && &af != &z.j && &ag != &z.i, ""); +static_assert (ak == 42 && al == -42 && am == 42, ""); +static_assert (&ak == &z.i && &al == &z.j && &am == &z.i, ""); diff --git a/gcc/testsuite/g++.dg/cpp26/decomp23.C b/gcc/testsuite/g++.dg/cpp26/decomp23.C new file mode 100644 index 0000000..ad2f7e0 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp26/decomp23.C @@ -0,0 +1,77 @@ +// C++26 P2686R4 - constexpr structured bindings +// { dg-do compile { target c++11 } } +// { dg-options "" } + +namespace std { + template <typename T> struct tuple_size; + template <int, typename> struct tuple_element; +} + +struct A { + int i, j; + template <int I> constexpr const int &get () const { return I == 1 ? j : i; } +}; + +template <> struct std::tuple_size <const A> { static const int value = 3; }; +template <int I> struct std::tuple_element <I, const A> { using type = const int; }; + +struct B { + int i, j; + long long k, l; +}; + +void +foo () +{ + static constexpr B a[3] = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } }; + static constexpr auto [ b, c, d ] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 } + // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-2 } +#if __cpp_constinit >= 201907 + static constinit auto [ e, f, g ] = a; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } } +#endif + static constexpr auto [ h, i, j, k ] = a[1]; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 } + // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-2 } +#if __cpp_constinit >= 201907 + static constinit auto [ l, m, n, o ] = a[2]; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } } +#endif + static constexpr auto & [ p, q, r ] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 } + // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-2 } +#if __cpp_constinit >= 201907 + static constinit auto & [ s, t, u ] = a; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } } +#endif + static constexpr auto & [ v, w, x, y ] = a[1]; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 } + // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-2 } +#if __cpp_constinit >= 201907 + static constinit auto & [ aa, ab, ac, ad ] = a[2]; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } } +#endif + static_assert (b.i == 1 && b.l == 4 && c.j == 6 && c.k == 7 && d.i == 9 && d.k == 11, ""); + static_assert (h == 5 && i == 6 && j == 7 && k == 8, ""); + static_assert (p.i == 1 && p.l == 4 && q.j == 6 && q.k == 7 && r.i == 9 && r.k == 11, ""); + static_assert (&p.i == &a[0].i && &p.l == &a[0].l && &q.j == &a[1].j, ""); + static_assert (&q.k == &a[1].k && &r.i == &a[2].i && &r.k == &a[2].k, ""); + static_assert (v == 5 && w == 6 && x == 7 && y == 8, ""); + static_assert (&v == &a[1].i && &w == &a[1].j && &x == &a[1].k && &y == &a[1].l, ""); + + static constexpr A z = { 42, -42 }; + static constexpr auto [ ae, af, ag ] = z; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 } + // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-2 } +#if __cpp_constinit >= 201907 + static constinit const auto [ ah, ai, aj ] = z; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } } +#endif + static constexpr auto & [ ak, al, am ] = z; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 } + // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-2 } +#if __cpp_constinit >= 201907 + static constinit auto & [ an, ao, ap ] = z; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } } +#endif + static_assert (ae == 42 && af == -42 && ag == 42, ""); + static_assert (&af == &ae + 1 && &ag == &ae, ""); + static_assert (&ae != &z.i && &af != &z.j && &ag != &z.i, ""); + static_assert (ak == 42 && al == -42 && am == 42, ""); + static_assert (&ak == &z.i && &al == &z.j && &am == &z.i, ""); +} diff --git a/gcc/testsuite/g++.dg/cpp26/decomp24.C b/gcc/testsuite/g++.dg/cpp26/decomp24.C new file mode 100644 index 0000000..5da1321 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp26/decomp24.C @@ -0,0 +1,20 @@ +// C++26 P2686R4 - constexpr structured bindings +// { dg-do compile { target c++11 } } +// { dg-options "" } + +struct B { + int i, j; + long long k, l; +}; + +void +foo () +{ + constexpr B a[3] = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } }; + constexpr auto [ b, c, d ] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 } + constexpr auto [ h, i, j, k ] = a[1]; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 } + static_assert (b.i == 1 && b.l == 4 && c.j == 6 && c.k == 7 && d.i == 9 && d.k == 11, ""); + static_assert (h == 5 && i == 6 && j == 7 && k == 8, ""); +} diff --git a/gcc/testsuite/g++.dg/cpp26/decomp25.C b/gcc/testsuite/g++.dg/cpp26/decomp25.C new file mode 100644 index 0000000..55559f0 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp26/decomp25.C @@ -0,0 +1,119 @@ +// C++26 P2686R4 - constexpr structured bindings +// { dg-do compile { target c++11 } } +// { dg-options "" } + +namespace std { + template <typename T> struct tuple_size; + template <int, typename> struct tuple_element; +} + +struct A { + int i, j; + template <int I> int &get () { return I == 1 ? j : i; } +}; + +template <> struct std::tuple_size <A> { static const int value = 3; }; +template <int I> struct std::tuple_element <I, A> { using type = int; }; +template <> struct std::tuple_size <const A> { static const int value = 3; }; +template <int I> struct std::tuple_element <I, const A> { using type = int; }; + +struct B { + int i, j; + long long k, l; +} a[3] = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } }; // { dg-message "'a' was not declared 'constexpr'" "" } + +struct C { + int i, j; + template <int I> const int &get () const { return I == 1 ? j : i; } +}; + +template <> struct std::tuple_size <const C> { static const int value = 3; }; +template <int I> struct std::tuple_element <I, const C> { using type = const int; }; + +constexpr auto [ b, c, d ] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 } + // { dg-error "the value of 'a' is not usable in a constant expression" "" { target *-*-* } .-2 } +#if __cpp_constinit >= 201907 +constinit auto [ e, f, g ] = a; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } } + // { dg-error "'constinit' variable '<structured bindings>' does not have a constant initializer" "" { target c++20 } .-1 } + // { dg-error "the value of 'a' is not usable in a constant expression" "" { target c++20 } .-2 } +#endif +constexpr auto [ h, i, j, k ] = a[1]; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 } + // { dg-error "the value of 'a' is not usable in a constant expression" "" { target *-*-* } .-2 } +#if __cpp_constinit >= 201907 +constinit auto [ l, m, n, o ] = a[2]; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } } + // { dg-error "'constinit' variable '<structured bindings>' does not have a constant initializer" "" { target c++20 } .-1 } + // { dg-error "the value of 'a' is not usable in a constant expression" "" { target c++20 } .-2 } +#endif +constexpr auto & [ p, q, r ] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 } +#if __cpp_constinit >= 201907 +constinit auto & [ s, t, u ] = a; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } } +#endif +constexpr auto & [ v, w, x, y ] = a[1]; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 } +#if __cpp_constinit >= 201907 +constinit auto & [ aa, ab, ac, ad ] = a[2]; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } } +#endif + +A z = { 42, -42 }; // { dg-message "'z' was not declared 'constexpr'" "" } +constexpr auto [ ae, af, ag ] = z; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 } + // { dg-error "the value of 'z' is not usable in a constant expression" "" { target *-*-* } .-2 } + // { dg-error "passing 'const A' as 'this' argument discards qualifiers" "" { target *-*-* } .-3 } + // { dg-error "call to non-'constexpr' function 'int\\\& A::get\\\(\\\)" "" { target *-*-* } .-4 } +#if __cpp_constinit >= 201907 +constinit const auto [ ah, ai, aj ] = z; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } } + // { dg-error "'constinit' variable '<structured bindings>' does not have a constant initializer" "" { target c++20 } .-1 } + // { dg-error "the value of 'z' is not usable in a constant expression" "" { target c++20 } .-2 } + // { dg-error "passing 'const A' as 'this' argument discards qualifiers" "" { target c++20 } .-3 } + // { dg-error "call to non-'constexpr' function 'int\\\& A::get\\\(\\\)" "" { target c++20 } .-4 } + // { dg-error "'constinit' variable 'ah' does not have a constant initializer" "" { target c++20 } .-5 } + // { dg-error "'constinit' variable 'ai' does not have a constant initializer" "" { target c++20 } .-6 } + // { dg-error "'constinit' variable 'aj' does not have a constant initializer" "" { target c++20 } .-7 } +#endif +constexpr auto & [ ak, al, am ] = z; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 } + // { dg-error "call to non-'constexpr' function 'int\\\& A::get\\\(\\\)" "" { target *-*-* } .-2 } +#if __cpp_constinit >= 201907 +constinit auto & [ an, ao, ap ] = z; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } } + // { dg-error "'constinit' variable 'an' does not have a constant initializer" "" { target c++20 } .-1 } + // { dg-error "'constinit' variable 'ao' does not have a constant initializer" "" { target c++20 } .-2 } + // { dg-error "'constinit' variable 'ap' does not have a constant initializer" "" { target c++20 } .-3 } + // { dg-message "call to non-'constexpr' function 'int\\\& A::get\\\(\\\)" "" { target c++20 } .-4 } +#endif + +constexpr C zz = { 42, -42 }; +constexpr auto [ aq, ar, as ] = zz; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 } + // { dg-error "call to non-'constexpr' function 'const int\\\& C::get\\\(\\\) const" "" { target *-*-* } .-2 } +#if __cpp_constinit >= 201907 +constinit const auto [ at, au, av ] = zz; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } } + // { dg-error "call to non-'constexpr' function 'const int\\\& C::get\\\(\\\) const" "" { target c++20 } .-1 } + // { dg-error "'constinit' variable 'at' does not have a constant initializer" "" { target c++20 } .-2 } + // { dg-error "'constinit' variable 'au' does not have a constant initializer" "" { target c++20 } .-3 } + // { dg-error "'constinit' variable 'av' does not have a constant initializer" "" { target c++20 } .-4 } +#endif +constexpr auto & [ aw, ax, ay ] = zz; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 } + // { dg-error "call to non-'constexpr' function 'const int\\\& C::get\\\(\\\) const" "" { target *-*-* } .-2 } +#if __cpp_constinit >= 201907 +constinit auto & [ az, ba, bb ] = zz; // { dg-warning "'constinit' can be applied to structured binding only with" "" { target { c++20 && c++23_down } } } + // { dg-error "'constinit' variable 'az' does not have a constant initializer" "" { target c++20 } .-1 } + // { dg-error "'constinit' variable 'ba' does not have a constant initializer" "" { target c++20 } .-2 } + // { dg-error "'constinit' variable 'bb' does not have a constant initializer" "" { target c++20 } .-3 } + // { dg-message "call to non-'constexpr' function 'const int\\\& C::get\\\(\\\) const" "" { target c++20 } .-4 } +#endif + +void +foo () +{ +#if __cpp_constinit >= 201907 + constexpr B a[3] = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } }; + constinit auto [ b, c, d ] = a; // { dg-error "'constinit' can only be applied to a variable with static or thread storage duration" "" { target c++20 } } + constinit auto & [ e, f, g ] = a; // { dg-error "'constinit' can only be applied to a variable with static or thread storage duration" "" { target c++20 } } + constinit auto [ h, i, j, k ] = a[1]; // { dg-error "'constinit' can only be applied to a variable with static or thread storage duration" "" { target c++20 } } + constinit auto & [ l, m, n, o ] = a[2]; // { dg-error "'constinit' can only be applied to a variable with static or thread storage duration" "" { target c++20 } } +#endif +} diff --git a/gcc/testsuite/g++.dg/cpp26/decomp9.C b/gcc/testsuite/g++.dg/cpp26/decomp9.C index 5629c4c..ee18b60 100644 --- a/gcc/testsuite/g++.dg/cpp26/decomp9.C +++ b/gcc/testsuite/g++.dg/cpp26/decomp9.C @@ -63,6 +63,7 @@ foo (const S &&s) if (static auto [i, j, k] = t) // { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } } ; // { dg-error "'static' invalid in condition" "" { target *-*-* } .-1 } // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-2 } - if (constexpr auto [i, j, k] = t) // { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } } - ; // { dg-error "structured binding declaration cannot be 'constexpr'" "" { target *-*-* } .-1 } + constexpr T t2 = { 1, 2, 3 }; + if (constexpr auto [i, j, k] = t2) // { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } } + ; // { dg-warning "structured binding declaration can be 'constexpr' only with" "" { target c++23_down } .-1 } } diff --git a/gcc/testsuite/g++.dg/cpp26/feat-cxx26.C b/gcc/testsuite/g++.dg/cpp26/feat-cxx26.C index e4ffc35..97bd36b 100644 --- a/gcc/testsuite/g++.dg/cpp26/feat-cxx26.C +++ b/gcc/testsuite/g++.dg/cpp26/feat-cxx26.C @@ -624,19 +624,25 @@ #endif #ifndef __cpp_pack_indexing -# error "__cpp_pack_indexing" +# error "__cpp_pack_indexing" #elif __cpp_pack_indexing != 202311 # error "__cpp_pack_indexing != 202311" #endif #ifndef __cpp_pp_embed -# error "__cpp_pp_embed" +# error "__cpp_pp_embed" #elif __cpp_pp_embed != 202502 # error "__cpp_pp_embed != 202502" #endif #ifndef __cpp_constexpr_virtual_inheritance -# error "__cpp_constexpr_virtual_inheritance" +# error "__cpp_constexpr_virtual_inheritance" #elif __cpp_constexpr_virtual_inheritance != 202506 # error "__cpp_constexpr_virtual_inheritance != 202506" #endif + +#ifndef __cpp_constexpr_exceptions +# error "__cpp_constexpr_exceptions" +#elif __cpp_constexpr_exceptions != 202411 +# error "__cpp_constexpr_exceptions != 202411" +#endif diff --git a/gcc/testsuite/g++.dg/cpp26/static_assert1.C b/gcc/testsuite/g++.dg/cpp26/static_assert1.C index 1d0e6f2..a6eab3c 100644 --- a/gcc/testsuite/g++.dg/cpp26/static_assert1.C +++ b/gcc/testsuite/g++.dg/cpp26/static_assert1.C @@ -51,7 +51,7 @@ static_assert (true, H {}); // { dg-warning "'static_assert' with non-string mes struct I { constexpr signed char size () const { return 0; } const char *data () const { return ""; } }; static_assert (true, I {}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } -struct J { constexpr int size () const { return j ? throw 1 : 0; } // { dg-error "expression '<throw-expression>' is not a constant expression" } +struct J { constexpr int size () const { return j ? throw 1 : 0; } // { dg-error "expression '<throw-expression>' is not a constant expression" "" { target c++23_down } } constexpr const char *data () const { return ""; }; constexpr J (int x) : j (x) {} int j; }; @@ -60,6 +60,7 @@ static_assert (false, J (0)); // { dg-warning "'static_assert' with non-string m // { dg-error "static assertion failed" "" { target *-*-* } .-1 } static_assert (false, J (1)); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } // { dg-error "constexpr string 'size\\\(\\\)' must be a constant expression" "" { target *-*-* } .-1 } + // { dg-error "uncaught exception '1'" "" { target c++26 } .-2 } struct K { constexpr operator int () { return 4; } }; struct L { constexpr operator const char * () { return "test"; } }; struct M { constexpr K size () const { return {}; } @@ -261,10 +262,11 @@ namespace NN #if __cplusplus >= 201402L struct J { static constexpr int size () { return 0; } - static constexpr const char *data (int x = 0) { if (x) return nullptr; else throw 1; } }; // { dg-error "expression '<throw-expression>' is not a constant expression" "" { target c++14 } } + static constexpr const char *data (int x = 0) { if (x) return nullptr; else throw 1; } }; // { dg-error "expression '<throw-expression>' is not a constant expression" "" { target { c++14 && c++23_down } } } static_assert (true, J{}); // { dg-warning "'static_assert' with non-string message only available with" "" { target { c++14 && c++23_down } } } static_assert (false, J{}); // { dg-warning "'static_assert' with non-string message only available with" "" { target { c++14 && c++23_down } } } // { dg-error "constexpr string 'data\\\(\\\)' must be a core constant expression" "" { target c++14 } .-1 } + // { dg-error "uncaught exception '1'" "" { target c++26 } .-2 } #endif #if __cpp_if_consteval >= 202106L struct K { @@ -282,19 +284,21 @@ namespace NN static_assert (false, L{}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_only } } // { dg-error "static assertion failed: test" "" { target c++23 } .-1 } struct M { - static constexpr int size () { if consteval { throw 1; } else { return 4; } } // { dg-error "expression '<throw-expression>' is not a constant expression" "" { target c++23 } } + static constexpr int size () { if consteval { throw 1; } else { return 4; } } // { dg-error "expression '<throw-expression>' is not a constant expression" "" { target c++23_only } } static constexpr const char *data () { return "test"; } }; static_assert (true, M{}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_only } } static_assert (false, M{}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_only } } // { dg-error "constexpr string 'size\\\(\\\)' must be a constant expression" "" { target c++23 } .-1 } + // { dg-error "uncaught exception '1'" "" { target c++26 } .-2 } struct N { static constexpr int size () { return 4; } - static constexpr const char *data () { if consteval { throw 1; } else { return "test"; } } // { dg-error "expression '<throw-expression>' is not a constant expression" "" { target c++23 } } + static constexpr const char *data () { if consteval { throw 1; } else { return "test"; } } // { dg-error "expression '<throw-expression>' is not a constant expression" "" { target c++23_only } } }; static_assert (true, N{}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_only } } static_assert (false, N{}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_only } } // { dg-error "constexpr string 'data\\\(\\\)\\\[0\\\]' must be a constant expression" "" { target c++23 } .-1 } + // { dg-error "uncaught exception '1'" "" { target c++26 } .-2 } #endif struct O { constexpr int operator () () const { return 12; } }; struct P { constexpr const char *operator () () const { return "another test"; } }; diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-pr67210.C b/gcc/testsuite/g++.dg/cpp2a/concepts-pr67210.C index a31750e..baddc1c 100644 --- a/gcc/testsuite/g++.dg/cpp2a/concepts-pr67210.C +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-pr67210.C @@ -7,4 +7,4 @@ concept C = true; template <class T> struct A {}; -void f(A<C<int> auto >) {} +void f(A<C<int> auto >) {} // { dg-error "auto" } diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-pr67210a.C b/gcc/testsuite/g++.dg/cpp2a/concepts-pr67210a.C new file mode 100644 index 0000000..1d63a84 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-pr67210a.C @@ -0,0 +1,11 @@ +// PR c++/67210 +// { dg-do compile { target c++20 } } +// { dg-additional-options -Wno-abbreviated-auto-in-template-arg } + +template <class T, class U> +concept C = true; + +template <class T> +struct A {}; + +void f(A<C<int> auto >) {} diff --git a/gcc/testsuite/g++.dg/cpp2a/consteval-memfn1.C b/gcc/testsuite/g++.dg/cpp2a/consteval-memfn1.C index ca92351..17a391b 100644 --- a/gcc/testsuite/g++.dg/cpp2a/consteval-memfn1.C +++ b/gcc/testsuite/g++.dg/cpp2a/consteval-memfn1.C @@ -4,13 +4,13 @@ struct fixed_string { consteval int size(int n) const { - if (n < 0) throw; // { dg-error "not a constant" } - return n; + if (n < 0) throw; // { dg-error "not a constant" "" { target c++23_down } } + return n; // { dg-error "'void __cxa_rethrow\\\(\\\)' called with no caught exceptions active" "" { target c++26 } .-1 } } static consteval int size_static(int n) { - if (n < 0) throw; // { dg-error "not a constant" } - return n; + if (n < 0) throw; // { dg-error "not a constant" "" { target c++23_down } } + return n; // { dg-error "'void __cxa_rethrow\\\(\\\)' called with no caught exceptions active" "" { target c++26 } .-1 } } consteval void operator()() const { } diff --git a/gcc/testsuite/g++.dg/cpp2a/consteval34.C b/gcc/testsuite/g++.dg/cpp2a/consteval34.C index 7562f40..73bcf77 100644 --- a/gcc/testsuite/g++.dg/cpp2a/consteval34.C +++ b/gcc/testsuite/g++.dg/cpp2a/consteval34.C @@ -1,42 +1,51 @@ // { dg-do compile { target c++20 } } // Explicit { dg-require-effective-target exceptions_enabled } to avoid verify compiler messages FAILs for '-fno-exceptions'. -consteval int bar (int i) { if (i != 1) throw 1; return 0; } // { dg-error "is not a constant expression" } +consteval int bar (int i) { if (i != 1) throw 1; return 0; } // { dg-error "is not a constant expression" "" { target c++23_down } } constexpr int foo (bool b) { - return b ? bar (3) : 2; // { dg-message "in .constexpr. expansion" } + return b ? bar (3) : 2; // { dg-message "in .constexpr. expansion" "" { target c++23_down } } // { dg-error "call to consteval function" "" { target *-*-* } .-1 } -} +} // { dg-error "uncaught exception '1'" "" { target c++26 } } static_assert (foo (false) == 2); -__extension__ constexpr int g1 = false ?: bar (2); // { dg-message "in .constexpr. expansion" } -__extension__ constexpr int g2 = false ?: (1 + bar (2)); // { dg-message "in .constexpr. expansion" } +__extension__ constexpr int g1 = false ?: bar (2); // { dg-message "in .constexpr. expansion" "" { target c++23_down } } +// { dg-error "uncaught exception '1'" "" { target c++26 } .-1 } +__extension__ constexpr int g2 = false ?: (1 + bar (2)); // { dg-message "in .constexpr. expansion" "" { target c++23_down } } +// { dg-error "uncaught exception '1'" "" { target c++26 } .-1 } __extension__ constexpr int g3 = true ?: bar (2); __extension__ constexpr int g4 = true ?: (1 + bar (2)); -constexpr int g5 = bar (2) ? 1 : 2; // { dg-message "in .constexpr. expansion" } -constexpr int g6 = bar (2) - 1 ? 1 : 2; // { dg-message "in .constexpr. expansion" } +constexpr int g5 = bar (2) ? 1 : 2; // { dg-message "in .constexpr. expansion" "" { target c++23_down } } +// { dg-error "uncaught exception '1'" "" { target c++26 } .-1 } +constexpr int g6 = bar (2) - 1 ? 1 : 2; // { dg-message "in .constexpr. expansion" "" { target c++23_down } } +// { dg-error "uncaught exception '1'" "" { target c++26 } .-1 } void g () { - __extension__ int a1[bar(3)]; // { dg-message "in .constexpr. expansion" } + __extension__ int a1[bar(3)]; // { dg-message "in .constexpr. expansion" "" { target c++23_down } } // { dg-error "call to consteval function" "" { target *-*-* } .-1 } int a2[sizeof (bar(3))]; - int a3 = false ? (1 + bar (8)) : 1; // { dg-message "in .constexpr. expansion" } + int a3 = false ? (1 + bar (8)) : 1; // { dg-message "in .constexpr. expansion" "" { target c++23_down } } // { dg-error "call to consteval function" "" { target *-*-* } .-1 } - a3 += false ? (1 + bar (8)) : 1; // { dg-message "in .constexpr. expansion" } +// { dg-error "uncaught exception '1'" "" { target c++26 } .-2 } + a3 += false ? (1 + bar (8)) : 1; // { dg-message "in .constexpr. expansion" "" { target c++23_down } } // { dg-error "call to consteval function" "" { target *-*-* } .-1 } - __extension__ int a4 = false ?: (1 + bar (8)); // { dg-message "in .constexpr. expansion" } + __extension__ int a4 = false ?: (1 + bar (8)); // { dg-message "in .constexpr. expansion" "" { target c++23_down } } // { dg-error "call to consteval function" "" { target *-*-* } .-1 } - __extension__ int a5 = true ?: (1 + bar (8)); // { dg-message "in .constexpr. expansion" } +// { dg-error "uncaught exception '1'" "" { target c++26 } .-2 } + __extension__ int a5 = true ?: (1 + bar (8)); // { dg-message "in .constexpr. expansion" "" { target c++23_down } } // { dg-error "call to consteval function" "" { target *-*-* } .-1 } - int a6 = bar (2) ? 1 : 2; // { dg-message "in .constexpr. expansion" } +// { dg-error "uncaught exception '1'" "" { target c++26 } .-2 } + int a6 = bar (2) ? 1 : 2; // { dg-message "in .constexpr. expansion" "" { target c++23_down } } // { dg-error "call to consteval function" "" { target *-*-* } .-1 } - int a7 = bar (2) - 1 ? 1 : 2; // { dg-message "in .constexpr. expansion" } +// { dg-error "uncaught exception '1'" "" { target c++26 } .-2 } + int a7 = bar (2) - 1 ? 1 : 2; // { dg-message "in .constexpr. expansion" "" { target c++23_down } } // { dg-error "call to consteval function" "" { target *-*-* } .-1 } -} +// { dg-error "uncaught exception '1'" "" { target c++26 } .-2 } +} // { dg-error "uncaught exception '1'" "" { target c++26 } } diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic11.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic11.C index 9ee93c3..12a071a 100644 --- a/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic11.C +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic11.C @@ -8,6 +8,22 @@ // a pointer to or object of the constructor or destructor's own class or one // of its bases, the dynamic_cast results in undefined behavior. +#if __cpp_constexpr_exceptions >= 202411L +namespace std { + struct exception { + constexpr exception () noexcept {} + constexpr virtual ~exception () noexcept {} + constexpr exception (const exception &) = default; + constexpr exception &operator= (const exception &) = default; + constexpr virtual const char *what () const noexcept { return "std::exception"; } + }; + struct bad_cast : public exception { + constexpr virtual ~bad_cast () noexcept {} + constexpr virtual const char *what () const noexcept { return "std::bad_cast"; } + }; +} +#endif + struct V { virtual void f(); }; @@ -19,7 +35,7 @@ struct B : V { }; struct D : A, B { - constexpr D() : B((A*)this, this) { } // { dg-message "in 'constexpr' expansion of" } + constexpr D() : B((A*)this, this) { } // { dg-message "in 'constexpr' expansion of" "" { target c++23_down } } }; constexpr B::B(V* v, A* a) @@ -29,8 +45,9 @@ constexpr B::B(V* v, A* a) if (b != nullptr) __builtin_abort (); - B& br = dynamic_cast<B&>(*v); // { dg-error "reference .dynamic_cast. failed" } -// { dg-message "dynamic type .A. of its operand does not have an unambiguous public base class .B." "" { target *-*-* } .-1 } + B& br = dynamic_cast<B&>(*v); // { dg-error "reference .dynamic_cast. failed" "" { target c++23_down } } +// { dg-message "dynamic type .A. of its operand does not have an unambiguous public base class .B." "" { target c++23_down } .-1 } } -constexpr D d; // { dg-message "in 'constexpr' expansion of" } +constexpr D d; // { dg-message "in 'constexpr' expansion of" "" { target c++23_down } } +// { dg-error "uncaught exception" "" { target c++26 } .-1 } diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic14.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic14.C index cc1cada..f966db4 100644 --- a/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic14.C +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic14.C @@ -4,6 +4,22 @@ // Adopted from g++.old-deja/g++.other/dyncast1.C. // But use reference dynamic_cast. +#if __cpp_constexpr_exceptions >= 202411L +namespace std { + struct exception { + constexpr exception () noexcept {} + constexpr virtual ~exception () noexcept {} + constexpr exception (const exception &) = default; + constexpr exception &operator= (const exception &) = default; + constexpr virtual const char *what () const noexcept { return "std::exception"; } + }; + struct bad_cast : public exception { + constexpr virtual ~bad_cast () noexcept {} + constexpr virtual const char *what () const noexcept { return "std::bad_cast"; } + }; +} +#endif + // 1. downcast // 1.1. single inheritance case @@ -21,27 +37,35 @@ class CCC : protected B {}; class DDD : protected CCC {}; constexpr D d; -constexpr bool b01 = (dynamic_cast<D&> ((A&)d), true); // { dg-error "reference .dynamic_cast. failed" } -// { dg-message "static type .const A. of its operand is a non-public base class of dynamic type .D." "" { target *-*-* } .-1 } -constexpr bool b02 = (dynamic_cast<D&> ((B&)d), true); // { dg-error "reference .dynamic_cast. failed" } -// { dg-message "static type .const B. of its operand is a non-public base class of dynamic type .D." "" { target *-*-* } .-1 } +constexpr bool b01 = (dynamic_cast<D&> ((A&)d), true); // { dg-error "reference .dynamic_cast. failed" "" { target c++23_down } } +// { dg-message "static type .const A. of its operand is a non-public base class of dynamic type .D." "" { target c++23_down } .-1 } +// { dg-error "uncaught exception" "" { target c++26 } .-2 } +constexpr bool b02 = (dynamic_cast<D&> ((B&)d), true); // { dg-error "reference .dynamic_cast. failed" "" { target c++23_down } } +// { dg-message "static type .const B. of its operand is a non-public base class of dynamic type .D." "" { target c++23_down } .-1 } +// { dg-error "uncaught exception" "" { target c++26 } .-2 } static_assert (&d == &dynamic_cast<const D&> ((C&)d)); -constexpr bool b03 = (dynamic_cast<C&> ((B&)d), true); // { dg-error "reference .dynamic_cast. failed" } -// { dg-message "static type .const B. of its operand is a non-public base class of dynamic type .D." "" { target *-*-* } .-1 } +constexpr bool b03 = (dynamic_cast<C&> ((B&)d), true); // { dg-error "reference .dynamic_cast. failed" "" { target c++23_down } } +// { dg-message "static type .const B. of its operand is a non-public base class of dynamic type .D." "" { target c++23_down } .-1 } +// { dg-error "uncaught exception" "" { target c++26 } .-2 } constexpr DD dd; -constexpr bool b04 = (dynamic_cast<DD&> ((A&)dd), true); // { dg-error "reference .dynamic_cast. failed" } -// { dg-message "static type .const A. of its operand is a non-public base class of dynamic type .DD." "" { target *-*-* } .-1 } -constexpr bool b05 = (dynamic_cast<DD&> ((B&)dd), true); // { dg-error "reference .dynamic_cast. failed" } -// { dg-message "static type .const B. of its operand is a non-public base class of dynamic type .DD." "" { target *-*-* } .-1 } +constexpr bool b04 = (dynamic_cast<DD&> ((A&)dd), true); // { dg-error "reference .dynamic_cast. failed" "" { target c++23_down } } +// { dg-message "static type .const A. of its operand is a non-public base class of dynamic type .DD." "" { target c++23_down } .-1 } +// { dg-error "uncaught exception" "" { target c++26 } .-2 } +constexpr bool b05 = (dynamic_cast<DD&> ((B&)dd), true); // { dg-error "reference .dynamic_cast. failed" "" { target c++23_down } } +// { dg-message "static type .const B. of its operand is a non-public base class of dynamic type .DD." "" { target c++23_down } .-1 } +// { dg-error "uncaught exception" "" { target c++26 } .-2 } constexpr DDD ddd; -constexpr bool b06 = (dynamic_cast<DDD&> ((A&)ddd), true); // { dg-error "reference .dynamic_cast. failed" } -// { dg-message "static type .const A. of its operand is a non-public base class of dynamic type .DDD." "" { target *-*-* } .-1 } -constexpr bool b07 = (dynamic_cast<DDD&> ((B&)ddd), true); // { dg-error "reference .dynamic_cast. failed" } -// { dg-message "static type .const B. of its operand is a non-public base class of dynamic type .DDD." "" { target *-*-* } .-1 } -constexpr bool b08 = (dynamic_cast<CCC&> ((B&)ddd), true); // { dg-error "reference .dynamic_cast. failed" } -// { dg-message "static type .const B. of its operand is a non-public base class of dynamic type .DDD." "" { target *-*-* } .-1 } +constexpr bool b06 = (dynamic_cast<DDD&> ((A&)ddd), true); // { dg-error "reference .dynamic_cast. failed" "" { target c++23_down } } +// { dg-message "static type .const A. of its operand is a non-public base class of dynamic type .DDD." "" { target c++23_down } .-1 } +// { dg-error "uncaught exception" "" { target c++26 } .-2 } +constexpr bool b07 = (dynamic_cast<DDD&> ((B&)ddd), true); // { dg-error "reference .dynamic_cast. failed" "" { target c++23_down } } +// { dg-message "static type .const B. of its operand is a non-public base class of dynamic type .DDD." "" { target c++23_down } .-1 } +// { dg-error "uncaught exception" "" { target c++26 } .-2 } +constexpr bool b08 = (dynamic_cast<CCC&> ((B&)ddd), true); // { dg-error "reference .dynamic_cast. failed" "" { target c++23_down } } +// { dg-message "static type .const B. of its operand is a non-public base class of dynamic type .DDD." "" { target c++23_down } .-1 } +// { dg-error "uncaught exception" "" { target c++26 } .-2 } // 1.2. multiple inheritance case // 1.2.1. all bases are public @@ -50,19 +74,23 @@ struct E : D, CC {}; struct EE : CC, D {}; //Will search in reverse order. constexpr E e; -constexpr bool b09 = (dynamic_cast<E&> ((A&)(D&)e), true); // { dg-error "reference .dynamic_cast. failed" } -// { dg-message "static type .A. of its operand is a non-public base class of dynamic type .E." "" { target *-*-* } .-1 } -constexpr bool b10 = (dynamic_cast<E&> ((B&)(D&)e), true); // { dg-error "reference .dynamic_cast. failed" } -// { dg-message "static type .B. of its operand is a non-public base class of dynamic type .E." "" { target *-*-* } .-1 } +constexpr bool b09 = (dynamic_cast<E&> ((A&)(D&)e), true); // { dg-error "reference .dynamic_cast. failed" "" { target c++23_down } } +// { dg-message "static type .A. of its operand is a non-public base class of dynamic type .E." "" { target c++23_down } .-1 } +// { dg-error "uncaught exception" "" { target c++26 } .-2 } +constexpr bool b10 = (dynamic_cast<E&> ((B&)(D&)e), true); // { dg-error "reference .dynamic_cast. failed" "" { target c++23_down } } +// { dg-message "static type .B. of its operand is a non-public base class of dynamic type .E." "" { target c++23_down } .-1 } +// { dg-error "uncaught exception" "" { target c++26 } .-2 } static_assert (&e == &dynamic_cast<E&> ((C&)(D&)e)); static_assert (&e == &dynamic_cast<E&> ((B&)(CC&)e)); static_assert (&(CC&)e == &dynamic_cast<CC&> ((B&)(CC&)e)); constexpr EE ee; -constexpr bool b11 = (dynamic_cast<EE&> ((A&)(D&)ee), true); // { dg-error "reference .dynamic_cast. failed" } -// { dg-message "static type .A. of its operand is a non-public base class of dynamic type .EE." "" { target *-*-* } .-1 } -constexpr bool b12 = (dynamic_cast<EE&> ((B&)(D&)ee), true); // { dg-error "reference .dynamic_cast. failed" } -// { dg-message "static type .B. of its operand is a non-public base class of dynamic type .EE." "" { target *-*-* } .-1 } +constexpr bool b11 = (dynamic_cast<EE&> ((A&)(D&)ee), true); // { dg-error "reference .dynamic_cast. failed" "" { target c++23_down } } +// { dg-message "static type .A. of its operand is a non-public base class of dynamic type .EE." "" { target c++23_down } .-1 } +// { dg-error "uncaught exception" "" { target c++26 } .-2 } +constexpr bool b12 = (dynamic_cast<EE&> ((B&)(D&)ee), true); // { dg-error "reference .dynamic_cast. failed" "" { target c++23_down } } +// { dg-message "static type .B. of its operand is a non-public base class of dynamic type .EE." "" { target c++23_down } .-1 } +// { dg-error "uncaught exception" "" { target c++26 } .-2 } static_assert (&ee == &dynamic_cast<EE&> ((C&)(D&)ee)); static_assert (&ee == &dynamic_cast<EE&> ((B&)(CC&)ee)); static_assert (&(CC&)ee == &dynamic_cast<CC&> ((B&)(CC&)ee)); @@ -78,14 +106,17 @@ constexpr X x; static_assert (&x == &dynamic_cast<X&>((B&)(CC&)(E&)x)); constexpr XX xx; -constexpr bool b13 = (dynamic_cast<XX&>((B&)(CC&)(E&)xx), true); // { dg-error "reference .dynamic_cast. failed" } -// { dg-message "static type .B. of its operand is a non-public base class of dynamic type .XX." "" { target *-*-* } .-1 } +constexpr bool b13 = (dynamic_cast<XX&>((B&)(CC&)(E&)xx), true); // { dg-error "reference .dynamic_cast. failed" "" { target c++23_down } } +// { dg-message "static type .B. of its operand is a non-public base class of dynamic type .XX." "" { target c++23_down } .-1 } +// { dg-error "uncaught exception" "" { target c++26 } .-2 } constexpr Y y; -constexpr bool b14 = (dynamic_cast<Y&>((B&)y), true); // { dg-error "reference .dynamic_cast. failed" } -// { dg-message "static type .const B. of its operand is a non-public base class of dynamic type .Y." "" { target *-*-* } .-1 } -constexpr bool b15 = (dynamic_cast<Y&>((A&)(B&)y), true); // { dg-error "reference .dynamic_cast. failed" } -// { dg-message "static type .A. of its operand is a non-public base class of dynamic type .Y." "" { target *-*-* } .-1 } +constexpr bool b14 = (dynamic_cast<Y&>((B&)y), true); // { dg-error "reference .dynamic_cast. failed" "" { target c++23_down } } +// { dg-message "static type .const B. of its operand is a non-public base class of dynamic type .Y." "" { target c++23_down } .-1 } +// { dg-error "uncaught exception" "" { target c++26 } .-2 } +constexpr bool b15 = (dynamic_cast<Y&>((A&)(B&)y), true); // { dg-error "reference .dynamic_cast. failed" "" { target c++23_down } } +// { dg-message "static type .A. of its operand is a non-public base class of dynamic type .Y." "" { target c++23_down } .-1 } +// { dg-error "uncaught exception" "" { target c++26 } .-2 } // 2. crosscast @@ -93,13 +124,16 @@ struct J { virtual void j(); }; struct K : CC, private J {}; class KK : J, CC{}; -constexpr bool b16 = (dynamic_cast<CC&> ((B&)(D&)e), true); // { dg-error "reference .dynamic_cast. failed" } -// { dg-message "static type .B. of its operand is a non-public base class of dynamic type .CC." "" { target *-*-* } .-1 } +constexpr bool b16 = (dynamic_cast<CC&> ((B&)(D&)e), true); // { dg-error "reference .dynamic_cast. failed" "" { target c++23_down } } +// { dg-message "static type .B. of its operand is a non-public base class of dynamic type .CC." "" { target c++23_down } .-1 } +// { dg-error "uncaught exception" "" { target c++26 } .-2 } static_assert (&(CC&)e == &dynamic_cast<CC&> ((C&)(D&)e)); constexpr K k; -constexpr bool b17 = (dynamic_cast<J&> ((B&)k), true); // { dg-error "reference .dynamic_cast. failed" } -// { dg-message "dynamic type .K. of its operand does not have an unambiguous public base class .J." "" { target *-*-* } .-1 } +constexpr bool b17 = (dynamic_cast<J&> ((B&)k), true); // { dg-error "reference .dynamic_cast. failed" "" { target c++23_down } } +// { dg-message "dynamic type .K. of its operand does not have an unambiguous public base class .J." "" { target c++23_down } .-1 } +// { dg-error "uncaught exception" "" { target c++26 } .-2 } constexpr KK kk; -constexpr bool b18 = (dynamic_cast<J&> ((CC&)kk), true); // { dg-error "reference .dynamic_cast. failed" } -// { dg-message "static type .const CC. of its operand is a non-public base class of dynamic type .KK." "" { target *-*-* } .-1 } +constexpr bool b18 = (dynamic_cast<J&> ((CC&)kk), true); // { dg-error "reference .dynamic_cast. failed" "" { target c++23_down } } +// { dg-message "static type .const CC. of its operand is a non-public base class of dynamic type .KK." "" { target c++23_down } .-1 } +// { dg-error "uncaught exception" "" { target c++26 } .-2 } diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic18.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic18.C index 25d98c2..112ff8a 100644 --- a/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic18.C +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic18.C @@ -2,6 +2,22 @@ // { dg-do compile { target c++20 } } // Here 'b' doesn't point/refer to a public base of Derived. +#if __cpp_constexpr_exceptions >= 202411L +namespace std { + struct exception { + constexpr exception () noexcept {} + constexpr virtual ~exception () noexcept {} + constexpr exception (const exception &) = default; + constexpr exception &operator= (const exception &) = default; + constexpr virtual const char *what () const noexcept { return "std::exception"; } + }; + struct bad_cast : public exception { + constexpr virtual ~bad_cast () noexcept {} + constexpr virtual const char *what () const noexcept { return "std::bad_cast"; } + }; +} +#endif + struct Base { constexpr virtual ~Base(){} }; @@ -11,12 +27,12 @@ struct Derived: Base { }; constexpr const Derived& cast(const Base& b) { - return dynamic_cast<const Derived&>(b); // { dg-error "reference .dynamic_cast. failed" } -// { dg-message "dynamic type .const Base. of its operand does not have a base class of type .Derived." "" { target *-*-* } .-1 } + return dynamic_cast<const Derived&>(b); // { dg-error "reference .dynamic_cast. failed" "" { target c++23_down } } +// { dg-message "dynamic type .const Base. of its operand does not have a base class of type .Derived." "" { target c++23_down } .-1 } } auto test() { static constexpr Base b; - constexpr auto res = cast(b); + constexpr auto res = cast(b); // { dg-error "uncaught exception" "" { target c++26 } } return res; } diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic4.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic4.C index da647bf..a237134 100644 --- a/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic4.C +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic4.C @@ -4,6 +4,22 @@ // From clang's constant-expression-cxx2a.cpp. +#if __cpp_constexpr_exceptions >= 202411L +namespace std { + struct exception { + constexpr exception () noexcept {} + constexpr virtual ~exception () noexcept {} + constexpr exception (const exception &) = default; + constexpr exception &operator= (const exception &) = default; + constexpr virtual const char *what () const noexcept { return "std::exception"; } + }; + struct bad_cast : public exception { + constexpr virtual ~bad_cast () noexcept {} + constexpr virtual const char *what () const noexcept { return "std::bad_cast"; } + }; +} +#endif + struct A2 { virtual void a2(); }; struct A : A2 { virtual void a(); }; struct B : A {}; @@ -26,31 +42,36 @@ static_assert(dynamic_cast<const A*>(static_cast<const C2*>(&g)) == nullptr); static_assert(g.f == (void*)(F*)&g); static_assert(dynamic_cast<const void*>(static_cast<const D*>(&g)) == &g); -constexpr int d_a = (dynamic_cast<const A&>(static_cast<const D&>(g)), 0); // { dg-error "reference .dynamic_cast. failed" } -// { dg-message ".A. is an ambiguous base class of dynamic type .G." "" { target *-*-* } .-1 } - +constexpr int d_a = (dynamic_cast<const A&>(static_cast<const D&>(g)), 0); // { dg-error "reference .dynamic_cast. failed" "" { target c++23_down } } +// { dg-message ".A. is an ambiguous base class of dynamic type .G." "" { target c++23_down } .-1 } +// { dg-error "uncaught exception" "" { target c++26 } .-2 } // Can navigate from A2 to its A... static_assert(&dynamic_cast<A&>((A2&)(B&)g) == &(A&)(B&)g); // ... and from B to its A ... static_assert(&dynamic_cast<A&>((B&)g) == &(A&)(B&)g); // ... but not from D. -static_assert(&dynamic_cast<A&>((D&)g) == &(A&)(B&)g); // { dg-error "non-constant condition for static assertion|reference .dynamic_cast. failed" } -// { dg-message ".A. is an ambiguous base class of dynamic type .G." "" { target *-*-* } .-1 } - +static_assert(&dynamic_cast<A&>((D&)g) == &(A&)(B&)g); // { dg-error "non-constant condition for static assertion" } +// { dg-message ".A. is an ambiguous base class of dynamic type .G." "" { target c++23_down } .-1 } +// { dg-error "reference .dynamic_cast. failed" "" { target c++23_down } .-2 } +// { dg-error "uncaught exception" "" { target c++26 } .-3 } // Can cast from A2 to sibling class D. static_assert(&dynamic_cast<D&>((A2&)(B&)g) == &(D&)g); // Cannot cast from private base E to derived class F. -constexpr int e_f = (dynamic_cast<F&>((E&)g), 0); // { dg-error "reference .dynamic_cast. failed" } -// { dg-message "static type .const E. of its operand is a non-public base class of dynamic type .G." "" { target *-*-* } .-1 } +constexpr int e_f = (dynamic_cast<F&>((E&)g), 0); // { dg-error "reference .dynamic_cast. failed" "" { target c++23_down } } +// { dg-message "static type .const E. of its operand is a non-public base class of dynamic type .G." "" { target c++23_down } .-1 } +// { dg-error "uncaught exception" "" { target c++26 } .-2 } // Cannot cast from B to private sibling E. -constexpr int b_e = (dynamic_cast<E&>((B&)g), 0); // { dg-error "reference .dynamic_cast. failed" } -// { dg-message "dynamic type .G. of its operand does not have an unambiguous public base class .E." "" { target *-*-* } .-1 } +constexpr int b_e = (dynamic_cast<E&>((B&)g), 0); // { dg-error "reference .dynamic_cast. failed" "" { target c++23_down } } +// { dg-message "dynamic type .G. of its operand does not have an unambiguous public base class .E." "" { target c++23_down } .-1 } +// { dg-error "uncaught exception" "" { target c++26 } .-2 } struct Unrelated { virtual void unrelated(); }; -constexpr int b_unrelated = (dynamic_cast<Unrelated&>((B&)g), 0); // { dg-error "reference .dynamic_cast. failed" } -// { dg-message "dynamic type .G. of its operand does not have an unambiguous public base class .Unrelated." "" { target *-*-* } .-1 } -constexpr int e_unrelated = (dynamic_cast<Unrelated&>((E&)g), 0); // { dg-error "reference .dynamic_cast. failed" } -// { dg-message "static type .const E. of its operand is a non-public base class of dynamic type .G." "" { target *-*-* } .-1 } +constexpr int b_unrelated = (dynamic_cast<Unrelated&>((B&)g), 0); // { dg-error "reference .dynamic_cast. failed" "" { target c++23_down } } +// { dg-message "dynamic type .G. of its operand does not have an unambiguous public base class .Unrelated." "" { target c++23_down } .-1 } +// { dg-error "uncaught exception" "" { target c++26 } .-2 } +constexpr int e_unrelated = (dynamic_cast<Unrelated&>((E&)g), 0); // { dg-error "reference .dynamic_cast. failed" "" { target c++23_down } } +// { dg-message "static type .const E. of its operand is a non-public base class of dynamic type .G." "" { target c++23_down } .-1 } +// { dg-error "uncaught exception" "" { target c++26 } .-2 } diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic6.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic6.C index d67c307..4434a1a 100644 --- a/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic6.C +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic6.C @@ -1,6 +1,22 @@ // PR c++/88337 - Implement P1327R1: Allow dynamic_cast/typeid in constexpr. // { dg-do compile { target c++20 } } +#if __cpp_constexpr_exceptions >= 202411L +namespace std { + struct exception { + constexpr exception () noexcept {} + constexpr virtual ~exception () noexcept {} + constexpr exception (const exception &) = default; + constexpr exception &operator= (const exception &) = default; + constexpr virtual const char *what () const noexcept { return "std::exception"; } + }; + struct bad_cast : public exception { + constexpr virtual ~bad_cast () noexcept {} + constexpr virtual const char *what () const noexcept { return "std::bad_cast"; } + }; +} +#endif + // Private base. struct P1 { virtual void p1(); }; @@ -12,14 +28,16 @@ struct A : B, C, private P2 { virtual void a(); }; constexpr A a; // P1 is a non-public base of A. -constexpr bool b1 = (dynamic_cast<B&>((P1&)a), false); // { dg-error "reference .dynamic_cast. failed" } -// { dg-message "static type .const P1. of its operand is a non-public base class of dynamic type .A." "" { target *-*-* } .-1 } +constexpr bool b1 = (dynamic_cast<B&>((P1&)a), false); // { dg-error "reference .dynamic_cast. failed" "" { target c++23_down } } +// { dg-message "static type .const P1. of its operand is a non-public base class of dynamic type .A." "" { target c++23_down } .-1 } +// { dg-error "uncaught exception" "" { target c++26 } .-2 } // Don't error here. static_assert (dynamic_cast<B*>((P1*)&a) == nullptr); -constexpr bool b2 = (dynamic_cast<C&>((P2&)a), false); // { dg-error "reference .dynamic_cast. failed" } -// { dg-message "static type .const P2. of its operand is a non-public base class of dynamic type .A." "" { target *-*-* } .-1 } +constexpr bool b2 = (dynamic_cast<C&>((P2&)a), false); // { dg-error "reference .dynamic_cast. failed" "" { target c++23_down } } +// { dg-message "static type .const P2. of its operand is a non-public base class of dynamic type .A." "" { target c++23_down } .-1 } +// { dg-error "uncaught exception" "" { target c++26 } .-2 } static_assert (dynamic_cast<C*>((P1*)&a) == nullptr); static_assert (dynamic_cast<C*>((P2*)&a) == nullptr); diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic7.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic7.C index bc3efd0..d504efd 100644 --- a/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic7.C +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic7.C @@ -1,6 +1,22 @@ // PR c++/88337 - Implement P1327R1: Allow dynamic_cast/typeid in constexpr. // { dg-do compile { target c++20 } } +#if __cpp_constexpr_exceptions >= 202411L +namespace std { + struct exception { + constexpr exception () noexcept {} + constexpr virtual ~exception () noexcept {} + constexpr exception (const exception &) = default; + constexpr exception &operator= (const exception &) = default; + constexpr virtual const char *what () const noexcept { return "std::exception"; } + }; + struct bad_cast : public exception { + constexpr virtual ~bad_cast () noexcept {} + constexpr virtual const char *what () const noexcept { return "std::bad_cast"; } + }; +} +#endif + // Protected base. struct P1 { virtual void p1(); }; @@ -12,14 +28,16 @@ struct A : B, C, protected P2 { virtual void a(); }; constexpr A a; // P1 is a non-public base of A. -constexpr bool b1 = (dynamic_cast<B&>((P1&)a), false); // { dg-error "reference .dynamic_cast. failed" } -// { dg-message "static type .const P1. of its operand is a non-public base class of dynamic type .A." "" { target *-*-* } .-1 } +constexpr bool b1 = (dynamic_cast<B&>((P1&)a), false); // { dg-error "reference .dynamic_cast. failed" "" { target c++23_down } } +// { dg-message "static type .const P1. of its operand is a non-public base class of dynamic type .A." "" { target c++23_down } .-1 } +// { dg-error "uncaught exception" "" { target c++26 } .-2 } // Don't error here. static_assert (dynamic_cast<B*>((P1*)&a) == nullptr); -constexpr bool b2 = (dynamic_cast<C&>((P2&)a), false); // { dg-error "reference .dynamic_cast. failed" } -// { dg-message "static type .const P2. of its operand is a non-public base class of dynamic type .A." "" { target *-*-* } .-1 } +constexpr bool b2 = (dynamic_cast<C&>((P2&)a), false); // { dg-error "reference .dynamic_cast. failed" "" { target c++23_down } } +// { dg-message "static type .const P2. of its operand is a non-public base class of dynamic type .A." "" { target c++23_down } .-1 } +// { dg-error "uncaught exception" "" { target c++26 } .-2 } static_assert (dynamic_cast<C*>((P1*)&a) == nullptr); static_assert (dynamic_cast<C*>((P2*)&a) == nullptr); diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic8.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic8.C index 1958cae4..2fc8242 100644 --- a/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic8.C +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic8.C @@ -1,6 +1,22 @@ // PR c++/88337 - Implement P1327R1: Allow dynamic_cast/typeid in constexpr. // { dg-do compile { target c++20 } } +#if __cpp_constexpr_exceptions >= 202411L +namespace std { + struct exception { + constexpr exception () noexcept {} + constexpr virtual ~exception () noexcept {} + constexpr exception (const exception &) = default; + constexpr exception &operator= (const exception &) = default; + constexpr virtual const char *what () const noexcept { return "std::exception"; } + }; + struct bad_cast : public exception { + constexpr virtual ~bad_cast () noexcept {} + constexpr virtual const char *what () const noexcept { return "std::bad_cast"; } + }; +} +#endif + // Unrelated type. struct B { virtual void b(); }; @@ -12,12 +28,15 @@ constexpr A a; struct U { virtual void u(); }; -constexpr bool b1 = (dynamic_cast<U&>((B&)a), 0); // { dg-error "reference .dynamic_cast. failed" } -// { dg-message "dynamic type .A. of its operand does not have an unambiguous public base class .U." "" { target *-*-* } .-1 } -constexpr bool b2 = (dynamic_cast<U&>((P1&)a), 0); // { dg-error "reference .dynamic_cast. failed" } -// { dg-message "static type .const P1. of its operand is a non-public base class of dynamic type .A." "" { target *-*-* } .-1 } -constexpr bool b3 = (dynamic_cast<U&>((P2&)a), 0); // { dg-error "reference .dynamic_cast. failed" } -// { dg-message "static type .const P2. of its operand is a non-public base class of dynamic type .A." "" { target *-*-* } .-1 } +constexpr bool b1 = (dynamic_cast<U&>((B&)a), 0); // { dg-error "reference .dynamic_cast. failed" "" { target c++23_down } } +// { dg-message "dynamic type .A. of its operand does not have an unambiguous public base class .U." "" { target c++23_down } .-1 } +// { dg-error "uncaught exception" "" { target c++26 } .-2 } +constexpr bool b2 = (dynamic_cast<U&>((P1&)a), 0); // { dg-error "reference .dynamic_cast. failed" "" { target c++23_down } } +// { dg-message "static type .const P1. of its operand is a non-public base class of dynamic type .A." "" { target c++23_down } .-1 } +// { dg-error "uncaught exception" "" { target c++26 } .-2 } +constexpr bool b3 = (dynamic_cast<U&>((P2&)a), 0); // { dg-error "reference .dynamic_cast. failed" "" { target c++23_down } } +// { dg-message "static type .const P2. of its operand is a non-public base class of dynamic type .A." "" { target c++23_down } .-1 } +// { dg-error "uncaught exception" "" { target c++26 } .-2 } static_assert (dynamic_cast<U*>((B*)&a) == nullptr); static_assert (dynamic_cast<U*>((P1*)&a) == nullptr); diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic9.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic9.C index 7d42ffa..3a50dde 100644 --- a/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic9.C +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic9.C @@ -1,6 +1,22 @@ // PR c++/88337 - Implement P1327R1: Allow dynamic_cast/typeid in constexpr. // { dg-do compile { target c++20 } } +#if __cpp_constexpr_exceptions >= 202411L +namespace std { + struct exception { + constexpr exception () noexcept {} + constexpr virtual ~exception () noexcept {} + constexpr exception (const exception &) = default; + constexpr exception &operator= (const exception &) = default; + constexpr virtual const char *what () const noexcept { return "std::exception"; } + }; + struct bad_cast : public exception { + constexpr virtual ~bad_cast () noexcept {} + constexpr virtual const char *what () const noexcept { return "std::bad_cast"; } + }; +} +#endif + // Ambiguous base. struct A { virtual void a(); }; @@ -11,7 +27,8 @@ struct E : B, C, D { virtual void d(); }; constexpr E e; -constexpr bool b1 = (dynamic_cast<A&>((D&)e), false); // { dg-error "reference .dynamic_cast. failed" } -// { dg-message ".A. is an ambiguous base class of dynamic type .E. of its operand" "" { target *-*-* } .-1 } +constexpr bool b1 = (dynamic_cast<A&>((D&)e), false); // { dg-error "reference .dynamic_cast. failed" "" { target c++23_down } } +// { dg-message ".A. is an ambiguous base class of dynamic type .E. of its operand" "" { target c++23_down } .-1 } +// { dg-error "uncaught exception" "" { target c++26 } .-2 } static_assert (dynamic_cast<A*>((D*)&e) == nullptr); diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-new27.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-new27.C new file mode 100644 index 0000000..a26fc7e --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-new27.C @@ -0,0 +1,41 @@ +// { dg-do compile { target c++20 } } + +#if __cpp_constexpr_exceptions >= 202411L +namespace std { + struct exception { + constexpr exception () noexcept {} + constexpr virtual ~exception () noexcept {} + constexpr exception (const exception &) = default; + constexpr exception &operator= (const exception &) = default; + constexpr virtual const char *what () const noexcept { return "std::exception"; } + }; + struct bad_alloc : public exception { + constexpr virtual ~bad_alloc () noexcept {} + constexpr virtual const char *what () const noexcept { return "std::bad_alloc"; } + }; + struct bad_array_new_length : public bad_alloc { + constexpr virtual ~bad_array_new_length () noexcept {} + constexpr virtual const char *what () const noexcept { return "std::bad_array_new_length"; } + }; +} +#endif + +constexpr int +foo (__SIZE_TYPE__ x, int y, int z) +{ + char (*a)[2] = new char[x][2]; // { dg-error "call to non-'constexpr' function 'void __cxa_throw_bad_array_new_length\\\(\\\)'" "" { target c++23_down } } + delete[] a; // { dg-message "declared here" "" { target c++23_down } .-1 } + int *b = new int[y]; // { dg-error "call to non-'constexpr' function 'void __cxa_throw_bad_array_new_length\\\(\\\)'" "" { target c++23_down } } + delete[] b; + int *c = new int[z]{1, 2, 3}; // { dg-error "call to non-'constexpr' function 'void __cxa_throw_bad_array_new_length\\\(\\\)'" "" { target c++23_down } } + delete[] c; + return 0; +} + +constexpr int a = foo (16, 2, 3); +constexpr int b = foo (-64, 2, 3); // { dg-message "in 'constexpr' expansion of" "" { target c++23_down } } + // { dg-error "uncaught exception" "" { target c++26 } .-1 } +constexpr int c = foo (16, -1, 3); // { dg-message "in 'constexpr' expansion of" "" { target c++23_down } } + // { dg-error "uncaught exception" "" { target c++26 } .-1 } +constexpr int d = foo (16, 2, 1); // { dg-message "in 'constexpr' expansion of" "" { target c++23_down } } + // { dg-error "uncaught exception" "" { target c++26 } .-1 } diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-typeid5.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-typeid5.C new file mode 100644 index 0000000..567383d --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-typeid5.C @@ -0,0 +1,20 @@ +// PR c++/88337 - Implement P1327R1: Allow dynamic_cast/typeid in constexpr. +// { dg-do compile { target c++17 } } + +#include <typeinfo> + +template <class T> +constexpr bool foo () +{ + bool r = false; + const std::type_info &s = typeid( (r = true), *(T *) 0); // { dg-error "call to non-'constexpr' function 'void __cxa_bad_typeid\\\(\\\)'" "" { target c++23_down } } + return r; // { dg-message "declared here" "" { target c++23_down } .-1 } +} + +struct A {}; +struct B { virtual ~B () {} }; + +static_assert (!foo <int> ()); +static_assert (!foo <A> ()); +constexpr bool a = foo <B> (); // { dg-message "in 'constexpr' expansion of" "" { target c++23_down } } +// { dg-error "uncaught exception" "" { target c++26 } .-1 } diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-targ17.C b/gcc/testsuite/g++.dg/cpp2a/lambda-targ17.C new file mode 100644 index 0000000..84955ae --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/lambda-targ17.C @@ -0,0 +1,8 @@ +// PR c++/12012 +// { dg-do compile { target c++20 } } + +template<auto> int x; + +int main() { + x<[](auto) {}>; +} diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-uneval28.C b/gcc/testsuite/g++.dg/cpp2a/lambda-uneval28.C new file mode 100644 index 0000000..4b1bfc8 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/lambda-uneval28.C @@ -0,0 +1,10 @@ +// PR c++/121008 +// { dg-do compile { target c++20 } } + +struct A { + void f() + noexcept(noexcept([this]() noexcept(noexcept(this)) {})) + {} +}; + +int main() {} diff --git a/gcc/testsuite/g++.dg/parse/template32.C b/gcc/testsuite/g++.dg/parse/template32.C new file mode 100644 index 0000000..b090f40 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/template32.C @@ -0,0 +1,13 @@ +// PR c++/119838 +// { dg-do compile { target c++11 } } + +template<typename T> +struct S { using U = T; static const int x = 0; }; +void +g () +{ + ::S<int>::U a; + ::template S<int>::U b; + auto c = ::S<int>::x; + auto d = ::template S<int>::x; +} diff --git a/gcc/testsuite/g++.dg/parse/union1.C b/gcc/testsuite/g++.dg/parse/union1.C new file mode 100644 index 0000000..d567ea3 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/union1.C @@ -0,0 +1,19 @@ +// PR c++/83469 +// { dg-do compile } + +struct S { + union U { int m; }; +}; + +template <typename T> +void +f () +{ + union T::U u; +} + +int +main() +{ + f<S>(); +} diff --git a/gcc/testsuite/g++.dg/parse/union2.C b/gcc/testsuite/g++.dg/parse/union2.C new file mode 100644 index 0000000..cdb1392 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/union2.C @@ -0,0 +1,19 @@ +// PR c++/83469 +// { dg-do compile } + +struct S { + union U { int m; }; +}; + +template <typename T> +void +f () +{ + struct T::U u; // { dg-error "not a non-union class type" } +} + +int +main() +{ + f<S>(); +} diff --git a/gcc/testsuite/g++.dg/parse/union3.C b/gcc/testsuite/g++.dg/parse/union3.C new file mode 100644 index 0000000..61552a4 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/union3.C @@ -0,0 +1,19 @@ +// PR c++/83469 +// { dg-do compile } + +struct S { + struct C { int m; }; +}; + +template <typename T> +void +f () +{ + union T::C u; // { dg-error "not a union type" } +} + +int +main() +{ + f<S>(); +} diff --git a/gcc/testsuite/g++.dg/parse/union4.C b/gcc/testsuite/g++.dg/parse/union4.C new file mode 100644 index 0000000..709f6a4 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/union4.C @@ -0,0 +1,12 @@ +// PR c++/93809 +// { dg-do compile } + +class C { }; +enum E { }; +struct S { }; +union U { }; + +typedef typename ::C C2; +typedef typename ::E E2; +typedef typename ::S S2; +typedef typename ::U U2; diff --git a/gcc/testsuite/g++.dg/parse/union5.C b/gcc/testsuite/g++.dg/parse/union5.C new file mode 100644 index 0000000..18238dd --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/union5.C @@ -0,0 +1,5 @@ +// PR c++/93809 +// { dg-do compile { target c++11 } } + +union U {}; +auto var = new (typename ::U); diff --git a/gcc/testsuite/g++.dg/parse/union6.C b/gcc/testsuite/g++.dg/parse/union6.C new file mode 100644 index 0000000..61b9568 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/union6.C @@ -0,0 +1,5 @@ +// PR c++/93809 +// { dg-do compile } + +typedef union{} U; +typename ::U foo () { return U(); } diff --git a/gcc/testsuite/g++.dg/template/error45.C b/gcc/testsuite/g++.dg/template/error45.C index 064554d..f4c6560 100644 --- a/gcc/testsuite/g++.dg/template/error45.C +++ b/gcc/testsuite/g++.dg/template/error45.C @@ -11,7 +11,7 @@ struct enable_if< true, T > template < typename T > struct enable_if< true, T >::type -f( T x ); // { dg-error "not a class type" } +f( T x ); // { dg-error "not a non-union class type" } void g( void ) diff --git a/gcc/testsuite/g++.dg/warn/Wredundant-tags-3.C b/gcc/testsuite/g++.dg/warn/Wredundant-tags-3.C index 0eeee34..dcccdca 100644 --- a/gcc/testsuite/g++.dg/warn/Wredundant-tags-3.C +++ b/gcc/testsuite/g++.dg/warn/Wredundant-tags-3.C @@ -28,7 +28,7 @@ struct N::S s3; // { dg-warning "-Wredundant-tags" } N::U u1; typename N::U u2; // { dg-bogus "-Wredundant-tags" } - // { dg-bogus "'class' tag used in naming 'union N::U" "pr93809" { xfail *-*-*} .-1 } + // { dg-bogus "'class' tag used in naming 'union N::U" "pr93809" { target *-*-*} .-1 } union N::U u3; // { dg-warning "-Wredundant-tags" } diff --git a/gcc/testsuite/g++.target/aarch64/pr119498.C b/gcc/testsuite/g++.target/aarch64/pr119498.C new file mode 100644 index 0000000..03f1659 --- /dev/null +++ b/gcc/testsuite/g++.target/aarch64/pr119498.C @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-require-ifunc "" } */ +/* { dg-options "-O0" } */ +/* { dg-additional-options "-Wno-experimental-fmv-target" } */ + +__attribute__ ((target_version ("default"))) int +foo (); + +__attribute__ ((target_version ("default"))) int +foo () { return 1; } /* { dg-message "old declaration" } */ + +__attribute__ ((target_version ("dotprod"))) float +foo () { return 3; } /* { dg-error "ambiguating new declaration" } */ + +__attribute__ ((target_version ("sve"))) int +foo2 () { return 1; } /* { dg-message "old declaration" } */ + +__attribute__ ((target_version ("dotprod"))) float +foo2 () { return 3; } /* { dg-error "ambiguating new declaration of" } */ diff --git a/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-pr120780.c b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-pr120780.c index 0d6593e..12e6c29 100644 --- a/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-pr120780.c +++ b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-pr120780.c @@ -207,7 +207,7 @@ test5 (size_t sz) } int -main (size_t sz) +main (void) { test1 (sizeof (struct container)); test1 (sizeof (struct container) - sizeof (int)); diff --git a/gcc/testsuite/gcc.dg/crc-non-cst-poly-1.c b/gcc/testsuite/gcc.dg/crc-non-cst-poly-1.c new file mode 100644 index 0000000..0c3d905 --- /dev/null +++ b/gcc/testsuite/gcc.dg/crc-non-cst-poly-1.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "" } */ + +/* PR middle-end/120709 */ +/* Make sure we don't ICE on a non-constant poly argument. */ + + +typedef unsigned char uint8_t; +uint8_t crc8_data8(uint8_t crc, uint8_t data, uint8_t polynomial) { + return __builtin_rev_crc32_data8 (crc, data, polynomial); /* { dg-error "must be a constant" } */ +} diff --git a/gcc/testsuite/gcc.dg/flex-array-counted-by-pr121000.c b/gcc/testsuite/gcc.dg/flex-array-counted-by-pr121000.c new file mode 100644 index 0000000..5b9a2c6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/flex-array-counted-by-pr121000.c @@ -0,0 +1,43 @@ +/* PR middle-end/121000 */ +/* { dg-do run } */ +/* { dg-options "-O" } */ + +#include "builtin-object-size-common.h" + +/* The parameter m must be const qualified to avoid the m is + marked as TREE_SIDE_EFFECTS in IR. + The __builtin_dynamic_object_size will be folded as -1 by + fold_builtin_object_size when m is NOT const qualified. */ + +void +foo (int n, const int m) +{ + typedef int A[m]; + struct S { int n, m; A a[2]; A b[] __attribute__((counted_by (n))); } *p; + p = __builtin_malloc (sizeof (struct S) + sizeof (A) * n); + p->n = n; + p->m = m; + EXPECT (__builtin_dynamic_object_size (p->b, 1), sizeof (A) * n); +} + +/* The parameter m1, m2 must be const qualified to avoid the m is + marked as TREE_SIDE_EFFECTS in IR. + The __builtin_dynamic_object_size will be folded as -1 by + fold_builtin_object_size when m1 or m2 is NOT const qualified. */ +void +foo_1 (int n, const int m1, const int m2) +{ + typedef int A[m1][m2]; + struct S { int n; A a[2]; A b[] __attribute__((counted_by (n))); } *p; + p = __builtin_malloc (sizeof (struct S) + sizeof (A) * n); + p->n = n; + EXPECT (__builtin_dynamic_object_size (p->b, 1), sizeof (A) * n); +} + +int +main () +{ + foo (2, 10); + foo_1 (2, 10, 20); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/flex-array-counted-by.c b/gcc/testsuite/gcc.dg/flex-array-counted-by.c index 4fa91ff..16eb2c6 100644 --- a/gcc/testsuite/gcc.dg/flex-array-counted-by.c +++ b/gcc/testsuite/gcc.dg/flex-array-counted-by.c @@ -10,7 +10,7 @@ int x __attribute ((counted_by (size))); /* { dg-error "attribute is not allowed struct trailing { int count; - int field __attribute ((counted_by (count))); /* { dg-error "attribute is not allowed for a non-array or non-pointer field" } */ + int field __attribute ((counted_by (count))); /* { dg-error "attribute is not allowed for a non-array field" } */ }; struct trailing_1 { diff --git a/gcc/testsuite/gcc.dg/guality/guality.h b/gcc/testsuite/gcc.dg/guality/guality.h index d41327c..48b59d2e 100644 --- a/gcc/testsuite/gcc.dg/guality/guality.h +++ b/gcc/testsuite/gcc.dg/guality/guality.h @@ -204,9 +204,10 @@ int volatile guality_attached; of this wrapping, guality_main may not have an empty argument list. */ -extern int guality_main (int argc, char *argv[]); +extern int __attribute__((noipa)) +guality_main (int argc, char *argv[]); -static void __attribute__((noinline)) +static void __attribute__((noipa)) guality_check (const char *name, gualchk_t value, int unknown_ok); /* Set things up, run guality_main, then print a summary and quit. */ diff --git a/gcc/testsuite/gcc.dg/pointer-counted-by-1.c b/gcc/testsuite/gcc.dg/pointer-counted-by-1.c deleted file mode 100644 index 395af34..0000000 --- a/gcc/testsuite/gcc.dg/pointer-counted-by-1.c +++ /dev/null @@ -1,34 +0,0 @@ -/* More testing the correct usage of attribute counted_by for pointer field. */ -/* { dg-do compile } */ -/* { dg-options "-O0" } */ - -typedef struct item1 Item1; -typedef union item2 Item2; - -struct pointer_array { - int count1; - Item1 *array_1 __attribute__ ((counted_by (count1))); - Item2 *array_2 __attribute__ ((counted_by (count2))); - int count2; -} *pointer_data; - -struct item1 { - int a; - float b[]; -}; - -union item2 { - int c; - float d[]; -}; - -void foo () -{ - pointer_data - = (struct pointer_array *) __builtin_malloc (sizeof (struct pointer_array)); - pointer_data->array_1 /* { dg-error "attribute is not allowed for a pointer to structure or union with flexible array member" } */ - = (Item1 *) __builtin_malloc (sizeof (Item1) + 3 * sizeof (float)); - pointer_data->array_2 /* { dg-error "attribute is not allowed for a pointer to structure or union with flexible array member" } */ - = (Item2 *) __builtin_malloc (sizeof (Item2) + 3 * sizeof (float)); - return; -} diff --git a/gcc/testsuite/gcc.dg/pointer-counted-by-2.c b/gcc/testsuite/gcc.dg/pointer-counted-by-2.c deleted file mode 100644 index 1f4a278..0000000 --- a/gcc/testsuite/gcc.dg/pointer-counted-by-2.c +++ /dev/null @@ -1,10 +0,0 @@ -/* Testing the correct usage of attribute counted_by for pointer: _BitInt */ -/* { dg-do compile { target bitint } } */ -/* { dg-options "-O2 -std=c23" } */ - -struct pointer_array { - _BitInt(24) count; - int *array __attribute__ ((counted_by (count))); - int *array1 __attribute__ ((counted_by (count1))); - _BitInt(24) count1; -}; diff --git a/gcc/testsuite/gcc.dg/pointer-counted-by-3.c b/gcc/testsuite/gcc.dg/pointer-counted-by-3.c deleted file mode 100644 index 7005609..0000000 --- a/gcc/testsuite/gcc.dg/pointer-counted-by-3.c +++ /dev/null @@ -1,127 +0,0 @@ - /* Testing the correct usage of attribute counted_by for pointer in c23, - multiple definitions of the same tag in same or different scopes. - { dg-do compile } - { dg-options "-std=c23" } - */ - -/* Allowed redefinitions of the same struct in the same scope, with the - same counted_by attribute. */ -struct f { - int b; - int c; - int *a __attribute__ ((counted_by (b))); }; -struct f { - int b; - int c; - int *a __attribute__ ((counted_by (b))); }; -struct f { - int b; - int c; - int *a; }; /* { dg-error "redefinition of struct or union" } */ - -/* Error when the counted_by attribute is defined differently. */ -struct f { - int b; - int c; - int *a __attribute__ ((counted_by (c))); }; /* { dg-error "redefinition of struct or union" } */ - -struct h { - int b; - int c; - int *a __attribute__ ((counted_by (b))); } p; - -void test (void) -{ - struct h { - int b; - int c; - int *a __attribute__ ((counted_by (b))); } x; - - p = x; -} - -void test1 (void) -{ - struct h { - int b; - int c; - int *a __attribute__ ((counted_by (c))); } y; - - p = y; /* { dg-error "incompatible types when assigning to type" } */ -} - -struct nested_f { - struct { - union { - int b; - float f; - }; - int n; - }; - char *c __attribute__ ((counted_by (b))); -}; - -struct nested_f { - struct { - union { - int b; - float f; - }; - int n; - }; - char *c __attribute__ ((counted_by (b))); -}; - -struct nested_f { - struct { - union { - int b; - float f; - }; - int n; - }; - char *c __attribute__ ((counted_by (n))); -}; /* { dg-error "redefinition of struct or union" } */ - -struct nested_h { - struct { - union { - int b; - float f; - }; - int n; - }; - char *c __attribute__ ((counted_by (b))); -} nested_p; - -void test_2 (void) -{ -struct nested_h { - struct { - union { - int b; - float f; - }; - int n; - }; - char *c __attribute__ ((counted_by (b))); -} nested_x; - - nested_p = nested_x; -} - -void test_3 (void) -{ -struct nested_h { - struct { - union { - int b; - float f; - }; - int n; - }; - char *c __attribute__ ((counted_by (n))); -} nested_y; - - nested_p = nested_y; /* { dg-error "incompatible types when assigning to type" } */ -} diff --git a/gcc/testsuite/gcc.dg/pointer-counted-by-4-char.c b/gcc/testsuite/gcc.dg/pointer-counted-by-4-char.c deleted file mode 100644 index c404e5b..0000000 --- a/gcc/testsuite/gcc.dg/pointer-counted-by-4-char.c +++ /dev/null @@ -1,6 +0,0 @@ -/* Test the attribute counted_by for pointer field and its usage in - * __builtin_dynamic_object_size. */ -/* { dg-do run } */ -/* { dg-options "-O2" } */ -#define PTR_TYPE char -#include "pointer-counted-by-4.c" diff --git a/gcc/testsuite/gcc.dg/pointer-counted-by-4-float.c b/gcc/testsuite/gcc.dg/pointer-counted-by-4-float.c deleted file mode 100644 index 383d8fb..0000000 --- a/gcc/testsuite/gcc.dg/pointer-counted-by-4-float.c +++ /dev/null @@ -1,6 +0,0 @@ -/* Test the attribute counted_by for pointer field and its usage in - * __builtin_dynamic_object_size. */ -/* { dg-do run } */ -/* { dg-options "-O2" } */ -#define PTR_TYPE float -#include "pointer-counted-by-4.c" diff --git a/gcc/testsuite/gcc.dg/pointer-counted-by-4-struct.c b/gcc/testsuite/gcc.dg/pointer-counted-by-4-struct.c deleted file mode 100644 index 50246d2..0000000 --- a/gcc/testsuite/gcc.dg/pointer-counted-by-4-struct.c +++ /dev/null @@ -1,10 +0,0 @@ -/* Test the attribute counted_by for pointer field and its usage in - * __builtin_dynamic_object_size. */ -/* { dg-do run } */ -/* { dg-options "-O2" } */ -struct A { - int a; - char *b; -}; -#define PTR_TYPE struct A -#include "pointer-counted-by-4.c" diff --git a/gcc/testsuite/gcc.dg/pointer-counted-by-4-union.c b/gcc/testsuite/gcc.dg/pointer-counted-by-4-union.c deleted file mode 100644 index e786d99..0000000 --- a/gcc/testsuite/gcc.dg/pointer-counted-by-4-union.c +++ /dev/null @@ -1,10 +0,0 @@ -/* Test the attribute counted_by for pointer field and its usage in - * __builtin_dynamic_object_size. */ -/* { dg-do run } */ -/* { dg-options "-O2" } */ -union A { - int a; - float b; -}; -#define PTR_TYPE union A -#include "pointer-counted-by-4.c" diff --git a/gcc/testsuite/gcc.dg/pointer-counted-by-4.c b/gcc/testsuite/gcc.dg/pointer-counted-by-4.c deleted file mode 100644 index c4b3631..0000000 --- a/gcc/testsuite/gcc.dg/pointer-counted-by-4.c +++ /dev/null @@ -1,77 +0,0 @@ -/* Test the attribute counted_by for pointer field and its usage in - * __builtin_dynamic_object_size. */ -/* { dg-do run } */ -/* { dg-options "-O2" } */ - -#include "builtin-object-size-common.h" -#ifndef PTR_TYPE -#define PTR_TYPE int -#endif -struct pointer_array { - int b; - PTR_TYPE *c; -} *p_array; - -struct annotated { - PTR_TYPE *c __attribute__ ((counted_by (b))); - int b; -} *p_array_annotated; - -struct nested_annotated { - PTR_TYPE *c __attribute__ ((counted_by (b))); - struct { - union { - int b; - float f; - }; - int n; - }; -} *p_array_nested_annotated; - -void __attribute__((__noinline__)) setup (int normal_count, int attr_count) -{ - p_array - = (struct pointer_array *) malloc (sizeof (struct pointer_array)); - p_array->c = (PTR_TYPE *) malloc (sizeof (PTR_TYPE) * normal_count); - p_array->b = normal_count; - - p_array_annotated - = (struct annotated *) malloc (sizeof (struct annotated)); - p_array_annotated->c = (PTR_TYPE *) malloc (sizeof (PTR_TYPE) * attr_count); - p_array_annotated->b = attr_count; - - p_array_nested_annotated - = (struct nested_annotated *) malloc (sizeof (struct nested_annotated)); - p_array_nested_annotated->c = (PTR_TYPE *) malloc (sizeof (PTR_TYPE) * attr_count); - p_array_nested_annotated->b = attr_count; - - return; -} - -void __attribute__((__noinline__)) test () -{ - EXPECT(__builtin_dynamic_object_size(p_array->c, 1), -1); - EXPECT(__builtin_dynamic_object_size(p_array_annotated->c, 1), - p_array_annotated->b * sizeof (PTR_TYPE)); - EXPECT(__builtin_dynamic_object_size(p_array_nested_annotated->c, 1), - p_array_nested_annotated->b * sizeof (PTR_TYPE)); -} - -void cleanup () -{ - free (p_array->c); - free (p_array); - free (p_array_annotated->c); - free (p_array_annotated); - free (p_array_nested_annotated->c); - free (p_array_nested_annotated); -} - -int main(int argc, char *argv[]) -{ - setup (10,10); - test (); - DONE (); - cleanup (); - return 0; -} diff --git a/gcc/testsuite/gcc.dg/pointer-counted-by-5.c b/gcc/testsuite/gcc.dg/pointer-counted-by-5.c deleted file mode 100644 index b43ffdf..0000000 --- a/gcc/testsuite/gcc.dg/pointer-counted-by-5.c +++ /dev/null @@ -1,56 +0,0 @@ -/* Test the attribute counted_by for pointer fields and its usage in - * __builtin_dynamic_object_size: when the counted_by field is negative. */ -/* { dg-do run } */ -/* { dg-options "-O2" } */ - -#include "builtin-object-size-common.h" - -struct annotated { - int b; - int *c __attribute__ ((counted_by (b))); -} *array_annotated; - -struct nested_annotated { - int *c __attribute__ ((counted_by (b))); - struct { - union { - int b; - float f; - }; - int n; - }; -} *array_nested_annotated; - -void __attribute__((__noinline__)) setup (int attr_count) -{ - array_annotated - = (struct annotated *)malloc (sizeof (struct annotated)); - array_annotated->b = attr_count; - - array_nested_annotated - = (struct nested_annotated *)malloc (sizeof (struct nested_annotated)); - array_nested_annotated->b = attr_count - 1; - - return; -} - -void __attribute__((__noinline__)) test () -{ - EXPECT(__builtin_dynamic_object_size(array_annotated->c, 1), 0); - EXPECT(__builtin_dynamic_object_size(array_nested_annotated->c, 1), 0); -} - -void cleanup () -{ - free (array_annotated); - free (array_nested_annotated); -} - -int main(int argc, char *argv[]) -{ - setup (-10); - test (); - DONE (); - cleanup (); - return 0; -} diff --git a/gcc/testsuite/gcc.dg/pointer-counted-by-6.c b/gcc/testsuite/gcc.dg/pointer-counted-by-6.c deleted file mode 100644 index 355558c..0000000 --- a/gcc/testsuite/gcc.dg/pointer-counted-by-6.c +++ /dev/null @@ -1,56 +0,0 @@ -/* Test the attribute counted_by for pointer fields and its usage in - * __builtin_dynamic_object_size: when the type of the pointer - * is casting to another type. */ -/* { dg-do run } */ -/* { dg-options "-O2" } */ - -#include "builtin-object-size-common.h" - -typedef unsigned short u16; - -struct info { - u16 data_len; - char *data __attribute__((counted_by(data_len))); -}; - -struct foo { - int a; - int b; -}; - -static __attribute__((__noinline__)) -struct info *setup () -{ - struct info *p; - size_t bytes = 3 * sizeof(struct foo); - - p = (struct info *) malloc (sizeof (struct info)); - p->data = (char *) malloc (bytes); - p->data_len = bytes; - - return p; -} - -static void -__attribute__((__noinline__)) report (struct info *p) -{ - struct foo *bar = (struct foo *)p->data; - EXPECT(__builtin_dynamic_object_size((char *)(bar + 1), 1), - sizeof (struct foo) * 2); - EXPECT(__builtin_dynamic_object_size((char *)(bar + 2), 1), - sizeof (struct foo)); -} - -void cleanup (struct info *p) -{ - free (p->data); - free (p); -} - -int main(int argc, char *argv[]) -{ - struct info *p = setup(); - report(p); - cleanup (p); - return 0; -} diff --git a/gcc/testsuite/gcc.dg/pointer-counted-by-7.c b/gcc/testsuite/gcc.dg/pointer-counted-by-7.c deleted file mode 100644 index af1ab27..0000000 --- a/gcc/testsuite/gcc.dg/pointer-counted-by-7.c +++ /dev/null @@ -1,32 +0,0 @@ -/* Additional test of the attribute counted_by for pointer field and its usage - in __builtin_dynamic_object_size. */ -/* { dg-do run } */ -/* { dg-options "-O2" } */ - -#include "builtin-object-size-common.h" - -struct annotated { - int b; - int *c __attribute__ ((counted_by (b))); -}; - -struct annotated __attribute__((__noinline__)) setup (int attr_count) -{ - struct annotated p_array_annotated; - p_array_annotated.c = (int *) malloc (sizeof (int) * attr_count); - p_array_annotated.b = attr_count; - - return p_array_annotated; -} - -int main(int argc, char *argv[]) -{ - struct annotated x = setup (10); - int *p = x.c; - x = setup (20); - EXPECT(__builtin_dynamic_object_size (p, 1), 10 * sizeof (int)); - EXPECT(__builtin_dynamic_object_size (x.c, 1), 20 * sizeof (int)); - free (p); - free (x.c); - DONE (); -} diff --git a/gcc/testsuite/gcc.dg/pointer-counted-by.c b/gcc/testsuite/gcc.dg/pointer-counted-by.c deleted file mode 100644 index 0f18828..0000000 --- a/gcc/testsuite/gcc.dg/pointer-counted-by.c +++ /dev/null @@ -1,111 +0,0 @@ -/* Testing the correct usage of attribute counted_by for pointer field. - and also mixed pointer field and FMA field in the same structure. */ -/* { dg-do compile } */ -/* { dg-options "-O0" } */ - -int size; -int *x __attribute__ ((counted_by (size))); /* { dg-error "attribute is not allowed for a non-field declaration" } */ - -struct pointer_array_0 { - int count; - int array __attribute__ ((counted_by (count))); /* { dg-error "attribute is not allowed for a non-array or non-pointer field" } */ - int other; -}; - -int count; -struct pointer_array_1 { - int other; - int *array_1 __attribute__ ((counted_by (count))); /* { dg-error "attribute is not a field declaration in the same structure as" } */ - int array_fam[] __attribute__ ((counted_by (count))); /* { dg-error "attribute is not a field declaration in the same structure as" } */ -}; - -struct pointer_array_2 { - float count1; - float count2; - int *array_2 __attribute__ ((counted_by (count1))); /* { dg-error "attribute is not a field declaration with an integer type" } */ - int array_fam[] __attribute__ ((counted_by (count2))); /* { dg-error "attribute is not a field declaration with an integer type" } */ -}; - -struct pointer_array_3 { - int count; - int *array_3 __attribute__ ((counted_by (count))) __attribute__ ((counted_by (count))); -}; - -struct pointer_array_4 { - int count1; - int count2; - int *array_4 __attribute__ ((counted_by (count1))) __attribute__ ((counted_by (count2))); /* { dg-error "conflicts with previous declaration" } */ - float array_fam[] __attribute__ ((counted_by (count2))) __attribute__ ((counted_by (count1))); /* { dg-error "conflicts with previous declaration" } */ -}; - -struct pointer_array_5 { - _Bool count; - int *array_5 __attribute__ ((counted_by (count))); -}; - -enum week {Mon, Tue, Wed}; -struct pointer_array_6 { - enum week days; - int *array_6 __attribute__ ((counted_by (days))); -}; - -struct pointer_array_7 { - int count; - void *array_7 __attribute__ ((counted_by (count))); /* { dg-error "attribute is not allowed for a pointer to void" } */ -}; - -struct pointer_array_8 { - int count; - int (*fpr)(int,int) __attribute__ ((counted_by (count))); /* { dg-error "attribute is not allowed for a pointer to function" } */ -}; - -struct item1 { - int a; - float b; -}; - -union item2 { - char *a; - int *b; -}; - -typedef struct item3 Item3; -typedef union item4 Item4; - -struct item5 { - int a; - float b[]; -}; - -/* Incomplete structure and union are allowed. */ -struct pointer_array_9 { - int count1; - int count2; - int count3; - struct item1 *array_1 __attribute__ ((counted_by (count1))); - union item2 *array_2 __attribute__ ((counted_by (count2))); - Item3 *array_3 __attribute__ ((counted_by (count3))); - Item4 *array_4 __attribute__ ((counted_by (count4))); - int count4; - int count5; - /* structure with flexible array member is not allowed. */ - struct item5 *array_5 __attribute__ ((counted_by (count5))); /* { dg-error "attribute is not allowed for a pointer to structure or union with flexible array member" } */ -}; - -struct mixed_array { - int count1; - float *array_1 __attribute__ ((counted_by (count1))); - float *array_2 __attribute__ ((counted_by (count1))); - int count2; - long *array_3 __attribute__ ((counted_by (count2))); - long array_4[] __attribute__ ((counted_by (count2))); -}; - -struct mixed_array_2 { - float *array_1 __attribute__ ((counted_by (count1))); - int count1; - float *array_2 __attribute__ ((counted_by (count1))); - long *array_3 __attribute__ ((counted_by (count2))); - int count2; - long array_4[] __attribute__ ((counted_by (count2))); -}; diff --git a/gcc/testsuite/gcc.dg/rtl/aarch64/vec-series-1.c b/gcc/testsuite/gcc.dg/rtl/aarch64/vec-series-1.c new file mode 100644 index 0000000..6f795c6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/rtl/aarch64/vec-series-1.c @@ -0,0 +1,35 @@ +/* { dg-do compile { target aarch64*-*-* } } */ +/* { dg-options "-O2 -msve-vector-bits=256 -mlittle-endian" } */ + +#include <arm_sve.h> + +#pragma GCC target "+sve" + +svint64x2_t __RTL (startwith ("vregs")) foo () +{ + (function "foo" + (insn-chain + (block 2 + (edge-from entry (flags "FALLTHRU")) + (cnote 1 [bb 2] NOTE_INSN_BASIC_BLOCK) + (cnote 2 NOTE_INSN_FUNCTION_BEG) + (insn 3 (set (reg:VNx4DI <0>) + (const_vector:VNx4DI [(const_int 11) + (const_int 12) + (const_int 13) + (const_int 14) + (const_int 15) + (const_int 16) + (const_int 17) + (const_int 18)]))) + (insn 4 (set (reg:VNx4DI v0) (reg:VNx4DI <0>))) + (insn 5 (use (reg:VNx4DI v0))) + (edge-to exit (flags "FALLTHRU")) + ) ;; block 2 + ) ;; insn-chain + (crtl (return_rtx (reg:VNx4DI v0))) + ) ;; function +} + +/* { dg-final { scan-assembler {\tindex\tz0\.d, #11, #1\n} } } */ +/* { dg-final { scan-assembler {\tindex\tz1\.d, #15, #1\n} } } */ diff --git a/gcc/testsuite/gcc.dg/rtl/aarch64/vec-series-2.c b/gcc/testsuite/gcc.dg/rtl/aarch64/vec-series-2.c new file mode 100644 index 0000000..17e46cb --- /dev/null +++ b/gcc/testsuite/gcc.dg/rtl/aarch64/vec-series-2.c @@ -0,0 +1,35 @@ +/* { dg-do compile { target aarch64*-*-* } } */ +/* { dg-options "-O2 -msve-vector-bits=256 -mlittle-endian" } */ + +#include <arm_sve.h> + +#pragma GCC target "+sve" + +svint64x2_t __RTL (startwith ("vregs")) foo () +{ + (function "foo" + (insn-chain + (block 2 + (edge-from entry (flags "FALLTHRU")) + (cnote 1 [bb 2] NOTE_INSN_BASIC_BLOCK) + (cnote 2 NOTE_INSN_FUNCTION_BEG) + (insn 3 (set (reg:VNx4DI <0>) + (const_vector:VNx4DI [(const_int -16) + (const_int -15) + (const_int -14) + (const_int -13) + (const_int -12) + (const_int -11) + (const_int -10) + (const_int -9)]))) + (insn 4 (set (reg:VNx4DI v0) (reg:VNx4DI <0>))) + (insn 5 (use (reg:VNx4DI v0))) + (edge-to exit (flags "FALLTHRU")) + ) ;; block 2 + ) ;; insn-chain + (crtl (return_rtx (reg:VNx4DI v0))) + ) ;; function +} + +/* { dg-final { scan-assembler {\tindex\tz0\.d, #-16, #1\n} } } */ +/* { dg-final { scan-assembler {\tindex\tz1\.d, #-12, #1\n} } } */ diff --git a/gcc/testsuite/gcc.dg/torture/pr120654.c b/gcc/testsuite/gcc.dg/torture/pr120654.c index 3819b78..aacfeea 100644 --- a/gcc/testsuite/gcc.dg/torture/pr120654.c +++ b/gcc/testsuite/gcc.dg/torture/pr120654.c @@ -2,8 +2,6 @@ int a, c, e, f, h, j; long g, k; -void *malloc(long); -void free(void *); int b(int m) { if (m || a) return 1; @@ -16,9 +14,9 @@ int i() { } void n() { long o; - int *p = malloc(sizeof(int)); + int *p = __builtin_malloc(sizeof(int)); k = 1 % j; for (; i() + f + h; o++) if (p[d(j + 6, (int)k + 1992695866) + h + f + j + (int)k - 1 + o]) - free(p); + __builtin_free(p); } diff --git a/gcc/testsuite/gcc.dg/tree-prof/afdo-inline.c b/gcc/testsuite/gcc.dg/tree-prof/afdo-inline.c index b67b3cb..ded4068 100644 --- a/gcc/testsuite/gcc.dg/tree-prof/afdo-inline.c +++ b/gcc/testsuite/gcc.dg/tree-prof/afdo-inline.c @@ -1,6 +1,15 @@ /* { dg-options "-O2 -fdump-tree-einline-details --param early-inlining-insns=1" } */ /* { dg-require-profiling "-fauto-profile" } */ volatile int a[1000]; + +#define STR1(X) #X +#define STR2(X) STR1(X) + +int reta (int i) +asm(STR2(__USER_LABEL_PREFIX__) "renamed_reta"); +int test () +asm(STR2(__USER_LABEL_PREFIX__) "renamed_test"); + int reta (int i) { if (a[i]) diff --git a/gcc/testsuite/gcc.dg/ubsan/pointer-counted-by-bounds-2.c b/gcc/testsuite/gcc.dg/ubsan/pointer-counted-by-bounds-2.c deleted file mode 100644 index 0653ecc..0000000 --- a/gcc/testsuite/gcc.dg/ubsan/pointer-counted-by-bounds-2.c +++ /dev/null @@ -1,51 +0,0 @@ -/* Test the attribute counted_by for pointer fields and its usage in - bounds sanitizer combined with VLA. */ -/* { dg-do run } */ -/* { dg-options "-fsanitize=bounds" } */ -/* { dg-output "index 11 out of bounds for type 'int \\\[\\\*\\\]\\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ -/* { dg-output "\[^\n\r]*index 20 out of bounds for type 'int \\\[\\\*\\\]\\\[\\\*\\\]\\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ -/* { dg-output "\[^\n\r]*index 11 out of bounds for type 'int \\\[\\\*\\\]\\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ -/* { dg-output "\[^\n\r]*index 10 out of bounds for type 'int \\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ - - -#include <stdlib.h> - -void __attribute__((__noinline__)) setup_and_test_vla (int n, int m) -{ - struct foo { - int n; - int (*p)[n] __attribute__((counted_by(n))); - } *f; - - f = (struct foo *) malloc (sizeof (struct foo)); - f->p = (int (*)[n]) malloc (m * sizeof (int[n])); - f->n = m; - f->p[m][n-1] = 1; - free (f->p); - free (f); - return; -} - -void __attribute__((__noinline__)) setup_and_test_vla_1 (int n1, int n2, int m) -{ - struct foo { - int n; - int (*p)[n2][n1] __attribute__((counted_by(n))); - } *f; - - f = (struct foo *) malloc (sizeof(struct foo)); - f->p = (int (*)[n2][n1]) malloc (m * sizeof (int[n2][n1])); - f->n = m; - f->p[m][n2][n1] = 1; - free (f->p); - free (f); - return; -} - -int main(int argc, char *argv[]) -{ - setup_and_test_vla (10, 11); - setup_and_test_vla_1 (10, 11, 20); - return 0; -} - diff --git a/gcc/testsuite/gcc.dg/ubsan/pointer-counted-by-bounds-3.c b/gcc/testsuite/gcc.dg/ubsan/pointer-counted-by-bounds-3.c deleted file mode 100644 index 731422d..0000000 --- a/gcc/testsuite/gcc.dg/ubsan/pointer-counted-by-bounds-3.c +++ /dev/null @@ -1,42 +0,0 @@ -/* Test the attribute counted_by for pointer fields and its usage in bounds - sanitizer. when counted_by field is negative value. */ -/* { dg-do run } */ -/* { dg-options "-fsanitize=bounds" } */ - -#include <stdlib.h> - -struct annotated { - int b; - int *c __attribute__ ((counted_by (b))); -} *array_annotated; - -void __attribute__((__noinline__)) setup (int annotated_count) -{ - array_annotated - = (struct annotated *)malloc (sizeof (struct annotated)); - array_annotated->c = (int *) malloc (sizeof (int) * 10); - array_annotated->b = annotated_count; - - return; -} - -void __attribute__((__noinline__)) test (int annotated_index) -{ - array_annotated->c[annotated_index] = 2; -} - -void cleanup () -{ - free (array_annotated->c); - free (array_annotated); -} - -int main(int argc, char *argv[]) -{ - setup (-3); - test (2); - cleanup (); - return 0; -} - -/* { dg-output "25:21: runtime error: index 2 out of bounds for type" } */ diff --git a/gcc/testsuite/gcc.dg/ubsan/pointer-counted-by-bounds-4.c b/gcc/testsuite/gcc.dg/ubsan/pointer-counted-by-bounds-4.c deleted file mode 100644 index 52f202f..0000000 --- a/gcc/testsuite/gcc.dg/ubsan/pointer-counted-by-bounds-4.c +++ /dev/null @@ -1,42 +0,0 @@ -/* Test the attribute counted_by for pointer fields and its usage in bounds - sanitizer. when counted_by field is zero value. */ -/* { dg-do run } */ -/* { dg-options "-fsanitize=bounds" } */ - -#include <stdlib.h> - -struct annotated { - int b; - int *c __attribute__ ((counted_by (b))); -} *array_annotated; - -void __attribute__((__noinline__)) setup (int annotated_count) -{ - array_annotated - = (struct annotated *)malloc (sizeof (struct annotated)); - array_annotated->c = (int *)malloc (sizeof (int) * 10); - array_annotated->b = annotated_count; - - return; -} - -void __attribute__((__noinline__)) test (int annotated_index) -{ - array_annotated->c[annotated_index] = 2; -} - -void cleanup () -{ - free (array_annotated->c); - free (array_annotated); -} - -int main(int argc, char *argv[]) -{ - setup (0); - test (1); - cleanup (); - return 0; -} - -/* { dg-output "25:21: runtime error: index 1 out of bounds for type" } */ diff --git a/gcc/testsuite/gcc.dg/ubsan/pointer-counted-by-bounds-5.c b/gcc/testsuite/gcc.dg/ubsan/pointer-counted-by-bounds-5.c deleted file mode 100644 index 8ad7572..0000000 --- a/gcc/testsuite/gcc.dg/ubsan/pointer-counted-by-bounds-5.c +++ /dev/null @@ -1,40 +0,0 @@ -/* Test the attribute counted_by for pointer fields and its usage in - bounds sanitizer. */ -/* { dg-do run } */ -/* { dg-options "-fsanitize=bounds" } */ - -#include <stdlib.h> - -struct annotated { - int b; - int *c __attribute__ ((counted_by (b))); -} *p_array_annotated; - -void __attribute__((__noinline__)) setup (int annotated_count) -{ - p_array_annotated - = (struct annotated *)malloc (sizeof (struct annotated)); - p_array_annotated->c = (int *) malloc (annotated_count * sizeof (int)); - p_array_annotated->b = annotated_count; - - return; -} - -void cleanup () -{ - free (p_array_annotated->c); - free (p_array_annotated); -} - -int main(int argc, char *argv[]) -{ - int i; - setup (10); - for (i = 0; i < 11; i++) - p_array_annotated->c[i] = 2; // goes boom at i == 10 - cleanup (); - return 0; -} - - -/* { dg-output "34:25: runtime error: index 10 out of bounds for type" } */ diff --git a/gcc/testsuite/gcc.dg/ubsan/pointer-counted-by-bounds.c b/gcc/testsuite/gcc.dg/ubsan/pointer-counted-by-bounds.c deleted file mode 100644 index c5a1ac5..0000000 --- a/gcc/testsuite/gcc.dg/ubsan/pointer-counted-by-bounds.c +++ /dev/null @@ -1,46 +0,0 @@ -/* Test the attribute counted_by for pointer fields and its usage in - bounds sanitizer. */ -/* { dg-do run } */ -/* { dg-options "-fsanitize=bounds" } */ - -#include <stdlib.h> - -struct pointer_array { - int b; - int *c; -} *p_array; - -struct annotated { - int b; - int *c __attribute__ ((counted_by (b))); -} *p_array_annotated; - -void __attribute__((__noinline__)) setup (int normal_count, int annotated_count) -{ - p_array - = (struct pointer_array *) malloc (sizeof (struct pointer_array)); - p_array->c = (int *) malloc (normal_count * sizeof (int)); - p_array->b = normal_count; - - p_array_annotated - = (struct annotated *) malloc (sizeof (struct annotated)); - p_array_annotated->c = (int *) malloc (annotated_count * sizeof (int)); - p_array_annotated->b = annotated_count; - - return; -} - -void __attribute__((__noinline__)) test (int normal_index, int annotated_index) -{ - p_array->c[normal_index] = 1; - p_array_annotated->c[annotated_index] = 2; -} - -int main(int argc, char *argv[]) -{ - setup (10, 10); - test (10, 10); - return 0; -} - -/* { dg-output "36:23: runtime error: index 10 out of bounds for type" } */ diff --git a/gcc/testsuite/gcc.dg/vect/pr101145.c b/gcc/testsuite/gcc.dg/vect/pr101145.c index cd11c03..c055ae6 100644 --- a/gcc/testsuite/gcc.dg/vect/pr101145.c +++ b/gcc/testsuite/gcc.dg/vect/pr101145.c @@ -2,7 +2,7 @@ /* { dg-additional-options "-O3" } */ #include <limits.h> -unsigned __attribute__ ((noinline)) +unsigned __attribute__ ((noipa)) foo (int *__restrict__ a, int *__restrict__ b, unsigned l, unsigned n) { while (n < ++l) @@ -10,7 +10,7 @@ foo (int *__restrict__ a, int *__restrict__ b, unsigned l, unsigned n) return l; } -unsigned __attribute__ ((noinline)) +unsigned __attribute__ ((noipa)) foo_1 (int *__restrict__ a, int *__restrict__ b, unsigned l, unsigned) { while (UINT_MAX - 64 < ++l) @@ -18,7 +18,7 @@ foo_1 (int *__restrict__ a, int *__restrict__ b, unsigned l, unsigned) return l; } -unsigned __attribute__ ((noinline)) +unsigned __attribute__ ((noipa)) foo_2 (int *__restrict__ a, int *__restrict__ b, unsigned l, unsigned n) { l = UINT_MAX - 32; @@ -27,7 +27,7 @@ foo_2 (int *__restrict__ a, int *__restrict__ b, unsigned l, unsigned n) return l; } -unsigned __attribute__ ((noinline)) +unsigned __attribute__ ((noipa)) foo_3 (int *__restrict__ a, int *__restrict__ b, unsigned l, unsigned n) { while (n <= ++l) @@ -35,7 +35,7 @@ foo_3 (int *__restrict__ a, int *__restrict__ b, unsigned l, unsigned n) return l; } -unsigned __attribute__ ((noinline)) +unsigned __attribute__ ((noipa)) foo_4 (int *__restrict__ a, int *__restrict__ b, unsigned l, unsigned n) { // infininate while (0 <= ++l) @@ -43,7 +43,7 @@ foo_4 (int *__restrict__ a, int *__restrict__ b, unsigned l, unsigned n) return l; } -unsigned __attribute__ ((noinline)) +unsigned __attribute__ ((noipa)) foo_5 (int *__restrict__ a, int *__restrict__ b, unsigned l, unsigned n) { //no loop @@ -53,7 +53,7 @@ foo_5 (int *__restrict__ a, int *__restrict__ b, unsigned l, unsigned n) return l; } -unsigned __attribute__ ((noinline)) +unsigned __attribute__ ((noipa)) bar (int *__restrict__ a, int *__restrict__ b, unsigned l, unsigned n) { while (--l < n) @@ -61,7 +61,7 @@ bar (int *__restrict__ a, int *__restrict__ b, unsigned l, unsigned n) return l; } -unsigned __attribute__ ((noinline)) +unsigned __attribute__ ((noipa)) bar_1 (int *__restrict__ a, int *__restrict__ b, unsigned l, unsigned) { while (--l < 64) @@ -69,7 +69,7 @@ bar_1 (int *__restrict__ a, int *__restrict__ b, unsigned l, unsigned) return l; } -unsigned __attribute__ ((noinline)) +unsigned __attribute__ ((noipa)) bar_2 (int *__restrict__ a, int *__restrict__ b, unsigned l, unsigned n) { l = 32; diff --git a/gcc/testsuite/gcc.dg/vect/pr120817.c b/gcc/testsuite/gcc.dg/vect/pr120817.c new file mode 100644 index 0000000..199189a --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr120817.c @@ -0,0 +1,41 @@ +/* { dg-additional-options "-O1" } */ +/* { dg-require-effective-target aarch64_sve_hw { target aarch64*-*-* } } */ +/* { dg-additional-options "-march=armv8-a+sve -mtune=neoverse-n2" { target aarch64*-*-* } } */ + +#include "tree-vect.h" + +typedef struct { + int _M_current; +} __normal_iterator; + +typedef struct { + char _M_elems[5]; +} array_5; + +__normal_iterator __trans_tmp_1 = {-5}; + +__attribute__((noipa)) +array_5 copySourceIntoTarget() { + array_5 target; + char* target_it = target._M_elems; + + while (__trans_tmp_1._M_current != 0) { + *target_it = 1; + __trans_tmp_1._M_current++; + target_it++; + } + + return target; +} + +int main () +{ + check_vect (); + + array_5 res = copySourceIntoTarget(); + +#pragma GCC novector + for (int i = 0; i < 5; i++) + if (res._M_elems[i] != 1) + __builtin_abort (); +} diff --git a/gcc/testsuite/gcc.dg/vect/pr120922.c b/gcc/testsuite/gcc.dg/vect/pr120922.c new file mode 100644 index 0000000..1a7247a --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr120922.c @@ -0,0 +1,18 @@ +/* { dg-require-effective-target vect_int } */ +/* { dg-additional-options "-fsigned-char -fno-strict-aliasing -fwrapv" } */ +/* { dg-additional-options "-march=rv64gcv_zvl1024b -mrvv-vector-bits=zvl -mrvv-max-lmul=m8 -O3" { target { riscv_v } } } */ + +char g; +unsigned char h; +int i[9][6]; +int main() { + int k[5]; + if (g) + goto l; + for (; h <= 5; h++) + i[0][h] = *k; +l: + return 0; +} + +/* { dg-final { scan-tree-dump "loop vectorized" "vect" { target riscv_v } } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/popcnt13.c b/gcc/testsuite/gcc.target/aarch64/popcnt13.c new file mode 100644 index 0000000..2a30e98 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/popcnt13.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +#pragma GCC target "+nocssc+sve" + +/* +** h128: +** ldr q([0-9]+), \[x0\] +** ptrue p([0-9]+).b, vl16 +** cnt z([0-9]+).d, p\2/m, z\1.d +** addp d([0-9]+), v\3.2d +** fmov x0, d\4 +** ret +*/ + +unsigned h128 (const unsigned __int128 *a) { + return __builtin_popcountg (a[0]); +} + +/* There should be only one POPCOUNT. */ +/* { dg-final { scan-tree-dump-times "POPCOUNT " 1 "optimized" } } */ +/* { dg-final { scan-tree-dump-not " __builtin_popcount" "optimized" } } */ + diff --git a/gcc/testsuite/gcc.target/aarch64/popcnt9.c b/gcc/testsuite/gcc.target/aarch64/popcnt9.c index c778fc7..cfed8c5 100644 --- a/gcc/testsuite/gcc.target/aarch64/popcnt9.c +++ b/gcc/testsuite/gcc.target/aarch64/popcnt9.c @@ -3,7 +3,7 @@ /* { dg-final { check-function-bodies "**" "" } } */ /* PR target/113042 */ -#pragma GCC target "+nocssc" +#pragma GCC target "+nocssc+nosve" /* ** h128: diff --git a/gcc/testsuite/gcc.target/aarch64/pr118348_1.c b/gcc/testsuite/gcc.target/aarch64/pr118348_1.c index 75f6dad..2715dcb 100644 --- a/gcc/testsuite/gcc.target/aarch64/pr118348_1.c +++ b/gcc/testsuite/gcc.target/aarch64/pr118348_1.c @@ -1,4 +1,4 @@ -/* { dg-do run { target aarch64_sve128_hw } } */ +/* { dg-do run { target { aarch64_sve128_hw && fstack_protector } } } */ /* { dg-options "-O2 -fopenmp-simd -fno-trapping-math -msve-vector-bits=128 --param aarch64-autovec-preference=sve-only -fstack-protector-strong" } */ #pragma GCC target "+sve" diff --git a/gcc/testsuite/gcc.target/aarch64/pr118348_2.c b/gcc/testsuite/gcc.target/aarch64/pr118348_2.c index 2e20004..4ce8d20 100644 --- a/gcc/testsuite/gcc.target/aarch64/pr118348_2.c +++ b/gcc/testsuite/gcc.target/aarch64/pr118348_2.c @@ -1,4 +1,4 @@ -/* { dg-do run { target aarch64_sve256_hw } } */ +/* { dg-do run { target { aarch64_sve256_hw && fstack_protector } } } */ /* { dg-options "-O2 -fopenmp-simd -fno-trapping-math -msve-vector-bits=256 --param aarch64-autovec-preference=sve-only -fstack-protector-strong" } */ #include "pr118348_1.c" diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_2.c index 218a660..13ebb9f 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_2.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_2.c @@ -10,6 +10,6 @@ dupq (int x) return svdupq_s32 (x, 1, 2, 3); } -/* { dg-final { scan-assembler {\tindex\tz[0-9]+\.s, #3, #-1} } } */ +/* { dg-final { scan-assembler {\tindex\tz[0-9]+\.s, #0, #1\n} } } */ /* { dg-final { scan-assembler {\tins\tv[0-9]+\.s\[0\], w0\n} } } */ /* { dg-final { scan-assembler {\tdup\tz[0-9]+\.q, z[0-9]+\.q\[0\]\n} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_4.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_4.c index cbee6f2..13d27e2 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_4.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_4.c @@ -10,6 +10,6 @@ dupq (int x) return svdupq_s32 (0, 1, x, 3); } -/* { dg-final { scan-assembler {\tindex\tz[0-9]+\.s, #3, #-1} } } */ +/* { dg-final { scan-assembler {\tindex\tz[0-9]+\.s, #0, #1\n} } } */ /* { dg-final { scan-assembler {\tins\tv[0-9]+\.s\[2\], w0\n} } } */ /* { dg-final { scan-assembler {\tdup\tz[0-9]+\.q, z[0-9]+\.q\[0\]\n} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-binary.c b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-binary.c index a8fd4c8..4708d57 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-binary.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-binary.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include "../pfalse-binary_0.h" diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-binary_int_opt_n.c b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-binary_int_opt_n.c index 08cd6a0..4530b18 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-binary_int_opt_n.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-binary_int_opt_n.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include "../pfalse-binary_0.h" diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-binary_opt_n.c b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-binary_opt_n.c index f5c9cbf..3097459 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-binary_opt_n.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-binary_opt_n.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include "../pfalse-binary_0.h" diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-binary_opt_single_n.c b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-binary_opt_single_n.c index 91ae3c8..5e9d21c 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-binary_opt_single_n.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-binary_opt_single_n.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include "../pfalse-binary_0.h" diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-binary_rotate.c b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-binary_rotate.c index 12368ce..768a740 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-binary_rotate.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-binary_rotate.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include <arm_sve.h> diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-binary_uint64_opt_n.c b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-binary_uint64_opt_n.c index dd52a58..ce14abb 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-binary_uint64_opt_n.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-binary_uint64_opt_n.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include "../pfalse-binary_0.h" diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-binary_uint_opt_n.c b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-binary_uint_opt_n.c index e55ddfb..ceeb5ae 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-binary_uint_opt_n.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-binary_uint_opt_n.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include "../pfalse-binary_0.h" diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-binaryxn.c b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-binaryxn.c index 6796229..f8b6b82 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-binaryxn.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-binaryxn.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include <arm_sve.h> diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-clast.c b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-clast.c index 7f2ec4a..45f74ed 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-clast.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-clast.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include "../pfalse-binary_0.h" diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-compare_opt_n.c b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-compare_opt_n.c index d18427b..fc601a1 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-compare_opt_n.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-compare_opt_n.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include "../pfalse-binary_0.h" diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-compare_wide_opt_n.c b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-compare_wide_opt_n.c index 983ab5c..4959f1d 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-compare_wide_opt_n.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-compare_wide_opt_n.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include "../pfalse-binary_0.h" diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-count_pred.c b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-count_pred.c index de36b66..d8a8a81 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-count_pred.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-count_pred.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include "../pfalse-unary_0.h" diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-fold_left.c b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-fold_left.c index 333140d..6cf2683 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-fold_left.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-fold_left.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include "../pfalse-binary_0.h" diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-load.c b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-load.c index 93d6693..a32b636 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-load.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-load.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include <arm_sve.h> diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-load_ext.c b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-load_ext.c index c88686a..72e743b 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-load_ext.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-load_ext.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include <arm_sve.h> diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-load_ext_gather_index.c b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-load_ext_gather_index.c index 5f4b562fc..1178104 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-load_ext_gather_index.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-load_ext_gather_index.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include <arm_sve.h> diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-load_ext_gather_offset.c b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-load_ext_gather_offset.c index 0fe8ab3..ebd313a 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-load_ext_gather_offset.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-load_ext_gather_offset.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include <arm_sve.h> diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-load_gather_sv.c b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-load_gather_sv.c index 758f00f..d531987 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-load_gather_sv.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-load_gather_sv.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include <arm_sve.h> diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-load_gather_vs.c b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-load_gather_vs.c index f82471f..55c9cef 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-load_gather_vs.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-load_gather_vs.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include <arm_sve.h> diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-load_replicate.c b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-load_replicate.c index ba500b6..5532232 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-load_replicate.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-load_replicate.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2 -march=armv8.2-a+sve+f64mm" } */ +/* { dg-options "-O2 -march=armv8.2-a+sve+f64mm -funwind-tables" } */ #include <arm_sve.h> diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-prefetch.c b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-prefetch.c index 71894c4..78bdb0b 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-prefetch.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-prefetch.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include <arm_sve.h> diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-prefetch_gather_index.c b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-prefetch_gather_index.c index 1b7cc42..e219007 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-prefetch_gather_index.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-prefetch_gather_index.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include <arm_sve.h> diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-prefetch_gather_offset.c b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-prefetch_gather_offset.c index 7f4ff2d..98897e9 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-prefetch_gather_offset.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-prefetch_gather_offset.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include <arm_sve.h> diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-ptest.c b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-ptest.c index 0a587fc..c6fe6b9 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-ptest.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-ptest.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include "../pfalse-unary_0.h" diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-rdffr.c b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-rdffr.c index d795f8e..7e2c1b9 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-rdffr.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-rdffr.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include <arm_sve.h> diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-reduction.c b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-reduction.c index 42b37ae..f7f75f6 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-reduction.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-reduction.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* { dg-options "-O2 -fdump-tree-optimized -funwind-tables" } */ #include "../pfalse-unary_0.h" diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-reduction_wide.c b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-reduction_wide.c index bd9a980..54b6197 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-reduction_wide.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-reduction_wide.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include "../pfalse-unary_0.h" diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-shift_right_imm.c b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-shift_right_imm.c index 62a0755..e8b8a55 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-shift_right_imm.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-shift_right_imm.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include <arm_sve.h> diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-store.c b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-store.c index 751e60e..1539f58 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-store.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-store.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include <arm_sve.h> diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-store_scatter_index.c b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-store_scatter_index.c index 44792d3..21c8f6b 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-store_scatter_index.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-store_scatter_index.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include <arm_sve.h> diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-store_scatter_offset.c b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-store_scatter_offset.c index f3820e0..a908289 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-store_scatter_offset.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-store_scatter_offset.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include <arm_sve.h> diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-storexn.c b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-storexn.c index e49266d..12b5e14 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-storexn.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-storexn.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include <arm_sve.h> diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-ternary_opt_n.c b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-ternary_opt_n.c index acdd141..89873fc 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-ternary_opt_n.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-ternary_opt_n.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include <arm_sve.h> diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-ternary_rotate.c b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-ternary_rotate.c index 7698045..c6d2cfb 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-ternary_rotate.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-ternary_rotate.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include <arm_sve.h> diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-unary.c b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-unary.c index 037376b..8a3b3e0 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-unary.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-unary.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include "../pfalse-unary_0.h" diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-unary_convert_narrowt.c b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-unary_convert_narrowt.c index 1287a70..04bc049 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-unary_convert_narrowt.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-unary_convert_narrowt.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2 -march=armv8.2-a+sve+bf16" } */ +/* { dg-options "-O2 -march=armv8.2-a+sve+bf16 -funwind-tables" } */ #include <arm_sve.h> diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-unary_convertxn.c b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-unary_convertxn.c index f519266..f39d2c5 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-unary_convertxn.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-unary_convertxn.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2 -march=armv8.2-a+sve+bf16" } */ +/* { dg-options "-O2 -march=armv8.2-a+sve+bf16 -funwind-tables" } */ #include <arm_sve.h> diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-unary_n.c b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-unary_n.c index fabde3e..4403e50 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-unary_n.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-unary_n.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include <arm_sve.h> diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-unary_pred.c b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-unary_pred.c index 46c9592..f06b067 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-unary_pred.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-unary_pred.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include "../pfalse-unary_0.h" diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-unary_to_uint.c b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-unary_to_uint.c index b820bde..a851c4a 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-unary_to_uint.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-unary_to_uint.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include "../pfalse-unary_0.h" diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-unaryxn.c b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-unaryxn.c index 1e99b7f..dde812b 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pfalse-unaryxn.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pfalse-unaryxn.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include "../pfalse-unary_0.h" diff --git a/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fcm_1.c b/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fcm_1.c new file mode 100644 index 0000000..bf9c127 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fcm_1.c @@ -0,0 +1,602 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -moverride=sve_width=2048 --param=aarch64-autovec-preference=sve-only -fno-schedule-insns -fno-schedule-insns2" } */ + +#include <stdint.h> + +#define UNLT(A, B) (!__builtin_isgreaterequal (A, B)) +#define UNLE(A, B) (!__builtin_isgreater (A, B)) +#define UNGT(A, B) (!__builtin_islessequal (A, B)) +#define UNGE(A, B) (!__builtin_isless (A, B)) +#define UNEQ(A, B) (!__builtin_islessgreater (A, B)) + +#define EQ(A, B) ((A) == (B)) +#define NE(A, B) ((A) != (B)) +#define LE(A, B) ((A) <= (B)) +#define LT(A, B) ((A) < (B)) +#define GE(A, B) ((A) >= (B)) +#define GT(A, B) ((A) > (B)) +#define ORDERED(A, B) (!__builtin_isunordered (A, B)) +#define UNORDERED(A, B) (__builtin_isunordered (A, B)) + +#define b_i b[i] + +#define TEST_FCM(TYPE0, TYPE1, CMP, RHS, COUNT) \ + void \ + f_##TYPE0##_##TYPE1##_##CMP##_##RHS (TYPE0 *__restrict out, \ + TYPE1 *__restrict a, \ + TYPE1 *__restrict b) \ + { \ + for (unsigned int i = 0; i < COUNT; i++) \ + out[i] = CMP (a[i], RHS) ? 3 : out[i]; \ + } + +#define TEST_CC_REG(CMP) \ + TEST_FCM (uint64_t, float, CMP, b_i, 32) \ + TEST_FCM (uint32_t, _Float16, CMP, b_i, 64) \ + TEST_FCM (uint64_t, _Float16, CMP, b_i, 32) + +#define TEST_CC_ALL(CMP) \ + TEST_CC_REG (CMP) \ + TEST_FCM (uint64_t, float, CMP, 0, 32) \ + TEST_FCM (uint32_t, _Float16, CMP, 0, 64) \ + TEST_FCM (uint64_t, _Float16, CMP, 0, 32) + + +/* +** f_uint64_t_float_UNLT_b_i: +** ... +** ptrue (p[0-9]+)\.d, all +** ... +** fcmuo (p[0-9]+)\.s, \1/z, z[0-9]+\.s, z[0-9]+\.s +** not (p[0-9]+)\.b, \1/z, \2\.b +** fcmge p[0-9]+\.s, \3/z, z[0-9]+\.s, z[0-9]+\.s +** ... +*/ + +/* +** f_uint32_t__Float16_UNLT_b_i: +** ... +** ptrue (p[0-9]+)\.s, all +** ... +** fcmuo (p[0-9]+)\.h, \1/z, z[0-9]+\.h, z[0-9]+\.h +** not (p[0-9]+)\.b, \1/z, \2\.b +** fcmge p[0-9]+\.h, \3/z, z[0-9]+\.h, z[0-9]+\.h +** ... +*/ + +/* +** f_uint64_t__Float16_UNLT_b_i: +** ... +** ptrue (p[0-9]+)\.d, all +** ... +** fcmuo (p[0-9]+)\.h, \1/z, z[0-9]+\.h, z[0-9]+\.h +** not (p[0-9]+)\.b, \1/z, \2\.b +** fcmge p[0-9]+\.h, \3/z, z[0-9]+\.h, z[0-9]+\.h +** ... +*/ +TEST_CC_REG (UNLT) + +/* +** f_uint64_t_float_UNLE_b_i: +** ... +** ptrue (p[0-9]+)\.d, all +** ... +** fcmuo (p[0-9]+)\.s, \1/z, z[0-9]+\.s, z[0-9]+\.s +** not (p[0-9]+)\.b, \1/z, \2\.b +** fcmgt p[0-9]+\.s, \3/z, z[0-9]+\.s, z[0-9]+\.s +** ... +*/ + +/* +** f_uint32_t__Float16_UNLE_b_i: +** ... +** ptrue (p[0-9]+)\.s, all +** ... +** fcmuo (p[0-9]+)\.h, \1/z, z[0-9]+\.h, z[0-9]+\.h +** not (p[0-9]+)\.b, \1/z, \2\.b +** fcmgt p[0-9]+\.h, \3/z, z[0-9]+\.h, z[0-9]+\.h +** ... +*/ + +/* +** f_uint64_t__Float16_UNLE_b_i: +** ... +** ptrue (p[0-9]+)\.d, all +** ... +** fcmuo (p[0-9]+)\.h, \1/z, z[0-9]+\.h, z[0-9]+\.h +** not (p[0-9]+)\.b, \1/z, \2\.b +** fcmgt p[0-9]+\.h, \3/z, z[0-9]+\.h, z[0-9]+\.h +** ... +*/ +TEST_CC_REG (UNLE) + +/* +** f_uint64_t_float_UNGT_b_i: +** ... +** ptrue (p[0-9]+)\.d, all +** ... +** fcmuo (p[0-9]+)\.s, \1/z, z[0-9]+\.s, z[0-9]+\.s +** not (p[0-9]+)\.b, \1/z, \2\.b +** fcmle p[0-9]+\.s, \3/z, z[0-9]+\.s, z[0-9]+\.s +** ... +*/ + +/* +** f_uint32_t__Float16_UNGT_b_i: +** ... +** ptrue (p[0-9]+)\.s, all +** ... +** fcmuo (p[0-9]+)\.h, \1/z, z[0-9]+\.h, z[0-9]+\.h +** not (p[0-9]+)\.b, \1/z, \2\.b +** fcmle p[0-9]+\.h, \3/z, z[0-9]+\.h, z[0-9]+\.h +** ... +*/ + +/* +** f_uint64_t__Float16_UNGT_b_i: +** ... +** ptrue (p[0-9]+)\.d, all +** ... +** fcmuo (p[0-9]+)\.h, \1/z, z[0-9]+\.h, z[0-9]+\.h +** not (p[0-9]+)\.b, \1/z, \2\.b +** fcmle p[0-9]+\.h, \3/z, z[0-9]+\.h, z[0-9]+\.h +** ... +*/ +TEST_CC_REG (UNGT) + +/* +** f_uint64_t_float_UNGE_b_i: +** ... +** ptrue (p[0-9]+)\.d, all +** ... +** fcmuo (p[0-9]+)\.s, \1/z, z[0-9]+\.s, z[0-9]+\.s +** not (p[0-9]+)\.b, \1/z, \2\.b +** fcmlt p[0-9]+\.s, \3/z, z[0-9]+\.s, z[0-9]+\.s +** ... +*/ + +/* +** f_uint32_t__Float16_UNGE_b_i: +** ... +** ptrue (p[0-9]+)\.s, all +** ... +** fcmuo (p[0-9]+)\.h, \1/z, z[0-9]+\.h, z[0-9]+\.h +** not (p[0-9]+)\.b, \1/z, \2\.b +** fcmlt p[0-9]+\.h, \3/z, z[0-9]+\.h, z[0-9]+\.h +** ... +*/ + +/* +** f_uint64_t__Float16_UNGE_b_i: +** ... +** ptrue (p[0-9]+)\.d, all +** ... +** fcmuo (p[0-9]+)\.h, \1/z, z[0-9]+\.h, z[0-9]+\.h +** not (p[0-9]+)\.b, \1/z, \2\.b +** fcmlt p[0-9]+\.h, \3/z, z[0-9]+\.h, z[0-9]+\.h +** ... +*/ +TEST_CC_REG (UNGE) + +/* +** f_uint64_t_float_UNEQ_b_i: +** ... +** ptrue (p[0-9]+)\.d, all +** ... +** fcmuo (p[0-9]+)\.s, \1/z, z[0-9]+\.s, z[0-9]+\.s +** not (p[0-9]+)\.b, \1/z, \2\.b +** fcmne p[0-9]+\.s, \3/z, z[0-9]+\.s, z[0-9]+\.s +** ... +*/ + +/* +** f_uint32_t__Float16_UNEQ_b_i: +** ... +** ptrue (p[0-9]+)\.s, all +** ... +** fcmuo (p[0-9]+)\.h, \1/z, z[0-9]+\.h, z[0-9]+\.h +** not (p[0-9]+)\.b, \1/z, \2\.b +** fcmne p[0-9]+\.h, \3/z, z[0-9]+\.h, z[0-9]+\.h +** ... +*/ + +/* +** f_uint64_t__Float16_UNEQ_b_i: +** ... +** ptrue (p[0-9]+)\.d, all +** ... +** fcmuo (p[0-9]+)\.h, \1/z, z[0-9]+\.h, z[0-9]+\.h +** not (p[0-9]+)\.b, \1/z, \2\.b +** fcmne p[0-9]+\.h, \3/z, z[0-9]+\.h, z[0-9]+\.h +** ... +*/ +TEST_CC_REG (UNEQ) + +/* +** f_uint64_t_float_EQ_b_i: +** ... +** ptrue (p[0-9]+)\.d, all +** ... +** fcmeq p[0-9]+\.s, \1/z, z[0-9]+\.s, z[0-9]+\.s +** ... +*/ + +/* +** f_uint32_t__Float16_EQ_b_i: +** ... +** ptrue (p[0-9]+)\.s, all +** ... +** fcmeq p[0-9]+\.h, \1/z, z[0-9]+\.h, z[0-9]+\.h +** ... +*/ + +/* +** f_uint64_t__Float16_EQ_b_i: +** ... +** ptrue (p[0-9]+)\.d, all +** ... +** fcmeq p[0-9]+\.h, \1/z, z[0-9]+\.h, z[0-9]+\.h +** ... +*/ + +/* +** f_uint64_t_float_EQ_0: +** ... +** ptrue (p[0-9]+)\.d, all +** ... +** fcmeq p[0-9]+\.s, \1/z, z[0-9]+\.s, #0.0 +** ... +*/ + +/* +** f_uint32_t__Float16_EQ_0: +** ... +** ptrue (p[0-9]+)\.s, all +** ... +** fcmeq p[0-9]+\.h, \1/z, z[0-9]+\.h, #0.0 +** ... +*/ + +/* +** f_uint64_t__Float16_EQ_0: +** ... +** ptrue (p[0-9]+)\.d, all +** ... +** fcmeq p[0-9]+\.h, \1/z, z[0-9]+\.h, #0.0 +** ... +*/ +TEST_CC_ALL (EQ) + +/* +** f_uint64_t_float_NE_b_i: +** ... +** ptrue (p[0-9]+)\.d, all +** ... +** fcmne p[0-9]+\.s, \1/z, z[0-9]+\.s, z[0-9]+\.s +** ... +*/ + +/* +** f_uint32_t__Float16_NE_b_i: +** ... +** ptrue (p[0-9]+)\.s, all +** ... +** fcmne p[0-9]+\.h, \1/z, z[0-9]+\.h, z[0-9]+\.h +** ... +*/ + +/* +** f_uint64_t__Float16_NE_b_i: +** ... +** ptrue (p[0-9]+)\.d, all +** ... +** fcmne p[0-9]+\.h, \1/z, z[0-9]+\.h, z[0-9]+\.h +** ... +*/ + +/* +** f_uint64_t_float_NE_0: +** ... +** ptrue (p[0-9]+)\.d, all +** ... +** fcmne p[0-9]+\.s, \1/z, z[0-9]+\.s, #0.0 +** ... +*/ + +/* +** f_uint32_t__Float16_NE_0: +** ... +** ptrue (p[0-9]+)\.s, all +** ... +** fcmne p[0-9]+\.h, \1/z, z[0-9]+\.h, #0.0 +** ... +*/ + +/* +** f_uint64_t__Float16_NE_0: +** ... +** ptrue (p[0-9]+)\.d, all +** ... +** fcmne p[0-9]+\.h, \1/z, z[0-9]+\.h, #0.0 +** ... +*/ +TEST_CC_ALL (NE) + +/* +** f_uint64_t_float_LE_b_i: +** ... +** ptrue (p[0-9]+)\.d, all +** ... +** fcmle p[0-9]+\.s, \1/z, z[0-9]+\.s, z[0-9]+\.s +** ... +*/ + +/* +** f_uint32_t__Float16_LE_b_i: +** ... +** ptrue (p[0-9]+)\.s, all +** ... +** fcmle p[0-9]+\.h, \1/z, z[0-9]+\.h, z[0-9]+\.h +** ... +*/ + +/* +** f_uint64_t__Float16_LE_b_i: +** ... +** ptrue (p[0-9]+)\.d, all +** ... +** fcmle p[0-9]+\.h, \1/z, z[0-9]+\.h, z[0-9]+\.h +** ... +*/ + +/* +** f_uint64_t_float_LE_0: +** ... +** ptrue (p[0-9]+)\.d, all +** ... +** fcmle p[0-9]+\.s, \1/z, z[0-9]+\.s, #0.0 +** ... +*/ + +/* +** f_uint32_t__Float16_LE_0: +** ... +** ptrue (p[0-9]+)\.s, all +** ... +** fcmle p[0-9]+\.h, \1/z, z[0-9]+\.h, #0.0 +** ... +*/ + +/* +** f_uint64_t__Float16_LE_0: +** ... +** ptrue (p[0-9]+)\.d, all +** ... +** fcmle p[0-9]+\.h, \1/z, z[0-9]+\.h, #0.0 +** ... +*/ +TEST_CC_ALL (LE) + +/* +** f_uint64_t_float_LT_b_i: +** ... +** ptrue (p[0-9]+)\.d, all +** ... +** fcmlt p[0-9]+\.s, \1/z, z[0-9]+\.s, z[0-9]+\.s +** ... +*/ + +/* +** f_uint32_t__Float16_LT_b_i: +** ... +** ptrue (p[0-9]+)\.s, all +** ... +** fcmlt p[0-9]+\.h, \1/z, z[0-9]+\.h, z[0-9]+\.h +** ... +*/ + +/* +** f_uint64_t__Float16_LT_b_i: +** ... +** ptrue (p[0-9]+)\.d, all +** ... +** fcmlt p[0-9]+\.h, \1/z, z[0-9]+\.h, z[0-9]+\.h +** ... +*/ + +/* +** f_uint64_t_float_LT_0: +** ... +** ptrue (p[0-9]+)\.d, all +** ... +** fcmlt p[0-9]+\.s, \1/z, z[0-9]+\.s, #0.0 +** ... +*/ + +/* +** f_uint32_t__Float16_LT_0: +** ... +** ptrue (p[0-9]+)\.s, all +** ... +** fcmlt p[0-9]+\.h, \1/z, z[0-9]+\.h, #0.0 +** ... +*/ + +/* +** f_uint64_t__Float16_LT_0: +** ... +** ptrue (p[0-9]+)\.d, all +** ... +** fcmlt p[0-9]+\.h, \1/z, z[0-9]+\.h, #0.0 +** ... +*/ +TEST_CC_ALL (LT) + +/* +** f_uint64_t_float_GE_b_i: +** ... +** ptrue (p[0-9]+)\.d, all +** ... +** fcmge p[0-9]+\.s, \1/z, z[0-9]+\.s, z[0-9]+\.s +** ... +*/ + +/* +** f_uint32_t__Float16_GE_b_i: +** ... +** ptrue (p[0-9]+)\.s, all +** ... +** fcmge p[0-9]+\.h, \1/z, z[0-9]+\.h, z[0-9]+\.h +** ... +*/ + +/* +** f_uint64_t__Float16_GE_b_i: +** ... +** ptrue (p[0-9]+)\.d, all +** ... +** fcmge p[0-9]+\.h, \1/z, z[0-9]+\.h, z[0-9]+\.h +** ... +*/ + +/* +** f_uint64_t_float_GE_0: +** ... +** ptrue (p[0-9]+)\.d, all +** ... +** fcmge p[0-9]+\.s, \1/z, z[0-9]+\.s, #0.0 +** ... +*/ + +/* +** f_uint32_t__Float16_GE_0: +** ... +** ptrue (p[0-9]+)\.s, all +** ... +** fcmge p[0-9]+\.h, \1/z, z[0-9]+\.h, #0.0 +** ... +*/ + +/* +** f_uint64_t__Float16_GE_0: +** ... +** ptrue (p[0-9]+)\.d, all +** ... +** fcmge p[0-9]+\.h, \1/z, z[0-9]+\.h, #0.0 +** ... +*/ +TEST_CC_ALL (GE) + +/* +** f_uint64_t_float_GT_b_i: +** ... +** ptrue (p[0-9]+)\.d, all +** ... +** fcmgt p[0-9]+\.s, \1/z, z[0-9]+\.s, z[0-9]+\.s +** ... +*/ + +/* +** f_uint32_t__Float16_GT_b_i: +** ... +** ptrue (p[0-9]+)\.s, all +** ... +** fcmgt p[0-9]+\.h, \1/z, z[0-9]+\.h, z[0-9]+\.h +** ... +*/ + +/* +** f_uint64_t__Float16_GT_b_i: +** ... +** ptrue (p[0-9]+)\.d, all +** ... +** fcmgt p[0-9]+\.h, \1/z, z[0-9]+\.h, z[0-9]+\.h +** ... +*/ + +/* +** f_uint64_t_float_GT_0: +** ... +** ptrue (p[0-9]+)\.d, all +** ... +** fcmgt p[0-9]+\.s, \1/z, z[0-9]+\.s, #0.0 +** ... +*/ + +/* +** f_uint32_t__Float16_GT_0: +** ... +** ptrue (p[0-9]+)\.s, all +** ... +** fcmgt p[0-9]+\.h, \1/z, z[0-9]+\.h, #0.0 +** ... +*/ + +/* +** f_uint64_t__Float16_GT_0: +** ... +** ptrue (p[0-9]+)\.d, all +** ... +** fcmgt p[0-9]+\.h, \1/z, z[0-9]+\.h, #0.0 +** ... +*/ +TEST_CC_ALL (GT) + +/* +** f_uint64_t_float_ORDERED_b_i: +** ... +** ptrue (p[0-9]+)\.d, all +** ... +** fcmuo p[0-9]+\.s, \1/z, z[0-9]+\.s, z[0-9]+\.s +** ... +*/ + +/* +** f_uint32_t__Float16_ORDERED_b_i: +** ... +** ptrue (p[0-9]+)\.s, all +** ... +** fcmuo p[0-9]+\.h, \1/z, z[0-9]+\.h, z[0-9]+\.h +** ... +*/ + +/* +** f_uint64_t__Float16_ORDERED_b_i: +** ... +** ptrue (p[0-9]+)\.d, all +** ... +** fcmuo p[0-9]+\.h, \1/z, z[0-9]+\.h, z[0-9]+\.h +** ... +*/ +TEST_CC_REG (ORDERED) + +/* +** f_uint64_t_float_UNORDERED_b_i: +** ... +** ptrue (p[0-9]+)\.d, all +** ... +** fcmuo p[0-9]+\.s, \1/z, z[0-9]+\.s, z[0-9]+\.s +** ... +*/ + +/* +** f_uint32_t__Float16_UNORDERED_b_i: +** ... +** ptrue (p[0-9]+)\.s, all +** ... +** fcmuo p[0-9]+\.h, \1/z, z[0-9]+\.h, z[0-9]+\.h +** ... +*/ + +/* +** f_uint64_t__Float16_UNORDERED_b_i: +** ... +** ptrue (p[0-9]+)\.d, all +** ... +** fcmuo p[0-9]+\.h, \1/z, z[0-9]+\.h, z[0-9]+\.h +** ... +*/ +TEST_CC_REG (UNORDERED) + + +/* { dg-final { check-function-bodies "**" "" ""} } */ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fcm_2.c b/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fcm_2.c new file mode 100644 index 0000000..ab210da --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/unpacked_fcm_2.c @@ -0,0 +1,50 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -moverride=sve_width=2048 --param=aarch64-autovec-preference=sve-only -fno-trapping-math" } */ + +#include "unpacked_fcm_1.c" + +/* { dg-final { scan-assembler-not {\tptrue\tp[0-7]\.s} } } */ +/* { dg-final { scan-assembler-not {\tptrue\tp[0-7]\.d} } } */ + +/* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.d} 32 } } */ +/* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.s} 32 } } */ +/* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.d} 32 } } */ + +/* { dg-final { scan-assembler-times {\tfcmeq\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, z[0-9]+\.s\n} 2 } } */ +/* { dg-final { scan-assembler-times {\tfcmeq\tp[0-9]+\.h, p[0-7]/z, z[0-9]+\.h, z[0-9]+\.h\n} 4 } } */ + +/* { dg-final { scan-assembler-times {\tfcmeq\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, #0.0\n} 1 } } */ +/* { dg-final { scan-assembler-times {\tfcmeq\tp[0-9]+\.h, p[0-7]/z, z[0-9]+\.h, #0.0\n} 2 } } */ + +/* { dg-final { scan-assembler-times {\tfcmne\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, z[0-9]+\.s\n} 1 } } */ +/* { dg-final { scan-assembler-times {\tfcmne\tp[0-9]+\.h, p[0-7]/z, z[0-9]+\.h, z[0-9]+\.h\n} 2 } } */ + +/* { dg-final { scan-assembler-times {\tfcmne\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, #0.0\n} 1 } } */ +/* { dg-final { scan-assembler-times {\tfcmne\tp[0-9]+\.h, p[0-7]/z, z[0-9]+\.h, #0.0\n} 2 } } */ + +/* { dg-final { scan-assembler-times {\tfcmle\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, z[0-9]+\.s\n} 2 } } */ +/* { dg-final { scan-assembler-times {\tfcmle\tp[0-9]+\.h, p[0-7]/z, z[0-9]+\.h, z[0-9]+\.h\n} 4 } } */ + +/* { dg-final { scan-assembler-times {\tfcmle\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, #0.0\n} 1 } } */ +/* { dg-final { scan-assembler-times {\tfcmle\tp[0-9]+\.h, p[0-7]/z, z[0-9]+\.h, #0.0\n} 2 } } */ + +/* { dg-final { scan-assembler-times {\tfcmlt\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, z[0-9]+\.s\n} 2 } } */ +/* { dg-final { scan-assembler-times {\tfcmlt\tp[0-9]+\.h, p[0-7]/z, z[0-9]+\.h, z[0-9]+\.h\n} 4 } } */ + +/* { dg-final { scan-assembler-times {\tfcmlt\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, #0.0\n} 1 } } */ +/* { dg-final { scan-assembler-times {\tfcmlt\tp[0-9]+\.h, p[0-7]/z, z[0-9]+\.h, #0.0\n} 2 } } */ + +/* { dg-final { scan-assembler-times {\tfcmge\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, z[0-9]+\.s\n} 2 } } */ +/* { dg-final { scan-assembler-times {\tfcmge\tp[0-9]+\.h, p[0-7]/z, z[0-9]+\.h, z[0-9]+\.h\n} 4 } } */ + +/* { dg-final { scan-assembler-times {\tfcmge\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, #0.0\n} 1 } } */ +/* { dg-final { scan-assembler-times {\tfcmge\tp[0-9]+\.h, p[0-7]/z, z[0-9]+\.h, #0.0\n} 2 } } */ + +/* { dg-final { scan-assembler-times {\tfcmgt\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, z[0-9]+\.s\n} 2 } } */ +/* { dg-final { scan-assembler-times {\tfcmgt\tp[0-9]+\.h, p[0-7]/z, z[0-9]+\.h, z[0-9]+\.h\n} 4 } } */ + +/* { dg-final { scan-assembler-times {\tfcmgt\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, #0.0\n} 1 } } */ +/* { dg-final { scan-assembler-times {\tfcmgt\tp[0-9]+\.h, p[0-7]/z, z[0-9]+\.h, #0.0\n} 2 } } */ + +/* { dg-final { scan-assembler-times {\tfcmuo\tp[0-9]+\.s, p[0-7]/z, z[0-9]+\.s, z[0-9]+\.s\n} 3 } } */ +/* { dg-final { scan-assembler-times {\tfcmuo\tp[0-9]+\.h, p[0-7]/z, z[0-9]+\.h, z[0-9]+\.h\n} 6 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/vec_init_3.c b/gcc/testsuite/gcc.target/aarch64/sve/vec_init_3.c index 25910db..5100a87 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/vec_init_3.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/vec_init_3.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -mlittle-endian" } */ /* { dg-final { check-function-bodies "**" "" "" } } */ typedef char v16qi __attribute__ ((vector_size (16))); @@ -8,7 +8,7 @@ typedef short v8hi __attribute__ ((vector_size (16))); typedef short v4hi __attribute__ ((vector_size (8))); typedef int v4si __attribute__ ((vector_size (16))); typedef int v2si __attribute__ ((vector_size (8))); -typedef long v2di __attribute__ ((vector_size (16))); +typedef long long v2di __attribute__ ((vector_size (16))); /* ** f_v16qi: @@ -97,3 +97,113 @@ g_v4si (void) { return (v4si){ 3, -1, -5, -9 }; } + +/* +** g_min_1: +** index z0\.s, #-16, #1 +** ret +*/ +v4si +g_min_1 (void) +{ + return (v4si){ -16, -15, -14, -13 }; +} + +/* +** g_min_min: +** index z0\.s, #-16, #-16 +** ret +*/ +v4si +g_min_min (void) +{ + return (v4si){ -16, -32, -48, -64 }; +} + +/* +** g_min_max: +** index z0\.s, #-16, #15 +** ret +*/ +v4si +g_min_max (void) +{ + return (v4si){ -16, -1, 14, 29 }; +} + +/* +** g_max_1: +** index z0\.s, #15, #1 +** ret +*/ +v4si +g_max_1 (void) +{ + return (v4si){ 15, 16, 17, 18 }; +} + +/* +** g_max_min: +** index z0\.s, #15, #-16 +** ret +*/ +v4si +g_max_min (void) +{ + return (v4si){ 15, -1, -17, -33 }; +} + +/* +** g_max_max: +** index z0\.s, #15, #15 +** ret +*/ +v4si +g_max_max (void) +{ + return (v4si){ 15, 30, 45, 60 }; +} + +/* +** g_ob_1: +** ((?!index).)* +** ret +*/ +v4si +g_ob_1 (void) +{ + return (v4si){ -17, -16, -15, -14 }; +} + +/* +** g_ob_2: +** ((?!index).)* +** ret +*/ +v4si +g_ob_2 (void) +{ + return (v4si){ 16, 17, 18, 19 }; +} + +/* +** g_ob_3: +** ((?!index).)* +** ret +*/ +v4si +g_ob_3 (void) +{ + return (v4si){ 0, -17, -34, -51 }; +} + +/* +** g_ob_4: +** ((?!index).)* +** ret +*/ +v4si +g_ob_4 (void) +{ + return (v4si){ 0, 16, 32, 48 }; +} diff --git a/gcc/testsuite/gcc.target/aarch64/sve/vec_init_4.c b/gcc/testsuite/gcc.target/aarch64/sve/vec_init_4.c new file mode 100644 index 0000000..0681d95 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/vec_init_4.c @@ -0,0 +1,209 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mbig-endian" } */ +/* { dg-final { check-function-bodies "**" "" "" } } */ + +typedef char v16qi __attribute__ ((vector_size (16))); +typedef char v8qi __attribute__ ((vector_size (8))); +typedef short v8hi __attribute__ ((vector_size (16))); +typedef short v4hi __attribute__ ((vector_size (8))); +typedef int v4si __attribute__ ((vector_size (16))); +typedef int v2si __attribute__ ((vector_size (8))); +typedef long long v2di __attribute__ ((vector_size (16))); + +/* +** f_v16qi: +** index z0\.b, #15, #-1 +** ret +*/ +v16qi +f_v16qi (void) +{ + return (v16qi){ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; +} + +/* +** f_v8qi: +** index z0\.b, #7, #-1 +** ret +*/ +v8qi +f_v8qi (void) +{ + return (v8qi){ 0, 1, 2, 3, 4, 5, 6, 7 }; +} + +/* +** f_v8hi: +** index z0\.h, #7, #-1 +** ret +*/ +v8hi +f_v8hi (void) +{ + return (v8hi){ 0, 1, 2, 3, 4, 5, 6, 7 }; +} + +/* +** f_v4hi: +** index z0\.h, #3, #-1 +** ret +*/ +v4hi +f_v4hi (void) +{ + return (v4hi){ 0, 1, 2, 3 }; +} + +/* +** f_v4si: +** index z0\.s, #3, #-1 +** ret +*/ +v4si +f_v4si (void) +{ + return (v4si){ 0, 1, 2, 3 }; +} + +/* +** f_v2si: +** index z0\.s, #1, #-1 +** ret +*/ +v2si +f_v2si (void) +{ + return (v2si){ 0, 1 }; +} + +/* +** f_v2di: +** index z0\.d, #1, #-1 +** ret +*/ +v2di +f_v2di (void) +{ + return (v2di){ 0, 1 }; +} + +/* +** g_v4si: +** index z0\.s, #-9, #4 +** ret +*/ +v4si +g_v4si (void) +{ + return (v4si){ 3, -1, -5, -9 }; +} + +/* +** g_min_1: +** index z0\.s, #-16, #1 +** ret +*/ +v4si +g_min_1 (void) +{ + return (v4si){ -13, -14, -15, -16 }; +} + +/* +** g_min_min: +** index z0\.s, #-16, #-16 +** ret +*/ +v4si +g_min_min (void) +{ + return (v4si){ -64, -48, -32, -16 }; +} + +/* +** g_min_max: +** index z0\.s, #-16, #15 +** ret +*/ +v4si +g_min_max (void) +{ + return (v4si){ 29, 14, -1, -16 }; +} + +/* +** g_max_1: +** index z0\.s, #15, #1 +** ret +*/ +v4si +g_max_1 (void) +{ + return (v4si){ 18, 17, 16, 15 }; +} + +/* +** g_max_min: +** index z0\.s, #15, #-16 +** ret +*/ +v4si +g_max_min (void) +{ + return (v4si){ -33, -17, -1, 15 }; +} + +/* +** g_max_max: +** index z0\.s, #15, #15 +** ret +*/ +v4si +g_max_max (void) +{ + return (v4si){ 60, 45, 30, 15 }; +} + +/* +** g_ob_1: +** ((?!index).)* +** ret +*/ +v4si +g_ob_1 (void) +{ + return (v4si){ -14, -15, -16, -17 }; +} + +/* +** g_ob_2: +** ((?!index).)* +** ret +*/ +v4si +g_ob_2 (void) +{ + return (v4si){ 19, 18, 17, 16 }; +} + +/* +** g_ob_3: +** ((?!index).)* +** ret +*/ +v4si +g_ob_3 (void) +{ + return (v4si){ -51, -34, -17, 0 }; +} + +/* +** g_ob_4: +** ((?!index).)* +** ret +*/ +v4si +g_ob_4 (void) +{ + return (v4si){ 48, 32, 16, 0 }; +} diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/dupq_1.c b/gcc/testsuite/gcc.target/aarch64/sve2/dupq_1.c index 5472e30..9db60b1 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve2/dupq_1.c +++ b/gcc/testsuite/gcc.target/aarch64/sve2/dupq_1.c @@ -1,5 +1,5 @@ /* { dg-options "-O2 -msve-vector-bits=256" } */ -/* { dg-final { check-function-bodies "**" "" "" { target { le } } } } */ +/* { dg-final { check-function-bodies "**" "" "" } } */ #include <arm_sve.h> @@ -15,7 +15,7 @@ typedef svuint64_t fixed_uint64_t __attribute__((arm_sve_vector_bits(256))); ** trn1 z0\.d, z0\.d, z0\.d ** ret */ -fixed_uint64_t +[[gnu::noipa]] fixed_uint64_t f1 (fixed_uint64_t z0) { return __builtin_shufflevector (z0, z0, 0, 0, 2, 2); @@ -26,7 +26,7 @@ f1 (fixed_uint64_t z0) ** trn2 z0\.d, z0\.d, z0\.d ** ret */ -fixed_uint64_t +[[gnu::noipa]] fixed_uint64_t f2 (fixed_uint64_t z0) { return __builtin_shufflevector (z0, z0, 1, 1, 3, 3); @@ -37,7 +37,7 @@ f2 (fixed_uint64_t z0) ** dupq z0\.s, z0\.s\[0\] ** ret */ -fixed_int32_t +[[gnu::noipa]] fixed_int32_t f3 (fixed_int32_t z0) { return __builtin_shufflevector (z0, z0, 0, 0, 0, 0, 4, 4, 4, 4); @@ -48,7 +48,7 @@ f3 (fixed_int32_t z0) ** dupq z0\.s, z0\.s\[1\] ** ret */ -fixed_int32_t +[[gnu::noipa]] fixed_int32_t f4 (fixed_int32_t z0) { return __builtin_shufflevector (z0, z0, 1, 1, 1, 1, 5, 5, 5, 5); @@ -59,7 +59,7 @@ f4 (fixed_int32_t z0) ** dupq z0\.s, z0\.s\[2\] ** ret */ -fixed_int32_t +[[gnu::noipa]] fixed_int32_t f5 (fixed_int32_t z0) { return __builtin_shufflevector (z0, z0, 2, 2, 2, 2, 6, 6, 6, 6); @@ -70,7 +70,7 @@ f5 (fixed_int32_t z0) ** dupq z0\.s, z0\.s\[3\] ** ret */ -fixed_int32_t +[[gnu::noipa]] fixed_int32_t f6 (fixed_int32_t z0) { return __builtin_shufflevector (z0, z0, 3, 3, 3, 3, 7, 7, 7, 7); @@ -81,7 +81,7 @@ f6 (fixed_int32_t z0) ** dupq z0\.h, z0\.h\[0\] ** ret */ -fixed_uint16_t +[[gnu::noipa]] fixed_uint16_t f7 (fixed_uint16_t z0) { return __builtin_shufflevector (z0, z0, @@ -95,7 +95,7 @@ f7 (fixed_uint16_t z0) ** dupq z0\.h, z0\.h\[5\] ** ret */ -fixed_uint16_t +[[gnu::noipa]] fixed_uint16_t f8 (fixed_uint16_t z0) { return __builtin_shufflevector (z0, z0, @@ -108,7 +108,7 @@ f8 (fixed_uint16_t z0) ** dupq z0\.h, z0\.h\[7\] ** ret */ -fixed_uint16_t +[[gnu::noipa]] fixed_uint16_t f9 (fixed_uint16_t z0) { return __builtin_shufflevector (z0, z0, @@ -121,7 +121,7 @@ f9 (fixed_uint16_t z0) ** dupq z0\.b, z0\.b\[0\] ** ret */ -fixed_uint8_t +[[gnu::noipa]] fixed_uint8_t f10 (fixed_uint8_t z0) { return __builtin_shufflevector (z0, z0, @@ -136,7 +136,7 @@ f10 (fixed_uint8_t z0) ** dupq z0\.b, z0\.b\[13\] ** ret */ -fixed_uint8_t +[[gnu::noipa]] fixed_uint8_t f11 (fixed_uint8_t z0) { return __builtin_shufflevector (z0, z0, @@ -151,7 +151,7 @@ f11 (fixed_uint8_t z0) ** dupq z0\.b, z0\.b\[15\] ** ret */ -fixed_uint8_t +[[gnu::noipa]] fixed_uint8_t f12 (fixed_uint8_t z0) { return __builtin_shufflevector (z0, z0, diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/dupq_1_run.c b/gcc/testsuite/gcc.target/aarch64/sve2/dupq_1_run.c new file mode 100644 index 0000000..fd25034 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve2/dupq_1_run.c @@ -0,0 +1,87 @@ +/* { dg-do run { target { aarch64_sve256_hw && aarch64_sve2p1_hw } } } */ +/* { dg-options "-O2 -msve-vector-bits=256" } */ + +#include "dupq_1.c" + +#define TEST(A, B) \ + do { \ + typeof(B) actual_ = (A); \ + if (__builtin_memcmp (&actual_, &(B), sizeof (actual_)) != 0) \ + __builtin_abort (); \ + } while (0) + +int +main () +{ + fixed_uint64_t a64 = { 0x1122, -1, 0x5566, -2 }; + fixed_int32_t a32 = { 0x1122, -0x3344, 0x5566, -0x7788, + 0x99aa, -0xbbcc, 0xddee, -0xff00 }; + fixed_uint16_t a16 = { 0x9a12, 0xbc34, 0xde56, 0xf078, + 0x00ff, 0x11ee, 0x22dd, 0x33cc, + 0x44bb, 0x55aa, 0x6699, 0x7788, + 0xfe01, 0xdc23, 0xba45, 0x9867 }; + fixed_uint8_t a8 = { 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x70, + 0x89, 0x9a, 0xab, 0xbc, 0xcd, 0xde, 0xef, 0xf8, + 0xfe, 0xed, 0xdc, 0xcb, 0xba, 0xa9, 0x98, 0x8f, + 0x76, 0x65, 0x54, 0x43, 0x32, 0x21, 0x10, 0x07 }; + + fixed_uint64_t expected1 = { 0x1122, 0x1122, 0x5566, 0x5566 }; + TEST (f1 (a64), expected1); + + fixed_uint64_t expected2 = { -1, -1, -2, -2 }; + TEST (f2 (a64), expected2); + + fixed_int32_t expected3 = { 0x1122, 0x1122, 0x1122, 0x1122, + 0x99aa, 0x99aa, 0x99aa, 0x99aa }; + TEST (f3 (a32), expected3); + + fixed_int32_t expected4 = { -0x3344, -0x3344, -0x3344, -0x3344, + -0xbbcc, -0xbbcc, -0xbbcc, -0xbbcc }; + TEST (f4 (a32), expected4); + + fixed_int32_t expected5 = { 0x5566, 0x5566, 0x5566, 0x5566, + 0xddee, 0xddee, 0xddee, 0xddee }; + TEST (f5 (a32), expected5); + + fixed_int32_t expected6 = { -0x7788, -0x7788, -0x7788, -0x7788, + -0xff00, -0xff00, -0xff00, -0xff00 }; + TEST (f6 (a32), expected6); + + fixed_uint16_t expected7 = { 0x9a12, 0x9a12, 0x9a12, 0x9a12, + 0x9a12, 0x9a12, 0x9a12, 0x9a12, + 0x44bb, 0x44bb, 0x44bb, 0x44bb, + 0x44bb, 0x44bb, 0x44bb, 0x44bb }; + TEST (f7 (a16), expected7); + + fixed_uint16_t expected8 = { 0x11ee, 0x11ee, 0x11ee, 0x11ee, + 0x11ee, 0x11ee, 0x11ee, 0x11ee, + 0xdc23, 0xdc23, 0xdc23, 0xdc23, + 0xdc23, 0xdc23, 0xdc23, 0xdc23 }; + TEST (f8 (a16), expected8); + + fixed_uint16_t expected9 = { 0x33cc, 0x33cc, 0x33cc, 0x33cc, + 0x33cc, 0x33cc, 0x33cc, 0x33cc, + 0x9867, 0x9867, 0x9867, 0x9867, + 0x9867, 0x9867, 0x9867, 0x9867 }; + TEST (f9 (a16), expected9); + + fixed_uint8_t expected10 = { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, + 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe }; + TEST (f10 (a8), expected10); + + fixed_uint8_t expected11 = { 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, + 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, + 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, + 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21 }; + TEST (f11 (a8), expected11); + + fixed_uint8_t expected12 = { 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, + 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07 }; + TEST (f12 (a8), expected12); + + return 0; +} diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/extq_1.c b/gcc/testsuite/gcc.target/aarch64/sve2/extq_1.c index 03c5fb1..be5ae71 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve2/extq_1.c +++ b/gcc/testsuite/gcc.target/aarch64/sve2/extq_1.c @@ -1,5 +1,5 @@ /* { dg-options "-O2 -msve-vector-bits=256" } */ -/* { dg-final { check-function-bodies "**" "" "" { target { le } } } } */ +/* { dg-final { check-function-bodies "**" "" "" } } */ #include <arm_sve.h> @@ -15,7 +15,7 @@ typedef svfloat64_t fixed_float64_t __attribute__((arm_sve_vector_bits(256))); ** extq z0\.b, z0\.b, z1\.b, #8 ** ret */ -fixed_float64_t +[[gnu::noipa]] fixed_float64_t f1 (fixed_float64_t z0, fixed_float64_t z1) { return __builtin_shufflevector (z0, z1, 1, 4, 3, 6); @@ -26,7 +26,7 @@ f1 (fixed_float64_t z0, fixed_float64_t z1) ** extq z0\.b, z0\.b, z1\.b, #4 ** ret */ -fixed_uint32_t +[[gnu::noipa]] fixed_uint32_t f2 (fixed_uint32_t z0, fixed_uint32_t z1) { return __builtin_shufflevector (z0, z1, 1, 2, 3, 8, 5, 6, 7, 12); @@ -37,7 +37,7 @@ f2 (fixed_uint32_t z0, fixed_uint32_t z1) ** extq z0\.b, z0\.b, z1\.b, #12 ** ret */ -fixed_uint32_t +[[gnu::noipa]] fixed_uint32_t f3 (fixed_uint32_t z0, fixed_uint32_t z1) { return __builtin_shufflevector (z0, z1, 3, 8, 9, 10, 7, 12, 13, 14); @@ -48,7 +48,7 @@ f3 (fixed_uint32_t z0, fixed_uint32_t z1) ** extq z0\.b, z0\.b, z1\.b, #2 ** ret */ -fixed_float16_t +[[gnu::noipa]] fixed_float16_t f4 (fixed_float16_t z0, fixed_float16_t z1) { return __builtin_shufflevector (z0, z1, @@ -61,7 +61,7 @@ f4 (fixed_float16_t z0, fixed_float16_t z1) ** extq z0\.b, z0\.b, z1\.b, #10 ** ret */ -fixed_float16_t +[[gnu::noipa]] fixed_float16_t f5 (fixed_float16_t z0, fixed_float16_t z1) { return __builtin_shufflevector (z0, z1, @@ -74,7 +74,7 @@ f5 (fixed_float16_t z0, fixed_float16_t z1) ** extq z0\.b, z0\.b, z1\.b, #14 ** ret */ -fixed_float16_t +[[gnu::noipa]] fixed_float16_t f6 (fixed_float16_t z0, fixed_float16_t z1) { return __builtin_shufflevector (z0, z1, @@ -87,7 +87,7 @@ f6 (fixed_float16_t z0, fixed_float16_t z1) ** extq z0\.b, z0\.b, z1\.b, #1 ** ret */ -fixed_int8_t +[[gnu::noipa]] fixed_int8_t f7 (fixed_int8_t z0, fixed_int8_t z1) { return __builtin_shufflevector (z0, z1, @@ -102,7 +102,7 @@ f7 (fixed_int8_t z0, fixed_int8_t z1) ** extq z0\.b, z0\.b, z1\.b, #11 ** ret */ -fixed_int8_t +[[gnu::noipa]] fixed_int8_t f8 (fixed_int8_t z0, fixed_int8_t z1) { return __builtin_shufflevector (z0, z1, @@ -117,7 +117,7 @@ f8 (fixed_int8_t z0, fixed_int8_t z1) ** extq z0\.b, z0\.b, z1\.b, #15 ** ret */ -fixed_int8_t +[[gnu::noipa]] fixed_int8_t f9 (fixed_int8_t z0, fixed_int8_t z1) { return __builtin_shufflevector (z0, z1, diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/extq_1_run.c b/gcc/testsuite/gcc.target/aarch64/sve2/extq_1_run.c new file mode 100644 index 0000000..6b72c98 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve2/extq_1_run.c @@ -0,0 +1,73 @@ +/* { dg-do run { target { aarch64_sve256_hw && aarch64_sve2p1_hw } } } */ +/* { dg-options "-O2 -msve-vector-bits=256" } */ + +#include "extq_1.c" + +#define TEST(A, B) \ + do { \ + typeof(B) actual_ = (A); \ + if (__builtin_memcmp (&actual_, &(B), sizeof (actual_)) != 0) \ + __builtin_abort (); \ + } while (0) + +int +main () +{ + fixed_float64_t a64 = { 1.5, 3.75, -5.25, 9 }; + fixed_float64_t b64 = { -2, 4.125, -6.375, 11.5 }; + fixed_float64_t expected1 = { 3.75, -2, 9, -6.375 }; + TEST (f1 (a64, b64), expected1); + + fixed_uint32_t a32 = { 0x1122, -0x3344, 0x5566, -0x7788, + 0x99aa, -0xbbcc, 0xddee, -0xff00 }; + fixed_uint32_t b32 = { 1 << 20, 1 << 21, 1 << 22, 1 << 23, + 5 << 6, 5 << 7, 5 << 8, 5 << 9 }; + fixed_uint32_t expected2 = { -0x3344, 0x5566, -0x7788, 1 << 20, + -0xbbcc, 0xddee, -0xff00, 5 << 6 }; + fixed_uint32_t expected3 = { -0x7788, 1 << 20, 1 << 21, 1 << 22, + -0xff00, 5 << 6, 5 << 7, 5 << 8 }; + TEST (f2 (a32, b32), expected2); + TEST (f3 (a32, b32), expected3); + + fixed_float16_t a16 = { 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2, 2.25, + 2.5, 2.75, 3, 3.25, 3.5, 3.75, 4, 4.25 }; + fixed_float16_t b16 = { -0.5, -0.75, -1, -1.25, -1.5, -1.75, -2, -2.25, + -2.5, -2.75, -3, -3.25, -3.5, -3.75, -4, -4.25 }; + fixed_float16_t expected4 = { 0.75, 1, 1.25, 1.5, 1.75, 2, 2.25, -0.5, + 2.75, 3, 3.25, 3.5, 3.75, 4, 4.25, -2.5 }; + fixed_float16_t expected5 = { 1.75, 2, 2.25, -0.5, -0.75, -1, -1.25, -1.5, + 3.75, 4, 4.25, -2.5, -2.75, -3, -3.25, -3.5 }; + fixed_float16_t expected6 = { 2.25, -0.5, -0.75, -1, + -1.25, -1.5, -1.75, -2, + 4.25, -2.5, -2.75, -3, + -3.25, -3.5, -3.75, -4 }; + TEST (f4 (a16, b16), expected4); + TEST (f5 (a16, b16), expected5); + TEST (f6 (a16, b16), expected6); + + fixed_int8_t a8 = { 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x70, + 0x89, 0x9a, 0xab, 0xbc, 0xcd, 0xde, 0xef, 0xf8, + 0xfe, 0xed, 0xdc, 0xcb, 0xba, 0xa9, 0x98, 0x8f, + 0x76, 0x65, 0x54, 0x43, 0x32, 0x21, 0x10, 0x07 }; + fixed_int8_t b8 = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, + 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, + 0x13, 0x24, 0x35, 0x46, 0x57, 0x68, 0x79, 0x8a, + 0x9b, 0xac, 0xbd, 0xce, 0xdf, 0xe0, 0xf1, 0x02 }; + fixed_int8_t expected7 = { 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x70, 0x89, + 0x9a, 0xab, 0xbc, 0xcd, 0xde, 0xef, 0xf8, 0x11, + 0xed, 0xdc, 0xcb, 0xba, 0xa9, 0x98, 0x8f, 0x76, + 0x65, 0x54, 0x43, 0x32, 0x21, 0x10, 0x07, 0x13 }; + fixed_int8_t expected8 = { 0xbc, 0xcd, 0xde, 0xef, 0xf8, 0x11, 0x22, 0x33, + 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, + 0x43, 0x32, 0x21, 0x10, 0x07, 0x13, 0x24, 0x35, + 0x46, 0x57, 0x68, 0x79, 0x8a, 0x9b, 0xac, 0xbd }; + fixed_int8_t expected9 = { 0xf8, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, + 0x07, 0x13, 0x24, 0x35, 0x46, 0x57, 0x68, 0x79, + 0x8a, 0x9b, 0xac, 0xbd, 0xce, 0xdf, 0xe0, 0xf1 }; + TEST (f7 (a8, b8), expected7); + TEST (f8 (a8, b8), expected8); + TEST (f9 (a8, b8), expected9); + + return 0; +} diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-binary.c b/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-binary.c index 94470a5..977fa39 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-binary.c +++ b/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-binary.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include "../pfalse-binary_0.h" diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-binary_int_opt_n.c b/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-binary_int_opt_n.c index b8747b8..b816fa1 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-binary_int_opt_n.c +++ b/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-binary_int_opt_n.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include "../pfalse-binary_0.h" diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-binary_int_opt_single_n.c b/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-binary_int_opt_single_n.c index 7cb7ee5..0e4427a 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-binary_int_opt_single_n.c +++ b/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-binary_int_opt_single_n.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include "../pfalse-binary_0.h" diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-binary_opt_n.c b/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-binary_opt_n.c index 787126f..81d0c82 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-binary_opt_n.c +++ b/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-binary_opt_n.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include "../pfalse-binary_0.h" diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-binary_opt_single_n.c b/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-binary_opt_single_n.c index 6b2b0a42..3920bdb 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-binary_opt_single_n.c +++ b/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-binary_opt_single_n.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2 -march=armv8.2-a+sve2+faminmax" } */ +/* { dg-options "-O2 -march=armv8.2-a+sve2+faminmax -funwind-tables" } */ #include "../pfalse-binary_0.h" diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-binary_to_uint.c b/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-binary_to_uint.c index a0a7f80..c7d10b3 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-binary_to_uint.c +++ b/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-binary_to_uint.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include "../pfalse-binary_0.h" diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-binary_uint_opt_n.c b/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-binary_uint_opt_n.c index c13db48..122fba7 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-binary_uint_opt_n.c +++ b/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-binary_uint_opt_n.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include "../pfalse-binary_0.h" diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-binary_wide.c b/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-binary_wide.c index 145b077..7f35859 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-binary_wide.c +++ b/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-binary_wide.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include "../pfalse-binary_0.h" diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-compare.c b/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-compare.c index da175db..b079a56 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-compare.c +++ b/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-compare.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include "../pfalse-binary_0.h" diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-load_ext_gather_index_restricted.c b/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-load_ext_gather_index_restricted.c index c0476ce..14e77c00 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-load_ext_gather_index_restricted.c +++ b/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-load_ext_gather_index_restricted.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include <arm_sve.h> diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-load_ext_gather_offset_restricted.c b/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-load_ext_gather_offset_restricted.c index f644024..b680548 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-load_ext_gather_offset_restricted.c +++ b/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-load_ext_gather_offset_restricted.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include <arm_sve.h> diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-load_gather_sv_restricted.c b/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-load_gather_sv_restricted.c index a48a8a9..6d1a356 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-load_gather_sv_restricted.c +++ b/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-load_gather_sv_restricted.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include <arm_sve.h> diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-load_gather_vs.c b/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-load_gather_vs.c index 1fc08a3..9cb4471 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-load_gather_vs.c +++ b/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-load_gather_vs.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include <arm_sve.h> diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-shift_left_imm_to_uint.c b/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-shift_left_imm_to_uint.c index bd2c937..e57a650 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-shift_left_imm_to_uint.c +++ b/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-shift_left_imm_to_uint.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include <arm_sve.h> diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-shift_right_imm.c b/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-shift_right_imm.c index f4994de..710ca73 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-shift_right_imm.c +++ b/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-shift_right_imm.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include <arm_sve.h> diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-store_scatter_index_restricted.c b/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-store_scatter_index_restricted.c index 6bec3b3..dc9cf46 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-store_scatter_index_restricted.c +++ b/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-store_scatter_index_restricted.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include <arm_sve.h> diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-store_scatter_offset_restricted.c b/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-store_scatter_offset_restricted.c index bcb4a14..2728c9b 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-store_scatter_offset_restricted.c +++ b/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-store_scatter_offset_restricted.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include <arm_sve.h> diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-unary.c b/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-unary.c index ba7e931..9f33295 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-unary.c +++ b/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-unary.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2 -march=armv9.2-a+sve+sme" } */ +/* { dg-options "-O2 -march=armv9.2-a+sve+sme -funwind-tables" } */ #include "../pfalse-unary_0.h" diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-unary_convert.c b/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-unary_convert.c index 7aa59ff..68769fe 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-unary_convert.c +++ b/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-unary_convert.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include <arm_sve.h> diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-unary_convert_narrowt.c b/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-unary_convert_narrowt.c index 1a4525c..692891f 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-unary_convert_narrowt.c +++ b/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-unary_convert_narrowt.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include <arm_sve.h> diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-unary_to_int.c b/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-unary_to_int.c index b64bfc3..7dffa1c 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-unary_to_int.c +++ b/gcc/testsuite/gcc.target/aarch64/sve2/pfalse-unary_to_int.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target elf } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -funwind-tables" } */ #include "../pfalse-unary_0.h" diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/pr120999.c b/gcc/testsuite/gcc.target/aarch64/sve2/pr120999.c new file mode 100644 index 0000000..2dca36a --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve2/pr120999.c @@ -0,0 +1,17 @@ +/* PR target/120999. */ +/* { dg-do assemble } */ +/* { dg-options "-O2 --save-temps" } */ +/* { dg-final { check-function-bodies "**" "" "" } } */ + +#include <arm_sve.h> + +#define NOR(x, y) (~((x) | (y))) + +/* +** nor_z: +** movprfx z0, z1 +** nbsl z0.d, z0.d, z2.d, z1.d +** ret +*/ +svuint64_t nor_z(svuint64_t c, svuint64_t a, svuint64_t b) { return NOR(a, b); } + diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/uzpq_1.c b/gcc/testsuite/gcc.target/aarch64/sve2/uzpq_1.c index f923e94..587f670 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve2/uzpq_1.c +++ b/gcc/testsuite/gcc.target/aarch64/sve2/uzpq_1.c @@ -1,5 +1,5 @@ /* { dg-options "-O2 -msve-vector-bits=256" } */ -/* { dg-final { check-function-bodies "**" "" "" { target { le } } } } */ +/* { dg-final { check-function-bodies "**" "" "" } } */ #include <arm_sve.h> @@ -15,7 +15,7 @@ typedef svint64_t fixed_int64_t __attribute__((arm_sve_vector_bits(256))); ** trn1 z0\.d, z0\.d, z1\.d ** ret */ -fixed_int64_t +[[gnu::noipa]] fixed_int64_t f1 (fixed_int64_t z0, fixed_int64_t z1) { return __builtin_shufflevector (z0, z1, 0, 4, 2, 6); @@ -26,7 +26,7 @@ f1 (fixed_int64_t z0, fixed_int64_t z1) ** trn2 z0\.d, z0\.d, z1\.d ** ret */ -fixed_int64_t +[[gnu::noipa]] fixed_int64_t f2 (fixed_int64_t z0, fixed_int64_t z1) { return __builtin_shufflevector (z0, z1, 1, 5, 3, 7); @@ -37,7 +37,7 @@ f2 (fixed_int64_t z0, fixed_int64_t z1) ** uzpq1 z0\.s, z0\.s, z1\.s ** ret */ -fixed_float32_t +[[gnu::noipa]] fixed_float32_t f3 (fixed_float32_t z0, fixed_float32_t z1) { return __builtin_shufflevector (z0, z1, 0, 2, 8, 10, 4, 6, 12, 14); @@ -48,7 +48,7 @@ f3 (fixed_float32_t z0, fixed_float32_t z1) ** uzpq2 z0\.s, z0\.s, z1\.s ** ret */ -fixed_float32_t +[[gnu::noipa]] fixed_float32_t f4 (fixed_float32_t z0, fixed_float32_t z1) { return __builtin_shufflevector (z0, z1, 1, 3, 9, 11, 5, 7, 13, 15); @@ -59,7 +59,7 @@ f4 (fixed_float32_t z0, fixed_float32_t z1) ** uzpq1 z0\.h, z0\.h, z1\.h ** ret */ -fixed_bfloat16_t +[[gnu::noipa]] fixed_bfloat16_t f5 (fixed_bfloat16_t z0, fixed_bfloat16_t z1) { return __builtin_shufflevector (z0, z1, @@ -72,7 +72,7 @@ f5 (fixed_bfloat16_t z0, fixed_bfloat16_t z1) ** uzpq2 z0\.h, z0\.h, z1\.h ** ret */ -fixed_bfloat16_t +[[gnu::noipa]] fixed_bfloat16_t f6 (fixed_bfloat16_t z0, fixed_bfloat16_t z1) { return __builtin_shufflevector (z0, z1, @@ -85,7 +85,7 @@ f6 (fixed_bfloat16_t z0, fixed_bfloat16_t z1) ** uzpq1 z0\.b, z0\.b, z1\.b ** ret */ -fixed_uint8_t +[[gnu::noipa]] fixed_uint8_t f7 (fixed_uint8_t z0, fixed_uint8_t z1) { return __builtin_shufflevector (z0, z1, @@ -100,7 +100,7 @@ f7 (fixed_uint8_t z0, fixed_uint8_t z1) ** uzpq2 z0\.b, z0\.b, z1\.b ** ret */ -fixed_uint8_t +[[gnu::noipa]] fixed_uint8_t f8 (fixed_uint8_t z0, fixed_uint8_t z1) { return __builtin_shufflevector (z0, z1, diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/uzpq_1_run.c b/gcc/testsuite/gcc.target/aarch64/sve2/uzpq_1_run.c new file mode 100644 index 0000000..9044cae --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve2/uzpq_1_run.c @@ -0,0 +1,78 @@ +/* { dg-do run { target { aarch64_sve256_hw && aarch64_sve2p1_hw } } } */ +/* { dg-options "-O2 -msve-vector-bits=256" } */ + +#include "uzpq_1.c" + +typedef svuint16_t fixed_uint16_t __attribute__((arm_sve_vector_bits(256))); + +#define TEST(A, B) \ + do { \ + typeof(A) actual_ = (A); \ + if (__builtin_memcmp (&actual_, &(B), sizeof (actual_)) != 0) \ + __builtin_abort (); \ + } while (0) + +int +main () +{ + fixed_int64_t a64 = { 0x1122LL << 31, -1LL << 47, 0x5566 << 15, -2 }; + fixed_int64_t b64 = { 42, -0x3344LL << 19, 303, -0x7788LL << 27 }; + fixed_int64_t expected1 = { 0x1122LL << 31, 42, + 0x5566 << 15, 303 }; + fixed_int64_t expected2 = { -1LL << 47, -0x3344LL << 19, + -2, -0x7788LL << 27 }; + TEST (f1 (a64, b64), expected1); + TEST (f2 (a64, b64), expected2); + + fixed_float32_t a32 = { 0.5, 0.75, 1, 1.25, 2.5, 2.75, 3, 3.25 }; + fixed_float32_t b32 = { -0.5, -0.75, -1, -1.25, -2.5, -2.75, -3, -3.25 }; + fixed_float32_t expected3 = { 0.5, 1, -0.5, -1, + 2.5, 3, -2.5, -3 }; + fixed_float32_t expected4 = { 0.75, 1.25, -0.75, -1.25, + 2.75, 3.25, -2.75, -3.25 }; + TEST (f3 (a32, b32), expected3); + TEST (f4 (a32, b32), expected4); + + fixed_uint16_t a16_i = { 0x9a12, 0xbc34, 0xde56, 0xf078, + 0x00ff, 0x11ee, 0x22dd, 0x33cc, + 0x44bb, 0x55aa, 0x6699, 0x7788, + 0xfe01, 0xdc23, 0xba45, 0x9867 }; + fixed_uint16_t b16_i = { 0x1010, 0x2020, 0x3030, 0x4040, + 0x5050, 0x6060, 0x7070, 0x8080, + 0x9090, 0xa0a0, 0xb0b0, 0xc0c0, + 0xd0d0, 0xe0e0, 0xf0f0, 0x0f0f }; + fixed_uint16_t expected5 = { 0x9a12, 0xde56, 0x00ff, 0x22dd, + 0x1010, 0x3030, 0x5050, 0x7070, + 0x44bb, 0x6699, 0xfe01, 0xba45, + 0x9090, 0xb0b0, 0xd0d0, 0xf0f0 }; + fixed_uint16_t expected6 = { 0xbc34, 0xf078, 0x11ee, 0x33cc, + 0x2020, 0x4040, 0x6060, 0x8080, + 0x55aa, 0x7788, 0xdc23, 0x9867, + 0xa0a0, 0xc0c0, 0xe0e0, 0x0f0f }; + fixed_bfloat16_t a16, b16; + __builtin_memcpy (&a16, &a16_i, sizeof (a16)); + __builtin_memcpy (&b16, &b16_i, sizeof (b16)); + TEST (f5 (a16, b16), expected5); + TEST (f6 (a16, b16), expected6); + + fixed_uint8_t a8 = { 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x70, + 0x89, 0x9a, 0xab, 0xbc, 0xcd, 0xde, 0xef, 0xf8, + 0xfe, 0xed, 0xdc, 0xcb, 0xba, 0xa9, 0x98, 0x8f, + 0x76, 0x65, 0x54, 0x43, 0x32, 0x21, 0x10, 0x07 }; + fixed_uint8_t b8 = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, + 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, + 0x13, 0x24, 0x35, 0x46, 0x57, 0x68, 0x79, 0x8a, + 0x9b, 0xac, 0xbd, 0xce, 0xdf, 0xe0, 0xf1, 0x02 }; + fixed_uint8_t expected7 = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0x11, 0x33, 0x55, 0x77, 0x99, 0xbb, 0xdd, 0xff, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + 0x13, 0x35, 0x57, 0x79, 0x9b, 0xbd, 0xdf, 0xf1 }; + fixed_uint8_t expected8 = { 0x12, 0x34, 0x56, 0x70, 0x9a, 0xbc, 0xde, 0xf8, + 0x22, 0x44, 0x66, 0x88, 0xaa, 0xcc, 0xee, 0x00, + 0xed, 0xcb, 0xa9, 0x8f, 0x65, 0x43, 0x21, 0x07, + 0x24, 0x46, 0x68, 0x8a, 0xac, 0xce, 0xe0, 0x02 }; + TEST (f7 (a8, b8), expected7); + TEST (f8 (a8, b8), expected8); + + return 0; +} diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/zipq_1.c b/gcc/testsuite/gcc.target/aarch64/sve2/zipq_1.c index fa420a9..76fb4b4 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve2/zipq_1.c +++ b/gcc/testsuite/gcc.target/aarch64/sve2/zipq_1.c @@ -1,5 +1,5 @@ /* { dg-options "-O2 -msve-vector-bits=256" } */ -/* { dg-final { check-function-bodies "**" "" "" { target { le } } } } */ +/* { dg-final { check-function-bodies "**" "" "" } } */ #include <arm_sve.h> @@ -15,7 +15,7 @@ typedef svint64_t fixed_int64_t __attribute__((arm_sve_vector_bits(256))); ** trn1 z0\.d, z0\.d, z1\.d ** ret */ -fixed_int64_t +[[gnu::noipa]] fixed_int64_t f1 (fixed_int64_t z0, fixed_int64_t z1) { return __builtin_shufflevector (z0, z1, 0, 4, 2, 6); @@ -26,7 +26,7 @@ f1 (fixed_int64_t z0, fixed_int64_t z1) ** trn2 z0\.d, z0\.d, z1\.d ** ret */ -fixed_int64_t +[[gnu::noipa]] fixed_int64_t f2 (fixed_int64_t z0, fixed_int64_t z1) { return __builtin_shufflevector (z0, z1, 1, 5, 3, 7); @@ -37,7 +37,7 @@ f2 (fixed_int64_t z0, fixed_int64_t z1) ** zipq1 z0\.s, z0\.s, z1\.s ** ret */ -fixed_float32_t +[[gnu::noipa]] fixed_float32_t f3 (fixed_float32_t z0, fixed_float32_t z1) { return __builtin_shufflevector (z0, z1, 0, 8, 1, 9, 4, 12, 5, 13); @@ -48,7 +48,7 @@ f3 (fixed_float32_t z0, fixed_float32_t z1) ** zipq2 z0\.s, z0\.s, z1\.s ** ret */ -fixed_float32_t +[[gnu::noipa]] fixed_float32_t f4 (fixed_float32_t z0, fixed_float32_t z1) { return __builtin_shufflevector (z0, z1, 2, 10, 3, 11, 6, 14, 7, 15); @@ -59,7 +59,7 @@ f4 (fixed_float32_t z0, fixed_float32_t z1) ** zipq1 z0\.h, z0\.h, z1\.h ** ret */ -fixed_bfloat16_t +[[gnu::noipa]] fixed_bfloat16_t f5 (fixed_bfloat16_t z0, fixed_bfloat16_t z1) { return __builtin_shufflevector (z0, z1, @@ -72,7 +72,7 @@ f5 (fixed_bfloat16_t z0, fixed_bfloat16_t z1) ** zipq2 z0\.h, z0\.h, z1\.h ** ret */ -fixed_bfloat16_t +[[gnu::noipa]] fixed_bfloat16_t f6 (fixed_bfloat16_t z0, fixed_bfloat16_t z1) { return __builtin_shufflevector (z0, z1, @@ -85,7 +85,7 @@ f6 (fixed_bfloat16_t z0, fixed_bfloat16_t z1) ** zipq1 z0\.b, z0\.b, z1\.b ** ret */ -fixed_uint8_t +[[gnu::noipa]] fixed_uint8_t f7 (fixed_uint8_t z0, fixed_uint8_t z1) { return __builtin_shufflevector (z0, z1, @@ -100,7 +100,7 @@ f7 (fixed_uint8_t z0, fixed_uint8_t z1) ** zipq2 z0\.b, z0\.b, z1\.b ** ret */ -fixed_uint8_t +[[gnu::noipa]] fixed_uint8_t f8 (fixed_uint8_t z0, fixed_uint8_t z1) { return __builtin_shufflevector (z0, z1, diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/zipq_1_run.c b/gcc/testsuite/gcc.target/aarch64/sve2/zipq_1_run.c new file mode 100644 index 0000000..211f9d9 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve2/zipq_1_run.c @@ -0,0 +1,78 @@ +/* { dg-do run { target { aarch64_sve256_hw && aarch64_sve2p1_hw } } } */ +/* { dg-options "-O2 -msve-vector-bits=256" } */ + +#include "zipq_1.c" + +typedef svuint16_t fixed_uint16_t __attribute__((arm_sve_vector_bits(256))); + +#define TEST(A, B) \ + do { \ + typeof(A) actual_ = (A); \ + if (__builtin_memcmp (&actual_, &(B), sizeof (actual_)) != 0) \ + __builtin_abort (); \ + } while (0) + +int +main () +{ + fixed_int64_t a64 = { 0x1122LL << 31, -1LL << 47, 0x5566 << 15, -2 }; + fixed_int64_t b64 = { 42, -0x3344LL << 19, 303, -0x7788LL << 27 }; + fixed_int64_t expected1 = { 0x1122LL << 31, 42, + 0x5566 << 15, 303 }; + fixed_int64_t expected2 = { -1LL << 47, -0x3344LL << 19, + -2, -0x7788LL << 27 }; + TEST (f1 (a64, b64), expected1); + TEST (f2 (a64, b64), expected2); + + fixed_float32_t a32 = { 0.5, 0.75, 1, 1.25, 2.5, 2.75, 3, 3.25 }; + fixed_float32_t b32 = { -0.5, -0.75, -1, -1.25, -2.5, -2.75, -3, -3.25 }; + fixed_float32_t expected3 = { 0.5, -0.5, 0.75, -0.75, + 2.5, -2.5, 2.75, -2.75 }; + fixed_float32_t expected4 = { 1, -1, 1.25, -1.25, + 3, -3, 3.25, -3.25 }; + TEST (f3 (a32, b32), expected3); + TEST (f4 (a32, b32), expected4); + + fixed_uint16_t a16_i = { 0x9a12, 0xbc34, 0xde56, 0xf078, + 0x00ff, 0x11ee, 0x22dd, 0x33cc, + 0x44bb, 0x55aa, 0x6699, 0x7788, + 0xfe01, 0xdc23, 0xba45, 0x9867 }; + fixed_uint16_t b16_i = { 0x1010, 0x2020, 0x3030, 0x4040, + 0x5050, 0x6060, 0x7070, 0x8080, + 0x9090, 0xa0a0, 0xb0b0, 0xc0c0, + 0xd0d0, 0xe0e0, 0xf0f0, 0x0f0f }; + fixed_uint16_t expected5 = { 0x9a12, 0x1010, 0xbc34, 0x2020, + 0xde56, 0x3030, 0xf078, 0x4040, + 0x44bb, 0x9090, 0x55aa, 0xa0a0, + 0x6699, 0xb0b0, 0x7788, 0xc0c0 }; + fixed_uint16_t expected6 = { 0x00ff, 0x5050, 0x11ee, 0x6060, + 0x22dd, 0x7070, 0x33cc, 0x8080, + 0xfe01, 0xd0d0, 0xdc23, 0xe0e0, + 0xba45, 0xf0f0, 0x9867, 0x0f0f }; + fixed_bfloat16_t a16, b16; + __builtin_memcpy (&a16, &a16_i, sizeof (a16)); + __builtin_memcpy (&b16, &b16_i, sizeof (b16)); + TEST (f5 (a16, b16), expected5); + TEST (f6 (a16, b16), expected6); + + fixed_uint8_t a8 = { 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x70, + 0x89, 0x9a, 0xab, 0xbc, 0xcd, 0xde, 0xef, 0xf8, + 0xfe, 0xed, 0xdc, 0xcb, 0xba, 0xa9, 0x98, 0x8f, + 0x76, 0x65, 0x54, 0x43, 0x32, 0x21, 0x10, 0x07 }; + fixed_uint8_t b8 = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, + 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, + 0x13, 0x24, 0x35, 0x46, 0x57, 0x68, 0x79, 0x8a, + 0x9b, 0xac, 0xbd, 0xce, 0xdf, 0xe0, 0xf1, 0x02 }; + fixed_uint8_t expected7 = { 0x01, 0x11, 0x12, 0x22, 0x23, 0x33, 0x34, 0x44, + 0x45, 0x55, 0x56, 0x66, 0x67, 0x77, 0x70, 0x88, + 0xfe, 0x13, 0xed, 0x24, 0xdc, 0x35, 0xcb, 0x46, + 0xba, 0x57, 0xa9, 0x68, 0x98, 0x79, 0x8f, 0x8a }; + fixed_uint8_t expected8 = { 0x89, 0x99, 0x9a, 0xaa, 0xab, 0xbb, 0xbc, 0xcc, + 0xcd, 0xdd, 0xde, 0xee, 0xef, 0xff, 0xf8, 0x00, + 0x76, 0x9b, 0x65, 0xac, 0x54, 0xbd, 0x43, 0xce, + 0x32, 0xdf, 0x21, 0xe0, 0x10, 0xf1, 0x07, 0x02 }; + TEST (f7 (a8, b8), expected7); + TEST (f8 (a8, b8), expected8); + + return 0; +} diff --git a/gcc/testsuite/gcc.target/aarch64/vector-compare-5.c b/gcc/testsuite/gcc.target/aarch64/vector-compare-5.c new file mode 100644 index 0000000..a1a601d --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/vector-compare-5.c @@ -0,0 +1,67 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ +/* { dg-additional-options "-fdump-tree-original-all" } */ + +typedef int v4i __attribute__((vector_size(4*sizeof(int)))); + +/* Ensure we can simplify `VEC_COND_EXPR(a OP1 b) OP2 VEC_COND_EXPR(a OP3 b)` + * into `VEC_COND_EXPR(a OP4 b)` + */ + +void use (v4i const *z); + +void +g (v4i *x, v4i const *y, v4i *z, v4i *t) +{ + *z = *x > *y | *x == *y; // expect >= + *t = *x > *y | *x <= *y; // expect true +} + +void +h (v4i *x, v4i const *y, v4i *z, v4i *t) +{ + *z = *x <= *y & *x >= *y; // expect x == y + *t = *x <= *y & *x != *y; // expect x<y +} + +void +i (v4i *x, v4i const *y, v4i *z, v4i *t) +{ + *z = *x == *y | *x != *y; // expect true + *t = *x == *y & *x != *y; // expect false +} + +void +k (v4i *x, v4i const *y, v4i *z, v4i *t) +{ + *z = *x < *y | *x == *y; // x <= y + *t = *x < *y & *x > *y; // expect false +} + +void +m (v4i *x, v4i const *y, v4i *z, v4i *t) +{ + *z = *x <= *y ^ *x >= *y; /* expect x != y */ + *t = *x <= *y ^ *x != *y; /* expect x <= y */ +} + +void +n (v4i *x, v4i const *y, v4i *z, v4i *t) +{ + *z = *x == *y ^ *x != *y; /* expect true */ + *t = *x == *y ^ *x == *y; /* expect false */ +} + + +/* { dg-final { scan-tree-dump ".*\\*zD\\.\\d+\\s*=\\s*VEC_COND_EXPR\\s*<\\s*\\*xD\\.\\d+\\s*>=\\s*VIEW_CONVERT_EXPR<v4iD\\.\\d+>\\(\\*yD\\.\\d+\\)\\s*,\\s*\\{\\s*-1(,\\s*-1){3}\\s*\\}\\s*,\\s*\\{\\s*0(,\\s*0){3}\\s*\\}\\s*>\\s*;" "original" } } */ +/* { dg-final { scan-tree-dump ".*\\*tD\\.\\d+\\s*=\\s*\\{\\s*-1(,\\s*-1){3}\\s*\\}\\s*;" "original" } } */ +/* { dg-final { scan-tree-dump ".*\\*zD\\.\\d+\\s*=\\s*VEC_COND_EXPR\\s*<\\s*\\*xD\\.\\d+\\s*==\\s*VIEW_CONVERT_EXPR<v4iD\\.\\d+>\\(\\*yD\\.\\d+\\)\\s*,\\s*\\{\\s*-1(,\\s*-1){3}\\s*\\}\\s*,\\s*\\{\\s*0(,\\s*0){3}\\s*\\}\\s*>\\s*;" "original" } } */ +/* { dg-final { scan-tree-dump ".*\\*tD\\.\\d+\\s*=\\s*VEC_COND_EXPR\\s*<\\s*\\*xD\\.\\d+\\s*<\\s*VIEW_CONVERT_EXPR<v4iD\\.\\d+>\\(\\*yD\\.\\d+\\)\\s*,\\s*\\{\\s*-1(,\\s*-1){3}\\s*\\}\\s*,\\s*\\{\\s*0(,\\s*0){3}\\s*\\}\\s*>\\s*;" "original" } } */ +/* { dg-final { scan-tree-dump ".*\\*zD\\.\\d+\\s*=\\s*\\{\\s*-1(,\\s*-1){3}\\s*\\}\\s*;" "original" } } */ +/* { dg-final { scan-tree-dump ".*\\*tD\\.\\d+\\s*=\\s*\\{\\s*0(,\\s*0){3}\\s*\\}\\s*;" "original" } } */ +/* { dg-final { scan-tree-dump ".*\\*zD\\.\\d+\\s*=\\s*VEC_COND_EXPR\\s*<\\s*\\*xD\\.\\d+\\s*<=\\s*VIEW_CONVERT_EXPR<v4iD\\.\\d+>\\(\\*yD\\.\\d+\\)\\s*,\\s*\\{\\s*-1(,\\s*-1){3}\\s*\\}\\s*,\\s*\\{\\s*0(,\\s*0){3}\\s*\\}\\s*>\\s*;" "original" } } */ +/* { dg-final { scan-tree-dump ".*\\*tD\\.\\d+\\s*=\\s*\\{\\s*0(,\\s*0){3}\\s*\\}\\s*;" "original" } } */ +/* { dg-final { scan-tree-dump ".*\\*zD\\.\\d+\\s*=\\s*VEC_COND_EXPR\\s*<\\s*\\*xD\\.\\d+\\s*!=\\s*VIEW_CONVERT_EXPR<v4iD\\.\\d+>\\(\\*yD\\.\\d+\\)\\s*,\\s*\\{\\s*-1(,\\s*-1){3}\\s*\\}\\s*,\\s*\\{\\s*0(,\\s*0){3}\\s*\\}\\s*>\\s*;" "original" } } */ +/* { dg-final { scan-tree-dump ".*\\*tD\\.\\d+\\s*=\\s*VEC_COND_EXPR\\s*<\\s*\\*xD\\.\\d+\\s*>=\\s*VIEW_CONVERT_EXPR<v4iD\\.\\d+>\\(\\*yD\\.\\d+\\)\\s*,\\s*\\{\\s*-1(,\\s*-1){3}\\s*\\}\\s*,\\s*\\{\\s*0(,\\s*0){3}\\s*\\}\\s*>\\s*;" "original" } } */ +/* { dg-final { scan-tree-dump ".*\\*zD\\.\\d+\\s*=\\s*\\{\\s*-1(,\\s*-1){3}\\s*\\}\\s*;" "original" } } */ +/* { dg-final { scan-tree-dump ".*\\*tD\\.\\d+\\s*=\\s*\\{\\s*0(,\\s*0){3}\\s*\\}\\s*;" "original" } } */ diff --git a/gcc/testsuite/gcc.target/i386/auto-init-padding-9.c b/gcc/testsuite/gcc.target/i386/auto-init-padding-9.c index 102217c..4f26aa4 100644 --- a/gcc/testsuite/gcc.target/i386/auto-init-padding-9.c +++ b/gcc/testsuite/gcc.target/i386/auto-init-padding-9.c @@ -8,17 +8,28 @@ /* **foo: **... +** leaq -160\(%rbp\), %rax +** movq %rax, %rcx ** pxor %xmm0, %xmm0 -**... +** movl \$160, %edx +** movl %edx, %edi +** andl \$-64, %edi +** movl \$0, %esi **.L[0-9]+: -** movl %esi, %ecx -** movaps %xmm0, \(%rdx,%rcx\) -** movaps %xmm0, 16\(%rdx,%rcx\) -** movaps %xmm0, 32\(%rdx,%rcx\) -** movaps %xmm0, 48\(%rdx,%rcx\) +** movl %esi, %edx +** movaps %xmm0, \(%rax,%rdx\) +** movaps %xmm0, 16\(%rax,%rdx\) +** movaps %xmm0, 32\(%rax,%rdx\) +** movaps %xmm0, 48\(%rax,%rdx\) ** addl \$64, %esi ** cmpl %edi, %esi ** jb .L[0-9]+ +** movl %esi, %eax +** addq %rax, %rcx +** movaps %xmm0, \(%rcx\) +** movaps %xmm0, 16\(%rcx\) +** movzbl -116\(%rbp\), %eax +** movsbl %al, %eax **... */ diff --git a/gcc/testsuite/gcc.target/i386/memcpy-pr120683-1.c b/gcc/testsuite/gcc.target/i386/memcpy-pr120683-1.c new file mode 100644 index 0000000..b1f6678 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/memcpy-pr120683-1.c @@ -0,0 +1,42 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mno-sse -mmemcpy-strategy=unrolled_loop:256:noalign,libcall:-1:noalign" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */ + +/* +**foo: +**.LFB[0-9]+: +** .cfi_startproc +** movq 221\(%rsi\), %rax +** xorl %edx, %edx +** movq %rax, 221\(%rdi\) +** movq 229\(%rsi\), %rax +** movq %rax, 229\(%rdi\) +** movq 237\(%rsi\), %rax +** movq %rax, 237\(%rdi\) +** movq 245\(%rsi\), %rax +** movq %rax, 245\(%rdi\) +**.L[0-9]+: +** movl %edx, %eax +** addl \$32, %edx +** movq \(%rsi,%rax\), %r10 +** movq 8\(%rsi,%rax\), %r9 +** movq 16\(%rsi,%rax\), %r8 +** movq 24\(%rsi,%rax\), %rcx +** movq %r10, \(%rdi,%rax\) +** movq %r9, 8\(%rdi,%rax\) +** movq %r8, 16\(%rdi,%rax\) +** movq %rcx, 24\(%rdi,%rax\) +** cmpl \$224, %edx +** jb .L[0-9]+ +** ret +**... +*/ + +void +foo (char *dest, char *src) +{ + __builtin_memcpy (dest, src, 253); +} + +/* { dg-final { scan-assembler-not "rep mov" } } */ diff --git a/gcc/testsuite/gcc.target/i386/memcpy-pr120683-2.c b/gcc/testsuite/gcc.target/i386/memcpy-pr120683-2.c new file mode 100644 index 0000000..0d0e348 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/memcpy-pr120683-2.c @@ -0,0 +1,41 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=x86-64 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemcpy-strategy=vector_loop:2048:noalign,libcall:-1:noalign" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */ + +/* +**foo: +**.LFB[0-9]+: +** .cfi_startproc +** xorl %edx, %edx +**.L[0-9]+: +** movl %edx, %eax +** addl \$64, %edx +** movdqa src\(%rax\), %xmm3 +** movdqa src\+16\(%rax\), %xmm2 +** movdqa src\+32\(%rax\), %xmm1 +** movdqa src\+48\(%rax\), %xmm0 +** movaps %xmm3, dest\(%rax\) +** movaps %xmm2, dest\+16\(%rax\) +** movaps %xmm1, dest\+32\(%rax\) +** movaps %xmm0, dest\+48\(%rax\) +** cmpl \$256, %edx +** jb .L[0-9]+ +** movdqa src\(%rdx\), %xmm0 +** movaps %xmm0, dest\(%rdx\) +** ret +**... +*/ + +#define SIZE (16 + 1) * 16 + +char dest[SIZE]; +char src[SIZE]; + +void +foo (void) +{ + __builtin_memcpy (dest, src, SIZE); +} + +/* { dg-final { scan-assembler-not "rep mov" } } */ diff --git a/gcc/testsuite/gcc.target/i386/memcpy-pr120683-3.c b/gcc/testsuite/gcc.target/i386/memcpy-pr120683-3.c new file mode 100644 index 0000000..e5aca32 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/memcpy-pr120683-3.c @@ -0,0 +1,43 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=x86-64 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemcpy-strategy=vector_loop:2048:noalign,libcall:-1:noalign" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */ + +/* +**foo: +**.LFB[0-9]+: +** .cfi_startproc +** xorl %edx, %edx +**.L[0-9]+: +** movl %edx, %eax +** addl \$64, %edx +** movdqa src\(%rax\), %xmm3 +** movdqa src\+16\(%rax\), %xmm2 +** movdqa src\+32\(%rax\), %xmm1 +** movdqa src\+48\(%rax\), %xmm0 +** movaps %xmm3, dest\(%rax\) +** movaps %xmm2, dest\+16\(%rax\) +** movaps %xmm1, dest\+32\(%rax\) +** movaps %xmm0, dest\+48\(%rax\) +** cmpl \$256, %edx +** jb .L[0-9]+ +** movdqa src\(%rdx\), %xmm0 +** movaps %xmm0, dest\(%rdx\) +** movdqu src\+15\(%rdx\), %xmm0 +** movups %xmm0, dest\+15\(%rdx\) +** ret +**... +*/ + +#define SIZE 16 * 16 + 31 + +char dest[SIZE]; +char src[SIZE]; + +void +foo (void) +{ + __builtin_memcpy (dest, src, SIZE); +} + +/* { dg-final { scan-assembler-not "rep mov" } } */ diff --git a/gcc/testsuite/gcc.target/i386/memcpy-pr120683-4.c b/gcc/testsuite/gcc.target/i386/memcpy-pr120683-4.c new file mode 100644 index 0000000..27f7bed --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/memcpy-pr120683-4.c @@ -0,0 +1,42 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=x86-64-v3 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemcpy-strategy=vector_loop:2048:noalign,libcall:-1:noalign" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */ + +/* +**foo: +**.LFB[0-9]+: +** .cfi_startproc +** xorl %edx, %edx +**.L[0-9]+: +** movl %edx, %eax +** subl \$-128, %edx +** vmovdqa src\(%rax\), %ymm3 +** vmovdqa src\+32\(%rax\), %ymm2 +** vmovdqa src\+64\(%rax\), %ymm1 +** vmovdqa src\+96\(%rax\), %ymm0 +** vmovdqa %ymm3, dest\(%rax\) +** vmovdqa %ymm2, dest\+32\(%rax\) +** vmovdqa %ymm1, dest\+64\(%rax\) +** vmovdqa %ymm0, dest\+96\(%rax\) +** cmpl \$512, %edx +** jb .L[0-9]+ +** vmovdqa src\(%rdx\), %ymm0 +** vmovdqa %ymm0, dest\(%rdx\) +** vzeroupper +** ret +**... +*/ + +#define SIZE (16 + 1) * 32 + +char dest[SIZE]; +char src[SIZE]; + +void +foo (void) +{ + __builtin_memcpy (dest, src, SIZE); +} + +/* { dg-final { scan-assembler-not "rep mov" } } */ diff --git a/gcc/testsuite/gcc.target/i386/memcpy-pr120683-5.c b/gcc/testsuite/gcc.target/i386/memcpy-pr120683-5.c new file mode 100644 index 0000000..34a7408 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/memcpy-pr120683-5.c @@ -0,0 +1,44 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=x86-64-v3 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemcpy-strategy=vector_loop:2048:noalign,libcall:-1:noalign" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */ + +/* +**foo: +**.LFB[0-9]+: +** .cfi_startproc +** xorl %edx, %edx +**.L[0-9]+: +** movl %edx, %eax +** subl \$-128, %edx +** vmovdqa src\(%rax\), %ymm3 +** vmovdqa src\+32\(%rax\), %ymm2 +** vmovdqa src\+64\(%rax\), %ymm1 +** vmovdqa src\+96\(%rax\), %ymm0 +** vmovdqa %ymm3, dest\(%rax\) +** vmovdqa %ymm2, dest\+32\(%rax\) +** vmovdqa %ymm1, dest\+64\(%rax\) +** vmovdqa %ymm0, dest\+96\(%rax\) +** cmpl \$512, %edx +** jb .L[0-9]+ +** vmovdqa src\(%rdx\), %ymm0 +** vmovdqa %ymm0, dest\(%rdx\) +** vmovdqu src\+31\(%rdx\), %ymm0 +** vmovdqu %ymm0, dest\+31\(%rdx\) +** vzeroupper +** ret +**... +*/ + +#define SIZE 16 * 32 + 32 + 31 + +char dest[SIZE]; +char src[SIZE]; + +void +foo (void) +{ + __builtin_memcpy (dest, src, SIZE); +} + +/* { dg-final { scan-assembler-not "rep mov" } } */ diff --git a/gcc/testsuite/gcc.target/i386/memcpy-pr120683-6.c b/gcc/testsuite/gcc.target/i386/memcpy-pr120683-6.c new file mode 100644 index 0000000..aa5d90d --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/memcpy-pr120683-6.c @@ -0,0 +1,42 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=x86-64-v4 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemcpy-strategy=vector_loop:2048:noalign,libcall:-1:noalign" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */ + +/* +**foo: +**.LFB[0-9]+: +** .cfi_startproc +** xorl %edx, %edx +**.L[0-9]+: +** movl %edx, %eax +** addl \$256, %edx +** vmovdqa64 src\(%rax\), %zmm3 +** vmovdqa64 src\+64\(%rax\), %zmm2 +** vmovdqa64 src\+128\(%rax\), %zmm1 +** vmovdqa64 src\+192\(%rax\), %zmm0 +** vmovdqa64 %zmm3, dest\(%rax\) +** vmovdqa64 %zmm2, dest\+64\(%rax\) +** vmovdqa64 %zmm1, dest\+128\(%rax\) +** vmovdqa64 %zmm0, dest\+192\(%rax\) +** cmpl \$1024, %edx +** jb .L[0-9]+ +** vmovdqa64 src\(%rdx\), %zmm0 +** vmovdqa64 %zmm0, dest\(%rdx\) +** vzeroupper +** ret +**... +*/ + +#define SIZE (16 + 1) * 64 + +char dest[SIZE] __attribute__((aligned(64))); +char src[SIZE] __attribute__((aligned(64))); + +void +foo (void) +{ + __builtin_memcpy (dest, src, SIZE); +} + +/* { dg-final { scan-assembler-not "rep mov" } } */ diff --git a/gcc/testsuite/gcc.target/i386/memcpy-pr120683-7.c b/gcc/testsuite/gcc.target/i386/memcpy-pr120683-7.c new file mode 100644 index 0000000..63d8a15 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/memcpy-pr120683-7.c @@ -0,0 +1,44 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=x86-64-v4 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemcpy-strategy=vector_loop:2048:noalign,libcall:-1:noalign" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */ + +/* +**foo: +**.LFB[0-9]+: +** .cfi_startproc +** xorl %edx, %edx +**.L[0-9]+: +** movl %edx, %eax +** addl \$256, %edx +** vmovdqa64 src\(%rax\), %zmm3 +** vmovdqa64 src\+64\(%rax\), %zmm2 +** vmovdqa64 src\+128\(%rax\), %zmm1 +** vmovdqa64 src\+192\(%rax\), %zmm0 +** vmovdqa64 %zmm3, dest\(%rax\) +** vmovdqa64 %zmm2, dest\+64\(%rax\) +** vmovdqa64 %zmm1, dest\+128\(%rax\) +** vmovdqa64 %zmm0, dest\+192\(%rax\) +** cmpl \$1024, %edx +** jb .L[0-9]+ +** vmovdqa src\(%rdx\), %ymm0 +** vmovdqa %ymm0, dest\(%rdx\) +** vmovdqu src\+31\(%rdx\), %ymm0 +** vmovdqu %ymm0, dest\+31\(%rdx\) +** vzeroupper +** ret +**... +*/ + +#define SIZE 16 * 64 + 63 + +char dest[SIZE] __attribute__((aligned(64))); +char src[SIZE] __attribute__((aligned(64))); + +void +foo (void) +{ + __builtin_memcpy (dest, src, SIZE); +} + +/* { dg-final { scan-assembler-not "rep mov" } } */ diff --git a/gcc/testsuite/gcc.target/i386/memcpy-strategy-12.c b/gcc/testsuite/gcc.target/i386/memcpy-strategy-12.c index d0316ef..c60cef0 100644 --- a/gcc/testsuite/gcc.target/i386/memcpy-strategy-12.c +++ b/gcc/testsuite/gcc.target/i386/memcpy-strategy-12.c @@ -1,14 +1,21 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -mtune=generic -mno-sse" } */ +/* { dg-options "-O2 -mtune=generic -mno-sse -fasynchronous-unwind-tables -fdwarf2-cfi-asm" } */ /* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ /* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */ /* **foo: **.LFB[0-9]+: -**... +** .cfi_startproc +** movq 221\(%rsi\), %rax ** xorl %edx, %edx -**... +** movq %rax, 221\(%rdi\) +** movq 229\(%rsi\), %rax +** movq %rax, 229\(%rdi\) +** movq 237\(%rsi\), %rax +** movq %rax, 237\(%rdi\) +** movq 245\(%rsi\), %rax +** movq %rax, 245\(%rdi\) **.L[0-9]+: ** movl %edx, %eax ** addl \$32, %edx @@ -22,6 +29,7 @@ ** movq %rcx, 24\(%rdi,%rax\) ** cmpl \$224, %edx ** jb .L[0-9]+ +** ret **... */ diff --git a/gcc/testsuite/gcc.target/i386/memset-pr120683-1.c b/gcc/testsuite/gcc.target/i386/memset-pr120683-1.c new file mode 100644 index 0000000..06e3892 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/memset-pr120683-1.c @@ -0,0 +1,35 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=x86-64 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */ + +/* +**foo: +**.LFB[0-9]+: +** .cfi_startproc +** pxor %xmm0, %xmm0 +** xorl %eax, %eax +** movups %xmm0, 190\(%rdi\) +** movups %xmm0, 206\(%rdi\) +** movups %xmm0, 222\(%rdi\) +** movups %xmm0, 238\(%rdi\) +**.L[0-9]+: +** movl %eax, %edx +** addl \$64, %eax +** movups %xmm0, \(%rdi,%rdx\) +** movups %xmm0, 16\(%rdi,%rdx\) +** movups %xmm0, 32\(%rdi,%rdx\) +** movups %xmm0, 48\(%rdi,%rdx\) +** cmpl \$192, %eax +** jb .L[0-9]+ +** ret +**... +*/ + +void +foo (char *dest) +{ + __builtin_memset (dest, 0, 254); +} + +/* { dg-final { scan-assembler-not "rep stos" } } */ diff --git a/gcc/testsuite/gcc.target/i386/memset-pr120683-10.c b/gcc/testsuite/gcc.target/i386/memset-pr120683-10.c new file mode 100644 index 0000000..36a924d --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/memset-pr120683-10.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mno-sse -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemset-strategy=unrolled_loop:256:noalign,libcall:-1:noalign" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */ + +/* +**foo: +**.LFB[0-9]+: +** .cfi_startproc +** movq \$0, 48\(%rdi\) +** movq \$0, \(%rdi\) +** movq \$0, 8\(%rdi\) +** movq \$0, 16\(%rdi\) +** movq \$0, 24\(%rdi\) +** movq \$0, 32\(%rdi\) +** movq \$0, 40\(%rdi\) +** movq \$0, 53\(%rdi\) +** ret +**... +*/ + +void +foo (char *dest) +{ + __builtin_memset (dest, 0, 61); +} + +/* { dg-final { scan-assembler-not "rep stos" } } */ diff --git a/gcc/testsuite/gcc.target/i386/memset-pr120683-11.c b/gcc/testsuite/gcc.target/i386/memset-pr120683-11.c new file mode 100644 index 0000000..4868e56 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/memset-pr120683-11.c @@ -0,0 +1,29 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mno-sse -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemset-strategy=unrolled_loop:256:noalign,libcall:-1:noalign" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */ + +/* +**foo: +**.LFB[0-9]+: +** .cfi_startproc +** movabsq \$289360691352306692, %rax +** movq %rax, 48\(%rdi\) +** movq %rax, \(%rdi\) +** movq %rax, 8\(%rdi\) +** movq %rax, 16\(%rdi\) +** movq %rax, 24\(%rdi\) +** movq %rax, 32\(%rdi\) +** movq %rax, 40\(%rdi\) +** movq %rax, 53\(%rdi\) +** ret +**... +*/ + +void +foo (char *dest) +{ + __builtin_memset (dest, 4, 61); +} + +/* { dg-final { scan-assembler-not "rep stos" } } */ diff --git a/gcc/testsuite/gcc.target/i386/memset-pr120683-12.c b/gcc/testsuite/gcc.target/i386/memset-pr120683-12.c new file mode 100644 index 0000000..9112897 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/memset-pr120683-12.c @@ -0,0 +1,31 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mno-sse -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemset-strategy=unrolled_loop:256:noalign,libcall:-1:noalign" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */ + +/* +**foo: +**.LFB[0-9]+: +** .cfi_startproc +** movabsq \$72340172838076673, %rax +** movzbl %sil, %esi +** imulq %rax, %rsi +** movq %rsi, 48\(%rdi\) +** movq %rsi, \(%rdi\) +** movq %rsi, 8\(%rdi\) +** movq %rsi, 16\(%rdi\) +** movq %rsi, 24\(%rdi\) +** movq %rsi, 32\(%rdi\) +** movq %rsi, 40\(%rdi\) +** movq %rsi, 53\(%rdi\) +** ret +**... +*/ + +void +foo (char *dest, int c) +{ + __builtin_memset (dest, c, 61); +} + +/* { dg-final { scan-assembler-not "rep stos" } } */ diff --git a/gcc/testsuite/gcc.target/i386/memset-pr120683-13.c b/gcc/testsuite/gcc.target/i386/memset-pr120683-13.c new file mode 100644 index 0000000..69ec6c6 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/memset-pr120683-13.c @@ -0,0 +1,36 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=x86-64 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */ + +/* +**foo: +**.LFB[0-9]+: +** .cfi_startproc +** pxor %xmm0, %xmm0 +** xorl %eax, %eax +**.L[0-9]+: +** movl %eax, %edx +** addl \$64, %eax +** movaps %xmm0, dest\(%rdx\) +** movaps %xmm0, dest\+16\(%rdx\) +** movaps %xmm0, dest\+32\(%rdx\) +** movaps %xmm0, dest\+48\(%rdx\) +** cmpl \$192, %eax +** jb .L[0-9]+ +** movaps %xmm0, dest\(%rax\) +** movaps %xmm0, dest\+16\(%rax\) +** movaps %xmm0, dest\+32\(%rax\) +** ret +**... +*/ + +char dest[240]; + +void +foo (void) +{ + __builtin_memset (dest, 0, sizeof (dest)); +} + +/* { dg-final { scan-assembler-not "rep stos" } } */ diff --git a/gcc/testsuite/gcc.target/i386/memset-pr120683-14.c b/gcc/testsuite/gcc.target/i386/memset-pr120683-14.c new file mode 100644 index 0000000..209cd67 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/memset-pr120683-14.c @@ -0,0 +1,91 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=x86-64 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign -minline-all-stringops" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */ + +/* +**foo: +**.LFB0: +** .cfi_startproc +** pxor %xmm0, %xmm0 +** cmpq \$64, %rsi +** jnb .L2 +** testb \$32, %sil +** jne .L19 +** testb \$16, %sil +** jne .L20 +** testb \$8, %sil +** jne .L21 +** testb \$4, %sil +** jne .L22 +** testq %rsi, %rsi +** jne .L23 +**.L1: +** ret +** .p2align 4,,10 +** .p2align 3 +**.L2: +** movups %xmm0, -64\(%rdi,%rsi\) +** movups %xmm0, -48\(%rdi,%rsi\) +** movups %xmm0, -32\(%rdi,%rsi\) +** movups %xmm0, -16\(%rdi,%rsi\) +** subq \$1, %rsi +** cmpq \$64, %rsi +** jb .L1 +** andq \$-64, %rsi +** xorl %eax, %eax +**.L9: +** movups %xmm0, \(%rdi,%rax\) +** movups %xmm0, 16\(%rdi,%rax\) +** movups %xmm0, 32\(%rdi,%rax\) +** movups %xmm0, 48\(%rdi,%rax\) +** addq \$64, %rax +** cmpq %rsi, %rax +** jb .L9 +** ret +** .p2align 4,,10 +** .p2align 3 +**.L23: +** movb \$0, \(%rdi\) +** testb \$2, %sil +** je .L1 +** xorl %eax, %eax +** movw %ax, -2\(%rdi,%rsi\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L19: +** movups %xmm0, \(%rdi\) +** movups %xmm0, 16\(%rdi\) +** movups %xmm0, -32\(%rdi,%rsi\) +** movups %xmm0, -16\(%rdi,%rsi\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L20: +** movups %xmm0, \(%rdi\) +** movups %xmm0, -16\(%rdi,%rsi\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L21: +** movq \$0, \(%rdi\) +** movq \$0, -8\(%rdi,%rsi\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L22: +** movl \$0, \(%rdi\) +** movl \$0, -4\(%rdi,%rsi\) +** ret +** .cfi_endproc +**... +*/ + +void +foo (char *dest, __SIZE_TYPE__ n) +{ + __builtin_memset (dest, 0, n); +} + +/* { dg-final { scan-assembler-not "rep stos" } } */ diff --git a/gcc/testsuite/gcc.target/i386/memset-pr120683-15.c b/gcc/testsuite/gcc.target/i386/memset-pr120683-15.c new file mode 100644 index 0000000..d19188f --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/memset-pr120683-15.c @@ -0,0 +1,103 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=x86-64-v3 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign -minline-all-stringops" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */ + +/* +**foo: +**.LFB0: +** .cfi_startproc +** vpxor %xmm0, %xmm0, %xmm0 +** cmpq \$128, %rsi +** jnb .L2 +** testb \$64, %sil +** jne .L22 +** testb \$32, %sil +** jne .L23 +** testb \$16, %sil +** jne .L24 +** testb \$8, %sil +** jne .L25 +** testb \$4, %sil +** jne .L26 +** testq %rsi, %rsi +** jne .L27 +**.L20: +** ret +** .p2align 4,,10 +** .p2align 3 +**.L2: +** vmovdqu %ymm0, -128\(%rdi,%rsi\) +** vmovdqu %ymm0, -96\(%rdi,%rsi\) +** vmovdqu %ymm0, -64\(%rdi,%rsi\) +** vmovdqu %ymm0, -32\(%rdi,%rsi\) +** subq \$1, %rsi +** cmpq \$128, %rsi +** jb .L19 +** andq \$-128, %rsi +** xorl %eax, %eax +**.L10: +** vmovdqu %ymm0, \(%rdi,%rax\) +** vmovdqu %ymm0, 32\(%rdi,%rax\) +** vmovdqu %ymm0, 64\(%rdi,%rax\) +** vmovdqu %ymm0, 96\(%rdi,%rax\) +** subq \$-128, %rax +** cmpq %rsi, %rax +** jb .L10 +**.L19: +** vzeroupper +** ret +** .p2align 4,,10 +** .p2align 3 +**.L27: +** movb \$0, \(%rdi\) +** testb \$2, %sil +** je .L20 +** xorl %eax, %eax +** movw %ax, -2\(%rdi,%rsi\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L22: +** vmovdqu %ymm0, \(%rdi\) +** vmovdqu %ymm0, 32\(%rdi\) +** vmovdqu %ymm0, -64\(%rdi,%rsi\) +** vmovdqu %ymm0, -32\(%rdi,%rsi\) +** vzeroupper +** ret +** .p2align 4,,10 +** .p2align 3 +**.L23: +** vmovdqu %ymm0, \(%rdi\) +** vmovdqu %ymm0, -32\(%rdi,%rsi\) +** vzeroupper +** ret +** .p2align 4,,10 +** .p2align 3 +**.L24: +** vmovdqu %xmm0, \(%rdi\) +** vmovdqu %xmm0, -16\(%rdi,%rsi\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L25: +** movq \$0, \(%rdi\) +** movq \$0, -8\(%rdi,%rsi\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L26: +** movl \$0, \(%rdi\) +** movl \$0, -4\(%rdi,%rsi\) +** ret +** .cfi_endproc +**... +*/ + +void +foo (char *dest, __SIZE_TYPE__ n) +{ + __builtin_memset (dest, 0, n); +} + +/* { dg-final { scan-assembler-not "rep stos" } } */ diff --git a/gcc/testsuite/gcc.target/i386/memset-pr120683-16.c b/gcc/testsuite/gcc.target/i386/memset-pr120683-16.c new file mode 100644 index 0000000..539714c --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/memset-pr120683-16.c @@ -0,0 +1,112 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=x86-64-v4 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign -minline-all-stringops" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */ + +/* +**foo: +**.LFB0: +** .cfi_startproc +** vpxor %xmm0, %xmm0, %xmm0 +** cmpq \$256, %rsi +** jnb .L2 +** testb \$-128, %sil +** jne .L23 +** testb \$64, %sil +** jne .L24 +** testb \$32, %sil +** jne .L25 +** testb \$16, %sil +** jne .L26 +** testb \$8, %sil +** jne .L27 +** testb \$4, %sil +** jne .L28 +** testq %rsi, %rsi +** jne .L29 +**.L21: +** ret +** .p2align 4,,10 +** .p2align 3 +**.L2: +** vmovdqu64 %zmm0, -256\(%rdi,%rsi\) +** vmovdqu64 %zmm0, -192\(%rdi,%rsi\) +** vmovdqu64 %zmm0, -128\(%rdi,%rsi\) +** vmovdqu64 %zmm0, -64\(%rdi,%rsi\) +** subq \$1, %rsi +** cmpq \$256, %rsi +** jb .L20 +** xorb %sil, %sil +** xorl %eax, %eax +**.L11: +** vmovdqu64 %zmm0, \(%rdi,%rax\) +** vmovdqu64 %zmm0, 64\(%rdi,%rax\) +** vmovdqu64 %zmm0, 128\(%rdi,%rax\) +** vmovdqu64 %zmm0, 192\(%rdi,%rax\) +** addq \$256, %rax +** cmpq %rsi, %rax +** jb .L11 +**.L20: +** vzeroupper +** ret +** .p2align 4,,10 +** .p2align 3 +**.L29: +** movb \$0, \(%rdi\) +** testb \$2, %sil +** je .L21 +** xorl %eax, %eax +** movw %ax, -2\(%rdi,%rsi\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L23: +** vmovdqu64 %zmm0, \(%rdi\) +** vmovdqu64 %zmm0, 64\(%rdi\) +** vmovdqu64 %zmm0, -128\(%rdi,%rsi\) +** vmovdqu64 %zmm0, -64\(%rdi,%rsi\) +** vzeroupper +** ret +** .p2align 4,,10 +** .p2align 3 +**.L24: +** vmovdqu64 %zmm0, \(%rdi\) +** vmovdqu64 %zmm0, -64\(%rdi,%rsi\) +** vzeroupper +** ret +** .p2align 4,,10 +** .p2align 3 +**.L25: +** vmovdqu %ymm0, \(%rdi\) +** vmovdqu %ymm0, -32\(%rdi,%rsi\) +** vzeroupper +** ret +** .p2align 4,,10 +** .p2align 3 +**.L26: +** vmovdqu %xmm0, \(%rdi\) +** vmovdqu %xmm0, -16\(%rdi,%rsi\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L27: +** movq \$0, \(%rdi\) +** movq \$0, -8\(%rdi,%rsi\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L28: +** movl \$0, \(%rdi\) +** movl \$0, -4\(%rdi,%rsi\) +** ret +** .cfi_endproc +**... +*/ + +void +foo (char *dest, __SIZE_TYPE__ n) +{ + __builtin_memset (dest, 0, n); +} + +/* { dg-final { scan-assembler-not "rep stos" } } */ diff --git a/gcc/testsuite/gcc.target/i386/memset-pr120683-17.c b/gcc/testsuite/gcc.target/i386/memset-pr120683-17.c new file mode 100644 index 0000000..f58cb28 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/memset-pr120683-17.c @@ -0,0 +1,37 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=x86-64 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */ + +/* +**foo: +**.LFB[0-9]+: +** .cfi_startproc +** pxor %xmm0, %xmm0 +** xorl %eax, %eax +**.L[0-9]+: +** movl %eax, %edx +** addl \$64, %eax +** movaps %xmm0, dest\(%rdx\) +** movaps %xmm0, dest\+16\(%rdx\) +** movaps %xmm0, dest\+32\(%rdx\) +** movaps %xmm0, dest\+48\(%rdx\) +** cmpl \$128, %eax +** jb .L[0-9]+ +** movq \$0, dest\+48\(%rax\) +** movaps %xmm0, dest\(%rax\) +** movaps %xmm0, dest\+16\(%rax\) +** movaps %xmm0, dest\+32\(%rax\) +** ret +**... +*/ + +char dest[184]; + +void +foo (void) +{ + __builtin_memset (dest, 0, sizeof (dest)); +} + +/* { dg-final { scan-assembler-not "rep stos" } } */ diff --git a/gcc/testsuite/gcc.target/i386/memset-pr120683-18.c b/gcc/testsuite/gcc.target/i386/memset-pr120683-18.c new file mode 100644 index 0000000..a127028 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/memset-pr120683-18.c @@ -0,0 +1,37 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=x86-64 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */ + +/* +**foo: +**.LFB[0-9]+: +** .cfi_startproc +** pxor %xmm0, %xmm0 +** xorl %eax, %eax +**.L[0-9]+: +** movl %eax, %edx +** addl \$64, %eax +** movaps %xmm0, dest\(%rdx\) +** movaps %xmm0, dest\+16\(%rdx\) +** movaps %xmm0, dest\+32\(%rdx\) +** movaps %xmm0, dest\+48\(%rdx\) +** cmpl \$128, %eax +** jb .L[0-9]+ +** movaps %xmm0, dest\+32\(%rax\) +** movaps %xmm0, dest\(%rax\) +** movl \$0, dest\+47\(%rax\) +** movaps %xmm0, dest\+16\(%rax\) +** ret +**... +*/ + +char dest[179]; + +void +foo (void) +{ + __builtin_memset (dest, 0, sizeof (dest)); +} + +/* { dg-final { scan-assembler-not "rep stos" } } */ diff --git a/gcc/testsuite/gcc.target/i386/memset-pr120683-19.c b/gcc/testsuite/gcc.target/i386/memset-pr120683-19.c new file mode 100644 index 0000000..8dd5ae6 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/memset-pr120683-19.c @@ -0,0 +1,37 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=x86-64 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */ + +/* +**foo: +**.LFB[0-9]+: +** .cfi_startproc +** pxor %xmm0, %xmm0 +** xorl %eax, %eax +**.L[0-9]+: +** movl %eax, %edx +** addl \$64, %eax +** movaps %xmm0, dest\(%rdx\) +** movaps %xmm0, dest\+16\(%rdx\) +** movaps %xmm0, dest\+32\(%rdx\) +** movaps %xmm0, dest\+48\(%rdx\) +** cmpl \$128, %eax +** jb .L[0-9]+ +** movb \$0, dest\+48\(%rax\) +** movaps %xmm0, dest\(%rax\) +** movaps %xmm0, dest\+16\(%rax\) +** movaps %xmm0, dest\+32\(%rax\) +** ret +**... +*/ + +char dest[177]; + +void +foo (void) +{ + __builtin_memset (dest, 0, sizeof (dest)); +} + +/* { dg-final { scan-assembler-not "rep stos" } } */ diff --git a/gcc/testsuite/gcc.target/i386/memset-pr120683-2.c b/gcc/testsuite/gcc.target/i386/memset-pr120683-2.c new file mode 100644 index 0000000..3b84b29 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/memset-pr120683-2.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=x86-64-v3 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */ + +/* +**foo: +**.LFB[0-9]+: +** .cfi_startproc +** vpxor %xmm0, %xmm0, %xmm0 +** vmovdqu %ymm0, 192\(%rdi\) +** vmovdqu %ymm0, \(%rdi\) +** vmovdqu %ymm0, 32\(%rdi\) +** vmovdqu %ymm0, 64\(%rdi\) +** vmovdqu %ymm0, 96\(%rdi\) +** vmovdqu %ymm0, 128\(%rdi\) +** vmovdqu %ymm0, 160\(%rdi\) +** vmovdqu %ymm0, 222\(%rdi\) +** vzeroupper +** ret +**... +*/ + +void +foo (char *dest) +{ + __builtin_memset (dest, 0, 254); +} + +/* { dg-final { scan-assembler-not "rep stos" } } */ diff --git a/gcc/testsuite/gcc.target/i386/memset-pr120683-20.c b/gcc/testsuite/gcc.target/i386/memset-pr120683-20.c new file mode 100644 index 0000000..b8b9cb7 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/memset-pr120683-20.c @@ -0,0 +1,38 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=x86-64 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */ + +/* +**foo: +**.LFB[0-9]+: +** .cfi_startproc +** movd %edi, %xmm0 +** punpcklbw %xmm0, %xmm0 +** punpcklwd %xmm0, %xmm0 +** pshufd \$0, %xmm0, %xmm0 +** movaps %xmm0, dest\+160\(%rip\) +** movaps %xmm0, dest\(%rip\) +** movaps %xmm0, dest\+16\(%rip\) +** movaps %xmm0, dest\+32\(%rip\) +** movaps %xmm0, dest\+48\(%rip\) +** movaps %xmm0, dest\+64\(%rip\) +** movaps %xmm0, dest\+80\(%rip\) +** movaps %xmm0, dest\+96\(%rip\) +** movaps %xmm0, dest\+112\(%rip\) +** movaps %xmm0, dest\+128\(%rip\) +** movaps %xmm0, dest\+144\(%rip\) +** movd %xmm0, dest\+175\(%rip\) +** ret +**... +*/ + +char dest[179]; + +void +foo (int c) +{ + __builtin_memset (dest, c, sizeof (dest)); +} + +/* { dg-final { scan-assembler-not "rep stos" } } */ diff --git a/gcc/testsuite/gcc.target/i386/memset-pr120683-21.c b/gcc/testsuite/gcc.target/i386/memset-pr120683-21.c new file mode 100644 index 0000000..3c7bb7c --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/memset-pr120683-21.c @@ -0,0 +1,38 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=x86-64 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */ + +/* +**foo: +**.LFB[0-9]+: +** .cfi_startproc +** movd %edi, %xmm0 +** movb %dil, dest\+176\(%rip\) +** punpcklbw %xmm0, %xmm0 +** punpcklwd %xmm0, %xmm0 +** pshufd \$0, %xmm0, %xmm0 +** movaps %xmm0, dest\(%rip\) +** movaps %xmm0, dest\+16\(%rip\) +** movaps %xmm0, dest\+32\(%rip\) +** movaps %xmm0, dest\+48\(%rip\) +** movaps %xmm0, dest\+64\(%rip\) +** movaps %xmm0, dest\+80\(%rip\) +** movaps %xmm0, dest\+96\(%rip\) +** movaps %xmm0, dest\+112\(%rip\) +** movaps %xmm0, dest\+128\(%rip\) +** movaps %xmm0, dest\+144\(%rip\) +** movaps %xmm0, dest\+160\(%rip\) +** ret +**... +*/ + +char dest[177]; + +void +foo (int c) +{ + __builtin_memset (dest, c, sizeof (dest)); +} + +/* { dg-final { scan-assembler-not "rep stos" } } */ diff --git a/gcc/testsuite/gcc.target/i386/memset-pr120683-22.c b/gcc/testsuite/gcc.target/i386/memset-pr120683-22.c new file mode 100644 index 0000000..96a21c8 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/memset-pr120683-22.c @@ -0,0 +1,27 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-O2 -march=x86-64 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemset-strategy=rep_8byte:8192:align,libcall:-1:noalign" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */ + +/* +**foo: +**.LFB[0-9]+: +** .cfi_startproc +** movl \$25, %ecx +** xorl %eax, %eax +** movl \$dest, %edi +** rep stosq +** movl \$0, \(%rdi\) +** ret +**... +*/ + +#define SIZE 204 + +char dest[SIZE]; + +void +foo (void) +{ + __builtin_memset (dest, 0, sizeof (dest)); +} diff --git a/gcc/testsuite/gcc.target/i386/memset-pr120683-23.c b/gcc/testsuite/gcc.target/i386/memset-pr120683-23.c new file mode 100644 index 0000000..f3f5d80 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/memset-pr120683-23.c @@ -0,0 +1,67 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=x86-64 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -minline-all-stringops -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */ + +/* +**foo: +**.LFB0: +** .cfi_startproc +** movzbl %dil, %edi +** movl \$p, %eax +** movabsq \$72340172838076673, %rdx +** imulq %rdx, %rdi +** movq %rdi, %xmm0 +** punpcklqdq %xmm0, %xmm0 +** cmpq \$64, %rsi +** jnb .L18 +**.L2: +** movq %rsi, %rcx +** andl \$63, %ecx +** je .L1 +** xorl %edx, %edx +** andl \$1, %esi +** je .L5 +** movl \$1, %edx +** movb %dil, \(%rax\) +** cmpq %rcx, %rdx +** jnb .L19 +**.L5: +** movb %dil, \(%rax,%rdx\) +** movb %dil, 1\(%rax,%rdx\) +** addq \$2, %rdx +** cmpq %rcx, %rdx +** jb .L5 +**.L1: +** ret +** .p2align 4,,10 +** .p2align 3 +**.L18: +** movq %rsi, %rdx +** xorl %eax, %eax +** andq \$-64, %rdx +**.L3: +** movaps %xmm0, p\(%rax\) +** addq \$64, %rax +** movaps %xmm0, p-48\(%rax\) +** movaps %xmm0, p-32\(%rax\) +** movaps %xmm0, p-16\(%rax\) +** cmpq %rdx, %rax +** jb .L3 +** addq \$p, %rax +** jmp .L2 +**.L19: +** ret +** .cfi_endproc +**... +*/ + + +#define WRITE_CHUNK 256 +char p[WRITE_CHUNK]; + +void +foo (int c, __SIZE_TYPE__ nbyte) +{ + __builtin_memset (p, c, nbyte); +} diff --git a/gcc/testsuite/gcc.target/i386/memset-pr120683-3.c b/gcc/testsuite/gcc.target/i386/memset-pr120683-3.c new file mode 100644 index 0000000..faa47ca --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/memset-pr120683-3.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=x86-64-v4 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */ + +/* +**foo: +**.LFB[0-9]+: +** .cfi_startproc +** vpxor %xmm0, %xmm0, %xmm0 +** vmovdqu8 %zmm0, 128\(%rdi\) +** vmovdqu8 %zmm0, \(%rdi\) +** vmovdqu8 %zmm0, 64\(%rdi\) +** vmovdqu8 %zmm0, 190\(%rdi\) +** vzeroupper +** ret +**... +*/ + +void +foo (char *dest) +{ + __builtin_memset (dest, 0, 254); +} + +/* { dg-final { scan-assembler-not "rep stos" } } */ diff --git a/gcc/testsuite/gcc.target/i386/memset-pr120683-4.c b/gcc/testsuite/gcc.target/i386/memset-pr120683-4.c new file mode 100644 index 0000000..dc3aa57b --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/memset-pr120683-4.c @@ -0,0 +1,93 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=x86-64 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign -minline-all-stringops" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */ + +/* +**foo: +**.LFB0: +** .cfi_startproc +** movabsq \$289360691352306692, %rax +** movq %rax, %xmm0 +** punpcklqdq %xmm0, %xmm0 +** cmpq \$64, %rsi +** jnb .L2 +** testb \$32, %sil +** jne .L19 +** testb \$16, %sil +** jne .L20 +** testb \$8, %sil +** jne .L21 +** testb \$4, %sil +** jne .L22 +** testq %rsi, %rsi +** jne .L23 +**.L1: +** ret +** .p2align 4,,10 +** .p2align 3 +**.L2: +** movups %xmm0, -64\(%rdi,%rsi\) +** movups %xmm0, -48\(%rdi,%rsi\) +** movups %xmm0, -32\(%rdi,%rsi\) +** movups %xmm0, -16\(%rdi,%rsi\) +** subq \$1, %rsi +** cmpq \$64, %rsi +** jb .L1 +** andq \$-64, %rsi +** xorl %eax, %eax +**.L9: +** movups %xmm0, \(%rdi,%rax\) +** movups %xmm0, 16\(%rdi,%rax\) +** movups %xmm0, 32\(%rdi,%rax\) +** movups %xmm0, 48\(%rdi,%rax\) +** addq \$64, %rax +** cmpq %rsi, %rax +** jb .L9 +** ret +** .p2align 4,,10 +** .p2align 3 +**.L23: +** movb \$4, \(%rdi\) +** testb \$2, %sil +** je .L1 +** movl \$1028, %eax +** movw %ax, -2\(%rdi,%rsi\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L19: +** movups %xmm0, \(%rdi\) +** movups %xmm0, 16\(%rdi\) +** movups %xmm0, -32\(%rdi,%rsi\) +** movups %xmm0, -16\(%rdi,%rsi\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L20: +** movups %xmm0, \(%rdi\) +** movups %xmm0, -16\(%rdi,%rsi\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L21: +** movq %rax, \(%rdi\) +** movq %rax, -8\(%rdi,%rsi\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L22: +** movl \$67372036, \(%rdi\) +** movl \$67372036, -4\(%rdi,%rsi\) +** ret +** .cfi_endproc +**... +*/ + +void +foo (char *dest, __SIZE_TYPE__ n) +{ + __builtin_memset (dest, 4, n); +} + +/* { dg-final { scan-assembler-not "rep stos" } } */ diff --git a/gcc/testsuite/gcc.target/i386/memset-pr120683-5.c b/gcc/testsuite/gcc.target/i386/memset-pr120683-5.c new file mode 100644 index 0000000..a324f8e --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/memset-pr120683-5.c @@ -0,0 +1,102 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=x86-64-v3 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign -minline-all-stringops" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */ + +/* +**foo: +**.LFB0: +** .cfi_startproc +** movabsq \$289360691352306692, %rax +** vmovq %rax, %xmm1 +** vpbroadcastq %xmm1, %ymm0 +** cmpq \$128, %rsi +** jnb .L2 +** testb \$64, %sil +** jne .L21 +** testb \$32, %sil +** jne .L22 +** testb \$16, %sil +** jne .L23 +** testb \$8, %sil +** jne .L24 +** testb \$4, %sil +** jne .L25 +** testq %rsi, %rsi +** jne .L26 +**.L19: +** vzeroupper +** ret +** .p2align 4,,10 +** .p2align 3 +**.L2: +** vmovdqu %ymm0, -128\(%rdi,%rsi\) +** vmovdqu %ymm0, -96\(%rdi,%rsi\) +** vmovdqu %ymm0, -64\(%rdi,%rsi\) +** vmovdqu %ymm0, -32\(%rdi,%rsi\) +** subq \$1, %rsi +** cmpq \$128, %rsi +** jb .L19 +** andq \$-128, %rsi +** xorl %eax, %eax +**.L10: +** vmovdqu %ymm0, \(%rdi,%rax\) +** vmovdqu %ymm0, 32\(%rdi,%rax\) +** vmovdqu %ymm0, 64\(%rdi,%rax\) +** vmovdqu %ymm0, 96\(%rdi,%rax\) +** subq \$-128, %rax +** cmpq %rsi, %rax +** jb .L10 +** jmp .L19 +** .p2align 4,,10 +** .p2align 3 +**.L26: +** movb \$4, \(%rdi\) +** testb \$2, %sil +** je .L19 +** movl \$1028, %eax +** movw %ax, -2\(%rdi,%rsi\) +** jmp .L19 +** .p2align 4,,10 +** .p2align 3 +**.L21: +** vmovdqu %ymm0, \(%rdi\) +** vmovdqu %ymm0, 32\(%rdi\) +** vmovdqu %ymm0, -64\(%rdi,%rsi\) +** vmovdqu %ymm0, -32\(%rdi,%rsi\) +** jmp .L19 +** .p2align 4,,10 +** .p2align 3 +**.L22: +** vmovdqu %ymm0, \(%rdi\) +** vmovdqu %ymm0, -32\(%rdi,%rsi\) +** jmp .L19 +** .p2align 4,,10 +** .p2align 3 +**.L23: +** vmovdqu %xmm0, \(%rdi\) +** vmovdqu %xmm0, -16\(%rdi,%rsi\) +** jmp .L19 +** .p2align 4,,10 +** .p2align 3 +**.L24: +** movq %rax, \(%rdi\) +** movq %rax, -8\(%rdi,%rsi\) +** jmp .L19 +** .p2align 4,,10 +** .p2align 3 +**.L25: +** movl \$67372036, \(%rdi\) +** movl \$67372036, -4\(%rdi,%rsi\) +** jmp .L19 +** .cfi_endproc +**... +*/ + +void +foo (char *dest, __SIZE_TYPE__ n) +{ + __builtin_memset (dest, 4, n); +} + +/* { dg-final { scan-assembler-not "rep stos" } } */ diff --git a/gcc/testsuite/gcc.target/i386/memset-pr120683-6.c b/gcc/testsuite/gcc.target/i386/memset-pr120683-6.c new file mode 100644 index 0000000..64e7589 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/memset-pr120683-6.c @@ -0,0 +1,109 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=x86-64-v4 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign -minline-all-stringops" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */ + +/* +**foo: +**.LFB0: +** .cfi_startproc +** movabsq \$289360691352306692, %rax +** vpbroadcastq %rax, %zmm0 +** cmpq \$256, %rsi +** jnb .L2 +** testb \$-128, %sil +** jne .L22 +** testb \$64, %sil +** jne .L23 +** testb \$32, %sil +** jne .L24 +** testb \$16, %sil +** jne .L25 +** testb \$8, %sil +** jne .L26 +** testb \$4, %sil +** jne .L27 +** testq %rsi, %rsi +** jne .L28 +**.L20: +** vzeroupper +** ret +** .p2align 4,,10 +** .p2align 3 +**.L2: +** vmovdqu64 %zmm0, -256\(%rdi,%rsi\) +** vmovdqu64 %zmm0, -192\(%rdi,%rsi\) +** vmovdqu64 %zmm0, -128\(%rdi,%rsi\) +** vmovdqu64 %zmm0, -64\(%rdi,%rsi\) +** subq \$1, %rsi +** cmpq \$256, %rsi +** jb .L20 +** xorb %sil, %sil +** xorl %eax, %eax +**.L11: +** vmovdqu64 %zmm0, \(%rdi,%rax\) +** vmovdqu64 %zmm0, 64\(%rdi,%rax\) +** vmovdqu64 %zmm0, 128\(%rdi,%rax\) +** vmovdqu64 %zmm0, 192\(%rdi,%rax\) +** addq \$256, %rax +** cmpq %rsi, %rax +** jb .L11 +** jmp .L20 +** .p2align 4,,10 +** .p2align 3 +**.L28: +** movb \$4, \(%rdi\) +** testb \$2, %sil +** je .L20 +** movl \$1028, %eax +** movw %ax, -2\(%rdi,%rsi\) +** jmp .L20 +** .p2align 4,,10 +** .p2align 3 +**.L22: +** vmovdqu64 %zmm0, \(%rdi\) +** vmovdqu64 %zmm0, 64\(%rdi\) +** vmovdqu64 %zmm0, -128\(%rdi,%rsi\) +** vmovdqu64 %zmm0, -64\(%rdi,%rsi\) +** jmp .L20 +** .p2align 4,,10 +** .p2align 3 +**.L23: +** vmovdqu64 %zmm0, \(%rdi\) +** vmovdqu64 %zmm0, -64\(%rdi,%rsi\) +** jmp .L20 +** .p2align 4,,10 +** .p2align 3 +**.L24: +** vmovdqu %ymm0, \(%rdi\) +** vmovdqu %ymm0, -32\(%rdi,%rsi\) +** jmp .L20 +** .p2align 4,,10 +** .p2align 3 +**.L25: +** vmovdqu %xmm0, \(%rdi\) +** vmovdqu %xmm0, -16\(%rdi,%rsi\) +** jmp .L20 +** .p2align 4,,10 +** .p2align 3 +**.L26: +** movq %rax, \(%rdi\) +** movq %rax, -8\(%rdi,%rsi\) +** jmp .L20 +** .p2align 4,,10 +** .p2align 3 +**.L27: +** movl \$67372036, \(%rdi\) +** movl \$67372036, -4\(%rdi,%rsi\) +** jmp .L20 +** .cfi_endproc +**... +*/ + +void +foo (char *dest, __SIZE_TYPE__ n) +{ + __builtin_memset (dest, 4, n); +} + +/* { dg-final { scan-assembler-not "rep stos" } } */ diff --git a/gcc/testsuite/gcc.target/i386/memset-pr120683-7.c b/gcc/testsuite/gcc.target/i386/memset-pr120683-7.c new file mode 100644 index 0000000..022f6f9 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/memset-pr120683-7.c @@ -0,0 +1,94 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=x86-64 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign -minline-all-stringops" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */ + +/* +**foo: +**.LFB0: +** .cfi_startproc +** movabsq \$72340172838076673, %rax +** movzbl %sil, %esi +** imulq %rax, %rsi +** movq %rsi, %xmm0 +** punpcklqdq %xmm0, %xmm0 +** cmpq \$64, %rdx +** jnb .L2 +** testb \$32, %dl +** jne .L19 +** testb \$16, %dl +** jne .L20 +** testb \$8, %dl +** jne .L21 +** testb \$4, %dl +** jne .L22 +** testq %rdx, %rdx +** jne .L23 +**.L1: +** ret +** .p2align 4,,10 +** .p2align 3 +**.L2: +** movups %xmm0, -64\(%rdi,%rdx\) +** movups %xmm0, -48\(%rdi,%rdx\) +** movups %xmm0, -32\(%rdi,%rdx\) +** movups %xmm0, -16\(%rdi,%rdx\) +** subq \$1, %rdx +** cmpq \$64, %rdx +** jb .L1 +** andq \$-64, %rdx +** xorl %eax, %eax +**.L9: +** movups %xmm0, \(%rdi,%rax\) +** movups %xmm0, 16\(%rdi,%rax\) +** movups %xmm0, 32\(%rdi,%rax\) +** movups %xmm0, 48\(%rdi,%rax\) +** addq \$64, %rax +** cmpq %rdx, %rax +** jb .L9 +** ret +** .p2align 4,,10 +** .p2align 3 +**.L23: +** movb %sil, \(%rdi\) +** testb \$2, %dl +** je .L1 +** movw %si, -2\(%rdi,%rdx\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L19: +** movups %xmm0, \(%rdi\) +** movups %xmm0, 16\(%rdi\) +** movups %xmm0, -32\(%rdi,%rdx\) +** movups %xmm0, -16\(%rdi,%rdx\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L20: +** movups %xmm0, \(%rdi\) +** movups %xmm0, -16\(%rdi,%rdx\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L21: +** movq %rsi, \(%rdi\) +** movq %rsi, -8\(%rdi,%rdx\) +** ret +** .p2align 4,,10 +** .p2align 3 +**.L22: +** movl %esi, \(%rdi\) +** movl %esi, -4\(%rdi,%rdx\) +** ret +** .cfi_endproc +**... +*/ + +void +foo (char *dest, int c, __SIZE_TYPE__ n) +{ + __builtin_memset (dest, c, n); +} + +/* { dg-final { scan-assembler-not "rep stos" } } */ diff --git a/gcc/testsuite/gcc.target/i386/memset-pr120683-8.c b/gcc/testsuite/gcc.target/i386/memset-pr120683-8.c new file mode 100644 index 0000000..5254e21 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/memset-pr120683-8.c @@ -0,0 +1,103 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=x86-64-v3 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign -minline-all-stringops" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */ + +/* +**foo: +**.LFB0: +** .cfi_startproc +** movabsq \$72340172838076673, %rax +** movzbl %sil, %esi +** imulq %rax, %rsi +** vmovq %rsi, %xmm1 +** vpbroadcastq %xmm1, %ymm0 +** cmpq \$128, %rdx +** jnb .L2 +** testb \$64, %dl +** jne .L21 +** testb \$32, %dl +** jne .L22 +** testb \$16, %dl +** jne .L23 +** testb \$8, %dl +** jne .L24 +** testb \$4, %dl +** jne .L25 +** testq %rdx, %rdx +** jne .L26 +**.L19: +** vzeroupper +** ret +** .p2align 4,,10 +** .p2align 3 +**.L2: +** vmovdqu %ymm0, -128\(%rdi,%rdx\) +** vmovdqu %ymm0, -96\(%rdi,%rdx\) +** vmovdqu %ymm0, -64\(%rdi,%rdx\) +** vmovdqu %ymm0, -32\(%rdi,%rdx\) +** subq \$1, %rdx +** cmpq \$128, %rdx +** jb .L19 +** andq \$-128, %rdx +** xorl %eax, %eax +**.L10: +** vmovdqu %ymm0, \(%rdi,%rax\) +** vmovdqu %ymm0, 32\(%rdi,%rax\) +** vmovdqu %ymm0, 64\(%rdi,%rax\) +** vmovdqu %ymm0, 96\(%rdi,%rax\) +** subq \$-128, %rax +** cmpq %rdx, %rax +** jb .L10 +** jmp .L19 +** .p2align 4,,10 +** .p2align 3 +**.L26: +** movb %sil, \(%rdi\) +** testb \$2, %dl +** je .L19 +** movw %si, -2\(%rdi,%rdx\) +** jmp .L19 +** .p2align 4,,10 +** .p2align 3 +**.L21: +** vmovdqu %ymm0, \(%rdi\) +** vmovdqu %ymm0, 32\(%rdi\) +** vmovdqu %ymm0, -64\(%rdi,%rdx\) +** vmovdqu %ymm0, -32\(%rdi,%rdx\) +** jmp .L19 +** .p2align 4,,10 +** .p2align 3 +**.L22: +** vmovdqu %ymm0, \(%rdi\) +** vmovdqu %ymm0, -32\(%rdi,%rdx\) +** jmp .L19 +** .p2align 4,,10 +** .p2align 3 +**.L23: +** vmovdqu %xmm0, \(%rdi\) +** vmovdqu %xmm0, -16\(%rdi,%rdx\) +** jmp .L19 +** .p2align 4,,10 +** .p2align 3 +**.L24: +** movq %rsi, \(%rdi\) +** movq %rsi, -8\(%rdi,%rdx\) +** jmp .L19 +** .p2align 4,,10 +** .p2align 3 +**.L25: +** movl %esi, \(%rdi\) +** movl %esi, -4\(%rdi,%rdx\) +** jmp .L19 +** .cfi_endproc +**... +*/ + +void +foo (char *dest, int c, __SIZE_TYPE__ n) +{ + __builtin_memset (dest, c, n); +} + +/* { dg-final { scan-assembler-not "rep stos" } } */ diff --git a/gcc/testsuite/gcc.target/i386/memset-pr120683-9.c b/gcc/testsuite/gcc.target/i386/memset-pr120683-9.c new file mode 100644 index 0000000..1719de6 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/memset-pr120683-9.c @@ -0,0 +1,110 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=x86-64-v4 -fasynchronous-unwind-tables -fdwarf2-cfi-asm -mmemset-strategy=vector_loop:256:noalign,libcall:-1:noalign -minline-all-stringops" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */ + +/* +**foo: +**.LFB0: +** .cfi_startproc +** movabsq \$72340172838076673, %rax +** movzbl %sil, %esi +** imulq %rax, %rsi +** vpbroadcastq %rsi, %zmm0 +** cmpq \$256, %rdx +** jnb .L2 +** testb \$-128, %dl +** jne .L22 +** testb \$64, %dl +** jne .L23 +** testb \$32, %dl +** jne .L24 +** testb \$16, %dl +** jne .L25 +** testb \$8, %dl +** jne .L26 +** testb \$4, %dl +** jne .L27 +** testq %rdx, %rdx +** jne .L28 +**.L20: +** vzeroupper +** ret +** .p2align 4,,10 +** .p2align 3 +**.L2: +** vmovdqu64 %zmm0, -256\(%rdi,%rdx\) +** vmovdqu64 %zmm0, -192\(%rdi,%rdx\) +** vmovdqu64 %zmm0, -128\(%rdi,%rdx\) +** vmovdqu64 %zmm0, -64\(%rdi,%rdx\) +** subq \$1, %rdx +** cmpq \$256, %rdx +** jb .L20 +** xorb %dl, %dl +** xorl %eax, %eax +**.L11: +** vmovdqu64 %zmm0, \(%rdi,%rax\) +** vmovdqu64 %zmm0, 64\(%rdi,%rax\) +** vmovdqu64 %zmm0, 128\(%rdi,%rax\) +** vmovdqu64 %zmm0, 192\(%rdi,%rax\) +** addq \$256, %rax +** cmpq %rdx, %rax +** jb .L11 +** jmp .L20 +** .p2align 4,,10 +** .p2align 3 +**.L28: +** movb %sil, \(%rdi\) +** testb \$2, %dl +** je .L20 +** movw %si, -2\(%rdi,%rdx\) +** jmp .L20 +** .p2align 4,,10 +** .p2align 3 +**.L22: +** vmovdqu64 %zmm0, \(%rdi\) +** vmovdqu64 %zmm0, 64\(%rdi\) +** vmovdqu64 %zmm0, -128\(%rdi,%rdx\) +** vmovdqu64 %zmm0, -64\(%rdi,%rdx\) +** jmp .L20 +** .p2align 4,,10 +** .p2align 3 +**.L23: +** vmovdqu64 %zmm0, \(%rdi\) +** vmovdqu64 %zmm0, -64\(%rdi,%rdx\) +** jmp .L20 +** .p2align 4,,10 +** .p2align 3 +**.L24: +** vmovdqu %ymm0, \(%rdi\) +** vmovdqu %ymm0, -32\(%rdi,%rdx\) +** jmp .L20 +** .p2align 4,,10 +** .p2align 3 +**.L25: +** vmovdqu %xmm0, \(%rdi\) +** vmovdqu %xmm0, -16\(%rdi,%rdx\) +** jmp .L20 +** .p2align 4,,10 +** .p2align 3 +**.L26: +** movq %rsi, \(%rdi\) +** movq %rsi, -8\(%rdi,%rdx\) +** jmp .L20 +** .p2align 4,,10 +** .p2align 3 +**.L27: +** movl %esi, \(%rdi\) +** movl %esi, -4\(%rdi,%rdx\) +** jmp .L20 +** .cfi_endproc +**... +*/ + +void +foo (char *dest, int c, __SIZE_TYPE__ n) +{ + __builtin_memset (dest, c, n); +} + +/* { dg-final { scan-assembler-not "rep stos" } } */ diff --git a/gcc/testsuite/gcc.target/i386/memset-strategy-25.c b/gcc/testsuite/gcc.target/i386/memset-strategy-25.c index 1cc3de7..7bd5d43 100644 --- a/gcc/testsuite/gcc.target/i386/memset-strategy-25.c +++ b/gcc/testsuite/gcc.target/i386/memset-strategy-25.c @@ -7,7 +7,11 @@ **foo: **.LFB[0-9]+: ** .cfi_startproc +** movq \$0, 221\(%rdi\) ** xorl %eax, %eax +** movq \$0, 229\(%rdi\) +** movq \$0, 237\(%rdi\) +** movq \$0, 245\(%rdi\) **.L[0-9]+: ** movl %eax, %edx ** addl \$32, %eax @@ -17,6 +21,7 @@ ** movq \$0, 24\(%rdi,%rdx\) ** cmpl \$224, %eax ** jb .L[0-9]+ +** ret **... */ diff --git a/gcc/testsuite/gcc.target/i386/memset-strategy-29.c b/gcc/testsuite/gcc.target/i386/memset-strategy-29.c index 61aef92..a33bf92 100644 --- a/gcc/testsuite/gcc.target/i386/memset-strategy-29.c +++ b/gcc/testsuite/gcc.target/i386/memset-strategy-29.c @@ -8,7 +8,11 @@ **... **.LFB[0-9]+: ** .cfi_startproc +** movq \$0, 49\(%rdi\) ** xorl %eax, %eax +** movq \$0, 57\(%rdi\) +** movq \$0, 65\(%rdi\) +** movq \$0, 73\(%rdi\) **.L[0-9]+: ** movl %eax, %edx ** addl \$32, %eax @@ -18,6 +22,7 @@ ** movq \$0, 24\(%rdi,%rdx\) ** cmpl \$64, %eax ** jb .L[0-9]+ +** ret **... */ diff --git a/gcc/testsuite/gcc.target/i386/memset-strategy-30.c b/gcc/testsuite/gcc.target/i386/memset-strategy-30.c index 917f151..f3912f8 100644 --- a/gcc/testsuite/gcc.target/i386/memset-strategy-30.c +++ b/gcc/testsuite/gcc.target/i386/memset-strategy-30.c @@ -8,7 +8,11 @@ **... **.LFB[0-9]+: ** .cfi_startproc +** movq \$0, 63\(%rdi\) ** xorl %eax, %eax +** movq \$0, 71\(%rdi\) +** movq \$0, 79\(%rdi\) +** movq \$0, 87\(%rdi\) **.L[0-9]+: ** movl %eax, %edx ** addl \$32, %eax @@ -18,6 +22,7 @@ ** movq \$0, 24\(%rdi,%rdx\) ** cmpl \$64, %eax ** jb .L[0-9]+ +** ret **... */ diff --git a/gcc/testsuite/gcc.target/i386/memset-strategy-31.c b/gcc/testsuite/gcc.target/i386/memset-strategy-31.c index 17a4df2..4791c4d 100644 --- a/gcc/testsuite/gcc.target/i386/memset-strategy-31.c +++ b/gcc/testsuite/gcc.target/i386/memset-strategy-31.c @@ -9,6 +9,10 @@ **... ** pxor %xmm0, %xmm0 ** xorl %eax, %eax +** movups %xmm0, 190\(%rdi\) +** movups %xmm0, 206\(%rdi\) +** movups %xmm0, 222\(%rdi\) +** movups %xmm0, 238\(%rdi\) **.L[0-9]+: ** movl %eax, %edx ** addl \$64, %eax diff --git a/gcc/testsuite/gcc.target/i386/vect-epilogues-3.c b/gcc/testsuite/gcc.target/i386/vect-epilogues-3.c index 0ee610f..e88ab30 100644 --- a/gcc/testsuite/gcc.target/i386/vect-epilogues-3.c +++ b/gcc/testsuite/gcc.target/i386/vect-epilogues-3.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O3 -mavx512bw -mtune=znver4 -fdump-tree-vect-optimized" } */ +/* { dg-options "-O3 -mavx512bw -mtune=znver4 --param vect-partial-vector-usage=0 -fdump-tree-vect-optimized" } */ int test (signed char *data, int n) { diff --git a/gcc/testsuite/gcc.target/i386/vect-mask-epilogue-1.c b/gcc/testsuite/gcc.target/i386/vect-mask-epilogue-1.c new file mode 100644 index 0000000..55519aa --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/vect-mask-epilogue-1.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -march=znver5 -fdump-tree-vect-optimized" } */ + +void bar (double *a, double *b, double c, int n, int m) +{ + for (int j = 0; j < m; ++j) + for (int i = 0; i < n; ++i) + a[j*n + i] = b[j*n + i] + c; +} + +/* { dg-final { scan-tree-dump "epilogue loop vectorized using masked 64 byte vectors" "vect" } } */ diff --git a/gcc/testsuite/gcc.target/i386/vect-mask-epilogue-2.c b/gcc/testsuite/gcc.target/i386/vect-mask-epilogue-2.c new file mode 100644 index 0000000..3dc28b3 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/vect-mask-epilogue-2.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -march=znver5 -fdump-tree-vect-optimized" } */ + +void foo (double *a, double b, double c, int n, int m) +{ + for (int j = 0; j < m; ++j) + for (int i = 0; i < n; ++i) + a[j*n + i] = a[j*n + i] * b + c; +} + +/* We do not want to use a masked epilogue for the inner loop as the next + outer iteration will possibly immediately read from elements masked of + the previous inner loop epilogue and that never forwards. */ +/* { dg-final { scan-tree-dump "epilogue loop vectorized using 32 byte vectors" "vect" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/amo/zabha-zacas-atomic-cas.c b/gcc/testsuite/gcc.target/riscv/amo/zabha-zacas-atomic-cas.c new file mode 100644 index 0000000..d3d84fd --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/amo/zabha-zacas-atomic-cas.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* PR target/120995 ICE unrecognized subword atomic cas */ +/* { dg-options "-O" } */ +/* { dg-add-options riscv_zacas } */ +/* { dg-add-options riscv_zabha } */ + +_Bool b; +void atomic_bool_cmpxchg() +{ + __sync_bool_compare_and_swap(&b, 1, 0); +} diff --git a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-amo-add-int.c b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-amo-add-int.c index 4cf617d..0dfe816 100644 --- a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-amo-add-int.c +++ b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-amo-add-int.c @@ -9,7 +9,7 @@ /* ** atomic_add_fetch_int_relaxed: -** 1: +**... ** lr.w\t[atx][0-9]+, 0\(a0\) ** add\t[atx][0-9]+, [atx][0-9]+, a1 ** sc.w\t[atx][0-9]+, [atx][0-9]+, 0\(a0\) @@ -23,7 +23,7 @@ void atomic_add_fetch_int_relaxed (int* bar, int baz) /* ** atomic_add_fetch_int_acquire: -** 1: +**... ** lr.w.aq\t[atx][0-9]+, 0\(a0\) ** add\t[atx][0-9]+, [atx][0-9]+, a1 ** sc.w\t[atx][0-9]+, [atx][0-9]+, 0\(a0\) @@ -37,7 +37,7 @@ void atomic_add_fetch_int_acquire (int* bar, int baz) /* ** atomic_add_fetch_int_release: -** 1: +**... ** lr.w\t[atx][0-9]+, 0\(a0\) ** add\t[atx][0-9]+, [atx][0-9]+, a1 ** sc.w.rl\t[atx][0-9]+, [atx][0-9]+, 0\(a0\) @@ -51,7 +51,7 @@ void atomic_add_fetch_int_release (int* bar, int baz) /* ** atomic_add_fetch_int_acq_rel: -** 1: +**... ** lr.w.aq\t[atx][0-9]+, 0\(a0\) ** add\t[atx][0-9]+, [atx][0-9]+, a1 ** sc.w.rl\t[atx][0-9]+, [atx][0-9]+, 0\(a0\) @@ -65,7 +65,7 @@ void atomic_add_fetch_int_acq_rel (int* bar, int baz) /* ** atomic_add_fetch_int_seq_cst: -** 1: +**... ** lr.w.aqrl\t[atx][0-9]+, 0\(a0\) ** add\t[atx][0-9]+, [atx][0-9]+, a1 ** sc.w.rl\t[atx][0-9]+, [atx][0-9]+, 0\(a0\) diff --git a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-amo-add-int.c b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-amo-add-int.c index 3fb16c0..658b040 100644 --- a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-amo-add-int.c +++ b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-amo-add-int.c @@ -9,7 +9,7 @@ /* ** atomic_add_fetch_int_relaxed: -** 1: +**... ** lr.w\t[atx][0-9]+, 0\(a0\) ** add\t[atx][0-9]+, [atx][0-9]+, a1 ** sc.w\t[atx][0-9]+, [atx][0-9]+, 0\(a0\) @@ -23,7 +23,7 @@ void atomic_add_fetch_int_relaxed (int* bar, int baz) /* ** atomic_add_fetch_int_acquire: -** 1: +**... ** lr.w\t[atx][0-9]+, 0\(a0\) ** add\t[atx][0-9]+, [atx][0-9]+, a1 ** sc.w\t[atx][0-9]+, [atx][0-9]+, 0\(a0\) @@ -37,7 +37,7 @@ void atomic_add_fetch_int_acquire (int* bar, int baz) /* ** atomic_add_fetch_int_release: -** 1: +**... ** lr.w\t[atx][0-9]+, 0\(a0\) ** add\t[atx][0-9]+, [atx][0-9]+, a1 ** sc.w\t[atx][0-9]+, [atx][0-9]+, 0\(a0\) @@ -51,7 +51,7 @@ void atomic_add_fetch_int_release (int* bar, int baz) /* ** atomic_add_fetch_int_acq_rel: -** 1: +**... ** lr.w\t[atx][0-9]+, 0\(a0\) ** add\t[atx][0-9]+, [atx][0-9]+, a1 ** sc.w\t[atx][0-9]+, [atx][0-9]+, 0\(a0\) @@ -65,7 +65,7 @@ void atomic_add_fetch_int_acq_rel (int* bar, int baz) /* ** atomic_add_fetch_int_seq_cst: -** 1: +**... ** lr.w.aqrl\t[atx][0-9]+, 0\(a0\) ** add\t[atx][0-9]+, [atx][0-9]+, a1 ** sc.w.rl\t[atx][0-9]+, [atx][0-9]+, 0\(a0\) diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_arith.h b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_arith.h index f78bdc0..9e4b4f4 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_arith.h +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_arith.h @@ -385,6 +385,8 @@ vec_sat_u_sub_##T##_fmt_1 (T *out, T *op_1, T *op_2, unsigned limit) \ out[i] = (x - y) & (-(T)(x >= y)); \ } \ } +#define DEF_VEC_SAT_U_SUB_FMT_1_WRAP(T) \ + DEF_VEC_SAT_U_SUB_FMT_1(T) #define DEF_VEC_SAT_U_SUB_FMT_2(T) \ void __attribute__((noinline)) \ @@ -398,6 +400,8 @@ vec_sat_u_sub_##T##_fmt_2 (T *out, T *op_1, T *op_2, unsigned limit) \ out[i] = (x - y) & (-(T)(x > y)); \ } \ } +#define DEF_VEC_SAT_U_SUB_FMT_2_WRAP(T) \ + DEF_VEC_SAT_U_SUB_FMT_2(T) #define DEF_VEC_SAT_U_SUB_FMT_3(T) \ void __attribute__((noinline)) \ @@ -411,6 +415,8 @@ vec_sat_u_sub_##T##_fmt_3 (T *out, T *op_1, T *op_2, unsigned limit) \ out[i] = x > y ? x - y : 0; \ } \ } +#define DEF_VEC_SAT_U_SUB_FMT_3_WRAP(T) \ + DEF_VEC_SAT_U_SUB_FMT_3(T) #define DEF_VEC_SAT_U_SUB_FMT_4(T) \ void __attribute__((noinline)) \ @@ -424,6 +430,8 @@ vec_sat_u_sub_##T##_fmt_4 (T *out, T *op_1, T *op_2, unsigned limit) \ out[i] = x >= y ? x - y : 0; \ } \ } +#define DEF_VEC_SAT_U_SUB_FMT_4_WRAP(T) \ + DEF_VEC_SAT_U_SUB_FMT_4(T) #define DEF_VEC_SAT_U_SUB_FMT_5(T) \ void __attribute__((noinline)) \ @@ -437,6 +445,8 @@ vec_sat_u_sub_##T##_fmt_5 (T *out, T *op_1, T *op_2, unsigned limit) \ out[i] = x < y ? 0 : x - y; \ } \ } +#define DEF_VEC_SAT_U_SUB_FMT_5_WRAP(T) \ + DEF_VEC_SAT_U_SUB_FMT_5(T) #define DEF_VEC_SAT_U_SUB_FMT_6(T) \ void __attribute__((noinline)) \ @@ -450,6 +460,8 @@ vec_sat_u_sub_##T##_fmt_6 (T *out, T *op_1, T *op_2, unsigned limit) \ out[i] = x <= y ? 0 : x - y; \ } \ } +#define DEF_VEC_SAT_U_SUB_FMT_6_WRAP(T) \ + DEF_VEC_SAT_U_SUB_FMT_6(T) #define DEF_VEC_SAT_U_SUB_FMT_7(T) \ void __attribute__((noinline)) \ @@ -465,6 +477,8 @@ vec_sat_u_sub_##T##_fmt_7 (T *out, T *op_1, T *op_2, unsigned limit) \ out[i] = ret & (T)(overflow - 1); \ } \ } +#define DEF_VEC_SAT_U_SUB_FMT_7_WRAP(T) \ + DEF_VEC_SAT_U_SUB_FMT_7(T) #define DEF_VEC_SAT_U_SUB_FMT_8(T) \ void __attribute__((noinline)) \ @@ -480,6 +494,8 @@ vec_sat_u_sub_##T##_fmt_8 (T *out, T *op_1, T *op_2, unsigned limit) \ out[i] = ret & (T)-(!overflow); \ } \ } +#define DEF_VEC_SAT_U_SUB_FMT_8_WRAP(T) \ + DEF_VEC_SAT_U_SUB_FMT_8(T) #define DEF_VEC_SAT_U_SUB_FMT_9(T) \ void __attribute__((noinline)) \ @@ -495,6 +511,8 @@ vec_sat_u_sub_##T##_fmt_9 (T *out, T *op_1, T *op_2, unsigned limit) \ out[i] = overflow ? 0 : ret; \ } \ } +#define DEF_VEC_SAT_U_SUB_FMT_9_WRAP(T) \ + DEF_VEC_SAT_U_SUB_FMT_9(T) #define DEF_VEC_SAT_U_SUB_FMT_10(T) \ void __attribute__((noinline)) \ @@ -510,6 +528,8 @@ vec_sat_u_sub_##T##_fmt_10 (T *out, T *op_1, T *op_2, unsigned limit) \ out[i] = !overflow ? ret : 0; \ } \ } +#define DEF_VEC_SAT_U_SUB_FMT_10_WRAP(T) \ + DEF_VEC_SAT_U_SUB_FMT_10(T) #define DEF_VEC_SAT_U_SUB_ZIP(T1, T2) \ void __attribute__((noinline)) \ @@ -669,33 +689,53 @@ vec_sat_s_sub_##T##_fmt_4 (T *out, T *op_1, T *op_2, unsigned limit) \ #define RUN_VEC_SAT_U_SUB_FMT_1(T, out, op_1, op_2, N) \ vec_sat_u_sub_##T##_fmt_1(out, op_1, op_2, N) +#define RUN_VEC_SAT_U_SUB_FMT_1_WRAP(T, out, op_1, op_2, N) \ + RUN_VEC_SAT_U_SUB_FMT_1(T, out, op_1, op_2, N) #define RUN_VEC_SAT_U_SUB_FMT_2(T, out, op_1, op_2, N) \ vec_sat_u_sub_##T##_fmt_2(out, op_1, op_2, N) +#define RUN_VEC_SAT_U_SUB_FMT_2_WRAP(T, out, op_1, op_2, N) \ + RUN_VEC_SAT_U_SUB_FMT_2(T, out, op_1, op_2, N) #define RUN_VEC_SAT_U_SUB_FMT_3(T, out, op_1, op_2, N) \ vec_sat_u_sub_##T##_fmt_3(out, op_1, op_2, N) +#define RUN_VEC_SAT_U_SUB_FMT_3_WRAP(T, out, op_1, op_2, N) \ + RUN_VEC_SAT_U_SUB_FMT_3(T, out, op_1, op_2, N) #define RUN_VEC_SAT_U_SUB_FMT_4(T, out, op_1, op_2, N) \ vec_sat_u_sub_##T##_fmt_4(out, op_1, op_2, N) +#define RUN_VEC_SAT_U_SUB_FMT_4_WRAP(T, out, op_1, op_2, N) \ + RUN_VEC_SAT_U_SUB_FMT_4(T, out, op_1, op_2, N) #define RUN_VEC_SAT_U_SUB_FMT_5(T, out, op_1, op_2, N) \ vec_sat_u_sub_##T##_fmt_5(out, op_1, op_2, N) +#define RUN_VEC_SAT_U_SUB_FMT_5_WRAP(T, out, op_1, op_2, N) \ + RUN_VEC_SAT_U_SUB_FMT_5(T, out, op_1, op_2, N) #define RUN_VEC_SAT_U_SUB_FMT_6(T, out, op_1, op_2, N) \ vec_sat_u_sub_##T##_fmt_6(out, op_1, op_2, N) +#define RUN_VEC_SAT_U_SUB_FMT_6_WRAP(T, out, op_1, op_2, N) \ + RUN_VEC_SAT_U_SUB_FMT_6(T, out, op_1, op_2, N) #define RUN_VEC_SAT_U_SUB_FMT_7(T, out, op_1, op_2, N) \ vec_sat_u_sub_##T##_fmt_7(out, op_1, op_2, N) +#define RUN_VEC_SAT_U_SUB_FMT_7_WRAP(T, out, op_1, op_2, N) \ + RUN_VEC_SAT_U_SUB_FMT_7(T, out, op_1, op_2, N) #define RUN_VEC_SAT_U_SUB_FMT_8(T, out, op_1, op_2, N) \ vec_sat_u_sub_##T##_fmt_8(out, op_1, op_2, N) +#define RUN_VEC_SAT_U_SUB_FMT_8_WRAP(T, out, op_1, op_2, N) \ + RUN_VEC_SAT_U_SUB_FMT_8(T, out, op_1, op_2, N) #define RUN_VEC_SAT_U_SUB_FMT_9(T, out, op_1, op_2, N) \ vec_sat_u_sub_##T##_fmt_9(out, op_1, op_2, N) +#define RUN_VEC_SAT_U_SUB_FMT_9_WRAP(T, out, op_1, op_2, N) \ + RUN_VEC_SAT_U_SUB_FMT_9(T, out, op_1, op_2, N) #define RUN_VEC_SAT_U_SUB_FMT_10(T, out, op_1, op_2, N) \ vec_sat_u_sub_##T##_fmt_10(out, op_1, op_2, N) +#define RUN_VEC_SAT_U_SUB_FMT_10_WRAP(T, out, op_1, op_2, N) \ + RUN_VEC_SAT_U_SUB_FMT_10(T, out, op_1, op_2, N) #define RUN_VEC_SAT_U_SUB_FMT_ZIP(T1, T2, x, b, N) \ vec_sat_u_sub_##T1##_##T2##_fmt_zip(x, b, N) diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_data.h b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_data.h index 9f05c0c..4469f0e 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_data.h +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_data.h @@ -744,6 +744,258 @@ uint64_t TEST_UNARY_DATA(uint64_t, sat_u_sub_imm)[][2][N] = }, }; +uint8_t TEST_UNARY_DATA(uint8_t, usub)[][3][N] = { + { + { + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + }, /* arg_0 */ + { + 0, 1, 2, 3, + 0, 1, 2, 3, + 0, 1, 2, 3, + 0, 1, 2, 3, + }, /* arg_1 */ + { + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + }, /* expect */ + }, + { + { + 0, 255, 255, 255, + 0, 255, 255, 255, + 0, 255, 255, 255, + 0, 255, 255, 255, + }, + { + 1, 255, 254, 251, + 1, 255, 254, 251, + 1, 255, 254, 251, + 1, 255, 254, 251, + }, + { + 0, 0, 1, 4, + 0, 0, 1, 4, + 0, 0, 1, 4, + 0, 0, 1, 4, + }, + }, + { + { + 0, 0, 1, 0, + 1, 2, 3, 0, + 1, 2, 3, 255, + 5, 254, 255, 9, + }, + { + 0, 1, 0, 254, + 254, 254, 254, 255, + 255, 255, 0, 252, + 255, 255, 255, 1, + }, + { + 0, 0, 1, 0, + 0, 0, 0, 0, + 0, 0, 3, 3, + 0, 0, 0, 8, + }, + }, +}; + +uint16_t TEST_UNARY_DATA(uint16_t, usub)[][3][N] = { + { + { + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + }, /* arg_0 */ + { + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + }, /* arg_1 */ + { + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + }, /* expect */ + }, + { + { + 65535, 65535, 65535, 65535, + 65535, 65535, 65535, 65535, + 65535, 65535, 65535, 65535, + 65535, 65535, 65535, 65535, + }, + { + 55535, 45535, 35535, 25535, + 55535, 45535, 35535, 25535, + 55535, 45535, 35535, 25535, + 55535, 45535, 35535, 25535, + }, + { + 10000, 20000, 30000, 40000, + 10000, 20000, 30000, 40000, + 10000, 20000, 30000, 40000, + 10000, 20000, 30000, 40000, + }, + }, + { + { + 0, 0, 1, 0, + 1, 2, 3, 0, + 1, 65535, 3, 65535, + 5, 65534, 65535, 9, + }, + { + 0, 1, 1, 65534, + 65534, 65534, 1, 65535, + 0, 65535, 65535, 0, + 65535, 65535, 1, 2, + }, + { + 0, 0, 0, 0, + 0, 0, 2, 0, + 1, 0, 0, 65535, + 0, 0, 65534, 7, + }, + }, +}; + +uint32_t TEST_UNARY_DATA(uint32_t, usub)[][3][N] = { + { + { + 0, 0, 4, 0, + 0, 0, 4, 0, + 0, 0, 4, 0, + 0, 0, 4, 0, + }, /* arg_0 */ + { + 0, 1, 2, 3, + 0, 1, 2, 3, + 0, 1, 2, 3, + 0, 1, 2, 3, + }, /* arg_1 */ + { + 0, 0, 2, 0, + 0, 0, 2, 0, + 0, 0, 2, 0, + 0, 0, 2, 0, + }, /* expect */ + }, + { + { + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + 4294967295, 4294967295, 4294967295, 4294967295, + }, + { + 1294967295, 2294967295, 3294967295, 4294967295, + 1294967295, 2294967295, 3294967295, 4294967295, + 1294967295, 2294967295, 3294967295, 4294967295, + 1294967295, 2294967295, 3294967295, 4294967295, + }, + { + 3000000000, 2000000000, 1000000000, 0, + 3000000000, 2000000000, 1000000000, 0, + 3000000000, 2000000000, 1000000000, 0, + 3000000000, 2000000000, 1000000000, 0, + }, + }, + { + { + 0, 0, 9, 0, + 1, 4294967295, 3, 0, + 1, 2, 3, 4, + 5, 4294967294, 4294967295, 4294967295, + }, + { + 0, 1, 1, 4294967294, + 1, 2, 4294967294, 4294967295, + 1, 4294967295, 4294967295, 1, + 1, 4294967295, 4294967290, 9, + }, + { + 0, 0, 8, 0, + 0, 4294967293, 0, 0, + 0, 0, 0, 3, + 4, 0, 5, 4294967286, + }, + }, +}; + +uint64_t TEST_UNARY_DATA(uint64_t, usub)[][3][N] = { + { + { + 0, 9, 0, 0, + 0, 9, 0, 0, + 0, 9, 0, 0, + 0, 9, 0, 0, + }, /* arg_0 */ + { + 0, 2, 3, 1, + 0, 2, 3, 1, + 0, 2, 3, 1, + 0, 2, 3, 1, + }, /* arg_1 */ + { + 0, 7, 0, 0, + 0, 7, 0, 0, + 0, 7, 0, 0, + 0, 7, 0, 0, + }, /* expect */ + }, + { + { + 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, + 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, + 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, + 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, + }, + { + 10446744073709551615u, 11446744073709551615u, 12446744073709551615u, 18446744073709551615u, + 10446744073709551615u, 11446744073709551615u, 12446744073709551615u, 18446744073709551615u, + 10446744073709551615u, 11446744073709551615u, 12446744073709551615u, 18446744073709551615u, + 10446744073709551615u, 11446744073709551615u, 12446744073709551615u, 18446744073709551615u, + }, + { + 8000000000000000000u, 7000000000000000000u, 6000000000000000000u, 0u, + 8000000000000000000u, 7000000000000000000u, 6000000000000000000u, 0u, + 8000000000000000000u, 7000000000000000000u, 6000000000000000000u, 0u, + 8000000000000000000u, 7000000000000000000u, 6000000000000000000u, 0u, + }, + }, + { + { + 0, 18446744073709551615u, 1, 0, + 1, 18446744073709551615u, 3, 0, + 1, 18446744073709551614u, 3, 4, + 5, 18446744073709551614u, 18446744073709551615u, 9, + }, + { + 0, 1, 1, 18446744073709551614u, + 18446744073709551614u, 18446744073709551614u, 18446744073709551614u, 18446744073709551615u, + 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, + 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 1, + }, + { + 0, 18446744073709551614u, 0, 0, + 0, 1, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 8, + }, + }, +}; + int8_t TEST_UNARY_DATA(int8_t, sat_s_add_imm)[][2][N] = { { /* For add imm -128 */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-1-u16.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-1-u16.c index 97e5040..5fc747b 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-1-u16.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-1-u16.c @@ -2,74 +2,14 @@ /* { dg-additional-options "-std=c99" } */ #include "vec_sat_arith.h" +#include "vec_sat_data.h" #define T uint16_t -#define N 16 -#define RUN_VEC_SAT_BINARY RUN_VEC_SAT_U_SUB_FMT_1 -DEF_VEC_SAT_U_SUB_FMT_1(T) +DEF_VEC_SAT_U_SUB_FMT_1_WRAP(T) -T test_data[][3][N] = { - { - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - }, /* arg_0 */ - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - }, /* arg_1 */ - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - }, /* expect */ - }, - { - { - 65535, 65535, 65535, 65535, - 65535, 65535, 65535, 65535, - 65535, 65535, 65535, 65535, - 65535, 65535, 65535, 65535, - }, - { - 55535, 45535, 35535, 25535, - 55535, 45535, 35535, 25535, - 55535, 45535, 35535, 25535, - 55535, 45535, 35535, 25535, - }, - { - 10000, 20000, 30000, 40000, - 10000, 20000, 30000, 40000, - 10000, 20000, 30000, 40000, - 10000, 20000, 30000, 40000, - }, - }, - { - { - 0, 0, 1, 0, - 1, 2, 3, 0, - 1, 65535, 3, 65535, - 5, 65534, 65535, 9, - }, - { - 0, 1, 1, 65534, - 65534, 65534, 1, 65535, - 0, 65535, 65535, 0, - 65535, 65535, 1, 2, - }, - { - 0, 0, 0, 0, - 0, 0, 2, 0, - 1, 0, 0, 65535, - 0, 0, 65534, 7, - }, - }, -}; +#define test_data TEST_UNARY_DATA_WRAP(T, usub) +#define RUN_VEC_SAT_BINARY(T, out, op_1, op_2, N) \ + RUN_VEC_SAT_U_SUB_FMT_1_WRAP(T, out, op_1, op_2, N) #include "vec_sat_binary_vvv_run.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-1-u32.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-1-u32.c index a5428c4..c9976d0 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-1-u32.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-1-u32.c @@ -2,74 +2,14 @@ /* { dg-additional-options "-std=c99" } */ #include "vec_sat_arith.h" +#include "vec_sat_data.h" #define T uint32_t -#define N 16 -#define RUN_VEC_SAT_BINARY RUN_VEC_SAT_U_SUB_FMT_1 -DEF_VEC_SAT_U_SUB_FMT_1(T) +DEF_VEC_SAT_U_SUB_FMT_1_WRAP(T) -T test_data[][3][N] = { - { - { - 0, 0, 4, 0, - 0, 0, 4, 0, - 0, 0, 4, 0, - 0, 0, 4, 0, - }, /* arg_0 */ - { - 0, 1, 2, 3, - 0, 1, 2, 3, - 0, 1, 2, 3, - 0, 1, 2, 3, - }, /* arg_1 */ - { - 0, 0, 2, 0, - 0, 0, 2, 0, - 0, 0, 2, 0, - 0, 0, 2, 0, - }, /* expect */ - }, - { - { - 4294967295, 4294967295, 4294967295, 4294967295, - 4294967295, 4294967295, 4294967295, 4294967295, - 4294967295, 4294967295, 4294967295, 4294967295, - 4294967295, 4294967295, 4294967295, 4294967295, - }, - { - 1294967295, 2294967295, 3294967295, 4294967295, - 1294967295, 2294967295, 3294967295, 4294967295, - 1294967295, 2294967295, 3294967295, 4294967295, - 1294967295, 2294967295, 3294967295, 4294967295, - }, - { - 3000000000, 2000000000, 1000000000, 0, - 3000000000, 2000000000, 1000000000, 0, - 3000000000, 2000000000, 1000000000, 0, - 3000000000, 2000000000, 1000000000, 0, - }, - }, - { - { - 0, 0, 9, 0, - 1, 4294967295, 3, 0, - 1, 2, 3, 4, - 5, 4294967294, 4294967295, 4294967295, - }, - { - 0, 1, 1, 4294967294, - 1, 2, 4294967294, 4294967295, - 1, 4294967295, 4294967295, 1, - 1, 4294967295, 4294967290, 9, - }, - { - 0, 0, 8, 0, - 0, 4294967293, 0, 0, - 0, 0, 0, 3, - 4, 0, 5, 4294967286, - }, - }, -}; +#define test_data TEST_UNARY_DATA_WRAP(T, usub) +#define RUN_VEC_SAT_BINARY(T, out, op_1, op_2, N) \ + RUN_VEC_SAT_U_SUB_FMT_1_WRAP(T, out, op_1, op_2, N) #include "vec_sat_binary_vvv_run.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-1-u64.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-1-u64.c index bdb65d9..10a0b0c 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-1-u64.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-1-u64.c @@ -2,74 +2,14 @@ /* { dg-additional-options "-std=c99" } */ #include "vec_sat_arith.h" +#include "vec_sat_data.h" #define T uint64_t -#define N 16 -#define RUN_VEC_SAT_BINARY RUN_VEC_SAT_U_SUB_FMT_1 -DEF_VEC_SAT_U_SUB_FMT_1(T) +DEF_VEC_SAT_U_SUB_FMT_1_WRAP(T) -T test_data[][3][N] = { - { - { - 0, 9, 0, 0, - 0, 9, 0, 0, - 0, 9, 0, 0, - 0, 9, 0, 0, - }, /* arg_0 */ - { - 0, 2, 3, 1, - 0, 2, 3, 1, - 0, 2, 3, 1, - 0, 2, 3, 1, - }, /* arg_1 */ - { - 0, 7, 0, 0, - 0, 7, 0, 0, - 0, 7, 0, 0, - 0, 7, 0, 0, - }, /* expect */ - }, - { - { - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, - }, - { - 10446744073709551615u, 11446744073709551615u, 12446744073709551615u, 18446744073709551615u, - 10446744073709551615u, 11446744073709551615u, 12446744073709551615u, 18446744073709551615u, - 10446744073709551615u, 11446744073709551615u, 12446744073709551615u, 18446744073709551615u, - 10446744073709551615u, 11446744073709551615u, 12446744073709551615u, 18446744073709551615u, - }, - { - 8000000000000000000u, 7000000000000000000u, 6000000000000000000u, 0u, - 8000000000000000000u, 7000000000000000000u, 6000000000000000000u, 0u, - 8000000000000000000u, 7000000000000000000u, 6000000000000000000u, 0u, - 8000000000000000000u, 7000000000000000000u, 6000000000000000000u, 0u, - }, - }, - { - { - 0, 18446744073709551615u, 1, 0, - 1, 18446744073709551615u, 3, 0, - 1, 18446744073709551614u, 3, 4, - 5, 18446744073709551614u, 18446744073709551615u, 9, - }, - { - 0, 1, 1, 18446744073709551614u, - 18446744073709551614u, 18446744073709551614u, 18446744073709551614u, 18446744073709551615u, - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 1, - }, - { - 0, 18446744073709551614u, 0, 0, - 0, 1, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 8, - }, - }, -}; +#define test_data TEST_UNARY_DATA_WRAP(T, usub) +#define RUN_VEC_SAT_BINARY(T, out, op_1, op_2, N) \ + RUN_VEC_SAT_U_SUB_FMT_1_WRAP(T, out, op_1, op_2, N) #include "vec_sat_binary_vvv_run.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-1-u8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-1-u8.c index 3fe5fe3..7b22863 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-1-u8.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-1-u8.c @@ -2,74 +2,15 @@ /* { dg-additional-options "-std=c99" } */ #include "vec_sat_arith.h" +#include "vec_sat_data.h" #define T uint8_t -#define N 16 -#define RUN_VEC_SAT_BINARY RUN_VEC_SAT_U_SUB_FMT_1 -DEF_VEC_SAT_U_SUB_FMT_1(T) +DEF_VEC_SAT_U_SUB_FMT_1_WRAP(T) + +#define test_data TEST_UNARY_DATA_WRAP(T, usub) +#define RUN_VEC_SAT_BINARY(T, out, op_1, op_2, N) \ + RUN_VEC_SAT_U_SUB_FMT_1_WRAP(T, out, op_1, op_2, N) -T test_data[][3][N] = { - { - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - }, /* arg_0 */ - { - 0, 1, 2, 3, - 0, 1, 2, 3, - 0, 1, 2, 3, - 0, 1, 2, 3, - }, /* arg_1 */ - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - }, /* expect */ - }, - { - { - 0, 255, 255, 255, - 0, 255, 255, 255, - 0, 255, 255, 255, - 0, 255, 255, 255, - }, - { - 1, 255, 254, 251, - 1, 255, 254, 251, - 1, 255, 254, 251, - 1, 255, 254, 251, - }, - { - 0, 0, 1, 4, - 0, 0, 1, 4, - 0, 0, 1, 4, - 0, 0, 1, 4, - }, - }, - { - { - 0, 0, 1, 0, - 1, 2, 3, 0, - 1, 2, 3, 255, - 5, 254, 255, 9, - }, - { - 0, 1, 0, 254, - 254, 254, 254, 255, - 255, 255, 0, 252, - 255, 255, 255, 1, - }, - { - 0, 0, 1, 0, - 0, 0, 0, 0, - 0, 0, 3, 3, - 0, 0, 0, 8, - }, - }, -}; #include "vec_sat_binary_vvv_run.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-10-u16.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-10-u16.c index 0f4129c..a6b2dc4 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-10-u16.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-10-u16.c @@ -2,74 +2,14 @@ /* { dg-additional-options "-std=c99" } */ #include "vec_sat_arith.h" +#include "vec_sat_data.h" #define T uint16_t -#define N 16 -#define RUN_VEC_SAT_BINARY RUN_VEC_SAT_U_SUB_FMT_10 -DEF_VEC_SAT_U_SUB_FMT_10(T) +DEF_VEC_SAT_U_SUB_FMT_10_WRAP(T) -T test_data[][3][N] = { - { - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - }, /* arg_0 */ - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - }, /* arg_1 */ - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - }, /* expect */ - }, - { - { - 65535, 65535, 65535, 65535, - 65535, 65535, 65535, 65535, - 65535, 65535, 65535, 65535, - 65535, 65535, 65535, 65535, - }, - { - 55535, 45535, 35535, 25535, - 55535, 45535, 35535, 25535, - 55535, 45535, 35535, 25535, - 55535, 45535, 35535, 25535, - }, - { - 10000, 20000, 30000, 40000, - 10000, 20000, 30000, 40000, - 10000, 20000, 30000, 40000, - 10000, 20000, 30000, 40000, - }, - }, - { - { - 0, 0, 1, 0, - 1, 2, 3, 0, - 1, 65535, 3, 65535, - 5, 65534, 65535, 9, - }, - { - 0, 1, 1, 65534, - 65534, 65534, 1, 65535, - 0, 65535, 65535, 0, - 65535, 65535, 1, 2, - }, - { - 0, 0, 0, 0, - 0, 0, 2, 0, - 1, 0, 0, 65535, - 0, 0, 65534, 7, - }, - }, -}; +#define test_data TEST_UNARY_DATA_WRAP(T, usub) +#define RUN_VEC_SAT_BINARY(T, out, op_1, op_2, N) \ + RUN_VEC_SAT_U_SUB_FMT_10_WRAP(T, out, op_1, op_2, N) #include "vec_sat_binary_vvv_run.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-10-u32.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-10-u32.c index 8b995eb..91e749e 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-10-u32.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-10-u32.c @@ -2,74 +2,14 @@ /* { dg-additional-options "-std=c99" } */ #include "vec_sat_arith.h" +#include "vec_sat_data.h" #define T uint32_t -#define N 16 -#define RUN_VEC_SAT_BINARY RUN_VEC_SAT_U_SUB_FMT_10 -DEF_VEC_SAT_U_SUB_FMT_10(T) +DEF_VEC_SAT_U_SUB_FMT_10_WRAP(T) -T test_data[][3][N] = { - { - { - 0, 0, 4, 0, - 0, 0, 4, 0, - 0, 0, 4, 0, - 0, 0, 4, 0, - }, /* arg_0 */ - { - 0, 1, 2, 3, - 0, 1, 2, 3, - 0, 1, 2, 3, - 0, 1, 2, 3, - }, /* arg_1 */ - { - 0, 0, 2, 0, - 0, 0, 2, 0, - 0, 0, 2, 0, - 0, 0, 2, 0, - }, /* expect */ - }, - { - { - 4294967295, 4294967295, 4294967295, 4294967295, - 4294967295, 4294967295, 4294967295, 4294967295, - 4294967295, 4294967295, 4294967295, 4294967295, - 4294967295, 4294967295, 4294967295, 4294967295, - }, - { - 1294967295, 2294967295, 3294967295, 4294967295, - 1294967295, 2294967295, 3294967295, 4294967295, - 1294967295, 2294967295, 3294967295, 4294967295, - 1294967295, 2294967295, 3294967295, 4294967295, - }, - { - 3000000000, 2000000000, 1000000000, 0, - 3000000000, 2000000000, 1000000000, 0, - 3000000000, 2000000000, 1000000000, 0, - 3000000000, 2000000000, 1000000000, 0, - }, - }, - { - { - 0, 0, 9, 0, - 1, 4294967295, 3, 0, - 1, 2, 3, 4, - 5, 4294967294, 4294967295, 4294967295, - }, - { - 0, 1, 1, 4294967294, - 1, 2, 4294967294, 4294967295, - 1, 4294967295, 4294967295, 1, - 1, 4294967295, 4294967290, 9, - }, - { - 0, 0, 8, 0, - 0, 4294967293, 0, 0, - 0, 0, 0, 3, - 4, 0, 5, 4294967286, - }, - }, -}; +#define test_data TEST_UNARY_DATA_WRAP(T, usub) +#define RUN_VEC_SAT_BINARY(T, out, op_1, op_2, N) \ + RUN_VEC_SAT_U_SUB_FMT_10_WRAP(T, out, op_1, op_2, N) #include "vec_sat_binary_vvv_run.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-10-u64.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-10-u64.c index d12d981..b7a6314 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-10-u64.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-10-u64.c @@ -2,74 +2,14 @@ /* { dg-additional-options "-std=c99" } */ #include "vec_sat_arith.h" +#include "vec_sat_data.h" #define T uint64_t -#define N 16 -#define RUN_VEC_SAT_BINARY RUN_VEC_SAT_U_SUB_FMT_10 -DEF_VEC_SAT_U_SUB_FMT_10(T) +DEF_VEC_SAT_U_SUB_FMT_10_WRAP(T) -T test_data[][3][N] = { - { - { - 0, 9, 0, 0, - 0, 9, 0, 0, - 0, 9, 0, 0, - 0, 9, 0, 0, - }, /* arg_0 */ - { - 0, 2, 3, 1, - 0, 2, 3, 1, - 0, 2, 3, 1, - 0, 2, 3, 1, - }, /* arg_1 */ - { - 0, 7, 0, 0, - 0, 7, 0, 0, - 0, 7, 0, 0, - 0, 7, 0, 0, - }, /* expect */ - }, - { - { - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, - }, - { - 10446744073709551615u, 11446744073709551615u, 12446744073709551615u, 18446744073709551615u, - 10446744073709551615u, 11446744073709551615u, 12446744073709551615u, 18446744073709551615u, - 10446744073709551615u, 11446744073709551615u, 12446744073709551615u, 18446744073709551615u, - 10446744073709551615u, 11446744073709551615u, 12446744073709551615u, 18446744073709551615u, - }, - { - 8000000000000000000u, 7000000000000000000u, 6000000000000000000u, 0u, - 8000000000000000000u, 7000000000000000000u, 6000000000000000000u, 0u, - 8000000000000000000u, 7000000000000000000u, 6000000000000000000u, 0u, - 8000000000000000000u, 7000000000000000000u, 6000000000000000000u, 0u, - }, - }, - { - { - 0, 18446744073709551615u, 1, 0, - 1, 18446744073709551615u, 3, 0, - 1, 18446744073709551614u, 3, 4, - 5, 18446744073709551614u, 18446744073709551615u, 9, - }, - { - 0, 1, 1, 18446744073709551614u, - 18446744073709551614u, 18446744073709551614u, 18446744073709551614u, 18446744073709551615u, - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 1, - }, - { - 0, 18446744073709551614u, 0, 0, - 0, 1, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 8, - }, - }, -}; +#define test_data TEST_UNARY_DATA_WRAP(T, usub) +#define RUN_VEC_SAT_BINARY(T, out, op_1, op_2, N) \ + RUN_VEC_SAT_U_SUB_FMT_10_WRAP(T, out, op_1, op_2, N) #include "vec_sat_binary_vvv_run.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-10-u8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-10-u8.c index 384ef3e..1d55798 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-10-u8.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-10-u8.c @@ -2,74 +2,14 @@ /* { dg-additional-options "-std=c99" } */ #include "vec_sat_arith.h" +#include "vec_sat_data.h" #define T uint8_t -#define N 16 -#define RUN_VEC_SAT_BINARY RUN_VEC_SAT_U_SUB_FMT_10 -DEF_VEC_SAT_U_SUB_FMT_10(T) +DEF_VEC_SAT_U_SUB_FMT_10_WRAP(T) -T test_data[][3][N] = { - { - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - }, /* arg_0 */ - { - 0, 1, 2, 3, - 0, 1, 2, 3, - 0, 1, 2, 3, - 0, 1, 2, 3, - }, /* arg_1 */ - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - }, /* expect */ - }, - { - { - 0, 255, 255, 255, - 0, 255, 255, 255, - 0, 255, 255, 255, - 0, 255, 255, 255, - }, - { - 1, 255, 254, 251, - 1, 255, 254, 251, - 1, 255, 254, 251, - 1, 255, 254, 251, - }, - { - 0, 0, 1, 4, - 0, 0, 1, 4, - 0, 0, 1, 4, - 0, 0, 1, 4, - }, - }, - { - { - 0, 0, 1, 0, - 1, 2, 3, 0, - 1, 2, 3, 255, - 5, 254, 255, 9, - }, - { - 0, 1, 0, 254, - 254, 254, 254, 255, - 255, 255, 0, 252, - 255, 255, 255, 1, - }, - { - 0, 0, 1, 0, - 0, 0, 0, 0, - 0, 0, 3, 3, - 0, 0, 0, 8, - }, - }, -}; +#define test_data TEST_UNARY_DATA_WRAP(T, usub) +#define RUN_VEC_SAT_BINARY(T, out, op_1, op_2, N) \ + RUN_VEC_SAT_U_SUB_FMT_10_WRAP(T, out, op_1, op_2, N) #include "vec_sat_binary_vvv_run.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-2-u16.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-2-u16.c index 5cf08ac..dcd6d17 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-2-u16.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-2-u16.c @@ -2,74 +2,14 @@ /* { dg-additional-options "-std=c99" } */ #include "vec_sat_arith.h" +#include "vec_sat_data.h" #define T uint16_t -#define N 16 -#define RUN_VEC_SAT_BINARY RUN_VEC_SAT_U_SUB_FMT_2 -DEF_VEC_SAT_U_SUB_FMT_2(T) +DEF_VEC_SAT_U_SUB_FMT_2_WRAP(T) -T test_data[][3][N] = { - { - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - }, /* arg_0 */ - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - }, /* arg_1 */ - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - }, /* expect */ - }, - { - { - 65535, 65535, 65535, 65535, - 65535, 65535, 65535, 65535, - 65535, 65535, 65535, 65535, - 65535, 65535, 65535, 65535, - }, - { - 55535, 45535, 35535, 25535, - 55535, 45535, 35535, 25535, - 55535, 45535, 35535, 25535, - 55535, 45535, 35535, 25535, - }, - { - 10000, 20000, 30000, 40000, - 10000, 20000, 30000, 40000, - 10000, 20000, 30000, 40000, - 10000, 20000, 30000, 40000, - }, - }, - { - { - 0, 0, 1, 0, - 1, 2, 3, 0, - 1, 65535, 3, 65535, - 5, 65534, 65535, 9, - }, - { - 0, 1, 1, 65534, - 65534, 65534, 1, 65535, - 0, 65535, 65535, 0, - 65535, 65535, 1, 2, - }, - { - 0, 0, 0, 0, - 0, 0, 2, 0, - 1, 0, 0, 65535, - 0, 0, 65534, 7, - }, - }, -}; +#define test_data TEST_UNARY_DATA_WRAP(T, usub) +#define RUN_VEC_SAT_BINARY(T, out, op_1, op_2, N) \ + RUN_VEC_SAT_U_SUB_FMT_2_WRAP(T, out, op_1, op_2, N) #include "vec_sat_binary_vvv_run.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-2-u32.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-2-u32.c index 85c8454..98a1fff 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-2-u32.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-2-u32.c @@ -2,74 +2,14 @@ /* { dg-additional-options "-std=c99" } */ #include "vec_sat_arith.h" +#include "vec_sat_data.h" #define T uint32_t -#define N 16 -#define RUN_VEC_SAT_BINARY RUN_VEC_SAT_U_SUB_FMT_2 -DEF_VEC_SAT_U_SUB_FMT_2(T) +DEF_VEC_SAT_U_SUB_FMT_2_WRAP(T) -T test_data[][3][N] = { - { - { - 0, 0, 4, 0, - 0, 0, 4, 0, - 0, 0, 4, 0, - 0, 0, 4, 0, - }, /* arg_0 */ - { - 0, 1, 2, 3, - 0, 1, 2, 3, - 0, 1, 2, 3, - 0, 1, 2, 3, - }, /* arg_1 */ - { - 0, 0, 2, 0, - 0, 0, 2, 0, - 0, 0, 2, 0, - 0, 0, 2, 0, - }, /* expect */ - }, - { - { - 4294967295, 4294967295, 4294967295, 4294967295, - 4294967295, 4294967295, 4294967295, 4294967295, - 4294967295, 4294967295, 4294967295, 4294967295, - 4294967295, 4294967295, 4294967295, 4294967295, - }, - { - 1294967295, 2294967295, 3294967295, 4294967295, - 1294967295, 2294967295, 3294967295, 4294967295, - 1294967295, 2294967295, 3294967295, 4294967295, - 1294967295, 2294967295, 3294967295, 4294967295, - }, - { - 3000000000, 2000000000, 1000000000, 0, - 3000000000, 2000000000, 1000000000, 0, - 3000000000, 2000000000, 1000000000, 0, - 3000000000, 2000000000, 1000000000, 0, - }, - }, - { - { - 0, 0, 9, 0, - 1, 4294967295, 3, 0, - 1, 2, 3, 4, - 5, 4294967294, 4294967295, 4294967295, - }, - { - 0, 1, 1, 4294967294, - 1, 2, 4294967294, 4294967295, - 1, 4294967295, 4294967295, 1, - 1, 4294967295, 4294967290, 9, - }, - { - 0, 0, 8, 0, - 0, 4294967293, 0, 0, - 0, 0, 0, 3, - 4, 0, 5, 4294967286, - }, - }, -}; +#define test_data TEST_UNARY_DATA_WRAP(T, usub) +#define RUN_VEC_SAT_BINARY(T, out, op_1, op_2, N) \ + RUN_VEC_SAT_U_SUB_FMT_2_WRAP(T, out, op_1, op_2, N) #include "vec_sat_binary_vvv_run.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-2-u64.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-2-u64.c index 67d5ac5..5445b01 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-2-u64.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-2-u64.c @@ -2,74 +2,14 @@ /* { dg-additional-options "-std=c99" } */ #include "vec_sat_arith.h" +#include "vec_sat_data.h" #define T uint64_t -#define N 16 -#define RUN_VEC_SAT_BINARY RUN_VEC_SAT_U_SUB_FMT_2 -DEF_VEC_SAT_U_SUB_FMT_2(T) +DEF_VEC_SAT_U_SUB_FMT_2_WRAP(T) -T test_data[][3][N] = { - { - { - 0, 9, 0, 0, - 0, 9, 0, 0, - 0, 9, 0, 0, - 0, 9, 0, 0, - }, /* arg_0 */ - { - 0, 2, 3, 1, - 0, 2, 3, 1, - 0, 2, 3, 1, - 0, 2, 3, 1, - }, /* arg_1 */ - { - 0, 7, 0, 0, - 0, 7, 0, 0, - 0, 7, 0, 0, - 0, 7, 0, 0, - }, /* expect */ - }, - { - { - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, - }, - { - 10446744073709551615u, 11446744073709551615u, 12446744073709551615u, 18446744073709551615u, - 10446744073709551615u, 11446744073709551615u, 12446744073709551615u, 18446744073709551615u, - 10446744073709551615u, 11446744073709551615u, 12446744073709551615u, 18446744073709551615u, - 10446744073709551615u, 11446744073709551615u, 12446744073709551615u, 18446744073709551615u, - }, - { - 8000000000000000000u, 7000000000000000000u, 6000000000000000000u, 0u, - 8000000000000000000u, 7000000000000000000u, 6000000000000000000u, 0u, - 8000000000000000000u, 7000000000000000000u, 6000000000000000000u, 0u, - 8000000000000000000u, 7000000000000000000u, 6000000000000000000u, 0u, - }, - }, - { - { - 0, 18446744073709551615u, 1, 0, - 1, 18446744073709551615u, 3, 0, - 1, 18446744073709551614u, 3, 4, - 5, 18446744073709551614u, 18446744073709551615u, 9, - }, - { - 0, 1, 1, 18446744073709551614u, - 18446744073709551614u, 18446744073709551614u, 18446744073709551614u, 18446744073709551615u, - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 1, - }, - { - 0, 18446744073709551614u, 0, 0, - 0, 1, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 8, - }, - }, -}; +#define test_data TEST_UNARY_DATA_WRAP(T, usub) +#define RUN_VEC_SAT_BINARY(T, out, op_1, op_2, N) \ + RUN_VEC_SAT_U_SUB_FMT_2_WRAP(T, out, op_1, op_2, N) #include "vec_sat_binary_vvv_run.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-2-u8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-2-u8.c index 809f07f..3aaec4d 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-2-u8.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-2-u8.c @@ -2,74 +2,14 @@ /* { dg-additional-options "-std=c99" } */ #include "vec_sat_arith.h" +#include "vec_sat_data.h" #define T uint8_t -#define N 16 -#define RUN_VEC_SAT_BINARY RUN_VEC_SAT_U_SUB_FMT_2 -DEF_VEC_SAT_U_SUB_FMT_2(T) +DEF_VEC_SAT_U_SUB_FMT_2_WRAP(T) -T test_data[][3][N] = { - { - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - }, /* arg_0 */ - { - 0, 1, 2, 3, - 0, 1, 2, 3, - 0, 1, 2, 3, - 0, 1, 2, 3, - }, /* arg_1 */ - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - }, /* expect */ - }, - { - { - 0, 255, 255, 255, - 0, 255, 255, 255, - 0, 255, 255, 255, - 0, 255, 255, 255, - }, - { - 1, 255, 254, 251, - 1, 255, 254, 251, - 1, 255, 254, 251, - 1, 255, 254, 251, - }, - { - 0, 0, 1, 4, - 0, 0, 1, 4, - 0, 0, 1, 4, - 0, 0, 1, 4, - }, - }, - { - { - 0, 0, 1, 0, - 1, 2, 3, 0, - 1, 2, 3, 255, - 5, 254, 255, 9, - }, - { - 0, 1, 0, 254, - 254, 254, 254, 255, - 255, 255, 0, 252, - 255, 255, 255, 1, - }, - { - 0, 0, 1, 0, - 0, 0, 0, 0, - 0, 0, 3, 3, - 0, 0, 0, 8, - }, - }, -}; +#define test_data TEST_UNARY_DATA_WRAP(T, usub) +#define RUN_VEC_SAT_BINARY(T, out, op_1, op_2, N) \ + RUN_VEC_SAT_U_SUB_FMT_2_WRAP(T, out, op_1, op_2, N) #include "vec_sat_binary_vvv_run.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-3-u16.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-3-u16.c index 57839a9..99e58cd 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-3-u16.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-3-u16.c @@ -2,74 +2,14 @@ /* { dg-additional-options "-std=c99" } */ #include "vec_sat_arith.h" +#include "vec_sat_data.h" #define T uint16_t -#define N 16 -#define RUN_VEC_SAT_BINARY RUN_VEC_SAT_U_SUB_FMT_3 -DEF_VEC_SAT_U_SUB_FMT_3(T) +DEF_VEC_SAT_U_SUB_FMT_3_WRAP(T) -T test_data[][3][N] = { - { - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - }, /* arg_0 */ - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - }, /* arg_1 */ - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - }, /* expect */ - }, - { - { - 65535, 65535, 65535, 65535, - 65535, 65535, 65535, 65535, - 65535, 65535, 65535, 65535, - 65535, 65535, 65535, 65535, - }, - { - 55535, 45535, 35535, 25535, - 55535, 45535, 35535, 25535, - 55535, 45535, 35535, 25535, - 55535, 45535, 35535, 25535, - }, - { - 10000, 20000, 30000, 40000, - 10000, 20000, 30000, 40000, - 10000, 20000, 30000, 40000, - 10000, 20000, 30000, 40000, - }, - }, - { - { - 0, 0, 1, 0, - 1, 2, 3, 0, - 1, 65535, 3, 65535, - 5, 65534, 65535, 9, - }, - { - 0, 1, 1, 65534, - 65534, 65534, 1, 65535, - 0, 65535, 65535, 0, - 65535, 65535, 1, 2, - }, - { - 0, 0, 0, 0, - 0, 0, 2, 0, - 1, 0, 0, 65535, - 0, 0, 65534, 7, - }, - }, -}; +#define test_data TEST_UNARY_DATA_WRAP(T, usub) +#define RUN_VEC_SAT_BINARY(T, out, op_1, op_2, N) \ + RUN_VEC_SAT_U_SUB_FMT_3_WRAP(T, out, op_1, op_2, N) #include "vec_sat_binary_vvv_run.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-3-u32.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-3-u32.c index ffb0dcc..bd7bcd0 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-3-u32.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-3-u32.c @@ -2,74 +2,14 @@ /* { dg-additional-options "-std=c99" } */ #include "vec_sat_arith.h" +#include "vec_sat_data.h" #define T uint32_t -#define N 16 -#define RUN_VEC_SAT_BINARY RUN_VEC_SAT_U_SUB_FMT_3 -DEF_VEC_SAT_U_SUB_FMT_3(T) +DEF_VEC_SAT_U_SUB_FMT_3_WRAP(T) -T test_data[][3][N] = { - { - { - 0, 0, 4, 0, - 0, 0, 4, 0, - 0, 0, 4, 0, - 0, 0, 4, 0, - }, /* arg_0 */ - { - 0, 1, 2, 3, - 0, 1, 2, 3, - 0, 1, 2, 3, - 0, 1, 2, 3, - }, /* arg_1 */ - { - 0, 0, 2, 0, - 0, 0, 2, 0, - 0, 0, 2, 0, - 0, 0, 2, 0, - }, /* expect */ - }, - { - { - 4294967295, 4294967295, 4294967295, 4294967295, - 4294967295, 4294967295, 4294967295, 4294967295, - 4294967295, 4294967295, 4294967295, 4294967295, - 4294967295, 4294967295, 4294967295, 4294967295, - }, - { - 1294967295, 2294967295, 3294967295, 4294967295, - 1294967295, 2294967295, 3294967295, 4294967295, - 1294967295, 2294967295, 3294967295, 4294967295, - 1294967295, 2294967295, 3294967295, 4294967295, - }, - { - 3000000000, 2000000000, 1000000000, 0, - 3000000000, 2000000000, 1000000000, 0, - 3000000000, 2000000000, 1000000000, 0, - 3000000000, 2000000000, 1000000000, 0, - }, - }, - { - { - 0, 0, 9, 0, - 1, 4294967295, 3, 0, - 1, 2, 3, 4, - 5, 4294967294, 4294967295, 4294967295, - }, - { - 0, 1, 1, 4294967294, - 1, 2, 4294967294, 4294967295, - 1, 4294967295, 4294967295, 1, - 1, 4294967295, 4294967290, 9, - }, - { - 0, 0, 8, 0, - 0, 4294967293, 0, 0, - 0, 0, 0, 3, - 4, 0, 5, 4294967286, - }, - }, -}; +#define test_data TEST_UNARY_DATA_WRAP(T, usub) +#define RUN_VEC_SAT_BINARY(T, out, op_1, op_2, N) \ + RUN_VEC_SAT_U_SUB_FMT_3_WRAP(T, out, op_1, op_2, N) #include "vec_sat_binary_vvv_run.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-3-u64.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-3-u64.c index 3966677..96ee0c8 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-3-u64.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-3-u64.c @@ -2,74 +2,14 @@ /* { dg-additional-options "-std=c99" } */ #include "vec_sat_arith.h" +#include "vec_sat_data.h" #define T uint64_t -#define N 16 -#define RUN_VEC_SAT_BINARY RUN_VEC_SAT_U_SUB_FMT_3 -DEF_VEC_SAT_U_SUB_FMT_3(T) +DEF_VEC_SAT_U_SUB_FMT_3_WRAP(T) -T test_data[][3][N] = { - { - { - 0, 9, 0, 0, - 0, 9, 0, 0, - 0, 9, 0, 0, - 0, 9, 0, 0, - }, /* arg_0 */ - { - 0, 2, 3, 1, - 0, 2, 3, 1, - 0, 2, 3, 1, - 0, 2, 3, 1, - }, /* arg_1 */ - { - 0, 7, 0, 0, - 0, 7, 0, 0, - 0, 7, 0, 0, - 0, 7, 0, 0, - }, /* expect */ - }, - { - { - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, - }, - { - 10446744073709551615u, 11446744073709551615u, 12446744073709551615u, 18446744073709551615u, - 10446744073709551615u, 11446744073709551615u, 12446744073709551615u, 18446744073709551615u, - 10446744073709551615u, 11446744073709551615u, 12446744073709551615u, 18446744073709551615u, - 10446744073709551615u, 11446744073709551615u, 12446744073709551615u, 18446744073709551615u, - }, - { - 8000000000000000000u, 7000000000000000000u, 6000000000000000000u, 0u, - 8000000000000000000u, 7000000000000000000u, 6000000000000000000u, 0u, - 8000000000000000000u, 7000000000000000000u, 6000000000000000000u, 0u, - 8000000000000000000u, 7000000000000000000u, 6000000000000000000u, 0u, - }, - }, - { - { - 0, 18446744073709551615u, 1, 0, - 1, 18446744073709551615u, 3, 0, - 1, 18446744073709551614u, 3, 4, - 5, 18446744073709551614u, 18446744073709551615u, 9, - }, - { - 0, 1, 1, 18446744073709551614u, - 18446744073709551614u, 18446744073709551614u, 18446744073709551614u, 18446744073709551615u, - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 1, - }, - { - 0, 18446744073709551614u, 0, 0, - 0, 1, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 8, - }, - }, -}; +#define test_data TEST_UNARY_DATA_WRAP(T, usub) +#define RUN_VEC_SAT_BINARY(T, out, op_1, op_2, N) \ + RUN_VEC_SAT_U_SUB_FMT_3_WRAP(T, out, op_1, op_2, N) #include "vec_sat_binary_vvv_run.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-3-u8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-3-u8.c index e795f62..b9fa957 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-3-u8.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-3-u8.c @@ -2,74 +2,14 @@ /* { dg-additional-options "-std=c99" } */ #include "vec_sat_arith.h" +#include "vec_sat_data.h" #define T uint8_t -#define N 16 -#define RUN_VEC_SAT_BINARY RUN_VEC_SAT_U_SUB_FMT_3 -DEF_VEC_SAT_U_SUB_FMT_3(T) +DEF_VEC_SAT_U_SUB_FMT_3_WRAP(T) -T test_data[][3][N] = { - { - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - }, /* arg_0 */ - { - 0, 1, 2, 3, - 0, 1, 2, 3, - 0, 1, 2, 3, - 0, 1, 2, 3, - }, /* arg_1 */ - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - }, /* expect */ - }, - { - { - 0, 255, 255, 255, - 0, 255, 255, 255, - 0, 255, 255, 255, - 0, 255, 255, 255, - }, - { - 1, 255, 254, 251, - 1, 255, 254, 251, - 1, 255, 254, 251, - 1, 255, 254, 251, - }, - { - 0, 0, 1, 4, - 0, 0, 1, 4, - 0, 0, 1, 4, - 0, 0, 1, 4, - }, - }, - { - { - 0, 0, 1, 0, - 1, 2, 3, 0, - 1, 2, 3, 255, - 5, 254, 255, 9, - }, - { - 0, 1, 0, 254, - 254, 254, 254, 255, - 255, 255, 0, 252, - 255, 255, 255, 1, - }, - { - 0, 0, 1, 0, - 0, 0, 0, 0, - 0, 0, 3, 3, - 0, 0, 0, 8, - }, - }, -}; +#define test_data TEST_UNARY_DATA_WRAP(T, usub) +#define RUN_VEC_SAT_BINARY(T, out, op_1, op_2, N) \ + RUN_VEC_SAT_U_SUB_FMT_3_WRAP(T, out, op_1, op_2, N) #include "vec_sat_binary_vvv_run.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-4-u16.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-4-u16.c index 0eecf82..6d4f377 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-4-u16.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-4-u16.c @@ -2,74 +2,14 @@ /* { dg-additional-options "-std=c99" } */ #include "vec_sat_arith.h" +#include "vec_sat_data.h" #define T uint16_t -#define N 16 -#define RUN_VEC_SAT_BINARY RUN_VEC_SAT_U_SUB_FMT_4 -DEF_VEC_SAT_U_SUB_FMT_4(T) +DEF_VEC_SAT_U_SUB_FMT_4_WRAP(T) -T test_data[][3][N] = { - { - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - }, /* arg_0 */ - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - }, /* arg_1 */ - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - }, /* expect */ - }, - { - { - 65535, 65535, 65535, 65535, - 65535, 65535, 65535, 65535, - 65535, 65535, 65535, 65535, - 65535, 65535, 65535, 65535, - }, - { - 55535, 45535, 35535, 25535, - 55535, 45535, 35535, 25535, - 55535, 45535, 35535, 25535, - 55535, 45535, 35535, 25535, - }, - { - 10000, 20000, 30000, 40000, - 10000, 20000, 30000, 40000, - 10000, 20000, 30000, 40000, - 10000, 20000, 30000, 40000, - }, - }, - { - { - 0, 0, 1, 0, - 1, 2, 3, 0, - 1, 65535, 3, 65535, - 5, 65534, 65535, 9, - }, - { - 0, 1, 1, 65534, - 65534, 65534, 1, 65535, - 0, 65535, 65535, 0, - 65535, 65535, 1, 2, - }, - { - 0, 0, 0, 0, - 0, 0, 2, 0, - 1, 0, 0, 65535, - 0, 0, 65534, 7, - }, - }, -}; +#define test_data TEST_UNARY_DATA_WRAP(T, usub) +#define RUN_VEC_SAT_BINARY(T, out, op_1, op_2, N) \ + RUN_VEC_SAT_U_SUB_FMT_4_WRAP(T, out, op_1, op_2, N) #include "vec_sat_binary_vvv_run.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-4-u32.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-4-u32.c index 1d0d16b..1425017 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-4-u32.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-4-u32.c @@ -2,74 +2,14 @@ /* { dg-additional-options "-std=c99" } */ #include "vec_sat_arith.h" +#include "vec_sat_data.h" #define T uint32_t -#define N 16 -#define RUN_VEC_SAT_BINARY RUN_VEC_SAT_U_SUB_FMT_4 -DEF_VEC_SAT_U_SUB_FMT_4(T) +DEF_VEC_SAT_U_SUB_FMT_4_WRAP(T) -T test_data[][3][N] = { - { - { - 0, 0, 4, 0, - 0, 0, 4, 0, - 0, 0, 4, 0, - 0, 0, 4, 0, - }, /* arg_0 */ - { - 0, 1, 2, 3, - 0, 1, 2, 3, - 0, 1, 2, 3, - 0, 1, 2, 3, - }, /* arg_1 */ - { - 0, 0, 2, 0, - 0, 0, 2, 0, - 0, 0, 2, 0, - 0, 0, 2, 0, - }, /* expect */ - }, - { - { - 4294967295, 4294967295, 4294967295, 4294967295, - 4294967295, 4294967295, 4294967295, 4294967295, - 4294967295, 4294967295, 4294967295, 4294967295, - 4294967295, 4294967295, 4294967295, 4294967295, - }, - { - 1294967295, 2294967295, 3294967295, 4294967295, - 1294967295, 2294967295, 3294967295, 4294967295, - 1294967295, 2294967295, 3294967295, 4294967295, - 1294967295, 2294967295, 3294967295, 4294967295, - }, - { - 3000000000, 2000000000, 1000000000, 0, - 3000000000, 2000000000, 1000000000, 0, - 3000000000, 2000000000, 1000000000, 0, - 3000000000, 2000000000, 1000000000, 0, - }, - }, - { - { - 0, 0, 9, 0, - 1, 4294967295, 3, 0, - 1, 2, 3, 4, - 5, 4294967294, 4294967295, 4294967295, - }, - { - 0, 1, 1, 4294967294, - 1, 2, 4294967294, 4294967295, - 1, 4294967295, 4294967295, 1, - 1, 4294967295, 4294967290, 9, - }, - { - 0, 0, 8, 0, - 0, 4294967293, 0, 0, - 0, 0, 0, 3, - 4, 0, 5, 4294967286, - }, - }, -}; +#define test_data TEST_UNARY_DATA_WRAP(T, usub) +#define RUN_VEC_SAT_BINARY(T, out, op_1, op_2, N) \ + RUN_VEC_SAT_U_SUB_FMT_4_WRAP(T, out, op_1, op_2, N) #include "vec_sat_binary_vvv_run.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-4-u64.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-4-u64.c index 98fdfa2..149d481 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-4-u64.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-4-u64.c @@ -2,74 +2,14 @@ /* { dg-additional-options "-std=c99" } */ #include "vec_sat_arith.h" +#include "vec_sat_data.h" #define T uint64_t -#define N 16 -#define RUN_VEC_SAT_BINARY RUN_VEC_SAT_U_SUB_FMT_4 -DEF_VEC_SAT_U_SUB_FMT_4(T) +DEF_VEC_SAT_U_SUB_FMT_4_WRAP(T) -T test_data[][3][N] = { - { - { - 0, 9, 0, 0, - 0, 9, 0, 0, - 0, 9, 0, 0, - 0, 9, 0, 0, - }, /* arg_0 */ - { - 0, 2, 3, 1, - 0, 2, 3, 1, - 0, 2, 3, 1, - 0, 2, 3, 1, - }, /* arg_1 */ - { - 0, 7, 0, 0, - 0, 7, 0, 0, - 0, 7, 0, 0, - 0, 7, 0, 0, - }, /* expect */ - }, - { - { - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, - }, - { - 10446744073709551615u, 11446744073709551615u, 12446744073709551615u, 18446744073709551615u, - 10446744073709551615u, 11446744073709551615u, 12446744073709551615u, 18446744073709551615u, - 10446744073709551615u, 11446744073709551615u, 12446744073709551615u, 18446744073709551615u, - 10446744073709551615u, 11446744073709551615u, 12446744073709551615u, 18446744073709551615u, - }, - { - 8000000000000000000u, 7000000000000000000u, 6000000000000000000u, 0u, - 8000000000000000000u, 7000000000000000000u, 6000000000000000000u, 0u, - 8000000000000000000u, 7000000000000000000u, 6000000000000000000u, 0u, - 8000000000000000000u, 7000000000000000000u, 6000000000000000000u, 0u, - }, - }, - { - { - 0, 18446744073709551615u, 1, 0, - 1, 18446744073709551615u, 3, 0, - 1, 18446744073709551614u, 3, 4, - 5, 18446744073709551614u, 18446744073709551615u, 9, - }, - { - 0, 1, 1, 18446744073709551614u, - 18446744073709551614u, 18446744073709551614u, 18446744073709551614u, 18446744073709551615u, - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 1, - }, - { - 0, 18446744073709551614u, 0, 0, - 0, 1, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 8, - }, - }, -}; +#define test_data TEST_UNARY_DATA_WRAP(T, usub) +#define RUN_VEC_SAT_BINARY(T, out, op_1, op_2, N) \ + RUN_VEC_SAT_U_SUB_FMT_4_WRAP(T, out, op_1, op_2, N) #include "vec_sat_binary_vvv_run.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-4-u8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-4-u8.c index 18a887d..12195cd 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-4-u8.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-4-u8.c @@ -2,74 +2,14 @@ /* { dg-additional-options "-std=c99" } */ #include "vec_sat_arith.h" +#include "vec_sat_data.h" #define T uint8_t -#define N 16 -#define RUN_VEC_SAT_BINARY RUN_VEC_SAT_U_SUB_FMT_4 -DEF_VEC_SAT_U_SUB_FMT_4(T) +DEF_VEC_SAT_U_SUB_FMT_4_WRAP(T) -T test_data[][3][N] = { - { - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - }, /* arg_0 */ - { - 0, 1, 2, 3, - 0, 1, 2, 3, - 0, 1, 2, 3, - 0, 1, 2, 3, - }, /* arg_1 */ - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - }, /* expect */ - }, - { - { - 0, 255, 255, 255, - 0, 255, 255, 255, - 0, 255, 255, 255, - 0, 255, 255, 255, - }, - { - 1, 255, 254, 251, - 1, 255, 254, 251, - 1, 255, 254, 251, - 1, 255, 254, 251, - }, - { - 0, 0, 1, 4, - 0, 0, 1, 4, - 0, 0, 1, 4, - 0, 0, 1, 4, - }, - }, - { - { - 0, 0, 1, 0, - 1, 2, 3, 0, - 1, 2, 3, 255, - 5, 254, 255, 9, - }, - { - 0, 1, 0, 254, - 254, 254, 254, 255, - 255, 255, 0, 252, - 255, 255, 255, 1, - }, - { - 0, 0, 1, 0, - 0, 0, 0, 0, - 0, 0, 3, 3, - 0, 0, 0, 8, - }, - }, -}; +#define test_data TEST_UNARY_DATA_WRAP(T, usub) +#define RUN_VEC_SAT_BINARY(T, out, op_1, op_2, N) \ + RUN_VEC_SAT_U_SUB_FMT_4_WRAP(T, out, op_1, op_2, N) #include "vec_sat_binary_vvv_run.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-5-u16.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-5-u16.c index ce44c04..9cd2577 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-5-u16.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-5-u16.c @@ -2,74 +2,14 @@ /* { dg-additional-options "-std=c99" } */ #include "vec_sat_arith.h" +#include "vec_sat_data.h" #define T uint16_t -#define N 16 -#define RUN_VEC_SAT_BINARY RUN_VEC_SAT_U_SUB_FMT_5 -DEF_VEC_SAT_U_SUB_FMT_5(T) +DEF_VEC_SAT_U_SUB_FMT_5_WRAP(T) -T test_data[][3][N] = { - { - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - }, /* arg_0 */ - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - }, /* arg_1 */ - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - }, /* expect */ - }, - { - { - 65535, 65535, 65535, 65535, - 65535, 65535, 65535, 65535, - 65535, 65535, 65535, 65535, - 65535, 65535, 65535, 65535, - }, - { - 55535, 45535, 35535, 25535, - 55535, 45535, 35535, 25535, - 55535, 45535, 35535, 25535, - 55535, 45535, 35535, 25535, - }, - { - 10000, 20000, 30000, 40000, - 10000, 20000, 30000, 40000, - 10000, 20000, 30000, 40000, - 10000, 20000, 30000, 40000, - }, - }, - { - { - 0, 0, 1, 0, - 1, 2, 3, 0, - 1, 65535, 3, 65535, - 5, 65534, 65535, 9, - }, - { - 0, 1, 1, 65534, - 65534, 65534, 1, 65535, - 0, 65535, 65535, 0, - 65535, 65535, 1, 2, - }, - { - 0, 0, 0, 0, - 0, 0, 2, 0, - 1, 0, 0, 65535, - 0, 0, 65534, 7, - }, - }, -}; +#define test_data TEST_UNARY_DATA_WRAP(T, usub) +#define RUN_VEC_SAT_BINARY(T, out, op_1, op_2, N) \ + RUN_VEC_SAT_U_SUB_FMT_5_WRAP(T, out, op_1, op_2, N) #include "vec_sat_binary_vvv_run.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-5-u32.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-5-u32.c index 36ae7b3..638e054 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-5-u32.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-5-u32.c @@ -2,74 +2,14 @@ /* { dg-additional-options "-std=c99" } */ #include "vec_sat_arith.h" +#include "vec_sat_data.h" #define T uint32_t -#define N 16 -#define RUN_VEC_SAT_BINARY RUN_VEC_SAT_U_SUB_FMT_5 -DEF_VEC_SAT_U_SUB_FMT_5(T) +DEF_VEC_SAT_U_SUB_FMT_5_WRAP(T) -T test_data[][3][N] = { - { - { - 0, 0, 4, 0, - 0, 0, 4, 0, - 0, 0, 4, 0, - 0, 0, 4, 0, - }, /* arg_0 */ - { - 0, 1, 2, 3, - 0, 1, 2, 3, - 0, 1, 2, 3, - 0, 1, 2, 3, - }, /* arg_1 */ - { - 0, 0, 2, 0, - 0, 0, 2, 0, - 0, 0, 2, 0, - 0, 0, 2, 0, - }, /* expect */ - }, - { - { - 4294967295, 4294967295, 4294967295, 4294967295, - 4294967295, 4294967295, 4294967295, 4294967295, - 4294967295, 4294967295, 4294967295, 4294967295, - 4294967295, 4294967295, 4294967295, 4294967295, - }, - { - 1294967295, 2294967295, 3294967295, 4294967295, - 1294967295, 2294967295, 3294967295, 4294967295, - 1294967295, 2294967295, 3294967295, 4294967295, - 1294967295, 2294967295, 3294967295, 4294967295, - }, - { - 3000000000, 2000000000, 1000000000, 0, - 3000000000, 2000000000, 1000000000, 0, - 3000000000, 2000000000, 1000000000, 0, - 3000000000, 2000000000, 1000000000, 0, - }, - }, - { - { - 0, 0, 9, 0, - 1, 4294967295, 3, 0, - 1, 2, 3, 4, - 5, 4294967294, 4294967295, 4294967295, - }, - { - 0, 1, 1, 4294967294, - 1, 2, 4294967294, 4294967295, - 1, 4294967295, 4294967295, 1, - 1, 4294967295, 4294967290, 9, - }, - { - 0, 0, 8, 0, - 0, 4294967293, 0, 0, - 0, 0, 0, 3, - 4, 0, 5, 4294967286, - }, - }, -}; +#define test_data TEST_UNARY_DATA_WRAP(T, usub) +#define RUN_VEC_SAT_BINARY(T, out, op_1, op_2, N) \ + RUN_VEC_SAT_U_SUB_FMT_5_WRAP(T, out, op_1, op_2, N) #include "vec_sat_binary_vvv_run.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-5-u64.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-5-u64.c index 7b40ffd..db86baf 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-5-u64.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-5-u64.c @@ -2,74 +2,14 @@ /* { dg-additional-options "-std=c99" } */ #include "vec_sat_arith.h" +#include "vec_sat_data.h" #define T uint64_t -#define N 16 -#define RUN_VEC_SAT_BINARY RUN_VEC_SAT_U_SUB_FMT_5 -DEF_VEC_SAT_U_SUB_FMT_5(T) +DEF_VEC_SAT_U_SUB_FMT_5_WRAP(T) -T test_data[][3][N] = { - { - { - 0, 9, 0, 0, - 0, 9, 0, 0, - 0, 9, 0, 0, - 0, 9, 0, 0, - }, /* arg_0 */ - { - 0, 2, 3, 1, - 0, 2, 3, 1, - 0, 2, 3, 1, - 0, 2, 3, 1, - }, /* arg_1 */ - { - 0, 7, 0, 0, - 0, 7, 0, 0, - 0, 7, 0, 0, - 0, 7, 0, 0, - }, /* expect */ - }, - { - { - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, - }, - { - 10446744073709551615u, 11446744073709551615u, 12446744073709551615u, 18446744073709551615u, - 10446744073709551615u, 11446744073709551615u, 12446744073709551615u, 18446744073709551615u, - 10446744073709551615u, 11446744073709551615u, 12446744073709551615u, 18446744073709551615u, - 10446744073709551615u, 11446744073709551615u, 12446744073709551615u, 18446744073709551615u, - }, - { - 8000000000000000000u, 7000000000000000000u, 6000000000000000000u, 0u, - 8000000000000000000u, 7000000000000000000u, 6000000000000000000u, 0u, - 8000000000000000000u, 7000000000000000000u, 6000000000000000000u, 0u, - 8000000000000000000u, 7000000000000000000u, 6000000000000000000u, 0u, - }, - }, - { - { - 0, 18446744073709551615u, 1, 0, - 1, 18446744073709551615u, 3, 0, - 1, 18446744073709551614u, 3, 4, - 5, 18446744073709551614u, 18446744073709551615u, 9, - }, - { - 0, 1, 1, 18446744073709551614u, - 18446744073709551614u, 18446744073709551614u, 18446744073709551614u, 18446744073709551615u, - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 1, - }, - { - 0, 18446744073709551614u, 0, 0, - 0, 1, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 8, - }, - }, -}; +#define test_data TEST_UNARY_DATA_WRAP(T, usub) +#define RUN_VEC_SAT_BINARY(T, out, op_1, op_2, N) \ + RUN_VEC_SAT_U_SUB_FMT_5_WRAP(T, out, op_1, op_2, N) #include "vec_sat_binary_vvv_run.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-5-u8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-5-u8.c index 3b0807f..b277e1c 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-5-u8.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-5-u8.c @@ -2,74 +2,14 @@ /* { dg-additional-options "-std=c99" } */ #include "vec_sat_arith.h" +#include "vec_sat_data.h" #define T uint8_t -#define N 16 -#define RUN_VEC_SAT_BINARY RUN_VEC_SAT_U_SUB_FMT_5 -DEF_VEC_SAT_U_SUB_FMT_5(T) +DEF_VEC_SAT_U_SUB_FMT_5_WRAP(T) -T test_data[][3][N] = { - { - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - }, /* arg_0 */ - { - 0, 1, 2, 3, - 0, 1, 2, 3, - 0, 1, 2, 3, - 0, 1, 2, 3, - }, /* arg_1 */ - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - }, /* expect */ - }, - { - { - 0, 255, 255, 255, - 0, 255, 255, 255, - 0, 255, 255, 255, - 0, 255, 255, 255, - }, - { - 1, 255, 254, 251, - 1, 255, 254, 251, - 1, 255, 254, 251, - 1, 255, 254, 251, - }, - { - 0, 0, 1, 4, - 0, 0, 1, 4, - 0, 0, 1, 4, - 0, 0, 1, 4, - }, - }, - { - { - 0, 0, 1, 0, - 1, 2, 3, 0, - 1, 2, 3, 255, - 5, 254, 255, 9, - }, - { - 0, 1, 0, 254, - 254, 254, 254, 255, - 255, 255, 0, 252, - 255, 255, 255, 1, - }, - { - 0, 0, 1, 0, - 0, 0, 0, 0, - 0, 0, 3, 3, - 0, 0, 0, 8, - }, - }, -}; +#define test_data TEST_UNARY_DATA_WRAP(T, usub) +#define RUN_VEC_SAT_BINARY(T, out, op_1, op_2, N) \ + RUN_VEC_SAT_U_SUB_FMT_5_WRAP(T, out, op_1, op_2, N) #include "vec_sat_binary_vvv_run.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-6-u16.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-6-u16.c index e972078..e79e2fc 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-6-u16.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-6-u16.c @@ -2,74 +2,14 @@ /* { dg-additional-options "-std=c99" } */ #include "vec_sat_arith.h" +#include "vec_sat_data.h" #define T uint16_t -#define N 16 -#define RUN_VEC_SAT_BINARY RUN_VEC_SAT_U_SUB_FMT_6 -DEF_VEC_SAT_U_SUB_FMT_6(T) +DEF_VEC_SAT_U_SUB_FMT_6_WRAP(T) -T test_data[][3][N] = { - { - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - }, /* arg_0 */ - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - }, /* arg_1 */ - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - }, /* expect */ - }, - { - { - 65535, 65535, 65535, 65535, - 65535, 65535, 65535, 65535, - 65535, 65535, 65535, 65535, - 65535, 65535, 65535, 65535, - }, - { - 55535, 45535, 35535, 25535, - 55535, 45535, 35535, 25535, - 55535, 45535, 35535, 25535, - 55535, 45535, 35535, 25535, - }, - { - 10000, 20000, 30000, 40000, - 10000, 20000, 30000, 40000, - 10000, 20000, 30000, 40000, - 10000, 20000, 30000, 40000, - }, - }, - { - { - 0, 0, 1, 0, - 1, 2, 3, 0, - 1, 65535, 3, 65535, - 5, 65534, 65535, 9, - }, - { - 0, 1, 1, 65534, - 65534, 65534, 1, 65535, - 0, 65535, 65535, 0, - 65535, 65535, 1, 2, - }, - { - 0, 0, 0, 0, - 0, 0, 2, 0, - 1, 0, 0, 65535, - 0, 0, 65534, 7, - }, - }, -}; +#define test_data TEST_UNARY_DATA_WRAP(T, usub) +#define RUN_VEC_SAT_BINARY(T, out, op_1, op_2, N) \ + RUN_VEC_SAT_U_SUB_FMT_6_WRAP(T, out, op_1, op_2, N) #include "vec_sat_binary_vvv_run.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-6-u32.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-6-u32.c index 54e2848..cd9cbfc 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-6-u32.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-6-u32.c @@ -2,74 +2,14 @@ /* { dg-additional-options "-std=c99" } */ #include "vec_sat_arith.h" +#include "vec_sat_data.h" #define T uint32_t -#define N 16 -#define RUN_VEC_SAT_BINARY RUN_VEC_SAT_U_SUB_FMT_6 -DEF_VEC_SAT_U_SUB_FMT_6(T) +DEF_VEC_SAT_U_SUB_FMT_6_WRAP(T) -T test_data[][3][N] = { - { - { - 0, 0, 4, 0, - 0, 0, 4, 0, - 0, 0, 4, 0, - 0, 0, 4, 0, - }, /* arg_0 */ - { - 0, 1, 2, 3, - 0, 1, 2, 3, - 0, 1, 2, 3, - 0, 1, 2, 3, - }, /* arg_1 */ - { - 0, 0, 2, 0, - 0, 0, 2, 0, - 0, 0, 2, 0, - 0, 0, 2, 0, - }, /* expect */ - }, - { - { - 4294967295, 4294967295, 4294967295, 4294967295, - 4294967295, 4294967295, 4294967295, 4294967295, - 4294967295, 4294967295, 4294967295, 4294967295, - 4294967295, 4294967295, 4294967295, 4294967295, - }, - { - 1294967295, 2294967295, 3294967295, 4294967295, - 1294967295, 2294967295, 3294967295, 4294967295, - 1294967295, 2294967295, 3294967295, 4294967295, - 1294967295, 2294967295, 3294967295, 4294967295, - }, - { - 3000000000, 2000000000, 1000000000, 0, - 3000000000, 2000000000, 1000000000, 0, - 3000000000, 2000000000, 1000000000, 0, - 3000000000, 2000000000, 1000000000, 0, - }, - }, - { - { - 0, 0, 9, 0, - 1, 4294967295, 3, 0, - 1, 2, 3, 4, - 5, 4294967294, 4294967295, 4294967295, - }, - { - 0, 1, 1, 4294967294, - 1, 2, 4294967294, 4294967295, - 1, 4294967295, 4294967295, 1, - 1, 4294967295, 4294967290, 9, - }, - { - 0, 0, 8, 0, - 0, 4294967293, 0, 0, - 0, 0, 0, 3, - 4, 0, 5, 4294967286, - }, - }, -}; +#define test_data TEST_UNARY_DATA_WRAP(T, usub) +#define RUN_VEC_SAT_BINARY(T, out, op_1, op_2, N) \ + RUN_VEC_SAT_U_SUB_FMT_6_WRAP(T, out, op_1, op_2, N) #include "vec_sat_binary_vvv_run.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-6-u64.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-6-u64.c index 33f3be0..7c0f753 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-6-u64.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-6-u64.c @@ -2,74 +2,14 @@ /* { dg-additional-options "-std=c99" } */ #include "vec_sat_arith.h" +#include "vec_sat_data.h" #define T uint64_t -#define N 16 -#define RUN_VEC_SAT_BINARY RUN_VEC_SAT_U_SUB_FMT_6 -DEF_VEC_SAT_U_SUB_FMT_6(T) +DEF_VEC_SAT_U_SUB_FMT_6_WRAP(T) -T test_data[][3][N] = { - { - { - 0, 9, 0, 0, - 0, 9, 0, 0, - 0, 9, 0, 0, - 0, 9, 0, 0, - }, /* arg_0 */ - { - 0, 2, 3, 1, - 0, 2, 3, 1, - 0, 2, 3, 1, - 0, 2, 3, 1, - }, /* arg_1 */ - { - 0, 7, 0, 0, - 0, 7, 0, 0, - 0, 7, 0, 0, - 0, 7, 0, 0, - }, /* expect */ - }, - { - { - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, - }, - { - 10446744073709551615u, 11446744073709551615u, 12446744073709551615u, 18446744073709551615u, - 10446744073709551615u, 11446744073709551615u, 12446744073709551615u, 18446744073709551615u, - 10446744073709551615u, 11446744073709551615u, 12446744073709551615u, 18446744073709551615u, - 10446744073709551615u, 11446744073709551615u, 12446744073709551615u, 18446744073709551615u, - }, - { - 8000000000000000000u, 7000000000000000000u, 6000000000000000000u, 0u, - 8000000000000000000u, 7000000000000000000u, 6000000000000000000u, 0u, - 8000000000000000000u, 7000000000000000000u, 6000000000000000000u, 0u, - 8000000000000000000u, 7000000000000000000u, 6000000000000000000u, 0u, - }, - }, - { - { - 0, 18446744073709551615u, 1, 0, - 1, 18446744073709551615u, 3, 0, - 1, 18446744073709551614u, 3, 4, - 5, 18446744073709551614u, 18446744073709551615u, 9, - }, - { - 0, 1, 1, 18446744073709551614u, - 18446744073709551614u, 18446744073709551614u, 18446744073709551614u, 18446744073709551615u, - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 1, - }, - { - 0, 18446744073709551614u, 0, 0, - 0, 1, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 8, - }, - }, -}; +#define test_data TEST_UNARY_DATA_WRAP(T, usub) +#define RUN_VEC_SAT_BINARY(T, out, op_1, op_2, N) \ + RUN_VEC_SAT_U_SUB_FMT_6_WRAP(T, out, op_1, op_2, N) #include "vec_sat_binary_vvv_run.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-6-u8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-6-u8.c index 1376038..d97a834 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-6-u8.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-6-u8.c @@ -2,74 +2,14 @@ /* { dg-additional-options "-std=c99" } */ #include "vec_sat_arith.h" +#include "vec_sat_data.h" #define T uint8_t -#define N 16 -#define RUN_VEC_SAT_BINARY RUN_VEC_SAT_U_SUB_FMT_6 -DEF_VEC_SAT_U_SUB_FMT_6(T) +DEF_VEC_SAT_U_SUB_FMT_6_WRAP(T) -T test_data[][3][N] = { - { - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - }, /* arg_0 */ - { - 0, 1, 2, 3, - 0, 1, 2, 3, - 0, 1, 2, 3, - 0, 1, 2, 3, - }, /* arg_1 */ - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - }, /* expect */ - }, - { - { - 0, 255, 255, 255, - 0, 255, 255, 255, - 0, 255, 255, 255, - 0, 255, 255, 255, - }, - { - 1, 255, 254, 251, - 1, 255, 254, 251, - 1, 255, 254, 251, - 1, 255, 254, 251, - }, - { - 0, 0, 1, 4, - 0, 0, 1, 4, - 0, 0, 1, 4, - 0, 0, 1, 4, - }, - }, - { - { - 0, 0, 1, 0, - 1, 2, 3, 0, - 1, 2, 3, 255, - 5, 254, 255, 9, - }, - { - 0, 1, 0, 254, - 254, 254, 254, 255, - 255, 255, 0, 252, - 255, 255, 255, 1, - }, - { - 0, 0, 1, 0, - 0, 0, 0, 0, - 0, 0, 3, 3, - 0, 0, 0, 8, - }, - }, -}; +#define test_data TEST_UNARY_DATA_WRAP(T, usub) +#define RUN_VEC_SAT_BINARY(T, out, op_1, op_2, N) \ + RUN_VEC_SAT_U_SUB_FMT_6_WRAP(T, out, op_1, op_2, N) #include "vec_sat_binary_vvv_run.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-7-u16.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-7-u16.c index 83241ef..3b8c870 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-7-u16.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-7-u16.c @@ -2,74 +2,14 @@ /* { dg-additional-options "-std=c99" } */ #include "vec_sat_arith.h" +#include "vec_sat_data.h" #define T uint16_t -#define N 16 -#define RUN_VEC_SAT_BINARY RUN_VEC_SAT_U_SUB_FMT_7 -DEF_VEC_SAT_U_SUB_FMT_7(T) +DEF_VEC_SAT_U_SUB_FMT_7_WRAP(T) -T test_data[][3][N] = { - { - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - }, /* arg_0 */ - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - }, /* arg_1 */ - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - }, /* expect */ - }, - { - { - 65535, 65535, 65535, 65535, - 65535, 65535, 65535, 65535, - 65535, 65535, 65535, 65535, - 65535, 65535, 65535, 65535, - }, - { - 55535, 45535, 35535, 25535, - 55535, 45535, 35535, 25535, - 55535, 45535, 35535, 25535, - 55535, 45535, 35535, 25535, - }, - { - 10000, 20000, 30000, 40000, - 10000, 20000, 30000, 40000, - 10000, 20000, 30000, 40000, - 10000, 20000, 30000, 40000, - }, - }, - { - { - 0, 0, 1, 0, - 1, 2, 3, 0, - 1, 65535, 3, 65535, - 5, 65534, 65535, 9, - }, - { - 0, 1, 1, 65534, - 65534, 65534, 1, 65535, - 0, 65535, 65535, 0, - 65535, 65535, 1, 2, - }, - { - 0, 0, 0, 0, - 0, 0, 2, 0, - 1, 0, 0, 65535, - 0, 0, 65534, 7, - }, - }, -}; +#define test_data TEST_UNARY_DATA_WRAP(T, usub) +#define RUN_VEC_SAT_BINARY(T, out, op_1, op_2, N) \ + RUN_VEC_SAT_U_SUB_FMT_7_WRAP(T, out, op_1, op_2, N) #include "vec_sat_binary_vvv_run.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-7-u32.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-7-u32.c index f20bb21..065d898 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-7-u32.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-7-u32.c @@ -2,74 +2,14 @@ /* { dg-additional-options "-std=c99" } */ #include "vec_sat_arith.h" +#include "vec_sat_data.h" #define T uint32_t -#define N 16 -#define RUN_VEC_SAT_BINARY RUN_VEC_SAT_U_SUB_FMT_7 -DEF_VEC_SAT_U_SUB_FMT_7(T) +DEF_VEC_SAT_U_SUB_FMT_7_WRAP(T) -T test_data[][3][N] = { - { - { - 0, 0, 4, 0, - 0, 0, 4, 0, - 0, 0, 4, 0, - 0, 0, 4, 0, - }, /* arg_0 */ - { - 0, 1, 2, 3, - 0, 1, 2, 3, - 0, 1, 2, 3, - 0, 1, 2, 3, - }, /* arg_1 */ - { - 0, 0, 2, 0, - 0, 0, 2, 0, - 0, 0, 2, 0, - 0, 0, 2, 0, - }, /* expect */ - }, - { - { - 4294967295, 4294967295, 4294967295, 4294967295, - 4294967295, 4294967295, 4294967295, 4294967295, - 4294967295, 4294967295, 4294967295, 4294967295, - 4294967295, 4294967295, 4294967295, 4294967295, - }, - { - 1294967295, 2294967295, 3294967295, 4294967295, - 1294967295, 2294967295, 3294967295, 4294967295, - 1294967295, 2294967295, 3294967295, 4294967295, - 1294967295, 2294967295, 3294967295, 4294967295, - }, - { - 3000000000, 2000000000, 1000000000, 0, - 3000000000, 2000000000, 1000000000, 0, - 3000000000, 2000000000, 1000000000, 0, - 3000000000, 2000000000, 1000000000, 0, - }, - }, - { - { - 0, 0, 9, 0, - 1, 4294967295, 3, 0, - 1, 2, 3, 4, - 5, 4294967294, 4294967295, 4294967295, - }, - { - 0, 1, 1, 4294967294, - 1, 2, 4294967294, 4294967295, - 1, 4294967295, 4294967295, 1, - 1, 4294967295, 4294967290, 9, - }, - { - 0, 0, 8, 0, - 0, 4294967293, 0, 0, - 0, 0, 0, 3, - 4, 0, 5, 4294967286, - }, - }, -}; +#define test_data TEST_UNARY_DATA_WRAP(T, usub) +#define RUN_VEC_SAT_BINARY(T, out, op_1, op_2, N) \ + RUN_VEC_SAT_U_SUB_FMT_7_WRAP(T, out, op_1, op_2, N) #include "vec_sat_binary_vvv_run.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-7-u64.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-7-u64.c index 4ad0afd..f6783a8 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-7-u64.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-7-u64.c @@ -2,74 +2,14 @@ /* { dg-additional-options "-std=c99" } */ #include "vec_sat_arith.h" +#include "vec_sat_data.h" #define T uint64_t -#define N 16 -#define RUN_VEC_SAT_BINARY RUN_VEC_SAT_U_SUB_FMT_7 -DEF_VEC_SAT_U_SUB_FMT_7(T) +DEF_VEC_SAT_U_SUB_FMT_7_WRAP(T) -T test_data[][3][N] = { - { - { - 0, 9, 0, 0, - 0, 9, 0, 0, - 0, 9, 0, 0, - 0, 9, 0, 0, - }, /* arg_0 */ - { - 0, 2, 3, 1, - 0, 2, 3, 1, - 0, 2, 3, 1, - 0, 2, 3, 1, - }, /* arg_1 */ - { - 0, 7, 0, 0, - 0, 7, 0, 0, - 0, 7, 0, 0, - 0, 7, 0, 0, - }, /* expect */ - }, - { - { - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, - }, - { - 10446744073709551615u, 11446744073709551615u, 12446744073709551615u, 18446744073709551615u, - 10446744073709551615u, 11446744073709551615u, 12446744073709551615u, 18446744073709551615u, - 10446744073709551615u, 11446744073709551615u, 12446744073709551615u, 18446744073709551615u, - 10446744073709551615u, 11446744073709551615u, 12446744073709551615u, 18446744073709551615u, - }, - { - 8000000000000000000u, 7000000000000000000u, 6000000000000000000u, 0u, - 8000000000000000000u, 7000000000000000000u, 6000000000000000000u, 0u, - 8000000000000000000u, 7000000000000000000u, 6000000000000000000u, 0u, - 8000000000000000000u, 7000000000000000000u, 6000000000000000000u, 0u, - }, - }, - { - { - 0, 18446744073709551615u, 1, 0, - 1, 18446744073709551615u, 3, 0, - 1, 18446744073709551614u, 3, 4, - 5, 18446744073709551614u, 18446744073709551615u, 9, - }, - { - 0, 1, 1, 18446744073709551614u, - 18446744073709551614u, 18446744073709551614u, 18446744073709551614u, 18446744073709551615u, - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 1, - }, - { - 0, 18446744073709551614u, 0, 0, - 0, 1, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 8, - }, - }, -}; +#define test_data TEST_UNARY_DATA_WRAP(T, usub) +#define RUN_VEC_SAT_BINARY(T, out, op_1, op_2, N) \ + RUN_VEC_SAT_U_SUB_FMT_7_WRAP(T, out, op_1, op_2, N) #include "vec_sat_binary_vvv_run.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-7-u8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-7-u8.c index 3b33b13..6b9ae2d 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-7-u8.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-7-u8.c @@ -2,74 +2,14 @@ /* { dg-additional-options "-std=c99" } */ #include "vec_sat_arith.h" +#include "vec_sat_data.h" #define T uint8_t -#define N 16 -#define RUN_VEC_SAT_BINARY RUN_VEC_SAT_U_SUB_FMT_7 -DEF_VEC_SAT_U_SUB_FMT_7(T) +DEF_VEC_SAT_U_SUB_FMT_7_WRAP(T) -T test_data[][3][N] = { - { - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - }, /* arg_0 */ - { - 0, 1, 2, 3, - 0, 1, 2, 3, - 0, 1, 2, 3, - 0, 1, 2, 3, - }, /* arg_1 */ - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - }, /* expect */ - }, - { - { - 0, 255, 255, 255, - 0, 255, 255, 255, - 0, 255, 255, 255, - 0, 255, 255, 255, - }, - { - 1, 255, 254, 251, - 1, 255, 254, 251, - 1, 255, 254, 251, - 1, 255, 254, 251, - }, - { - 0, 0, 1, 4, - 0, 0, 1, 4, - 0, 0, 1, 4, - 0, 0, 1, 4, - }, - }, - { - { - 0, 0, 1, 0, - 1, 2, 3, 0, - 1, 2, 3, 255, - 5, 254, 255, 9, - }, - { - 0, 1, 0, 254, - 254, 254, 254, 255, - 255, 255, 0, 252, - 255, 255, 255, 1, - }, - { - 0, 0, 1, 0, - 0, 0, 0, 0, - 0, 0, 3, 3, - 0, 0, 0, 8, - }, - }, -}; +#define test_data TEST_UNARY_DATA_WRAP(T, usub) +#define RUN_VEC_SAT_BINARY(T, out, op_1, op_2, N) \ + RUN_VEC_SAT_U_SUB_FMT_7_WRAP(T, out, op_1, op_2, N) #include "vec_sat_binary_vvv_run.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-8-u16.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-8-u16.c index b212550..27c4563 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-8-u16.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-8-u16.c @@ -2,74 +2,14 @@ /* { dg-additional-options "-std=c99" } */ #include "vec_sat_arith.h" +#include "vec_sat_data.h" #define T uint16_t -#define N 16 -#define RUN_VEC_SAT_BINARY RUN_VEC_SAT_U_SUB_FMT_8 -DEF_VEC_SAT_U_SUB_FMT_8(T) +DEF_VEC_SAT_U_SUB_FMT_8_WRAP(T) -T test_data[][3][N] = { - { - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - }, /* arg_0 */ - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - }, /* arg_1 */ - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - }, /* expect */ - }, - { - { - 65535, 65535, 65535, 65535, - 65535, 65535, 65535, 65535, - 65535, 65535, 65535, 65535, - 65535, 65535, 65535, 65535, - }, - { - 55535, 45535, 35535, 25535, - 55535, 45535, 35535, 25535, - 55535, 45535, 35535, 25535, - 55535, 45535, 35535, 25535, - }, - { - 10000, 20000, 30000, 40000, - 10000, 20000, 30000, 40000, - 10000, 20000, 30000, 40000, - 10000, 20000, 30000, 40000, - }, - }, - { - { - 0, 0, 1, 0, - 1, 2, 3, 0, - 1, 65535, 3, 65535, - 5, 65534, 65535, 9, - }, - { - 0, 1, 1, 65534, - 65534, 65534, 1, 65535, - 0, 65535, 65535, 0, - 65535, 65535, 1, 2, - }, - { - 0, 0, 0, 0, - 0, 0, 2, 0, - 1, 0, 0, 65535, - 0, 0, 65534, 7, - }, - }, -}; +#define test_data TEST_UNARY_DATA_WRAP(T, usub) +#define RUN_VEC_SAT_BINARY(T, out, op_1, op_2, N) \ + RUN_VEC_SAT_U_SUB_FMT_8_WRAP(T, out, op_1, op_2, N) #include "vec_sat_binary_vvv_run.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-8-u32.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-8-u32.c index 1fb707c..2dba875 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-8-u32.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-8-u32.c @@ -2,74 +2,14 @@ /* { dg-additional-options "-std=c99" } */ #include "vec_sat_arith.h" +#include "vec_sat_data.h" #define T uint32_t -#define N 16 -#define RUN_VEC_SAT_BINARY RUN_VEC_SAT_U_SUB_FMT_8 -DEF_VEC_SAT_U_SUB_FMT_8(T) +DEF_VEC_SAT_U_SUB_FMT_8_WRAP(T) -T test_data[][3][N] = { - { - { - 0, 0, 4, 0, - 0, 0, 4, 0, - 0, 0, 4, 0, - 0, 0, 4, 0, - }, /* arg_0 */ - { - 0, 1, 2, 3, - 0, 1, 2, 3, - 0, 1, 2, 3, - 0, 1, 2, 3, - }, /* arg_1 */ - { - 0, 0, 2, 0, - 0, 0, 2, 0, - 0, 0, 2, 0, - 0, 0, 2, 0, - }, /* expect */ - }, - { - { - 4294967295, 4294967295, 4294967295, 4294967295, - 4294967295, 4294967295, 4294967295, 4294967295, - 4294967295, 4294967295, 4294967295, 4294967295, - 4294967295, 4294967295, 4294967295, 4294967295, - }, - { - 1294967295, 2294967295, 3294967295, 4294967295, - 1294967295, 2294967295, 3294967295, 4294967295, - 1294967295, 2294967295, 3294967295, 4294967295, - 1294967295, 2294967295, 3294967295, 4294967295, - }, - { - 3000000000, 2000000000, 1000000000, 0, - 3000000000, 2000000000, 1000000000, 0, - 3000000000, 2000000000, 1000000000, 0, - 3000000000, 2000000000, 1000000000, 0, - }, - }, - { - { - 0, 0, 9, 0, - 1, 4294967295, 3, 0, - 1, 2, 3, 4, - 5, 4294967294, 4294967295, 4294967295, - }, - { - 0, 1, 1, 4294967294, - 1, 2, 4294967294, 4294967295, - 1, 4294967295, 4294967295, 1, - 1, 4294967295, 4294967290, 9, - }, - { - 0, 0, 8, 0, - 0, 4294967293, 0, 0, - 0, 0, 0, 3, - 4, 0, 5, 4294967286, - }, - }, -}; +#define test_data TEST_UNARY_DATA_WRAP(T, usub) +#define RUN_VEC_SAT_BINARY(T, out, op_1, op_2, N) \ + RUN_VEC_SAT_U_SUB_FMT_8_WRAP(T, out, op_1, op_2, N) #include "vec_sat_binary_vvv_run.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-8-u64.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-8-u64.c index da8c09c..149a522 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-8-u64.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-8-u64.c @@ -2,74 +2,14 @@ /* { dg-additional-options "-std=c99" } */ #include "vec_sat_arith.h" +#include "vec_sat_data.h" #define T uint64_t -#define N 16 -#define RUN_VEC_SAT_BINARY RUN_VEC_SAT_U_SUB_FMT_8 -DEF_VEC_SAT_U_SUB_FMT_8(T) +DEF_VEC_SAT_U_SUB_FMT_8_WRAP(T) -T test_data[][3][N] = { - { - { - 0, 9, 0, 0, - 0, 9, 0, 0, - 0, 9, 0, 0, - 0, 9, 0, 0, - }, /* arg_0 */ - { - 0, 2, 3, 1, - 0, 2, 3, 1, - 0, 2, 3, 1, - 0, 2, 3, 1, - }, /* arg_1 */ - { - 0, 7, 0, 0, - 0, 7, 0, 0, - 0, 7, 0, 0, - 0, 7, 0, 0, - }, /* expect */ - }, - { - { - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, - }, - { - 10446744073709551615u, 11446744073709551615u, 12446744073709551615u, 18446744073709551615u, - 10446744073709551615u, 11446744073709551615u, 12446744073709551615u, 18446744073709551615u, - 10446744073709551615u, 11446744073709551615u, 12446744073709551615u, 18446744073709551615u, - 10446744073709551615u, 11446744073709551615u, 12446744073709551615u, 18446744073709551615u, - }, - { - 8000000000000000000u, 7000000000000000000u, 6000000000000000000u, 0u, - 8000000000000000000u, 7000000000000000000u, 6000000000000000000u, 0u, - 8000000000000000000u, 7000000000000000000u, 6000000000000000000u, 0u, - 8000000000000000000u, 7000000000000000000u, 6000000000000000000u, 0u, - }, - }, - { - { - 0, 18446744073709551615u, 1, 0, - 1, 18446744073709551615u, 3, 0, - 1, 18446744073709551614u, 3, 4, - 5, 18446744073709551614u, 18446744073709551615u, 9, - }, - { - 0, 1, 1, 18446744073709551614u, - 18446744073709551614u, 18446744073709551614u, 18446744073709551614u, 18446744073709551615u, - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 1, - }, - { - 0, 18446744073709551614u, 0, 0, - 0, 1, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 8, - }, - }, -}; +#define test_data TEST_UNARY_DATA_WRAP(T, usub) +#define RUN_VEC_SAT_BINARY(T, out, op_1, op_2, N) \ + RUN_VEC_SAT_U_SUB_FMT_8_WRAP(T, out, op_1, op_2, N) #include "vec_sat_binary_vvv_run.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-8-u8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-8-u8.c index 647607f..739850e 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-8-u8.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-8-u8.c @@ -2,74 +2,14 @@ /* { dg-additional-options "-std=c99" } */ #include "vec_sat_arith.h" +#include "vec_sat_data.h" #define T uint8_t -#define N 16 -#define RUN_VEC_SAT_BINARY RUN_VEC_SAT_U_SUB_FMT_8 -DEF_VEC_SAT_U_SUB_FMT_8(T) +DEF_VEC_SAT_U_SUB_FMT_8_WRAP(T) -T test_data[][3][N] = { - { - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - }, /* arg_0 */ - { - 0, 1, 2, 3, - 0, 1, 2, 3, - 0, 1, 2, 3, - 0, 1, 2, 3, - }, /* arg_1 */ - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - }, /* expect */ - }, - { - { - 0, 255, 255, 255, - 0, 255, 255, 255, - 0, 255, 255, 255, - 0, 255, 255, 255, - }, - { - 1, 255, 254, 251, - 1, 255, 254, 251, - 1, 255, 254, 251, - 1, 255, 254, 251, - }, - { - 0, 0, 1, 4, - 0, 0, 1, 4, - 0, 0, 1, 4, - 0, 0, 1, 4, - }, - }, - { - { - 0, 0, 1, 0, - 1, 2, 3, 0, - 1, 2, 3, 255, - 5, 254, 255, 9, - }, - { - 0, 1, 0, 254, - 254, 254, 254, 255, - 255, 255, 0, 252, - 255, 255, 255, 1, - }, - { - 0, 0, 1, 0, - 0, 0, 0, 0, - 0, 0, 3, 3, - 0, 0, 0, 8, - }, - }, -}; +#define test_data TEST_UNARY_DATA_WRAP(T, usub) +#define RUN_VEC_SAT_BINARY(T, out, op_1, op_2, N) \ + RUN_VEC_SAT_U_SUB_FMT_8_WRAP(T, out, op_1, op_2, N) #include "vec_sat_binary_vvv_run.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-9-u16.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-9-u16.c index 9bb0664..3eb91ef 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-9-u16.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-9-u16.c @@ -2,74 +2,14 @@ /* { dg-additional-options "-std=c99" } */ #include "vec_sat_arith.h" +#include "vec_sat_data.h" #define T uint16_t -#define N 16 -#define RUN_VEC_SAT_BINARY RUN_VEC_SAT_U_SUB_FMT_9 -DEF_VEC_SAT_U_SUB_FMT_9(T) +DEF_VEC_SAT_U_SUB_FMT_9_WRAP(T) -T test_data[][3][N] = { - { - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - }, /* arg_0 */ - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - }, /* arg_1 */ - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - }, /* expect */ - }, - { - { - 65535, 65535, 65535, 65535, - 65535, 65535, 65535, 65535, - 65535, 65535, 65535, 65535, - 65535, 65535, 65535, 65535, - }, - { - 55535, 45535, 35535, 25535, - 55535, 45535, 35535, 25535, - 55535, 45535, 35535, 25535, - 55535, 45535, 35535, 25535, - }, - { - 10000, 20000, 30000, 40000, - 10000, 20000, 30000, 40000, - 10000, 20000, 30000, 40000, - 10000, 20000, 30000, 40000, - }, - }, - { - { - 0, 0, 1, 0, - 1, 2, 3, 0, - 1, 65535, 3, 65535, - 5, 65534, 65535, 9, - }, - { - 0, 1, 1, 65534, - 65534, 65534, 1, 65535, - 0, 65535, 65535, 0, - 65535, 65535, 1, 2, - }, - { - 0, 0, 0, 0, - 0, 0, 2, 0, - 1, 0, 0, 65535, - 0, 0, 65534, 7, - }, - }, -}; +#define test_data TEST_UNARY_DATA_WRAP(T, usub) +#define RUN_VEC_SAT_BINARY(T, out, op_1, op_2, N) \ + RUN_VEC_SAT_U_SUB_FMT_9_WRAP(T, out, op_1, op_2, N) #include "vec_sat_binary_vvv_run.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-9-u32.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-9-u32.c index f142b8b..3e8d6fb 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-9-u32.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-9-u32.c @@ -2,74 +2,14 @@ /* { dg-additional-options "-std=c99" } */ #include "vec_sat_arith.h" +#include "vec_sat_data.h" #define T uint32_t -#define N 16 -#define RUN_VEC_SAT_BINARY RUN_VEC_SAT_U_SUB_FMT_9 -DEF_VEC_SAT_U_SUB_FMT_9(T) +DEF_VEC_SAT_U_SUB_FMT_9_WRAP(T) -T test_data[][3][N] = { - { - { - 0, 0, 4, 0, - 0, 0, 4, 0, - 0, 0, 4, 0, - 0, 0, 4, 0, - }, /* arg_0 */ - { - 0, 1, 2, 3, - 0, 1, 2, 3, - 0, 1, 2, 3, - 0, 1, 2, 3, - }, /* arg_1 */ - { - 0, 0, 2, 0, - 0, 0, 2, 0, - 0, 0, 2, 0, - 0, 0, 2, 0, - }, /* expect */ - }, - { - { - 4294967295, 4294967295, 4294967295, 4294967295, - 4294967295, 4294967295, 4294967295, 4294967295, - 4294967295, 4294967295, 4294967295, 4294967295, - 4294967295, 4294967295, 4294967295, 4294967295, - }, - { - 1294967295, 2294967295, 3294967295, 4294967295, - 1294967295, 2294967295, 3294967295, 4294967295, - 1294967295, 2294967295, 3294967295, 4294967295, - 1294967295, 2294967295, 3294967295, 4294967295, - }, - { - 3000000000, 2000000000, 1000000000, 0, - 3000000000, 2000000000, 1000000000, 0, - 3000000000, 2000000000, 1000000000, 0, - 3000000000, 2000000000, 1000000000, 0, - }, - }, - { - { - 0, 0, 9, 0, - 1, 4294967295, 3, 0, - 1, 2, 3, 4, - 5, 4294967294, 4294967295, 4294967295, - }, - { - 0, 1, 1, 4294967294, - 1, 2, 4294967294, 4294967295, - 1, 4294967295, 4294967295, 1, - 1, 4294967295, 4294967290, 9, - }, - { - 0, 0, 8, 0, - 0, 4294967293, 0, 0, - 0, 0, 0, 3, - 4, 0, 5, 4294967286, - }, - }, -}; +#define test_data TEST_UNARY_DATA_WRAP(T, usub) +#define RUN_VEC_SAT_BINARY(T, out, op_1, op_2, N) \ + RUN_VEC_SAT_U_SUB_FMT_9_WRAP(T, out, op_1, op_2, N) #include "vec_sat_binary_vvv_run.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-9-u64.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-9-u64.c index 574b91a..bb09035 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-9-u64.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-9-u64.c @@ -2,74 +2,14 @@ /* { dg-additional-options "-std=c99" } */ #include "vec_sat_arith.h" +#include "vec_sat_data.h" #define T uint64_t -#define N 16 -#define RUN_VEC_SAT_BINARY RUN_VEC_SAT_U_SUB_FMT_9 -DEF_VEC_SAT_U_SUB_FMT_9(T) +DEF_VEC_SAT_U_SUB_FMT_9_WRAP(T) -T test_data[][3][N] = { - { - { - 0, 9, 0, 0, - 0, 9, 0, 0, - 0, 9, 0, 0, - 0, 9, 0, 0, - }, /* arg_0 */ - { - 0, 2, 3, 1, - 0, 2, 3, 1, - 0, 2, 3, 1, - 0, 2, 3, 1, - }, /* arg_1 */ - { - 0, 7, 0, 0, - 0, 7, 0, 0, - 0, 7, 0, 0, - 0, 7, 0, 0, - }, /* expect */ - }, - { - { - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, - }, - { - 10446744073709551615u, 11446744073709551615u, 12446744073709551615u, 18446744073709551615u, - 10446744073709551615u, 11446744073709551615u, 12446744073709551615u, 18446744073709551615u, - 10446744073709551615u, 11446744073709551615u, 12446744073709551615u, 18446744073709551615u, - 10446744073709551615u, 11446744073709551615u, 12446744073709551615u, 18446744073709551615u, - }, - { - 8000000000000000000u, 7000000000000000000u, 6000000000000000000u, 0u, - 8000000000000000000u, 7000000000000000000u, 6000000000000000000u, 0u, - 8000000000000000000u, 7000000000000000000u, 6000000000000000000u, 0u, - 8000000000000000000u, 7000000000000000000u, 6000000000000000000u, 0u, - }, - }, - { - { - 0, 18446744073709551615u, 1, 0, - 1, 18446744073709551615u, 3, 0, - 1, 18446744073709551614u, 3, 4, - 5, 18446744073709551614u, 18446744073709551615u, 9, - }, - { - 0, 1, 1, 18446744073709551614u, - 18446744073709551614u, 18446744073709551614u, 18446744073709551614u, 18446744073709551615u, - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, - 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, 1, - }, - { - 0, 18446744073709551614u, 0, 0, - 0, 1, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 8, - }, - }, -}; +#define test_data TEST_UNARY_DATA_WRAP(T, usub) +#define RUN_VEC_SAT_BINARY(T, out, op_1, op_2, N) \ + RUN_VEC_SAT_U_SUB_FMT_9_WRAP(T, out, op_1, op_2, N) #include "vec_sat_binary_vvv_run.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-9-u8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-9-u8.c index 2c8ee42..1dc3191 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-9-u8.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/sat/vec_sat_u_sub-run-9-u8.c @@ -2,74 +2,14 @@ /* { dg-additional-options "-std=c99" } */ #include "vec_sat_arith.h" +#include "vec_sat_data.h" #define T uint8_t -#define N 16 -#define RUN_VEC_SAT_BINARY RUN_VEC_SAT_U_SUB_FMT_9 -DEF_VEC_SAT_U_SUB_FMT_9(T) +DEF_VEC_SAT_U_SUB_FMT_9_WRAP(T) -T test_data[][3][N] = { - { - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - }, /* arg_0 */ - { - 0, 1, 2, 3, - 0, 1, 2, 3, - 0, 1, 2, 3, - 0, 1, 2, 3, - }, /* arg_1 */ - { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - }, /* expect */ - }, - { - { - 0, 255, 255, 255, - 0, 255, 255, 255, - 0, 255, 255, 255, - 0, 255, 255, 255, - }, - { - 1, 255, 254, 251, - 1, 255, 254, 251, - 1, 255, 254, 251, - 1, 255, 254, 251, - }, - { - 0, 0, 1, 4, - 0, 0, 1, 4, - 0, 0, 1, 4, - 0, 0, 1, 4, - }, - }, - { - { - 0, 0, 1, 0, - 1, 2, 3, 0, - 1, 2, 3, 255, - 5, 254, 255, 9, - }, - { - 0, 1, 0, 254, - 254, 254, 254, 255, - 255, 255, 0, 252, - 255, 255, 255, 1, - }, - { - 0, 0, 1, 0, - 0, 0, 0, 0, - 0, 0, 3, 3, - 0, 0, 0, 8, - }, - }, -}; +#define test_data TEST_UNARY_DATA_WRAP(T, usub) +#define RUN_VEC_SAT_BINARY(T, out, op_1, op_2, N) \ + RUN_VEC_SAT_U_SUB_FMT_9_WRAP(T, out, op_1, op_2, N) #include "vec_sat_binary_vvv_run.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_mulop_run.h b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_mulop_run.h index 3dc3999..3dadfab 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_mulop_run.h +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_mulop_run.h @@ -6,6 +6,10 @@ #define TYPE_FABS(x, T) \ (__builtin_types_compatible_p (T, double) ? fabs (x) : fabsf (x)) +#define MAX_RELATIVE_DIFF(T) \ + (__builtin_types_compatible_p (T, _Float16) ? 0.1f : \ + (__builtin_types_compatible_p (T, float) ? 0.01f : 0.01)) + int main () { @@ -23,7 +27,8 @@ main () for (k = 0; k < N; k++) { T diff = expect[k] - TEST_OUT[k]; - if (TYPE_FABS (diff, T) > .01 * TYPE_FABS (expect[k], T)) + if (TYPE_FABS (diff, T) + > MAX_RELATIVE_DIFF (T) * TYPE_FABS (expect[k], T)) __builtin_abort (); } } diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmacc-run-1-f16.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmacc-run-1-f16.c index 5bb926d..982dd97 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmacc-run-1-f16.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmacc-run-1-f16.c @@ -1,5 +1,5 @@ /* { dg-do run { target { riscv_v } } } */ -/* { dg-additional-options "--param=fpr2vr-cost=0" } */ +/* { dg-additional-options "-march=rv64gcv_zvfh --param=fpr2vr-cost=0" } */ #include "vf_mulop.h" #include "vf_mulop_data.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmadd-run-1-f16.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmadd-run-1-f16.c index be4dc1d..400bbcd 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmadd-run-1-f16.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmadd-run-1-f16.c @@ -1,5 +1,5 @@ /* { dg-do run { target { riscv_v } } } */ -/* { dg-additional-options "--param=fpr2vr-cost=0" } */ +/* { dg-additional-options "-march=rv64gcv_zvfh --param=fpr2vr-cost=0" } */ #include "vf_mulop.h" #include "vf_mulop_data.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmsac-run-1-f16.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmsac-run-1-f16.c index 812e608..21c1860 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmsac-run-1-f16.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmsac-run-1-f16.c @@ -1,5 +1,5 @@ /* { dg-do run { target { riscv_v } } } */ -/* { dg-additional-options "--param=fpr2vr-cost=0" } */ +/* { dg-additional-options "-march=rv64gcv_zvfh --param=fpr2vr-cost=0" } */ #include "vf_mulop.h" #include "vf_mulop_data.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmsub-run-1-f16.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmsub-run-1-f16.c index 48c2880..163b5bd 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmsub-run-1-f16.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfmsub-run-1-f16.c @@ -1,5 +1,5 @@ /* { dg-do run { target { riscv_v } } } */ -/* { dg-additional-options "--param=fpr2vr-cost=0" } */ +/* { dg-additional-options "-march=rv64gcv_zvfh --param=fpr2vr-cost=0" } */ #include "vf_mulop.h" #include "vf_mulop_data.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmacc-run-1-f16.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmacc-run-1-f16.c index b960e7a..71f350f 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmacc-run-1-f16.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmacc-run-1-f16.c @@ -1,5 +1,5 @@ /* { dg-do run { target { riscv_v } } } */ -/* { dg-additional-options "--param=fpr2vr-cost=0" } */ +/* { dg-additional-options "-march=rv64gcv_zvfh --param=fpr2vr-cost=0" } */ #include "vf_mulop.h" #include "vf_mulop_data.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmadd-run-1-f16.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmadd-run-1-f16.c index 2be8917..e252e0d 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmadd-run-1-f16.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmadd-run-1-f16.c @@ -1,5 +1,5 @@ /* { dg-do run { target { riscv_v } } } */ -/* { dg-additional-options "--param=fpr2vr-cost=0" } */ +/* { dg-additional-options "-march=rv64gcv_zvfh --param=fpr2vr-cost=0" } */ #include "vf_mulop.h" #include "vf_mulop_data.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmsac-run-1-f16.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmsac-run-1-f16.c index 4f10600..439fd3e 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmsac-run-1-f16.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmsac-run-1-f16.c @@ -1,5 +1,5 @@ /* { dg-do run { target { riscv_v } } } */ -/* { dg-additional-options "--param=fpr2vr-cost=0" } */ +/* { dg-additional-options "-march=rv64gcv_zvfh --param=fpr2vr-cost=0" } */ #include "vf_mulop.h" #include "vf_mulop_data.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmsub-run-1-f16.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmsub-run-1-f16.c index 7bed0ed..b9d66ba 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmsub-run-1-f16.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vf_vfnmsub-run-1-f16.c @@ -1,5 +1,5 @@ /* { dg-do run { target { riscv_v } } } */ -/* { dg-additional-options "--param=fpr2vr-cost=0" } */ +/* { dg-additional-options "-march=rv64gcv_zvfh --param=fpr2vr-cost=0" } */ #include "vf_mulop.h" #include "vf_mulop_data.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i16.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i16.c index 25652ec..83515ee 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i16.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i16.c @@ -19,3 +19,4 @@ TEST_BINARY_VX_SIGNED_0(T) /* { dg-final { scan-assembler-times {vmax.vx} 2 } } */ /* { dg-final { scan-assembler-times {vmin.vx} 2 } } */ /* { dg-final { scan-assembler-times {vsadd.vx} 1 } } */ +/* { dg-final { scan-assembler-times {vssub.vx} 1 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i32.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i32.c index cbf4e28..1488fe1 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i32.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i32.c @@ -19,3 +19,4 @@ TEST_BINARY_VX_SIGNED_0(T) /* { dg-final { scan-assembler-times {vmax.vx} 2 } } */ /* { dg-final { scan-assembler-times {vmin.vx} 2 } } */ /* { dg-final { scan-assembler-times {vsadd.vx} 1 } } */ +/* { dg-final { scan-assembler-times {vssub.vx} 1 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i64.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i64.c index e5519e6..342ea18 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i64.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i64.c @@ -19,3 +19,4 @@ TEST_BINARY_VX_SIGNED_0(T) /* { dg-final { scan-assembler-times {vmax.vx} 2 } } */ /* { dg-final { scan-assembler-times {vmin.vx} 2 } } */ /* { dg-final { scan-assembler-times {vsadd.vx} 1 } } */ +/* { dg-final { scan-assembler-times {vssub.vx} 1 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i8.c index beaf174..583f917 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i8.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i8.c @@ -19,3 +19,4 @@ TEST_BINARY_VX_SIGNED_0(T) /* { dg-final { scan-assembler-times {vmax.vx} 2 } } */ /* { dg-final { scan-assembler-times {vmin.vx} 2 } } */ /* { dg-final { scan-assembler-times {vsadd.vx} 1 } } */ +/* { dg-final { scan-assembler-times {vssub.vx} 1 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i16.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i16.c index 23c0ec9..78d3e0b 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i16.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i16.c @@ -19,3 +19,4 @@ TEST_BINARY_VX_SIGNED_0(T) /* { dg-final { scan-assembler-not {vmax.vx} } } */ /* { dg-final { scan-assembler-not {vmin.vx} } } */ /* { dg-final { scan-assembler-not {vsadd.vx} } } */ +/* { dg-final { scan-assembler-not {vssub.vx} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i32.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i32.c index e5fc38e..e7bcfe5 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i32.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i32.c @@ -19,3 +19,4 @@ TEST_BINARY_VX_SIGNED_0(T) /* { dg-final { scan-assembler-not {vmax.vx} } } */ /* { dg-final { scan-assembler-not {vmin.vx} } } */ /* { dg-final { scan-assembler-not {vsadd.vx} } } */ +/* { dg-final { scan-assembler-not {vssub.vx} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i64.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i64.c index 7701fc9..f9f1e39 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i64.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i64.c @@ -19,3 +19,4 @@ TEST_BINARY_VX_SIGNED_0(T) /* { dg-final { scan-assembler-not {vmax.vx} } } */ /* { dg-final { scan-assembler-not {vmin.vx} } } */ /* { dg-final { scan-assembler-not {vsadd.vx} } } */ +/* { dg-final { scan-assembler-not {vssub.vx} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i8.c index 4b84204..80d6aaa 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i8.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i8.c @@ -19,3 +19,4 @@ TEST_BINARY_VX_SIGNED_0(T) /* { dg-final { scan-assembler-not {vmax.vx} } } */ /* { dg-final { scan-assembler-not {vmin.vx} } } */ /* { dg-final { scan-assembler-not {vsadd.vx} } } */ +/* { dg-final { scan-assembler-not {vssub.vx} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i16.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i16.c index 09058a8..6bf2a35 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i16.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i16.c @@ -19,3 +19,4 @@ TEST_BINARY_VX_SIGNED_0(T) /* { dg-final { scan-assembler-not {vmax.vx} } } */ /* { dg-final { scan-assembler-not {vmin.vx} } } */ /* { dg-final { scan-assembler-not {vsadd.vx} } } */ +/* { dg-final { scan-assembler-not {vssub.vx} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i32.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i32.c index fa0ef42..5432706 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i32.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i32.c @@ -19,3 +19,4 @@ TEST_BINARY_VX_SIGNED_0(T) /* { dg-final { scan-assembler-not {vmax.vx} } } */ /* { dg-final { scan-assembler-not {vmin.vx} } } */ /* { dg-final { scan-assembler-not {vsadd.vx} } } */ +/* { dg-final { scan-assembler-not {vssub.vx} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i64.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i64.c index 7d8358a..a2099fd 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i64.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i64.c @@ -19,3 +19,4 @@ TEST_BINARY_VX_SIGNED_0(T) /* { dg-final { scan-assembler-not {vmax.vx} } } */ /* { dg-final { scan-assembler-not {vmin.vx} } } */ /* { dg-final { scan-assembler-not {vsadd.vx} } } */ +/* { dg-final { scan-assembler-not {vssub.vx} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i8.c index 4657932..1daede9 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i8.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i8.c @@ -19,3 +19,4 @@ TEST_BINARY_VX_SIGNED_0(T) /* { dg-final { scan-assembler-not {vmax.vx} } } */ /* { dg-final { scan-assembler-not {vmin.vx} } } */ /* { dg-final { scan-assembler-not {vsadd.vx} } } */ +/* { dg-final { scan-assembler-not {vssub.vx} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i16.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i16.c index 92f1b7b..d79a9f2 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i16.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i16.c @@ -19,6 +19,7 @@ DEF_VX_BINARY_CASE_3_WRAP(T, MAX_FUNC_1_WARP(T), max, VX_BINARY_FUNC_BODY_X8) DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_0_WARP(T), min, VX_BINARY_FUNC_BODY_X8) DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_1_WARP(T), min, VX_BINARY_FUNC_BODY_X8) DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_ADD_FUNC_WRAP(T), sat_add, VX_BINARY_FUNC_BODY_X8) +DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_SUB_FUNC_WRAP(T), sat_sub, VX_BINARY_FUNC_BODY_X8) /* { dg-final { scan-assembler {vadd.vx} } } */ /* { dg-final { scan-assembler {vsub.vx} } } */ @@ -32,3 +33,4 @@ DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_ADD_FUNC_WRAP(T), sat_add, VX_BINARY_FUNC_BOD /* { dg-final { scan-assembler {vmax.vx} } } */ /* { dg-final { scan-assembler {vmin.vx} } } */ /* { dg-final { scan-assembler {vsadd.vx} } } */ +/* { dg-final { scan-assembler {vssub.vx} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i32.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i32.c index 31594ce..940f596 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i32.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i32.c @@ -19,6 +19,7 @@ DEF_VX_BINARY_CASE_3_WRAP(T, MAX_FUNC_1_WARP(T), max, VX_BINARY_FUNC_BODY_X4) DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_0_WARP(T), min, VX_BINARY_FUNC_BODY_X4) DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_1_WARP(T), min, VX_BINARY_FUNC_BODY_X4) DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_ADD_FUNC_WRAP(T), sat_add, VX_BINARY_FUNC_BODY_X4) +DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_SUB_FUNC_WRAP(T), sat_sub, VX_BINARY_FUNC_BODY_X4) /* { dg-final { scan-assembler {vadd.vx} } } */ /* { dg-final { scan-assembler {vsub.vx} } } */ @@ -32,3 +33,4 @@ DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_ADD_FUNC_WRAP(T), sat_add, VX_BINARY_FUNC_BOD /* { dg-final { scan-assembler {vmax.vx} } } */ /* { dg-final { scan-assembler {vmin.vx} } } */ /* { dg-final { scan-assembler {vsadd.vx} } } */ +/* { dg-final { scan-assembler {vssub.vx} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i64.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i64.c index 02e03ec..22a64f6 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i64.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i64.c @@ -19,6 +19,7 @@ DEF_VX_BINARY_CASE_3_WRAP(T, MAX_FUNC_1_WARP(T), max, VX_BINARY_FUNC_BODY) DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_0_WARP(T), min, VX_BINARY_FUNC_BODY) DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_1_WARP(T), min, VX_BINARY_FUNC_BODY) DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_ADD_FUNC_WRAP(T), sat_add, VX_BINARY_FUNC_BODY) +DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_SUB_FUNC_WRAP(T), sat_sub, VX_BINARY_FUNC_BODY) /* { dg-final { scan-assembler {vadd.vx} } } */ /* { dg-final { scan-assembler {vsub.vx} } } */ @@ -32,3 +33,4 @@ DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_ADD_FUNC_WRAP(T), sat_add, VX_BINARY_FUNC_BOD /* { dg-final { scan-assembler {vmax.vx} } } */ /* { dg-final { scan-assembler {vmin.vx} } } */ /* { dg-final { scan-assembler-not {vsadd.vx} } } */ +/* { dg-final { scan-assembler-not {vssub.vx} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i8.c index 2c296ad..3286b1a 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i8.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i8.c @@ -19,6 +19,7 @@ DEF_VX_BINARY_CASE_3_WRAP(T, MAX_FUNC_1_WARP(T), max, VX_BINARY_FUNC_BODY_X8) DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_0_WARP(T), min, VX_BINARY_FUNC_BODY_X8) DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_1_WARP(T), min, VX_BINARY_FUNC_BODY_X8) DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_ADD_FUNC_WRAP(T), sat_add, VX_BINARY_FUNC_BODY_X8) +DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_SUB_FUNC_WRAP(T), sat_sub, VX_BINARY_FUNC_BODY_X8) /* { dg-final { scan-assembler {vadd.vx} } } */ /* { dg-final { scan-assembler {vsub.vx} } } */ @@ -32,3 +33,4 @@ DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_ADD_FUNC_WRAP(T), sat_add, VX_BINARY_FUNC_BOD /* { dg-final { scan-assembler {vmax.vx} } } */ /* { dg-final { scan-assembler {vmin.vx} } } */ /* { dg-final { scan-assembler {vsadd.vx} } } */ +/* { dg-final { scan-assembler {vssub.vx} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i16.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i16.c index 3ea8f0f..b92db10 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i16.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i16.c @@ -19,6 +19,7 @@ DEF_VX_BINARY_CASE_3_WRAP(T, MAX_FUNC_1_WARP(T), max, VX_BINARY_FUNC_BODY_X8) DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_0_WARP(T), min, VX_BINARY_FUNC_BODY_X8) DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_1_WARP(T), min, VX_BINARY_FUNC_BODY_X8) DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_ADD_FUNC_WRAP(T), sat_add, VX_BINARY_FUNC_BODY_X8) +DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_SUB_FUNC_WRAP(T), sat_sub, VX_BINARY_FUNC_BODY_X8) /* { dg-final { scan-assembler-not {vadd.vx} } } */ /* { dg-final { scan-assembler {vsub.vx} } } */ @@ -32,3 +33,4 @@ DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_ADD_FUNC_WRAP(T), sat_add, VX_BINARY_FUNC_BOD /* { dg-final { scan-assembler {vmax.vx} } } */ /* { dg-final { scan-assembler {vmin.vx} } } */ /* { dg-final { scan-assembler {vsadd.vx} } } */ +/* { dg-final { scan-assembler {vssub.vx} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i32.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i32.c index cb742aa..0870cde 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i32.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i32.c @@ -19,6 +19,7 @@ DEF_VX_BINARY_CASE_3_WRAP(T, MAX_FUNC_1_WARP(T), max, VX_BINARY_FUNC_BODY_X4) DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_0_WARP(T), min, VX_BINARY_FUNC_BODY_X4) DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_1_WARP(T), min, VX_BINARY_FUNC_BODY_X4) DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_ADD_FUNC_WRAP(T), sat_add, VX_BINARY_FUNC_BODY_X4) +DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_SUB_FUNC_WRAP(T), sat_sub, VX_BINARY_FUNC_BODY_X4) /* { dg-final { scan-assembler {vadd.vx} } } */ /* { dg-final { scan-assembler {vsub.vx} } } */ @@ -32,3 +33,4 @@ DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_ADD_FUNC_WRAP(T), sat_add, VX_BINARY_FUNC_BOD /* { dg-final { scan-assembler {vmax.vx} } } */ /* { dg-final { scan-assembler {vmin.vx} } } */ /* { dg-final { scan-assembler-not {vsadd.vx} } } */ +/* { dg-final { scan-assembler-not {vssub.vx} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i64.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i64.c index 1580073..a4d60e9 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i64.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i64.c @@ -19,6 +19,7 @@ DEF_VX_BINARY_CASE_3_WRAP(T, MAX_FUNC_1_WARP(T), max, VX_BINARY_FUNC_BODY) DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_0_WARP(T), min, VX_BINARY_FUNC_BODY) DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_1_WARP(T), min, VX_BINARY_FUNC_BODY) DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_ADD_FUNC_WRAP(T), sat_add, VX_BINARY_FUNC_BODY) +DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_SUB_FUNC_WRAP(T), sat_sub, VX_BINARY_FUNC_BODY) /* { dg-final { scan-assembler {vadd.vx} } } */ /* { dg-final { scan-assembler {vsub.vx} } } */ @@ -32,3 +33,4 @@ DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_ADD_FUNC_WRAP(T), sat_add, VX_BINARY_FUNC_BOD /* { dg-final { scan-assembler {vmax.vx} } } */ /* { dg-final { scan-assembler {vmin.vx} } } */ /* { dg-final { scan-assembler-not {vsadd.vx} } } */ +/* { dg-final { scan-assembler-not {vssub.vx} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i8.c index 16b2e6a..ec069a3 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i8.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i8.c @@ -19,6 +19,7 @@ DEF_VX_BINARY_CASE_3_WRAP(T, MAX_FUNC_1_WARP(T), max, VX_BINARY_FUNC_BODY_X8) DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_0_WARP(T), min, VX_BINARY_FUNC_BODY_X8) DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_1_WARP(T), min, VX_BINARY_FUNC_BODY_X8) DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_ADD_FUNC_WRAP(T), sat_add, VX_BINARY_FUNC_BODY_X8) +DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_SUB_FUNC_WRAP(T), sat_sub, VX_BINARY_FUNC_BODY_X8) /* { dg-final { scan-assembler-not {vadd.vx} } } */ /* { dg-final { scan-assembler {vsub.vx} } } */ @@ -32,3 +33,4 @@ DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_ADD_FUNC_WRAP(T), sat_add, VX_BINARY_FUNC_BOD /* { dg-final { scan-assembler {vmax.vx} } } */ /* { dg-final { scan-assembler {vmin.vx} } } */ /* { dg-final { scan-assembler {vsadd.vx} } } */ +/* { dg-final { scan-assembler {vssub.vx} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i16.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i16.c index 60e2029..473c31b 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i16.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i16.c @@ -19,6 +19,7 @@ DEF_VX_BINARY_CASE_3_WRAP(T, MAX_FUNC_1_WARP(T), max, VX_BINARY_FUNC_BODY_X8) DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_0_WARP(T), min, VX_BINARY_FUNC_BODY_X8) DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_1_WARP(T), min, VX_BINARY_FUNC_BODY_X8) DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_ADD_FUNC_WRAP(T), sat_add, VX_BINARY_FUNC_BODY_X8) +DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_SUB_FUNC_WRAP(T), sat_sub, VX_BINARY_FUNC_BODY_X8) /* { dg-final { scan-assembler-not {vadd.vx} } } */ /* { dg-final { scan-assembler {vsub.vx} } } */ @@ -32,3 +33,4 @@ DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_ADD_FUNC_WRAP(T), sat_add, VX_BINARY_FUNC_BOD /* { dg-final { scan-assembler {vmax.vx} } } */ /* { dg-final { scan-assembler {vmin.vx} } } */ /* { dg-final { scan-assembler {vsadd.vx} } } */ +/* { dg-final { scan-assembler {vssub.vx} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i32.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i32.c index 073d83d3..6ae84c1 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i32.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i32.c @@ -19,6 +19,7 @@ DEF_VX_BINARY_CASE_3_WRAP(T, MAX_FUNC_1_WARP(T), max, VX_BINARY_FUNC_BODY_X4) DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_0_WARP(T), min, VX_BINARY_FUNC_BODY_X4) DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_1_WARP(T), min, VX_BINARY_FUNC_BODY_X4) DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_ADD_FUNC_WRAP(T), sat_add, VX_BINARY_FUNC_BODY_X4) +DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_SUB_FUNC_WRAP(T), sat_sub, VX_BINARY_FUNC_BODY_X4) /* { dg-final { scan-assembler {vadd.vx} } } */ /* { dg-final { scan-assembler {vsub.vx} } } */ @@ -32,3 +33,4 @@ DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_ADD_FUNC_WRAP(T), sat_add, VX_BINARY_FUNC_BOD /* { dg-final { scan-assembler {vmax.vx} } } */ /* { dg-final { scan-assembler {vmin.vx} } } */ /* { dg-final { scan-assembler-not {vsadd.vx} } } */ +/* { dg-final { scan-assembler-not {vssub.vx} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i64.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i64.c index 9a718c6..794f506 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i64.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i64.c @@ -19,6 +19,7 @@ DEF_VX_BINARY_CASE_3_WRAP(T, MAX_FUNC_1_WARP(T), max, VX_BINARY_FUNC_BODY) DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_0_WARP(T), min, VX_BINARY_FUNC_BODY) DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_1_WARP(T), min, VX_BINARY_FUNC_BODY) DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_ADD_FUNC_WRAP(T), sat_add, VX_BINARY_FUNC_BODY) +DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_SUB_FUNC_WRAP(T), sat_sub, VX_BINARY_FUNC_BODY) /* { dg-final { scan-assembler-not {vadd.vx} } } */ /* { dg-final { scan-assembler-not {vsub.vx} } } */ @@ -32,3 +33,4 @@ DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_ADD_FUNC_WRAP(T), sat_add, VX_BINARY_FUNC_BOD /* { dg-final { scan-assembler-not {vmax.vx} } } */ /* { dg-final { scan-assembler-not {vmin.vx} } } */ /* { dg-final { scan-assembler-not {vsadd.vx} } } */ +/* { dg-final { scan-assembler-not {vssub.vx} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i8.c index 02ad831..77bcdeb 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i8.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i8.c @@ -19,6 +19,7 @@ DEF_VX_BINARY_CASE_3_WRAP(T, MAX_FUNC_1_WARP(T), max, VX_BINARY_FUNC_BODY_X8) DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_0_WARP(T), min, VX_BINARY_FUNC_BODY_X8) DEF_VX_BINARY_CASE_3_WRAP(T, MIN_FUNC_1_WARP(T), min, VX_BINARY_FUNC_BODY_X8) DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_ADD_FUNC_WRAP(T), sat_add, VX_BINARY_FUNC_BODY_X8) +DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_SUB_FUNC_WRAP(T), sat_sub, VX_BINARY_FUNC_BODY_X8) /* { dg-final { scan-assembler-not {vadd.vx} } } */ /* { dg-final { scan-assembler {vsub.vx} } } */ @@ -32,3 +33,4 @@ DEF_VX_BINARY_CASE_3_WRAP(T, SAT_S_ADD_FUNC_WRAP(T), sat_add, VX_BINARY_FUNC_BOD /* { dg-final { scan-assembler {vmax.vx} } } */ /* { dg-final { scan-assembler {vmin.vx} } } */ /* { dg-final { scan-assembler {vsadd.vx} } } */ +/* { dg-final { scan-assembler {vssub.vx} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_binary.h b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_binary.h index 944a863..6d4d720 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_binary.h +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_binary.h @@ -311,6 +311,23 @@ DEF_SAT_S_ADD(int16_t, uint16_t, INT16_MIN, INT16_MAX) DEF_SAT_S_ADD(int32_t, uint32_t, INT32_MIN, INT32_MAX) DEF_SAT_S_ADD(int64_t, uint64_t, INT64_MIN, INT64_MAX) +#define DEF_SAT_S_SUB(T, UT, MIN, MAX) \ +T \ +test_##T##_sat_sub (T x, T y) \ +{ \ + T minus = (UT)x - (UT)y; \ + return (x ^ y) >= 0 \ + ? minus \ + : (minus ^ x) >= 0 \ + ? minus \ + : x < 0 ? MIN : MAX; \ +} + +DEF_SAT_S_SUB(int8_t, uint8_t, INT8_MIN, INT8_MAX) +DEF_SAT_S_SUB(int16_t, uint16_t, INT16_MIN, INT16_MAX) +DEF_SAT_S_SUB(int32_t, uint32_t, INT32_MIN, INT32_MAX) +DEF_SAT_S_SUB(int64_t, uint64_t, INT64_MIN, INT64_MAX) + #define SAT_U_ADD_FUNC(T) test_##T##_sat_add #define SAT_U_ADD_FUNC_WRAP(T) SAT_U_ADD_FUNC(T) @@ -320,6 +337,9 @@ DEF_SAT_S_ADD(int64_t, uint64_t, INT64_MIN, INT64_MAX) #define SAT_S_ADD_FUNC(T) test_##T##_sat_add #define SAT_S_ADD_FUNC_WRAP(T) SAT_S_ADD_FUNC(T) +#define SAT_S_SUB_FUNC(T) test_##T##_sat_sub +#define SAT_S_SUB_FUNC_WRAP(T) SAT_S_SUB_FUNC(T) + #define TEST_BINARY_VX_SIGNED_0(T) \ DEF_VX_BINARY_CASE_0_WRAP(T, +, add) \ DEF_VX_BINARY_CASE_0_WRAP(T, -, sub) \ @@ -335,6 +355,7 @@ DEF_SAT_S_ADD(int64_t, uint64_t, INT64_MIN, INT64_MAX) DEF_VX_BINARY_CASE_2_WRAP(T, MIN_FUNC_0_WARP(T), min) \ DEF_VX_BINARY_CASE_2_WRAP(T, MIN_FUNC_1_WARP(T), min) \ DEF_VX_BINARY_CASE_2_WRAP(T, SAT_S_ADD_FUNC(T), sat_add) \ + DEF_VX_BINARY_CASE_2_WRAP(T, SAT_S_SUB_FUNC(T), sat_sub) \ #define TEST_BINARY_VX_UNSIGNED_0(T) \ DEF_VX_BINARY_CASE_0_WRAP(T, +, add) \ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_binary_data.h b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_binary_data.h index 9020eaf..47f6128 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_binary_data.h +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_binary_data.h @@ -4710,4 +4710,200 @@ int64_t TEST_BINARY_DATA(int64_t, sat_add)[][3][N] = }, }; +int8_t TEST_BINARY_DATA(int8_t, sat_sub)[][3][N] = +{ + { + { 1 }, + { + 2, 2, 2, 2, + 1, 1, 1, 1, + 0, 0, 0, 0, + 4, 4, 4, 4, + }, + { + 1, 1, 1, 1, + 0, 0, 0, 0, + -1, -1, -1, -1, + 3, 3, 3, 3, + }, + }, + { + { 127 }, + { + 127, 127, 127, 127, + -128, -128, -128, -128, + -127, -127, -127, -127, + 1, 1, 1, 1, + }, + { + 0, 0, 0, 0, + -128, -128, -128, -128, + -128, -128, -128, -128, + -126, -126, -126, -126, + }, + }, + { + { -128 }, + { + 127, 127, 127, 127, + -1, -1, -1, -1, + -128, -128, -128, -128, + 1, 1, 1, 1, + }, + { + 127, 127, 127, 127, + 127, 127, 127, 127, + 0, 0, 0, 0, + 127, 127, 127, 127, + }, + }, +}; + +int16_t TEST_BINARY_DATA(int16_t, sat_sub)[][3][N] = +{ + { + { 1 }, + { + 2, 2, 2, 2, + 1, 1, 1, 1, + 0, 0, 0, 0, + 4, 4, 4, 4, + }, + { + 1, 1, 1, 1, + 0, 0, 0, 0, + -1, -1, -1, -1, + 3, 3, 3, 3, + }, + }, + { + { 32767 }, + { + 32767, 32767, 32767, 32767, + -32768, -32768, -32768, -32768, + -32767, -32767, -32767, -32767, + 1, 1, 1, 1, + }, + { + 0, 0, 0, 0, + -32768, -32768, -32768, -32768, + -32768, -32768, -32768, -32768, + -32766, -32766, -32766, -32766, + }, + }, + { + { -32768 }, + { + 32767, 32767, 32767, 32767, + -1, -1, -1, -1, + -32768, -32768, -32768, -32768, + 1, 1, 1, 1, + }, + { + 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, + 0, 0, 0, 0, + 32767, 32767, 32767, 32767, + }, + }, +}; + +int32_t TEST_BINARY_DATA(int32_t, sat_sub)[][3][N] = +{ + { + { 1 }, + { + 2, 2, 2, 2, + 1, 1, 1, 1, + 0, 0, 0, 0, + 4, 4, 4, 4, + }, + { + 1, 1, 1, 1, + 0, 0, 0, 0, + -1, -1, -1, -1, + 3, 3, 3, 3, + }, + }, + { + { 2147483647 }, + { + 2147483647, 2147483647, 2147483647, 2147483647, + -2147483648, -2147483648, -2147483648, -2147483648, + -2147483647, -2147483647, -2147483647, -2147483647, + 1, 1, 1, 1, + }, + { + 0, 0, 0, 0, + -2147483648, -2147483648, -2147483648, -2147483648, + -2147483648, -2147483648, -2147483648, -2147483648, + -2147483646, -2147483646, -2147483646, -2147483646, + }, + }, + { + { -2147483648 }, + { + 2147483647, 2147483647, 2147483647, 2147483647, + -1, -1, -1, -1, + -2147483648, -2147483648, -2147483648, -2147483648, + 1, 1, 1, 1, + }, + { + 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, + 0, 0, 0, 0, + 2147483647, 2147483647, 2147483647, 2147483647, + }, + }, +}; + +int64_t TEST_BINARY_DATA(int64_t, sat_sub)[][3][N] = +{ + { + { 1 }, + { + 2, 2, 2, 2, + 1, 1, 1, 1, + 0, 0, 0, 0, + 4, 4, 4, 4, + }, + { + 1, 1, 1, 1, + 0, 0, 0, 0, + -1, -1, -1, -1, + 3, 3, 3, 3, + }, + }, + { + { 9223372036854775807ull }, + { + 9223372036854775807ull, 9223372036854775807ull, 9223372036854775807ull, 9223372036854775807ull, + -9223372036854775808ull, -9223372036854775808ull, -9223372036854775808ull, -9223372036854775808ull, + -9223372036854775807ull, -9223372036854775807ull, -9223372036854775807ull, -9223372036854775807ull, + 1, 1, 1, 1, + }, + { + 0, 0, 0, 0, + -9223372036854775808ull, -9223372036854775808ull, -9223372036854775808ull, -9223372036854775808ull, + -9223372036854775808ull, -9223372036854775808ull, -9223372036854775808ull, -9223372036854775808ull, + -9223372036854775806ull, -9223372036854775806ull, -9223372036854775806ull, -9223372036854775806ull, + }, + }, + { + { -9223372036854775808ull }, + { + 9223372036854775807ull, 9223372036854775807ull, 9223372036854775807ull, 9223372036854775807ull, + -1, -1, -1, -1, + -9223372036854775808ull, -9223372036854775808ull, -9223372036854775808ull, -9223372036854775808ull, + 1, 1, 1, 1, + }, + { + 9223372036854775807ull, 9223372036854775807ull, 9223372036854775807ull, 9223372036854775807ull, + 9223372036854775807ull, 9223372036854775807ull, 9223372036854775807ull, 9223372036854775807ull, + 0, 0, 0, 0, + 9223372036854775807ull, 9223372036854775807ull, 9223372036854775807ull, 9223372036854775807ull, + }, + }, +}; + #endif diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vssub-run-1-i16.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vssub-run-1-i16.c new file mode 100644 index 0000000..bd985c2 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vssub-run-1-i16.c @@ -0,0 +1,17 @@ +/* { dg-do run { target { riscv_v } } } */ +/* { dg-additional-options "-std=c99 --param=gpr2vr-cost=0" } */ + +#include "vx_binary.h" +#include "vx_binary_data.h" + +#define T int16_t +#define NAME sat_sub +#define FUNC SAT_S_SUB_FUNC_WRAP(T) +#define TEST_DATA TEST_BINARY_DATA_WRAP(T, NAME) + +DEF_VX_BINARY_CASE_2_WRAP(T, FUNC, NAME) + +#define TEST_RUN(T, NAME, out, in, x, n) \ + RUN_VX_BINARY_CASE_2_WRAP(T, NAME, FUNC, out, in, x, n) + +#include "vx_binary_run.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vssub-run-1-i32.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vssub-run-1-i32.c new file mode 100644 index 0000000..c510ea0 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vssub-run-1-i32.c @@ -0,0 +1,17 @@ +/* { dg-do run { target { riscv_v } } } */ +/* { dg-additional-options "-std=c99 --param=gpr2vr-cost=0" } */ + +#include "vx_binary.h" +#include "vx_binary_data.h" + +#define T int32_t +#define NAME sat_sub +#define FUNC SAT_S_SUB_FUNC_WRAP(T) +#define TEST_DATA TEST_BINARY_DATA_WRAP(T, NAME) + +DEF_VX_BINARY_CASE_2_WRAP(T, FUNC, NAME) + +#define TEST_RUN(T, NAME, out, in, x, n) \ + RUN_VX_BINARY_CASE_2_WRAP(T, NAME, FUNC, out, in, x, n) + +#include "vx_binary_run.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vssub-run-1-i64.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vssub-run-1-i64.c new file mode 100644 index 0000000..b82278d --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vssub-run-1-i64.c @@ -0,0 +1,17 @@ +/* { dg-do run { target { riscv_v } } } */ +/* { dg-additional-options "-std=c99 --param=gpr2vr-cost=0" } */ + +#include "vx_binary.h" +#include "vx_binary_data.h" + +#define T int64_t +#define NAME sat_sub +#define FUNC SAT_S_SUB_FUNC_WRAP(T) +#define TEST_DATA TEST_BINARY_DATA_WRAP(T, NAME) + +DEF_VX_BINARY_CASE_2_WRAP(T, FUNC, NAME) + +#define TEST_RUN(T, NAME, out, in, x, n) \ + RUN_VX_BINARY_CASE_2_WRAP(T, NAME, FUNC, out, in, x, n) + +#include "vx_binary_run.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vssub-run-1-i8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vssub-run-1-i8.c new file mode 100644 index 0000000..5fae704 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx_vssub-run-1-i8.c @@ -0,0 +1,17 @@ +/* { dg-do run { target { riscv_v } } } */ +/* { dg-additional-options "-std=c99 --param=gpr2vr-cost=0" } */ + +#include "vx_binary.h" +#include "vx_binary_data.h" + +#define T int8_t +#define NAME sat_sub +#define FUNC SAT_S_SUB_FUNC_WRAP(T) +#define TEST_DATA TEST_BINARY_DATA_WRAP(T, NAME) + +DEF_VX_BINARY_CASE_2_WRAP(T, FUNC, NAME) + +#define TEST_RUN(T, NAME, out, in, x, n) \ + RUN_VX_BINARY_CASE_2_WRAP(T, NAME, FUNC, out, in, x, n) + +#include "vx_binary_run.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/pr113829.c b/gcc/testsuite/gcc.target/riscv/rvv/base/pr113829.c new file mode 100644 index 0000000..48c291a --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/pr113829.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=rv64gcv -mabi=lp64d" } */ + +#pragma riscv intrinsic "vector" +void +foo (void) +{ + __riscv_vfredosum_tu (X); /* { dg-error "undeclared" } */ + /* { dg-error "too many arguments" "" { target *-*-* } .-1 } */ +} diff --git a/gcc/testsuite/gcc.target/riscv/rvv/xtheadvector/pr120461.c b/gcc/testsuite/gcc.target/riscv/rvv/xtheadvector/pr120461.c new file mode 100644 index 0000000..6939157 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/xtheadvector/pr120461.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-options "-mcpu=xt-c920 -mrvv-vector-bits=zvl -fzero-call-used-regs=all" */ + +void +foo () +{} diff --git a/gcc/testsuite/gcc.target/riscv/rvv/xtheadvector/pr120642.c b/gcc/testsuite/gcc.target/riscv/rvv/xtheadvector/pr120642.c new file mode 100644 index 0000000..1a72580 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/xtheadvector/pr120642.c @@ -0,0 +1,4 @@ +/* { dg-do compile } */ +/* { dg-options "-O -mcpu=xt-c920 -mrvv-vector-bits=zvl" } */ +int __attribute__((__vector_size__(4 * sizeof(int)))) v; +void foo() { v /= 3; } diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_arith.h b/gcc/testsuite/gcc.target/riscv/sat/sat_arith.h index 84f013f..7e2c93e 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_arith.h +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_arith.h @@ -4,6 +4,10 @@ #include <stdint-gcc.h> #include <stdbool.h> +#if __riscv_xlen == 64 +typedef unsigned __int128 uint128_t; +#endif + /******************************************************************************/ /* Saturation Add (unsigned and signed) */ /******************************************************************************/ @@ -648,4 +652,25 @@ sat_s_trunc_##WT##_to_##NT##_fmt_8 (WT x) \ #define RUN_SAT_S_TRUNC_FMT_8(NT, WT, x) sat_s_trunc_##WT##_to_##NT##_fmt_8 (x) #define RUN_SAT_S_TRUNC_FMT_8_WRAP(NT, WT, x) RUN_SAT_S_TRUNC_FMT_8(NT, WT, x) +/******************************************************************************/ +/* Saturation Mult (unsigned and signed) */ +/******************************************************************************/ + +#define DEF_SAT_U_MUL_FMT_1(NT, WT) \ +NT __attribute__((noinline)) \ +sat_u_mul_##NT##_from_##WT##_fmt_1 (NT a, NT b) \ +{ \ + WT x = (WT)a * (WT)b; \ + NT max = -1; \ + if (x > (WT)(max)) \ + return max; \ + else \ + return (NT)x; \ +} + +#define DEF_SAT_U_MUL_FMT_1_WRAP(NT, WT) DEF_SAT_U_MUL_FMT_1(NT, WT) +#define RUN_SAT_U_MUL_FMT_1(NT, WT, a, b) \ + sat_u_mul_##NT##_from_##WT##_fmt_1 (a, b) +#define RUN_SAT_U_MUL_FMT_1_WRAP(NT, WT, a, b) RUN_SAT_U_MUL_FMT_1(NT, WT, a, b) + #endif diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_arith_data.h b/gcc/testsuite/gcc.target/riscv/sat/sat_arith_data.h index f100688..bd33ff1 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_arith_data.h +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_arith_data.h @@ -12,6 +12,7 @@ #define TEST_BINARY_STRUCT_NAME(T, NAME) test_##T##_##NAME##_s #define TEST_BINARY_STRUCT_DECL(T, NAME) struct TEST_BINARY_STRUCT_NAME(T, NAME) +#define TEST_BINARY_STRUCT_DECL_WRAP(T, NAME) TEST_BINARY_STRUCT_DECL(T, NAME) #define TEST_BINARY_STRUCT(T, NAME) \ struct TEST_BINARY_STRUCT_NAME(T, NAME) \ { \ @@ -37,6 +38,11 @@ TEST_BINARY_STRUCT (uint16_t, usadd) TEST_BINARY_STRUCT (uint32_t, usadd) TEST_BINARY_STRUCT (uint64_t, usadd) +TEST_BINARY_STRUCT (uint8_t, usmul) +TEST_BINARY_STRUCT (uint16_t, usmul) +TEST_BINARY_STRUCT (uint32_t, usmul) +TEST_BINARY_STRUCT (uint64_t, usmul) + TEST_BINARY_STRUCT (int8_t, ssadd) TEST_BINARY_STRUCT (int16_t, ssadd) TEST_BINARY_STRUCT (int32_t, ssadd) @@ -433,4 +439,60 @@ TEST_BINARY_STRUCT_DECL(int64_t, sssub) TEST_BINARY_DATA(int64_t, sssub)[] = { 9223372036854775806ll, 9223372036854775800ll, 6}, }; +TEST_BINARY_STRUCT_DECL(uint8_t, usmul) TEST_BINARY_DATA(uint8_t, usmul)[] = +{ + { 0, 0, 0, }, + { 0, 1, 0, }, + { 1, 1, 1, }, + { 1, 127, 127, }, + { 2, 127, 254, }, + { 3, 127, 255, }, + { 127, 127, 255, }, + { 1, 255, 255, }, + { 127, 255, 255, }, + { 255, 255, 255, }, +}; + +TEST_BINARY_STRUCT_DECL(uint16_t, usmul) TEST_BINARY_DATA(uint16_t, usmul)[] = +{ + { 0, 0, 0, }, + { 0, 1, 0, }, + { 1, 1, 1, }, + { 1, 32767, 32767, }, + { 2, 32767, 65534, }, + { 3, 32767, 65535, }, + { 32767, 32767, 65535, }, + { 1, 65535, 65535, }, + { 32767, 65535, 65535, }, + { 65535, 65535, 65535, }, +}; + +TEST_BINARY_STRUCT_DECL(uint32_t, usmul) TEST_BINARY_DATA(uint32_t, usmul)[] = +{ + { 0, 0, 0, }, + { 0, 1, 0, }, + { 1, 1, 1, }, + { 1, 2147483647, 2147483647, }, + { 2, 2147483647, 4294967294, }, + { 3, 2147483647, 4294967295, }, + { 2147483647, 2147483647, 4294967295, }, + { 1, 4294967295, 4294967295, }, + { 2147483647, 4294967295, 4294967295, }, + { 4294967295, 4294967295, 4294967295, }, +}; + +TEST_BINARY_STRUCT_DECL(uint64_t, usmul) TEST_BINARY_DATA(uint64_t, usmul)[] = +{ + { 0, 0, 0, }, + { 0, 1, 0, }, + { 1, 1, 1, }, + { 1, 9223372036854775807ull, 9223372036854775807ull, }, + { 2, 9223372036854775807ull, 18446744073709551614ull, }, + { 3, 9223372036854775807ull, 18446744073709551615ull, }, + { 9223372036854775807ull, 9223372036854775807ull, 18446744073709551615ull, }, + { 1, 18446744073709551615ull, 18446744073709551615ull, }, + { 9223372036854775807ull, 18446744073709551615ull, 18446744073709551615ull, }, + { 18446744073709551615ull, 18446744073709551615ull, 18446744073709551615ull, }, +}; + #endif diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-1-i16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-1-i16.c index 34459b8..1023934 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-1-i16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-1-i16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-1-i32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-1-i32.c index 4d4841f..bccb768 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-1-i32.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-1-i32.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-1-i64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-1-i64.c index df81887..34de520 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-1-i64.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-1-i64.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-1-i8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-1-i8.c index 9a4ce33..6d136ec 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-1-i8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-1-i8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-2-i16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-2-i16.c index cdac5bd..ee8e439 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-2-i16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-2-i16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-2-i32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-2-i32.c index 4ac952e..8996dd2 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-2-i32.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-2-i32.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-2-i64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-2-i64.c index 4d25e7f..155c8e9 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-2-i64.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-2-i64.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-2-i8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-2-i8.c index d57e0a0..4502ed3 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-2-i8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-2-i8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-3-i16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-3-i16.c index 08b961a..21289c9 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-3-i16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-3-i16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-3-i32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-3-i32.c index 3611b6e..3d4a6fa 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-3-i32.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-3-i32.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-3-i64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-3-i64.c index 3eaa6c2..b55d221 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-3-i64.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-3-i64.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-3-i8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-3-i8.c index 6d38e5f..9fef8b0 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-3-i8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-3-i8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-4-i16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-4-i16.c index 2e73450..fd135e5 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-4-i16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-4-i16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-4-i32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-4-i32.c index ec3022d..38ade40 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-4-i32.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-4-i32.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-4-i64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-4-i64.c index 911856e..04ba746 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-4-i64.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-4-i64.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-4-i8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-4-i8.c index 94d48ef..32aea5c 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-4-i8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_add-run-4-i8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-1-i16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-1-i16.c index e248b73..b2c5735 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-1-i16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-1-i16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-1-i32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-1-i32.c index bebb4be..6d1518e 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-1-i32.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-1-i32.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-1-i64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-1-i64.c index f31eb29..adcd1bb 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-1-i64.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-1-i64.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-1-i8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-1-i8.c index e165e39..31fa0a6 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-1-i8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-1-i8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-2-i16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-2-i16.c index 08a9b5c..0c5ad8c 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-2-i16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-2-i16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-2-i32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-2-i32.c index fc79969..5e89539 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-2-i32.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-2-i32.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-2-i64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-2-i64.c index 8d5f745..199e204 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-2-i64.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-2-i64.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-2-i8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-2-i8.c index 9f6ef30..4cfe787 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-2-i8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-2-i8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-3-i16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-3-i16.c index 0523d13..3cf4ecd 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-3-i16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-3-i16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-3-i32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-3-i32.c index e720964..ce2151c 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-3-i32.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-3-i32.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-3-i64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-3-i64.c index 49ed051..158eeaa 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-3-i64.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-3-i64.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-3-i8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-3-i8.c index 99b413f..8eb7ab5 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-3-i8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-3-i8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-4-i16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-4-i16.c index c7056ed..339a403 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-4-i16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-4-i16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-4-i32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-4-i32.c index 7168f94..285733a 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-4-i32.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-4-i32.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-4-i64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-4-i64.c index 29b2b54..546bac1 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-4-i64.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-4-i64.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-4-i8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-4-i8.c index 65027b7..dafc86f1 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-4-i8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_sub-run-4-i8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-1-i16-to-i8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-1-i16-to-i8.c index 1f230c5..7ed6809 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-1-i16-to-i8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-1-i16-to-i8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-1-i32-to-i16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-1-i32-to-i16.c index 563760b..82e4201 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-1-i32-to-i16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-1-i32-to-i16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-1-i32-to-i8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-1-i32-to-i8.c index af50d3e..78be831 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-1-i32-to-i8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-1-i32-to-i8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-1-i64-to-i16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-1-i64-to-i16.c index 4ac7025..e8a497f 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-1-i64-to-i16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-1-i64-to-i16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-1-i64-to-i32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-1-i64-to-i32.c index ca6d31c..1420541 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-1-i64-to-i32.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-1-i64-to-i32.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-1-i64-to-i8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-1-i64-to-i8.c index 697e1bc..31fecc7 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-1-i64-to-i8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-1-i64-to-i8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-2-i16-to-i8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-2-i16-to-i8.c index 0d9da40..333bb92 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-2-i16-to-i8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-2-i16-to-i8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-2-i32-to-i16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-2-i32-to-i16.c index 2e183ef..f494909 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-2-i32-to-i16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-2-i32-to-i16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-2-i32-to-i8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-2-i32-to-i8.c index 1950092..d8a619b 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-2-i32-to-i8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-2-i32-to-i8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-2-i64-to-i16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-2-i64-to-i16.c index b11b097..348832d 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-2-i64-to-i16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-2-i64-to-i16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-2-i64-to-i32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-2-i64-to-i32.c index 419e909..fc183cf 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-2-i64-to-i32.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-2-i64-to-i32.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-2-i64-to-i8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-2-i64-to-i8.c index de3d9f1..dec54d3 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-2-i64-to-i8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-2-i64-to-i8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-3-i16-to-i8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-3-i16-to-i8.c index 032c83b..2b8700a 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-3-i16-to-i8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-3-i16-to-i8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-3-i32-to-i16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-3-i32-to-i16.c index 51f4946..cf3f763 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-3-i32-to-i16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-3-i32-to-i16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-3-i32-to-i8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-3-i32-to-i8.c index b959bce..20a68bb 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-3-i32-to-i8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-3-i32-to-i8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-3-i64-to-i16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-3-i64-to-i16.c index ddfb522..5159ab1 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-3-i64-to-i16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-3-i64-to-i16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-3-i64-to-i32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-3-i64-to-i32.c index 22965e2..edeff90 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-3-i64-to-i32.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-3-i64-to-i32.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-3-i64-to-i8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-3-i64-to-i8.c index 7cba408..7a22637 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-3-i64-to-i8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-3-i64-to-i8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-4-i16-to-i8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-4-i16-to-i8.c index 6dfdd4b..65f9aea 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-4-i16-to-i8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-4-i16-to-i8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-4-i32-to-i16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-4-i32-to-i16.c index fcf8e47..ab32e5d 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-4-i32-to-i16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-4-i32-to-i16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-4-i32-to-i8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-4-i32-to-i8.c index 9d911a4..eecfc49 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-4-i32-to-i8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-4-i32-to-i8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-4-i64-to-i16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-4-i64-to-i16.c index 3cc2498..410d202 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-4-i64-to-i16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-4-i64-to-i16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-4-i64-to-i32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-4-i64-to-i32.c index b9abf50..17518ba 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-4-i64-to-i32.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-4-i64-to-i32.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-4-i64-to-i8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-4-i64-to-i8.c index d90682f..bf0c43e 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-4-i64-to-i8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-4-i64-to-i8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-5-i16-to-i8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-5-i16-to-i8.c index 1911166..bac1fda 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-5-i16-to-i8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-5-i16-to-i8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-5-i32-to-i16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-5-i32-to-i16.c index 28116eb..3a82ea0 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-5-i32-to-i16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-5-i32-to-i16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-5-i32-to-i8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-5-i32-to-i8.c index 54b1ffb..26a89e7 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-5-i32-to-i8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-5-i32-to-i8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-5-i64-to-i16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-5-i64-to-i16.c index 633417b..a8bfeef 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-5-i64-to-i16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-5-i64-to-i16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-5-i64-to-i32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-5-i64-to-i32.c index c5e4e4a..f79a049 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-5-i64-to-i32.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-5-i64-to-i32.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-5-i64-to-i8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-5-i64-to-i8.c index 9acbee0..eea31af 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-5-i64-to-i8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-5-i64-to-i8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-6-i16-to-i8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-6-i16-to-i8.c index db1a698..0ea32f0 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-6-i16-to-i8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-6-i16-to-i8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-6-i32-to-i16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-6-i32-to-i16.c index e6b52d4..39e44d8 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-6-i32-to-i16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-6-i32-to-i16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-6-i32-to-i8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-6-i32-to-i8.c index d83836d..cb42b7e 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-6-i32-to-i8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-6-i32-to-i8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-6-i64-to-i16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-6-i64-to-i16.c index e910edf..f64a46b 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-6-i64-to-i16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-6-i64-to-i16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-6-i64-to-i32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-6-i64-to-i32.c index 98dd0c2..18e9029 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-6-i64-to-i32.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-6-i64-to-i32.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-6-i64-to-i8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-6-i64-to-i8.c index b843300..d8cda79 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-6-i64-to-i8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-6-i64-to-i8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-7-i16-to-i8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-7-i16-to-i8.c index ab51ad5..894d5f5 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-7-i16-to-i8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-7-i16-to-i8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-7-i32-to-i16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-7-i32-to-i16.c index 9b2c525..1ced757 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-7-i32-to-i16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-7-i32-to-i16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-7-i32-to-i8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-7-i32-to-i8.c index ab409f2..ab41a84 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-7-i32-to-i8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-7-i32-to-i8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-7-i64-to-i16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-7-i64-to-i16.c index 9013952..c078136 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-7-i64-to-i16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-7-i64-to-i16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-7-i64-to-i32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-7-i64-to-i32.c index 67e19e7..af86e69 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-7-i64-to-i32.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-7-i64-to-i32.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-7-i64-to-i8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-7-i64-to-i8.c index a573706..4a2532d 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-7-i64-to-i8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-7-i64-to-i8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-8-i16-to-i8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-8-i16-to-i8.c index dbd70de..65c82ad 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-8-i16-to-i8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-8-i16-to-i8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-8-i32-to-i16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-8-i32-to-i16.c index 25bb42f..a8cb8e1 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-8-i32-to-i16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-8-i32-to-i16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-8-i32-to-i8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-8-i32-to-i8.c index 7c71b3d..5b5f8f4 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-8-i32-to-i8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-8-i32-to-i8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-8-i64-to-i16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-8-i64-to-i16.c index 61392b5..f489846 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-8-i64-to-i16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-8-i64-to-i16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-8-i64-to-i32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-8-i64-to-i32.c index b47e5da..a3f3ae5 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-8-i64-to-i32.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-8-i64-to-i32.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-8-i64-to-i8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-8-i64-to-i8.c index 1cd7f80..aafe96b 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-8-i64-to-i8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_s_trunc-run-8-i64-to-i8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-1-u16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-1-u16.c index fe015cc..548fae3 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-1-u16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-1-u16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-1-u32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-1-u32.c index 8ee6501..e76b636 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-1-u32.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-1-u32.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-1-u64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-1-u64.c index d2c6af0..0ea6509 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-1-u64.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-1-u64.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-1-u8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-1-u8.c index 154edde..3aa7441 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-1-u8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-1-u8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-2-u16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-2-u16.c index 1fc08bd..f6f8b9d 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-2-u16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-2-u16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-2-u32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-2-u32.c index a52a230..da8c3eb 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-2-u32.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-2-u32.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-2-u64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-2-u64.c index d05ed33..03f5960 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-2-u64.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-2-u64.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-2-u8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-2-u8.c index fd39335..af898e55 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-2-u8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-2-u8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-3-u16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-3-u16.c index 7084272..7862a48 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-3-u16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-3-u16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-3-u32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-3-u32.c index 82de67d..d2fbcf2 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-3-u32.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-3-u32.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-3-u64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-3-u64.c index d73f305..23b5488 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-3-u64.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-3-u64.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-3-u8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-3-u8.c index f572c44..b5931d4 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-3-u8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-3-u8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-4-u16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-4-u16.c index 65c431f..a9937a7 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-4-u16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-4-u16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-4-u32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-4-u32.c index 8a73fcd..966831a 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-4-u32.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-4-u32.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-4-u64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-4-u64.c index 0903e10..08db7a1 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-4-u64.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-4-u64.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-4-u8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-4-u8.c index ffdd390..f7bbb5a 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-4-u8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-4-u8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-5-u16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-5-u16.c index 72ccd2f..da1782d 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-5-u16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-5-u16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-5-u32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-5-u32.c index 34d1a4e..524106a 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-5-u32.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-5-u32.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-5-u64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-5-u64.c index d502a58..62fdd25 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-5-u64.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-5-u64.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-5-u8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-5-u8.c index f611376..334eb04 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-5-u8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-5-u8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-6-u16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-6-u16.c index 5ef250d..28a2fb8 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-6-u16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-6-u16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-6-u32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-6-u32.c index ba95dbf..3b19af3 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-6-u32.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-6-u32.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-6-u64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-6-u64.c index d0e9dfd..f35334a 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-6-u64.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-6-u64.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-6-u8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-6-u8.c index b3d00df..e04fbf0 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-6-u8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-6-u8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-7-u16-from-u32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-7-u16-from-u32.c index 26c2778..3363220 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-7-u16-from-u32.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-7-u16-from-u32.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-7-u16-from-u64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-7-u16-from-u64.c index 1f3e2f3..bc4ca2f 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-7-u16-from-u64.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-7-u16-from-u64.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-7-u32-from-u64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-7-u32-from-u64.c index 558f6ce..04abd95 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-7-u32-from-u64.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-7-u32-from-u64.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-7-u8-from-u16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-7-u8-from-u16.c index ec5ac70..c514a86 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-7-u8-from-u16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-7-u8-from-u16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-7-u8-from-u32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-7-u8-from-u32.c index aa94eef..b1a644b 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-7-u8-from-u32.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-7-u8-from-u32.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-7-u8-from-u64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-7-u8-from-u64.c index 6ac38ba..8664ffa 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-7-u8-from-u64.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add-run-7-u8-from-u64.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-1-u16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-1-u16.c index 090c765..e715bb0 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-1-u16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-1-u16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-1-u32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-1-u32.c index 8dade74..8b8b475 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-1-u32.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-1-u32.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-1-u64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-1-u64.c index ace2df8..f6f6408 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-1-u64.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-1-u64.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-1-u8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-1-u8.c index 0ce546f..f2154fc 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-1-u8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-1-u8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-2-u16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-2-u16.c index 7b6bd73..8e3aa83 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-2-u16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-2-u16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-2-u32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-2-u32.c index 8024152..403cf14 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-2-u32.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-2-u32.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-2-u64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-2-u64.c index 4a76dbb..17eca5e 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-2-u64.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-2-u64.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-2-u8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-2-u8.c index 8e8759c..9a277a1 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-2-u8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-2-u8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-3-u16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-3-u16.c index 64924a6..2068037 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-3-u16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-3-u16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-3-u32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-3-u32.c index 04f3217..5f8f1e6 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-3-u32.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-3-u32.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-3-u64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-3-u64.c index 8ef6c14..c574521 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-3-u64.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-3-u64.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-3-u8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-3-u8.c index 8867361..6b9439a 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-3-u8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-3-u8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-4-u16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-4-u16.c index 0b75206..224c3ae 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-4-u16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-4-u16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-4-u32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-4-u32.c index e548d0c..5c03e1b7 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-4-u32.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-4-u32.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-4-u64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-4-u64.c index 4335d82..1ceacd2 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-4-u64.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-4-u64.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-4-u8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-4-u8.c index 872923e..aef253c 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-4-u8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_add_imm-run-4-u8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-1-u16-from-u128.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-1-u16-from-u128.c new file mode 100644 index 0000000..b60c91c --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-1-u16-from-u128.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gc -mabi=lp64d -fdump-tree-optimized" } */ + +#include "sat_arith.h" + +#define NT uint16_t +#define WT uint128_t + +DEF_SAT_U_MUL_FMT_1_WRAP(NT, WT) + +/* { dg-final { scan-tree-dump-times ".SAT_MUL" 1 "optimized" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-1-u32-from-u128.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-1-u32-from-u128.c new file mode 100644 index 0000000..1ac6f39 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-1-u32-from-u128.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gc -mabi=lp64d -fdump-tree-optimized" } */ + +#include "sat_arith.h" + +#define NT uint32_t +#define WT uint128_t + +DEF_SAT_U_MUL_FMT_1_WRAP(NT, WT) + +/* { dg-final { scan-tree-dump-times ".SAT_MUL" 1 "optimized" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-1-u64-from-u128.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-1-u64-from-u128.c new file mode 100644 index 0000000..af12d82 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-1-u64-from-u128.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gc -mabi=lp64d -fdump-tree-optimized" } */ + +#include "sat_arith.h" + +#define NT uint64_t +#define WT uint128_t + +DEF_SAT_U_MUL_FMT_1_WRAP(NT, WT) + +/* { dg-final { scan-tree-dump-times ".SAT_MUL" 1 "optimized" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-1-u8-from-u128.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-1-u8-from-u128.c new file mode 100644 index 0000000..c73353a --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-1-u8-from-u128.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gc -mabi=lp64d -fdump-tree-optimized" } */ + +#include "sat_arith.h" + +#define NT uint8_t +#define WT uint128_t + +DEF_SAT_U_MUL_FMT_1_WRAP(NT, WT) + +/* { dg-final { scan-tree-dump-times ".SAT_MUL" 1 "optimized" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u16-from-u128.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u16-from-u128.c new file mode 100644 index 0000000..79f6297 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u16-from-u128.c @@ -0,0 +1,16 @@ +/* { dg-do run { target { rv64 } } } */ +/* { dg-additional-options "-std=c99" } */ + +#include "sat_arith.h" +#include "sat_arith_data.h" + +#define NT uint16_t +#define WT uint128_t +#define NAME usmul +#define DATA TEST_BINARY_DATA_WRAP(NT, NAME) +#define T TEST_BINARY_STRUCT_DECL_WRAP(NT, NAME) +#define RUN_BINARY(x, y) RUN_SAT_U_MUL_FMT_1_WRAP(NT, WT, x, y) + +DEF_SAT_U_MUL_FMT_1_WRAP(NT, WT) + +#include "scalar_sat_binary_run_xxx.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u32-from-u128.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u32-from-u128.c new file mode 100644 index 0000000..e5a9462 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u32-from-u128.c @@ -0,0 +1,16 @@ +/* { dg-do run { target { rv64 } } } */ +/* { dg-additional-options "-std=c99" } */ + +#include "sat_arith.h" +#include "sat_arith_data.h" + +#define NT uint32_t +#define WT uint128_t +#define NAME usmul +#define DATA TEST_BINARY_DATA_WRAP(NT, NAME) +#define T TEST_BINARY_STRUCT_DECL_WRAP(NT, NAME) +#define RUN_BINARY(x, y) RUN_SAT_U_MUL_FMT_1_WRAP(NT, WT, x, y) + +DEF_SAT_U_MUL_FMT_1_WRAP(NT, WT) + +#include "scalar_sat_binary_run_xxx.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u64-from-u128.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u64-from-u128.c new file mode 100644 index 0000000..cbe2a22 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u64-from-u128.c @@ -0,0 +1,16 @@ +/* { dg-do run { target { rv64 } } } */ +/* { dg-additional-options "-std=c99" } */ + +#include "sat_arith.h" +#include "sat_arith_data.h" + +#define NT uint64_t +#define WT uint128_t +#define NAME usmul +#define DATA TEST_BINARY_DATA_WRAP(NT, NAME) +#define T TEST_BINARY_STRUCT_DECL_WRAP(NT, NAME) +#define RUN_BINARY(x, y) RUN_SAT_U_MUL_FMT_1_WRAP(NT, WT, x, y) + +DEF_SAT_U_MUL_FMT_1_WRAP(NT, WT) + +#include "scalar_sat_binary_run_xxx.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u8-from-u128.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u8-from-u128.c new file mode 100644 index 0000000..1f54c30 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u8-from-u128.c @@ -0,0 +1,16 @@ +/* { dg-do run { target { rv64 } } } */ +/* { dg-additional-options "-std=c99" } */ + +#include "sat_arith.h" +#include "sat_arith_data.h" + +#define NT uint8_t +#define WT uint128_t +#define NAME usmul +#define DATA TEST_BINARY_DATA_WRAP(NT, NAME) +#define T TEST_BINARY_STRUCT_DECL_WRAP(NT, NAME) +#define RUN_BINARY(x, y) RUN_SAT_U_MUL_FMT_1_WRAP(NT, WT, x, y) + +DEF_SAT_U_MUL_FMT_1_WRAP(NT, WT) + +#include "scalar_sat_binary_run_xxx.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-1-u16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-1-u16.c index 1534cf9..20e14d6 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-1-u16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-1-u16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-1-u32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-1-u32.c index 5c60d28..1a0c394 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-1-u32.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-1-u32.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-1-u64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-1-u64.c index 403764c..ee348b3 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-1-u64.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-1-u64.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-1-u8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-1-u8.c index 931420a..216af86 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-1-u8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-1-u8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-10-u16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-10-u16.c index ae87544..109539d 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-10-u16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-10-u16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-10-u32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-10-u32.c index 43414ae..9e35fa2 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-10-u32.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-10-u32.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-10-u64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-10-u64.c index 3ef70a1..3c7c8db 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-10-u64.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-10-u64.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-10-u8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-10-u8.c index 2a157f0..df291e2 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-10-u8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-10-u8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-11-u16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-11-u16.c index 534795c..88dded4 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-11-u16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-11-u16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-11-u32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-11-u32.c index 4d0a34f..239b422 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-11-u32.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-11-u32.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-11-u64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-11-u64.c index d74d10d..9a524fd 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-11-u64.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-11-u64.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-11-u8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-11-u8.c index 949bd0d..b9b84ea 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-11-u8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-11-u8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-12-u16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-12-u16.c index 80cce95..91bd9de 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-12-u16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-12-u16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-12-u32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-12-u32.c index 3ecd19c..eaaa256 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-12-u32.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-12-u32.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-12-u64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-12-u64.c index 2d7bfc4..04d2a20 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-12-u64.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-12-u64.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-12-u8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-12-u8.c index 209965c..caedfe7 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-12-u8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-12-u8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-2-u16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-2-u16.c index 7deaae9a5..06a44f1 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-2-u16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-2-u16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-2-u32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-2-u32.c index d9b1d5c..9d38c9c 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-2-u32.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-2-u32.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-2-u64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-2-u64.c index 2774c23..5c10409 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-2-u64.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-2-u64.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-2-u8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-2-u8.c index 6fa44ca..0ff9827 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-2-u8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-2-u8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-3-u16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-3-u16.c index ea52ff4..aab99ca 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-3-u16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-3-u16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-3-u32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-3-u32.c index fdea891..5231d6f 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-3-u32.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-3-u32.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-3-u64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-3-u64.c index 164ee77..d7462a8 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-3-u64.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-3-u64.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-3-u8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-3-u8.c index 724adf9..5da7838 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-3-u8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-3-u8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-4-u16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-4-u16.c index 9b57861..8e69888 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-4-u16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-4-u16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-4-u32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-4-u32.c index df2eece..9b22dda 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-4-u32.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-4-u32.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-4-u64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-4-u64.c index 09e9ac3..abd0a95 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-4-u64.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-4-u64.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-4-u8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-4-u8.c index c8ae7a6..d92c0e1 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-4-u8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-4-u8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-5-u16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-5-u16.c index 9f575a47..b404bfd 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-5-u16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-5-u16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-5-u32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-5-u32.c index c370455..b746712 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-5-u32.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-5-u32.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-5-u64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-5-u64.c index 22d82f9..da90b7a 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-5-u64.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-5-u64.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-5-u8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-5-u8.c index b282311..38dcabe 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-5-u8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-5-u8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-6-u16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-6-u16.c index e0dda45..fd55bec 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-6-u16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-6-u16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-6-u32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-6-u32.c index dfd95ef..2e810dd 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-6-u32.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-6-u32.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-6-u64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-6-u64.c index 7cac446..e86eebc 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-6-u64.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-6-u64.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-6-u8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-6-u8.c index 0b4cbdb..e749bb5 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-6-u8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-6-u8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-7-u16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-7-u16.c index 10c65fe..eb57d55 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-7-u16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-7-u16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-7-u32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-7-u32.c index e3b4dde..c1a5bcf 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-7-u32.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-7-u32.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-7-u64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-7-u64.c index 6e93fcf..27d4b82 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-7-u64.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-7-u64.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-7-u8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-7-u8.c index d101d28..feb56e1 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-7-u8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-7-u8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-8-u16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-8-u16.c index 4e50e3f..a22f1df 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-8-u16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-8-u16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-8-u32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-8-u32.c index 3c8f78d..b98931d 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-8-u32.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-8-u32.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-8-u64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-8-u64.c index 932596a..dff3c0a 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-8-u64.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-8-u64.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-8-u8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-8-u8.c index 1f74562..d2f3126 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-8-u8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-8-u8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-9-u16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-9-u16.c index 66a82f2..3740099 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-9-u16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-9-u16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-9-u32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-9-u32.c index a54b5c3..b6ae459 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-9-u32.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-9-u32.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-9-u64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-9-u64.c index 97943b3e..55198d6 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-9-u64.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-9-u64.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-9-u8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-9-u8.c index ab8b475..ce73d26 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-9-u8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub-run-9-u8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-1-u16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-1-u16.c index 2bc3be3..a193d88 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-1-u16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-1-u16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-1-u32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-1-u32.c index b1d1ee3..e1dd81c 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-1-u32.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-1-u32.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-1-u64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-1-u64.c index 2539d75..a71526c 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-1-u64.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-1-u64.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-1-u8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-1-u8.c index 5091872..4fedf96 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-1-u8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-1-u8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-2-u16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-2-u16.c index 0f4f9e4..f990c43 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-2-u16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-2-u16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-2-u32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-2-u32.c index ea15d85..44d5e88 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-2-u32.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-2-u32.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-2-u64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-2-u64.c index 612da92..91ea986 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-2-u64.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-2-u64.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-2-u8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-2-u8.c index fc38095..7da49eb 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-2-u8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-2-u8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-3-u16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-3-u16.c index 150ab2a..8c44ee0 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-3-u16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-3-u16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-3-u32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-3-u32.c index c7d2850..f5c4e5a 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-3-u32.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-3-u32.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-3-u64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-3-u64.c index 6bf5cd2..393f7f6 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-3-u64.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-3-u64.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-3-u8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-3-u8.c index dfef1f2..e46463b 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-3-u8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-3-u8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-4-u16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-4-u16.c index 610e021..3062e0f 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-4-u16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-4-u16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-4-u32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-4-u32.c index 1d9e0cb..e621cd2 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-4-u32.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-4-u32.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-4-u64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-4-u64.c index f864a67..cfc96bf 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-4-u64.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-4-u64.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-4-u8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-4-u8.c index 603f2ee..771ec4a 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-4-u8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_sub_imm-run-4-u8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-1-u16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-1-u16.c index a5f43e9..72c175c 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-1-u16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-1-u16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-1-u32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-1-u32.c index a76ae08..aef195a 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-1-u32.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-1-u32.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-1-u64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-1-u64.c index d05ea79..4517418 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-1-u64.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-1-u64.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-1-u8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-1-u8.c index adaa421..2e51023 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-1-u8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-1-u8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-2-u16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-2-u16.c index 38fcba3..8ea83d6 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-2-u16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-2-u16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-2-u32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-2-u32.c index 93705f9..1d0dd5b 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-2-u32.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-2-u32.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-2-u64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-2-u64.c index c116484..f69968c 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-2-u64.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-2-u64.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-2-u8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-2-u8.c index 4fbdc91..dcff0b4 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-2-u8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-2-u8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-3-u16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-3-u16.c index 2281610..33f46ec 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-3-u16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-3-u16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-3-u32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-3-u32.c index 126c97c..b9c4617 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-3-u32.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-3-u32.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-3-u64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-3-u64.c index 61ad79d..21755a7 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-3-u64.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-3-u64.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-3-u8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-3-u8.c index 4142e87..bcf2081 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-3-u8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-3-u8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-4-u16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-4-u16.c index 8952c06..69f5352 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-4-u16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-4-u16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-4-u32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-4-u32.c index 8952c06..69f5352 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-4-u32.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-4-u32.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-4-u64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-4-u64.c index 20ceda6..f001c39 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-4-u64.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-4-u64.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-4-u8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-4-u8.c index 7011e50..1394d9f 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-4-u8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-4-u8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-5-u16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-5-u16.c index e868da1..de5d723 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-5-u16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-5-u16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-5-u32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-5-u32.c index 7f52283fb..c345bfa 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-5-u32.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-5-u32.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-5-u64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-5-u64.c index ee13f0a..8ca8cc7 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-5-u64.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-5-u64.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-5-u8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-5-u8.c index 8471c76..54e00e8 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-5-u8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-5-u8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-6-u16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-6-u16.c index f056bd4..a957cc3 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-6-u16.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-6-u16.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-6-u32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-6-u32.c index 96c06eb..9691b4d 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-6-u32.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-6-u32.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-6-u64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-6-u64.c index 1623e52..ff2c2a5 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-6-u64.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-6-u64.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-6-u8.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-6-u8.c index a1b8a5f..918eabb 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-6-u8.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_trunc-run-6-u8.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { riscv_v } } } */ +/* { dg-do run { target { rv32 || rv64 } } } */ /* { dg-additional-options "-std=c99" } */ #include "sat_arith.h" diff --git a/gcc/testsuite/gcc.target/s390/fminmax-1.c b/gcc/testsuite/gcc.target/s390/fminmax-1.c new file mode 100644 index 0000000..df10905 --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/fminmax-1.c @@ -0,0 +1,77 @@ +/* Check fmin/fmax expanders for scalars on VXE targets. */ + +/* { dg-do compile } */ +/* { dg-options "-O2 -march=z14 -mzarch" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +/* +** dofmaxl: +** vl (%v.),0\(%r3\),3 +** vl (%v.),0\(%r4\),3 +** wfmaxxb (%v.),\1,\2,4 +** vst \3,0\(%r2\),3 +** br %r14 +*/ +long double +dofmaxl (long double d1, long double d2) +{ + return __builtin_fmaxl (d1, d2); +} + +/* +** dofminl: +** vl (%v.),0\(%r3\),3 +** vl (%v.),0\(%r4\),3 +** wfminxb (%v.),\1,\2,4 +** vst \3,0\(%r2\),3 +** br %r14 +*/ +long double +dofminl (long double d1, long double d2) +{ + return __builtin_fminl (d1, d2); +} + +/* +** dofmax: +** wfmaxdb %v0,%v0,%v2,4 +** br %r14 +*/ +double +dofmax (double d1, double d2) +{ + return __builtin_fmax (d1, d2); +} + +/* +** dofmin: +** wfmindb %v0,%v0,%v2,4 +** br %r14 +*/ +double +dofmin (double d1, double d2) +{ + return __builtin_fmin (d1, d2); +} + +/* +** dofmaxf: +** wfmaxsb %v0,%v0,%v2,4 +** br %r14 +*/ +float +dofmaxf (float f1, float f2) +{ + return __builtin_fmaxf (f1, f2); +} + +/* +** dofminf: +** wfminsb %v0,%v0,%v2,4 +** br %r14 +*/ +float +dofminf (float f1, float f2) +{ + return __builtin_fminf (f1, f2); +} diff --git a/gcc/testsuite/gcc.target/s390/fminmax-2.c b/gcc/testsuite/gcc.target/s390/fminmax-2.c new file mode 100644 index 0000000..ea37a0a --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/fminmax-2.c @@ -0,0 +1,29 @@ +/* Check fmin/fmax expanders for scalars on non-VXE targets. */ + +/* { dg-do compile } */ +/* { dg-options "-O2 -march=z13 -mzarch" } */ +/* { dg-final { scan-assembler-times "jg" 4 } } */ + +double +dofmax (double d1, double d2) +{ + return __builtin_fmax (d1, d2); +} + +double +dofmin (double d1, double d2) +{ + return __builtin_fmin (d1, d2); +} + +float +dofmaxf (float f1, float f2) +{ + return __builtin_fmaxf (f1, f2); +} + +float +dofminf (float f1, float f2) +{ + return __builtin_fminf (f1, f2); +} diff --git a/gcc/testsuite/gcc.target/s390/stack-protector-guard-tls-1.c b/gcc/testsuite/gcc.target/s390/stack-protector-guard-tls-1.c new file mode 100644 index 0000000..1efd245 --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/stack-protector-guard-tls-1.c @@ -0,0 +1,39 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fstack-protector-all" } */ +/* { dg-final { scan-assembler-times {\tear\t%r[0-9]+,%a[01]} 8 { target lp64 } } } */ +/* { dg-final { scan-assembler-times {\tsllg\t%r[0-9]+,%r[0-9]+,32} 4 { target lp64 } } } */ +/* { dg-final { scan-assembler-times {\tear\t%r[0-9]+,%a[01]} 3 { target { ! lp64 } } } } */ +/* { dg-final { scan-assembler-times {\tmvc\t160\(8,%r15\),40\(%r[0-9]+\)} 2 { target lp64 } } } */ +/* { dg-final { scan-assembler-times {\tmvc\t100\(4,%r15\),20\(%r[0-9]+\)} 2 { target { ! lp64 } } } } */ +/* { dg-final { scan-assembler-times {\tclc\t160\(8,%r15\),40\(%r[0-9]+\)} 2 { target lp64 } } } */ +/* { dg-final { scan-assembler-times {\tclc\t100\(4,%r15\),20\(%r[0-9]+\)} 2 { target { ! lp64 } } } } */ + +/* Computing the address of the thread pointer on s390 involves multiple + instructions and therefore bears the risk that the address of the canary or + intermediate values of it are spilled and reloaded. Therefore, as a + precaution compute the address always twice, i.e., one time for the prologue + and one time for the epilogue. */ + +void test_0 (void) { } + +void test_1 (void) +{ + __asm__ __volatile ("" ::: + "r0", + "r1", + "r2", + "r3", + "r4", + "r5", + "r6", + "r7", + "r8", + "r9", + "r10", + "r11", +#ifndef __PIC__ + "r12", +#endif + "r13", + "r14"); +} diff --git a/gcc/testsuite/gcc.target/s390/vector/pattern-avg-1.c b/gcc/testsuite/gcc.target/s390/vector/pattern-avg-1.c new file mode 100644 index 0000000..285ebc9 --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/vector/pattern-avg-1.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -mzarch -march=z16 -ftree-vectorize -fdump-tree-optimized" } */ + +#define TEST(T1,T2,N) \ + void \ + avg##T1 (signed T1 *__restrict res, signed T1 *__restrict a, \ + signed T1 *__restrict b) \ + { \ + for (int i = 0; i < N; ++i) \ + res[i] = ((signed T2)a[i] + b[i] + 1) >> 1; \ + } \ + \ + void \ + uavg##T1 (unsigned T1 *__restrict res, unsigned T1 *__restrict a, \ + unsigned T1 *__restrict b) \ + { \ + for (int i = 0; i < N; ++i) \ + res[i] = ((unsigned T2)a[i] + b[i] + 1) >> 1; \ + } + +TEST(char,short,16) +TEST(short,int,8) +TEST(int,long,4) + +/* { dg-final { scan-tree-dump-times "\.AVG_CEIL" 6 "optimized" { target lp64 } } } */ +/* { dg-final { scan-tree-dump-times "\.AVG_CEIL" 4 "optimized" { target { ! lp64 } } } } */ diff --git a/gcc/testsuite/gcc.target/s390/vector/pattern-avg-2.c b/gcc/testsuite/gcc.target/s390/vector/pattern-avg-2.c new file mode 100644 index 0000000..1cc614e --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/vector/pattern-avg-2.c @@ -0,0 +1,23 @@ +/* { dg-do compile { target int128 } } */ +/* { dg-options "-O3 -mzarch -march=z16 -ftree-vectorize -fdump-tree-optimized" } */ + +#define TEST(T1,T2,N) \ + void \ + avg##T1 (signed T1 *__restrict res, signed T1 *__restrict a, \ + signed T1 *__restrict b) \ + { \ + for (int i = 0; i < N; ++i) \ + res[i] = ((signed T2)a[i] + b[i] + 1) >> 1; \ + } \ + \ + void \ + uavg##T1 (unsigned T1 *__restrict res, unsigned T1 *__restrict a, \ + unsigned T1 *__restrict b) \ + { \ + for (int i = 0; i < N; ++i) \ + res[i] = ((unsigned T2)a[i] + b[i] + 1) >> 1; \ + } + +TEST(long,__int128,2) + +/* { dg-final { scan-tree-dump-times "\.AVG_CEIL" 2 "optimized" } } */ diff --git a/gcc/testsuite/gcc.target/s390/vector/pattern-mulh-1.c b/gcc/testsuite/gcc.target/s390/vector/pattern-mulh-1.c new file mode 100644 index 0000000..f0b37d6 --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/vector/pattern-mulh-1.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -mzarch -march=arch15 -ftree-vectorize -fdump-tree-optimized" } */ + +#define TEST(T1,T2,N,S) \ + void \ + mulh##T1 (signed T1 *__restrict res, \ + signed T1 *__restrict l, \ + signed T1 *__restrict r) \ + { \ + for (int i = 0; i < N; ++i) \ + res[i] = (signed T1) (((signed T2)l[i] * (signed T2)r[i]) >> S); \ + } \ + \ + void \ + umulh##T1 (unsigned T1 *__restrict res, \ + unsigned T1 *__restrict l, \ + unsigned T1 *__restrict r) \ + { \ + for (int i = 0; i < N; ++i) \ + res[i] = (unsigned T1) \ + (((unsigned T2)l[i] * (unsigned T2)r[i]) >> S); \ + } + +TEST(char,short,16,8) +TEST(short,int,8,16) + +/* { dg-final { scan-tree-dump-times "\.MULH" 4 "optimized" } } */ diff --git a/gcc/testsuite/gcc.target/s390/vector/pattern-mulh-2.c b/gcc/testsuite/gcc.target/s390/vector/pattern-mulh-2.c new file mode 100644 index 0000000..2ff66b7 --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/vector/pattern-mulh-2.c @@ -0,0 +1,27 @@ +/* { dg-do compile { target int128 } } */ +/* { dg-options "-O3 -mzarch -march=arch15 -ftree-vectorize -fdump-tree-optimized" } */ + +#define TEST(T1,T2,N,S) \ + void \ + mulh##T1 (signed T1 *__restrict res, \ + signed T1 *__restrict l, \ + signed T1 *__restrict r) \ + { \ + for (int i = 0; i < N; ++i) \ + res[i] = (signed T1) (((signed T2)l[i] * (signed T2)r[i]) >> S); \ + } \ + \ + void \ + umulh##T1 (unsigned T1 *__restrict res, \ + unsigned T1 *__restrict l, \ + unsigned T1 *__restrict r) \ + { \ + for (int i = 0; i < N; ++i) \ + res[i] = (unsigned T1) \ + (((unsigned T2)l[i] * (unsigned T2)r[i]) >> S); \ + } + +TEST(int,long,4,32) +TEST(long,__int128,2,64) + +/* { dg-final { scan-tree-dump-times "\.MULH" 4 "optimized" } } */ diff --git a/gcc/testsuite/gcc.target/xtensa/BGEUI-BLTUI-32k-64k.c b/gcc/testsuite/gcc.target/xtensa/BGEUI-BLTUI-32k-64k.c new file mode 100644 index 0000000..05873b8 --- /dev/null +++ b/gcc/testsuite/gcc.target/xtensa/BGEUI-BLTUI-32k-64k.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +extern void foo(void); + +void BGEUI_test(unsigned int a) +{ + if (a < 32768U) + foo(); +} + +void BLTUI_test(unsigned int a) +{ + if (a >= 65536U) + foo(); +} + +/* { dg-final { scan-assembler-times "bgeui" 1 } } */ +/* { dg-final { scan-assembler-times "bltui" 1 } } */ diff --git a/gcc/testsuite/gcc.target/xtensa/pr120888-1.c b/gcc/testsuite/gcc.target/xtensa/pr120888-1.c new file mode 100644 index 0000000..f438e4c --- /dev/null +++ b/gcc/testsuite/gcc.target/xtensa/pr120888-1.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-rtl-expand" } */ + +void u8(unsigned char c); +void cu8(unsigned char *p) +{ + u8(*p); +} + +/* { dg-final { scan-rtl-dump "zero_extend" "expand" } } */ +/* { dg-final { scan-rtl-dump-not "sign_extend" "expand" } } */ diff --git a/gcc/testsuite/gcc.target/xtensa/pr120888-2.c b/gcc/testsuite/gcc.target/xtensa/pr120888-2.c new file mode 100644 index 0000000..9b5caad --- /dev/null +++ b/gcc/testsuite/gcc.target/xtensa/pr120888-2.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-rtl-expand" } */ + +void s8(signed char c); +void cs8(signed char *p) +{ + s8(*p); +} + +/* { dg-final { scan-rtl-dump "sign_extend" "expand" } } */ +/* { dg-final { scan-rtl-dump-not "zero_extend" "expand" } } */ diff --git a/gcc/testsuite/gfortran.dg/asan/array_constructor_1.f90 b/gcc/testsuite/gfortran.dg/asan/array_constructor_1.f90 index 45eafac..a0c5507 100644 --- a/gcc/testsuite/gfortran.dg/asan/array_constructor_1.f90 +++ b/gcc/testsuite/gfortran.dg/asan/array_constructor_1.f90 @@ -9,6 +9,8 @@ program grow_type_array type(container), allocatable :: list(:) + allocate(list(0)) + list = [list, new_elem(5)] deallocate(list) diff --git a/gcc/testsuite/gfortran.dg/asan/finalize_1.f90 b/gcc/testsuite/gfortran.dg/asan/finalize_1.f90 new file mode 100644 index 0000000..ab53a9e --- /dev/null +++ b/gcc/testsuite/gfortran.dg/asan/finalize_1.f90 @@ -0,0 +1,67 @@ +!{ dg-do run } + +! PR fortran/120637 + +! Contributed by Antony Lewis <antony@cosmologist.info> +! The unused module is needed to trigger the issue of not freeing the +! memory of second module. + + module MiscUtils + implicit none + + contains + + logical function isFloat0(R) + class(*), intent(in) :: R + + select type(R) + type is (real) + isFloat0 = .true. + end select + end function isFloat0 + + end module MiscUtils + + module results3 + implicit none + public + + Type ClTransferData2 + real, dimension(:,:,:), allocatable :: Delta_p_l_k + end type ClTransferData2 + + type TCLdata2 + Type(ClTransferData2) :: CTransScal, CTransTens, CTransVec + end type TCLdata2 + + type :: CAMBdata2 + Type(TClData2) :: CLdata2 + end type + + end module results3 + +program driver + use results3 + integer i + do i=1, 2 + call test() + end do + + contains + + subroutine test + implicit none + class(CAMBdata2), pointer :: Data + + allocate(CAMBdata2::Data) + + allocate(Data%ClData2%CTransScal%Delta_p_l_k(3, 1000, 1000)) + allocate(Data%ClData2%CTransVec%Delta_p_l_k(3, 1000, 1000)) + deallocate(Data) + + end subroutine test + + end program driver + +!{ dg-final { cleanup-modules "miscutils results3" } } + diff --git a/gcc/testsuite/gfortran.dg/g77/980310-3.f b/gcc/testsuite/gfortran.dg/g77/980310-3.f index 39bd86c..4bf4d91 100644 --- a/gcc/testsuite/gfortran.dg/g77/980310-3.f +++ b/gcc/testsuite/gfortran.dg/g77/980310-3.f @@ -12,7 +12,7 @@ C Date: Wed, 17 Dec 1997 23:20:29 +0000 C From: Joao Cardoso <jcardoso@inescn.pt> C To: egcs-bugs@cygnus.com C Subject: egcs-1.0 f77 bug on OSR5 -C When trying to compile the Fortran file that I enclose bellow, +C When trying to compile the Fortran file that I enclose below, C I got an assembler error: C C ./g77 -B./ -fpic -O -c scaleg.f diff --git a/gcc/testsuite/gfortran.dg/move_alloc_20.f03 b/gcc/testsuite/gfortran.dg/move_alloc_20.f03 new file mode 100644 index 0000000..20403c3 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/move_alloc_20.f03 @@ -0,0 +1,151 @@ +! { dg-do run } +! +! Check the presence of the pre and post code of the FROM and TO arguments +! of the MOVE_ALLOC intrinsic subroutine. + +module m + implicit none + type :: t + integer, allocatable :: a(:) + end type +end module + +module pre + use m + implicit none + private + public :: check_pre + +contains + + subroutine check_pre + integer, parameter :: n = 5 + type(t) :: x(n) + integer, allocatable :: tmp(:) + integer :: array(4) = [ -1, 0, 1, 2 ] + integer :: i + + if (allocated(tmp)) error stop 1 + + tmp = [17] + + if (.not. allocated(tmp)) error stop 11 + if (any(shape(tmp) /= [1])) error stop 12 + if (any(tmp /= [17])) error stop 13 + do i=1,n + if (allocated(x(i)%a)) error stop 14 + end do + + ! Check that the index of X is properly computed for the evaluation of TO. + call move_alloc(tmp, x(sum(array))%a) + + do i=1,n + if (i == 2) cycle + if (allocated(x(i)%a)) error stop 21 + end do + if (.not. allocated(x(2)%a)) error stop 22 + if (any(shape(x(2)%a) /= [1])) error stop 23 + if (any(x(2)%a /= [17])) error stop 24 + if (allocated(tmp)) error stop 25 + + ! Check that the index of X is properly computed for the evaluation of FROM. + call move_alloc(x(sum(array))%a, tmp) + + if (.not. allocated(tmp)) error stop 31 + if (any(shape(tmp) /= [1])) error stop 32 + if (any(tmp /= [17])) error stop 33 + do i=1,n + if (allocated(x(i)%a)) error stop 34 + end do + end subroutine + +end module + +module post + use m + implicit none + private + public :: check_post + integer, parameter :: n = 5 + type(t), target :: x(n) + type :: u + integer :: a + contains + final :: finalize + end type + integer :: finalization_count = 0 + +contains + + function idx(arg) + type(u) :: arg + integer :: idx + idx = mod(arg%a, n) + end function + + subroutine check_post + type(u) :: y + integer, allocatable :: tmp(:) + integer, target :: array(4) = [ -1, 0, 1, 2 ] + integer :: i + + y%a = 12 + + if (allocated(tmp)) error stop 1 + + tmp = [37] + + if (.not. allocated(tmp)) error stop 11 + if (any(shape(tmp) /= [1])) error stop 12 + if (any(tmp /= [37])) error stop 13 + if (finalization_count /= 0) error stop 14 + do i=1,n + if (allocated(x(i)%a)) error stop 15 + end do + + ! Check that the cleanup code for the evaluation of TO is properly + ! executed after MOVE_ALLOC: the result of GET_U should be finalized. + call move_alloc(tmp, x(idx(get_u(y)))%a) + + do i=1,n + if (i == 2) cycle + if (allocated(x(i)%a)) error stop 21 + end do + if (.not. allocated(x(2)%a)) error stop 22 + if (any(shape(x(2)%a) /= [1])) error stop 23 + if (any(x(2)%a /= [37])) error stop 24 + if (allocated(tmp)) error stop 25 + if (finalization_count /= 1) error stop 26 + + ! Check that the cleanup code for the evaluation of FROM is properly + ! executed after MOVE_ALLOC: the result of GET_U should be finalized. + call move_alloc(x(idx(get_u(y)))%a, tmp) + + if (.not. allocated(tmp)) error stop 31 + if (any(shape(tmp) /= [1])) error stop 32 + if (any(tmp /= [37])) error stop 33 + if (finalization_count /= 2) error stop 34 + do i=1,n + if (allocated(x(i)%a)) error stop 35 + end do + end subroutine + + function get_u(arg) + type(u) :: arg, get_u + get_u = arg + end function get_u + + subroutine finalize(obj) + type(u) :: obj + finalization_count = finalization_count + 1 + end subroutine + +end module + +program p + use pre + use post + implicit none + call check_pre + call check_post +end program diff --git a/gcc/testsuite/jit.dg/test-debuginfo.c b/gcc/testsuite/jit.dg/test-debuginfo.c index 49e8834..e0d6f2d 100644 --- a/gcc/testsuite/jit.dg/test-debuginfo.c +++ b/gcc/testsuite/jit.dg/test-debuginfo.c @@ -1,5 +1,5 @@ /* Essentially this test checks that debug info are generated for globals - locals and functions, including type info. The comment bellow is used + locals and functions, including type info. The comment below is used as fake code (does not affect the test, use for manual debugging). */ /* int a_global_for_test_debuginfo; diff --git a/gcc/testsuite/lib/scanasm.exp b/gcc/testsuite/lib/scanasm.exp index 97935cb..a2311de 100644 --- a/gcc/testsuite/lib/scanasm.exp +++ b/gcc/testsuite/lib/scanasm.exp @@ -1109,6 +1109,8 @@ proc check-function-bodies { args } { append function_regexp ".*" } elseif { [regexp {^\.L} $line] } { append function_regexp $line "\n" + } elseif { [regexp {^[0-9]+:} $line] } { + append function_regexp $line "\n" } else { append function_regexp $config(line_prefix) $line "\n" } diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index 956bc0b..9ab46a0 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -6491,6 +6491,23 @@ proc check_effective_target_aarch64_sve2_hw { } { }] } +# Return true if this is an AArch64 target that can run SVE2.1 code. + +proc check_effective_target_aarch64_sve2p1_hw { } { + if { ![istarget aarch64*-*-*] } { + return 0 + } + return [check_runtime aarch64_sve2p1_hw_available { + #pragma GCC target "+sve2p1" + int + main (void) + { + asm volatile ("dupq z0.b, z0.b[0]"); + return 0; + } + }] +} + # Return true if this is an AArch64 target that can run SVE code and # if its SVE vectors have exactly BITS bits. diff --git a/gcc/tree-inline.cc b/gcc/tree-inline.cc index 7e0ac69..e8fe035 100644 --- a/gcc/tree-inline.cc +++ b/gcc/tree-inline.cc @@ -2888,11 +2888,9 @@ initialize_cfun (tree new_fndecl, tree callee_fndecl, profile_count count) profile_count::adjust_for_ipa_scaling (&num, &den); ENTRY_BLOCK_PTR_FOR_FN (cfun)->count = - ENTRY_BLOCK_PTR_FOR_FN (src_cfun)->count.apply_scale (count, - ENTRY_BLOCK_PTR_FOR_FN (src_cfun)->count); + ENTRY_BLOCK_PTR_FOR_FN (src_cfun)->count.apply_scale (num, den); EXIT_BLOCK_PTR_FOR_FN (cfun)->count = - EXIT_BLOCK_PTR_FOR_FN (src_cfun)->count.apply_scale (count, - ENTRY_BLOCK_PTR_FOR_FN (src_cfun)->count); + EXIT_BLOCK_PTR_FOR_FN (src_cfun)->count.apply_scale (num, den); if (src_cfun->eh) init_eh_for_function (); diff --git a/gcc/tree-object-size.cc b/gcc/tree-object-size.cc index a551f2b..8545eff 100644 --- a/gcc/tree-object-size.cc +++ b/gcc/tree-object-size.cc @@ -851,21 +851,17 @@ addr_object_size (struct object_size_info *osi, const_tree ptr, /* Compute __builtin_object_size for a CALL to .ACCESS_WITH_SIZE, OBJECT_SIZE_TYPE is the second argument from __builtin_object_size. - The 2nd, 3rd, and the 4th parameters of the call determine the size of + + The 2nd, 3rd, and 4th parameters of the call determine the size of the CALL: 2nd argument REF_TO_SIZE: The reference to the size of the object, - 3rd argument CLASS_OF_SIZE: The size referenced by the REF_TO_SIZE represents - 0: the number of bytes; - 1: the number of the elements of the object type; - 4th argument TYPE_OF_SIZE: A constant 0 with its TYPE being the same as the TYPE - of the object referenced by REF_TO_SIZE - 6th argument: A constant 0 with the pointer TYPE to the original flexible - array type or pointer field type. - - The size of the element can be retrived from the TYPE of the 6th argument - of the call, which is the pointer to the original flexible array type or - the type of the original pointer field. */ + 3rd argument TYPE_OF_SIZE + ACCESS_MODE: An integer constant with a pointer + TYPE. + The pointee TYPE of this pointer TYPE is the TYPE of the object referenced + by REF_TO_SIZE. + + 4th argument: The TYPE_SIZE_UNIT of the element TYPE of the array. */ static tree access_with_size_object_size (const gcall *call, int object_size_type) @@ -873,17 +869,14 @@ access_with_size_object_size (const gcall *call, int object_size_type) /* If not for dynamic object size, return. */ if ((object_size_type & OST_DYNAMIC) == 0) return size_unknown (object_size_type); - gcc_assert (gimple_call_internal_p (call, IFN_ACCESS_WITH_SIZE)); - /* The type of the 6th argument type is the pointer TYPE to the original - flexible array type or to the original pointer type. */ - tree pointer_to_array_type = TREE_TYPE (gimple_call_arg (call, 5)); - gcc_assert (POINTER_TYPE_P (pointer_to_array_type)); - tree element_type = TREE_TYPE (TREE_TYPE (pointer_to_array_type)); - tree element_size = TYPE_SIZE_UNIT (element_type); + tree ref_to_size = gimple_call_arg (call, 1); - unsigned int class_of_size = TREE_INT_CST_LOW (gimple_call_arg (call, 2)); - tree type = TREE_TYPE (gimple_call_arg (call, 3)); + tree type = TREE_TYPE (TREE_TYPE (gimple_call_arg (call, 2))); + + /* The 4th argument is the TYPE_SIZE_UNIT for the element of the original + flexible array. */ + tree element_size = gimple_call_arg (call, 3); tree size = fold_build2 (MEM_REF, type, ref_to_size, build_int_cst (ptr_type_node, 0)); @@ -897,12 +890,9 @@ access_with_size_object_size (const gcall *call, int object_size_type) build_zero_cst (type), size); } - if (class_of_size == 1) - size = size_binop (MULT_EXPR, - fold_convert (sizetype, size), - fold_convert (sizetype, element_size)); - else - size = fold_convert (sizetype, size); + size = size_binop (MULT_EXPR, + fold_convert (sizetype, size), + fold_convert (sizetype, element_size)); if (!todo) todo = TODO_update_ssa_only_virtuals; @@ -1944,17 +1934,6 @@ collect_object_sizes_for (struct object_size_info *osi, tree var) if (TREE_CODE (rhs) == SSA_NAME && POINTER_TYPE_P (TREE_TYPE (rhs))) reexamine = merge_object_sizes (osi, var, rhs); - /* Handle the following stmt #2 to propagate the size from the - stmt #1 to #3: - 1 _1 = .ACCESS_WITH_SIZE (_3, _4, 1, 0, -1, 0B); - 2 _5 = *_1; - 3 _6 = __builtin_dynamic_object_size (_5, 1); - */ - else if (TREE_CODE (rhs) == MEM_REF - && POINTER_TYPE_P (TREE_TYPE (rhs)) - && TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME - && integer_zerop (TREE_OPERAND (rhs, 1))) - reexamine = merge_object_sizes (osi, var, TREE_OPERAND (rhs, 0)); else expr_object_size (osi, var, rhs); } diff --git a/gcc/tree-scalar-evolution.cc b/gcc/tree-scalar-evolution.cc index 43311e5..413ca49 100644 --- a/gcc/tree-scalar-evolution.cc +++ b/gcc/tree-scalar-evolution.cc @@ -3088,7 +3088,7 @@ iv_can_overflow_p (class loop *loop, tree type, tree base, tree step) type_max = wi::max_value (type); /* Just sanity check that we don't see values out of the range of the type. - In this case the arithmetics bellow would overflow. */ + In this case the arithmetics below would overflow. */ gcc_checking_assert (wi::ge_p (base_min, type_min, sgn) && wi::le_p (base_max, type_max, sgn)); diff --git a/gcc/tree-ssa-alias.cc b/gcc/tree-ssa-alias.cc index 9dd1780..4119343 100644 --- a/gcc/tree-ssa-alias.cc +++ b/gcc/tree-ssa-alias.cc @@ -4376,7 +4376,7 @@ ao_compare::compare_ao_refs (ao_ref *ref1, ao_ref *ref2, i++; } - /* For variable accesses we can not rely on offset match bellow. + /* For variable accesses we can not rely on offset match below. We know that paths are struturally same, so only check that starts of TBAA paths did not diverge. */ if (!known_eq (ref1->size, ref1->max_size) diff --git a/gcc/tree-ssa-dse.cc b/gcc/tree-ssa-dse.cc index 5ac4280..51a5723 100644 --- a/gcc/tree-ssa-dse.cc +++ b/gcc/tree-ssa-dse.cc @@ -181,10 +181,10 @@ initialize_ao_ref_for_dse (gimple *stmt, ao_ref *write, bool may_def_ok = false) can provide a may-def variant. */ if (may_def_ok) { - ao_ref_init_from_ptr_and_size ( - write, gimple_call_arg (stmt, 0), - TYPE_SIZE_UNIT ( - TREE_TYPE (gimple_call_arg (stmt, stored_value_index)))); + ao_ref_init_from_ptr_and_range ( + write, gimple_call_arg (stmt, 0), true, 0, -1, + tree_to_poly_int64 (TYPE_SIZE ( + TREE_TYPE (gimple_call_arg (stmt, stored_value_index))))); return true; } break; diff --git a/gcc/tree-ssa-live.cc b/gcc/tree-ssa-live.cc index 5b8bfd0..5e08913 100644 --- a/gcc/tree-ssa-live.cc +++ b/gcc/tree-ssa-live.cc @@ -702,7 +702,10 @@ dump_scope_block (FILE *file, int indent, tree scope, dump_flags_t flags) if (LOCATION_LOCUS (BLOCK_SOURCE_LOCATION (scope)) != UNKNOWN_LOCATION) { expanded_location s = expand_location (BLOCK_SOURCE_LOCATION (scope)); - fprintf (file, " %s:%i", s.file, s.line); + fprintf (file, " %s:%i:%i", s.file, s.line, s.column); + if (has_discriminator (BLOCK_SOURCE_LOCATION (scope))) + fprintf (file, " discrim %i", + get_discriminator_from_loc (BLOCK_SOURCE_LOCATION (scope))); } if (BLOCK_ABSTRACT_ORIGIN (scope)) { diff --git a/gcc/tree-ssa-loop-niter.cc b/gcc/tree-ssa-loop-niter.cc index 9ce8813..6e13086 100644 --- a/gcc/tree-ssa-loop-niter.cc +++ b/gcc/tree-ssa-loop-niter.cc @@ -4701,7 +4701,7 @@ maybe_lower_iteration_bound (class loop *loop) TODO: Due to the way record_estimate choose estimates to store, the bounds will be always nb_iterations_upper_bound-1. We can change this to record - also statements not dominating the loop latch and update the walk bellow + also statements not dominating the loop latch and update the walk below to the shortest path algorithm. */ for (elt = loop->bounds; elt; elt = elt->next) { diff --git a/gcc/tree-ssa-math-opts.cc b/gcc/tree-ssa-math-opts.cc index 4cfcc42..ca98205 100644 --- a/gcc/tree-ssa-math-opts.cc +++ b/gcc/tree-ssa-math-opts.cc @@ -4064,6 +4064,7 @@ arith_overflow_check_p (gimple *stmt, gimple *cast_stmt, gimple *&use_stmt, extern bool gimple_unsigned_integer_sat_add (tree, tree*, tree (*)(tree)); extern bool gimple_unsigned_integer_sat_sub (tree, tree*, tree (*)(tree)); extern bool gimple_unsigned_integer_sat_trunc (tree, tree*, tree (*)(tree)); +extern bool gimple_unsigned_integer_sat_mul (tree, tree*, tree (*)(tree)); extern bool gimple_signed_integer_sat_add (tree, tree*, tree (*)(tree)); extern bool gimple_signed_integer_sat_sub (tree, tree*, tree (*)(tree)); @@ -4217,6 +4218,30 @@ match_unsigned_saturation_sub (gimple_stmt_iterator *gsi, gassign *stmt) } /* + * Try to match saturation unsigned mul. + * _1 = (unsigned int) a_6(D); + * _2 = (unsigned int) b_7(D); + * x_8 = _1 * _2; + * overflow_9 = x_8 > 255; + * _3 = (unsigned char) overflow_9; + * _4 = -_3; + * _5 = (unsigned char) x_8; + * _10 = _4 | _5; + * => + * _10 = .SAT_SUB (a_6, b_7); */ + +static void +match_unsigned_saturation_mul (gimple_stmt_iterator *gsi, gassign *stmt) +{ + tree ops[2]; + tree lhs = gimple_assign_lhs (stmt); + + if (gimple_unsigned_integer_sat_mul (lhs, ops, NULL)) + build_saturation_binary_arith_call_and_replace (gsi, IFN_SAT_MUL, lhs, + ops[0], ops[1]); +} + +/* * Try to match saturation unsigned sub. * <bb 2> [local count: 1073741824]: * if (x_2(D) > y_3(D)) @@ -6469,6 +6494,7 @@ math_opts_dom_walker::after_dom_children (basic_block bb) break; case NOP_EXPR: + match_unsigned_saturation_mul (&gsi, as_a<gassign *> (stmt)); match_unsigned_saturation_trunc (&gsi, as_a<gassign *> (stmt)); match_saturation_add_with_assign (&gsi, as_a<gassign *> (stmt)); break; diff --git a/gcc/tree-ssa-structalias.cc b/gcc/tree-ssa-structalias.cc index deca44a..0215243 100644 --- a/gcc/tree-ssa-structalias.cc +++ b/gcc/tree-ssa-structalias.cc @@ -3690,7 +3690,10 @@ get_constraint_for_1 (tree t, vec<ce_s> *results, bool address_p, size = -1; for (; curr; curr = vi_next (curr)) { - if (curr->offset - vi->offset < size) + /* The start of the access might happen anywhere + within vi, so conservatively assume it was + at its end. */ + if (curr->offset - (vi->offset + vi->size - 1) < size) { cs.var = curr->id; results->safe_push (cs); diff --git a/gcc/tree-vect-loop-manip.cc b/gcc/tree-vect-loop-manip.cc index 4696943..2d01a4b 100644 --- a/gcc/tree-vect-loop-manip.cc +++ b/gcc/tree-vect-loop-manip.cc @@ -2859,7 +2859,19 @@ vect_gen_vector_loop_niters (loop_vec_info loop_vinfo, tree niters, we have to represent the vector niter TYPE_MAX_VALUE + 1 / vf. */ if (stmts != NULL && const_vf > 0) { - if (niters_no_overflow) + if (niters_no_overflow + && LOOP_VINFO_USING_PARTIAL_VECTORS_P (loop_vinfo)) + { + int_range<1> vr (type, + wi::one (TYPE_PRECISION (type)), + wi::div_ceil (wi::max_value + (TYPE_PRECISION (type), + TYPE_SIGN (type)), + const_vf, + TYPE_SIGN (type))); + set_range_info (niters_vector, vr); + } + else if (niters_no_overflow) { int_range<1> vr (type, wi::one (TYPE_PRECISION (type)), diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc index 2782d61..56f80db 100644 --- a/gcc/tree-vect-loop.cc +++ b/gcc/tree-vect-loop.cc @@ -58,6 +58,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-eh.h" #include "case-cfn-macros.h" #include "langhooks.h" +#include "opts.h" /* Loop Vectorization Pass. @@ -167,9 +168,8 @@ static stmt_vec_info vect_is_simple_reduction (loop_vec_info, stmt_vec_info, may already be set for general statements (not just data refs). */ static opt_result -vect_determine_vf_for_stmt_1 (vec_info *vinfo, stmt_vec_info stmt_info, - bool vectype_maybe_set_p, - poly_uint64 *vf) +vect_determine_vectype_for_stmt_1 (vec_info *vinfo, stmt_vec_info stmt_info, + bool vectype_maybe_set_p) { gimple *stmt = stmt_info->stmt; @@ -191,6 +191,12 @@ vect_determine_vf_for_stmt_1 (vec_info *vinfo, stmt_vec_info stmt_info, if (stmt_vectype) { + if (known_le (TYPE_VECTOR_SUBPARTS (stmt_vectype), 1U)) + return opt_result::failure_at (STMT_VINFO_STMT (stmt_info), + "not vectorized: unsupported " + "data-type in %G", + STMT_VINFO_STMT (stmt_info)); + if (STMT_VINFO_VECTYPE (stmt_info)) /* The only case when a vectype had been already set is for stmts that contain a data ref, or for "pattern-stmts" (stmts generated @@ -202,9 +208,6 @@ vect_determine_vf_for_stmt_1 (vec_info *vinfo, stmt_vec_info stmt_info, STMT_VINFO_VECTYPE (stmt_info) = stmt_vectype; } - if (nunits_vectype) - vect_update_max_nunits (vf, nunits_vectype); - return opt_result::success (); } @@ -214,13 +217,12 @@ vect_determine_vf_for_stmt_1 (vec_info *vinfo, stmt_vec_info stmt_info, or false if something prevented vectorization. */ static opt_result -vect_determine_vf_for_stmt (vec_info *vinfo, - stmt_vec_info stmt_info, poly_uint64 *vf) +vect_determine_vectype_for_stmt (vec_info *vinfo, stmt_vec_info stmt_info) { if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, "==> examining statement: %G", stmt_info->stmt); - opt_result res = vect_determine_vf_for_stmt_1 (vinfo, stmt_info, false, vf); + opt_result res = vect_determine_vectype_for_stmt_1 (vinfo, stmt_info, false); if (!res) return res; @@ -239,7 +241,7 @@ vect_determine_vf_for_stmt (vec_info *vinfo, dump_printf_loc (MSG_NOTE, vect_location, "==> examining pattern def stmt: %G", def_stmt_info->stmt); - res = vect_determine_vf_for_stmt_1 (vinfo, def_stmt_info, true, vf); + res = vect_determine_vectype_for_stmt_1 (vinfo, def_stmt_info, true); if (!res) return res; } @@ -248,7 +250,7 @@ vect_determine_vf_for_stmt (vec_info *vinfo, dump_printf_loc (MSG_NOTE, vect_location, "==> examining pattern statement: %G", stmt_info->stmt); - res = vect_determine_vf_for_stmt_1 (vinfo, stmt_info, true, vf); + res = vect_determine_vectype_for_stmt_1 (vinfo, stmt_info, true); if (!res) return res; } @@ -256,45 +258,23 @@ vect_determine_vf_for_stmt (vec_info *vinfo, return opt_result::success (); } -/* Function vect_determine_vectorization_factor - - Determine the vectorization factor (VF). VF is the number of data elements - that are operated upon in parallel in a single iteration of the vectorized - loop. For example, when vectorizing a loop that operates on 4byte elements, - on a target with vector size (VS) 16byte, the VF is set to 4, since 4 - elements can fit in a single vector register. - - We currently support vectorization of loops in which all types operated upon - are of the same size. Therefore this function currently sets VF according to - the size of the types operated upon, and fails if there are multiple sizes - in the loop. - - VF is also the factor by which the loop iterations are strip-mined, e.g.: - original loop: - for (i=0; i<N; i++){ - a[i] = b[i] + c[i]; - } +/* Function vect_set_stmts_vectype - vectorized loop: - for (i=0; i<N; i+=VF){ - a[i:VF] = b[i:VF] + c[i:VF]; - } -*/ + Set STMT_VINFO_VECTYPE of all stmts. */ static opt_result -vect_determine_vectorization_factor (loop_vec_info loop_vinfo) +vect_set_stmts_vectype (loop_vec_info loop_vinfo) { class loop *loop = LOOP_VINFO_LOOP (loop_vinfo); basic_block *bbs = LOOP_VINFO_BBS (loop_vinfo); unsigned nbbs = loop->num_nodes; - poly_uint64 vectorization_factor = 1; tree scalar_type = NULL_TREE; gphi *phi; tree vectype; stmt_vec_info stmt_info; unsigned i; - DUMP_VECT_SCOPE ("vect_determine_vectorization_factor"); + DUMP_VECT_SCOPE ("vect_set_stmts_vectype"); for (i = 0; i < nbbs; i++) { @@ -323,7 +303,8 @@ vect_determine_vectorization_factor (loop_vec_info loop_vinfo) scalar_type); vectype = get_vectype_for_scalar_type (loop_vinfo, scalar_type); - if (!vectype) + if (!vectype + || known_le (TYPE_VECTOR_SUBPARTS (vectype), 1U)) return opt_result::failure_at (phi, "not vectorized: unsupported " "data-type %T\n", @@ -333,15 +314,6 @@ vect_determine_vectorization_factor (loop_vec_info loop_vinfo) if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, "vectype: %T\n", vectype); - - if (dump_enabled_p ()) - { - dump_printf_loc (MSG_NOTE, vect_location, "nunits = "); - dump_dec (MSG_NOTE, TYPE_VECTOR_SUBPARTS (vectype)); - dump_printf (MSG_NOTE, "\n"); - } - - vect_update_max_nunits (&vectorization_factor, vectype); } } @@ -352,25 +324,12 @@ vect_determine_vectorization_factor (loop_vec_info loop_vinfo) continue; stmt_info = loop_vinfo->lookup_stmt (gsi_stmt (si)); opt_result res - = vect_determine_vf_for_stmt (loop_vinfo, - stmt_info, &vectorization_factor); + = vect_determine_vectype_for_stmt (loop_vinfo, stmt_info); if (!res) return res; } } - /* TODO: Analyze cost. Decide if worth while to vectorize. */ - if (dump_enabled_p ()) - { - dump_printf_loc (MSG_NOTE, vect_location, "vectorization factor = "); - dump_dec (MSG_NOTE, vectorization_factor); - dump_printf (MSG_NOTE, "\n"); - } - - if (known_le (vectorization_factor, 1U)) - return opt_result::failure_at (vect_location, - "not vectorized: unsupported data-type\n"); - LOOP_VINFO_VECT_FACTOR (loop_vinfo) = vectorization_factor; return opt_result::success (); } @@ -2001,234 +1960,6 @@ vect_create_loop_vinfo (class loop *loop, vec_info_shared *shared, -/* Scan the loop stmts and dependent on whether there are any (non-)SLP - statements update the vectorization factor. */ - -static void -vect_update_vf_for_slp (loop_vec_info loop_vinfo) -{ - class loop *loop = LOOP_VINFO_LOOP (loop_vinfo); - basic_block *bbs = LOOP_VINFO_BBS (loop_vinfo); - int nbbs = loop->num_nodes; - poly_uint64 vectorization_factor; - int i; - - DUMP_VECT_SCOPE ("vect_update_vf_for_slp"); - - vectorization_factor = LOOP_VINFO_VECT_FACTOR (loop_vinfo); - gcc_assert (known_ne (vectorization_factor, 0U)); - - /* If all the stmts in the loop can be SLPed, we perform only SLP, and - vectorization factor of the loop is the unrolling factor required by - the SLP instances. If that unrolling factor is 1, we say, that we - perform pure SLP on loop - cross iteration parallelism is not - exploited. */ - bool only_slp_in_loop = true; - for (i = 0; i < nbbs; i++) - { - basic_block bb = bbs[i]; - for (gphi_iterator si = gsi_start_phis (bb); !gsi_end_p (si); - gsi_next (&si)) - { - stmt_vec_info stmt_info = loop_vinfo->lookup_stmt (si.phi ()); - if (!stmt_info) - continue; - if ((STMT_VINFO_RELEVANT_P (stmt_info) - || VECTORIZABLE_CYCLE_DEF (STMT_VINFO_DEF_TYPE (stmt_info))) - && !PURE_SLP_STMT (stmt_info)) - /* STMT needs both SLP and loop-based vectorization. */ - only_slp_in_loop = false; - } - for (gimple_stmt_iterator si = gsi_start_bb (bb); !gsi_end_p (si); - gsi_next (&si)) - { - if (is_gimple_debug (gsi_stmt (si))) - continue; - stmt_vec_info stmt_info = loop_vinfo->lookup_stmt (gsi_stmt (si)); - stmt_info = vect_stmt_to_vectorize (stmt_info); - if ((STMT_VINFO_RELEVANT_P (stmt_info) - || VECTORIZABLE_CYCLE_DEF (STMT_VINFO_DEF_TYPE (stmt_info))) - && !PURE_SLP_STMT (stmt_info)) - /* STMT needs both SLP and loop-based vectorization. */ - only_slp_in_loop = false; - } - } - - if (only_slp_in_loop) - { - if (dump_enabled_p ()) - dump_printf_loc (MSG_NOTE, vect_location, - "Loop contains only SLP stmts\n"); - vectorization_factor = LOOP_VINFO_SLP_UNROLLING_FACTOR (loop_vinfo); - } - else - { - if (dump_enabled_p ()) - dump_printf_loc (MSG_NOTE, vect_location, - "Loop contains SLP and non-SLP stmts\n"); - /* Both the vectorization factor and unroll factor have the form - GET_MODE_SIZE (loop_vinfo->vector_mode) * X for some rational X, - so they must have a common multiple. */ - vectorization_factor - = force_common_multiple (vectorization_factor, - LOOP_VINFO_SLP_UNROLLING_FACTOR (loop_vinfo)); - } - - LOOP_VINFO_VECT_FACTOR (loop_vinfo) = vectorization_factor; - if (dump_enabled_p ()) - { - dump_printf_loc (MSG_NOTE, vect_location, - "Updating vectorization factor to "); - dump_dec (MSG_NOTE, vectorization_factor); - dump_printf (MSG_NOTE, ".\n"); - } -} - -/* Return true if STMT_INFO describes a double reduction phi and if - the other phi in the reduction is also relevant for vectorization. - This rejects cases such as: - - outer1: - x_1 = PHI <x_3(outer2), ...>; - ... - - inner: - x_2 = ...; - ... - - outer2: - x_3 = PHI <x_2(inner)>; - - if nothing in x_2 or elsewhere makes x_1 relevant. */ - -static bool -vect_active_double_reduction_p (stmt_vec_info stmt_info) -{ - if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_double_reduction_def) - return false; - - return STMT_VINFO_RELEVANT_P (STMT_VINFO_REDUC_DEF (stmt_info)); -} - -/* Function vect_analyze_loop_operations. - - Scan the loop stmts and make sure they are all vectorizable. */ - -static opt_result -vect_analyze_loop_operations (loop_vec_info loop_vinfo) -{ - class loop *loop = LOOP_VINFO_LOOP (loop_vinfo); - basic_block *bbs = LOOP_VINFO_BBS (loop_vinfo); - int nbbs = loop->num_nodes; - int i; - stmt_vec_info stmt_info; - - DUMP_VECT_SCOPE ("vect_analyze_loop_operations"); - - for (i = 0; i < nbbs; i++) - { - basic_block bb = bbs[i]; - - for (gphi_iterator si = gsi_start_phis (bb); !gsi_end_p (si); - gsi_next (&si)) - { - gphi *phi = si.phi (); - - stmt_info = loop_vinfo->lookup_stmt (phi); - if (dump_enabled_p ()) - dump_printf_loc (MSG_NOTE, vect_location, "examining phi: %G", - (gimple *) phi); - if (virtual_operand_p (gimple_phi_result (phi))) - continue; - - /* ??? All of the below unconditional FAILs should be in - done earlier after analyzing cycles, possibly when - determining stmt relevancy? */ - - /* Inner-loop loop-closed exit phi in outer-loop vectorization - (i.e., a phi in the tail of the outer-loop). */ - if (! is_loop_header_bb_p (bb)) - { - /* FORNOW: we currently don't support the case that these phis - are not used in the outerloop (unless it is double reduction, - i.e., this phi is vect_reduction_def), cause this case - requires to actually do something here. */ - if (STMT_VINFO_LIVE_P (stmt_info) - && !vect_active_double_reduction_p (stmt_info)) - return opt_result::failure_at (phi, - "Unsupported loop-closed phi" - " in outer-loop.\n"); - - /* If PHI is used in the outer loop, we check that its operand - is defined in the inner loop. */ - if (STMT_VINFO_RELEVANT_P (stmt_info)) - { - tree phi_op; - - if (gimple_phi_num_args (phi) != 1) - return opt_result::failure_at (phi, "unsupported phi"); - - phi_op = PHI_ARG_DEF (phi, 0); - stmt_vec_info op_def_info = loop_vinfo->lookup_def (phi_op); - if (!op_def_info) - return opt_result::failure_at (phi, "unsupported phi\n"); - - if (STMT_VINFO_RELEVANT (op_def_info) != vect_used_in_outer - && (STMT_VINFO_RELEVANT (op_def_info) - != vect_used_in_outer_by_reduction)) - return opt_result::failure_at (phi, "unsupported phi\n"); - - if ((STMT_VINFO_DEF_TYPE (stmt_info) == vect_internal_def - || (STMT_VINFO_DEF_TYPE (stmt_info) - == vect_double_reduction_def)) - && ! PURE_SLP_STMT (stmt_info)) - return opt_result::failure_at (phi, "unsupported phi\n"); - } - - continue; - } - - gcc_assert (stmt_info); - - if ((STMT_VINFO_RELEVANT (stmt_info) == vect_used_in_scope - || STMT_VINFO_LIVE_P (stmt_info)) - && STMT_VINFO_DEF_TYPE (stmt_info) != vect_induction_def - && STMT_VINFO_DEF_TYPE (stmt_info) != vect_first_order_recurrence) - /* A scalar-dependence cycle that we don't support. */ - return opt_result::failure_at (phi, - "not vectorized:" - " scalar dependence cycle.\n"); - - if (STMT_VINFO_RELEVANT_P (stmt_info) - && ! PURE_SLP_STMT (stmt_info)) - return opt_result::failure_at (phi, - "not vectorized: relevant phi not " - "supported: %G", - static_cast <gimple *> (phi)); - } - - for (gimple_stmt_iterator si = gsi_start_bb (bb); !gsi_end_p (si); - gsi_next (&si)) - { - gimple *stmt = gsi_stmt (si); - if (!gimple_clobber_p (stmt) - && !is_gimple_debug (stmt)) - { - bool need_to_vectorize = false; - opt_result res - = vect_analyze_stmt (loop_vinfo, - loop_vinfo->lookup_stmt (stmt), - &need_to_vectorize, - NULL, NULL, NULL); - if (!res) - return res; - } - } - } /* bbs */ - - return opt_result::success (); -} - /* Return true if we know that the iteration count is smaller than the vectorization factor. Return false if it isn't, or if we can't be sure either way. */ @@ -2529,78 +2260,6 @@ vect_get_datarefs_in_loop (loop_p loop, basic_block *bbs, return opt_result::success (); } -/* Look for SLP-only access groups and turn each individual access into its own - group. */ -static void -vect_dissolve_slp_only_groups (loop_vec_info loop_vinfo) -{ - unsigned int i; - struct data_reference *dr; - - DUMP_VECT_SCOPE ("vect_dissolve_slp_only_groups"); - - vec<data_reference_p> datarefs = LOOP_VINFO_DATAREFS (loop_vinfo); - FOR_EACH_VEC_ELT (datarefs, i, dr) - { - gcc_assert (DR_REF (dr)); - stmt_vec_info stmt_info - = vect_stmt_to_vectorize (loop_vinfo->lookup_stmt (DR_STMT (dr))); - - /* Check if the load is a part of an interleaving chain. */ - if (STMT_VINFO_GROUPED_ACCESS (stmt_info)) - { - stmt_vec_info first_element = DR_GROUP_FIRST_ELEMENT (stmt_info); - dr_vec_info *dr_info = STMT_VINFO_DR_INFO (first_element); - unsigned int group_size = DR_GROUP_SIZE (first_element); - - /* Check if SLP-only groups. */ - if (!STMT_SLP_TYPE (stmt_info) - && STMT_VINFO_SLP_VECT_ONLY (first_element)) - { - /* Dissolve the group. */ - STMT_VINFO_SLP_VECT_ONLY (first_element) = false; - - stmt_vec_info vinfo = first_element; - while (vinfo) - { - stmt_vec_info next = DR_GROUP_NEXT_ELEMENT (vinfo); - DR_GROUP_FIRST_ELEMENT (vinfo) = vinfo; - DR_GROUP_NEXT_ELEMENT (vinfo) = NULL; - DR_GROUP_SIZE (vinfo) = 1; - if (STMT_VINFO_STRIDED_P (first_element) - /* We cannot handle stores with gaps. */ - || DR_IS_WRITE (dr_info->dr)) - { - STMT_VINFO_STRIDED_P (vinfo) = true; - DR_GROUP_GAP (vinfo) = 0; - } - else - DR_GROUP_GAP (vinfo) = group_size - 1; - /* Duplicate and adjust alignment info, it needs to - be present on each group leader, see dr_misalignment. */ - if (vinfo != first_element) - { - dr_vec_info *dr_info2 = STMT_VINFO_DR_INFO (vinfo); - dr_info2->target_alignment = dr_info->target_alignment; - int misalignment = dr_info->misalignment; - if (misalignment != DR_MISALIGNMENT_UNKNOWN) - { - HOST_WIDE_INT diff - = (TREE_INT_CST_LOW (DR_INIT (dr_info2->dr)) - - TREE_INT_CST_LOW (DR_INIT (dr_info->dr))); - unsigned HOST_WIDE_INT align_c - = dr_info->target_alignment.to_constant (); - misalignment = (misalignment + diff) % align_c; - } - dr_info2->misalignment = misalignment; - } - vinfo = next; - } - } - } - } -} - /* Determine if operating on full vectors for LOOP_VINFO might leave some scalar iterations still to do. If so, decide how we should handle those scalar iterations. The possibilities are: @@ -2838,19 +2497,18 @@ vect_analyze_loop_2 (loop_vec_info loop_vinfo, bool &fatal, return opt_result::failure_at (vect_location, "bad data dependence.\n"); LOOP_VINFO_MAX_VECT_FACTOR (loop_vinfo) = max_vf; - ok = vect_determine_vectorization_factor (loop_vinfo); + ok = vect_set_stmts_vectype (loop_vinfo); if (!ok) { if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, - "can't determine vectorization factor.\n"); + "cannot determine vector types.\n"); return ok; } /* Compute the scalar iteration cost. */ vect_compute_single_scalar_iteration_cost (loop_vinfo); - poly_uint64 saved_vectorization_factor = LOOP_VINFO_VECT_FACTOR (loop_vinfo); bool saved_can_use_partial_vectors_p = LOOP_VINFO_CAN_USE_PARTIAL_VECTORS_P (loop_vinfo); @@ -2866,21 +2524,29 @@ start_over: return ok; /* If there are any SLP instances mark them as pure_slp. */ - if (vect_make_slp_decision (loop_vinfo)) - { - /* Find stmts that need to be both vectorized and SLPed. */ - vect_detect_hybrid_slp (loop_vinfo); - - /* Update the vectorization factor based on the SLP decision. */ - vect_update_vf_for_slp (loop_vinfo); + if (!vect_make_slp_decision (loop_vinfo)) + return opt_result::failure_at (vect_location, "no stmts to vectorize.\n"); - /* Optimize the SLP graph with the vectorization factor fixed. */ - vect_optimize_slp (loop_vinfo); + /* Find stmts that need to be both vectorized and SLPed. */ + if (!vect_detect_hybrid_slp (loop_vinfo)) + return opt_result::failure_at (vect_location, "needs non-SLP handling\n"); - /* Gather the loads reachable from the SLP graph entries. */ - vect_gather_slp_loads (loop_vinfo); + /* Determine the vectorization factor from the SLP decision. */ + LOOP_VINFO_VECT_FACTOR (loop_vinfo) + = LOOP_VINFO_SLP_UNROLLING_FACTOR (loop_vinfo); + if (dump_enabled_p ()) + { + dump_printf_loc (MSG_NOTE, vect_location, "vectorization factor = "); + dump_dec (MSG_NOTE, LOOP_VINFO_VECT_FACTOR (loop_vinfo)); + dump_printf (MSG_NOTE, "\n"); } + /* Optimize the SLP graph with the vectorization factor fixed. */ + vect_optimize_slp (loop_vinfo); + + /* Gather the loads reachable from the SLP graph entries. */ + vect_gather_slp_loads (loop_vinfo); + /* We don't expect to have to roll back to anything other than an empty set of rgroups. */ gcc_assert (LOOP_VINFO_MASKS (loop_vinfo).is_empty ()); @@ -2949,19 +2615,6 @@ start_over: goto again; } - /* Dissolve SLP-only groups. */ - vect_dissolve_slp_only_groups (loop_vinfo); - - /* Scan all the remaining operations in the loop that we did not catch - during SLP build and make sure we fail. */ - ok = vect_analyze_loop_operations (loop_vinfo); - if (!ok) - { - ok = opt_result::failure_at (vect_location, - "bad operation or unsupported loop bound\n"); - goto again; - } - /* For now, we don't expect to mix both masking and length approaches for one loop, disable it if both are recorded. */ if (LOOP_VINFO_CAN_USE_PARTIAL_VECTORS_P (loop_vinfo) @@ -3271,8 +2924,8 @@ again: dump_printf_loc (MSG_NOTE, vect_location, "re-trying with single-lane SLP\n"); - /* Restore vectorization factor as it were without SLP. */ - LOOP_VINFO_VECT_FACTOR (loop_vinfo) = saved_vectorization_factor; + /* Reset the vectorization factor. */ + LOOP_VINFO_VECT_FACTOR (loop_vinfo) = 0; /* Free the SLP instances. */ FOR_EACH_VEC_ELT (LOOP_VINFO_SLP_INSTANCES (loop_vinfo), j, instance) vect_free_slp_instance (instance); @@ -3400,8 +3053,10 @@ vect_joust_loop_vinfos (loop_vec_info new_loop_vinfo, } /* Analyze LOOP with VECTOR_MODES[MODE_I] and as epilogue if ORIG_LOOP_VINFO is - not NULL. Set AUTODETECTED_VECTOR_MODE if VOIDmode and advance - MODE_I to the next mode useful to analyze. + not NULL. When MASKED_P is not -1 override the default + LOOP_VINFO_CAN_USE_PARTIAL_VECTORS_P with it. + Set AUTODETECTED_VECTOR_MODE if VOIDmode and advance MODE_I to the next + mode useful to analyze. Return the loop_vinfo on success and wrapped null on failure. */ static opt_loop_vec_info @@ -3409,6 +3064,7 @@ vect_analyze_loop_1 (class loop *loop, vec_info_shared *shared, const vect_loop_form_info *loop_form_info, loop_vec_info orig_loop_vinfo, const vector_modes &vector_modes, unsigned &mode_i, + int masked_p, machine_mode &autodetected_vector_mode, bool &fatal) { @@ -3417,6 +3073,8 @@ vect_analyze_loop_1 (class loop *loop, vec_info_shared *shared, machine_mode vector_mode = vector_modes[mode_i]; loop_vinfo->vector_mode = vector_mode; + if (masked_p != -1) + loop_vinfo->can_use_partial_vectors_p = masked_p; unsigned int suggested_unroll_factor = 1; unsigned slp_done_for_suggested_uf = 0; @@ -3600,7 +3258,7 @@ vect_analyze_loop (class loop *loop, gimple *loop_vectorized_call, cached_vf_per_mode[last_mode_i] = -1; opt_loop_vec_info loop_vinfo = vect_analyze_loop_1 (loop, shared, &loop_form_info, - NULL, vector_modes, mode_i, + NULL, vector_modes, mode_i, -1, autodetected_vector_mode, fatal); if (fatal) break; @@ -3685,18 +3343,21 @@ vect_analyze_loop (class loop *loop, gimple *loop_vectorized_call, array may contain length-agnostic and length-specific modes. Their ordering is not guaranteed, so we could end up picking a mode for the main loop that is after the epilogue's optimal mode. */ + int masked_p = -1; if (!unlimited_cost_model (loop) - && first_loop_vinfo->vector_costs->suggested_epilogue_mode () != VOIDmode) + && (first_loop_vinfo->vector_costs->suggested_epilogue_mode (masked_p) + != VOIDmode)) { vector_modes[0] - = first_loop_vinfo->vector_costs->suggested_epilogue_mode (); + = first_loop_vinfo->vector_costs->suggested_epilogue_mode (masked_p); cached_vf_per_mode[0] = 0; } else vector_modes[0] = autodetected_vector_mode; mode_i = 0; - bool supports_partial_vectors = param_vect_partial_vector_usage != 0; + bool supports_partial_vectors = (param_vect_partial_vector_usage != 0 + || masked_p == 1); machine_mode mask_mode; if (supports_partial_vectors && !partial_vectors_supported_p () @@ -3710,6 +3371,10 @@ vect_analyze_loop (class loop *loop, gimple *loop_vectorized_call, loop_vec_info orig_loop_vinfo = first_loop_vinfo; do { + /* Let the user override what the target suggests. */ + if (OPTION_SET_P (param_vect_partial_vector_usage)) + masked_p = -1; + while (1) { /* If the target does not support partial vectors we can shorten the @@ -3750,7 +3415,7 @@ vect_analyze_loop (class loop *loop, gimple *loop_vectorized_call, opt_loop_vec_info loop_vinfo = vect_analyze_loop_1 (loop, shared, &loop_form_info, orig_loop_vinfo, - vector_modes, mode_i, + vector_modes, mode_i, masked_p, autodetected_vector_mode, fatal); if (fatal) break; @@ -3781,6 +3446,9 @@ vect_analyze_loop (class loop *loop, gimple *loop_vectorized_call, break; } + /* Revert back to the default from the suggested prefered + epilogue vectorization mode. */ + masked_p = -1; if (mode_i == vector_modes.length ()) break; } @@ -3791,13 +3459,14 @@ vect_analyze_loop (class loop *loop, gimple *loop_vectorized_call, /* When we selected a first vectorized epilogue, see if the target suggests to have another one. */ + masked_p = -1; if (!unlimited_cost_model (loop) && !LOOP_VINFO_USING_PARTIAL_VECTORS_P (orig_loop_vinfo) - && (orig_loop_vinfo->vector_costs->suggested_epilogue_mode () + && (orig_loop_vinfo->vector_costs->suggested_epilogue_mode (masked_p) != VOIDmode)) { vector_modes[0] - = orig_loop_vinfo->vector_costs->suggested_epilogue_mode (); + = orig_loop_vinfo->vector_costs->suggested_epilogue_mode (masked_p); cached_vf_per_mode[0] = 0; mode_i = 0; } @@ -5332,7 +5001,7 @@ vect_is_emulated_mixed_dot_prod (stmt_vec_info stmt_info) static void vect_model_reduction_cost (loop_vec_info loop_vinfo, - stmt_vec_info stmt_info, internal_fn reduc_fn, + slp_tree node, internal_fn reduc_fn, vect_reduction_type reduction_type, int ncopies, stmt_vector_for_cost *cost_vec) { @@ -5348,9 +5017,10 @@ vect_model_reduction_cost (loop_vec_info loop_vinfo, if (reduction_type == COND_REDUCTION) ncopies *= 2; - vectype = STMT_VINFO_VECTYPE (stmt_info); + vectype = SLP_TREE_VECTYPE (node); mode = TYPE_MODE (vectype); - stmt_vec_info orig_stmt_info = vect_orig_stmt (stmt_info); + stmt_vec_info orig_stmt_info + = vect_orig_stmt (SLP_TREE_REPRESENTATIVE (node)); gimple_match_op op; if (!gimple_extract_op (orig_stmt_info->stmt, &op)) @@ -5368,16 +5038,16 @@ vect_model_reduction_cost (loop_vec_info loop_vinfo, if (reduc_fn != IFN_LAST) /* Count one reduction-like operation per vector. */ inside_cost = record_stmt_cost (cost_vec, ncopies, vec_to_scalar, - stmt_info, 0, vect_body); + node, 0, vect_body); else { /* Use NELEMENTS extracts and NELEMENTS scalar ops. */ unsigned int nelements = ncopies * vect_nunits_for_cost (vectype); inside_cost = record_stmt_cost (cost_vec, nelements, - vec_to_scalar, stmt_info, 0, + vec_to_scalar, node, 0, vect_body); inside_cost += record_stmt_cost (cost_vec, nelements, - scalar_stmt, stmt_info, 0, + scalar_stmt, node, 0, vect_body); } } @@ -5394,7 +5064,7 @@ vect_model_reduction_cost (loop_vec_info loop_vinfo, /* We need the initial reduction value. */ prologue_stmts = 1; prologue_cost += record_stmt_cost (cost_vec, prologue_stmts, - scalar_to_vec, stmt_info, 0, + scalar_to_vec, node, 0, vect_prologue); } @@ -5411,24 +5081,24 @@ vect_model_reduction_cost (loop_vec_info loop_vinfo, { /* An EQ stmt and an COND_EXPR stmt. */ epilogue_cost += record_stmt_cost (cost_vec, 2, - vector_stmt, stmt_info, 0, + vector_stmt, node, 0, vect_epilogue); /* Reduction of the max index and a reduction of the found values. */ epilogue_cost += record_stmt_cost (cost_vec, 2, - vec_to_scalar, stmt_info, 0, + vec_to_scalar, node, 0, vect_epilogue); /* A broadcast of the max value. */ epilogue_cost += record_stmt_cost (cost_vec, 1, - scalar_to_vec, stmt_info, 0, + scalar_to_vec, node, 0, vect_epilogue); } else { epilogue_cost += record_stmt_cost (cost_vec, 1, vector_stmt, - stmt_info, 0, vect_epilogue); + node, 0, vect_epilogue); epilogue_cost += record_stmt_cost (cost_vec, 1, - vec_to_scalar, stmt_info, 0, + vec_to_scalar, node, 0, vect_epilogue); } } @@ -5438,12 +5108,12 @@ vect_model_reduction_cost (loop_vec_info loop_vinfo, /* Extraction of scalar elements. */ epilogue_cost += record_stmt_cost (cost_vec, 2 * estimated_nunits, - vec_to_scalar, stmt_info, 0, + vec_to_scalar, node, 0, vect_epilogue); /* Scalar max reductions via COND_EXPR / MAX_EXPR. */ epilogue_cost += record_stmt_cost (cost_vec, 2 * estimated_nunits - 3, - scalar_stmt, stmt_info, 0, + scalar_stmt, node, 0, vect_epilogue); } else if (reduction_type == EXTRACT_LAST_REDUCTION @@ -5469,10 +5139,10 @@ vect_model_reduction_cost (loop_vec_info loop_vinfo, Also requires scalar extract. */ epilogue_cost += record_stmt_cost (cost_vec, exact_log2 (nelements) * 2, - vector_stmt, stmt_info, 0, + vector_stmt, node, 0, vect_epilogue); epilogue_cost += record_stmt_cost (cost_vec, 1, - vec_to_scalar, stmt_info, 0, + vec_to_scalar, node, 0, vect_epilogue); } else @@ -5480,7 +5150,7 @@ vect_model_reduction_cost (loop_vec_info loop_vinfo, elements, we have N extracts and N-1 reduction ops. */ epilogue_cost += record_stmt_cost (cost_vec, nelements + nelements - 1, - vector_stmt, stmt_info, 0, + vector_stmt, node, 0, vect_epilogue); } } @@ -7708,23 +7378,20 @@ vectorizable_reduction (loop_vec_info loop_vinfo, if (lane_reducing_op_p (op.code)) { - enum vect_def_type dt; - tree vectype_op; - /* The last operand of lane-reducing operation is for reduction. */ gcc_assert (reduc_idx > 0 && reduc_idx == (int) op.num_ops - 1); - if (!vect_is_simple_use (op.ops[0], loop_vinfo, &dt, &vectype_op)) - return false; - + slp_tree op_node = SLP_TREE_CHILDREN (slp_for_stmt_info)[0]; + tree vectype_op = SLP_TREE_VECTYPE (op_node); tree type_op = TREE_TYPE (op.ops[0]); - if (!vectype_op) { vectype_op = get_vectype_for_scalar_type (loop_vinfo, type_op); - if (!vectype_op) + if (!vectype_op + || !vect_maybe_update_slp_op_vectype (op_node, + vectype_op)) return false; } @@ -7805,7 +7472,7 @@ vectorizable_reduction (loop_vec_info loop_vinfo, inside the loop body. The last operand is the reduction variable, which is defined by the loop-header-phi. */ - tree vectype_out = STMT_VINFO_VECTYPE (stmt_info); + tree vectype_out = SLP_TREE_VECTYPE (slp_for_stmt_info); STMT_VINFO_REDUC_VECTYPE (reduc_info) = vectype_out; STMT_VINFO_REDUC_VECTYPE_IN (reduc_info) = vectype_in; @@ -8408,7 +8075,7 @@ vectorizable_reduction (loop_vec_info loop_vinfo, return false; } - vect_model_reduction_cost (loop_vinfo, stmt_info, reduc_fn, + vect_model_reduction_cost (loop_vinfo, slp_for_stmt_info, reduc_fn, reduction_type, ncopies, cost_vec); /* Cost the reduction op inside the loop if transformed via vect_transform_reduction for non-lane-reducing operation. Otherwise @@ -11412,7 +11079,7 @@ vect_get_loop_len (loop_vec_info loop_vinfo, gimple_stmt_iterator *gsi, factor = exact_div (nunits1, nunits2).to_constant (); tree iv_type = LOOP_VINFO_RGROUP_IV_TYPE (loop_vinfo); gimple_seq seq = NULL; - loop_len = gimple_build (&seq, RDIV_EXPR, iv_type, loop_len, + loop_len = gimple_build (&seq, EXACT_DIV_EXPR, iv_type, loop_len, build_int_cst (iv_type, factor)); if (seq) gsi_insert_seq_before (gsi, seq, GSI_SAME_STMT); @@ -11472,7 +11139,7 @@ scale_profile_for_vect_loop (class loop *loop, edge exit_e, unsigned vf, bool fl profile_count entry_count = loop_preheader_edge (loop)->count (); /* If we have unreliable loop profile avoid dropping entry - count bellow header count. This can happen since loops + count below header count. This can happen since loops has unrealistically low trip counts. */ while (vf > 1 && loop->header->count > entry_count diff --git a/gcc/tree-vect-slp.cc b/gcc/tree-vect-slp.cc index 7a828ca..ad753869 100644 --- a/gcc/tree-vect-slp.cc +++ b/gcc/tree-vect-slp.cc @@ -4067,7 +4067,12 @@ vect_build_slp_instance (vec_info *vinfo, for (unsigned i = 0; i < group_size; ++i) scalar_stmts.quick_push (next_info); slp_tree conv = vect_create_new_slp_node (scalar_stmts, 1); - SLP_TREE_VECTYPE (conv) = STMT_VINFO_VECTYPE (next_info); + SLP_TREE_VECTYPE (conv) + = get_vectype_for_scalar_type (vinfo, + TREE_TYPE + (gimple_assign_lhs + (scalar_def)), + group_size); SLP_TREE_CHILDREN (conv).quick_push (node); SLP_INSTANCE_TREE (new_instance) = conv; /* We also have to fake this conversion stmt as SLP reduction @@ -5063,9 +5068,15 @@ vect_analyze_slp (vec_info *vinfo, unsigned max_tree_size, tree args0 = gimple_cond_lhs (stmt); tree args1 = gimple_cond_rhs (stmt); - /* These should be enforced by cond lowering. */ - gcc_assert (gimple_cond_code (stmt) == NE_EXPR); - gcc_assert (zerop (args1)); + /* These should be enforced by cond lowering, but if it failed + bail. */ + if (gimple_cond_code (stmt) != NE_EXPR + || TREE_TYPE (args0) != boolean_type_node + || !integer_zerop (args1)) + { + roots.release (); + continue; + } /* An argument without a loop def will be codegened from vectorizing the root gcond itself. As such we don't need to try to build an SLP tree @@ -7691,7 +7702,7 @@ maybe_push_to_hybrid_worklist (vec_info *vinfo, /* Find stmts that must be both vectorized and SLPed. */ -void +bool vect_detect_hybrid_slp (loop_vec_info loop_vinfo) { DUMP_VECT_SCOPE ("vect_detect_hybrid_slp"); @@ -7772,6 +7783,52 @@ vect_detect_hybrid_slp (loop_vec_info loop_vinfo) vect_detect_hybrid_slp (&gs_info.offset, &dummy, &wi); } } + + /* Determine if all the stmts in the loop can be SLPed. */ + for (unsigned i = 0; i < LOOP_VINFO_LOOP (loop_vinfo)->num_nodes; i++) + { + basic_block bb = LOOP_VINFO_BBS (loop_vinfo)[i]; + for (gphi_iterator si = gsi_start_phis (bb); !gsi_end_p (si); + gsi_next (&si)) + { + stmt_vec_info stmt_info = loop_vinfo->lookup_stmt (si.phi ()); + if (!stmt_info) + continue; + if ((STMT_VINFO_RELEVANT_P (stmt_info) + || VECTORIZABLE_CYCLE_DEF (STMT_VINFO_DEF_TYPE (stmt_info))) + && !PURE_SLP_STMT (stmt_info)) + { + /* STMT needs both SLP and loop-based vectorization. */ + if (dump_enabled_p ()) + dump_printf_loc (MSG_NOTE, vect_location, + "Loop contains SLP and non-SLP stmts\n"); + return false; + } + } + for (gimple_stmt_iterator si = gsi_start_bb (bb); !gsi_end_p (si); + gsi_next (&si)) + { + if (is_gimple_debug (gsi_stmt (si))) + continue; + stmt_vec_info stmt_info = loop_vinfo->lookup_stmt (gsi_stmt (si)); + stmt_info = vect_stmt_to_vectorize (stmt_info); + if ((STMT_VINFO_RELEVANT_P (stmt_info) + || VECTORIZABLE_CYCLE_DEF (STMT_VINFO_DEF_TYPE (stmt_info))) + && !PURE_SLP_STMT (stmt_info)) + { + /* STMT needs both SLP and loop-based vectorization. */ + if (dump_enabled_p ()) + dump_printf_loc (MSG_NOTE, vect_location, + "Loop contains SLP and non-SLP stmts\n"); + return false; + } + } + } + + if (dump_enabled_p ()) + dump_printf_loc (MSG_NOTE, vect_location, + "Loop contains only SLP stmts\n"); + return true; } @@ -7852,8 +7909,6 @@ vect_slp_analyze_node_operations_1 (vec_info *vinfo, slp_tree node, slp_instance node_instance, stmt_vector_for_cost *cost_vec) { - stmt_vec_info stmt_info = SLP_TREE_REPRESENTATIVE (node); - /* Calculate the number of vector statements to be created for the scalar stmts in this node. It is the number of scalar elements in one scalar iteration (DR_GROUP_SIZE) multiplied by VF divided by the number of @@ -7882,9 +7937,7 @@ vect_slp_analyze_node_operations_1 (vec_info *vinfo, slp_tree node, return true; } - bool dummy; - return vect_analyze_stmt (vinfo, stmt_info, &dummy, - node, node_instance, cost_vec); + return vect_analyze_stmt (vinfo, node, node_instance, cost_vec); } static int diff --git a/gcc/tree-vect-stmts.cc b/gcc/tree-vect-stmts.cc index 95406b4..4aa69da 100644 --- a/gcc/tree-vect-stmts.cc +++ b/gcc/tree-vect-stmts.cc @@ -2466,17 +2466,10 @@ get_load_store_type (vec_info *vinfo, stmt_vec_info stmt_info, vls_type == VLS_LOAD ? "gather" : "scatter"); return false; } - else if (!vect_is_simple_use (gs_info->offset, vinfo, - &gs_info->offset_dt, - &gs_info->offset_vectype)) - { - if (dump_enabled_p ()) - dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, - "%s index use not simple.\n", - vls_type == VLS_LOAD ? "gather" : "scatter"); - return false; - } - else if (gs_info->ifn == IFN_LAST && !gs_info->decl) + slp_tree offset_node = SLP_TREE_CHILDREN (slp_node)[0]; + gs_info->offset_dt = SLP_TREE_DEF_TYPE (offset_node); + gs_info->offset_vectype = SLP_TREE_VECTYPE (offset_node); + if (gs_info->ifn == IFN_LAST && !gs_info->decl) { if (!TYPE_VECTOR_SUBPARTS (vectype).is_constant () || !TYPE_VECTOR_SUBPARTS (gs_info->offset_vectype).is_constant () @@ -13186,37 +13179,27 @@ vectorizable_early_exit (vec_info *vinfo, stmt_vec_info stmt_info, VEC_STMT_P is as for vectorizable_live_operation. */ static bool -can_vectorize_live_stmts (vec_info *vinfo, stmt_vec_info stmt_info, +can_vectorize_live_stmts (vec_info *vinfo, slp_tree slp_node, slp_instance slp_node_instance, bool vec_stmt_p, stmt_vector_for_cost *cost_vec) { loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo); - if (slp_node) - { - stmt_vec_info slp_stmt_info; - unsigned int i; - FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (slp_node), i, slp_stmt_info) - { - if (slp_stmt_info - && (STMT_VINFO_LIVE_P (slp_stmt_info) - || (loop_vinfo - && LOOP_VINFO_EARLY_BREAKS (loop_vinfo) - && STMT_VINFO_DEF_TYPE (slp_stmt_info) - == vect_induction_def)) - && !vectorizable_live_operation (vinfo, slp_stmt_info, slp_node, - slp_node_instance, i, - vec_stmt_p, cost_vec)) - return false; - } + stmt_vec_info slp_stmt_info; + unsigned int i; + FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (slp_node), i, slp_stmt_info) + { + if (slp_stmt_info + && (STMT_VINFO_LIVE_P (slp_stmt_info) + || (loop_vinfo + && LOOP_VINFO_EARLY_BREAKS (loop_vinfo) + && STMT_VINFO_DEF_TYPE (slp_stmt_info) + == vect_induction_def)) + && !vectorizable_live_operation (vinfo, slp_stmt_info, slp_node, + slp_node_instance, i, + vec_stmt_p, cost_vec)) + return false; } - else if ((STMT_VINFO_LIVE_P (stmt_info) - || (LOOP_VINFO_EARLY_BREAKS (loop_vinfo) - && STMT_VINFO_DEF_TYPE (stmt_info) == vect_induction_def)) - && !vectorizable_live_operation (vinfo, stmt_info, - slp_node, slp_node_instance, -1, - vec_stmt_p, cost_vec)) - return false; return true; } @@ -13225,115 +13208,42 @@ can_vectorize_live_stmts (vec_info *vinfo, stmt_vec_info stmt_info, opt_result vect_analyze_stmt (vec_info *vinfo, - stmt_vec_info stmt_info, bool *need_to_vectorize, slp_tree node, slp_instance node_instance, stmt_vector_for_cost *cost_vec) { + stmt_vec_info stmt_info = SLP_TREE_REPRESENTATIVE (node); bb_vec_info bb_vinfo = dyn_cast <bb_vec_info> (vinfo); enum vect_relevant relevance = STMT_VINFO_RELEVANT (stmt_info); bool ok; - gimple_seq pattern_def_seq; if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, "==> examining statement: %G", stmt_info->stmt); if (gimple_has_volatile_ops (stmt_info->stmt)) - return opt_result::failure_at (stmt_info->stmt, - "not vectorized:" - " stmt has volatile operands: %G\n", - stmt_info->stmt); - - if (STMT_VINFO_IN_PATTERN_P (stmt_info) - && node == NULL - && (pattern_def_seq = STMT_VINFO_PATTERN_DEF_SEQ (stmt_info))) { - gimple_stmt_iterator si; - - for (si = gsi_start (pattern_def_seq); !gsi_end_p (si); gsi_next (&si)) - { - stmt_vec_info pattern_def_stmt_info - = vinfo->lookup_stmt (gsi_stmt (si)); - if (STMT_VINFO_RELEVANT_P (pattern_def_stmt_info) - || STMT_VINFO_LIVE_P (pattern_def_stmt_info)) - { - /* Analyze def stmt of STMT if it's a pattern stmt. */ - if (dump_enabled_p ()) - dump_printf_loc (MSG_NOTE, vect_location, - "==> examining pattern def statement: %G", - pattern_def_stmt_info->stmt); - - opt_result res - = vect_analyze_stmt (vinfo, pattern_def_stmt_info, - need_to_vectorize, node, node_instance, - cost_vec); - if (!res) - return res; - } - } + /* ??? This shouldn't really happen, volatile stmts should + not end up in the SLP graph. */ + return opt_result::failure_at (stmt_info->stmt, + "not vectorized:" + " stmt has volatile operands: %G\n", + stmt_info->stmt); } - /* Skip stmts that do not need to be vectorized. In loops this is expected - to include: - - the COND_EXPR which is the loop exit condition - - any LABEL_EXPRs in the loop - - computations that are used only for array indexing or loop control. - In basic blocks we only analyze statements that are a part of some SLP - instance, therefore, all the statements are relevant. - - Pattern statement needs to be analyzed instead of the original statement - if the original statement is not relevant. Otherwise, we analyze both - statements. In basic blocks we are called from some SLP instance - traversal, don't analyze pattern stmts instead, the pattern stmts - already will be part of SLP instance. */ - - stmt_vec_info pattern_stmt_info = STMT_VINFO_RELATED_STMT (stmt_info); + /* Skip stmts that do not need to be vectorized. */ if (!STMT_VINFO_RELEVANT_P (stmt_info) && !STMT_VINFO_LIVE_P (stmt_info)) { - if (STMT_VINFO_IN_PATTERN_P (stmt_info) - && pattern_stmt_info - && (STMT_VINFO_RELEVANT_P (pattern_stmt_info) - || STMT_VINFO_LIVE_P (pattern_stmt_info))) - { - /* Analyze PATTERN_STMT instead of the original stmt. */ - stmt_info = pattern_stmt_info; - if (dump_enabled_p ()) - dump_printf_loc (MSG_NOTE, vect_location, - "==> examining pattern statement: %G", - stmt_info->stmt); - } - else - { - if (dump_enabled_p ()) - dump_printf_loc (MSG_NOTE, vect_location, "irrelevant.\n"); - - if (node) - return opt_result::failure_at (stmt_info->stmt, - "not vectorized:" - " irrelevant stmt as SLP node %p " - "representative.\n", - (void *)node); - return opt_result::success (); - } - } - else if (STMT_VINFO_IN_PATTERN_P (stmt_info) - && node == NULL - && pattern_stmt_info - && (STMT_VINFO_RELEVANT_P (pattern_stmt_info) - || STMT_VINFO_LIVE_P (pattern_stmt_info))) - { - /* Analyze PATTERN_STMT too. */ if (dump_enabled_p ()) - dump_printf_loc (MSG_NOTE, vect_location, - "==> examining pattern statement: %G", - pattern_stmt_info->stmt); + dump_printf_loc (MSG_NOTE, vect_location, "irrelevant.\n"); - opt_result res - = vect_analyze_stmt (vinfo, pattern_stmt_info, need_to_vectorize, node, - node_instance, cost_vec); - if (!res) - return res; + /* ??? This shouldn't really happen, irrelevant stmts should + not end up in the SLP graph. */ + return opt_result::failure_at (stmt_info->stmt, + "not vectorized:" + " irrelevant stmt as SLP node %p " + "representative.\n", + (void *)node); } switch (STMT_VINFO_DEF_TYPE (stmt_info)) @@ -13369,8 +13279,7 @@ vect_analyze_stmt (vec_info *vinfo, } tree saved_vectype = STMT_VINFO_VECTYPE (stmt_info); - if (node) - STMT_VINFO_VECTYPE (stmt_info) = SLP_TREE_VECTYPE (node); + STMT_VINFO_VECTYPE (stmt_info) = SLP_TREE_VECTYPE (node); if (STMT_VINFO_RELEVANT_P (stmt_info)) { @@ -13378,23 +13287,8 @@ vect_analyze_stmt (vec_info *vinfo, gcc_assert (STMT_VINFO_VECTYPE (stmt_info) || gimple_code (stmt_info->stmt) == GIMPLE_COND || (call && gimple_call_lhs (call) == NULL_TREE)); - *need_to_vectorize = true; } - if (PURE_SLP_STMT (stmt_info) && !node) - { - if (dump_enabled_p ()) - dump_printf_loc (MSG_NOTE, vect_location, - "handled only by SLP analysis\n"); - return opt_result::success (); - } - - /* When we arrive here with a non-SLP statement and we are supposed - to use SLP for everything fail vectorization. */ - if (!node) - return opt_result::failure_at (stmt_info->stmt, - "needs non-SLP handling\n"); - ok = true; if (!bb_vinfo && (STMT_VINFO_RELEVANT_P (stmt_info) @@ -13458,8 +13352,7 @@ vect_analyze_stmt (vec_info *vinfo, } - if (node) - STMT_VINFO_VECTYPE (stmt_info) = saved_vectype; + STMT_VINFO_VECTYPE (stmt_info) = saved_vectype; if (!ok) return opt_result::failure_at (stmt_info->stmt, @@ -13472,9 +13365,9 @@ vect_analyze_stmt (vec_info *vinfo, if (!bb_vinfo && STMT_VINFO_TYPE (stmt_info) != reduc_vec_info_type && STMT_VINFO_TYPE (stmt_info) != lc_phi_info_type - && (!node || !node->ldst_lanes || SLP_TREE_CODE (node) == VEC_PERM_EXPR) + && (!node->ldst_lanes || SLP_TREE_CODE (node) == VEC_PERM_EXPR) && !can_vectorize_live_stmts (as_a <loop_vec_info> (vinfo), - stmt_info, node, node_instance, + node, node_instance, false, cost_vec)) return opt_result::failure_at (stmt_info->stmt, "not vectorized:" @@ -13646,7 +13539,7 @@ vect_transform_stmt (vec_info *vinfo, { /* Handle stmts whose DEF is used outside the loop-nest that is being vectorized. */ - done = can_vectorize_live_stmts (vinfo, stmt_info, slp_node, + done = can_vectorize_live_stmts (vinfo, slp_node, slp_node_instance, true, NULL); gcc_assert (done); } @@ -14410,6 +14303,8 @@ supportable_widening_operation (vec_info *vinfo, internal_fn lo, hi, even, odd; lookup_hilo_internal_fn (ifn, &lo, &hi); + if (BYTES_BIG_ENDIAN) + std::swap (lo, hi); *code1 = as_combined_fn (lo); *code2 = as_combined_fn (hi); optab1 = direct_internal_fn_optab (lo, {vectype, vectype}); diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h index 66a2964..799d5fe 100644 --- a/gcc/tree-vectorizer.h +++ b/gcc/tree-vectorizer.h @@ -1714,7 +1714,7 @@ public: unsigned int outside_cost () const; unsigned int total_cost () const; unsigned int suggested_unroll_factor () const; - machine_mode suggested_epilogue_mode () const; + machine_mode suggested_epilogue_mode (int &masked) const; protected: unsigned int record_stmt_cost (stmt_vec_info, vect_cost_model_location, @@ -1738,8 +1738,13 @@ protected: unsigned int m_suggested_unroll_factor; /* The suggested mode to be used for a vectorized epilogue or VOIDmode, - determined at finish_cost. */ + determined at finish_cost. m_masked_epilogue specifies whether the + epilogue should use masked vectorization, regardless of the + --param vect-partial-vector-usage default. If -1 then the + --param setting takes precedence. If the user explicitly specified + --param vect-partial-vector-usage then that takes precedence. */ machine_mode m_suggested_epilogue_mode; + int m_masked_epilogue; /* True if finish_cost has been called. */ bool m_finished; @@ -1755,6 +1760,7 @@ vector_costs::vector_costs (vec_info *vinfo, bool costing_for_scalar) m_costs (), m_suggested_unroll_factor(1), m_suggested_epilogue_mode(VOIDmode), + m_masked_epilogue (-1), m_finished (false) { } @@ -1815,9 +1821,10 @@ vector_costs::suggested_unroll_factor () const /* Return the suggested epilogue mode. */ inline machine_mode -vector_costs::suggested_epilogue_mode () const +vector_costs::suggested_epilogue_mode (int &masked_p) const { gcc_checking_assert (m_finished); + masked_p = m_masked_epilogue; return m_suggested_epilogue_mode; } @@ -2499,8 +2506,7 @@ extern bool vect_transform_stmt (vec_info *, stmt_vec_info, slp_tree, slp_instance); extern void vect_remove_stores (vec_info *, stmt_vec_info); extern bool vect_nop_conversion_p (stmt_vec_info); -extern opt_result vect_analyze_stmt (vec_info *, stmt_vec_info, bool *, - slp_tree, +extern opt_result vect_analyze_stmt (vec_info *, slp_tree, slp_instance, stmt_vector_for_cost *); extern void vect_get_load_cost (vec_info *, stmt_vec_info, slp_tree, int, dr_alignment_support, int, bool, @@ -2682,7 +2688,7 @@ extern bool vect_slp_analyze_operations (vec_info *); extern void vect_schedule_slp (vec_info *, const vec<slp_instance> &); extern opt_result vect_analyze_slp (vec_info *, unsigned, bool); extern bool vect_make_slp_decision (loop_vec_info); -extern void vect_detect_hybrid_slp (loop_vec_info); +extern bool vect_detect_hybrid_slp (loop_vec_info); extern void vect_optimize_slp (vec_info *); extern void vect_gather_slp_loads (vec_info *); extern tree vect_get_slp_scalar_def (slp_tree, unsigned); diff --git a/gcc/value-range.h b/gcc/value-range.h index 5c358f3..3bc02db 100644 --- a/gcc/value-range.h +++ b/gcc/value-range.h @@ -324,7 +324,7 @@ public: virtual void update_bitmask (const class irange_bitmask &) override; virtual irange_bitmask get_bitmask () const override; - virtual void verify_range () const; + virtual void verify_range () const override; protected: void maybe_resize (int needed); virtual void set (tree, tree, value_range_kind = VR_RANGE) override; @@ -422,7 +422,7 @@ public: bool contains_p (const wide_int &) const; wide_int lower_bound () const; wide_int upper_bound () const; - virtual void verify_range () const; + virtual void verify_range () const final override; irange_bitmask get_bitmask () const final override; void update_bitmask (const irange_bitmask &) final override; protected: @@ -594,7 +594,7 @@ public: bool nan_signbit_p (bool &signbit) const; bool known_isnormal () const; bool known_isdenormal_or_zero () const; - virtual void verify_range () const; + virtual void verify_range () const override; protected: virtual bool contains_p (tree cst) const override; virtual void set (tree, tree, value_range_kind = VR_RANGE) override; diff --git a/include/ChangeLog b/include/ChangeLog index b11102d..b3fdd3c 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,7 @@ +2025-07-09 Matthieu Longo <matthieu.longo@arm.com> + + * doubly-linked-list.h: New file. + 2025-06-20 Sosutha Sethuramapandian <ssethuramapa@marvell.com> PR target/110181 diff --git a/include/doubly-linked-list.h b/include/doubly-linked-list.h new file mode 100644 index 0000000..3f5ea28 --- /dev/null +++ b/include/doubly-linked-list.h @@ -0,0 +1,447 @@ +/* Manipulate doubly linked lists. + Copyright (C) 2025 Free Software Foundation, Inc. + + This program 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 of the License, or + (at your option) any later version. + + This program 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. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + + +#ifndef _DOUBLY_LINKED_LIST_H +#define _DOUBLY_LINKED_LIST_H + +/* Doubly linked list implementation enforcing typing. + + This implementation of doubly linked list tries to achieve the enforcement of + typing similarly to C++ templates, but without encapsulation. + + All the functions are prefixed with the type of the value: "AType_xxx". + Some functions are prefixed with "_AType_xxx" and are not part of the public + API, so should not be used, except for _##LTYPE##_merge_sort with a caveat + (see note above its definition). + + Each function (### is a placeholder for method name) has a macro for: + (1) its invocation LINKED_LIST_###(LTYPE). + (2) its prototype LINKED_LIST_DECL_###(A, A2, scope). To add in a header + file, or a source file for forward declaration. 'scope' should be set + respectively to 'extern', or 'static'. + (3) its definition LINKED_LIST_DEFN_###(A, A2, scope). To add in a source + file with the 'scope' set respectively to nothing, or 'static' depending + on (2). + + Data structures requirements: + - LTYPE corresponds to the node of a doubly linked list. It needs to define + attributes 'prev' and 'next' which are pointers on the type of a node. + For instance: + struct my_list_node + { + T value; + struct my_list_node *prev; + struct my_list_node *next; + }; + - LWRAPPERTYPE is a structure wrapping the nodes and others metadata (first, + last, size). + */ + + +/* Mutative operations: + - append + - prepend + - insert_before + - pop_front + - pop_back + - remove + - swap + The header and body of each of those operation can be declared individually, + or as a whole via LINKED_LIST_MUTATIVE_OPS_PROTOTYPE for the prototypes, and + LINKED_LIST_MUTATIVE_OPS_DECL for the implementations. */ + +/* Append the given node new_ to the exising list. + Precondition: prev and next of new_ must be NULL. */ +#define LINKED_LIST_APPEND(LTYPE) LTYPE##_append + +#define LINKED_LIST_DECL_APPEND(LWRAPPERTYPE, LTYPE, EXPORT) \ + EXPORT void \ + LTYPE##_append (LWRAPPERTYPE *wrapper, LTYPE *new_) + +#define LINKED_LIST_DEFN_APPEND(LWRAPPERTYPE, LTYPE, EXPORT) \ +EXPORT void \ +LTYPE##_append (LWRAPPERTYPE *wrapper, LTYPE *new_) \ +{ \ + if (wrapper->last == NULL) \ + wrapper->first = new_; \ + else \ + { \ + new_->prev = wrapper->last; \ + wrapper->last->next = new_; \ + } \ + wrapper->last = new_; \ + ++wrapper->size; \ +} + +/* Prepend the given node new_ to the existing list. + Precondition: prev and next of new_ must be NULL. */ +#define LINKED_LIST_PREPEND(LTYPE) LTYPE##_prepend + +#define LINKED_LIST_DECL_PREPEND(LWRAPPERTYPE, LTYPE, EXPORT) \ + EXPORT void \ + LTYPE##_prepend (LWRAPPERTYPE *wrapper, LTYPE *new_) + +#define LINKED_LIST_DEFN_PREPEND(LWRAPPERTYPE, LTYPE, EXPORT) \ +EXPORT void \ +LTYPE##_prepend (LWRAPPERTYPE *wrapper, LTYPE *new_) \ +{ \ + if (wrapper->first == NULL) \ + wrapper->last = new_; \ + else \ + { \ + new_->next = wrapper->first; \ + wrapper->first->prev = new_; \ + } \ + wrapper->first = new_; \ + ++wrapper->size; \ +} + +/* Insert the given node new_ before 'where' in the existing list. + If where == NULL, the insertion is equivalent to an append. + If where == first, the insertion is equivalent to a prepend. */ +#define LINKED_LIST_INSERT_BEFORE(LTYPE) LTYPE##_insert_before + +#define LINKED_LIST_DECL_INSERT_BEFORE(LWRAPPERTYPE, LTYPE, EXPORT) \ + EXPORT void \ + LTYPE##_insert_before (LWRAPPERTYPE *wrapper, \ + LTYPE *new_, \ + LTYPE *where) + +#define LINKED_LIST_DEFN_INSERT_BEFORE(LWRAPPERTYPE, LTYPE, EXPORT) \ +EXPORT void \ +LTYPE##_insert_before (LWRAPPERTYPE *wrapper, \ + LTYPE *new_, \ + LTYPE *where) \ +{ \ + if (where == wrapper->first) \ + LTYPE##_prepend (wrapper, new_); \ + else if (where == NULL) \ + LTYPE##_append (wrapper, new_); \ + else \ + { \ + where->prev->next = new_; \ + new_->prev = where->prev; \ + where->prev = new_; \ + new_->next = where; \ + ++wrapper->size; \ + } \ +} + +/* Pop the first node of the list. */ +#define LINKED_LIST_POP_FRONT(LTYPE) LTYPE##_pop_front + +#define LINKED_LIST_DECL_POP_FRONT(LWRAPPERTYPE, LTYPE, EXPORT) \ + EXPORT LTYPE * \ + LTYPE##_pop_front (LWRAPPERTYPE *wrapper) + +#define LINKED_LIST_DEFN_POP_FRONT(LWRAPPERTYPE, LTYPE, EXPORT) \ +EXPORT LTYPE * \ +LTYPE##_pop_front (LWRAPPERTYPE *wrapper) \ +{ \ + LTYPE *front_node = wrapper->first; \ + if (front_node != NULL) \ + { \ + wrapper->first = front_node->next; \ + if (wrapper->last == front_node) \ + wrapper->last = NULL; \ + else \ + { \ + front_node->next->prev = NULL; \ + front_node->next = NULL; \ + } \ + front_node->next = NULL; \ + --wrapper->size; \ + } \ + return front_node; \ +} + +/* Pop the last node of the list. */ +#define LINKED_LIST_POP_BACK(LTYPE) LTYPE##_pop_back + +#define LINKED_LIST_DECL_POP_BACK(LWRAPPERTYPE, LTYPE, EXPORT) \ + EXPORT LTYPE * \ + LTYPE##_pop_back (LWRAPPERTYPE *wrapper) + +#define LINKED_LIST_DEFN_POP_BACK(LWRAPPERTYPE, LTYPE, EXPORT) \ +EXPORT LTYPE * \ +LTYPE##_pop_back (LWRAPPERTYPE *wrapper) \ +{ \ + LTYPE *back_node = wrapper->last; \ + if (back_node != NULL) \ + { \ + wrapper->last = back_node->prev; \ + if (wrapper->first == back_node) \ + wrapper->first = NULL; \ + else \ + { \ + back_node->prev->next = NULL; \ + back_node->prev = NULL; \ + } \ + back_node->prev = NULL; \ + --wrapper->size; \ + } \ + return back_node; \ +} + +/* Remove the given node from the existing list, and return the previous + node. */ +#define LINKED_LIST_REMOVE(LTYPE) LTYPE##_remove + +#define LINKED_LIST_DECL_REMOVE(LWRAPPERTYPE, LTYPE, EXPORT) \ + EXPORT LTYPE * \ + LTYPE##_remove (LWRAPPERTYPE *wrapper, LTYPE *node) + +#define LINKED_LIST_DEFN_REMOVE(LWRAPPERTYPE, LTYPE, EXPORT) \ +EXPORT LTYPE * \ +LTYPE##_remove (LWRAPPERTYPE *wrapper, LTYPE *node) \ +{ \ + LTYPE *previous = NULL; \ + \ + if (node->prev != NULL) \ + { \ + node->prev->next = node->next; \ + if (node->next == NULL) \ + wrapper->last = node->prev; \ + else \ + node->next->prev = node->prev; \ + previous = node->prev; \ + node->next = NULL; \ + node->prev = NULL; \ + --wrapper->size; \ + } \ + else \ + LTYPE##_pop_front (wrapper); \ + \ + return previous; \ +} + +/* Generic swap. */ +#define LINKED_LIST_SWAP(LTYPE) LTYPE##_swap + +#define LINKED_LIST_DECL_SWAP(LWRAPPERTYPE, LTYPE, EXPORT) \ + EXPORT void \ + LTYPE##_swap (LWRAPPERTYPE *wrapper, LTYPE *node1, LTYPE *node2) + +/* Swap two nodes in a list. */ +#define LINKED_LIST_DEFN_SWAP(LWRAPPERTYPE, LTYPE, EXPORT) \ +EXPORT void \ +LTYPE##_swap (LWRAPPERTYPE *wrapper, LTYPE *node1, LTYPE *node2) \ +{ \ + LTYPE *prev1 = node1->prev; \ + LTYPE *next1 = node1->next; \ + LTYPE *prev2 = node2->prev; \ + LTYPE *next2 = node2->next; \ + \ + if (prev1 != NULL) \ + prev1->next = node2; \ + else \ + wrapper->first = node2; \ + if (prev2 != NULL) \ + prev2->next = node1; \ + else \ + wrapper->first = node1; \ + \ + if (next1 != NULL) \ + next1->prev = node2; \ + else \ + wrapper->last = node2; \ + if (next2 != NULL) \ + next2->prev = node1; \ + else \ + wrapper->last = node1; \ + \ + { \ + LTYPE *temp = node1->next; \ + node1->next = node2->next; \ + node2->next = temp; \ + } \ + { \ + LTYPE *temp = node1->prev; \ + node1->prev = node2->prev; \ + node2->prev = temp; \ + } \ +} + +/* Note: all the mutative operations below also update the data in the wrapper, + i.e. first, last and size. */ +#define LINKED_LIST_MUTATIVE_OPS_PROTOTYPE(LWRAPPERTYPE, LTYPE, EXPORT) \ + LINKED_LIST_DECL_APPEND(LWRAPPERTYPE, LTYPE, EXPORT); \ + LINKED_LIST_DECL_PREPEND(LWRAPPERTYPE, LTYPE, EXPORT); \ + LINKED_LIST_DECL_INSERT_BEFORE(LWRAPPERTYPE, LTYPE, EXPORT); \ + LINKED_LIST_DECL_POP_FRONT(LWRAPPERTYPE, LTYPE, EXPORT); \ + LINKED_LIST_DECL_POP_BACK(LWRAPPERTYPE, LTYPE, EXPORT); \ + LINKED_LIST_DECL_REMOVE(LWRAPPERTYPE, LTYPE, EXPORT); \ + LINKED_LIST_DECL_SWAP(LWRAPPERTYPE, LTYPE, EXPORT) + +#define LINKED_LIST_MUTATIVE_OPS_DECL(LWRAPPERTYPE, LTYPE, EXPORT) \ + LINKED_LIST_DEFN_APPEND(LWRAPPERTYPE, LTYPE, EXPORT) \ + LINKED_LIST_DEFN_PREPEND(LWRAPPERTYPE, LTYPE, EXPORT) \ + LINKED_LIST_DEFN_INSERT_BEFORE(LWRAPPERTYPE, LTYPE, EXPORT) \ + LINKED_LIST_DEFN_POP_FRONT(LWRAPPERTYPE, LTYPE, EXPORT) \ + LINKED_LIST_DEFN_POP_BACK(LWRAPPERTYPE, LTYPE, EXPORT) \ + LINKED_LIST_DEFN_REMOVE(LWRAPPERTYPE, LTYPE, EXPORT) \ + LINKED_LIST_DEFN_SWAP(LWRAPPERTYPE, LTYPE, EXPORT) + + +/* Sorting. */ + +#define LINKED_LIST_MERGE_SORT_(LTYPE) LTYPE##_merge_sort_ + +#define LINKED_LIST_MERGE_SORT(LTYPE) LTYPE##_merge_sort + +#define LINKED_LIST_MERGE_SORT_PROTOTYPE_(LTYPE, EXPORT) \ + EXPORT LTYPE * \ + LTYPE##_merge_sort_ (LTYPE *node, \ + int (*fn_cmp) (const LTYPE *, const LTYPE *)) + +#define LINKED_LIST_MERGE_SORT_PROTOTYPE(LWRAPPERTYPE, LTYPE, EXPORT) \ + EXPORT void \ + LTYPE##_merge_sort (LWRAPPERTYPE *wrapper, \ + int (*fn_cmp) (const LTYPE *, const LTYPE *)) + +/* Note: all the functions and macros below starting with "_" should be + considered private. */ + +/* Compute the middle element of the list based on the turtle and hare + approach, i.e. the hare runs twice faster than the turtle. */ +#define _MERGE_SORT_IMPL_COMPUTE_TURTLE(LTYPE) \ +static inline LTYPE * \ +LTYPE##_merge_sort_compute_turtle_ (LTYPE *node) \ +{ \ + if (node == NULL) \ + return node; \ + \ + LTYPE *turtle = node, *hare = node->next; \ + while (hare != NULL && hare->next != NULL) \ + { \ + turtle = turtle->next; \ + hare = hare->next->next; \ + } \ + return turtle; \ +} + +/* Append n at the end of l_out, and return the next node after n. + l_out and l_last should be ideally encapsulated into a list structure + but this is overkill for what we need here. */ +#define _MERGE_SORT_IMPL_OUT_APPEND(LTYPE) \ +static inline LTYPE * \ +LTYPE##_merge_sort_out_append_ (LTYPE **l_out, LTYPE **l_last, \ + LTYPE *n) \ +{ \ + if (*l_last == NULL) \ + { \ + *l_last = n; \ + *l_out = n; \ + n->prev = NULL; \ + } \ + else \ + { \ + (*l_last)->next = n; \ + n->prev = *l_last; \ + *l_last = n; \ + } \ + \ + return n->next; \ +} + +/* Merge two sorted lists together. + The returned value corresponds to the first element of the list. + Note: both input lists are invalidated after the call. */ +#define _MERGE_SORT_IMPL_MERGE(LTYPE) \ +static inline LTYPE * \ +LTYPE##_merge_sort_merge_ (LTYPE *l_left, LTYPE *l_right, \ + int (*fn_cmp) (const LTYPE *, const LTYPE *))\ +{ \ + if (l_left == NULL) \ + return l_right; \ + else if (l_right == NULL) \ + return l_left; \ + \ + LTYPE *l_out = NULL, *l_last = NULL; \ + \ + LTYPE *l_l = l_left, *l_r = l_right; \ + while (l_l != NULL && l_r != NULL) \ + { \ + int cmp = fn_cmp (l_l, l_r); \ + if (cmp <= 0) \ + l_l = LTYPE##_merge_sort_out_append_ (&l_out, &l_last, l_l); \ + else \ + l_r = LTYPE##_merge_sort_out_append_ (&l_out, &l_last, l_r); \ + } \ + \ + LTYPE *l_remaining = (l_l != NULL) ? l_l : l_r; \ + while (l_remaining != NULL) \ + l_remaining = \ + LTYPE##_merge_sort_out_append_ (&l_out, &l_last, l_remaining); \ + \ + return l_out; \ +} + +/* Merge sort implementation taking the first node of the list to sort, + and the comparison function. Returns the first node of the sorted list. + Note: use this if you don't care about updating the information in the + wrapper. */ +#define _MERGE_SORT_DEFN_SORT(LTYPE, EXPORT) \ +EXPORT LTYPE * \ +LTYPE##_merge_sort_ (LTYPE *node, \ + int (*fn_cmp)(const LTYPE *, const LTYPE *)) \ +{ \ + if (node == NULL) \ + return NULL; \ + else if (node->next == NULL) \ + return node; \ + \ + LTYPE *left_end = LTYPE##_merge_sort_compute_turtle_ (node); \ + LTYPE *left_begin = node; \ + LTYPE *right_begin = left_end->next; \ + /* break the list. */ \ + left_end->next = NULL; \ + right_begin->prev = NULL; \ + \ + left_begin = LTYPE##_merge_sort_ (left_begin, fn_cmp); \ + right_begin = LTYPE##_merge_sort_ (right_begin, fn_cmp); \ + return LTYPE##_merge_sort_merge_ (left_begin, right_begin, fn_cmp); \ +} + +/* Merge sort wrapper that the end-user should be using as it updates the + first and last metadata of the list in wrapper as well. + If the user does not want to pay the cost of the update of the data, + it can directly use _##LTYPE##_merge_sort_merge. */ +#define _MERGE_SORT_DEFN_WRAPPER_SORT(LWRAPPERTYPE, LTYPE, EXPORT) \ +EXPORT void \ +LTYPE##_merge_sort (LWRAPPERTYPE *wrapper, \ + int (*fn_cmp) (const LTYPE *, const LTYPE *)) \ +{ \ + wrapper->first = LTYPE##_merge_sort_ (wrapper->first, fn_cmp); \ + \ + if (wrapper->first == NULL || wrapper->first->next == NULL) \ + wrapper->last = wrapper->first; \ + else \ + for (LTYPE *node = wrapper->first; \ + node != NULL; \ + node = node->next) \ + wrapper->last = node; \ +} + +#define LINKED_LIST_MERGE_SORT_DECL(LWRAPPERTYPE, LTYPE, EXPORT) \ + _MERGE_SORT_IMPL_COMPUTE_TURTLE(LTYPE) \ + _MERGE_SORT_IMPL_OUT_APPEND(LTYPE) \ + _MERGE_SORT_IMPL_MERGE(LTYPE) \ + _MERGE_SORT_DEFN_SORT(LTYPE, EXPORT) \ + _MERGE_SORT_DEFN_WRAPPER_SORT(LWRAPPERTYPE, LTYPE, EXPORT) + +#endif /* _DOUBLY_LINKED_LIST_H */ diff --git a/libgcc/libgcc2.c b/libgcc/libgcc2.c index faefff3..df99c78 100644 --- a/libgcc/libgcc2.c +++ b/libgcc/libgcc2.c @@ -2187,36 +2187,21 @@ __fixunssfDI (SFtype a) if (a < 1) return 0; if (a < Wtype_MAXp1_F) - return (UWtype)a; + return (UWtype) a; if (a < Wtype_MAXp1_F * Wtype_MAXp1_F) { - /* Since we know that there are fewer significant bits in the SFmode - quantity than in a word, we know that we can convert out all the - significant bits in one step, and thus avoid losing bits. */ - - /* ??? This following loop essentially performs frexpf. If we could - use the real libm function, or poke at the actual bits of the fp - format, it would be significantly faster. */ - - UWtype shift = 0, counter; - SFtype msb; - - a /= Wtype_MAXp1_F; - for (counter = W_TYPE_SIZE / 2; counter != 0; counter >>= 1) - { - SFtype counterf = (UWtype)1 << counter; - if (a >= counterf) - { - shift |= counter; - a /= counterf; - } - } - - /* Rescale into the range of one word, extract the bits of that - one word, and shift the result into position. */ - a *= Wtype_MAXp1_F; - counter = a; - return (DWtype)counter << shift; + /* We assume that SFtype -> UWtype and UWtype -> UDWtype casts work + properly. Obviously, we *cannot* assume that SFtype -> UDWtype + works as expected. */ + SFtype a_hi, a_lo; + + a_hi = a / Wtype_MAXp1_F; + a_lo = a - a_hi * Wtype_MAXp1_F; + + /* A lot of parentheses. This is to make it very clear what is + the sequence of operations. */ + return ((UDWtype) ((UWtype) a_hi)) << W_TYPE_SIZE + | (UDWtype) ((UWtype) a_lo); } return -1; #else diff --git a/libgcobol/ChangeLog b/libgcobol/ChangeLog index e851b39..25ef409 100644 --- a/libgcobol/ChangeLog +++ b/libgcobol/ChangeLog @@ -1,3 +1,19 @@ +2025-07-09 Robert Dubner <rdubner@symas.com> + James K. Lowden <jklowden@cobolworx.com> + + * libgcobol.cc (__gg__accept_envar): ACCEPT/DISPLAY environment variables. + (accept_envar): Likewise. + (default_exception_handler): Refine system log entries. + (open_syslog): Likewise. + (__gg__set_env_name): ACCEPT/DISPLAY environment variables. + (__gg__get_env_name): ACCEPT/DISPLAY environment variables. + (__gg__get_env_value): ACCEPT/DISPLAY environment variables. + (__gg__set_env_value): ACCEPT/DISPLAY environment variables. + (__gg__fprintf_stderr): Adjust __attribute__ for printf. + (__gg__set_arg_num): ACCEPT/DISPLAY command-line arguments. + (__gg__accept_arg_value): ACCEPT/DISPLAY command-line arguments. + (__gg__get_file_descriptor): DISPLAY on os_filename[] /dev device. + 2025-06-20 James K. Lowden <jklowden@cobolworx.com> * LICENSE: New file. diff --git a/libgcobol/common-defs.h b/libgcobol/common-defs.h index a78022a..a3884fd 100644 --- a/libgcobol/common-defs.h +++ b/libgcobol/common-defs.h @@ -589,7 +589,7 @@ class cbl_enabled_exceptions_t : protected std::set<cbl_enabled_exception_t> cbl_enabled_exceptions_t& operator=( const cbl_enabled_exceptions_t& ) = default; }; -extern cbl_enabled_exceptions_t enabled_exceptions; +cbl_enabled_exceptions_t& cdf_enabled_exceptions(); template <typename T> T enabled_exception_match( T beg, T end, ec_type_t type, size_t file ) { diff --git a/libgcobol/libgcobol.cc b/libgcobol/libgcobol.cc index 81b5b7a..c3d78d4 100644 --- a/libgcobol/libgcobol.cc +++ b/libgcobol/libgcobol.cc @@ -10132,49 +10132,45 @@ __gg__classify( classify_t type, return retval; } -extern "C" +static int -__gg__accept_envar( cblc_field_t *tgt, - size_t tgt_offset, - size_t tgt_length, - cblc_field_t *name, - size_t name_offset, - size_t name_length) +accept_envar( cblc_field_t *tgt, + size_t tgt_offset, + size_t tgt_length, + const char *psz_name) { - int retval; - tgt_length = tgt_length ? tgt_length : tgt->capacity; - name_length = name_length ? name_length : name->capacity; - - // Pick up the environment variable name, which is in teh internal codeset - static char *env = NULL; - static size_t env_length = 0; - if( env_length < name_length+1 ) + int retval = 1; // 1 means we couldn't find it + if( psz_name ) { - env_length = name_length+1; - env = static_cast<char *>(realloc(env, env_length)); - } - memcpy(env, name->data + name_offset, name_length); - env[name_length] = '\0'; + tgt_length = tgt_length ? tgt_length : tgt->capacity; - // Get rid of leading and trailing internal_space characters: - char *trimmed_env = brute_force_trim(env); + // Pick up the environment variable name, which is in the internal codeset + char *env = strdup(psz_name); + massert(env); - // Convert the name to the console codeset: - __gg__internal_to_console_in_place(trimmed_env, strlen(trimmed_env)); + // Get rid of leading and trailing internal_space characters: + char *trimmed_env = brute_force_trim(env); - // Pick up the environment variable, and convert it to the internal codeset - const char *p = getenv(trimmed_env); - if(p) - { - char *pp = strdup(p); - console_to_internal(pp, strlen(pp)); - retval = 0; // Okay - move_string(tgt, tgt_offset, tgt_length, pp); - free(pp); + // Convert the name to the console codeset: + __gg__internal_to_console_in_place(trimmed_env, strlen(trimmed_env)); + + // Pick up the environment variable, and convert it to the internal codeset + const char *p = getenv(trimmed_env); + if(p) + { + char *pp = strdup(p); + massert(pp); + console_to_internal(pp, strlen(pp)); + retval = 0; // Okay + move_string(tgt, tgt_offset, tgt_length, pp); + free(pp); + } + free(env); } - else + + if( retval == 1 ) { - retval = 1; // Could't find it + // Could't find it exception_raise(ec_argument_imp_environment_e); } @@ -10182,6 +10178,28 @@ __gg__accept_envar( cblc_field_t *tgt, } extern "C" +int +__gg__accept_envar( cblc_field_t *tgt, + size_t tgt_offset, + size_t tgt_length, + const cblc_field_t *name, + size_t name_offset, + size_t name_length) + { + // We need the name to be nul-terminated: + char *p = static_cast<char *>(malloc(name_length + 1)); + massert(p); + memcpy(p, name->data+name_offset, name_length); + p[name_length] = '\0'; + int retval = accept_envar(tgt, + tgt_offset, + tgt_length, + p); + free(p); + return retval; + } + +extern "C" bool __gg__set_envar(cblc_field_t *name, size_t name_offset, @@ -11247,35 +11265,42 @@ match_declarative( bool enabled, return matches; } -/* - * The default exception handler is called if: - * 1. The EC is enabled and was not handled by a Declarative, or - * 2. The EC is EC-I-O and was not handled by a Format-1 Declarative, or - * 3. The EC is EC-I-O, associated with a file, and is not OPEN or CLOSE. - */ -static void -default_exception_handler( ec_type_t ec ) +static +void open_syslog(int option, int facility) { + static bool first_time = true; + if( first_time ) { #if HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME /* Declared in errno.h, when available. */ - static const char * const ident = program_invocation_short_name; + static const char * const ident = program_invocation_short_name; #elif defined (HAVE_GETPROGNAME) /* Declared in stdlib.h. */ - static const char * const ident = getprogname(); + static const char * const ident = getprogname(); #else /* Avoid a NULL entry. */ - static const char * const ident = "unnamed_COBOL_program"; + static const char * const ident = "unnamed_COBOL_program"; #endif - static bool first_time = true; - static const int priority = LOG_INFO, option = LOG_PERROR, facility = LOG_USER; - ec_disposition_t disposition = ec_category_fatal_e; - - if( first_time ) { // TODO: Program to set option in library via command-line and/or environment. // Library listens to program, not to the environment. openlog(ident, option, facility); first_time = false; } +} + +/* + * The default exception handler is called if: + * 1. The EC is enabled and was not handled by a Declarative, or + * 2. The EC is EC-I-O and was not handled by a Format-1 Declarative, or + * 3. The EC is EC-I-O, associated with a file, and is not OPEN or CLOSE. + */ +static void +default_exception_handler( ec_type_t ec ) +{ + static const int priority = LOG_INFO, option = LOG_PERROR, facility = LOG_USER; + open_syslog(option, facility); + + ec_disposition_t disposition = ec_category_fatal_e; + if( ec != ec_none_e ) { auto pec = std::find_if( __gg__exception_table, __gg__exception_table_end, @@ -13149,6 +13174,7 @@ operator<<( std::vector<cbl_declarative_t>& dcls, } // The first element of each array is the number of elements that follow +// The first element of each array is the number of elements that follow extern "C" void __gg__set_exception_environment( uint64_t *ecs, uint64_t *dcls ) @@ -13207,6 +13233,7 @@ __gg__set_env_name( const cblc_field_t *var, size_t offset, size_t length ) { + // implements DISPLAY UPON ENVIRONMENT-NAME free(sv_envname); sv_envname = static_cast<char *>(malloc(length+1)); massert(sv_envname); @@ -13214,12 +13241,41 @@ __gg__set_env_name( const cblc_field_t *var, sv_envname[length] = '\0'; } + +extern "C" +void +__gg__get_env_name( cblc_field_t *dest, + size_t dest_offset, + size_t dest_length) + { + // Implements ACCEPT FROM ENVIRONMENT-NAME + // It returns the value previously established by __gg__set_env_name. + if( sv_envname ) + { + sv_envname = strdup(""); + } + move_string(dest, dest_offset, dest_length, sv_envname); + } + +extern "C" +int +__gg__get_env_value(cblc_field_t *dest, + size_t dest_offset, + size_t dest_length) + { + return accept_envar(dest, + dest_offset, + dest_length, + sv_envname); + } + extern "C" void __gg__set_env_value(const cblc_field_t *value, size_t offset, size_t length ) { + // implements DISPLAY UPON ENVIRONMENT-VALUE size_t name_length = strlen(sv_envname); size_t value_length = length; @@ -13261,6 +13317,11 @@ __gg__set_env_value(const cblc_field_t *value, extern "C" void __gg__fprintf_stderr(const char *format_string, ...) + __attribute__ ((__format__ (__printf__, 1, 2))); + +extern "C" +void +__gg__fprintf_stderr(const char *format_string, ...) { /* This routine allows the compiler to send stuff to stderr in a way that is straightforward to use.. */ @@ -13270,3 +13331,81 @@ __gg__fprintf_stderr(const char *format_string, ...) va_end(ap); } + +static int sv_argument_number = 0; + +extern "C" +void +__gg__set_arg_num( const cblc_field_t *index, + size_t index_offset, + size_t index_size ) + { + // Implements DISPLAY UPON ARGUMENT-NUMBER. + int rdigits; + __int128 N = get_binary_value_local(&rdigits, + index, + index->data + index_offset, + index_size); + // If he gives us fractional digits, just truncate + N /= __gg__power_of_ten(rdigits); + + // N is 1-based, per normal COBOL. We have to decrement it here: + N -= 1; + sv_argument_number = static_cast<int>(N); + } + +extern "C" +int +__gg__accept_arg_value( cblc_field_t *dest, + size_t dest_offset, + size_t dest_length) + { + // Implements ACCEPT FROM ARGUMENT-VALUE + int retcode; + command_line_plan_b(); + if( sv_argument_number >= stashed_argc || sv_argument_number < 0 ) + { + exception_raise(ec_argument_imp_command_e); + retcode = 1; // Error + } + else + { + char *retval = strdup(stashed_argv[sv_argument_number]); + console_to_internal(retval, strlen(retval)); + move_string(dest, dest_offset, dest_length, retval); + free(retval); + retcode = 0; // Okay + + // The Fujitsu spec says bump this value by one. + sv_argument_number += 1; + } + return retcode; + } + +extern "C" +int +__gg__get_file_descriptor(const char *device) + { + int retval = open(device, O_WRONLY); + + if( retval == -1 ) + { + char *msg; + int ec = asprintf(&msg, + "Trying to open %s. Got error %s", + device, + strerror(errno)); + if( ec != -1 ) + { + static const int priority = LOG_INFO, + option = LOG_PERROR, + facility = LOG_USER; + open_syslog(option, facility); + syslog(priority, "%s", msg); + } + + // Open a new handle to /dev/stdout, since our caller will be closing it + retval = open("/dev/stdout", O_WRONLY); + } + return retval; + } diff --git a/libgo/go/syscall/socket.go b/libgo/go/syscall/socket.go index 54a4a99..35665d5 100644 --- a/libgo/go/syscall/socket.go +++ b/libgo/go/syscall/socket.go @@ -467,7 +467,7 @@ func Sendto(fd int, p []byte, flags int, to Sockaddr) (err error) { func recvmsgRaw(fd int, p, oob []byte, flags int, rsa *RawSockaddrAny) (n, oobn int, recvflags int, err error) { var msg Msghdr - msg.Name = (*byte)(unsafe.Pointer(&rsa)) + msg.Name = (*byte)(unsafe.Pointer(rsa)) msg.Namelen = uint32(SizeofSockaddrAny) var iov Iovec if len(p) > 0 { diff --git a/libgo/runtime/go-memclr.c b/libgo/runtime/go-memclr.c index 53b8117..84df98d 100644 --- a/libgo/runtime/go-memclr.c +++ b/libgo/runtime/go-memclr.c @@ -11,50 +11,39 @@ void memclrNoHeapPointers(void *, uintptr) __attribute__ ((no_split_stack)); void -memclrNoHeapPointers (void *p1, uintptr len) +memclrNoHeapPointers(void *p1, uintptr len) { - -#if !defined(__PPC64__) - __builtin_memset(p1, 0, len); -#else - int64 rem,drem,i; - uint64 offset; - volatile uint64 *vp; + const uintptr ptr_size = sizeof(p1); + uintptr rem,drem,i; + uintptr offset; + volatile uintptr *vp; if (len == 0) { return; } rem = len; - offset = (uint64)p1 % 8; - // This memset is OK since it can't contain - // an 8 byte aligned pointer. - if ((rem < 8) || (offset > 0 && offset+rem <= 16)) { + offset = (uintptr)p1 % ptr_size; + if (rem < ptr_size || offset > 0) { + // This memset is OK since it can't contain + // an pointer aligned pointer. __builtin_memset(p1, 0, rem); return; } - // Move initial bytes to get to 8 byte boundary - if (offset > 0) { - __builtin_memset(p1, 0, 8-offset); - p1 = (void*)((char*)p1+8-offset); - rem -= 8-offset; - } - // If at least 8 bytes left, clear - drem = rem>>3; + drem = rem / ptr_size; - vp = (volatile uint64*)(p1); + vp = (volatile uintptr*)(p1); // Without the use of volatile here, the compiler // might convert the loop into a memset. for (i=0; i<drem; i++) { *vp = 0; vp++; - rem -= 8; + rem -= ptr_size; } - p1 = (void*)((char*)p1 + 8*drem); - // Clear any remaining + // Clear any remaining bytes. if (rem > 0) { - __builtin_memset (p1, 0, rem); + p1 = (void*)((char*)p1 + ptr_size*drem); + __builtin_memset(p1, 0, rem); } -#endif } diff --git a/libgo/runtime/go-memmove.c b/libgo/runtime/go-memmove.c index 1ca3f48..1dbd2b3 100644 --- a/libgo/runtime/go-memmove.c +++ b/libgo/runtime/go-memmove.c @@ -12,78 +12,60 @@ void gomemmove(void *, void *, uintptr) // This implementation is necessary since // the __builtin_memmove might use __libc_memmove -// which doesn't require atomicity of 8 byte +// which doesn't require atomicity of pointer-sized // moves. void -gomemmove (void *dst, void *src, uintptr len) +gomemmove(void *dst, void *src, uintptr len) { -#if !defined(__PPC64__) - __builtin_memmove(dst, src, len); -#else - uint64 offset, tail; - int64 rem; - uint64 dwords; - uint64 i; - char *bdst,*bsrc; - - rem = len; + const uintptr ptr_size = sizeof(dst); + uintptr tail; + uintptr rem; + uintptr dwords; + uintptr i; + char *bdst, *bsrc; if (len == 0) { - return; + return; } - // If src and dst don't have the same 8 byte alignment then - // there is no issue with copying pointer atomicity. Use the - // builtin. - if (((uint64)dst % 8) != ((uint64)src % 8) || len < 8) { - __builtin_memmove(dst, src, len); - return; + // We expect pointer-containing values to be pointer-aligned. + // If these pointers are not aligned, they don't contain pointers. + if ((uintptr)dst % ptr_size != 0 || (uintptr)src % ptr_size != 0 || len < ptr_size) { + __builtin_memmove(dst, src, len); + return; } - // Length >= 8 && same ptr alignment - offset = (uint64)dst % 8; - - // If not 8 byte alignment, move the intial bytes. - if (offset > 0) { - __builtin_memmove(dst, src, 8-offset); - dst += (8-offset); - src += (8-offset); - rem -= (8-offset); - } + bdst = (char*)dst; + bsrc = (char*)src; - // Move the tail bytes to make the backward move - // easier. - tail = rem % 8; + // Move the tail bytes to make the backward move easier. + rem = len; + tail = rem % ptr_size; if (tail > 0) { - __builtin_memmove(dst+rem-tail, src+rem-tail, tail); - rem -= tail; - } - - if (rem == 0) { - return; + __builtin_memmove(bdst+rem-tail, bsrc+rem-tail, tail); + rem -= tail; } - // Must now be 8 byte alignment and rem is multiple of 8. - dwords = len>>3; + // Must now be pointer alignment and rem is multiple of ptr_size. + dwords = rem / ptr_size; - // Determine if a backwards move is needed - // Forward or backward, move all doublewords + // Determine if a backwards move is needed. + // Forward or backward, move all words. - if ((uint64)(dst - src) < (uint64)rem) { - bdst = dst+rem-8; - bsrc = src+rem-8; - for (i = 0; i<dwords; i++) { - *(uint64*)bdst = *(uint64*)bsrc; - bdst -= 8; - bsrc -= 8; - } + if ((uintptr)(bdst - bsrc) < rem) { + bdst += rem - ptr_size; + bsrc += rem - ptr_size; + for (i = 0; i<dwords; i++) { + *(uintptr*)bdst = *(uintptr*)bsrc; + bdst -= ptr_size; + bsrc -= ptr_size; + } } else { - for (i = 0; i<dwords; i++) { - *(uint64*)dst = *(uint64*)src; - dst += 8; - src += 8; - } + for (i = 0; i<dwords; i++) { + *(uintptr*)bdst = *(uintptr*)bsrc; + bdst += ptr_size; + bsrc += ptr_size; + } } -#endif } diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog index 2ae5626..cf90917 100644 --- a/libiberty/ChangeLog +++ b/libiberty/ChangeLog @@ -1,3 +1,9 @@ +2025-07-09 Matthieu Longo <matthieu.longo@arm.com> + + * Makefile.in: Add new header. + * testsuite/Makefile.in: Add new test. + * testsuite/test-doubly-linked-list.c: New test. + 2025-05-13 Andreas Schwab <schwab@suse.de> * regex.c (regex_compile): Don't write beyond array bounds when diff --git a/libiberty/Makefile.in b/libiberty/Makefile.in index ce54d88..e4d7d0a 100644 --- a/libiberty/Makefile.in +++ b/libiberty/Makefile.in @@ -237,6 +237,7 @@ CONFIGURED_OFILES = ./asprintf.$(objext) ./atexit.$(objext) \ INSTALLED_HEADERS = \ $(INCDIR)/ansidecl.h \ $(INCDIR)/demangle.h \ + $(INCDIR)/doubly-linked-list.h \ $(INCDIR)/dyn-string.h \ $(INCDIR)/fibheap.h \ $(INCDIR)/floatformat.h \ diff --git a/libiberty/testsuite/Makefile.in b/libiberty/testsuite/Makefile.in index 2b0883c..ef549ca 100644 --- a/libiberty/testsuite/Makefile.in +++ b/libiberty/testsuite/Makefile.in @@ -45,7 +45,8 @@ all: check: @CHECK@ really-check: check-cplus-dem check-d-demangle check-rust-demangle \ - check-pexecute check-expandargv check-strtol + check-pexecute check-expandargv check-strtol \ + check-doubly-linked-list # Run some tests of the demangler. check-cplus-dem: test-demangle $(srcdir)/demangle-expected @@ -69,6 +70,10 @@ check-expandargv: test-expandargv check-strtol: test-strtol ./test-strtol +# Check the linked list functionality +check-doubly-linked-list: test-doubly-linked-list + ./test-doubly-linked-list + # Run the demangler fuzzer fuzz-demangler: demangler-fuzzer ./demangler-fuzzer @@ -90,6 +95,10 @@ test-strtol: $(srcdir)/test-strtol.c ../libiberty.a $(TEST_COMPILE) -DHAVE_CONFIG_H -I.. -o test-strtol \ $(srcdir)/test-strtol.c ../libiberty.a +test-doubly-linked-list: $(srcdir)/test-doubly-linked-list.c + $(TEST_COMPILE) -DHAVE_CONFIG_H -I.. -o test-doubly-linked-list \ + $(srcdir)/test-doubly-linked-list.c + demangler-fuzzer: $(srcdir)/demangler-fuzzer.c ../libiberty.a $(TEST_COMPILE) -o demangler-fuzzer \ $(srcdir)/demangler-fuzzer.c ../libiberty.a @@ -104,6 +113,7 @@ mostlyclean: rm -f test-pexecute rm -f test-expandargv rm -f test-strtol + rm -f test-doubly-linked-list rm -f demangler-fuzzer rm -f core clean: mostlyclean diff --git a/libiberty/testsuite/test-doubly-linked-list.c b/libiberty/testsuite/test-doubly-linked-list.c new file mode 100644 index 0000000..1e1fc63 --- /dev/null +++ b/libiberty/testsuite/test-doubly-linked-list.c @@ -0,0 +1,269 @@ +#include <stdbool.h> +#include <stdlib.h> +#include <stdio.h> + +#include "doubly-linked-list.h" + +#ifndef EXIT_SUCCESS +#define EXIT_SUCCESS 0 +#endif + +#ifndef EXIT_FAILURE +#define EXIT_FAILURE 1 +#endif + +/* Implementation */ + +typedef int T; + +typedef struct ListNodeType +{ + T value; + struct ListNodeType *next; + struct ListNodeType *prev; +} ListNodeType; + +ListNodeType * l_new_node (T value) +{ + ListNodeType *n = malloc (sizeof (ListNodeType)); + n->next = NULL; + n->prev = NULL; + n->value = value; + return n; +} + +typedef struct LinkedListWrapperType +{ + ListNodeType *first; + ListNodeType *last; + size_t size; +} LinkedListWrapperType; + +int compare_nodes (const ListNodeType *n1, const ListNodeType *n2) +{ + if (n1->value == n2->value) + return 0; + else if (n1->value < n2->value) + return -1; + else + return 1; +} + +LINKED_LIST_MUTATIVE_OPS_PROTOTYPE (LinkedListWrapperType, ListNodeType, static); +LINKED_LIST_MERGE_SORT_PROTOTYPE (LinkedListWrapperType, ListNodeType, static); + +LINKED_LIST_MUTATIVE_OPS_DECL (LinkedListWrapperType, ListNodeType, static) +LINKED_LIST_MERGE_SORT_DECL (LinkedListWrapperType, ListNodeType, static) + +ListNodeType * find_last_node (ListNodeType *head) +{ + if (head == NULL) + return NULL; + + ListNodeType *n = head; + while (n->next != NULL) + n = n->next; + + return n; +} + +void l_print (ListNodeType *node) +{ + for (ListNodeType *l = node; l != NULL; l = l->next) + printf ("%d ", l->value); + printf ("\n"); +} + +void l_reverse_print (ListNodeType *last_node) +{ + for (ListNodeType *l = last_node; l != NULL; l = l->prev) + printf ("%d ", l->value); + printf ("\n"); +} + +struct test_data_t +{ + T const *content; + size_t size; +}; + +bool run_test (const struct test_data_t *expect, + LinkedListWrapperType *current, + bool reversed) +{ + ListNodeType *node = (reversed) ? current->last : current->first; + bool passed = true; + for (int i=0; i<expect->size && node != NULL; ++i) + { + if (reversed) + { + if (expect->content[expect->size - 1 - i] != node->value) + { + printf ("FAIL: mismatching expected (%d) VS current (%d).\n", + expect->content[expect->size - 1 - i], node->value); + passed = false; + } + if (node->prev == NULL && current->first != node) + { + printf ("FAIL: first is not matching the first node.\n"); + passed = false; + } + } + else + { + if (expect->content[i] != node->value) + { + printf ("FAIL: mismatching expected (%d) VS current (%d).\n", + expect->content[i], node->value); + passed = false; + } + if (node->next == NULL && current->last != node) + { + printf ("FAIL: last_ is not matching the last node.\n"); + passed = false; + } + } + + if (!passed) + return false; + + if (reversed) + node = node->prev; + else + node = node->next; + } + + if (node != NULL) + { + printf ("FAIL: the list is longer than expected.\n"); + passed = false; + } + if (expect->size != current->size) + { + printf ("FAIL: size (%ld) is not matching the real size of the list (%ld).\n", + current->size, expect->size); + passed = false; + } + + return passed; +} + +bool check(const char *op, + const struct test_data_t *expect, + LinkedListWrapperType *wrapper) +{ + bool success = true; + bool res; + + l_print (wrapper->first); + res = run_test (expect, wrapper, false); + printf ("%s: test-linked-list::%s: check forward conformity\n", + res ? "PASS": "FAIL", op); + success &= res; + + l_reverse_print (wrapper->last); + res = run_test (expect, wrapper, true); + printf ("%s: test-linked-list::%s: check backward conformity\n", + res ? "PASS": "FAIL", op); + success &= res; + + printf("\n"); + + return success; +} + +const int EXPECT_0 [] = { 10, 4, 3, 1, 9, 2 }; +const int EXPECT_1 [] = { 1, 2, 3, 4, 9, 10 }; +const int EXPECT_2 [] = { 11, 1, 2, 3, 4, 9, 10 }; +const int EXPECT_3 [] = { 11, 1, 2, 3, 4, 9, 8, 10 }; +const int EXPECT_4 [] = { 11, 2, 3, 4, 9, 8, 10 }; +const int EXPECT_5 [] = { 10, 2, 3, 4, 9, 8, 11 }; +const int EXPECT_6 [] = { 10, 3, 2, 4, 9, 8, 11 }; +const int EXPECT_7 [] = { 10, 9, 2, 4, 3, 8, 11 }; +const int EXPECT_8 [] = { 2, 3, 4, 8, 9, 10, 11 }; +const int EXPECT_9 [] = { 3, 4, 8, 9, 10, 11 }; +const int EXPECT_10 [] = { 3, 4, 8, 9, 10 }; +const struct test_data_t test_data[] = { + { .content = EXPECT_0, .size = sizeof(EXPECT_0) / sizeof(EXPECT_0[0]) }, + { .content = EXPECT_1, .size = sizeof(EXPECT_1) / sizeof(EXPECT_1[0]) }, + { .content = EXPECT_2, .size = sizeof(EXPECT_2) / sizeof(EXPECT_2[0]) }, + { .content = EXPECT_3, .size = sizeof(EXPECT_3) / sizeof(EXPECT_3[0]) }, + { .content = EXPECT_4, .size = sizeof(EXPECT_4) / sizeof(EXPECT_4[0]) }, + { .content = EXPECT_5, .size = sizeof(EXPECT_5) / sizeof(EXPECT_5[0]) }, + { .content = EXPECT_6, .size = sizeof(EXPECT_6) / sizeof(EXPECT_6[0]) }, + { .content = EXPECT_7, .size = sizeof(EXPECT_7) / sizeof(EXPECT_7[0]) }, + { .content = EXPECT_8, .size = sizeof(EXPECT_8) / sizeof(EXPECT_8[0]) }, + { .content = EXPECT_9, .size = sizeof(EXPECT_9) / sizeof(EXPECT_9[0]) }, + { .content = EXPECT_10, .size = sizeof(EXPECT_10) / sizeof(EXPECT_10[0]) }, +}; + +int main (void) +{ + int failures = 0; + + LinkedListWrapperType wrapper = { + .first = NULL, + .last = NULL, + .size = 0, + }; + + /* Append nodes. */ + LINKED_LIST_APPEND(ListNodeType) (&wrapper, l_new_node (10)); + LINKED_LIST_APPEND(ListNodeType) (&wrapper, l_new_node (4)); + LINKED_LIST_APPEND(ListNodeType) (&wrapper, l_new_node (3)); + LINKED_LIST_APPEND(ListNodeType) (&wrapper, l_new_node (1)); + LINKED_LIST_APPEND(ListNodeType) (&wrapper, l_new_node (9)); + LINKED_LIST_APPEND(ListNodeType) (&wrapper, l_new_node (2)); + + failures += ! check ("append", &test_data[0], &wrapper); + + /* Sort nodes (without updating wrapper). */ + wrapper.first = + LINKED_LIST_MERGE_SORT_(ListNodeType) (wrapper.first, compare_nodes); + wrapper.last = find_last_node (wrapper.first); + + failures += ! check ("sort", &test_data[1], &wrapper); + + /* Save a reference to this node for later. */ + ListNodeType *n_to_remove = wrapper.first; + + /* Prepend node. */ + LINKED_LIST_PREPEND(ListNodeType) (&wrapper, l_new_node (11)); + failures += ! check ("prepend", &test_data[2], &wrapper); + + /* Insert node. */ + LINKED_LIST_INSERT_BEFORE(ListNodeType) (&wrapper, l_new_node (8), wrapper.last); + failures += ! check ("insert_before", &test_data[3], &wrapper); + + /* Remove a node. */ + LINKED_LIST_REMOVE(ListNodeType) (&wrapper, n_to_remove); + failures += ! check ("remove", &test_data[4], &wrapper); + + /* Swap first and last. */ + LINKED_LIST_SWAP(ListNodeType) (&wrapper, wrapper.first, wrapper.last); + failures += ! check ("swap first and last", &test_data[5], &wrapper); + + /* Swap adjacent nodes. */ + LINKED_LIST_SWAP(ListNodeType) (&wrapper, wrapper.first->next, + wrapper.first->next->next); + failures += ! check ("swap adjacent nodes", &test_data[6], &wrapper); + + /* Swap non-adjacent nodes, but neither first nor last. */ + LINKED_LIST_SWAP(ListNodeType) (&wrapper, wrapper.first->next, + wrapper.first->next->next->next->next); + failures += ! check ("swap non-adjacent nodes", &test_data[7], &wrapper); + + /* Sort nodes. */ + LINKED_LIST_MERGE_SORT(ListNodeType) (&wrapper, compare_nodes); + failures += ! check ("sort", &test_data[8], &wrapper); + + /* Pop front. */ + LINKED_LIST_POP_FRONT(ListNodeType) (&wrapper); + failures += ! check ("pop_front", &test_data[9], &wrapper); + + /* Pop back. */ + LINKED_LIST_POP_BACK(ListNodeType) (&wrapper); + failures += ! check ("pop_back", &test_data[10], &wrapper); + + exit (failures ? EXIT_FAILURE : EXIT_SUCCESS); +} diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 77333e4..8abb719 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,294 @@ +2025-07-09 Jonathan Wakely <jwakely@redhat.com> + + * include/bits/stl_uninitialized.h (__uninitialized_default): + Do not use optimized implementation for constexpr case. Use + _GLIBCXX20_CONSTEXPR instead of _GLIBCXX26_CONSTEXPR. + +2025-07-09 Jonathan Wakely <jwakely@redhat.com> + + * include/std/mdspan (mdspan): Add template keyword for + dependent name. + +2025-07-09 Jonathan Wakely <jwakely@redhat.com> + + PR libstdc++/120997 + * include/std/span (span::first, span::last, span::subspan): Do + not use braced-init-list for return statements. + * testsuite/23_containers/span/120997.cc: New test. + +2025-07-09 Paul Keir <pkeir@outlook.com> + + PR libstdc++/117403 + * include/bits/shared_ptr.h (shared_ptr::owner_equal) + (shared_ptr::owner_hash, weak_ptr::owner_equal) + (weak_ptr::owner_hash): Define new member functions. + * include/bits/shared_ptr_base.h (owner_equal, owner_hash): + Define new structs. + * include/bits/version.def (smart_ptr_owner_equality): Define. + * include/bits/version.h: Regenerate. + * include/std/memory: Added define for + __glibcxx_want_smart_ptr_owner_equality. + * testsuite/20_util/owner_equal/version.cc: New test. + * testsuite/20_util/owner_equal/cmp.cc: New test. + * testsuite/20_util/owner_equal/noexcept.cc: New test. + * testsuite/20_util/owner_hash/cmp.cc: New test. + * testsuite/20_util/owner_hash/noexcept.cc: New test. + * testsuite/20_util/shared_ptr/observers/owner_equal.cc: New + test. + * testsuite/20_util/shared_ptr/observers/owner_hash.cc: + New test. + * testsuite/20_util/weak_ptr/observers/owner_equal.cc: New test. + * testsuite/20_util/weak_ptr/observers/owner_hash.cc: New test. + +2025-07-09 Mateusz Zych <mte.zych@gmail.com> + + * include/bits/max_size_type.h (numeric_limits<__max_size_type>): + New members. + (numeric_limits<__max_diff_type>): Likewise. + * testsuite/std/ranges/iota/max_size_type.cc: New test cases. + +2025-07-09 Jonathan Wakely <jwakely@redhat.com> + + * src/c++17/memory_resource.cc: Adjust indentation of unnamed + namespaces. + (pool_sizes): Add comment. + (choose_block_size): Move outside preprocessor group for + gthreads targets. + * testsuite/20_util/synchronized_pool_resource/118681.cc: + Require gthreads. + +2025-07-09 H.J. Lu <hjl.tools@gmail.com> + + * config/abi/post/x86_64-linux-gnu/x32/baseline_symbols.txt: + Updated. + +2025-07-08 Jonathan Wakely <jwakely@redhat.com> + + PR libstdc++/118681 + * testsuite/20_util/unsynchronized_pool_resource/118681.cc: Fix + deallocate argument. + +2025-07-08 Jonathan Wakely <jwakely@redhat.com> + + PR libstdc++/118681 + * src/c++17/memory_resource.cc (choose_block_size): New + function. + (synchronized_pool_resource::do_allocate): Use choose_block_size + to determine appropriate block size. + (synchronized_pool_resource::do_deallocate): Likewise + (unsynchronized_pool_resource::do_allocate): Likewise. + (unsynchronized_pool_resource::do_deallocate): Likewise + * testsuite/20_util/synchronized_pool_resource/118681.cc: New + test. + * testsuite/20_util/unsynchronized_pool_resource/118681.cc: New + test. + +2025-07-08 Jonathan Wakely <jwakely@redhat.com> + + * include/debug/forward_list (_Safe_forward_list<>::_M_swap): + Adapt to _M_this() signature change. + +2025-07-08 Tomasz Kamiński <tkaminsk@redhat.com> + + PR libstdc++/119861 + * include/std/format (formatter<_Rg, _CharT>::set_separator) + (formatter<_Rg, _CharT>::set_brackets): Constrain with + (format_kind<_Rg> == range_format::sequence). + * testsuite/std/format/ranges/pr119861_neg.cc: New test. + +2025-07-08 Luc Grosheintz <luc.grosheintz@gmail.com> + + PR libstdc++/120914 + * include/std/span (span): Update CTAD to enable + integral constants [P3029R1]. + * include/std/mdspan (extents): ditto. + (mdspan): ditto. + * testsuite/23_containers/span/deduction.cc: Test deduction + guide. + * testsuite/23_containers/mdspan/extents/misc.cc: ditto. + * testsuite/23_containers/mdspan/mdspan.cc: ditto. + +2025-07-08 Luc Grosheintz <luc.grosheintz@gmail.com> + + * testsuite/23_containers/span/contiguous_range_neg.cc: Silence + warning about unused variable myspan. + +2025-07-08 Luc Grosheintz <luc.grosheintz@gmail.com> + + PR libstdc++/107761 + * include/bits/version.def (mdspan): Set to 202207 and remove + no_stdname. + * include/bits/version.h: Regenerate. + * testsuite/23_containers/mdspan/version.cc: Test presence + of feature test macro. + +2025-07-08 Luc Grosheintz <luc.grosheintz@gmail.com> + + PR libstdc++/107761 + * include/std/mdspan (mdspan): New class. + * src/c++23/std.cc.in (mdspan): Add. + * testsuite/23_containers/mdspan/class_mandate_neg.cc: New test. + * testsuite/23_containers/mdspan/mdspan.cc: New test. + * testsuite/23_containers/mdspan/layout_like.h: Add class + LayoutLike which models a user-defined layout. + * testsuite/23_containers/mdspan/out_of_bounds_neg.cc: New file. + +2025-07-08 Luc Grosheintz <luc.grosheintz@gmail.com> + + * include/std/mdspan (__mdspan::__size): New function. + +2025-07-08 Luc Grosheintz <luc.grosheintz@gmail.com> + + * testsuite/23_containers/mdspan/extents/custom_integer.cc: + Delete IntLike and include "int_like.h". + * testsuite/23_containers/mdspan/extents/int_like.h: Add + IntLike. + +2025-07-08 Luc Grosheintz <luc.grosheintz@gmail.com> + + * include/std/mdspan (extents): Check prerequisite of the ctor that + static_extent(i) == dynamic_extent || extent(i) == other.extent(i). + * testsuite/23_containers/mdspan/extents/class_mandates_neg.cc: + Test the implemented prerequisite. + * testsuite/23_containers/mdspan/extents/extents_mismatch_neg.cc: New file. + +2025-07-08 Luc Grosheintz <luc.grosheintz@gmail.com> + + * include/std/mdspan: Check prerequisites of + layout_*::operator() with _GLIBCXX_DEBUG_ASSERTs. + * testsuite/23_containers/mdspan/layouts/debug/out_of_bounds_neg.cc: + Add tests for prerequisites. + +2025-07-08 Tomasz Kamiński <tkaminsk@redhat.com> + + * include/std/queue (formatter<queue<_Tp, _Container>, _CharT>) + (formatter<priority_queue<_Tp, _Container, _Compare>, _CharT>): + Add _GLIBCXX_RESOLVE_LIB_DEFECTS comments. + +2025-07-08 François Dumont <frs.dumont@gmail.com> + + PR c++/116369 + * config/abi/pre/gnu-versioned-namespace.ver: Use new const qualified symbols. + * config/abi/pre/gnu.ver: Add new const qualified symbols. + * include/debug/safe_base.h + (_Safe_iterator_base::_M_sequence): Declare as pointer-to-const. + (_Safe_iterator_base::_M_attach, _M_attach_single): New, take pointer-to-const + _Safe_sequence_base. + (_Safe_sequence_base::_M_detach_all, _M_detach_singular, _M_revalidate_singular) + (_M_swap, _M_get_mutex): New, const qualified. + (_Safe_sequence_base::_M_attach, _M_attach_single, _M_detach, _M_detach_single): + const qualify. + * include/debug/safe_container.h (_Safe_container<>::_M_cont): Add const qualifier. + (_Safe_container<>::_M_swap_base): New. + (_Safe_container(_Safe_container&&, const _Alloc&, std::false_type)): + Adapt to use latter. + (_Safe_container<>::operator=(_Safe_container&&)): Likewise. + (_Safe_container<>::_M_swap): Likewise and take parameter as const reference. + * include/debug/safe_unordered_base.h + (_Safe_local_iterator_base::_M_safe_container): New. + (_Safe_local_iterator_base::_Safe_local_iterator_base): Take + _Safe_unordered_container_base as pointer-to-const. + (_Safe_unordered_container_base::_M_attach, _M_attach_single): New, take + container as _Safe_unordered_container_base pointer-to-const. + (_Safe_unordered_container_base::_M_local_iterators, _M_const_local_iterators): + Add mutable. + (_Safe_unordered_container_base::_M_detach_all, _M_swap): New, const qualify. + (_Safe_unordered_container_base::_M_attach_local, _M_attach_local_single) + (_M_detach_local, _M_detach_local_single): Add const qualifier. + * include/debug/safe_unordered_container.h (_Safe_unordered_container::_M_self()): New. + * include/debug/safe_unordered_container.tcc + (_Safe_unordered_container::_M_invalidate_if, _M_invalidated_local_if): Use latter. + * include/debug/safe_iterator.h (_Safe_iterator<>::_M_attach, _M_attach_single): + Take _Safe_sequence_base as pointer-to-const. + (_Safe_iterator<>::_M_get_sequence): Add const_cast and comment about it. + * include/debug/safe_local_iterator.h (_Safe_local_iterator<>): Replace usages + of _M_sequence member by _M_safe_container(). + (_Safe_local_iterator<>::_M_attach, _M_attach_single): Take + _Safe_unordered_container_base as pointer-to-const. + (_Safe_local_iterator<>::_M_get_sequence): Rename into... + (_Safe_local_iterator<>::_M_get_ucontainer): ...this. Add necessary const_cast and + comment to explain it. + (_Safe_local_iterator<>::_M_is_begin, _M_is_end): Adapt. + * include/debug/safe_local_iterator.tcc: Adapt. + * include/debug/safe_sequence.h + (_Safe_sequence<>::_M_invalidate_if, _M_transfer_from_if): Add const qualifier. + * include/debug/safe_sequence.tcc: Adapt. + * include/debug/deque (std::__debug::deque::erase): Adapt to use new const + qualified methods. + * include/debug/formatter.h: Adapt. + * include/debug/forward_list (_Safe_forward_list::_M_this): Add const + qualification and return pointer for consistency with 'this' keyword. + (_Safe_forward_list::_M_swap_aux): Rename into... + (_Safe_forward_list::_S_swap_aux): ...this and take sequence as const reference. + (forward_list<>::resize): Adapt to use const methods. + * include/debug/list (list<>::resize): Likewise. + * src/c++11/debug.cc: Adapt to const qualification. + * testsuite/util/testsuite_containers.h + (forward_members_unordered::forward_members_unordered): Add check on local_iterator + conversion to const_local_iterator. + (forward_members::forward_members): Add check on iterator conversion to + const_iterator. + * testsuite/23_containers/unordered_map/const_container.cc: New test case. + * testsuite/23_containers/unordered_multimap/const_container.cc: New test case. + * testsuite/23_containers/unordered_multiset/const_container.cc: New test case. + * testsuite/23_containers/unordered_set/const_container.cc: New test case. + * testsuite/23_containers/vector/debug/mutex_association.cc: Adapt. + +2025-07-07 Jonathan Wakely <jwakely@redhat.com> + + PR libstdc++/120949 + * include/bits/stl_iterator.h (__normal_iterator): Fix order of + always_inline and nodiscard attributes for Clang compatibility. + +2025-07-07 Jonathan Wakely <jwakely@redhat.com> + + * testsuite/util/testsuite_hooks.h (VERIFY): Define as variadic + macro. + * testsuite/ext/verify_neg.cc: New test. + +2025-07-07 Jonathan Wakely <jwakely@redhat.com> + + * include/std/mdspan (__mapping_of): Add template keyword. + +2025-07-07 XU Kailiang <xu2k3l4@outlook.com> + Tomasz Kaminski <tkaminsk@redhat.com> + + PR libstdc++/117214 + * include/bits/chrono_io.h (_ChronoSpec::_M_time_only): Remove. + (_ChronoSpec::_M_time_point): Define. + (__formatter_chrono::_M_parse): Use __parts to determine + interpretation of j. + (__formatter_chrono::_M_check_ok): Define. + (__formatter_chrono::_M_format_to): Invoke _M_check_ok. + (__formatter_chrono::_M_a_A, __formatter_chrono::_M_b_B): Move + exception throwing to _M_check_ok. + (__formatter_chrono::_M_j): Use _M_needs to define interpretation. + (__formatter_duration::_S_spec_for): Set _M_time_point. + * testsuite/std/time/format/format.cc: Test for exception for !ok() + months/weekday. + * testsuite/std/time/format/pr117214_custom_timeput.cc: New + test. + +2025-07-07 Tomasz Kamiński <tkaminsk@redhat.com> + + PR libstdc++/120976 + * include/std/format (formatter<__float128, _Char_T): Define if + _GLIBCXX_FORMAT_F128 == 2. + +2025-07-06 Patrick Palka <ppalka@redhat.com> + + * include/bits/ranges_algo.h (shift_left, shift_right): Guard + with __glibcxx_shift >= 201806L. + (ranges::__shift_left_fn, ranges::shift_left): Define for C++23. + (ranges::__shift_right_fn, ranges::shift_right): Likewise. + * include/bits/version.def (shift): Update for C++23. + * include/bits/version.h: Regenerate. + * src/c++23/std.cc.in: Add ranges::shift_left/right. + * testsuite/25_algorithms/shift_left/constrained.cc: New test, + based off of 1.cc. + * testsuite/25_algorithms/shift_right/constrained.cc: New test, + based off of 1.cc. + 2025-07-04 Jonathan Wakely <jwakely@redhat.com> * include/bits/chrono_io.h (__formatter_duration::_S_spec_for): diff --git a/libstdc++-v3/config/abi/post/x86_64-linux-gnu/x32/baseline_symbols.txt b/libstdc++-v3/config/abi/post/x86_64-linux-gnu/x32/baseline_symbols.txt index ac11d5d..5d55287 100644 --- a/libstdc++-v3/config/abi/post/x86_64-linux-gnu/x32/baseline_symbols.txt +++ b/libstdc++-v3/config/abi/post/x86_64-linux-gnu/x32/baseline_symbols.txt @@ -2124,6 +2124,10 @@ FUNC:_ZNSt12__shared_ptrINSt10filesystem7__cxx114_DirELN9__gnu_cxx12_Lock_policy FUNC:_ZNSt12__shared_ptrINSt10filesystem7__cxx114_DirELN9__gnu_cxx12_Lock_policyE2EEC2EOS5_@@GLIBCXX_3.4.28 FUNC:_ZNSt12__shared_ptrINSt10filesystem7__cxx114_DirELN9__gnu_cxx12_Lock_policyE2EEC2Ev@@GLIBCXX_3.4.27 FUNC:_ZNSt12__shared_ptrINSt10filesystem7__cxx114_DirELN9__gnu_cxx12_Lock_policyE2EEaSEOS5_@@GLIBCXX_3.4.26 +FUNC:_ZNSt12__sso_stringC1Ev@@GLIBCXX_3.4.34 +FUNC:_ZNSt12__sso_stringC2Ev@@GLIBCXX_3.4.34 +FUNC:_ZNSt12__sso_stringD1Ev@@GLIBCXX_3.4.34 +FUNC:_ZNSt12__sso_stringD2Ev@@GLIBCXX_3.4.34 FUNC:_ZNSt12bad_weak_ptrD0Ev@@GLIBCXX_3.4.15 FUNC:_ZNSt12bad_weak_ptrD1Ev@@GLIBCXX_3.4.15 FUNC:_ZNSt12bad_weak_ptrD2Ev@@GLIBCXX_3.4.15 @@ -3221,6 +3225,8 @@ FUNC:_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_Alloc_hiderC1EPcRKS FUNC:_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_Alloc_hiderC2EPcOS3_@@GLIBCXX_3.4.23 FUNC:_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_Alloc_hiderC2EPcRKS3_@@GLIBCXX_3.4.21 FUNC:_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructEjc@@GLIBCXX_3.4.21 +FUNC:_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructILb0EEEvPKcj@@GLIBCXX_3.4.34 +FUNC:_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructILb1EEEvPKcj@@GLIBCXX_3.4.34 FUNC:_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructIN9__gnu_cxx17__normal_iteratorIPKcS4_EEEEvT_SB_St20forward_iterator_tag@@GLIBCXX_3.4.21 FUNC:_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructIN9__gnu_cxx17__normal_iteratorIPcS4_EEEEvT_SA_St20forward_iterator_tag@@GLIBCXX_3.4.21 FUNC:_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructIPKcEEvT_S8_St20forward_iterator_tag@@GLIBCXX_3.4.21 @@ -3374,6 +3380,8 @@ FUNC:_ZNSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEE12_Alloc_hiderC1EPwRKS FUNC:_ZNSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEE12_Alloc_hiderC2EPwOS3_@@GLIBCXX_3.4.23 FUNC:_ZNSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEE12_Alloc_hiderC2EPwRKS3_@@GLIBCXX_3.4.21 FUNC:_ZNSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEE12_M_constructEjw@@GLIBCXX_3.4.21 +FUNC:_ZNSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEE12_M_constructILb0EEEvPKwj@@GLIBCXX_3.4.34 +FUNC:_ZNSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEE12_M_constructILb1EEEvPKwj@@GLIBCXX_3.4.34 FUNC:_ZNSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEE12_M_constructIN9__gnu_cxx17__normal_iteratorIPKwS4_EEEEvT_SB_St20forward_iterator_tag@@GLIBCXX_3.4.21 FUNC:_ZNSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEE12_M_constructIN9__gnu_cxx17__normal_iteratorIPwS4_EEEEvT_SA_St20forward_iterator_tag@@GLIBCXX_3.4.21 FUNC:_ZNSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEE12_M_constructIPKwEEvT_S8_St20forward_iterator_tag@@GLIBCXX_3.4.21 @@ -3941,6 +3949,8 @@ FUNC:_ZNSt8__detail15_List_node_base11_M_transferEPS0_S1_@@GLIBCXX_3.4.15 FUNC:_ZNSt8__detail15_List_node_base4swapERS0_S1_@@GLIBCXX_3.4.15 FUNC:_ZNSt8__detail15_List_node_base7_M_hookEPS0_@@GLIBCXX_3.4.15 FUNC:_ZNSt8__detail15_List_node_base9_M_unhookEv@@GLIBCXX_3.4.15 +FUNC:_ZNSt8__format25__locale_encoding_to_utf8ERKSt6localeSt17basic_string_viewIcSt11char_traitsIcEEPv@@GLIBCXX_3.4.34 +FUNC:_ZNSt8__format26__with_encoding_conversionERKSt6locale@@GLIBCXX_3.4.34 FUNC:_ZNSt8bad_castD0Ev@@GLIBCXX_3.4 FUNC:_ZNSt8bad_castD1Ev@@GLIBCXX_3.4 FUNC:_ZNSt8bad_castD2Ev@@GLIBCXX_3.4 @@ -4617,6 +4627,7 @@ OBJECT:0:GLIBCXX_3.4.30 OBJECT:0:GLIBCXX_3.4.31 OBJECT:0:GLIBCXX_3.4.32 OBJECT:0:GLIBCXX_3.4.33 +OBJECT:0:GLIBCXX_3.4.34 OBJECT:0:GLIBCXX_3.4.4 OBJECT:0:GLIBCXX_3.4.5 OBJECT:0:GLIBCXX_3.4.6 diff --git a/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver b/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver index 2818ab3..1c423ff 100644 --- a/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver +++ b/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver @@ -117,11 +117,11 @@ GLIBCXX_8.0 { _ZN9__gnu_cxx3__818stdio_sync_filebufI[cw]NSt3__811char_traitsI[cw]EEE[5-9]*; # debug mode - _ZN11__gnu_debug19_Safe_sequence_base12_M_get_mutexEv; - _ZN11__gnu_debug19_Safe_sequence_base13_M_detach_allEv; - _ZN11__gnu_debug19_Safe_sequence_base18_M_detach_singularEv; - _ZN11__gnu_debug19_Safe_sequence_base22_M_revalidate_singularEv; - _ZN11__gnu_debug19_Safe_sequence_base7_M_swapERS0_; + _ZNK11__gnu_debug19_Safe_sequence_base12_M_get_mutexEv; + _ZNK11__gnu_debug19_Safe_sequence_base13_M_detach_allEv; + _ZNK11__gnu_debug19_Safe_sequence_base18_M_detach_singularEv; + _ZNK11__gnu_debug19_Safe_sequence_base22_M_revalidate_singularEv; + _ZNK11__gnu_debug19_Safe_sequence_base7_M_swapERKS0_; _ZN11__gnu_debug19_Safe_iterator_base9_M_attach*; _ZN11__gnu_debug19_Safe_iterator_base16_M_attach_single*; @@ -136,11 +136,11 @@ GLIBCXX_8.0 { # __gnu_debug::_Safe_unordered_container_base # __gnu_debug::_Safe_local_iterator_base - _ZN11__gnu_debug30_Safe_unordered_container_base7_M_swapERS0_; - _ZN11__gnu_debug30_Safe_unordered_container_base13_M_detach_allEv; - _ZN11__gnu_debug25_Safe_local_iterator_base9_M_attachEPNS_19_Safe_sequence_baseEb; + _ZNK11__gnu_debug30_Safe_unordered_container_base7_M_swapERKS0_; + _ZNK11__gnu_debug30_Safe_unordered_container_base13_M_detach_allEv; + _ZN11__gnu_debug25_Safe_local_iterator_base9_M_attachEPKNS_30_Safe_unordered_container_baseEb; _ZN11__gnu_debug25_Safe_local_iterator_base9_M_detachEv; - _ZN11__gnu_debug25_Safe_local_iterator_base16_M_attach_singleEPNS_19_Safe_sequence_baseEb; + _ZN11__gnu_debug25_Safe_local_iterator_base16_M_attach_singleEPKNS_30_Safe_unordered_container_baseEb; # parallel mode _ZN14__gnu_parallel9_Settings3getEv; diff --git a/libstdc++-v3/config/abi/pre/gnu.ver b/libstdc++-v3/config/abi/pre/gnu.ver index 73b6f33..b5a89c3 100644 --- a/libstdc++-v3/config/abi/pre/gnu.ver +++ b/libstdc++-v3/config/abi/pre/gnu.ver @@ -2555,6 +2555,20 @@ GLIBCXX_3.4.35 { _ZNSt8__detail17__wait_until_implEPKvRNS_16__wait_args_baseERKNSt6chrono8durationI[lx]St5ratioIL[lx]1EL[lx]1000000000EEEE; _ZNSt8__detail11__wait_args22_M_load_proxy_wait_valEPKv; + # __gnu_debug::_Safe_iterator_base and _Safe_sequence_base const + _ZN11__gnu_debug19_Safe_iterator_base9_M_attachEPKNS_19_Safe_sequence_baseEb; + _ZN11__gnu_debug19_Safe_iterator_base16_M_attach_singleEPKNS_19_Safe_sequence_baseEb; + _ZNK11__gnu_debug19_Safe_sequence_base13_M_detach_allEv; + _ZNK11__gnu_debug19_Safe_sequence_base18_M_detach_singularEv; + _ZNK11__gnu_debug19_Safe_sequence_base12_M_get_mutexEv; + _ZNK11__gnu_debug19_Safe_sequence_base22_M_revalidate_singularEv; + _ZNK11__gnu_debug19_Safe_sequence_base7_M_swapERKS0_; + + # __gnu_debug::_Safe_local_iterator_base and _Safe_unordered_container_base const + _ZN11__gnu_debug25_Safe_local_iterator_base9_M_attachEPKNS_30_Safe_unordered_container_baseEb; + _ZN11__gnu_debug25_Safe_local_iterator_base16_M_attach_singleEPKNS_30_Safe_unordered_container_baseEb; + _ZNK11__gnu_debug30_Safe_unordered_container_base13_M_detach_allEv; + _ZNK11__gnu_debug30_Safe_unordered_container_base7_M_swapERKS0_; } GLIBCXX_3.4.34; # Symbols in the support library (libsupc++) have their own tag. diff --git a/libstdc++-v3/include/bits/chrono_io.h b/libstdc++-v3/include/bits/chrono_io.h index 72cd569..75ee7e8 100644 --- a/libstdc++-v3/include/bits/chrono_io.h +++ b/libstdc++-v3/include/bits/chrono_io.h @@ -280,8 +280,8 @@ namespace __format // in the format-spec, e.g. "{:L%a}" is localized and locale-specific, // but "{:L}" is only localized and "{:%a}" is only locale-specific. unsigned _M_locale_specific : 1; - // Indicates that we are handling duration. - unsigned _M_time_only : 1; + // Indicates that we are handling time_point. + unsigned _M_time_point : 1; // Indicates that duration should be treated as floating point. unsigned _M_floating_point_rep : 1; // Indicate that duration uses user-defined representation. @@ -693,8 +693,11 @@ namespace __format __allowed_mods = _Mod_O; break; case 'j': - __needed = __spec._M_time_only ? _HoursMinutesSeconds - : _DayOfYear; + __needed = __parts & _DayOfYear; + // If we do not know day-of-year then we must have a duration, + // which is to be formatted as decimal number of days. + if (__needed == _None) + __needed = _HoursMinutesSeconds; break; case 'm': __needed = _Month; @@ -919,7 +922,13 @@ namespace __format { switch (__conv) { + case 'a': + case 'A': + case 'b': + case 'B': case 'c': + case 'h': + case 'p': case 'r': case 'x': case 'X': @@ -947,6 +956,32 @@ namespace __format return __out; } + void + _M_check_ok(const _ChronoData<_CharT>& __t, _CharT __conv) const + { + // n.b. for time point all date parts are computed, so + // they are always ok. + if (_M_spec._M_time_point || _M_spec._M_debug) + return; + + switch (__conv) + { + case 'a': + case 'A': + if (!__t._M_weekday.ok()) [[unlikely]] + __throw_format_error("format error: invalid weekday"); + return; + case 'b': + case 'h': + case 'B': + if (!__t._M_month.ok()) [[unlikely]] + __throw_format_error("format error: invalid month"); + return; + default: + return; + } + } + template<typename _OutIter, typename _FormatContext> _OutIter _M_format_to(const _ChronoData<_CharT>& __t, _OutIter __out, @@ -1003,6 +1038,8 @@ namespace __format do { _CharT __c = *__first++; + _M_check_ok(__t, __c); + if (__use_locale_fmt && _S_localized_spec(__c, __mod)) [[unlikely]] __out = _M_locale_fmt(std::move(__out), __fc.locale(), __tm, __c, __mod); @@ -1153,11 +1190,8 @@ namespace __format { // %a Locale's abbreviated weekday name. // %A Locale's full weekday name. - if (!__wd.ok()) + if (_M_spec._M_debug && !__wd.ok()) { - if (!_M_spec._M_debug) - __throw_format_error("format error: invalid weekday"); - _CharT __buf[3]; __out = __format::__write(std::move(__out), _S_str_d1(__buf, __wd.c_encoding())); @@ -1183,11 +1217,8 @@ namespace __format { // %b Locale's abbreviated month name. // %B Locale's full month name. - if (!__m.ok()) + if (_M_spec._M_debug && !__m.ok()) { - if (!_M_spec._M_debug) - __throw_format_error("format error: invalid month"); - _CharT __buf[3]; __out = __format::__write(std::move(__out), _S_str_d1(__buf, (unsigned)__m)); @@ -1419,7 +1450,7 @@ namespace __format _OutIter _M_j(const _ChronoData<_CharT>& __t, _OutIter __out) const { - if (_M_spec._M_time_only) + if (!_M_spec._M_needs(_ChronoParts::_DayOfYear)) { // Decimal number of days, without padding. auto __d = chrono::floor<chrono::days>(__t._M_hours).count(); @@ -1766,7 +1797,7 @@ namespace __format { if (__n < 100) [[likely]] return _S_two_digits(__n); - return _S_str_d3(__buf, __n); + return _S_str_d3(__buf, __n); } // Returns decimal representation of __n, padded to 3 digits. @@ -1811,7 +1842,7 @@ namespace __format using enum _ChronoParts; _ChronoSpec<_CharT> __res{}; - __res._M_time_only = (__parts & _Date) == 0; + __res._M_time_point = (__parts & _DateTime) == _DateTime; __res._M_floating_point_rep = chrono::treat_as_floating_point_v<_Rep>; __res._M_custom_rep = !is_arithmetic_v<_Rep>; __res._M_prec = chrono::hh_mm_ss<_Duration>::fractional_width; diff --git a/libstdc++-v3/include/bits/max_size_type.h b/libstdc++-v3/include/bits/max_size_type.h index 73a6d14..30c5b12 100644 --- a/libstdc++-v3/include/bits/max_size_type.h +++ b/libstdc++-v3/include/bits/max_size_type.h @@ -38,6 +38,7 @@ #include <ext/numeric_traits.h> #include <bit> // __bit_width #include <numbers> +#include <limits> // __glibcxx_integral_traps // This header implements unsigned and signed integer-class types (as per // [iterator.concept.winc]) that are one bit wider than the widest supported @@ -775,10 +776,27 @@ namespace ranges static constexpr bool is_signed = false; static constexpr bool is_integer = true; static constexpr bool is_exact = true; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = true; + static constexpr bool traps = __glibcxx_integral_traps; + static constexpr int radix = 2; static constexpr int digits = __gnu_cxx::__int_traits<_Sp::__rep>::__digits + 1; static constexpr int digits10 = static_cast<int>(digits * numbers::ln2 / numbers::ln10); + static constexpr int max_digits10 = 0; + static constexpr int min_exponent = 0; + static constexpr int min_exponent10 = 0; + static constexpr int max_exponent = 0; + static constexpr int max_exponent10 = 0; + static constexpr bool is_iec559 = false; + static constexpr bool has_infinity = false; + static constexpr bool has_quiet_NaN = false; + static constexpr bool has_signaling_NaN = false; + static constexpr bool has_denorm_loss = false; + static constexpr bool tinyness_before = false; + static constexpr float_denorm_style has_denorm = denorm_absent; + static constexpr float_round_style round_style = round_toward_zero; static constexpr _Sp min() noexcept @@ -791,6 +809,30 @@ namespace ranges static constexpr _Sp lowest() noexcept { return min(); } + + static constexpr _Sp + denorm_min() noexcept + { return 0; } + + static constexpr _Sp + epsilon() noexcept + { return 0; } + + static constexpr _Sp + round_error() noexcept + { return 0; } + + static constexpr _Sp + infinity() noexcept + { return 0; } + + static constexpr _Sp + quiet_NaN() noexcept + { return 0; } + + static constexpr _Sp + signaling_NaN() noexcept + { return 0; } }; template<> @@ -802,9 +844,26 @@ namespace ranges static constexpr bool is_signed = true; static constexpr bool is_integer = true; static constexpr bool is_exact = true; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = false; + static constexpr bool traps = __glibcxx_integral_traps; + static constexpr int radix = 2; static constexpr int digits = numeric_limits<_Sp>::digits - 1; static constexpr int digits10 = static_cast<int>(digits * numbers::ln2 / numbers::ln10); + static constexpr int max_digits10 = 0; + static constexpr int min_exponent = 0; + static constexpr int min_exponent10 = 0; + static constexpr int max_exponent = 0; + static constexpr int max_exponent10 = 0; + static constexpr bool is_iec559 = false; + static constexpr bool has_infinity = false; + static constexpr bool has_quiet_NaN = false; + static constexpr bool has_signaling_NaN = false; + static constexpr bool has_denorm_loss = false; + static constexpr bool tinyness_before = false; + static constexpr float_denorm_style has_denorm = denorm_absent; + static constexpr float_round_style round_style = round_toward_zero; static constexpr _Dp min() noexcept @@ -817,6 +876,30 @@ namespace ranges static constexpr _Dp lowest() noexcept { return min(); } + + static constexpr _Dp + denorm_min() noexcept + { return 0; } + + static constexpr _Dp + epsilon() noexcept + { return 0; } + + static constexpr _Dp + round_error() noexcept + { return 0; } + + static constexpr _Dp + infinity() noexcept + { return 0; } + + static constexpr _Dp + quiet_NaN() noexcept + { return 0; } + + static constexpr _Dp + signaling_NaN() noexcept + { return 0; } }; template<> diff --git a/libstdc++-v3/include/bits/shared_ptr.h b/libstdc++-v3/include/bits/shared_ptr.h index a196a0f..f2b4601 100644 --- a/libstdc++-v3/include/bits/shared_ptr.h +++ b/libstdc++-v3/include/bits/shared_ptr.h @@ -909,6 +909,64 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : public _Sp_owner_less<weak_ptr<_Tp>, shared_ptr<_Tp>> { }; +#ifdef __glibcxx_smart_ptr_owner_equality // >= C++26 + + /** + * @brief Provides ownership-based hashing. + * @headerfile memory + * @since C++26 + */ + struct owner_hash + { + template<typename _Tp> + size_t + operator()(const shared_ptr<_Tp>& __s) const noexcept + { return __s.owner_hash(); } + + template<typename _Tp> + size_t + operator()(const weak_ptr<_Tp>& __s) const noexcept + { return __s.owner_hash(); } + + using is_transparent = void; + }; + + /** + * @brief Provides ownership-based mixed equality comparisons of + * shared and weak pointers. + * @headerfile memory + * @since C++26 + */ + struct owner_equal + { + template<typename _Tp1, typename _Tp2> + bool + operator()(const shared_ptr<_Tp1>& __lhs, + const shared_ptr<_Tp2>& __rhs) const noexcept + { return __lhs.owner_equal(__rhs); } + + template<typename _Tp1, typename _Tp2> + bool + operator()(const shared_ptr<_Tp1>& __lhs, + const weak_ptr<_Tp2>& __rhs) const noexcept + { return __lhs.owner_equal(__rhs); } + + template<typename _Tp1, typename _Tp2> + bool + operator()(const weak_ptr<_Tp1>& __lhs, + const shared_ptr<_Tp2>& __rhs) const noexcept + { return __lhs.owner_equal(__rhs); } + + template<typename _Tp1, typename _Tp2> + bool + operator()(const weak_ptr<_Tp1>& __lhs, + const weak_ptr<_Tp2>& __rhs) const noexcept + { return __lhs.owner_equal(__rhs); } + + using is_transparent = void; + }; +#endif + /** * @brief Base class allowing use of the member function `shared_from_this`. * @headerfile memory diff --git a/libstdc++-v3/include/bits/shared_ptr_base.h b/libstdc++-v3/include/bits/shared_ptr_base.h index b4be1b4..fb868e7 100644 --- a/libstdc++-v3/include/bits/shared_ptr_base.h +++ b/libstdc++-v3/include/bits/shared_ptr_base.h @@ -1122,6 +1122,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_less(const __weak_count<_Lp>& __rhs) const noexcept { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); } +#ifdef __glibcxx_smart_ptr_owner_equality // >= C++26 + size_t + _M_owner_hash() const noexcept + { return std::hash<_Sp_counted_base<_Lp>*>()(this->_M_pi); } +#endif + // Friend function injected into enclosing namespace and found by ADL friend inline bool operator==(const __shared_count& __a, const __shared_count& __b) noexcept @@ -1225,6 +1231,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_less(const __shared_count<_Lp>& __rhs) const noexcept { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); } +#ifdef __glibcxx_smart_ptr_owner_equality // >= C++26 + size_t + _M_owner_hash() const noexcept + { return std::hash<_Sp_counted_base<_Lp>*>()(this->_M_pi); } +#endif + // Friend function injected into enclosing namespace and found by ADL friend inline bool operator==(const __weak_count& __a, const __weak_count& __b) noexcept @@ -1715,6 +1727,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return _M_refcount._M_less(__rhs._M_refcount); } /// @} +#ifdef __glibcxx_smart_ptr_owner_equality // >= C++26 + size_t owner_hash() const noexcept { return _M_refcount._M_owner_hash(); } + + template<typename _Tp1> + bool + owner_equal(__shared_ptr<_Tp1, _Lp> const& __rhs) const noexcept + { return _M_refcount == __rhs._M_refcount; } + + template<typename _Tp1> + bool + owner_equal(__weak_ptr<_Tp1, _Lp> const& __rhs) const noexcept + { return _M_refcount == __rhs._M_refcount; } +#endif + protected: // This constructor is non-standard, it is used by allocate_shared. template<typename _Alloc, typename... _Args> @@ -2098,6 +2124,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION owner_before(const __weak_ptr<_Tp1, _Lp>& __rhs) const noexcept { return _M_refcount._M_less(__rhs._M_refcount); } +#ifdef __glibcxx_smart_ptr_owner_equality // >= C++26 + size_t owner_hash() const noexcept { return _M_refcount._M_owner_hash(); } + + template<typename _Tp1> + bool + owner_equal(const __shared_ptr<_Tp1, _Lp> & __rhs) const noexcept + { return _M_refcount == __rhs._M_refcount; } + + template<typename _Tp1> + bool + owner_equal(const __weak_ptr<_Tp1, _Lp> & __rhs) const noexcept + { return _M_refcount == __rhs._M_refcount; } +#endif + void reset() noexcept { __weak_ptr().swap(*this); } diff --git a/libstdc++-v3/include/bits/stl_iterator.h b/libstdc++-v3/include/bits/stl_iterator.h index a7188f4..75e794f 100644 --- a/libstdc++-v3/include/bits/stl_iterator.h +++ b/libstdc++-v3/include/bits/stl_iterator.h @@ -1211,7 +1211,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #else // Forward iterator requirements template<typename _Iter> - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend _GLIBCXX_CONSTEXPR bool @@ -1220,7 +1220,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_NOEXCEPT { return __lhs.base() == __rhs.base(); } - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend _GLIBCXX_CONSTEXPR bool @@ -1229,7 +1229,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __lhs.base() == __rhs.base(); } template<typename _Iter> - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend _GLIBCXX_CONSTEXPR bool @@ -1238,7 +1238,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_NOEXCEPT { return __lhs.base() != __rhs.base(); } - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend _GLIBCXX_CONSTEXPR bool @@ -1248,15 +1248,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Random access iterator requirements template<typename _Iter> + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD _GLIBCXX_CONSTEXPR + _GLIBCXX_CONSTEXPR inline bool operator<(const __normal_iterator& __lhs, const __normal_iterator<_Iter, _Container>& __rhs) _GLIBCXX_NOEXCEPT { return __lhs.base() < __rhs.base(); } - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend _GLIBCXX20_CONSTEXPR bool @@ -1265,15 +1266,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __lhs.base() < __rhs.base(); } template<typename _Iter> + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD _GLIBCXX_CONSTEXPR + _GLIBCXX_CONSTEXPR bool operator>(const __normal_iterator& __lhs, const __normal_iterator<_Iter, _Container>& __rhs) _GLIBCXX_NOEXCEPT { return __lhs.base() > __rhs.base(); } - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend _GLIBCXX_CONSTEXPR bool @@ -1282,7 +1284,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __lhs.base() > __rhs.base(); } template<typename _Iter> - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend _GLIBCXX_CONSTEXPR bool @@ -1291,7 +1293,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_NOEXCEPT { return __lhs.base() <= __rhs.base(); } - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend _GLIBCXX_CONSTEXPR bool @@ -1300,7 +1302,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __lhs.base() <= __rhs.base(); } template<typename _Iter> - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend _GLIBCXX_CONSTEXPR bool @@ -1309,7 +1311,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_NOEXCEPT { return __lhs.base() >= __rhs.base(); } - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend _GLIBCXX_CONSTEXPR bool @@ -1341,7 +1343,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #endif { return __lhs.base() - __rhs.base(); } - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend _GLIBCXX_CONSTEXPR difference_type @@ -1349,7 +1351,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_NOEXCEPT { return __lhs.base() - __rhs.base(); } - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend _GLIBCXX_CONSTEXPR __normal_iterator diff --git a/libstdc++-v3/include/bits/stl_uninitialized.h b/libstdc++-v3/include/bits/stl_uninitialized.h index 3a37ddc..351c3a1 100644 --- a/libstdc++-v3/include/bits/stl_uninitialized.h +++ b/libstdc++-v3/include/bits/stl_uninitialized.h @@ -922,11 +922,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // __uninitialized_default // Fills [first, last) with value-initialized value_types. template<typename _ForwardIterator> - _GLIBCXX26_CONSTEXPR + _GLIBCXX20_CONSTEXPR inline void __uninitialized_default(_ForwardIterator __first, _ForwardIterator __last) { +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return __uninitialized_default_1<false>:: + __uninit_default(__first, __last); +#endif + typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType; // trivial types can have deleted assignment diff --git a/libstdc++-v3/include/bits/version.def b/libstdc++-v3/include/bits/version.def index 64f8190..df58e70 100644 --- a/libstdc++-v3/include/bits/version.def +++ b/libstdc++-v3/include/bits/version.def @@ -1007,9 +1007,8 @@ ftms = { ftms = { name = mdspan; - no_stdname = true; // FIXME: remove values = { - v = 1; // FIXME: 202207 + v = 202207; cxxmin = 23; }; }; @@ -2008,6 +2007,15 @@ ftms = { }; ftms = { + name = smart_ptr_owner_equality; + values = { + v = 202306; + cxxmin = 26; + hosted = yes; + }; +}; + +ftms = { name = sstream_from_string_view; values = { v = 202306; @@ -2042,6 +2050,15 @@ ftms = { }; }; +ftms = { + name = constexpr_exceptions; + values = { + v = 202502; + cxxmin = 26; + extra_cond = "__cpp_constexpr_exceptions >= 202411L"; + }; +}; + // Standard test specifications. stds[97] = ">= 199711L"; stds[03] = ">= 199711L"; diff --git a/libstdc++-v3/include/bits/version.h b/libstdc++-v3/include/bits/version.h index 744246a..1414dd7 100644 --- a/libstdc++-v3/include/bits/version.h +++ b/libstdc++-v3/include/bits/version.h @@ -1126,8 +1126,9 @@ #if !defined(__cpp_lib_mdspan) # if (__cplusplus >= 202100L) -# define __glibcxx_mdspan 1L +# define __glibcxx_mdspan 202207L # if defined(__glibcxx_want_all) || defined(__glibcxx_want_mdspan) +# define __cpp_lib_mdspan 202207L # endif # endif #endif /* !defined(__cpp_lib_mdspan) && defined(__glibcxx_want_mdspan) */ @@ -2248,6 +2249,16 @@ #endif /* !defined(__cpp_lib_polymorphic) && defined(__glibcxx_want_polymorphic) */ #undef __glibcxx_want_polymorphic +#if !defined(__cpp_lib_smart_ptr_owner_equality) +# if (__cplusplus > 202302L) && _GLIBCXX_HOSTED +# define __glibcxx_smart_ptr_owner_equality 202306L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_smart_ptr_owner_equality) +# define __cpp_lib_smart_ptr_owner_equality 202306L +# endif +# endif +#endif /* !defined(__cpp_lib_smart_ptr_owner_equality) && defined(__glibcxx_want_smart_ptr_owner_equality) */ +#undef __glibcxx_want_smart_ptr_owner_equality + #if !defined(__cpp_lib_sstream_from_string_view) # if (__cplusplus > 202302L) && _GLIBCXX_HOSTED # define __glibcxx_sstream_from_string_view 202306L @@ -2288,4 +2299,14 @@ #endif /* !defined(__cpp_lib_bitset) && defined(__glibcxx_want_bitset) */ #undef __glibcxx_want_bitset +#if !defined(__cpp_lib_constexpr_exceptions) +# if (__cplusplus > 202302L) && (__cpp_constexpr_exceptions >= 202411L) +# define __glibcxx_constexpr_exceptions 202502L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_constexpr_exceptions) +# define __cpp_lib_constexpr_exceptions 202502L +# endif +# endif +#endif /* !defined(__cpp_lib_constexpr_exceptions) && defined(__glibcxx_want_constexpr_exceptions) */ +#undef __glibcxx_want_constexpr_exceptions + #undef __glibcxx_want_all diff --git a/libstdc++-v3/include/debug/deque b/libstdc++-v3/include/debug/deque index 59d60b2..ed69eb8 100644 --- a/libstdc++-v3/include/debug/deque +++ b/libstdc++-v3/include/debug/deque @@ -650,7 +650,8 @@ namespace __debug else if (__first.base() == _Base::begin() || __last.base() == _Base::end()) { - this->_M_detach_singular(); + const deque* __this = this; + __this->_M_detach_singular(); for (_Base_const_iterator __position = __first.base(); __position != __last.base(); ++__position) { @@ -663,7 +664,7 @@ namespace __debug } __catch(...) { - this->_M_revalidate_singular(); + __this->_M_revalidate_singular(); __throw_exception_again; } } diff --git a/libstdc++-v3/include/debug/formatter.h b/libstdc++-v3/include/debug/formatter.h index d80e8a7..8aa84ad 100644 --- a/libstdc++-v3/include/debug/formatter.h +++ b/libstdc++-v3/include/debug/formatter.h @@ -96,7 +96,7 @@ namespace __gnu_debug template<typename _Iterator, typename _Sequence, typename _Category> class _Safe_iterator; - template<typename _Iterator, typename _Sequence> + template<typename _Iterator, typename _UContainer> class _Safe_local_iterator; template<typename _Sequence> @@ -316,8 +316,8 @@ namespace __gnu_debug } } - template<typename _Iterator, typename _Sequence> - _Parameter(_Safe_local_iterator<_Iterator, _Sequence> const& __it, + template<typename _Iterator, typename _UContainer> + _Parameter(_Safe_local_iterator<_Iterator, _UContainer> const& __it, const char* __name, _Is_iterator) : _M_kind(__iterator), _M_variant() { @@ -326,8 +326,8 @@ namespace __gnu_debug _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(_Iterator); _M_variant._M_iterator._M_constness = __it._S_constant() ? __const_iterator : __mutable_iterator; - _M_variant._M_iterator._M_sequence = __it._M_get_sequence(); - _M_variant._M_iterator._M_seq_type = _GLIBCXX_TYPEID(_Sequence); + _M_variant._M_iterator._M_sequence = __it._M_get_ucontainer(); + _M_variant._M_iterator._M_seq_type = _GLIBCXX_TYPEID(_UContainer); if (__it._M_singular()) { diff --git a/libstdc++-v3/include/debug/forward_list b/libstdc++-v3/include/debug/forward_list index 60a2542..9da7dda 100644 --- a/libstdc++-v3/include/debug/forward_list +++ b/libstdc++-v3/include/debug/forward_list @@ -58,44 +58,44 @@ namespace __gnu_debug class _Safe_forward_list : public _Safe_sequence<_SafeSequence> { - _SafeSequence& - _M_this() noexcept - { return *static_cast<_SafeSequence*>(this); } + const _SafeSequence* + _M_this() const noexcept + { return static_cast<const _SafeSequence*>(this); } static void - _M_swap_aux(_Safe_sequence_base& __lhs, + _S_swap_aux(const _Safe_forward_list& __lhs, _Safe_iterator_base*& __lhs_iterators, - _Safe_sequence_base& __rhs, + const _Safe_forward_list& __rhs, _Safe_iterator_base*& __rhs_iterators); - void _M_swap_single(_Safe_sequence_base&) noexcept; + void _M_swap_single(const _Safe_forward_list&) const noexcept; protected: void - _M_invalidate_all() + _M_invalidate_all() const { - using _Base_const_iterator = __decltype(_M_this()._M_base().cend()); + using _Base_const_iterator = __decltype(_M_this()->_M_base().cend()); this->_M_invalidate_if([this](_Base_const_iterator __it) { - return __it != _M_this()._M_base().cbefore_begin() - && __it != _M_this()._M_base().cend(); }); + return __it != _M_this()->_M_base().cbefore_begin() + && __it != _M_this()->_M_base().cend(); }); } - void _M_swap(_Safe_sequence_base&) noexcept; + void + _M_swap(const _Safe_forward_list&) const noexcept; }; template<typename _SafeSequence> void _Safe_forward_list<_SafeSequence>:: - _M_swap_aux(_Safe_sequence_base& __lhs, + _S_swap_aux(const _Safe_forward_list& __lhs, _Safe_iterator_base*& __lhs_iterators, - _Safe_sequence_base& __rhs, + const _Safe_forward_list& __rhs, _Safe_iterator_base*& __rhs_iterators) { using const_iterator = typename _SafeSequence::const_iterator; _Safe_iterator_base* __bbegin_its = 0; _Safe_iterator_base* __last_bbegin = 0; - _SafeSequence& __rseq = static_cast<_SafeSequence&>(__rhs); for (_Safe_iterator_base* __iter = __lhs_iterators; __iter;) { @@ -104,7 +104,7 @@ namespace __gnu_debug const_iterator* __victim = static_cast<const_iterator*>(__victim_base); __iter = __iter->_M_next; - if (__victim->base() == __rseq._M_base().cbefore_begin()) + if (__victim->base() == __rhs._M_this()->_M_base().cbefore_begin()) { __victim->_M_unlink(); if (__lhs_iterators == __victim_base) @@ -136,21 +136,21 @@ namespace __gnu_debug template<typename _SafeSequence> void _Safe_forward_list<_SafeSequence>:: - _M_swap_single(_Safe_sequence_base& __other) noexcept + _M_swap_single(const _Safe_forward_list& __other) const noexcept { - std::swap(_M_this()._M_iterators, __other._M_iterators); - std::swap(_M_this()._M_const_iterators, __other._M_const_iterators); + std::swap(_M_this()->_M_iterators, __other._M_iterators); + std::swap(_M_this()->_M_const_iterators, __other._M_const_iterators); // Useless, always 1 on forward_list - //std::swap(_M_this()_M_version, __other._M_version); - _Safe_iterator_base* __this_its = _M_this()._M_iterators; - _M_swap_aux(__other, __other._M_iterators, - _M_this(), _M_this()._M_iterators); - _Safe_iterator_base* __this_const_its = _M_this()._M_const_iterators; - _M_swap_aux(__other, __other._M_const_iterators, - _M_this(), _M_this()._M_const_iterators); - _M_swap_aux(_M_this(), __this_its, + //std::swap(_M_this()->_M_version, __other._M_version); + _Safe_iterator_base* __this_its = _M_this()->_M_iterators; + _S_swap_aux(__other, __other._M_iterators, + *_M_this(), _M_this()->_M_iterators); + _Safe_iterator_base* __this_const_its = _M_this()->_M_const_iterators; + _S_swap_aux(__other, __other._M_const_iterators, + *_M_this(), _M_this()->_M_const_iterators); + _S_swap_aux(*_M_this(), __this_its, __other, __other._M_iterators); - _M_swap_aux(_M_this(), __this_const_its, + _S_swap_aux(*_M_this(), __this_const_its, __other, __other._M_const_iterators); } @@ -159,13 +159,12 @@ namespace __gnu_debug template<typename _SafeSequence> void _Safe_forward_list<_SafeSequence>:: - _M_swap(_Safe_sequence_base& __other) noexcept + _M_swap(const _Safe_forward_list& __other) const noexcept { // We need to lock both sequences to swap using namespace __gnu_cxx; - __mutex *__this_mutex = &_M_this()._M_get_mutex(); - __mutex *__other_mutex = - &static_cast<_SafeSequence&>(__other)._M_get_mutex(); + __mutex *__this_mutex = &_M_this()->_M_get_mutex(); + __mutex *__other_mutex = &__other._M_get_mutex(); if (__this_mutex == __other_mutex) { __scoped_lock __lock(*__this_mutex); @@ -565,7 +564,8 @@ namespace __debug void resize(size_type __sz) { - this->_M_detach_singular(); + const forward_list* __this = this; + __this->_M_detach_singular(); // if __sz < size(), invalidate all iterators in [begin+__sz, end() _Base_iterator __victim = _Base::begin(); @@ -585,7 +585,7 @@ namespace __debug } __catch(...) { - this->_M_revalidate_singular(); + __this->_M_revalidate_singular(); __throw_exception_again; } } @@ -593,7 +593,8 @@ namespace __debug void resize(size_type __sz, const value_type& __val) { - this->_M_detach_singular(); + const forward_list* __this = this; + __this->_M_detach_singular(); // if __sz < size(), invalidate all iterators in [begin+__sz, end()) _Base_iterator __victim = _Base::begin(); @@ -613,7 +614,7 @@ namespace __debug } __catch(...) { - this->_M_revalidate_singular(); + __this->_M_revalidate_singular(); __throw_exception_again; } } diff --git a/libstdc++-v3/include/debug/list b/libstdc++-v3/include/debug/list index a9d974c..c502c7c 100644 --- a/libstdc++-v3/include/debug/list +++ b/libstdc++-v3/include/debug/list @@ -321,7 +321,8 @@ namespace __debug void resize(size_type __sz) { - this->_M_detach_singular(); + const list* __this = this; + __this->_M_detach_singular(); // if __sz < size(), invalidate all iterators in [begin + __sz, end()) _Base_iterator __victim = _Base::begin(); @@ -338,7 +339,7 @@ namespace __debug } __catch(...) { - this->_M_revalidate_singular(); + __this->_M_revalidate_singular(); __throw_exception_again; } } @@ -346,7 +347,8 @@ namespace __debug void resize(size_type __sz, const _Tp& __c) { - this->_M_detach_singular(); + const list* __this = this; + __this->_M_detach_singular(); // if __sz < size(), invalidate all iterators in [begin + __sz, end()) _Base_iterator __victim = _Base::begin(); @@ -363,7 +365,7 @@ namespace __debug } __catch(...) { - this->_M_revalidate_singular(); + __this->_M_revalidate_singular(); __throw_exception_again; } } @@ -371,7 +373,8 @@ namespace __debug void resize(size_type __sz, _Tp __c = _Tp()) { - this->_M_detach_singular(); + const list* __this = this; + __this->_M_detach_singular(); // if __sz < size(), invalidate all iterators in [begin + __sz, end()) _Base_iterator __victim = _Base::begin(); @@ -388,7 +391,7 @@ namespace __debug } __catch(...) { - this->_M_revalidate_singular(); + __this->_M_revalidate_singular(); __throw_exception_again; } } diff --git a/libstdc++-v3/include/debug/safe_base.h b/libstdc++-v3/include/debug/safe_base.h index cf3f170..4462297 100644 --- a/libstdc++-v3/include/debug/safe_base.h +++ b/libstdc++-v3/include/debug/safe_base.h @@ -53,8 +53,10 @@ namespace __gnu_debug public: /** The sequence this iterator references; may be NULL to indicate - a singular iterator. */ - _Safe_sequence_base* _M_sequence; + * a singular iterator. Stored as pointer-to-const because sequence + * could be declared as const. + */ + const _Safe_sequence_base* _M_sequence; /** The version number of this iterator. The sentinel value 0 is * used to indicate an invalidated iterator (i.e., one that is @@ -92,7 +94,7 @@ namespace __gnu_debug : _M_sequence(0), _M_version(0), _M_prior(0), _M_next(0) { if (!std::__is_constant_evaluated()) - this->_M_attach(const_cast<_Safe_sequence_base*>(__seq), __constant); + this->_M_attach(__seq, __constant); } /** Initializes the iterator to reference the same sequence that @@ -115,7 +117,7 @@ namespace __gnu_debug /** For use in _Safe_iterator. */ __gnu_cxx::__mutex& - _M_get_mutex() throw (); + _M_get_mutex() _GLIBCXX_USE_NOEXCEPT; /** Attaches this iterator to the given sequence, detaching it * from whatever sequence it was attached to originally. If the @@ -123,11 +125,12 @@ namespace __gnu_debug * unattached. */ void - _M_attach(_Safe_sequence_base* __seq, bool __constant); + _M_attach(const _Safe_sequence_base* __seq, bool __constant); /** Likewise, but not thread-safe. */ void - _M_attach_single(_Safe_sequence_base* __seq, bool __constant) throw (); + _M_attach_single(const _Safe_sequence_base* __seq, + bool __constant) _GLIBCXX_USE_NOEXCEPT; /** Detach the iterator for whatever sequence it is attached to, * if any. @@ -135,10 +138,23 @@ namespace __gnu_debug void _M_detach(); +#if !_GLIBCXX_INLINE_VERSION + private: + /***************************************************************/ + /** Not-const method preserved for abi backward compatibility. */ + void + _M_attach(_Safe_sequence_base* __seq, bool __constant); + + void + _M_attach_single(_Safe_sequence_base* __seq, + bool __constant) _GLIBCXX_USE_NOEXCEPT; + /***************************************************************/ +#endif + public: /** Likewise, but not thread-safe. */ void - _M_detach_single() throw (); + _M_detach_single() _GLIBCXX_USE_NOEXCEPT; /** Determines if we are attached to the given sequence. */ bool @@ -147,13 +163,13 @@ namespace __gnu_debug /** Is this iterator singular? */ _GLIBCXX_PURE bool - _M_singular() const throw (); + _M_singular() const _GLIBCXX_USE_NOEXCEPT; /** Can we compare this iterator to the given iterator @p __x? Returns true if both iterators are nonsingular and reference the same sequence. */ _GLIBCXX_PURE bool - _M_can_compare(const _Safe_iterator_base& __x) const throw (); + _M_can_compare(const _Safe_iterator_base& __x) const _GLIBCXX_USE_NOEXCEPT; /** Invalidate the iterator, making it singular. */ void @@ -162,11 +178,11 @@ namespace __gnu_debug /** Reset all member variables */ void - _M_reset() throw (); + _M_reset() _GLIBCXX_USE_NOEXCEPT; /** Unlink itself */ void - _M_unlink() throw () + _M_unlink() _GLIBCXX_USE_NOEXCEPT { if (_M_prior) _M_prior->_M_next = _M_next; @@ -246,14 +262,14 @@ namespace __gnu_debug /** Detach all iterators, leaving them singular. */ void - _M_detach_all(); + _M_detach_all() const; /** Detach all singular iterators. * @post for all iterators i attached to this sequence, * i->_M_version == _M_version. */ void - _M_detach_singular(); + _M_detach_singular() const; /** Revalidates all attached singular iterators. This method may * be used to validate iterators that were invalidated before @@ -261,7 +277,7 @@ namespace __gnu_debug * valid again). */ void - _M_revalidate_singular(); + _M_revalidate_singular() const; /** Swap this sequence with the given sequence. This operation * also swaps ownership of the iterators, so that when the @@ -269,11 +285,11 @@ namespace __gnu_debug * one container now reference the other container. */ void - _M_swap(_Safe_sequence_base& __x) _GLIBCXX_USE_NOEXCEPT; + _M_swap(const _Safe_sequence_base& __x) const _GLIBCXX_USE_NOEXCEPT; /** For use in _Safe_sequence. */ __gnu_cxx::__mutex& - _M_get_mutex() throw (); + _M_get_mutex() const _GLIBCXX_USE_NOEXCEPT; /** Invalidates all iterators. */ void @@ -281,21 +297,42 @@ namespace __gnu_debug { if (++_M_version == 0) _M_version = 1; } private: +#if !_GLIBCXX_INLINE_VERSION + /***************************************************************/ + /** Not-const method preserved for abi backward compatibility. */ + void + _M_detach_all(); + + void + _M_detach_singular(); + + void + _M_revalidate_singular(); + + void + _M_swap(_Safe_sequence_base& __x) _GLIBCXX_USE_NOEXCEPT; + + __gnu_cxx::__mutex& + _M_get_mutex() _GLIBCXX_USE_NOEXCEPT; + /***************************************************************/ +#endif + /** Attach an iterator to this sequence. */ void - _M_attach(_Safe_iterator_base* __it, bool __constant); + _M_attach(_Safe_iterator_base* __it, bool __constant) const; /** Likewise but not thread safe. */ void - _M_attach_single(_Safe_iterator_base* __it, bool __constant) throw (); + _M_attach_single(_Safe_iterator_base* __it, + bool __constant) const _GLIBCXX_USE_NOEXCEPT; /** Detach an iterator from this sequence */ void - _M_detach(_Safe_iterator_base* __it); + _M_detach(_Safe_iterator_base* __it) const; /** Likewise but not thread safe. */ void - _M_detach_single(_Safe_iterator_base* __it) throw (); + _M_detach_single(_Safe_iterator_base* __it) const _GLIBCXX_USE_NOEXCEPT; }; } // namespace __gnu_debug diff --git a/libstdc++-v3/include/debug/safe_container.h b/libstdc++-v3/include/debug/safe_container.h index cb1e69a..3341806 100644 --- a/libstdc++-v3/include/debug/safe_container.h +++ b/libstdc++-v3/include/debug/safe_container.h @@ -44,9 +44,9 @@ namespace __gnu_debug typedef _SafeBase<_SafeContainer> _Base; _GLIBCXX20_CONSTEXPR - _SafeContainer& - _M_cont() _GLIBCXX_NOEXCEPT - { return *static_cast<_SafeContainer*>(this); } + const _SafeContainer& + _M_cont() const _GLIBCXX_NOEXCEPT + { return *static_cast<const _SafeContainer*>(this); } protected: #if __cplusplus >= 201103L @@ -56,6 +56,11 @@ namespace __gnu_debug private: _GLIBCXX20_CONSTEXPR + void + _M_swap_base(const _Safe_container& __x) const noexcept + { _Base::_M_swap(__x); } + + _GLIBCXX20_CONSTEXPR _Safe_container(_Safe_container&& __x, const _Alloc&, std::true_type) : _Safe_container(std::move(__x)) { } @@ -67,7 +72,7 @@ namespace __gnu_debug if (!std::__is_constant_evaluated()) { if (__x._M_cont().get_allocator() == __a) - _Base::_M_swap(__x); + _M_swap_base(__x); else __x._M_invalidate_all(); } @@ -115,12 +120,12 @@ namespace __gnu_debug bool __xfer_memory = _Alloc_traits::_S_propagate_on_move_assign() || _M_cont().get_allocator() == __x._M_cont().get_allocator(); if (__xfer_memory) - _Base::_M_swap(__x); + _M_swap_base(__x); else this->_M_invalidate_all(); } else - _Base::_M_swap(__x); + _M_swap_base(__x); __x._M_invalidate_all(); return *this; @@ -128,7 +133,7 @@ namespace __gnu_debug _GLIBCXX20_CONSTEXPR void - _M_swap(_Safe_container& __x) noexcept + _M_swap(const _Safe_container& __x) const noexcept { if (_IsCxx11AllocatorAware) { @@ -139,8 +144,12 @@ namespace __gnu_debug __x._M_cont()._M_base()); } - _Base::_M_swap(__x); + _M_swap_base(__x); } +#else + void + _M_swap(const _Safe_container& __x) const throw() + { _Base::_M_swap(__x); } #endif }; diff --git a/libstdc++-v3/include/debug/safe_iterator.h b/libstdc++-v3/include/debug/safe_iterator.h index 7c56338..e0b1b46 100644 --- a/libstdc++-v3/include/debug/safe_iterator.h +++ b/libstdc++-v3/include/debug/safe_iterator.h @@ -224,7 +224,7 @@ namespace __gnu_debug _M_message(__msg_init_copy_singular) ._M_iterator(*this, "this") ._M_iterator(__x, "other")); - _Safe_sequence_base* __seq = __x._M_sequence; + const _Safe_sequence_base* __seq = __x._M_sequence; __x._M_detach(); std::swap(base(), __x.base()); _M_attach(__seq); @@ -445,12 +445,12 @@ namespace __gnu_debug /** Attach iterator to the given sequence. */ void - _M_attach(_Safe_sequence_base* __seq) + _M_attach(const _Safe_sequence_base* __seq) { _Safe_base::_M_attach(__seq, _S_constant()); } /** Likewise, but not thread-safe. */ void - _M_attach_single(_Safe_sequence_base* __seq) + _M_attach_single(const _Safe_sequence_base* __seq) { _Safe_base::_M_attach_single(__seq, _S_constant()); } /// Is the iterator dereferenceable? @@ -500,7 +500,13 @@ namespace __gnu_debug typename __gnu_cxx::__conditional_type< _IsConstant::__value, const _Sequence*, _Sequence*>::__type _M_get_sequence() const - { return static_cast<_Sequence*>(_M_sequence); } + { + // Looks like not const-correct, but if _IsConstant the constness + // is restored when returning the sequence pointer and if not + // _IsConstant we are allowed to remove constness. + return static_cast<_Sequence*> + (const_cast<_Safe_sequence_base*>(_M_sequence)); + } // Get distance to __rhs. typename _Distance_traits<_Iterator>::__type diff --git a/libstdc++-v3/include/debug/safe_local_iterator.h b/libstdc++-v3/include/debug/safe_local_iterator.h index c84f4f1..47b3a80 100644 --- a/libstdc++-v3/include/debug/safe_local_iterator.h +++ b/libstdc++-v3/include/debug/safe_local_iterator.h @@ -52,15 +52,15 @@ namespace __gnu_debug /** \brief Safe iterator wrapper. * * The class template %_Safe_local_iterator is a wrapper around an - * iterator that tracks the iterator's movement among sequences and - * checks that operations performed on the "safe" iterator are + * iterator that tracks the iterator's movement among unordered containers + * and checks that operations performed on the "safe" iterator are * legal. In additional to the basic iterator operations (which are * validated, and then passed to the underlying iterator), * %_Safe_local_iterator has member functions for iterator invalidation, - * attaching/detaching the iterator from sequences, and querying + * attaching/detaching the iterator from unordered containers, and querying * the iterator's state. */ - template<typename _Iterator, typename _Sequence> + template<typename _Iterator, typename _UContainer> class _Safe_local_iterator : private _Iterator , public _Safe_local_iterator_base @@ -68,28 +68,27 @@ namespace __gnu_debug typedef _Iterator _Iter_base; typedef _Safe_local_iterator_base _Safe_base; - typedef typename _Sequence::size_type size_type; + typedef typename _UContainer::size_type size_type; typedef std::iterator_traits<_Iterator> _Traits; - typedef std::__are_same< - typename _Sequence::_Base::const_local_iterator, - _Iterator> _IsConstant; + using _IsConstant = std::__are_same< + typename _UContainer::_Base::const_local_iterator, _Iterator>; - typedef typename __gnu_cxx::__conditional_type<_IsConstant::__value, - typename _Sequence::_Base::local_iterator, - typename _Sequence::_Base::const_local_iterator>::__type - _OtherIterator; + using _OtherIterator = std::__conditional_t< + _IsConstant::__value, + typename _UContainer::_Base::local_iterator, + typename _UContainer::_Base::const_local_iterator>; typedef _Safe_local_iterator _Self; - typedef _Safe_local_iterator<_OtherIterator, _Sequence> _OtherSelf; + typedef _Safe_local_iterator<_OtherIterator, _UContainer> _OtherSelf; struct _Unchecked { }; _Safe_local_iterator(const _Safe_local_iterator& __x, _Unchecked) noexcept : _Iter_base(__x.base()) - { _M_attach(__x._M_sequence); } + { _M_attach(__x._M_safe_container()); } public: typedef _Iterator iterator_type; @@ -104,12 +103,13 @@ namespace __gnu_debug /** * @brief Safe iterator construction from an unsafe iterator and - * its sequence. + * its unordered container. * - * @pre @p seq is not NULL + * @pre @p cont is not NULL * @post this is not singular */ - _Safe_local_iterator(_Iterator __i, const _Safe_sequence_base* __cont) + _Safe_local_iterator(_Iterator __i, + const _Safe_unordered_container_base* __cont) : _Iter_base(__i), _Safe_base(__cont, _S_constant()) { } @@ -126,7 +126,7 @@ namespace __gnu_debug _M_message(__msg_init_copy_singular) ._M_iterator(*this, "this") ._M_iterator(__x, "other")); - _M_attach(__x._M_sequence); + _M_attach(__x._M_safe_container()); } /** @@ -141,7 +141,7 @@ namespace __gnu_debug _M_message(__msg_init_copy_singular) ._M_iterator(*this, "this") ._M_iterator(__x, "other")); - auto __cont = __x._M_sequence; + auto __cont = __x._M_safe_container(); __x._M_detach(); std::swap(base(), __x.base()); _M_attach(__cont); @@ -156,7 +156,7 @@ namespace __gnu_debug const _Safe_local_iterator<_MutableIterator, typename __gnu_cxx::__enable_if<_IsConstant::__value && std::__are_same<_MutableIterator, _OtherIterator>::__value, - _Sequence>::__type>& __x) noexcept + _UContainer>::__type>& __x) noexcept : _Iter_base(__x.base()) { // _GLIBCXX_RESOLVE_LIB_DEFECTS @@ -166,7 +166,7 @@ namespace __gnu_debug _M_message(__msg_init_const_singular) ._M_iterator(*this, "this") ._M_iterator(__x, "other")); - _M_attach(__x._M_sequence); + _M_attach(__x._M_safe_container()); } /** @@ -193,7 +193,7 @@ namespace __gnu_debug { _M_detach(); base() = __x.base(); - _M_attach(__x._M_sequence); + _M_attach(__x._M_safe_container()); } return *this; @@ -225,7 +225,7 @@ namespace __gnu_debug { _M_detach(); base() = __x.base(); - _M_attach(__x._M_sequence); + _M_attach(__x._M_safe_container()); } __x._M_detach(); @@ -318,15 +318,15 @@ namespace __gnu_debug */ operator _Iterator() const { return *this; } - /** Attach iterator to the given sequence. */ + /** Attach iterator to the given unordered container. */ void - _M_attach(_Safe_sequence_base* __seq) - { _Safe_base::_M_attach(__seq, _S_constant()); } + _M_attach(const _Safe_unordered_container_base* __cont) + { _Safe_base::_M_attach(__cont, _S_constant()); } /** Likewise, but not thread-safe. */ void - _M_attach_single(_Safe_sequence_base* __seq) - { _Safe_base::_M_attach_single(__seq, _S_constant()); } + _M_attach_single(const _Safe_unordered_container_base* __cont) + { _Safe_base::_M_attach_single(__cont, _S_constant()); } /// Is the iterator dereferenceable? bool @@ -353,25 +353,31 @@ namespace __gnu_debug typename _Distance_traits<_Iterator>::__type _M_get_distance_to(const _Safe_local_iterator& __rhs) const; - // The sequence this iterator references. - typename __gnu_cxx::__conditional_type< - _IsConstant::__value, const _Sequence*, _Sequence*>::__type - _M_get_sequence() const - { return static_cast<_Sequence*>(_M_sequence); } + // The unordered container this iterator references. + std::__conditional_t< + _IsConstant::__value, const _UContainer*, _UContainer*> + _M_get_ucontainer() const + { + // Looks like not const-correct, but if _IsConstant the constness + // is restored when returning the container pointer and if not + // _IsConstant we are allowed to remove constness. + return static_cast<_UContainer*> + (const_cast<_Safe_unordered_container_base*>(_M_safe_container())); + } - /// Is this iterator equal to the sequence's begin(bucket) iterator? + /// Is this iterator equal to the container's begin(bucket) iterator? bool _M_is_begin() const - { return base() == _M_get_sequence()->_M_base().begin(bucket()); } + { return base() == _M_get_ucontainer()->_M_base().begin(bucket()); } - /// Is this iterator equal to the sequence's end(bucket) iterator? + /// Is this iterator equal to the container's end(bucket) iterator? bool _M_is_end() const - { return base() == _M_get_sequence()->_M_base().end(bucket()); } + { return base() == _M_get_ucontainer()->_M_base().end(bucket()); } /// Is this iterator part of the same bucket as the other one? template<typename _Other> bool _M_in_same_bucket(const _Safe_local_iterator<_Other, - _Sequence>& __other) const + _UContainer>& __other) const { return bucket() == __other.bucket(); } friend inline bool @@ -404,31 +410,31 @@ namespace __gnu_debug }; /** Safe local iterators know how to check if they form a valid range. */ - template<typename _Iterator, typename _Sequence> + template<typename _Iterator, typename _UContainer> inline bool - __valid_range(const _Safe_local_iterator<_Iterator, _Sequence>& __first, - const _Safe_local_iterator<_Iterator, _Sequence>& __last, + __valid_range(const _Safe_local_iterator<_Iterator, _UContainer>& __first, + const _Safe_local_iterator<_Iterator, _UContainer>& __last, typename _Distance_traits<_Iterator>::__type& __dist_info) { return __first._M_valid_range(__last, __dist_info); } - template<typename _Iterator, typename _Sequence> + template<typename _Iterator, typename _UContainer> inline bool - __valid_range(const _Safe_local_iterator<_Iterator, _Sequence>& __first, - const _Safe_local_iterator<_Iterator, _Sequence>& __last) + __valid_range(const _Safe_local_iterator<_Iterator, _UContainer>& __first, + const _Safe_local_iterator<_Iterator, _UContainer>& __last) { typename _Distance_traits<_Iterator>::__type __dist_info; return __first._M_valid_range(__last, __dist_info); } #if __cplusplus < 201103L - template<typename _Iterator, typename _Sequence> - struct _Unsafe_type<_Safe_local_iterator<_Iterator, _Sequence> > + template<typename _Iterator, typename _UContainer> + struct _Unsafe_type<_Safe_local_iterator<_Iterator, _UContainer> > { typedef _Iterator _Type; }; #endif - template<typename _Iterator, typename _Sequence> + template<typename _Iterator, typename _UContainer> inline _Iterator - __unsafe(const _Safe_local_iterator<_Iterator, _Sequence>& __it) + __unsafe(const _Safe_local_iterator<_Iterator, _UContainer>& __it) { return __it.base(); } } // namespace __gnu_debug diff --git a/libstdc++-v3/include/debug/safe_local_iterator.tcc b/libstdc++-v3/include/debug/safe_local_iterator.tcc index 71e5320..10fec3f 100644 --- a/libstdc++-v3/include/debug/safe_local_iterator.tcc +++ b/libstdc++-v3/include/debug/safe_local_iterator.tcc @@ -44,7 +44,7 @@ namespace __gnu_debug if (__rhs._M_is_end()) return { - _M_get_sequence()->bucket_size(bucket()), + _M_get_ucontainer()->bucket_size(bucket()), __dp_exact }; @@ -56,7 +56,7 @@ namespace __gnu_debug if (__rhs._M_is_begin()) return { - -_M_get_sequence()->bucket_size(bucket()), + -_M_get_ucontainer()->bucket_size(bucket()), __dp_exact }; diff --git a/libstdc++-v3/include/debug/safe_sequence.h b/libstdc++-v3/include/debug/safe_sequence.h index 6b35afa..e10474a 100644 --- a/libstdc++-v3/include/debug/safe_sequence.h +++ b/libstdc++-v3/include/debug/safe_sequence.h @@ -114,7 +114,7 @@ namespace __gnu_debug in the safe ones. */ template<typename _Predicate> void - _M_invalidate_if(_Predicate __pred); + _M_invalidate_if(_Predicate __pred) const; /** Transfers all iterators @c x that reference @c from sequence, are not singular, and for which @c __pred(x) returns @c @@ -122,7 +122,8 @@ namespace __gnu_debug in the safe ones. */ template<typename _Predicate> void - _M_transfer_from_if(_Safe_sequence& __from, _Predicate __pred); + _M_transfer_from_if(const _Safe_sequence& __from, + _Predicate __pred) const; }; /// Like _Safe_sequence but with a special _M_invalidate_all implementation @@ -133,12 +134,12 @@ namespace __gnu_debug { protected: void - _M_invalidate_all() + _M_invalidate_all() const { typedef typename _Sequence::const_iterator _Const_iterator; typedef typename _Const_iterator::iterator_type _Base_const_iterator; typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal; - const _Sequence& __seq = *static_cast<_Sequence*>(this); + const _Sequence& __seq = *static_cast<const _Sequence*>(this); this->_M_invalidate_if(_Not_equal(__seq._M_base().end())); } }; diff --git a/libstdc++-v3/include/debug/safe_sequence.tcc b/libstdc++-v3/include/debug/safe_sequence.tcc index 336bf2a..053361d 100644 --- a/libstdc++-v3/include/debug/safe_sequence.tcc +++ b/libstdc++-v3/include/debug/safe_sequence.tcc @@ -35,7 +35,7 @@ namespace __gnu_debug template<typename _Predicate> void _Safe_sequence<_Sequence>:: - _M_invalidate_if(_Predicate __pred) + _M_invalidate_if(_Predicate __pred) const { typedef typename _Sequence::iterator iterator; typedef typename _Sequence::const_iterator const_iterator; @@ -66,7 +66,7 @@ namespace __gnu_debug template<typename _Predicate> void _Safe_sequence<_Sequence>:: - _M_transfer_from_if(_Safe_sequence& __from, _Predicate __pred) + _M_transfer_from_if(const _Safe_sequence& __from, _Predicate __pred) const { if (this == std::__addressof(__from)) return; @@ -104,7 +104,7 @@ namespace __gnu_debug } for (_Safe_iterator_base* __iter2 = __from._M_const_iterators; - __iter2;) + __iter2;) { _Safe_iterator_base* __victim_base = __iter2; const_iterator* __victim = diff --git a/libstdc++-v3/include/debug/safe_unordered_base.h b/libstdc++-v3/include/debug/safe_unordered_base.h index 1547f5b..55cf581 100644 --- a/libstdc++-v3/include/debug/safe_unordered_base.h +++ b/libstdc++-v3/include/debug/safe_unordered_base.h @@ -49,6 +49,10 @@ namespace __gnu_debug */ class _Safe_local_iterator_base : public _Safe_iterator_base { + public: + const _Safe_unordered_container_base* + _M_safe_container() const noexcept; + protected: /** Initializes the iterator and makes it singular. */ _Safe_local_iterator_base() @@ -61,32 +65,32 @@ namespace __gnu_debug * singular. Otherwise, the iterator will reference @p __seq and * be nonsingular. */ - _Safe_local_iterator_base(const _Safe_sequence_base* __seq, bool __constant) - { this->_M_attach(const_cast<_Safe_sequence_base*>(__seq), __constant); } + _Safe_local_iterator_base(const _Safe_unordered_container_base* __seq, + bool __constant) + { _M_attach(__seq, __constant); } /** Initializes the iterator to reference the same container that @p __x does. @p __constant is true if this is a constant iterator, and false if it is mutable. */ _Safe_local_iterator_base(const _Safe_local_iterator_base& __x, bool __constant) - { this->_M_attach(__x._M_sequence, __constant); } + { this->_M_attach(__x._M_safe_container(), __constant); } ~_Safe_local_iterator_base() { this->_M_detach(); } - _Safe_unordered_container_base* - _M_get_container() const noexcept; - /** Attaches this iterator to the given container, detaching it * from whatever container it was attached to originally. If the * new container is the NULL pointer, the iterator is left * unattached. */ void - _M_attach(_Safe_sequence_base* __seq, bool __constant); + _M_attach(const _Safe_unordered_container_base* __cont, + bool __constant); /** Likewise, but not thread-safe. */ void - _M_attach_single(_Safe_sequence_base* __seq, bool __constant) throw (); + _M_attach_single(const _Safe_unordered_container_base* __cont, + bool __constant) noexcept; /** Detach the iterator for whatever container it is attached to, * if any. @@ -96,7 +100,19 @@ namespace __gnu_debug /** Likewise, but not thread-safe. */ void - _M_detach_single() throw (); + _M_detach_single() noexcept; + +#if !_GLIBCXX_INLINE_VERSION + private: + /***************************************************************/ + /** Not-const method preserved for abi backward compatibility. */ + void + _M_attach(_Safe_sequence_base* __seq, bool __constant); + + void + _M_attach_single(_Safe_sequence_base* __seq, bool __constant) noexcept; + /***************************************************************/ +#endif }; /** @@ -124,10 +140,10 @@ namespace __gnu_debug public: /// The list of mutable local iterators that reference this container - _Safe_iterator_base* _M_local_iterators; + mutable _Safe_iterator_base* _M_local_iterators; /// The list of constant local iterators that reference this container - _Safe_iterator_base* _M_const_local_iterators; + mutable _Safe_iterator_base* _M_const_local_iterators; protected: // Initialize with a version number of 1 and no iterators @@ -153,7 +169,7 @@ namespace __gnu_debug /** Detach all iterators, leaving them singular. */ void - _M_detach_all(); + _M_detach_all() const; /** Swap this container with the given container. This operation * also swaps ownership of the iterators, so that when the @@ -161,25 +177,42 @@ namespace __gnu_debug * one container now reference the other container. */ void - _M_swap(_Safe_unordered_container_base& __x) noexcept; + _M_swap(const _Safe_unordered_container_base& __x) const noexcept; private: +#if !_GLIBCXX_INLINE_VERSION + /***************************************************************/ + /** Not-const method preserved for abi backward compatibility. */ + void + _M_detach_all(); + + void + _M_swap(_Safe_unordered_container_base& __x) noexcept; + /***************************************************************/ +#endif + /** Attach an iterator to this container. */ void - _M_attach_local(_Safe_iterator_base* __it, bool __constant); + _M_attach_local(_Safe_iterator_base* __it, bool __constant) const; /** Likewise but not thread safe. */ void - _M_attach_local_single(_Safe_iterator_base* __it, bool __constant) throw (); + _M_attach_local_single(_Safe_iterator_base* __it, + bool __constant) const noexcept; /** Detach an iterator from this container */ void - _M_detach_local(_Safe_iterator_base* __it); + _M_detach_local(_Safe_iterator_base* __it) const; /** Likewise but not thread safe. */ void - _M_detach_local_single(_Safe_iterator_base* __it) throw (); + _M_detach_local_single(_Safe_iterator_base* __it) const noexcept; }; + + inline const _Safe_unordered_container_base* + _Safe_local_iterator_base:: + _M_safe_container() const noexcept + { return static_cast<const _Safe_unordered_container_base*>(_M_sequence); } } // namespace __gnu_debug #endif diff --git a/libstdc++-v3/include/debug/safe_unordered_container.h b/libstdc++-v3/include/debug/safe_unordered_container.h index 2ba27db..b67b7e0 100644 --- a/libstdc++-v3/include/debug/safe_unordered_container.h +++ b/libstdc++-v3/include/debug/safe_unordered_container.h @@ -62,6 +62,10 @@ namespace __gnu_debug _M_cont() noexcept { return *static_cast<_Container*>(this); } + const _Safe_unordered_container* + _M_self() const + { return this; } + protected: void _M_invalidate_locals() diff --git a/libstdc++-v3/include/debug/safe_unordered_container.tcc b/libstdc++-v3/include/debug/safe_unordered_container.tcc index 6819389..0732e63 100644 --- a/libstdc++-v3/include/debug/safe_unordered_container.tcc +++ b/libstdc++-v3/include/debug/safe_unordered_container.tcc @@ -40,7 +40,7 @@ namespace __gnu_debug typedef typename _Container::iterator iterator; typedef typename _Container::const_iterator const_iterator; - __gnu_cxx::__scoped_lock sentry(this->_M_get_mutex()); + __gnu_cxx::__scoped_lock sentry(_M_self()->_M_get_mutex()); for (_Safe_iterator_base* __iter = _M_iterators; __iter;) { iterator* __victim = static_cast<iterator*>(__iter); @@ -72,7 +72,7 @@ namespace __gnu_debug typedef typename _Container::local_iterator local_iterator; typedef typename _Container::const_local_iterator const_local_iterator; - __gnu_cxx::__scoped_lock sentry(this->_M_get_mutex()); + __gnu_cxx::__scoped_lock sentry(_M_self()->_M_get_mutex()); for (_Safe_iterator_base* __iter = _M_local_iterators; __iter;) { local_iterator* __victim = static_cast<local_iterator*>(__iter); diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format index 46bd5d5..d584b81 100644 --- a/libstdc++-v3/include/std/format +++ b/libstdc++-v3/include/std/format @@ -2998,11 +2998,9 @@ namespace __format }; #endif -#if defined(__SIZEOF_FLOAT128__) && _GLIBCXX_FORMAT_F128 > 1 - // Reuse __formatter_fp<C>::format<__format::__flt128_t, Out> for __float128. - // This formatter is not declared if _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT is true, - // as __float128 when present is same type as __ieee128, which may be same as - // long double. +#if defined(__SIZEOF_FLOAT128__) && _GLIBCXX_FORMAT_F128 == 2 + // Use __formatter_fp<C>::format<__format::__flt128_t, Out> for __float128, + // when long double is not 128bit IEEE type. template<__format::__char _CharT> struct formatter<__float128, _CharT> { @@ -3020,9 +3018,6 @@ namespace __format private: __format::__formatter_fp<_CharT> _M_f; - - static_assert( !is_same_v<__float128, long double>, - "This specialization should not be used for long double" ); }; #endif @@ -6035,13 +6030,13 @@ namespace __format constexpr void set_separator(basic_string_view<_CharT> __sep) noexcept - requires (!_S_range_format_is_string) + requires (format_kind<_Rg> == range_format::sequence) { _M_under.set_separator(__sep); } constexpr void set_brackets(basic_string_view<_CharT> __open, basic_string_view<_CharT> __close) noexcept - requires (!_S_range_format_is_string) + requires (format_kind<_Rg> == range_format::sequence) { _M_under.set_brackets(__open, __close); } // We deviate from standard, that declares this as template accepting diff --git a/libstdc++-v3/include/std/mdspan b/libstdc++-v3/include/std/mdspan index c72a640..b34116a 100644 --- a/libstdc++-v3/include/std/mdspan +++ b/libstdc++-v3/include/std/mdspan @@ -111,9 +111,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template<size_t _OtherRank, typename _GetOtherExtent> + static constexpr bool + _S_is_compatible_extents(_GetOtherExtent __get_extent) noexcept + { + if constexpr (_OtherRank == _S_rank) + for (size_t __i = 0; __i < _S_rank; ++__i) + if (_Extents[__i] != dynamic_extent + && !cmp_equal(_Extents[__i], _S_int_cast(__get_extent(__i)))) + return false; + return true; + } + + template<size_t _OtherRank, typename _GetOtherExtent> constexpr void _M_init_dynamic_extents(_GetOtherExtent __get_extent) noexcept { + __glibcxx_assert(_S_is_compatible_extents<_OtherRank>(__get_extent)); for (size_t __i = 0; __i < _S_rank_dynamic; ++__i) { size_t __di = __i; @@ -385,13 +398,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __rev_prod(const _Extents& __exts, size_t __r) noexcept { return __exts_prod(__exts, __r + 1, __exts.rank()); } + template<typename _Extents> + constexpr typename _Extents::index_type + __size(const _Extents& __exts) noexcept + { return __fwd_prod(__exts, __exts.rank()); } + template<typename _IndexType, size_t... _Counts> auto __build_dextents_type(integer_sequence<size_t, _Counts...>) -> extents<_IndexType, ((void) _Counts, dynamic_extent)...>; - - template<typename _Tp> - consteval size_t - __dynamic_extent() { return dynamic_extent; } } template<typename _IndexType, size_t _Rank> @@ -401,7 +415,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename... _Integrals> requires (is_convertible_v<_Integrals, size_t> && ...) explicit extents(_Integrals...) -> - extents<size_t, __mdspan::__dynamic_extent<_Integrals>()...>; + extents<size_t, __detail::__maybe_static_ext<_Integrals>...>; struct layout_left { @@ -441,6 +455,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _IndexType __mult = 1; auto __update = [&, __pos = 0u](_IndexType __idx) mutable { + _GLIBCXX_DEBUG_ASSERT(cmp_less(__idx, __exts.extent(__pos))); __res += __idx * __mult; __mult *= __exts.extent(__pos); ++__pos; @@ -509,7 +524,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Layout, typename _Mapping> concept __mapping_of = - is_same_v<typename _Layout::mapping<typename _Mapping::extents_type>, + is_same_v<typename _Layout::template mapping<typename _Mapping::extents_type>, _Mapping>; template<typename _Mapping> @@ -577,7 +592,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr index_type required_span_size() const noexcept - { return __mdspan::__fwd_prod(_M_extents, extents_type::rank()); } + { return __mdspan::__size(_M_extents); } template<__mdspan::__valid_index_type<index_type>... _Indices> requires (sizeof...(_Indices) == extents_type::rank()) @@ -651,6 +666,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION auto __update = [&, __pos = __exts.rank()](_IndexType) mutable { --__pos; + _GLIBCXX_DEBUG_ASSERT(cmp_less(__ind_arr[__pos], + __exts.extent(__pos))); __res += __ind_arr[__pos] * __mult; __mult *= __exts.extent(__pos); }; @@ -714,7 +731,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr index_type required_span_size() const noexcept - { return __mdspan::__fwd_prod(_M_extents, extents_type::rank()); } + { return __mdspan::__size(_M_extents); } template<__mdspan::__valid_index_type<index_type>... _Indices> requires (sizeof...(_Indices) == extents_type::rank()) @@ -822,6 +839,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { auto __update = [&, __pos = 0u](_IndexType __idx) mutable { + _GLIBCXX_DEBUG_ASSERT(cmp_less(__idx, + __m.extents().extent(__pos))); __res += __idx * __m.stride(__pos++); }; (__update(__indices), ...); @@ -968,8 +987,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { if constexpr (!is_always_exhaustive()) { - constexpr auto __rank = extents_type::rank(); - auto __size = __mdspan::__fwd_prod(_M_extents, __rank); + auto __size = __mdspan::__size(_M_extents); if(__size > 0) return __size == required_span_size(); } @@ -1035,6 +1053,291 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __p + __i; } }; + namespace __mdspan + { + template<typename _Extents, typename _IndexType, size_t _Nm> + constexpr bool + __is_multi_index(const _Extents& __exts, span<_IndexType, _Nm> __indices) + { + static_assert(__exts.rank() == _Nm); + for (size_t __i = 0; __i < __exts.rank(); ++__i) + if (__indices[__i] >= __exts.extent(__i)) + return false; + return true; + } + } + + template<typename _ElementType, typename _Extents, + typename _LayoutPolicy = layout_right, + typename _AccessorPolicy = default_accessor<_ElementType>> + class mdspan + { + static_assert(!is_array_v<_ElementType>, + "ElementType must not be an array type"); + static_assert(!is_abstract_v<_ElementType>, + "ElementType must not be an abstract class type"); + static_assert(__mdspan::__is_extents<_Extents>, + "Extents must be a specialization of std::extents"); + static_assert(is_same_v<_ElementType, + typename _AccessorPolicy::element_type>); + + public: + using extents_type = _Extents; + using layout_type = _LayoutPolicy; + using accessor_type = _AccessorPolicy; + using mapping_type = typename layout_type::template mapping<extents_type>; + using element_type = _ElementType; + using value_type = remove_cv_t<element_type>; + using index_type = typename extents_type::index_type; + using size_type = typename extents_type::size_type; + using rank_type = typename extents_type::rank_type; + using data_handle_type = typename accessor_type::data_handle_type; + using reference = typename accessor_type::reference; + + static constexpr rank_type + rank() noexcept { return extents_type::rank(); } + + static constexpr rank_type + rank_dynamic() noexcept { return extents_type::rank_dynamic(); } + + static constexpr size_t + static_extent(rank_type __r) noexcept + { return extents_type::static_extent(__r); } + + constexpr index_type + extent(rank_type __r) const noexcept { return extents().extent(__r); } + + constexpr + mdspan() + requires (rank_dynamic() > 0) + && is_default_constructible_v<data_handle_type> + && is_default_constructible_v<mapping_type> + && is_default_constructible_v<accessor_type> + : _M_accessor(), _M_mapping(), _M_handle() + { } + + constexpr + mdspan(const mdspan& __other) = default; + + constexpr + mdspan(mdspan&& __other) = default; + + template<__mdspan::__valid_index_type<index_type>... _OIndexTypes> + requires (sizeof...(_OIndexTypes) == rank() + || sizeof...(_OIndexTypes) == rank_dynamic()) + && is_constructible_v<mapping_type, extents_type> + && is_default_constructible_v<accessor_type> + constexpr explicit + mdspan(data_handle_type __handle, _OIndexTypes... __exts) + : _M_accessor(), + _M_mapping(_Extents(static_cast<index_type>(std::move(__exts))...)), + _M_handle(std::move(__handle)) + { } + + template<__mdspan::__valid_index_type<index_type> _OIndexType, + size_t _Nm> + requires (_Nm == rank() || _Nm == rank_dynamic()) + && is_constructible_v<mapping_type, extents_type> + && is_default_constructible_v<accessor_type> + constexpr explicit(_Nm != rank_dynamic()) + mdspan(data_handle_type __handle, span<_OIndexType, _Nm> __exts) + : _M_accessor(), _M_mapping(extents_type(__exts)), + _M_handle(std::move(__handle)) + { } + + template<__mdspan::__valid_index_type<index_type> _OIndexType, + size_t _Nm> + requires (_Nm == rank() || _Nm == rank_dynamic()) + && is_constructible_v<mapping_type, extents_type> + && is_default_constructible_v<accessor_type> + constexpr explicit(_Nm != rank_dynamic()) + mdspan(data_handle_type __handle, const array<_OIndexType, _Nm>& __exts) + : _M_accessor(), _M_mapping(extents_type(__exts)), + _M_handle(std::move(__handle)) + { } + + constexpr + mdspan(data_handle_type __handle, const extents_type& __exts) + requires is_constructible_v<mapping_type, const extents_type&> + && is_default_constructible_v<accessor_type> + : _M_accessor(), _M_mapping(__exts), _M_handle(std::move(__handle)) + { } + + constexpr + mdspan(data_handle_type __handle, const mapping_type& __mapping) + requires is_default_constructible_v<accessor_type> + : _M_accessor(), _M_mapping(__mapping), _M_handle(std::move(__handle)) + { } + + constexpr + mdspan(data_handle_type __handle, const mapping_type& __mapping, + const accessor_type& __accessor) + : _M_accessor(__accessor), _M_mapping(__mapping), + _M_handle(std::move(__handle)) + { } + + template<typename _OElementType, typename _OExtents, typename _OLayout, + typename _OAccessor> + requires is_constructible_v<mapping_type, + const typename _OLayout::template mapping<_OExtents>&> + && is_constructible_v<accessor_type, const _OAccessor&> + constexpr explicit(!is_convertible_v< + const typename _OLayout::template mapping<_OExtents>&, mapping_type> + || !is_convertible_v<const _OAccessor&, accessor_type>) + mdspan(const mdspan<_OElementType, _OExtents, _OLayout, _OAccessor>& + __other) + : _M_accessor(__other.accessor()), _M_mapping(__other.mapping()), + _M_handle(__other.data_handle()) + { + static_assert(is_constructible_v<data_handle_type, + const typename _OAccessor::data_handle_type&>); + static_assert(is_constructible_v<extents_type, _OExtents>); + } + + constexpr mdspan& + operator=(const mdspan& __other) = default; + + constexpr mdspan& + operator=(mdspan&& __other) = default; + + template<__mdspan::__valid_index_type<index_type>... _OIndexTypes> + requires (sizeof...(_OIndexTypes) == rank()) + constexpr reference + operator[](_OIndexTypes... __indices) const + { + auto __checked_call = [this](auto... __idxs) -> index_type + { + if constexpr (sizeof...(__idxs) > 0) + __glibcxx_assert(__mdspan::__is_multi_index(extents(), + span<const index_type, sizeof...(__idxs)>({__idxs...}))); + return _M_mapping(__idxs...); + }; + + auto __index = __checked_call( + static_cast<index_type>(std::move(__indices))...); + return _M_accessor.access(_M_handle, __index); + } + + template<__mdspan::__valid_index_type<index_type> _OIndexType> + constexpr reference + operator[](span<_OIndexType, rank()> __indices) const + { + auto __call = [&]<size_t... _Counts>(index_sequence<_Counts...>) + -> reference + { return (*this)[index_type(as_const(__indices[_Counts]))...]; }; + return __call(make_index_sequence<rank()>()); + } + + template<__mdspan::__valid_index_type<index_type> _OIndexType> + constexpr reference + operator[](const array<_OIndexType, rank()>& __indices) const + { return (*this)[span<const _OIndexType, rank()>(__indices)]; } + + constexpr size_type + size() const noexcept + { + __glibcxx_assert(cmp_less_equal(_M_mapping.required_span_size(), + numeric_limits<size_t>::max())); + return size_type(__mdspan::__size(extents())); + } + + [[nodiscard]] + constexpr bool + empty() const noexcept + { + return __mdspan::__empty(extents()); + } + + friend constexpr void + swap(mdspan& __x, mdspan& __y) noexcept + { + using std::swap; + swap(__x._M_mapping, __y._M_mapping); + swap(__x._M_accessor, __y._M_accessor); + swap(__x._M_handle, __y._M_handle); + } + + constexpr const extents_type& + extents() const noexcept { return _M_mapping.extents(); } + + constexpr const data_handle_type& + data_handle() const noexcept { return _M_handle; } + + constexpr const mapping_type& + mapping() const noexcept { return _M_mapping; } + + constexpr const accessor_type& + accessor() const noexcept { return _M_accessor; } + + static constexpr bool + is_always_unique() { return mapping_type::is_always_unique(); } + + static constexpr bool + is_always_exhaustive() { return mapping_type::is_always_exhaustive(); } + + static constexpr bool + is_always_strided() { return mapping_type::is_always_strided(); } + + constexpr bool + is_unique() const { return _M_mapping.is_unique(); } + + constexpr bool + is_exhaustive() const { return _M_mapping.is_exhaustive(); } + + constexpr bool + is_strided() const { return _M_mapping. is_strided(); } + + constexpr index_type + stride(rank_type __r) const { return _M_mapping.stride(__r); } + + private: + [[no_unique_address]] accessor_type _M_accessor; + [[no_unique_address]] mapping_type _M_mapping; + [[no_unique_address]] data_handle_type _M_handle; + }; + + template<typename _CArray> + requires is_array_v<_CArray> && (rank_v<_CArray> == 1) + mdspan(_CArray&) + -> mdspan<remove_all_extents_t<_CArray>, + extents<size_t, extent_v<_CArray, 0>>>; + + template<typename _Pointer> + requires is_pointer_v<remove_reference_t<_Pointer>> + mdspan(_Pointer&&) + -> mdspan<remove_pointer_t<remove_reference_t<_Pointer>>, extents<size_t>>; + + template<typename _ElementType, typename... _Integrals> + requires (is_convertible_v<_Integrals, size_t> && ...) + && (sizeof...(_Integrals) > 0) + explicit mdspan(_ElementType*, _Integrals...) + -> mdspan<_ElementType, + extents<size_t, __detail::__maybe_static_ext<_Integrals>...>>; + + template<typename _ElementType, typename _OIndexType, size_t _Nm> + mdspan(_ElementType*, span<_OIndexType, _Nm>) + -> mdspan<_ElementType, dextents<size_t, _Nm>>; + + template<typename _ElementType, typename _OIndexType, size_t _Nm> + mdspan(_ElementType*, const array<_OIndexType, _Nm>&) + -> mdspan<_ElementType, dextents<size_t, _Nm>>; + + template<typename _ElementType, typename _IndexType, size_t... _ExtentsPack> + mdspan(_ElementType*, const extents<_IndexType, _ExtentsPack...>&) + -> mdspan<_ElementType, extents<_IndexType, _ExtentsPack...>>; + + template<typename _ElementType, typename _MappingType> + mdspan(_ElementType*, const _MappingType&) + -> mdspan<_ElementType, typename _MappingType::extents_type, + typename _MappingType::layout_type>; + + template<typename _MappingType, typename _AccessorType> + mdspan(const typename _AccessorType::data_handle_type&, const _MappingType&, + const _AccessorType&) + -> mdspan<typename _AccessorType::element_type, + typename _MappingType::extents_type, + typename _MappingType::layout_type, _AccessorType>; + _GLIBCXX_END_NAMESPACE_VERSION } #endif diff --git a/libstdc++-v3/include/std/memory b/libstdc++-v3/include/std/memory index 1da03b3..763a57e 100644 --- a/libstdc++-v3/include/std/memory +++ b/libstdc++-v3/include/std/memory @@ -121,6 +121,7 @@ #define __glibcxx_want_smart_ptr_for_overwrite #define __glibcxx_want_to_address #define __glibcxx_want_transparent_operators +#define __glibcxx_want_smart_ptr_owner_equality #include <bits/version.h> #if __cplusplus >= 201103L && __cplusplus <= 202002L && _GLIBCXX_HOSTED diff --git a/libstdc++-v3/include/std/queue b/libstdc++-v3/include/std/queue index 9052589..1b76088 100644 --- a/libstdc++-v3/include/std/queue +++ b/libstdc++-v3/include/std/queue @@ -105,7 +105,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return _M_f.format(__a.c, __fc); } private: - // Standard uses formatter<ref_view<_Container>, _CharT>. + // Standard uses formatter<ref_view<_Container>, _CharT>, but range_formatter + // provides same behavior. + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3881. Incorrect formatting of container adapters backed by std::string range_formatter<_Tp, _CharT> _M_f; }; @@ -136,7 +139,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return _M_f.format(__a.c, __fc); } private: - // Standard uses formatter<ref_view<_Container>, _CharT>. + // Standard uses formatter<ref_view<_Container>, _CharT>, but range_formatter + // provides same behavior. + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3881. Incorrect formatting of container adapters backed by std::string range_formatter<_Tp, _CharT> _M_f; }; diff --git a/libstdc++-v3/include/std/span b/libstdc++-v3/include/std/span index 49ab910..44f9b36 100644 --- a/libstdc++-v3/include/std/span +++ b/libstdc++-v3/include/std/span @@ -376,7 +376,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION else static_assert(_Count <= extent); using _Sp = span<element_type, _Count>; - return _Sp{ _SizedPtr{this->data()} }; + return _Sp(_SizedPtr{this->data()}); } [[nodiscard]] @@ -384,7 +384,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION first(size_type __count) const noexcept { __glibcxx_assert(__count <= size()); - return { this->data(), __count }; + return span<element_type>(this->data(), __count); } template<size_t _Count> @@ -397,7 +397,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION else static_assert(_Count <= extent); using _Sp = span<element_type, _Count>; - return _Sp{ _SizedPtr{this->data() + (this->size() - _Count)} }; + return _Sp(_SizedPtr{this->data() + (this->size() - _Count)}); } [[nodiscard]] @@ -405,7 +405,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION last(size_type __count) const noexcept { __glibcxx_assert(__count <= size()); - return { this->data() + (this->size() - __count), __count }; + return span<element_type>(this->data() + (this->size() - __count), + __count); } template<size_t _Offset, size_t _Count = dynamic_extent> @@ -424,7 +425,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION using _Sp = span<element_type, _S_subspan_extent<_Offset, _Count>()>; if constexpr (_Count == dynamic_extent) - return _Sp{ this->data() + _Offset, this->size() - _Offset }; + return _Sp(this->data() + _Offset, this->size() - _Offset); else { if constexpr (_Extent == dynamic_extent) @@ -437,7 +438,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION static_assert(_Count <= extent); static_assert(_Count <= (extent - _Offset)); } - return _Sp{ _SizedPtr{this->data() + _Offset} }; + return _Sp(_SizedPtr{this->data() + _Offset}); } } @@ -454,7 +455,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __glibcxx_assert(__count <= size()); __glibcxx_assert(__offset + __count <= size()); } - return {this->data() + __offset, __count}; + return span<element_type>(this->data() + __offset, __count); } private: @@ -476,6 +477,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION }; // deduction guides + namespace __detail + { + template<typename _Tp> + concept __integral_constant_like = is_integral_v<decltype(_Tp::value)> + && !is_same_v<bool, remove_const_t<decltype(_Tp::value)>> + && convertible_to<_Tp, decltype(_Tp::value)> + && equality_comparable_with<_Tp, decltype(_Tp::value)> + && bool_constant<_Tp() == _Tp::value>::value + && bool_constant<static_cast<decltype(_Tp::value)>(_Tp()) == _Tp::value> + ::value; + + template<typename _Tp> + constexpr size_t __maybe_static_ext = dynamic_extent; + + template<__integral_constant_like _Tp> + constexpr size_t __maybe_static_ext<_Tp> = {_Tp::value}; + } template<typename _Type, size_t _ArrayExtent> span(_Type(&)[_ArrayExtent]) -> span<_Type, _ArrayExtent>; @@ -489,7 +507,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<contiguous_iterator _Iter, typename _End> span(_Iter, _End) - -> span<remove_reference_t<iter_reference_t<_Iter>>>; + -> span<remove_reference_t<iter_reference_t<_Iter>>, + __detail::__maybe_static_ext<_End>>; template<ranges::contiguous_range _Range> span(_Range &&) diff --git a/libstdc++-v3/libsupc++/exception b/libstdc++-v3/libsupc++/exception index 61d4131..25ce8d9 100644 --- a/libstdc++-v3/libsupc++/exception +++ b/libstdc++-v3/libsupc++/exception @@ -57,8 +57,16 @@ namespace std _GLIBCXX_VISIBILITY(default) class bad_exception : public exception { public: - bad_exception() _GLIBCXX_USE_NOEXCEPT { } + _GLIBCXX26_CONSTEXPR bad_exception() _GLIBCXX_USE_NOEXCEPT { } +#if __cplusplus >= 202400L + constexpr virtual ~bad_exception() _GLIBCXX_TXN_SAFE_DYN noexcept {} + + constexpr virtual const char* what() const _GLIBCXX_TXN_SAFE_DYN noexcept + { + return "std::bad_exception"; + } +#else // This declaration is not useless: // http://gcc.gnu.org/onlinedocs/gcc-3.0.2/gcc_6.html#SEC118 virtual ~bad_exception() _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_USE_NOEXCEPT; @@ -66,6 +74,7 @@ namespace std _GLIBCXX_VISIBILITY(default) // See comment in eh_exception.cc. virtual const char* what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_USE_NOEXCEPT; +#endif }; /// If you write a replacement %terminate handler, it must be of this type. diff --git a/libstdc++-v3/libsupc++/exception.h b/libstdc++-v3/libsupc++/exception.h index f8bca91..efb5fea 100644 --- a/libstdc++-v3/libsupc++/exception.h +++ b/libstdc++-v3/libsupc++/exception.h @@ -61,19 +61,28 @@ namespace std _GLIBCXX_VISIBILITY(default) class exception { public: - exception() _GLIBCXX_NOTHROW { } + _GLIBCXX26_CONSTEXPR exception() _GLIBCXX_NOTHROW { } +#if __cplusplus >= 202400L + constexpr virtual ~exception() _GLIBCXX_TXN_SAFE_DYN noexcept {} +#else virtual ~exception() _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_NOTHROW; +#endif #if __cplusplus >= 201103L - exception(const exception&) = default; - exception& operator=(const exception&) = default; - exception(exception&&) = default; - exception& operator=(exception&&) = default; + _GLIBCXX26_CONSTEXPR exception(const exception&) = default; + _GLIBCXX26_CONSTEXPR exception& operator=(const exception&) = default; + _GLIBCXX26_CONSTEXPR exception(exception&&) = default; + _GLIBCXX26_CONSTEXPR exception& operator=(exception&&) = default; #endif /** Returns a C-style character string describing the general cause * of the current error. */ +#if __cplusplus >= 202400L + constexpr virtual const char* + what() const _GLIBCXX_TXN_SAFE_DYN noexcept { return "std::exception"; } +#else virtual const char* what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_NOTHROW; +#endif }; /// @} diff --git a/libstdc++-v3/libsupc++/exception_ptr.h b/libstdc++-v3/libsupc++/exception_ptr.h index a6ff8c0..be516d7 100644 --- a/libstdc++-v3/libsupc++/exception_ptr.h +++ b/libstdc++-v3/libsupc++/exception_ptr.h @@ -75,7 +75,8 @@ namespace std _GLIBCXX_VISIBILITY(default) exception_ptr current_exception() _GLIBCXX_USE_NOEXCEPT; template<typename _Ex> - exception_ptr make_exception_ptr(_Ex) _GLIBCXX_USE_NOEXCEPT; + _GLIBCXX26_CONSTEXPR exception_ptr make_exception_ptr(_Ex) + _GLIBCXX_USE_NOEXCEPT; /// Throw the object pointed to by the exception_ptr. void rethrow_exception(exception_ptr) __attribute__ ((__noreturn__)); @@ -105,7 +106,25 @@ namespace std _GLIBCXX_VISIBILITY(default) { void* _M_exception_object; +#if __cplusplus >= 202400L + constexpr explicit exception_ptr(void* __e) noexcept + : _M_exception_object(__e) + { + if (_M_exception_object) + { +#if __cpp_if_consteval >= 202106L \ + && _GLIBCXX_HAS_BUILTIN(__builtin_eh_ptr_adjust_ref) + if consteval { + __builtin_eh_ptr_adjust_ref(_M_exception_object, 1); + return; + } +#endif + _M_addref(); + } + } +#else explicit exception_ptr(void* __e) _GLIBCXX_USE_NOEXCEPT; +#endif void _M_addref() _GLIBCXX_USE_NOEXCEPT; void _M_release() _GLIBCXX_USE_NOEXCEPT; @@ -115,7 +134,8 @@ namespace std _GLIBCXX_VISIBILITY(default) friend exception_ptr std::current_exception() _GLIBCXX_USE_NOEXCEPT; friend void std::rethrow_exception(exception_ptr); template<typename _Ex> - friend exception_ptr std::make_exception_ptr(_Ex) _GLIBCXX_USE_NOEXCEPT; + friend _GLIBCXX26_CONSTEXPR exception_ptr std::make_exception_ptr(_Ex) + _GLIBCXX_USE_NOEXCEPT; #if __cpp_lib_exception_ptr_cast >= 202506L template<typename _Ex> friend const _Ex* std::exception_ptr_cast(const exception_ptr&) noexcept; @@ -125,16 +145,17 @@ namespace std _GLIBCXX_VISIBILITY(default) _GLIBCXX_USE_NOEXCEPT; public: - exception_ptr() _GLIBCXX_USE_NOEXCEPT; + _GLIBCXX26_CONSTEXPR exception_ptr() _GLIBCXX_USE_NOEXCEPT; - exception_ptr(const exception_ptr&) _GLIBCXX_USE_NOEXCEPT; + _GLIBCXX26_CONSTEXPR exception_ptr(const exception_ptr&) + _GLIBCXX_USE_NOEXCEPT; #if __cplusplus >= 201103L - exception_ptr(nullptr_t) noexcept + _GLIBCXX26_CONSTEXPR exception_ptr(nullptr_t) noexcept : _M_exception_object(nullptr) { } - exception_ptr(exception_ptr&& __o) noexcept + _GLIBCXX26_CONSTEXPR exception_ptr(exception_ptr&& __o) noexcept : _M_exception_object(__o._M_exception_object) { __o._M_exception_object = nullptr; } #endif @@ -146,11 +167,11 @@ namespace std _GLIBCXX_VISIBILITY(default) exception_ptr(__safe_bool) _GLIBCXX_USE_NOEXCEPT; #endif - exception_ptr& + _GLIBCXX26_CONSTEXPR exception_ptr& operator=(const exception_ptr&) _GLIBCXX_USE_NOEXCEPT; #if __cplusplus >= 201103L - exception_ptr& + _GLIBCXX26_CONSTEXPR exception_ptr& operator=(exception_ptr&& __o) noexcept { exception_ptr(static_cast<exception_ptr&&>(__o)).swap(*this); @@ -158,9 +179,9 @@ namespace std _GLIBCXX_VISIBILITY(default) } #endif - ~exception_ptr() _GLIBCXX_USE_NOEXCEPT; + _GLIBCXX26_CONSTEXPR ~exception_ptr() _GLIBCXX_USE_NOEXCEPT; - void + _GLIBCXX26_CONSTEXPR void swap(exception_ptr&) _GLIBCXX_USE_NOEXCEPT; #ifdef _GLIBCXX_EH_PTR_COMPAT @@ -172,13 +193,13 @@ namespace std _GLIBCXX_VISIBILITY(default) #endif #if __cplusplus >= 201103L - explicit operator bool() const noexcept + _GLIBCXX26_CONSTEXPR explicit operator bool() const noexcept { return _M_exception_object; } #endif #if __cpp_impl_three_way_comparison >= 201907L \ && ! defined _GLIBCXX_EH_PTR_RELOPS_COMPAT - friend bool + _GLIBCXX26_CONSTEXPR friend bool operator==(const exception_ptr&, const exception_ptr&) noexcept = default; #else friend _GLIBCXX_EH_PTR_USED bool @@ -198,31 +219,49 @@ namespace std _GLIBCXX_VISIBILITY(default) }; _GLIBCXX_EH_PTR_USED - inline + _GLIBCXX26_CONSTEXPR inline exception_ptr::exception_ptr() _GLIBCXX_USE_NOEXCEPT : _M_exception_object(0) { } _GLIBCXX_EH_PTR_USED - inline + _GLIBCXX26_CONSTEXPR inline exception_ptr::exception_ptr(const exception_ptr& __other) _GLIBCXX_USE_NOEXCEPT : _M_exception_object(__other._M_exception_object) { if (_M_exception_object) - _M_addref(); + { +#if __cpp_if_consteval >= 202106L \ + && _GLIBCXX_HAS_BUILTIN(__builtin_eh_ptr_adjust_ref) + if consteval { + __builtin_eh_ptr_adjust_ref(_M_exception_object, 1); + return; + } +#endif + _M_addref(); + } } _GLIBCXX_EH_PTR_USED - inline + _GLIBCXX26_CONSTEXPR inline exception_ptr::~exception_ptr() _GLIBCXX_USE_NOEXCEPT { if (_M_exception_object) - _M_release(); + { +#if __cpp_if_consteval >= 202106L \ + && _GLIBCXX_HAS_BUILTIN(__builtin_eh_ptr_adjust_ref) + if consteval { + __builtin_eh_ptr_adjust_ref(_M_exception_object, -1); + return; + } +#endif + _M_release(); + } } _GLIBCXX_EH_PTR_USED - inline exception_ptr& + _GLIBCXX26_CONSTEXPR inline exception_ptr& exception_ptr::operator=(const exception_ptr& __other) _GLIBCXX_USE_NOEXCEPT { exception_ptr(__other).swap(*this); @@ -230,7 +269,7 @@ namespace std _GLIBCXX_VISIBILITY(default) } _GLIBCXX_EH_PTR_USED - inline void + _GLIBCXX26_CONSTEXPR inline void exception_ptr::swap(exception_ptr &__other) _GLIBCXX_USE_NOEXCEPT { void *__tmp = _M_exception_object; @@ -239,7 +278,7 @@ namespace std _GLIBCXX_VISIBILITY(default) } /// @relates exception_ptr - inline void + _GLIBCXX26_CONSTEXPR inline void swap(exception_ptr& __lhs, exception_ptr& __rhs) { __lhs.swap(__rhs); } @@ -258,9 +297,21 @@ namespace std _GLIBCXX_VISIBILITY(default) /// Obtain an exception_ptr pointing to a copy of the supplied object. #if (__cplusplus >= 201103L && __cpp_rtti) || __cpp_exceptions template<typename _Ex> - exception_ptr + _GLIBCXX26_CONSTEXPR exception_ptr make_exception_ptr(_Ex __ex) _GLIBCXX_USE_NOEXCEPT { +#if __cplusplus >= 202400L + if consteval { + try + { + throw __ex; + } + catch(...) + { + return current_exception(); + } + } +#endif #if __cplusplus >= 201103L && __cpp_rtti using _Ex2 = typename decay<_Ex>::type; void* __e = __cxxabiv1::__cxa_allocate_exception(sizeof(_Ex)); @@ -293,7 +344,7 @@ namespace std _GLIBCXX_VISIBILITY(default) // instead of a working one compiled with RTTI and/or exceptions enabled. template<typename _Ex> __attribute__ ((__always_inline__)) - inline exception_ptr + _GLIBCXX26_CONSTEXPR inline exception_ptr make_exception_ptr(_Ex) _GLIBCXX_USE_NOEXCEPT { return exception_ptr(); } #endif diff --git a/libstdc++-v3/libsupc++/nested_exception.h b/libstdc++-v3/libsupc++/nested_exception.h index c9f63e5..aff47bc 100644 --- a/libstdc++-v3/libsupc++/nested_exception.h +++ b/libstdc++-v3/libsupc++/nested_exception.h @@ -62,17 +62,24 @@ namespace std _GLIBCXX_VISIBILITY(default) public: /// The default constructor stores the current exception (if any). + _GLIBCXX26_CONSTEXPR nested_exception() noexcept : _M_ptr(current_exception()) { } + _GLIBCXX26_CONSTEXPR nested_exception(const nested_exception&) noexcept = default; + _GLIBCXX26_CONSTEXPR nested_exception& operator=(const nested_exception&) noexcept = default; +#if __cplusplus >= 202400L + constexpr virtual ~nested_exception() noexcept {} +#else virtual ~nested_exception() noexcept; +#endif /// Rethrow the stored exception, or terminate if none was stored. [[noreturn]] - void + _GLIBCXX26_CONSTEXPR void rethrow_nested() const { if (_M_ptr) @@ -81,7 +88,7 @@ namespace std _GLIBCXX_VISIBILITY(default) } /// Access the stored exception. - exception_ptr + _GLIBCXX26_CONSTEXPR exception_ptr nested_ptr() const noexcept { return _M_ptr; } }; @@ -91,11 +98,11 @@ namespace std _GLIBCXX_VISIBILITY(default) template<typename _Except> struct _Nested_exception : public _Except, public nested_exception { - explicit _Nested_exception(const _Except& __ex) + _GLIBCXX26_CONSTEXPR explicit _Nested_exception(const _Except& __ex) : _Except(__ex) { } - explicit _Nested_exception(_Except&& __ex) + _GLIBCXX26_CONSTEXPR explicit _Nested_exception(_Except&& __ex) : _Except(static_cast<_Except&&>(__ex)) { } }; @@ -144,7 +151,7 @@ namespace std _GLIBCXX_VISIBILITY(default) */ template<typename _Tp> [[noreturn]] - inline void + _GLIBCXX26_CONSTEXPR inline void throw_with_nested(_Tp&& __t) { using _Up = typename decay<_Tp>::type; @@ -204,7 +211,7 @@ namespace std _GLIBCXX_VISIBILITY(default) # if ! __cpp_rtti [[__gnu__::__always_inline__]] #endif - inline void + _GLIBCXX26_CONSTEXPR inline void rethrow_if_nested(const _Ex& __ex) { const _Ex* __ptr = __builtin_addressof(__ex); diff --git a/libstdc++-v3/libsupc++/new b/libstdc++-v3/libsupc++/new index a550373..fb36dae 100644 --- a/libstdc++-v3/libsupc++/new +++ b/libstdc++-v3/libsupc++/new @@ -66,33 +66,51 @@ namespace std class bad_alloc : public exception { public: - bad_alloc() throw() { } + _GLIBCXX26_CONSTEXPR bad_alloc() throw() { } #if __cplusplus >= 201103L - bad_alloc(const bad_alloc&) = default; - bad_alloc& operator=(const bad_alloc&) = default; + _GLIBCXX26_CONSTEXPR bad_alloc(const bad_alloc&) = default; + _GLIBCXX26_CONSTEXPR bad_alloc& operator=(const bad_alloc&) = default; #endif +#if __cplusplus >= 202400L + constexpr virtual ~bad_alloc() noexcept {} + + constexpr virtual const char* what() const noexcept + { + return "std::bad_alloc"; + } +#else // This declaration is not useless: // http://gcc.gnu.org/onlinedocs/gcc-3.0.2/gcc_6.html#SEC118 virtual ~bad_alloc() throw(); // See comment in eh_exception.cc. virtual const char* what() const throw(); +#endif }; #if __cplusplus >= 201103L class bad_array_new_length : public bad_alloc { public: - bad_array_new_length() throw() { } + _GLIBCXX26_CONSTEXPR bad_array_new_length() throw() { } +#if __cplusplus >= 202400L + constexpr virtual ~bad_array_new_length() noexcept {} + + constexpr virtual const char* what() const noexcept + { + return "std::bad_array_new_length"; + } +#else // This declaration is not useless: // http://gcc.gnu.org/onlinedocs/gcc-3.0.2/gcc_6.html#SEC118 virtual ~bad_array_new_length() throw(); // See comment in eh_exception.cc. virtual const char* what() const throw(); +#endif }; #endif diff --git a/libstdc++-v3/libsupc++/typeinfo b/libstdc++-v3/libsupc++/typeinfo index 0a94b86..a31be7c 100644 --- a/libstdc++-v3/libsupc++/typeinfo +++ b/libstdc++-v3/libsupc++/typeinfo @@ -224,14 +224,23 @@ namespace std class bad_cast : public exception { public: - bad_cast() _GLIBCXX_USE_NOEXCEPT { } + _GLIBCXX26_CONSTEXPR bad_cast() _GLIBCXX_USE_NOEXCEPT { } +#if __cplusplus >= 202400L + constexpr virtual ~bad_cast() noexcept {} + + constexpr virtual const char* what() const noexcept + { + return "std::bad_cast"; + } +#else // This declaration is not useless: // http://gcc.gnu.org/onlinedocs/gcc-3.0.2/gcc_6.html#SEC118 virtual ~bad_cast() _GLIBCXX_USE_NOEXCEPT; // See comment in eh_exception.cc. virtual const char* what() const _GLIBCXX_USE_NOEXCEPT; +#endif }; /** @@ -241,14 +250,23 @@ namespace std class bad_typeid : public exception { public: - bad_typeid () _GLIBCXX_USE_NOEXCEPT { } + _GLIBCXX26_CONSTEXPR bad_typeid () _GLIBCXX_USE_NOEXCEPT { } +#if __cplusplus >= 202400L + constexpr virtual ~bad_typeid() noexcept {} + + constexpr virtual const char* what() const noexcept + { + return "std::bad_typeid"; + } +#else // This declaration is not useless: // http://gcc.gnu.org/onlinedocs/gcc-3.0.2/gcc_6.html#SEC118 virtual ~bad_typeid() _GLIBCXX_USE_NOEXCEPT; // See comment in eh_exception.cc. virtual const char* what() const _GLIBCXX_USE_NOEXCEPT; +#endif }; } // namespace std diff --git a/libstdc++-v3/src/c++11/debug.cc b/libstdc++-v3/src/c++11/debug.cc index 3533b5e..c6f6ef7 100644 --- a/libstdc++-v3/src/c++11/debug.cc +++ b/libstdc++-v3/src/c++11/debug.cc @@ -54,7 +54,7 @@ namespace * in order to limit contention without breaking current library binary * compatibility. */ __gnu_cxx::__mutex& - get_safe_base_mutex(void* address) + get_safe_base_mutex(const void* address) { // Use arbitrarily __gnu_debug::vector<int> as the container giving // alignment of debug containers. @@ -70,9 +70,9 @@ namespace #pragma GCC diagnostic warning "-Wabi=6" void - swap_its(__gnu_debug::_Safe_sequence_base& __lhs, + swap_its(const __gnu_debug::_Safe_sequence_base& __lhs, __gnu_debug::_Safe_iterator_base*& __lhs_its, - __gnu_debug::_Safe_sequence_base& __rhs, + const __gnu_debug::_Safe_sequence_base& __rhs, __gnu_debug::_Safe_iterator_base*& __rhs_its) { swap(__lhs_its, __rhs_its); @@ -84,8 +84,8 @@ namespace } void - swap_seq_single(__gnu_debug::_Safe_sequence_base& __lhs, - __gnu_debug::_Safe_sequence_base& __rhs) + swap_seq_single(const __gnu_debug::_Safe_sequence_base& __lhs, + const __gnu_debug::_Safe_sequence_base& __rhs) { swap(__lhs._M_version, __rhs._M_version); swap_its(__lhs, __lhs._M_iterators, @@ -118,17 +118,17 @@ namespace void swap_seq(__gnu_cxx::__mutex& lhs_mutex, - __gnu_debug::_Safe_sequence_base& lhs, + const __gnu_debug::_Safe_sequence_base& lhs, __gnu_cxx::__mutex& rhs_mutex, - __gnu_debug::_Safe_sequence_base& rhs) + const __gnu_debug::_Safe_sequence_base& rhs) { lock_and_run(lhs_mutex, rhs_mutex, [&lhs, &rhs]() { swap_seq_single(lhs, rhs); }); } void - swap_ucont_single(__gnu_debug::_Safe_unordered_container_base& __lhs, - __gnu_debug::_Safe_unordered_container_base& __rhs) + swap_ucont_single(const __gnu_debug::_Safe_unordered_container_base& __lhs, + const __gnu_debug::_Safe_unordered_container_base& __rhs) { swap_seq_single(__lhs, __rhs); swap_its(__lhs, __lhs._M_local_iterators, @@ -139,9 +139,9 @@ namespace void swap_ucont(__gnu_cxx::__mutex& lhs_mutex, - __gnu_debug::_Safe_unordered_container_base& lhs, + const __gnu_debug::_Safe_unordered_container_base& lhs, __gnu_cxx::__mutex& rhs_mutex, - __gnu_debug::_Safe_unordered_container_base& rhs) + const __gnu_debug::_Safe_unordered_container_base& rhs) { lock_and_run(lhs_mutex, rhs_mutex, [&lhs, &rhs]() { swap_ucont_single(lhs, rhs); }); @@ -158,8 +158,8 @@ namespace } } - void* - acquire_sequence_ptr_for_lock(__gnu_debug::_Safe_sequence_base*& seq) + const void* + acquire_sequence_ptr_for_lock(__gnu_debug::_Safe_sequence_base const*& seq) { #ifdef __GTHREADS if (!__gnu_cxx::__is_single_threaded()) @@ -169,7 +169,7 @@ namespace } void - reset_sequence_ptr(__gnu_debug::_Safe_sequence_base*& seq) + reset_sequence_ptr(__gnu_debug::_Safe_sequence_base const*& seq) { #ifdef __GTHREADS if (!__gnu_cxx::__is_single_threaded()) @@ -327,7 +327,7 @@ namespace __gnu_debug void _Safe_sequence_base:: - _M_detach_all() + _M_detach_all() const { __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); detach_all(_M_iterators); @@ -339,7 +339,7 @@ namespace __gnu_debug void _Safe_sequence_base:: - _M_detach_singular() + _M_detach_singular() const { __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); for (_Safe_iterator_base* __iter = _M_iterators; __iter;) @@ -361,7 +361,7 @@ namespace __gnu_debug void _Safe_sequence_base:: - _M_revalidate_singular() + _M_revalidate_singular() const { __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); for (_Safe_iterator_base* __iter = _M_iterators; __iter; @@ -375,17 +375,59 @@ namespace __gnu_debug void _Safe_sequence_base:: - _M_swap(_Safe_sequence_base& __x) noexcept + _M_swap(const _Safe_sequence_base& __x) const noexcept { swap_seq(_M_get_mutex(), *this, __x._M_get_mutex(), __x); } __gnu_cxx::__mutex& _Safe_sequence_base:: - _M_get_mutex() noexcept + _M_get_mutex() const noexcept { return get_safe_base_mutex(this); } +#if !_GLIBCXX_INLINE_VERSION + void + _Safe_sequence_base:: + _M_detach_all() + { + const _Safe_sequence_base* __this = this; + __this->_M_detach_all(); + } + + void + _Safe_sequence_base:: + _M_detach_singular() + { + const _Safe_sequence_base* __this = this; + __this->_M_detach_singular(); + } + + void + _Safe_sequence_base:: + _M_revalidate_singular() + { + const _Safe_sequence_base* __this = this; + __this->_M_revalidate_singular(); + } + void _Safe_sequence_base:: - _M_attach(_Safe_iterator_base* __it, bool __constant) + _M_swap(_Safe_sequence_base& __x) noexcept + { + const _Safe_sequence_base* __this = this; + __this->_M_swap(__x); + } + + __gnu_cxx::__mutex& + _Safe_sequence_base:: + _M_get_mutex() noexcept + { + const _Safe_sequence_base* __this = this; + return __this->_M_get_mutex(); + } +#endif + + void + _Safe_sequence_base:: + _M_attach(_Safe_iterator_base* __it, bool __constant) const { __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); _M_attach_single(__it, __constant); @@ -393,7 +435,7 @@ namespace __gnu_debug void _Safe_sequence_base:: - _M_attach_single(_Safe_iterator_base* __it, bool __constant) noexcept + _M_attach_single(_Safe_iterator_base* __it, bool __constant) const noexcept { _Safe_iterator_base*& __its = __constant ? _M_const_iterators : _M_iterators; @@ -405,7 +447,7 @@ namespace __gnu_debug void _Safe_sequence_base:: - _M_detach(_Safe_iterator_base* __it) + _M_detach(_Safe_iterator_base* __it) const { // Remove __it from this sequence's list __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); @@ -414,7 +456,7 @@ namespace __gnu_debug void _Safe_sequence_base:: - _M_detach_single(_Safe_iterator_base* __it) noexcept + _M_detach_single(_Safe_iterator_base* __it) const noexcept { // Remove __it from this sequence's list __it->_M_unlink(); @@ -426,7 +468,7 @@ namespace __gnu_debug void _Safe_iterator_base:: - _M_attach(_Safe_sequence_base* __seq, bool __constant) + _M_attach(const _Safe_sequence_base* __seq, bool __constant) { _M_detach(); @@ -443,7 +485,7 @@ namespace __gnu_debug void _Safe_iterator_base:: - _M_attach_single(_Safe_sequence_base* __seq, bool __constant) noexcept + _M_attach_single(const _Safe_sequence_base* __seq, bool __constant) noexcept { _M_detach_single(); @@ -514,14 +556,27 @@ namespace __gnu_debug _M_get_mutex() noexcept { return _M_sequence->_M_get_mutex(); } - _Safe_unordered_container_base* - _Safe_local_iterator_base:: - _M_get_container() const noexcept - { return static_cast<_Safe_unordered_container_base*>(_M_sequence); } +#if !_GLIBCXX_INLINE_VERSION + void + _Safe_iterator_base:: + _M_attach(_Safe_sequence_base* __seq, bool __constant) + { + const _Safe_sequence_base* __cseq = __seq; + _M_attach(__cseq, __constant); + } + + void + _Safe_iterator_base:: + _M_attach_single(_Safe_sequence_base* __seq, bool __constant) noexcept + { + const _Safe_sequence_base* __cseq = __seq; + _M_attach_single(__cseq, __constant); + } +#endif void _Safe_local_iterator_base:: - _M_attach(_Safe_sequence_base* __cont, bool __constant) + _M_attach(const _Safe_unordered_container_base* __cont, bool __constant) { _M_detach(); @@ -530,7 +585,7 @@ namespace __gnu_debug { _M_sequence = __cont; _M_version = _M_sequence->_M_version; - _M_get_container()->_M_attach_local(this, __constant); + _M_safe_container()->_M_attach_local(this, __constant); } else _M_version = 0; @@ -538,7 +593,8 @@ namespace __gnu_debug void _Safe_local_iterator_base:: - _M_attach_single(_Safe_sequence_base* __cont, bool __constant) noexcept + _M_attach_single(const _Safe_unordered_container_base* __cont, + bool __constant) noexcept { _M_detach_single(); @@ -547,7 +603,7 @@ namespace __gnu_debug { _M_sequence = __cont; _M_version = _M_sequence->_M_version; - _M_get_container()->_M_attach_local_single(this, __constant); + _M_safe_container()->_M_attach_local_single(this, __constant); } else _M_version = 0; @@ -570,14 +626,34 @@ namespace __gnu_debug { if (_M_sequence) { - _M_get_container()->_M_detach_local_single(this); + _M_safe_container()->_M_detach_local_single(this); _M_reset(); } } +#if !_GLIBCXX_INLINE_VERSION + void + _Safe_local_iterator_base:: + _M_attach(_Safe_sequence_base* __seq, bool __constant) + { + const _Safe_unordered_container_base* __cont + = static_cast<_Safe_unordered_container_base*>(__seq); + _M_attach(__cont, __constant); + } + + void + _Safe_local_iterator_base:: + _M_attach_single(_Safe_sequence_base* __seq, bool __constant) noexcept + { + const _Safe_unordered_container_base* __cont + = static_cast<_Safe_unordered_container_base*>(__seq); + _M_attach_single(__cont, __constant); + } +#endif + void _Safe_unordered_container_base:: - _M_detach_all() + _M_detach_all() const { __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); detach_all(_M_iterators); @@ -595,12 +671,12 @@ namespace __gnu_debug void _Safe_unordered_container_base:: - _M_swap(_Safe_unordered_container_base& __x) noexcept + _M_swap(const _Safe_unordered_container_base& __x) const noexcept { swap_ucont(_M_get_mutex(), *this, __x._M_get_mutex(), __x); } void _Safe_unordered_container_base:: - _M_attach_local(_Safe_iterator_base* __it, bool __constant) + _M_attach_local(_Safe_iterator_base* __it, bool __constant) const { __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); _M_attach_local_single(__it, __constant); @@ -608,7 +684,7 @@ namespace __gnu_debug void _Safe_unordered_container_base:: - _M_attach_local_single(_Safe_iterator_base* __it, bool __constant) noexcept + _M_attach_local_single(_Safe_iterator_base* __it, bool __constant) const noexcept { _Safe_iterator_base*& __its = __constant ? _M_const_local_iterators : _M_local_iterators; @@ -620,7 +696,7 @@ namespace __gnu_debug void _Safe_unordered_container_base:: - _M_detach_local(_Safe_iterator_base* __it) + _M_detach_local(_Safe_iterator_base* __it) const { // Remove __it from this container's list __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); @@ -629,7 +705,7 @@ namespace __gnu_debug void _Safe_unordered_container_base:: - _M_detach_local_single(_Safe_iterator_base* __it) noexcept + _M_detach_local_single(_Safe_iterator_base* __it) const noexcept { // Remove __it from this container's list __it->_M_unlink(); @@ -638,6 +714,24 @@ namespace __gnu_debug if (_M_local_iterators == __it) _M_local_iterators = __it->_M_next; } + +#if !_GLIBCXX_INLINE_VERSION + void + _Safe_unordered_container_base:: + _M_detach_all() + { + const _Safe_unordered_container_base* __this = this; + __this->_M_detach_all(); + } + + void + _Safe_unordered_container_base:: + _M_swap(_Safe_unordered_container_base& __x) noexcept + { + const _Safe_unordered_container_base* __this = this; + __this->_M_swap(__x); + } +#endif } namespace diff --git a/libstdc++-v3/src/c++17/memory_resource.cc b/libstdc++-v3/src/c++17/memory_resource.cc index fac4c78..c61569f 100644 --- a/libstdc++-v3/src/c++17/memory_resource.cc +++ b/libstdc++-v3/src/c++17/memory_resource.cc @@ -182,8 +182,8 @@ namespace pmr // versions will not use this symbol. monotonic_buffer_resource::~monotonic_buffer_resource() { release(); } - namespace { - +namespace +{ // aligned_size<N> stores the size and alignment of a memory allocation. // The size must be a multiple of N, leaving the low log2(N) bits free // to store the base-2 logarithm of the alignment. @@ -221,7 +221,7 @@ namespace pmr return (n + alignment - 1) & ~(alignment - 1); } - } // namespace +} // namespace // Memory allocated by the upstream resource is managed in a linked list // of _Chunk objects. A _Chunk object recording the size and alignment of @@ -307,8 +307,8 @@ namespace pmr // Helper types for synchronized_pool_resource & unsynchronized_pool_resource - namespace { - +namespace +{ // Simple bitset with runtime size. // Tracks which blocks in a pool chunk are used/unused. struct bitset @@ -636,7 +636,7 @@ namespace pmr static_assert(sizeof(big_block) == (2 * sizeof(void*))); - } // namespace +} // namespace // A pool that serves blocks of a particular size. // Each pool manages a number of chunks. @@ -868,7 +868,16 @@ namespace pmr using big_block::big_block; }; - namespace { +namespace +{ + // N.B. it is important that we don't skip any power of two sizes if there + // is a non-power of two size between them, e.g. must not have pool sizes + // of 24 and 40 without having a pool size of 32. Otherwise an allocation + // of 32 bytes with alignment 16 would choose the 40-byte pool which is not + // correctly aligned for 16-byte alignment. It would be OK (but suboptimal) + // to have no pool of size 32 if we have pool sizes of 16 and 64 and no + // non-power of two sizes between those, because the example of (32, 16) + // would choose the 64-byte pool, which would be correctly aligned. constexpr size_t pool_sizes[] = { 8, 16, 24, @@ -983,7 +992,7 @@ namespace pmr using exclusive_lock = lock_guard<shared_mutex>; #endif - } // namespace +} // namespace __pool_resource:: __pool_resource(const pool_options& opts, memory_resource* upstream) @@ -1075,12 +1084,33 @@ namespace pmr return p; } + // Determine the appropriate allocation size, rounding up to a multiple + // of the alignment if needed. + static inline size_t + choose_block_size(size_t bytes, size_t alignment) + { + if (bytes == 0) [[unlikely]] + return alignment; + + // Use bit_ceil in case alignment is invalid (i.e. not a power of two). + size_t mask = std::__bit_ceil(alignment) - 1; + // Round up to a multiple of alignment. + size_t block_size = (bytes + mask) & ~mask; + + if (block_size >= bytes) [[likely]] + return block_size; + + // Wrapped around to zero, bytes must have been impossibly large. + return numeric_limits<size_t>::max(); + } + + #ifdef _GLIBCXX_HAS_GTHREADS // synchronized_pool_resource members. /* Notes on implementation and thread safety: * - * Each synchronized_pool_resource manages an linked list of N+1 _TPools + * Each synchronized_pool_resource manages a linked list of N+1 _TPools * objects, where N is the number of threads using the pool resource. * Each _TPools object has its own set of pools, with their own chunks. * The first element of the list, _M_tpools[0], can be used by any thread. @@ -1247,7 +1277,7 @@ namespace pmr synchronized_pool_resource:: do_allocate(size_t bytes, size_t alignment) { - const auto block_size = std::max(bytes, alignment); + const auto block_size = choose_block_size(bytes, alignment); const pool_options opts = _M_impl._M_opts; if (block_size <= opts.largest_required_pool_block) { @@ -1294,7 +1324,7 @@ namespace pmr synchronized_pool_resource:: do_deallocate(void* p, size_t bytes, size_t alignment) { - size_t block_size = std::max(bytes, alignment); + size_t block_size = choose_block_size(bytes, alignment); if (block_size <= _M_impl._M_opts.largest_required_pool_block) { const ptrdiff_t index = pool_index(block_size, _M_impl._M_npools); @@ -1453,7 +1483,7 @@ namespace pmr void* unsynchronized_pool_resource::do_allocate(size_t bytes, size_t alignment) { - const auto block_size = std::max(bytes, alignment); + const auto block_size = choose_block_size(bytes, alignment); if (block_size <= _M_impl._M_opts.largest_required_pool_block) { // Recreate pools if release() has been called: @@ -1470,7 +1500,7 @@ namespace pmr unsynchronized_pool_resource:: do_deallocate(void* p, size_t bytes, size_t alignment) { - size_t block_size = std::max(bytes, alignment); + size_t block_size = choose_block_size(bytes, alignment); if (block_size <= _M_impl._M_opts.largest_required_pool_block) { if (auto pool = _M_find_pool(block_size)) diff --git a/libstdc++-v3/src/c++23/std.cc.in b/libstdc++-v3/src/c++23/std.cc.in index 86e6d88..dd05a83 100644 --- a/libstdc++-v3/src/c++23/std.cc.in +++ b/libstdc++-v3/src/c++23/std.cc.in @@ -1846,7 +1846,8 @@ export namespace std using std::layout_right; using std::layout_stride; using std::default_accessor; - // FIXME layout_left_padded, layout_right_padded, aligned_accessor and mdspan + using std::mdspan; + // FIXME layout_left_padded, layout_right_padded, aligned_accessor, mdsubspan } #endif diff --git a/libstdc++-v3/testsuite/20_util/owner_equal/cmp.cc b/libstdc++-v3/testsuite/20_util/owner_equal/cmp.cc new file mode 100644 index 0000000..311ddf2 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/owner_equal/cmp.cc @@ -0,0 +1,105 @@ +// { dg-do run { target c++26 } } +// { dg-require-effective-target hosted } + +// N5008 20.3.2.6 Struct owner_equal [util.smartptr.owner.equal] + +#include <memory> +#include <algorithm> +#include <testsuite_hooks.h> + +struct A { }; + +struct B { A a[2]; }; + +int +test01() +{ + // test empty shared_ptr owners compare equivalent + std::owner_equal eq; + std::shared_ptr<A> p1; + std::shared_ptr<A> p2; + VERIFY( eq(p1, p2) && eq(p2, p1) ); + std::weak_ptr<A> p3; + VERIFY( eq(p1, p3) && eq(p3, p1) ); + VERIFY( eq(p1, p3) && eq(p3, p1) ); + return 0; +} + + +// Construction from pointer +int +test02() +{ + std::owner_equal eq; + + std::shared_ptr<A> empty; + + std::shared_ptr<A> a1(new A); + VERIFY( !eq(empty, a1) && !eq(a1, empty) ); + + std::shared_ptr<A> a2(new A); + VERIFY( !eq(a1, a2) && !eq(a2, a1) ); + + std::weak_ptr<A> w1(a1); + VERIFY( eq(a1, w1) && eq(w1, a1) ); + + std::weak_ptr<A> w2(a2); + VERIFY( !eq(w1, w2) && !eq(w2, w1) ); + + a1.reset(); + VERIFY( eq(empty, a1) && eq(a1, empty) ); + VERIFY( !eq(a1, w1) && !eq(w1, a1) ); + + a2.reset(); + VERIFY( eq(a2, a1) && eq(a1, a2) ); + + return 0; +} + +// aliasing +int +test03() +{ + std::owner_equal eq; + + std::shared_ptr<B> b(new B); + std::shared_ptr<A> a0(b, &b->a[0]); + std::shared_ptr<A> a1(b, &b->a[1]); + // values are different but owners are equivalent: + VERIFY( a0 < a1 && eq(a0, a1) && eq(b, a0) && eq(b, a1) ); + + std::weak_ptr<A> w0(a0); + std::weak_ptr<A> w1(a1); + VERIFY( eq(w0, w1) && eq(w1, w0) ); + VERIFY( eq(a0, w1) && eq(w1, a0) ); + VERIFY( eq(w0, a1) && eq(a1, w0) ); + + return 0; +} + +// as binary predicate +int +test04() +{ + std::owner_equal eq; + + std::shared_ptr<B> b(new B); + std::shared_ptr<A> a0(b, &b->a[0]); + std::shared_ptr<A> a1(b, &b->a[1]); + std::shared_ptr<A> c(new A); + std::weak_ptr<A> a[3]{a0, a1, c}; + std::weak_ptr<A>* p = std::unique(a, a+3, eq); + VERIFY( p == &a[2] ); + + return 0; +} + +int +main() +{ + test01(); + test02(); + test03(); + test04(); + return 0; +} diff --git a/libstdc++-v3/testsuite/20_util/owner_equal/noexcept.cc b/libstdc++-v3/testsuite/20_util/owner_equal/noexcept.cc new file mode 100644 index 0000000..fb479f6 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/owner_equal/noexcept.cc @@ -0,0 +1,30 @@ +// { dg-do compile { target c++26 } } +// { dg-require-effective-target hosted } + +// N5008 20.3.2.6 Struct owner_equal [util.smartptr.owner.equal] + +#include <memory> + +#ifndef __cpp_lib_smart_ptr_owner_equality +# error "Feature-test macro for smart ptr owner equality missing in <memory>" +#elif __cpp_lib_smart_ptr_owner_equality != 202306L +# error "Feature-test macro for smart ptr owner equality has wrong value in <memory>" +#endif + +const std::owner_equal eq; +const std::shared_ptr<int> si; +const std::weak_ptr<int> wi; +static_assert( noexcept(!eq(si, si)) ); +static_assert( noexcept(!eq(si, wi)) ); +static_assert( noexcept(!eq(wi, si)) ); +static_assert( noexcept(!eq(wi, wi)) ); +static_assert( noexcept(!eq(si, wi)) ); +static_assert( noexcept(!eq(wi, si)) ); +const std::shared_ptr<long> sl; +const std::weak_ptr<char> wc; +static_assert( noexcept(!eq(si, si)) ); +static_assert( noexcept(!eq(si, sl)) ); +static_assert( noexcept(!eq(sl, si)) ); +static_assert( noexcept(!eq(si, wc)) ); +static_assert( noexcept(!eq(wc, si)) ); +static_assert( noexcept(!eq(wc, wi)) ); diff --git a/libstdc++-v3/testsuite/20_util/owner_equal/version.cc b/libstdc++-v3/testsuite/20_util/owner_equal/version.cc new file mode 100644 index 0000000..db29154 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/owner_equal/version.cc @@ -0,0 +1,13 @@ +// { dg-do compile { target c++26 } } +// { dg-require-effective-target hosted } + +// N5008 17.3.2 Header <version> synopsis [version.syn] + +#include <version> + +#ifndef __cpp_lib_smart_ptr_owner_equality +# error "Feature-test macro for smart ptr owner equality missing in <version>" +#elif __cpp_lib_smart_ptr_owner_equality != 202306L +# error "Feature-test macro for smart ptr owner equality has wrong value in <version>" +#endif + diff --git a/libstdc++-v3/testsuite/20_util/owner_hash/cmp.cc b/libstdc++-v3/testsuite/20_util/owner_hash/cmp.cc new file mode 100644 index 0000000..c03a926 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/owner_hash/cmp.cc @@ -0,0 +1,87 @@ +// { dg-do run { target c++26 } } +// { dg-require-effective-target hosted } + +// N5008 20.3.2.5 Struct owner_hash [util.smartptr.owner.hash] + +#include <memory> +#include <algorithm> +#include <testsuite_hooks.h> + +struct A { }; + +struct B { A a[2]; }; + +int +test01() +{ + // test empty shared_ptr hashes compare equivalent + std::owner_hash oh; + std::shared_ptr<A> p1; + std::shared_ptr<A> p2; + VERIFY( oh(p1) == oh(p2) ); + std::weak_ptr<A> p3; + VERIFY( oh(p1) == oh(p3) ); + VERIFY( oh(p1) == oh(p3) ); + return 0; +} + + +// Construction from pointer +int +test02() +{ + std::owner_hash oh; + + std::shared_ptr<A> empty; + + std::shared_ptr<A> a1(new A); + VERIFY( oh(empty) != oh(a1) ); + + std::shared_ptr<A> a2(new A); + VERIFY( oh(a1) != oh(a2) ); + + std::weak_ptr<A> w1(a1); + VERIFY( oh(a1) == oh(w1) ); + + std::weak_ptr<A> w2(a2); + VERIFY( oh(w1) != oh(w2) ); + + a1.reset(); + VERIFY( oh(empty) == oh(a1) ); + VERIFY( oh(a1) != oh(w1) ); + + a2.reset(); + VERIFY( oh(a2) == oh(a1) ); + + return 0; +} + +// aliasing +int +test03() +{ + std::owner_hash oh; + + std::shared_ptr<B> b(new B); + std::shared_ptr<A> a0(b, &b->a[0]); + std::shared_ptr<A> a1(b, &b->a[1]); + // values are different but owners are ohuivalent: + VERIFY( a0 < a1 && oh(a0) == oh(a1) && oh(b) == oh(a0) && oh(b) == oh(a1) ); + + std::weak_ptr<A> w0(a0); + std::weak_ptr<A> w1(a1); + VERIFY( oh(w0) == oh(w1) ); + VERIFY( oh(a0) == oh(w1) ); + VERIFY( oh(w0) == oh(a1) ); + + return 0; +} + +int +main() +{ + test01(); + test02(); + test03(); + return 0; +} diff --git a/libstdc++-v3/testsuite/20_util/owner_hash/noexcept.cc b/libstdc++-v3/testsuite/20_util/owner_hash/noexcept.cc new file mode 100644 index 0000000..12b2f2f --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/owner_hash/noexcept.cc @@ -0,0 +1,16 @@ +// { dg-do compile { target c++26 } } +// { dg-require-effective-target hosted } + +// N5008 20.3.2.5 Struct owner_hash [util.smartptr.owner.hash] + +#include <memory> + +const std::owner_hash oh; +const std::shared_ptr<int> si; +const std::weak_ptr<int> wi; +static_assert( noexcept(!oh(si)) ); +static_assert( noexcept(!oh(wi)) ); +const std::shared_ptr<long> sl; +const std::weak_ptr<char> wc; +static_assert( noexcept(!oh(sl)) ); +static_assert( noexcept(!oh(wc)) ); diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/observers/owner_equal.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/observers/owner_equal.cc new file mode 100644 index 0000000..7ec8691 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/shared_ptr/observers/owner_equal.cc @@ -0,0 +1,74 @@ +// { dg-do run { target c++26 } } +// { dg-require-effective-target hosted } + +// N5008 20.3.2.2.6 shared_ptr observers [util.smartptr.shared.obs] + +#include <memory> +#include <testsuite_hooks.h> + +struct A +{ + int i; + virtual ~A() { } +}; + +struct B : A +{ +}; + +void +test01() +{ + // test empty shared_ptr owners compare equivalent + std::shared_ptr<A> p1; + std::shared_ptr<B> p2; + VERIFY( p1.owner_equal(p2) && p2.owner_equal(p1) ); +} + + +// Construction from pointer +void +test02() +{ + std::shared_ptr<A> a0; + + std::shared_ptr<A> a1(new A); + VERIFY( !a1.owner_equal(a0) && !a0.owner_equal(a1) ); + + std::shared_ptr<B> b1(new B); + VERIFY( !a1.owner_equal(b1) && !b1.owner_equal(a1) ); + + std::shared_ptr<A> a2(a1); + VERIFY( a1.owner_equal(a2) && a2.owner_equal(a1) ); + a2 = b1; + VERIFY( b1.owner_equal(a2) && a2.owner_equal(b1) ); + + std::weak_ptr<A> w1(a1); + VERIFY( a1.owner_equal(w1) && w1.owner_equal(a1) ); + std::weak_ptr<A> w2(a2); + VERIFY( b1.owner_equal(w2) && w2.owner_equal(b1) ); + + static_assert( noexcept(a1.owner_equal(a0)) ); + static_assert( noexcept(a1.owner_equal(b1)) ); + static_assert( noexcept(b1.owner_equal(a1)) ); + static_assert( noexcept(a1.owner_equal(w1)) ); + static_assert( noexcept(b1.owner_equal(w1)) ); +} + +// Aliasing +void +test03() +{ + std::shared_ptr<A> p1(new A()); + std::shared_ptr<int> p2(p1, &p1->i); + VERIFY( p1.owner_equal(p2) && p2.owner_equal(p1) ); +} + +int +main() +{ + test01(); + test02(); + test03(); + return 0; +} diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/observers/owner_hash.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/observers/owner_hash.cc new file mode 100644 index 0000000..8e6c02c --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/shared_ptr/observers/owner_hash.cc @@ -0,0 +1,71 @@ +// { dg-do run { target c++26 } } +// { dg-require-effective-target hosted } + +// N5008 20.3.2.2.6 shared_ptr observers [util.smartptr.shared.obs] + +#include <memory> +#include <testsuite_hooks.h> + +struct A +{ + int i; + virtual ~A() { } +}; + +struct B : A +{ +}; + +void +test01() +{ + // test empty shared_ptr hashes compare equivalent + std::shared_ptr<A> p1; + std::shared_ptr<B> p2; + VERIFY( p1.owner_hash() == p2.owner_hash() ); +} + + +// Construction from pointer +void +test02() +{ + std::shared_ptr<A> a0; + + std::shared_ptr<A> a1(new A); + VERIFY( a1.owner_hash() != a0.owner_hash() ); + + std::shared_ptr<B> b1(new B); + VERIFY( a1.owner_hash() != b1.owner_hash() ); + + std::shared_ptr<A> a2(a1); + VERIFY( a1.owner_hash() == a2.owner_hash() ); + a2 = b1; + VERIFY( b1.owner_hash() == a2.owner_hash() ); + + std::weak_ptr<A> w1(a1); + VERIFY( a1.owner_hash() == w1.owner_hash() ); + std::weak_ptr<A> w2(a2); + VERIFY( b1.owner_hash() == w2.owner_hash() ); + + static_assert( noexcept(a1.owner_hash()) ); + static_assert( noexcept(b1.owner_hash()) ); +} + +// Aliasing +void +test03() +{ + std::shared_ptr<A> p1(new A()); + std::shared_ptr<int> p2(p1, &p1->i); + VERIFY( p1.owner_hash() == p2.owner_hash() ); +} + +int +main() +{ + test01(); + test02(); + test03(); + return 0; +} diff --git a/libstdc++-v3/testsuite/20_util/synchronized_pool_resource/118681.cc b/libstdc++-v3/testsuite/20_util/synchronized_pool_resource/118681.cc new file mode 100644 index 0000000..facbf00 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/synchronized_pool_resource/118681.cc @@ -0,0 +1,6 @@ +// { dg-do run { target c++17 } } +// { dg-require-gthreads "" } +// Bug 118681 - unsynchronized_pool_resource may fail to respect alignment + +#define RESOURCE std::pmr::synchronized_pool_resource +#include "../unsynchronized_pool_resource/118681.cc" diff --git a/libstdc++-v3/testsuite/20_util/unsynchronized_pool_resource/118681.cc b/libstdc++-v3/testsuite/20_util/unsynchronized_pool_resource/118681.cc new file mode 100644 index 0000000..9935f79 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/unsynchronized_pool_resource/118681.cc @@ -0,0 +1,58 @@ +// { dg-do run { target c++17 } } +// Bug 118681 - unsynchronized_pool_resource may fail to respect alignment + +#include <memory_resource> +#include <cstdio> +#include <testsuite_hooks.h> + +#ifndef RESOURCE +# define RESOURCE std::pmr::unsynchronized_pool_resource +#endif + +bool any_misaligned = false; + +bool +is_aligned(void* p, [[maybe_unused]] std::size_t size, std::size_t alignment) +{ + const bool misaligned = reinterpret_cast<std::uintptr_t>(p) % alignment; +#ifdef DEBUG + std::printf("allocate(%2zu, %2zu): %p is aligned %scorrectly\n", + size, alignment, p, misaligned ? "in" : ""); + any_misaligned |= misaligned; + return true; +#endif + return ! misaligned; +} + +void +test_alignment(std::pmr::memory_resource& res, bool dealloc) +{ + for (std::size_t alignment : { 8, 16, 32, 64 }) + { + for (std::size_t size : { 9, 12, 24, 40, 48, 56, 72 }) + { + void* p1 = res.allocate(size, alignment); + void* p2 = res.allocate(size, alignment); + + VERIFY( is_aligned(p1, size, alignment) ); + VERIFY( is_aligned(p2, size, alignment) ); + + if (dealloc) + { + res.deallocate(p1, size, alignment); + res.deallocate(p2, size, alignment); + } + } + } +} + +int main() +{ + RESOURCE res; + test_alignment(res, true); + res.release(); + test_alignment(res, false); + res.release(); + + VERIFY( ! any_misaligned ); +} diff --git a/libstdc++-v3/testsuite/20_util/weak_ptr/observers/owner_equal.cc b/libstdc++-v3/testsuite/20_util/weak_ptr/observers/owner_equal.cc new file mode 100644 index 0000000..0217a6e --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/weak_ptr/observers/owner_equal.cc @@ -0,0 +1,52 @@ +// { dg-do run { target c++26 } } +// { dg-require-effective-target hosted } + +// N5008 20.3.2.3.6 weak_ptr observers [util.smartptr.weak.obs] + +#include <memory> +#include <testsuite_hooks.h> + +struct A { }; +struct B { }; + +void +test01() +{ + // test empty weak_ptr owners compare equivalent + std::weak_ptr<A> p1; + std::weak_ptr<B> p2; + VERIFY( p1.owner_equal(p2) && p2.owner_equal(p1) ); + + std::shared_ptr<B> p3; + VERIFY( p1.owner_equal(p3) && p3.owner_equal(p1) ); + + static_assert( noexcept(p1.owner_equal(p1)) ); + static_assert( noexcept(p1.owner_equal(p2)) ); + static_assert( noexcept(p1.owner_equal(p3)) ); + static_assert( noexcept(p2.owner_equal(p1)) ); +} + + +void +test02() +{ + std::shared_ptr<A> a0; + std::weak_ptr<A> w0(a0); + + std::shared_ptr<A> a1(new A); + std::weak_ptr<A> w1(a1); + VERIFY( a1.owner_equal(w1) && w1.owner_equal(a1) ); + VERIFY( !w1.owner_equal(w0) && !w0.owner_equal(w1) ); + VERIFY( !w1.owner_equal(a0) && !a0.owner_equal(w1) ); + + std::shared_ptr<B> b1(new B); + VERIFY( !w1.owner_equal(b1) && !b1.owner_equal(w1) ); +} + +int +main() +{ + test01(); + test02(); + return 0; +} diff --git a/libstdc++-v3/testsuite/20_util/weak_ptr/observers/owner_hash.cc b/libstdc++-v3/testsuite/20_util/weak_ptr/observers/owner_hash.cc new file mode 100644 index 0000000..148a93b --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/weak_ptr/observers/owner_hash.cc @@ -0,0 +1,50 @@ +// { dg-do run { target c++26 } } +// { dg-require-effective-target hosted } + +// N5008 20.3.2.3.6 weak_ptr observers [util.smartptr.weak.obs] + +#include <memory> +#include <testsuite_hooks.h> + +struct A { }; +struct B { }; + +void +test01() +{ + // test empty weak_ptr hashes compare equivalent + std::weak_ptr<A> p1; + std::weak_ptr<B> p2; + VERIFY( p1.owner_hash() == p2.owner_hash() ); + + std::shared_ptr<B> p3; + VERIFY( p1.owner_hash() == p3.owner_hash() ); + + static_assert( noexcept(p1.owner_hash()) ); + static_assert( noexcept(p2.owner_hash()) ); +} + + +void +test02() +{ + std::shared_ptr<A> a0; + std::weak_ptr<A> w0(a0); + + std::shared_ptr<A> a1(new A); + std::weak_ptr<A> w1(a1); + VERIFY( a1.owner_hash() == w1.owner_hash() ); + VERIFY( w1.owner_hash() != w0.owner_hash() ); + VERIFY( w1.owner_hash() != a0.owner_hash() ); + + std::shared_ptr<B> b1(new B); + VERIFY( w1.owner_hash() != b1.owner_hash() ); +} + +int +main() +{ + test01(); + test02(); + return 0; +} diff --git a/libstdc++-v3/testsuite/22_locale/codecvt/codecvt_unicode.h b/libstdc++-v3/testsuite/22_locale/codecvt/codecvt_unicode.h index 9fe9ac8..2ba23bf 100644 --- a/libstdc++-v3/testsuite/22_locale/codecvt/codecvt_unicode.h +++ b/libstdc++-v3/testsuite/22_locale/codecvt/codecvt_unicode.h @@ -1439,7 +1439,7 @@ ucs2_to_utf8_out_error (const std::codecvt<InternT, ExternT, mbstate_t> &cvt) // make the trailing surrogate a BMP char {5, 10, 3, 6, u'z', 4}, - // don't replace anything in the test cases bellow, just show the surrogate + // don't replace anything in the test cases below, just show the surrogate // pair (fourth CP) fully or partially {5, 10, 3, 6, u'b', 0}, {5, 7, 3, 6, u'b', 0}, // no space for fourth CP @@ -2072,7 +2072,7 @@ utf16_to_ucs2_in_error (const std::codecvt<InternT, char, mbstate_t> &cvt, // make the trailing surrogate a BMP char {10, 5, 6, 3, u'z', 4}, - // don't replace anything in the test cases bellow, just show the surrogate + // don't replace anything in the test cases below, just show the surrogate // pair (fourth CP) fully or partially (just the first surrogate) {10, 5, 6, 3, u'b', 0}, {8, 5, 6, 3, u'b', 0}, diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/class_mandate_neg.cc b/libstdc++-v3/testsuite/23_containers/mdspan/class_mandate_neg.cc new file mode 100644 index 0000000..de19b6d --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/mdspan/class_mandate_neg.cc @@ -0,0 +1,41 @@ +// { dg-do compile { target c++23 } } +#include<mdspan> + +#include <cstdint> +#include "layout_like.h" + +struct ExtentsLike +{ + using index_type = int; + using size_type = unsigned int; + using rank_type = size_t; + + static constexpr size_t rank() { return 1; } + static constexpr size_t rank_dynamic() { return 0; } +}; + +constexpr bool +test_custom_extents_type() +{ + std::mdspan<double, ExtentsLike> md1; // { dg-error "required from here" } + return true; +} +static_assert(test_custom_extents_type()); + +constexpr bool +test_element_type_mismatch() +{ + using E = std::extents<int, 1>; + using L = std::layout_right; + using A = std::default_accessor<double>; + + [[maybe_unused]] std::mdspan<float, E, L, A> md2; // { dg-error "required from here" } + return true; +}; +static_assert(test_element_type_mismatch()); + +// { dg-prune-output "Extents must be a specialization of std::extents" } +// { dg-prune-output "no type named '_S_storage'" } +// { dg-prune-output "non-constant condition" } +// { dg-prune-output "static assertion failed" } +// { dg-prune-output "__glibcxx_assert" } diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/extents/class_mandates_neg.cc b/libstdc++-v3/testsuite/23_containers/mdspan/extents/class_mandates_neg.cc index f9c1c01..67d18fe 100644 --- a/libstdc++-v3/testsuite/23_containers/mdspan/extents/class_mandates_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/mdspan/extents/class_mandates_neg.cc @@ -7,6 +7,8 @@ std::extents<uint8_t, size_t(1) << 9> e1; // { dg-error "from here" } std::extents<char, 1> e2; // { dg-error "from here" } std::extents<bool, 1> e3; // { dg-error "from here" } std::extents<double, 1> e4; // { dg-error "from here" } + // { dg-prune-output "dynamic or representable as IndexType" } // { dg-prune-output "signed or unsigned integer" } // { dg-prune-output "invalid use of incomplete type" } +// { dg-prune-output "non-constant condition for static assertion" } diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/extents/custom_integer.cc b/libstdc++-v3/testsuite/23_containers/mdspan/extents/custom_integer.cc index 2907ad1..404755b 100644 --- a/libstdc++-v3/testsuite/23_containers/mdspan/extents/custom_integer.cc +++ b/libstdc++-v3/testsuite/23_containers/mdspan/extents/custom_integer.cc @@ -2,38 +2,13 @@ #include <mdspan> #include <testsuite_hooks.h> +#include "int_like.h" // Test construction from a custom integer-like object, that has // no copy/move ctor or copy/move assignment operator. constexpr size_t dyn = std::dynamic_extent; -class IntLike -{ -public: - explicit - IntLike(int i) - : _M_i(i) - { } - - IntLike() = delete; - IntLike(const IntLike&) = delete; - IntLike(IntLike&&) = delete; - - const IntLike& - operator=(const IntLike&) = delete; - - const IntLike& - operator=(IntLike&&) = delete; - - constexpr - operator int() const noexcept - { return _M_i; } - -private: - int _M_i; -}; - static_assert(std::is_convertible_v<IntLike, int>); static_assert(std::is_nothrow_constructible_v<int, IntLike>); diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/extents/extents_mismatch_neg.cc b/libstdc++-v3/testsuite/23_containers/mdspan/extents/extents_mismatch_neg.cc new file mode 100644 index 0000000..b35e531 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/mdspan/extents/extents_mismatch_neg.cc @@ -0,0 +1,35 @@ +// { dg-do compile { target c++23 } } +#include<mdspan> + +#include <cstdint> + +constexpr size_t dyn = std::dynamic_extent; + +constexpr bool +test_dyn2sta_extents_mismatch_00() +{ + auto e0 = std::extents<int, dyn>{1}; + [[maybe_unused]] auto e1 = std::extents<int, 2>{e0}; // { dg-error "expansion of" } + return true; +} +static_assert(test_dyn2sta_extents_mismatch_00()); // { dg-error "expansion of" } + +constexpr bool +test_dyn2sta_extents_mismatch_01() +{ + [[maybe_unused]] auto e = std::extents<int, 1, dyn>{2, 2}; // { dg-error "expansion of" } + return true; +} +static_assert(test_dyn2sta_extents_mismatch_01()); // { dg-error "expansion of" } + +constexpr bool +test_dyn2sta_extents_mismatch_02() +{ + std::array<int, 2> exts{2, 2}; + [[maybe_unused]] auto e = std::extents<int, 1, dyn>{exts}; // { dg-error "expansion of" } + return true; +} +static_assert(test_dyn2sta_extents_mismatch_02()); // { dg-error "expansion of" } + +// { dg-prune-output "non-constant condition for static assertion" } +// { dg-prune-output "__glibcxx_assert" } diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/extents/int_like.h b/libstdc++-v3/testsuite/23_containers/mdspan/extents/int_like.h new file mode 100644 index 0000000..f39f4cc --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/mdspan/extents/int_like.h @@ -0,0 +1,30 @@ +#ifndef TEST_MDSPAN_INT_LIKE_H +#define TEST_MDSPAN_INT_LIKE_H + +class IntLike +{ +public: + explicit + IntLike(int i) + : _M_i(i) + { } + + IntLike() = delete; + IntLike(const IntLike&) = delete; + IntLike(IntLike&&) = delete; + + const IntLike& + operator=(const IntLike&) = delete; + + const IntLike& + operator=(IntLike&&) = delete; + + constexpr + operator int() const noexcept + { return _M_i; } + +private: + int _M_i; +}; + +#endif // TEST_MDSPAN_INT_LIKE_H diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/extents/misc.cc b/libstdc++-v3/testsuite/23_containers/mdspan/extents/misc.cc index e71fdc5..bca8901 100644 --- a/libstdc++-v3/testsuite/23_containers/mdspan/extents/misc.cc +++ b/libstdc++-v3/testsuite/23_containers/mdspan/extents/misc.cc @@ -98,12 +98,32 @@ test_deduction(Extents... exts) } constexpr bool +test_integral_constant_deduction() +{ + auto verify = [](auto actual, auto expected) + { + static_assert(std::same_as<decltype(actual), decltype(expected)>); + VERIFY(actual == expected); + }; + + constexpr auto c1 = std::integral_constant<size_t, 1>{}; + constexpr auto c2 = std::integral_constant<int, 2>{}; + + verify(std::extents(1), std::extents<size_t, dyn>{1}); + verify(std::extents(c1), std::extents<size_t, 1>{}); + verify(std::extents(c2), std::extents<size_t, 2>{}); + verify(std::extents(c1, 2), std::extents<size_t, 1, dyn>{2}); + return true; +} + +constexpr bool test_deduction_all() { test_deduction<0>(); test_deduction<1>(1); test_deduction<2>(1.0, 2.0f); test_deduction<3>(int(1), short(2), size_t(3)); + test_integral_constant_deduction(); return true; } diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/layout_like.h b/libstdc++-v3/testsuite/23_containers/mdspan/layout_like.h new file mode 100644 index 0000000..6a0f8ca --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/mdspan/layout_like.h @@ -0,0 +1,83 @@ +#ifndef TEST_MDSPAN_LAYOUT_LIKE_H +#define TEST_MDSPAN_LAYOUT_LIKE_H 1 + +struct LayoutLike +{ + template<typename Extents> + class mapping + { + public: + using extents_type = Extents; + using index_type = typename extents_type::index_type; + using size_type = typename extents_type::size_type; + using rank_type = typename extents_type::rank_type; + using layout_type = LayoutLike; + + constexpr + mapping() noexcept = default; + + constexpr + mapping(Extents exts) + : m_exts(exts) + { } + + constexpr const extents_type& + extents() const noexcept { return m_exts; } + + constexpr index_type + required_span_size() const noexcept + { + for (size_t i = 0; i < extents_type::rank(); ++i) + if (m_exts.extent(i) == 0) + return 0; + return 1; + } + + template<typename... Indices> + requires (sizeof...(Indices) == extents_type::rank()) + constexpr index_type + operator()(Indices...) const noexcept + { return 0; } + + static constexpr index_type + stride(rank_type) noexcept + { return 0; } + + static constexpr bool + is_always_unique() noexcept + { return false; } + + static constexpr bool + is_always_exhaustive() noexcept + { return true; } + + static constexpr bool + is_always_strided() noexcept + { return true; } + + constexpr bool + is_unique() noexcept + { + if (required_span_size() == 0) + return true; + + for (size_t i = 0; i < extents_type::rank(); ++i) + if (m_exts.extent(i) > 1) + return false; + return true; + } + + static constexpr bool + is_exhaustive() noexcept + { return true; } + + static constexpr bool + is_strided() noexcept + { return true; } + + private: + Extents m_exts; + }; +}; + +#endif diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/debug/out_of_bounds_neg.cc b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/debug/out_of_bounds_neg.cc new file mode 100644 index 0000000..fb8ff01 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/debug/out_of_bounds_neg.cc @@ -0,0 +1,30 @@ +// { dg-do compile { target c++23 } } +// { dg-require-debug-mode "" } +#include<mdspan> + +template<typename Layout> + constexpr bool + test_out_of_bounds_1d() + { + auto m = typename Layout::mapping<std::extents<int, 0>>{}; + (void) m(0); // { dg-error "expansion of" } + return true; + } +static_assert(test_out_of_bounds_1d<std::layout_left>()); // { dg-error "expansion of" } +static_assert(test_out_of_bounds_1d<std::layout_right>()); // { dg-error "expansion of" } +static_assert(test_out_of_bounds_1d<std::layout_stride>()); // { dg-error "expansion of" } + +template<typename Layout> + constexpr bool + test_out_of_bounds_3d() + { + auto m = typename Layout::mapping<std::extents<int, 3, 5, 7>>{}; + (void) m(2, 5, 5); // { dg-error "expansion of" } + return true; + } +static_assert(test_out_of_bounds_3d<std::layout_left>()); // { dg-error "expansion of" } +static_assert(test_out_of_bounds_3d<std::layout_right>()); // { dg-error "expansion of" } +static_assert(test_out_of_bounds_3d<std::layout_stride>()); // { dg-error "expansion of" } + +// { dg-prune-output "non-constant condition for static assertion" } +// { dg-prune-output "__glibcxx_assert" } diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc b/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc new file mode 100644 index 0000000..a650fb1 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc @@ -0,0 +1,668 @@ +// { dg-do run { target c++23 } } +#include <mdspan> + +#include <testsuite_hooks.h> +#include "extents/int_like.h" +#include "layout_like.h" + +constexpr auto dyn = std::dynamic_extent; + +template<typename MDSpan, typename T, typename E, typename L = std::layout_right, + typename A = std::default_accessor<T>> + constexpr void + assert_typedefs() + { + static_assert(std::same_as<typename MDSpan::extents_type, E>); + static_assert(std::same_as<typename MDSpan::layout_type, L>); + static_assert(std::same_as<typename MDSpan::accessor_type, A>); + static_assert(std::same_as<typename MDSpan::mapping_type, + typename L::mapping<E>>); + static_assert(std::same_as<typename MDSpan::element_type, T>); + static_assert(std::same_as<typename MDSpan::value_type, + std::remove_const_t<T>>); + static_assert(std::same_as<typename MDSpan::index_type, + typename E::index_type>); + static_assert(std::same_as<typename MDSpan::size_type, + typename E::size_type>); + static_assert(std::same_as<typename MDSpan::rank_type, + typename E::rank_type>); + static_assert(std::same_as<typename MDSpan::data_handle_type, + typename A::data_handle_type>); + static_assert(std::same_as<typename MDSpan::reference, + typename A::reference>); + } + +template<typename T, typename E, typename L, template<typename U> typename A> + constexpr void + test_typedefs() + { assert_typedefs<std::mdspan<T, E, L, A<T>>, T, E, L, A<T>>(); } + +constexpr void +test_typedefs_all() +{ + using E = std::extents<int, 1, 2>; + using L = std::layout_left; + + test_typedefs<double, E, L, std::default_accessor>(); + test_typedefs<const double, E, L, std::default_accessor>(); +} + +template<typename MDSpan> + constexpr void + test_rank() + { + using Extents = typename MDSpan::extents_type; + static_assert(MDSpan::rank() == Extents::rank()); + static_assert(MDSpan::rank_dynamic() == Extents::rank_dynamic()); + } + +constexpr bool +test_rank_all() +{ + test_rank<std::mdspan<double, std::extents<int>>>(); + test_rank<std::mdspan<double, std::extents<int, 1>>>(); + test_rank<std::mdspan<double, std::extents<int, dyn>>>(); + return true; +} + +template<typename Extents> + constexpr void + test_extent(Extents exts) + { + double data = 1.0; + auto md = std::mdspan(&data, exts); + using MDSpan = decltype(md); + + for(size_t i = 0; i < MDSpan::rank(); ++i) + { + VERIFY(MDSpan::static_extent(i) == Extents::static_extent(i)); + VERIFY(md.extent(i) == exts.extent(i)); + } + } + +constexpr bool +test_extent_all() +{ + // For rank == 0, check existence of the methods without calling them. + test_extent(std::extents<int>{}); + test_extent(std::extents<int, 0>{}); + test_extent(std::extents<int, dyn>{}); + return true; +} + +template<typename MDSpan> + constexpr void + test_class_properties() + { + static_assert(std::copyable<MDSpan>); + static_assert(std::is_nothrow_move_constructible_v<MDSpan>); + static_assert(std::is_nothrow_move_assignable_v<MDSpan>); + static_assert(std::is_nothrow_swappable_v<MDSpan>); + constexpr bool trivially_copyable = + std::is_trivially_copyable_v<typename MDSpan::accessor_type> + && std::is_trivially_copyable_v<typename MDSpan::mapping_type> + && std::is_trivially_copyable_v<typename MDSpan::data_handle_type>; + static_assert(std::is_trivially_copyable_v<MDSpan> == trivially_copyable); + } + +constexpr bool +test_class_properties_all() +{ + test_class_properties<std::mdspan<double, std::extents<int>>>(); + test_class_properties<std::mdspan<double, std::extents<int, 1>>>(); + test_class_properties<std::mdspan<double, std::extents<int, dyn>>>(); + return true; +} + +constexpr bool +test_default_ctor() +{ + static_assert(!std::is_default_constructible_v<std::mdspan<double, + std::extents<int>>>); + static_assert(!std::is_default_constructible_v<std::mdspan<double, + std::extents<int, 1>>>); + static_assert(std::is_default_constructible_v<std::mdspan<double, + std::extents<int, dyn>>>); + + std::mdspan<double, std::extents<int, dyn>> md; + VERIFY(md.data_handle() == nullptr); + VERIFY(md.empty()); + return true; +} + +constexpr bool +test_from_other() +{ + using Extents = std::extents<int, 3, 5, 7>; + auto exts = Extents{}; + + auto mapping = std::layout_right::mapping(exts); + constexpr size_t n = mapping.required_span_size(); + std::array<double, n> storage{}; + + auto md1 = std::mdspan(storage.data(), exts); + auto md2 = std::mdspan<double, std::dextents<int, 3>>(md1); + + VERIFY(md1.data_handle() == md2.data_handle()); + VERIFY(md1.size() == md2.size()); + + static_assert(!std::is_convertible_v< + std::mdspan<double, std::extents<unsigned int, 2>>, + std::mdspan<double, std::extents<int, 2>>>); + + static_assert(std::is_convertible_v< + std::mdspan<double, std::extents<int, 2>>, + std::mdspan<const double, std::extents<int, 2>>>); + + static_assert(!std::is_constructible_v< + std::mdspan<double, std::extents<int, 2>>, + std::mdspan<const double, std::extents<int, 2>>>); + + return true; +} + +template<typename T, typename E, typename L = std::layout_right, + typename A = std::default_accessor<T>> + constexpr void + assert_deduced_typedefs(auto md) + { assert_typedefs<decltype(md), T, E, L, A>(); } + +constexpr bool +test_from_carray() +{ + constexpr size_t n = 5; + double data[n] = {1.1, 2.2, 3.3, 4.4, 5.5}; + + auto md = std::mdspan(data); + assert_deduced_typedefs<double, std::extents<size_t, n>>(md); + VERIFY(md.rank() == 1); + VERIFY(md.rank_dynamic() == 0); + VERIFY(md[2] == data[2]); + return true; +} + +constexpr bool +test_from_pointer() +{ + double value = 12.3; + auto md = std::mdspan(&value); + assert_deduced_typedefs<double, std::extents<size_t>>(md); + VERIFY(md.rank() == 0); + VERIFY(md.rank_dynamic() == 0); + VERIFY(md[] == value); + return true; +} + +constexpr bool +test_from_pointer_and_shape() +{ + constexpr size_t n = 6; + std::array<double, n> data{1.1, 2.2, 3.3, 4.4, 5.5, 6.6}; + std::array<int, 2> shape{2, 3}; + std::span<const int, 2> shape_view(shape); + + auto verify = [&data](auto md) + { + assert_deduced_typedefs<double, std::dextents<size_t, 2>>(md); + VERIFY(md.rank() == 2); + VERIFY(md.rank_dynamic() == 2); + VERIFY((md[0, 0]) == data[0]); + VERIFY((md[0, 1]) == data[1]); + VERIFY((md[1, 0]) == data[3]); + }; + + verify(std::mdspan(data.data(), shape[0], shape[1])); + verify(std::mdspan(data.data(), shape)); + verify(std::mdspan(data.data(), shape_view)); + + std::mdspan<double, std::dextents<size_t, 2>> md1 = {data.data(), shape}; + verify(md1); + + std::mdspan<double, std::dextents<size_t, 2>> md2 = {data.data(), shape_view}; + verify(md2); + + static_assert(std::is_constructible_v< + std::mdspan<float, std::extents<int, 3, 5>>, float*>); + static_assert(!std::is_constructible_v< + std::mdspan<float, std::extents<int, 3, 5>>, float*, int>); + static_assert(std::is_constructible_v< + std::mdspan<float, std::extents<int, 3, 5>>, float*, int, int>); + static_assert(std::is_constructible_v< + std::mdspan<float, std::extents<int, 3, 5>>, float*, std::span<int, 0>>); + static_assert(std::is_constructible_v< + std::mdspan<float, std::extents<int, 3, 5>>, float*, std::span<int, 2>>); + static_assert(!std::is_convertible_v< + float*, std::mdspan<float, std::extents<int, 3, 5>>>); + + static_assert(std::is_constructible_v< + std::mdspan<float, std::dextents<int, 2>>, float*, std::span<int, 2>>); + static_assert(!std::is_constructible_v< + std::mdspan<float, std::dextents<int, 2>>, float*, std::span<int, 1>>); + static_assert(!std::is_constructible_v< + std::mdspan<float, std::dextents<int, 2>>, float*, std::span<int, 3>>); + static_assert(!std::is_constructible_v< + std::mdspan<float, std::dextents<int, 2>>, float*, std::span<int, dyn>>); + return true; +} + +constexpr bool +test_from_pointer_and_integral_constant() +{ + std::array<double, 6> buffer{}; + double * ptr = buffer.data(); + + auto verify = [ptr](auto actual, auto exts) + { + auto expected = std::mdspan<double, decltype(exts)>(ptr, exts); + static_assert(std::same_as<decltype(actual), decltype(expected)>); + VERIFY(actual.extents() == expected.extents()); + }; + + auto c3 = std::integral_constant<int, 3>{}; + auto c6 = std::integral_constant<int, 6>{}; + + verify(std::mdspan(ptr, 6), std::extents(6)); + verify(std::mdspan(ptr, c6), std::extents(c6)); + verify(std::mdspan(ptr, 2, c3), std::extents(2, c3)); + return true; +} + +constexpr bool +test_from_extents() +{ + constexpr size_t n = 3*5*7; + std::array<double, n> storage{}; + using Extents = std::extents<int, 3, 5, 7>; + auto exts = Extents{}; + auto md = std::mdspan(storage.data(), exts); + + assert_deduced_typedefs<double, Extents>(md); + VERIFY(md.data_handle() == storage.data()); + VERIFY(md.extents() == exts); + return true; +} + +constexpr bool +test_from_mapping() +{ + constexpr size_t n = 3*5*7; + std::array<double, n> storage{}; + using Extents = std::extents<int, 3, 5, 7>; + + auto exts = Extents{}; + auto m = std::layout_left::mapping(exts); + auto md = std::mdspan(storage.data(), m); + + assert_deduced_typedefs<double, Extents, std::layout_left>(md); + VERIFY(md.data_handle() == storage.data()); + VERIFY(md.mapping() == m); + return true; +} + +constexpr bool +test_from_accessor() +{ + constexpr size_t n = 3*5*7; + std::array<double, n> storage{}; + using Extents = std::extents<int, 3, 5, 7>; + + auto exts = Extents{}; + auto m = std::layout_left::mapping(exts); + auto a = std::default_accessor<double>{}; + auto md = std::mdspan(storage.data(), m, a); + + assert_deduced_typedefs<double, Extents, std::layout_left>(md); + VERIFY(md.data_handle() == storage.data()); + VERIFY(md.mapping() == m); + return true; +} + +void +test_from_int_like() +{ + constexpr size_t n = 3*5*7; + std::array<double, n> storage{}; + + auto verify = [&](auto md) + { + VERIFY(md.data_handle() == storage.data()); + VERIFY(md.extent(0) == 3); + VERIFY(md.extent(1) == 5); + VERIFY(md.extent(2) == 7); + + VERIFY((md[IntLike(0), 0, IntLike(0)]) == 0.0); + auto zero = std::array{IntLike(0), IntLike(0), IntLike(0)}; + auto zero_view = std::span<IntLike, 3>{zero}; + VERIFY((md[zero]) == 0.0); + VERIFY((md[zero_view]) == 0.0); + }; + + auto shape = std::array{IntLike(3), IntLike(5), IntLike(7)}; + auto shape_view = std::span<IntLike, 3>{shape}; + verify(std::mdspan(storage.data(), IntLike(3), 5, IntLike(7))); + verify(std::mdspan(storage.data(), shape)); + verify(std::mdspan(storage.data(), shape_view)); +} + +template<typename T, bool NothrowConstructible = true, + bool NothrowAssignable = true> + class OpaqueAccessor + { + struct Handle + { + constexpr + Handle(T * other) + : ptr(other) + { } + + constexpr + Handle(const Handle&) noexcept(NothrowConstructible) = default; + + constexpr + Handle(Handle&&) noexcept(NothrowConstructible) = default; + + constexpr Handle& + operator=(const Handle&) noexcept(NothrowAssignable) = default; + + constexpr Handle& + operator=(Handle&&) noexcept(NothrowAssignable) = default; + + T * ptr; + }; + + public: + using element_type = T; + using reference = T&; + using data_handle_type = Handle; + using offset_policy = OpaqueAccessor; + + reference + access(data_handle_type p, size_t i) const + { + ++access_count; + return p.ptr[i]; + } + + typename offset_policy::data_handle_type + offset(data_handle_type p, size_t i) const + { + ++offset_count; + return typename offset_policy::data_handle_type{(void*)(p.ptr + i)}; + } + + mutable size_t access_count = 0; + mutable size_t offset_count = 0; + }; + +void +test_from_opaque_accessor() +{ + constexpr size_t n = 3*5*7; + std::array<double, n> storage{}; + using Extents = std::extents<int, 3, 5, 7>; + + auto exts = Extents{}; + auto m = std::layout_left::mapping(exts); + auto a = OpaqueAccessor<double>{}; + auto handle = OpaqueAccessor<double>::data_handle_type{storage.data()}; + auto md = std::mdspan(handle, m, a); + + using MDSpan = decltype(md); + static_assert(std::same_as<MDSpan::accessor_type, decltype(a)>); + + VERIFY((md[0, 0, 0]) == 0.0); + VERIFY(md.accessor().access_count == 1); + + VERIFY((md[2, 4, 6]) == 0.0); + VERIFY(md.accessor().access_count == 2); +} + +template<typename T, typename Base> + class BaseClassAccessor + { + public: + using element_type = T; + using reference = Base&; + using data_handle_type = T*; + using offset_policy = BaseClassAccessor; + + static_assert(std::common_reference_with<reference&&, element_type&>); + + reference + access(data_handle_type p, size_t i) const + { return p[i]; } + + typename offset_policy::data_handle_type + offset(data_handle_type p, size_t i) const + { return typename offset_policy::data_handle_type{p + i}; } + }; + +struct Base +{ + double value = 1.0; +}; + +struct Derived : Base +{ + double value = 2.0; +}; + +void +test_from_base_class_accessor() +{ + constexpr size_t n = 3*5*7; + std::array<Derived, n> storage{}; + using Extents = std::extents<int, 3, 5, 7>; + + auto exts = Extents{}; + auto m = std::layout_left::mapping(exts); + auto a = BaseClassAccessor<Derived, Base>{}; + auto md = std::mdspan(storage.data(), m, a); + + using MDSpan = decltype(md); + static_assert(std::same_as<MDSpan::accessor_type, decltype(a)>); + static_assert(std::same_as<decltype(md[0, 0, 0]), Base&>); + VERIFY((md[0, 0, 0].value) == 1.0); + VERIFY((md[2, 4, 6].value) == 1.0); +} + +constexpr bool +test_from_mapping_like() +{ + double data = 1.1; + auto m = LayoutLike::mapping<std::extents<int, 1, 2, 3>>{}; + auto md = std::mdspan(&data, m); + VERIFY((md[0, 0, 0]) == data); + VERIFY((md[0, 1, 2]) == data); + return true; +} + +template<typename MDSpan> + constexpr void + test_empty(MDSpan md) + { + VERIFY(md.empty() == (md.size() == 0)); + } + +constexpr bool +test_empty_all() +{ + test_empty(std::mdspan<double, std::extents<int, dyn>>{}); + return true; +} + +constexpr bool +test_access() +{ + using Extents = std::extents<int, 3, 5, 7>; + auto exts = Extents{}; + + auto mapping = std::layout_left::mapping(exts); + constexpr size_t n = mapping.required_span_size(); + std::array<double, n> storage{}; + + auto md = std::mdspan(storage.data(), mapping); + static_assert(std::__mdspan::__mapping_alike<decltype(md)>); + + for(int i = 0; i < exts.extent(0); ++i) + for(int j = 0; j < exts.extent(1); ++j) + for(int k = 0; k < exts.extent(2); ++k) + { + std::array<int, 3> ijk{i, j, k}; + storage[mapping(i, j, k)] = 1.0; + VERIFY((md[i, j, k]) == 1.0); + VERIFY((md[ijk]) == 1.0); + VERIFY((md[std::span(ijk)]) == 1.0); + storage[mapping(i, j, k)] = 0.0; + } + return true; +} + +constexpr bool +test_swap() +{ + using Extents = std::dextents<int, 2>; + auto e1 = Extents{3, 5}; + auto e2 = Extents{7, 11}; + + std::array<double, 3*5> s1{}; + std::array<double, 7*11> s2{}; + + auto md1 = std::mdspan(s1.data(), e1); + auto md2 = std::mdspan(s2.data(), e2); + + std::swap(md1, md2); + + VERIFY(md1.data_handle() == s2.data()); + VERIFY(md2.data_handle() == s1.data()); + + VERIFY(md1.size() == s2.size()); + VERIFY(md2.size() == s1.size()); + return true; +} + +namespace adl +{ + template<typename T> + struct SwappableAccessor + { + using element_type = T; + using reference = T&; + using data_handle_type = T*; + using offset_policy = SwappableAccessor; + + reference + access(data_handle_type p, size_t i) const + { return p[i]; } + + typename offset_policy::data_handle_type + offset(data_handle_type p, size_t i) const + { return p + i; } + + friend void + swap(SwappableAccessor&, SwappableAccessor&) + { ++swap_count; } + + static inline size_t swap_count = 0; + }; +} + +void +test_swap_adl() +{ + using Extents = std::extents<int, dyn>; + using Layout = std::layout_left; + using Accessor = adl::SwappableAccessor<double>; + Accessor::swap_count = 0; + + std::mdspan<double, Extents, Layout, Accessor> m1, m2; + swap(m1, m2); + VERIFY(Accessor::swap_count == 1); +} + +template<bool Constructible, bool Assignable> +constexpr void +test_nothrow_movable() +{ + using Layout = std::layout_left; + using Extents = std::dextents<int, 3>; + using Accessor = OpaqueAccessor<int, Constructible, Assignable>; + using Handle = Accessor::data_handle_type; + static_assert(std::is_nothrow_move_assignable_v<Accessor>); + static_assert(std::is_nothrow_move_constructible_v<Accessor>); + static_assert(std::is_nothrow_move_assignable_v<Handle> == Assignable); + static_assert(std::is_nothrow_move_constructible_v<Handle> == Constructible); + + using MDSpan = std::mdspan<int, Extents, Layout, Accessor>; + static_assert(std::is_nothrow_move_assignable_v<MDSpan> == Assignable); + static_assert(std::is_nothrow_move_constructible_v<MDSpan> == Constructible); +} + +constexpr void +test_nothrow_movable_all() +{ + using MDSpan = std::mdspan<double, std::dextents<int, 3>>; + static_assert(std::is_nothrow_move_assignable_v<MDSpan>); + static_assert(std::is_nothrow_move_constructible_v<MDSpan>); + + test_nothrow_movable<true, true>(); + test_nothrow_movable<true, false>(); + test_nothrow_movable<false, true>(); + test_nothrow_movable<false, false>(); +} + +int +main() +{ + test_typedefs_all(); + + test_rank_all(); + test_extent_all(); + static_assert(test_extent_all()); + + test_class_properties_all(); + static_assert(test_class_properties_all()); + + test_empty_all(); + static_assert(test_empty_all()); + + test_default_ctor(); + static_assert(test_default_ctor()); + + test_from_other(); + static_assert(test_from_other()); + + test_from_carray(); + static_assert(test_from_carray()); + + test_from_pointer_and_shape(); + static_assert(test_from_pointer_and_shape()); + + test_from_pointer_and_integral_constant(); + static_assert(test_from_pointer_and_integral_constant()); + + test_from_extents(); + static_assert(test_from_extents()); + + test_from_mapping(); + static_assert(test_from_mapping()); + + test_from_accessor(); + static_assert(test_from_accessor()); + + test_from_int_like(); + test_from_opaque_accessor(); + test_from_base_class_accessor(); + test_from_mapping_like(); + static_assert(test_from_mapping_like()); + + test_access(); + static_assert(test_access()); + + test_swap(); + static_assert(test_swap()); + test_swap_adl(); + + test_nothrow_movable_all(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/out_of_bounds_neg.cc b/libstdc++-v3/testsuite/23_containers/mdspan/out_of_bounds_neg.cc new file mode 100644 index 0000000..dceae56 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/mdspan/out_of_bounds_neg.cc @@ -0,0 +1,24 @@ +// { dg-do compile { target c++23 } } +#include<mdspan> + +#include "layout_like.h" + +template<typename Layout> +constexpr bool +test_invalid_multi_index() +{ + + double data = 1.1; + auto m = typename Layout::mapping<std::extents<int, 1, 2, 3>>{}; + auto md = std::mdspan(&data, m); + + [[maybe_unused]] double x = md[0, 2, 2]; // { dg-error "expansion of" } + return true; +}; +static_assert(test_invalid_multi_index<LayoutLike>()); // { dg-error "expansion of" } +static_assert(test_invalid_multi_index<std::layout_left>()); // { dg-error "expansion of" } +static_assert(test_invalid_multi_index<std::layout_right>()); // { dg-error "expansion of" } +static_assert(test_invalid_multi_index<std::layout_stride>()); // { dg-error "expansion of" } + +// { dg-prune-output "non-constant condition" } +// { dg-prune-output "__glibcxx_assert" } diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/version.cc b/libstdc++-v3/testsuite/23_containers/mdspan/version.cc new file mode 100644 index 0000000..106ee40 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/mdspan/version.cc @@ -0,0 +1,9 @@ +// { dg-do compile { target c++23 } } +#include <mdspan> + +#ifndef __cpp_lib_mdspan +#error "Feature test macro __cpp_lib_mdspan is missing for <mdspan>" +#if __cpp_lib_mdspan < 202207 +#error "Feature test macro __cpp_lib_mdspan has the wrong value" +#endif +#endif diff --git a/libstdc++-v3/testsuite/23_containers/span/120997.cc b/libstdc++-v3/testsuite/23_containers/span/120997.cc new file mode 100644 index 0000000..fbf194c --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/span/120997.cc @@ -0,0 +1,46 @@ +// { dg-do run { target c++26 } } + +#include <span> +#include <testsuite_hooks.h> + +void +test_first() +{ + bool arr[5]; + std::span<const bool> s(arr); + std::span<const bool> s2 = s.first(5); + VERIFY( s2.data() == s.data() ); + std::span<const bool> s3 = s.first<5>(); + VERIFY( s3.data() == s.data() ); +} + +void +test_last() +{ + bool arr[5]; + std::span<const bool> s(arr); + std::span<const bool> s2 = s.last(5); + VERIFY( s2.data() == s.data() ); + std::span<const bool> s3 = s.last<5>(); + VERIFY( s3.data() == s.data() ); +} + +void +test_subspan() +{ + bool arr[5]; + std::span<const bool> s(arr); + std::span<const bool> s2 = s.subspan(0, 5); + VERIFY( s2.data() == s.data() ); + std::span<const bool> s3 = s.subspan<0>(); + VERIFY( s3.data() == s.data() ); + std::span<const bool> s4 = s.subspan<0, 5>(); + VERIFY( s4.data() == s.data() ); +} + +int main() +{ + test_first(); + test_last(); + test_subspan(); +} diff --git a/libstdc++-v3/testsuite/23_containers/span/contiguous_range_neg.cc b/libstdc++-v3/testsuite/23_containers/span/contiguous_range_neg.cc index c9e9112..890fdf8 100644 --- a/libstdc++-v3/testsuite/23_containers/span/contiguous_range_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/span/contiguous_range_neg.cc @@ -25,6 +25,7 @@ main() { std::deque<int> d{}; std::span<int, std::dynamic_extent> myspan(d); // { dg-error "no match" } + (void) myspan; } // { dg-prune-output "data" } diff --git a/libstdc++-v3/testsuite/23_containers/span/deduction.cc b/libstdc++-v3/testsuite/23_containers/span/deduction.cc index dce6ced..c66db90 100644 --- a/libstdc++-v3/testsuite/23_containers/span/deduction.cc +++ b/libstdc++-v3/testsuite/23_containers/span/deduction.cc @@ -80,4 +80,7 @@ test01() std::span s12(const_cast<const std::span<int>&>(s5)); static_assert( is_dynamic_span<int>(s12) ); + + std::span s13(a.data(), std::integral_constant<size_t, 3>{}); + static_assert( is_static_span<long, 3>(s13)); } diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/const_container.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/const_container.cc new file mode 100644 index 0000000..e62f158 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/unordered_map/const_container.cc @@ -0,0 +1,19 @@ +// { dg-do compile { target c++11 } } + +#include <unordered_map> + +#include <testsuite_hooks.h> + +// PR c++/116369 +const std::unordered_map<int, int> um + { + { 0, 1 }, + { 2, 3 }, + { 4, 5 } + }; + +int main() +{ + VERIFY( um.size() == 3 ); + VERIFY( um.find(0) != um.end() ); +} diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/const_container.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/const_container.cc new file mode 100644 index 0000000..3da1e33 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/const_container.cc @@ -0,0 +1,22 @@ +// { dg-do compile { target c++11 } } + +#include <unordered_map> + +#include <testsuite_hooks.h> + +// PR c++/116369 +const std::unordered_multimap<int, int> umm + { + { 0, 1 }, + { 0, 1 }, + { 2, 3 }, + { 2, 3 }, + { 4, 5 }, + { 4, 5 } + }; + +int main() +{ + VERIFY( umm.size() == 6 ); + VERIFY( umm.find(0) != umm.end() ); +} diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/const_container.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/const_container.cc new file mode 100644 index 0000000..841d25a --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/const_container.cc @@ -0,0 +1,15 @@ +// { dg-do compile { target c++11 } } + +#include <unordered_set> + +#include <testsuite_hooks.h> + +// PR c++/116369 +const std::unordered_multiset<int> ums + { 0, 0, 1, 1, 2, 2 }; + +int main() +{ + VERIFY( ums.size() == 6 ); + VERIFY( ums.find(0) != ums.end() ); +} diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/const_container.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/const_container.cc new file mode 100644 index 0000000..ffdbbad --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/unordered_set/const_container.cc @@ -0,0 +1,14 @@ +// { dg-do compile { target c++11 } } + +#include <unordered_set> + +#include <testsuite_hooks.h> + +// PR c++/116369 +const std::unordered_set<int> us { 0, 1, 2 }; + +int main() +{ + VERIFY( us.size() == 3 ); + VERIFY( us.find(0) != us.end() ); +} diff --git a/libstdc++-v3/testsuite/23_containers/vector/debug/mutex_association.cc b/libstdc++-v3/testsuite/23_containers/vector/debug/mutex_association.cc index ba2ede0..792ed45 100644 --- a/libstdc++-v3/testsuite/23_containers/vector/debug/mutex_association.cc +++ b/libstdc++-v3/testsuite/23_containers/vector/debug/mutex_association.cc @@ -25,7 +25,7 @@ class container : public __gnu_debug::_Safe_sequence<container> { public: __gnu_cxx::__mutex& - get_mutex() + get_mutex() const { return this->_M_get_mutex(); } }; diff --git a/libstdc++-v3/testsuite/ext/verify_neg.cc b/libstdc++-v3/testsuite/ext/verify_neg.cc new file mode 100644 index 0000000..ce03374 --- /dev/null +++ b/libstdc++-v3/testsuite/ext/verify_neg.cc @@ -0,0 +1,28 @@ +// { dg-do compile { target c++11 } } + +#include <testsuite_hooks.h> + +struct X { explicit operator void*() const { return nullptr; } }; + +void +test_VERIFY(int i) +{ + // This should not be parsed as a function type bool(bool(i)): + VERIFY( bool(i) ); + + // This should not produce warnings about lambda in unevaluated context: + VERIFY( []{ return 1; }() ); + + // Only one expression allowed: + VERIFY(1, 2); // { dg-error "in expansion of macro" } + // { dg-error "compound expression in functional cast" "" { target *-*-* } 0 } + + // A scoped enum is not contextually convertible to bool: + enum class E { E0 }; + VERIFY( E::E0 ); // { dg-error "could not convert" } + + // explicit conversion to void* is not contextually convertible to bool: + X x; + VERIFY( x ); // { dg-error "in expansion of macro" } + // { dg-error "invalid cast .* to type 'bool'" "" { target *-*-* } 0 } +} diff --git a/libstdc++-v3/testsuite/std/format/ranges/pr119861_neg.cc b/libstdc++-v3/testsuite/std/format/ranges/pr119861_neg.cc new file mode 100644 index 0000000..9a6ed16 --- /dev/null +++ b/libstdc++-v3/testsuite/std/format/ranges/pr119861_neg.cc @@ -0,0 +1,52 @@ +// { dg-do compile { target c++23 } } + +#include <format> +#include <vector> + +// only format_kind::sequence provides set_brackets and set_separator methods + +template<std::range_format fk, typename T> +struct MyCont : std::vector<T> +{ + using std::vector<T>::vector; +}; + +template<std::range_format fk, typename T> +constexpr std::range_format std::format_kind<MyCont<fk, T>> = fk; + +void test_sequence() +{ + std::formatter<MyCont<std::range_format::sequence, int>, char> fmtter; + fmtter.set_brackets("{", "}"); + fmtter.set_separator(","); +} + +void test_map() +{ + std::formatter<MyCont<std::range_format::map, std::pair<int, int>>, char> fmtter; + fmtter.set_brackets("{", "}"); // { dg-error "here" } + fmtter.set_separator(","); // { dg-error "here" } +} + +void test_set() +{ + std::formatter<MyCont<std::range_format::set, int>, char> fmtter; + fmtter.set_brackets("{", "}"); // { dg-error "here" } + fmtter.set_separator(","); // { dg-error "here" } +} + +void test_string() +{ + std::formatter<MyCont<std::range_format::string, char>, char> fmtter; + fmtter.set_brackets("{", "}"); // { dg-error "here" } + fmtter.set_separator(","); // { dg-error "here" } +} + +void test_debug_string() +{ + std::formatter<MyCont<std::range_format::debug_string, char>, char> fmtter; + fmtter.set_brackets("{", "}"); // { dg-error "here" } + fmtter.set_separator(","); // { dg-error "here" } +} + +// { dg-error "no matching function for call to 'std::formatter<" "" { target *-*-* } 0 } diff --git a/libstdc++-v3/testsuite/std/ranges/iota/max_size_type.cc b/libstdc++-v3/testsuite/std/ranges/iota/max_size_type.cc index 4739d9e..fbd783b 100644 --- a/libstdc++-v3/testsuite/std/ranges/iota/max_size_type.cc +++ b/libstdc++-v3/testsuite/std/ranges/iota/max_size_type.cc @@ -352,6 +352,9 @@ static_assert(numeric_limits<max_size_t>::is_specialized); static_assert(!numeric_limits<max_size_t>::is_signed); static_assert(numeric_limits<max_size_t>::is_integer); static_assert(numeric_limits<max_size_t>::is_exact); +static_assert(numeric_limits<max_size_t>::is_bounded); +static_assert(numeric_limits<max_size_t>::is_modulo); +static_assert(numeric_limits<max_size_t>::radix == 2); // We can't unconditionally use numeric_limits here because __int128 is an // integral type only in GNU mode. #if __SIZEOF_INT128__ @@ -379,6 +382,9 @@ static_assert(numeric_limits<max_diff_t>::is_specialized); static_assert(numeric_limits<max_diff_t>::is_signed); static_assert(numeric_limits<max_diff_t>::is_integer); static_assert(numeric_limits<max_diff_t>::is_exact); +static_assert(numeric_limits<max_diff_t>::is_bounded); +static_assert(!numeric_limits<max_diff_t>::is_modulo); +static_assert(numeric_limits<max_diff_t>::radix == 2); static_assert(numeric_limits<max_diff_t>::digits == numeric_limits<max_size_t>::digits - 1); static_assert(numeric_limits<max_diff_t>::digits10 @@ -400,6 +406,31 @@ static_assert(max_diff_t(max_size_t(1) << (numeric_limits<max_size_t>::digits-1)) == numeric_limits<max_diff_t>::min()); +template <typename integer_class> +constexpr bool verify_numeric_limits_values_not_meaningful_for = true + && (numeric_limits<integer_class>::max_digits10 == 0) + && (numeric_limits<integer_class>::min_exponent == 0) + && (numeric_limits<integer_class>::min_exponent10 == 0) + && (numeric_limits<integer_class>::max_exponent == 0) + && (numeric_limits<integer_class>::max_exponent10 == 0) + && !numeric_limits<integer_class>::is_iec559 + && !numeric_limits<integer_class>::has_infinity + && !numeric_limits<integer_class>::has_quiet_NaN + && !numeric_limits<integer_class>::has_signaling_NaN + && !numeric_limits<integer_class>::has_denorm_loss + && !numeric_limits<integer_class>::tinyness_before + && (numeric_limits<integer_class>::has_denorm == std::denorm_absent) + && (numeric_limits<integer_class>::round_style == std::round_toward_zero) + && (numeric_limits<integer_class>::denorm_min() == 0) + && (numeric_limits<integer_class>::epsilon() == 0) + && (numeric_limits<integer_class>::round_error() == 0) + && (numeric_limits<integer_class>::infinity() == 0) + && (numeric_limits<integer_class>::quiet_NaN() == 0) + && (numeric_limits<integer_class>::signaling_NaN() == 0); + +static_assert(verify_numeric_limits_values_not_meaningful_for<max_size_t>); +static_assert(verify_numeric_limits_values_not_meaningful_for<max_diff_t>); + // Verify that the types are structural types and can therefore be used // as NTTP types. template<max_size_t V> struct Su { static_assert(V*V == V+132); }; diff --git a/libstdc++-v3/testsuite/std/time/format/format.cc b/libstdc++-v3/testsuite/std/time/format/format.cc index d6e3583..00affb9 100644 --- a/libstdc++-v3/testsuite/std/time/format/format.cc +++ b/libstdc++-v3/testsuite/std/time/format/format.cc @@ -78,6 +78,13 @@ test_bad_format_strings() VERIFY( not is_format_string_for("{:%OOy}", t) ); VERIFY( not is_format_string_for("{:%OEy}", t) ); VERIFY( not is_format_string_for("{:%EOy}", t) ); + + // weekday and month values for which ok() is false + VERIFY( not is_format_string_for("{:%a}", std::chrono::weekday(8)) ); + VERIFY( not is_format_string_for("{:%A}", std::chrono::weekday(8)) ); + VERIFY( not is_format_string_for("{:%b}", std::chrono::month(13)) ); + VERIFY( not is_format_string_for("{:%h}", std::chrono::month(13)) ); + VERIFY( not is_format_string_for("{:%B}", std::chrono::month(13)) ); } template<typename I> diff --git a/libstdc++-v3/testsuite/std/time/format/pr117214_custom_timeput.cc b/libstdc++-v3/testsuite/std/time/format/pr117214_custom_timeput.cc new file mode 100644 index 0000000..03b9496 --- /dev/null +++ b/libstdc++-v3/testsuite/std/time/format/pr117214_custom_timeput.cc @@ -0,0 +1,37 @@ +// { dg-do run { target c++20 } } + +#include <chrono> +#include <format> +#include <locale> +#include <testsuite_hooks.h> + +struct custom_time_put : std::time_put<char> +{ + iter_type + do_put(iter_type out, std::ios_base& io, char_type fill, const tm* t, + char format, char modifier) const override + { + using Base = std::time_put<char>; + + switch (format) { + case 'a': case 'A': case 'b': case 'h': case 'B': case 'p': + *out++ = '['; + *out++ = format; + *out++ = ']'; + } + return Base::do_put(out, io, fill, t, format, modifier); + } +}; + +int main() +{ + using namespace std::chrono; + std::locale loc(std::locale::classic(), new custom_time_put); +#define test(t, fmt, exp) VERIFY( std::format(loc, fmt, t) == exp ) + test(Monday, "{:L%a}", "[a]Mon"); + test(Monday, "{:L%A}", "[A]Monday"); + test(January, "{:L%b}", "[b]Jan"); + test(January, "{:L%h}", "[h]Jan"); + test(January, "{:L%B}", "[B]January"); + test(1h, "{:L%p}", "[p]AM"); +} diff --git a/libstdc++-v3/testsuite/util/testsuite_containers.h b/libstdc++-v3/testsuite/util/testsuite_containers.h index 37491a4..ab0107f 100644 --- a/libstdc++-v3/testsuite/util/testsuite_containers.h +++ b/libstdc++-v3/testsuite/util/testsuite_containers.h @@ -210,6 +210,9 @@ namespace __gnu_test clit = container.cbegin(bn); assert( ++clit == container.cend(bn) ); + clit = container.begin(bn); + assert( ++clit == container.cend(bn) ); + assert( container.begin(bn) != container.cend(bn) ); } }; @@ -304,6 +307,9 @@ namespace __gnu_test assert( container.cbegin() != container.cend() ); assert( container.cbegin() != container.end() ); assert( container.begin() != container.cend() ); + + auto cit = container.begin(); + assert( cit == container.cbegin() ); } }; diff --git a/libstdc++-v3/testsuite/util/testsuite_hooks.h b/libstdc++-v3/testsuite/util/testsuite_hooks.h index faa01ba..bf34fd1 100644 --- a/libstdc++-v3/testsuite/util/testsuite_hooks.h +++ b/libstdc++-v3/testsuite/util/testsuite_hooks.h @@ -58,16 +58,13 @@ # define _VERIFY_PRINT(S, F, L, P, C) __builtin_printf(S, F, L, P, C) #endif -#define VERIFY(fn) \ - do \ - { \ - if (! (fn)) \ - { \ - _VERIFY_PRINT("%s:%d: %s: Assertion '%s' failed.\n", \ - __FILE__, __LINE__, __PRETTY_FUNCTION__, #fn); \ - __builtin_abort(); \ - } \ - } while (false) +#define VERIFY(...) \ + ((void)((__VA_ARGS__) \ + ? (void)(true ? true : bool(__VA_ARGS__)) \ + : (_VERIFY_PRINT("%s:%d: %s: Assertion '%s' failed.\n", \ + __FILE__, __LINE__, __PRETTY_FUNCTION__, \ + #__VA_ARGS__), \ + __builtin_abort()))) #ifdef _GLIBCXX_HAVE_UNISTD_H # include <unistd.h> |