diff options
author | Martin Liska <mliska@suse.cz> | 2022-09-26 21:05:44 +0200 |
---|---|---|
committer | Martin Liska <mliska@suse.cz> | 2022-09-26 21:05:44 +0200 |
commit | 3c527a35fa428b727807c81f1225a5e0025446c1 (patch) | |
tree | 787e21d7bf8a1d85ac7b9ccee784909e85ebf61b | |
parent | c9c59aa19c0b7159636763294b7b0c87c696d675 (diff) | |
parent | 7701ea4a70a5a5c0fd977da90a30ffc4f3f87617 (diff) | |
download | gcc-3c527a35fa428b727807c81f1225a5e0025446c1.zip gcc-3c527a35fa428b727807c81f1225a5e0025446c1.tar.gz gcc-3c527a35fa428b727807c81f1225a5e0025446c1.tar.bz2 |
Merge branch 'master' into devel/sphinx
294 files changed, 8580 insertions, 3042 deletions
@@ -1,3 +1,7 @@ +2022-09-23 Paul-Antoine Arras <pa@codesourcery.com> + + * MAINTAINERS (Write After Approval): Add myself. + 2022-09-15 Torbjörn SVENSSON <torbjorn.svensson@foss.st.com> * MAINTAINERS (Write After Approval): Add myself. diff --git a/MAINTAINERS b/MAINTAINERS index be14685..11fa8bc 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -30,7 +30,7 @@ Richard Biener <rguenther@suse.de> Richard Earnshaw <richard.earnshaw@arm.com> Jakub Jelinek <jakub@redhat.com> Richard Kenner <kenner@nyu.edu> -Jeff Law <jeffreyalaw@gmail.com> +Jeff Law <jlaw@ventanamicro.com> Michael Meissner <gnu@the-meissners.org> Jason Merrill <jason@redhat.com> David S. Miller <davem@redhat.com> @@ -316,6 +316,7 @@ from other maintainers or reviewers. Mark G. Adams <mark.g.adams@sympatico.ca> Pedro Alves <palves@redhat.com> +Paul-Antoine Arras <pa@codesourcery.com> Raksit Ashok <raksit@google.com> Matt Austern <austern@google.com> David Ayers <ayers@fsfe.org> @@ -724,6 +725,7 @@ Matthias Kretz <m.kretz@gsi.de> Tim Lange <mail@tim-lange.me> Jeff Law <jeffreyalaw@gmail.com> Jeff Law <jlaw@tachyum.com> +Jeff Law <jlaw@ventanamicro.com> Immad Mir <mir@sourceware.org> Gaius Mulley <gaiusmod2@gmail.com> Siddhesh Poyarekar <siddhesh@gotplt.org> diff --git a/contrib/ChangeLog b/contrib/ChangeLog index d76b1b4..c375530 100644 --- a/contrib/ChangeLog +++ b/contrib/ChangeLog @@ -1,3 +1,8 @@ +2022-09-20 Martin Liska <mliska@suse.cz> + + * filter-clang-warnings.py: Skip egrep: warning: egrep is + obsolescent; using grep -E. + 2022-08-31 Martin Liska <mliska@suse.cz> * config-list.mk: Remove deprecated ports. diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6dded16..6890dd1 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,516 @@ +2022-09-25 Torbjörn SVENSSON <torbjorn.svensson@foss.st.com> + + * doc/sourcebuild.texi: Fix chapter level. + +2022-09-24 Jakub Jelinek <jakub@redhat.com> + + PR c/107001 + * omp-low.cc (lower_omp_taskgroup): Don't add GOMP_RETURN statement + at the end. + * omp-expand.cc (build_omp_regions_1): Clarify GF_OMP_TARGET_KIND_DATA + is not stand-alone directive. For GIMPLE_OMP_TASKGROUP, also don't + update parent. + (omp_make_gimple_edges) <case GIMPLE_OMP_TASKGROUP>: Reset + cur_region back after new_omp_region. + +2022-09-23 Vineet Gupta <vineetg@rivosinc.com> + + * config/riscv/riscv.h (LOCAL_SYM_P): New. + (USE_LOAD_ADDRESS_MACRO): Simplify by calling LOCAL_SYM_P. + +2022-09-23 zhongjuzhe <juzhe.zhong@rivai.ai> + + * config/riscv/riscv-modes.def (VECTOR_BOOL_MODE): Add RVV mask modes. + (ADJUST_NUNITS): Adjust nunits using riscv_vector_chunks. + (ADJUST_ALIGNMENT): Adjust alignment. + (ADJUST_BYTESIZE): Adjust bytesize using riscv_vector_chunks. + (RVV_MODES): New macro. + (VECTOR_MODE_WITH_PREFIX): Add RVV vector modes. + (VECTOR_MODES_WITH_PREFIX): Add RVV vector modes. + +2022-09-23 zhongjuzhe <juzhe.zhong@rivai.ai> + + * common/config/riscv/riscv-common.cc: Change "static void" to "void". + * config.gcc: Add riscv-selftests.o + * config/riscv/predicates.md: Allow const_poly_int. + * config/riscv/riscv-protos.h (riscv_reinit): New function. + (riscv_parse_arch_string): change as exten function. + (riscv_run_selftests): New function. + * config/riscv/riscv.cc (riscv_cannot_force_const_mem): Don't allow poly + into const pool. + (riscv_report_v_required): New function. + (riscv_expand_op): New function. + (riscv_expand_mult_with_const_int): New function. + (riscv_legitimize_poly_move): Ditto. + (riscv_legitimize_move): New function. + (riscv_hard_regno_mode_ok): Add VL/VTYPE register allocation and fix + vector RA. + (riscv_convert_vector_bits): Fix riscv_vector_chunks configuration for + -marh no 'v'. + (riscv_reinit): New function. + (TARGET_RUN_TARGET_SELFTESTS): New target hook support. + * config/riscv/t-riscv: Add riscv-selftests.o. + * config/riscv/riscv-selftests.cc: New file. + +2022-09-23 Richard Biener <rguenther@suse.de> + + PR tree-optimization/106922 + * tree-ssa-sccvn.cc (vn_reference_lookup_3): Allow + an arbitrary number of same valued skipped stores. + +2022-09-23 Aldy Hernandez <aldyh@redhat.com> + + * value-range.cc (frange::set): Swap setters such that the one + accepting REAL_VALUE_TYPE does all the work. + +2022-09-23 Kyrylo Tkachov <kyrylo.tkachov@arm.com> + + * config/aarch64/aarch64-cores.def (neoverse-v2): New entry. + (demeter): Update tunings to neoversev2. + * config/aarch64/aarch64-tune.md: Regenerate. + * config/aarch64/aarch64.cc (demeter_addrcost_table): Rename to + neoversev2_addrcost_table. + (demeter_regmove_cost): Rename to neoversev2_addrcost_table. + (demeter_advsimd_vector_cost): Rename to neoversev2_advsimd_vector_cost. + (demeter_sve_vector_cost): Rename to neoversev2_sve_vector_cost. + (demeter_scalar_issue_info): Rename to neoversev2_scalar_issue_info. + (demeter_advsimd_issue_info): Rename to neoversev2_advsimd_issue_info. + (demeter_sve_issue_info): Rename to neoversev2_sve_issue_info. + (demeter_vec_issue_info): Rename to neoversev2_vec_issue_info. + Update references to above. + (demeter_vector_cost): Rename to neoversev2_vector_cost. + (demeter_tunings): Rename to neoversev2_tunings. + (aarch64_vec_op_count::rename_cycles_per_iter): Use + neoversev2_sve_issue_info instead of demeter_sve_issue_info. + * doc/invoke.texi (AArch64 Options): Document neoverse-v2. + +2022-09-23 Aldy Hernandez <aldyh@redhat.com> + + * range-op-float.cc (build_le): Use vrp_val_*. + (build_lt): Same. + (build_ge): Same. + (build_gt): Same. + * value-range.cc (frange::set): Chop ranges outside of the + representable numbers for -ffinite-math-only. + (frange::normalize_kind): Use vrp_val*. + (frange::verify_range): Same. + (frange::set_nonnegative): Same. + (range_tests_floats): Remove tests that depend on -INF and +INF. + * value-range.h (real_max_representable): Add prototype. + (real_min_representable): Same. + (vrp_val_max): Set max representable number for + -ffinite-math-only. + (vrp_val_min): Same but for min. + (frange::set_varying): Use vrp_val*. + +2022-09-23 Aldy Hernandez <aldyh@redhat.com> + + * real.cc (debug): New. + +2022-09-23 Aldy Hernandez <aldyh@redhat.com> + + * value-range-pretty-print.cc (vrange_printer::print_real_value): New. + (vrange_printer::visit): Call print_real_value. + * value-range-pretty-print.h: New print_real_value. + +2022-09-23 Martin Liska <mliska@suse.cz> + + * common.opt: Update -flto-compression-level documentation. + * opts.cc (print_filtered_help): Do not append range to an + option that uses \t syntax. + +2022-09-23 Jakub Jelinek <jakub@redhat.com> + + * attribs.cc (decl_attributes): Improve diagnostics, instead of + saying expected between 1 and 1, found 2 just say expected 1, found 2. + +2022-09-23 Hu, Lin1 <lin1.hu@intel.com> + + PR target/94962 + * config/i386/constraints.md (BH): New define_constraint. + * config/i386/i386.cc (standard_sse_constant_p): Add return + 3/4 when operand matches new predicate. + (standard_sse_constant_opcode): Add new alternative branch to + return "vpcmpeqd". + * config/i386/predicates.md + (vector_all_ones_zero_extend_half_operand): New define_predicate. + (vector_all_ones_zero_extend_quarter_operand): Ditto. + * config/i386/sse.md: Add constraint to insn "mov<mode>_internal". + +2022-09-22 Andrew MacLeod <amacleod@redhat.com> + + * gimple-range-fold.cc (range_of_range_op): Handle no operands. + (range_of_call): Do not check for builtins. + (fold_using_range::range_of_builtin_call): Delete. + (fold_using_range::range_of_builtin_int_call): Delete. + * gimple-range-fold.h: Adjust prototypes. + * gimple-range-op.cc (class cfn_parity): New. + (gimple_range_op_handler::maybe_builtin_call): Set arguments. + +2022-09-22 Andrew MacLeod <amacleod@redhat.com> + + * gimple-range-fold.cc (range_of_builtin_int_call): Remove case + for CFN_GOACC_DIM_*. + * gimple-range-op.cc (class cfn_goacc_dim): New. + (gimple_range_op_handler::maybe_builtin_call): Set arguments. + +2022-09-22 Andrew MacLeod <amacleod@redhat.com> + + * gimple-range-fold.cc (range_of_builtin_int_call): Remove case + for CFN_BUILT_IN_STRLEN. + * gimple-range-op.cc (class cfn_strlen): New. + (gimple_range_op_handler::maybe_builtin_call): Set arguments. + +2022-09-22 Andrew MacLeod <amacleod@redhat.com> + + * gimple-range-fold.cc (range_of_builtin_ubsan_call): Delete. + (range_of_builtin_int_call): Remove cases for + CFN_BUILT_IN_UBSAN_CHECK. + * gimple-range-op.cc (class cfn_ubsan): New. + (gimple_range_op_handler::maybe_builtin_call): Set arguments. + +2022-09-22 Andrew MacLeod <amacleod@redhat.com> + + * gimple-range-fold.cc (range_of_builtin_int_call): Remove case + for CFN_BUILT_IN_CLRSB. + * gimple-range-op.cc (class cfn_clrsb): New. + (gimple_range_op_handler::maybe_builtin_call): Set arguments. + +2022-09-22 Andrew MacLeod <amacleod@redhat.com> + + * gimple-range-fold.cc (range_of_builtin_int_call): Remove case + for CFN_CTZ. + * gimple-range-op.cc (class cfn_ctz): New. + (gimple_range_op_handler::maybe_builtin_call): Set arguments. + +2022-09-22 Andrew MacLeod <amacleod@redhat.com> + + * gimple-range-fold.cc (range_of_builtin_int_call): Remove case + for CFN_CLZ. + * gimple-range-op.cc (class cfn_clz): New. + (gimple_range_op_handler::maybe_builtin_call): Set arguments. + +2022-09-22 Andrew MacLeod <amacleod@redhat.com> + + * gimple-range-fold.cc (range_of_builtin_int_call): Remove case + for CFN_FFS and CFN_POPCOUNT. + * gimple-range-op.cc (class cfn_pocount): New. + (gimple_range_op_handler::maybe_builtin_call): Set arguments. + +2022-09-22 Andrew MacLeod <amacleod@redhat.com> + + * gimple-range-fold.cc (get_letter_range): Move to new class. + (range_of_builtin_int_call): Remove case for CFN_BUILT_IN_TOUPPER + and CFN_BUILT_IN_TOLOWER. + * gimple-range-op.cc (class cfn_toupper_tolower): New. + (gimple_range_op_handler::maybe_builtin_call): Set arguments. + +2022-09-22 Andrew MacLeod <amacleod@redhat.com> + + * gimple-range-fold.cc (range_of_builtin_int_call): Remove case + for CFN_BUILT_IN_SIGNBIT. + * gimple-range-op.cc (class cfn_signbit): New. + (gimple_range_op_handler::maybe_builtin_call): Set arguments. + +2022-09-22 Andrew MacLeod <amacleod@redhat.com> + + * gimple-range-fold.cc + (fold_using_range::range_of_builtin_int_call): Remove case for + CFN_BUILT_IN_CONSTANT_P. + * gimple-range-op.cc (gimple_range_op_handler::supported_p): + Check if a call also creates a range-op object. + (gimple_range_op_handler): Also check builtin calls. + (class cfn_constant_float_p): New. Float CFN_BUILT_IN_CONSTANT_P. + (class cfn_constant_p): New. Integral CFN_BUILT_IN_CONSTANT_P. + (gimple_range_op_handler::maybe_builtin_call): Set arguments and + handler for supported built-in calls. + * gimple-range-op.h (maybe_builtin_call): New prototype. + +2022-09-22 Andrew MacLeod <amacleod@redhat.com> + + * gimple-range-fold.cc (range_of_range_op): Set result to + VARYING if the call to fold_range fails. + * tree-data-ref.cc (compute_distributive_range): Ditto. + * tree-vrp.cc (range_fold_binary_expr): Ditto. + (range_fold_unary_expr): Ditto. + * value-query.cc (range_query::get_tree_range): Ditto. + +2022-09-22 Andrew MacLeod <amacleod@redhat.com> + + * range-op-float.cc (range_operator_float::fold_range): New base + method for "int = float op int". + * range-op.cc (range_op_handler::fold_range): New case. + * range-op.h: Update prototypes. + +2022-09-22 Andrew MacLeod <amacleod@redhat.com> + + * gimple-range-op.cc (gimple_range_op_handler::calc_op1): Use + operand 1 for second range if there is no operand 2. + +2022-09-22 Andrew MacLeod <amacleod@redhat.com> + + * Makefile.in (OBJS): Add gimple-range-op.o. + * gimple-range-edge.cc (gimple_outgoing_range_stmt_p): Use + gimple_range_op_handler. + * gimple-range-fold.cc (gimple_range_base_of_assignment): Move + to a method in gimple_range_op_handler. + (gimple_range_operand1): Ditto. + (gimple_range_operand2): Ditto. + (fold_using_range::fold_stmt): Use gimple_range_op_handler. + (fold_using_range::range_of_range_op): Ditto. + (fold_using_range::relation_fold_and_or): Ditto. + (fur_source::register_outgoing_edges): Ditto. + (gimple_range_ssa_names): Relocate to gimple-range-op.cc. + * gimple-range-fold.h: Adjust prototypes. + * gimple-range-gori.cc (gimple_range_calc_op1): Move + to a method in gimple_range_op_handler. + (gimple_range_calc_op2): Ditto. + (gori_compute::compute_operand_range): Use + gimple_range_op_handler. + (gori_compute::compute_logical_operands): Ditto. + (compute_operand1_range): Ditto. + (gori_compute::compute_operand2_range): Ditto. + (gori_compute::compute_operand1_and_operand2_range): Ditto. + * gimple-range-gori.h: Adjust protoypes. + * gimple-range-op.cc: New. Supply gimple_range_op_handler methods. + * gimple-range-op.h: New. Supply gimple_range_op_handler class. + * gimple-range.cc (gimple_ranger::prefill_name): Use + gimple_range_op_handler. + (gimple_ranger::prefill_stmt_dependencies): Ditto. + * gimple-range.h: Include gimple-range-op.h. + * range-op.cc (range_op_handler::range_op_handler): Adjust and + remove gimple * parameter option. + * range-op.h: Adjust prototypes. + +2022-09-22 Andrew MacLeod <amacleod@redhat.com> + + * range-op.cc (range_op_handler::set_op_handler): Set new fields. + (ange_op_handler::range_op_handler): Likewise. + (range_op_handler::operator bool): Remove. + (range_op_handler::fold_range): Use appropriate handler. + (range_op_handler::op1_range): Likewise. + (range_op_handler::op2_range): Likewise. + (range_op_handler::lhs_op1_relation): Likewise. + (range_op_handler::lhs_op2_relation): Likewise. + (range_op_handler::op1_op2_relation): Likewise. + * range-op.h (class range_op_handler): Store handler pointers. + (range_op_handler:: operator bool): Inline. + +2022-09-22 Andrew MacLeod <amacleod@redhat.com> + + * tree-ssa-threadbackward.cc + (back_threader::find_paths_to_names): Replace sequence with + a call to gimple_range_ssa_names. + +2022-09-22 Martin Liska <mliska@suse.cz> + Fangrui Song <i@maskray.me> + + * configure: Regenerate. + * configure.ac: Simplify to gcc_cv_ld_compress_debug={0,1} + and gcc_cv_as_compress_debug={0,1}. + * doc/invoke.texi: Document the removal. + * gcc.cc (LINK_COMPRESS_DEBUG_SPEC): Simplify and ignore + zlib-gnu. + (ASM_COMPRESS_DEBUG_SPEC): Likewise. + +2022-09-22 Richard Biener <rguenther@suse.de> + + PR tree-optimization/106922 + * tree-ssa-sccvn.cc (vn_walk_cb_data::same_val): New member. + (vn_walk_cb_data::finish): Perform delayed verification of + a skipped may-alias. + (vn_reference_lookup_pieces): Likewise. + (vn_reference_lookup): Likewise. + (vn_reference_lookup_3): When skipping stores of the same + value also handle constant stores that are more than a + single VDEF away by delaying the verification. + +2022-09-22 Max Filippov <jcmvbkbc@gmail.com> + + * config/xtensa/xtensa.cc (TARGET_MAX_ANCHOR_OFFSET): New + definition. + +2022-09-22 Max Filippov <jcmvbkbc@gmail.com> + + * config/xtensa/xtensa.cc (xtensa_can_output_mi_thunk) + (xtensa_output_mi_thunk): New functions. + (TARGET_ASM_CAN_OUTPUT_MI_THUNK) + (TARGET_ASM_OUTPUT_MI_THUNK): New macro definitions. + (xtensa_prepare_expand_call): Use fixed register a8 as temporary + when called with reload_completed set to 1. + +2022-09-22 Richard Biener <rguenther@suse.de> + + PR tree-optimization/99407 + * tree-ssa-dse.cc (dse_stmt_to_dr_map): New global. + (dse_classify_store): Use data-ref analysis to disambiguate more uses. + (pass_dse::use_dr_analysis_p): New pass parameter. + (pass_dse::set_pass_param): Implement. + (pass_dse::execute): Allocate and deallocate dse_stmt_to_dr_map. + * passes.def: Allow DR analysis for the DSE pass before loop. + +2022-09-22 Richard Biener <rguenther@suse.de> + + * tree-ssa-sccvn.cc (can_track_predicate_on_edge): New + function split out from ... + (vn_nary_op_insert_pieces_predicated): ... here. + +2022-09-22 liuhongt <hongtao.liu@intel.com> + + PR target/106994 + * config/i386/mmx.md (floorv2sf2): Fix typo, use + register_operand instead of vector_operand for operands[1]. + +2022-09-21 Aldy Hernandez <aldyh@redhat.com> + + PR tree-optimization/106967 + * value-range.cc (frange::set): Set known NANs to undefined for + flag_finite_math_only. + +2022-09-21 Aldy Hernandez <aldyh@redhat.com> + + * value-range.cc (frange::combine_zeros): Call set_undefined. + (frange::intersect_nans): Same. + (frange::intersect): Same. + (frange::verify_range): Undefined ranges do not have a type. + * value-range.h (frange::set_undefined): Clear NAN flags and type. + +2022-09-21 Richard Biener <rguenther@suse.de> + + PR tree-optimization/106984 + * tsan.cc (instrument_builtin_call): Build the COND_EXPR condition in + a separate statement. + +2022-09-21 Kyrylo Tkachov <kyrylo.tkachov@arm.com> + + * config/aarch64/aarch64.h (HAVE_LOCAL_CPU_DETECT, + EXTRA_SPEC_FUNCTIONS, MCPU_MTUNE_NATIVE_SPECS): Move definitions up before + OPTION_DEFAULT_SPECS. + (MCPU_MTUNE_NATIVE_SPECS): Pass "cpu" to + local_cpu_detect when rewriting -march=native and no -mcpu or -mtune + is given. + (CONFIG_TUNE_SPEC): Define. + (OPTION_DEFAULT_SPECS): Use CONFIG_TUNE_SPEC for "tune". + +2022-09-21 Aldy Hernandez <aldyh@redhat.com> + + PR tree-optimization/106967 + * range-op-float.cc (foperator_equal::fold_range): Adjust for NAN. + (foperator_equal::op1_range): Same. + (foperator_not_equal::fold_range): Same. + (foperator_not_equal::op1_range): Same. + (foperator_lt::fold_range): Same. + (foperator_lt::op1_range): Same. + (foperator_lt::op2_range): Same. + (foperator_le::fold_range): Same. + (foperator_le::op1_range): Same. + (foperator_le::op2_range): Same. + (foperator_gt::fold_range): Same. + (foperator_gt::op1_range): Same. + (foperator_gt::op2_range): Same. + (foperator_ge::fold_range): Same. + (foperator_ge::op1_range): Same. + (foperator_ge::op2_range): Same. + (foperator_unordered::op1_range): Same. + (foperator_ordered::fold_range): Same. + (foperator_ordered::op1_range): Same. + (build_le): Assert that we don't have a NAN. + (build_lt): Same. + (build_gt): Same. + (build_ge): Same. + +2022-09-21 liuhongt <hongtao.liu@intel.com> + + PR tree-optimization/106963 + * tree-vect-loop.cc (vect_create_nonlinear_iv_init): Use + vec_gen_perm_mask_any instead of vec_gen_perm_mask_check. + +2022-09-20 Aldy Hernandez <aldyh@redhat.com> + + * value-range.h (frange::maybe_isnan): Return false for + undefined ranges. + +2022-09-20 Aldy Hernandez <aldyh@redhat.com> + + * value-range.cc (frange::set_nonnegative): Set +NAN. + (range_tests_signed_zeros): New test. + * value-range.h (frange::update_nan): New overload to set NAN sign. + +2022-09-20 Richard Sandiford <richard.sandiford@arm.com> + + PR target/106491 + * config/aarch64/aarch64-sve-builtins.cc (scalar_types) + (acle_vector_types, acle_svpattern, acle_svprfop): Add GTY + markup to (new) extern declarations instead of to the main + definition. + +2022-09-20 Richard Sandiford <richard.sandiford@arm.com> + + PR tree-optimization/106794 + PR tree-optimization/106914 + * tree-vect-slp.cc (vect_optimize_slp_pass::internal_node_cost): + Only consider loads that already have a permutation. + (vect_optimize_slp_pass::start_choosing_layouts): Assert that + loads with permutations are leaf nodes. Prevent any kind of grouped + access from changing layout if it doesn't have a load permutation. + +2022-09-20 Richard Sandiford <richard.sandiford@arm.com> + + * tree-vect-data-refs.cc (vect_check_gather_scatter): Restrict + early-out optimisation to SSA_NAMEs. + +2022-09-20 Martin Liska <mliska@suse.cz> + + * ctfc.cc (ctf_add_string): Replace "the the" with "the". + * doc/md.texi: Likewise. + * gimple-range-infer.cc (non_null_loadstore): Likewise. + +2022-09-20 liuhongt <hongtao.liu@intel.com> + + PR target/106910 + * config/i386/mmx.md (nearbyintv2sf2): New expander. + (rintv2sf2): Ditto. + (ceilv2sf2): Ditto. + (lceilv2sfv2si2): Ditto. + (floorv2sf2): Ditto. + (lfloorv2sfv2si2): Ditto. + (btruncv2sf2): Ditto. + (lrintv2sfv2si2): Ditto. + (roundv2sf2): Ditto. + (lroundv2sfv2si2): Ditto. + (*mmx_roundv2sf2): New define_insn. + +2022-09-20 konglin1 <lingling.kong@intel.com> + + PR middle-end/105735 + * tree-scalar-evolution.cc + (analyze_and_compute_bitop_with_inv_effect): New function. + (final_value_replacement_loop): Enhanced to handle bitop + with inv induction. + +2022-09-20 Xi Ruoyao <xry111@xry111.site> + + * config/loongarch/gnu-user.h (GNU_USER_TARGET_LINK_SPEC): For + -static-pie, pass -static -pie --no-dynamic-linker -z text to + the linker, and do not pass --dynamic-linker. + +2022-09-20 Aldy Hernandez <aldyh@redhat.com> + + * value-range.cc (frange::flush_denormals_to_zero): New. + (frange::set): Call flush_denormals_to_zero. + * value-range.h (class frange): Add flush_denormals_to_zero. + +2022-09-20 liuhongt <hongtao.liu@intel.com> + + * config/i386/x86-tune-sched.cc (ix86_issue_rate): Adjust for + latest Intel processors. + +2022-09-20 konglin1 <lingling.kong@intel.com> + + PR target/106887 + * config/i386/i386-expand.cc (ix86_expand_vector_init_duplicate): + Fixed V16BF mode case. + 2022-09-19 Torbjörn SVENSSON <torbjorn.svensson@foss.st.com> * targhooks.cc (default_zero_call_used_regs): Improve sorry diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 54f97aa..7764f7e 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20220920 +20220926 diff --git a/gcc/Makefile.in b/gcc/Makefile.in index a4689d5..59b67d9 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1416,6 +1416,7 @@ OBJS = \ gimple-range-fold.o \ gimple-range-gori.o \ gimple-range-infer.o \ + gimple-range-op.o \ gimple-range-trace.o \ gimple-ssa-backprop.o \ gimple-ssa-isolate-paths.o \ diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index a1c4375..c48bbdf 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,9 @@ +2022-09-20 Martin Liska <mliska@suse.cz> + + * exp_ch6.adb: Replace "the the" with "the". + * sem_ch6.adb: Likewise. + * sem_disp.ads: Likewise. + 2022-09-15 Richard Biener <rguenther@suse.de> * gcc-interface/trans.cc (gigi): Do not initialize void_list_node. @@ -60,7 +66,7 @@ 2022-09-12 Eric Botcazou <ebotcazou@adacore.com> - * contracts.adb (uild_Subprogram_Contract_Wrapper): Remove useless + * contracts.adb (Build_Subprogram_Contract_Wrapper): Remove useless local variable. In the case of a function, replace the extended return statement by a block statement declaring a renaming of the call to the local subprogram after removing side effects manually. @@ -1173,14 +1179,14 @@ 2022-09-02 Eric Botcazou <ebotcazou@adacore.com> - * exp_util.adb (Expand_Subtype_From_Expr): Be prepared for - rewritten aggregates as expressions. + * exp_util.adb (Expand_Subtype_From_Expr): Be prepared for rewritten + aggregates as expressions. 2022-09-02 Gary Dismukes <dismukes@adacore.com> - * exp_ch6.adb (Expand_Simple_Function_Return) Bypass creation of an actual - subtype and unchecked conversion to that subtype when the underlying type - of the expression has discriminants without defaults. + * exp_ch6.adb (Expand_Simple_Function_Return) Bypass creation of an + actual subtype and unchecked conversion to that subtype when the + underlying type of the expression has discriminants without defaults. 2022-09-02 Eric Botcazou <ebotcazou@adacore.com> diff --git a/gcc/ada/adaint.c b/gcc/ada/adaint.c index 2ae4ded..199dbe0 100644 --- a/gcc/ada/adaint.c +++ b/gcc/ada/adaint.c @@ -200,11 +200,7 @@ UINT __gnat_current_ccs_encoding; #endif /* wait.h processing */ -#ifdef __MINGW32__ -# if OLD_MINGW -# include <sys/wait.h> -# endif -#elif defined (__vxworks) && defined (__RTP__) +#if defined (__vxworks) && defined (__RTP__) # include <wait.h> #elif defined (__Lynx__) /* ??? We really need wait.h and it includes resource.h on Lynx. GCC @@ -214,7 +210,7 @@ UINT __gnat_current_ccs_encoding; preventing the inclusion of the GCC header from doing anything. */ # define GCC_RESOURCE_H # include <sys/wait.h> -#elif defined (__PikeOS__) +#elif defined (__PikeOS__) || defined (__MINGW32__) /* No wait() or waitpid() calls available. */ #else /* Default case. */ @@ -335,11 +331,6 @@ const char *__gnat_library_template = GNAT_LIBRARY_TEMPLATE; #if defined (__MINGW32__) #include "mingw32.h" - -#if OLD_MINGW -#include <sys/param.h> -#endif - #else #include <sys/param.h> #endif diff --git a/gcc/ada/bindgen.adb b/gcc/ada/bindgen.adb index b2fa44d..f2aaa2d 100644 --- a/gcc/ada/bindgen.adb +++ b/gcc/ada/bindgen.adb @@ -134,9 +134,6 @@ package body Bindgen is -- Text for aspect specifications (if any) given as part of the -- Adainit and Adafinal spec declarations. - function Aspect_Text return String is - (if Enable_CUDA_Device_Expansion then " with CUDA_Global" else ""); - ---------------------------------- -- Interface_State Pragma Table -- ---------------------------------- @@ -2644,10 +2641,11 @@ package body Bindgen is end if; WBI (""); - WBI (" procedure " & Ada_Init_Name.all & Aspect_Text & ";"); + WBI (" procedure " & Ada_Init_Name.all & ";"); if Enable_CUDA_Device_Expansion then WBI (" pragma Export (C, " & Ada_Init_Name.all & ", Link_Name => """ & Device_Ada_Init_Link_Name & """);"); + WBI (" pragma CUDA_Global (" & Ada_Init_Name.all & ");"); else WBI (" pragma Export (C, " & Ada_Init_Name.all & ", """ & Ada_Init_Name.all & """);"); @@ -2662,11 +2660,12 @@ package body Bindgen is if not Cumulative_Restrictions.Set (No_Finalization) then WBI (""); - WBI (" procedure " & Ada_Final_Name.all & Aspect_Text & ";"); + WBI (" procedure " & Ada_Final_Name.all & ";"); if Enable_CUDA_Device_Expansion then WBI (" pragma Export (C, " & Ada_Final_Name.all & ", Link_Name => """ & Device_Ada_Final_Link_Name & """);"); + WBI (" pragma CUDA_Global (" & Ada_Final_Name.all & ");"); else WBI (" pragma Export (C, " & Ada_Final_Name.all & ", """ & Ada_Final_Name.all & """);"); diff --git a/gcc/ada/cal.c b/gcc/ada/cal.c index e1ab692..09bcc15 100644 --- a/gcc/ada/cal.c +++ b/gcc/ada/cal.c @@ -53,10 +53,8 @@ #ifdef __MINGW32__ #include "mingw32.h" -#if STD_MINGW #include <winsock.h> #endif -#endif void __gnat_timeval_to_duration (struct timeval *t, long long *sec, long *usec) diff --git a/gcc/ada/contracts.adb b/gcc/ada/contracts.adb index 34db67a..dd573d3 100644 --- a/gcc/ada/contracts.adb +++ b/gcc/ada/contracts.adb @@ -1207,7 +1207,7 @@ package body Contracts is -- A Ghost object cannot be effectively volatile (SPARK RM 6.9(7) and -- SPARK RM 6.9(19)). - elsif Is_Effectively_Volatile (Obj_Id) then + elsif SPARK_Mode = On and then Is_Effectively_Volatile (Obj_Id) then Error_Msg_N ("ghost object & cannot be volatile", Obj_Id); -- A Ghost object cannot be imported or exported (SPARK RM 6.9(7)). diff --git a/gcc/ada/cstreams.c b/gcc/ada/cstreams.c index 10cc3a6..fc583e1 100644 --- a/gcc/ada/cstreams.c +++ b/gcc/ada/cstreams.c @@ -97,14 +97,6 @@ extern "C" { #undef fileno #endif -/* The _IONBF value in MINGW32 stdio.h is wrong. */ -#if defined (WINNT) || defined (_WINNT) -#if OLD_MINGW -#undef _IONBF -#define _IONBF 0004 -#endif -#endif - int __gnat_feof (FILE *stream) { diff --git a/gcc/ada/doc/gnat_rm/implementation_defined_attributes.rst b/gcc/ada/doc/gnat_rm/implementation_defined_attributes.rst index c25e3d4..d839b1f 100644 --- a/gcc/ada/doc/gnat_rm/implementation_defined_attributes.rst +++ b/gcc/ada/doc/gnat_rm/implementation_defined_attributes.rst @@ -1623,13 +1623,13 @@ Multi-dimensional arrays can be modified, as shown by this example: which changes element (1,2) to 20 and (3,4) to 30. -Attribute Valid_Image +Attribute Valid_Value ======================= -.. index:: Valid_Image +.. index:: Valid_Value -The ``'Valid_Image`` attribute is defined for enumeration types other than +The ``'Valid_Value`` attribute is defined for enumeration types other than those in package Standard. This attribute is a function that takes -a String, and returns Boolean. ``T'Valid_Image (S)`` returns True +a String, and returns Boolean. ``T'Valid_Value (S)`` returns True if and only if ``T'Value (S)`` would not raise Constraint_Error. Attribute Valid_Scalars diff --git a/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst b/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst index 6a47809..d4bddff 100644 --- a/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst +++ b/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst @@ -1719,6 +1719,7 @@ Alphabetical List of All Switches Float_Words_BE : Nat; -- Float words stored big-endian? Int_Size : Pos; -- Standard.Integer'Size Long_Double_Size : Pos; -- Standard.Long_Long_Float'Size + Long_Long_Long_Size : Pos; -- Standard.Long_Long_Long_Integer'Size Long_Long_Size : Pos; -- Standard.Long_Long_Integer'Size Long_Size : Pos; -- Standard.Long_Integer'Size Maximum_Alignment : Pos; -- Maximum permitted alignment @@ -1816,6 +1817,7 @@ Alphabetical List of All Switches Float_Words_BE 0 Int_Size 64 Long_Double_Size 128 + Long_Long_Long_Size 128 Long_Long_Size 64 Long_Size 64 Maximum_Alignment 16 @@ -6229,11 +6231,33 @@ Linker switches can be specified after :switch:`-largs` builder switch. .. index:: -fuse-ld=name :switch:`-fuse-ld={name}` - Linker to be used. The default is ``bfd`` for :file:`ld.bfd`, - the alternative being ``gold`` for :file:`ld.gold`. The later is - a more recent and faster linker, but only available on GNU/Linux + Linker to be used. The default is ``bfd`` for :file:`ld.bfd`; ``gold`` + (for :file:`ld.gold`) and ``mold`` (for :file:`ld.mold`) are more + recent and faster alternatives, but only available on GNU/Linux platforms. + .. only:: PRO + + The GNAT distribution for native Linux platforms includes ``mold``, + compiled against OpenSSL version 1.1; however, the distribution does + not include OpenSSL. In order to use this linker, you may either: + + * use your system's OpenSSL library, if the version matches: in this + situation, you need not do anything beside using the + :switch:`-fuse-ld=mold` switch, + + * obtain a source distribution for OpenSSL 1.1, compile the + :file:`libcrypto.so` library and install it in the directory of + your choice, then include this directory in the + :envvar:`LD_LIBRARY_PATH` environment variable, + + * install another copy of ``mold`` by other means in the directory + of your choice, and include this directory in the :envvar:`PATH` + environment variable; you may find this alternative preferable if + the copy of ``mold`` included in GNAT does not suit your needs + (e.g. being able to link against your system's OpenSSL, or using + another version of ``mold``). + .. _Binding_with_gnatbind: Binding with ``gnatbind`` diff --git a/gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst b/gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst index d670839..92877a2 100644 --- a/gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst +++ b/gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst @@ -15,7 +15,6 @@ This chapter describes a number of utility programs: * :ref:`The_File_Cleanup_Utility_gnatclean` * :ref:`The_GNAT_Library_Browser_gnatls` * :ref:`The_Coding_Standard_Verifier_gnatcheck` - * :ref:`The_GNAT_Metrics_Tool_gnatmetric` * :ref:`The_GNAT_Pretty_Printer_gnatpp` * :ref:`The_Body_Stub_Generator_gnatstub` * :ref:`The_Backtrace_Symbolizer_gnatsymbolize` @@ -487,1123 +486,6 @@ building specialized scripts. For full details, plese refer to :title:`GNATcheck Reference Manual`. - -.. only:: PRO or GPL - - .. _The_GNAT_Metrics_Tool_gnatmetric: - - The GNAT Metrics Tool ``gnatmetric`` - ==================================== - - .. index:: ! gnatmetric - .. index:: Metric tool - - The ``gnatmetric`` tool is a utility - for computing various program metrics. - It takes an Ada source file as input and generates a file containing the - metrics data as output. Various switches control which - metrics are reported. - - ``gnatmetric`` is a project-aware tool - (see :ref:`Using_Project_Files_with_GNAT_Tools` for a description of - the project-related switches). The project file package that can specify - ``gnatmetric`` switches is named ``Metrics``. - - The ``gnatmetric`` command has the form - - :: - - $ gnatmetric [ switches ] { filename } - - where: - - * ``switches`` specify the metrics to compute and define the destination for - the output - - * Each ``filename`` is the name of a source file to process. 'Wildcards' are - allowed, and the file name may contain path information. If no - ``filename`` is supplied, then the ``switches`` list must contain at least - one :switch:`--files` switch (see :ref:`Other_gnatmetric_Switches`). - Including both a :switch:`--files` switch and one or more ``filename`` - arguments is permitted. - - Note that it is no longer necessary to specify the Ada language version; - ``gnatmetric`` can process Ada source code written in any version from - Ada 83 onward without specifying any language version switch. - - The following subsections describe the various switches accepted by - ``gnatmetric``, organized by category. - - .. _Output_File_Control-gnatmetric: - - Output File Control - ------------------- - - .. index:: Output file control in gnatmetric - - ``gnatmetric`` has two output formats. It can generate a - textual (human-readable) form, and also XML. By default only textual - output is generated. - - When generating the output in textual form, ``gnatmetric`` creates - for each Ada source file a corresponding text file - containing the computed metrics, except for the case when the set of metrics - specified by gnatmetric parameters consists only of metrics that are computed - for the whole set of analyzed sources, but not for each Ada source. - By default, the name of the file containing metric information for a source - is obtained by appending the :file:`.metrix` suffix to the - name of the input source file. If not otherwise specified and no project file - is specified as ``gnatmetric`` option this file is placed in the same - directory as where the source file is located. If ``gnatmetric`` has a - project file as its parameter, it places all the generated files in the - object directory of the project (or in the project source directory if the - project does not define an object directory). If :switch:`--subdirs` option - is specified, the files are placed in the subrirectory of this directory - specified by this option. - - All the output information generated in XML format is placed in a single - file. By default the name of this file is :file:`metrix.xml`. - If not otherwise specified and if no project file is specified - as ``gnatmetric`` option this file is placed in the - current directory. - - Some of the computed metrics are summed over the units passed to - ``gnatmetric``; for example, the total number of lines of code. - By default this information is sent to :file:`stdout`, but a file - can be specified with the :switch:`--global-file-name` switch. - - The following switches control the ``gnatmetric`` output: - - .. index:: --generate-xml-output (gnatmetric) - - :switch:`--generate-xml-output` - Generate XML output. - - .. index:: --generate-xml-schema (gnatmetric) - - :switch:`--generate-xml-schema` - Generate XML output and an XML schema file that describes the structure - of the XML metric report. This schema is assigned to the XML file. The schema - file has the same name as the XML output file with :file:`.xml` suffix replaced - with :file:`.xsd`. - - .. index:: --no-text-output (gnatmetric) - - - :switch:`--no-text-output` - Do not generate the output in text form (implies :switch:`-x`). - - .. index:: --output-dir (gnatmetric) - - - :switch:`--output-dir={output_dir}` - Put text files with detailed metrics into ``output_dir``. - - .. index:: --output-suffix (gnatmetric) - - - :switch:`--output-suffix={file_suffix}` - Use ``file_suffix``, instead of :file:`.metrix` - in the name of the output file. - - .. index:: --global-file-name (gnatmetric) - - :switch:`--global-file-name={file_name}` - Put global metrics into ``file_name``. - - .. index:: --xml-file-name (gnatmetric) - - - :switch:`--xml-file-name={file_name}` - Put the XML output into ``file_name`` - (also implies :switch:`--generate-xml-output`). - - .. index:: --short-file-names (gnatmetric) - - :switch:`--short-file-names` - Use 'short' source file names in the output. (The ``gnatmetric`` - output includes the name(s) of the Ada source file(s) from which the - metrics are computed. By default each name includes the absolute - path. The :switch:`--short-file-names` switch causes ``gnatmetric`` - to exclude all directory information from the file names that are - output.) - - .. index:: --wide-character-encoding (gnatmetric) - - :switch:`--wide-character-encoding={e}` - Specify the wide character encoding method for the input and output - files. ``e`` is one of the following: - - * *8* - UTF-8 encoding - - * *b* - Brackets encoding (default value) - - - .. index:: Disable Metrics For Local Units in gnatmetric - - .. _Disable_Metrics_For_Local_Units: - - Disable Metrics For Local Units - ------------------------------- - - ``gnatmetric`` relies on the GNAT compilation model -- - one compilation - unit per one source file. It computes line metrics for the whole source - file, and it also computes syntax - and complexity metrics for the file's outermost unit. - - By default, ``gnatmetric`` will also compute all metrics for certain - kinds of locally declared program units: - - * subprogram (and generic subprogram) bodies; - - * package (and generic package) specs and bodies; - - * task object and type specifications and bodies; - - * protected object and type specifications and bodies. - - .. index:: Eligible local unit (for gnatmetric) - - These kinds of entities will be referred to as - *eligible local program units*, or simply *eligible local units*, - in the discussion below. - - Note that a subprogram declaration, generic instantiation, - or renaming declaration only receives metrics - computation when it appear as the outermost entity - in a source file. - - Suppression of metrics computation for eligible local units can be - obtained via the following switch: - - - .. index:: --no-local-metrics (gnatmetric) - - - :switch:`--no-local-metrics` - Do not compute detailed metrics for eligible local program units. - - - .. _Specifying_a_set_of_metrics_to_compute: - - Specifying a set of metrics to compute - -------------------------------------- - - By default all the metrics are reported. The switches described in this - subsection allow you to control, on an individual basis, whether metrics are - reported. If at least one positive metric switch is specified (that is, a - switch that defines that a given metric or set of metrics is to be computed), - then only explicitly specified metrics are reported. - - .. _Line_Metrics_Control: - - Line Metrics Control - ^^^^^^^^^^^^^^^^^^^^ - - .. index:: Line metrics control in gnatmetric - - For each source file, and for each of its eligible local program - units, ``gnatmetric`` computes the following metrics: - - * the total number of lines; - - * the total number of code lines (i.e., non-blank lines that are not - comments) - - * the number of comment lines - - * the number of code lines containing end-of-line comments; - - * the comment percentage: the ratio between the number of lines that - contain comments and the number of all non-blank lines, expressed as - a percentage - - * the number of empty lines and lines containing only space characters - and/or format effectors (blank lines) - - * the average number of code lines in subprogram bodies, task bodies, - entry bodies and statement sequences in package bodies - - ``gnatmetric`` sums the values of the line metrics for all the files - being processed and then generates the cumulative results. The tool - also computes for all the files being processed the average number of - code lines in bodies. - - You can use the following switches to select the specific line metrics - to be reported. - - - .. index:: --lines (gnatmetric) - .. index:: --no-lines (gnatmetric) - - - :switch:`--lines-all` - Report all the line metrics - - - :switch:`--no-lines-all` - Do not report any of line metrics - - - :switch:`--lines` - Report the number of all lines - - - :switch:`--no-lines` - Do not report the number of all lines - - - :switch:`--lines-code` - Report the number of code lines - - - :switch:`--no-lines-code` - Do not report the number of code lines - - - :switch:`--lines-comment` - Report the number of comment lines - - - :switch:`--no-lines-comment` - Do not report the number of comment lines - - - :switch:`--lines-eol-comment` - Report the number of code lines containing - end-of-line comments - - - :switch:`--no-lines-eol-comment` - Do not report the number of code lines containing - end-of-line comments - - - :switch:`--lines-ratio` - Report the comment percentage in the program text - - - :switch:`--no-lines-ratio` - Do not report the comment percentage in the program text - - - :switch:`--lines-blank` - Report the number of blank lines - - - :switch:`--no-lines-blank` - Do not report the number of blank lines - - - :switch:`--lines-average` - Report the average number of code lines in subprogram bodies, task bodies, - entry bodies and statement sequences in package bodies. - - - :switch:`--no-lines-average` - Do not report the average number of code lines in subprogram bodies, - task bodies, entry bodies and statement sequences in package bodies. - - - :switch:`--lines-spark` - Report the number of lines written in SPARK. - - - :switch:`--no-lines-spark` - Do not report the number of lines written in SPARK. - - - .. _Syntax_Metrics_Control: - - Syntax Metrics Control - ^^^^^^^^^^^^^^^^^^^^^^ - - .. index:: Syntax metrics control in gnatmetric - - ``gnatmetric`` computes various syntactic metrics for the - outermost unit and for each eligible local unit: - - * *LSLOC ('Logical Source Lines Of Code')* - The total number of declarations and the total number of - statements. Note that the definition of declarations is the one - given in the reference manual: - - "Each of the following is defined to be a declaration: any - basic_declaration; an enumeration_literal_specification; a - discriminant_specification; a component_declaration; a - loop_parameter_specification; a parameter_specification; a - subprogram_body; an entry_declaration; an - entry_index_specification; a choice_parameter_specification; a - generic_formal_parameter_declaration." - - This means for example that each enumeration literal adds one to - the count, as well as each subprogram parameter. - - * *Maximal static nesting level of inner program units* - According to :title:`Ada Reference Manual`, 10.1(1): - - "A program unit is either a package, a task unit, a protected - unit, a protected entry, a generic unit, or an explicitly - declared subprogram other than an enumeration literal." - - * *Maximal nesting level of composite syntactic constructs* - This corresponds to the notion of the maximum nesting level in the - GNAT built-in style checks (see :ref:`Style_Checking`). - - * *Number of formal parameters* - Number of formal parameters of a subprogram; if a subprogram does - have parameters, then numbers of "in", "out" and "in out" - parameters are also reported. This metric is reported for - subprogram specifications and for subprogram instantiations. For - subprogram bodies, expression functions and null procedures this - metric is reported if the construct acts as a subprogram - declaration but is not a completion of previous declaration. This - metric is not reported for generic and formal subprograms. - - For the outermost unit in the file, ``gnatmetric`` additionally - computes the following metrics: - - * *Public subprograms* - This metric is computed for package specs. It is the number of - subprograms and generic subprograms declared in the visible part - (including the visible part of nested packages, protected objects, - and protected types). - - - * *All subprograms* - This metric is computed for bodies and subunits. The metric is - equal to a total number of subprogram bodies in the compilation - unit. - Neither generic instantiations nor renamings-as-a-body nor body - stubs are counted. Any subprogram body is counted, independently - of its nesting level and enclosing constructs. Generic bodies and - bodies of protected subprograms are counted in the same way as - 'usual' subprogram bodies. - - - * *Public types* - This metric is computed for package specs and generic package - declarations. It is the total number of types that can be - referenced from outside this compilation unit, plus the number of - types from all the visible parts of all the visible generic - packages. Generic formal types are not counted. Only types, not - subtypes, are included. - - Along with the total number of public types, the following - types are counted and reported separately: - - * *Abstract types* - - * *Root tagged types^ (abstract, non-abstract, private, - non-private). Type extensions are *not* counted - - * *Private types* (including private extensions) - - * *Task types* - - * *Protected types* - - * *All types* - This metric is computed for any compilation unit. It is equal to - the total number of the declarations of different types given in - the compilation unit. The private and the corresponding full type - declaration are counted as one type declaration. Incomplete type - declarations and generic formal types are not counted. - No distinction is made among different kinds of types (abstract, - private etc.); the total number of types is reported. - - By default, all the syntax metrics are reported. You can use the following - switches to select specific syntax metrics. - - - .. index:: --syntax (gnatmetric) - .. index:: --no-syntax (gnatmetric) - - - :switch:`--syntax-all` - Report all the syntax metrics - - - :switch:`--no-syntax-all` - Do not report any of syntax metrics - - - :switch:`--declarations` - Report the total number of declarations - - - :switch:`--no-declarations` - Do not report the total number of declarations - - - :switch:`--statements` - Report the total number of statements - - - :switch:`--no-statements` - Do not report the total number of statements - - - :switch:`--public-subprograms` - Report the number of public subprograms in a compilation unit - - - :switch:`--no-public-subprograms` - Do not report the number of public subprograms in a compilation unit - - - :switch:`--all-subprograms` - Report the number of all the subprograms in a compilation unit - - - :switch:`--no-all-subprograms` - Do not report the number of all the subprograms in a compilation unit - - - :switch:`--public-types` - Report the number of public types in a compilation unit - - - :switch:`--no-public-types` - Do not report the number of public types in a compilation unit - - - :switch:`--all-types` - Report the number of all the types in a compilation unit - - - :switch:`--no-all-types` - Do not report the number of all the types in a compilation unit - - - :switch:`--unit-nesting` - Report the maximal program unit nesting level - - - :switch:`--no-unit-nesting` - Do not report the maximal program unit nesting level - - - :switch:`--construct-nesting` - Report the maximal construct nesting level - - - :switch:`--no-construct-nesting` - Do not report the maximal construct nesting level - - :switch:`--param-number` - Report the number of subprogram parameters - - - :switch:`--no-param-number` - Do not report the number of subprogram parameters - - - .. _Contract_Metrics_Control: - - Contract Metrics Control - ^^^^^^^^^^^^^^^^^^^^^^^^ - - .. index:: Contract metrics control in gnatmetric - - :switch:`--contract-all` - Report all the contract metrics - - - :switch:`--no-contract-all` - Do not report any of the contract metrics - - - :switch:`--contract` - Report the number of public subprograms with contracts - - - :switch:`--no-contract` - Do not report the number of public subprograms with contracts - - - :switch:`--post` - Report the number of public subprograms with postconditions - - - :switch:`--no-post` - Do not report the number of public subprograms with postconditions - - - :switch:`--contract-complete` - Report the number of public subprograms with complete contracts - - - :switch:`--no-contract-complete` - Do not report the number of public subprograms with complete contracts - - - :switch:`--contract-cyclomatic` - Report the McCabe complexity of public subprograms - - - :switch:`--no-contract-cyclomatic` - Do not report the McCabe complexity of public subprograms - - - .. _Complexity_Metrics_Control: - - Complexity Metrics Control - ^^^^^^^^^^^^^^^^^^^^^^^^^^ - - .. index:: Complexity metrics control in gnatmetric - - For a program unit that is an executable body (a subprogram body - (including generic bodies), task body, entry body or a package body - containing its own statement sequence) ``gnatmetric`` computes the - following complexity metrics: - - * McCabe cyclomatic complexity; - - * McCabe essential complexity; - - * maximal loop nesting level; - - * extra exit points (for subprograms); - - The McCabe cyclomatic complexity metric is defined - in `http://www.mccabe.com/pdf/mccabe-nist235r.pdf <http://www.mccabe.com/pdf/mccabe-nist235r.pdf>`_ - - According to McCabe, both control statements and short-circuit control - forms should be taken into account when computing cyclomatic - complexity. For Ada 2012 we have also take into account conditional - expressions and quantified expressions. For each body, we compute - three metric values: - - * the complexity introduced by control - statements only, without taking into account short-circuit forms - (referred as ``statement complexity`` in ``gnatmetric`` output), - - * the complexity introduced by short-circuit control forms only - (referred as ``expression complexity`` in ``gnatmetric`` output), - and - - * the total - cyclomatic complexity, which is the sum of these two values - (referred as ``cyclomatic complexity`` in ``gnatmetric`` output). - - The cyclomatic complexity is also computed for Ada 2012 expression functions. - An expression function cannot have statements as its components, so only one - metric value is computed as a cyclomatic complexity of an expression function. - - The origin of cyclomatic complexity metric is the need to estimate the number - of independent paths in the control flow graph that in turn gives the number - of tests needed to satisfy paths coverage testing completeness criterion. - Considered from the testing point of view, a static Ada ``loop`` (that is, - the ``loop`` statement having static subtype in loop parameter - specification) does not add to cyclomatic complexity. By providing - :switch:`--no-static-loop` option a user - may specify that such loops should not be counted when computing the - cyclomatic complexity metric - - The Ada essential complexity metric is a McCabe cyclomatic complexity metric - counted for the code that is reduced by excluding all the pure structural Ada - control statements. An compound statement is considered as a non-structural - if it contains a ``raise`` or ``return`` statement as it subcomponent, - or if it contains a ``goto`` statement that transfers the control outside - the operator. A selective ``accept`` statement with a ``terminate`` alternative - is considered a non-structural statement. When computing this metric, - ``exit`` statements are treated in the same way as ``goto`` - statements unless the :switch:`-ne` option is specified. - - The Ada essential complexity metric defined here is intended to quantify - the extent to which the software is unstructured. It is adapted from - the McCabe essential complexity metric defined in - http://www.mccabe.com/pdf/mccabe-nist235r.pdf - but is modified to be more - suitable for typical Ada usage. For example, short circuit forms - are not penalized as unstructured in the Ada essential complexity metric. - - When computing cyclomatic and essential complexity, ``gnatmetric`` skips - the code in the exception handlers and in all the nested program units. The - code of assertions and predicates (that is, subprogram preconditions and - postconditions, subtype predicates and type invariants) is also skipped. - - By default, all the complexity metrics are reported. For more fine-grained - control you can use the following switches: - - - .. index:: --complexity (gnatmetric) - .. index:: --no-complexity (gnatmetric) - - - :switch:`--complexity-all` - Report all the complexity metrics - - - :switch:`--no-complexity-all` - Do not report any of the complexity metrics - - - :switch:`--complexity-cyclomatic` - Report the McCabe Cyclomatic Complexity - - - :switch:`--no-complexity-cyclomatic` - Do not report the McCabe Cyclomatic Complexity - - - :switch:`--complexity-essential` - Report the Essential Complexity - - - :switch:`--no-complexity-essential` - Do not report the Essential Complexity - - - :switch:`--loop-nesting` - Report maximal loop nesting level - - - :switch:`--no-loop-nesting` - Do not report maximal loop nesting level - - - :switch:`--complexity-average` - Report the average McCabe Cyclomatic Complexity for all the subprogram bodies, - task bodies, entry bodies and statement sequences in package bodies. - The metric is reported for whole set of processed Ada sources only. - - - :switch:`--no-complexity-average` - Do not report the average McCabe Cyclomatic Complexity for all the subprogram - bodies, task bodies, entry bodies and statement sequences in package bodies - - .. index:: --no-treat-exit-as-goto (gnatmetric) - - - :switch:`--no-treat-exit-as-goto` - Do not consider ``exit`` statements as ``goto``\ s when - computing Essential Complexity - - .. index:: --no-static-loop (gnatmetric) - - - :switch:`--no-static-loop` - Do not consider static loops when computing cyclomatic complexity - - - :switch:`--extra-exit-points` - Report the extra exit points for subprogram bodies. As an exit point, this - metric counts ``return`` statements and raise statements in case when the - raised exception is not handled in the same body. In case of a function this - metric subtracts 1 from the number of exit points, because a function body - must contain at least one ``return`` statement. - - - :switch:`--no-extra-exit-points` - Do not report the extra exit points for subprogram bodies - - - .. _Coupling_Metrics_Control: - - Coupling Metrics Control - ^^^^^^^^^^^^^^^^^^^^^^^^ - - .. index:: Coupling metrics control in gnatmetric - - .. index:: Coupling metrics (in gnatmetric) - - Coupling metrics measure the dependencies between a given entity and other - entities in the program. This information is useful since high coupling - may signal potential issues with maintainability as the program evolves. - - ``gnatmetric`` computes the following coupling metrics: - - - * *object-oriented coupling*, for classes in traditional object-oriented - sense; - - * *unit coupling*, for all the program units making up a program; - - * *control coupling*, reflecting dependencies between a unit and - other units that contain subprograms. - - .. index:: fan-out coupling - .. index:: efferent coupling - - Two kinds of coupling metrics are computed: - - * fan-out coupling ('efferent coupling'): - the number of entities the given entity depends upon. This metric - reflects how the given entity depends on the changes in the - 'external world'. - - .. index:: fan-in coupling - .. index:: afferent coupling - - * fan-in coupling ('afferent' coupling): - the number of entities that depend on a given entity. - This metric reflects how the 'external world' depends on the changes in a - given entity. - - Object-oriented coupling metrics measure the dependencies - between a given class (or a group of classes) and the other classes in the - program. In this subsection the term 'class' is used in its traditional - object-oriented programming sense (an instantiable module that contains data - and/or method members). A *category* (of classes) is a group of closely - related classes that are reused and/or modified together. - - A class ``K``\ 's fan-out coupling is the number of classes - that ``K`` depends upon. - A category's fan-out coupling is the number of classes outside the - category that the classes inside the category depend upon. - - A class ``K``\ 's fan-in coupling is the number of classes - that depend upon ``K``. - A category's fan-in coupling is the number of classes outside the - category that depend on classes belonging to the category. - - Ada's object-oriented paradigm separates the instantiable entity - (type) from the module (package), so the definition of the coupling - metrics for Ada maps the class and class category notions - onto Ada constructs. - - For the coupling metrics, several kinds of modules that define a tagged type - or an interface type -- library packages, library generic packages, and - library generic package instantiations -- are considered to be classes. - A category consists of a library package (or - a library generic package) that defines a tagged or an interface type, - together with all its descendant (generic) packages that define tagged - or interface types. Thus a - category is an Ada hierarchy of library-level program units. Class - coupling in Ada is referred to as 'tagged coupling', and category coupling - is referred to as 'hierarchy coupling'. - - For any package serving as a class, its body and subunits (if any) are - considered together with its spec when computing dependencies, and coupling - metrics are reported for spec units only. Dependencies between classes - mean Ada semantic dependencies. For object-oriented coupling - metrics, only dependencies on units treated as classes are - considered. - - Similarly, for unit and control coupling an entity is considered to be the - conceptual construct consisting of the entity's specification, body, and - any subunits (transitively). - ``gnatmetric`` computes - the dependencies of all these units as a whole, but - metrics are only reported for spec - units (or for a subprogram body unit in case if there is no - separate spec for the given subprogram). - - For unit coupling, dependencies are computed between all kinds of program - units. For control coupling, the dependencies of a given unit are limited to - those units that define subprograms. Thus control fan-out coupling is reported - for all units, but control fan-in coupling is only reported for units - that define subprograms. - - The following simple example illustrates the difference between unit coupling - and control coupling metrics: - - .. code-block:: ada - - package Lib_1 is - function F_1 (I : Integer) return Integer; - end Lib_1; - - package Lib_2 is - type T_2 is new Integer; - end Lib_2; - - package body Lib_1 is - function F_1 (I : Integer) return Integer is - begin - return I + 1; - end F_1; - end Lib_1; - - with Lib_2; use Lib_2; - package Pack is - Var : T_2; - function Fun (I : Integer) return Integer; - end Pack; - - with Lib_1; use Lib_1; - package body Pack is - function Fun (I : Integer) return Integer is - begin - return F_1 (I); - end Fun; - end Pack; - - If we apply ``gnatmetric`` with the :switch:`--coupling-all` option to - these units, the result will be: - - :: - - Coupling metrics: - ================= - Unit Lib_1 (C:\\customers\\662\\L406-007\\lib_1.ads) - control fan-out coupling : 0 - control fan-in coupling : 1 - unit fan-out coupling : 0 - unit fan-in coupling : 1 - - Unit Pack (C:\\customers\\662\\L406-007\\pack.ads) - control fan-out coupling : 1 - control fan-in coupling : 0 - unit fan-out coupling : 2 - unit fan-in coupling : 0 - - Unit Lib_2 (C:\\customers\\662\\L406-007\\lib_2.ads) - control fan-out coupling : 0 - unit fan-out coupling : 0 - unit fan-in coupling : 1 - - The result does not contain values for object-oriented - coupling because none of the argument units contains a tagged type and - therefore none of these units can be treated as a class. - - The ``Pack`` package (spec and body) depends on two - units -- ``Lib_1`` and ``Lib_2`` -- and so its unit fan-out coupling - is 2. Since nothing depends on it, its unit fan-in coupling is 0, as - is its control fan-in coupling. Only one of the units ``Pack`` depends - upon defines a subprogram, so its control fan-out coupling is 1. - - ``Lib_2`` depends on nothing, so its fan-out metrics are 0. It does - not define any subprograms, so it has no control fan-in metric. - One unit (``Pack``) depends on it , so its unit fan-in coupling is 1. - - ``Lib_1`` is similar to ``Lib_2``, but it does define a subprogram. - Its control fan-in coupling is 1 (because there is one unit - depending on it). - - When computing coupling metrics, ``gnatmetric`` counts only - dependencies between units that are arguments of the ``gnatmetric`` - invocation. Coupling metrics are program-wide (or project-wide) metrics, so - you should invoke ``gnatmetric`` for - the complete set of sources comprising your program. This can be done - by invoking ``gnatmetric`` with the corresponding project file - and with the :switch:`-U` option. - - By default, all the coupling metrics are reported. You can use the following - switches to select specific syntax metrics. - - .. index:: --tagged-coupling (gnatmetric) - .. index:: --hierarchy-coupling (gnatmetric) - .. index:: --unit-coupling (gnatmetric) - .. index:: --control-coupling (gnatmetric) - - :switch:`--coupling-all` - Report all the coupling metrics - - - :switch:`--tagged-coupling-out` - Report tagged (class) fan-out coupling - - - :switch:`--tagged-coupling-in` - Report tagged (class) fan-in coupling - - - :switch:`--hierarchy-coupling-out` - Report hierarchy (category) fan-out coupling - - - :switch:`--hierarchy-coupling-in` - Report hierarchy (category) fan-in coupling - - - :switch:`--unit-coupling-out` - Report unit fan-out coupling - - - :switch:`--unit-coupling-in` - Report unit fan-in coupling - - - :switch:`--control-coupling-out` - Report control fan-out coupling - - - :switch:`--control-coupling-in` - Report control fan-in coupling - - - .. _Other_gnatmetric_Switches: - - Other ``gnatmetric`` Switches - ----------------------------- - - Additional ``gnatmetric`` switches are as follows: - - - .. index:: --version (gnatmetric) - - :switch:`--version` - Display copyright and version, then exit disregarding all other options. - - - .. index:: --help (gnatmetric) - - :switch:`--help` - Display usage, then exit disregarding all other options. - - - .. index:: -P (gnatmetric) - - :switch:`-P {file}` - Indicates the name of the project file that describes the set of sources - to be processed. The exact set of argument sources depends on other options - specified, see below. An aggregate project is allowed as the file parameter - only if it has exactly one non-aggregate project being aggregated. - - - .. index:: -U (gnatmetric) - - :switch:`-U` - If a project file is specified and no argument source is explicitly - specified (either directly or by means of :switch:`-files` option), process - all the units of the closure of the argument project. Otherwise this option - has no effect. - - - :switch:`-U {main_unit}` - If a project file is specified and no argument source is explicitly - specified (either directly or by means of :switch:`-files` option), process - the closure of units rooted at ``main_unit``. Otherwise this option - has no effect. - - - .. index:: -X (gnatmetric) - - :switch:`-X{name}={value}` - Indicates that external variable ``name`` in the argument project - has the value ``value``. Has no effect if no project is specified. - - - .. index:: --RTS (gnatmetric) - - :switch:`--RTS={rts-path}` - Specifies the default location of the runtime library. Same meaning as the - equivalent ``gnatmake`` flag (see :ref:`Switches_for_gnatmake`). - - - .. index:: --subdirs=dir (gnatmetric) - - :switch:`--subdirs={dir}` - Use the specified subdirectory of the project objects file (or of the - project file directory if the project does not specify an object directory) - for tool output files. Has no effect if no project is specified as - tool argument r if :switch:`--no-objects-dir` is specified. - - - .. index:: --files (gnatmetric) - - :switch:`--files={file}` - Take as arguments the files listed in text file ``file``. - Text file ``file`` may contain empty lines that are ignored. - Each nonempty line should contain the name of an existing file. - Several such switches may be specified simultaneously. - - - .. index:: --ignore (gnatmetric) - - :switch:`--ignore={filename}` - Do not process the sources listed in a specified file. - - - .. index:: --verbose (gnatmetric) - - :switch:`--verbose` - Verbose mode; - ``gnatmetric`` generates version information and then - a trace of sources being processed. - - - .. index:: --quiet (gnatmetric) - - :switch:`--quiet` - Quiet mode. - - If a project file is specified and no argument source is explicitly - specified (either directly or by means of :switch:`-files` option), and no - :switch:`-U` is specified, then the set of processed sources is - all the immediate units of the argument project. - - - Legacy Switches - ^^^^^^^^^^^^^^^ - - Some switches have a short form, mostly for legacy reasons, - as shown below. - - .. index:: -x (gnatmetric) - - :switch:`-x` - :switch:`--generate-xml-output` - - .. index:: -xs (gnatmetric) - - :switch:`-xs` - :switch:`--generate-xml-schema` - - .. index:: -nt (gnatmetric) - - :switch:`-nt` - :switch:`--no-text-output` - - .. index:: -d (gnatmetric) - - :switch:`-d {output-dir}` - :switch:`--output-dir` - - .. index:: -o (gnatmetric) - - :switch:`-o {file-suffix}` - :switch:`--output-suffix` - - .. index:: -og (gnatmetric) - - :switch:`-og {file-name}` - :switch:`--global-file-name` - - .. index:: -ox (gnatmetric) - - :switch:`-ox {file-name}` - :switch:`--xml-file-name` - - .. index:: -sfn (gnatmetric) - - :switch:`-sfn` - :switch:`--short-file-names` - - .. index:: -W (gnatsmetric) - - :switch:`-W{e}` - :switch:`--wide-character-encoding={e}` - - .. index:: -nolocal (gnatmetric) - - :switch:`-nolocal` - :switch:`--no-local-metrics` - - .. index:: -ne (gnatmetric) - - :switch:`-ne` - :switch:`--no-treat-exit-as-goto` - - .. index:: -files (gnatmetric) - - :switch:`-files {filename}` - :switch:`--files` - - .. index:: -v (gnatmetric) - - :switch:`-v` - :switch:`--verbose` - - .. index:: -q (gnatmetric) - - :switch:`-q` - :switch:`--quiet` - .. only:: PRO or GPL .. _The_GNAT_Pretty_Printer_gnatpp: @@ -3026,7 +1908,7 @@ building specialized scripts. naming conventions. Note that it is no longer necessary to specify the Ada language version; - ``gnatmetric`` can process Ada source code written in any version from + ``gnatstub`` can process Ada source code written in any version from Ada 83 onward without specifying any language version switch. * *switches* diff --git a/gcc/ada/expect.c b/gcc/ada/expect.c index b1889fe..48fb107 100644 --- a/gcc/ada/expect.c +++ b/gcc/ada/expect.c @@ -42,17 +42,13 @@ #include "adaint.h" #include <sys/types.h> -#ifdef __MINGW32__ -# if OLD_MINGW -# include <sys/wait.h> -# endif -#elif defined (__vxworks) && defined (__RTP__) +#if defined (__vxworks) && defined (__RTP__) # include <wait.h> #elif defined (__Lynx__) /* ??? See comment in adaint.c. */ # define GCC_RESOURCE_H # include <sys/wait.h> -#elif defined (__PikeOS__) +#elif defined (__PikeOS__) || defined (__MINGW32__) /* No wait.h available */ #else #include <sys/wait.h> diff --git a/gcc/ada/gnat_rm.texi b/gcc/ada/gnat_rm.texi index cdf8605..64f2e79 100644 --- a/gcc/ada/gnat_rm.texi +++ b/gcc/ada/gnat_rm.texi @@ -19,7 +19,7 @@ @copying @quotation -GNAT Reference Manual , Sep 09, 2022 +GNAT Reference Manual , Sep 23, 2022 AdaCore @@ -433,7 +433,7 @@ Implementation Defined Attributes * Attribute Universal_Literal_String:: * Attribute Unrestricted_Access:: * Attribute Update:: -* Attribute Valid_Image:: +* Attribute Valid_Value:: * Attribute Valid_Scalars:: * Attribute VADS_Size:: * Attribute Value_Size:: @@ -10295,7 +10295,7 @@ consideration, you should minimize the use of these attributes. * Attribute Universal_Literal_String:: * Attribute Unrestricted_Access:: * Attribute Update:: -* Attribute Valid_Image:: +* Attribute Valid_Value:: * Attribute Valid_Scalars:: * Attribute VADS_Size:: * Attribute Value_Size:: @@ -12040,7 +12040,7 @@ In general this is a risky approach. It may appear to “work” but such uses o @code{Unrestricted_Access} are potentially non-portable, even from one version of GNAT to another, so are best avoided if possible. -@node Attribute Update,Attribute Valid_Image,Attribute Unrestricted_Access,Implementation Defined Attributes +@node Attribute Update,Attribute Valid_Value,Attribute Unrestricted_Access,Implementation Defined Attributes @anchor{gnat_rm/implementation_defined_attributes attribute-update}@anchor{1ac} @section Attribute Update @@ -12121,19 +12121,19 @@ A := A'Update ((1, 2) => 20, (3, 4) => 30); which changes element (1,2) to 20 and (3,4) to 30. -@node Attribute Valid_Image,Attribute Valid_Scalars,Attribute Update,Implementation Defined Attributes -@anchor{gnat_rm/implementation_defined_attributes attribute-valid-image}@anchor{1ad} -@section Attribute Valid_Image +@node Attribute Valid_Value,Attribute Valid_Scalars,Attribute Update,Implementation Defined Attributes +@anchor{gnat_rm/implementation_defined_attributes attribute-valid-value}@anchor{1ad} +@section Attribute Valid_Value -@geindex Valid_Image +@geindex Valid_Value -The @code{'Valid_Image} attribute is defined for enumeration types other than +The @code{'Valid_Value} attribute is defined for enumeration types other than those in package Standard. This attribute is a function that takes -a String, and returns Boolean. @code{T'Valid_Image (S)} returns True +a String, and returns Boolean. @code{T'Valid_Value (S)} returns True if and only if @code{T'Value (S)} would not raise Constraint_Error. -@node Attribute Valid_Scalars,Attribute VADS_Size,Attribute Valid_Image,Implementation Defined Attributes +@node Attribute Valid_Scalars,Attribute VADS_Size,Attribute Valid_Value,Implementation Defined Attributes @anchor{gnat_rm/implementation_defined_attributes attribute-valid-scalars}@anchor{1ae} @section Attribute Valid_Scalars diff --git a/gcc/ada/gnat_ugn.texi b/gcc/ada/gnat_ugn.texi index f2cb1ed..7d96dbe 100644 --- a/gcc/ada/gnat_ugn.texi +++ b/gcc/ada/gnat_ugn.texi @@ -19,7 +19,7 @@ @copying @quotation -GNAT User's Guide for Native Platforms , Sep 09, 2022 +GNAT User's Guide for Native Platforms , Sep 26, 2022 AdaCore @@ -9220,6 +9220,7 @@ Float_Size : Pos; -- Standard.Float'Size Float_Words_BE : Nat; -- Float words stored big-endian? Int_Size : Pos; -- Standard.Integer'Size Long_Double_Size : Pos; -- Standard.Long_Long_Float'Size +Long_Long_Long_Size : Pos; -- Standard.Long_Long_Long_Integer'Size Long_Long_Size : Pos; -- Standard.Long_Long_Integer'Size Long_Size : Pos; -- Standard.Long_Integer'Size Maximum_Alignment : Pos; -- Maximum permitted alignment @@ -9307,6 +9308,7 @@ Float_Size 32 Float_Words_BE 0 Int_Size 64 Long_Double_Size 128 +Long_Long_Long_Size 128 Long_Long_Size 64 Long_Size 64 Maximum_Alignment 16 @@ -15317,10 +15319,11 @@ Linker switches can be specified after @code{-largs} builder switch. @item @code{-fuse-ld=`name'} -Linker to be used. The default is @code{bfd} for @code{ld.bfd}, -the alternative being @code{gold} for @code{ld.gold}. The later is -a more recent and faster linker, but only available on GNU/Linux +Linker to be used. The default is @code{bfd} for @code{ld.bfd}; @code{gold} +(for @code{ld.gold}) and @code{mold} (for @code{ld.mold}) are more +recent and faster alternatives, but only available on GNU/Linux platforms. + @end table @node Binding with gnatbind,Linking with gnatlink,Linker Switches,Building Executable Programs with GNAT @@ -17932,7 +17935,6 @@ instr.ads - @c -- Example: A |withing| unit has a |with| clause, it |withs| a |withed| unit @node GNAT and Program Execution,Platform-Specific Information,GNAT Utility Programs,Top diff --git a/gcc/ada/gsocket.h b/gcc/ada/gsocket.h index e7284a1..561f2ff 100644 --- a/gcc/ada/gsocket.h +++ b/gcc/ada/gsocket.h @@ -80,12 +80,6 @@ #define FD_SETSIZE 1024 #ifdef __MINGW32__ -/* winsock2.h allows WSAPoll related definitions only when - * _WIN32_WINNT >= 0x0600 */ -#if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600 -#define _WIN32_WINNT 0x0600 -#endif - #include <winsock2.h> #include <ws2tcpip.h> #include <versionhelpers.h> diff --git a/gcc/ada/mingw32.h b/gcc/ada/mingw32.h index 1157fc6..d038211 100644 --- a/gcc/ada/mingw32.h +++ b/gcc/ada/mingw32.h @@ -44,11 +44,6 @@ #define UNICODE /* For Win32 API */ #endif -/* We need functionality available only starting with Windows XP */ -#ifndef _WIN32_WINNT -#define _WIN32_WINNT 0x0501 -#endif - #ifndef __CYGWIN__ #include <tchar.h> #endif @@ -99,27 +94,4 @@ extern UINT __gnat_current_ccs_encoding; #define WS2S(str,wstr,len) strncpy(str,wstr,len) #endif -#include <stdlib.h> - -/* STD_MINGW: standard if MINGW32 version > 1.3, we have switched to this - version instead of the previous enhanced version to ease building GNAT on - Windows platforms. By using STD_MINGW or OLD_MINGW it is possible to build - GNAT using both MingW include files (Old MingW + ACT changes and standard - MingW starting with version 1.3. - For w64 Mingw the define STD_MINGW is always set to value 1, because - there is no old header set present. */ -#ifdef _WIN64 -#define STD_MINGW 1 -#else -#define STD_MINGW ((__MINGW32_MAJOR_VERSION == 1 \ - && __MINGW32_MINOR_VERSION >= 3) \ - || (__MINGW32_MAJOR_VERSION >= 2)) -#endif - -#define OLD_MINGW (!(STD_MINGW)) - -#ifndef MAXPATHLEN -#define MAXPATHLEN MAX_PATH -#endif - #endif /* _MINGW32_H */ diff --git a/gcc/ada/rtsfind.ads b/gcc/ada/rtsfind.ads index 65c6409..24aca2c 100644 --- a/gcc/ada/rtsfind.ads +++ b/gcc/ada/rtsfind.ads @@ -189,7 +189,6 @@ package Rtsfind is -- Children of Interfaces Interfaces_C, - Interfaces_Packed_Decimal, -- Children of Interfaces.C @@ -205,7 +204,6 @@ package Rtsfind is System_Address_To_Access_Conversions, System_Arith_64, System_Arith_128, - System_AST_Handling, System_Assertions, System_Atomic_Operations, System_Atomic_Primitives, @@ -257,9 +255,6 @@ package Rtsfind is System_Fat_LFlt, System_Fat_LLF, System_Fat_SFlt, - System_Fat_VAX_D_Float, - System_Fat_VAX_F_Float, - System_Fat_VAX_G_Float, System_Finalization_Masters, System_Finalization_Root, System_Fore_Decimal_32, @@ -288,14 +283,12 @@ package Rtsfind is System_Img_LLLI, System_Img_LLU, System_Img_LLLU, - System_Img_Name, System_Img_Uns, System_Img_WChar, System_Interrupts, System_Long_Long_Float_Expon, System_Machine_Code, System_Mantissa, - System_Memcop, System_Memory, System_Multiprocessors, System_Pack_03, @@ -420,10 +413,7 @@ package Rtsfind is System_Pack_127, System_Parameters, System_Partition_Interface, - System_Pool_32_Global, System_Pool_Global, - System_Pool_Empty, - System_Pool_Local, System_Pool_Size, System_Put_Images, System_Put_Task_Images, @@ -440,7 +430,6 @@ package Rtsfind is System_Stream_Attributes, System_Task_Info, System_Tasking, - System_Threads, System_Unsigned_Types, System_Val_Bool, System_Val_Char, @@ -461,7 +450,6 @@ package Rtsfind is System_Val_LLLI, System_Val_LLU, System_Val_LLLU, - System_Val_Name, System_Val_Uns, System_Val_WChar, System_Version_Control, @@ -475,7 +463,6 @@ package Rtsfind is System_Wid_LLLI, System_Wid_LLU, System_Wid_LLLU, - System_Wid_Name, System_Wid_Uns, System_Wid_WChar, System_WWd_Char, @@ -484,7 +471,7 @@ package Rtsfind is -- Children of System.Atomic_Operations - System_Atomic_Operations_Test_And_Set, + System_Atomic_Operations_Test_And_Set, -- Children of System.Dim @@ -561,17 +548,13 @@ package Rtsfind is RE_Set_Deadline, -- Ada.Dispatching.EDF - RE_Code_Loc, -- Ada.Exceptions RE_Exception_Id, -- Ada.Exceptions - RE_Exception_Identity, -- Ada.Exceptions RE_Exception_Information, -- Ada.Exceptions RE_Exception_Message, -- Ada.Exceptions RE_Exception_Name_Simple, -- Ada.Exceptions RE_Exception_Occurrence, -- Ada.Exceptions - RE_Exception_Occurrence_Access, -- Ada.Exceptions RE_Null_Id, -- Ada.Exceptions RE_Null_Occurrence, -- Ada.Exceptions - RE_Poll, -- Ada.Exceptions RE_Raise_Exception, -- Ada.Exceptions RE_Raise_Exception_Always, -- Ada.Exceptions RE_Raise_From_Controlled_Operation, -- Ada.Exceptions @@ -596,7 +579,7 @@ package Rtsfind is RE_Names, -- Ada.Interrupts.Names RE_Clock, -- Ada.Real_Time - RE_Clock_Time, -- Ada.Real_Time + RE_Clock_Time, -- Ada.Real_Time [used by GNATprove] RE_Time_Span, -- Ada.Real_Time RE_Time_Span_Zero, -- Ada.Real_Time RO_RT_Time, -- Ada.Real_Time @@ -612,8 +595,6 @@ package Rtsfind is RE_Stream_Element_Array, -- Ada.Streams RE_Stream_Element_Offset, -- Ada.Streams - RE_Stream_Access, -- Ada.Streams.Stream_IO - RO_SU_Super_String, -- Ada.Strings.Superbounded RO_WI_Super_String, -- Ada.Strings.Wide_Superbounded @@ -628,8 +609,6 @@ package Rtsfind is RE_Buffer_Type, -- Ada.Strings.Text_Buffers.Unbounded RE_Get, -- Ada.Strings.Text_Buffers.Unbounded - RE_Wide_Get, -- Ada.Strings.Text_Buffers.Unbounded - RE_Wide_Wide_Get, -- Ada.Strings.Text_Buffers.Unbounded RE_Wait_For_Release, -- Ada.Synchronous_Barriers @@ -641,7 +620,6 @@ package Rtsfind is RE_Address_Array, -- Ada.Tags RE_Addr_Ptr, -- Ada.Tags RE_Base_Address, -- Ada.Tags - RE_Check_Interface_Conversion, -- Ada.Tags RE_Check_TSD, -- Ada.Tags RE_Cstring_Ptr, -- Ada.Tags RE_CW_Membership, -- Ada.Tags @@ -656,13 +634,11 @@ package Rtsfind is RE_External_Tag, -- Ada.Tags RO_TA_External_Tag, -- Ada.Tags RE_Get_Access_Level, -- Ada.Tags - RE_Get_Alignment, -- Ada.Tags RE_Get_Entry_Index, -- Ada.Tags RE_Get_Offset_Index, -- Ada.Tags RE_Get_Prim_Op_Kind, -- Ada.Tags RE_Get_Tagged_Kind, -- Ada.Tags RE_HT_Link, -- Ada.Tags - RE_Idepth, -- Ada.Tags RE_Interfaces_Array, -- Ada.Tags RE_Interfaces_Table, -- Ada.Tags RE_Interface_Data, -- Ada.Tags @@ -675,8 +651,6 @@ package Rtsfind is RE_No_Dispatch_Table_Wrapper, -- Ada.Tags RE_No_Tag, -- Ada.Tags RE_NDT_Prims_Ptr, -- Ada.Tags - RE_NDT_TSD, -- Ada.Tags - RE_Num_Prims, -- Ada.Tags RE_Object_Specific_Data, -- Ada.Tags RE_Offset_To_Top, -- Ada.Tags RE_Offset_To_Top_Ptr, -- Ada.Tags @@ -699,11 +673,9 @@ package Rtsfind is RE_Primary_DT, -- Ada.Tags RE_Signature, -- Ada.Tags RE_SSD, -- Ada.Tags - RE_TSD, -- Ada.Tags RE_Type_Specific_Data, -- Ada.Tags RE_Register_Interface_Offset, -- Ada.Tags RE_Register_Tag, -- Ada.Tags - RE_Register_TSD, -- Ada.Tags RE_Transportable, -- Ada.Tags RE_Secondary_DT, -- Ada.Tags RE_Secondary_Tag, -- Ada.Tags @@ -749,7 +721,6 @@ package Rtsfind is RE_Stream_T, -- CUDA.Driver_Types - RE_Fatbin_Wrapper, -- CUDA.Internal RE_Launch_Kernel, -- CUDA.Internal RE_Pop_Call_Configuration, -- CUDA.Internal RE_Push_Call_Configuration, -- CUDA.Internal @@ -772,19 +743,14 @@ package Rtsfind is RO_IC_Unsigned, -- Interfaces.C - RE_Chars_Ptr, -- Interfaces.C.Strings - RE_New_Char_Array, -- Interfaces.C.Strings - RE_Address, -- System RE_Any_Priority, -- System RE_Bit_Order, -- System RE_Default_Priority, -- System RE_High_Order_First, -- System RE_Interrupt_Priority, -- System - RE_Lib_Stop, -- System RE_Low_Order_First, -- System RE_Max_Base_Digits, -- System - RE_Max_Priority, -- System RE_Null_Address, -- System RE_Priority, -- System @@ -802,8 +768,6 @@ package Rtsfind is RE_Subtract_With_Ovflo_Check128, -- System.Arith_128 RE_Scaled_Divide128, -- System.Arith_128 - RE_Create_AST_Handler, -- System.AST_Handling - RE_Assert_Failure, -- System.Assertions RE_Raise_Assert_Failure, -- System.Assertions @@ -824,9 +788,6 @@ package Rtsfind is RE_Atomic_Test_And_Set, -- System.Atomic_Operations.Test_And_Set RE_AST_Handler, -- System.Aux_DEC - RE_Import_Address, -- System.Aux_DEC - RE_Import_Value, -- System.Aux_DEC - RE_No_AST_Handler, -- System.Aux_DEC RE_Type_Class, -- System.Aux_DEC RE_Type_Class_Enumeration, -- System.Aux_DEC RE_Type_Class_Integer, -- System.Aux_DEC @@ -954,15 +915,6 @@ package Rtsfind is RE_Attr_Long_Long_Float, -- System.Fat_LLF - RE_Attr_VAX_D_Float, -- System.Fat_VAX_D_Float - RE_Fat_VAX_D, -- System.Fat_VAX_D_Float - - RE_Attr_VAX_F_Float, -- System.Fat_VAX_F_Float - RE_Fat_VAX_F, -- System.Fat_VAX_F_Float - - RE_Attr_VAX_G_Float, -- System.Fat_VAX_G_Float - RE_Fat_VAX_G, -- System.Fat_VAX_G_Float - RE_Add_Offset_To_Address, -- System.Finalization_Masters RE_Attach, -- System.Finalization_Masters RE_Base_Pool, -- System.Finalization_Masters @@ -970,10 +922,8 @@ package Rtsfind is RE_Finalization_Master_Ptr, -- System.Finalization_Masters RE_Set_Base_Pool, -- System.Finalization_Masters RE_Set_Finalize_Address, -- System.Finalization_Masters - RE_Set_Is_Heterogeneous, -- System.Finalization_Masters RE_Root_Controlled, -- System.Finalization_Root - RE_Root_Controlled_Ptr, -- System.Finalization_Root RE_Fore_Decimal32, -- System.Fore_Decimal_32 @@ -1649,9 +1599,7 @@ package Rtsfind is RE_Set_127, -- System.Pack_127 RE_Adjust_Storage_Size, -- System.Parameters - RE_Default_Secondary_Stack_Size, -- System.Parameters RE_Default_Stack_Size, -- System.Parameters - RE_Garbage_Collected, -- System.Parameters RE_Size_Type, -- System.Parameters RE_Unspecified_Size, -- System.Parameters @@ -1677,8 +1625,6 @@ package Rtsfind is RE_Global_Pool_Object, -- System.Pool_Global - RE_Global_Pool_32_Object, -- System.Pool_32_Global - RE_Stack_Bounded_Pool, -- System.Pool_Size RE_Put_Image_Integer, -- System.Put_Images @@ -1744,11 +1690,8 @@ package Rtsfind is RE_Set_Result, -- System.Partition_Interface RE_Register_Obj_Receiving_Stub, -- System.Partition_Interface RE_Register_Pkg_Receiving_Stub, -- System.Partition_Interface - RE_Is_Nil, -- System.Partition_Interface - RE_Entity_Ptr, -- System.Partition_Interface RE_Entity_Of, -- System.Partition_Interface RE_Inc_Usage, -- System.Partition_Interface - RE_Set_Ref, -- System.Partition_Interface RE_Make_Ref, -- System.Partition_Interface RE_Get_Local_Address, -- System.Partition_Interface RE_Get_Reference, -- System.Partition_Interface @@ -1881,8 +1824,6 @@ package Rtsfind is RE_Deallocate_Any_Controlled, -- System.Storage_Pools.Subpools RE_Header_Size_With_Padding, -- System.Storage_Pools.Subpools RE_Root_Storage_Pool_With_Subpools, -- System.Storage_Pools.Subpools - RE_Root_Subpool, -- System.Storage_Pools.Subpools - RE_Subpool_Handle, -- System.Storage_Pools.Subpools RE_I_AD, -- System.Stream_Attributes RE_I_AS, -- System.Stream_Attributes @@ -2006,7 +1947,6 @@ package Rtsfind is RE_Simple_Mode, -- System.Tasking RE_Terminate_Mode, -- System.Tasking RE_Delay_Mode, -- System.Tasking - RE_Entry_Index, -- System.Tasking RE_Task_Entry_Index, -- System.Tasking RE_Self, -- System.Tasking @@ -2244,17 +2184,13 @@ package Rtsfind is RE_Set_Deadline => Ada_Dispatching_EDF, - RE_Code_Loc => Ada_Exceptions, RE_Exception_Id => Ada_Exceptions, - RE_Exception_Identity => Ada_Exceptions, RE_Exception_Information => Ada_Exceptions, RE_Exception_Message => Ada_Exceptions, RE_Exception_Name_Simple => Ada_Exceptions, RE_Exception_Occurrence => Ada_Exceptions, - RE_Exception_Occurrence_Access => Ada_Exceptions, RE_Null_Id => Ada_Exceptions, RE_Null_Occurrence => Ada_Exceptions, - RE_Poll => Ada_Exceptions, RE_Raise_Exception => Ada_Exceptions, RE_Raise_Exception_Always => Ada_Exceptions, RE_Raise_From_Controlled_Operation => Ada_Exceptions, @@ -2295,8 +2231,6 @@ package Rtsfind is RE_Stream_Element_Array => Ada_Streams, RE_Stream_Element_Offset => Ada_Streams, - RE_Stream_Access => Ada_Streams_Stream_IO, - RO_SU_Super_String => Ada_Strings_Superbounded, RO_WI_Super_String => Ada_Strings_Wide_Superbounded, @@ -2311,8 +2245,6 @@ package Rtsfind is RE_Buffer_Type => Ada_Strings_Text_Buffers_Unbounded, RE_Get => Ada_Strings_Text_Buffers_Unbounded, - RE_Wide_Get => Ada_Strings_Text_Buffers_Unbounded, - RE_Wide_Wide_Get => Ada_Strings_Text_Buffers_Unbounded, RE_Wait_For_Release => Ada_Synchronous_Barriers, @@ -2324,7 +2256,6 @@ package Rtsfind is RE_Address_Array => Ada_Tags, RE_Addr_Ptr => Ada_Tags, RE_Base_Address => Ada_Tags, - RE_Check_Interface_Conversion => Ada_Tags, RE_Check_TSD => Ada_Tags, RE_Cstring_Ptr => Ada_Tags, RE_CW_Membership => Ada_Tags, @@ -2339,13 +2270,11 @@ package Rtsfind is RE_External_Tag => Ada_Tags, RO_TA_External_Tag => Ada_Tags, RE_Get_Access_Level => Ada_Tags, - RE_Get_Alignment => Ada_Tags, RE_Get_Entry_Index => Ada_Tags, RE_Get_Offset_Index => Ada_Tags, RE_Get_Prim_Op_Kind => Ada_Tags, RE_Get_Tagged_Kind => Ada_Tags, RE_HT_Link => Ada_Tags, - RE_Idepth => Ada_Tags, RE_Interfaces_Array => Ada_Tags, RE_Interfaces_Table => Ada_Tags, RE_Interface_Data => Ada_Tags, @@ -2358,8 +2287,6 @@ package Rtsfind is RE_No_Dispatch_Table_Wrapper => Ada_Tags, RE_No_Tag => Ada_Tags, RE_NDT_Prims_Ptr => Ada_Tags, - RE_NDT_TSD => Ada_Tags, - RE_Num_Prims => Ada_Tags, RE_Object_Specific_Data => Ada_Tags, RE_Offset_To_Top => Ada_Tags, RE_Offset_To_Top_Ptr => Ada_Tags, @@ -2382,11 +2309,9 @@ package Rtsfind is RE_Primary_DT => Ada_Tags, RE_Signature => Ada_Tags, RE_SSD => Ada_Tags, - RE_TSD => Ada_Tags, RE_Type_Specific_Data => Ada_Tags, RE_Register_Interface_Offset => Ada_Tags, RE_Register_Tag => Ada_Tags, - RE_Register_TSD => Ada_Tags, RE_Transportable => Ada_Tags, RE_Secondary_DT => Ada_Tags, RE_Secondary_Tag => Ada_Tags, @@ -2432,7 +2357,6 @@ package Rtsfind is RE_Stream_T => CUDA_Driver_Types, - RE_Fatbin_Wrapper => CUDA_Internal, RE_Launch_Kernel => CUDA_Internal, RE_Pop_Call_Configuration => CUDA_Internal, RE_Push_Call_Configuration => CUDA_Internal, @@ -2455,19 +2379,14 @@ package Rtsfind is RO_IC_Unsigned => Interfaces_C, - RE_Chars_Ptr => Interfaces_C_Strings, - RE_New_Char_Array => Interfaces_C_Strings, - RE_Address => System, RE_Any_Priority => System, RE_Bit_Order => System, RE_Default_Priority => System, RE_High_Order_First => System, RE_Interrupt_Priority => System, - RE_Lib_Stop => System, RE_Low_Order_First => System, RE_Max_Base_Digits => System, - RE_Max_Priority => System, RE_Null_Address => System, RE_Priority => System, @@ -2485,8 +2404,6 @@ package Rtsfind is RE_Subtract_With_Ovflo_Check128 => System_Arith_128, RE_Scaled_Divide128 => System_Arith_128, - RE_Create_AST_Handler => System_AST_Handling, - RE_Assert_Failure => System_Assertions, RE_Raise_Assert_Failure => System_Assertions, @@ -2507,9 +2424,6 @@ package Rtsfind is RE_Atomic_Test_And_Set => System_Atomic_Operations_Test_And_Set, RE_AST_Handler => System_Aux_DEC, - RE_Import_Address => System_Aux_DEC, - RE_Import_Value => System_Aux_DEC, - RE_No_AST_Handler => System_Aux_DEC, RE_Type_Class => System_Aux_DEC, RE_Type_Class_Enumeration => System_Aux_DEC, RE_Type_Class_Integer => System_Aux_DEC, @@ -2643,15 +2557,6 @@ package Rtsfind is RE_Attr_Long_Long_Float => System_Fat_LLF, - RE_Attr_VAX_D_Float => System_Fat_VAX_D_Float, - RE_Fat_VAX_D => System_Fat_VAX_D_Float, - - RE_Attr_VAX_F_Float => System_Fat_VAX_F_Float, - RE_Fat_VAX_F => System_Fat_VAX_F_Float, - - RE_Attr_VAX_G_Float => System_Fat_VAX_G_Float, - RE_Fat_VAX_G => System_Fat_VAX_G_Float, - RE_Add_Offset_To_Address => System_Finalization_Masters, RE_Attach => System_Finalization_Masters, RE_Base_Pool => System_Finalization_Masters, @@ -2659,10 +2564,8 @@ package Rtsfind is RE_Finalization_Master_Ptr => System_Finalization_Masters, RE_Set_Base_Pool => System_Finalization_Masters, RE_Set_Finalize_Address => System_Finalization_Masters, - RE_Set_Is_Heterogeneous => System_Finalization_Masters, RE_Root_Controlled => System_Finalization_Root, - RE_Root_Controlled_Ptr => System_Finalization_Root, RE_Fore_Decimal32 => System_Fore_Decimal_32, @@ -3340,9 +3243,7 @@ package Rtsfind is RE_Set_127 => System_Pack_127, RE_Adjust_Storage_Size => System_Parameters, - RE_Default_Secondary_Stack_Size => System_Parameters, RE_Default_Stack_Size => System_Parameters, - RE_Garbage_Collected => System_Parameters, RE_Size_Type => System_Parameters, RE_Unspecified_Size => System_Parameters, @@ -3399,11 +3300,8 @@ package Rtsfind is RE_Set_Result => System_Partition_Interface, RE_Register_Obj_Receiving_Stub => System_Partition_Interface, RE_Register_Pkg_Receiving_Stub => System_Partition_Interface, - RE_Is_Nil => System_Partition_Interface, - RE_Entity_Ptr => System_Partition_Interface, RE_Entity_Of => System_Partition_Interface, RE_Inc_Usage => System_Partition_Interface, - RE_Set_Ref => System_Partition_Interface, RE_Make_Ref => System_Partition_Interface, RE_Get_Local_Address => System_Partition_Interface, RE_Get_Reference => System_Partition_Interface, @@ -3488,8 +3386,6 @@ package Rtsfind is RE_Global_Pool_Object => System_Pool_Global, - RE_Global_Pool_32_Object => System_Pool_32_Global, - RE_Stack_Bounded_Pool => System_Pool_Size, RE_Put_Image_Integer => System_Put_Images, @@ -3572,8 +3468,6 @@ package Rtsfind is RE_Deallocate_Any_Controlled => System_Storage_Pools_Subpools, RE_Header_Size_With_Padding => System_Storage_Pools_Subpools, RE_Root_Storage_Pool_With_Subpools => System_Storage_Pools_Subpools, - RE_Root_Subpool => System_Storage_Pools_Subpools, - RE_Subpool_Handle => System_Storage_Pools_Subpools, RE_I_AD => System_Stream_Attributes, RE_I_AS => System_Stream_Attributes, @@ -3697,7 +3591,6 @@ package Rtsfind is RE_Simple_Mode => System_Tasking, RE_Terminate_Mode => System_Tasking, RE_Delay_Mode => System_Tasking, - RE_Entry_Index => System_Tasking, RE_Task_Entry_Index => System_Tasking, RE_Self => System_Tasking, diff --git a/gcc/ada/s-oscons-tmplt.c b/gcc/ada/s-oscons-tmplt.c index af69190..5394122 100644 --- a/gcc/ada/s-oscons-tmplt.c +++ b/gcc/ada/s-oscons-tmplt.c @@ -237,9 +237,6 @@ int counter = 0; #define CST(name,comment) C(#name,String,name,comment) /* String constant */ -#define STR(x) STR1(x) -#define STR1(x) #x - #ifdef __MINGW32__ unsigned int _CRT_fmode = _O_BINARY; #endif diff --git a/gcc/ada/sem_ch12.adb b/gcc/ada/sem_ch12.adb index 9525140..ab2e182 100644 --- a/gcc/ada/sem_ch12.adb +++ b/gcc/ada/sem_ch12.adb @@ -6296,13 +6296,16 @@ package body Sem_Ch12 is Old_Main : constant Entity_Id := Cunit_Entity (Main_Unit); begin - -- A new compilation unit node is built for the instance declaration + -- A new compilation unit node is built for the instance declaration. + -- It relocates the auxiliary declaration node from the compilation unit + -- where the instance appeared, so that declarations that originally + -- followed the instance will be attached to the spec compilation unit. Decl_Cunit := Make_Compilation_Unit (Sloc (N), Context_Items => Empty_List, Unit => Act_Decl, - Aux_Decls_Node => Make_Compilation_Unit_Aux (Sloc (N))); + Aux_Decls_Node => Relocate_Node (Aux_Decls_Node (Parent (N)))); Set_Parent_Spec (Act_Decl, Parent_Spec (N)); diff --git a/gcc/ada/sem_ch5.adb b/gcc/ada/sem_ch5.adb index 17bf6d9..d0f00b3 100644 --- a/gcc/ada/sem_ch5.adb +++ b/gcc/ada/sem_ch5.adb @@ -2429,13 +2429,9 @@ package body Sem_Ch5 is if not Is_Entity_Name (Iter_Name) - -- When the context is a quantified expression, the renaming - -- declaration is delayed until the expansion phase if we are - -- doing expansion. + -- Do not perform this expansion in preanalysis - and then (Nkind (Parent (N)) /= N_Quantified_Expression - or else (Operating_Mode = Check_Semantics - and then not GNATprove_Mode)) + and then Full_Analysis -- Do not perform this expansion when expansion is disabled, where the -- temporary may hide the transformation of a selected component into diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb index b0babeb..9ae082c 100644 --- a/gcc/ada/sem_util.adb +++ b/gcc/ada/sem_util.adb @@ -531,7 +531,7 @@ package body Sem_Util is -- Local variables - E : Entity_Id := Original_Node (Expr); + E : Node_Id := Original_Node (Expr); Pre : Node_Id; -- Start of processing for Accessibility_Level @@ -777,8 +777,18 @@ package body Sem_Util is -- We don't handle function calls in prefix notation correctly ??? - when N_Indexed_Component | N_Selected_Component => - Pre := Original_Node (Prefix (E)); + when N_Indexed_Component | N_Selected_Component | N_Slice => + Pre := Prefix (E); + + -- Fetch the original node when the prefix comes from the result + -- of expanding a function call since we want to find the level + -- of the original source call. + + if not Comes_From_Source (Pre) + and then Nkind (Original_Node (Pre)) = N_Function_Call + then + Pre := Original_Node (Pre); + end if; -- When E is an indexed component or selected component and -- the current Expr is a function call, we know that we are @@ -26549,6 +26559,14 @@ package body Sem_Util is Item_Nam := Chars (Original_Node (Pragma_Identifier (Original_Node (Item)))); + if Item_Nam = Name_Check then + -- Pragma "Check" preserves the original pragma name as its first + -- argument. + Item_Nam := + Chars (Expression (First (Pragma_Argument_Associations + (Original_Node (Item))))); + end if; + else pragma Assert (Nkind (Item) = N_Aspect_Specification); Item_Nam := Chars (Identifier (Item)); diff --git a/gcc/ada/sem_warn.ads b/gcc/ada/sem_warn.ads index 1894f36..6681e54 100644 --- a/gcc/ada/sem_warn.ads +++ b/gcc/ada/sem_warn.ads @@ -257,12 +257,9 @@ package Sem_Warn is ---------------------- function Has_Junk_Name (E : Entity_Id) return Boolean; - -- Return True if the entity name contains any of the following substrings: - -- discard - -- dummy - -- ignore - -- junk - -- unused + -- Return True if the entity name contains substrings like "junk" or + -- "dummy" (see the body for the complete list). + -- -- Used to suppress warnings on names matching these patterns. The contents -- of Name_Buffer and Name_Len are destroyed by this call. diff --git a/gcc/ada/sysdep.c b/gcc/ada/sysdep.c index 5e9cf70..7bdfcbc 100644 --- a/gcc/ada/sysdep.c +++ b/gcc/ada/sysdep.c @@ -323,11 +323,7 @@ __gnat_ttyname (int filedes ATTRIBUTE_UNUSED) || defined (__QNX__) # ifdef __MINGW32__ -# if OLD_MINGW -# include <termios.h> -# else -# include <conio.h> /* for getch(), kbhit() */ -# endif +# include <conio.h> /* for getch(), kbhit() */ # else # include <termios.h> # endif diff --git a/gcc/attribs.cc b/gcc/attribs.cc index fb89616..b1f1032 100644 --- a/gcc/attribs.cc +++ b/gcc/attribs.cc @@ -737,6 +737,9 @@ decl_attributes (tree *node, tree attributes, int flags, if (spec->max_length < 0) inform (input_location, "expected %i or more, found %i", spec->min_length, nargs); + else if (spec->min_length == spec->max_length) + inform (input_location, "expected %i, found %i", + spec->min_length, nargs); else inform (input_location, "expected between %i and %i, found %i", spec->min_length, spec->max_length, nargs); diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index ba3d76d..415c4cf 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,17 @@ +2022-09-23 Marek Polacek <polacek@redhat.com> + + PR c++/106784 + * c-common.cc (c_common_reswords): Add __is_convertible and + __is_nothrow_convertible. + * c-common.h (enum rid): Add RID_IS_CONVERTIBLE and + RID_IS_NOTHROW_CONVERTIBLE. + +2022-09-22 David Malcolm <dmalcolm@redhat.com> + + PR c/106830 + * c-warn.cc (check_for_xor_used_as_pow): Don't try checking + values that don't fit in uhwi. + 2022-09-15 Richard Biener <rguenther@suse.de> * c-common.h (build_void_list_node): Remove. diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc index c0f15f4..dce3045 100644 --- a/gcc/c-family/c-common.cc +++ b/gcc/c-family/c-common.cc @@ -541,6 +541,8 @@ const struct c_common_resword c_common_reswords[] = { "__is_constructible", RID_IS_CONSTRUCTIBLE, D_CXXONLY }, { "__is_nothrow_assignable", RID_IS_NOTHROW_ASSIGNABLE, D_CXXONLY }, { "__is_nothrow_constructible", RID_IS_NOTHROW_CONSTRUCTIBLE, D_CXXONLY }, + { "__is_convertible", RID_IS_CONVERTIBLE, D_CXXONLY }, + { "__is_nothrow_convertible", RID_IS_NOTHROW_CONVERTIBLE, D_CXXONLY }, { "__reference_constructs_from_temporary", RID_REF_CONSTRUCTS_FROM_TEMPORARY, D_CXXONLY }, { "__reference_converts_from_temporary", RID_REF_CONVERTS_FROM_TEMPORARY, diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 2f592f5..31397d8 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -184,6 +184,7 @@ enum rid RID_IS_UNION, RID_UNDERLYING_TYPE, RID_IS_ASSIGNABLE, RID_IS_CONSTRUCTIBLE, RID_IS_NOTHROW_ASSIGNABLE, RID_IS_NOTHROW_CONSTRUCTIBLE, + RID_IS_CONVERTIBLE, RID_IS_NOTHROW_CONVERTIBLE, RID_REF_CONSTRUCTS_FROM_TEMPORARY, RID_REF_CONVERTS_FROM_TEMPORARY, diff --git a/gcc/c-family/c-cppbuiltin.cc b/gcc/c-family/c-cppbuiltin.cc index a1557eb..b709f84 100644 --- a/gcc/c-family/c-cppbuiltin.cc +++ b/gcc/c-family/c-cppbuiltin.cc @@ -1112,7 +1112,7 @@ c_cpp_builtins (cpp_reader *pfile) if (flag_threadsafe_statics) cpp_define (pfile, "__cpp_threadsafe_static_init=200806L"); if (flag_char8_t) - cpp_define (pfile, "__cpp_char8_t=201811L"); + cpp_define (pfile, "__cpp_char8_t=202207L"); #ifndef THREAD_MODEL_SPEC /* Targets that define THREAD_MODEL_SPEC need to define __STDCPP_THREADS__ in their config/XXX/XXX-c.c themselves. */ diff --git a/gcc/c-family/c-warn.cc b/gcc/c-family/c-warn.cc index ed79cc3..6742f44 100644 --- a/gcc/c-family/c-warn.cc +++ b/gcc/c-family/c-warn.cc @@ -3809,12 +3809,9 @@ check_for_xor_used_as_pow (location_t lhs_loc, tree lhs_val, location_t operator_loc, tree rhs_val) { - /* Only complain if both args are non-negative integer constants. */ - if (!(TREE_CODE (lhs_val) == INTEGER_CST - && tree_int_cst_sgn (lhs_val) >= 0)) - return; - if (!(TREE_CODE (rhs_val) == INTEGER_CST - && tree_int_cst_sgn (rhs_val) >= 0)) + /* Only complain if both args are non-negative integer constants that fit + in uhwi. */ + if (!tree_fits_uhwi_p (lhs_val) || !tree_fits_uhwi_p (rhs_val)) return; /* Only complain if the LHS is 2 or 10. */ diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index b7fe1a4..4b852b8 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,29 @@ +2022-09-24 Jakub Jelinek <jakub@redhat.com> + + PR c/106981 + * c-typeck.cc (c_tree_equal): Only strip NON_LVALUE_EXPRs at the + start. For CONSTANT_CLASS_P or CASE_CONVERT: return false if t1 and + t2 have different types. + +2022-09-22 David Malcolm <dmalcolm@redhat.com> + + PR c/106830 + * c-parser.cc (c_parser_initelt): Initialize m_decimal. + (c_parser_cast_expression): Likewise. + (c_parser_alignof_expression): Likewise. + (c_parser_postfix_expression_after_paren_type): Likewise. + (c_parser_postfix_expression_after_primary): Likewise. + (c_parser_expression): Likewise. + (c_parser_omp_variable_list): Likewise. + (c_parser_transaction_expression): Likewise. + * c-tree.h (c_expr::set_error): Likewise. + * c-typeck.cc (c_expr_sizeof_expr): Likewise. + (parser_build_unary_op): Likewise. + (parser_build_binary_op): Likewise. + (digest_init): Likewise. + (pop_init_level): Likewise. + * gimple-parser.cc (c_parser_gimple_call_internal): Likewise. + 2022-09-19 Marek Polacek <polacek@redhat.com> PR c/106947 diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc index d134448..bce79d3 100644 --- a/gcc/c/c-parser.cc +++ b/gcc/c/c-parser.cc @@ -5464,6 +5464,7 @@ c_parser_initelt (c_parser *parser, struct obstack * braced_init_obstack) = objc_build_message_expr (rec, args); mexpr.original_code = ERROR_MARK; mexpr.original_type = NULL; + mexpr.m_decimal = 0; /* Now parse and process the remainder of the initializer, starting with this message expression as a primary-expression. */ @@ -8146,6 +8147,7 @@ c_parser_cast_expression (c_parser *parser, struct c_expr *after) set_c_expr_source_range (&ret, cast_loc, expr.get_finish ()); ret.original_code = ERROR_MARK; ret.original_type = NULL; + ret.m_decimal = 0; return ret; } else @@ -8464,6 +8466,7 @@ c_parser_alignof_expression (c_parser *parser) ret.original_code = ERROR_MARK; ret.original_type = NULL; set_c_expr_source_range (&ret, start_loc, end_loc); + ret.m_decimal = 0; return ret; } else @@ -8483,6 +8486,7 @@ c_parser_alignof_expression (c_parser *parser) ret.original_code = ERROR_MARK; ret.original_type = NULL; set_c_expr_source_range (&ret, start_loc, end_loc); + ret.m_decimal = 0; return ret; } } @@ -10383,6 +10387,7 @@ c_parser_postfix_expression_after_paren_type (c_parser *parser, expr.value = build_compound_literal (start_loc, type, init.value, non_const, alignas_align); set_c_expr_source_range (&expr, init.src_range); + expr.m_decimal = 0; expr.original_code = ERROR_MARK; expr.original_type = NULL; if (type != error_mark_node @@ -10597,6 +10602,7 @@ c_parser_postfix_expression_after_primary (c_parser *parser, set_c_expr_source_range (&expr, start, finish); expr.original_code = ERROR_MARK; expr.original_type = NULL; + expr.m_decimal = 0; break; case CPP_OPEN_PAREN: /* Function call. */ @@ -10645,6 +10651,7 @@ c_parser_postfix_expression_after_primary (c_parser *parser, = c_build_function_call_vec (expr_loc, arg_loc, expr.value, exprlist, origtypes); set_c_expr_source_range (&expr, start, finish); + expr.m_decimal = 0; expr.original_code = ERROR_MARK; if (TREE_CODE (expr.value) == INTEGER_CST @@ -10695,6 +10702,7 @@ c_parser_postfix_expression_after_primary (c_parser *parser, else expr.original_type = DECL_BIT_FIELD_TYPE (field); } + expr.m_decimal = 0; break; case CPP_DEREF: /* Structure element reference. */ @@ -10736,6 +10744,7 @@ c_parser_postfix_expression_after_primary (c_parser *parser, else expr.original_type = DECL_BIT_FIELD_TYPE (field); } + expr.m_decimal = 0; break; case CPP_PLUS_PLUS: /* Postincrement. */ @@ -10806,6 +10815,7 @@ c_parser_expression (c_parser *parser) expr.value = build_compound_expr (loc, expr.value, next.value); expr.original_code = COMPOUND_EXPR; expr.original_type = next.original_type; + expr.m_decimal = 0; } return expr; } @@ -13256,6 +13266,7 @@ c_parser_omp_variable_list (c_parser *parser, t_expr.original_code = ERROR_MARK; t_expr.original_type = NULL; set_c_expr_source_range (&t_expr, op_loc, op_loc); + t_expr.m_decimal = 0; t_expr = convert_lvalue_to_rvalue (op_loc, t_expr, true, false); t = build_indirect_ref (op_loc, t_expr.value, RO_ARROW); @@ -23566,6 +23577,7 @@ c_parser_transaction_expression (c_parser *parser, enum rid keyword) TRANSACTION_EXPR_RELAXED (ret.value) = 1; SET_EXPR_LOCATION (ret.value, loc); ret.original_code = TRANSACTION_EXPR; + ret.m_decimal = 0; if (!parens.require_close (parser)) { c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h index b4231a1..46a3e8e 100644 --- a/gcc/c/c-tree.h +++ b/gcc/c/c-tree.h @@ -164,12 +164,13 @@ struct c_expr } /* Set the value to error_mark_node whilst ensuring that src_range - is initialized. */ + and m_decimal are initialized. */ void set_error () { value = error_mark_node; src_range.m_start = UNKNOWN_LOCATION; src_range.m_finish = UNKNOWN_LOCATION; + m_decimal = 0; } }; diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc index 33d1e84..ac242b5 100644 --- a/gcc/c/c-typeck.cc +++ b/gcc/c/c-typeck.cc @@ -2994,6 +2994,7 @@ c_expr_sizeof_expr (location_t loc, struct c_expr expr) ret.value = error_mark_node; ret.original_code = ERROR_MARK; ret.original_type = NULL; + ret.m_decimal = 0; pop_maybe_used (false); } else @@ -3017,6 +3018,7 @@ c_expr_sizeof_expr (location_t loc, struct c_expr expr) c_last_sizeof_loc = loc; ret.original_code = SIZEOF_EXPR; ret.original_type = NULL; + ret.m_decimal = 0; if (C_TYPE_VARIABLE_SIZE (TREE_TYPE (folded_expr))) { /* sizeof is evaluated when given a vla (C99 6.5.3.4p2). */ @@ -3047,6 +3049,7 @@ c_expr_sizeof_type (location_t loc, struct c_type_name *t) c_last_sizeof_loc = loc; ret.original_code = SIZEOF_EXPR; ret.original_type = NULL; + ret.m_decimal = 0; if (type == error_mark_node) { ret.value = error_mark_node; @@ -3782,6 +3785,7 @@ parser_build_unary_op (location_t loc, enum tree_code code, struct c_expr arg) result.original_code = code; result.original_type = NULL; + result.m_decimal = 0; if (reject_gcc_builtin (arg.value)) { @@ -3844,6 +3848,7 @@ parser_build_binary_op (location_t location, enum tree_code code, arg1.value, arg2.value, true); result.original_code = code; result.original_type = NULL; + result.m_decimal = 0; if (TREE_CODE (result.value) == ERROR_MARK) { @@ -8072,6 +8077,7 @@ digest_init (location_t init_loc, tree type, tree init, tree origtype, expr.value = inside_init; expr.original_code = (strict_string ? STRING_CST : ERROR_MARK); expr.original_type = NULL; + expr.m_decimal = 0; maybe_warn_string_init (init_loc, type, expr); if (TYPE_DOMAIN (type) && !TYPE_MAX_VALUE (TYPE_DOMAIN (type))) @@ -8936,6 +8942,7 @@ pop_init_level (location_t loc, int implicit, ret.value = NULL_TREE; ret.original_code = ERROR_MARK; ret.original_type = NULL; + ret.m_decimal = 0; if (implicit == 0) { @@ -16044,14 +16051,10 @@ c_tree_equal (tree t1, tree t2) if (!t1 || !t2) return false; - for (code1 = TREE_CODE (t1); - CONVERT_EXPR_CODE_P (code1) - || code1 == NON_LVALUE_EXPR; + for (code1 = TREE_CODE (t1); code1 == NON_LVALUE_EXPR; code1 = TREE_CODE (t1)) t1 = TREE_OPERAND (t1, 0); - for (code2 = TREE_CODE (t2); - CONVERT_EXPR_CODE_P (code2) - || code2 == NON_LVALUE_EXPR; + for (code2 = TREE_CODE (t2); code2 == NON_LVALUE_EXPR; code2 = TREE_CODE (t2)) t2 = TREE_OPERAND (t2, 0); @@ -16062,6 +16065,9 @@ c_tree_equal (tree t1, tree t2) if (code1 != code2) return false; + if (CONSTANT_CLASS_P (t1) && !comptypes (TREE_TYPE (t1), TREE_TYPE (t2))) + return false; + switch (code1) { case INTEGER_CST: @@ -16181,6 +16187,11 @@ c_tree_equal (tree t1, tree t2) return true; } + CASE_CONVERT: + if (!comptypes (TREE_TYPE (t1), TREE_TYPE (t2))) + return false; + break; + default: break; } diff --git a/gcc/c/gimple-parser.cc b/gcc/c/gimple-parser.cc index b909eac..5a2da2c 100644 --- a/gcc/c/gimple-parser.cc +++ b/gcc/c/gimple-parser.cc @@ -1332,6 +1332,7 @@ c_parser_gimple_call_internal (gimple_parser &parser) exprlist.address ()); expr.original_code = ERROR_MARK; expr.original_type = NULL; + expr.m_decimal = 0; } } return expr; @@ -1751,6 +1752,7 @@ c_parser_gimple_postfix_expression_after_primary (gimple_parser &parser, finish = c_parser_tokens_buf (parser, 0)->location; expr.value = build_array_ref (op_loc, expr.value, idx); set_c_expr_source_range (&expr, start, finish); + expr.m_decimal = 0; expr.original_code = ERROR_MARK; expr.original_type = NULL; @@ -1774,6 +1776,7 @@ c_parser_gimple_postfix_expression_after_primary (gimple_parser &parser, expr.value = build_call_array_loc (expr_loc, TREE_TYPE (TREE_TYPE (expr.value)), expr.value, exprlist.length (), exprlist.address ()); + expr.m_decimal = 0; expr.original_code = ERROR_MARK; expr.original_type = NULL; break; @@ -1802,6 +1805,7 @@ c_parser_gimple_postfix_expression_after_primary (gimple_parser &parser, expr.value = build_component_ref (op_loc, expr.value, ident, comp_loc, UNKNOWN_LOCATION); set_c_expr_source_range (&expr, start, finish); + expr.m_decimal = 0; expr.original_code = ERROR_MARK; if (TREE_CODE (expr.value) != COMPONENT_REF) expr.original_type = NULL; @@ -1851,6 +1855,7 @@ c_parser_gimple_postfix_expression_after_primary (gimple_parser &parser, ident, comp_loc, expr.get_location ()); set_c_expr_source_range (&expr, start, finish); + expr.m_decimal = 0; expr.original_code = ERROR_MARK; if (TREE_CODE (expr.value) != COMPONENT_REF) expr.original_type = NULL; diff --git a/gcc/cfgcleanup.cc b/gcc/cfgcleanup.cc index a8b0139..a363e0b 100644 --- a/gcc/cfgcleanup.cc +++ b/gcc/cfgcleanup.cc @@ -2599,7 +2599,7 @@ trivially_empty_bb_p (basic_block bb) return value. Fill in *RET and *USE with the return and use insns if any found, otherwise NULL. All CLOBBERs are ignored. */ -static bool +bool bb_is_just_return (basic_block bb, rtx_insn **ret, rtx_insn **use) { *ret = *use = NULL; diff --git a/gcc/cfgcleanup.h b/gcc/cfgcleanup.h index a6d882f..f1021ca 100644 --- a/gcc/cfgcleanup.h +++ b/gcc/cfgcleanup.h @@ -30,5 +30,6 @@ extern int flow_find_head_matching_sequence (basic_block, basic_block, extern bool delete_unreachable_blocks (void); extern void delete_dead_jumptables (void); extern bool cleanup_cfg (int); +extern bool bb_is_just_return (basic_block, rtx_insn **, rtx_insn **); #endif /* GCC_CFGCLEANUP_H */ diff --git a/gcc/cfgrtl.cc b/gcc/cfgrtl.cc index a05c338..90cd6ee 100644 --- a/gcc/cfgrtl.cc +++ b/gcc/cfgrtl.cc @@ -3901,6 +3901,7 @@ fixup_reorder_chain (void) /* Now add jumps and labels as needed to match the blocks new outgoing edges. */ + bool remove_unreachable_blocks = false; for (bb = ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb; bb ; bb = (basic_block) bb->aux) { @@ -4043,10 +4044,30 @@ fixup_reorder_chain (void) continue; } + /* If E_FALL->dest is just a return block, then we can emit a + return rather than a jump to the return block. */ + rtx_insn *ret, *use; + basic_block dest; + if (bb_is_just_return (e_fall->dest, &ret, &use) + && (PATTERN (ret) == simple_return_rtx || PATTERN (ret) == ret_rtx)) + { + ret_label = PATTERN (ret); + dest = EXIT_BLOCK_PTR_FOR_FN (cfun); + + /* E_FALL->dest might become unreachable as a result of + replacing the jump with a return. So arrange to remove + unreachable blocks. */ + remove_unreachable_blocks = true; + } + else + { + dest = e_fall->dest; + } + /* We got here if we need to add a new jump insn. Note force_nonfallthru can delete E_FALL and thus we have to save E_FALL->src prior to the call to force_nonfallthru. */ - nb = force_nonfallthru_and_redirect (e_fall, e_fall->dest, ret_label); + nb = force_nonfallthru_and_redirect (e_fall, dest, ret_label); if (nb) { nb->aux = bb->aux; @@ -4134,6 +4155,12 @@ fixup_reorder_chain (void) ei_next (&ei2); } } + + /* Replacing a jump with a return may have exposed an unreachable + block. Conditionally remove them if such transformations were + made. */ + if (remove_unreachable_blocks) + delete_unreachable_blocks (); } /* Perform sanity checks on the insn chain. diff --git a/gcc/common.opt b/gcc/common.opt index 06ef768..296d6f1 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -2106,7 +2106,7 @@ Specify the algorithm to partition symbols and vars at linktime. ; The initial value of -1 comes from Z_DEFAULT_COMPRESSION in zlib.h. flto-compression-level= Common Joined RejectNegative UInteger Var(flag_lto_compression_level) Init(-1) IntegerRange(0, 19) --flto-compression-level=<number> Use zlib/zstd compression level <number> for IL. +Use zlib/zstd compression level <number> for IL. flto-odr-type-merging Common Ignore diff --git a/gcc/common/config/riscv/riscv-common.cc b/gcc/common/config/riscv/riscv-common.cc index 7721916..c39ed2e 100644 --- a/gcc/common/config/riscv/riscv-common.cc +++ b/gcc/common/config/riscv/riscv-common.cc @@ -1224,7 +1224,7 @@ static const riscv_ext_flag_table_t riscv_ext_flag_table[] = /* Parse a RISC-V ISA string into an option mask. Must clear or set all arch dependent mask bits, in case more than one -march string is passed. */ -static void +void riscv_parse_arch_string (const char *isa, struct gcc_options *opts, location_t loc) diff --git a/gcc/config.gcc b/gcc/config.gcc index f4e757b..c1b1215 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -515,7 +515,7 @@ pru-*-*) ;; riscv*) cpu_type=riscv - extra_objs="riscv-builtins.o riscv-c.o riscv-sr.o riscv-shorten-memrefs.o" + extra_objs="riscv-builtins.o riscv-c.o riscv-sr.o riscv-shorten-memrefs.o riscv-selftests.o" d_target_objs="riscv-d.o" ;; rs6000*-*-*) @@ -3941,6 +3941,9 @@ if test x$with_arch = x ; then mips*-*-vxworks) with_arch=mips2 ;; + nvptx-*) + with_arch=sm_30 + ;; esac # Avoid overriding --with-arch-32 and --with-arch-64 values. @@ -5293,6 +5296,25 @@ case "${target}" in esac ;; + nvptx-*) + supported_defaults=arch + TM_MULTILIB_CONFIG=$with_arch + #TODO 'sm_[...]' list per 'nvptx-sm.def'. + case $with_arch in + sm_30 ) + # OK; default. + ;; + sm_35 | sm_53 | sm_70 | sm_75 | sm_80 ) + # OK, but we'd like 'sm_30', too. + TM_MULTILIB_CONFIG="$TM_MULTILIB_CONFIG sm_30" + ;; + * ) + echo "Unknown arch used in --with-arch=$with_arch" 1>&2 + exit 1 + ;; + esac + ;; + powerpc*-*-* | rs6000-*-*) supported_defaults="abi cpu cpu_32 cpu_64 float tune tune_32 tune_64 advance_toolchain" diff --git a/gcc/config/aarch64/aarch64-arches.def b/gcc/config/aarch64/aarch64-arches.def index 3c2b165..6150448 100644 --- a/gcc/config/aarch64/aarch64-arches.def +++ b/gcc/config/aarch64/aarch64-arches.def @@ -41,5 +41,8 @@ AARCH64_ARCH("armv8.7-a", generic, 8_7A, 8, AARCH64_FL_FOR_ARCH8 AARCH64_ARCH("armv8.8-a", generic, 8_8A, 8, AARCH64_FL_FOR_ARCH8_8) AARCH64_ARCH("armv8-r", generic, 8R , 8, AARCH64_FL_FOR_ARCH8_R) AARCH64_ARCH("armv9-a", generic, 9A , 9, AARCH64_FL_FOR_ARCH9) +AARCH64_ARCH("armv9.1-a", generic, 9_1A, 9, AARCH64_FL_FOR_ARCH9_1) +AARCH64_ARCH("armv9.2-a", generic, 9_2A, 9, AARCH64_FL_FOR_ARCH9_2) +AARCH64_ARCH("armv9.3-a", generic, 9_3A, 9, AARCH64_FL_FOR_ARCH9_3) #undef AARCH64_ARCH diff --git a/gcc/config/aarch64/aarch64-cores.def b/gcc/config/aarch64/aarch64-cores.def index 41d9535..0402bfb 100644 --- a/gcc/config/aarch64/aarch64-cores.def +++ b/gcc/config/aarch64/aarch64-cores.def @@ -171,6 +171,7 @@ AARCH64_CORE("cortex-x2", cortexx2, cortexa57, 9A, AARCH64_FL_FOR_ARCH9 | AARC AARCH64_CORE("neoverse-n2", neoversen2, cortexa57, 9A, AARCH64_FL_FOR_ARCH9 | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_SVE2_BITPERM | AARCH64_FL_RNG | AARCH64_FL_MEMTAG | AARCH64_FL_PROFILE, neoversen2, 0x41, 0xd49, -1) -AARCH64_CORE("demeter", demeter, cortexa57, 9A, AARCH64_FL_FOR_ARCH9 | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_SVE2_BITPERM | AARCH64_FL_RNG | AARCH64_FL_MEMTAG | AARCH64_FL_PROFILE, demeter, 0x41, 0xd4f, -1) +AARCH64_CORE("demeter", demeter, cortexa57, 9A, AARCH64_FL_FOR_ARCH9 | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_SVE2_BITPERM | AARCH64_FL_RNG | AARCH64_FL_MEMTAG | AARCH64_FL_PROFILE, neoversev2, 0x41, 0xd4f, -1) +AARCH64_CORE("neoverse-v2", neoversev2, cortexa57, 9A, AARCH64_FL_FOR_ARCH9 | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_SVE2_BITPERM | AARCH64_FL_RNG | AARCH64_FL_MEMTAG | AARCH64_FL_PROFILE, neoversev2, 0x41, 0xd4f, -1) #undef AARCH64_CORE diff --git a/gcc/config/aarch64/aarch64-tune.md b/gcc/config/aarch64/aarch64-tune.md index 27da961..84e9bbf 100644 --- a/gcc/config/aarch64/aarch64-tune.md +++ b/gcc/config/aarch64/aarch64-tune.md @@ -1,5 +1,5 @@ ;; -*- buffer-read-only: t -*- ;; Generated automatically by gentune.sh from aarch64-cores.def (define_attr "tune" - "cortexa34,cortexa35,cortexa53,cortexa57,cortexa72,cortexa73,thunderx,thunderxt88p1,thunderxt88,octeontx,octeontxt81,octeontxt83,thunderxt81,thunderxt83,ampere1,emag,xgene1,falkor,qdf24xx,exynosm1,phecda,thunderx2t99p1,vulcan,thunderx2t99,cortexa55,cortexa75,cortexa76,cortexa76ae,cortexa77,cortexa78,cortexa78ae,cortexa78c,cortexa65,cortexa65ae,cortexx1,ares,neoversen1,neoversee1,octeontx2,octeontx2t98,octeontx2t96,octeontx2t93,octeontx2f95,octeontx2f95n,octeontx2f95mm,a64fx,tsv110,thunderx3t110,zeus,neoversev1,neoverse512tvb,saphira,cortexa57cortexa53,cortexa72cortexa53,cortexa73cortexa35,cortexa73cortexa53,cortexa75cortexa55,cortexa76cortexa55,cortexr82,cortexa510,cortexa710,cortexx2,neoversen2,demeter" + "cortexa34,cortexa35,cortexa53,cortexa57,cortexa72,cortexa73,thunderx,thunderxt88p1,thunderxt88,octeontx,octeontxt81,octeontxt83,thunderxt81,thunderxt83,ampere1,emag,xgene1,falkor,qdf24xx,exynosm1,phecda,thunderx2t99p1,vulcan,thunderx2t99,cortexa55,cortexa75,cortexa76,cortexa76ae,cortexa77,cortexa78,cortexa78ae,cortexa78c,cortexa65,cortexa65ae,cortexx1,ares,neoversen1,neoversee1,octeontx2,octeontx2t98,octeontx2t96,octeontx2t93,octeontx2f95,octeontx2f95n,octeontx2f95mm,a64fx,tsv110,thunderx3t110,zeus,neoversev1,neoverse512tvb,saphira,cortexa57cortexa53,cortexa72cortexa53,cortexa73cortexa35,cortexa73cortexa53,cortexa75cortexa55,cortexa76cortexa55,cortexr82,cortexa510,cortexa710,cortexx2,neoversen2,demeter,neoversev2" (const (symbol_ref "((enum attr_tune) aarch64_tune)"))) diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc index 467979a..b4971bd 100644 --- a/gcc/config/aarch64/aarch64.cc +++ b/gcc/config/aarch64/aarch64.cc @@ -534,7 +534,7 @@ static const struct cpu_addrcost_table neoversen2_addrcost_table = 0 /* imm_offset */ }; -static const struct cpu_addrcost_table demeter_addrcost_table = +static const struct cpu_addrcost_table neoversev2_addrcost_table = { { 1, /* hi */ @@ -677,7 +677,7 @@ static const struct cpu_regmove_cost neoversev1_regmove_cost = 2 /* FP2FP */ }; -static const struct cpu_regmove_cost demeter_regmove_cost = +static const struct cpu_regmove_cost neoversev2_regmove_cost = { 1, /* GP2GP */ /* Spilling to int<->fp instead of memory is recommended so set @@ -2426,7 +2426,7 @@ static const struct tune_params neoversen2_tunings = &generic_prefetch_tune }; -static const advsimd_vec_cost demeter_advsimd_vector_cost = +static const advsimd_vec_cost neoversev2_advsimd_vector_cost = { 2, /* int_stmt_cost */ 2, /* fp_stmt_cost */ @@ -2457,7 +2457,7 @@ static const advsimd_vec_cost demeter_advsimd_vector_cost = 1 /* store_cost */ }; -static const sve_vec_cost demeter_sve_vector_cost = +static const sve_vec_cost neoversev2_sve_vector_cost = { { 2, /* int_stmt_cost */ @@ -2514,7 +2514,7 @@ static const sve_vec_cost demeter_sve_vector_cost = 3 /* scatter_store_elt_cost */ }; -static const aarch64_scalar_vec_issue_info demeter_scalar_issue_info = +static const aarch64_scalar_vec_issue_info neoversev2_scalar_issue_info = { 3, /* loads_stores_per_cycle */ 2, /* stores_per_cycle */ @@ -2523,7 +2523,7 @@ static const aarch64_scalar_vec_issue_info demeter_scalar_issue_info = 1 /* fp_simd_store_general_ops */ }; -static const aarch64_advsimd_vec_issue_info demeter_advsimd_issue_info = +static const aarch64_advsimd_vec_issue_info neoversev2_advsimd_issue_info = { { 3, /* loads_stores_per_cycle */ @@ -2537,7 +2537,7 @@ static const aarch64_advsimd_vec_issue_info demeter_advsimd_issue_info = 3 /* ld4_st4_general_ops */ }; -static const aarch64_sve_vec_issue_info demeter_sve_issue_info = +static const aarch64_sve_vec_issue_info neoversev2_sve_issue_info = { { { @@ -2559,15 +2559,15 @@ static const aarch64_sve_vec_issue_info demeter_sve_issue_info = 1 /* gather_scatter_pair_pred_ops */ }; -static const aarch64_vec_issue_info demeter_vec_issue_info = +static const aarch64_vec_issue_info neoversev2_vec_issue_info = { - &demeter_scalar_issue_info, - &demeter_advsimd_issue_info, - &demeter_sve_issue_info + &neoversev2_scalar_issue_info, + &neoversev2_advsimd_issue_info, + &neoversev2_sve_issue_info }; /* Demeter costs for vector insn classes. */ -static const struct cpu_vector_cost demeter_vector_cost = +static const struct cpu_vector_cost neoversev2_vector_cost = { 1, /* scalar_int_stmt_cost */ 2, /* scalar_fp_stmt_cost */ @@ -2575,17 +2575,17 @@ static const struct cpu_vector_cost demeter_vector_cost = 1, /* scalar_store_cost */ 1, /* cond_taken_branch_cost */ 1, /* cond_not_taken_branch_cost */ - &demeter_advsimd_vector_cost, /* advsimd */ - &demeter_sve_vector_cost, /* sve */ - &demeter_vec_issue_info /* issue_info */ + &neoversev2_advsimd_vector_cost, /* advsimd */ + &neoversev2_sve_vector_cost, /* sve */ + &neoversev2_vec_issue_info /* issue_info */ }; -static const struct tune_params demeter_tunings = +static const struct tune_params neoversev2_tunings = { &cortexa76_extra_costs, - &demeter_addrcost_table, - &demeter_regmove_cost, - &demeter_vector_cost, + &neoversev2_addrcost_table, + &neoversev2_regmove_cost, + &neoversev2_vector_cost, &generic_branch_cost, &generic_approx_modes, SVE_128, /* sve_width */ @@ -15566,7 +15566,7 @@ aarch64_vec_op_count::rename_cycles_per_iter () const { if (sve_issue_info () == &neoverse512tvb_sve_issue_info || sve_issue_info () == &neoversen2_sve_issue_info - || sve_issue_info () == &demeter_sve_issue_info) + || sve_issue_info () == &neoversev2_sve_issue_info) /* + 1 for an addition. We've already counted a general op for each store, so we don't need to account for stores separately. The branch reads no registers and so does not need to be counted either. diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h index 2eed6e8..f790de1 100644 --- a/gcc/config/aarch64/aarch64.h +++ b/gcc/config/aarch64/aarch64.h @@ -239,6 +239,15 @@ /* Armv8.8-a architecture extensions. */ #define AARCH64_FL_V8_8 (1ULL << 45) +/* Armv9.1-A. */ +#define AARCH64_FL_V9_1 (1ULL << 46) + +/* Armv9.2-A. */ +#define AARCH64_FL_V9_2 (1ULL << 47) + +/* Armv9.3-A. */ +#define AARCH64_FL_V9_3 (1ULL << 48) + /* Has FP and SIMD. */ #define AARCH64_FL_FPSIMD (AARCH64_FL_FP | AARCH64_FL_SIMD) @@ -273,6 +282,12 @@ #define AARCH64_FL_FOR_ARCH9 \ (AARCH64_FL_FOR_ARCH8_5 | AARCH64_FL_SVE | AARCH64_FL_SVE2 | AARCH64_FL_V9 \ | AARCH64_FL_F16) +#define AARCH64_FL_FOR_ARCH9_1 \ + (AARCH64_FL_FOR_ARCH9 | AARCH64_FL_FOR_ARCH8_6 | AARCH64_FL_V9_1) +#define AARCH64_FL_FOR_ARCH9_2 \ + (AARCH64_FL_FOR_ARCH9_1 | AARCH64_FL_FOR_ARCH8_7 | AARCH64_FL_V9_2) +#define AARCH64_FL_FOR_ARCH9_3 \ + (AARCH64_FL_FOR_ARCH9_2 | AARCH64_FL_FOR_ARCH8_8 | AARCH64_FL_V9_3) /* Macros to test ISA flags. */ @@ -312,6 +327,9 @@ #define AARCH64_ISA_V8_R (aarch64_isa_flags & AARCH64_FL_V8_R) #define AARCH64_ISA_PAUTH (aarch64_isa_flags & AARCH64_FL_PAUTH) #define AARCH64_ISA_V9 (aarch64_isa_flags & AARCH64_FL_V9) +#define AARCH64_ISA_V9_1 (aarch64_isa_flags & AARCH64_FL_V9_1) +#define AARCH64_ISA_V9_2 (aarch64_isa_flags & AARCH64_FL_V9_2) +#define AARCH64_ISA_V9_3 (aarch64_isa_flags & AARCH64_FL_V9_3) #define AARCH64_ISA_MOPS (aarch64_isa_flags & AARCH64_FL_MOPS) #define AARCH64_ISA_LS64 (aarch64_isa_flags & AARCH64_FL_LS64) @@ -1260,14 +1278,44 @@ extern enum aarch64_code_model aarch64_cmodel; #define ENDIAN_LANE_N(NUNITS, N) \ (BYTES_BIG_ENDIAN ? NUNITS - 1 - N : N) +/* Extra specs when building a native AArch64-hosted compiler. + Option rewriting rules based on host system. */ +#if defined(__aarch64__) +extern const char *host_detect_local_cpu (int argc, const char **argv); +#define HAVE_LOCAL_CPU_DETECT +# define EXTRA_SPEC_FUNCTIONS \ + { "local_cpu_detect", host_detect_local_cpu }, \ + MCPU_TO_MARCH_SPEC_FUNCTIONS + +/* Rewrite -m{arch,cpu,tune}=native based on the host system information. + When rewriting -march=native convert it into an -mcpu option if no other + -mcpu or -mtune was given. */ +# define MCPU_MTUNE_NATIVE_SPECS \ + " %{march=native:%<march=native %:local_cpu_detect(%{mcpu=*|mtune=*:arch;:cpu})}" \ + " %{mcpu=native:%<mcpu=native %:local_cpu_detect(cpu)}" \ + " %{mtune=native:%<mtune=native %:local_cpu_detect(tune)}" +/* This will be used in OPTION_DEFAULT_SPECS below. + When GCC is configured with --with-tune we don't want to materialize an + implicit -mtune would prevent the rewriting of -march=native into + -mcpu=native as per the above rules. */ +#define CONFIG_TUNE_SPEC \ + { "tune", "%{!mcpu=*:%{!mtune=*:%{!march=native:-mtune=%(VALUE)}}}" }, +#else +# define MCPU_MTUNE_NATIVE_SPECS "" +# define EXTRA_SPEC_FUNCTIONS MCPU_TO_MARCH_SPEC_FUNCTIONS +# define CONFIG_TUNE_SPEC \ + {"tune", "%{!mcpu=*:%{!mtune=*:-mtune=%(VALUE)}}"}, +#endif + /* Support for configure-time --with-arch, --with-cpu and --with-tune. --with-arch and --with-cpu are ignored if either -mcpu or -march is used. --with-tune is ignored if either -mtune or -mcpu is used (but is not - affected by -march). */ + affected by -march, except in the -march=native case as per the + CONFIG_TUNE_SPEC above). */ #define OPTION_DEFAULT_SPECS \ {"arch", "%{!march=*:%{!mcpu=*:-march=%(VALUE)}}" }, \ {"cpu", "%{!march=*:%{!mcpu=*:-mcpu=%(VALUE)}}" }, \ - {"tune", "%{!mcpu=*:%{!mtune=*:-mtune=%(VALUE)}}"}, + CONFIG_TUNE_SPEC #define MCPU_TO_MARCH_SPEC \ " %{mcpu=*:-march=%:rewrite_mcpu(%{mcpu=*:%*})}" @@ -1276,22 +1324,6 @@ extern const char *aarch64_rewrite_mcpu (int argc, const char **argv); #define MCPU_TO_MARCH_SPEC_FUNCTIONS \ { "rewrite_mcpu", aarch64_rewrite_mcpu }, -#if defined(__aarch64__) -extern const char *host_detect_local_cpu (int argc, const char **argv); -#define HAVE_LOCAL_CPU_DETECT -# define EXTRA_SPEC_FUNCTIONS \ - { "local_cpu_detect", host_detect_local_cpu }, \ - MCPU_TO_MARCH_SPEC_FUNCTIONS - -# define MCPU_MTUNE_NATIVE_SPECS \ - " %{march=native:%<march=native %:local_cpu_detect(arch)}" \ - " %{mcpu=native:%<mcpu=native %:local_cpu_detect(cpu)}" \ - " %{mtune=native:%<mtune=native %:local_cpu_detect(tune)}" -#else -# define MCPU_MTUNE_NATIVE_SPECS "" -# define EXTRA_SPEC_FUNCTIONS MCPU_TO_MARCH_SPEC_FUNCTIONS -#endif - #define ASM_CPU_SPEC \ MCPU_TO_MARCH_SPEC diff --git a/gcc/config/i386/constraints.md b/gcc/config/i386/constraints.md index 7361687..95b2b14 100644 --- a/gcc/config/i386/constraints.md +++ b/gcc/config/i386/constraints.md @@ -168,6 +168,9 @@ ;; z Constant call address operand. ;; C Integer SSE constant with all bits set operand. ;; F Floating-point SSE constant with all bits set operand. +;; H Integer SSE constant that is 128/256bit all ones +;; and zero-extand to 256/512bit, or 128bit all ones +;; and zero-extend to 512bit. ;; M x86-64 memory operand. (define_constraint "Bf" @@ -233,6 +236,11 @@ (and (match_test "TARGET_SSE") (match_operand 0 "float_vector_all_ones_operand"))) +(define_constraint "BH" + "@internal integer constant with last half/quarter bits set operand." + (ior (match_operand 0 "vector_all_ones_zero_extend_half_operand") + (match_operand 0 "vector_all_ones_zero_extend_quarter_operand"))) + ;; NB: Similar to 'm', but don't use define_memory_constraint on x86-64 ;; to prevent LRA from converting the operand to the form '(mem (reg X))' ;; where X is a base register. diff --git a/gcc/config/i386/i386-expand.cc b/gcc/config/i386/i386-expand.cc index 5334363..6baff6d 100644 --- a/gcc/config/i386/i386-expand.cc +++ b/gcc/config/i386/i386-expand.cc @@ -19604,6 +19604,119 @@ expand_vec_perm_1 (struct expand_vec_perm_d *d) return false; } +/* A subroutine of ix86_expand_vec_perm_const_1. Try to implement D + in terms of a pair of shufps+ shufps/pshufd instructions. */ +static bool +expand_vec_perm_shufps_shufps (struct expand_vec_perm_d *d) +{ + unsigned char perm1[4]; + machine_mode vmode = d->vmode; + bool ok; + unsigned i, j, k, count = 0; + + if (d->one_operand_p + || (vmode != V4SImode && vmode != V4SFmode)) + return false; + + if (d->testing_p) + return true; + + for (i = 0; i < 4; ++i) + count += d->perm[i] > 3 ? 1 : 0; + + gcc_assert (count & 3); + + rtx tmp = gen_reg_rtx (vmode); + /* 2 from op0 and 2 from op1. */ + if (count == 2) + { + unsigned char perm2[4]; + for (i = 0, j = 0, k = 2; i < 4; ++i) + if (d->perm[i] & 4) + { + perm1[k++] = d->perm[i]; + perm2[i] = k - 1; + } + else + { + perm1[j++] = d->perm[i]; + perm2[i] = j - 1; + } + + /* shufps. */ + ok = expand_vselect_vconcat (tmp, d->op0, d->op1, + perm1, d->nelt, false); + gcc_assert (ok); + if (vmode == V4SImode && TARGET_SSE2) + /* pshufd. */ + ok = expand_vselect (d->target, tmp, + perm2, d->nelt, false); + else + { + /* shufps. */ + perm2[2] += 4; + perm2[3] += 4; + ok = expand_vselect_vconcat (d->target, tmp, tmp, + perm2, d->nelt, false); + } + gcc_assert (ok); + } + /* 3 from one op and 1 from another. */ + else + { + unsigned pair_idx = 8, lone_idx = 8, shift; + + /* Find the lone index. */ + for (i = 0; i < 4; ++i) + if ((d->perm[i] > 3 && count == 1) + || (d->perm[i] < 4 && count == 3)) + lone_idx = i; + + /* When lone_idx is not 0, it must from second op(count == 1). */ + gcc_assert (count == (lone_idx ? 1 : 3)); + + /* Find the pair index that sits in the same half as the lone index. */ + shift = lone_idx & 2; + pair_idx = 1 - lone_idx + 2 * shift; + + /* First permutate lone index and pair index into the same vector as + [ lone, lone, pair, pair ]. */ + perm1[1] = perm1[0] + = (count == 3) ? d->perm[lone_idx] : d->perm[lone_idx] - 4; + perm1[3] = perm1[2] + = (count == 3) ? d->perm[pair_idx] : d->perm[pair_idx] + 4; + + /* Alway put the vector contains lone indx at the first. */ + if (count == 1) + std::swap (d->op0, d->op1); + + /* shufps. */ + ok = expand_vselect_vconcat (tmp, d->op0, d->op1, + perm1, d->nelt, false); + gcc_assert (ok); + + /* Refine lone and pair index to original order. */ + perm1[shift] = lone_idx << 1; + perm1[shift + 1] = pair_idx << 1; + + /* Select the remaining 2 elements in another vector. */ + for (i = 2 - shift; i < 4 - shift; ++i) + perm1[i] = lone_idx == 1 ? d->perm[i] + 4 : d->perm[i]; + + /* Adjust to original selector. */ + if (lone_idx > 1) + std::swap (tmp, d->op1); + + /* shufps. */ + ok = expand_vselect_vconcat (d->target, tmp, d->op1, + perm1, d->nelt, false); + + gcc_assert (ok); + } + + return true; +} + /* A subroutine of ix86_expand_vec_perm_const_1. Try to implement D in terms of a pair of pshuflw + pshufhw instructions. */ @@ -22152,6 +22265,9 @@ ix86_expand_vec_perm_const_1 (struct expand_vec_perm_d *d) if (expand_vec_perm_2perm_pblendv (d, true)) return true; + if (expand_vec_perm_shufps_shufps (d)) + return true; + /* Try sequences of three instructions. */ if (expand_vec_perm_even_odd_pack (d)) diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc index dadf453..ca799da 100644 --- a/gcc/config/i386/i386.cc +++ b/gcc/config/i386/i386.cc @@ -5186,7 +5186,8 @@ standard_80387_constant_rtx (int idx) XFmode); } -/* Return 1 if X is all bits 0 and 2 if X is all bits 1 +/* Return 1 if X is all bits 0, 2 if X is all bits 1 + and 3 if X is all bits 1 with zero extend in supported SSE/AVX vector mode. */ int @@ -5234,6 +5235,10 @@ standard_sse_constant_p (rtx x, machine_mode pred_mode) } } + if (vector_all_ones_zero_extend_half_operand (x, mode) + || vector_all_ones_zero_extend_quarter_operand (x, mode)) + return 3; + return 0; } @@ -5341,6 +5346,25 @@ standard_sse_constant_opcode (rtx_insn *insn, rtx *operands) gcc_unreachable (); } } + else if (vector_all_ones_zero_extend_half_operand (x, mode)) + { + if (GET_MODE_SIZE (mode) == 64) + { + gcc_assert (TARGET_AVX512F); + return "vpcmpeqd \t %t0, %t0, %t0"; + } + else if (GET_MODE_SIZE (mode) == 32) + { + gcc_assert (TARGET_AVX); + return "vpcmpeqd \t %x0, %x0, %x0"; + } + gcc_unreachable (); + } + else if (vector_all_ones_zero_extend_quarter_operand (x, mode)) + { + gcc_assert (TARGET_AVX512F); + return "vpcmpeqd \t %x0, %x0, %x0"; + } gcc_unreachable (); } diff --git a/gcc/config/i386/mmx.md b/gcc/config/i386/mmx.md index 222a041..c359e2d 100644 --- a/gcc/config/i386/mmx.md +++ b/gcc/config/i386/mmx.md @@ -1676,7 +1676,7 @@ (define_expand "floorv2sf2" [(set (match_operand:V2SF 0 "register_operand") (unspec:V2SF - [(match_operand:V2SF 1 "vector_operand") + [(match_operand:V2SF 1 "register_operand") (match_dup 2)] UNSPEC_ROUND))] "TARGET_SSE4_1 && !flag_trapping_math diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md index 4f16bb7..655eabf 100644 --- a/gcc/config/i386/predicates.md +++ b/gcc/config/i386/predicates.md @@ -1159,6 +1159,55 @@ (match_test "INTEGRAL_MODE_P (GET_MODE (op))") (match_test "op == CONSTM1_RTX (GET_MODE (op))"))) +/* Return true if operand is an 128/256bit all ones vector + that zero-extends to 256/512bit. */ +(define_predicate "vector_all_ones_zero_extend_half_operand" + (match_code "const_vector") +{ + mode = GET_MODE (op); + if (GET_MODE_CLASS (mode) != MODE_VECTOR_INT + || (GET_MODE_SIZE (mode) != 32 + && GET_MODE_SIZE (mode) != 64)) + return false; + + int nelts = CONST_VECTOR_NUNITS (op); + for (int i = 0; i != nelts; i++) + { + rtx elt = CONST_VECTOR_ELT (op, i); + if (i < nelts / 2 + && elt != CONSTM1_RTX (GET_MODE_INNER (mode))) + return false; + if (i >= nelts / 2 + && elt != CONST0_RTX (GET_MODE_INNER (mode))) + return false; + } + return true; +}) + +/* Return true if operand is an 128bit all ones vector + that zero extends to 512bit. */ +(define_predicate "vector_all_ones_zero_extend_quarter_operand" + (match_code "const_vector") +{ + mode = GET_MODE (op); + if (GET_MODE_CLASS (mode) != MODE_VECTOR_INT + || GET_MODE_SIZE (mode) != 64) + return false; + + int nelts = CONST_VECTOR_NUNITS (op); + for (int i = 0; i != nelts; i++) + { + rtx elt = CONST_VECTOR_ELT (op, i); + if (i < nelts / 4 + && elt != CONSTM1_RTX (GET_MODE_INNER (mode))) + return false; + if (i >= nelts / 4 + && elt != CONST0_RTX (GET_MODE_INNER (mode))) + return false; + } + return true; +}) + ; Return true when OP is operand acceptable for vector memory operand. ; Only AVX can have misaligned memory operand. (define_predicate "vector_memory_operand" diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md index b60c0d3..5c18963 100644 --- a/gcc/config/i386/sse.md +++ b/gcc/config/i386/sse.md @@ -1323,9 +1323,9 @@ (define_insn "mov<mode>_internal" [(set (match_operand:VMOVE 0 "nonimmediate_operand" - "=v,v ,v ,m") + "=v,v ,v,v ,m") (match_operand:VMOVE 1 "nonimmediate_or_sse_const_operand" - " C,<sseconstm1>,vm,v"))] + " C,<sseconstm1>,BH,vm,v"))] "TARGET_SSE && (register_operand (operands[0], <MODE>mode) || register_operand (operands[1], <MODE>mode)) @@ -1343,7 +1343,7 @@ gcc_unreachable (); } } - [(set_attr "type" "sselog1,sselog1,ssemov,ssemov") + [(set_attr "type" "sselog1,sselog1,sselog1,ssemov,ssemov") (set_attr "prefix" "maybe_vex") (set (attr "mode") (cond [(match_test "TARGET_AVX") @@ -1354,7 +1354,7 @@ (and (match_test "<MODE>mode == V2DFmode") (match_test "TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL")) (const_string "V4SF") - (and (eq_attr "alternative" "3") + (and (eq_attr "alternative" "4") (match_test "TARGET_SSE_TYPELESS_STORES")) (const_string "V4SF") (and (eq_attr "alternative" "0") diff --git a/gcc/config/nvptx/gen-multilib-matches.sh b/gcc/config/nvptx/gen-multilib-matches.sh new file mode 100755 index 0000000..9a5878e --- /dev/null +++ b/gcc/config/nvptx/gen-multilib-matches.sh @@ -0,0 +1,60 @@ +#!/bin/sh + +# Print nvptx 'MULTILIB_MATCHES' + +# Copyright (C) 2022 Free Software Foundation, Inc. +# +# This file is part of GCC. +# +# GCC is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GCC is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# <http://www.gnu.org/licenses/>. + +set -e + +nvptx_sm_def="$1/nvptx-sm.def" +multilib_options_isa_default=$2 +multilib_options_isa_list=$3 + +sms=$(grep ^NVPTX_SM $nvptx_sm_def | sed 's/.*(//;s/,.*//') + +# Every variant in 'sms' has to either be remapped to the default variant +# ('.', which is always built), or does get built as non-default variant +# ('misa=sm_SM'; thus not remapped), or has to be remapped to the "next lower" +# variant that does get built. + +# The "lowest" variant has to be built. +sm_next_lower=INVALID + +for sm in $sms; do + if [ x"sm_$sm" = x"$multilib_options_isa_default" ]; then + sm_map=. + elif expr " $multilib_options_isa_list " : ".* sm_$sm " > /dev/null; then + sm_map= + else + sm_map=$sm_next_lower + fi + + if [ x"$sm_map" = x ]; then + sm_next_lower=$sm + else + # Output format as required for 'MULTILIB_MATCHES'. + if [ x"$sm_map" = x. ]; then + echo ".=misa?sm_$sm" + else + echo "misa?sm_$sm_map=misa?sm_$sm" + fi + + sm_next_lower=$sm_map + fi +done diff --git a/gcc/config/nvptx/nvptx.cc b/gcc/config/nvptx/nvptx.cc index 49cc681..2fe120b 100644 --- a/gcc/config/nvptx/nvptx.cc +++ b/gcc/config/nvptx/nvptx.cc @@ -334,6 +334,10 @@ nvptx_option_override (void) { init_machine_status = nvptx_init_machine_status; + /* Via nvptx 'OPTION_DEFAULT_SPECS', '-misa' always appears on the command + line. */ + gcc_checking_assert (OPTION_SET_P (ptx_isa_option)); + handle_ptx_version_option (); /* Set toplevel_reorder, unless explicitly disabled. We need diff --git a/gcc/config/nvptx/nvptx.h b/gcc/config/nvptx/nvptx.h index dc9cad1..0afc83b 100644 --- a/gcc/config/nvptx/nvptx.h +++ b/gcc/config/nvptx/nvptx.h @@ -27,6 +27,14 @@ /* Run-time Target. */ +/* Use '--with-arch' for default '-misa'. */ +#define OPTION_DEFAULT_SPECS \ + { "arch", "%{!misa=*:-misa=%(VALUE)}" }, \ + +/* Assembler supports '-v' option; handle similar to + '../../gcc.cc:asm_options', 'HAVE_GNU_AS'. */ +#define ASM_SPEC "%{v}" + #define STARTFILE_SPEC "%{mmainkernel:crt0.o}" #define TARGET_CPU_CPP_BUILTINS() nvptx_cpu_cpp_builtins () diff --git a/gcc/config/nvptx/nvptx.opt b/gcc/config/nvptx/nvptx.opt index c5a5668..71d3b68 100644 --- a/gcc/config/nvptx/nvptx.opt +++ b/gcc/config/nvptx/nvptx.opt @@ -53,7 +53,7 @@ Target Mask(GOMP) Generate code for OpenMP offloading: enables -msoft-stack and -muniform-simt. misa= -Target RejectNegative ToLower Joined Enum(ptx_isa) Var(ptx_isa_option) Init(PTX_ISA_SM30) +Target RejectNegative ToLower Joined Enum(ptx_isa) Var(ptx_isa_option) Specify the PTX ISA target architecture to use. march= diff --git a/gcc/config/nvptx/t-nvptx b/gcc/config/nvptx/t-nvptx index 2b68149..9c5cbda 100644 --- a/gcc/config/nvptx/t-nvptx +++ b/gcc/config/nvptx/t-nvptx @@ -31,4 +31,33 @@ s-nvptx-gen-opt: $(srcdir)/config/nvptx/nvptx-sm.def \ tmp-nvptx-gen.opt $(srcdir)/config/nvptx/nvptx-gen.opt $(STAMP) s-nvptx-gen-opt -MULTILIB_OPTIONS = mgomp mptx=3.1 + +# Multilib setup. + +MULTILIB_OPTIONS = +MULTILIB_MATCHES = +MULTILIB_EXCEPTIONS = + +MULTILIB_OPTIONS += mgomp + +multilib_options_isa_list := $(TM_MULTILIB_CONFIG) +multilib_options_isa_default := $(word 1,$(multilib_options_isa_list)) +multilib_options_misa_list := $(addprefix misa=,$(multilib_options_isa_list)) +# Add the requested '-misa' variants as a multilib option ('misa=VAR1/misa=VAR2/misa=VAR3' etc.): +empty := +space := $(empty) $(empty) +MULTILIB_OPTIONS += $(subst $(space),/,$(multilib_options_misa_list)) +# ..., and remap '-misa' variants as appropriate: +multilib_matches := $(shell $(srcdir)/config/nvptx/gen-multilib-matches.sh $(srcdir)/config/nvptx $(multilib_options_isa_default) "$(multilib_options_isa_list)") +MULTILIB_MATCHES += $(multilib_matches) +# ..., and don't actually build what's the default '-misa': +MULTILIB_EXCEPTIONS += *misa=$(multilib_options_isa_default)* + +MULTILIB_OPTIONS += mptx=3.1 +# Filter out invalid '-misa'/'-mptx=3.1' combinations; per 'nvptx-sm.def', +# 'nvptx.opt:ptx_version', 'nvptx.cc:first_ptx_version_supporting_sm' +# (that is, '-mptx=3.1' only for sm_30, sm_35 variants): +MULTILIB_EXCEPTIONS += $(foreach misa,$(filter-out %=sm_30 %=sm_35,$(multilib_options_misa_list)),*$(misa)/mptx=3.1) +# ..., and special care has to be taken if '-mptx=3.1' is invalid for the +# default variant: +MULTILIB_EXCEPTIONS += $(if $(filter-out sm_30 sm_35,$(multilib_options_isa_default)),mgomp/mptx=3.1 mptx=3.1) diff --git a/gcc/config/riscv/predicates.md b/gcc/config/riscv/predicates.md index 862e72b..5e149b3 100644 --- a/gcc/config/riscv/predicates.md +++ b/gcc/config/riscv/predicates.md @@ -146,6 +146,9 @@ case CONST_INT: return !splittable_const_int_operand (op, mode); + case CONST_POLY_INT: + return known_eq (rtx_to_poly_int64 (op), BYTES_PER_RISCV_VECTOR); + case CONST: case SYMBOL_REF: case LABEL_REF: diff --git a/gcc/config/riscv/riscv-modes.def b/gcc/config/riscv/riscv-modes.def index 6e30c1a..95f69e8 100644 --- a/gcc/config/riscv/riscv-modes.def +++ b/gcc/config/riscv/riscv-modes.def @@ -22,6 +22,147 @@ along with GCC; see the file COPYING3. If not see FLOAT_MODE (HF, 2, ieee_half_format); FLOAT_MODE (TF, 16, ieee_quad_format); +/* Vector modes. */ + +/* Encode the ratio of SEW/LMUL into the mask types. There are the following + * mask types. */ + +/* | Mode | MIN_VLEN = 32 | MIN_VLEN = 64 | + | | SEW/LMUL | SEW/LMUL | + | VNx1BI | 32 | 64 | + | VNx2BI | 16 | 32 | + | VNx4BI | 8 | 16 | + | VNx8BI | 4 | 8 | + | VNx16BI | 2 | 4 | + | VNx32BI | 1 | 2 | + | VNx64BI | N/A | 1 | */ + +VECTOR_BOOL_MODE (VNx1BI, 1, BI, 8); +VECTOR_BOOL_MODE (VNx2BI, 2, BI, 8); +VECTOR_BOOL_MODE (VNx4BI, 4, BI, 8); +VECTOR_BOOL_MODE (VNx8BI, 8, BI, 8); +VECTOR_BOOL_MODE (VNx16BI, 16, BI, 8); +VECTOR_BOOL_MODE (VNx32BI, 32, BI, 8); +VECTOR_BOOL_MODE (VNx64BI, 64, BI, 8); + +ADJUST_NUNITS (VNx1BI, riscv_vector_chunks * 1); +ADJUST_NUNITS (VNx2BI, riscv_vector_chunks * 2); +ADJUST_NUNITS (VNx4BI, riscv_vector_chunks * 4); +ADJUST_NUNITS (VNx8BI, riscv_vector_chunks * 8); +ADJUST_NUNITS (VNx16BI, riscv_vector_chunks * 16); +ADJUST_NUNITS (VNx32BI, riscv_vector_chunks * 32); +ADJUST_NUNITS (VNx64BI, riscv_vector_chunks * 64); + +ADJUST_ALIGNMENT (VNx1BI, 1); +ADJUST_ALIGNMENT (VNx2BI, 1); +ADJUST_ALIGNMENT (VNx4BI, 1); +ADJUST_ALIGNMENT (VNx8BI, 1); +ADJUST_ALIGNMENT (VNx16BI, 1); +ADJUST_ALIGNMENT (VNx32BI, 1); +ADJUST_ALIGNMENT (VNx64BI, 1); + +ADJUST_BYTESIZE (VNx1BI, riscv_vector_chunks * riscv_bytes_per_vector_chunk); +ADJUST_BYTESIZE (VNx2BI, riscv_vector_chunks * riscv_bytes_per_vector_chunk); +ADJUST_BYTESIZE (VNx4BI, riscv_vector_chunks * riscv_bytes_per_vector_chunk); +ADJUST_BYTESIZE (VNx8BI, riscv_vector_chunks * riscv_bytes_per_vector_chunk); +ADJUST_BYTESIZE (VNx16BI, riscv_vector_chunks * riscv_bytes_per_vector_chunk); +ADJUST_BYTESIZE (VNx32BI, riscv_vector_chunks * riscv_bytes_per_vector_chunk); +ADJUST_BYTESIZE (VNx64BI, riscv_vector_chunks * riscv_bytes_per_vector_chunk); + +/* + | Mode | MIN_VLEN=32 | MIN_VLEN=32 | MIN_VLEN=64 | MIN_VLEN=64 | + | | LMUL | SEW/LMUL | LMUL | SEW/LMUL | + | VNx1QI | MF4 | 32 | MF8 | 64 | + | VNx2QI | MF2 | 16 | MF4 | 32 | + | VNx4QI | M1 | 8 | MF2 | 16 | + | VNx8QI | M2 | 4 | M1 | 8 | + | VNx16QI | M4 | 2 | M2 | 4 | + | VNx32QI | M8 | 1 | M4 | 2 | + | VNx64QI | N/A | N/A | M8 | 1 | + | VNx1(HI|HF) | MF2 | 32 | MF4 | 64 | + | VNx2(HI|HF) | M1 | 16 | MF2 | 32 | + | VNx4(HI|HF) | M2 | 8 | M1 | 16 | + | VNx8(HI|HF) | M4 | 4 | M2 | 8 | + | VNx16(HI|HF)| M8 | 2 | M4 | 4 | + | VNx32(HI|HF)| N/A | N/A | M8 | 2 | + | VNx1(SI|SF) | M1 | 32 | MF2 | 64 | + | VNx2(SI|SF) | M2 | 16 | M1 | 32 | + | VNx4(SI|SF) | M4 | 8 | M2 | 16 | + | VNx8(SI|SF) | M8 | 4 | M4 | 8 | + | VNx16(SI|SF)| N/A | N/A | M8 | 4 | + | VNx1(DI|DF) | N/A | N/A | M1 | 64 | + | VNx2(DI|DF) | N/A | N/A | M2 | 32 | + | VNx4(DI|DF) | N/A | N/A | M4 | 16 | + | VNx8(DI|DF) | N/A | N/A | M8 | 8 | +*/ + +/* Define RVV modes whose sizes are multiples of 64-bit chunks. */ +#define RVV_MODES(NVECS, VB, VH, VS, VD) \ + VECTOR_MODES_WITH_PREFIX (VNx, INT, 8 * NVECS, 0); \ + VECTOR_MODES_WITH_PREFIX (VNx, FLOAT, 8 * NVECS, 0); \ + \ + ADJUST_NUNITS (VB##QI, riscv_vector_chunks * NVECS * 8); \ + ADJUST_NUNITS (VH##HI, riscv_vector_chunks * NVECS * 4); \ + ADJUST_NUNITS (VS##SI, riscv_vector_chunks * NVECS * 2); \ + ADJUST_NUNITS (VD##DI, riscv_vector_chunks * NVECS); \ + ADJUST_NUNITS (VH##HF, riscv_vector_chunks * NVECS * 4); \ + ADJUST_NUNITS (VS##SF, riscv_vector_chunks * NVECS * 2); \ + ADJUST_NUNITS (VD##DF, riscv_vector_chunks * NVECS); \ + \ + ADJUST_ALIGNMENT (VB##QI, 1); \ + ADJUST_ALIGNMENT (VH##HI, 2); \ + ADJUST_ALIGNMENT (VS##SI, 4); \ + ADJUST_ALIGNMENT (VD##DI, 8); \ + ADJUST_ALIGNMENT (VH##HF, 2); \ + ADJUST_ALIGNMENT (VS##SF, 4); \ + ADJUST_ALIGNMENT (VD##DF, 8); + +/* 'VECTOR_MODES_WITH_PREFIX' does not allow ncomponents < 2. + So we use 'VECTOR_MODE_WITH_PREFIX' to define VNx1DImode and VNx1DFmode. */ +VECTOR_MODE_WITH_PREFIX (VNx, INT, DI, 1, 0); +VECTOR_MODE_WITH_PREFIX (VNx, FLOAT, DF, 1, 0); +RVV_MODES (1, VNx8, VNx4, VNx2, VNx1) +RVV_MODES (2, VNx16, VNx8, VNx4, VNx2) +RVV_MODES (4, VNx32, VNx16, VNx8, VNx4) +RVV_MODES (8, VNx64, VNx32, VNx16, VNx8) + +VECTOR_MODES_WITH_PREFIX (VNx, INT, 4, 0); +VECTOR_MODES_WITH_PREFIX (VNx, FLOAT, 4, 0); +ADJUST_NUNITS (VNx4QI, riscv_vector_chunks * 4); +ADJUST_NUNITS (VNx2HI, riscv_vector_chunks * 2); +ADJUST_NUNITS (VNx2HF, riscv_vector_chunks * 2); +ADJUST_ALIGNMENT (VNx4QI, 1); +ADJUST_ALIGNMENT (VNx2HI, 2); +ADJUST_ALIGNMENT (VNx2HF, 2); + +/* 'VECTOR_MODES_WITH_PREFIX' does not allow ncomponents < 2. + So we use 'VECTOR_MODE_WITH_PREFIX' to define VNx1SImode and VNx1SFmode. */ +VECTOR_MODE_WITH_PREFIX (VNx, INT, SI, 1, 0); +VECTOR_MODE_WITH_PREFIX (VNx, FLOAT, SF, 1, 0); +ADJUST_NUNITS (VNx1SI, riscv_vector_chunks); +ADJUST_NUNITS (VNx1SF, riscv_vector_chunks); +ADJUST_ALIGNMENT (VNx1SI, 4); +ADJUST_ALIGNMENT (VNx1SF, 4); + +VECTOR_MODES_WITH_PREFIX (VNx, INT, 2, 0); +ADJUST_NUNITS (VNx2QI, riscv_vector_chunks * 2); +ADJUST_ALIGNMENT (VNx2QI, 1); + +/* 'VECTOR_MODES_WITH_PREFIX' does not allow ncomponents < 2. + So we use 'VECTOR_MODE_WITH_PREFIX' to define VNx1HImode and VNx1HFmode. */ +VECTOR_MODE_WITH_PREFIX (VNx, INT, HI, 1, 0); +VECTOR_MODE_WITH_PREFIX (VNx, FLOAT, HF, 1, 0); +ADJUST_NUNITS (VNx1HI, riscv_vector_chunks); +ADJUST_NUNITS (VNx1HF, riscv_vector_chunks); +ADJUST_ALIGNMENT (VNx1HI, 2); +ADJUST_ALIGNMENT (VNx1HF, 2); + +/* 'VECTOR_MODES_WITH_PREFIX' does not allow ncomponents < 2. + So we use 'VECTOR_MODE_WITH_PREFIX' to define VNx1QImode. */ +VECTOR_MODE_WITH_PREFIX (VNx, INT, QI, 1, 0); +ADJUST_NUNITS (VNx1QI, riscv_vector_chunks); +ADJUST_ALIGNMENT (VNx1QI, 1); + /* TODO: According to RISC-V 'V' ISA spec, the maximun vector length can be 65536 for a single vector register which means the vector mode in GCC can be maximum = 65536 * 8 bits (LMUL=8). diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h index 649c5c9..f9a2baa 100644 --- a/gcc/config/riscv/riscv-protos.h +++ b/gcc/config/riscv/riscv-protos.h @@ -74,6 +74,7 @@ extern bool riscv_expand_block_move (rtx, rtx, rtx); extern bool riscv_store_data_bypass_p (rtx_insn *, rtx_insn *); extern rtx riscv_gen_gpr_save_insn (struct riscv_frame_info *); extern bool riscv_gpr_save_operation_p (rtx); +extern void riscv_reinit (void); /* Routines implemented in riscv-c.cc. */ void riscv_cpu_cpp_builtins (cpp_reader *); @@ -86,6 +87,7 @@ extern void riscv_init_builtins (void); /* Routines implemented in riscv-common.cc. */ extern std::string riscv_arch_str (bool version_p = true); +extern void riscv_parse_arch_string (const char *, struct gcc_options *, location_t); extern bool riscv_hard_regno_rename_ok (unsigned, unsigned); @@ -105,4 +107,11 @@ struct riscv_cpu_info { extern const riscv_cpu_info *riscv_find_cpu (const char *); +/* Routines implemented in riscv-selftests.cc. */ +#if CHECKING_P +namespace selftest { +extern void riscv_run_selftests (void); +} // namespace selftest +#endif + #endif /* ! GCC_RISCV_PROTOS_H */ diff --git a/gcc/config/riscv/riscv-selftests.cc b/gcc/config/riscv/riscv-selftests.cc new file mode 100644 index 0000000..636874e --- /dev/null +++ b/gcc/config/riscv/riscv-selftests.cc @@ -0,0 +1,241 @@ +/* This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +#define IN_TARGET_CODE 1 + +#define INCLUDE_STRING +#define INCLUDE_MAP +#define INCLUDE_VECTOR +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tm.h" +#include "rtl.h" +#include "tree.h" +#include "stringpool.h" +#include "function.h" +#include "memmodel.h" +#include "emit-rtl.h" +#include "tm_p.h" +#include "expr.h" +#include "selftest.h" +#include "selftest-rtl.h" + +#if CHECKING_P +using namespace selftest; +class riscv_selftest_arch_abi_setter +{ +private: + std::string m_arch_backup; + enum riscv_abi_type m_abi_backup; + +public: + riscv_selftest_arch_abi_setter (const char *arch, enum riscv_abi_type abi) + : m_arch_backup (riscv_arch_str ()), m_abi_backup (riscv_abi) + { + riscv_parse_arch_string (arch, &global_options, UNKNOWN_LOCATION); + riscv_abi = abi; + riscv_reinit (); + } + ~riscv_selftest_arch_abi_setter () + { + riscv_parse_arch_string (m_arch_backup.c_str (), &global_options, + UNKNOWN_LOCATION); + riscv_abi = m_abi_backup; + riscv_reinit (); + } +}; + +static poly_int64 +eval_value (rtx x, std::map<unsigned, rtx> ®no_to_rtx) +{ + if (!REG_P (x)) + { + debug (x); + gcc_unreachable (); + } + + rtx expr = NULL_RTX; + unsigned regno = REGNO (x); + expr = regno_to_rtx[regno]; + + poly_int64 op1_val = 0; + poly_int64 op2_val = 0; + if (UNARY_P (expr)) + { + op1_val = eval_value (XEXP (expr, 0), regno_to_rtx); + } + if (BINARY_P (expr)) + { + op1_val = eval_value (XEXP (expr, 0), regno_to_rtx); + op2_val = eval_value (XEXP (expr, 1), regno_to_rtx); + } + + switch (GET_CODE (expr)) + { + case CONST_POLY_INT: + return rtx_to_poly_int64 (expr); + case CONST_INT: + return INTVAL (expr); + + case MULT: + if (op1_val.is_constant ()) + return op1_val.to_constant () * op2_val; + else if (op2_val.is_constant ()) + return op1_val * op2_val.to_constant (); + else + gcc_unreachable (); + case PLUS: + return op1_val + op2_val; + default: + gcc_unreachable (); + } +} + +/* Calculate the value of x register in the sequence. */ +static poly_int64 +calculate_x_in_sequence (rtx reg) +{ + std::map<unsigned, rtx> regno_to_rtx; + rtx_insn *insn; + for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) + { + rtx pat = PATTERN (insn); + rtx dest = SET_DEST (pat); + + if (GET_CODE (pat) == CLOBBER) + continue; + + if (SUBREG_P (dest)) + continue; + + gcc_assert (REG_P (dest)); + rtx note = find_reg_equal_equiv_note (insn); + unsigned regno = REGNO (dest); + if (note) + regno_to_rtx[regno] = XEXP (note, 0); + else + regno_to_rtx[regno] = SET_SRC (pat); + } + + return eval_value (reg, regno_to_rtx); +} + +typedef enum +{ + POLY_TEST_DIMODE, + POLY_TEST_PMODE +} poly_test_mode_t; + +static void +simple_poly_selftest (const char *arch, enum riscv_abi_type abi, + const std::vector<machine_mode> &modes) +{ + riscv_selftest_arch_abi_setter rv (arch, abi); + rtl_dump_test t (SELFTEST_LOCATION, locate_file ("riscv/empty-func.rtl")); + set_new_first_and_last_insn (NULL, NULL); + + for (machine_mode mode : modes) + emit_move_insn (gen_reg_rtx (mode), + gen_int_mode (BYTES_PER_RISCV_VECTOR, mode)); +} + +static void +run_poly_int_selftest (const char *arch, enum riscv_abi_type abi, + poly_test_mode_t test_mode, + const std::vector<poly_int64> &worklist) +{ + riscv_selftest_arch_abi_setter rv (arch, abi); + rtl_dump_test t (SELFTEST_LOCATION, locate_file ("riscv/empty-func.rtl")); + set_new_first_and_last_insn (NULL, NULL); + machine_mode mode = VOIDmode; + + switch (test_mode) + { + case POLY_TEST_DIMODE: + mode = DImode; + break; + case POLY_TEST_PMODE: + mode = Pmode; + break; + default: + gcc_unreachable (); + } + + for (const poly_int64 &poly_val : worklist) + { + start_sequence (); + rtx dest = gen_reg_rtx (mode); + emit_move_insn (dest, gen_int_mode (poly_val, mode)); + ASSERT_TRUE (known_eq (calculate_x_in_sequence (dest), poly_val)); + end_sequence (); + } +} + +static void +run_poly_int_selftests (void) +{ + std::vector<poly_int64> worklist + = {BYTES_PER_RISCV_VECTOR, BYTES_PER_RISCV_VECTOR * 8, + BYTES_PER_RISCV_VECTOR * 32, -BYTES_PER_RISCV_VECTOR * 8, + -BYTES_PER_RISCV_VECTOR * 32, BYTES_PER_RISCV_VECTOR * 7, + BYTES_PER_RISCV_VECTOR * 31, -BYTES_PER_RISCV_VECTOR * 7, + -BYTES_PER_RISCV_VECTOR * 31, BYTES_PER_RISCV_VECTOR * 9, + BYTES_PER_RISCV_VECTOR * 33, -BYTES_PER_RISCV_VECTOR * 9, + -BYTES_PER_RISCV_VECTOR * 33, poly_int64 (207, 0), + poly_int64 (-207, 0), poly_int64 (0, 207), + poly_int64 (0, -207), poly_int64 (5555, 0), + poly_int64 (0, 5555), poly_int64 (4096, 4096), + poly_int64 (17, 4088), poly_int64 (3889, 4104), + poly_int64 (-4096, -4096), poly_int64 (219, -4088), + poly_int64 (-4309, -4104), poly_int64 (-7337, 88), + poly_int64 (9317, -88), poly_int64 (4, 4), + poly_int64 (17, 4), poly_int64 (-7337, 4), + poly_int64 (-4, -4), poly_int64 (-389, -4), + poly_int64 (4789, -4), poly_int64 (-5977, 1508), + poly_int64 (219, -1508), poly_int64 (2, 2), + poly_int64 (33, 2), poly_int64 (-7337, 2), + poly_int64 (-2, -2), poly_int64 (-389, -2), + poly_int64 (4789, -2), poly_int64 (-3567, 954), + poly_int64 (945, -954), poly_int64 (1, 1), + poly_int64 (977, 1), poly_int64 (-339, 1), + poly_int64 (-1, -1), poly_int64 (-12, -1), + poly_int64 (44, -1), poly_int64 (9567, 77), + poly_int64 (3467, -77)}; + + simple_poly_selftest ("rv64imafdv", ABI_LP64D, + {QImode, HImode, SImode, DImode}); + simple_poly_selftest ("rv32imafdv", ABI_ILP32D, {QImode, HImode, SImode}); + + run_poly_int_selftest ("rv64imafdv", ABI_LP64D, POLY_TEST_PMODE, worklist); + run_poly_int_selftest ("rv64imafd_zve32x1p0", ABI_LP64D, POLY_TEST_PMODE, + worklist); + run_poly_int_selftest ("rv32imafdv", ABI_ILP32, POLY_TEST_PMODE, worklist); + run_poly_int_selftest ("rv32imafdv", ABI_ILP32, POLY_TEST_DIMODE, worklist); + run_poly_int_selftest ("rv32imafd_zve32x1p0", ABI_ILP32D, POLY_TEST_PMODE, + worklist); + run_poly_int_selftest ("rv32imafd_zve32x1p0", ABI_ILP32D, POLY_TEST_DIMODE, + worklist); +} +namespace selftest { +/* Run all target-specific selftests. */ +void +riscv_run_selftests (void) +{ + run_poly_int_selftests (); +} +} // namespace selftest +#endif /* #if CHECKING_P */ diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index 675d92c..4d5d887 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -57,6 +57,8 @@ along with GCC; see the file COPYING3. If not see #include "predict.h" #include "tree-pass.h" #include "opts.h" +#include "tm-constrs.h" +#include "rtl-iter.h" /* True if X is an UNSPEC wrapper around a SYMBOL_REF or LABEL_REF. */ #define UNSPEC_ADDRESS_P(X) \ @@ -778,6 +780,12 @@ riscv_cannot_force_const_mem (machine_mode mode ATTRIBUTE_UNUSED, rtx x) enum riscv_symbol_type type; rtx base, offset; + /* There's no way to calculate VL-based values using relocations. */ + subrtx_iterator::array_type array; + FOR_EACH_SUBRTX (iter, array, x, ALL) + if (GET_CODE (*iter) == CONST_POLY_INT) + return true; + /* There is no assembler syntax for expressing an address-sized high part. */ if (GET_CODE (x) == HIGH) @@ -1684,12 +1692,268 @@ riscv_legitimize_const_move (machine_mode mode, rtx dest, rtx src) riscv_emit_move (dest, src); } +/* Report when we try to do something that requires vector when vector is + disabled. This is an error of last resort and isn't very high-quality. It + usually involves attempts to measure the vector length in some way. */ + +static void +riscv_report_v_required (void) +{ + static bool reported_p = false; + + /* Avoid reporting a slew of messages for a single oversight. */ + if (reported_p) + return; + + error ("this operation requires the RVV ISA extension"); + inform (input_location, "you can enable RVV using the command-line" + " option %<-march%>, or by using the %<target%>" + " attribute or pragma"); + reported_p = true; +} + +/* Helper function to operation for rtx_code CODE. */ +static void +riscv_expand_op (enum rtx_code code, machine_mode mode, rtx op0, rtx op1, + rtx op2) +{ + if (can_create_pseudo_p ()) + { + rtx result; + if (GET_RTX_CLASS (code) == RTX_UNARY) + result = expand_simple_unop (mode, code, op1, NULL_RTX, false); + else + result = expand_simple_binop (mode, code, op1, op2, NULL_RTX, false, + OPTAB_DIRECT); + riscv_emit_move (op0, result); + } + else + { + rtx pat; + /* The following implementation is for prologue and epilogue. + Because prologue and epilogue can not use pseudo register. + We can't using expand_simple_binop or expand_simple_unop. */ + if (GET_RTX_CLASS (code) == RTX_UNARY) + pat = gen_rtx_fmt_e (code, mode, op1); + else + pat = gen_rtx_fmt_ee (code, mode, op1, op2); + emit_insn (gen_rtx_SET (op0, pat)); + } +} + +/* Expand mult operation with constant integer, multiplicand also used as a + * temporary register. */ + +static void +riscv_expand_mult_with_const_int (machine_mode mode, rtx dest, rtx multiplicand, + int multiplier) +{ + if (multiplier == 0) + { + riscv_emit_move (dest, GEN_INT (0)); + return; + } + + bool neg_p = multiplier < 0; + int multiplier_abs = abs (multiplier); + + if (multiplier_abs == 1) + { + if (neg_p) + riscv_expand_op (NEG, mode, dest, multiplicand, NULL_RTX); + else + riscv_emit_move (dest, multiplicand); + } + else + { + if (pow2p_hwi (multiplier_abs)) + { + /* + multiplicand = [BYTES_PER_RISCV_VECTOR]. + 1. const_poly_int:P [BYTES_PER_RISCV_VECTOR * 8]. + Sequence: + csrr a5, vlenb + slli a5, a5, 3 + 2. const_poly_int:P [-BYTES_PER_RISCV_VECTOR * 8]. + Sequence: + csrr a5, vlenb + slli a5, a5, 3 + neg a5, a5 + */ + riscv_expand_op (ASHIFT, mode, dest, multiplicand, + gen_int_mode (exact_log2 (multiplier_abs), QImode)); + if (neg_p) + riscv_expand_op (NEG, mode, dest, dest, NULL_RTX); + } + else if (pow2p_hwi (multiplier_abs + 1)) + { + /* + multiplicand = [BYTES_PER_RISCV_VECTOR]. + 1. const_poly_int:P [BYTES_PER_RISCV_VECTOR * 7]. + Sequence: + csrr a5, vlenb + slli a4, a5, 3 + sub a5, a4, a5 + 2. const_poly_int:P [-BYTES_PER_RISCV_VECTOR * 7]. + Sequence: + csrr a5, vlenb + slli a4, a5, 3 + sub a5, a4, a5 + neg a5, a5 => sub a5, a5, a4 + */ + riscv_expand_op (ASHIFT, mode, dest, multiplicand, + gen_int_mode (exact_log2 (multiplier_abs + 1), + QImode)); + if (neg_p) + riscv_expand_op (MINUS, mode, dest, multiplicand, dest); + else + riscv_expand_op (MINUS, mode, dest, dest, multiplicand); + } + else if (pow2p_hwi (multiplier - 1)) + { + /* + multiplicand = [BYTES_PER_RISCV_VECTOR]. + 1. const_poly_int:P [BYTES_PER_RISCV_VECTOR * 9]. + Sequence: + csrr a5, vlenb + slli a4, a5, 3 + add a5, a4, a5 + 2. const_poly_int:P [-BYTES_PER_RISCV_VECTOR * 9]. + Sequence: + csrr a5, vlenb + slli a4, a5, 3 + add a5, a4, a5 + neg a5, a5 + */ + riscv_expand_op (ASHIFT, mode, dest, multiplicand, + gen_int_mode (exact_log2 (multiplier_abs - 1), + QImode)); + riscv_expand_op (PLUS, mode, dest, dest, multiplicand); + if (neg_p) + riscv_expand_op (NEG, mode, dest, dest, NULL_RTX); + } + else + { + /* We use multiplication for remaining cases. */ + gcc_assert ( + TARGET_MUL + && "M-extension must be enabled to calculate the poly_int " + "size/offset."); + riscv_emit_move (dest, gen_int_mode (multiplier, mode)); + riscv_expand_op (MULT, mode, dest, dest, multiplicand); + } + } +} + +/* Analyze src and emit const_poly_int mov sequence. */ + +static void +riscv_legitimize_poly_move (machine_mode mode, rtx dest, rtx tmp, rtx src) +{ + poly_int64 value = rtx_to_poly_int64 (src); + int offset = value.coeffs[0]; + int factor = value.coeffs[1]; + int vlenb = BYTES_PER_RISCV_VECTOR.coeffs[1]; + int div_factor = 0; + /* Calculate (const_poly_int:MODE [m, n]) using scalar instructions. + For any (const_poly_int:MODE [m, n]), the calculation formula is as + follows. + constant = m - n. + When minimum VLEN = 32, poly of VLENB = (4, 4). + base = vlenb(4, 4) or vlenb/2(2, 2) or vlenb/4(1, 1). + When minimum VLEN > 32, poly of VLENB = (8, 8). + base = vlenb(8, 8) or vlenb/2(4, 4) or vlenb/4(2, 2) or vlenb/8(1, 1). + magn = (n, n) / base. + (m, n) = base * magn + constant. + This calculation doesn't need div operation. */ + + emit_move_insn (tmp, gen_int_mode (BYTES_PER_RISCV_VECTOR, mode)); + + if (BYTES_PER_RISCV_VECTOR.is_constant ()) + { + gcc_assert (value.is_constant ()); + riscv_emit_move (dest, GEN_INT (value.to_constant ())); + return; + } + else if ((factor % vlenb) == 0) + div_factor = 1; + else if ((factor % (vlenb / 2)) == 0) + div_factor = 2; + else if ((factor % (vlenb / 4)) == 0) + div_factor = 4; + else if ((factor % (vlenb / 8)) == 0) + div_factor = 8; + else + gcc_unreachable (); + + if (div_factor != 1) + riscv_expand_op (LSHIFTRT, mode, tmp, tmp, + gen_int_mode (exact_log2 (div_factor), QImode)); + + riscv_expand_mult_with_const_int (mode, dest, tmp, + factor / (vlenb / div_factor)); + HOST_WIDE_INT constant = offset - factor; + + if (constant == 0) + return; + else if (SMALL_OPERAND (constant)) + riscv_expand_op (PLUS, mode, dest, dest, gen_int_mode (constant, mode)); + else + { + /* Handle the constant value is not a 12-bit value. */ + rtx high; + + /* Leave OFFSET as a 16-bit offset and put the excess in HIGH. + The addition inside the macro CONST_HIGH_PART may cause an + overflow, so we need to force a sign-extension check. */ + high = gen_int_mode (CONST_HIGH_PART (constant), mode); + constant = CONST_LOW_PART (constant); + riscv_emit_move (tmp, high); + riscv_expand_op (PLUS, mode, dest, tmp, dest); + riscv_expand_op (PLUS, mode, dest, dest, gen_int_mode (constant, mode)); + } +} + /* If (set DEST SRC) is not a valid move instruction, emit an equivalent sequence that is valid. */ bool riscv_legitimize_move (machine_mode mode, rtx dest, rtx src) { + if (CONST_POLY_INT_P (src)) + { + poly_int64 value = rtx_to_poly_int64 (src); + if (!value.is_constant () && !TARGET_VECTOR) + { + riscv_report_v_required (); + return false; + } + + if (satisfies_constraint_vp (src)) + return false; + + if (GET_MODE_SIZE (mode).to_constant () < GET_MODE_SIZE (Pmode)) + { + /* In RV32 system, handle (const_poly_int:QI [m, n]) + (const_poly_int:HI [m, n]). + In RV64 system, handle (const_poly_int:QI [m, n]) + (const_poly_int:HI [m, n]) + (const_poly_int:SI [m, n]). */ + rtx tmp = gen_reg_rtx (Pmode); + riscv_legitimize_poly_move (Pmode, gen_lowpart (Pmode, dest), tmp, + src); + } + else + { + /* In RV32 system, handle (const_poly_int:SI [m, n]) + (const_poly_int:DI [m, n]). + In RV64 system, handle (const_poly_int:DI [m, n]). + FIXME: Maybe we could gen SImode in RV32 and then sign-extend to DImode, + the offset should not exceed 4GiB in general. */ + rtx tmp = gen_reg_rtx (mode); + riscv_legitimize_poly_move (mode, dest, tmp, src); + } + return true; + } /* Expand (set (reg:QI target) (mem:QI (address))) to @@ -5033,6 +5297,9 @@ riscv_hard_regno_mode_ok (unsigned int regno, machine_mode mode) if (!riscv_v_ext_vector_mode_p (mode)) return false; + if (!V_REG_P (regno + nregs - 1)) + return false; + /* 3.3.2. LMUL = 2,4,8, register numbers should be multiple of 2,4,8. but for mask vector register, register numbers can be any number. */ int lmul = 1; @@ -5041,6 +5308,8 @@ riscv_hard_regno_mode_ok (unsigned int regno, machine_mode mode) if (lmul != 1) return ((regno % lmul) == 0); } + else if (regno == VL_REGNUM || regno == VTYPE_REGNUM) + return true; else return false; @@ -5231,10 +5500,6 @@ riscv_init_machine_status (void) static poly_uint16 riscv_convert_vector_bits (void) { - /* The runtime invariant is only meaningful when TARGET_VECTOR is enabled. */ - if (!TARGET_VECTOR) - return 0; - if (TARGET_MIN_VLEN > 32) { /* When targetting minimum VLEN > 32, we should use 64-bit chunk size. @@ -5255,7 +5520,13 @@ riscv_convert_vector_bits (void) riscv_bytes_per_vector_chunk = 4; } - return poly_uint16 (1, 1); + /* Set riscv_vector_chunks as poly (1, 1) run-time constant if TARGET_VECTOR + is enabled. Set riscv_vector_chunks as 1 compile-time constant if + TARGET_VECTOR is disabled. riscv_vector_chunks is used in "riscv-modes.def" + to set RVV mode size. The RVV machine modes size are run-time constant if + TARGET_VECTOR is enabled. The RVV machine modes size remains default + compile-time constant if TARGET_VECTOR is disabled. */ + return TARGET_VECTOR ? poly_uint16 (1, 1) : 1; } /* Implement TARGET_OPTION_OVERRIDE. */ @@ -6002,6 +6273,23 @@ riscv_init_libfuncs (void) set_optab_libfunc (unord_optab, HFmode, NULL); } +#if CHECKING_P +void +riscv_reinit (void) +{ + riscv_option_override (); + init_adjust_machine_modes (); + init_derived_machine_modes (); + reinit_regs (); + init_optabs (); +} +#endif + +#if CHECKING_P +#undef TARGET_RUN_TARGET_SELFTESTS +#define TARGET_RUN_TARGET_SELFTESTS selftest::riscv_run_selftests +#endif /* #if CHECKING_P */ + /* Initialize the GCC target structure. */ #undef TARGET_ASM_ALIGNED_HI_OP #define TARGET_ASM_ALIGNED_HI_OP "\t.half\t" diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h index eb1284e..363113c 100644 --- a/gcc/config/riscv/riscv.h +++ b/gcc/config/riscv/riscv.h @@ -749,18 +749,19 @@ typedef struct { #define CASE_VECTOR_MODE SImode #define CASE_VECTOR_PC_RELATIVE (riscv_cmodel != CM_MEDLOW) +#define LOCAL_SYM_P(sym) \ + ((SYMBOL_REF_P (sym) && SYMBOL_REF_LOCAL_P (sym)) \ + || ((GET_CODE (sym) == CONST) \ + && SYMBOL_REF_P (XEXP (XEXP (sym, 0),0)) \ + && SYMBOL_REF_LOCAL_P (XEXP (XEXP (sym, 0),0)))) + /* The load-address macro is used for PC-relative addressing of symbols that bind locally. Don't use it for symbols that should be addressed via the GOT. Also, avoid it for CM_MEDLOW, where LUI addressing currently results in more opportunities for linker relaxation. */ #define USE_LOAD_ADDRESS_MACRO(sym) \ (!TARGET_EXPLICIT_RELOCS && \ - ((flag_pic \ - && ((SYMBOL_REF_P (sym) && SYMBOL_REF_LOCAL_P (sym)) \ - || ((GET_CODE (sym) == CONST) \ - && SYMBOL_REF_P (XEXP (XEXP (sym, 0),0)) \ - && SYMBOL_REF_LOCAL_P (XEXP (XEXP (sym, 0),0))))) \ - || riscv_cmodel == CM_MEDANY)) + ((flag_pic && LOCAL_SYM_P (sym)) || riscv_cmodel == CM_MEDANY)) /* Define this as 1 if `char' should by default be signed; else as 0. */ #define DEFAULT_SIGNED_CHAR 0 diff --git a/gcc/config/riscv/t-riscv b/gcc/config/riscv/t-riscv index 19736b3..2b82e5f 100644 --- a/gcc/config/riscv/t-riscv +++ b/gcc/config/riscv/t-riscv @@ -23,6 +23,10 @@ riscv-shorten-memrefs.o: $(srcdir)/config/riscv/riscv-shorten-memrefs.cc $(COMPILE) $< $(POSTCOMPILE) +riscv-selftests.o: $(srcdir)/config/riscv/riscv-selftests.cc + $(COMPILE) $< + $(POSTCOMPILE) + PASSES_EXTRA += $(srcdir)/config/riscv/riscv-passes.def $(common_out_file): $(srcdir)/config/riscv/riscv-cores.def \ diff --git a/gcc/config/rs6000/rs6000-logue.cc b/gcc/config/rs6000/rs6000-logue.cc index ddd849e..a11d020 100644 --- a/gcc/config/rs6000/rs6000-logue.cc +++ b/gcc/config/rs6000/rs6000-logue.cc @@ -4920,7 +4920,7 @@ rs6000_emit_epilogue (enum epilogue_type epilogue_type) a REG_CFA_DEF_CFA note, but that's OK; A duplicate is discarded by dwarf2cfi.cc/dwarf2out.cc, and in any case would be harmless if emitted. */ - if (frame_pointer_needed) + if (frame_pointer_needed_indeed) { insn = get_last_insn (); add_reg_note (insn, REG_CFA_DEF_CFA, diff --git a/gcc/config/rs6000/vector.md b/gcc/config/rs6000/vector.md index a0d33d2..0171705 100644 --- a/gcc/config/rs6000/vector.md +++ b/gcc/config/rs6000/vector.md @@ -1475,7 +1475,7 @@ [(match_operand:VEC_L 0 "vlogical_operand") (match_operand:VEC_L 1 "vlogical_operand") (match_operand:QI 2 "reg_or_short_operand")] - "TARGET_ALTIVEC" + "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" { rtx bitshift = operands[2]; rtx shift; diff --git a/gcc/config/s390/s390.cc b/gcc/config/s390/s390.cc index 3ae586c..9861913 100644 --- a/gcc/config/s390/s390.cc +++ b/gcc/config/s390/s390.cc @@ -3648,7 +3648,7 @@ s390_rtx_costs (rtx x, machine_mode mode, int outer_code, *total = 0; return true; case SET: { - rtx dest = SET_DEST (x); + rtx dst = SET_DEST (x); rtx src = SET_SRC (x); switch (GET_CODE (src)) @@ -3669,7 +3669,6 @@ s390_rtx_costs (rtx x, machine_mode mode, int outer_code, slightly more expensive than a normal load. */ *total = COSTS_N_INSNS (1) + 2; - rtx dst = SET_DEST (src); rtx then = XEXP (src, 1); rtx els = XEXP (src, 2); @@ -3696,25 +3695,25 @@ s390_rtx_costs (rtx x, machine_mode mode, int outer_code, break; } - switch (GET_CODE (dest)) + switch (GET_CODE (dst)) { case SUBREG: - if (!REG_P (SUBREG_REG (dest))) + if (!REG_P (SUBREG_REG (dst))) *total += rtx_cost (SUBREG_REG (src), VOIDmode, SET, 0, speed); /* fallthrough */ case REG: /* If this is a VR -> VR copy, count the number of registers. */ - if (VECTOR_MODE_P (GET_MODE (dest)) && REG_P (src)) + if (VECTOR_MODE_P (GET_MODE (dst)) && REG_P (src)) { - int nregs = s390_hard_regno_nregs (VR0_REGNUM, GET_MODE (dest)); + int nregs = s390_hard_regno_nregs (VR0_REGNUM, GET_MODE (dst)); *total = COSTS_N_INSNS (nregs); } /* Same for GPRs. */ else if (REG_P (src)) { int nregs - = s390_hard_regno_nregs (GPR0_REGNUM, GET_MODE (dest)); + = s390_hard_regno_nregs (GPR0_REGNUM, GET_MODE (dst)); *total = COSTS_N_INSNS (nregs); } else @@ -3722,7 +3721,7 @@ s390_rtx_costs (rtx x, machine_mode mode, int outer_code, *total += rtx_cost (src, mode, SET, 1, speed); return true; case MEM: { - rtx address = XEXP (dest, 0); + rtx address = XEXP (dst, 0); rtx tmp; HOST_WIDE_INT tmp2; if (s390_loadrelative_operand_p (address, &tmp, &tmp2)) diff --git a/gcc/config/xtensa/xtensa.cc b/gcc/config/xtensa/xtensa.cc index f1b3331..828c764 100644 --- a/gcc/config/xtensa/xtensa.cc +++ b/gcc/config/xtensa/xtensa.cc @@ -191,6 +191,15 @@ static bool xtensa_can_eliminate (const int from ATTRIBUTE_UNUSED, static HOST_WIDE_INT xtensa_starting_frame_offset (void); static unsigned HOST_WIDE_INT xtensa_asan_shadow_offset (void); static bool xtensa_function_ok_for_sibcall (tree, tree); +static bool xtensa_can_output_mi_thunk (const_tree thunk_fndecl ATTRIBUTE_UNUSED, + HOST_WIDE_INT delta ATTRIBUTE_UNUSED, + HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED, + const_tree function ATTRIBUTE_UNUSED); +static void xtensa_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED, + HOST_WIDE_INT delta, + HOST_WIDE_INT vcall_offset, + tree function); + static rtx xtensa_delegitimize_address (rtx); @@ -351,6 +360,15 @@ static rtx xtensa_delegitimize_address (rtx); #undef TARGET_FUNCTION_OK_FOR_SIBCALL #define TARGET_FUNCTION_OK_FOR_SIBCALL xtensa_function_ok_for_sibcall +#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK +#define TARGET_ASM_CAN_OUTPUT_MI_THUNK xtensa_can_output_mi_thunk + +#undef TARGET_ASM_OUTPUT_MI_THUNK +#define TARGET_ASM_OUTPUT_MI_THUNK xtensa_output_mi_thunk + +#undef TARGET_MAX_ANCHOR_OFFSET +#define TARGET_MAX_ANCHOR_OFFSET 1020 + struct gcc_target targetm = TARGET_INITIALIZER; @@ -2173,7 +2191,16 @@ xtensa_prepare_expand_call (int callop, rtx *operands) addr = gen_sym_PLT (addr); if (!call_insn_operand (addr, VOIDmode)) - XEXP (operands[callop], 0) = copy_to_mode_reg (Pmode, addr); + { + /* This may be called while generating MI thunk when we pretend + that reload is over. Use a8 as a temporary register in that case. */ + rtx reg = can_create_pseudo_p () + ? copy_to_mode_reg (Pmode, addr) + : copy_to_suggested_reg (addr, + gen_rtx_REG (Pmode, A8_REG), + Pmode); + XEXP (operands[callop], 0) = reg; + } } @@ -4983,6 +5010,96 @@ xtensa_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED, tree exp ATTRIBUTE_U return true; } +static bool +xtensa_can_output_mi_thunk (const_tree thunk_fndecl ATTRIBUTE_UNUSED, + HOST_WIDE_INT delta ATTRIBUTE_UNUSED, + HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED, + const_tree function ATTRIBUTE_UNUSED) +{ + if (TARGET_WINDOWED_ABI) + return false; + + return true; +} + +/* Output code to add DELTA to the first argument, and then jump + to FUNCTION. Used for C++ multiple inheritance. */ +static void +xtensa_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED, + HOST_WIDE_INT delta, + HOST_WIDE_INT vcall_offset, + tree function) +{ + rtx this_rtx; + rtx funexp; + rtx_insn *insn; + int this_reg_no; + rtx temp0 = gen_rtx_REG (Pmode, A9_REG); + const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk)); + + reload_completed = 1; + + if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function)) + this_reg_no = 3; + else + this_reg_no = 2; + + this_rtx = gen_rtx_REG (Pmode, A0_REG + this_reg_no); + + if (delta) + { + if (xtensa_simm8 (delta)) + emit_insn (gen_addsi3 (this_rtx, this_rtx, GEN_INT (delta))); + else + { + emit_move_insn (temp0, GEN_INT (delta)); + emit_insn (gen_addsi3 (this_rtx, this_rtx, temp0)); + } + } + + if (vcall_offset) + { + rtx temp1 = gen_rtx_REG (Pmode, A0_REG + 10); + rtx addr = temp1; + + emit_move_insn (temp0, gen_rtx_MEM (Pmode, this_rtx)); + if (xtensa_uimm8x4 (vcall_offset)) + addr = plus_constant (Pmode, temp0, vcall_offset); + else if (xtensa_simm8 (vcall_offset)) + emit_insn (gen_addsi3 (temp1, temp0, GEN_INT (vcall_offset))); + else + { + emit_move_insn (temp1, GEN_INT (vcall_offset)); + emit_insn (gen_addsi3 (temp1, temp0, temp1)); + } + emit_move_insn (temp1, gen_rtx_MEM (Pmode, addr)); + emit_insn (gen_add2_insn (this_rtx, temp1)); + } + + /* Generate a tail call to the target function. */ + if (!TREE_USED (function)) + { + assemble_external (function); + TREE_USED (function) = 1; + } + + funexp = XEXP (DECL_RTL (function), 0); + funexp = gen_rtx_MEM (FUNCTION_MODE, funexp); + insn = emit_call_insn (gen_sibcall (funexp, const0_rtx)); + SIBLING_CALL_P (insn) = 1; + + insn = get_insns (); + shorten_branches (insn); + assemble_start_function (thunk, fnname); + final_start_function (insn, file, 1); + final (insn, file, 1); + final_end_function (); + assemble_end_function (thunk, fnname); + + /* Stop pretending to be a post-reload pass. */ + reload_completed = 0; +} + static rtx xtensa_delegitimize_address (rtx op) { diff --git a/gcc/configure b/gcc/configure index 817d765..70a013e 100755 --- a/gcc/configure +++ b/gcc/configure @@ -29727,16 +29727,9 @@ else if $gcc_cv_as --compress-debug-sections -o conftest.o conftest.s 2>&1 | grep -i warning > /dev/null then gcc_cv_as_compress_debug=0 - # Since binutils 2.26, gas supports --compress-debug-sections=type, + # Since binutils 2.26, gas supports --compress-debug-sections=zlib, # defaulting to the ELF gABI format. - elif $gcc_cv_as --compress-debug-sections=zlib-gnu -o conftest.o conftest.s > /dev/null 2>&1 - then - gcc_cv_as_compress_debug=2 - gcc_cv_as_compress_debug_option="--compress-debug-sections" - gcc_cv_as_no_compress_debug_option="--nocompress-debug-sections" - # Before binutils 2.26, gas only supported --compress-debug-options and - # emitted the traditional GNU format. - elif $gcc_cv_as --compress-debug-sections -o conftest.o conftest.s > /dev/null 2>&1 + elif $gcc_cv_as --compress-debug-sections=zlib -o conftest.o conftest.s > /dev/null 2>&1 then gcc_cv_as_compress_debug=1 gcc_cv_as_compress_debug_option="--compress-debug-sections" @@ -30254,48 +30247,16 @@ $as_echo "$gcc_cv_ld_eh_gc_sections_bug" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking linker for compressed debug sections" >&5 $as_echo_n "checking linker for compressed debug sections... " >&6; } -# gold/gld support compressed debug sections since binutils 2.19/2.21 -# In binutils 2.26, gld gained support for the ELF gABI format. -if test $in_tree_ld = yes ; then - gcc_cv_ld_compress_debug=0 - if test $ld_is_mold = yes; then - gcc_cv_ld_compress_debug=3 - gcc_cv_ld_compress_debug_option="--compress-debug-sections" - elif test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 19 -o "$gcc_cv_gld_major_version" -gt 2 \ - && test $in_tree_ld_is_elf = yes && test $ld_is_gold = yes; then - gcc_cv_ld_compress_debug=2 - gcc_cv_ld_compress_debug_option="--compress-debug-sections" - elif test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 26 -o "$gcc_cv_gld_major_version" -gt 2 \ - && test $in_tree_ld_is_elf = yes && test $ld_is_gold = no; then - gcc_cv_ld_compress_debug=3 - gcc_cv_ld_compress_debug_option="--compress-debug-sections" - elif test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 21 -o "$gcc_cv_gld_major_version" -gt 2 \ - && test $in_tree_ld_is_elf = yes; then +# GNU ld/gold support --compressed-debug-sections=zlib since binutils 2.26. +if $gcc_cv_ld --help 2>&1 | grep -- '--compress-debug-sections.*\<zlib-gabi\>' > /dev/null; then gcc_cv_ld_compress_debug=1 - fi -elif echo "$ld_ver" | grep GNU > /dev/null; then - if test $ld_is_mold = yes; then - gcc_cv_ld_compress_debug=3 - gcc_cv_ld_compress_debug_option="--compress-debug-sections" - elif test "$ld_vers_major" -lt 2 \ - || test "$ld_vers_major" -eq 2 -a "$ld_vers_minor" -lt 21; then - gcc_cv_ld_compress_debug=0 - elif test "$ld_vers_major" -eq 2 -a "$ld_vers_minor" -lt 26; then - gcc_cv_ld_compress_debug=1 - else - gcc_cv_ld_compress_debug=3 - gcc_cv_ld_compress_debug_option="--compress-debug-sections" - fi - if test $ld_is_gold = yes; then - gcc_cv_ld_compress_debug=2 gcc_cv_ld_compress_debug_option="--compress-debug-sections" - fi else case "${target}" in *-*-solaris2*) # Introduced in Solaris 11.2. if $gcc_cv_ld --help 2>&1 | grep -- '-z compress-sections' > /dev/null; then - gcc_cv_ld_compress_debug=3 + gcc_cv_ld_compress_debug=1 gcc_cv_ld_compress_debug_option="-z compress-sections" else gcc_cv_ld_compress_debug=0 diff --git a/gcc/configure.ac b/gcc/configure.ac index 59f205a1..96e10d7 100644 --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -5732,16 +5732,9 @@ gcc_GAS_CHECK_FEATURE([compressed debug sections], if $gcc_cv_as --compress-debug-sections -o conftest.o conftest.s 2>&1 | grep -i warning > /dev/null then gcc_cv_as_compress_debug=0 - # Since binutils 2.26, gas supports --compress-debug-sections=type, + # Since binutils 2.26, gas supports --compress-debug-sections=zlib, # defaulting to the ELF gABI format. - elif $gcc_cv_as --compress-debug-sections=zlib-gnu -o conftest.o conftest.s > /dev/null 2>&1 - then - gcc_cv_as_compress_debug=2 - gcc_cv_as_compress_debug_option="--compress-debug-sections" - gcc_cv_as_no_compress_debug_option="--nocompress-debug-sections" - # Before binutils 2.26, gas only supported --compress-debug-options and - # emitted the traditional GNU format. - elif $gcc_cv_as --compress-debug-sections -o conftest.o conftest.s > /dev/null 2>&1 + elif $gcc_cv_as --compress-debug-sections=zlib -o conftest.o conftest.s > /dev/null 2>&1 then gcc_cv_as_compress_debug=1 gcc_cv_as_compress_debug_option="--compress-debug-sections" @@ -6130,49 +6123,17 @@ fi AC_MSG_RESULT($gcc_cv_ld_eh_gc_sections_bug) AC_MSG_CHECKING(linker for compressed debug sections) -# gold/gld support compressed debug sections since binutils 2.19/2.21 -# In binutils 2.26, gld gained support for the ELF gABI format. -if test $in_tree_ld = yes ; then - gcc_cv_ld_compress_debug=0 - if test $ld_is_mold = yes; then - gcc_cv_ld_compress_debug=3 - gcc_cv_ld_compress_debug_option="--compress-debug-sections" - elif test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 19 -o "$gcc_cv_gld_major_version" -gt 2 \ - && test $in_tree_ld_is_elf = yes && test $ld_is_gold = yes; then - gcc_cv_ld_compress_debug=2 - gcc_cv_ld_compress_debug_option="--compress-debug-sections" - elif test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 26 -o "$gcc_cv_gld_major_version" -gt 2 \ - && test $in_tree_ld_is_elf = yes && test $ld_is_gold = no; then - gcc_cv_ld_compress_debug=3 - gcc_cv_ld_compress_debug_option="--compress-debug-sections" - elif test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 21 -o "$gcc_cv_gld_major_version" -gt 2 \ - && test $in_tree_ld_is_elf = yes; then +# GNU ld/gold support --compressed-debug-sections=zlib since binutils 2.26. +if $gcc_cv_ld --help 2>&1 | grep -- '--compress-debug-sections.*\<zlib-gabi\>' > /dev/null; then gcc_cv_ld_compress_debug=1 - fi -elif echo "$ld_ver" | grep GNU > /dev/null; then - if test $ld_is_mold = yes; then - gcc_cv_ld_compress_debug=3 - gcc_cv_ld_compress_debug_option="--compress-debug-sections" - elif test "$ld_vers_major" -lt 2 \ - || test "$ld_vers_major" -eq 2 -a "$ld_vers_minor" -lt 21; then - gcc_cv_ld_compress_debug=0 - elif test "$ld_vers_major" -eq 2 -a "$ld_vers_minor" -lt 26; then - gcc_cv_ld_compress_debug=1 - else - gcc_cv_ld_compress_debug=3 - gcc_cv_ld_compress_debug_option="--compress-debug-sections" - fi - if test $ld_is_gold = yes; then - gcc_cv_ld_compress_debug=2 gcc_cv_ld_compress_debug_option="--compress-debug-sections" - fi else changequote(,)dnl case "${target}" in *-*-solaris2*) # Introduced in Solaris 11.2. if $gcc_cv_ld --help 2>&1 | grep -- '-z compress-sections' > /dev/null; then - gcc_cv_ld_compress_debug=3 + gcc_cv_ld_compress_debug=1 gcc_cv_ld_compress_debug_option="-z compress-sections" else gcc_cv_ld_compress_debug=0 diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index dc4ce202..b9b2729 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,55 @@ +2022-09-23 Marek Polacek <polacek@redhat.com> + + PR c++/106784 + * constraint.cc (diagnose_trait_expr): Handle CPTK_IS_CONVERTIBLE + and CPTK_IS_NOTHROW_CONVERTIBLE. + * cp-objcp-common.cc (names_builtin_p): Handle RID_IS_CONVERTIBLE + RID_IS_NOTHROW_CONVERTIBLE. + * cp-tree.h (enum cp_trait_kind): Add CPTK_IS_CONVERTIBLE and + CPTK_IS_NOTHROW_CONVERTIBLE. + (is_convertible): Declare. + (is_nothrow_convertible): Likewise. + * cxx-pretty-print.cc (pp_cxx_trait_expression): Handle + CPTK_IS_CONVERTIBLE and CPTK_IS_NOTHROW_CONVERTIBLE. + * method.cc (is_convertible): New. + (is_nothrow_convertible): Likewise. + * parser.cc (cp_parser_primary_expression): Handle RID_IS_CONVERTIBLE + and RID_IS_NOTHROW_CONVERTIBLE. + (cp_parser_trait_expr): Likewise. + * semantics.cc (trait_expr_value): Handle CPTK_IS_CONVERTIBLE and + CPTK_IS_NOTHROW_CONVERTIBLE. + (finish_trait_expr): Likewise. + +2022-09-23 Marek Polacek <polacek@redhat.com> + + PR c++/106983 + * typeck2.cc (split_nonconstant_init_1): Check TYPE_P. + +2022-09-22 Patrick Palka <ppalka@redhat.com> + + PR c++/106826 + * module.cc (trees_out::decl_value): Use get_template_info in + the MK_partial case to handle both VAR_DECL and TYPE_DECL. + (trees_out::key_mergeable): Likewise. + (trees_in::key_mergeable): Likewise. + (has_definition): Consider DECL_INITIAL of a partial variable + template specialization. + (depset::hash::make_dependency): Handle partial variable template + specializations too. + +2022-09-20 Patrick Palka <ppalka@redhat.com> + + * decl.cc (cp_finish_decl): After updating the deduced type of a + VAR_DECL, also update the corresponding TEMPLATE_DECL if there + is one. + +2022-09-20 Patrick Palka <ppalka@redhat.com> + + PR c++/106761 + * module.cc (trees_out::type_node) <case TYPE_PACK_EXPANSION>: + Stream PACK_EXPANSION_EXTRA_ARGS. + (trees_in::tree_node) <case TYPE_PACK_EXPANSION>: Likewise. + 2022-09-17 Patrick Palka <ppalka@redhat.com> * module.cc (friend_from_decl_list): Don't consider diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc index 568318f..5839bfb 100644 --- a/gcc/cp/constraint.cc +++ b/gcc/cp/constraint.cc @@ -3697,6 +3697,12 @@ diagnose_trait_expr (tree expr, tree args) case CPTK_HAS_UNIQUE_OBJ_REPRESENTATIONS: inform (loc, " %qT does not have unique object representations", t1); break; + case CPTK_IS_CONVERTIBLE: + inform (loc, " %qT is not convertible from %qE", t2, t1); + break; + case CPTK_IS_NOTHROW_CONVERTIBLE: + inform (loc, " %qT is not %<nothrow%> convertible from %qE", t2, t1); + break; case CPTK_REF_CONSTRUCTS_FROM_TEMPORARY: inform (loc, " %qT is not a reference that binds to a temporary " "object of type %qT (direct-initialization)", t1, t2); diff --git a/gcc/cp/cp-objcp-common.cc b/gcc/cp/cp-objcp-common.cc index 1ffac08..6497569 100644 --- a/gcc/cp/cp-objcp-common.cc +++ b/gcc/cp/cp-objcp-common.cc @@ -463,6 +463,8 @@ names_builtin_p (const char *name) case RID_IS_NOTHROW_ASSIGNABLE: case RID_IS_NOTHROW_CONSTRUCTIBLE: case RID_UNDERLYING_TYPE: + case RID_IS_CONVERTIBLE: + case RID_IS_NOTHROW_CONVERTIBLE: case RID_REF_CONSTRUCTS_FROM_TEMPORARY: case RID_REF_CONVERTS_FROM_TEMPORARY: return true; diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index f19ecaf..e4d8920 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -1407,6 +1407,8 @@ enum cp_trait_kind CPTK_IS_CONSTRUCTIBLE, CPTK_IS_NOTHROW_ASSIGNABLE, CPTK_IS_NOTHROW_CONSTRUCTIBLE, + CPTK_IS_CONVERTIBLE, + CPTK_IS_NOTHROW_CONVERTIBLE, CPTK_REF_CONSTRUCTS_FROM_TEMPORARY, CPTK_REF_CONVERTS_FROM_TEMPORARY }; @@ -7116,6 +7118,8 @@ extern tree forward_parm (tree); extern bool is_trivially_xible (enum tree_code, tree, tree); extern bool is_nothrow_xible (enum tree_code, tree, tree); extern bool is_xible (enum tree_code, tree, tree); +extern bool is_convertible (tree, tree); +extern bool is_nothrow_convertible (tree, tree); extern bool ref_xes_from_temporary (tree, tree, bool); extern tree get_defaulted_eh_spec (tree, tsubst_flags_t = tf_warning_or_error); extern bool maybe_explain_implicit_delete (tree); diff --git a/gcc/cp/cxx-pretty-print.cc b/gcc/cp/cxx-pretty-print.cc index 4459083..e18143e3 100644 --- a/gcc/cp/cxx-pretty-print.cc +++ b/gcc/cp/cxx-pretty-print.cc @@ -2696,6 +2696,12 @@ pp_cxx_trait_expression (cxx_pretty_printer *pp, tree t) case CPTK_IS_NOTHROW_CONSTRUCTIBLE: pp_cxx_ws_string (pp, "__is_nothrow_constructible"); break; + case CPTK_IS_CONVERTIBLE: + pp_cxx_ws_string (pp, "__is_convertible"); + break; + case CPTK_IS_NOTHROW_CONVERTIBLE: + pp_cxx_ws_string (pp, "__is_nothrow_convertible"); + break; case CPTK_REF_CONSTRUCTS_FROM_TEMPORARY: pp_cxx_ws_string (pp, "__reference_constructs_from_temporary"); break; diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index 070f673..80467c1 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -8180,6 +8180,12 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, return; } cp_apply_type_quals_to_decl (cp_type_quals (type), decl); + + /* Update the type of the corresponding TEMPLATE_DECL to match. */ + if (DECL_LANG_SPECIFIC (decl) + && DECL_TEMPLATE_INFO (decl) + && DECL_TEMPLATE_RESULT (DECL_TI_TEMPLATE (decl)) == decl) + TREE_TYPE (DECL_TI_TEMPLATE (decl)) = type; } if (ensure_literal_type_for_constexpr_object (decl) == error_mark_node) diff --git a/gcc/cp/method.cc b/gcc/cp/method.cc index 573ef01..9f917f1 100644 --- a/gcc/cp/method.cc +++ b/gcc/cp/method.cc @@ -2236,6 +2236,44 @@ ref_xes_from_temporary (tree to, tree from, bool direct_init_p) return ref_conv_binds_directly (to, val, direct_init_p).is_false (); } +/* Worker for is_{,nothrow_}convertible. Attempt to perform an implicit + conversion from FROM to TO and return the result. */ + +static tree +is_convertible_helper (tree from, tree to) +{ + if (VOID_TYPE_P (from) && VOID_TYPE_P (to)) + return integer_one_node; + cp_unevaluated u; + tree expr = build_stub_object (from); + return perform_implicit_conversion (to, expr, tf_none); +} + +/* Return true if FROM can be converted to TO using implicit conversions, + or both FROM and TO are possibly cv-qualified void. NB: This doesn't + implement the "Access checks are performed as if from a context unrelated + to either type" restriction. */ + +bool +is_convertible (tree from, tree to) +{ + tree expr = is_convertible_helper (from, to); + if (expr == error_mark_node) + return false; + return !!expr; +} + +/* Like is_convertible, but the conversion is also noexcept. */ + +bool +is_nothrow_convertible (tree from, tree to) +{ + tree expr = is_convertible_helper (from, to); + if (expr == NULL_TREE || expr == error_mark_node) + return false; + return expr_noexcept_p (expr, tf_none); +} + /* Categorize various special_function_kinds. */ #define SFK_CTOR_P(sfk) \ ((sfk) >= sfk_constructor && (sfk) <= sfk_move_constructor) diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index 9a9ef4e..7496df5 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -7789,8 +7789,9 @@ trees_out::decl_value (tree decl, depset *dep) } else { - tree_node (CLASSTYPE_TI_TEMPLATE (TREE_TYPE (inner))); - tree_node (CLASSTYPE_TI_ARGS (TREE_TYPE (inner))); + tree ti = get_template_info (inner); + tree_node (TI_TEMPLATE (ti)); + tree_node (TI_ARGS (ti)); } } tree_node (get_constraints (decl)); @@ -8184,13 +8185,18 @@ trees_in::decl_value () /* Set the TEMPLATE_DECL's type. */ TREE_TYPE (decl) = TREE_TYPE (inner); - if (mk & MK_template_mask - || mk == MK_partial) + /* Add to specialization tables now that constraints etc are + added. */ + if (mk == MK_partial) { - /* Add to specialization tables now that constraints etc are - added. */ - bool is_type = mk == MK_partial || !(mk & MK_tmpl_decl_mask); - + bool is_type = TREE_CODE (inner) == TYPE_DECL; + spec.spec = is_type ? type : inner; + add_mergeable_specialization (!is_type, false, + &spec, decl, spec_flags); + } + else if (mk & MK_template_mask) + { + bool is_type = !(mk & MK_tmpl_decl_mask); spec.spec = is_type ? type : mk & MK_tmpl_tmpl_mask ? inner : decl; add_mergeable_specialization (!is_type, !is_type && mk & MK_tmpl_alias_mask, @@ -10625,9 +10631,10 @@ trees_out::key_mergeable (int tag, merge_kind mk, tree decl, tree inner, case MK_partial: { + tree ti = get_template_info (inner); key.constraints = get_constraints (inner); - key.ret = CLASSTYPE_TI_TEMPLATE (TREE_TYPE (inner)); - key.args = CLASSTYPE_TI_ARGS (TREE_TYPE (inner)); + key.ret = TI_TEMPLATE (ti); + key.args = TI_ARGS (ti); } break; } @@ -10866,8 +10873,8 @@ trees_in::key_mergeable (int tag, merge_kind mk, tree decl, tree inner, spec; spec = TREE_CHAIN (spec)) { tree tmpl = TREE_VALUE (spec); - if (template_args_equal (key.args, - CLASSTYPE_TI_ARGS (TREE_TYPE (tmpl))) + tree ti = get_template_info (tmpl); + if (template_args_equal (key.args, TI_ARGS (ti)) && cp_tree_equal (key.constraints, get_constraints (DECL_TEMPLATE_RESULT (tmpl)))) @@ -11381,8 +11388,7 @@ has_definition (tree decl) case VAR_DECL: if (DECL_LANG_SPECIFIC (decl) - && DECL_TEMPLATE_INFO (decl) - && DECL_USE_TEMPLATE (decl) < 2) + && DECL_TEMPLATE_INFO (decl)) return DECL_INITIAL (decl); else { @@ -12498,11 +12504,14 @@ depset::hash::make_dependency (tree decl, entity_kind ek) if (!dep) { - if (DECL_IMPLICIT_TYPEDEF_P (decl) - /* ... not an enum, for instance. */ - && RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)) - && TYPE_LANG_SPECIFIC (TREE_TYPE (decl)) - && CLASSTYPE_USE_TEMPLATE (TREE_TYPE (decl)) == 2) + if ((DECL_IMPLICIT_TYPEDEF_P (decl) + /* ... not an enum, for instance. */ + && RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)) + && TYPE_LANG_SPECIFIC (TREE_TYPE (decl)) + && CLASSTYPE_USE_TEMPLATE (TREE_TYPE (decl)) == 2) + || (VAR_P (decl) + && DECL_LANG_SPECIFIC (decl) + && DECL_USE_TEMPLATE (decl) == 2)) { /* A partial or explicit specialization. Partial specializations might not be in the hash table, because @@ -12515,7 +12524,7 @@ depset::hash::make_dependency (tree decl, entity_kind ek) dep_hash, and then convert the dep we just found into a redirect. */ - tree ti = TYPE_TEMPLATE_INFO (TREE_TYPE (decl)); + tree ti = get_template_info (decl); tree tmpl = TI_TEMPLATE (ti); tree partial = NULL_TREE; for (tree spec = DECL_TEMPLATE_SPECIALIZATIONS (tmpl); diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 3cbe0d6..bb83d1c 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -5922,6 +5922,8 @@ cp_parser_primary_expression (cp_parser *parser, case RID_IS_CONSTRUCTIBLE: case RID_IS_NOTHROW_ASSIGNABLE: case RID_IS_NOTHROW_CONSTRUCTIBLE: + case RID_IS_CONVERTIBLE: + case RID_IS_NOTHROW_CONVERTIBLE: case RID_REF_CONSTRUCTS_FROM_TEMPORARY: case RID_REF_CONVERTS_FROM_TEMPORARY: return cp_parser_trait_expr (parser, token->keyword); @@ -11008,6 +11010,14 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword) kind = CPTK_IS_NOTHROW_CONSTRUCTIBLE; variadic = true; break; + case RID_IS_CONVERTIBLE: + kind = CPTK_IS_CONVERTIBLE; + binary = true; + break; + case RID_IS_NOTHROW_CONVERTIBLE: + kind = CPTK_IS_NOTHROW_CONVERTIBLE; + binary = true; + break; case RID_REF_CONSTRUCTS_FROM_TEMPORARY: kind = CPTK_REF_CONSTRUCTS_FROM_TEMPORARY; binary = true; diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index db4e808..1f088fe 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -31010,7 +31010,7 @@ add_mergeable_specialization (bool decl_p, bool alias_p, spec_entry *elt, /* A partial specialization. */ tree cons = tree_cons (elt->args, decl, DECL_TEMPLATE_SPECIALIZATIONS (elt->tmpl)); - TREE_TYPE (cons) = elt->spec; + TREE_TYPE (cons) = decl_p ? TREE_TYPE (elt->spec) : elt->spec; DECL_TEMPLATE_SPECIALIZATIONS (elt->tmpl) = cons; } } diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc index 8656207..92fc795 100644 --- a/gcc/cp/semantics.cc +++ b/gcc/cp/semantics.cc @@ -12044,6 +12044,12 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2) case CPTK_IS_NOTHROW_CONSTRUCTIBLE: return is_nothrow_xible (INIT_EXPR, type1, type2); + case CPTK_IS_CONVERTIBLE: + return is_convertible (type1, type2); + + case CPTK_IS_NOTHROW_CONVERTIBLE: + return is_nothrow_convertible (type1, type2); + case CPTK_REF_CONSTRUCTS_FROM_TEMPORARY: return ref_xes_from_temporary (type1, type2, /*direct_init=*/true); @@ -12165,6 +12171,8 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2) case CPTK_IS_TRIVIALLY_CONSTRUCTIBLE: case CPTK_IS_NOTHROW_ASSIGNABLE: case CPTK_IS_NOTHROW_CONSTRUCTIBLE: + case CPTK_IS_CONVERTIBLE: + case CPTK_IS_NOTHROW_CONVERTIBLE: case CPTK_REF_CONSTRUCTS_FROM_TEMPORARY: case CPTK_REF_CONVERTS_FROM_TEMPORARY: if (!check_trait_type (type1) diff --git a/gcc/cp/typeck2.cc b/gcc/cp/typeck2.cc index 688e9c1..739097a 100644 --- a/gcc/cp/typeck2.cc +++ b/gcc/cp/typeck2.cc @@ -597,7 +597,7 @@ split_nonconstant_init_1 (tree dest, tree init, bool last, if (prev == field_index) break; tree ptype = TREE_TYPE (prev); - if (type_build_dtor_call (ptype)) + if (TYPE_P (ptype) && type_build_dtor_call (ptype)) { tree pcref = build3 (COMPONENT_REF, ptype, dest, prev, NULL_TREE); @@ -1118,6 +1118,15 @@ array_string_literal_compatible_p (tree type, tree init) if (ordinary_char_type_p (to_char_type) && ordinary_char_type_p (from_char_type)) return true; + + /* P2513 (C++20/C++23): "an array of char or unsigned char may + be initialized by a UTF-8 string literal, or by such a string + literal enclosed in braces." */ + if (from_char_type == char8_type_node + && (to_char_type == char_type_node + || to_char_type == unsigned_char_type_node)) + return true; + return false; } diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi index 0449dc1..a0792fe 100644 --- a/gcc/doc/install.texi +++ b/gcc/doc/install.texi @@ -4560,6 +4560,15 @@ the GCC sources. Use the @option{--disable-sjlj-exceptions} and @option{--enable-newlib-io-long-long} options when configuring. +The @option{--with-arch} option may be specified to override the +default value for the @option{-march} option, and to also build +corresponding target libraries. +The default is @option{--with-arch=sm_30}. + +For example, if @option{--with-arch=sm_70} is specified, +@option{-march=sm_30} and @option{-march=sm_70} target libraries are +built, and code generation defaults to @option{-march=sm_70}. + @html <hr /> @end html diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index a134df7..4a01cfb 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -9863,7 +9863,7 @@ security-sensitive value is written to an output file See @uref{https://cwe.mitre.org/data/definitions/532.html, CWE-532: Information Exposure Through Log Files}. -@item Wanalyzer-exposure-through-uninit-copy +@item -Wanalyzer-exposure-through-uninit-copy @opindex Wanalyzer-exposure-through-uninit-copy @opindex Wno-analyzer-exposure-through-uninit-copy This warning requires both @option{-fanalyzer} and the use of a plugin @@ -11039,12 +11039,11 @@ location views are enabled. Produce compressed debug sections in DWARF format, if that is supported. If @var{type} is not given, the default type depends on the capabilities of the assembler and linker used. @var{type} may be one of -@samp{none} (don't compress debug sections), @samp{zlib} (use zlib -compression in ELF gABI format), or @samp{zlib-gnu} (use zlib -compression in traditional GNU format). If the linker doesn't support -writing compressed debug sections, the option is rejected. Otherwise, -if the assembler does not support them, @option{-gz} is silently ignored -when producing object files. +@samp{none} (don't compress debug sections), or @samp{zlib} (use zlib +compression in ELF gABI format). If the linker doesn't support writing +compressed debug sections, the option is rejected. Otherwise, if the +assembler does not support them, @option{-gz} is silently ignored when +producing object files. @item -femit-struct-debug-baseonly @opindex femit-struct-debug-baseonly @@ -19644,6 +19643,9 @@ and the features that they enable by default: @item @samp{armv8.7-a} @tab Armv8.7-A @tab @samp{armv8.6-a}, @samp{+ls64} @item @samp{armv8.8-a} @tab Armv8.8-a @tab @samp{armv8.7-a}, @samp{+mops} @item @samp{armv9-a} @tab Armv9-A @tab @samp{armv8.5-a}, @samp{+sve}, @samp{+sve2} +@item @samp{armv9.1-a} @tab Armv9.1-A @tab @samp{armv9-a}, @samp{+bf16}, @samp{+i8mm} +@item @samp{armv9.2-a} @tab Armv9.2-A @tab @samp{armv9.1-a}, @samp{+ls64} +@item @samp{armv9.3-a} @tab Armv9.3-A @tab @samp{armv9.2-a}, @samp{+mops} @item @samp{armv8-r} @tab Armv8-R @tab @samp{armv8-r} @end multitable @@ -19674,7 +19676,7 @@ performance of the code. Permissible values for this option are: @samp{cortex-a78}, @samp{cortex-a78ae}, @samp{cortex-a78c}, @samp{ares}, @samp{exynos-m1}, @samp{emag}, @samp{falkor}, @samp{neoverse-512tvb}, @samp{neoverse-e1}, @samp{neoverse-n1}, -@samp{neoverse-n2}, @samp{neoverse-v1}, @samp{qdf24xx}, +@samp{neoverse-n2}, @samp{neoverse-v1}, @samp{neoverse-v2}, @samp{qdf24xx}, @samp{saphira}, @samp{phecda}, @samp{xgene1}, @samp{vulcan}, @samp{octeontx}, @samp{octeontx81}, @samp{octeontx83}, @samp{octeontx2}, @samp{octeontx2t98}, @samp{octeontx2t96} @@ -28014,7 +28016,9 @@ supported. Generate code for the specified PTX ISA target architecture (e.g.@: @samp{sm_35}). Valid architecture strings are @samp{sm_30}, @samp{sm_35}, @samp{sm_53}, @samp{sm_70}, @samp{sm_75} and -@samp{sm_80}. The default target architecture is sm_30. +@samp{sm_80}. +The default depends on how the compiler has been configured, see +@option{--with-arch}. This option sets the value of the preprocessor macro @code{__PTX_SM__}; for instance, for @samp{sm_35}, it has the value diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi index 760ff95..52357cc 100644 --- a/gcc/doc/sourcebuild.texi +++ b/gcc/doc/sourcebuild.texi @@ -2447,7 +2447,7 @@ PowerPC target pre-defines macro _ARCH_PWR9 which means the @code{-mcpu} setting is Power9 or later. @end table -@subsection RISC-V specific attributes +@subsubsection RISC-V specific attributes @table @code diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index f5f8ac0..6985e62 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,119 @@ +2022-09-25 Mikael Morin <mikael@gcc.gnu.org> + + PR fortran/41453 + * trans-expr.cc (gfc_conv_procedure_call): Allow strictly + matching derived types. + +2022-09-25 Mikael Morin <mikael@gcc.gnu.org> + + PR fortran/41453 + PR fortran/99169 + * trans-expr.cc (gfc_conv_procedure_call): Remove conditions + on ALLOCATABLE and POINTER attributes guarding clobber + generation. + +2022-09-25 Mikael Morin <mikael@gcc.gnu.org> + + PR fortran/41453 + PR fortran/87401 + * trans-expr.cc (gfc_conv_procedure_call): Remove condition + disabling clobber generation for ASSOCIATE variables. + +2022-09-25 Mikael Morin <mikael@gcc.gnu.org> + + PR fortran/41453 + PR fortran/87395 + * trans-expr.cc (gfc_conv_procedure_call): Remove condition + on SAVE attribute guarding clobber generation. + +2022-09-25 Mikael Morin <mikael@gcc.gnu.org> + + PR fortran/41453 + PR fortran/87395 + * trans-expr.cc (gfc_conv_procedure_call): Remove condition + disabling clobber generation for dummy variables. Remove + obsolete comment. + +2022-09-25 Harald Anlauf <anlauf@gmx.de> + Mikael Morin <mikael@gcc.gnu.org> + + PR fortran/105012 + * trans-expr.cc (gfc_conv_procedure_call): Use dummy + information from associated_dummy if there is no information + from the procedure interface. + +2022-09-25 Mikael Morin <mikael@gcc.gnu.org> + + PR fortran/106817 + * trans-expr.cc (gfc_conv_procedure_call): Collect all clobbers + to their own separate block. Append the block of clobbers to + the procedure preliminary block after the argument evaluation + codes for all the arguments. + +2022-09-25 Mikael Morin <mikael@gcc.gnu.org> + + PR fortran/105012 + * trans-expr.cc (gfc_conv_procedure_call): Retrieve variable + from the just calculated variable reference. + +2022-09-25 Mikael Morin <mikael@gcc.gnu.org> + + * trans.h (gfc_conv_expr_reference): Remove add_clobber + argument. + * trans-expr.cc (gfc_conv_expr_reference): Ditto. Inline code + depending on add_clobber and conditions controlling it ... + (gfc_conv_procedure_call): ... to here. + +2022-09-22 José Rui Faustino de Sousa <jrfsousa@gmail.com> + + PR fortran/100103 + * trans-array.cc (gfc_is_reallocatable_lhs): Add select rank + temporary associate names as possible targets of automatic + reallocation. + +2022-09-22 Harald Anlauf <anlauf@gmx.de> + + PR fortran/82868 + * trans-decl.cc (generate_coarray_sym_init): Skip symbol + if attr.associate_var. + +2022-09-20 Tobias Burnus <tobias@codesourcery.com> + + PR fortran/104143 + * interface.cc (compare_parameter): Permit scalar args to + 'type(*), dimension(*)'. + +2022-09-20 Harald Anlauf <anlauf@gmx.de> + + PR fortran/106986 + * simplify.cc (gfc_simplify_findloc): Do not try to simplify + intrinsic FINDLOC when the ARRAY argument has a NULL shape. + +2022-09-20 Harald Anlauf <anlauf@gmx.de> + + PR fortran/106985 + * expr.cc (gfc_simplify_expr): Avoid NULL pointer dereference. + +2022-09-20 José Rui Faustino de Sousa <jrfsousa@gmail.com> + + PR fortran/100132 + * trans-types.cc (create_fn_spec): Fix function attributes when + passing polymorphic pointers. + +2022-09-20 Martin Liska <mliska@suse.cz> + + PR fortran/106636 + * gfortran.texi: Add back link to ISO_VARYING_STRING. + +2022-09-20 Martin Liska <mliska@suse.cz> + + * gfortran.texi: Replace "the the" with "the". + +2022-09-20 Martin Liska <mliska@suse.cz> + + PR fortran/106636 + * gfortran.texi: Remove 2 dead links. + 2022-09-19 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> * libgfortran.h: Declare GFC_FPE_AWAY. diff --git a/gcc/fortran/expr.cc b/gcc/fortran/expr.cc index be94c18..290ddf3 100644 --- a/gcc/fortran/expr.cc +++ b/gcc/fortran/expr.cc @@ -2287,7 +2287,8 @@ gfc_simplify_expr (gfc_expr *p, int type) initialization expression, or we want a subsection. */ if (p->symtree->n.sym->attr.flavor == FL_PARAMETER && (gfc_init_expr_flag || p->ref - || p->symtree->n.sym->value->expr_type != EXPR_ARRAY)) + || (p->symtree->n.sym->value + && p->symtree->n.sym->value->expr_type != EXPR_ARRAY))) { if (!simplify_parameter_variable (p, type)) return false; diff --git a/gcc/fortran/interface.cc b/gcc/fortran/interface.cc index 71eec78..d3e1995 100644 --- a/gcc/fortran/interface.cc +++ b/gcc/fortran/interface.cc @@ -2692,7 +2692,8 @@ compare_parameter (gfc_symbol *formal, gfc_expr *actual, - if the actual argument is (a substring of) an element of a non-assumed-shape/non-pointer/non-polymorphic array; or - (F2003) if the actual argument is of type character of default/c_char - kind. */ + kind. + - (F2018) if the dummy argument is type(*). */ is_pointer = actual->expr_type == EXPR_VARIABLE ? actual->symtree->n.sym->attr.pointer : false; @@ -2759,6 +2760,14 @@ compare_parameter (gfc_symbol *formal, gfc_expr *actual, if (ref == NULL && actual->expr_type != EXPR_NULL) { + if (actual->rank == 0 + && formal->ts.type == BT_ASSUMED + && formal->as + && formal->as->type == AS_ASSUMED_SIZE) + /* This is new in F2018, type(*) is new in TS29113, but gfortran does + not differentiate. Thus, if type(*) exists, it is valid; + otherwise, type(*) is already rejected. */ + return true; if (where && (!formal->attr.artificial || (!formal->maybe_array && !maybe_dummy_array_arg (actual)))) diff --git a/gcc/fortran/simplify.cc b/gcc/fortran/simplify.cc index 140c177..c0fbd0e 100644 --- a/gcc/fortran/simplify.cc +++ b/gcc/fortran/simplify.cc @@ -5895,6 +5895,7 @@ gfc_simplify_findloc (gfc_expr *array, gfc_expr *value, gfc_expr *dim, bool back_val = false; if (!is_constant_array_expr (array) + || array->shape == NULL || !gfc_is_constant_expr (dim)) return NULL; diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc index 0513495..795ce14 100644 --- a/gcc/fortran/trans-array.cc +++ b/gcc/fortran/trans-array.cc @@ -10378,7 +10378,7 @@ gfc_is_reallocatable_lhs (gfc_expr *expr) /* An allocatable class variable with no reference. */ if (sym->ts.type == BT_CLASS - && !sym->attr.associate_var + && (!sym->attr.associate_var || sym->attr.select_rank_temporary) && CLASS_DATA (sym)->attr.allocatable && expr->ref && ((expr->ref->type == REF_ARRAY && expr->ref->u.ar.type == AR_FULL @@ -10393,7 +10393,7 @@ gfc_is_reallocatable_lhs (gfc_expr *expr) /* An allocatable variable. */ if (sym->attr.allocatable - && !sym->attr.associate_var + && (!sym->attr.associate_var || sym->attr.select_rank_temporary) && expr->ref && expr->ref->type == REF_ARRAY && expr->ref->u.ar.type == AR_FULL) diff --git a/gcc/fortran/trans-decl.cc b/gcc/fortran/trans-decl.cc index 908a4c6..5d16d64 100644 --- a/gcc/fortran/trans-decl.cc +++ b/gcc/fortran/trans-decl.cc @@ -5529,6 +5529,7 @@ generate_coarray_sym_init (gfc_symbol *sym) if (sym->attr.dummy || sym->attr.allocatable || !sym->attr.codimension || sym->attr.use_assoc || !sym->attr.referenced + || sym->attr.associate_var || sym->attr.select_type_temporary) return; diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc index 7895d03..4f3ae82 100644 --- a/gcc/fortran/trans-expr.cc +++ b/gcc/fortran/trans-expr.cc @@ -6018,7 +6018,6 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym, gfc_charlen cl; gfc_expr *e; gfc_symbol *fsym; - stmtblock_t post; enum {MISSING = 0, ELEMENTAL, SCALAR, SCALAR_POINTER, ARRAY}; gfc_component *comp = NULL; int arglen; @@ -6062,7 +6061,9 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym, else info = NULL; + stmtblock_t post, clobbers; gfc_init_block (&post); + gfc_init_block (&clobbers); gfc_init_interface_mapping (&mapping); if (!comp) { @@ -6395,7 +6396,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym, && e->symtree->n.sym->attr.pointer)) && fsym && fsym->attr.target) /* Make sure the function only gets called once. */ - gfc_conv_expr_reference (&parmse, e, false); + gfc_conv_expr_reference (&parmse, e); else if (e->expr_type == EXPR_FUNCTION && e->symtree->n.sym->result && e->symtree->n.sym->result != e->symtree->n.sym @@ -6502,22 +6503,55 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym, } else { - bool add_clobber; - add_clobber = fsym && fsym->attr.intent == INTENT_OUT - && !fsym->attr.allocatable && !fsym->attr.pointer - && e->symtree && e->symtree->n.sym - && !e->symtree->n.sym->attr.dimension - && !e->symtree->n.sym->attr.pointer - && !e->symtree->n.sym->attr.allocatable - /* See PR 41453. */ - && !e->symtree->n.sym->attr.dummy - /* FIXME - PR 87395 and PR 41453 */ - && e->symtree->n.sym->attr.save == SAVE_NONE - && !e->symtree->n.sym->attr.associate_var - && e->ts.type != BT_CHARACTER && e->ts.type != BT_DERIVED - && e->ts.type != BT_CLASS && !sym->attr.elemental; - - gfc_conv_expr_reference (&parmse, e, add_clobber); + gfc_conv_expr_reference (&parmse, e); + + gfc_symbol *dsym = fsym; + gfc_dummy_arg *dummy; + + /* Use associated dummy as fallback for formal + argument if there is no explicit interface. */ + if (dsym == NULL + && (dummy = arg->associated_dummy) + && dummy->intrinsicness == GFC_NON_INTRINSIC_DUMMY_ARG + && dummy->u.non_intrinsic->sym) + dsym = dummy->u.non_intrinsic->sym; + + if (dsym + && dsym->attr.intent == INTENT_OUT + && !dsym->attr.allocatable + && !dsym->attr.pointer + && e->expr_type == EXPR_VARIABLE + && e->ref == NULL + && e->symtree + && e->symtree->n.sym + && !e->symtree->n.sym->attr.dimension + && e->ts.type != BT_CHARACTER + && e->ts.type != BT_CLASS + && (e->ts.type != BT_DERIVED + || (dsym->ts.type == BT_DERIVED + && e->ts.u.derived == dsym->ts.u.derived + /* Types with allocatable components are + excluded from clobbering because we need + the unclobbered pointers to free the + allocatable components in the callee. + Same goes for finalizable types or types + with finalizable components, we need to + pass the unclobbered values to the + finalization routines. + For parameterized types, it's less clear + but they may not have a constant size + so better exclude them in any case. */ + && !e->ts.u.derived->attr.alloc_comp + && !e->ts.u.derived->attr.pdt_type + && !gfc_is_finalizable (e->ts.u.derived, NULL))) + && !sym->attr.elemental) + { + tree var; + var = build_fold_indirect_ref_loc (input_location, + parmse.expr); + tree clobber = build_clobber (TREE_TYPE (var)); + gfc_add_modify (&clobbers, var, clobber); + } } /* Catch base objects that are not variables. */ if (e->ts.type == BT_CLASS @@ -7384,6 +7418,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym, vec_safe_push (arglist, parmse.expr); } + gfc_add_block_to_block (&se->pre, &clobbers); gfc_finish_interface_mapping (&mapping, &se->pre, &se->post); if (comp) @@ -9484,7 +9519,7 @@ gfc_conv_expr_type (gfc_se * se, gfc_expr * expr, tree type) values only. */ void -gfc_conv_expr_reference (gfc_se * se, gfc_expr * expr, bool add_clobber) +gfc_conv_expr_reference (gfc_se * se, gfc_expr * expr) { gfc_ss *ss; tree var; @@ -9524,16 +9559,6 @@ gfc_conv_expr_reference (gfc_se * se, gfc_expr * expr, bool add_clobber) gfc_add_block_to_block (&se->pre, &se->post); se->expr = var; } - else if (add_clobber && expr->ref == NULL) - { - tree clobber; - tree var; - /* FIXME: This fails if var is passed by reference, see PR - 41453. */ - var = expr->symtree->n.sym->backend_decl; - clobber = build_clobber (TREE_TYPE (var)); - gfc_add_modify (&se->pre, var, clobber); - } return; } diff --git a/gcc/fortran/trans-types.cc b/gcc/fortran/trans-types.cc index 0ea7c74..c062a5b 100644 --- a/gcc/fortran/trans-types.cc +++ b/gcc/fortran/trans-types.cc @@ -3054,12 +3054,23 @@ create_fn_spec (gfc_symbol *sym, tree fntype) for (f = gfc_sym_get_dummy_args (sym); f; f = f->next) if (spec_len < sizeof (spec)) { - if (!f->sym || f->sym->attr.pointer || f->sym->attr.target + bool is_class = false; + bool is_pointer = false; + + if (f->sym) + { + is_class = f->sym->ts.type == BT_CLASS && CLASS_DATA (f->sym) + && f->sym->attr.class_ok; + is_pointer = is_class ? CLASS_DATA (f->sym)->attr.class_pointer + : f->sym->attr.pointer; + } + + if (f->sym == NULL || is_pointer || f->sym->attr.target || f->sym->attr.external || f->sym->attr.cray_pointer || (f->sym->ts.type == BT_DERIVED && (f->sym->ts.u.derived->attr.proc_pointer_comp || f->sym->ts.u.derived->attr.pointer_comp)) - || (f->sym->ts.type == BT_CLASS + || (is_class && (CLASS_DATA (f->sym)->ts.u.derived->attr.proc_pointer_comp || CLASS_DATA (f->sym)->ts.u.derived->attr.pointer_comp)) || (f->sym->ts.type == BT_INTEGER && f->sym->ts.is_c_interop)) diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h index 03d5288..bc9035c 100644 --- a/gcc/fortran/trans.h +++ b/gcc/fortran/trans.h @@ -499,8 +499,7 @@ tree gfc_build_compare_string (tree, tree, tree, tree, int, enum tree_code); void gfc_conv_expr (gfc_se * se, gfc_expr * expr); void gfc_conv_expr_val (gfc_se * se, gfc_expr * expr); void gfc_conv_expr_lhs (gfc_se * se, gfc_expr * expr); -void gfc_conv_expr_reference (gfc_se * se, gfc_expr * expr, - bool add_clobber = false); +void gfc_conv_expr_reference (gfc_se * se, gfc_expr * expr); void gfc_conv_expr_type (gfc_se * se, gfc_expr *, tree); @@ -831,21 +831,11 @@ proper position among the other output files. */ #define LINK_COMPRESS_DEBUG_SPEC \ " %{gz*:%e-gz is not supported in this configuration} " #elif HAVE_LD_COMPRESS_DEBUG == 1 -/* GNU style on input, GNU ld options. Reject, not useful. */ -#define LINK_COMPRESS_DEBUG_SPEC \ - " %{gz*:%e-gz is not supported in this configuration} " -#elif HAVE_LD_COMPRESS_DEBUG == 2 -/* GNU style, GNU gold options. */ -#define LINK_COMPRESS_DEBUG_SPEC \ - " %{gz|gz=zlib-gnu:" LD_COMPRESS_DEBUG_OPTION "=zlib}" \ - " %{gz=none:" LD_COMPRESS_DEBUG_OPTION "=none}" \ - " %{gz=zlib:%e-gz=zlib is not supported in this configuration} " -#elif HAVE_LD_COMPRESS_DEBUG == 3 /* ELF gABI style. */ #define LINK_COMPRESS_DEBUG_SPEC \ " %{gz|gz=zlib:" LD_COMPRESS_DEBUG_OPTION "=zlib}" \ " %{gz=none:" LD_COMPRESS_DEBUG_OPTION "=none}" \ - " %{gz=zlib-gnu:" LD_COMPRESS_DEBUG_OPTION "=zlib-gnu} " + " %{gz=zlib-gnu:}" /* Ignore silently zlib-gnu option value. */ #else #error Unknown value for HAVE_LD_COMPRESS_DEBUG. #endif @@ -885,31 +875,25 @@ proper position among the other output files. */ #endif /* Assembler options for compressed debug sections. */ -#if HAVE_LD_COMPRESS_DEBUG < 2 +#if HAVE_LD_COMPRESS_DEBUG == 0 /* Reject if the linker cannot write compressed debug sections. */ #define ASM_COMPRESS_DEBUG_SPEC \ " %{gz*:%e-gz is not supported in this configuration} " -#else /* HAVE_LD_COMPRESS_DEBUG >= 2 */ +#else /* HAVE_LD_COMPRESS_DEBUG >= 1 */ #if HAVE_AS_COMPRESS_DEBUG == 0 /* No assembler support. Ignore silently. */ #define ASM_COMPRESS_DEBUG_SPEC \ " %{gz*:} " #elif HAVE_AS_COMPRESS_DEBUG == 1 -/* GNU style, GNU as options. */ -#define ASM_COMPRESS_DEBUG_SPEC \ - " %{gz|gz=zlib-gnu:" AS_COMPRESS_DEBUG_OPTION "}" \ - " %{gz=none:" AS_NO_COMPRESS_DEBUG_OPTION "}" \ - " %{gz=zlib:%e-gz=zlib is not supported in this configuration} " -#elif HAVE_AS_COMPRESS_DEBUG == 2 /* ELF gABI style. */ #define ASM_COMPRESS_DEBUG_SPEC \ " %{gz|gz=zlib:" AS_COMPRESS_DEBUG_OPTION "=zlib}" \ " %{gz=none:" AS_COMPRESS_DEBUG_OPTION "=none}" \ - " %{gz=zlib-gnu:" AS_COMPRESS_DEBUG_OPTION "=zlib-gnu} " + " %{gz=zlib-gnu:}" /* Ignore silently zlib-gnu option value. */ #else #error Unknown value for HAVE_AS_COMPRESS_DEBUG. #endif -#endif /* HAVE_LD_COMPRESS_DEBUG >= 2 */ +#endif /* HAVE_LD_COMPRESS_DEBUG >= 1 */ /* Define ASM_DEBUG_SPEC to be a spec suitable for translating '-g' to the assembler, when compiling assembly sources only. */ diff --git a/gcc/gimple-range-edge.cc b/gcc/gimple-range-edge.cc index 194e8f8..95deadf 100644 --- a/gcc/gimple-range-edge.cc +++ b/gcc/gimple-range-edge.cc @@ -43,7 +43,7 @@ gimple_outgoing_range_stmt_p (basic_block bb) if (!gsi_end_p (gsi)) { gimple *s = gsi_stmt (gsi); - if (is_a<gcond *> (s) && range_op_handler (s)) + if (is_a<gcond *> (s) && gimple_range_op_handler::supported_p (s)) return gsi_stmt (gsi); if (is_a <gswitch *> (s)) return gsi_stmt (gsi); diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc index a45fc7a..c381ef9 100644 --- a/gcc/gimple-range-fold.cc +++ b/gcc/gimple-range-fold.cc @@ -42,7 +42,7 @@ along with GCC; see the file COPYING3. If not see #include "vr-values.h" #include "range.h" #include "value-query.h" -#include "range-op.h" +#include "gimple-range-op.h" #include "gimple-range.h" // Construct a fur_source, and set the m_query field. @@ -463,73 +463,6 @@ gimple_range_adjustment (vrange &res, const gimple *stmt) } } -// Return the base of the RHS of an assignment. - -static tree -gimple_range_base_of_assignment (const gimple *stmt) -{ - gcc_checking_assert (gimple_code (stmt) == GIMPLE_ASSIGN); - tree op1 = gimple_assign_rhs1 (stmt); - if (gimple_assign_rhs_code (stmt) == ADDR_EXPR) - return get_base_address (TREE_OPERAND (op1, 0)); - return op1; -} - -// Return the first operand of this statement if it is a valid operand -// supported by ranges, otherwise return NULL_TREE. Special case is -// &(SSA_NAME expr), return the SSA_NAME instead of the ADDR expr. - -tree -gimple_range_operand1 (const gimple *stmt) -{ - gcc_checking_assert (range_op_handler (stmt)); - - switch (gimple_code (stmt)) - { - case GIMPLE_COND: - return gimple_cond_lhs (stmt); - case GIMPLE_ASSIGN: - { - tree base = gimple_range_base_of_assignment (stmt); - if (base && TREE_CODE (base) == MEM_REF) - { - // If the base address is an SSA_NAME, we return it - // here. This allows processing of the range of that - // name, while the rest of the expression is simply - // ignored. The code in range_ops will see the - // ADDR_EXPR and do the right thing. - tree ssa = TREE_OPERAND (base, 0); - if (TREE_CODE (ssa) == SSA_NAME) - return ssa; - } - return base; - } - default: - break; - } - return NULL; -} - -// Return the second operand of statement STMT, otherwise return NULL_TREE. - -tree -gimple_range_operand2 (const gimple *stmt) -{ - gcc_checking_assert (range_op_handler (stmt)); - - switch (gimple_code (stmt)) - { - case GIMPLE_COND: - return gimple_cond_rhs (stmt); - case GIMPLE_ASSIGN: - if (gimple_num_ops (stmt) >= 3) - return gimple_assign_rhs2 (stmt); - default: - break; - } - return NULL_TREE; -} - // Calculate a range for statement S and return it in R. If NAME is provided it // represents the SSA_NAME on the LHS of the statement. It is only required // if there is more than one lhs/output. If a range cannot @@ -551,8 +484,9 @@ fold_using_range::fold_stmt (vrange &r, gimple *s, fur_source &src, tree name) && gimple_assign_rhs_code (s) == ADDR_EXPR) return range_of_address (as_a <irange> (r), s, src); - if (range_op_handler (s)) - res = range_of_range_op (r, s, src); + gimple_range_op_handler handler (s); + if (handler) + res = range_of_range_op (r, handler, src); else if (is_a<gphi *>(s)) res = range_of_phi (r, as_a<gphi *> (s), src); else if (is_a<gcall *>(s)) @@ -587,17 +521,29 @@ fold_using_range::fold_stmt (vrange &r, gimple *s, fur_source &src, tree name) // If a range cannot be calculated, return false. bool -fold_using_range::range_of_range_op (vrange &r, gimple *s, fur_source &src) +fold_using_range::range_of_range_op (vrange &r, + gimple_range_op_handler &handler, + fur_source &src) { + gcc_checking_assert (handler); + gimple *s = handler.stmt (); tree type = gimple_range_type (s); if (!type) return false; - range_op_handler handler (s); - gcc_checking_assert (handler); - tree lhs = gimple_get_lhs (s); - tree op1 = gimple_range_operand1 (s); - tree op2 = gimple_range_operand2 (s); + tree lhs = handler.lhs (); + tree op1 = handler.operand1 (); + tree op2 = handler.operand2 (); + + // Certain types of builtin functions may have no arguments. + if (!op1) + { + Value_Range r1 (type); + if (!handler.fold_range (r, type, r1, r1)) + r.set_varying (type); + return true; + } + Value_Range range1 (TREE_TYPE (op1)); Value_Range range2 (op2 ? TREE_TYPE (op2) : TREE_TYPE (op1)); @@ -608,7 +554,8 @@ fold_using_range::range_of_range_op (vrange &r, gimple *s, fur_source &src) // Fold range, and register any dependency if available. Value_Range r2 (type); r2.set_varying (type); - handler.fold_range (r, type, range1, r2); + if (!handler.fold_range (r, type, range1, r2)) + r.set_varying (type); if (lhs && gimple_range_ssa_p (op1)) { if (src.gori ()) @@ -631,7 +578,8 @@ fold_using_range::range_of_range_op (vrange &r, gimple *s, fur_source &src) fputc ('\n', dump_file); } // Fold range, and register any dependency if available. - handler.fold_range (r, type, range1, range2, rel); + if (!handler.fold_range (r, type, range1, range2, rel)) + r.set_varying (type); if (irange::supports_p (type)) relation_fold_and_or (as_a <irange> (r), s, src); if (lhs) @@ -885,7 +833,7 @@ fold_using_range::range_of_phi (vrange &r, gphi *phi, fur_source &src) // If a range cannot be calculated, return false. bool -fold_using_range::range_of_call (vrange &r, gcall *call, fur_source &src) +fold_using_range::range_of_call (vrange &r, gcall *call, fur_source &) { tree type = gimple_range_type (call); if (!type) @@ -894,9 +842,7 @@ fold_using_range::range_of_call (vrange &r, gcall *call, fur_source &src) tree lhs = gimple_call_lhs (call); bool strict_overflow_p; - if (range_of_builtin_call (r, call, src)) - ; - else if (gimple_stmt_nonnegative_warnv_p (call, &strict_overflow_p)) + if (gimple_stmt_nonnegative_warnv_p (call, &strict_overflow_p)) r.set_nonnegative (type); else if (gimple_call_nonnull_result_p (call) || gimple_call_nonnull_arg (call)) @@ -914,387 +860,6 @@ fold_using_range::range_of_call (vrange &r, gcall *call, fur_source &src) return true; } -// Return the range of a __builtin_ubsan* in CALL and set it in R. -// CODE is the type of ubsan call (PLUS_EXPR, MINUS_EXPR or -// MULT_EXPR). - -void -fold_using_range::range_of_builtin_ubsan_call (irange &r, gcall *call, - tree_code code, fur_source &src) -{ - gcc_checking_assert (code == PLUS_EXPR || code == MINUS_EXPR - || code == MULT_EXPR); - tree type = gimple_range_type (call); - range_op_handler op (code, type); - gcc_checking_assert (op); - int_range_max ir0, ir1; - tree arg0 = gimple_call_arg (call, 0); - tree arg1 = gimple_call_arg (call, 1); - src.get_operand (ir0, arg0); - src.get_operand (ir1, arg1); - // Check for any relation between arg0 and arg1. - relation_kind relation = src.query_relation (arg0, arg1); - - bool saved_flag_wrapv = flag_wrapv; - // Pretend the arithmetic is wrapping. If there is any overflow, - // we'll complain, but will actually do wrapping operation. - flag_wrapv = 1; - op.fold_range (r, type, ir0, ir1, relation); - flag_wrapv = saved_flag_wrapv; - - // If for both arguments vrp_valueize returned non-NULL, this should - // have been already folded and if not, it wasn't folded because of - // overflow. Avoid removing the UBSAN_CHECK_* calls in that case. - if (r.singleton_p ()) - r.set_varying (type); -} - -// Return TRUE if we recognize the target character set and return the -// range for lower case and upper case letters. - -static bool -get_letter_range (tree type, irange &lowers, irange &uppers) -{ - // ASCII - int a = lang_hooks.to_target_charset ('a'); - int z = lang_hooks.to_target_charset ('z'); - int A = lang_hooks.to_target_charset ('A'); - int Z = lang_hooks.to_target_charset ('Z'); - - if ((z - a == 25) && (Z - A == 25)) - { - lowers = int_range<2> (build_int_cst (type, a), build_int_cst (type, z)); - uppers = int_range<2> (build_int_cst (type, A), build_int_cst (type, Z)); - return true; - } - // Unknown character set. - return false; -} - -// For a builtin in CALL, return a range in R if known and return -// TRUE. Otherwise return FALSE. - -bool -fold_using_range::range_of_builtin_call (vrange &r, gcall *call, - fur_source &src) -{ - combined_fn func = gimple_call_combined_fn (call); - if (func == CFN_LAST) - return false; - - tree type = gimple_range_type (call); - gcc_checking_assert (type); - - if (irange::supports_p (type)) - return range_of_builtin_int_call (as_a <irange> (r), call, src); - - return false; -} - -bool -fold_using_range::range_of_builtin_int_call (irange &r, gcall *call, - fur_source &src) -{ - combined_fn func = gimple_call_combined_fn (call); - if (func == CFN_LAST) - return false; - - tree type = gimple_range_type (call); - tree arg; - int mini, maxi, zerov = 0, prec; - scalar_int_mode mode; - - switch (func) - { - case CFN_BUILT_IN_CONSTANT_P: - { - arg = gimple_call_arg (call, 0); - Value_Range tmp (TREE_TYPE (arg)); - if (src.get_operand (tmp, arg) && tmp.singleton_p ()) - { - r.set (build_one_cst (type), build_one_cst (type)); - return true; - } - if (cfun->after_inlining) - { - r.set_zero (type); - return true; - } - break; - } - - case CFN_BUILT_IN_SIGNBIT: - { - arg = gimple_call_arg (call, 0); - frange tmp; - if (src.get_operand (tmp, arg)) - { - bool signbit; - if (tmp.signbit_p (signbit)) - { - if (signbit) - r.set_nonzero (type); - else - r.set_zero (type); - return true; - } - return false; - } - break; - } - - case CFN_BUILT_IN_TOUPPER: - { - arg = gimple_call_arg (call, 0); - // If the argument isn't compatible with the LHS, do nothing. - if (!range_compatible_p (type, TREE_TYPE (arg))) - return false; - if (!src.get_operand (r, arg)) - return false; - - int_range<3> lowers; - int_range<3> uppers; - if (!get_letter_range (type, lowers, uppers)) - return false; - - // Return the range passed in without any lower case characters, - // but including all the upper case ones. - lowers.invert (); - r.intersect (lowers); - r.union_ (uppers); - return true; - } - - case CFN_BUILT_IN_TOLOWER: - { - arg = gimple_call_arg (call, 0); - // If the argument isn't compatible with the LHS, do nothing. - if (!range_compatible_p (type, TREE_TYPE (arg))) - return false; - if (!src.get_operand (r, arg)) - return false; - - int_range<3> lowers; - int_range<3> uppers; - if (!get_letter_range (type, lowers, uppers)) - return false; - - // Return the range passed in without any upper case characters, - // but including all the lower case ones. - uppers.invert (); - r.intersect (uppers); - r.union_ (lowers); - return true; - } - - CASE_CFN_FFS: - CASE_CFN_POPCOUNT: - // __builtin_ffs* and __builtin_popcount* return [0, prec]. - arg = gimple_call_arg (call, 0); - prec = TYPE_PRECISION (TREE_TYPE (arg)); - mini = 0; - maxi = prec; - src.get_operand (r, arg); - // If arg is non-zero, then ffs or popcount are non-zero. - if (!range_includes_zero_p (&r)) - mini = 1; - // If some high bits are known to be zero, decrease the maximum. - if (!r.undefined_p ()) - { - if (TYPE_SIGN (r.type ()) == SIGNED) - range_cast (r, unsigned_type_for (r.type ())); - wide_int max = r.upper_bound (); - maxi = wi::floor_log2 (max) + 1; - } - r.set (build_int_cst (type, mini), build_int_cst (type, maxi)); - return true; - - CASE_CFN_PARITY: - r.set (build_zero_cst (type), build_one_cst (type)); - return true; - - CASE_CFN_CLZ: - // __builtin_c[lt]z* return [0, prec-1], except when the - // argument is 0, but that is undefined behavior. - // - // For __builtin_c[lt]z* consider argument of 0 always undefined - // behavior, for internal fns depending on C?Z_DEFINED_VALUE_AT_ZERO. - arg = gimple_call_arg (call, 0); - prec = TYPE_PRECISION (TREE_TYPE (arg)); - mini = 0; - maxi = prec - 1; - mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg)); - if (gimple_call_internal_p (call)) - { - if (optab_handler (clz_optab, mode) != CODE_FOR_nothing - && CLZ_DEFINED_VALUE_AT_ZERO (mode, zerov) == 2) - { - // Only handle the single common value. - if (zerov == prec) - maxi = prec; - else - // Magic value to give up, unless we can prove arg is non-zero. - mini = -2; - } - } - - src.get_operand (r, arg); - // From clz of minimum we can compute result maximum. - if (!r.undefined_p ()) - { - // From clz of minimum we can compute result maximum. - if (wi::gt_p (r.lower_bound (), 0, TYPE_SIGN (r.type ()))) - { - maxi = prec - 1 - wi::floor_log2 (r.lower_bound ()); - if (mini == -2) - mini = 0; - } - else if (!range_includes_zero_p (&r)) - { - mini = 0; - maxi = prec - 1; - } - if (mini == -2) - break; - // From clz of maximum we can compute result minimum. - wide_int max = r.upper_bound (); - int newmini = prec - 1 - wi::floor_log2 (max); - if (max == 0) - { - // If CLZ_DEFINED_VALUE_AT_ZERO is 2 with VALUE of prec, - // return [prec, prec], otherwise ignore the range. - if (maxi == prec) - mini = prec; - } - else - mini = newmini; - } - if (mini == -2) - break; - r.set (build_int_cst (type, mini), build_int_cst (type, maxi)); - return true; - - CASE_CFN_CTZ: - // __builtin_ctz* return [0, prec-1], except for when the - // argument is 0, but that is undefined behavior. - // - // For __builtin_ctz* consider argument of 0 always undefined - // behavior, for internal fns depending on CTZ_DEFINED_VALUE_AT_ZERO. - arg = gimple_call_arg (call, 0); - prec = TYPE_PRECISION (TREE_TYPE (arg)); - mini = 0; - maxi = prec - 1; - mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg)); - if (gimple_call_internal_p (call)) - { - if (optab_handler (ctz_optab, mode) != CODE_FOR_nothing - && CTZ_DEFINED_VALUE_AT_ZERO (mode, zerov) == 2) - { - // Handle only the two common values. - if (zerov == -1) - mini = -1; - else if (zerov == prec) - maxi = prec; - else - // Magic value to give up, unless we can prove arg is non-zero. - mini = -2; - } - } - src.get_operand (r, arg); - if (!r.undefined_p ()) - { - // If arg is non-zero, then use [0, prec - 1]. - if (!range_includes_zero_p (&r)) - { - mini = 0; - maxi = prec - 1; - } - // If some high bits are known to be zero, we can decrease - // the maximum. - wide_int max = r.upper_bound (); - if (max == 0) - { - // Argument is [0, 0]. If CTZ_DEFINED_VALUE_AT_ZERO - // is 2 with value -1 or prec, return [-1, -1] or [prec, prec]. - // Otherwise ignore the range. - if (mini == -1) - maxi = -1; - else if (maxi == prec) - mini = prec; - } - // If value at zero is prec and 0 is in the range, we can't lower - // the upper bound. We could create two separate ranges though, - // [0,floor_log2(max)][prec,prec] though. - else if (maxi != prec) - maxi = wi::floor_log2 (max); - } - if (mini == -2) - break; - r.set (build_int_cst (type, mini), build_int_cst (type, maxi)); - return true; - - CASE_CFN_CLRSB: - arg = gimple_call_arg (call, 0); - prec = TYPE_PRECISION (TREE_TYPE (arg)); - r.set (build_int_cst (type, 0), build_int_cst (type, prec - 1)); - return true; - case CFN_UBSAN_CHECK_ADD: - range_of_builtin_ubsan_call (r, call, PLUS_EXPR, src); - return true; - case CFN_UBSAN_CHECK_SUB: - range_of_builtin_ubsan_call (r, call, MINUS_EXPR, src); - return true; - case CFN_UBSAN_CHECK_MUL: - range_of_builtin_ubsan_call (r, call, MULT_EXPR, src); - return true; - - case CFN_GOACC_DIM_SIZE: - case CFN_GOACC_DIM_POS: - // Optimizing these two internal functions helps the loop - // optimizer eliminate outer comparisons. Size is [1,N] - // and pos is [0,N-1]. - { - bool is_pos = func == CFN_GOACC_DIM_POS; - int axis = oacc_get_ifn_dim_arg (call); - int size = oacc_get_fn_dim_size (current_function_decl, axis); - if (!size) - // If it's dynamic, the backend might know a hardware limitation. - size = targetm.goacc.dim_limit (axis); - - r.set (build_int_cst (type, is_pos ? 0 : 1), - size - ? build_int_cst (type, size - is_pos) : vrp_val_max (type)); - return true; - } - - case CFN_BUILT_IN_STRLEN: - if (tree lhs = gimple_call_lhs (call)) - if (ptrdiff_type_node - && (TYPE_PRECISION (ptrdiff_type_node) - == TYPE_PRECISION (TREE_TYPE (lhs)))) - { - tree type = TREE_TYPE (lhs); - tree max = vrp_val_max (ptrdiff_type_node); - wide_int wmax - = wi::to_wide (max, TYPE_PRECISION (TREE_TYPE (max))); - tree range_min = build_zero_cst (type); - // To account for the terminating NULL, the maximum length - // is one less than the maximum array size, which in turn - // is one less than PTRDIFF_MAX (or SIZE_MAX where it's - // smaller than the former type). - // FIXME: Use max_object_size() - 1 here. - tree range_max = wide_int_to_tree (type, wmax - 2); - r.set (range_min, range_max); - return true; - } - break; - default: - break; - } - return false; -} - - // Calculate a range for COND_EXPR statement S and return it in R. // If a range cannot be calculated, return false. @@ -1430,9 +995,10 @@ fold_using_range::relation_fold_and_or (irange& lhs_range, gimple *s, else if (code != BIT_IOR_EXPR && code != TRUTH_OR_EXPR) return; - tree lhs = gimple_get_lhs (s); - tree ssa1 = gimple_range_ssa_p (gimple_range_operand1 (s)); - tree ssa2 = gimple_range_ssa_p (gimple_range_operand2 (s)); + gimple_range_op_handler handler (s); + tree lhs = handler.lhs (); + tree ssa1 = gimple_range_ssa_p (handler.operand1 ()); + tree ssa2 = gimple_range_ssa_p (handler.operand2 ()); // Deal with || and && only when there is a full set of symbolics. if (!lhs || !ssa1 || !ssa2 @@ -1448,18 +1014,18 @@ fold_using_range::relation_fold_and_or (irange& lhs_range, gimple *s, gimple *ssa1_stmt = SSA_NAME_DEF_STMT (ssa1); gimple *ssa2_stmt = SSA_NAME_DEF_STMT (ssa2); - range_op_handler handler1 (SSA_NAME_DEF_STMT (ssa1)); - range_op_handler handler2 (SSA_NAME_DEF_STMT (ssa2)); + gimple_range_op_handler handler1 (ssa1_stmt); + gimple_range_op_handler handler2 (ssa2_stmt); // If either handler is not present, no relation can be found. if (!handler1 || !handler2) return; // Both stmts will need to have 2 ssa names in the stmt. - tree ssa1_dep1 = gimple_range_ssa_p (gimple_range_operand1 (ssa1_stmt)); - tree ssa1_dep2 = gimple_range_ssa_p (gimple_range_operand2 (ssa1_stmt)); - tree ssa2_dep1 = gimple_range_ssa_p (gimple_range_operand1 (ssa2_stmt)); - tree ssa2_dep2 = gimple_range_ssa_p (gimple_range_operand2 (ssa2_stmt)); + tree ssa1_dep1 = gimple_range_ssa_p (handler1.operand1 ()); + tree ssa1_dep2 = gimple_range_ssa_p (handler1.operand2 ()); + tree ssa2_dep1 = gimple_range_ssa_p (handler2.operand1 ()); + tree ssa2_dep2 = gimple_range_ssa_p (handler2.operand2 ()); if (!ssa1_dep1 || !ssa1_dep2 || !ssa2_dep1 || !ssa2_dep2) return; @@ -1516,7 +1082,7 @@ fur_source::register_outgoing_edges (gcond *s, irange &lhs_range, edge e0, edge tree name; basic_block bb = gimple_bb (s); - range_op_handler handler (s); + gimple_range_op_handler handler (s); if (!handler) return; @@ -1529,7 +1095,6 @@ fur_source::register_outgoing_edges (gcond *s, irange &lhs_range, edge e0, edge e0 = NULL; } - if (e1) { // If this edge is never taken, ignore it. @@ -1544,8 +1109,8 @@ fur_source::register_outgoing_edges (gcond *s, irange &lhs_range, edge e0, edge // First, register the gcond itself. This will catch statements like // if (a_2 < b_5) - tree ssa1 = gimple_range_ssa_p (gimple_range_operand1 (s)); - tree ssa2 = gimple_range_ssa_p (gimple_range_operand2 (s)); + tree ssa1 = gimple_range_ssa_p (handler.operand1 ()); + tree ssa2 = gimple_range_ssa_p (handler.operand2 ()); if (ssa1 && ssa2) { if (e0) @@ -1575,11 +1140,11 @@ fur_source::register_outgoing_edges (gcond *s, irange &lhs_range, edge e0, edge if (TREE_CODE (TREE_TYPE (name)) != BOOLEAN_TYPE) continue; gimple *stmt = SSA_NAME_DEF_STMT (name); - range_op_handler handler (stmt); + gimple_range_op_handler handler (stmt); if (!handler) continue; - tree ssa1 = gimple_range_ssa_p (gimple_range_operand1 (stmt)); - tree ssa2 = gimple_range_ssa_p (gimple_range_operand2 (stmt)); + tree ssa1 = gimple_range_ssa_p (handler.operand1 ()); + tree ssa2 = gimple_range_ssa_p (handler.operand2 ()); Value_Range r (TREE_TYPE (name)); if (ssa1 && ssa2) { @@ -1600,36 +1165,3 @@ fur_source::register_outgoing_edges (gcond *s, irange &lhs_range, edge e0, edge } } } - -// Given stmt S, fill VEC, up to VEC_SIZE elements, with relevant ssa-names -// on the statement. For efficiency, it is an error to not pass in enough -// elements for the vector. Return the number of ssa-names. - -unsigned -gimple_range_ssa_names (tree *vec, unsigned vec_size, gimple *stmt) -{ - tree ssa; - int count = 0; - - if (range_op_handler (stmt)) - { - gcc_checking_assert (vec_size >= 2); - if ((ssa = gimple_range_ssa_p (gimple_range_operand1 (stmt)))) - vec[count++] = ssa; - if ((ssa = gimple_range_ssa_p (gimple_range_operand2 (stmt)))) - vec[count++] = ssa; - } - else if (is_a<gassign *> (stmt) - && gimple_assign_rhs_code (stmt) == COND_EXPR) - { - gcc_checking_assert (vec_size >= 3); - gassign *st = as_a<gassign *> (stmt); - if ((ssa = gimple_range_ssa_p (gimple_assign_rhs1 (st)))) - vec[count++] = ssa; - if ((ssa = gimple_range_ssa_p (gimple_assign_rhs2 (st)))) - vec[count++] = ssa; - if ((ssa = gimple_range_ssa_p (gimple_assign_rhs3 (st)))) - vec[count++] = ssa; - } - return count; -} diff --git a/gcc/gimple-range-fold.h b/gcc/gimple-range-fold.h index f2eab72..d1ed2bc 100644 --- a/gcc/gimple-range-fold.h +++ b/gcc/gimple-range-fold.h @@ -96,15 +96,6 @@ range_compatible_p (tree type1, tree type2) && TYPE_SIGN (type1) == TYPE_SIGN (type2)); } -extern tree gimple_range_operand1 (const gimple *s); -extern tree gimple_range_operand2 (const gimple *s); - -// Given stmt S, fill VEC, up to VEC_SIZE elements, with relevant ssa-names -// on the statement. For efficiency, it is an error to not pass in enough -// elements for the vector. Return the number of ssa-names. - -unsigned gimple_range_ssa_names (tree *vec, unsigned vec_size, gimple *stmt); - // Source of all operands for fold_using_range and gori_compute. // It abstracts out the source of an operand so it can come from a stmt or // and edge or anywhere a derived class of fur_source wants. @@ -169,14 +160,11 @@ public: bool fold_stmt (vrange &r, gimple *s, class fur_source &src, tree name = NULL_TREE); protected: - bool range_of_range_op (vrange &r, gimple *s, fur_source &src); + bool range_of_range_op (vrange &r, gimple_range_op_handler &handler, + fur_source &src); bool range_of_call (vrange &r, gcall *call, fur_source &src); bool range_of_cond_expr (vrange &r, gassign* cond, fur_source &src); bool range_of_address (irange &r, gimple *s, fur_source &src); - bool range_of_builtin_call (vrange &r, gcall *call, fur_source &src); - bool range_of_builtin_int_call (irange &r, gcall *call, fur_source &src); - void range_of_builtin_ubsan_call (irange &r, gcall *call, tree_code code, - fur_source &src); bool range_of_phi (vrange &r, gphi *phi, fur_source &src); void range_of_ssa_name_with_loop_info (vrange &, tree, class loop *, gphi *, fur_source &src); diff --git a/gcc/gimple-range-gori.cc b/gcc/gimple-range-gori.cc index 957b8d5..40b2f2f 100644 --- a/gcc/gimple-range-gori.cc +++ b/gcc/gimple-range-gori.cc @@ -29,83 +29,6 @@ along with GCC; see the file COPYING3. If not see #include "gimple-pretty-print.h" #include "gimple-range.h" -// Calculate what we can determine of the range of this unary -// statement's operand if the lhs of the expression has the range -// LHS_RANGE. Return false if nothing can be determined. - -bool -gimple_range_calc_op1 (vrange &r, const gimple *stmt, const vrange &lhs_range) -{ - gcc_checking_assert (gimple_num_ops (stmt) < 3); - // Give up on empty ranges. - if (lhs_range.undefined_p ()) - return false; - - // Unary operations require the type of the first operand in the - // second range position. - tree type = TREE_TYPE (gimple_range_operand1 (stmt)); - Value_Range type_range (type); - type_range.set_varying (type); - return range_op_handler (stmt).op1_range (r, type, lhs_range, type_range); -} - -// Calculate what we can determine of the range of this statement's -// first operand if the lhs of the expression has the range LHS_RANGE -// and the second operand has the range OP2_RANGE. Return false if -// nothing can be determined. - -bool -gimple_range_calc_op1 (vrange &r, const gimple *stmt, - const vrange &lhs_range, const vrange &op2_range) -{ - // Give up on empty ranges. - if (lhs_range.undefined_p ()) - return false; - - // Unary operation are allowed to pass a range in for second operand - // as there are often additional restrictions beyond the type which - // can be imposed. See operator_cast::op1_range(). - tree type = TREE_TYPE (gimple_range_operand1 (stmt)); - // If op2 is undefined, solve as if it is varying. - if (op2_range.undefined_p ()) - { - // This is sometimes invoked on single operand stmts. - if (gimple_num_ops (stmt) < 3) - return false; - tree op2_type = TREE_TYPE (gimple_range_operand2 (stmt)); - Value_Range trange (op2_type); - trange.set_varying (op2_type); - return range_op_handler (stmt).op1_range (r, type, lhs_range, trange); - } - return range_op_handler (stmt).op1_range (r, type, lhs_range, op2_range); -} - -// Calculate what we can determine of the range of this statement's -// second operand if the lhs of the expression has the range LHS_RANGE -// and the first operand has the range OP1_RANGE. Return false if -// nothing can be determined. - -bool -gimple_range_calc_op2 (vrange &r, const gimple *stmt, - const vrange &lhs_range, const vrange &op1_range) -{ - // Give up on empty ranges. - if (lhs_range.undefined_p ()) - return false; - - tree type = TREE_TYPE (gimple_range_operand2 (stmt)); - // If op1 is undefined, solve as if it is varying. - if (op1_range.undefined_p ()) - { - tree op1_type = TREE_TYPE (gimple_range_operand1 (stmt)); - Value_Range trange (op1_type); - trange.set_varying (op1_type); - return range_op_handler (stmt).op2_range (r, type, lhs_range, trange); - } - return range_op_handler (stmt).op2_range (r, type, lhs_range, - op1_range); -} - // Return TRUE if GS is a logical && or || expression. static inline bool @@ -695,17 +618,18 @@ gori_compute::compute_operand_range (vrange &r, gimple *stmt, if (is_a<gswitch *> (stmt)) return compute_operand_range_switch (r, as_a<gswitch *> (stmt), lhs, name, src); - if (!range_op_handler (stmt)) + gimple_range_op_handler handler (stmt); + if (!handler) return false; - tree op1 = gimple_range_ssa_p (gimple_range_operand1 (stmt)); - tree op2 = gimple_range_ssa_p (gimple_range_operand2 (stmt)); + tree op1 = gimple_range_ssa_p (handler.operand1 ()); + tree op2 = gimple_range_ssa_p (handler.operand2 ()); // Handle end of lookup first. if (op1 == name) - return compute_operand1_range (r, stmt, lhs, name, src); + return compute_operand1_range (r, handler, lhs, name, src); if (op2 == name) - return compute_operand2_range (r, stmt, lhs, name, src); + return compute_operand2_range (r, handler, lhs, name, src); // NAME is not in this stmt, but one of the names in it ought to be // derived from it. @@ -733,10 +657,10 @@ gori_compute::compute_operand_range (vrange &r, gimple *stmt, tree type = TREE_TYPE (name); Value_Range op1_trange (type), op1_frange (type); Value_Range op2_trange (type), op2_frange (type); - compute_logical_operands (op1_trange, op1_frange, stmt, + compute_logical_operands (op1_trange, op1_frange, handler, as_a <irange> (lhs), name, src, op1, op1_in_chain); - compute_logical_operands (op2_trange, op2_frange, stmt, + compute_logical_operands (op2_trange, op2_frange, handler, as_a <irange> (lhs), name, src, op2, op2_in_chain); res = logical_combine (r, @@ -748,11 +672,11 @@ gori_compute::compute_operand_range (vrange &r, gimple *stmt, } // Follow the appropriate operands now. else if (op1_in_chain && op2_in_chain) - res = compute_operand1_and_operand2_range (r, stmt, lhs, name, src); + res = compute_operand1_and_operand2_range (r, handler, lhs, name, src); else if (op1_in_chain) - res = compute_operand1_range (r, stmt, lhs, name, src); + res = compute_operand1_range (r, handler, lhs, name, src); else if (op2_in_chain) - res = compute_operand2_range (r, stmt, lhs, name, src); + res = compute_operand2_range (r, handler, lhs, name, src); else gcc_unreachable (); @@ -944,13 +868,14 @@ gori_compute::logical_combine (vrange &r, enum tree_code code, void gori_compute::compute_logical_operands (vrange &true_range, vrange &false_range, - gimple *stmt, + gimple_range_op_handler &handler, const irange &lhs, tree name, fur_source &src, tree op, bool op_in_chain) { + gimple *stmt = handler.stmt (); gimple *src_stmt = gimple_range_ssa_p (op) ? SSA_NAME_DEF_STMT (op) : NULL; - if (!op_in_chain || !src_stmt || chain_import_p (gimple_get_lhs (stmt), op)) + if (!op_in_chain || !src_stmt || chain_import_p (handler.lhs (), op)) { // If op is not in the def chain, or defined in this block, // use its known value on entry to the block. @@ -999,12 +924,15 @@ gori_compute::compute_logical_operands (vrange &true_range, vrange &false_range, // R, or false if no range could be calculated. bool -gori_compute::compute_operand1_range (vrange &r, gimple *stmt, +gori_compute::compute_operand1_range (vrange &r, + gimple_range_op_handler &handler, const vrange &lhs, tree name, fur_source &src) { - tree op1 = gimple_range_operand1 (stmt); - tree op2 = gimple_range_operand2 (stmt); + gimple *stmt = handler.stmt (); + tree op1 = handler.operand1 (); + tree op2 = handler.operand2 (); + Value_Range op1_range (TREE_TYPE (op1)); Value_Range tmp (TREE_TYPE (op1)); Value_Range op2_range (op2 ? TREE_TYPE (op2) : TREE_TYPE (op1)); @@ -1016,7 +944,7 @@ gori_compute::compute_operand1_range (vrange &r, gimple *stmt, if (op2) { src.get_operand (op2_range, op2); - if (!gimple_range_calc_op1 (tmp, stmt, lhs, op2_range)) + if (!handler.calc_op1 (tmp, lhs, op2_range)) return false; } else @@ -1024,7 +952,7 @@ gori_compute::compute_operand1_range (vrange &r, gimple *stmt, // We pass op1_range to the unary operation. Nomally it's a // hidden range_for_type parameter, but sometimes having the // actual range can result in better information. - if (!gimple_range_calc_op1 (tmp, stmt, lhs, op1_range)) + if (!handler.calc_op1 (tmp, lhs, op1_range)) return false; } @@ -1079,12 +1007,15 @@ gori_compute::compute_operand1_range (vrange &r, gimple *stmt, // R, or false if no range could be calculated. bool -gori_compute::compute_operand2_range (vrange &r, gimple *stmt, +gori_compute::compute_operand2_range (vrange &r, + gimple_range_op_handler &handler, const vrange &lhs, tree name, fur_source &src) { - tree op1 = gimple_range_operand1 (stmt); - tree op2 = gimple_range_operand2 (stmt); + gimple *stmt = handler.stmt (); + tree op1 = handler.operand1 (); + tree op2 = handler.operand2 (); + Value_Range op1_range (TREE_TYPE (op1)); Value_Range op2_range (TREE_TYPE (op2)); Value_Range tmp (TREE_TYPE (op2)); @@ -1093,7 +1024,7 @@ gori_compute::compute_operand2_range (vrange &r, gimple *stmt, src.get_operand (op2_range, op2); // Intersect with range for op2 based on lhs and op1. - if (!gimple_range_calc_op2 (tmp, stmt, lhs, op1_range)) + if (!handler.calc_op2 (tmp, lhs, op1_range)) return false; unsigned idx; @@ -1148,7 +1079,8 @@ gori_compute::compute_operand2_range (vrange &r, gimple *stmt, bool gori_compute::compute_operand1_and_operand2_range (vrange &r, - gimple *stmt, + gimple_range_op_handler + &handler, const vrange &lhs, tree name, fur_source &src) @@ -1157,11 +1089,11 @@ gori_compute::compute_operand1_and_operand2_range (vrange &r, // Calculate a good a range for op2. Since op1 == op2, this will // have already included whatever the actual range of name is. - if (!compute_operand2_range (op_range, stmt, lhs, name, src)) + if (!compute_operand2_range (op_range, handler, lhs, name, src)) return false; // Now get the range thru op1. - if (!compute_operand1_range (r, stmt, lhs, name, src)) + if (!compute_operand1_range (r, handler, lhs, name, src)) return false; // Both operands have to be simultaneously true, so perform an intersection. diff --git a/gcc/gimple-range-gori.h b/gcc/gimple-range-gori.h index 3d57ab9..0c776ef 100644 --- a/gcc/gimple-range-gori.h +++ b/gcc/gimple-range-gori.h @@ -170,17 +170,18 @@ private: tree name, class fur_source &src); bool compute_operand_range_switch (vrange &r, gswitch *s, const vrange &lhs, tree name, fur_source &src); - bool compute_operand1_range (vrange &r, gimple *stmt, const vrange &lhs, - tree name, fur_source &src); - bool compute_operand2_range (vrange &r, gimple *stmt, const vrange &lhs, - tree name, fur_source &src); - bool compute_operand1_and_operand2_range (vrange &r, gimple *stmt, + bool compute_operand1_range (vrange &r, gimple_range_op_handler &handler, + const vrange &lhs, tree name, fur_source &src); + bool compute_operand2_range (vrange &r, gimple_range_op_handler &handler, + const vrange &lhs, tree name, fur_source &src); + bool compute_operand1_and_operand2_range (vrange &r, + gimple_range_op_handler &handler, const vrange &lhs, tree name, fur_source &src); void compute_logical_operands (vrange &true_range, vrange &false_range, - gimple *stmt, const irange &lhs, - tree name, fur_source &src, tree op, - bool op_in_chain); + gimple_range_op_handler &handler, + const irange &lhs, tree name, fur_source &src, + tree op, bool op_in_chain); bool logical_combine (vrange &r, enum tree_code code, const irange &lhs, const vrange &op1_true, const vrange &op1_false, const vrange &op2_true, const vrange &op2_false); @@ -192,16 +193,6 @@ private: int m_not_executable_flag; }; -// These routines provide a GIMPLE interface to the range-ops code. -extern bool gimple_range_calc_op1 (vrange &r, const gimple *s, - const vrange &lhs_range); -extern bool gimple_range_calc_op1 (vrange &r, const gimple *s, - const vrange &lhs_range, - const vrange &op2_range); -extern bool gimple_range_calc_op2 (vrange &r, const gimple *s, - const vrange &lhs_range, - const vrange &op1_range); - // For each name that is an import into BB's exports.. #define FOR_EACH_GORI_IMPORT_NAME(gori, bb, name) \ for (gori_export_iterator iter ((gori).imports ((bb))); \ diff --git a/gcc/gimple-range-op.cc b/gcc/gimple-range-op.cc new file mode 100644 index 0000000..d7c6dfa --- /dev/null +++ b/gcc/gimple-range-op.cc @@ -0,0 +1,820 @@ +/* Code for GIMPLE range op related routines. + Copyright (C) 2019-2022 Free Software Foundation, Inc. + Contributed by Andrew MacLeod <amacleod@redhat.com> + and Aldy Hernandez <aldyh@redhat.com>. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "backend.h" +#include "insn-codes.h" +#include "tree.h" +#include "gimple.h" +#include "ssa.h" +#include "gimple-pretty-print.h" +#include "optabs-tree.h" +#include "gimple-iterator.h" +#include "gimple-fold.h" +#include "wide-int.h" +#include "fold-const.h" +#include "case-cfn-macros.h" +#include "omp-general.h" +#include "cfgloop.h" +#include "tree-ssa-loop.h" +#include "tree-scalar-evolution.h" +#include "langhooks.h" +#include "vr-values.h" +#include "range.h" +#include "value-query.h" +#include "gimple-range.h" + +// Given stmt S, fill VEC, up to VEC_SIZE elements, with relevant ssa-names +// on the statement. For efficiency, it is an error to not pass in enough +// elements for the vector. Return the number of ssa-names. + +unsigned +gimple_range_ssa_names (tree *vec, unsigned vec_size, gimple *stmt) +{ + tree ssa; + int count = 0; + + gimple_range_op_handler handler (stmt); + if (handler) + { + gcc_checking_assert (vec_size >= 2); + if ((ssa = gimple_range_ssa_p (handler.operand1 ()))) + vec[count++] = ssa; + if ((ssa = gimple_range_ssa_p (handler.operand2 ()))) + vec[count++] = ssa; + } + else if (is_a<gassign *> (stmt) + && gimple_assign_rhs_code (stmt) == COND_EXPR) + { + gcc_checking_assert (vec_size >= 3); + gassign *st = as_a<gassign *> (stmt); + if ((ssa = gimple_range_ssa_p (gimple_assign_rhs1 (st)))) + vec[count++] = ssa; + if ((ssa = gimple_range_ssa_p (gimple_assign_rhs2 (st)))) + vec[count++] = ssa; + if ((ssa = gimple_range_ssa_p (gimple_assign_rhs3 (st)))) + vec[count++] = ssa; + } + return count; +} + +// Return the base of the RHS of an assignment. + +static tree +gimple_range_base_of_assignment (const gimple *stmt) +{ + gcc_checking_assert (gimple_code (stmt) == GIMPLE_ASSIGN); + tree op1 = gimple_assign_rhs1 (stmt); + if (gimple_assign_rhs_code (stmt) == ADDR_EXPR) + return get_base_address (TREE_OPERAND (op1, 0)); + return op1; +} + +// If statement is supported by range-ops, set the CODE and return the TYPE. + +static tree +get_code_and_type (gimple *s, enum tree_code &code) +{ + tree type = NULL_TREE; + code = NOP_EXPR; + + if (const gassign *ass = dyn_cast<const gassign *> (s)) + { + code = gimple_assign_rhs_code (ass); + // The LHS of a comparison is always an int, so we must look at + // the operands. + if (TREE_CODE_CLASS (code) == tcc_comparison) + type = TREE_TYPE (gimple_assign_rhs1 (ass)); + else + type = TREE_TYPE (gimple_assign_lhs (ass)); + } + else if (const gcond *cond = dyn_cast<const gcond *> (s)) + { + code = gimple_cond_code (cond); + type = TREE_TYPE (gimple_cond_lhs (cond)); + } + return type; +} + +// If statement S has a supported range_op handler return TRUE. + +bool +gimple_range_op_handler::supported_p (gimple *s) +{ + enum tree_code code; + tree type = get_code_and_type (s, code); + if (type && range_op_handler (code, type)) + return true; + if (is_a <gcall *> (s) && gimple_range_op_handler (s)) + return true; + return false; +} + +// Construct a handler object for statement S. + +gimple_range_op_handler::gimple_range_op_handler (gimple *s) +{ + enum tree_code code; + tree type = get_code_and_type (s, code); + m_stmt = s; + m_op1 = NULL_TREE; + m_op2 = NULL_TREE; + if (type) + set_op_handler (code, type); + + if (m_valid) + switch (gimple_code (m_stmt)) + { + case GIMPLE_COND: + m_op1 = gimple_cond_lhs (m_stmt); + m_op2 = gimple_cond_rhs (m_stmt); + return; + case GIMPLE_ASSIGN: + m_op1 = gimple_range_base_of_assignment (m_stmt); + if (m_op1 && TREE_CODE (m_op1) == MEM_REF) + { + // If the base address is an SSA_NAME, we return it + // here. This allows processing of the range of that + // name, while the rest of the expression is simply + // ignored. The code in range_ops will see the + // ADDR_EXPR and do the right thing. + tree ssa = TREE_OPERAND (m_op1, 0); + if (TREE_CODE (ssa) == SSA_NAME) + m_op1 = ssa; + } + if (gimple_num_ops (m_stmt) >= 3) + m_op2 = gimple_assign_rhs2 (m_stmt); + return; + default: + gcc_unreachable (); + return; + } + // If no range-op table entry handled this stmt, check for other supported + // statements. + if (is_a <gcall *> (m_stmt)) + maybe_builtin_call (); +} + +// Calculate what we can determine of the range of this unary +// statement's operand if the lhs of the expression has the range +// LHS_RANGE. Return false if nothing can be determined. + +bool +gimple_range_op_handler::calc_op1 (vrange &r, const vrange &lhs_range) +{ + gcc_checking_assert (gimple_num_ops (m_stmt) < 3); + // Give up on empty ranges. + if (lhs_range.undefined_p ()) + return false; + + // Unary operations require the type of the first operand in the + // second range position. + tree type = TREE_TYPE (operand1 ()); + Value_Range type_range (type); + type_range.set_varying (type); + return op1_range (r, type, lhs_range, type_range); +} + +// Calculate what we can determine of the range of this statement's +// first operand if the lhs of the expression has the range LHS_RANGE +// and the second operand has the range OP2_RANGE. Return false if +// nothing can be determined. + +bool +gimple_range_op_handler::calc_op1 (vrange &r, const vrange &lhs_range, + const vrange &op2_range) +{ + // Give up on empty ranges. + if (lhs_range.undefined_p ()) + return false; + + // Unary operation are allowed to pass a range in for second operand + // as there are often additional restrictions beyond the type which + // can be imposed. See operator_cast::op1_range(). + tree type = TREE_TYPE (operand1 ()); + // If op2 is undefined, solve as if it is varying. + if (op2_range.undefined_p ()) + { + if (gimple_num_ops (m_stmt) < 3) + return false; + tree op2_type; + // This is sometimes invoked on single operand stmts. + if (operand2 ()) + op2_type = TREE_TYPE (operand2 ()); + else + op2_type = TREE_TYPE (operand1 ()); + Value_Range trange (op2_type); + trange.set_varying (op2_type); + return op1_range (r, type, lhs_range, trange); + } + return op1_range (r, type, lhs_range, op2_range); +} + +// Calculate what we can determine of the range of this statement's +// second operand if the lhs of the expression has the range LHS_RANGE +// and the first operand has the range OP1_RANGE. Return false if +// nothing can be determined. + +bool +gimple_range_op_handler::calc_op2 (vrange &r, const vrange &lhs_range, + const vrange &op1_range) +{ + // Give up on empty ranges. + if (lhs_range.undefined_p ()) + return false; + + tree type = TREE_TYPE (operand2 ()); + // If op1 is undefined, solve as if it is varying. + if (op1_range.undefined_p ()) + { + tree op1_type = TREE_TYPE (operand1 ()); + Value_Range trange (op1_type); + trange.set_varying (op1_type); + return op2_range (r, type, lhs_range, trange); + } + return op2_range (r, type, lhs_range, op1_range); +} + +// -------------------------------------------------------------------- + +// Implement range operator for float CFN_BUILT_IN_CONSTANT_P. +class cfn_constant_float_p : public range_operator_float +{ +public: + using range_operator_float::fold_range; + virtual bool fold_range (irange &r, tree type, const frange &lh, + const irange &, relation_kind) const + { + if (lh.singleton_p ()) + { + r.set (build_one_cst (type), build_one_cst (type)); + return true; + } + if (cfun->after_inlining) + { + r.set_zero (type); + return true; + } + return false; + } +} op_cfn_constant_float_p; + +// Implement range operator for integral CFN_BUILT_IN_CONSTANT_P. +class cfn_constant_p : public range_operator +{ +public: + using range_operator::fold_range; + virtual bool fold_range (irange &r, tree type, const irange &lh, + const irange &, relation_kind) const + { + if (lh.singleton_p ()) + { + r.set (build_one_cst (type), build_one_cst (type)); + return true; + } + if (cfun->after_inlining) + { + r.set_zero (type); + return true; + } + return false; + } +} op_cfn_constant_p; + +// Implement range operator for CFN_BUILT_IN_SIGNBIT. +class cfn_signbit : public range_operator_float +{ +public: + using range_operator_float::fold_range; + virtual bool fold_range (irange &r, tree type, const frange &lh, + const irange &, relation_kind) const + { + bool signbit; + if (lh.signbit_p (signbit)) + { + if (signbit) + r.set_nonzero (type); + else + r.set_zero (type); + return true; + } + return false; + } +} op_cfn_signbit; + +// Implement range operator for CFN_BUILT_IN_TOUPPER and CFN_BUILT_IN_TOLOWER. +class cfn_toupper_tolower : public range_operator +{ +public: + using range_operator::fold_range; + cfn_toupper_tolower (bool toupper) { m_toupper = toupper; } + virtual bool fold_range (irange &r, tree type, const irange &lh, + const irange &, relation_kind) const; +private: + bool get_letter_range (tree type, irange &lowers, irange &uppers) const; + bool m_toupper; +} op_cfn_toupper (true), op_cfn_tolower (false); + +// Return TRUE if we recognize the target character set and return the +// range for lower case and upper case letters. + +bool +cfn_toupper_tolower::get_letter_range (tree type, irange &lowers, + irange &uppers) const +{ + // ASCII + int a = lang_hooks.to_target_charset ('a'); + int z = lang_hooks.to_target_charset ('z'); + int A = lang_hooks.to_target_charset ('A'); + int Z = lang_hooks.to_target_charset ('Z'); + + if ((z - a == 25) && (Z - A == 25)) + { + lowers = int_range<2> (build_int_cst (type, a), build_int_cst (type, z)); + uppers = int_range<2> (build_int_cst (type, A), build_int_cst (type, Z)); + return true; + } + // Unknown character set. + return false; +} + +bool +cfn_toupper_tolower::fold_range (irange &r, tree type, const irange &lh, + const irange &, relation_kind) const +{ + int_range<3> lowers; + int_range<3> uppers; + if (!get_letter_range (type, lowers, uppers)) + return false; + + r = lh; + if (m_toupper) + { + // Return the range passed in without any lower case characters, + // but including all the upper case ones. + lowers.invert (); + r.intersect (lowers); + r.union_ (uppers); + } + else + { + // Return the range passed in without any lower case characters, + // but including all the upper case ones. + uppers.invert (); + r.intersect (uppers); + r.union_ (lowers); + } + return true; +} + +// Implement range operator for CFN_BUILT_IN_FFS and CFN_BUILT_IN_POPCOUNT. +class cfn_popcount : public range_operator +{ +public: + using range_operator::fold_range; + virtual bool fold_range (irange &r, tree type, const irange &lh, + const irange &, relation_kind) const + { + if (lh.undefined_p ()) + return false; + // __builtin_ffs* and __builtin_popcount* return [0, prec]. + int prec = TYPE_PRECISION (lh.type ()); + // If arg is non-zero, then ffs or popcount are non-zero. + int mini = range_includes_zero_p (&lh) ? 0 : 1; + int maxi = prec; + + // If some high bits are known to be zero, decrease the maximum. + int_range_max tmp = lh; + if (TYPE_SIGN (tmp.type ()) == SIGNED) + range_cast (tmp, unsigned_type_for (tmp.type ())); + wide_int max = tmp.upper_bound (); + maxi = wi::floor_log2 (max) + 1; + r.set (build_int_cst (type, mini), build_int_cst (type, maxi)); + return true; + } +} op_cfn_popcount; + +// Implement range operator for CFN_BUILT_IN_CLZ +class cfn_clz : public range_operator +{ +public: + cfn_clz (bool internal) { m_gimple_call_internal_p = internal; } + using range_operator::fold_range; + virtual bool fold_range (irange &r, tree type, const irange &lh, + const irange &, relation_kind) const; +private: + bool m_gimple_call_internal_p; +} op_cfn_clz (false), op_cfn_clz_internal (true); + +bool +cfn_clz::fold_range (irange &r, tree type, const irange &lh, + const irange &, relation_kind) const +{ + // __builtin_c[lt]z* return [0, prec-1], except when the + // argument is 0, but that is undefined behavior. + // + // For __builtin_c[lt]z* consider argument of 0 always undefined + // behavior, for internal fns depending on C?Z_DEFINED_ALUE_AT_ZERO. + if (lh.undefined_p ()) + return false; + int prec = TYPE_PRECISION (lh.type ()); + int mini = 0; + int maxi = prec - 1; + int zerov = 0; + scalar_int_mode mode = SCALAR_INT_TYPE_MODE (lh.type ()); + if (m_gimple_call_internal_p) + { + if (optab_handler (clz_optab, mode) != CODE_FOR_nothing + && CLZ_DEFINED_VALUE_AT_ZERO (mode, zerov) == 2) + { + // Only handle the single common value. + if (zerov == prec) + maxi = prec; + else + // Magic value to give up, unless we can prove arg is non-zero. + mini = -2; + } + } + + // From clz of minimum we can compute result maximum. + if (wi::gt_p (lh.lower_bound (), 0, TYPE_SIGN (lh.type ()))) + { + maxi = prec - 1 - wi::floor_log2 (lh.lower_bound ()); + if (mini == -2) + mini = 0; + } + else if (!range_includes_zero_p (&lh)) + { + mini = 0; + maxi = prec - 1; + } + if (mini == -2) + return false; + // From clz of maximum we can compute result minimum. + wide_int max = lh.upper_bound (); + int newmini = prec - 1 - wi::floor_log2 (max); + if (max == 0) + { + // If CLZ_DEFINED_VALUE_AT_ZERO is 2 with VALUE of prec, + // return [prec, prec], otherwise ignore the range. + if (maxi == prec) + mini = prec; + } + else + mini = newmini; + + if (mini == -2) + return false; + r.set (build_int_cst (type, mini), build_int_cst (type, maxi)); + return true; +} + +// Implement range operator for CFN_BUILT_IN_CTZ +class cfn_ctz : public range_operator +{ +public: + cfn_ctz (bool internal) { m_gimple_call_internal_p = internal; } + using range_operator::fold_range; + virtual bool fold_range (irange &r, tree type, const irange &lh, + const irange &, relation_kind) const; +private: + bool m_gimple_call_internal_p; +} op_cfn_ctz (false), op_cfn_ctz_internal (true); + +bool +cfn_ctz::fold_range (irange &r, tree type, const irange &lh, + const irange &, relation_kind) const +{ + if (lh.undefined_p ()) + return false; + int prec = TYPE_PRECISION (lh.type ()); + int mini = 0; + int maxi = prec - 1; + int zerov = 0; + scalar_int_mode mode = SCALAR_INT_TYPE_MODE (lh.type ()); + + if (m_gimple_call_internal_p) + { + if (optab_handler (ctz_optab, mode) != CODE_FOR_nothing + && CTZ_DEFINED_VALUE_AT_ZERO (mode, zerov) == 2) + { + // Handle only the two common values. + if (zerov == -1) + mini = -1; + else if (zerov == prec) + maxi = prec; + else + // Magic value to give up, unless we can prove arg is non-zero. + mini = -2; + } + } + // If arg is non-zero, then use [0, prec - 1]. + if (!range_includes_zero_p (&lh)) + { + mini = 0; + maxi = prec - 1; + } + // If some high bits are known to be zero, we can decrease + // the maximum. + wide_int max = lh.upper_bound (); + if (max == 0) + { + // Argument is [0, 0]. If CTZ_DEFINED_VALUE_AT_ZERO + // is 2 with value -1 or prec, return [-1, -1] or [prec, prec]. + // Otherwise ignore the range. + if (mini == -1) + maxi = -1; + else if (maxi == prec) + mini = prec; + } + // If value at zero is prec and 0 is in the range, we can't lower + // the upper bound. We could create two separate ranges though, + // [0,floor_log2(max)][prec,prec] though. + else if (maxi != prec) + maxi = wi::floor_log2 (max); + + if (mini == -2) + return false; + r.set (build_int_cst (type, mini), build_int_cst (type, maxi)); + return true; +} + + +// Implement range operator for CFN_BUILT_IN_ +class cfn_clrsb : public range_operator +{ +public: + using range_operator::fold_range; + virtual bool fold_range (irange &r, tree type, const irange &lh, + const irange &, relation_kind) const + { + if (lh.undefined_p ()) + return false; + int prec = TYPE_PRECISION (lh.type ()); + r.set (build_int_cst (type, 0), build_int_cst (type, prec - 1)); + return true; + } +} op_cfn_clrsb; + + +// Implement range operator for CFN_BUILT_IN_ +class cfn_ubsan : public range_operator +{ +public: + cfn_ubsan (enum tree_code code) { m_code = code; } + using range_operator::fold_range; + virtual bool fold_range (irange &r, tree type, const irange &lh, + const irange &rh, relation_kind rel) const + { + range_op_handler handler (m_code, type); + gcc_checking_assert (handler); + + bool saved_flag_wrapv = flag_wrapv; + // Pretend the arithmetic is wrapping. If there is any overflow, + // we'll complain, but will actually do wrapping operation. + flag_wrapv = 1; + bool result = handler.fold_range (r, type, lh, rh, rel); + flag_wrapv = saved_flag_wrapv; + + // If for both arguments vrp_valueize returned non-NULL, this should + // have been already folded and if not, it wasn't folded because of + // overflow. Avoid removing the UBSAN_CHECK_* calls in that case. + if (result && r.singleton_p ()) + r.set_varying (type); + return result; + } +private: + enum tree_code m_code; +}; + +cfn_ubsan op_cfn_ubsan_add (PLUS_EXPR); +cfn_ubsan op_cfn_ubsan_sub (MINUS_EXPR); +cfn_ubsan op_cfn_ubsan_mul (MULT_EXPR); + + +// Implement range operator for CFN_BUILT_IN_STRLEN +class cfn_strlen : public range_operator +{ +public: + using range_operator::fold_range; + virtual bool fold_range (irange &r, tree type, const irange &, + const irange &, relation_kind) const + { + tree max = vrp_val_max (ptrdiff_type_node); + wide_int wmax + = wi::to_wide (max, TYPE_PRECISION (TREE_TYPE (max))); + tree range_min = build_zero_cst (type); + // To account for the terminating NULL, the maximum length + // is one less than the maximum array size, which in turn + // is one less than PTRDIFF_MAX (or SIZE_MAX where it's + // smaller than the former type). + // FIXME: Use max_object_size() - 1 here. + tree range_max = wide_int_to_tree (type, wmax - 2); + r.set (range_min, range_max); + return true; + } +} op_cfn_strlen; + + +// Implement range operator for CFN_BUILT_IN_GOACC_DIM +class cfn_goacc_dim : public range_operator +{ +public: + cfn_goacc_dim (bool is_pos) { m_is_pos = is_pos; } + using range_operator::fold_range; + virtual bool fold_range (irange &r, tree type, const irange &lh, + const irange &, relation_kind) const + { + tree axis_tree; + if (!lh.singleton_p (&axis_tree)) + return false; + HOST_WIDE_INT axis = TREE_INT_CST_LOW (axis_tree); + int size = oacc_get_fn_dim_size (current_function_decl, axis); + if (!size) + // If it's dynamic, the backend might know a hardware limitation. + size = targetm.goacc.dim_limit (axis); + + r.set (build_int_cst (type, m_is_pos ? 0 : 1), + size + ? build_int_cst (type, size - m_is_pos) : vrp_val_max (type)); + return true; + } +private: + bool m_is_pos; +} op_cfn_goacc_dim_size (false), op_cfn_goacc_dim_pos (true); + + +// Implement range operator for CFN_BUILT_IN_ +class cfn_parity : public range_operator +{ +public: + using range_operator::fold_range; + virtual bool fold_range (irange &r, tree type, const irange &, + const irange &, relation_kind) const + { + r.set (build_zero_cst (type), build_one_cst (type)); + return true; + } +} op_cfn_parity; + +// Set up a gimple_range_op_handler for any built in function which can be +// supported via range-ops. + +void +gimple_range_op_handler::maybe_builtin_call () +{ + gcc_checking_assert (is_a <gcall *> (m_stmt)); + + gcall *call = as_a <gcall *> (m_stmt); + combined_fn func = gimple_call_combined_fn (call); + if (func == CFN_LAST) + return; + tree type = gimple_range_type (call); + gcc_checking_assert (type); + if (!Value_Range::supports_type_p (type)) + return; + + switch (func) + { + case CFN_BUILT_IN_CONSTANT_P: + m_op1 = gimple_call_arg (call, 0); + m_valid = true; + if (irange::supports_p (TREE_TYPE (m_op1))) + m_int = &op_cfn_constant_p; + else if (frange::supports_p (TREE_TYPE (m_op1))) + m_float = &op_cfn_constant_float_p; + else + m_valid = false; + break; + + case CFN_BUILT_IN_SIGNBIT: + m_op1 = gimple_call_arg (call, 0); + m_float = &op_cfn_signbit; + m_valid = true; + break; + + case CFN_BUILT_IN_TOUPPER: + case CFN_BUILT_IN_TOLOWER: + // Only proceed If the argument is compatible with the LHS. + m_op1 = gimple_call_arg (call, 0); + if (range_compatible_p (type, TREE_TYPE (m_op1))) + { + m_valid = true; + m_int = (func == CFN_BUILT_IN_TOLOWER) ? &op_cfn_tolower + : &op_cfn_toupper; + } + break; + + CASE_CFN_FFS: + CASE_CFN_POPCOUNT: + m_op1 = gimple_call_arg (call, 0); + m_int = &op_cfn_popcount; + m_valid = true; + break; + + CASE_CFN_CLZ: + m_op1 = gimple_call_arg (call, 0); + m_valid = true; + if (gimple_call_internal_p (call)) + m_int = &op_cfn_clz_internal; + else + m_int = &op_cfn_clz; + break; + + CASE_CFN_CTZ: + m_op1 = gimple_call_arg (call, 0); + m_valid = true; + if (gimple_call_internal_p (call)) + m_int = &op_cfn_ctz_internal; + else + m_int = &op_cfn_ctz; + break; + + CASE_CFN_CLRSB: + m_op1 = gimple_call_arg (call, 0); + m_valid = true; + m_int = &op_cfn_clrsb; + break; + + case CFN_UBSAN_CHECK_ADD: + m_op1 = gimple_call_arg (call, 0); + m_op2 = gimple_call_arg (call, 1); + m_valid = true; + m_int = &op_cfn_ubsan_add; + break; + + case CFN_UBSAN_CHECK_SUB: + m_op1 = gimple_call_arg (call, 0); + m_op2 = gimple_call_arg (call, 1); + m_valid = true; + m_int = &op_cfn_ubsan_sub; + break; + + case CFN_UBSAN_CHECK_MUL: + m_op1 = gimple_call_arg (call, 0); + m_op2 = gimple_call_arg (call, 1); + m_valid = true; + m_int = &op_cfn_ubsan_mul; + break; + + case CFN_BUILT_IN_STRLEN: + { + tree lhs = gimple_call_lhs (call); + if (lhs && ptrdiff_type_node && (TYPE_PRECISION (ptrdiff_type_node) + == TYPE_PRECISION (TREE_TYPE (lhs)))) + { + m_op1 = gimple_call_arg (call, 0); + m_valid = true; + m_int = &op_cfn_strlen; + } + break; + } + + // Optimizing these two internal functions helps the loop + // optimizer eliminate outer comparisons. Size is [1,N] + // and pos is [0,N-1]. + case CFN_GOACC_DIM_SIZE: + // This call will ensure all the asserts are triggered. + oacc_get_ifn_dim_arg (call); + m_op1 = gimple_call_arg (call, 0); + m_valid = true; + m_int = &op_cfn_goacc_dim_size; + break; + + case CFN_GOACC_DIM_POS: + // This call will ensure all the asserts are triggered. + oacc_get_ifn_dim_arg (call); + m_op1 = gimple_call_arg (call, 0); + m_valid = true; + m_int = &op_cfn_goacc_dim_pos; + break; + + CASE_CFN_PARITY: + m_valid = true; + m_int = &op_cfn_parity; + break; + + default: + break; + } +} diff --git a/gcc/gimple-range-op.h b/gcc/gimple-range-op.h new file mode 100644 index 0000000..6876419 --- /dev/null +++ b/gcc/gimple-range-op.h @@ -0,0 +1,52 @@ +/* Header file for the GIMPLE range-op interface. + Copyright (C) 2022 Free Software Foundation, Inc. + Contributed by Andrew MacLeod <amacleod@redhat.com> + and Aldy Hernandez <aldyh@redhat.com>. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +#ifndef GCC_GIMPLE_RANGE_OP_H +#define GCC_GIMPLE_RANGE_OP_H + +#include "range-op.h" + + +class gimple_range_op_handler : public range_op_handler +{ +public: + static bool supported_p (gimple *s); + gimple_range_op_handler (gimple *s); + inline gimple *stmt () const { return m_stmt; } + inline tree lhs () const { return gimple_get_lhs (m_stmt); } + tree operand1 () const { gcc_checking_assert (m_valid); return m_op1; } + tree operand2 () const { gcc_checking_assert (m_valid); return m_op2; } + bool calc_op1 (vrange &r, const vrange &lhs_range); + bool calc_op1 (vrange &r, const vrange &lhs_range, const vrange &op2_range); + bool calc_op2 (vrange &r, const vrange &lhs_range, const vrange &op1_range); +private: + void maybe_builtin_call (); + gimple *m_stmt; + tree m_op1, m_op2; +}; + +// Given stmt S, fill VEC, up to VEC_SIZE elements, with relevant ssa-names +// on the statement. For efficiency, it is an error to not pass in enough +// elements for the vector. Return the number of ssa-names. + +unsigned gimple_range_ssa_names (tree *vec, unsigned vec_size, gimple *stmt); + +#endif // GCC_GIMPLE_RANGE_OP_H diff --git a/gcc/gimple-range.cc b/gcc/gimple-range.cc index eb347ee..d67d649 100644 --- a/gcc/gimple-range.cc +++ b/gcc/gimple-range.cc @@ -341,7 +341,7 @@ gimple_ranger::prefill_name (vrange &r, tree name) if (!gimple_range_ssa_p (name)) return; gimple *stmt = SSA_NAME_DEF_STMT (name); - if (!range_op_handler (stmt) && !is_a<gphi *> (stmt)) + if (!gimple_range_op_handler::supported_p (stmt) && !is_a<gphi *> (stmt)) return; bool current; @@ -364,7 +364,7 @@ gimple_ranger::prefill_stmt_dependencies (tree ssa) gcc_checking_assert (stmt && gimple_bb (stmt)); // Only pre-process range-ops and phis. - if (!range_op_handler (stmt) && !is_a<gphi *> (stmt)) + if (!gimple_range_op_handler::supported_p (stmt) && !is_a<gphi *> (stmt)) return; // Mark where on the stack we are starting. @@ -422,14 +422,15 @@ gimple_ranger::prefill_stmt_dependencies (tree ssa) } else { - gcc_checking_assert (range_op_handler (stmt)); - tree op = gimple_range_operand2 (stmt); + gimple_range_op_handler handler (stmt); + gcc_checking_assert (handler); + tree op = handler.operand2 (); if (op) { Value_Range r (TREE_TYPE (op)); prefill_name (r, op); } - op = gimple_range_operand1 (stmt); + op = handler.operand1 (); if (op) { Value_Range r (TREE_TYPE (op)); diff --git a/gcc/gimple-range.h b/gcc/gimple-range.h index 34f6102..8b2ff56 100644 --- a/gcc/gimple-range.h +++ b/gcc/gimple-range.h @@ -24,7 +24,7 @@ along with GCC; see the file COPYING3. If not see #include "range.h" #include "value-query.h" -#include "range-op.h" +#include "gimple-range-op.h" #include "gimple-range-trace.h" #include "gimple-range-edge.h" #include "gimple-range-fold.h" diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index dce38e7..f7a7985 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -6543b7fc6da533eb976b37649a925e7fd5a521fa +42efec8c126cf3787bc7c89d9c7f224eff7c5a21 The first line of this file holds the git revision number of the last merge done from the gofrontend repository. diff --git a/gcc/omp-expand.cc b/gcc/omp-expand.cc index 5cac8df..5dc0bf1 100644 --- a/gcc/omp-expand.cc +++ b/gcc/omp-expand.cc @@ -10712,7 +10712,10 @@ build_omp_regions_1 (basic_block bb, struct omp_region *parent, case GF_OMP_TARGET_KIND_OACC_ENTER_DATA: case GF_OMP_TARGET_KIND_OACC_EXIT_DATA: case GF_OMP_TARGET_KIND_OACC_DECLARE: - /* ..., other than for those stand-alone directives... */ + /* ..., other than for those stand-alone directives... + To be precise, target data isn't stand-alone, but + gimplifier put the end API call into try finally block + for it, so omp expansion can treat it as such. */ region = NULL; break; default: @@ -10728,6 +10731,11 @@ build_omp_regions_1 (basic_block bb, struct omp_region *parent, && gimple_omp_task_taskwait_p (stmt)) /* #pragma omp taskwait depend(...) is a stand-alone directive. */ region = NULL; + else if (code == GIMPLE_OMP_TASKGROUP) + /* #pragma omp taskgroup isn't a stand-alone directive, but + gimplifier put the end API call into try finall block + for it, so omp expansion can treat it as such. */ + region = NULL; /* ..., this directive becomes the parent for a new region. */ if (region) parent = region; @@ -10927,13 +10935,18 @@ omp_make_gimple_edges (basic_block bb, struct omp_region **region, case GIMPLE_OMP_MASTER: case GIMPLE_OMP_MASKED: case GIMPLE_OMP_SCOPE: - case GIMPLE_OMP_TASKGROUP: case GIMPLE_OMP_CRITICAL: case GIMPLE_OMP_SECTION: cur_region = new_omp_region (bb, code, cur_region); fallthru = true; break; + case GIMPLE_OMP_TASKGROUP: + cur_region = new_omp_region (bb, code, cur_region); + fallthru = true; + cur_region = cur_region->outer; + break; + case GIMPLE_OMP_TASK: cur_region = new_omp_region (bb, code, cur_region); fallthru = true; diff --git a/gcc/omp-low.cc b/gcc/omp-low.cc index f0469d2..dc42c75 100644 --- a/gcc/omp-low.cc +++ b/gcc/omp-low.cc @@ -7631,6 +7631,7 @@ lower_oacc_reductions (location_t loc, tree clauses, tree level, bool inner, incoming = build_simple_mem_ref (incoming); } else + /* Note that 'var' might be a mem ref. */ v1 = v2 = v3 = var; /* Determine position in reduction buffer, which may be used @@ -7659,26 +7660,28 @@ lower_oacc_reductions (location_t loc, tree clauses, tree level, bool inner, = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION, TREE_TYPE (var), 6, setup_code, unshare_expr (ref_to_res), - incoming, level, op, off); + unshare_expr (incoming), + level, op, off); tree init_call = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION, TREE_TYPE (var), 6, init_code, unshare_expr (ref_to_res), - v1, level, op, off); + unshare_expr (v1), level, op, off); tree fini_call = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION, TREE_TYPE (var), 6, fini_code, unshare_expr (ref_to_res), - v2, level, op, off); + unshare_expr (v2), level, op, off); tree teardown_call = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION, TREE_TYPE (var), 6, teardown_code, - ref_to_res, v3, level, op, off); + ref_to_res, unshare_expr (v3), + level, op, off); - gimplify_assign (v1, setup_call, &before_fork); - gimplify_assign (v2, init_call, &after_fork); - gimplify_assign (v3, fini_call, &before_join); - gimplify_assign (outgoing, teardown_call, &after_join); + gimplify_assign (unshare_expr (v1), setup_call, &before_fork); + gimplify_assign (unshare_expr (v2), init_call, &after_fork); + gimplify_assign (unshare_expr (v3), fini_call, &before_join); + gimplify_assign (unshare_expr (outgoing), teardown_call, &after_join); } /* Now stitch things together. */ @@ -9724,7 +9727,6 @@ lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx) gimple_bind_add_seq (bind, gimple_omp_body (stmt)); gimple_omp_set_body (stmt, NULL); - gimple_bind_add_stmt (bind, gimple_build_omp_return (true)); gimple_bind_add_seq (bind, dseq); pop_gimplify_context (bind); diff --git a/gcc/opts.cc b/gcc/opts.cc index e058aaf..eb5db01 100644 --- a/gcc/opts.cc +++ b/gcc/opts.cc @@ -1801,7 +1801,7 @@ print_filtered_help (unsigned int include_flags, help = new_help; } - if (option->range_max != -1) + if (option->range_max != -1 && tab == NULL) { char b[128]; snprintf (b, sizeof (b), "<%d,%d>", option->range_min, diff --git a/gcc/passes.def b/gcc/passes.def index 6bb92ef..939ec3e 100644 --- a/gcc/passes.def +++ b/gcc/passes.def @@ -263,7 +263,7 @@ along with GCC; see the file COPYING3. If not see NEXT_PASS (pass_sancov); NEXT_PASS (pass_asan); NEXT_PASS (pass_tsan); - NEXT_PASS (pass_dse); + NEXT_PASS (pass_dse, true /* use DR analysis */); NEXT_PASS (pass_dce); /* Pass group that runs when 1) enabled, 2) there are loops in the function. Make sure to run pass_fix_loops before diff --git a/gcc/po/ChangeLog b/gcc/po/ChangeLog index eeb2b8e..55d13c7 100644 --- a/gcc/po/ChangeLog +++ b/gcc/po/ChangeLog @@ -1,3 +1,7 @@ +2022-09-22 Joseph Myers <joseph@codesourcery.com> + + * fr.po: Update. + 2022-08-30 Joseph Myers <joseph@codesourcery.com> * sv.po: Update. diff --git a/gcc/po/fr.po b/gcc/po/fr.po index 4190306..39cbfb7 100644 --- a/gcc/po/fr.po +++ b/gcc/po/fr.po @@ -97,10 +97,10 @@ # msgid "" msgstr "" -"Project-Id-Version: gcc 12.1.0\n" +"Project-Id-Version: gcc 12.2.0\n" "Report-Msgid-Bugs-To: https://gcc.gnu.org/bugs/\n" "POT-Creation-Date: 2022-08-17 22:17+0000\n" -"PO-Revision-Date: 2022-05-09 10:26+0200\n" +"PO-Revision-Date: 2022-09-16 06:43+0200\n" "Last-Translator: Frédéric Marchal <fmarchal@perso.be>\n" "Language-Team: French <traduc@traduc.org>\n" "Language: fr\n" @@ -58941,10 +58941,9 @@ msgid "redeclared here as %q#D" msgstr "redéclaré ici comme %q#D" #: cp/pt.cc:6321 -#, fuzzy, gcc-internal-format -#| msgid "declared here" +#, gcc-internal-format msgid "redeclared here" -msgstr "déclaré ici" +msgstr "redéclaré ici" #: cp/pt.cc:6332 #, gcc-internal-format @@ -62308,10 +62307,9 @@ msgid "toHash() must be declared as extern (D) size_t toHash() const nothrow @sa msgstr "toHash() doit être déclaré comme extern (D) size_t toHash() const nothrow @safe et non comme %s" #: d/typeinfo.cc:1415 -#, fuzzy, gcc-internal-format -#| msgid "%<object.TypeInfo%> cannot be used with %<-fno-rtti%>" +#, gcc-internal-format msgid "expression %qs requires %<object.TypeInfo%> and cannot be used with %<-fno-rtti%>" -msgstr "%<object.TypeInfo%> ne peut pas être utilisé avec %<-fno-rtti%>" +msgstr "l'expression %qs requiert %<object.TypeInfo%> et ne peut pas être utilisée avec %<-fno-rtti%>" #: d/typeinfo.cc:1419 #, gcc-internal-format @@ -64958,10 +64956,9 @@ msgid "BIND(C) statement at %C" msgstr "Instruction BIND(C) à %C" #: fortran/decl.cc:6268 -#, fuzzy, gcc-internal-format, gfc-internal-format -#| msgid "CLASS variable %qs at %L cannot have the PARAMETER attribute" +#, gcc-internal-format, gfc-internal-format msgid "CLASS entity at %C cannot have the PARAMETER attribute" -msgstr "La variable CLASS %qs à %L ne peut pas avoir l'attribut PARAMETER" +msgstr "L'entité CLASS à %C ne peut pas avoir l'attribut PARAMETER" #: fortran/decl.cc:6300 #, gcc-internal-format, gfc-internal-format diff --git a/gcc/range-op-float.cc b/gcc/range-op-float.cc index 1e39a07..6e9d51d 100644 --- a/gcc/range-op-float.cc +++ b/gcc/range-op-float.cc @@ -62,6 +62,16 @@ bool range_operator_float::fold_range (irange &r ATTRIBUTE_UNUSED, tree type ATTRIBUTE_UNUSED, const frange &lh ATTRIBUTE_UNUSED, + const irange &rh ATTRIBUTE_UNUSED, + relation_kind rel ATTRIBUTE_UNUSED) const +{ + return false; +} + +bool +range_operator_float::fold_range (irange &r ATTRIBUTE_UNUSED, + tree type ATTRIBUTE_UNUSED, + const frange &lh ATTRIBUTE_UNUSED, const frange &rh ATTRIBUTE_UNUSED, relation_kind rel ATTRIBUTE_UNUSED) const { @@ -190,8 +200,7 @@ frelop_early_resolve (irange &r, tree type, static inline void frange_drop_inf (frange &r, tree type) { - REAL_VALUE_TYPE max; - real_max_representable (&max, type); + REAL_VALUE_TYPE max = real_max_representable (type); frange tmp (type, r.lower_bound (), max); r.intersect (tmp); } @@ -202,8 +211,7 @@ frange_drop_inf (frange &r, tree type) static inline void frange_drop_ninf (frange &r, tree type) { - REAL_VALUE_TYPE min; - real_min_representable (&min, type); + REAL_VALUE_TYPE min = real_min_representable (type); frange tmp (type, min, r.upper_bound ()); r.intersect (tmp); } @@ -230,12 +238,10 @@ frange_add_zeros (frange &r, tree type) static bool build_le (frange &r, tree type, const frange &val) { - if (val.known_isnan ()) - { - r.set_undefined (); - return false; - } - r.set (type, dconstninf, val.upper_bound ()); + gcc_checking_assert (!val.known_isnan ()); + + REAL_VALUE_TYPE ninf = frange_val_min (type); + r.set (type, ninf, val.upper_bound ()); // Add both zeros if there's the possibility of zero equality. frange_add_zeros (r, type); @@ -248,11 +254,8 @@ build_le (frange &r, tree type, const frange &val) static bool build_lt (frange &r, tree type, const frange &val) { - if (val.known_isnan ()) - { - r.set_undefined (); - return false; - } + gcc_checking_assert (!val.known_isnan ()); + // < -INF is outside the range. if (real_isinf (&val.upper_bound (), 1)) { @@ -263,7 +266,8 @@ build_lt (frange &r, tree type, const frange &val) return false; } // We only support closed intervals. - r.set (type, dconstninf, val.upper_bound ()); + REAL_VALUE_TYPE ninf = frange_val_min (type); + r.set (type, ninf, val.upper_bound ()); return true; } @@ -272,12 +276,10 @@ build_lt (frange &r, tree type, const frange &val) static bool build_ge (frange &r, tree type, const frange &val) { - if (val.known_isnan ()) - { - r.set_undefined (); - return false; - } - r.set (type, val.lower_bound (), dconstinf); + gcc_checking_assert (!val.known_isnan ()); + + REAL_VALUE_TYPE inf = frange_val_max (type); + r.set (type, val.lower_bound (), inf); // Add both zeros if there's the possibility of zero equality. frange_add_zeros (r, type); @@ -290,11 +292,8 @@ build_ge (frange &r, tree type, const frange &val) static bool build_gt (frange &r, tree type, const frange &val) { - if (val.known_isnan ()) - { - r.set_undefined (); - return false; - } + gcc_checking_assert (!val.known_isnan ()); + // > +INF is outside the range. if (real_isinf (&val.lower_bound (), 0)) { @@ -306,7 +305,8 @@ build_gt (frange &r, tree type, const frange &val) } // We only support closed intervals. - r.set (type, val.lower_bound (), dconstinf); + REAL_VALUE_TYPE inf = frange_val_max (type); + r.set (type, val.lower_bound (), inf); return true; } @@ -365,9 +365,11 @@ foperator_equal::fold_range (irange &r, tree type, if (frelop_early_resolve (r, type, op1, op2, rel, VREL_EQ)) return true; + if (op1.known_isnan () || op2.known_isnan ()) + r = range_false (type); // We can be sure the values are always equal or not if both ranges // consist of a single value, and then compare them. - if (op1.singleton_p () && op2.singleton_p ()) + else if (op1.singleton_p () && op2.singleton_p ()) { if (op1 == op2) r = range_true (type); @@ -393,25 +395,33 @@ foperator_equal::fold_range (irange &r, tree type, bool foperator_equal::op1_range (frange &r, tree type, const irange &lhs, - const frange &op2 ATTRIBUTE_UNUSED, + const frange &op2, relation_kind rel) const { switch (get_bool_state (r, lhs, type)) { case BRS_TRUE: - // If it's true, the result is the same as OP2. - r = op2; - // Add both zeros if there's the possibility of zero equality. - frange_add_zeros (r, type); - // The TRUE side of op1 == op2 implies op1 is !NAN. - r.clear_nan (); + // The TRUE side of x == NAN is unreachable. + if (op2.known_isnan ()) + r.set_undefined (); + else + { + // If it's true, the result is the same as OP2. + r = op2; + // Add both zeros if there's the possibility of zero equality. + frange_add_zeros (r, type); + // The TRUE side of op1 == op2 implies op1 is !NAN. + r.clear_nan (); + } break; case BRS_FALSE: - r.set_varying (type); // The FALSE side of op1 == op1 implies op1 is a NAN. if (rel == VREL_EQ) r.set_nan (type); + // On the FALSE side of x == NAN, we know nothing about x. + else if (op2.known_isnan ()) + r.set_varying (type); // If the result is false, the only time we know anything is // if OP2 is a constant. else if (op2.singleton_p () @@ -420,6 +430,8 @@ foperator_equal::op1_range (frange &r, tree type, REAL_VALUE_TYPE tmp = op2.lower_bound (); r.set (type, tmp, tmp, VR_ANTI_RANGE); } + else + r.set_varying (type); break; default: @@ -453,9 +465,12 @@ foperator_not_equal::fold_range (irange &r, tree type, if (frelop_early_resolve (r, type, op1, op2, rel, VREL_NE)) return true; + // x != NAN is always TRUE. + if (op1.known_isnan () || op2.known_isnan ()) + r = range_true (type); // We can be sure the values are always equal or not if both ranges // consist of a single value, and then compare them. - if (op1.singleton_p () && op2.singleton_p ()) + else if (op1.singleton_p () && op2.singleton_p ()) { if (op1 != op2) r = range_true (type); @@ -481,7 +496,7 @@ foperator_not_equal::fold_range (irange &r, tree type, bool foperator_not_equal::op1_range (frange &r, tree type, const irange &lhs, - const frange &op2 ATTRIBUTE_UNUSED, + const frange &op2, relation_kind) const { switch (get_bool_state (r, lhs, type)) @@ -502,12 +517,18 @@ foperator_not_equal::op1_range (frange &r, tree type, break; case BRS_FALSE: - // If it's false, the result is the same as OP2. - r = op2; - // Add both zeros if there's the possibility of zero equality. - frange_add_zeros (r, type); - // The FALSE side of op1 != op2 implies op1 is !NAN. - r.clear_nan (); + // The FALSE side of x != NAN is impossible. + if (op2.known_isnan ()) + r.set_undefined (); + else + { + // If it's false, the result is the same as OP2. + r = op2; + // Add both zeros if there's the possibility of zero equality. + frange_add_zeros (r, type); + // The FALSE side of op1 != op2 implies op1 is !NAN. + r.clear_nan (); + } break; default: @@ -545,7 +566,9 @@ foperator_lt::fold_range (irange &r, tree type, if (frelop_early_resolve (r, type, op1, op2, rel, VREL_LT)) return true; - if (finite_operands_p (op1, op2)) + if (op1.known_isnan () || op2.known_isnan ()) + r = range_false (type); + else if (finite_operands_p (op1, op2)) { if (real_less (&op1.upper_bound (), &op2.lower_bound ())) r = range_true (type); @@ -555,8 +578,6 @@ foperator_lt::fold_range (irange &r, tree type, else r = range_true_and_false (type); } - else if (op1.known_isnan () || op2.known_isnan ()) - r = range_false (type); else r = range_true_and_false (type); return true; @@ -566,13 +587,16 @@ bool foperator_lt::op1_range (frange &r, tree type, const irange &lhs, - const frange &op2 ATTRIBUTE_UNUSED, + const frange &op2, relation_kind) const { switch (get_bool_state (r, lhs, type)) { case BRS_TRUE: - if (build_lt (r, type, op2)) + // The TRUE side of x < NAN is unreachable. + if (op2.known_isnan ()) + r.set_undefined (); + else if (build_lt (r, type, op2)) { r.clear_nan (); // x < y implies x is not +INF. @@ -581,7 +605,11 @@ foperator_lt::op1_range (frange &r, break; case BRS_FALSE: - build_ge (r, type, op2); + // On the FALSE side of x < NAN, we know nothing about x. + if (op2.known_isnan ()) + r.set_varying (type); + else + build_ge (r, type, op2); break; default: @@ -594,13 +622,16 @@ bool foperator_lt::op2_range (frange &r, tree type, const irange &lhs, - const frange &op1 ATTRIBUTE_UNUSED, + const frange &op1, relation_kind) const { switch (get_bool_state (r, lhs, type)) { case BRS_TRUE: - if (build_gt (r, type, op1)) + // The TRUE side of NAN < x is unreachable. + if (op1.known_isnan ()) + r.set_undefined (); + else if (build_gt (r, type, op1)) { r.clear_nan (); // x < y implies y is not -INF. @@ -609,7 +640,11 @@ foperator_lt::op2_range (frange &r, break; case BRS_FALSE: - build_le (r, type, op1); + // On the FALSE side of NAN < x, we know nothing about x. + if (op1.known_isnan ()) + r.set_varying (type); + else + build_le (r, type, op1); break; default: @@ -647,7 +682,9 @@ foperator_le::fold_range (irange &r, tree type, if (frelop_early_resolve (r, type, op1, op2, rel, VREL_LE)) return true; - if (finite_operands_p (op1, op2)) + if (op1.known_isnan () || op2.known_isnan ()) + r = range_false (type); + else if (finite_operands_p (op1, op2)) { if (real_compare (LE_EXPR, &op1.upper_bound (), &op2.lower_bound ())) r = range_true (type); @@ -657,8 +694,6 @@ foperator_le::fold_range (irange &r, tree type, else r = range_true_and_false (type); } - else if (op1.known_isnan () || op2.known_isnan ()) - r = range_false (type); else r = range_true_and_false (type); return true; @@ -674,12 +709,19 @@ foperator_le::op1_range (frange &r, switch (get_bool_state (r, lhs, type)) { case BRS_TRUE: - if (build_le (r, type, op2)) + // The TRUE side of x <= NAN is unreachable. + if (op2.known_isnan ()) + r.set_undefined (); + else if (build_le (r, type, op2)) r.clear_nan (); break; case BRS_FALSE: - build_gt (r, type, op2); + // On the FALSE side of x <= NAN, we know nothing about x. + if (op2.known_isnan ()) + r.set_varying (type); + else + build_gt (r, type, op2); break; default: @@ -698,12 +740,19 @@ foperator_le::op2_range (frange &r, switch (get_bool_state (r, lhs, type)) { case BRS_TRUE: - if (build_ge (r, type, op1)) + // The TRUE side of NAN <= x is unreachable. + if (op1.known_isnan ()) + r.set_undefined (); + else if (build_ge (r, type, op1)) r.clear_nan (); break; case BRS_FALSE: - build_lt (r, type, op1); + // On the FALSE side of NAN <= x, we know nothing about x. + if (op1.known_isnan ()) + r.set_varying (type); + else + build_lt (r, type, op1); break; default: @@ -741,7 +790,9 @@ foperator_gt::fold_range (irange &r, tree type, if (frelop_early_resolve (r, type, op1, op2, rel, VREL_GT)) return true; - if (finite_operands_p (op1, op2)) + if (op1.known_isnan () || op2.known_isnan ()) + r = range_false (type); + else if (finite_operands_p (op1, op2)) { if (real_compare (GT_EXPR, &op1.lower_bound (), &op2.upper_bound ())) r = range_true (type); @@ -751,8 +802,6 @@ foperator_gt::fold_range (irange &r, tree type, else r = range_true_and_false (type); } - else if (op1.known_isnan () || op2.known_isnan ()) - r = range_false (type); else r = range_true_and_false (type); return true; @@ -762,13 +811,16 @@ bool foperator_gt::op1_range (frange &r, tree type, const irange &lhs, - const frange &op2 ATTRIBUTE_UNUSED, + const frange &op2, relation_kind) const { switch (get_bool_state (r, lhs, type)) { case BRS_TRUE: - if (build_gt (r, type, op2)) + // The TRUE side of x > NAN is unreachable. + if (op2.known_isnan ()) + r.set_undefined (); + else if (build_gt (r, type, op2)) { r.clear_nan (); // x > y implies x is not -INF. @@ -777,7 +829,11 @@ foperator_gt::op1_range (frange &r, break; case BRS_FALSE: - build_le (r, type, op2); + // On the FALSE side of x > NAN, we know nothing about x. + if (op2.known_isnan ()) + r.set_varying (type); + else + build_le (r, type, op2); break; default: @@ -790,13 +846,16 @@ bool foperator_gt::op2_range (frange &r, tree type, const irange &lhs, - const frange &op1 ATTRIBUTE_UNUSED, + const frange &op1, relation_kind) const { switch (get_bool_state (r, lhs, type)) { case BRS_TRUE: - if (build_lt (r, type, op1)) + // The TRUE side of NAN > x is unreachable. + if (op1.known_isnan ()) + r.set_undefined (); + else if (build_lt (r, type, op1)) { r.clear_nan (); // x > y implies y is not +INF. @@ -805,7 +864,11 @@ foperator_gt::op2_range (frange &r, break; case BRS_FALSE: - build_ge (r, type, op1); + // On The FALSE side of NAN > x, we know nothing about x. + if (op1.known_isnan ()) + r.set_varying (type); + else + build_ge (r, type, op1); break; default: @@ -843,7 +906,9 @@ foperator_ge::fold_range (irange &r, tree type, if (frelop_early_resolve (r, type, op1, op2, rel, VREL_GE)) return true; - if (finite_operands_p (op1, op2)) + if (op1.known_isnan () || op2.known_isnan ()) + r = range_false (type); + else if (finite_operands_p (op1, op2)) { if (real_compare (GE_EXPR, &op1.lower_bound (), &op2.upper_bound ())) r = range_true (type); @@ -853,8 +918,6 @@ foperator_ge::fold_range (irange &r, tree type, else r = range_true_and_false (type); } - else if (op1.known_isnan () || op2.known_isnan ()) - r = range_false (type); else r = range_true_and_false (type); return true; @@ -870,12 +933,19 @@ foperator_ge::op1_range (frange &r, switch (get_bool_state (r, lhs, type)) { case BRS_TRUE: - build_ge (r, type, op2); - r.clear_nan (); + // The TRUE side of x >= NAN is unreachable. + if (op2.known_isnan ()) + r.set_undefined (); + else if (build_ge (r, type, op2)) + r.clear_nan (); break; case BRS_FALSE: - build_lt (r, type, op2); + // On the FALSE side of x >= NAN, we know nothing about x. + if (op2.known_isnan ()) + r.set_varying (type); + else + build_lt (r, type, op2); break; default: @@ -892,13 +962,23 @@ foperator_ge::op2_range (frange &r, tree type, { switch (get_bool_state (r, lhs, type)) { - case BRS_FALSE: - build_gt (r, type, op1); + case BRS_TRUE: + // The TRUE side of NAN >= x is unreachable. + if (op1.known_isnan ()) + r.set_undefined (); + else + { + build_le (r, type, op1); + r.clear_nan (); + } break; - case BRS_TRUE: - build_le (r, type, op1); - r.clear_nan (); + case BRS_FALSE: + // On the FALSE side of NAN >= x, we know nothing about x. + if (op1.known_isnan ()) + r.set_varying (type); + else + build_gt (r, type, op1); break; default: @@ -949,23 +1029,30 @@ foperator_unordered::fold_range (irange &r, tree type, bool foperator_unordered::op1_range (frange &r, tree type, const irange &lhs, - const frange &op2 ATTRIBUTE_UNUSED, + const frange &op2, relation_kind) const { switch (get_bool_state (r, lhs, type)) { case BRS_TRUE: - r.set_varying (type); // Since at least one operand must be NAN, if one of them is // not, the other must be. if (!op2.maybe_isnan ()) r.set_nan (type); + else + r.set_varying (type); break; case BRS_FALSE: - r.set_varying (type); - // A false UNORDERED means both operands are !NAN. - r.clear_nan (); + // A false UNORDERED means both operands are !NAN, so it's + // impossible for op2 to be a NAN. + if (op2.known_isnan ()) + r.set_undefined (); + else + { + r.set_varying (type); + r.clear_nan (); + } break; default: @@ -1002,10 +1089,10 @@ foperator_ordered::fold_range (irange &r, tree type, const frange &op1, const frange &op2, relation_kind) const { - if (!op1.maybe_isnan () && !op2.maybe_isnan ()) - r = range_true (type); - else if (op1.known_isnan () || op2.known_isnan ()) + if (op1.known_isnan () || op2.known_isnan ()) r = range_false (type); + else if (!op1.maybe_isnan () && !op2.maybe_isnan ()) + r = range_true (type); else r = range_true_and_false (type); return true; @@ -1014,15 +1101,21 @@ foperator_ordered::fold_range (irange &r, tree type, bool foperator_ordered::op1_range (frange &r, tree type, const irange &lhs, - const frange &op2 ATTRIBUTE_UNUSED, + const frange &op2, relation_kind rel) const { switch (get_bool_state (r, lhs, type)) { case BRS_TRUE: - r.set_varying (type); - // The TRUE side of op1 ORDERED op2 implies op1 is !NAN. - r.clear_nan (); + // The TRUE side of ORDERED means both operands are !NAN, so + // it's impossible for op2 to be a NAN. + if (op2.known_isnan ()) + r.set_undefined (); + else + { + r.set_varying (type); + r.clear_nan (); + } break; case BRS_FALSE: @@ -1046,13 +1139,16 @@ class foperator_relop_unknown : public range_operator_float public: bool fold_range (irange &r, tree type, - const frange &, const frange &, + const frange &op1, const frange &op2, relation_kind) const final override { - r.set_varying (type); + if (op1.known_isnan () || op2.known_isnan ()) + r = range_true (type); + else + r.set_varying (type); return true; } -} fop_relop_unknown; +} fop_unordered_relop_unknown; // Instantiate a range_op_table for floating point operations. @@ -1077,11 +1173,11 @@ floating_op_table::floating_op_table () set (LE_EXPR, fop_le); set (GT_EXPR, fop_gt); set (GE_EXPR, fop_ge); - set (UNLE_EXPR, fop_relop_unknown); - set (UNLT_EXPR, fop_relop_unknown); - set (UNGE_EXPR, fop_relop_unknown); - set (UNGT_EXPR, fop_relop_unknown); - set (UNEQ_EXPR, fop_relop_unknown); + set (UNLE_EXPR, fop_unordered_relop_unknown); + set (UNLT_EXPR, fop_unordered_relop_unknown); + set (UNGE_EXPR, fop_unordered_relop_unknown); + set (UNGT_EXPR, fop_unordered_relop_unknown); + set (UNEQ_EXPR, fop_unordered_relop_unknown); set (ORDERED_EXPR, fop_ordered); set (UNORDERED_EXPR, fop_unordered); } diff --git a/gcc/range-op.cc b/gcc/range-op.cc index 806edf1..fc930f4 100644 --- a/gcc/range-op.cc +++ b/gcc/range-op.cc @@ -2951,6 +2951,15 @@ operator_bitwise_and::op1_range (irange &r, tree type, } if (r.undefined_p ()) set_nonzero_range_from_mask (r, type, lhs); + + // For 0 = op1 & MASK, op1 is ~MASK. + if (lhs.zero_p () && op2.singleton_p ()) + { + wide_int nz = wi::bit_not (op2.get_nonzero_bits ()); + int_range<2> tmp (type); + tmp.set_nonzero_bits (nz); + r.intersect (tmp); + } return true; } @@ -4159,76 +4168,68 @@ get_float_handler (enum tree_code code, tree) return (*floating_tree_table)[code]; } -range_op_handler::range_op_handler (tree_code code, tree type) - : m_code (code), m_type (type) -{ -} - -range_op_handler::range_op_handler (const gimple *s) +void +range_op_handler::set_op_handler (tree_code code, tree type) { - if (const gassign *ass = dyn_cast<const gassign *> (s)) + if (irange::supports_p (type)) { - m_code = gimple_assign_rhs_code (ass); - // The LHS of a comparison is always an int, so we must look at - // the operands. - if (TREE_CODE_CLASS (m_code) == tcc_comparison) - m_type = TREE_TYPE (gimple_assign_rhs1 (ass)); - else - m_type = TREE_TYPE (gimple_assign_lhs (ass)); + m_float = NULL; + m_int = get_handler (code, type); + m_valid = m_int != NULL; } - else if (const gcond *cond = dyn_cast<const gcond *> (s)) + else if (frange::supports_p (type)) { - m_code = gimple_cond_code (cond); - m_type = TREE_TYPE (gimple_cond_lhs (cond)); + m_int = NULL; + m_float = get_float_handler (code, type); + m_valid = m_float != NULL; } else { - // A null type means there is no handler for this combination, - // but the decision whether there is one or not, is delayed - // until operator bool below is queried. - m_code = NOP_EXPR; - m_type = nullptr; + m_int = NULL; + m_float = NULL; + m_valid = false; } } -// Return TRUE if there is a handler available for the current -// combination of tree_code and type. +range_op_handler::range_op_handler () +{ + m_int = NULL; + m_float = NULL; + m_valid = false; +} -range_op_handler::operator bool () const +range_op_handler::range_op_handler (tree_code code, tree type) { - if (!m_type) - return false; - if (frange::supports_p (m_type)) - return get_float_handler (m_code, m_type); - return get_handler (m_code, m_type); + set_op_handler (code, type); } + bool range_op_handler::fold_range (vrange &r, tree type, const vrange &lh, const vrange &rh, relation_kind rel) const { - if (irange::supports_p (m_type)) - { - range_operator *op = get_handler (m_code, m_type); - return op->fold_range (as_a <irange> (r), type, - as_a <irange> (lh), - as_a <irange> (rh), rel); - } - if (frange::supports_p (m_type)) + gcc_checking_assert (m_valid); + if (m_int) + return m_int->fold_range (as_a <irange> (r), type, + as_a <irange> (lh), + as_a <irange> (rh), rel); + + if (is_a <irange> (r)) { - range_operator_float *op = get_float_handler (m_code, m_type); - if (is_a <irange> (r)) - return op->fold_range (as_a <irange> (r), type, - as_a <frange> (lh), - as_a <frange> (rh), rel); - return op->fold_range (as_a <frange> (r), type, - as_a <frange> (lh), - as_a <frange> (rh), rel); + if (is_a <irange> (rh)) + return m_float->fold_range (as_a <irange> (r), type, + as_a <frange> (lh), + as_a <irange> (rh), rel); + else + return m_float->fold_range (as_a <irange> (r), type, + as_a <frange> (lh), + as_a <frange> (rh), rel); } - gcc_unreachable (); - return false; + return m_float->fold_range (as_a <frange> (r), type, + as_a <frange> (lh), + as_a <frange> (rh), rel); } bool @@ -4237,26 +4238,19 @@ range_op_handler::op1_range (vrange &r, tree type, const vrange &op2, relation_kind rel) const { - if (irange::supports_p (m_type)) - { - range_operator *op = get_handler (m_code, m_type); - return op->op1_range (as_a <irange> (r), type, - as_a <irange> (lhs), - as_a <irange> (op2), rel); - } - if (frange::supports_p (m_type)) - { - range_operator_float *op = get_float_handler (m_code, m_type); - if (is_a <irange> (lhs)) - return op->op1_range (as_a <frange> (r), type, - as_a <irange> (lhs), - as_a <frange> (op2), rel); - return op->op1_range (as_a <frange> (r), type, - as_a <frange> (lhs), - as_a <frange> (op2), rel); - } - gcc_unreachable (); - return false; + gcc_checking_assert (m_valid); + if (m_int) + return m_int->op1_range (as_a <irange> (r), type, + as_a <irange> (lhs), + as_a <irange> (op2), rel); + + if (is_a <irange> (lhs)) + return m_float->op1_range (as_a <frange> (r), type, + as_a <irange> (lhs), + as_a <frange> (op2), rel); + return m_float->op1_range (as_a <frange> (r), type, + as_a <frange> (lhs), + as_a <frange> (op2), rel); } bool @@ -4265,26 +4259,19 @@ range_op_handler::op2_range (vrange &r, tree type, const vrange &op1, relation_kind rel) const { - if (irange::supports_p (m_type)) - { - range_operator *op = get_handler (m_code, m_type); - return op->op2_range (as_a <irange> (r), type, - as_a <irange> (lhs), - as_a <irange> (op1), rel); - } - if (frange::supports_p (m_type)) - { - range_operator_float *op = get_float_handler (m_code, m_type); - if (is_a <irange> (lhs)) - return op->op2_range (as_a <frange> (r), type, - as_a <irange> (lhs), - as_a <frange> (op1), rel); - return op->op2_range (as_a <frange> (r), type, - as_a <frange> (lhs), - as_a <frange> (op1), rel); - } - gcc_unreachable (); - return false; + gcc_checking_assert (m_valid); + if (m_int) + return m_int->op2_range (as_a <irange> (r), type, + as_a <irange> (lhs), + as_a <irange> (op1), rel); + + if (is_a <irange> (lhs)) + return m_float->op2_range (as_a <frange> (r), type, + as_a <irange> (lhs), + as_a <frange> (op1), rel); + return m_float->op2_range (as_a <frange> (r), type, + as_a <frange> (lhs), + as_a <frange> (op1), rel); } relation_kind @@ -4293,26 +4280,19 @@ range_op_handler::lhs_op1_relation (const vrange &lhs, const vrange &op2, relation_kind rel) const { - if (irange::supports_p (m_type)) - { - range_operator *op = get_handler (m_code, m_type); - return op->lhs_op1_relation (as_a <irange> (lhs), - as_a <irange> (op1), - as_a <irange> (op2), rel); - } - if (frange::supports_p (m_type)) - { - range_operator_float *op = get_float_handler (m_code, m_type); - if (is_a <irange> (lhs)) - return op->lhs_op1_relation (as_a <irange> (lhs), - as_a <frange> (op1), - as_a <frange> (op2), rel); - return op->lhs_op1_relation (as_a <frange> (lhs), - as_a <frange> (op1), - as_a <frange> (op2), rel); - } - gcc_unreachable (); - return VREL_VARYING; + gcc_checking_assert (m_valid); + if (m_int) + return m_int->lhs_op1_relation (as_a <irange> (lhs), + as_a <irange> (op1), + as_a <irange> (op2), rel); + + if (is_a <irange> (lhs)) + return m_float->lhs_op1_relation (as_a <irange> (lhs), + as_a <frange> (op1), + as_a <frange> (op2), rel); + return m_float->lhs_op1_relation (as_a <frange> (lhs), + as_a <frange> (op1), + as_a <frange> (op2), rel); } relation_kind @@ -4321,43 +4301,28 @@ range_op_handler::lhs_op2_relation (const vrange &lhs, const vrange &op2, relation_kind rel) const { - if (irange::supports_p (m_type)) - { - range_operator *op = get_handler (m_code, m_type); - return op->lhs_op2_relation (as_a <irange> (lhs), - as_a <irange> (op1), - as_a <irange> (op2), rel); - } - if (frange::supports_p (m_type)) - { - range_operator_float *op = get_float_handler (m_code, m_type); - if (is_a <irange> (lhs)) - return op->lhs_op2_relation (as_a <irange> (lhs), - as_a <frange> (op1), - as_a <frange> (op2), rel); - return op->lhs_op2_relation (as_a <frange> (lhs), - as_a <frange> (op1), - as_a <frange> (op2), rel); - } - gcc_unreachable (); - return VREL_VARYING; + gcc_checking_assert (m_valid); + if (m_int) + return m_int->lhs_op2_relation (as_a <irange> (lhs), + as_a <irange> (op1), + as_a <irange> (op2), rel); + + if (is_a <irange> (lhs)) + return m_float->lhs_op2_relation (as_a <irange> (lhs), + as_a <frange> (op1), + as_a <frange> (op2), rel); + return m_float->lhs_op2_relation (as_a <frange> (lhs), + as_a <frange> (op1), + as_a <frange> (op2), rel); } relation_kind range_op_handler::op1_op2_relation (const vrange &lhs) const { - if (irange::supports_p (m_type)) - { - range_operator *op = get_handler (m_code, m_type); - return op->op1_op2_relation (as_a <irange> (lhs)); - } - if (frange::supports_p (m_type)) - { - range_operator_float *op = get_float_handler (m_code, m_type); - return op->op1_op2_relation (as_a <irange> (lhs)); - } - gcc_unreachable (); - return VREL_VARYING; + gcc_checking_assert (m_valid); + if (m_int) + return m_int->op1_op2_relation (as_a <irange> (lhs)); + return m_float->op1_op2_relation (as_a <irange> (lhs)); } // Cast the range in R to TYPE. @@ -4656,6 +4621,15 @@ range_op_bitwise_and_tests () op_bitwise_and.op1_range (res, integer_type_node, i1, i2); ASSERT_TRUE (res == int_range<1> (integer_type_node)); + // For 0 = x & MASK, x is ~MASK. + { + int_range<2> zero (integer_zero_node, integer_zero_node); + int_range<2> mask = int_range<2> (INT (7), INT (7)); + op_bitwise_and.op1_range (res, integer_type_node, zero, mask); + wide_int inv = wi::shwi (~7U, TYPE_PRECISION (integer_type_node)); + ASSERT_TRUE (res.get_nonzero_bits () == inv); + } + // (NONZERO | X) is nonzero. i1.set_nonzero (integer_type_node); i2.set_varying (integer_type_node); diff --git a/gcc/range-op.h b/gcc/range-op.h index 37d9aa9..b2f063a 100644 --- a/gcc/range-op.h +++ b/gcc/range-op.h @@ -117,6 +117,11 @@ public: const frange &lh, const frange &rh, relation_kind rel = VREL_VARYING) const; + // Unary operations have the range of the LHS as op2. + virtual bool fold_range (irange &r, tree type, + const frange &lh, + const irange &rh, + relation_kind rel = VREL_VARYING) const; virtual bool fold_range (irange &r, tree type, const frange &lh, const frange &rh, @@ -160,9 +165,9 @@ public: class range_op_handler { public: + range_op_handler (); range_op_handler (enum tree_code code, tree type); - range_op_handler (const gimple *s); - operator bool () const; + inline operator bool () const { return m_valid; } bool fold_range (vrange &r, tree type, const vrange &lh, @@ -185,9 +190,11 @@ public: const vrange &op2, relation_kind = VREL_VARYING) const; relation_kind op1_op2_relation (const vrange &lhs) const; -private: - enum tree_code m_code; - tree m_type; +protected: + void set_op_handler (enum tree_code code, tree type); + bool m_valid; + range_operator *m_int; + range_operator_float *m_float; }; extern bool range_cast (vrange &, tree type); diff --git a/gcc/real.cc b/gcc/real.cc index 73bbac6..aae7c33 100644 --- a/gcc/real.cc +++ b/gcc/real.cc @@ -1900,6 +1900,14 @@ real_to_decimal (char *str, const REAL_VALUE_TYPE *r_orig, size_t buf_size, digits, crop_trailing_zeros, VOIDmode); } +DEBUG_FUNCTION void +debug (const REAL_VALUE_TYPE &r) +{ + char s[60]; + real_to_hexadecimal (s, &r, sizeof (s), 0, 1); + fprintf (stderr, "%s\n", s); +} + /* Render R as a hexadecimal floating point constant. Emit DIGITS significant digits in the result, bounded by BUF_SIZE. If DIGITS is 0, choose the maximum for the representation. If CROP_TRAILING_ZEROS, diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a6048da..0e7cd64e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,261 @@ +2022-09-25 Mikael Morin <mikael@gcc.gnu.org> + + PR fortran/41453 + * gfortran.dg/intent_optimize_10.f90: New test. + +2022-09-25 Mikael Morin <mikael@gcc.gnu.org> + + PR fortran/41453 + PR fortran/99169 + * gfortran.dg/intent_optimize_9.f90: New test. + +2022-09-25 Mikael Morin <mikael@gcc.gnu.org> + + PR fortran/41453 + PR fortran/87401 + * gfortran.dg/intent_optimize_8.f90: New test. + +2022-09-25 Mikael Morin <mikael@gcc.gnu.org> + + PR fortran/41453 + PR fortran/87395 + * gfortran.dg/intent_optimize_7.f90: New test. + +2022-09-25 Mikael Morin <mikael@gcc.gnu.org> + + PR fortran/41453 + PR fortran/87395 + * gfortran.dg/intent_optimize_6.f90: New test. + +2022-09-25 Harald Anlauf <anlauf@gmx.de> + Mikael Morin <mikael@gcc.gnu.org> + + PR fortran/105012 + * gfortran.dg/intent_optimize_5.f90: New test. + +2022-09-25 Mikael Morin <mikael@gcc.gnu.org> + + PR fortran/106817 + * gfortran.dg/intent_optimize_4.f90: New test. + +2022-09-25 Mikael Morin <mikael@gcc.gnu.org> + + PR fortran/105012 + * gfortran.dg/intent_out_15.f90: New test. + +2022-09-24 Jakub Jelinek <jakub@redhat.com> + + PR c/107001 + * c-c++-common/gomp/pr107001.c: New test. + +2022-09-24 Jakub Jelinek <jakub@redhat.com> + + PR c/106981 + * c-c++-common/gomp/pr106981.c: New test. + +2022-09-23 Joseph Myers <joseph@codesourcery.com> + + * gcc.dg/c2x-complit-1.c, gcc.dg/c2x-concat-1.c, + gcc.dg/cpp/c2x-ucn-1.c: New tests. + +2022-09-23 Torbjörn SVENSSON <torbjorn.svensson@foss.st.com> + Yvan ROUX <yvan.roux@foss.st.com> + + * gcc.target/aarch64/advsimd-intrinsics/vld1x2.c: Replace + dg-xfail-if with dg-skip-if. + * gcc.target/aarch64/advsimd-intrinsics/vld1x3.c: Likewise. + * gcc.target/aarch64/advsimd-intrinsics/vld1x4.c: Likewise. + +2022-09-23 Marek Polacek <polacek@redhat.com> + + PR c++/106784 + * g++.dg/ext/has-builtin-1.C: Enhance to test __is_convertible and + __is_nothrow_convertible. + * g++.dg/ext/is_convertible1.C: New test. + * g++.dg/ext/is_convertible2.C: New test. + * g++.dg/ext/is_nothrow_convertible1.C: New test. + * g++.dg/ext/is_nothrow_convertible2.C: New test. + +2022-09-23 zhongjuzhe <juzhe.zhong@rivai.ai> + + * selftests/riscv/empty-func.rtl: New test. + +2022-09-23 Richard Biener <rguenther@suse.de> + + PR tree-optimization/106922 + * g++.dg/torture/pr106922.C: New testcase. + +2022-09-23 Tamar Christina <tamar.christina@arm.com> + + * lib/scanasm.exp (check_function_body): Add debug output to verbose log + on failure. + +2022-09-23 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/106922 + * g++.dg/tree-ssa/pr106922.C: Scan in cddce3 dump rather than + dce3. Remove -fdump-tree-pre-details from dg-options. + +2022-09-23 Hu, Lin1 <lin1.hu@intel.com> + + PR target/94962 + * gcc.target/i386/avx256-unaligned-load-1.c: Modify test. + * gcc.target/i386/avx256-unaligned-store-1.c: Ditto. + * gcc.target/i386/avx256-unaligned-store-2.c: Ditto. + * gcc.target/i386/avx256-unaligned-store-3.c: Ditto. + * gcc.target/i386/pr94962-1.c: New test. + * gcc.target/i386/pr94962-2.c: Ditto. + * gcc.target/i386/pr94962-3.c: Ditto. + * gcc.target/i386/pr94962-4.c: Ditto. + +2022-09-23 Marek Polacek <polacek@redhat.com> + + PR c++/106983 + * g++.dg/other/error36.C: New test. + +2022-09-22 José Rui Faustino de Sousa <jrfsousa@gmail.com> + + PR fortran/100103 + * gfortran.dg/PR100103.f90: New test. + +2022-09-22 Harald Anlauf <anlauf@gmx.de> + + PR fortran/82868 + * gfortran.dg/associate_26a.f90: New test. + +2022-09-22 Richard Biener <rguenther@suse.de> + + PR tree-optimization/102801 + * g++.dg/warn/Wuninitialized-33.C: New testcase. + +2022-09-22 Patrick Palka <ppalka@redhat.com> + + PR c++/106826 + * g++.dg/modules/partial-2_a.C: New test. + * g++.dg/modules/partial-2_b.C: New test. + +2022-09-22 David Malcolm <dmalcolm@redhat.com> + + PR c/106830 + * gcc.dg/Wxor-used-as-pow-pr106830.c: New test. + +2022-09-22 Richard Biener <rguenther@suse.de> + + PR tree-optimization/106922 + * gcc.dg/tree-ssa/ssa-fre-100.c: New testcase. + * g++.dg/tree-ssa/pr106922.C: Adjust. + +2022-09-22 Richard Biener <rguenther@suse.de> + + PR tree-optimization/99407 + * gcc.dg/vect/tsvc/vect-tsvc-s243.c: Remove XFAIL. + +2022-09-22 liuhongt <hongtao.liu@intel.com> + + * gcc.target/i386/pr106994.c: New test. + +2022-09-21 Richard Biener <rguenther@suse.de> + + PR tree-optimization/106984 + * gcc.dg/tsan/pr106984.c: New testcase. + +2022-09-21 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> + + * gfortran.dg/ieee/rounding_3.f90: New test. + +2022-09-21 Aldy Hernandez <aldyh@redhat.com> + + PR tree-optimization/106967 + * gcc.dg/tree-ssa/pr106967.c: New test. + +2022-09-21 liuhongt <hongtao.liu@intel.com> + + * gcc.target/i386/pr106963.c: New test. + +2022-09-20 Tobias Burnus <tobias@codesourcery.com> + + PR fortran/104143 + * gfortran.dg/c-interop/c407b-2.f90: Remove dg-error. + * gfortran.dg/assumed_type_16.f90: New test. + * gfortran.dg/assumed_type_17.f90: New test. + +2022-09-20 Harald Anlauf <anlauf@gmx.de> + + PR fortran/106986 + * gfortran.dg/pr106986.f90: New test. + +2022-09-20 Harald Anlauf <anlauf@gmx.de> + + PR fortran/106985 + * gfortran.dg/pr106985.f90: New test. + +2022-09-20 Patrick Palka <ppalka@redhat.com> + + * g++.dg/modules/xtreme-header-2.h: Include <execution>. + * g++.dg/modules/xtreme-header-6.h: Include implemented + C++20 library headers. + * g++.dg/modules/xtreme-header.h: Likewise. Remove + NO_ASSOCIATED_LAMBDA workaround. Include implemented C++23 + library headers. + +2022-09-20 Patrick Palka <ppalka@redhat.com> + + * g++.dg/modules/auto-3.h: New test. + * g++.dg/modules/auto-3_a.H: New test. + * g++.dg/modules/auto-3_b.C: New test. + +2022-09-20 José Rui Faustino de Sousa <jrfsousa@gmail.com> + + PR fortran/100132 + * gfortran.dg/PR100132.f90: New test. + +2022-09-20 Richard Sandiford <richard.sandiford@arm.com> + + * gcc.dg/vect/pr106914.c: New test. + * g++.dg/vect/pr106794.cc: Likewise. + +2022-09-20 Richard Sandiford <richard.sandiford@arm.com> + + * gcc.dg/vect/vect-gather-5.c: New test. + +2022-09-20 Aldy Hernandez <aldyh@redhat.com> + + PR tree-optimization/106970 + * gcc.dg/tree-ssa/pr106970.c: New test. + +2022-09-20 Patrick Palka <ppalka@redhat.com> + + PR c++/106761 + * g++.dg/modules/pr106761.h: New test. + * g++.dg/modules/pr106761_a.H: New test. + * g++.dg/modules/pr106761_b.C: New test. + +2022-09-20 Martin Liska <mliska@suse.cz> + + * g++.dg/warn/Wclass-memaccess.C: Replace "the the" with "the". + * g++.dg/warn/Wconversion-real-integer2.C: Likewise. + * gcc.target/powerpc/p9-extract-1.c: Likewise. + * gcc.target/s390/s390.exp: Likewise. + * gcc.target/s390/zvector/vec-cmp-2.c: Likewise. + * gdc.dg/torture/simd_store.d: Likewise. + * gfortran.dg/actual_array_offset_1.f90: Likewise. + * gfortran.dg/pdt_15.f03: Likewise. + * gfortran.dg/pointer_array_8.f90: Likewise. + +2022-09-20 liuhongt <hongtao.liu@intel.com> + + * gcc.target/i386/pr106910-1.c: New test. + +2022-09-20 konglin1 <lingling.kong@intel.com> + + * gcc.target/i386/pr105735-1.c: New test. + * gcc.target/i386/pr105735-2.c: New test. + +2022-09-20 konglin1 <lingling.kong@intel.com> + + PR target/106887 + * gcc.target/i386/vect-bfloat16-2c.c: New test. + 2022-09-19 Marek Polacek <polacek@redhat.com> PR c/106947 diff --git a/gcc/testsuite/c-c++-common/goacc/reduction-7.c b/gcc/testsuite/c-c++-common/goacc/reduction-7.c new file mode 100644 index 0000000..482b0ab --- /dev/null +++ b/gcc/testsuite/c-c++-common/goacc/reduction-7.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ + +/* PR middle-end/106982 */ + +long long n = 100; +int multiplicitive_n = 128; + +void test1(double *rand, double *a, double *b, double *c) +{ +#pragma acc data copyin(a[0:10*multiplicitive_n], b[0:10*multiplicitive_n]) copyout(c[0:10]) + { +#pragma acc parallel loop + for (int i = 0; i < 10; ++i) + { + double temp = 1.0; +#pragma acc loop vector reduction(*:temp) + for (int j = 0; j < multiplicitive_n; ++j) + temp *= a[(i * multiplicitive_n) + j] + b[(i * multiplicitive_n) + j]; + c[i] = temp; + } + } +} diff --git a/gcc/testsuite/c-c++-common/goacc/reduction-8.c b/gcc/testsuite/c-c++-common/goacc/reduction-8.c new file mode 100644 index 0000000..2c3ed49 --- /dev/null +++ b/gcc/testsuite/c-c++-common/goacc/reduction-8.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ + +/* PR middle-end/106982 */ + +void test1(double *c) +{ + double reduced[5]; +#pragma acc parallel loop gang private(reduced) + for (int x = 0; x < 5; ++x) +#pragma acc loop worker reduction(*:reduced) + for (int y = 0; y < 5; ++y) { } +} diff --git a/gcc/testsuite/c-c++-common/gomp/pr106981.c b/gcc/testsuite/c-c++-common/gomp/pr106981.c new file mode 100644 index 0000000..a21d3c2 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/pr106981.c @@ -0,0 +1,9 @@ +/* PR c/106981 */ +/* { dg-do compile } */ + +void +foo (int a, double *b, double *c, double *d, long long e) +{ +#pragma omp atomic capture + c[a] = d[((int) (e / 10 + 1))] = b[a] + d[((int) e / 10 + 1)]; /* { dg-error "invalid form" } */ +} diff --git a/gcc/testsuite/c-c++-common/gomp/pr107001.c b/gcc/testsuite/c-c++-common/gomp/pr107001.c new file mode 100644 index 0000000..9c19d9b --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/pr107001.c @@ -0,0 +1,14 @@ +/* PR c/107001 */ +/* { dg-do compile } */ +/* { dg-options "-O0 -fopenmp -fexceptions" } */ +/* { dg-require-effective-target exceptions } */ + +void bar (void); +void foo (void) +{ + #pragma omp taskgroup + { + #pragma omp taskgroup + bar (); + } +} diff --git a/gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C b/gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C index d3e4072..0537e1d 100644 --- a/gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C +++ b/gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C @@ -504,8 +504,8 @@ #ifndef __cpp_char8_t # error "__cpp_char8_t" -#elif __cpp_char8_t != 201811 -# error "__cpp_char8_t != 201811" +#elif __cpp_char8_t != 202207 +# error "__cpp_char8_t != 202207" #endif #ifndef __cpp_designated_initializers diff --git a/gcc/testsuite/g++.dg/cpp2a/char8_t3.C b/gcc/testsuite/g++.dg/cpp2a/char8_t3.C new file mode 100644 index 0000000..071a718 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/char8_t3.C @@ -0,0 +1,37 @@ +// PR c++/106656 - P2513 - char8_t Compatibility and Portability Fixes +// { dg-do compile { target c++20 } } + +const char *p1 = u8""; // { dg-error "invalid conversion" } +const unsigned char *p2 = u8""; // { dg-error "invalid conversion" } +const signed char *p3 = u8""; // { dg-error "invalid conversion" } +const char *p4 = { u8"" }; // { dg-error "invalid conversion" } +const unsigned char *p5 = { u8"" }; // { dg-error "invalid conversion" } +const signed char *p6 = { u8"" }; // { dg-error "invalid conversion" } +const char *p7 = static_cast<const char *>(u8""); // { dg-error "invalid" } +const char a1[] = u8"text"; +const unsigned char a2[] = u8""; +const signed char a3[] = u8""; // { dg-error "cannot initialize array" } +const char a4[] = { u8"text" }; +const unsigned char a5[] = { u8"" }; +const signed char a6[] = { u8"" }; // { dg-error "cannot initialize array" } + +const char * +resource_id () +{ + static const char res_id[] = u8""; + return res_id; +} + +const char8_t x[] = "fail"; // { dg-error "cannot initialize array" } + +void fn (const char a[]); +void +g () +{ + fn (u8"z"); // { dg-error "invalid conversion" } +} + +char c = u8'c'; +unsigned char uc = u8'c'; +signed char sc = u8'c'; +char8_t c8 = 'c'; diff --git a/gcc/testsuite/g++.dg/cpp2a/char8_t4.C b/gcc/testsuite/g++.dg/cpp2a/char8_t4.C new file mode 100644 index 0000000..c18081b --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/char8_t4.C @@ -0,0 +1,17 @@ +// PR c++/106656 - P2513 - char8_t Compatibility and Portability Fixes +// { dg-do compile { target c++20 } } +// [diff.cpp20.dcl] + +struct A { + char8_t s[10]; +}; +struct B { + char s[10]; +}; + +void f(A); +void f(B); + +int main() { + f({u8""}); // { dg-error "ambiguous" } +} diff --git a/gcc/testsuite/g++.dg/cpp2a/feat-cxx2a.C b/gcc/testsuite/g++.dg/cpp2a/feat-cxx2a.C index c65ea6b..02f3a37 100644 --- a/gcc/testsuite/g++.dg/cpp2a/feat-cxx2a.C +++ b/gcc/testsuite/g++.dg/cpp2a/feat-cxx2a.C @@ -504,8 +504,8 @@ #ifndef __cpp_char8_t # error "__cpp_char8_t" -#elif __cpp_char8_t != 201811 -# error "__cpp_char8_t != 201811" +#elif __cpp_char8_t != 202207 +# error "__cpp_char8_t != 202207" #endif #ifndef __cpp_designated_initializers diff --git a/gcc/testsuite/g++.dg/ext/char8_t-feature-test-macro-2.C b/gcc/testsuite/g++.dg/ext/char8_t-feature-test-macro-2.C index df1063f..2d0f904 100644 --- a/gcc/testsuite/g++.dg/ext/char8_t-feature-test-macro-2.C +++ b/gcc/testsuite/g++.dg/ext/char8_t-feature-test-macro-2.C @@ -5,6 +5,6 @@ #if !defined(__cpp_char8_t) # error __cpp_char8_t is not defined! -#elif __cpp_char8_t != 201811 -# error __cpp_char8_t != 201811 +#elif __cpp_char8_t != 202207 +# error __cpp_char8_t != 202207 #endif diff --git a/gcc/testsuite/g++.dg/ext/char8_t-init-2.C b/gcc/testsuite/g++.dg/ext/char8_t-init-2.C index c713bc1..02a96ff 100644 --- a/gcc/testsuite/g++.dg/ext/char8_t-init-2.C +++ b/gcc/testsuite/g++.dg/ext/char8_t-init-2.C @@ -21,7 +21,7 @@ const char8_t (&rca4)[2] = u8"x"; const char8_t (&rca5)[2] = u"x"; // { dg-error "invalid initialization of reference of type .const char8_t ....... from expression of type .const char16_t ...." "char8_t" } char ca1[] = "x"; -char ca2[] = u8"x"; // { dg-error "from a string literal with type array of .char8_t." "char8_t" } +char ca2[] = u8"x"; char8_t ca3[] = "x"; // { dg-error "from a string literal with type array of .char." "char8_t" } char8_t ca4[] = u8"x"; char8_t ca5[] = u"x"; // { dg-error "from a string literal with type array of .char16_t." "char8_t" } @@ -30,4 +30,4 @@ signed char sca1[] = "x"; signed char sca2[] = u8"x"; // { dg-error "from a string literal with type array of .char8_t." "char8_t" } unsigned char uca1[] = "x"; -unsigned char uca2[] = u8"x"; // { dg-error "from a string literal with type array of .char8_t." "char8_t" } +unsigned char uca2[] = u8"x"; diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C b/gcc/testsuite/g++.dg/ext/has-builtin-1.C index fe25cb2..17dabf6 100644 --- a/gcc/testsuite/g++.dg/ext/has-builtin-1.C +++ b/gcc/testsuite/g++.dg/ext/has-builtin-1.C @@ -131,3 +131,9 @@ #if !__has_builtin (__builtin_is_pointer_interconvertible_with_class) # error "__has_builtin (__builtin_is_pointer_interconvertible_with_class) failed" #endif +#if !__has_builtin (__is_convertible) +# error "__has_builtin (__is_convertible) failed" +#endif +#if !__has_builtin (__is_nothrow_convertible) +# error "__has_builtin (__is_nothrow_convertible) failed" +#endif diff --git a/gcc/testsuite/g++.dg/ext/is_convertible1.C b/gcc/testsuite/g++.dg/ext/is_convertible1.C new file mode 100644 index 0000000..2e72945 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/is_convertible1.C @@ -0,0 +1,269 @@ +// PR c++/106784 +// { dg-do compile { target c++11 } } + +#define SA(X) static_assert((X),#X) + +template<typename From, typename To> +struct is_convertible { + static const bool value = __is_convertible(From, To); +}; + +struct from_int { + from_int(int); +}; + +struct from_charp { + from_charp(const char *); +}; + +struct to_int { + operator int(); +}; + +typedef int Fn(int); +typedef char Arr[10]; +enum E { XYZZY }; + +SA(!__is_convertible(int, void)); +SA(__is_convertible(int, int)); +SA(__is_convertible(int, from_int)); +SA(__is_convertible(long, from_int)); +SA(__is_convertible(double, from_int)); +SA(__is_convertible(const int, from_int)); +SA(__is_convertible(const int&, from_int)); +SA(__is_convertible(to_int, int)); +SA(__is_convertible(to_int, const int&)); +SA(__is_convertible(to_int, long)); +SA(!__is_convertible(to_int, int&)); +SA(!__is_convertible(to_int, from_int)); +SA(!__is_convertible(int, Fn)); +SA(!__is_convertible(int, Fn*)); +SA(!__is_convertible(int, Fn&)); +SA(!__is_convertible(int, Arr)); +SA(!__is_convertible(int, Arr&)); +SA(!__is_convertible(int, int&)); +SA(__is_convertible(int, const int&)); +SA(!__is_convertible(const int, int&)); +SA(__is_convertible(const int, const int&)); +SA(!__is_convertible(int, int*)); + +SA(!__is_convertible(int, E)); +SA(__is_convertible(E, int)); + +SA(__is_convertible(int&, int)); +SA(__is_convertible(int&, int&)); +SA(__is_convertible(int&, const int&)); +SA(!__is_convertible(const int&, int&)); +SA(__is_convertible(const int&, const int&)); +SA(!__is_convertible(int&, int*)); +SA(!__is_convertible(int&, void)); +SA(!__is_convertible(int&, Fn)); +SA(!__is_convertible(int&, Fn*)); +SA(!__is_convertible(int&, Fn&)); +SA(!__is_convertible(int&, Arr)); +SA(!__is_convertible(int&, Arr&)); + +SA(!__is_convertible(int*, int)); +SA(!__is_convertible(int*, int&)); +SA(!__is_convertible(int*, void)); +SA(__is_convertible(int*, int*)); +SA(__is_convertible(int*, const int*)); +SA(!__is_convertible(const int*, int*)); +SA(__is_convertible(const int*, const int*)); +SA(!__is_convertible(int*, Fn)); +SA(!__is_convertible(int*, Fn*)); +SA(!__is_convertible(int*, Fn&)); +SA(!__is_convertible(int*, Arr)); +SA(!__is_convertible(int*, Arr&)); +SA(!__is_convertible(int*, float*)); + +SA(__is_convertible(void, void)); +SA(!__is_convertible(void, char)); +SA(!__is_convertible(void, char&)); +SA(!__is_convertible(void, char*)); +SA(!__is_convertible(char, void)); +SA(__is_convertible(const void, void)); +SA(__is_convertible(void, const void)); +SA(__is_convertible(const void, const void)); +SA(!__is_convertible(void, Fn)); +SA(!__is_convertible(void, Fn&)); +SA(!__is_convertible(void, Fn*)); +SA(!__is_convertible(void, Arr)); +SA(!__is_convertible(void, Arr&)); + +SA(!__is_convertible(Fn, void)); +SA(!__is_convertible(Fn, Fn)); +SA(__is_convertible(Fn, Fn*)); +SA(__is_convertible(Fn, Fn&)); +SA(!__is_convertible(int(int), int(int))); +SA(__is_convertible(int(int), int(&)(int))); +SA(__is_convertible(int(int), int(&&)(int))); +SA(__is_convertible(int(int), int(*)(int))); +SA(__is_convertible(int(int), int(*const)(int))); +SA(!__is_convertible(int(int), char)); +SA(!__is_convertible(int(int), char*)); +SA(!__is_convertible(int(int), char&)); + +SA(!__is_convertible(Fn&, void)); +SA(!__is_convertible(Fn&, Fn)); +SA(__is_convertible(Fn&, Fn&)); +SA(__is_convertible(Fn&, Fn*)); +SA(!__is_convertible(Fn&, Arr)); +SA(!__is_convertible(Fn&, Arr&)); +SA(!__is_convertible(Fn&, char)); +SA(!__is_convertible(Fn&, char&)); +SA(!__is_convertible(Fn&, char*)); + +SA(!__is_convertible(Fn*, void)); +SA(!__is_convertible(Fn*, Fn)); +SA(!__is_convertible(Fn*, Fn&)); +SA(__is_convertible(Fn*, Fn*)); +SA(!__is_convertible(Fn*, Arr)); +SA(!__is_convertible(Fn*, Arr&)); +SA(!__is_convertible(Fn*, char)); +SA(!__is_convertible(Fn*, char&)); +SA(!__is_convertible(Fn*, char*)); + +SA(!__is_convertible(Arr, void)); +SA(!__is_convertible(Arr, Fn)); +SA(!__is_convertible(Arr, Fn*)); +SA(!__is_convertible(Arr, Fn&)); +SA(!__is_convertible(Arr, Arr)); +SA(!__is_convertible(Arr, Arr&)); +SA(__is_convertible(Arr, const Arr&)); +SA(!__is_convertible(Arr, volatile Arr&)); +SA(!__is_convertible(Arr, const volatile Arr&)); +SA(!__is_convertible(const Arr, Arr&)); +SA(__is_convertible(const Arr, const Arr&)); +SA(__is_convertible(Arr, Arr&&)); +SA(__is_convertible(Arr, const Arr&&)); +SA(__is_convertible(Arr, volatile Arr&&)); +SA(__is_convertible(Arr, const volatile Arr&&)); +SA(__is_convertible(const Arr, const Arr&&)); +SA(!__is_convertible(Arr&, Arr&&)); +SA(!__is_convertible(Arr&&, Arr&)); +SA(!__is_convertible(Arr, char)); +SA(__is_convertible(Arr, char*)); +SA(__is_convertible(Arr, const char*)); +SA(!__is_convertible(Arr, char&)); +SA(!__is_convertible(const Arr, char*)); +SA(__is_convertible(const Arr, const char*)); +SA(!__is_convertible(int, int[1])); +SA(!__is_convertible(int[1], int[1])); +SA(!__is_convertible(int[1], int(&)[1])); +SA(__is_convertible(int(&)[1], int(&)[1])); +SA(__is_convertible(int(&)[1], const int(&)[1])); +SA(!__is_convertible(const int(&)[1], int(&)[1])); +SA(!__is_convertible(int[1][1], int*)); +SA(!__is_convertible(int[][1], int*)); + +SA(!__is_convertible(Arr&, void)); +SA(!__is_convertible(Arr&, Fn)); +SA(!__is_convertible(Arr&, Fn*)); +SA(!__is_convertible(Arr&, Fn&)); +SA(!__is_convertible(Arr&, Arr)); +SA(__is_convertible(Arr&, Arr&)); +SA(__is_convertible(Arr&, const Arr&)); +SA(!__is_convertible(const Arr&, Arr&)); +SA(__is_convertible(const Arr&, const Arr&)); +SA(!__is_convertible(Arr&, char)); +SA(__is_convertible(Arr&, char*)); +SA(__is_convertible(Arr&, const char*)); +SA(!__is_convertible(Arr&, char&)); +SA(!__is_convertible(const Arr&, char*)); +SA(__is_convertible(const Arr&, const char*)); +SA(__is_convertible(Arr, from_charp)); +SA(__is_convertible(Arr&, from_charp)); + +struct B { }; +struct D : B { }; + +SA(__is_convertible(D, B)); +SA(__is_convertible(D*, B*)); +SA(__is_convertible(D&, B&)); +SA(!__is_convertible(B, D)); +SA(!__is_convertible(B*, D*)); +SA(!__is_convertible(B&, D&)); + +/* These are taken from LLVM's test/SemaCXX/type-traits.cpp. */ + +struct I { + int i; + I(int _i) : i(_i) { } + operator int() const { + return i; + } +}; + +struct F +{ + float f; + F(float _f) : f(_f) {} + F(const I& obj) + : f(static_cast<float>(obj.i)) {} + operator float() const { + return f; + } + operator I() const { + return I(static_cast<int>(f)); + } +}; + +SA(__is_convertible(I, I)); +SA(__is_convertible(I, const I)); +SA(__is_convertible(I, int)); +SA(__is_convertible(int, I)); +SA(__is_convertible(I, F)); +SA(__is_convertible(F, I)); +SA(__is_convertible(F, float)); +SA(__is_convertible(float, F)); + +template<typename> +struct X { + template<typename U> X(const X<U>&); +}; + +SA(__is_convertible(X<int>, X<float>)); +SA(__is_convertible(X<float>, X<int>)); + +struct Abstract { + virtual void f() = 0; +}; + +SA(!__is_convertible(Abstract, Abstract)); + +class hidden { + hidden(const hidden&); + friend void test (); +}; + +SA(__is_convertible(hidden&, hidden&)); +SA(__is_convertible(hidden&, const hidden&)); +SA(__is_convertible(hidden&, volatile hidden&)); +SA(__is_convertible(hidden&, const volatile hidden&)); +SA(__is_convertible(const hidden&, const hidden&)); +SA(__is_convertible(const hidden&, const volatile hidden&)); +SA(__is_convertible(volatile hidden&, const volatile hidden&)); +SA(__is_convertible(const volatile hidden&, const volatile hidden&)); +SA(!__is_convertible(const hidden&, hidden&)); + +void +test () +{ + /* __is_convertible(hidden, hidden) should be false despite the + friend declaration above, because "Access checks are performed + as if from a context unrelated to either type", but we don't + implement that for the built-in (std::is_convertible works as + expected). This is the case for __is_assignable as well. */ + //SA(!__is_convertible(hidden, hidden)); +} + +void +test2 () +{ + struct X { }; + struct Y { + explicit Y(X); // not viable for implicit conversions + }; + SA(!__is_convertible(X, Y)); +} diff --git a/gcc/testsuite/g++.dg/ext/is_convertible2.C b/gcc/testsuite/g++.dg/ext/is_convertible2.C new file mode 100644 index 0000000..9b46e26 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/is_convertible2.C @@ -0,0 +1,46 @@ +// PR c++/106784 +// { dg-do compile { target c++20 } } +// Adapted from <https://en.cppreference.com/w/cpp/types/is_convertible>. + +#include <string> +#include <string_view> + +#define SA(X) static_assert((X),#X) + +class E { public: template<class T> E(T&&) { } }; + +int main() +{ + class A {}; + class B : public A {}; + class C {}; + class D { public: operator C() { return c; } C c; }; + + SA(__is_convertible(B*, A*)); + SA(!__is_convertible(A*, B*)); + SA(__is_convertible(D, C)); + SA(!__is_convertible(B*, C*)); + SA(__is_convertible(A, E)); + + using std::operator "" s, std::operator "" sv; + + auto stringify = []<typename T>(T x) { + if constexpr (std::is_convertible_v<T, std::string> or + std::is_convertible_v<T, std::string_view>) { + return x; + } else { + return std::to_string(x); + } + }; + + const char* three = "three"; + + SA(!__is_convertible(std::string_view, std::string)); + SA(__is_convertible(std::string, std::string_view)); + + auto s1 = stringify("one"s); + auto s2 = stringify("two"sv); + auto s3 = stringify(three); + auto s4 = stringify(42); + auto s5 = stringify(42.); +} diff --git a/gcc/testsuite/g++.dg/ext/is_convertible3.C b/gcc/testsuite/g++.dg/ext/is_convertible3.C new file mode 100644 index 0000000..7a986d0 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/is_convertible3.C @@ -0,0 +1,9 @@ +// PR c++/106784 +// { dg-do compile { target c++11 } } +// Make sure we don't reject this at runtime by trying to instantiate +// something that would be ill-formed. + +struct A; +struct B { template<class T> B(const T&) noexcept { T::nonexistent; } }; + +static_assert(__is_convertible(const A&, B), ""); diff --git a/gcc/testsuite/g++.dg/ext/is_nothrow_convertible1.C b/gcc/testsuite/g++.dg/ext/is_nothrow_convertible1.C new file mode 100644 index 0000000..bb7243e --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/is_nothrow_convertible1.C @@ -0,0 +1,270 @@ +// PR c++/106784 +// { dg-do compile { target c++11 } } +// Like is_convertible1.C, but conversion functions are made noexcept. + +#define SA(X) static_assert((X),#X) + +template<typename From, typename To> +struct is_nothrow_convertible { + static const bool value = __is_nothrow_convertible(From, To); +}; + +struct from_int { + from_int(int) noexcept; +}; + +struct from_charp { + from_charp(const char *) noexcept; +}; + +struct to_int { + operator int() noexcept; +}; + +typedef int Fn(int); +typedef char Arr[10]; +enum E { XYZZY }; + +SA(!__is_nothrow_convertible(int, void)); +SA(__is_nothrow_convertible(int, int)); +SA(__is_nothrow_convertible(int, from_int)); +SA(__is_nothrow_convertible(long, from_int)); +SA(__is_nothrow_convertible(double, from_int)); +SA(__is_nothrow_convertible(const int, from_int)); +SA(__is_nothrow_convertible(const int&, from_int)); +SA(__is_nothrow_convertible(to_int, int)); +SA(__is_nothrow_convertible(to_int, const int&)); +SA(__is_nothrow_convertible(to_int, long)); +SA(!__is_nothrow_convertible(to_int, int&)); +SA(!__is_nothrow_convertible(to_int, from_int)); +SA(!__is_nothrow_convertible(int, Fn)); +SA(!__is_nothrow_convertible(int, Fn*)); +SA(!__is_nothrow_convertible(int, Fn&)); +SA(!__is_nothrow_convertible(int, Arr)); +SA(!__is_nothrow_convertible(int, Arr&)); +SA(!__is_nothrow_convertible(int, int&)); +SA(__is_nothrow_convertible(int, const int&)); +SA(!__is_nothrow_convertible(const int, int&)); +SA(__is_nothrow_convertible(const int, const int&)); +SA(!__is_nothrow_convertible(int, int*)); + +SA(!__is_nothrow_convertible(int, E)); +SA(__is_nothrow_convertible(E, int)); + +SA(__is_nothrow_convertible(int&, int)); +SA(__is_nothrow_convertible(int&, int&)); +SA(__is_nothrow_convertible(int&, const int&)); +SA(!__is_nothrow_convertible(const int&, int&)); +SA(__is_nothrow_convertible(const int&, const int&)); +SA(!__is_nothrow_convertible(int&, int*)); +SA(!__is_nothrow_convertible(int&, void)); +SA(!__is_nothrow_convertible(int&, Fn)); +SA(!__is_nothrow_convertible(int&, Fn*)); +SA(!__is_nothrow_convertible(int&, Fn&)); +SA(!__is_nothrow_convertible(int&, Arr)); +SA(!__is_nothrow_convertible(int&, Arr&)); + +SA(!__is_nothrow_convertible(int*, int)); +SA(!__is_nothrow_convertible(int*, int&)); +SA(!__is_nothrow_convertible(int*, void)); +SA(__is_nothrow_convertible(int*, int*)); +SA(__is_nothrow_convertible(int*, const int*)); +SA(!__is_nothrow_convertible(const int*, int*)); +SA(__is_nothrow_convertible(const int*, const int*)); +SA(!__is_nothrow_convertible(int*, Fn)); +SA(!__is_nothrow_convertible(int*, Fn*)); +SA(!__is_nothrow_convertible(int*, Fn&)); +SA(!__is_nothrow_convertible(int*, Arr)); +SA(!__is_nothrow_convertible(int*, Arr&)); +SA(!__is_nothrow_convertible(int*, float*)); + +SA(__is_nothrow_convertible(void, void)); +SA(!__is_nothrow_convertible(void, char)); +SA(!__is_nothrow_convertible(void, char&)); +SA(!__is_nothrow_convertible(void, char*)); +SA(!__is_nothrow_convertible(char, void)); +SA(__is_nothrow_convertible(const void, void)); +SA(__is_nothrow_convertible(void, const void)); +SA(__is_nothrow_convertible(const void, const void)); +SA(!__is_nothrow_convertible(void, Fn)); +SA(!__is_nothrow_convertible(void, Fn&)); +SA(!__is_nothrow_convertible(void, Fn*)); +SA(!__is_nothrow_convertible(void, Arr)); +SA(!__is_nothrow_convertible(void, Arr&)); + +SA(!__is_nothrow_convertible(Fn, void)); +SA(!__is_nothrow_convertible(Fn, Fn)); +SA(__is_nothrow_convertible(Fn, Fn*)); +SA(__is_nothrow_convertible(Fn, Fn&)); +SA(!__is_nothrow_convertible(int(int), int(int))); +SA(__is_nothrow_convertible(int(int), int(&)(int))); +SA(__is_nothrow_convertible(int(int), int(&&)(int))); +SA(__is_nothrow_convertible(int(int), int(*)(int))); +SA(__is_nothrow_convertible(int(int), int(*const)(int))); +SA(!__is_nothrow_convertible(int(int), char)); +SA(!__is_nothrow_convertible(int(int), char*)); +SA(!__is_nothrow_convertible(int(int), char&)); + +SA(!__is_nothrow_convertible(Fn&, void)); +SA(!__is_nothrow_convertible(Fn&, Fn)); +SA(__is_nothrow_convertible(Fn&, Fn&)); +SA(__is_nothrow_convertible(Fn&, Fn*)); +SA(!__is_nothrow_convertible(Fn&, Arr)); +SA(!__is_nothrow_convertible(Fn&, Arr&)); +SA(!__is_nothrow_convertible(Fn&, char)); +SA(!__is_nothrow_convertible(Fn&, char&)); +SA(!__is_nothrow_convertible(Fn&, char*)); + +SA(!__is_nothrow_convertible(Fn*, void)); +SA(!__is_nothrow_convertible(Fn*, Fn)); +SA(!__is_nothrow_convertible(Fn*, Fn&)); +SA(__is_nothrow_convertible(Fn*, Fn*)); +SA(!__is_nothrow_convertible(Fn*, Arr)); +SA(!__is_nothrow_convertible(Fn*, Arr&)); +SA(!__is_nothrow_convertible(Fn*, char)); +SA(!__is_nothrow_convertible(Fn*, char&)); +SA(!__is_nothrow_convertible(Fn*, char*)); + +SA(!__is_nothrow_convertible(Arr, void)); +SA(!__is_nothrow_convertible(Arr, Fn)); +SA(!__is_nothrow_convertible(Arr, Fn*)); +SA(!__is_nothrow_convertible(Arr, Fn&)); +SA(!__is_nothrow_convertible(Arr, Arr)); +SA(!__is_nothrow_convertible(Arr, Arr&)); +SA(__is_nothrow_convertible(Arr, const Arr&)); +SA(!__is_nothrow_convertible(Arr, volatile Arr&)); +SA(!__is_nothrow_convertible(Arr, const volatile Arr&)); +SA(!__is_nothrow_convertible(const Arr, Arr&)); +SA(__is_nothrow_convertible(const Arr, const Arr&)); +SA(__is_nothrow_convertible(Arr, Arr&&)); +SA(__is_nothrow_convertible(Arr, const Arr&&)); +SA(__is_nothrow_convertible(Arr, volatile Arr&&)); +SA(__is_nothrow_convertible(Arr, const volatile Arr&&)); +SA(__is_nothrow_convertible(const Arr, const Arr&&)); +SA(!__is_nothrow_convertible(Arr&, Arr&&)); +SA(!__is_nothrow_convertible(Arr&&, Arr&)); +SA(!__is_nothrow_convertible(Arr, char)); +SA(__is_nothrow_convertible(Arr, char*)); +SA(__is_nothrow_convertible(Arr, const char*)); +SA(!__is_nothrow_convertible(Arr, char&)); +SA(!__is_nothrow_convertible(const Arr, char*)); +SA(__is_nothrow_convertible(const Arr, const char*)); +SA(!__is_nothrow_convertible(int, int[1])); +SA(!__is_nothrow_convertible(int[1], int[1])); +SA(!__is_nothrow_convertible(int[1], int(&)[1])); +SA(__is_nothrow_convertible(int(&)[1], int(&)[1])); +SA(__is_nothrow_convertible(int(&)[1], const int(&)[1])); +SA(!__is_nothrow_convertible(const int(&)[1], int(&)[1])); +SA(!__is_nothrow_convertible(int[1][1], int*)); +SA(!__is_nothrow_convertible(int[][1], int*)); + +SA(!__is_nothrow_convertible(Arr&, void)); +SA(!__is_nothrow_convertible(Arr&, Fn)); +SA(!__is_nothrow_convertible(Arr&, Fn*)); +SA(!__is_nothrow_convertible(Arr&, Fn&)); +SA(!__is_nothrow_convertible(Arr&, Arr)); +SA(__is_nothrow_convertible(Arr&, Arr&)); +SA(__is_nothrow_convertible(Arr&, const Arr&)); +SA(!__is_nothrow_convertible(const Arr&, Arr&)); +SA(__is_nothrow_convertible(const Arr&, const Arr&)); +SA(!__is_nothrow_convertible(Arr&, char)); +SA(__is_nothrow_convertible(Arr&, char*)); +SA(__is_nothrow_convertible(Arr&, const char*)); +SA(!__is_nothrow_convertible(Arr&, char&)); +SA(!__is_nothrow_convertible(const Arr&, char*)); +SA(__is_nothrow_convertible(const Arr&, const char*)); +SA(__is_nothrow_convertible(Arr, from_charp)); +SA(__is_nothrow_convertible(Arr&, from_charp)); + +struct B { }; +struct D : B { }; + +SA(__is_nothrow_convertible(D, B)); +SA(__is_nothrow_convertible(D*, B*)); +SA(__is_nothrow_convertible(D&, B&)); +SA(!__is_nothrow_convertible(B, D)); +SA(!__is_nothrow_convertible(B*, D*)); +SA(!__is_nothrow_convertible(B&, D&)); + +/* These are taken from LLVM's test/SemaCXX/type-traits.cpp. */ + +struct I { + int i; + I(int _i) noexcept : i(_i) { } + operator int() const noexcept { + return i; + } +}; + +struct F +{ + float f; + F(float _f) noexcept : f(_f) {} + F(const I& obj) noexcept + : f(static_cast<float>(obj.i)) {} + operator float() const noexcept { + return f; + } + operator I() const noexcept { + return I(static_cast<int>(f)); + } +}; + +SA(__is_nothrow_convertible(I, I)); +SA(__is_nothrow_convertible(I, const I)); +SA(__is_nothrow_convertible(I, int)); +SA(__is_nothrow_convertible(int, I)); +SA(__is_nothrow_convertible(I, F)); +SA(__is_nothrow_convertible(F, I)); +SA(__is_nothrow_convertible(F, float)); +SA(__is_nothrow_convertible(float, F)); + +template<typename> +struct X { + template<typename U> X(const X<U>&) noexcept; +}; + +SA(__is_nothrow_convertible(X<int>, X<float>)); +SA(__is_nothrow_convertible(X<float>, X<int>)); + +struct Abstract { + virtual void f() = 0; +}; + +SA(!__is_nothrow_convertible(Abstract, Abstract)); + +class hidden { + hidden(const hidden&); + friend void test (); +}; + +SA(__is_nothrow_convertible(hidden&, hidden&)); +SA(__is_nothrow_convertible(hidden&, const hidden&)); +SA(__is_nothrow_convertible(hidden&, volatile hidden&)); +SA(__is_nothrow_convertible(hidden&, const volatile hidden&)); +SA(__is_nothrow_convertible(const hidden&, const hidden&)); +SA(__is_nothrow_convertible(const hidden&, const volatile hidden&)); +SA(__is_nothrow_convertible(volatile hidden&, const volatile hidden&)); +SA(__is_nothrow_convertible(const volatile hidden&, const volatile hidden&)); +SA(!__is_nothrow_convertible(const hidden&, hidden&)); + +void +test () +{ + /* __is_nothrow_convertible(hidden, hidden) should be false despite the + friend declaration above, because "Access checks are performed + as if from a context unrelated to either type", but we don't + implement that for the built-in (std::is_convertible works as + expected). This is the case for __is_assignable as well. */ + //SA(!__is_nothrow_convertible(hidden, hidden)); +} + +void +test2 () +{ + struct X { }; + struct Y { + explicit Y(X); // not viable for implicit conversions + }; + SA(!__is_nothrow_convertible(X, Y)); +} diff --git a/gcc/testsuite/g++.dg/ext/is_nothrow_convertible2.C b/gcc/testsuite/g++.dg/ext/is_nothrow_convertible2.C new file mode 100644 index 0000000..aa08917 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/is_nothrow_convertible2.C @@ -0,0 +1,19 @@ +// PR c++/106784 +// { dg-do compile { target c++11 } } + +#define SA(X) static_assert((X),#X) + +struct A { }; +struct B { }; + +struct M { + operator A(); + operator B() noexcept; + M(const A&); + M(const B&) noexcept; +}; + +SA(!__is_nothrow_convertible(A, M)); +SA(!__is_nothrow_convertible(M, A)); +SA(__is_nothrow_convertible(B, M)); +SA(__is_nothrow_convertible(M, B)); diff --git a/gcc/testsuite/g++.dg/ext/is_nothrow_convertible3.C b/gcc/testsuite/g++.dg/ext/is_nothrow_convertible3.C new file mode 100644 index 0000000..05b1e1d --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/is_nothrow_convertible3.C @@ -0,0 +1,9 @@ +// PR c++/106784 +// { dg-do compile { target c++11 } } +// Make sure we don't reject this at runtime by trying to instantiate +// something that would be ill-formed. + +struct A; +struct B { template<class T> B(const T&) noexcept { T::nonexistent; } }; + +static_assert(__is_nothrow_convertible(const A&, B), ""); diff --git a/gcc/testsuite/g++.dg/modules/auto-3.h b/gcc/testsuite/g++.dg/modules/auto-3.h new file mode 100644 index 0000000..f129433 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/auto-3.h @@ -0,0 +1,10 @@ +template<class> +struct __tree_barrier { + static const auto __phase_alignment_1 = 0; + + template<class> + static const auto __phase_alignment_2 = 0; +}; + +template<class> +inline auto __phase_alignment_3 = 0; diff --git a/gcc/testsuite/g++.dg/modules/auto-3_a.H b/gcc/testsuite/g++.dg/modules/auto-3_a.H new file mode 100644 index 0000000..25a7a73 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/auto-3_a.H @@ -0,0 +1,4 @@ +// { dg-additional-options "-fmodule-header" } +// { dg-module-cmi {} } + +#include "auto-3.h" diff --git a/gcc/testsuite/g++.dg/modules/auto-3_b.C b/gcc/testsuite/g++.dg/modules/auto-3_b.C new file mode 100644 index 0000000..03b6d46 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/auto-3_b.C @@ -0,0 +1,4 @@ +// { dg-additional-options "-fmodules-ts -fno-module-lazy" } + +#include "auto-3.h" +import "auto-3_a.H"; diff --git a/gcc/testsuite/g++.dg/modules/partial-2.cc b/gcc/testsuite/g++.dg/modules/partial-2.cc new file mode 100644 index 0000000..1316bf5 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/partial-2.cc @@ -0,0 +1,17 @@ +static_assert(is_reference_v<int&>); +static_assert(is_reference_v<int&&>); +static_assert(!is_reference_v<int>); + +static_assert(A::is_reference_v<long&>); +static_assert(A::is_reference_v<long&&>); +static_assert(!A::is_reference_v<long>); + +#if __cpp_concepts +static_assert(concepts::is_reference_v<char&>); +static_assert(concepts::is_reference_v<char&&>); +static_assert(!concepts::is_reference_v<char>); + +static_assert(concepts::A::is_reference_v<bool&>); +static_assert(concepts::A::is_reference_v<bool&&>); +static_assert(!concepts::A::is_reference_v<bool>); +#endif diff --git a/gcc/testsuite/g++.dg/modules/partial-2.h b/gcc/testsuite/g++.dg/modules/partial-2.h new file mode 100644 index 0000000..afcfce7 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/partial-2.h @@ -0,0 +1,38 @@ +template<class T> constexpr bool is_reference_v = false; +template<class T> constexpr bool is_reference_v<T&> = true; +template<class T> constexpr bool is_reference_v<T&&> = true; + +struct A { + template<class T> static constexpr bool is_reference_v = false; +}; + +template<class T> constexpr bool A::is_reference_v<T&> = true; +template<class T> constexpr bool A::is_reference_v<T&&> = true; + +#if __cpp_concepts +namespace concepts { + template<class T> bool is_reference_v; + + template<class T> requires __is_same(T, T&) + constexpr bool is_reference_v<T> = true; + + template<class T> requires __is_same(T, T&&) && (!__is_same(T, T&)) + constexpr bool is_reference_v<T> = true; + + template<class T> requires (!__is_same(T, T&)) && (!__is_same(T, T&&)) + constexpr bool is_reference_v<T> = false; + + struct A { + template<class T> static bool is_reference_v; + }; + + template<class T> requires __is_same(T, T&) + constexpr bool A::is_reference_v<T> = true; + + template<class T> requires __is_same(T, T&&) && (!__is_same(T, T&)) + constexpr bool A::is_reference_v<T> = true; + + template<class T> requires (!__is_same(T, T&)) && (!__is_same(T, T&&)) + constexpr bool A::is_reference_v<T> = false; +} +#endif diff --git a/gcc/testsuite/g++.dg/modules/partial-2_a.C b/gcc/testsuite/g++.dg/modules/partial-2_a.C new file mode 100644 index 0000000..1582f56 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/partial-2_a.C @@ -0,0 +1,6 @@ +// PR c++/106826 +// { dg-additional-options -fmodules-ts } +// { dg-module-cmi pr106826 } +export module pr106826; + +#include "partial-2.h" diff --git a/gcc/testsuite/g++.dg/modules/partial-2_b.C b/gcc/testsuite/g++.dg/modules/partial-2_b.C new file mode 100644 index 0000000..1b0c7a5 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/partial-2_b.C @@ -0,0 +1,5 @@ +// PR c++/106826 +// { dg-additional-options -fmodules-ts } +module pr106826; + +#include "partial-2.cc" diff --git a/gcc/testsuite/g++.dg/modules/partial-2_c.H b/gcc/testsuite/g++.dg/modules/partial-2_c.H new file mode 100644 index 0000000..bd83852 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/partial-2_c.H @@ -0,0 +1,5 @@ +// PR c++/107033 +// { dg-additional-options -fmodule-header } +// { dg-module-cmi {} } + +#include "partial-2.h" diff --git a/gcc/testsuite/g++.dg/modules/partial-2_d.C b/gcc/testsuite/g++.dg/modules/partial-2_d.C new file mode 100644 index 0000000..ed54d3c --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/partial-2_d.C @@ -0,0 +1,8 @@ +// PR c++/107033 +// { dg-additional-options -fmodules-ts } +// { dg-module-cmi pr107033 } +export module pr107033; + +import "partial-2_c.H"; + +#include "partial-2.cc" diff --git a/gcc/testsuite/g++.dg/modules/xtreme-header-2.h b/gcc/testsuite/g++.dg/modules/xtreme-header-2.h index ded093e..dfe94aa 100644 --- a/gcc/testsuite/g++.dg/modules/xtreme-header-2.h +++ b/gcc/testsuite/g++.dg/modules/xtreme-header-2.h @@ -1,8 +1,7 @@ // Everything that transitively includes <ranges> #include <algorithm> -// FIXME: PR 97549 -// #include <execution> +#include <execution> #include <functional> #include <future> #include <memory> diff --git a/gcc/testsuite/g++.dg/modules/xtreme-header-6.h b/gcc/testsuite/g++.dg/modules/xtreme-header-6.h index 85894b2..8d024b6 100644 --- a/gcc/testsuite/g++.dg/modules/xtreme-header-6.h +++ b/gcc/testsuite/g++.dg/modules/xtreme-header-6.h @@ -1,22 +1,22 @@ // C++20 headers #if __cplusplus > 201703 #include <version> +#include <barrier> #include <bit> #include <compare> #include <concepts> #if __cpp_coroutines #include <coroutine> #endif +#include <latch> #include <numbers> +#include <semaphore> +#include <source_location> #include <span> #include <stop_token> +#include <syncstream> #if 0 // Unimplemented -#include <barrier> #include <format> -#include <latch> -#include <semaphore> -#include <source_location> -#include <syncstream> #endif #endif diff --git a/gcc/testsuite/g++.dg/modules/xtreme-header.h b/gcc/testsuite/g++.dg/modules/xtreme-header.h index 41302c7..3147aaf 100644 --- a/gcc/testsuite/g++.dg/modules/xtreme-header.h +++ b/gcc/testsuite/g++.dg/modules/xtreme-header.h @@ -1,17 +1,8 @@ // All the headers! -#if __cplusplus > 201703L -// FIXME: if we include everything, something goes wrong with location -// information. We used to not handle lambdas attached to global -// vars, and this is a convienient flag to stop including everything. -#define NO_ASSOCIATED_LAMBDA 1 -#endif - // C++ 17 and below #if 1 -#if !NO_ASSOCIATED_LAMBDA #include <algorithm> -#endif #include <any> #include <array> #include <atomic> @@ -26,19 +17,12 @@ #include <cwctype> #include <deque> #include <exception> -#if !NO_ASSOCIATED_LAMBDA -// FIXME: PR 97549 -//#include <execution> -#endif +#include <execution> #include <filesystem> #include <forward_list> #include <fstream> -#if !NO_ASSOCIATED_LAMBDA #include <functional> -#endif -#if !NO_ASSOCIATED_LAMBDA #include <future> -#endif #include <initializer_list> #include <iomanip> #include <ios> @@ -49,12 +33,8 @@ #include <list> #include <locale> #include <map> -#if !NO_ASSOCIATED_LAMBDA #include <memory> -#endif -#if !NO_ASSOCIATED_LAMBDA #include <memory_resource> -#endif #include <mutex> #include <new> #include <numeric> @@ -63,12 +43,8 @@ #include <queue> #include <random> #include <ratio> -#if !NO_ASSOCIATED_LAMBDA #include <regex> -#endif -#if !NO_ASSOCIATED_LAMBDA #include <scoped_allocator> -#endif #include <set> #include <shared_mutex> #include <sstream> @@ -78,9 +54,7 @@ #include <string> #include <string_view> #include <system_error> -#if !NO_ASSOCIATED_LAMBDA #include <thread> -#endif #include <tuple> #include <type_traits> #include <typeindex> @@ -88,9 +62,7 @@ #include <unordered_map> #include <unordered_set> #include <utility> -#if !NO_ASSOCIATED_LAMBDA #include <valarray> -#endif #include <variant> #include <vector> #endif @@ -119,26 +91,39 @@ #if __cplusplus > 201703 #if 1 #include <version> +#include <barrier> #include <bit> #include <compare> #include <concepts> #if __cpp_coroutines #include <coroutine> #endif -#if !NO_ASSOCIATED_LAMBDA -#include <ranges> -#endif +#include <latch> #include <numbers> +#include <ranges> +#include <semaphore> +#include <source_location> #include <span> #include <stop_token> +#include <syncstream> #if 0 // Unimplemented -#include <barrier> #include <format> -#include <latch> -#include <semaphore> -#include <source_location> -#include <syncstream> #endif #endif #endif + +// C++23 +#if __cplusplus > 202002L +#include <expected> +#include <spanstream> +#include <stacktrace> +#if 0 +// Unimplemented +#include <flat_map> +#include <flat_set> +#include <generator> +#include <mdspan> +#include <print> +#endif +#endif diff --git a/gcc/testsuite/g++.dg/other/error36.C b/gcc/testsuite/g++.dg/other/error36.C new file mode 100644 index 0000000..5562878 --- /dev/null +++ b/gcc/testsuite/g++.dg/other/error36.C @@ -0,0 +1,13 @@ +// PR c++/106983 +// { dg-do compile { target c++20 } } + +typedef unsigned long long A; +typedef union +{ + struct B s; // { dg-error "incomplete" } + A a; +} U; +void f (A x, unsigned int b) +{ + const U y = {.a = x}; +} diff --git a/gcc/testsuite/g++.dg/torture/pr106922.C b/gcc/testsuite/g++.dg/torture/pr106922.C new file mode 100644 index 0000000..046fc6c --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr106922.C @@ -0,0 +1,48 @@ +// { dg-do compile } +// { dg-require-effective-target c++17 } +// { dg-additional-options "-Wall" } +// -O1 doesn't iterate VN and thus has bogus uninit diagnostics +// { dg-skip-if "" { *-*-* } { "-O1" } { "" } } + +#include <vector> + +#include <optional> +template <class T> +using Optional = std::optional<T>; + +#include <sstream> + +struct MyOptionalStructWithInt { + int myint; /* works without this */ + Optional<std::vector<std::string>> myoptional; +}; + +struct MyOptionalsStruct { + MyOptionalStructWithInt external1; + MyOptionalStructWithInt external2; +}; + +struct MyStruct { }; +std::ostream &operator << (std::ostream &os, const MyStruct &myStruct); + +std::vector<MyStruct> getMyStructs(); + +void test() +{ + MyOptionalsStruct externals; + MyOptionalStructWithInt internal1; + MyOptionalStructWithInt internal2; + + std::vector<MyStruct> myStructs; + myStructs = getMyStructs(); + + for (const auto& myStruct : myStructs) + { + std::stringstream address_stream; + address_stream << myStruct; + internal1.myint = internal2.myint = 0; + externals.external1 = internal1; + externals.external2 = internal2; + externals.external2 = internal2; + } +} diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr106922.C b/gcc/testsuite/g++.dg/tree-ssa/pr106922.C index faf379b..2aec497 100644 --- a/gcc/testsuite/g++.dg/tree-ssa/pr106922.C +++ b/gcc/testsuite/g++.dg/tree-ssa/pr106922.C @@ -1,5 +1,5 @@ // { dg-require-effective-target c++20 } -// { dg-options "-O2 -fdump-tree-pre-details -fdump-tree-cddce3" } +// { dg-options "-O2 -fdump-tree-cddce3" } template <typename> struct __new_allocator { void deallocate(int *, int) { operator delete(0); } @@ -87,5 +87,4 @@ void testfunctionfoo() { } } -// { dg-final { scan-tree-dump-times "Found fully redundant value" 4 "pre" { xfail { ! lp64 } } } } -// { dg-final { scan-tree-dump-not "m_initialized" "cddce3" { xfail { ! lp64 } } } } +// { dg-final { scan-tree-dump-not "m_initialized" "cddce3" } } diff --git a/gcc/testsuite/g++.dg/warn/Wuninitialized-33.C b/gcc/testsuite/g++.dg/warn/Wuninitialized-33.C new file mode 100644 index 0000000..1bb0639 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wuninitialized-33.C @@ -0,0 +1,55 @@ +// PR102801 +// { dg-do compile } +// { dg-require-effective-target c++17 } +// { dg-options "-O2 -Wall" } + +#include <algorithm> +#include <memory> +#include <optional> +#include <string> +#include <utility> +#include <vector> + +class C { + bool b{}; // { dg-bogus "uninitialized" } + + struct Shared {}; + using SharedPtr = std::shared_ptr<const Shared>; + + SharedPtr shared; + +public: + C() = delete; + C(bool bIn) : b(bIn) {} + ~C(); + int someMethod() const; +}; + +using OptC = std::optional<C>; + +class C2 { + OptC c; +public: + C2() = default; + C2(const C &cIn) : c(cIn) {} + ~C2(); + void operator()() const; + void swap(C2 &o) { std::swap(c, o.c); } +}; + + +template <typename T> +class Q { + std::vector<T> queue; +public: + void Add(std::vector<T> &items) { + for (T & item : items) { + queue.push_back(T()); + item.swap(queue.back()); + } + } + void Exec(); +}; + +extern void foo(Q<C2> & q, std::vector<C2> &items); +void foo(Q<C2> & q, std::vector<C2> &items) { q.Add(items); q.Exec(); } diff --git a/gcc/testsuite/gcc.dg/Wxor-used-as-pow-pr106830.c b/gcc/testsuite/gcc.dg/Wxor-used-as-pow-pr106830.c new file mode 100644 index 0000000..104897a --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wxor-used-as-pow-pr106830.c @@ -0,0 +1,6 @@ +/* { dg-require-effective-target int128 } + { dg-options "-Wno-pedantic" } */ + +void foo0_u16_0() { + (__int128)(18302628885633695743 << 4) ^ 0; /* { dg-warning "integer constant is so large that it is unsigned" } */ +} diff --git a/gcc/testsuite/gcc.dg/c2x-complit-1.c b/gcc/testsuite/gcc.dg/c2x-complit-1.c new file mode 100644 index 0000000..af92d4d --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-complit-1.c @@ -0,0 +1,35 @@ +/* Test storage duration of compound literals in parameter lists for C2x. */ +/* { dg-do run } */ +/* { dg-options "-std=c2x -pedantic-errors" } */ + +extern void abort (void); +extern void exit (int); + +int x; + +void f (int a[(int) { x }]); + +int *q; + +int +fp (int *p) +{ + q = p; + return 1; +} + +void +g (int a, int b[fp ((int [2]) { a, a + 2 })]) +{ + if (q[0] != a || q[1] != a + 2) + abort (); +} + +int +main (void) +{ + int t[1] = { 0 }; + g (1, t); + g (2, t); + exit (0); +} diff --git a/gcc/testsuite/gcc.dg/c2x-concat-1.c b/gcc/testsuite/gcc.dg/c2x-concat-1.c new file mode 100644 index 0000000..e92eaaf --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-concat-1.c @@ -0,0 +1,31 @@ +/* Test errors for bad string literal concatenation. */ +/* { dg-do compile } */ +/* { dg-options "-std=c2x -pedantic-errors" } */ + +void *pLU = L"" U""; /* { dg-error "non-standard concatenation" } */ +void *pL_U = L"" "" U""; /* { dg-error "non-standard concatenation" } */ +void *pLu = L"" u""; /* { dg-error "non-standard concatenation" } */ +void *pL_u = L"" "" u""; /* { dg-error "non-standard concatenation" } */ +void *pLu8 = L"" u8""; /* { dg-error "non-standard concatenation" } */ +void *pL_u8 = L"" "" u8""; /* { dg-error "non-standard concatenation" } */ + +void *pUL = U"" L""; /* { dg-error "non-standard concatenation" } */ +void *pU_L = U"" "" L""; /* { dg-error "non-standard concatenation" } */ +void *pUu = U"" u""; /* { dg-error "non-standard concatenation" } */ +void *pU_u = U"" "" u""; /* { dg-error "non-standard concatenation" } */ +void *pUu8 = U"" u8""; /* { dg-error "non-standard concatenation" } */ +void *pU_u8 = U"" "" u8""; /* { dg-error "non-standard concatenation" } */ + +void *puL = u"" L""; /* { dg-error "non-standard concatenation" } */ +void *pu_L = u"" "" L""; /* { dg-error "non-standard concatenation" } */ +void *puU = u"" U""; /* { dg-error "non-standard concatenation" } */ +void *pu_U = u"" "" U""; /* { dg-error "non-standard concatenation" } */ +void *puu8 = u"" u8""; /* { dg-error "non-standard concatenation" } */ +void *pu_u8 = u"" "" u8""; /* { dg-error "non-standard concatenation" } */ + +void *pu8L = u8"" L""; /* { dg-error "non-standard concatenation" } */ +void *pu8_L = u8"" "" L""; /* { dg-error "non-standard concatenation" } */ +void *pu8U = u8"" U""; /* { dg-error "non-standard concatenation" } */ +void *pu8_U = u8"" "" U""; /* { dg-error "non-standard concatenation" } */ +void *pu8u = u8"" u""; /* { dg-error "non-standard concatenation" } */ +void *pu8_u = u8"" "" u""; /* { dg-error "non-standard concatenation" } */ diff --git a/gcc/testsuite/gcc.dg/cpp/c2x-ucn-1.c b/gcc/testsuite/gcc.dg/cpp/c2x-ucn-1.c new file mode 100644 index 0000000..a4998ae --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/c2x-ucn-1.c @@ -0,0 +1,996 @@ +/* Test characters not permitted in UCNs in C2x. */ +/* { dg-do compile } */ +/* { dg-options "-std=c2x -pedantic-errors" } */ + +#if U'\u0000' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu0 = U"\u0000"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000000' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU0 = U"\U00000000"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0001' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu1 = U"\u0001"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000001' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU1 = U"\U00000001"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0002' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu2 = U"\u0002"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000002' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU2 = U"\U00000002"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0003' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu3 = U"\u0003"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000003' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU3 = U"\U00000003"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0004' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu4 = U"\u0004"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000004' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU4 = U"\U00000004"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0005' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu5 = U"\u0005"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000005' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU5 = U"\U00000005"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0006' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu6 = U"\u0006"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000006' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU6 = U"\U00000006"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0007' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu7 = U"\u0007"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000007' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU7 = U"\U00000007"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0008' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu8 = U"\u0008"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000008' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU8 = U"\U00000008"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0009' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu9 = U"\u0009"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000009' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU9 = U"\U00000009"; /* { dg-error "is not a valid universal character" } */ +#if U'\u000a' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu10 = U"\u000a"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000000a' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU10 = U"\U0000000a"; /* { dg-error "is not a valid universal character" } */ +#if U'\u000b' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu11 = U"\u000b"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000000b' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU11 = U"\U0000000b"; /* { dg-error "is not a valid universal character" } */ +#if U'\u000c' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu12 = U"\u000c"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000000c' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU12 = U"\U0000000c"; /* { dg-error "is not a valid universal character" } */ +#if U'\u000d' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu13 = U"\u000d"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000000d' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU13 = U"\U0000000d"; /* { dg-error "is not a valid universal character" } */ +#if U'\u000e' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu14 = U"\u000e"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000000e' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU14 = U"\U0000000e"; /* { dg-error "is not a valid universal character" } */ +#if U'\u000f' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu15 = U"\u000f"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000000f' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU15 = U"\U0000000f"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0010' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu16 = U"\u0010"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000010' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU16 = U"\U00000010"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0011' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu17 = U"\u0011"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000011' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU17 = U"\U00000011"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0012' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu18 = U"\u0012"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000012' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU18 = U"\U00000012"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0013' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu19 = U"\u0013"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000013' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU19 = U"\U00000013"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0014' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu20 = U"\u0014"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000014' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU20 = U"\U00000014"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0015' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu21 = U"\u0015"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000015' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU21 = U"\U00000015"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0016' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu22 = U"\u0016"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000016' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU22 = U"\U00000016"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0017' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu23 = U"\u0017"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000017' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU23 = U"\U00000017"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0018' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu24 = U"\u0018"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000018' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU24 = U"\U00000018"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0019' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu25 = U"\u0019"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000019' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU25 = U"\U00000019"; /* { dg-error "is not a valid universal character" } */ +#if U'\u001a' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu26 = U"\u001a"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000001a' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU26 = U"\U0000001a"; /* { dg-error "is not a valid universal character" } */ +#if U'\u001b' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu27 = U"\u001b"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000001b' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU27 = U"\U0000001b"; /* { dg-error "is not a valid universal character" } */ +#if U'\u001c' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu28 = U"\u001c"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000001c' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU28 = U"\U0000001c"; /* { dg-error "is not a valid universal character" } */ +#if U'\u001d' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu29 = U"\u001d"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000001d' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU29 = U"\U0000001d"; /* { dg-error "is not a valid universal character" } */ +#if U'\u001e' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu30 = U"\u001e"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000001e' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU30 = U"\U0000001e"; /* { dg-error "is not a valid universal character" } */ +#if U'\u001f' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu31 = U"\u001f"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000001f' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU31 = U"\U0000001f"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0020' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu32 = U"\u0020"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000020' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU32 = U"\U00000020"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0021' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu33 = U"\u0021"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000021' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU33 = U"\U00000021"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0022' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu34 = U"\u0022"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000022' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU34 = U"\U00000022"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0023' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu35 = U"\u0023"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000023' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU35 = U"\U00000023"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0024' +#endif +void *tu36 = U"\u0024"; +#if U'\U00000024' +#endif +void *tU36 = U"\U00000024"; +#if U'\u0025' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu37 = U"\u0025"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000025' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU37 = U"\U00000025"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0026' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu38 = U"\u0026"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000026' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU38 = U"\U00000026"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0027' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu39 = U"\u0027"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000027' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU39 = U"\U00000027"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0028' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu40 = U"\u0028"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000028' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU40 = U"\U00000028"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0029' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu41 = U"\u0029"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000029' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU41 = U"\U00000029"; /* { dg-error "is not a valid universal character" } */ +#if U'\u002a' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu42 = U"\u002a"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000002a' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU42 = U"\U0000002a"; /* { dg-error "is not a valid universal character" } */ +#if U'\u002b' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu43 = U"\u002b"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000002b' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU43 = U"\U0000002b"; /* { dg-error "is not a valid universal character" } */ +#if U'\u002c' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu44 = U"\u002c"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000002c' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU44 = U"\U0000002c"; /* { dg-error "is not a valid universal character" } */ +#if U'\u002d' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu45 = U"\u002d"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000002d' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU45 = U"\U0000002d"; /* { dg-error "is not a valid universal character" } */ +#if U'\u002e' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu46 = U"\u002e"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000002e' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU46 = U"\U0000002e"; /* { dg-error "is not a valid universal character" } */ +#if U'\u002f' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu47 = U"\u002f"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000002f' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU47 = U"\U0000002f"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0030' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu48 = U"\u0030"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000030' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU48 = U"\U00000030"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0031' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu49 = U"\u0031"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000031' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU49 = U"\U00000031"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0032' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu50 = U"\u0032"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000032' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU50 = U"\U00000032"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0033' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu51 = U"\u0033"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000033' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU51 = U"\U00000033"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0034' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu52 = U"\u0034"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000034' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU52 = U"\U00000034"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0035' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu53 = U"\u0035"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000035' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU53 = U"\U00000035"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0036' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu54 = U"\u0036"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000036' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU54 = U"\U00000036"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0037' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu55 = U"\u0037"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000037' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU55 = U"\U00000037"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0038' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu56 = U"\u0038"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000038' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU56 = U"\U00000038"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0039' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu57 = U"\u0039"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000039' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU57 = U"\U00000039"; /* { dg-error "is not a valid universal character" } */ +#if U'\u003a' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu58 = U"\u003a"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000003a' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU58 = U"\U0000003a"; /* { dg-error "is not a valid universal character" } */ +#if U'\u003b' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu59 = U"\u003b"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000003b' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU59 = U"\U0000003b"; /* { dg-error "is not a valid universal character" } */ +#if U'\u003c' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu60 = U"\u003c"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000003c' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU60 = U"\U0000003c"; /* { dg-error "is not a valid universal character" } */ +#if U'\u003d' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu61 = U"\u003d"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000003d' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU61 = U"\U0000003d"; /* { dg-error "is not a valid universal character" } */ +#if U'\u003e' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu62 = U"\u003e"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000003e' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU62 = U"\U0000003e"; /* { dg-error "is not a valid universal character" } */ +#if U'\u003f' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu63 = U"\u003f"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000003f' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU63 = U"\U0000003f"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0040' +#endif +void *tu64 = U"\u0040"; +#if U'\U00000040' +#endif +void *tU64 = U"\U00000040"; +#if U'\u0041' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu65 = U"\u0041"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000041' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU65 = U"\U00000041"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0042' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu66 = U"\u0042"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000042' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU66 = U"\U00000042"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0043' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu67 = U"\u0043"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000043' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU67 = U"\U00000043"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0044' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu68 = U"\u0044"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000044' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU68 = U"\U00000044"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0045' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu69 = U"\u0045"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000045' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU69 = U"\U00000045"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0046' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu70 = U"\u0046"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000046' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU70 = U"\U00000046"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0047' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu71 = U"\u0047"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000047' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU71 = U"\U00000047"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0048' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu72 = U"\u0048"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000048' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU72 = U"\U00000048"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0049' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu73 = U"\u0049"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000049' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU73 = U"\U00000049"; /* { dg-error "is not a valid universal character" } */ +#if U'\u004a' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu74 = U"\u004a"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000004a' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU74 = U"\U0000004a"; /* { dg-error "is not a valid universal character" } */ +#if U'\u004b' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu75 = U"\u004b"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000004b' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU75 = U"\U0000004b"; /* { dg-error "is not a valid universal character" } */ +#if U'\u004c' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu76 = U"\u004c"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000004c' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU76 = U"\U0000004c"; /* { dg-error "is not a valid universal character" } */ +#if U'\u004d' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu77 = U"\u004d"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000004d' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU77 = U"\U0000004d"; /* { dg-error "is not a valid universal character" } */ +#if U'\u004e' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu78 = U"\u004e"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000004e' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU78 = U"\U0000004e"; /* { dg-error "is not a valid universal character" } */ +#if U'\u004f' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu79 = U"\u004f"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000004f' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU79 = U"\U0000004f"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0050' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu80 = U"\u0050"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000050' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU80 = U"\U00000050"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0051' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu81 = U"\u0051"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000051' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU81 = U"\U00000051"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0052' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu82 = U"\u0052"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000052' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU82 = U"\U00000052"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0053' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu83 = U"\u0053"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000053' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU83 = U"\U00000053"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0054' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu84 = U"\u0054"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000054' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU84 = U"\U00000054"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0055' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu85 = U"\u0055"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000055' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU85 = U"\U00000055"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0056' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu86 = U"\u0056"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000056' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU86 = U"\U00000056"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0057' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu87 = U"\u0057"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000057' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU87 = U"\U00000057"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0058' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu88 = U"\u0058"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000058' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU88 = U"\U00000058"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0059' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu89 = U"\u0059"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000059' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU89 = U"\U00000059"; /* { dg-error "is not a valid universal character" } */ +#if U'\u005a' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu90 = U"\u005a"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000005a' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU90 = U"\U0000005a"; /* { dg-error "is not a valid universal character" } */ +#if U'\u005b' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu91 = U"\u005b"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000005b' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU91 = U"\U0000005b"; /* { dg-error "is not a valid universal character" } */ +#if U'\u005c' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu92 = U"\u005c"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000005c' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU92 = U"\U0000005c"; /* { dg-error "is not a valid universal character" } */ +#if U'\u005d' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu93 = U"\u005d"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000005d' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU93 = U"\U0000005d"; /* { dg-error "is not a valid universal character" } */ +#if U'\u005e' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu94 = U"\u005e"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000005e' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU94 = U"\U0000005e"; /* { dg-error "is not a valid universal character" } */ +#if U'\u005f' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu95 = U"\u005f"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000005f' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU95 = U"\U0000005f"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0060' +#endif +void *tu96 = U"\u0060"; +#if U'\U00000060' +#endif +void *tU96 = U"\U00000060"; +#if U'\u0061' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu97 = U"\u0061"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000061' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU97 = U"\U00000061"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0062' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu98 = U"\u0062"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000062' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU98 = U"\U00000062"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0063' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu99 = U"\u0063"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000063' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU99 = U"\U00000063"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0064' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu100 = U"\u0064"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000064' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU100 = U"\U00000064"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0065' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu101 = U"\u0065"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000065' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU101 = U"\U00000065"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0066' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu102 = U"\u0066"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000066' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU102 = U"\U00000066"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0067' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu103 = U"\u0067"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000067' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU103 = U"\U00000067"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0068' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu104 = U"\u0068"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000068' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU104 = U"\U00000068"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0069' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu105 = U"\u0069"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000069' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU105 = U"\U00000069"; /* { dg-error "is not a valid universal character" } */ +#if U'\u006a' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu106 = U"\u006a"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000006a' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU106 = U"\U0000006a"; /* { dg-error "is not a valid universal character" } */ +#if U'\u006b' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu107 = U"\u006b"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000006b' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU107 = U"\U0000006b"; /* { dg-error "is not a valid universal character" } */ +#if U'\u006c' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu108 = U"\u006c"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000006c' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU108 = U"\U0000006c"; /* { dg-error "is not a valid universal character" } */ +#if U'\u006d' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu109 = U"\u006d"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000006d' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU109 = U"\U0000006d"; /* { dg-error "is not a valid universal character" } */ +#if U'\u006e' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu110 = U"\u006e"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000006e' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU110 = U"\U0000006e"; /* { dg-error "is not a valid universal character" } */ +#if U'\u006f' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu111 = U"\u006f"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000006f' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU111 = U"\U0000006f"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0070' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu112 = U"\u0070"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000070' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU112 = U"\U00000070"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0071' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu113 = U"\u0071"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000071' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU113 = U"\U00000071"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0072' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu114 = U"\u0072"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000072' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU114 = U"\U00000072"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0073' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu115 = U"\u0073"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000073' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU115 = U"\U00000073"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0074' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu116 = U"\u0074"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000074' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU116 = U"\U00000074"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0075' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu117 = U"\u0075"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000075' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU117 = U"\U00000075"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0076' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu118 = U"\u0076"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000076' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU118 = U"\U00000076"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0077' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu119 = U"\u0077"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000077' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU119 = U"\U00000077"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0078' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu120 = U"\u0078"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000078' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU120 = U"\U00000078"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0079' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu121 = U"\u0079"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000079' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU121 = U"\U00000079"; /* { dg-error "is not a valid universal character" } */ +#if U'\u007a' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu122 = U"\u007a"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000007a' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU122 = U"\U0000007a"; /* { dg-error "is not a valid universal character" } */ +#if U'\u007b' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu123 = U"\u007b"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000007b' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU123 = U"\U0000007b"; /* { dg-error "is not a valid universal character" } */ +#if U'\u007c' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu124 = U"\u007c"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000007c' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU124 = U"\U0000007c"; /* { dg-error "is not a valid universal character" } */ +#if U'\u007d' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu125 = U"\u007d"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000007d' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU125 = U"\U0000007d"; /* { dg-error "is not a valid universal character" } */ +#if U'\u007e' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu126 = U"\u007e"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000007e' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU126 = U"\U0000007e"; /* { dg-error "is not a valid universal character" } */ +#if U'\u007f' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu127 = U"\u007f"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000007f' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU127 = U"\U0000007f"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0080' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu128 = U"\u0080"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000080' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU128 = U"\U00000080"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0081' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu129 = U"\u0081"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000081' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU129 = U"\U00000081"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0082' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu130 = U"\u0082"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000082' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU130 = U"\U00000082"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0083' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu131 = U"\u0083"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000083' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU131 = U"\U00000083"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0084' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu132 = U"\u0084"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000084' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU132 = U"\U00000084"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0085' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu133 = U"\u0085"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000085' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU133 = U"\U00000085"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0086' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu134 = U"\u0086"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000086' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU134 = U"\U00000086"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0087' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu135 = U"\u0087"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000087' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU135 = U"\U00000087"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0088' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu136 = U"\u0088"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000088' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU136 = U"\U00000088"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0089' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu137 = U"\u0089"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000089' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU137 = U"\U00000089"; /* { dg-error "is not a valid universal character" } */ +#if U'\u008a' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu138 = U"\u008a"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000008a' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU138 = U"\U0000008a"; /* { dg-error "is not a valid universal character" } */ +#if U'\u008b' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu139 = U"\u008b"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000008b' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU139 = U"\U0000008b"; /* { dg-error "is not a valid universal character" } */ +#if U'\u008c' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu140 = U"\u008c"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000008c' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU140 = U"\U0000008c"; /* { dg-error "is not a valid universal character" } */ +#if U'\u008d' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu141 = U"\u008d"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000008d' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU141 = U"\U0000008d"; /* { dg-error "is not a valid universal character" } */ +#if U'\u008e' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu142 = U"\u008e"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000008e' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU142 = U"\U0000008e"; /* { dg-error "is not a valid universal character" } */ +#if U'\u008f' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu143 = U"\u008f"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000008f' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU143 = U"\U0000008f"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0090' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu144 = U"\u0090"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000090' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU144 = U"\U00000090"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0091' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu145 = U"\u0091"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000091' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU145 = U"\U00000091"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0092' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu146 = U"\u0092"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000092' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU146 = U"\U00000092"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0093' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu147 = U"\u0093"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000093' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU147 = U"\U00000093"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0094' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu148 = U"\u0094"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000094' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU148 = U"\U00000094"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0095' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu149 = U"\u0095"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000095' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU149 = U"\U00000095"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0096' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu150 = U"\u0096"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000096' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU150 = U"\U00000096"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0097' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu151 = U"\u0097"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000097' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU151 = U"\U00000097"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0098' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu152 = U"\u0098"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000098' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU152 = U"\U00000098"; /* { dg-error "is not a valid universal character" } */ +#if U'\u0099' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu153 = U"\u0099"; /* { dg-error "is not a valid universal character" } */ +#if U'\U00000099' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU153 = U"\U00000099"; /* { dg-error "is not a valid universal character" } */ +#if U'\u009a' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu154 = U"\u009a"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000009a' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU154 = U"\U0000009a"; /* { dg-error "is not a valid universal character" } */ +#if U'\u009b' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu155 = U"\u009b"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000009b' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU155 = U"\U0000009b"; /* { dg-error "is not a valid universal character" } */ +#if U'\u009c' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu156 = U"\u009c"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000009c' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU156 = U"\U0000009c"; /* { dg-error "is not a valid universal character" } */ +#if U'\u009d' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu157 = U"\u009d"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000009d' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU157 = U"\U0000009d"; /* { dg-error "is not a valid universal character" } */ +#if U'\u009e' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu158 = U"\u009e"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000009e' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU158 = U"\U0000009e"; /* { dg-error "is not a valid universal character" } */ +#if U'\u009f' /* { dg-error "is not a valid universal character" } */ +#endif +void *tu159 = U"\u009f"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000009f' /* { dg-error "is not a valid universal character" } */ +#endif +void *tU159 = U"\U0000009f"; /* { dg-error "is not a valid universal character" } */ +#if U'\u00a0' +#endif +void *tu160 = U"\u00a0"; +#if U'\U000000a0' +#endif +void *tU160 = U"\U000000a0"; + +#if U'\ud800' /* { dg-error "is not a valid universal character" } */ +#endif +void *tud800 = U"\ud800"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000d800' /* { dg-error "is not a valid universal character" } */ +#endif +void *tUd800 = U"\U0000d800"; /* { dg-error "is not a valid universal character" } */ + +#if U'\udfff' /* { dg-error "is not a valid universal character" } */ +#endif +void *tudfff = U"\udfff"; /* { dg-error "is not a valid universal character" } */ +#if U'\U0000dfff' /* { dg-error "is not a valid universal character" } */ +#endif +void *tUdfff = U"\U0000dfff"; /* { dg-error "is not a valid universal character" } */ + +#if U'\U0010ffff' +#endif +void *tU10ffff = U"\U0010ffff"; + +#if U'\U00110000' /* { dg-error "is outside the UCS codespace" } */ +#endif +void *tU110000 = U"\U00110000"; /* { dg-error "is outside the UCS codespace" } */ + +#if U'\Uffffffff' /* { dg-error "is not a valid universal character" } */ +#endif +void *tUffffffff = U"\Uffffffff"; /* { dg-error "is not a valid universal character" } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr106967.c b/gcc/testsuite/gcc.dg/tree-ssa/pr106967.c new file mode 100644 index 0000000..bff2795 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr106967.c @@ -0,0 +1,16 @@ +// { dg-do compile } +// { dg-options "-O2 -ffinite-math-only -fno-trapping-math -fno-tree-dominator-opts" } + +void +foo (float x, int *y) +{ + int i; + float sum2 = 0.0; + + for (i = 0; i < *y; ++i) + sum2 += x; + + sum2 = 1.0 / sum2; + if (sum2 * 0.0 < 5.E-5) + *y = 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr107009.c b/gcc/testsuite/gcc.dg/tree-ssa/pr107009.c new file mode 100644 index 0000000..5010aed --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr107009.c @@ -0,0 +1,15 @@ +// { dg-do compile } +// { dg-options "-O2 -fdump-tree-dom2-alias" } + +typedef __SIZE_TYPE__ size_t; + +void saxpy(size_t n) +{ + if (n == 0 || n % 8 != 0) + __builtin_unreachable(); + + extern void foobar (size_t n); + foobar (n); +} + +// { dg-final { scan-tree-dump "NONZERO.*fff8" "dom2" } } diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-100.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-100.c new file mode 100644 index 0000000..ead7654 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-100.c @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-fre1" } */ + +float bar, baz; +void foo (int *p, int n) +{ + *p = 0; + do + { + bar = 1.; + /* When iterating we should have optimistically value-numbered + *p to zero, on the second iteration we have to prove the + store below does not affect the value of this load though. + We can compare the stored value against the value from the + previous iteration instead relying on a non-walking lookup. */ + if (*p) + { + baz = 2.; + *p = 0; + } + } + while (--n); +} + +/* { dg-final { scan-tree-dump-not "baz" "fre1" } } */ diff --git a/gcc/testsuite/gcc.dg/tsan/pr106984.c b/gcc/testsuite/gcc.dg/tsan/pr106984.c new file mode 100644 index 0000000..69cf83d --- /dev/null +++ b/gcc/testsuite/gcc.dg/tsan/pr106984.c @@ -0,0 +1,7 @@ +/* { dg-do compile } */ +/* { dg-options "-fsanitize=thread" } */ + +int svcsw (int *ptr, int oldval, int newval) +{ + return __sync_val_compare_and_swap (ptr, oldval, newval); +} diff --git a/gcc/testsuite/gcc.dg/vect/tsvc/vect-tsvc-s243.c b/gcc/testsuite/gcc.dg/vect/tsvc/vect-tsvc-s243.c index 9361821..6eb0240 100644 --- a/gcc/testsuite/gcc.dg/vect/tsvc/vect-tsvc-s243.c +++ b/gcc/testsuite/gcc.dg/vect/tsvc/vect-tsvc-s243.c @@ -38,4 +38,4 @@ int main (int argc, char **argv) return 0; } -/* { dg-final { scan-tree-dump "vectorized 1 loops" "vect" { xfail *-*-* } } } */ +/* { dg-final { scan-tree-dump "vectorized 1 loops" "vect" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vld1x2.c b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vld1x2.c index 92a139b..f933102 100644 --- a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vld1x2.c +++ b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vld1x2.c @@ -1,6 +1,6 @@ /* We haven't implemented these intrinsics for arm yet. */ -/* { dg-xfail-if "" { arm*-*-* } } */ /* { dg-do run } */ +/* { dg-skip-if "unsupported" { arm*-*-* } } */ /* { dg-options "-O3" } */ #include <arm_neon.h> diff --git a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vld1x3.c b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vld1x3.c index 6ddd507..b20dec0 100644 --- a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vld1x3.c +++ b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vld1x3.c @@ -1,6 +1,6 @@ /* We haven't implemented these intrinsics for arm yet. */ -/* { dg-xfail-if "" { arm*-*-* } } */ /* { dg-do run } */ +/* { dg-skip-if "unsupported" { arm*-*-* } } */ /* { dg-options "-O3" } */ #include <arm_neon.h> diff --git a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vld1x4.c b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vld1x4.c index 451a0af..e59f845 100644 --- a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vld1x4.c +++ b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vld1x4.c @@ -1,6 +1,6 @@ /* We haven't implemented these intrinsics for arm yet. */ -/* { dg-xfail-if "" { arm*-*-* } } */ /* { dg-do run } */ +/* { dg-skip-if "unsupported" { arm*-*-* } } */ /* { dg-options "-O3" } */ #include <arm_neon.h> diff --git a/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-1.c b/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-1.c index 68378a5..7115b0a 100644 --- a/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-1.c +++ b/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-1.c @@ -14,6 +14,6 @@ avx_test (void) c[i] = a[i] * b[i+3]; } -/* { dg-final { scan-assembler-not "vmovups\[^\n\r]*movv8sf_internal/2" } } */ -/* { dg-final { scan-assembler "movv4sf_internal/2" } } */ +/* { dg-final { scan-assembler-not "vmovups\[^\n\r]*movv8sf_internal/3" } } */ +/* { dg-final { scan-assembler "movv4sf_internal/3" } } */ /* { dg-final { scan-assembler "vinsertf128" } } */ diff --git a/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-1.c b/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-1.c index d82aecf..4c71395 100644 --- a/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-1.c +++ b/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-1.c @@ -17,6 +17,6 @@ avx_test (void) d[i] = c[i] * 20.0; } -/* { dg-final { scan-assembler-not "vmovups.*movv8sf_internal/3" } } */ -/* { dg-final { scan-assembler "vmovups.*movv4sf_internal/3" } } */ +/* { dg-final { scan-assembler-not "vmovups.*movv8sf_internal/4" } } */ +/* { dg-final { scan-assembler "vmovups.*movv4sf_internal/4" } } */ /* { dg-final { scan-assembler "vextractf128" } } */ diff --git a/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-2.c b/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-2.c index be12529..4978c37 100644 --- a/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-2.c +++ b/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-2.c @@ -23,6 +23,6 @@ avx_test (void) } } -/* { dg-final { scan-assembler-not "vmovdqu.*movv32qi_internal/3" } } */ -/* { dg-final { scan-assembler "vmovdqu.*movv16qi_internal/3" } } */ +/* { dg-final { scan-assembler-not "vmovdqu.*movv32qi_internal/4" } } */ +/* { dg-final { scan-assembler "vmovdqu.*movv16qi_internal/4" } } */ /* { dg-final { scan-assembler "vextract.128" } } */ diff --git a/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-3.c b/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-3.c index 918028d..67635fb 100644 --- a/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-3.c +++ b/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-3.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O3 -dp -mavx -mavx256-split-unaligned-store -mtune=generic -fno-common" } */ +/* { dg-options "-O3 -dp -mavx -mavx256-split-unaligned-store -mtune=generic -fno-common -mno-avx512f" } */ #define N 1024 @@ -17,6 +17,6 @@ avx_test (void) d[i] = c[i] * 20.0; } -/* { dg-final { scan-assembler-not "vmovupd.*movv4df_internal/3" } } */ -/* { dg-final { scan-assembler "vmovupd.*movv2df_internal/3" } } */ +/* { dg-final { scan-assembler-not "vmovupd.*movv4df_internal/4" } } */ +/* { dg-final { scan-assembler "vmovupd.*movv2df_internal/4" } } */ /* { dg-final { scan-assembler "vextractf128" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr106963.c b/gcc/testsuite/gcc.target/i386/pr106963.c new file mode 100644 index 0000000..9f2d20e --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr106963.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mavx -mno-avx2" } */ + +void +foo_neg_const (int *a) +{ + int i, b = 1; + + for (i = 0; i < 1000; i++) + { + a[i] = b; + b = -b; + } +} diff --git a/gcc/testsuite/gcc.target/i386/pr106994.c b/gcc/testsuite/gcc.target/i386/pr106994.c new file mode 100644 index 0000000..0803311 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr106994.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-march=skylake -Ofast" } */ + +typedef struct { + float ymin, ymax; +} rctf; + +rctf view2d_map_cur_using_maskUI_view2d_view_ortho_curmasked; +float view2d_map_cur_using_maskUI_view2d_view_ortho_yofs; + +void BLI_rctf_translate(); +void glLoadIdentity(); + +void +view2d_map_cur_using_maskUI_view2d_view_ortho() { + BLI_rctf_translate(&view2d_map_cur_using_maskUI_view2d_view_ortho_curmasked); + view2d_map_cur_using_maskUI_view2d_view_ortho_curmasked.ymin = + __builtin_floor(view2d_map_cur_using_maskUI_view2d_view_ortho_curmasked.ymin) - + view2d_map_cur_using_maskUI_view2d_view_ortho_yofs; + view2d_map_cur_using_maskUI_view2d_view_ortho_curmasked.ymax = + __builtin_floor(view2d_map_cur_using_maskUI_view2d_view_ortho_curmasked.ymax) - + view2d_map_cur_using_maskUI_view2d_view_ortho_yofs; + glLoadIdentity(); +} diff --git a/gcc/testsuite/gcc.target/i386/pr53346-1.c b/gcc/testsuite/gcc.target/i386/pr53346-1.c new file mode 100644 index 0000000..6d230da --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr53346-1.c @@ -0,0 +1,70 @@ +/* { dg-do compile } */ +/* { dg-options "-msse2 -O2 -mno-sse3" } */ +/* { dg-final { scan-assembler-times "shufps" 15 } } */ +/* { dg-final { scan-assembler-times "pshufd" 2 } } */ + +typedef int v4si __attribute__((vector_size(16))); + +v4si +__attribute__((noipa)) +foo (v4si a, v4si b) +{ + return __builtin_shufflevector (a, b, 1, 2, 5, 3); +} + +v4si +__attribute__((noipa)) +foo1 (v4si a, v4si b) +{ + return __builtin_shufflevector (a, b, 1, 5, 2, 3); +} + +v4si +__attribute__((noipa)) +foo2 (v4si a, v4si b) +{ + return __builtin_shufflevector (a, b, 1, 2, 3, 5); +} + +v4si +__attribute__((noipa)) +foo3 (v4si a, v4si b) +{ + return __builtin_shufflevector (a, b, 1, 4, 5, 6); +} + +v4si +__attribute__((noipa)) +foo4 (v4si a, v4si b) +{ + return __builtin_shufflevector (a, b, 3, 6, 7, 5); +} + +v4si +__attribute__((noipa)) +foo5 (v4si a, v4si b) +{ + return __builtin_shufflevector (a, b, 2, 4, 7, 6); +} + +v4si +__attribute__((noipa)) +foo6 (v4si a, v4si b) +{ + return __builtin_shufflevector (a, b, 2, 4, 3, 6); +} + +v4si +__attribute__((noipa)) +foo7 (v4si a, v4si b) +{ + return __builtin_shufflevector (a, b, 2, 3, 4, 6); +} + +v4si +__attribute__((noipa)) +foo8 (v4si a, v4si b) +{ + return __builtin_shufflevector (a, b, 2, 4, 6, 3); +} + diff --git a/gcc/testsuite/gcc.target/i386/pr53346-2.c b/gcc/testsuite/gcc.target/i386/pr53346-2.c new file mode 100644 index 0000000..0c6c7b3 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr53346-2.c @@ -0,0 +1,59 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -msse2" } */ +/* { dg-require-effective-target sse2 } */ + +#include "sse2-check.h" +#include "pr53346-1.c" + +static void +sse2_test () +{ + v4si a = __extension__(v4si) { 0, 1, 2, 3 }; + v4si b = __extension__(v4si) { 4, 5, 6, 7 }; + v4si exp = __extension__(v4si) { 1, 2, 5, 3 }; + v4si dest; + dest = foo (a, b); + if (__builtin_memcmp (&dest, &exp, 16)) + __builtin_abort (); + + exp = __extension__ (v4si) { 1, 5, 2, 3 }; + dest = foo1 (a, b); + if (__builtin_memcmp (&dest, &exp, 16)) + __builtin_abort (); + + exp = __extension__ (v4si) { 1, 2, 3, 5 }; + dest = foo2 (a, b); + if (__builtin_memcmp (&dest, &exp, 16)) + __builtin_abort (); + + exp = __extension__ (v4si) { 1, 4, 5, 6 }; + dest = foo3 (a, b); + if (__builtin_memcmp (&dest, &exp, 16)) + __builtin_abort (); + + exp = __extension__ (v4si) { 3, 6, 7, 5 }; + dest = foo4 (a, b); + if (__builtin_memcmp (&dest, &exp, 16)) + __builtin_abort (); + + exp = __extension__ (v4si) { 2, 4, 7, 6 }; + dest = foo5 (a, b); + if (__builtin_memcmp (&dest, &exp, 16)) + __builtin_abort (); + + exp = __extension__ (v4si) { 2, 4, 3, 6 }; + dest = foo6 (a, b); + if (__builtin_memcmp (&dest, &exp, 16)) + __builtin_abort (); + + exp = __extension__ (v4si) { 2, 3, 4, 6 }; + dest = foo7 (a, b); + if (__builtin_memcmp (&dest, &exp, 16)) + __builtin_abort (); + + exp = __extension__ (v4si) { 2, 4, 6, 3 }; + dest = foo8 (a, b); + if (__builtin_memcmp (&dest, &exp, 16)) + __builtin_abort (); + +} diff --git a/gcc/testsuite/gcc.target/i386/pr53346-3.c b/gcc/testsuite/gcc.target/i386/pr53346-3.c new file mode 100644 index 0000000..0b204f6 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr53346-3.c @@ -0,0 +1,69 @@ +/* { dg-do compile } */ +/* { dg-options "-msse2 -O2 -mno-sse3" } */ +/* { dg-final { scan-assembler-times "shufps" 17 } } */ + +typedef float v4sf __attribute__((vector_size(16))); + +v4sf +__attribute__((noipa)) +foo (v4sf a, v4sf b) +{ + return __builtin_shufflevector (a, b, 1, 2, 5, 3); +} + +v4sf +__attribute__((noipa)) +foo1 (v4sf a, v4sf b) +{ + return __builtin_shufflevector (a, b, 1, 5, 2, 3); +} + +v4sf +__attribute__((noipa)) +foo2 (v4sf a, v4sf b) +{ + return __builtin_shufflevector (a, b, 1, 2, 3, 5); +} + +v4sf +__attribute__((noipa)) +foo3 (v4sf a, v4sf b) +{ + return __builtin_shufflevector (a, b, 1, 4, 5, 6); +} + +v4sf +__attribute__((noipa)) +foo4 (v4sf a, v4sf b) +{ + return __builtin_shufflevector (a, b, 3, 6, 7, 5); +} + +v4sf +__attribute__((noipa)) +foo5 (v4sf a, v4sf b) +{ + return __builtin_shufflevector (a, b, 2, 4, 7, 6); +} + +v4sf +__attribute__((noipa)) +foo6 (v4sf a, v4sf b) +{ + return __builtin_shufflevector (a, b, 2, 4, 3, 6); +} + +v4sf +__attribute__((noipa)) +foo7 (v4sf a, v4sf b) +{ + return __builtin_shufflevector (a, b, 2, 3, 4, 6); +} + +v4sf +__attribute__((noipa)) +foo8 (v4sf a, v4sf b) +{ + return __builtin_shufflevector (a, b, 2, 4, 6, 3); +} + diff --git a/gcc/testsuite/gcc.target/i386/pr53346-4.c b/gcc/testsuite/gcc.target/i386/pr53346-4.c new file mode 100644 index 0000000..9e4e45b --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr53346-4.c @@ -0,0 +1,59 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -msse2" } */ +/* { dg-require-effective-target sse2 } */ + +#include "sse2-check.h" +#include "pr53346-3.c" + +static void +sse2_test () +{ + v4sf a = __extension__(v4sf) { 0, 1, 2, 3 }; + v4sf b = __extension__(v4sf) { 4, 5, 6, 7 }; + v4sf exp = __extension__(v4sf) { 1, 2, 5, 3 }; + v4sf dest; + dest = foo (a, b); + if (__builtin_memcmp (&dest, &exp, 16)) + __builtin_abort (); + + exp = __extension__ (v4sf) { 1, 5, 2, 3 }; + dest = foo1 (a, b); + if (__builtin_memcmp (&dest, &exp, 16)) + __builtin_abort (); + + exp = __extension__ (v4sf) { 1, 2, 3, 5 }; + dest = foo2 (a, b); + if (__builtin_memcmp (&dest, &exp, 16)) + __builtin_abort (); + + exp = __extension__ (v4sf) { 1, 4, 5, 6 }; + dest = foo3 (a, b); + if (__builtin_memcmp (&dest, &exp, 16)) + __builtin_abort (); + + exp = __extension__ (v4sf) { 3, 6, 7, 5 }; + dest = foo4 (a, b); + if (__builtin_memcmp (&dest, &exp, 16)) + __builtin_abort (); + + exp = __extension__ (v4sf) { 2, 4, 7, 6 }; + dest = foo5 (a, b); + if (__builtin_memcmp (&dest, &exp, 16)) + __builtin_abort (); + + exp = __extension__ (v4sf) { 2, 4, 3, 6 }; + dest = foo6 (a, b); + if (__builtin_memcmp (&dest, &exp, 16)) + __builtin_abort (); + + exp = __extension__ (v4sf) { 2, 3, 4, 6 }; + dest = foo7 (a, b); + if (__builtin_memcmp (&dest, &exp, 16)) + __builtin_abort (); + + exp = __extension__ (v4sf) { 2, 4, 6, 3 }; + dest = foo8 (a, b); + if (__builtin_memcmp (&dest, &exp, 16)) + __builtin_abort (); + +} diff --git a/gcc/testsuite/gcc.target/i386/pr94962-1.c b/gcc/testsuite/gcc.target/i386/pr94962-1.c new file mode 100644 index 0000000..e3b0124 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr94962-1.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mavx" } */ +/* { dg-final { scan-assembler-not "vmovdqa" } } */ +/* { dg-final { scan-assembler-times "vpcmpeqd\[ \\t\]+%xmm\[0-9\]" 1 } } */ + +#include <immintrin.h> + +__m256i mask() +{ + return _mm256_zextsi128_si256(_mm_set1_epi8(-1)); +} diff --git a/gcc/testsuite/gcc.target/i386/pr94962-2.c b/gcc/testsuite/gcc.target/i386/pr94962-2.c new file mode 100644 index 0000000..4e10e92 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr94962-2.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mavx512f" } */ +/* { dg-final { scan-assembler-not "vmovdqa" } } */ +/* { dg-final { scan-assembler-times "vpcmpeqd\[ \\t\]+%xmm\[0-9\]" 1 } } */ +/* { dg-final { scan-assembler-times "vpcmpeqd\[ \\t\]+%ymm\[0-9\]" 1 } } */ + +#include <immintrin.h> + +__m512i mask1() +{ + return _mm512_zextsi128_si512(_mm_set1_epi8(-1)); +} + +__m512i mask2() +{ + return _mm512_zextsi256_si512(_mm256_set1_epi8(-1)); +} diff --git a/gcc/testsuite/gcc.target/i386/pr94962-3.c b/gcc/testsuite/gcc.target/i386/pr94962-3.c new file mode 100644 index 0000000..8d0b997 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr94962-3.c @@ -0,0 +1,64 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mavx512f" } */ +/* { dg-final { scan-assembler-not "vmovdqa" } } */ +/* { dg-final { scan-assembler-times "vpcmpeqd\[ \\t\]+%ymm\[0-9\]" 4 } } */ + +typedef long long __v8di __attribute__ ((__vector_size__ (64))); +typedef int __v16si __attribute__ ((__vector_size__ (64))); +typedef short __v32hi __attribute__ ((__vector_size__ (64))); +typedef char __v64qi __attribute__ ((__vector_size__ (64))); +typedef long long __m512i __attribute__ ((__vector_size__ (64), __may_alias__)); + +__m512i +__attribute__ ((noinline, noclone)) +foo1 () +{ + return __extension__ (__m512i)(__v8di) { -1, -1, -1, -1, + 0, 0, 0, 0 }; +} + +__m512i +__attribute__ ((noinline, noclone)) +foo2 () +{ + return __extension__ (__m512i)(__v16si) { -1, -1, -1, -1, + -1, -1, -1, -1, + 0, 0, 0, 0, + 0, 0, 0, 0 }; +} + +__m512i +__attribute__ ((noinline, noclone)) +foo3 () +{ + return __extension__ (__m512i)(__v32hi) { -1, -1, -1, -1, + -1, -1, -1, -1, + -1, -1, -1, -1, + -1, -1, -1, -1, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0 }; +} + +__m512i +__attribute__ ((noinline, noclone)) +foo4 () +{ + return __extension__ (__m512i)(__v64qi) { -1, -1, -1, -1, + -1, -1, -1, -1, + -1, -1, -1, -1, + -1, -1, -1, -1, + -1, -1, -1, -1, + -1, -1, -1, -1, + -1, -1, -1, -1, + -1, -1, -1, -1, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0 }; +} diff --git a/gcc/testsuite/gcc.target/i386/pr94962-4.c b/gcc/testsuite/gcc.target/i386/pr94962-4.c new file mode 100644 index 0000000..5502c39 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr94962-4.c @@ -0,0 +1,49 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mavx" } */ +/* { dg-final { scan-assembler-not "vmovdqa" } } */ +/* { dg-final { scan-assembler-times "vpcmpeqd\[ \\t\]+%xmm\[0-9\]" 4 } } */ + +typedef long long __v4di __attribute__ ((__vector_size__ (32))); +typedef int __v8si __attribute__ ((__vector_size__ (32))); +typedef short __v16hi __attribute__ ((__vector_size__ (32))); +typedef char __v32qi __attribute__ ((__vector_size__ (32))); +typedef long long __m256i __attribute__ ((__vector_size__ (32), __may_alias__)); + +__m256i +__attribute__ ((noinline, noclone)) +foo1 () +{ + return __extension__ (__m256i)(__v4di) { -1, -1, 0, 0 }; +} + +__m256i +__attribute__ ((noinline, noclone)) +foo2 () +{ + return __extension__ (__m256i)(__v8si) { -1, -1, -1, -1, + 0, 0, 0, 0 }; +} + +__m256i +__attribute__ ((noinline, noclone)) +foo3 () +{ + return __extension__ (__m256i)(__v16hi) { -1, -1, -1, -1, + -1, -1, -1, -1, + 0, 0, 0, 0, + 0, 0, 0, 0 }; +} + +__m256i +__attribute__ ((noinline, noclone)) +foo4 () +{ + return __extension__ (__m256i)(__v32qi) { -1, -1, -1, -1, + -1, -1, -1, -1, + -1, -1, -1, -1, + -1, -1, -1, -1, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0 }; +} diff --git a/gcc/testsuite/gcc.target/powerpc/pr100645.c b/gcc/testsuite/gcc.target/powerpc/pr100645.c new file mode 100644 index 0000000..c4e92cc --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr100645.c @@ -0,0 +1,13 @@ +/* { dg-require-effective-target powerpc_altivec_ok } */ +/* { dg-options "-mdejagnu-cpu=power6 -maltivec" } */ + +/* This used to ICE. */ + +typedef long long v2di __attribute__ ((vector_size (16))); + +v2di +foo_v2di_l (v2di x) +{ + return __builtin_shuffle ((v2di){0, 0}, x, (v2di){3, 0}); +} + diff --git a/gcc/testsuite/gcc.target/powerpc/pr96072.c b/gcc/testsuite/gcc.target/powerpc/pr96072.c new file mode 100644 index 0000000..10341c9 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr96072.c @@ -0,0 +1,14 @@ +/* { dg-options "-O2" } */ + +/* This used to ICE with the SYSV ABI (PR96072). */ + +void +he (int jn) +{ + { + int bh[jn]; + if (jn != 0) + goto wa; + } +wa:; +} diff --git a/gcc/testsuite/gcc.target/riscv/ret-1.c b/gcc/testsuite/gcc.target/riscv/ret-1.c new file mode 100644 index 0000000..28133aa --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/ret-1.c @@ -0,0 +1,41 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -dp" } */ +/* This was extracted from coremark. */ + + +typedef signed short ee_s16; +typedef struct list_data_s +{ + ee_s16 data16; + ee_s16 idx; +} list_data; + +typedef struct list_head_s +{ + struct list_head_s *next; + struct list_data_s *info; +} list_head; + + +list_head * +core_list_find(list_head *list, list_data *info) +{ + if (info->idx >= 0) + { + while (list && (list->info->idx != info->idx)) + list = list->next; + return list; + } + else + { + while (list && ((list->info->data16 & 0xff) != info->data16)) + list = list->next; + return list; + } +} + +/* There is only one legitimate unconditional jump, so test for that, + which will catch the case where bb-reorder leaves a jump to a ret + in the IL. */ +/* { dg-final { scan-assembler-times "jump" 1 } } */ + diff --git a/gcc/testsuite/gfortran.dg/PR100103.f90 b/gcc/testsuite/gfortran.dg/PR100103.f90 new file mode 100644 index 0000000..2140561 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/PR100103.f90 @@ -0,0 +1,76 @@ +! { dg-do run } +! +! Test the fix for PR100103 +! + +program main_p + implicit none + + integer :: i + integer, parameter :: n = 11 + + type :: foo_t + integer :: i + end type foo_t + + type(foo_t), parameter :: a(*) = [(foo_t(i), i=1,n)] + + type(foo_t), allocatable :: bar_d(:) + class(foo_t), allocatable :: bar_p(:) + class(*), allocatable :: bar_u(:) + + + call foo_d(bar_d) + if(.not.allocated(bar_d)) stop 1 + if(any(bar_d%i/=a%i)) stop 2 + deallocate(bar_d) + call foo_p(bar_p) + if(.not.allocated(bar_p)) stop 3 + if(any(bar_p%i/=a%i)) stop 4 + deallocate(bar_p) + call foo_u(bar_u) + if(.not.allocated(bar_u)) stop 5 + select type(bar_u) + type is(foo_t) + if(any(bar_u%i/=a%i)) stop 6 + class default + stop 7 + end select + deallocate(bar_u) + +contains + + subroutine foo_d(that) + type(foo_t), allocatable, intent(out) :: that(..) + + select rank(that) + rank(1) + that = a + rank default + stop 8 + end select + end subroutine foo_d + + subroutine foo_p(that) + class(foo_t), allocatable, intent(out) :: that(..) + + select rank(that) + rank(1) + that = a + rank default + stop 9 + end select + end subroutine foo_p + + subroutine foo_u(that) + class(*), allocatable, intent(out) :: that(..) + + select rank(that) + rank(1) + that = a + rank default + stop 10 + end select + end subroutine foo_u + +end program main_p diff --git a/gcc/testsuite/gfortran.dg/PR100132.f90 b/gcc/testsuite/gfortran.dg/PR100132.f90 new file mode 100644 index 0000000..78ae670 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/PR100132.f90 @@ -0,0 +1,75 @@ +! { dg-do run } +! +! Test the fix for PR100132 +! + +module main_m + implicit none + + private + + public :: & + foo_t + + public :: & + set, & + get + + type :: foo_t + integer :: i + end type foo_t + + type(foo_t), save, pointer :: data => null() + +contains + + subroutine set(this) + class(foo_t), pointer, intent(in) :: this + + if(associated(data)) stop 1 + data => this + end subroutine set + + subroutine get(this) + type(foo_t), pointer, intent(out) :: this + + if(.not.associated(data)) stop 4 + this => data + nullify(data) + end subroutine get + +end module main_m + +program main_p + + use :: main_m, only: & + foo_t, set, get + + implicit none + + integer, parameter :: n = 1000 + + type(foo_t), pointer :: ps + type(foo_t), target :: s + integer :: i, j, yay, nay + + yay = 0 + nay = 0 + do i = 1, n + s%i = i + call set(s) + call get(ps) + if(.not.associated(ps)) stop 13 + j = ps%i + if(i/=j) stop 14 + if(i/=s%i) stop 15 + if(ps%i/=s%i) stop 16 + if(associated(ps, s))then + yay = yay + 1 + else + nay = nay + 1 + end if + end do + if((yay/=n).or.(nay/=0)) stop 17 + +end program main_p diff --git a/gcc/testsuite/gfortran.dg/associate_26a.f90 b/gcc/testsuite/gfortran.dg/associate_26a.f90 new file mode 100644 index 0000000..85aebeb --- /dev/null +++ b/gcc/testsuite/gfortran.dg/associate_26a.f90 @@ -0,0 +1,15 @@ +! { dg-do compile } +! { dg-options "-fcoarray=lib" } +! +! Test the fix for PR78152 and the followup in PR82868 +! +! Contributed by <physiker@toast2.net> +! +program co_assoc + implicit none + integer, parameter :: p = 5 + real, allocatable :: a(:,:)[:,:] + allocate (a(p,p)[2,*]) + associate (i => a(1:p, 1:p)) + end associate +end program co_assoc diff --git a/gcc/testsuite/gfortran.dg/assumed_type_16.f90 b/gcc/testsuite/gfortran.dg/assumed_type_16.f90 new file mode 100644 index 0000000..52d8ef5 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/assumed_type_16.f90 @@ -0,0 +1,14 @@ +! { dg-do compile } +! { dg-additional-options "-std=f2008" } +! +! PR fortran/104143 +! + interface + subroutine foo(x) + type(*) :: x(*) ! { dg-error "Fortran 2018: Assumed type" } + end + end interface + integer :: a + call foo(a) ! { dg-error "Type mismatch in argument" } + call foo((a)) ! { dg-error "Type mismatch in argument" } +end diff --git a/gcc/testsuite/gfortran.dg/assumed_type_17.f90 b/gcc/testsuite/gfortran.dg/assumed_type_17.f90 new file mode 100644 index 0000000..d6ccd30 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/assumed_type_17.f90 @@ -0,0 +1,18 @@ +! { dg-do compile } +! { dg-additional-options "-std=f2018 -fdump-tree-original" } +! +! PR fortran/104143 +! + interface + subroutine foo(x) + type(*) :: x(*) + end + end interface + integer :: a + call foo(a) + call foo((a)) +end + +! { dg-final { scan-tree-dump-times "foo \\(&a\\);" 1 "original" } } +! { dg-final { scan-tree-dump-times "D.\[0-9\]+ = a;" 1 "original" } } +! { dg-final { scan-tree-dump-times "foo \\(&D.\[0-9\]+\\);" 1 "original" } } diff --git a/gcc/testsuite/gfortran.dg/c-interop/c407b-2.f90 b/gcc/testsuite/gfortran.dg/c-interop/c407b-2.f90 index 4f9f6c7..49352fc 100644 --- a/gcc/testsuite/gfortran.dg/c-interop/c407b-2.f90 +++ b/gcc/testsuite/gfortran.dg/c-interop/c407b-2.f90 @@ -40,7 +40,7 @@ subroutine s0 (x) call g (x, 1) call f (x, 1) ! { dg-error "Type mismatch" } - call h (x, 1) ! { dg-error "Rank mismatch" } + call h (x, 1) ! Scalar to type(*),dimension(*): Invalid in TS29113 but valid since F2018 end subroutine ! Check that you can't use an assumed-type array variable in an array diff --git a/gcc/testsuite/gfortran.dg/ieee/rounding_3.f90 b/gcc/testsuite/gfortran.dg/ieee/rounding_3.f90 new file mode 100644 index 0000000..ff4e834 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/ieee/rounding_3.f90 @@ -0,0 +1,27 @@ +! { dg-do run } + + ! Test IEEE_GET_ROUNDING_MODE and IEEE_SET_ROUNDING_MODE + ! with a RADIX argument + use, intrinsic :: ieee_arithmetic + implicit none + + real :: sx1 + type(ieee_round_type) :: r + + if (ieee_support_rounding(ieee_up, sx1) .and. & + ieee_support_rounding(ieee_down, sx1)) then + + call ieee_set_rounding_mode(ieee_up) + call ieee_get_rounding_mode(r) + if (r /= ieee_up) stop 1 + + call ieee_set_rounding_mode(ieee_down, radix=2) + call ieee_get_rounding_mode(r, radix=2) + if (r /= ieee_down) stop 2 + + call ieee_set_rounding_mode(ieee_up, radix=10) + call ieee_get_rounding_mode(r, radix=2) + if (r /= ieee_down) stop 3 + end if + +end diff --git a/gcc/testsuite/gfortran.dg/intent_optimize_10.f90 b/gcc/testsuite/gfortran.dg/intent_optimize_10.f90 new file mode 100644 index 0000000..d8bc1bb --- /dev/null +++ b/gcc/testsuite/gfortran.dg/intent_optimize_10.f90 @@ -0,0 +1,66 @@ +! { dg-do run } +! { dg-additional-options "-fno-inline -fno-ipa-modref -fdump-tree-optimized -fdump-tree-original" } +! +! PR fortran/41453 +! Check that the INTENT(OUT) attribute causes in the case of non-polymorphic derived type arguments: +! - one clobber to be emitted in the caller before calls to FOO in the *.original dump, +! - no clobber to be emitted in the caller before calls to BAR in the *.original dump, +! - the initialization constants to be optimized away in the *.optimized dump. + +module x + implicit none + type :: t + integer :: c + end type t + type, extends(t) :: u + integer :: d + end type u +contains + subroutine foo(a) + type(t), intent(out) :: a + a = t(42) + end subroutine foo + subroutine bar(b) + class(t), intent(out) :: b + b%c = 24 + end subroutine bar +end module x + +program main + use x + implicit none + type(t) :: tc + type(u) :: uc, ud + class(t), allocatable :: te, tf + + tc = t(123456789) + call foo(tc) + if (tc%c /= 42) stop 1 + + uc = u(987654321, 0) + call foo(uc%t) + if (uc%c /= 42) stop 2 + if (uc%d /= 0) stop 3 + + ud = u(11223344, 0) + call bar(ud) + if (ud%c /= 24) stop 4 + + te = t(55667788) + call foo(te) + if (te%c /= 42) stop 5 + + tf = t(99887766) + call bar(tf) + if (tf%c /= 24) stop 6 + +end program main + +! We don't support class descriptors, neither derived type components, so there is a clobber for tc only; +! no clobber for uc, ud, te, tf. +! { dg-final { scan-tree-dump-times "CLOBBER" 1 "original" } } +! { dg-final { scan-tree-dump "tc = {CLOBBER};" "original" } } + +! There is a clobber for tc, so we should manage to optimize away the associated initialization constant (but not other +! initialization constants). +! { dg-final { scan-tree-dump-not "123456789" "optimized" { target __OPTIMIZE__ } } } diff --git a/gcc/testsuite/gfortran.dg/intent_optimize_4.f90 b/gcc/testsuite/gfortran.dg/intent_optimize_4.f90 new file mode 100644 index 0000000..effbaa1 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/intent_optimize_4.f90 @@ -0,0 +1,43 @@ +! { dg-do run } +! { dg-additional-options "-fdump-tree-original" } +! { dg-final { scan-tree-dump-times "CLOBBER" 2 "original" } } +! +! PR fortran/106817 +! Check that for an actual argument whose dummy is INTENT(OUT), +! the clobber that is emitted in the caller before a procedure call +! happens after any expression depending on the argument value has been +! evaluated. +! + +module m + implicit none +contains + subroutine copy1(out, in) + integer, intent(in) :: in + integer, intent(out) :: out + out = in + end subroutine copy1 + subroutine copy2(in, out) + integer, intent(in) :: in + integer, intent(out) :: out + out = in + end subroutine copy2 +end module m + +program p + use m + implicit none + integer :: a, b + + ! Clobbering of a should happen after a+1 has been evaluated. + a = 3 + call copy1(a, a+1) + if (a /= 4) stop 1 + + ! Clobbering order does not depend on the order of arguments. + ! It should also come last with reversed arguments. + b = 12 + call copy2(b+1, b) + if (b /= 13) stop 2 + +end program p diff --git a/gcc/testsuite/gfortran.dg/intent_optimize_5.f90 b/gcc/testsuite/gfortran.dg/intent_optimize_5.f90 new file mode 100644 index 0000000..2f184bf --- /dev/null +++ b/gcc/testsuite/gfortran.dg/intent_optimize_5.f90 @@ -0,0 +1,24 @@ +! { dg-do run } +! { dg-additional-options "-fno-inline -fno-ipa-modref -fdump-tree-optimized -fdump-tree-original" } +! +! PR fortran/105012 +! Check that the INTENT(OUT) attribute causes one clobber to be emitted in +! the caller before the call to Y in the *.original dump, and the +! initialization constant to be optimized away in the *.optimized dump, +! despite the non-explicit interface if the subroutine with the INTENT(OUT) +! is declared in the same file. + +SUBROUTINE Y (Z) + integer, intent(out) :: Z + Z = 42 +END SUBROUTINE Y +PROGRAM TEST + integer :: X + X = 123456789 + CALL Y (X) + if (X.ne.42) STOP 1 +END PROGRAM + +! { dg-final { scan-tree-dump-times "CLOBBER" 1 "original" } } +! { dg-final { scan-tree-dump "x = {CLOBBER};" "original" } } +! { dg-final { scan-tree-dump-not "123456789" "optimized" { target __OPTIMIZE__ } } } diff --git a/gcc/testsuite/gfortran.dg/intent_optimize_6.f90 b/gcc/testsuite/gfortran.dg/intent_optimize_6.f90 new file mode 100644 index 0000000..72fec3d --- /dev/null +++ b/gcc/testsuite/gfortran.dg/intent_optimize_6.f90 @@ -0,0 +1,34 @@ +! { dg-do run } +! { dg-additional-options "-fno-inline -fno-ipa-modref -fdump-tree-optimized -fdump-tree-original" } +! +! PR fortran/41453 +! Check that the INTENT(OUT) attribute causes one clobber to be emitted in +! the caller before each call to FOO in the *.original dump, and the +! initialization constant to be optimized away in the *.optimized dump, +! in the case of an argument passed by reference to the caller. + +module x +implicit none +contains + subroutine foo(a) + integer(kind=4), intent(out) :: a + a = 42 + end subroutine foo + subroutine bar(b) + integer(kind=4) :: b + b = 123456789 + call foo(b) + end subroutine bar +end module x + +program main + use x + implicit none + integer(kind=4) :: c + call bar(c) + if (c /= 42) stop 1 +end program main + +! { dg-final { scan-tree-dump-times "CLOBBER" 1 "original" } } +! { dg-final { scan-tree-dump "\\*\\\(integer\\\(kind=4\\\) \\*\\\) b = {CLOBBER};" "original" } } +! { dg-final { scan-tree-dump-not "123456789" "optimized" { target __OPTIMIZE__ } } } diff --git a/gcc/testsuite/gfortran.dg/intent_optimize_7.f90 b/gcc/testsuite/gfortran.dg/intent_optimize_7.f90 new file mode 100644 index 0000000..c2f2192 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/intent_optimize_7.f90 @@ -0,0 +1,45 @@ +! { dg-do run } +! { dg-additional-options "-fno-inline -fno-ipa-modref -fdump-tree-optimized -fdump-tree-original" } +! +! PR fortran/41453 +! Check that the INTENT(OUT) attribute causes one clobber to be emitted in +! the caller before each call to FOO in the *.original dump, and the +! initialization constants to be optimized away in the *.optimized dump, +! in the case of SAVE variables. + +module x +implicit none +contains + subroutine foo(a) + integer, intent(out) :: a + a = 42 + end subroutine foo +end module x + +program main + use x + implicit none + integer :: c = 0 + + ! implicit SAVE attribute + c = 123456789 + call foo(c) + if (c /= 42) stop 1 + + ! explicit SAVE attribute + call check_save_explicit + +contains + subroutine check_save_explicit + integer, save :: d + d = 987654321 + call foo(d) + if (d /= 42) stop 2 + end subroutine check_save_explicit +end program main + +! { dg-final { scan-tree-dump-times "CLOBBER" 2 "original" } } +! { dg-final { scan-tree-dump "c = {CLOBBER};" "original" } } +! { dg-final { scan-tree-dump "d = {CLOBBER};" "original" } } +! { dg-final { scan-tree-dump-not "123456789" "optimized" { target __OPTIMIZE__ } } } +! { dg-final { scan-tree-dump-not "987654321" "optimized" { target __OPTIMIZE__ } } } diff --git a/gcc/testsuite/gfortran.dg/intent_optimize_8.f90 b/gcc/testsuite/gfortran.dg/intent_optimize_8.f90 new file mode 100644 index 0000000..4336fce --- /dev/null +++ b/gcc/testsuite/gfortran.dg/intent_optimize_8.f90 @@ -0,0 +1,45 @@ +! { dg-do run } +! { dg-additional-options "-fno-inline -fno-ipa-modref -fdump-tree-optimized -fdump-tree-original" } +! +! PR fortran/41453 +! Check that the INTENT(OUT) attribute causes one clobber to be emitted in +! the caller before each call to FOO in the *.original dump, and the +! initialization constants to be optimized away in the *.optimized dump, +! in the case of associate variables. + +module x +implicit none +contains + subroutine foo(a) + integer, intent(out) :: a + a = 42 + end subroutine foo +end module x + +program main + use x + implicit none + integer :: c1, c2 + + c1 = 123456789 + associate (d1 => c1) + call foo(d1) + if (d1 /= 42) stop 1 + end associate + if (c1 /= 42) stop 2 + + c2 = 0 + associate (d2 => c2) + d2 = 987654321 + call foo(d2) + if (d2 /= 42) stop 3 + end associate + if (c2 /= 42) stop 4 + +end program main + +! { dg-final { scan-tree-dump-times "CLOBBER" 2 "original" } } +! { dg-final { scan-tree-dump "d1 = {CLOBBER};" "original" } } +! { dg-final { scan-tree-dump "\\*d2 = {CLOBBER};" "original" } } +! { dg-final { scan-tree-dump-not "123456789" "optimized" { target __OPTIMIZE__ } } } +! { dg-final { scan-tree-dump-not "987654321" "optimized" { target __OPTIMIZE__ } } } diff --git a/gcc/testsuite/gfortran.dg/intent_optimize_9.f90 b/gcc/testsuite/gfortran.dg/intent_optimize_9.f90 new file mode 100644 index 0000000..0146dff --- /dev/null +++ b/gcc/testsuite/gfortran.dg/intent_optimize_9.f90 @@ -0,0 +1,42 @@ +! { dg-do run } +! { dg-additional-options "-fno-inline -fno-ipa-modref -fdump-tree-optimized -fdump-tree-original" } +! +! PR fortran/41453 +! Check that the INTENT(OUT) attribute causes one clobber to be emitted in +! the caller before each call to FOO in the *.original dump, and the +! initialization constants to be optimized away in the *.optimized dump, +! in the case of scalar allocatables and pointers. + +module x +implicit none +contains + subroutine foo(a) + integer, intent(out) :: a + a = 42 + end subroutine foo +end module x + +program main + use x + implicit none + integer, allocatable :: ca + integer, target :: ct + integer, pointer :: cp + + allocate(ca) + ca = 123456789 + call foo(ca) + if (ca /= 42) stop 1 + deallocate(ca) + + ct = 987654321 + cp => ct + call foo(cp) + if (ct /= 42) stop 2 +end program main + +! { dg-final { scan-tree-dump-times "CLOBBER" 2 "original" } } +! { dg-final { scan-tree-dump "\\*ca = {CLOBBER};" "original" } } +! { dg-final { scan-tree-dump "\\*cp = {CLOBBER};" "original" } } +! { dg-final { scan-tree-dump-not "123456789" "optimized" { target __OPTIMIZE__ } } } +! { dg-final { scan-tree-dump-not "987654321" "optimized" { target __OPTIMIZE__ } } } diff --git a/gcc/testsuite/gfortran.dg/intent_out_15.f90 b/gcc/testsuite/gfortran.dg/intent_out_15.f90 new file mode 100644 index 0000000..64334e6 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/intent_out_15.f90 @@ -0,0 +1,27 @@ +! { dg-do compile } +! { dg-additional-options "-fdump-tree-original" } +! +! PR fortran/105012 +! The following case was triggering an ICE because of a clobber +! on the DERFC function decl instead of its result. + +module error_function +integer, parameter :: r8 = selected_real_kind(12) ! 8 byte real +contains +SUBROUTINE CALERF_r8(ARG, RESULT, JINT) + integer, parameter :: rk = r8 + real(rk), intent(in) :: arg + real(rk), intent(out) :: result + IF (Y .LE. THRESH) THEN + END IF +end SUBROUTINE CALERF_r8 +FUNCTION DERFC(X) + integer, parameter :: rk = r8 ! 8 byte real + real(rk), intent(in) :: X + real(rk) :: DERFC + CALL CALERF_r8(X, DERFC, JINT) +END FUNCTION DERFC +end module error_function + +! { dg-final { scan-tree-dump-times "CLOBBER" 1 "original" } } +! { dg-final { scan-tree-dump "__result_derfc = {CLOBBER};" "original" } } diff --git a/gcc/testsuite/gfortran.dg/pr106985.f90 b/gcc/testsuite/gfortran.dg/pr106985.f90 new file mode 100644 index 0000000..f4ed925 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pr106985.f90 @@ -0,0 +1,8 @@ +! { dg-do compile } +! PR fortran/106985 - ICE in gfc_simplify_expr +! Contributed by G.Steinmetz + +program p + integer, parameter :: a(2) = 1 + integer, parameter :: b = a(2) + b ! { dg-error "before its definition is complete" } +end diff --git a/gcc/testsuite/gfortran.dg/pr106986.f90 b/gcc/testsuite/gfortran.dg/pr106986.f90 new file mode 100644 index 0000000..a309b25 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pr106986.f90 @@ -0,0 +1,8 @@ +! { dg-do compile } +! PR fortran/106986 - ICE in simplify_findloc_nodim +! Contributed by G.Steinmetz + +program p + integer, parameter :: a(:) = [1] ! { dg-error "deferred shape" } + print *, findloc (a, 1) +end diff --git a/gcc/testsuite/lib/scanasm.exp b/gcc/testsuite/lib/scanasm.exp index a80630b..7c9dcfc 100644 --- a/gcc/testsuite/lib/scanasm.exp +++ b/gcc/testsuite/lib/scanasm.exp @@ -803,7 +803,12 @@ proc check_function_body { functions name body_regexp } { if { ![info exists up_functions($name)] } { return 0 } - return [regexp "^$body_regexp\$" $up_functions($name)] + set fn_res [regexp "^$body_regexp\$" $up_functions($name)] + if { !$fn_res } { + verbose -log "body: $body_regexp" + verbose -log "against: $up_functions($name)" + } + return $fn_res } # Check the implementations of functions against expected output. Used as: diff --git a/gcc/testsuite/selftests/riscv/empty-func.rtl b/gcc/testsuite/selftests/riscv/empty-func.rtl new file mode 100644 index 0000000..32bcf72 --- /dev/null +++ b/gcc/testsuite/selftests/riscv/empty-func.rtl @@ -0,0 +1,8 @@ +(function "func" + (insn-chain + (block 2 + (edge-from entry (flags "FALLTHRU")) + (edge-to exit (flags "FALLTHRU")) + ) ;; block 2 + ) ;; insn-chain +) ;; function diff --git a/gcc/tree-data-ref.cc b/gcc/tree-data-ref.cc index ff9327f..91bfb619d 100644 --- a/gcc/tree-data-ref.cc +++ b/gcc/tree-data-ref.cc @@ -594,7 +594,8 @@ compute_distributive_range (tree type, value_range &op0_range, if (result_range) { range_op_handler op (code, type); - op.fold_range (*result_range, type, op0_range, op1_range); + if (!op.fold_range (*result_range, type, op0_range, op1_range)) + result_range->set_varying (type); } /* The distributive property guarantees that if TYPE is no narrower @@ -642,7 +643,8 @@ compute_distributive_range (tree type, value_range &op0_range, range_op_handler op (code, ssizetype); bool saved_flag_wrapv = flag_wrapv; flag_wrapv = 1; - op.fold_range (wide_range, ssizetype, op0_range, op1_range); + if (!op.fold_range (wide_range, ssizetype, op0_range, op1_range)) + wide_range.set_varying (ssizetype);; flag_wrapv = saved_flag_wrapv; if (wide_range.num_pairs () != 1 || !range_int_cst_p (&wide_range)) return false; diff --git a/gcc/tree-ssa-dom.cc b/gcc/tree-ssa-dom.cc index 513e0c8..84bef79 100644 --- a/gcc/tree-ssa-dom.cc +++ b/gcc/tree-ssa-dom.cc @@ -1227,29 +1227,30 @@ void dom_opt_dom_walker::set_global_ranges_from_unreachable_edges (basic_block bb) { edge pred_e = single_pred_edge_ignoring_loop_edges (bb, false); - if (!pred_e) return; gimple *stmt = last_stmt (pred_e->src); + if (!stmt + || gimple_code (stmt) != GIMPLE_COND + || !assert_unreachable_fallthru_edge_p (pred_e)) + return; + tree name; - if (stmt - && gimple_code (stmt) == GIMPLE_COND - && (name = gimple_cond_lhs (stmt)) - && TREE_CODE (name) == SSA_NAME - && assert_unreachable_fallthru_edge_p (pred_e) - && all_uses_feed_or_dominated_by_stmt (name, stmt)) - { - Value_Range r (TREE_TYPE (name)); + gori_compute &gori = m_ranger->gori (); + FOR_EACH_GORI_EXPORT_NAME (gori, pred_e->src, name) + if (all_uses_feed_or_dominated_by_stmt (name, stmt)) + { + Value_Range r (TREE_TYPE (name)); - if (m_ranger->range_on_edge (r, pred_e, name) - && !r.varying_p () - && !r.undefined_p ()) - { - set_range_info (name, r); - maybe_set_nonzero_bits (pred_e, name); - } - } + if (m_ranger->range_on_edge (r, pred_e, name) + && !r.varying_p () + && !r.undefined_p ()) + { + set_range_info (name, r); + maybe_set_nonzero_bits (pred_e, name); + } + } } /* Record any equivalences created by the incoming edge to BB into diff --git a/gcc/tree-ssa-dse.cc b/gcc/tree-ssa-dse.cc index 34cfd1a..2411ac7 100644 --- a/gcc/tree-ssa-dse.cc +++ b/gcc/tree-ssa-dse.cc @@ -18,6 +18,7 @@ along with GCC; see the file COPYING3. If not see <http://www.gnu.org/licenses/>. */ #include "config.h" +#define INCLUDE_MEMORY #include "system.h" #include "coretypes.h" #include "backend.h" @@ -45,6 +46,8 @@ along with GCC; see the file COPYING3. If not see #include "ipa-modref.h" #include "target.h" #include "tree-ssa-loop-niter.h" +#include "cfgloop.h" +#include "tree-data-ref.h" /* This file implements dead store elimination. @@ -937,6 +940,10 @@ contains_phi_arg (gphi *phi, tree arg) return false; } +/* Hash map of the memory use in a GIMPLE assignment to its + data reference. If NULL data-ref analysis isn't used. */ +static hash_map<gimple *, data_reference_p> *dse_stmt_to_dr_map; + /* A helper of dse_optimize_stmt. Given a GIMPLE_ASSIGN in STMT that writes to REF, classify it according to downstream uses and defs. Sets *BY_CLOBBER_P to true @@ -951,6 +958,8 @@ dse_classify_store (ao_ref *ref, gimple *stmt, gimple *temp; int cnt = 0; auto_bitmap visited; + std::unique_ptr<data_reference, void(*)(data_reference_p)> + dra (nullptr, free_data_ref); if (by_clobber_p) *by_clobber_p = true; @@ -1019,6 +1028,28 @@ dse_classify_store (ao_ref *ref, gimple *stmt, /* If the statement is a use the store is not dead. */ else if (ref_maybe_used_by_stmt_p (use_stmt, ref)) { + if (dse_stmt_to_dr_map + && ref->ref + && is_gimple_assign (use_stmt)) + { + if (!dra) + dra.reset (create_data_ref (NULL, NULL, ref->ref, stmt, + false, false)); + bool existed_p; + data_reference_p &drb + = dse_stmt_to_dr_map->get_or_insert (use_stmt, &existed_p); + if (!existed_p) + drb = create_data_ref (NULL, NULL, + gimple_assign_rhs1 (use_stmt), + use_stmt, false, false); + if (!dr_may_alias_p (dra.get (), drb, NULL)) + { + if (gimple_vdef (use_stmt)) + defs.safe_push (use_stmt); + continue; + } + } + /* Handle common cases where we can easily build an ao_ref structure for USE_STMT and in doing so we find that the references hit non-live bytes and thus can be ignored. @@ -1535,14 +1566,21 @@ class pass_dse : public gimple_opt_pass { public: pass_dse (gcc::context *ctxt) - : gimple_opt_pass (pass_data_dse, ctxt) + : gimple_opt_pass (pass_data_dse, ctxt), use_dr_analysis_p (false) {} /* opt_pass methods: */ opt_pass * clone () final override { return new pass_dse (m_ctxt); } + void set_pass_param (unsigned n, bool param) final override + { + gcc_assert (n == 0); + use_dr_analysis_p = param; + } bool gate (function *) final override { return flag_tree_dse != 0; } unsigned int execute (function *) final override; +private: + bool use_dr_analysis_p; }; // class pass_dse unsigned int @@ -1554,6 +1592,8 @@ pass_dse::execute (function *fun) need_eh_cleanup = BITMAP_ALLOC (NULL); need_ab_cleanup = BITMAP_ALLOC (NULL); auto_sbitmap live_bytes (param_dse_max_object_size); + if (flag_expensive_optimizations && use_dr_analysis_p) + dse_stmt_to_dr_map = new hash_map<gimple *, data_reference_p>; renumber_gimple_stmt_uids (fun); @@ -1644,6 +1684,15 @@ pass_dse::execute (function *fun) if (released_def) free_numbers_of_iterations_estimates (fun); + if (flag_expensive_optimizations && use_dr_analysis_p) + { + for (auto i = dse_stmt_to_dr_map->begin (); + i != dse_stmt_to_dr_map->end (); ++i) + free_data_ref ((*i).second); + delete dse_stmt_to_dr_map; + dse_stmt_to_dr_map = NULL; + } + return todo; } diff --git a/gcc/tree-ssa-sccvn.cc b/gcc/tree-ssa-sccvn.cc index 74b8d8d..2cc2c0e 100644 --- a/gcc/tree-ssa-sccvn.cc +++ b/gcc/tree-ssa-sccvn.cc @@ -1803,7 +1803,8 @@ struct vn_walk_cb_data vn_lookup_kind vn_walk_kind_, bool tbaa_p_, tree mask_, bool redundant_store_removal_p_) : vr (vr_), last_vuse_ptr (last_vuse_ptr_), last_vuse (NULL_TREE), - mask (mask_), masked_result (NULL_TREE), vn_walk_kind (vn_walk_kind_), + mask (mask_), masked_result (NULL_TREE), same_val (NULL_TREE), + vn_walk_kind (vn_walk_kind_), tbaa_p (tbaa_p_), redundant_store_removal_p (redundant_store_removal_p_), saved_operands (vNULL), first_set (-2), first_base_set (-2), known_ranges (NULL) @@ -1864,6 +1865,7 @@ struct vn_walk_cb_data tree last_vuse; tree mask; tree masked_result; + tree same_val; vn_lookup_kind vn_walk_kind; bool tbaa_p; bool redundant_store_removal_p; @@ -1902,6 +1904,8 @@ vn_walk_cb_data::finish (alias_set_type set, alias_set_type base_set, tree val) masked_result = val; return (void *) -1; } + if (same_val && !operand_equal_p (val, same_val)) + return (void *) -1; vec<vn_reference_op_s> &operands = saved_operands.exists () ? saved_operands : vr->operands; return vn_reference_lookup_or_insert_for_pieces (last_vuse, set, base_set, @@ -2675,36 +2679,61 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_, and return the found value. */ if (is_gimple_reg_type (TREE_TYPE (lhs)) && types_compatible_p (TREE_TYPE (lhs), vr->type) - && (ref->ref || data->orig_ref.ref)) - { - tree *saved_last_vuse_ptr = data->last_vuse_ptr; - /* Do not update last_vuse_ptr in vn_reference_lookup_2. */ - data->last_vuse_ptr = NULL; - tree saved_vuse = vr->vuse; - hashval_t saved_hashcode = vr->hashcode; - void *res = vn_reference_lookup_2 (ref, gimple_vuse (def_stmt), data); - /* Need to restore vr->vuse and vr->hashcode. */ - vr->vuse = saved_vuse; - vr->hashcode = saved_hashcode; - data->last_vuse_ptr = saved_last_vuse_ptr; - if (res && res != (void *)-1) + && (ref->ref || data->orig_ref.ref) + && !data->mask + && data->partial_defs.is_empty () + && multiple_p (get_object_alignment + (ref->ref ? ref->ref : data->orig_ref.ref), + ref->size) + && multiple_p (get_object_alignment (lhs), ref->size)) + { + tree rhs = gimple_assign_rhs1 (def_stmt); + /* ??? We may not compare to ahead values which might be from + a different loop iteration but only to loop invariants. Use + CONSTANT_CLASS_P (unvalueized!) as conservative approximation. + The one-hop lookup below doesn't have this issue since there's + a virtual PHI before we ever reach a backedge to cross. + We can skip multiple defs as long as they are from the same + value though. */ + if (data->same_val + && !operand_equal_p (data->same_val, rhs)) + ; + else if (CONSTANT_CLASS_P (rhs)) { - vn_reference_t vnresult = (vn_reference_t) res; - tree rhs = gimple_assign_rhs1 (def_stmt); - if (TREE_CODE (rhs) == SSA_NAME) - rhs = SSA_VAL (rhs); - if (vnresult->result - && operand_equal_p (vnresult->result, rhs, 0) - /* We have to honor our promise about union type punning - and also support arbitrary overlaps with - -fno-strict-aliasing. So simply resort to alignment to - rule out overlaps. Do this check last because it is - quite expensive compared to the hash-lookup above. */ - && multiple_p (get_object_alignment - (ref->ref ? ref->ref : data->orig_ref.ref), - ref->size) - && multiple_p (get_object_alignment (lhs), ref->size)) - return res; + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file, + "Skipping possible redundant definition "); + print_gimple_stmt (dump_file, def_stmt, 0); + } + /* Delay the actual compare of the values to the end of the walk + but do not update last_vuse from here. */ + data->last_vuse_ptr = NULL; + data->same_val = rhs; + return NULL; + } + else + { + tree *saved_last_vuse_ptr = data->last_vuse_ptr; + /* Do not update last_vuse_ptr in vn_reference_lookup_2. */ + data->last_vuse_ptr = NULL; + tree saved_vuse = vr->vuse; + hashval_t saved_hashcode = vr->hashcode; + void *res = vn_reference_lookup_2 (ref, gimple_vuse (def_stmt), + data); + /* Need to restore vr->vuse and vr->hashcode. */ + vr->vuse = saved_vuse; + vr->hashcode = saved_hashcode; + data->last_vuse_ptr = saved_last_vuse_ptr; + if (res && res != (void *)-1) + { + vn_reference_t vnresult = (vn_reference_t) res; + if (TREE_CODE (rhs) == SSA_NAME) + rhs = SSA_VAL (rhs); + if (vnresult->result + && operand_equal_p (vnresult->result, rhs, 0)) + return res; + } } } } @@ -3798,6 +3827,14 @@ vn_reference_lookup_pieces (tree vuse, alias_set_type set, if (ops_for_ref != shared_lookup_references) ops_for_ref.release (); gcc_checking_assert (vr1.operands == shared_lookup_references); + if (*vnresult + && data.same_val + && (!(*vnresult)->result + || !operand_equal_p ((*vnresult)->result, data.same_val))) + { + *vnresult = NULL; + return NULL_TREE; + } } if (*vnresult) @@ -3913,6 +3950,10 @@ vn_reference_lookup (tree op, tree vuse, vn_lookup_kind kind, if (wvnresult) { gcc_assert (mask == NULL_TREE); + if (data.same_val + && (!wvnresult->result + || !operand_equal_p (wvnresult->result, data.same_val))) + return NULL_TREE; if (vnresult) *vnresult = wvnresult; return wvnresult->result; @@ -4460,28 +4501,39 @@ vn_nary_op_insert_pieces (unsigned int length, enum tree_code code, return vn_nary_op_insert_into (vno1, valid_info->nary); } +/* Return whether we can track a predicate valid when PRED_E is executed. */ + +static bool +can_track_predicate_on_edge (edge pred_e) +{ + /* ??? As we are currently recording a basic-block index in + vn_pval.valid_dominated_by_p and using dominance for the + validity check we cannot track predicates on all edges. */ + if (single_pred_p (pred_e->dest)) + return true; + /* Never record for backedges. */ + if (pred_e->flags & EDGE_DFS_BACK) + return false; + /* When there's more than one predecessor we cannot track + predicate validity based on the destination block. The + exception is when all other incoming edges are backedges. */ + edge_iterator ei; + edge e; + int cnt = 0; + FOR_EACH_EDGE (e, ei, pred_e->dest->preds) + if (! dominated_by_p (CDI_DOMINATORS, e->src, e->dest)) + cnt++; + return cnt == 1; +} + static vn_nary_op_t vn_nary_op_insert_pieces_predicated (unsigned int length, enum tree_code code, tree type, tree *ops, tree result, unsigned int value_id, edge pred_e) { - /* ??? Currently tracking BBs. */ - if (! single_pred_p (pred_e->dest)) - { - /* Never record for backedges. */ - if (pred_e->flags & EDGE_DFS_BACK) - return NULL; - edge_iterator ei; - edge e; - int cnt = 0; - /* Ignore backedges. */ - FOR_EACH_EDGE (e, ei, pred_e->dest->preds) - if (! dominated_by_p (CDI_DOMINATORS, e->src, e->dest)) - cnt++; - if (cnt != 1) - return NULL; - } + if (!can_track_predicate_on_edge (pred_e)) + return NULL; if (dump_file && (dump_flags & TDF_DETAILS) /* ??? Fix dumping, but currently we only get comparisons. */ && TREE_CODE_CLASS (code) == tcc_comparison) diff --git a/gcc/tree-ssa-threadbackward.cc b/gcc/tree-ssa-threadbackward.cc index 9725f50..2a8cfa3 100644 --- a/gcc/tree-ssa-threadbackward.cc +++ b/gcc/tree-ssa-threadbackward.cc @@ -435,28 +435,14 @@ back_threader::find_paths_to_names (basic_block bb, bitmap interesting, } /* For other local defs process their uses, amending imports on the way. */ - else if (gassign *ass = dyn_cast <gassign *> (def_stmt)) + else { tree ssa[3]; - if (range_op_handler (ass)) - { - ssa[0] = gimple_range_ssa_p (gimple_range_operand1 (ass)); - ssa[1] = gimple_range_ssa_p (gimple_range_operand2 (ass)); - ssa[2] = NULL_TREE; - } - else if (gimple_assign_rhs_code (ass) == COND_EXPR) - { - ssa[0] = gimple_range_ssa_p (gimple_assign_rhs1 (ass)); - ssa[1] = gimple_range_ssa_p (gimple_assign_rhs2 (ass)); - ssa[2] = gimple_range_ssa_p (gimple_assign_rhs3 (ass)); - } - else - continue; - for (unsigned j = 0; j < 3; ++j) + unsigned lim = gimple_range_ssa_names (ssa, 3, def_stmt); + for (unsigned j = 0; j < lim; ++j) { tree rhs = ssa[j]; if (rhs - && TREE_CODE (rhs) == SSA_NAME && bitmap_set_bit (m_imports, SSA_NAME_VERSION (rhs))) { diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc index 9c434b6..aabdc6f 100644 --- a/gcc/tree-vect-loop.cc +++ b/gcc/tree-vect-loop.cc @@ -8356,8 +8356,11 @@ vect_create_nonlinear_iv_init (gimple_seq* stmts, tree init_expr, sel[2 * i + 1] = i + nunits; } vec_perm_indices indices (sel, 2, nunits); + /* Don't use vect_gen_perm_mask_checked since can_vec_perm_const_p may + fail when vec_init is const vector. In that situation vec_perm is not + really needed. */ tree perm_mask_even - = vect_gen_perm_mask_checked (vectype, indices); + = vect_gen_perm_mask_any (vectype, indices); vec_init = gimple_build (stmts, VEC_PERM_EXPR, vectype, vec_init, vec_neg, diff --git a/gcc/tree-vrp.cc b/gcc/tree-vrp.cc index c3030a1..93482e5 100644 --- a/gcc/tree-vrp.cc +++ b/gcc/tree-vrp.cc @@ -1069,7 +1069,8 @@ range_fold_binary_expr (value_range *vr, vr1.set_varying (expr_type); vr0.normalize_addresses (); vr1.normalize_addresses (); - op.fold_range (*vr, expr_type, vr0, vr1); + if (!op.fold_range (*vr, expr_type, vr0, vr1)) + vr->set_varying (expr_type); } /* Perform a unary operation on a range. */ @@ -1095,7 +1096,8 @@ range_fold_unary_expr (value_range *vr, value_range vr0_cst (*vr0); vr0_cst.normalize_addresses (); - op.fold_range (*vr, expr_type, vr0_cst, value_range (expr_type)); + if (!op.fold_range (*vr, expr_type, vr0_cst, value_range (expr_type))) + vr->set_varying (expr_type); } /* If the range of values taken by OP can be inferred after STMT executes, diff --git a/gcc/tsan.cc b/gcc/tsan.cc index 79d4582..2406527 100644 --- a/gcc/tsan.cc +++ b/gcc/tsan.cc @@ -620,15 +620,16 @@ instrument_builtin_call (gimple_stmt_iterator *gsi) maybe_clean_or_replace_eh_stmt (stmt, gsi_stmt (*gsi)); if (tsan_atomic_table[i].action == val_cas && lhs) { - tree cond; stmt = gsi_stmt (*gsi); - g = gimple_build_assign (make_ssa_name (TREE_TYPE (t)), t); + tree t2 = make_ssa_name (TREE_TYPE (t)); + g = gimple_build_assign (t2, t); gsi_insert_after (gsi, g, GSI_NEW_STMT); t = make_ssa_name (TREE_TYPE (TREE_TYPE (decl)), stmt); - cond = build2 (NE_EXPR, boolean_type_node, t, - build_int_cst (TREE_TYPE (t), 0)); - g = gimple_build_assign (lhs, COND_EXPR, cond, args[1], - gimple_assign_lhs (g)); + tree cond = make_ssa_name (boolean_type_node); + g = gimple_build_assign (cond, NE_EXPR, + t, build_zero_cst (TREE_TYPE (t))); + gsi_insert_after (gsi, g, GSI_NEW_STMT); + g = gimple_build_assign (lhs, COND_EXPR, cond, args[1], t2); gimple_call_set_lhs (stmt, t); update_stmt (stmt); gsi_insert_after (gsi, g, GSI_NEW_STMT); diff --git a/gcc/value-query.cc b/gcc/value-query.cc index 0bdd670..296784b 100644 --- a/gcc/value-query.cc +++ b/gcc/value-query.cc @@ -252,7 +252,8 @@ range_query::get_tree_range (vrange &r, tree expr, gimple *stmt) Value_Range r1 (TREE_TYPE (TREE_OPERAND (expr, 1))); range_of_expr (r0, TREE_OPERAND (expr, 0), stmt); range_of_expr (r1, TREE_OPERAND (expr, 1), stmt); - op.fold_range (r, type, r0, r1); + if (!op.fold_range (r, type, r0, r1)) + r.set_varying (type); } else r.set_varying (type); @@ -268,7 +269,8 @@ range_query::get_tree_range (vrange &r, tree expr, gimple *stmt) Value_Range r1 (type); r1.set_varying (type); range_of_expr (r0, TREE_OPERAND (expr, 0), stmt); - op.fold_range (r, type, r0, r1); + if (!op.fold_range (r, type, r0, r1)) + r.set_varying (type); } else r.set_varying (type); diff --git a/gcc/value-range-pretty-print.cc b/gcc/value-range-pretty-print.cc index eb74422..8cbe97b 100644 --- a/gcc/value-range-pretty-print.cc +++ b/gcc/value-range-pretty-print.cc @@ -117,6 +117,19 @@ vrange_printer::print_irange_bitmasks (const irange &r) const pp_string (pp, buf); } +void +vrange_printer::print_real_value (tree type, const REAL_VALUE_TYPE &r) const +{ + char s[100]; + real_to_decimal_for_mode (s, &r, sizeof (s), 0, 1, TYPE_MODE (type)); + pp_string (pp, s); + if (!DECIMAL_FLOAT_TYPE_P (type)) + { + real_to_hexadecimal (s, &r, sizeof (s), 0, 1); + pp_printf (pp, " (%s)", s); + } +} + // Print an frange. void @@ -141,11 +154,9 @@ vrange_printer::visit (const frange &r) const bool has_endpoints = !r.known_isnan (); if (has_endpoints) { - dump_generic_node (pp, - build_real (type, r.lower_bound ()), 0, TDF_NONE, false); + print_real_value (type, r.lower_bound ()); pp_string (pp, ", "); - dump_generic_node (pp, - build_real (type, r.upper_bound ()), 0, TDF_NONE, false); + print_real_value (type, r.upper_bound ()); } pp_character (pp, ']'); print_frange_nan (r); diff --git a/gcc/value-range-pretty-print.h b/gcc/value-range-pretty-print.h index 20c2659..a9ae5a7 100644 --- a/gcc/value-range-pretty-print.h +++ b/gcc/value-range-pretty-print.h @@ -32,6 +32,7 @@ private: void print_irange_bound (const wide_int &w, tree type) const; void print_irange_bitmasks (const irange &) const; void print_frange_nan (const frange &) const; + void print_real_value (tree type, const REAL_VALUE_TYPE &r) const; pretty_printer *pp; }; diff --git a/gcc/value-range.cc b/gcc/value-range.cc index a8e3bb3..754379a 100644 --- a/gcc/value-range.cc +++ b/gcc/value-range.cc @@ -258,15 +258,6 @@ frange::accept (const vrange_visitor &v) const v.visit (*this); } -// Helper function to compare floats. Returns TRUE if op1 .CODE. op2 -// is nonzero. - -static inline bool -tree_compare (tree_code code, tree op1, tree op2) -{ - return !integer_zerop (fold_build2 (code, integer_type_node, op1, op2)); -} - // Flush denormal endpoints to the appropriate 0.0. void @@ -290,7 +281,9 @@ frange::flush_denormals_to_zero () // Setter for franges. void -frange::set (tree min, tree max, value_range_kind kind) +frange::set (tree type, + const REAL_VALUE_TYPE &min, const REAL_VALUE_TYPE &max, + value_range_kind kind) { switch (kind) { @@ -299,7 +292,7 @@ frange::set (tree min, tree max, value_range_kind kind) return; case VR_VARYING: case VR_ANTI_RANGE: - set_varying (TREE_TYPE (min)); + set_varying (type); return; case VR_RANGE: break; @@ -308,20 +301,23 @@ frange::set (tree min, tree max, value_range_kind kind) } // Handle NANs. - if (real_isnan (TREE_REAL_CST_PTR (min)) || real_isnan (TREE_REAL_CST_PTR (max))) + if (real_isnan (&min) || real_isnan (&max)) { - gcc_checking_assert (real_identical (TREE_REAL_CST_PTR (min), - TREE_REAL_CST_PTR (max))); - tree type = TREE_TYPE (min); - bool sign = real_isneg (TREE_REAL_CST_PTR (min)); - set_nan (type, sign); + gcc_checking_assert (real_identical (&min, &max)); + if (HONOR_NANS (type)) + { + bool sign = real_isneg (&min); + set_nan (type, sign); + } + else + set_undefined (); return; } m_kind = kind; - m_type = TREE_TYPE (min); - m_min = *TREE_REAL_CST_PTR (min); - m_max = *TREE_REAL_CST_PTR (max); + m_type = type; + m_min = min; + m_max = max; if (HONOR_NANS (m_type)) { m_pos_nan = true; @@ -333,8 +329,20 @@ frange::set (tree min, tree max, value_range_kind kind) m_neg_nan = false; } + // For -ffinite-math-only we can drop ranges outside the + // representable numbers to min/max for the type. + if (flag_finite_math_only) + { + REAL_VALUE_TYPE min_repr = frange_val_min (m_type); + REAL_VALUE_TYPE max_repr = frange_val_max (m_type); + if (real_less (&m_min, &min_repr)) + m_min = min_repr; + if (real_less (&max_repr, &m_max)) + m_max = max_repr; + } + // Check for swapped ranges. - gcc_checking_assert (tree_compare (LE_EXPR, min, max)); + gcc_checking_assert (real_compare (LE_EXPR, &min, &max)); normalize_kind (); @@ -344,14 +352,11 @@ frange::set (tree min, tree max, value_range_kind kind) verify_range (); } -// Setter for frange from REAL_VALUE_TYPE endpoints. - void -frange::set (tree type, - const REAL_VALUE_TYPE &min, const REAL_VALUE_TYPE &max, - value_range_kind kind) +frange::set (tree min, tree max, value_range_kind kind) { - set (build_real (type, min), build_real (type, max), kind); + set (TREE_TYPE (min), + *TREE_REAL_CST_PTR (min), *TREE_REAL_CST_PTR (max), kind); } // Normalize range to VARYING or UNDEFINED, or vice versa. Return @@ -366,8 +371,8 @@ bool frange::normalize_kind () { if (m_kind == VR_RANGE - && real_isinf (&m_min, 1) - && real_isinf (&m_max, 0)) + && frange_val_is_min (m_min, m_type) + && frange_val_is_max (m_max, m_type)) { if (m_pos_nan && m_neg_nan) { @@ -380,8 +385,8 @@ frange::normalize_kind () if (!m_pos_nan || !m_neg_nan) { m_kind = VR_RANGE; - m_min = dconstninf; - m_max = dconstinf; + m_min = frange_val_min (m_type); + m_max = frange_val_max (m_type); return true; } } @@ -422,7 +427,7 @@ frange::combine_zeros (const frange &r, bool union_p) if (maybe_isnan ()) m_kind = VR_NAN; else - m_kind = VR_UNDEFINED; + set_undefined (); changed = true; } return changed; @@ -506,7 +511,7 @@ frange::intersect_nans (const frange &r) if (maybe_isnan ()) m_kind = VR_NAN; else - m_kind = VR_UNDEFINED; + set_undefined (); if (flag_checking) verify_range (); return true; @@ -558,7 +563,7 @@ frange::intersect (const vrange &v) if (maybe_isnan ()) m_kind = VR_NAN; else - m_kind = VR_UNDEFINED; + set_undefined (); if (flag_checking) verify_range (); return true; @@ -696,13 +701,13 @@ frange::verify_range () switch (m_kind) { case VR_UNDEFINED: - // m_type is ignored. + gcc_checking_assert (!m_type); return; case VR_VARYING: gcc_checking_assert (m_type); gcc_checking_assert (m_pos_nan && m_neg_nan); - gcc_checking_assert (real_isinf (&m_min, 1)); - gcc_checking_assert (real_isinf (&m_max, 0)); + gcc_checking_assert (frange_val_is_min (m_min, m_type)); + gcc_checking_assert (frange_val_is_max (m_max, m_type)); return; case VR_RANGE: gcc_checking_assert (m_type); @@ -727,7 +732,8 @@ frange::verify_range () // If all the properties are clear, we better not span the entire // domain, because that would make us varying. if (m_pos_nan && m_neg_nan) - gcc_checking_assert (!real_isinf (&m_min, 1) || !real_isinf (&m_max, 0)); + gcc_checking_assert (!frange_val_is_min (m_min, m_type) + || !frange_val_is_max (m_max, m_type)); } // We can't do much with nonzeros yet. @@ -774,7 +780,11 @@ frange::zero_p () const void frange::set_nonnegative (tree type) { - set (type, dconst0, dconstinf); + set (type, dconst0, frange_val_max (type)); + + // Set +NAN as the only possibility. + if (HONOR_NANS (type)) + update_nan (/*sign=*/0); } // Here we copy between any two irange's. The ranges can be legacy or @@ -3823,6 +3833,11 @@ range_tests_signed_zeros () r1.update_nan (); r0.intersect (r1); ASSERT_TRUE (r0.known_isnan ()); + + r0.set_nonnegative (float_type_node); + ASSERT_TRUE (r0.signbit_p (signbit) && !signbit); + if (HONOR_NANS (float_type_node)) + ASSERT_TRUE (r0.maybe_isnan ()); } static void @@ -3872,23 +3887,6 @@ range_tests_floats () r0.clear_nan (); ASSERT_FALSE (r0.varying_p ()); - // The endpoints of a VARYING are +-INF. - r0.set_varying (float_type_node); - ASSERT_TRUE (real_identical (&r0.lower_bound (), &dconstninf)); - ASSERT_TRUE (real_identical (&r0.upper_bound (), &dconstinf)); - - // The maximum representable range for a type is still a subset of VARYING. - REAL_VALUE_TYPE q, r; - real_min_representable (&q, float_type_node); - real_max_representable (&r, float_type_node); - r0 = frange (float_type_node, q, r); - // r0 is not a varying, because it does not include -INF/+INF. - ASSERT_FALSE (r0.varying_p ()); - // The upper bound of r0 must be less than +INF. - ASSERT_TRUE (real_less (&r0.upper_bound (), &dconstinf)); - // The lower bound of r0 must be greater than -INF. - ASSERT_TRUE (real_less (&dconstninf, &r0.lower_bound ())); - // For most architectures, where float and double are different // sizes, having the same endpoints does not necessarily mean the // ranges are equal. diff --git a/gcc/value-range.h b/gcc/value-range.h index 795b1f0..413e54b 100644 --- a/gcc/value-range.h +++ b/gcc/value-range.h @@ -312,6 +312,7 @@ public: const REAL_VALUE_TYPE &lower_bound () const; const REAL_VALUE_TYPE &upper_bound () const; void update_nan (); + void update_nan (bool sign); void clear_nan (); // fpclassify like API @@ -592,6 +593,8 @@ extern void dump_value_range (FILE *, const vrange *); extern bool vrp_val_is_min (const_tree); extern bool vrp_val_is_max (const_tree); extern bool vrp_operand_equal_p (const_tree, const_tree); +inline REAL_VALUE_TYPE frange_val_min (const_tree type); +inline REAL_VALUE_TYPE frange_val_max (const_tree type); inline value_range_kind vrange::kind () const @@ -1008,7 +1011,10 @@ vrp_val_max (const_tree type) return wide_int_to_tree (const_cast<tree> (type), max); } if (frange::supports_p (type)) - return build_real (const_cast <tree> (type), dconstinf); + { + REAL_VALUE_TYPE r = frange_val_max (type); + return build_real (const_cast <tree> (type), r); + } return NULL_TREE; } @@ -1022,7 +1028,10 @@ vrp_val_min (const_tree type) if (POINTER_TYPE_P (type)) return build_zero_cst (const_cast<tree> (type)); if (frange::supports_p (type)) - return build_real (const_cast <tree> (type), dconstninf); + { + REAL_VALUE_TYPE r = frange_val_min (type); + return build_real (const_cast <tree> (type), r); + } return NULL_TREE; } @@ -1072,8 +1081,8 @@ frange::set_varying (tree type) { m_kind = VR_VARYING; m_type = type; - m_min = dconstninf; - m_max = dconstinf; + m_min = frange_val_min (type); + m_max = frange_val_max (type); m_pos_nan = true; m_neg_nan = true; } @@ -1082,6 +1091,10 @@ inline void frange::set_undefined () { m_kind = VR_UNDEFINED; + m_type = NULL; + m_pos_nan = false; + m_neg_nan = false; + // m_min and m_min are unitialized as they are REAL_VALUE_TYPE ??. if (flag_checking) verify_range (); } @@ -1099,6 +1112,19 @@ frange::update_nan () verify_range (); } +// Like above, but set the sign of the NAN. + +inline void +frange::update_nan (bool sign) +{ + gcc_checking_assert (!undefined_p ()); + m_pos_nan = !sign; + m_neg_nan = sign; + normalize_kind (); + if (flag_checking) + verify_range (); +} + // Clear the NAN bit and adjust the range. inline void @@ -1114,23 +1140,66 @@ frange::clear_nan () // Set R to maximum representable value for TYPE. -inline void -real_max_representable (REAL_VALUE_TYPE *r, tree type) +inline REAL_VALUE_TYPE +real_max_representable (const_tree type) { + REAL_VALUE_TYPE r; char buf[128]; get_max_float (REAL_MODE_FORMAT (TYPE_MODE (type)), buf, sizeof (buf), false); - int res = real_from_string (r, buf); + int res = real_from_string (&r, buf); gcc_checking_assert (!res); + return r; } -// Set R to minimum representable value for TYPE. +// Return the minimum representable value for TYPE. -inline void -real_min_representable (REAL_VALUE_TYPE *r, tree type) +inline REAL_VALUE_TYPE +real_min_representable (const_tree type) { - real_max_representable (r, type); - *r = real_value_negate (r); + REAL_VALUE_TYPE r = real_max_representable (type); + r = real_value_negate (&r); + return r; +} + +// Return the minimum value for TYPE. + +inline REAL_VALUE_TYPE +frange_val_min (const_tree type) +{ + if (flag_finite_math_only) + return real_min_representable (type); + else + return dconstninf; +} + +// Return the maximum value for TYPE. + +inline REAL_VALUE_TYPE +frange_val_max (const_tree type) +{ + if (flag_finite_math_only) + return real_max_representable (type); + else + return dconstinf; +} + +// Return TRUE if R is the minimum value for TYPE. + +inline bool +frange_val_is_min (const REAL_VALUE_TYPE &r, const_tree type) +{ + REAL_VALUE_TYPE min = frange_val_min (type); + return real_identical (&min, &r); +} + +// Return TRUE if R is the max value for TYPE. + +inline bool +frange_val_is_max (const REAL_VALUE_TYPE &r, const_tree type) +{ + REAL_VALUE_TYPE max = frange_val_max (type); + return real_identical (&max, &r); } // Build a signless NAN of type TYPE. @@ -1196,6 +1265,8 @@ frange::known_isinf () const inline bool frange::maybe_isnan () const { + if (undefined_p ()) + return false; return m_pos_nan || m_neg_nan; } diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index 7c434c9..9ebfaa0 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,10 @@ +2022-09-22 Thomas Neumann <tneumann@users.sourceforge.net> + + * unwind-dw2-fde.c: (release_register_frames) Remember + when the btree has been destroyed. + (__deregister_frame_info_bases) Disable the assert when + shutting down. + 2022-09-18 Thomas Neumann <tneumann@users.sourceforge.net> * unwind-dw2-fde.c: Replace uintptr_t with typedef diff --git a/libgcc/unwind-dw2-fde.c b/libgcc/unwind-dw2-fde.c index 919abfe..3c0cc65 100644 --- a/libgcc/unwind-dw2-fde.c +++ b/libgcc/unwind-dw2-fde.c @@ -48,15 +48,17 @@ typedef __UINTPTR_TYPE__ uintptr_type; #include "unwind-dw2-btree.h" static struct btree registered_frames; +static bool in_shutdown; static void -release_registered_frames (void) __attribute__ ((destructor (110))); +release_registered_frames (void) __attribute__ ((destructor)); static void release_registered_frames (void) { /* Release the b-tree and all frames. Frame releases that happen later are * silently ignored */ btree_destroy (®istered_frames); + in_shutdown = true; } static void @@ -65,6 +67,8 @@ static void init_object (struct object *ob); #else +/* Without fast path frame deregistration must always succeed. */ +static const int in_shutdown = 0; /* The unseen_objects list contains objects that have been registered but not yet categorized in any way. The seen_objects list has had @@ -282,7 +286,7 @@ __deregister_frame_info_bases (const void *begin) __gthread_mutex_unlock (&object_mutex); #endif - gcc_assert (ob); + gcc_assert (in_shutdown || ob); return (void *) ob; } diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog index fab472e..864bf6a 100644 --- a/libgfortran/ChangeLog +++ b/libgfortran/ChangeLog @@ -1,3 +1,13 @@ +2022-09-21 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> + + * ieee/ieee_arithmetic.F90 (IEEE_SET_ROUNDING_MODE): Handle + RADIX argument better. + +2022-09-21 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> + + * gfortran.map: Add symbols for IEEE_GET_MODES + and IEEE_SET_MODES. + 2022-09-19 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> * ieee/ieee_exceptions.F90: Add IEEE_MODES_TYPE, IEEE_GET_MODES diff --git a/libgfortran/gfortran.map b/libgfortran/gfortran.map index e0e795c..db9b86c 100644 --- a/libgfortran/gfortran.map +++ b/libgfortran/gfortran.map @@ -1759,3 +1759,9 @@ GFORTRAN_12 { _gfortran_transfer_real128_write; #endif } GFORTRAN_10.2; + +GFORTRAN_13 { + global: + __ieee_exceptions_MOD_ieee_get_modes; + __ieee_exceptions_MOD_ieee_set_modes; +} GFORTRAN_12; diff --git a/libgfortran/ieee/ieee_arithmetic.F90 b/libgfortran/ieee/ieee_arithmetic.F90 index ce30e4a..4c8e3bb 100644 --- a/libgfortran/ieee/ieee_arithmetic.F90 +++ b/libgfortran/ieee/ieee_arithmetic.F90 @@ -816,7 +816,7 @@ REM_MACRO(4,4,4) IEEE_SUPPORT_ROUNDING_NOARG end interface public :: IEEE_SUPPORT_ROUNDING - + ! Interface to the FPU-specific function interface pure integer function support_rounding_helper(flag) & @@ -839,7 +839,7 @@ REM_MACRO(4,4,4) IEEE_SUPPORT_UNDERFLOW_CONTROL_NOARG end interface public :: IEEE_SUPPORT_UNDERFLOW_CONTROL - + ! Interface to the FPU-specific function interface pure integer function support_underflow_control_helper(kind) & @@ -1074,7 +1074,13 @@ contains integer, value :: val end subroutine end interface - + + ! We do not support RADIX = 10, and such calls should not + ! modify the binary rounding mode. + if (present(RADIX)) then + if (RADIX == 10) return + end if + call helper(ROUND_VALUE%hidden) end subroutine diff --git a/libgo/go/cmd/cgo/gcc.go b/libgo/go/cmd/cgo/gcc.go index 0239149..e786aea 100644 --- a/libgo/go/cmd/cgo/gcc.go +++ b/libgo/go/cmd/cgo/gcc.go @@ -132,12 +132,11 @@ func (p *Package) addToFlag(flag string, args []string) { // // For example, the following string: // -// `a b:"c d" 'e''f' "g\""` +// `a b:"c d" 'e''f' "g\""` // // Would be parsed as: // -// []string{"a", "b:c d", "ef", `g"`} -// +// []string{"a", "b:c d", "ef", `g"`} func splitQuoted(s string) (r []string, err error) { var args []string arg := make([]rune, len(s)) @@ -1156,13 +1155,19 @@ func (p *Package) mangle(f *File, arg *ast.Expr, addPosition bool) (ast.Expr, bo // checkIndex checks whether arg has the form &a[i], possibly inside // type conversions. If so, then in the general case it writes -// _cgoIndexNN := a -// _cgoNN := &cgoIndexNN[i] // with type conversions, if any +// +// _cgoIndexNN := a +// _cgoNN := &cgoIndexNN[i] // with type conversions, if any +// // to sb, and writes -// _cgoCheckPointer(_cgoNN, _cgoIndexNN) +// +// _cgoCheckPointer(_cgoNN, _cgoIndexNN) +// // to sbCheck, and returns true. If a is a simple variable or field reference, // it writes -// _cgoIndexNN := &a +// +// _cgoIndexNN := &a +// // and dereferences the uses of _cgoIndexNN. Taking the address avoids // making a copy of an array. // @@ -1210,10 +1215,14 @@ func (p *Package) checkIndex(sb, sbCheck *bytes.Buffer, arg ast.Expr, i int) boo // checkAddr checks whether arg has the form &x, possibly inside type // conversions. If so, it writes -// _cgoBaseNN := &x -// _cgoNN := _cgoBaseNN // with type conversions, if any +// +// _cgoBaseNN := &x +// _cgoNN := _cgoBaseNN // with type conversions, if any +// // to sb, and writes -// _cgoCheckPointer(_cgoBaseNN, true) +// +// _cgoCheckPointer(_cgoBaseNN, true) +// // to sbCheck, and returns true. This tells _cgoCheckPointer to check // just the contents of the pointer being passed, not any other part // of the memory allocation. This is run after checkIndex, which looks @@ -2131,8 +2140,8 @@ type typeConv struct { // Type names X for which there exists an XGetTypeID function with type func() CFTypeID. getTypeIDs map[string]bool - // badStructs contains C structs that should be marked NotInHeap. - notInHeapStructs map[string]bool + // incompleteStructs contains C structs that should be marked Incomplete. + incompleteStructs map[string]bool // Predeclared types. bool ast.Expr @@ -2145,7 +2154,6 @@ type typeConv struct { string ast.Expr goVoid ast.Expr // _Ctype_void, denotes C's void goVoidPtr ast.Expr // unsafe.Pointer or *byte - goVoidPtrNoHeap ast.Expr // *_Ctype_void_notinheap, like goVoidPtr but marked NotInHeap ptrSize int64 intSize int64 @@ -2169,7 +2177,7 @@ func (c *typeConv) Init(ptrSize, intSize int64) { c.m = make(map[string]*Type) c.ptrs = make(map[string][]*Type) c.getTypeIDs = make(map[string]bool) - c.notInHeapStructs = make(map[string]bool) + c.incompleteStructs = make(map[string]bool) c.bool = c.Ident("bool") c.byte = c.Ident("byte") c.int8 = c.Ident("int8") @@ -2188,7 +2196,6 @@ func (c *typeConv) Init(ptrSize, intSize int64) { c.void = c.Ident("void") c.string = c.Ident("string") c.goVoid = c.Ident("_Ctype_void") - c.goVoidPtrNoHeap = c.Ident("*_Ctype_void_notinheap") // Normally cgo translates void* to unsafe.Pointer, // but for historical reasons -godefs uses *byte instead. @@ -2531,19 +2538,13 @@ func (c *typeConv) loadType(dtype dwarf.Type, pos token.Pos, parent string) *Typ // other than try to determine a Go representation. tt := *t tt.C = &TypeRepr{"%s %s", []interface{}{dt.Kind, tag}} - tt.Go = c.Ident("struct{}") - if dt.Kind == "struct" { - // We don't know what the representation of this struct is, so don't let - // anyone allocate one on the Go side. As a side effect of this annotation, - // pointers to this type will not be considered pointers in Go. They won't - // get writebarrier-ed or adjusted during a stack copy. This should handle - // all the cases badPointerTypedef used to handle, but hopefully will - // continue to work going forward without any more need for cgo changes. - tt.NotInHeap = true - // TODO: we should probably do the same for unions. Unions can't live - // on the Go heap, right? It currently doesn't work for unions because - // they are defined as a type alias for struct{}, not a defined type. - } + // We don't know what the representation of this struct is, so don't let + // anyone allocate one on the Go side. As a side effect of this annotation, + // pointers to this type will not be considered pointers in Go. They won't + // get writebarrier-ed or adjusted during a stack copy. This should handle + // all the cases badPointerTypedef used to handle, but hopefully will + // continue to work going forward without any more need for cgo changes. + tt.Go = c.Ident("_cgopackage.Incomplete") typedef[name.Name] = &tt break } @@ -2569,7 +2570,9 @@ func (c *typeConv) loadType(dtype dwarf.Type, pos token.Pos, parent string) *Typ tt.C = &TypeRepr{"struct %s", []interface{}{tag}} } tt.Go = g - tt.NotInHeap = c.notInHeapStructs[tag] + if c.incompleteStructs[tag] { + tt.Go = c.Ident("_cgopackage.Incomplete") + } typedef[name.Name] = &tt } @@ -2614,9 +2617,9 @@ func (c *typeConv) loadType(dtype dwarf.Type, pos token.Pos, parent string) *Typ } } if c.badVoidPointerTypedef(dt) { - // Treat this typedef as a pointer to a NotInHeap void. + // Treat this typedef as a pointer to a _cgopackage.Incomplete. s := *sub - s.Go = c.goVoidPtrNoHeap + s.Go = c.Ident("*_cgopackage.Incomplete") sub = &s // Make sure we update any previously computed type. if oldType := typedef[name.Name]; oldType != nil { @@ -2624,22 +2627,21 @@ func (c *typeConv) loadType(dtype dwarf.Type, pos token.Pos, parent string) *Typ } } // Check for non-pointer "struct <tag>{...}; typedef struct <tag> *<name>" - // typedefs that should be marked NotInHeap. + // typedefs that should be marked Incomplete. if ptr, ok := dt.Type.(*dwarf.PtrType); ok { if strct, ok := ptr.Type.(*dwarf.StructType); ok { if c.badStructPointerTypedef(dt.Name, strct) { - c.notInHeapStructs[strct.StructName] = true + c.incompleteStructs[strct.StructName] = true // Make sure we update any previously computed type. name := "_Ctype_struct_" + strct.StructName if oldType := typedef[name]; oldType != nil { - oldType.NotInHeap = true + oldType.Go = c.Ident("_cgopackage.Incomplete") } } } } t.Go = name t.BadPointer = sub.BadPointer - t.NotInHeap = sub.NotInHeap if unionWithPointer[sub.Go] { unionWithPointer[t.Go] = true } @@ -2650,7 +2652,6 @@ func (c *typeConv) loadType(dtype dwarf.Type, pos token.Pos, parent string) *Typ tt := *t tt.Go = sub.Go tt.BadPointer = sub.BadPointer - tt.NotInHeap = sub.NotInHeap typedef[name.Name] = &tt } @@ -3174,7 +3175,7 @@ func (c *typeConv) anonymousStructTypedef(dt *dwarf.TypedefType) bool { // non-pointers in this type. // TODO: Currently our best solution is to find these manually and list them as // they come up. A better solution is desired. -// Note: DEPRECATED. There is now a better solution. Search for NotInHeap in this file. +// Note: DEPRECATED. There is now a better solution. Search for _cgopackage.Incomplete in this file. func (c *typeConv) badPointerTypedef(dt *dwarf.TypedefType) bool { if c.badCFType(dt) { return true @@ -3188,7 +3189,7 @@ func (c *typeConv) badPointerTypedef(dt *dwarf.TypedefType) bool { return false } -// badVoidPointerTypedef is like badPointerTypeDef, but for "void *" typedefs that should be NotInHeap. +// badVoidPointerTypedef is like badPointerTypeDef, but for "void *" typedefs that should be _cgopackage.Incomplete. func (c *typeConv) badVoidPointerTypedef(dt *dwarf.TypedefType) bool { // Match the Windows HANDLE type (#42018). if goos != "windows" || dt.Name != "HANDLE" { diff --git a/libgo/go/cmd/cgo/main.go b/libgo/go/cmd/cgo/main.go index 58477e4..186aef0 100644 --- a/libgo/go/cmd/cgo/main.go +++ b/libgo/go/cmd/cgo/main.go @@ -153,7 +153,6 @@ type Type struct { EnumValues map[string]int64 Typedef string BadPointer bool // this pointer type should be represented as a uintptr (deprecated) - NotInHeap bool // this type should have a go:notinheap annotation } // A FuncType collects information about a function type in both the C and Go worlds. diff --git a/libgo/go/cmd/cgo/out.go b/libgo/go/cmd/cgo/out.go index 8d1eb5b..9ed88b8 100644 --- a/libgo/go/cmd/cgo/out.go +++ b/libgo/go/cmd/cgo/out.go @@ -85,11 +85,14 @@ func (p *Package) writeDefs() { fmt.Fprintf(fgo2, "// Code generated by cmd/cgo; DO NOT EDIT.\n\n") fmt.Fprintf(fgo2, "package %s\n\n", p.PackageName) fmt.Fprintf(fgo2, "import \"unsafe\"\n\n") - if !*gccgo && *importRuntimeCgo { - fmt.Fprintf(fgo2, "import _ \"runtime/cgo\"\n\n") - } if *importSyscall { fmt.Fprintf(fgo2, "import \"syscall\"\n\n") + } + if *importRuntimeCgo { + fmt.Fprintf(fgo2, "import _cgopackage \"runtime/cgo\"\n\n") + fmt.Fprintf(fgo2, "type _ _cgopackage.Incomplete\n") // prevent import-not-used error + } + if *importSyscall { fmt.Fprintf(fgo2, "var _ syscall.Errno\n") } fmt.Fprintf(fgo2, "func _Cgo_ptr(ptr unsafe.Pointer) unsafe.Pointer { return ptr }\n\n") @@ -113,9 +116,6 @@ func (p *Package) writeDefs() { sort.Strings(typedefNames) for _, name := range typedefNames { def := typedef[name] - if def.NotInHeap { - fmt.Fprintf(fgo2, "//go:notinheap\n") - } fmt.Fprintf(fgo2, "type %s ", name) // We don't have source info for these types, so write them out without source info. // Otherwise types would look like: @@ -140,7 +140,6 @@ func (p *Package) writeDefs() { fmt.Fprintf(fgo2, "%s", buf.Bytes()) fmt.Fprintf(fgo2, "\n\n") } - fmt.Fprintf(fgo2, "//go:notinheap\ntype _Ctype_void_notinheap struct{}\n\n") if *gccgo { fmt.Fprintf(fgo2, "type _Ctype_void byte\n") } else { diff --git a/libgo/go/cmd/go/internal/load/pkg.go b/libgo/go/cmd/go/internal/load/pkg.go index 44bd61c..9c5c0a1 100644 --- a/libgo/go/cmd/go/internal/load/pkg.go +++ b/libgo/go/cmd/go/internal/load/pkg.go @@ -1818,7 +1818,7 @@ func (p *Package) load(ctx context.Context, opts PackageOpts, path string, stk * if p.UsesCgo() { addImport("unsafe", true) } - if p.UsesCgo() && (!p.Standard || !cgoExclude[p.ImportPath]) && cfg.BuildContext.Compiler != "gccgo" { + if p.UsesCgo() && (!p.Standard || !cgoExclude[p.ImportPath]) { addImport("runtime/cgo", true) } if p.UsesCgo() && (!p.Standard || !cgoSyscallExclude[p.ImportPath]) { @@ -1828,9 +1828,7 @@ func (p *Package) load(ctx context.Context, opts PackageOpts, path string, stk * // SWIG adds imports of some standard packages. if p.UsesSwig() { addImport("unsafe", true) - if cfg.BuildContext.Compiler != "gccgo" { - addImport("runtime/cgo", true) - } + addImport("runtime/cgo", true) addImport("syscall", true) addImport("sync", true) @@ -2455,7 +2453,7 @@ func LinkerDeps(p *Package) []string { deps := []string{"runtime"} // External linking mode forces an import of runtime/cgo. - if externalLinkingForced(p) && cfg.BuildContext.Compiler != "gccgo" { + if externalLinkingForced(p) { deps = append(deps, "runtime/cgo") } // On ARM with GOARM=5, it forces an import of math, for soft floating point. diff --git a/libgo/go/runtime/cgo/cgo.go b/libgo/go/runtime/cgo/cgo.go new file mode 100644 index 0000000..5921435 --- /dev/null +++ b/libgo/go/runtime/cgo/cgo.go @@ -0,0 +1,18 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* +Package cgo contains runtime support for code generated +by the cgo tool. See the documentation for the cgo command +for details on using cgo. +*/ +package cgo + +// Incomplete is used specifically for the semantics of incomplete C types. +// +//go:notinheap +type Incomplete struct { + // _ sys.NotInHeap + _ struct{ _ struct{} } +} diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog index d3b4758..a5830a4 100644 --- a/libgomp/ChangeLog +++ b/libgomp/ChangeLog @@ -1,3 +1,8 @@ +2022-09-24 Jakub Jelinek <jakub@redhat.com> + + PR c/106981 + * testsuite/libgomp.c-c++-common/pr106981.c: New test. + 2022-09-14 Julian Brown <julian@codesourcery.com> * testsuite/libgomp.oacc-c-c++-common/deep-copy-15.c: New test. diff --git a/libgomp/testsuite/libgomp.c-c++-common/pr106981.c b/libgomp/testsuite/libgomp.c-c++-common/pr106981.c new file mode 100644 index 0000000..ed48d27 --- /dev/null +++ b/libgomp/testsuite/libgomp.c-c++-common/pr106981.c @@ -0,0 +1,19 @@ +/* PR c/106981 */ + +int +main () +{ + int a[0x101]; + unsigned int b = 0x100; + if ((unsigned char) b || (unsigned short) b != 0x100) + return 0; + a[0] = 0; + a[0x100] = 42; + #pragma omp atomic update + a[(unsigned char) b] = a[(unsigned short) b] + a[(unsigned char) b]; + #pragma omp atomic update + a[(unsigned char) b] = a[(unsigned char) b] + a[(unsigned short) b]; + if (a[0] != 84 || a[0x100] != 42) + __builtin_abort (); + return 0; +} diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog index 736288f..f537372 100644 --- a/libiberty/ChangeLog +++ b/libiberty/ChangeLog @@ -1,3 +1,7 @@ +2022-09-22 Jonathan Wakely <jwakely@redhat.com> + + * README: Replace gcc-bugs email address with Bugzilla URL. + 2022-08-25 Martin Liska <mliska@suse.cz> * configure: Regenerate. diff --git a/libiberty/README b/libiberty/README index 9f1cc97..e7ffb17 100644 --- a/libiberty/README +++ b/libiberty/README @@ -15,7 +15,7 @@ The library must be configured from the top source directory. Don't try to run configure in this directory. Follow the configuration instructions in ../README. -Please report bugs to "gcc-bugs@gcc.gnu.org" and send fixes to +Please report bugs to https://gcc.gnu.org/bugzilla/ and send fixes to "gcc-patches@gcc.gnu.org". Thank you. ADDING A NEW FILE diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index a55293e..e6722cf 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,207 @@ +2022-09-24 Jonathan Wakely <jwakely@redhat.com> + + * include/bits/alloc_traits.h (allocator_traits::is_always_equal): + Only instantiate is_empty if needed. + * include/bits/ptr_traits.h (__ptr_traits_impl::difference_type) + (__ptr_traits_impl::rebind): Use __detected_or. + * include/experimental/type_traits (is_same_v): Add a partial + specialization instead of instantiating the std::is_same class + template. + (detected_t): Redefine in terms of detected_or_t. + (is_detected, is_detected_v): Redefine in terms of detected_t. + * include/std/type_traits [__cpp_concepts] (__detected_or): Add + new definition using concepts. + (__detector::value_t): Rename to __is_detected. + * testsuite/17_intro/names.cc: Check value_t isn't used. + +2022-09-23 Jonathan Wakely <jwakely@redhat.com> + + * testsuite/20_util/is_assignable/requirements/access.cc: + New test. + +2022-09-23 Jonathan Wakely <jwakely@redhat.com> + + PR libstdc++/91456 + * include/std/type_traits (__is_nothrow_invocable_lib): Remove. + (__is_invocable_impl::__nothrow_type): New member type which + checks if the conversion can throw. + (__is_nt_invocable_impl): Replace class template with alias + template to __is_nt_invocable_impl::__nothrow_type. + * testsuite/20_util/is_nothrow_invocable/91456.cc: New test. + * testsuite/20_util/is_nothrow_convertible/value.cc: Remove + macro used by value_ext.cc test. + * testsuite/20_util/is_nothrow_convertible/value_ext.cc: Remove + test for non-standard __is_nothrow_invocable_lib trait. + +2022-09-23 Marek Polacek <polacek@redhat.com> + + PR c++/106784 + * include/std/type_traits: Rename __is_nothrow_convertible to + __is_nothrow_convertible_lib. + * testsuite/20_util/is_nothrow_convertible/value_ext.cc: Likewise. + +2022-09-23 Jonathan Wakely <jwakely@redhat.com> + + * include/std/bitset (operator>>): Do not copy for N==0. + * testsuite/20_util/bitset/io/input.cc: Add comment. + +2022-09-23 Jonathan Wakely <jwakely@redhat.com> + + * include/debug/bitset (__debug::bitset): Add constexpr to all + member functions. + (operator&, operator|, operator^): Add inline and constexpr. + (operator>>, operator<<): Add inline. + * testsuite/20_util/bitset/access/constexpr.cc: Only check using + constexpr std::string for the cxx11 ABI. + * testsuite/20_util/bitset/cons/constexpr_c++23.cc: Likewise. + * testsuite/20_util/headers/bitset/synopsis.cc: Check constexpr + for C++23. + +2022-09-23 Jonathan Wakely <jwakely@redhat.com> + + * include/std/bitset (bitset::_M_copy_to_string): Find set bits + instead of iterating over individual bits. + +2022-09-22 Jonathan Wakely <jwakely@redhat.com> + + * include/std/bitset (bitset): Add constexpr for C++23. Guard + members using std::string with _GLIBCXX_HOSTED. + * include/std/version (__cpp_lib_constexpr_bitset): Define. + * testsuite/20_util/bitset/access/constexpr.cc: New test. + * testsuite/20_util/bitset/cons/constexpr_c++23.cc: New test. + * testsuite/20_util/bitset/count/constexpr.cc: New test. + * testsuite/20_util/bitset/ext/constexpr.cc: New test. + * testsuite/20_util/bitset/operations/constexpr_c++23.cc: New test. + * testsuite/20_util/bitset/version.cc: New test. + +2022-09-22 Jonathan Wakely <jwakely@redhat.com> + + * testsuite/23_containers/bitset/18604.cc: Moved to... + * testsuite/20_util/bitset/18604.cc: ...here. + * testsuite/23_containers/bitset/45713.cc: Moved to... + * testsuite/20_util/bitset/45713.cc: ...here. + * testsuite/23_containers/bitset/to_string/dr396.cc: Moved to... + * testsuite/20_util/bitset/access/dr396.cc: ...here. + * testsuite/23_containers/bitset/to_string/1.cc: Moved to... + * testsuite/20_util/bitset/access/to_string.cc: ...here. + * testsuite/23_containers/bitset/to_ullong/1.cc: Moved to... + * testsuite/20_util/bitset/access/to_ullong.cc: ...here. + * testsuite/23_containers/bitset/to_ulong/1.cc: Moved to... + * testsuite/20_util/bitset/access/to_ulong.cc: ...here. + * testsuite/23_containers/bitset/cons/1.cc: Moved to... + * testsuite/20_util/bitset/cons/1.cc: ...here. + * testsuite/23_containers/bitset/cons/16020.cc: Moved to... + * testsuite/20_util/bitset/cons/16020.cc: ...here. + * testsuite/23_containers/bitset/cons/2.cc: Moved to... + * testsuite/20_util/bitset/cons/2.cc: ...here. + * testsuite/23_containers/bitset/cons/3.cc: Moved to... + * testsuite/20_util/bitset/cons/3.cc: ...here. + * testsuite/23_containers/bitset/cons/38244.cc: Moved to... + * testsuite/20_util/bitset/cons/38244.cc: ...here. + * testsuite/23_containers/bitset/cons/50268.cc: Moved to... + * testsuite/20_util/bitset/cons/50268.cc: ...here. + * testsuite/23_containers/bitset/cons/6282.cc: Moved to... + * testsuite/20_util/bitset/cons/6282.cc: ...here. + * testsuite/23_containers/bitset/cons/constexpr.cc: Moved to... + * testsuite/20_util/bitset/cons/constexpr.cc: ...here. + * testsuite/23_containers/bitset/cons/dr1325-1.cc: Moved to... + * testsuite/20_util/bitset/cons/dr1325-1.cc: ...here. + * testsuite/23_containers/bitset/cons/dr1325-2.cc: Moved to... + * testsuite/20_util/bitset/cons/dr1325-2.cc: ...here. + * testsuite/23_containers/bitset/cons/dr396.cc: Moved to... + * testsuite/20_util/bitset/cons/dr396.cc: ...here. + * testsuite/23_containers/bitset/debug/invalidation/1.cc: Moved to... + * testsuite/20_util/bitset/debug/invalidation/1.cc: ...here. + * testsuite/23_containers/bitset/ext/15361.cc: Moved to... + * testsuite/20_util/bitset/ext/15361.cc: ...here. + * testsuite/23_containers/bitset/hash/1.cc: Moved to... + * testsuite/20_util/bitset/hash/1.cc: ...here. + * testsuite/23_containers/bitset/input/1.cc: Moved to... + * testsuite/20_util/bitset/io/input.cc: ...here. + * testsuite/23_containers/bitset/count/6124.cc: Moved to... + * testsuite/20_util/bitset/observers/6124.cc: ...here. + * testsuite/23_containers/bitset/all/1.cc: Moved to... + * testsuite/20_util/bitset/observers/all.cc: ...here. + * testsuite/23_containers/bitset/test/1.cc: Moved to... + * testsuite/20_util/bitset/observers/test.cc: ...here. + * testsuite/23_containers/bitset/operations/1.cc: Moved to... + * testsuite/20_util/bitset/operations/1.cc: ...here. + * testsuite/23_containers/bitset/operations/13838.cc: Moved to... + * testsuite/20_util/bitset/operations/13838.cc: ...here. + * testsuite/23_containers/bitset/operations/2.cc: Moved to... + * testsuite/20_util/bitset/operations/2.cc: ...here. + * testsuite/23_containers/bitset/operations/96303.cc: Moved to... + * testsuite/20_util/bitset/operations/96303.cc: ...here. + * testsuite/23_containers/bitset/operations/constexpr-2.cc: Moved to... + * testsuite/20_util/bitset/operations/constexpr-2.cc: ...here. + * testsuite/23_containers/bitset/operations/constexpr.cc: Moved to... + * testsuite/20_util/bitset/operations/constexpr.cc: ...here. + * testsuite/23_containers/bitset/requirements/constexpr_functions.cc: Moved to... + * testsuite/20_util/bitset/requirements/constexpr_functions.cc: ...here. + * testsuite/23_containers/bitset/requirements/explicit_instantiation/1.cc: Moved to... + * testsuite/20_util/bitset/requirements/explicit_instantiation/1.cc: ...here. + * testsuite/23_containers/bitset/requirements/explicit_instantiation/1_c++0x.cc: Moved to... + * testsuite/20_util/bitset/requirements/explicit_instantiation/1_c++0x.cc: ...here. + * testsuite/23_containers/headers/bitset/synopsis.cc: Moved to... + * testsuite/20_util/headers/bitset/synopsis.cc: ...here. + +2022-09-22 François Dumont <fdumont@gcc.gnu.org> + + * python/libstdcxx/v6/printers.py: Remove ptinter registration for non-existing + types std::__debug::unique_ptr, std::__debug::stack, std::__debug::queue, + std::__debug::priority_queue. + +2022-09-21 Jonathan Wakely <jwakely@redhat.com> + + PR libstdc++/91456 + * testsuite/20_util/function/91456.cc: Add comment with PR + number. + * testsuite/20_util/is_invocable/91456.cc: Likewise. Replace + std::function checks with std::is_invocable_r checks. + +2022-09-21 Jonathan Wakely <jwakely@redhat.com> + + * testsuite/17_intro/headers/c++1998/all_attributes.cc: Remove + unnecessary main function. + * testsuite/17_intro/headers/c++2011/all_attributes.cc: + Likewise. + * testsuite/17_intro/headers/c++2014/all_attributes.cc: + Likewise. + * testsuite/17_intro/headers/c++2017/all_attributes.cc: + Likewise. + * testsuite/17_intro/headers/c++2020/all_attributes.cc: + Likewise. + +2022-09-21 Jonathan Wakely <jwakely@redhat.com> + + * testsuite/20_util/headers/memory/synopsis.cc: Add declarations + from C++11 and later. + +2022-09-21 Jonathan Wakely <jwakely@redhat.com> + + * doc/xml/manual/documentation_hacking.xml: Remove trailing + whitespace. + * doc/xml/manual/policy_data_structures.xml: Likewise. + +2022-09-21 Jonathan Wakely <jwakely@redhat.com> + + * include/c_compatibility/stdlib.h [!_GLIBCXX_HOSTED]: Add + using-declaration for _Exit. + +2022-09-21 Jonathan Wakely <jwakely@redhat.com> + + * testsuite/18_support/uncaught_exception/14026.cc: Qualify + call to std::abort. + +2022-09-21 Jonathan Wakely <jwakely@redhat.com> + + * include/bits/ranges_base.h: Include <initializer_list>. + +2022-09-20 Jonathan Wakely <jwakely@redhat.com> + + * include/c_global/cstdlib [!_GLIBCXX_HOSTED] (quick_exit): Fix + missing space. + 2022-09-16 Jonathan Wakely <jwakely@redhat.com> PR libstdc++/106953 diff --git a/libstdc++-v3/doc/xml/manual/documentation_hacking.xml b/libstdc++-v3/doc/xml/manual/documentation_hacking.xml index 03bf1f1..776d5e8 100644 --- a/libstdc++-v3/doc/xml/manual/documentation_hacking.xml +++ b/libstdc++-v3/doc/xml/manual/documentation_hacking.xml @@ -353,7 +353,7 @@ documentation. Here are some of the obvious errors, and ways to fix some common issues that may appear quite cryptic. </para> - + <para> First, if using a rule like <code>make pdf</code>, try to narrow down the scope of the error to either docbook @@ -844,7 +844,7 @@ make <literal>XSL_STYLE_DIR="/usr/share/xml/docbook/stylesheet/nwalsh"</literal> documentation. Here are some of the obvious errors, and ways to fix some common issues that may appear quite cryptic. </para> - + <para> First, if using a rule like <code>make pdf</code>, try to narrow down the scope of the error to either docbook diff --git a/libstdc++-v3/doc/xml/manual/policy_data_structures.xml b/libstdc++-v3/doc/xml/manual/policy_data_structures.xml index 3e59810..305257c 100644 --- a/libstdc++-v3/doc/xml/manual/policy_data_structures.xml +++ b/libstdc++-v3/doc/xml/manual/policy_data_structures.xml @@ -3003,7 +3003,7 @@ </textobject> </mediaobject> </figure> - + <para>Let U be a domain (e.g., the integers, or the strings of 3 characters). A hash-table algorithm needs to map elements of U "uniformly" into the range [0,..., m - @@ -3179,7 +3179,7 @@ 0</subscript><superscript>t - 1</superscript> s<subscript>i</subscript> a<superscript>i</superscript> mod m </mathphrase> </equation> - + <para>where a is some non-negative integral value. This is the standard string-hashing function used in SGI's @@ -3278,7 +3278,7 @@ </textobject> </mediaobject> </figure> - + <para>If <classname>cc_hash_table</classname>'s hash-functor, <classname>Hash_Fn</classname> is instantiated by <classname>null_type</classname> , then <classname>Comb_Hash_Fn</classname> is taken to be a ranged-hash function. The graphic below shows an <function>insert</function> sequence @@ -3298,7 +3298,7 @@ </textobject> </mediaobject> </figure> - + </section> <section xml:id="hash_policies.implementation.probe"> @@ -3917,7 +3917,7 @@ </textobject> </mediaobject> </figure> - + <para>Supporting such trees is difficult for a number of reasons:</para> @@ -4819,7 +4819,7 @@ assert(p.top() == 3); </programlisting> - + <para>It should be noted that an alternative design could embed an associative container in a priority queue. Could, but most probably should not. To begin with, it should be noted that one diff --git a/libstdc++-v3/include/bits/alloc_traits.h b/libstdc++-v3/include/bits/alloc_traits.h index 507e8f1..8479bfd 100644 --- a/libstdc++-v3/include/bits/alloc_traits.h +++ b/libstdc++-v3/include/bits/alloc_traits.h @@ -74,7 +74,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp> using __pocs = typename _Tp::propagate_on_container_swap; template<typename _Tp> - using __equal = typename _Tp::is_always_equal; + using __equal = __type_identity<typename _Tp::is_always_equal>; }; template<typename _Alloc, typename _Up> @@ -209,7 +209,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * otherwise @c is_empty<Alloc>::type */ using is_always_equal - = __detected_or_t<typename is_empty<_Alloc>::type, __equal, _Alloc>; + = typename __detected_or_t<is_empty<_Alloc>, __equal, _Alloc>::type; template<typename _Tp> using rebind_alloc = __alloc_rebind<_Alloc, _Tp>; diff --git a/libstdc++-v3/include/bits/ptr_traits.h b/libstdc++-v3/include/bits/ptr_traits.h index 8360c3b..ae88107 100644 --- a/libstdc++-v3/include/bits/ptr_traits.h +++ b/libstdc++-v3/include/bits/ptr_traits.h @@ -144,29 +144,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct __ptr_traits_impl : __ptr_traits_ptr_to<_Ptr, _Elt> { private: - template<typename _Tp, typename = void> - struct __difference { using type = ptrdiff_t; }; - template<typename _Tp> -#if __cpp_concepts - requires requires { typename _Tp::difference_type; } - struct __difference<_Tp> -#else - struct __difference<_Tp, __void_t<typename _Tp::difference_type>> -#endif - { using type = typename _Tp::difference_type; }; - - template<typename _Tp, typename _Up, typename = void> - struct __rebind : __replace_first_arg<_Tp, _Up> { }; + using __diff_t = typename _Tp::difference_type; template<typename _Tp, typename _Up> -#if __cpp_concepts - requires requires { typename _Tp::template rebind<_Up>; } - struct __rebind<_Tp, _Up> -#else - struct __rebind<_Tp, _Up, __void_t<typename _Tp::template rebind<_Up>>> -#endif - { using type = typename _Tp::template rebind<_Up>; }; + using __rebind = __type_identity<typename _Tp::template rebind<_Up>>; public: /// The pointer type. @@ -176,11 +158,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION using element_type = _Elt; /// The type used to represent the difference between two pointers. - using difference_type = typename __difference<_Ptr>::type; + using difference_type = __detected_or_t<ptrdiff_t, __diff_t, _Ptr>; /// A pointer to a different type. template<typename _Up> - using rebind = typename __rebind<_Ptr, _Up>::type; + using rebind = typename __detected_or_t<__replace_first_arg<_Ptr, _Up>, + __rebind, _Ptr, _Up>::type; }; // _GLIBCXX_RESOLVE_LIB_DEFECTS diff --git a/libstdc++-v3/include/bits/ranges_base.h b/libstdc++-v3/include/bits/ranges_base.h index 866d7c5..805f196 100644 --- a/libstdc++-v3/include/bits/ranges_base.h +++ b/libstdc++-v3/include/bits/ranges_base.h @@ -33,6 +33,7 @@ #pragma GCC system_header #if __cplusplus > 201703L +#include <initializer_list> #include <bits/iterator_concepts.h> #include <ext/numeric_traits.h> #include <bits/max_size_type.h> diff --git a/libstdc++-v3/include/c_compatibility/stdlib.h b/libstdc++-v3/include/c_compatibility/stdlib.h index 377b910..70fa4c8 100644 --- a/libstdc++-v3/include/c_compatibility/stdlib.h +++ b/libstdc++-v3/include/c_compatibility/stdlib.h @@ -45,6 +45,9 @@ using std::exit; # ifdef _GLIBCXX_HAVE_QUICK_EXIT using std::quick_exit; # endif +# if _GLIBCXX_USE_C99_STDLIB + using std::_Exit; +# endif #endif #if _GLIBCXX_HOSTED diff --git a/libstdc++-v3/include/debug/bitset b/libstdc++-v3/include/debug/bitset index 4c0af03..9335fe4 100644 --- a/libstdc++-v3/include/debug/bitset +++ b/libstdc++-v3/include/debug/bitset @@ -141,6 +141,7 @@ namespace __debug : _Base(__val) { } template<typename _CharT, typename _Traits, typename _Alloc> + _GLIBCXX23_CONSTEXPR explicit bitset(const std::basic_string<_CharT, _Traits, _Alloc>& __str, typename std::basic_string<_CharT, _Traits, _Alloc>::size_type @@ -152,6 +153,7 @@ namespace __debug // _GLIBCXX_RESOLVE_LIB_DEFECTS // 396. what are characters zero and one. template<class _CharT, class _Traits, class _Alloc> + _GLIBCXX23_CONSTEXPR bitset(const std::basic_string<_CharT, _Traits, _Alloc>& __str, typename std::basic_string<_CharT, _Traits, _Alloc>::size_type __pos, @@ -160,10 +162,12 @@ namespace __debug _CharT __zero, _CharT __one = _CharT('1')) : _Base(__str, __pos, __n, __zero, __one) { } + _GLIBCXX23_CONSTEXPR bitset(const _Base& __x) : _Base(__x) { } #if __cplusplus >= 201103L template<typename _CharT> + _GLIBCXX23_CONSTEXPR explicit bitset(const _CharT* __str, typename std::basic_string<_CharT>::size_type __n @@ -173,6 +177,7 @@ namespace __debug #endif // 23.3.5.2 bitset operations: + _GLIBCXX23_CONSTEXPR bitset<_Nb>& operator&=(const bitset<_Nb>& __rhs) _GLIBCXX_NOEXCEPT { @@ -180,6 +185,7 @@ namespace __debug return *this; } + _GLIBCXX23_CONSTEXPR bitset<_Nb>& operator|=(const bitset<_Nb>& __rhs) _GLIBCXX_NOEXCEPT { @@ -187,6 +193,7 @@ namespace __debug return *this; } + _GLIBCXX23_CONSTEXPR bitset<_Nb>& operator^=(const bitset<_Nb>& __rhs) _GLIBCXX_NOEXCEPT { @@ -194,6 +201,7 @@ namespace __debug return *this; } + _GLIBCXX23_CONSTEXPR bitset<_Nb>& operator<<=(size_t __pos) _GLIBCXX_NOEXCEPT { @@ -201,6 +209,7 @@ namespace __debug return *this; } + _GLIBCXX23_CONSTEXPR bitset<_Nb>& operator>>=(size_t __pos) _GLIBCXX_NOEXCEPT { @@ -208,6 +217,7 @@ namespace __debug return *this; } + _GLIBCXX23_CONSTEXPR bitset<_Nb>& set() _GLIBCXX_NOEXCEPT { @@ -217,6 +227,7 @@ namespace __debug // _GLIBCXX_RESOLVE_LIB_DEFECTS // 186. bitset::set() second parameter should be bool + _GLIBCXX23_CONSTEXPR bitset<_Nb>& set(size_t __pos, bool __val = true) { @@ -224,6 +235,7 @@ namespace __debug return *this; } + _GLIBCXX23_CONSTEXPR bitset<_Nb>& reset() _GLIBCXX_NOEXCEPT { @@ -231,6 +243,7 @@ namespace __debug return *this; } + _GLIBCXX23_CONSTEXPR bitset<_Nb>& reset(size_t __pos) { @@ -238,10 +251,12 @@ namespace __debug return *this; } + _GLIBCXX23_CONSTEXPR bitset<_Nb> operator~() const _GLIBCXX_NOEXCEPT { return bitset(~_M_base()); } + _GLIBCXX23_CONSTEXPR bitset<_Nb>& flip() _GLIBCXX_NOEXCEPT { @@ -249,6 +264,7 @@ namespace __debug return *this; } + _GLIBCXX23_CONSTEXPR bitset<_Nb>& flip(size_t __pos) { @@ -259,6 +275,7 @@ namespace __debug // element access: // _GLIBCXX_RESOLVE_LIB_DEFECTS // 11. Bitset minor problems + _GLIBCXX23_CONSTEXPR reference operator[](size_t __pos) { @@ -288,6 +305,7 @@ namespace __debug #endif template <typename _CharT, typename _Traits, typename _Alloc> + _GLIBCXX23_CONSTEXPR std::basic_string<_CharT, _Traits, _Alloc> to_string() const { return _M_base().template to_string<_CharT, _Traits, _Alloc>(); } @@ -295,6 +313,7 @@ namespace __debug // _GLIBCXX_RESOLVE_LIB_DEFECTS // 396. what are characters zero and one. template<class _CharT, class _Traits, class _Alloc> + _GLIBCXX23_CONSTEXPR std::basic_string<_CharT, _Traits, _Alloc> to_string(_CharT __zero, _CharT __one = _CharT('1')) const { @@ -305,6 +324,7 @@ namespace __debug // _GLIBCXX_RESOLVE_LIB_DEFECTS // 434. bitset::to_string() hard to use. template<typename _CharT, typename _Traits> + _GLIBCXX23_CONSTEXPR std::basic_string<_CharT, _Traits, std::allocator<_CharT> > to_string() const { return to_string<_CharT, _Traits, std::allocator<_CharT> >(); } @@ -312,12 +332,14 @@ namespace __debug // _GLIBCXX_RESOLVE_LIB_DEFECTS // 853. to_string needs updating with zero and one. template<class _CharT, class _Traits> + _GLIBCXX23_CONSTEXPR std::basic_string<_CharT, _Traits, std::allocator<_CharT> > to_string(_CharT __zero, _CharT __one = _CharT('1')) const { return to_string<_CharT, _Traits, std::allocator<_CharT> >(__zero, __one); } template<typename _CharT> + _GLIBCXX23_CONSTEXPR std::basic_string<_CharT, std::char_traits<_CharT>, std::allocator<_CharT> > to_string() const @@ -327,6 +349,7 @@ namespace __debug } template<class _CharT> + _GLIBCXX23_CONSTEXPR std::basic_string<_CharT, std::char_traits<_CharT>, std::allocator<_CharT> > to_string(_CharT __zero, _CharT __one = _CharT('1')) const @@ -335,12 +358,14 @@ namespace __debug std::allocator<_CharT> >(__zero, __one); } + _GLIBCXX23_CONSTEXPR std::basic_string<char, std::char_traits<char>, std::allocator<char> > to_string() const { return to_string<char,std::char_traits<char>,std::allocator<char> >(); } + _GLIBCXX23_CONSTEXPR std::basic_string<char, std::char_traits<char>, std::allocator<char> > to_string(char __zero, char __one = '1') const { @@ -351,6 +376,7 @@ namespace __debug using _Base::count; using _Base::size; + _GLIBCXX23_CONSTEXPR bool operator==(const bitset<_Nb>& __rhs) const _GLIBCXX_NOEXCEPT { return _M_base() == __rhs._M_base(); } @@ -366,45 +392,52 @@ namespace __debug using _Base::any; using _Base::none; + _GLIBCXX23_CONSTEXPR bitset<_Nb> operator<<(size_t __pos) const _GLIBCXX_NOEXCEPT { return bitset<_Nb>(_M_base() << __pos); } + _GLIBCXX23_CONSTEXPR bitset<_Nb> operator>>(size_t __pos) const _GLIBCXX_NOEXCEPT { return bitset<_Nb>(_M_base() >> __pos); } + _GLIBCXX23_CONSTEXPR _Base& _M_base() _GLIBCXX_NOEXCEPT { return *this; } + _GLIBCXX23_CONSTEXPR const _Base& _M_base() const _GLIBCXX_NOEXCEPT { return *this; } }; template<size_t _Nb> - bitset<_Nb> + _GLIBCXX23_CONSTEXPR + inline bitset<_Nb> operator&(const bitset<_Nb>& __x, const bitset<_Nb>& __y) _GLIBCXX_NOEXCEPT { return bitset<_Nb>(__x) &= __y; } template<size_t _Nb> - bitset<_Nb> + _GLIBCXX23_CONSTEXPR + inline bitset<_Nb> operator|(const bitset<_Nb>& __x, const bitset<_Nb>& __y) _GLIBCXX_NOEXCEPT { return bitset<_Nb>(__x) |= __y; } template<size_t _Nb> - bitset<_Nb> + _GLIBCXX23_CONSTEXPR + inline bitset<_Nb> operator^(const bitset<_Nb>& __x, const bitset<_Nb>& __y) _GLIBCXX_NOEXCEPT { return bitset<_Nb>(__x) ^= __y; } template<typename _CharT, typename _Traits, size_t _Nb> - std::basic_istream<_CharT, _Traits>& + inline std::basic_istream<_CharT, _Traits>& operator>>(std::basic_istream<_CharT, _Traits>& __is, bitset<_Nb>& __x) { return __is >> __x._M_base(); } template<typename _CharT, typename _Traits, size_t _Nb> - std::basic_ostream<_CharT, _Traits>& + inline std::basic_ostream<_CharT, _Traits>& operator<<(std::basic_ostream<_CharT, _Traits>& __os, const bitset<_Nb>& __x) { return __os << __x._M_base(); } diff --git a/libstdc++-v3/include/experimental/type_traits b/libstdc++-v3/include/experimental/type_traits index af5970e..fa25a1c 100644 --- a/libstdc++-v3/include/experimental/type_traits +++ b/libstdc++-v3/include/experimental/type_traits @@ -223,7 +223,9 @@ template <typename _Tp, unsigned _Idx = 0> // See C++14 20.10.6, type relations template <typename _Tp, typename _Up> - constexpr bool is_same_v = is_same<_Tp, _Up>::value; + constexpr bool is_same_v = false; +template <typename _Tp> + constexpr bool is_same_v<_Tp, _Tp> = true; template <typename _Base, typename _Derived> constexpr bool is_base_of_v = is_base_of<_Base, _Derived>::value; template <typename _From, typename _To> @@ -266,23 +268,21 @@ struct nonesuch : private __nonesuchbase }; #pragma GCC diagnostic pop -template<template<typename...> class _Op, typename... _Args> - using is_detected - = typename std::__detector<nonesuch, void, _Op, _Args...>::value_t; - -template<template<typename...> class _Op, typename... _Args> - constexpr bool is_detected_v = is_detected<_Op, _Args...>::value; - -template<template<typename...> class _Op, typename... _Args> - using detected_t - = typename std::__detector<nonesuch, void, _Op, _Args...>::type; - template<typename _Default, template<typename...> class _Op, typename... _Args> using detected_or = std::__detected_or<_Default, _Op, _Args...>; template<typename _Default, template<typename...> class _Op, typename... _Args> using detected_or_t = typename detected_or<_Default, _Op, _Args...>::type; +template<template<typename...> class _Op, typename... _Args> + using detected_t = detected_or_t<nonesuch, _Op, _Args...>; + +template<template<typename...> class _Op, typename... _Args> + using is_detected = typename detected_or<void, _Op, _Args...>::__is_detected; + +template<template<typename...> class _Op, typename... _Args> + constexpr bool is_detected_v = is_detected<_Op, _Args...>::value; + template<typename _Expected, template<typename...> class _Op, typename... _Args> using is_detected_exact = is_same<_Expected, detected_t<_Op, _Args...>>; diff --git a/libstdc++-v3/include/std/bitset b/libstdc++-v3/include/std/bitset index 438c2f7..1a551cf 100644 --- a/libstdc++-v3/include/std/bitset +++ b/libstdc++-v3/include/std/bitset @@ -44,14 +44,15 @@ #pragma GCC system_header -#include <string> #include <bits/functexcept.h> // For invalid_argument, out_of_range, // overflow_error -#include <iosfwd> -#include <bits/cxxabi_forced.h> - -#if __cplusplus >= 201103L -# include <bits/functional_hash.h> +#if _GLIBCXX_HOSTED +# include <string> +# include <iosfwd> +# include <bits/cxxabi_forced.h> +# if __cplusplus >= 201103L +# include <bits/functional_hash.h> +# endif #endif #define _GLIBCXX_BITSET_BITS_PER_WORD (__CHAR_BIT__ * __SIZEOF_LONG__) @@ -65,6 +66,10 @@ namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_CONTAINER +#if __cplusplus > 202002L && _GLIBCXX_HOSTED +# define __cpp_lib_constexpr_bitset 202202L +#endif + /** * Base class, general case. It is a class invariant that _Nw will be * nonnegative. @@ -111,7 +116,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _S_maskbit(size_t __pos) _GLIBCXX_NOEXCEPT { return (static_cast<_WordT>(1)) << _S_whichbit(__pos); } - _WordT& + _GLIBCXX14_CONSTEXPR _WordT& _M_getword(size_t __pos) _GLIBCXX_NOEXCEPT { return _M_w[_S_whichword(__pos)]; } @@ -120,12 +125,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { return _M_w[_S_whichword(__pos)]; } #if __cplusplus >= 201103L - const _WordT* + constexpr const _WordT* _M_getdata() const noexcept { return _M_w; } #endif - _WordT& + _GLIBCXX23_CONSTEXPR _WordT& _M_hiword() _GLIBCXX_NOEXCEPT { return _M_w[_Nw - 1]; } @@ -133,52 +138,62 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _M_hiword() const _GLIBCXX_NOEXCEPT { return _M_w[_Nw - 1]; } - void + _GLIBCXX23_CONSTEXPR void _M_do_and(const _Base_bitset<_Nw>& __x) _GLIBCXX_NOEXCEPT { for (size_t __i = 0; __i < _Nw; __i++) _M_w[__i] &= __x._M_w[__i]; } - void + _GLIBCXX14_CONSTEXPR void _M_do_or(const _Base_bitset<_Nw>& __x) _GLIBCXX_NOEXCEPT { for (size_t __i = 0; __i < _Nw; __i++) _M_w[__i] |= __x._M_w[__i]; } - void + _GLIBCXX14_CONSTEXPR void _M_do_xor(const _Base_bitset<_Nw>& __x) _GLIBCXX_NOEXCEPT { for (size_t __i = 0; __i < _Nw; __i++) _M_w[__i] ^= __x._M_w[__i]; } - void + _GLIBCXX14_CONSTEXPR void _M_do_left_shift(size_t __shift) _GLIBCXX_NOEXCEPT; - void + _GLIBCXX14_CONSTEXPR void _M_do_right_shift(size_t __shift) _GLIBCXX_NOEXCEPT; - void + _GLIBCXX14_CONSTEXPR void _M_do_flip() _GLIBCXX_NOEXCEPT { for (size_t __i = 0; __i < _Nw; __i++) _M_w[__i] = ~_M_w[__i]; } - void + _GLIBCXX14_CONSTEXPR void _M_do_set() _GLIBCXX_NOEXCEPT { for (size_t __i = 0; __i < _Nw; __i++) _M_w[__i] = ~static_cast<_WordT>(0); } - void + _GLIBCXX14_CONSTEXPR void _M_do_reset() _GLIBCXX_NOEXCEPT - { __builtin_memset(_M_w, 0, _Nw * sizeof(_WordT)); } + { +#if __cplusplus >= 201402L + if (__builtin_is_constant_evaluated()) + { + for (_WordT& __w : _M_w) + __w = 0; + return; + } +#endif + __builtin_memset(_M_w, 0, _Nw * sizeof(_WordT)); + } - bool + _GLIBCXX14_CONSTEXPR bool _M_is_equal(const _Base_bitset<_Nw>& __x) const _GLIBCXX_NOEXCEPT { for (size_t __i = 0; __i < _Nw; ++__i) @@ -188,7 +203,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } template<size_t _Nb> - bool + _GLIBCXX14_CONSTEXPR bool _M_are_all() const _GLIBCXX_NOEXCEPT { for (size_t __i = 0; __i < _Nw - 1; __i++) @@ -199,7 +214,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER - _Nb)); } - bool + _GLIBCXX14_CONSTEXPR bool _M_is_any() const _GLIBCXX_NOEXCEPT { for (size_t __i = 0; __i < _Nw; __i++) @@ -208,7 +223,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER return false; } - size_t + _GLIBCXX14_CONSTEXPR size_t _M_do_count() const _GLIBCXX_NOEXCEPT { size_t __result = 0; @@ -217,26 +232,26 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER return __result; } - unsigned long + _GLIBCXX14_CONSTEXPR unsigned long _M_do_to_ulong() const; #if __cplusplus >= 201103L - unsigned long long + _GLIBCXX14_CONSTEXPR unsigned long long _M_do_to_ullong() const; #endif // find first "on" bit - size_t + _GLIBCXX14_CONSTEXPR size_t _M_do_find_first(size_t) const _GLIBCXX_NOEXCEPT; // find the next "on" bit that follows "prev" - size_t + _GLIBCXX14_CONSTEXPR size_t _M_do_find_next(size_t, size_t) const _GLIBCXX_NOEXCEPT; }; // Definitions of non-inline functions from _Base_bitset. template<size_t _Nw> - void + _GLIBCXX14_CONSTEXPR void _Base_bitset<_Nw>::_M_do_left_shift(size_t __shift) _GLIBCXX_NOEXCEPT { if (__builtin_expect(__shift != 0, 1)) @@ -262,7 +277,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } template<size_t _Nw> - void + _GLIBCXX14_CONSTEXPR void _Base_bitset<_Nw>::_M_do_right_shift(size_t __shift) _GLIBCXX_NOEXCEPT { if (__builtin_expect(__shift != 0, 1)) @@ -289,7 +304,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } template<size_t _Nw> - unsigned long + _GLIBCXX14_CONSTEXPR unsigned long _Base_bitset<_Nw>::_M_do_to_ulong() const { for (size_t __i = 1; __i < _Nw; ++__i) @@ -300,7 +315,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER #if __cplusplus >= 201103L template<size_t _Nw> - unsigned long long + _GLIBCXX14_CONSTEXPR unsigned long long _Base_bitset<_Nw>::_M_do_to_ullong() const { const bool __dw = sizeof(unsigned long long) > sizeof(unsigned long); @@ -316,7 +331,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER #endif template<size_t _Nw> - size_t + _GLIBCXX14_CONSTEXPR size_t _Base_bitset<_Nw>:: _M_do_find_first(size_t __not_found) const _GLIBCXX_NOEXCEPT { @@ -332,7 +347,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } template<size_t _Nw> - size_t + _GLIBCXX14_CONSTEXPR size_t _Base_bitset<_Nw>:: _M_do_find_next(size_t __prev, size_t __not_found) const _GLIBCXX_NOEXCEPT { @@ -406,7 +421,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _S_maskbit(size_t __pos) _GLIBCXX_NOEXCEPT { return (static_cast<_WordT>(1)) << _S_whichbit(__pos); } - _WordT& + _GLIBCXX14_CONSTEXPR _WordT& _M_getword(size_t) _GLIBCXX_NOEXCEPT { return _M_w; } @@ -415,12 +430,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { return _M_w; } #if __cplusplus >= 201103L - const _WordT* + constexpr const _WordT* _M_getdata() const noexcept { return &_M_w; } #endif - _WordT& + _GLIBCXX14_CONSTEXPR _WordT& _M_hiword() _GLIBCXX_NOEXCEPT { return _M_w; } @@ -428,67 +443,67 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _M_hiword() const _GLIBCXX_NOEXCEPT { return _M_w; } - void + _GLIBCXX14_CONSTEXPR void _M_do_and(const _Base_bitset<1>& __x) _GLIBCXX_NOEXCEPT { _M_w &= __x._M_w; } - void + _GLIBCXX14_CONSTEXPR void _M_do_or(const _Base_bitset<1>& __x) _GLIBCXX_NOEXCEPT { _M_w |= __x._M_w; } - void + _GLIBCXX14_CONSTEXPR void _M_do_xor(const _Base_bitset<1>& __x) _GLIBCXX_NOEXCEPT { _M_w ^= __x._M_w; } - void + _GLIBCXX14_CONSTEXPR void _M_do_left_shift(size_t __shift) _GLIBCXX_NOEXCEPT { _M_w <<= __shift; } - void + _GLIBCXX14_CONSTEXPR void _M_do_right_shift(size_t __shift) _GLIBCXX_NOEXCEPT { _M_w >>= __shift; } - void + _GLIBCXX14_CONSTEXPR void _M_do_flip() _GLIBCXX_NOEXCEPT { _M_w = ~_M_w; } - void + _GLIBCXX14_CONSTEXPR void _M_do_set() _GLIBCXX_NOEXCEPT { _M_w = ~static_cast<_WordT>(0); } - void + _GLIBCXX14_CONSTEXPR void _M_do_reset() _GLIBCXX_NOEXCEPT { _M_w = 0; } - bool + _GLIBCXX14_CONSTEXPR bool _M_is_equal(const _Base_bitset<1>& __x) const _GLIBCXX_NOEXCEPT { return _M_w == __x._M_w; } template<size_t _Nb> - bool + _GLIBCXX14_CONSTEXPR bool _M_are_all() const _GLIBCXX_NOEXCEPT { return _M_w == (~static_cast<_WordT>(0) >> (_GLIBCXX_BITSET_BITS_PER_WORD - _Nb)); } - bool + _GLIBCXX14_CONSTEXPR bool _M_is_any() const _GLIBCXX_NOEXCEPT { return _M_w != 0; } - size_t + _GLIBCXX14_CONSTEXPR size_t _M_do_count() const _GLIBCXX_NOEXCEPT { return __builtin_popcountl(_M_w); } - unsigned long + _GLIBCXX14_CONSTEXPR unsigned long _M_do_to_ulong() const _GLIBCXX_NOEXCEPT { return _M_w; } #if __cplusplus >= 201103L - unsigned long long + constexpr unsigned long long _M_do_to_ullong() const noexcept { return _M_w; } #endif - size_t + _GLIBCXX14_CONSTEXPR size_t _M_do_find_first(size_t __not_found) const _GLIBCXX_NOEXCEPT { if (_M_w != 0) @@ -498,7 +513,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } // find the next "on" bit that follows "prev" - size_t + _GLIBCXX14_CONSTEXPR size_t _M_do_find_next(size_t __prev, size_t __not_found) const _GLIBCXX_NOEXCEPT { @@ -552,17 +567,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER // This would normally give access to the data. The bounds-checking // in the bitset class will prevent the user from getting this far, - // but (1) it must still return an lvalue to compile, and (2) the - // user might call _Unchecked_set directly, in which case this /needs/ - // to fail. Let's not penalize zero-length users unless they actually + // but this must fail if the user calls _Unchecked_set directly. + // Let's not penalize zero-length users unless they actually // make an unchecked call; all the memory ugliness is therefore // localized to this single should-never-get-this-far function. + __attribute__((__noreturn__)) _WordT& _M_getword(size_t) _GLIBCXX_NOEXCEPT - { - __throw_out_of_range(__N("_Base_bitset::_M_getword")); - return *new _WordT; - } + { __throw_out_of_range(__N("_Base_bitset::_M_getword")); } _GLIBCXX_CONSTEXPR _WordT _M_getword(size_t) const _GLIBCXX_NOEXCEPT @@ -572,75 +584,75 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _M_hiword() const _GLIBCXX_NOEXCEPT { return 0; } - void + _GLIBCXX14_CONSTEXPR void _M_do_and(const _Base_bitset<0>&) _GLIBCXX_NOEXCEPT { } - void + _GLIBCXX14_CONSTEXPR void _M_do_or(const _Base_bitset<0>&) _GLIBCXX_NOEXCEPT { } - void + _GLIBCXX14_CONSTEXPR void _M_do_xor(const _Base_bitset<0>&) _GLIBCXX_NOEXCEPT { } - void + _GLIBCXX14_CONSTEXPR void _M_do_left_shift(size_t) _GLIBCXX_NOEXCEPT { } - void + _GLIBCXX14_CONSTEXPR void _M_do_right_shift(size_t) _GLIBCXX_NOEXCEPT { } - void + _GLIBCXX14_CONSTEXPR void _M_do_flip() _GLIBCXX_NOEXCEPT { } - void + _GLIBCXX14_CONSTEXPR void _M_do_set() _GLIBCXX_NOEXCEPT { } - void + _GLIBCXX14_CONSTEXPR void _M_do_reset() _GLIBCXX_NOEXCEPT { } // Are all empty bitsets equal to each other? Are they equal to // themselves? How to compare a thing which has no state? What is // the sound of one zero-length bitset clapping? - bool + _GLIBCXX_CONSTEXPR bool _M_is_equal(const _Base_bitset<0>&) const _GLIBCXX_NOEXCEPT { return true; } template<size_t _Nb> - bool + _GLIBCXX_CONSTEXPR bool _M_are_all() const _GLIBCXX_NOEXCEPT { return true; } - bool + _GLIBCXX_CONSTEXPR bool _M_is_any() const _GLIBCXX_NOEXCEPT { return false; } - size_t + _GLIBCXX_CONSTEXPR size_t _M_do_count() const _GLIBCXX_NOEXCEPT { return 0; } - unsigned long + _GLIBCXX_CONSTEXPR unsigned long _M_do_to_ulong() const _GLIBCXX_NOEXCEPT { return 0; } #if __cplusplus >= 201103L - unsigned long long + constexpr unsigned long long _M_do_to_ullong() const noexcept { return 0; } #endif // Normally "not found" is the size, but that could also be // misinterpreted as an index in this corner case. Oh well. - size_t + _GLIBCXX_CONSTEXPR size_t _M_do_find_first(size_t) const _GLIBCXX_NOEXCEPT { return 0; } - size_t + _GLIBCXX_CONSTEXPR size_t _M_do_find_next(size_t, size_t) const _GLIBCXX_NOEXCEPT { return 0; } }; @@ -652,7 +664,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { typedef unsigned long _WordT; - static void + static _GLIBCXX14_CONSTEXPR void _S_do_sanitize(_WordT& __val) _GLIBCXX_NOEXCEPT { __val &= ~((~static_cast<_WordT>(0)) << _Extrabits); } }; @@ -662,7 +674,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { typedef unsigned long _WordT; - static void + static _GLIBCXX14_CONSTEXPR void _S_do_sanitize(_WordT) _GLIBCXX_NOEXCEPT { } }; @@ -755,7 +767,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER typedef _Base_bitset<_GLIBCXX_BITSET_WORDS(_Nb)> _Base; typedef unsigned long _WordT; +#if _GLIBCXX_HOSTED template<class _CharT, class _Traits, class _Alloc> + _GLIBCXX23_CONSTEXPR void _M_check_initial_position(const std::basic_string<_CharT, _Traits, _Alloc>& __s, size_t __position) const @@ -766,7 +780,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER "(which is %zu)"), __position, __s.size()); } +#endif // HOSTED + _GLIBCXX23_CONSTEXPR void _M_check(size_t __position, const char *__s) const { if (__position >= _Nb) @@ -775,6 +791,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER __s, __position, _Nb); } + _GLIBCXX23_CONSTEXPR void _M_do_sanitize() _GLIBCXX_NOEXCEPT { @@ -810,6 +827,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER reference(); public: + _GLIBCXX23_CONSTEXPR reference(bitset& __b, size_t __pos) _GLIBCXX_NOEXCEPT { _M_wp = &__b._M_getword(__pos); @@ -820,10 +838,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER reference(const reference&) = default; #endif +#if __cplusplus > 202002L && __cpp_constexpr_dynamic_alloc + constexpr +#endif ~reference() _GLIBCXX_NOEXCEPT { } // For b[i] = __x; + _GLIBCXX23_CONSTEXPR reference& operator=(bool __x) _GLIBCXX_NOEXCEPT { @@ -835,6 +857,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } // For b[i] = b[__j]; + _GLIBCXX23_CONSTEXPR reference& operator=(const reference& __j) _GLIBCXX_NOEXCEPT { @@ -846,15 +869,18 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } // Flips the bit + _GLIBCXX23_CONSTEXPR bool operator~() const _GLIBCXX_NOEXCEPT { return (*(_M_wp) & _Base::_S_maskbit(_M_bpos)) == 0; } // For __x = b[i]; + _GLIBCXX23_CONSTEXPR operator bool() const _GLIBCXX_NOEXCEPT { return (*(_M_wp) & _Base::_S_maskbit(_M_bpos)) != 0; } // For b[i].flip(); + _GLIBCXX23_CONSTEXPR reference& flip() _GLIBCXX_NOEXCEPT { @@ -879,6 +905,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { _M_do_sanitize(); } #endif +#if _GLIBCXX_HOSTED /** * Use a subset of a string. * @param __s A string of @a 0 and @a 1 characters. @@ -889,6 +916,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * which is neither @a 0 nor @a 1. */ template<class _CharT, class _Traits, class _Alloc> + _GLIBCXX23_CONSTEXPR explicit bitset(const std::basic_string<_CharT, _Traits, _Alloc>& __s, size_t __position = 0) @@ -911,6 +939,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * which is neither @a 0 nor @a 1. */ template<class _CharT, class _Traits, class _Alloc> + _GLIBCXX23_CONSTEXPR bitset(const std::basic_string<_CharT, _Traits, _Alloc>& __s, size_t __position, size_t __n) : _Base() @@ -922,6 +951,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER // _GLIBCXX_RESOLVE_LIB_DEFECTS // 396. what are characters zero and one. template<class _CharT, class _Traits, class _Alloc> + _GLIBCXX23_CONSTEXPR bitset(const std::basic_string<_CharT, _Traits, _Alloc>& __s, size_t __position, size_t __n, _CharT __zero, _CharT __one = _CharT('1')) @@ -942,6 +972,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * which is neither @a __zero nor @a __one. */ template<typename _CharT> + [[__gnu__::__nonnull__]] + _GLIBCXX23_CONSTEXPR explicit bitset(const _CharT* __str, typename std::basic_string<_CharT>::size_type __n @@ -958,7 +990,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER __n, __zero, __one); } -#endif +#endif // C++11 +#endif // HOSTED // 23.3.5.2 bitset operations: ///@{ @@ -968,6 +1001,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * * These should be self-explanatory. */ + _GLIBCXX23_CONSTEXPR bitset<_Nb>& operator&=(const bitset<_Nb>& __rhs) _GLIBCXX_NOEXCEPT { @@ -975,6 +1009,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER return *this; } + _GLIBCXX23_CONSTEXPR bitset<_Nb>& operator|=(const bitset<_Nb>& __rhs) _GLIBCXX_NOEXCEPT { @@ -982,6 +1017,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER return *this; } + _GLIBCXX23_CONSTEXPR bitset<_Nb>& operator^=(const bitset<_Nb>& __rhs) _GLIBCXX_NOEXCEPT { @@ -997,6 +1033,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * * These should be self-explanatory. */ + _GLIBCXX23_CONSTEXPR bitset<_Nb>& operator<<=(size_t __position) _GLIBCXX_NOEXCEPT { @@ -1010,6 +1047,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER return *this; } + _GLIBCXX23_CONSTEXPR bitset<_Nb>& operator>>=(size_t __position) _GLIBCXX_NOEXCEPT { @@ -1030,6 +1068,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * extensions from the SGI version. They do no range checking. * @ingroup SGIextensions */ + _GLIBCXX23_CONSTEXPR bitset<_Nb>& _Unchecked_set(size_t __pos) _GLIBCXX_NOEXCEPT { @@ -1037,6 +1076,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER return *this; } + _GLIBCXX23_CONSTEXPR bitset<_Nb>& _Unchecked_set(size_t __pos, int __val) _GLIBCXX_NOEXCEPT { @@ -1047,6 +1087,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER return *this; } + _GLIBCXX23_CONSTEXPR bitset<_Nb>& _Unchecked_reset(size_t __pos) _GLIBCXX_NOEXCEPT { @@ -1054,6 +1095,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER return *this; } + _GLIBCXX23_CONSTEXPR bitset<_Nb>& _Unchecked_flip(size_t __pos) _GLIBCXX_NOEXCEPT { @@ -1071,6 +1113,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER /** * @brief Sets every bit to true. */ + _GLIBCXX23_CONSTEXPR bitset<_Nb>& set() _GLIBCXX_NOEXCEPT { @@ -1085,6 +1128,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * @param __val Either true or false, defaults to true. * @throw std::out_of_range If @a pos is bigger the size of the %set. */ + _GLIBCXX23_CONSTEXPR bitset<_Nb>& set(size_t __position, bool __val = true) { @@ -1095,6 +1139,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER /** * @brief Sets every bit to false. */ + _GLIBCXX23_CONSTEXPR bitset<_Nb>& reset() _GLIBCXX_NOEXCEPT { @@ -1109,6 +1154,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * * Same as writing @c set(pos,false). */ + _GLIBCXX23_CONSTEXPR bitset<_Nb>& reset(size_t __position) { @@ -1119,6 +1165,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER /** * @brief Toggles every bit to its opposite value. */ + _GLIBCXX23_CONSTEXPR bitset<_Nb>& flip() _GLIBCXX_NOEXCEPT { @@ -1132,6 +1179,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * @param __position The index of the bit. * @throw std::out_of_range If @a pos is bigger the size of the %set. */ + _GLIBCXX23_CONSTEXPR bitset<_Nb>& flip(size_t __position) { @@ -1140,6 +1188,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } /// See the no-argument flip(). + _GLIBCXX23_CONSTEXPR bitset<_Nb> operator~() const _GLIBCXX_NOEXCEPT { return bitset<_Nb>(*this).flip(); } @@ -1159,6 +1208,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * The DR has since been changed: range-checking is a precondition * (users' responsibility), and these functions must not throw. -pme */ + _GLIBCXX23_CONSTEXPR reference operator[](size_t __position) { return reference(*this, __position); } @@ -1174,16 +1224,19 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * @throw std::overflow_error If there are too many bits to be * represented in an @c unsigned @c long. */ + _GLIBCXX23_CONSTEXPR unsigned long to_ulong() const { return this->_M_do_to_ulong(); } #if __cplusplus >= 201103L + _GLIBCXX23_CONSTEXPR unsigned long long to_ullong() const { return this->_M_do_to_ullong(); } #endif +#if _GLIBCXX_HOSTED /** * @brief Returns a character interpretation of the %bitset. * @return The string equivalent of the bits. @@ -1193,6 +1246,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * an example). */ template<class _CharT, class _Traits, class _Alloc> + _GLIBCXX23_CONSTEXPR std::basic_string<_CharT, _Traits, _Alloc> to_string() const { @@ -1204,6 +1258,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER // _GLIBCXX_RESOLVE_LIB_DEFECTS // 396. what are characters zero and one. template<class _CharT, class _Traits, class _Alloc> + _GLIBCXX23_CONSTEXPR std::basic_string<_CharT, _Traits, _Alloc> to_string(_CharT __zero, _CharT __one = _CharT('1')) const { @@ -1215,6 +1270,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER // _GLIBCXX_RESOLVE_LIB_DEFECTS // 434. bitset::to_string() hard to use. template<class _CharT, class _Traits> + _GLIBCXX23_CONSTEXPR std::basic_string<_CharT, _Traits, std::allocator<_CharT> > to_string() const { return to_string<_CharT, _Traits, std::allocator<_CharT> >(); } @@ -1222,12 +1278,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER // _GLIBCXX_RESOLVE_LIB_DEFECTS // 853. to_string needs updating with zero and one. template<class _CharT, class _Traits> + _GLIBCXX23_CONSTEXPR std::basic_string<_CharT, _Traits, std::allocator<_CharT> > to_string(_CharT __zero, _CharT __one = _CharT('1')) const { return to_string<_CharT, _Traits, std::allocator<_CharT> >(__zero, __one); } template<class _CharT> + _GLIBCXX23_CONSTEXPR std::basic_string<_CharT, std::char_traits<_CharT>, std::allocator<_CharT> > to_string() const @@ -1237,6 +1295,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } template<class _CharT> + _GLIBCXX23_CONSTEXPR std::basic_string<_CharT, std::char_traits<_CharT>, std::allocator<_CharT> > to_string(_CharT __zero, _CharT __one = _CharT('1')) const @@ -1245,6 +1304,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER std::allocator<_CharT> >(__zero, __one); } + _GLIBCXX23_CONSTEXPR std::basic_string<char, std::char_traits<char>, std::allocator<char> > to_string() const { @@ -1252,6 +1312,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER std::allocator<char> >(); } + _GLIBCXX23_CONSTEXPR std::basic_string<char, std::char_traits<char>, std::allocator<char> > to_string(char __zero, char __one = '1') const { @@ -1261,11 +1322,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER // Helper functions for string operations. template<class _CharT, class _Traits> + _GLIBCXX23_CONSTEXPR void _M_copy_from_ptr(const _CharT*, size_t, size_t, size_t, _CharT, _CharT); template<class _CharT, class _Traits, class _Alloc> + _GLIBCXX23_CONSTEXPR void _M_copy_from_string(const std::basic_string<_CharT, _Traits, _Alloc>& __s, size_t __pos, size_t __n, @@ -1274,23 +1337,28 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER __zero, __one); } template<class _CharT, class _Traits, class _Alloc> + _GLIBCXX23_CONSTEXPR void _M_copy_to_string(std::basic_string<_CharT, _Traits, _Alloc>&, _CharT, _CharT) const; // NB: Backward compat. template<class _CharT, class _Traits, class _Alloc> + _GLIBCXX23_CONSTEXPR void _M_copy_from_string(const std::basic_string<_CharT, _Traits, _Alloc>& __s, size_t __pos, size_t __n) { _M_copy_from_string(__s, __pos, __n, _CharT('0'), _CharT('1')); } template<class _CharT, class _Traits, class _Alloc> + _GLIBCXX23_CONSTEXPR void _M_copy_to_string(std::basic_string<_CharT, _Traits,_Alloc>& __s) const { _M_copy_to_string(__s, _CharT('0'), _CharT('1')); } +#endif // HOSTED /// Returns the number of bits which are set. + _GLIBCXX23_CONSTEXPR size_t count() const _GLIBCXX_NOEXCEPT { return this->_M_do_count(); } @@ -1302,11 +1370,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER ///@{ /// These comparisons for equality/inequality are, well, @e bitwise. + _GLIBCXX23_CONSTEXPR bool operator==(const bitset<_Nb>& __rhs) const _GLIBCXX_NOEXCEPT { return this->_M_is_equal(__rhs); } #if __cpp_impl_three_way_comparison < 201907L + _GLIBCXX23_CONSTEXPR bool operator!=(const bitset<_Nb>& __rhs) const _GLIBCXX_NOEXCEPT { return !this->_M_is_equal(__rhs); } @@ -1319,6 +1389,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * @return The value at @a pos. * @throw std::out_of_range If @a pos is bigger the size of the %set. */ + _GLIBCXX23_CONSTEXPR bool test(size_t __position) const { @@ -1332,6 +1403,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * @brief Tests whether all the bits are on. * @return True if all the bits are set. */ + _GLIBCXX23_CONSTEXPR bool all() const _GLIBCXX_NOEXCEPT { return this->template _M_are_all<_Nb>(); } @@ -1340,6 +1412,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * @brief Tests whether any of the bits are on. * @return True if at least one bit is set. */ + _GLIBCXX23_CONSTEXPR bool any() const _GLIBCXX_NOEXCEPT { return this->_M_is_any(); } @@ -1348,16 +1421,19 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * @brief Tests whether any of the bits are on. * @return True if none of the bits are set. */ + _GLIBCXX23_CONSTEXPR bool none() const _GLIBCXX_NOEXCEPT { return !this->_M_is_any(); } ///@{ /// Self-explanatory. + _GLIBCXX23_CONSTEXPR bitset<_Nb> operator<<(size_t __position) const _GLIBCXX_NOEXCEPT { return bitset<_Nb>(*this) <<= __position; } + _GLIBCXX23_CONSTEXPR bitset<_Nb> operator>>(size_t __position) const _GLIBCXX_NOEXCEPT { return bitset<_Nb>(*this) >>= __position; } @@ -1369,6 +1445,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * @ingroup SGIextensions * @sa _Find_next */ + _GLIBCXX23_CONSTEXPR size_t _Find_first() const _GLIBCXX_NOEXCEPT { return this->_M_do_find_first(_Nb); } @@ -1380,14 +1457,17 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * @ingroup SGIextensions * @sa _Find_first */ + _GLIBCXX23_CONSTEXPR size_t _Find_next(size_t __prev) const _GLIBCXX_NOEXCEPT { return this->_M_do_find_next(__prev, _Nb); } }; +#if _GLIBCXX_HOSTED // Definitions of non-inline member functions. template<size_t _Nb> template<class _CharT, class _Traits> + _GLIBCXX23_CONSTEXPR void bitset<_Nb>:: _M_copy_from_ptr(const _CharT* __s, size_t __len, @@ -1409,16 +1489,21 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template<size_t _Nb> template<class _CharT, class _Traits, class _Alloc> + _GLIBCXX23_CONSTEXPR void bitset<_Nb>:: _M_copy_to_string(std::basic_string<_CharT, _Traits, _Alloc>& __s, _CharT __zero, _CharT __one) const { __s.assign(_Nb, __zero); - for (size_t __i = _Nb; __i > 0; --__i) - if (_Unchecked_test(__i - 1)) - _Traits::assign(__s[_Nb - __i], __one); + size_t __n = this->_Find_first(); + while (__n < _Nb) + { + __s[_Nb - __n - 1] = __one; + __n = _Find_next(__n); + } } +#endif // HOSTED // 23.3.5.3 bitset operations: ///@{ @@ -1431,6 +1516,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * These should be self-explanatory. */ template<size_t _Nb> + _GLIBCXX23_CONSTEXPR inline bitset<_Nb> operator&(const bitset<_Nb>& __x, const bitset<_Nb>& __y) _GLIBCXX_NOEXCEPT { @@ -1440,6 +1526,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } template<size_t _Nb> + _GLIBCXX23_CONSTEXPR inline bitset<_Nb> operator|(const bitset<_Nb>& __x, const bitset<_Nb>& __y) _GLIBCXX_NOEXCEPT { @@ -1449,6 +1536,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } template <size_t _Nb> + _GLIBCXX23_CONSTEXPR inline bitset<_Nb> operator^(const bitset<_Nb>& __x, const bitset<_Nb>& __y) _GLIBCXX_NOEXCEPT { @@ -1458,6 +1546,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } ///@} +#if _GLIBCXX_HOSTED ///@{ /** * @brief Global I/O operators for bitsets. @@ -1527,7 +1616,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER if (__tmp.empty() && _Nb) __state |= __ios_base::failbit; - else + else if _GLIBCXX17_CONSTEXPR (_Nb) __x._M_copy_from_string(__tmp, static_cast<size_t>(0), _Nb, __zero, __one); if (__state) @@ -1549,6 +1638,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER return __os << __tmp; } ///@} +#endif // HOSTED _GLIBCXX_END_NAMESPACE_CONTAINER } // namespace std @@ -1557,7 +1647,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER #undef _GLIBCXX_BITSET_BITS_PER_WORD #undef _GLIBCXX_BITSET_BITS_PER_ULL -#if __cplusplus >= 201103L +#if __cplusplus >= 201103L && _GLIBCXX_HOSTED namespace std _GLIBCXX_VISIBILITY(default) { @@ -1591,7 +1681,7 @@ _GLIBCXX_END_NAMESPACE_VERSION #endif // C++11 -#ifdef _GLIBCXX_DEBUG +#if defined _GLIBCXX_DEBUG && _GLIBCXX_HOSTED # include <debug/bitset> #endif diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits index 94e73ea..c5853fc 100644 --- a/libstdc++-v3/include/std/type_traits +++ b/libstdc++-v3/include/std/type_traits @@ -1451,12 +1451,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION }; #pragma GCC diagnostic pop - // is_nothrow_convertible for C++11 - template<typename _From, typename _To> - struct __is_nothrow_convertible - : public __is_nt_convertible_helper<_From, _To>::type - { }; - #if __cplusplus > 201703L #define __cpp_lib_is_nothrow_convertible 201806L /// is_nothrow_convertible @@ -2557,13 +2551,34 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// @cond undocumented + // Detection idiom. + // Detect whether _Op<_Args...> is a valid type, use default _Def if not. + +#if __cpp_concepts + // Implementation of the detection idiom (negative case). + template<typename _Def, template<typename...> class _Op, typename... _Args> + struct __detected_or + { + using type = _Def; + using __is_detected = false_type; + }; + + // Implementation of the detection idiom (positive case). + template<typename _Def, template<typename...> class _Op, typename... _Args> + requires requires { typename _Op<_Args...>; } + struct __detected_or<_Def, _Op, _Args...> + { + using type = _Op<_Args...>; + using __is_detected = true_type; + }; +#else /// Implementation of the detection idiom (negative case). template<typename _Default, typename _AlwaysVoid, template<typename...> class _Op, typename... _Args> struct __detector { - using value_t = false_type; using type = _Default; + using __is_detected = false_type; }; /// Implementation of the detection idiom (positive case). @@ -2571,14 +2586,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typename... _Args> struct __detector<_Default, __void_t<_Op<_Args...>>, _Op, _Args...> { - using value_t = true_type; using type = _Op<_Args...>; + using __is_detected = true_type; }; - // Detect whether _Op<_Args...> is a valid type, use _Default if not. template<typename _Default, template<typename...> class _Op, typename... _Args> using __detected_or = __detector<_Default, void, _Op, _Args...>; +#endif // __cpp_concepts // _Op<_Args...> if that is a valid type, otherwise _Default. template<typename _Default, template<typename...> class _Op, @@ -2825,7 +2840,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // The primary template is used for invalid INVOKE expressions. template<typename _Result, typename _Ret, bool = is_void<_Ret>::value, typename = void> - struct __is_invocable_impl : false_type { }; + struct __is_invocable_impl + : false_type + { + using __nothrow_type = false_type; // For is_nothrow_invocable_r + }; // Used for valid INVOKE and INVOKE<void> expressions. template<typename _Result, typename _Ret> @@ -2833,7 +2852,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /* is_void<_Ret> = */ true, __void_t<typename _Result::type>> : true_type - { }; + { + using __nothrow_type = true_type; // For is_nothrow_invocable_r + }; #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wctor-dtor-privacy" @@ -2845,23 +2866,30 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { private: // The type of the INVOKE expression. - // Unlike declval, this doesn't add_rvalue_reference. - static typename _Result::type _S_get(); + // Unlike declval, this doesn't add_rvalue_reference, so it respects + // guaranteed copy elision. + static typename _Result::type _S_get() noexcept; template<typename _Tp> - static void _S_conv(_Tp); + static void _S_conv(_Tp) noexcept; // This overload is viable if INVOKE(f, args...) can convert to _Tp. - template<typename _Tp, typename = decltype(_S_conv<_Tp>(_S_get()))> - static true_type + template<typename _Tp, bool _Check_Noex = false, + typename = decltype(_S_conv<_Tp>(_S_get())), + bool _Noex = noexcept(_S_conv<_Tp>(_S_get()))> + static __bool_constant<_Check_Noex ? _Noex : true> _S_test(int); - template<typename _Tp> + template<typename _Tp, bool = false> static false_type _S_test(...); public: + // For is_invocable_r using type = decltype(_S_test<_Ret>(1)); + + // For is_nothrow_invocable_r + using __nothrow_type = decltype(_S_test<_Ret, true>(1)); }; #pragma GCC diagnostic pop @@ -2992,15 +3020,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION }; /// @cond undocumented - template<typename _Result, typename _Ret, typename = void> - struct __is_nt_invocable_impl : false_type { }; - template<typename _Result, typename _Ret> - struct __is_nt_invocable_impl<_Result, _Ret, - __void_t<typename _Result::type>> - : __or_<is_void<_Ret>, - __is_nothrow_convertible<typename _Result::type, _Ret>>::type - { }; + using __is_nt_invocable_impl + = typename __is_invocable_impl<_Result, _Ret>::__nothrow_type; /// @endcond /// std::is_nothrow_invocable_r diff --git a/libstdc++-v3/include/std/version b/libstdc++-v3/include/std/version index 6b61879..3fd5182 100644 --- a/libstdc++-v3/include/std/version +++ b/libstdc++-v3/include/std/version @@ -309,6 +309,7 @@ #if _GLIBCXX_HOSTED #define __cpp_lib_adaptor_iterator_pair_constructor 202106L #if __cpp_constexpr_dynamic_alloc +# define __cpp_lib_constexpr_bitset 202202L # undef __cpp_lib_constexpr_memory # define __cpp_lib_constexpr_memory 202202L #endif diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py b/libstdc++-v3/python/libstdcxx/v6/printers.py index bd4289c..5a3dcbd 100644 --- a/libstdc++-v3/python/libstdcxx/v6/printers.py +++ b/libstdc++-v3/python/libstdcxx/v6/printers.py @@ -2246,12 +2246,7 @@ def build_libstdcxx_dictionary (): libstdcxx_printer.add('std::__debug::map', StdMapPrinter) libstdcxx_printer.add('std::__debug::multimap', StdMapPrinter) libstdcxx_printer.add('std::__debug::multiset', StdSetPrinter) - libstdcxx_printer.add('std::__debug::priority_queue', - StdStackOrQueuePrinter) - libstdcxx_printer.add('std::__debug::queue', StdStackOrQueuePrinter) libstdcxx_printer.add('std::__debug::set', StdSetPrinter) - libstdcxx_printer.add('std::__debug::stack', StdStackOrQueuePrinter) - libstdcxx_printer.add('std::__debug::unique_ptr', UniquePointerPrinter) libstdcxx_printer.add('std::__debug::vector', StdVectorPrinter) # These are the TR1 and C++11 printers. diff --git a/libstdc++-v3/testsuite/17_intro/headers/c++1998/all_attributes.cc b/libstdc++-v3/testsuite/17_intro/headers/c++1998/all_attributes.cc index 20cda77..b8b3747 100644 --- a/libstdc++-v3/testsuite/17_intro/headers/c++1998/all_attributes.cc +++ b/libstdc++-v3/testsuite/17_intro/headers/c++1998/all_attributes.cc @@ -38,8 +38,3 @@ #include <bits/extc++.h> #include <cxxabi.h> - -int -main() -{ -} diff --git a/libstdc++-v3/testsuite/17_intro/headers/c++2011/all_attributes.cc b/libstdc++-v3/testsuite/17_intro/headers/c++2011/all_attributes.cc index c2b4c23..222ab78 100644 --- a/libstdc++-v3/testsuite/17_intro/headers/c++2011/all_attributes.cc +++ b/libstdc++-v3/testsuite/17_intro/headers/c++2011/all_attributes.cc @@ -38,8 +38,3 @@ #include <bits/extc++.h> #include <cxxabi.h> - -int -main() -{ -} diff --git a/libstdc++-v3/testsuite/17_intro/headers/c++2014/all_attributes.cc b/libstdc++-v3/testsuite/17_intro/headers/c++2014/all_attributes.cc index f6c4251..b31d13f 100644 --- a/libstdc++-v3/testsuite/17_intro/headers/c++2014/all_attributes.cc +++ b/libstdc++-v3/testsuite/17_intro/headers/c++2014/all_attributes.cc @@ -38,8 +38,3 @@ #include <bits/extc++.h> #include <cxxabi.h> - -int -main() -{ -} diff --git a/libstdc++-v3/testsuite/17_intro/headers/c++2017/all_attributes.cc b/libstdc++-v3/testsuite/17_intro/headers/c++2017/all_attributes.cc index 170ebef..fd4d7d4 100644 --- a/libstdc++-v3/testsuite/17_intro/headers/c++2017/all_attributes.cc +++ b/libstdc++-v3/testsuite/17_intro/headers/c++2017/all_attributes.cc @@ -37,8 +37,3 @@ #include <bits/extc++.h> #include <cxxabi.h> - -int -main() -{ -} diff --git a/libstdc++-v3/testsuite/17_intro/headers/c++2020/all_attributes.cc b/libstdc++-v3/testsuite/17_intro/headers/c++2020/all_attributes.cc index 1d573a2..f700bad 100644 --- a/libstdc++-v3/testsuite/17_intro/headers/c++2020/all_attributes.cc +++ b/libstdc++-v3/testsuite/17_intro/headers/c++2020/all_attributes.cc @@ -36,8 +36,3 @@ #include <bits/extc++.h> #include <cxxabi.h> - -int -main() -{ -} diff --git a/libstdc++-v3/testsuite/17_intro/names.cc b/libstdc++-v3/testsuite/17_intro/names.cc index 82e201c..6490cd6 100644 --- a/libstdc++-v3/testsuite/17_intro/names.cc +++ b/libstdc++-v3/testsuite/17_intro/names.cc @@ -112,6 +112,7 @@ #define tmp ( #define sz ( #define token ( +#define value_t ( #if __cplusplus < 201103L #define uses_allocator ( diff --git a/libstdc++-v3/testsuite/18_support/uncaught_exception/14026.cc b/libstdc++-v3/testsuite/18_support/uncaught_exception/14026.cc index 22d4a90..bd281b9 100644 --- a/libstdc++-v3/testsuite/18_support/uncaught_exception/14026.cc +++ b/libstdc++-v3/testsuite/18_support/uncaught_exception/14026.cc @@ -28,7 +28,7 @@ static void no_uncaught () { if (std::uncaught_exception()) - abort(); + std::abort(); } int diff --git a/libstdc++-v3/testsuite/20_util/bitset/107037.cc b/libstdc++-v3/testsuite/20_util/bitset/107037.cc new file mode 100644 index 0000000..b4560dd --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/bitset/107037.cc @@ -0,0 +1,7 @@ +// { dg-options "-std=c++03" } +// { dg-do compile } +// PR libstdc++/107037 bitset::_M_do_reset fails for strict -std=c++03 mode +#include <bitset> +template class std::bitset<0>; +template class std::bitset<1>; +template class std::bitset<100>; diff --git a/libstdc++-v3/testsuite/23_containers/bitset/18604.cc b/libstdc++-v3/testsuite/20_util/bitset/18604.cc index f91cdfa..f91cdfa 100644 --- a/libstdc++-v3/testsuite/23_containers/bitset/18604.cc +++ b/libstdc++-v3/testsuite/20_util/bitset/18604.cc diff --git a/libstdc++-v3/testsuite/23_containers/bitset/45713.cc b/libstdc++-v3/testsuite/20_util/bitset/45713.cc index 5cec1b5..5cec1b5 100644 --- a/libstdc++-v3/testsuite/23_containers/bitset/45713.cc +++ b/libstdc++-v3/testsuite/20_util/bitset/45713.cc diff --git a/libstdc++-v3/testsuite/20_util/bitset/access/constexpr.cc b/libstdc++-v3/testsuite/20_util/bitset/access/constexpr.cc new file mode 100644 index 0000000..53bb07f --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/bitset/access/constexpr.cc @@ -0,0 +1,57 @@ +// { dg-options "-std=gnu++23" } +// { dg-do compile { target c++23 } } + +#include <bitset> +#include <string> +#include <testsuite_hooks.h> + +constexpr bool +test_indexing() +{ + std::bitset<100> b("10010110"); + VERIFY( b[0] == 0 ); + VERIFY( b[1] == 1 ); + const auto& cb = b; + VERIFY( cb[0] == 0 ); + VERIFY( cb[1] == 1 ); + b[1].flip(); + VERIFY( cb[1] == 0 ); + VERIFY( b[1] == 0 ); + VERIFY( ~b[1] == 1 ); + b[3] = true; + bool b3 = b[3]; + VERIFY( b3 ); + b[4] = b[3]; + return true; +} + +static_assert( test_indexing() ); + +#if _GLIBCXX_USE_CXX11_ABI +constexpr bool +test_to_string() +{ + std::string str = "01101001"; + return std::bitset<8>(str).to_string() == str; +} + +static_assert( test_to_string() ); +#endif + +constexpr bool +test_to_ulong() +{ + unsigned long val = 0xcabba123; + return std::bitset<100>(val).to_ulong() == val; +} + +static_assert( test_to_ulong() ); + +constexpr bool +test_to_ullong() +{ + unsigned long long val = 0x0123abcd0123abcd; + return std::bitset<100>(val).to_ullong() == val; +} + +static_assert( test_to_ullong() ); diff --git a/libstdc++-v3/testsuite/23_containers/bitset/to_string/dr396.cc b/libstdc++-v3/testsuite/20_util/bitset/access/dr396.cc index dfba27e..dfba27e 100644 --- a/libstdc++-v3/testsuite/23_containers/bitset/to_string/dr396.cc +++ b/libstdc++-v3/testsuite/20_util/bitset/access/dr396.cc diff --git a/libstdc++-v3/testsuite/23_containers/bitset/to_string/1.cc b/libstdc++-v3/testsuite/20_util/bitset/access/to_string.cc index 8384eb9..8384eb9 100644 --- a/libstdc++-v3/testsuite/23_containers/bitset/to_string/1.cc +++ b/libstdc++-v3/testsuite/20_util/bitset/access/to_string.cc diff --git a/libstdc++-v3/testsuite/23_containers/bitset/to_ullong/1.cc b/libstdc++-v3/testsuite/20_util/bitset/access/to_ullong.cc index 18fc077..18fc077 100644 --- a/libstdc++-v3/testsuite/23_containers/bitset/to_ullong/1.cc +++ b/libstdc++-v3/testsuite/20_util/bitset/access/to_ullong.cc diff --git a/libstdc++-v3/testsuite/23_containers/bitset/to_ulong/1.cc b/libstdc++-v3/testsuite/20_util/bitset/access/to_ulong.cc index 8163701..8163701 100644 --- a/libstdc++-v3/testsuite/23_containers/bitset/to_ulong/1.cc +++ b/libstdc++-v3/testsuite/20_util/bitset/access/to_ulong.cc diff --git a/libstdc++-v3/testsuite/23_containers/bitset/cons/1.cc b/libstdc++-v3/testsuite/20_util/bitset/cons/1.cc index c2a54c3..c2a54c3 100644 --- a/libstdc++-v3/testsuite/23_containers/bitset/cons/1.cc +++ b/libstdc++-v3/testsuite/20_util/bitset/cons/1.cc diff --git a/libstdc++-v3/testsuite/23_containers/bitset/cons/16020.cc b/libstdc++-v3/testsuite/20_util/bitset/cons/16020.cc index ffccdd2..ffccdd2 100644 --- a/libstdc++-v3/testsuite/23_containers/bitset/cons/16020.cc +++ b/libstdc++-v3/testsuite/20_util/bitset/cons/16020.cc diff --git a/libstdc++-v3/testsuite/23_containers/bitset/cons/2.cc b/libstdc++-v3/testsuite/20_util/bitset/cons/2.cc index 947124e..947124e 100644 --- a/libstdc++-v3/testsuite/23_containers/bitset/cons/2.cc +++ b/libstdc++-v3/testsuite/20_util/bitset/cons/2.cc diff --git a/libstdc++-v3/testsuite/23_containers/bitset/cons/3.cc b/libstdc++-v3/testsuite/20_util/bitset/cons/3.cc index 6308e4e..6308e4e 100644 --- a/libstdc++-v3/testsuite/23_containers/bitset/cons/3.cc +++ b/libstdc++-v3/testsuite/20_util/bitset/cons/3.cc diff --git a/libstdc++-v3/testsuite/23_containers/bitset/cons/38244.cc b/libstdc++-v3/testsuite/20_util/bitset/cons/38244.cc index 610197c..610197c 100644 --- a/libstdc++-v3/testsuite/23_containers/bitset/cons/38244.cc +++ b/libstdc++-v3/testsuite/20_util/bitset/cons/38244.cc diff --git a/libstdc++-v3/testsuite/23_containers/bitset/cons/50268.cc b/libstdc++-v3/testsuite/20_util/bitset/cons/50268.cc index 6d4b946..6d4b946 100644 --- a/libstdc++-v3/testsuite/23_containers/bitset/cons/50268.cc +++ b/libstdc++-v3/testsuite/20_util/bitset/cons/50268.cc diff --git a/libstdc++-v3/testsuite/23_containers/bitset/cons/6282.cc b/libstdc++-v3/testsuite/20_util/bitset/cons/6282.cc index 5409336..5409336 100644 --- a/libstdc++-v3/testsuite/23_containers/bitset/cons/6282.cc +++ b/libstdc++-v3/testsuite/20_util/bitset/cons/6282.cc diff --git a/libstdc++-v3/testsuite/23_containers/bitset/cons/constexpr.cc b/libstdc++-v3/testsuite/20_util/bitset/cons/constexpr.cc index bf16b19..bf16b19 100644 --- a/libstdc++-v3/testsuite/23_containers/bitset/cons/constexpr.cc +++ b/libstdc++-v3/testsuite/20_util/bitset/cons/constexpr.cc diff --git a/libstdc++-v3/testsuite/20_util/bitset/cons/constexpr_c++23.cc b/libstdc++-v3/testsuite/20_util/bitset/cons/constexpr_c++23.cc new file mode 100644 index 0000000..532fc9d --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/bitset/cons/constexpr_c++23.cc @@ -0,0 +1,55 @@ +// { dg-options "-std=gnu++23" } +// { dg-do compile { target c++23 } } + +#include <bitset> + +#ifndef __cpp_lib_constexpr_bitset +# error "Feature-test macro for constexpr bitset missing in <bitset>" +#elif __cpp_lib_constexpr_bitset != 202202L +# error "Feature-test macro for constexpr bitset has wrong value in <bitset>" +#endif + +#include <testsuite_hooks.h> + +constexpr bool test_ntbs() +{ + VERIFY( std::bitset<0>("000").all() ); + VERIFY( std::bitset<0>("000", 2).all() ); + VERIFY( std::bitset<1>("100", 2).all() ); + VERIFY( std::bitset<1>("z00", 2, 'z').none() ); + VERIFY( std::bitset<2>("ab0", 3, 'a', 'b').count() == 1 ); + + return true; +} + +static_assert( test_ntbs() ); + +#if _GLIBCXX_USE_CXX11_ABI +constexpr bool test_string() +{ + using S = std::string; + VERIFY( std::bitset<0>(S("000")).all() ); + VERIFY( std::bitset<1>(S("010"), 1, 2).all() ); + VERIFY( std::bitset<2>(S("0110"), 1, 2).all() ); + VERIFY( std::bitset<2>(S("1z110"), 1, 3, 'z').count() == 1 ); + VERIFY( std::bitset<3>(S("0abab0"), 2, 3, 'a', 'b').count() == 2 ); + + return true; +} + +static_assert( test_string() ); + +constexpr bool test_wstring() +{ + using S = std::wstring; + VERIFY( std::bitset<0>(S(L"000")).all() ); + VERIFY( std::bitset<1>(S(L"010"), 1, 2).all() ); + VERIFY( std::bitset<2>(S(L"0110"), 1, 2).all() ); + VERIFY( std::bitset<2>(S(L"1z110"), 1, 3, L'z').count() == 1 ); + VERIFY( std::bitset<3>(S(L"0abab0"), 2, 3, L'a', L'b').count() == 2 ); + + return true; +} + +static_assert( test_wstring() ); +#endif diff --git a/libstdc++-v3/testsuite/23_containers/bitset/cons/dr1325-1.cc b/libstdc++-v3/testsuite/20_util/bitset/cons/dr1325-1.cc index aa50804..aa50804 100644 --- a/libstdc++-v3/testsuite/23_containers/bitset/cons/dr1325-1.cc +++ b/libstdc++-v3/testsuite/20_util/bitset/cons/dr1325-1.cc diff --git a/libstdc++-v3/testsuite/23_containers/bitset/cons/dr1325-2.cc b/libstdc++-v3/testsuite/20_util/bitset/cons/dr1325-2.cc index 2371bef..2371bef 100644 --- a/libstdc++-v3/testsuite/23_containers/bitset/cons/dr1325-2.cc +++ b/libstdc++-v3/testsuite/20_util/bitset/cons/dr1325-2.cc diff --git a/libstdc++-v3/testsuite/23_containers/bitset/cons/dr396.cc b/libstdc++-v3/testsuite/20_util/bitset/cons/dr396.cc index f1f9d87..f1f9d87 100644 --- a/libstdc++-v3/testsuite/23_containers/bitset/cons/dr396.cc +++ b/libstdc++-v3/testsuite/20_util/bitset/cons/dr396.cc diff --git a/libstdc++-v3/testsuite/20_util/bitset/count/constexpr.cc b/libstdc++-v3/testsuite/20_util/bitset/count/constexpr.cc new file mode 100644 index 0000000..98f8e22 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/bitset/count/constexpr.cc @@ -0,0 +1,93 @@ +// { dg-options "-std=gnu++23" } +// { dg-do compile { target c++23 } } + +#include <bitset> +#include <testsuite_hooks.h> + +constexpr bool +test_counting() +{ + auto check = []<std::size_t N>(const std::bitset<N>& bs) { + VERIFY( bs.size() == N ); + unsigned count = 0; + for (unsigned n = 0; n < N; ++n) + if (bs.test(n)) + ++count; + VERIFY( count == bs.count() ); + VERIFY( bs.all() == (bs.count() == bs.size()) ); + VERIFY( bs.any() == (bs.count() != 0) ); + VERIFY( bs.none() == (bs.count() == 0) ); + return true; + }; + + std::bitset<0> z0; + VERIFY( z0.count() == 0 ); + VERIFY( check(z0) ); + z0.set(); + VERIFY( z0.count() == 0 ); + VERIFY( check(z0) ); + + std::bitset<7> z7; + VERIFY( z7.count() == 0 ); + VERIFY( check(z7) ); + z7.set(); + VERIFY( z7.count() == 7 ); + VERIFY( check(z7) ); + z7.flip(1); + VERIFY( z7.count() == 6 ); + VERIFY( check(z7) ); + + std::bitset<31> z31; + VERIFY( z31.count() == 0 ); + VERIFY( check(z31) ); + z31.set(); + VERIFY( z31.count() == 31 ); + VERIFY( check(z31) ); + z31.flip(1); + VERIFY( z31.count() == 30 ); + VERIFY( check(z31) ); + + std::bitset<32> z32; + VERIFY( z32.count() == 0 ); + VERIFY( check(z32) ); + z32.set(); + VERIFY( z32.count() == 32 ); + VERIFY( check(z32) ); + z32.flip(1); + VERIFY( z32.count() == 31 ); + VERIFY( check(z32) ); + + std::bitset<63> z63; + VERIFY( z63.count() == 0 ); + VERIFY( check(z63) ); + z63.set(); + VERIFY( z63.count() == 63 ); + VERIFY( check(z63) ); + z63.flip(1); + VERIFY( z63.count() == 62 ); + VERIFY( check(z63) ); + + std::bitset<64> z64; + VERIFY( z64.count() == 0 ); + VERIFY( check(z64) ); + z64.set(); + VERIFY( z64.count() == 64 ); + VERIFY( check(z64) ); + z64.flip(1); + VERIFY( z64.count() == 63 ); + VERIFY( check(z64) ); + + std::bitset<1000> z1k; + VERIFY( z1k.count() == 0 ); + VERIFY( check(z1k) ); + z1k.set(); + VERIFY( z1k.count() == 1000 ); + VERIFY( check(z1k) ); + z1k.flip(1); + VERIFY( z1k.count() == 999 ); + VERIFY( check(z1k) ); + + return true; +} + +static_assert( test_counting() ); diff --git a/libstdc++-v3/testsuite/23_containers/bitset/debug/invalidation/1.cc b/libstdc++-v3/testsuite/20_util/bitset/debug/invalidation/1.cc index 5d0e3c15..5d0e3c15 100644 --- a/libstdc++-v3/testsuite/23_containers/bitset/debug/invalidation/1.cc +++ b/libstdc++-v3/testsuite/20_util/bitset/debug/invalidation/1.cc diff --git a/libstdc++-v3/testsuite/23_containers/bitset/ext/15361.cc b/libstdc++-v3/testsuite/20_util/bitset/ext/15361.cc index 3924700..3924700 100644 --- a/libstdc++-v3/testsuite/23_containers/bitset/ext/15361.cc +++ b/libstdc++-v3/testsuite/20_util/bitset/ext/15361.cc diff --git a/libstdc++-v3/testsuite/20_util/bitset/ext/constexpr.cc b/libstdc++-v3/testsuite/20_util/bitset/ext/constexpr.cc new file mode 100644 index 0000000..f82e7aa --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/bitset/ext/constexpr.cc @@ -0,0 +1,32 @@ +// { dg-options "-std=gnu++23" } +// { dg-do compile { target c++23 } } + +#include <bitset> +#include <testsuite_hooks.h> + +constexpr bool +test_find() +{ + VERIFY( std::bitset<0>()._Find_first() == 0 ); + VERIFY( std::bitset<1>()._Find_first() == 1 ); + VERIFY( std::bitset<55>("001000")._Find_first() == 3 ); + VERIFY( std::bitset<66>("101000")._Find_next(3) == 5 ); + return true; +} + +static_assert( test_find() ); + +constexpr bool +test_unchecked() +{ + VERIFY( std::bitset<1>()._Unchecked_set(0).count() == 1 ); + VERIFY( std::bitset<44>()._Unchecked_set(3).count() == 1 ); + VERIFY( std::bitset<55>()._Unchecked_set(3, 0).count() == 0 ); + VERIFY( std::bitset<66>()._Unchecked_set(3, 1).count() == 1 ); + VERIFY( std::bitset<77>("111")._Unchecked_reset(1).count() == 2 ); + VERIFY( std::bitset<88>("101")._Unchecked_flip(1).count() == 3 ); + VERIFY( std::bitset<99>("010")._Unchecked_test(1) ); + return true; +} + +static_assert( test_unchecked() ); diff --git a/libstdc++-v3/testsuite/23_containers/bitset/hash/1.cc b/libstdc++-v3/testsuite/20_util/bitset/hash/1.cc index aba6b72..aba6b72 100644 --- a/libstdc++-v3/testsuite/23_containers/bitset/hash/1.cc +++ b/libstdc++-v3/testsuite/20_util/bitset/hash/1.cc diff --git a/libstdc++-v3/testsuite/23_containers/bitset/input/1.cc b/libstdc++-v3/testsuite/20_util/bitset/io/input.cc index 939861b..0f22cef 100644 --- a/libstdc++-v3/testsuite/23_containers/bitset/input/1.cc +++ b/libstdc++-v3/testsuite/20_util/bitset/io/input.cc @@ -39,7 +39,7 @@ void test01() ss.clear(); ss.str("*"); ss >> b0; - VERIFY( ss.rdstate() == ios_base::goodbit ); + VERIFY( ss.rdstate() == ios_base::goodbit ); // LWG 3199 } int main() diff --git a/libstdc++-v3/testsuite/23_containers/bitset/count/6124.cc b/libstdc++-v3/testsuite/20_util/bitset/observers/6124.cc index d08211c..d08211c 100644 --- a/libstdc++-v3/testsuite/23_containers/bitset/count/6124.cc +++ b/libstdc++-v3/testsuite/20_util/bitset/observers/6124.cc diff --git a/libstdc++-v3/testsuite/23_containers/bitset/all/1.cc b/libstdc++-v3/testsuite/20_util/bitset/observers/all.cc index 9840f25..9840f25 100644 --- a/libstdc++-v3/testsuite/23_containers/bitset/all/1.cc +++ b/libstdc++-v3/testsuite/20_util/bitset/observers/all.cc diff --git a/libstdc++-v3/testsuite/23_containers/bitset/test/1.cc b/libstdc++-v3/testsuite/20_util/bitset/observers/test.cc index 2444499..2444499 100644 --- a/libstdc++-v3/testsuite/23_containers/bitset/test/1.cc +++ b/libstdc++-v3/testsuite/20_util/bitset/observers/test.cc diff --git a/libstdc++-v3/testsuite/23_containers/bitset/operations/1.cc b/libstdc++-v3/testsuite/20_util/bitset/operations/1.cc index 5894210..5894210 100644 --- a/libstdc++-v3/testsuite/23_containers/bitset/operations/1.cc +++ b/libstdc++-v3/testsuite/20_util/bitset/operations/1.cc diff --git a/libstdc++-v3/testsuite/23_containers/bitset/operations/13838.cc b/libstdc++-v3/testsuite/20_util/bitset/operations/13838.cc index c38ccc3..c38ccc3 100644 --- a/libstdc++-v3/testsuite/23_containers/bitset/operations/13838.cc +++ b/libstdc++-v3/testsuite/20_util/bitset/operations/13838.cc diff --git a/libstdc++-v3/testsuite/23_containers/bitset/operations/2.cc b/libstdc++-v3/testsuite/20_util/bitset/operations/2.cc index a909e38..a909e38 100644 --- a/libstdc++-v3/testsuite/23_containers/bitset/operations/2.cc +++ b/libstdc++-v3/testsuite/20_util/bitset/operations/2.cc diff --git a/libstdc++-v3/testsuite/23_containers/bitset/operations/96303.cc b/libstdc++-v3/testsuite/20_util/bitset/operations/96303.cc index b1f729d..b1f729d 100644 --- a/libstdc++-v3/testsuite/23_containers/bitset/operations/96303.cc +++ b/libstdc++-v3/testsuite/20_util/bitset/operations/96303.cc diff --git a/libstdc++-v3/testsuite/23_containers/bitset/operations/constexpr-2.cc b/libstdc++-v3/testsuite/20_util/bitset/operations/constexpr-2.cc index 91098d9..91098d9 100644 --- a/libstdc++-v3/testsuite/23_containers/bitset/operations/constexpr-2.cc +++ b/libstdc++-v3/testsuite/20_util/bitset/operations/constexpr-2.cc diff --git a/libstdc++-v3/testsuite/23_containers/bitset/operations/constexpr.cc b/libstdc++-v3/testsuite/20_util/bitset/operations/constexpr.cc index 3f77003..3f77003 100644 --- a/libstdc++-v3/testsuite/23_containers/bitset/operations/constexpr.cc +++ b/libstdc++-v3/testsuite/20_util/bitset/operations/constexpr.cc diff --git a/libstdc++-v3/testsuite/20_util/bitset/operations/constexpr_c++23.cc b/libstdc++-v3/testsuite/20_util/bitset/operations/constexpr_c++23.cc new file mode 100644 index 0000000..c594dd6 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/bitset/operations/constexpr_c++23.cc @@ -0,0 +1,31 @@ +// { dg-options "-std=gnu++23" } +// { dg-do compile { target c++23 } } + +#include <bitset> +#include <testsuite_hooks.h> + +constexpr bool +test() +{ + std::bitset<16> b0; + std::bitset<16> b1 = ~b0; + VERIFY( b1.all() ); + b0 &= b1; + VERIFY( b0.none() ); + b0 |= b1; + VERIFY( b0.all() ); + b0 ^= b1; + VERIFY( b0.none() ); + b0 = b1 << 8; + VERIFY( !b0.all() && !b0.none() ); + VERIFY( ((b1 << 8) | (b1 >> 8)).all() ); + b1 <<= 8; + b1 >>= 8; + b1 >>= 8; + VERIFY( b1.none() ); + VERIFY( (~b1).all() ); + VERIFY( b1.flip().all() ); + return true; +} + +static_assert( test() ); diff --git a/libstdc++-v3/testsuite/23_containers/bitset/requirements/constexpr_functions.cc b/libstdc++-v3/testsuite/20_util/bitset/requirements/constexpr_functions.cc index a3c9047..a3c9047 100644 --- a/libstdc++-v3/testsuite/23_containers/bitset/requirements/constexpr_functions.cc +++ b/libstdc++-v3/testsuite/20_util/bitset/requirements/constexpr_functions.cc diff --git a/libstdc++-v3/testsuite/23_containers/bitset/requirements/explicit_instantiation/1.cc b/libstdc++-v3/testsuite/20_util/bitset/requirements/explicit_instantiation/1.cc index d1d8f57..d1d8f57 100644 --- a/libstdc++-v3/testsuite/23_containers/bitset/requirements/explicit_instantiation/1.cc +++ b/libstdc++-v3/testsuite/20_util/bitset/requirements/explicit_instantiation/1.cc diff --git a/libstdc++-v3/testsuite/23_containers/bitset/requirements/explicit_instantiation/1_c++0x.cc b/libstdc++-v3/testsuite/20_util/bitset/requirements/explicit_instantiation/1_c++0x.cc index 9a1c147..9a1c147 100644 --- a/libstdc++-v3/testsuite/23_containers/bitset/requirements/explicit_instantiation/1_c++0x.cc +++ b/libstdc++-v3/testsuite/20_util/bitset/requirements/explicit_instantiation/1_c++0x.cc diff --git a/libstdc++-v3/testsuite/20_util/bitset/version.cc b/libstdc++-v3/testsuite/20_util/bitset/version.cc new file mode 100644 index 0000000..7197b1e --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/bitset/version.cc @@ -0,0 +1,10 @@ +// { dg-options "-std=gnu++23" } +// { dg-do preprocess { target c++23 } } + +#include <version> + +#ifndef __cpp_lib_constexpr_bitset +# error "Feature-test macro for constexpr bitset missing in <version>" +#elif __cpp_lib_constexpr_bitset != 202202L +# error "Feature-test macro for constexpr bitset has wrong value in <version>" +#endif diff --git a/libstdc++-v3/testsuite/20_util/function/91456.cc b/libstdc++-v3/testsuite/20_util/function/91456.cc index 6b6631c..081bf20 100644 --- a/libstdc++-v3/testsuite/20_util/function/91456.cc +++ b/libstdc++-v3/testsuite/20_util/function/91456.cc @@ -17,6 +17,9 @@ // { dg-do compile { target c++17 } } +// PR 91456 +// std::function and std::is_invocable_r do not understand guaranteed elision + #include <functional> struct Immovable { diff --git a/libstdc++-v3/testsuite/23_containers/headers/bitset/synopsis.cc b/libstdc++-v3/testsuite/20_util/headers/bitset/synopsis.cc index e7ea4f8..ed5604b 100644 --- a/libstdc++-v3/testsuite/23_containers/headers/bitset/synopsis.cc +++ b/libstdc++-v3/testsuite/20_util/headers/bitset/synopsis.cc @@ -27,17 +27,26 @@ # define NOTHROW #endif +#if __cplusplus > 202002L +# define CONSTEXPR constexpr +#else +# define CONSTEXPR +#endif + namespace std { template <size_t N> class bitset; // 23.3.5.3 bitset operations: template <size_t N> + CONSTEXPR bitset<N> operator&(const bitset<N>&, const bitset<N>&) NOTHROW; template <size_t N> + CONSTEXPR bitset<N> operator|(const bitset<N>&, const bitset<N>&) NOTHROW; template <size_t N> + CONSTEXPR bitset<N> operator^(const bitset<N>&, const bitset<N>&) NOTHROW; template <class charT, class traits, size_t N> diff --git a/libstdc++-v3/testsuite/20_util/headers/memory/synopsis.cc b/libstdc++-v3/testsuite/20_util/headers/memory/synopsis.cc index 03e3f80d..15437c7 100644 --- a/libstdc++-v3/testsuite/20_util/headers/memory/synopsis.cc +++ b/libstdc++-v3/testsuite/20_util/headers/memory/synopsis.cc @@ -26,20 +26,35 @@ # define NOTHROW #endif -namespace std { +namespace std +{ +#if __cplusplus >= 201103L + template<class Ptr> struct pointer_traits; + template<class T> struct pointer_traits<T*>; + + void* align(size_t alignment, size_t size, void*& ptr, size_t& space); + + struct allocator_arg_t; + extern const allocator_arg_t allocator_arg; + + template<class T, class Alloc> struct uses_allocator; + + template<class Alloc> struct allocator_traits; +#endif // C++11 + +#if __STDC_HOSTED__ // lib.default.allocator, the default allocator: template <class T> class allocator; +#if __cplusplus >= 202002L + template <class T, class U> + constexpr bool operator==(const allocator<T>&, const allocator<U>&) throw(); +#else template <> class allocator<void>; template <class T, class U> -#if __cplusplus > 201703L - constexpr -#endif bool operator==(const allocator<T>&, const allocator<U>&) throw(); template <class T, class U> -#if __cplusplus > 201703L - constexpr -#endif bool operator!=(const allocator<T>&, const allocator<U>&) throw(); +#endif // lib.storage.iterator, raw storage iterator: template <class OutputIterator, class T> class raw_storage_iterator; @@ -49,18 +64,55 @@ namespace std { pair<T*,ptrdiff_t> get_temporary_buffer(ptrdiff_t n) NOTHROW; template <class T> void return_temporary_buffer(T* p); +#endif // HOSTED // lib.specialized.algorithms, specialized algorithms: +#if __cplusplus >= 201703L + template <class T> constexpr T* addressof(T&) noexcept; +#elif __cplusplus >= 201402L + template <class T> T* addressof(T&) noexcept; +#endif template <class InputIterator, class ForwardIterator> ForwardIterator uninitialized_copy(InputIterator first, InputIterator last, ForwardIterator result); +#if __cplusplus >= 201103L + template <class InputIterator, class Size, class ForwardIterator> + ForwardIterator + uninitialized_copy_n(InputIterator first, Size n, ForwardIterator result); +#endif template <class ForwardIterator, class T> void uninitialized_fill(ForwardIterator first, ForwardIterator last, const T& x); template <class ForwardIterator, class Size, class T> void uninitialized_fill_n(ForwardIterator first, Size n, const T& x); +#if __cplusplus >= 201103L + template<class T> class default_delete; + template<class T> class default_delete<T[]>; + template<class T, class D> class unique_ptr; + template<class T, class D> class unique_ptr<T[], D>; + template<class T, class D> + void swap(unique_ptr<T, D>&, unique_ptr<T, D>&) noexcept; +#if __cplusplus >= 201402L + template<class T, class... Args> unique_ptr<T> make_unique(Args&&...); +#endif + + class bad_weak_ptr; + template<class T> class shared_ptr; + template<class T, class... Args> shared_ptr<T> make_shared(Args&&... args); + template<class T, class A, class... Args> + shared_ptr<T> allocate_shared(const A& a, Args&&... args); + template<class T> void swap(shared_ptr<T>&, shared_ptr<T>&) noexcept; + template<class T> class weak_ptr; + template<class T> void swap(weak_ptr<T>&, weak_ptr<T>&) noexcept; + template<class T> class owner_less; + template<class T> class enable_shared_from_this; + + template<class T, class D> struct hash<unique_ptr<T, D>>; + template<class T> struct hash<shared_ptr<T>>; +#endif + // lib.auto.ptr, pointers: template<class X> class auto_ptr; } diff --git a/libstdc++-v3/testsuite/20_util/is_assignable/requirements/access.cc b/libstdc++-v3/testsuite/20_util/is_assignable/requirements/access.cc new file mode 100644 index 0000000..a96fba6 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/is_assignable/requirements/access.cc @@ -0,0 +1,22 @@ +// { dg-do compile { target c++11 } } + +#include <type_traits> + +class S { + operator int(); + friend void g(); // #1 +}; + +void +g() +{ + int i = 0; + S s; + i = s; // this works, because we're inside a friend. + + // But the traits are evaluated in "a context unrelated to either type". + static_assert( ! std::is_assignable<int&, S>::value, "unfriendly"); +#if __cplusplus >= 201703L + static_assert( ! std::is_assignable_v<int&, S>, "unfriendly"); +#endif +} diff --git a/libstdc++-v3/testsuite/20_util/is_invocable/91456.cc b/libstdc++-v3/testsuite/20_util/is_invocable/91456.cc index a946db1..976d257 100644 --- a/libstdc++-v3/testsuite/20_util/is_invocable/91456.cc +++ b/libstdc++-v3/testsuite/20_util/is_invocable/91456.cc @@ -17,6 +17,9 @@ // { dg-do compile { target c++17 } } +// PR 91456 +// std::function and std::is_invocable_r do not understand guaranteed elision + #include <type_traits> #include <functional> @@ -27,7 +30,6 @@ struct Immovable { Immovable& operator=(const Immovable&) = delete; }; -Immovable get() { return {}; } -const Immovable i = get(); // OK -std::function<const Immovable()> f{&get}; // fails -const Immovable i2 = f(); +static_assert(std::is_invocable_r_v<Immovable, Immovable(*)()>); +static_assert(std::is_invocable_r_v<const Immovable, Immovable(*)()>); +static_assert(std::is_invocable_r_v<Immovable, const Immovable(*)()>); diff --git a/libstdc++-v3/testsuite/20_util/is_nothrow_convertible/value.cc b/libstdc++-v3/testsuite/20_util/is_nothrow_convertible/value.cc index e9aded7..a268628 100644 --- a/libstdc++-v3/testsuite/20_util/is_nothrow_convertible/value.cc +++ b/libstdc++-v3/testsuite/20_util/is_nothrow_convertible/value.cc @@ -21,9 +21,7 @@ #include <type_traits> #include <testsuite_tr1.h> -#ifndef IS_NT_CONVERTIBLE_DEFINED using std::is_nothrow_convertible; -#endif void test01() { diff --git a/libstdc++-v3/testsuite/20_util/is_nothrow_convertible/value_ext.cc b/libstdc++-v3/testsuite/20_util/is_nothrow_invocable/91456.cc index 0f89642..abbbd1a 100644 --- a/libstdc++-v3/testsuite/20_util/is_nothrow_convertible/value_ext.cc +++ b/libstdc++-v3/testsuite/20_util/is_nothrow_invocable/91456.cc @@ -15,14 +15,21 @@ // with this library; see the file COPYING3. If not see // <http://www.gnu.org/licenses/>. -// { dg-do compile { target c++11 } } +// { dg-do compile { target c++17 } } + +// PR 91456 +// std::function and std::is_invocable_r do not understand guaranteed elision #include <type_traits> -// Test the non-standard __is_nothrow_convertible trait +#include <functional> -template<typename From, typename To> - using is_nothrow_convertible = std::__is_nothrow_convertible<From, To>; +struct Immovable { + Immovable() = default; + Immovable(const Immovable&) = delete; + Immovable& operator=(const Immovable&) = delete; +}; -#define IS_NT_CONVERTIBLE_DEFINED -#include "value.cc" +static_assert(std::is_nothrow_invocable_r_v<Immovable, Immovable(*)() noexcept>); +static_assert(std::is_nothrow_invocable_r_v<const Immovable, Immovable(*)() noexcept>); +static_assert(std::is_nothrow_invocable_r_v<Immovable, const Immovable(*)() noexcept>); |