diff options
author | Martin Liska <mliska@suse.cz> | 2022-01-28 14:08:09 +0100 |
---|---|---|
committer | Martin Liska <mliska@suse.cz> | 2022-01-28 14:08:09 +0100 |
commit | f015156d6662c3ce367c5834eb109a0a77b56f39 (patch) | |
tree | e296374325c59068a60eb7a6b9ec721d1c931750 /gcc | |
parent | 58446a69f792166ea2e12d44d5bb3ef1aa61c00d (diff) | |
parent | 9ec306582fd60e5b76f07eb81c9ed2415d9a3590 (diff) | |
download | gcc-f015156d6662c3ce367c5834eb109a0a77b56f39.zip gcc-f015156d6662c3ce367c5834eb109a0a77b56f39.tar.gz gcc-f015156d6662c3ce367c5834eb109a0a77b56f39.tar.bz2 |
Merge branch 'master' into devel/sphinx
Diffstat (limited to 'gcc')
154 files changed, 2977 insertions, 391 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3a7842c..7b9ef63 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,279 @@ +2022-01-27 Patrick Palka <ppalka@redhat.com> + + PR c++/99895 + * tree.cc (build_call_vec): Add const to second parameter. + * tree.h (build_call_vec): Likewise. + +2022-01-27 Martin Liska <mliska@suse.cz> + + PR web/104254 + * diagnostic.cc (diagnostic_initialize): + Initialize report_bug flag. + (diagnostic_action_after_output): + Explain that -freport-bug option can be used for pre-processed + file creation. Make the message shorter. + (error_recursion): Rename Internal to internal. + * diagnostic.h (struct diagnostic_context): New field. + * opts.cc (common_handle_option): Init the field here. + +2022-01-27 Kewen Lin <linkw@linux.ibm.com> + + PR target/103702 + * config/rs6000/rs6000.cc + (rs6000_cost_data::update_target_cost_per_stmt): Fix one wrong + assertion with early return. + +2022-01-27 Chung-Lin Tang <cltang@codesourcery.com> + + PR middle-end/103642 + * gimplify.cc (gimplify_scan_omp_clauses): Do not do indir_p handling + for non-pointer or non-reference-to-pointer cases. + +2022-01-27 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/104196 + * gimple-fold.h (rewrite_to_defined_overflow): Add IN_PLACE argument. + * gimple-fold.cc (rewrite_to_defined_overflow): Likewise. If true, + return NULL and emit needed stmts before and after stmt. + * tree-ssa-reassoc.cc (update_range_test): For inter-bb range opt + pick as operand_entry that will hold the merged test the one feeding + earliest condition, ensure that by swapping range->idx with some + other range's idx if needed. If seq is non-NULL, don't actually swap + it but instead rewrite stmts with undefined overflow in between + the two locations. + (maybe_optimize_range_tests): Set ops[]->id to bb->index with the + corresponding condition even if they have non-NULL ops[]->op. + Formatting fix. + +2022-01-26 Jakub Jelinek <jakub@redhat.com> + + PR target/104239 + * config/rs6000/emmintrin.h (_mm_sad_epu8): Use __asm__ instead of + asm. + * config/rs6000/smmintrin.h (_mm_minpos_epu16): Declare iterator + before for loop instead of for init clause. + * config/rs6000/bmi2intrin.h (_pext_u64): Likewise. + +2022-01-26 Jakub Jelinek <jakub@redhat.com> + + PR target/104239 + * config/rs6000/bmiintrin.h: Test _X86GPRINTRIN_H_INCLUDED instead of + _X86INTRIN_H_INCLUDED and adjust #error wording. + * config/rs6000/bmi2intrin.h: Likewise. + +2022-01-26 Jakub Jelinek <jakub@redhat.com> + + PR debug/104194 + * dwarf2out.cc (long_double_as_float128): New function. + (modified_type_die): For powerpc64le IEEE 754 quad long double + and complex long double emit those as DW_TAG_typedef to + _Float128 or complex _Float128 base type. + +2022-01-26 Marek Polacek <polacek@redhat.com> + + PR target/104213 + * gimple-ssa-warn-access.cc (pass_waccess::warn_invalid_pointer): Don't + warn when the SSA_NAME_VAR of REF has supressed -Wuse-after-free. + +2022-01-26 Martin Liska <mliska@suse.cz> + + * ipa-modref-tree.cc (modref_access_node::update): + Remove "--param param=foo" with "--param foo". + (modref_access_node::insert): Likewise. + (modref_access_node::insert_kill): Likewise. + * ipa-modref-tree.h (struct modref_ref_node): Likewise. + (struct modref_base_node): Likewise. + (struct modref_tree): Likewise. + +2022-01-26 Raoni Fassina Firmino <raoni@linux.ibm.com> + + PR target/94193 + * builtins.cc (expand_builtin_feclear_feraise_except): Add op0 + predicate check. + +2022-01-25 Martin Sebor <msebor@redhat.com> + + PR tree-optimization/104203 + * gimple-ssa-warn-access.cc (pass_data pass_data_waccess): Use + TV_WARN_ACCESS. + * pointer-query.cc (access_ref::merge_ref): Change return type. + Convert failure to a conservative success. + (access_ref::get_ref): Adjust to the change above. Short-circuit + PHI evaluation after first failure turned into conservative success. + * pointer-query.h (access_ref::merge_ref): Change return type. + * timevar.def (TV_WARN_ACCESS): New timer variable. + +2022-01-25 David Edelsohn <dje.gcc@gmail.com> + + * config/rs6000/aix.h (OPTION_GLIBC): Define as 0. + +2022-01-25 Richard Biener <rguenther@suse.de> + + PR tree-optimization/104214 + * tree-ssa-loop-niter.cc (number_of_iterations_cond): Use + stronger guarantees for relational pointer compares when + rewriting BASE0 + STEP0 cmp BASE1 + STEP1 as + BASE0 + STEP0 - STEP1 cmp BASE1. + +2022-01-25 Jakub Jelinek <jakub@redhat.com> + + PR target/104172 + * config/rs6000/rs6000-internal.h (rs6000_passes_ieee128): Don't + declare. + * config/rs6000/rs6000.cc (rs6000_passes_ieee128, + ieee128_mangling_gcc_8_1): Remove. + (TARGET_ASM_GLOBALIZE_DECL_NAME): Don't redefine. + (rs6000_mangle_type): Return "u9__ieee128" instead of + ieee128_mangling_gcc_8_1 ? "U10__float128" : "u9__ieee128". + (rs6000_globalize_decl_name): Remove. + * config/rs6000/rs6000-call.cc (init_cumulative_args, + rs6000_function_arg_advance_1): Don't set rs6000_passes_ieee128. + +2022-01-24 Martin Sebor <msebor@redhat.com> + + * pointer-query.cc (pointer_query::dump): Remove duplicate + block. + +2022-01-24 Marek Polacek <polacek@redhat.com> + + PR preprocessor/104030 + * doc/invoke.texi: Update documentation for -Wbidi-chars. + +2022-01-24 Raoni Fassina Firmino <raoni@linux.ibm.com> + + PR target/94193 + * builtins.cc (expand_builtin_fegetround): New function. + (expand_builtin_feclear_feraise_except): New function. + (expand_builtin): Add cases for BUILT_IN_FEGETROUND, + BUILT_IN_FECLEAREXCEPT and BUILT_IN_FERAISEEXCEPT. + * config/rs6000/rs6000.md (fegetroundsi): New pattern. + (feclearexceptsi): New Pattern. + (feraiseexceptsi): New Pattern. + * doc/extend.texi: Add a new introductory paragraph about the + new builtins. + * doc/md.texi: (fegetround@var{m}): Document new optab. + (feclearexcept@var{m}): Document new optab. + (feraiseexcept@var{m}): Document new optab. + * optabs.def (fegetround_optab): New optab. + (feclearexcept_optab): New optab. + (feraiseexcept_optab): New optab. + +2022-01-24 Richard Biener <rguenther@suse.de> + Jiufu Guo <guojiufu@linux.ibm.com> + + PR tree-optimization/100740 + PR tree-optimization/101508 + PR tree-optimization/101972 + PR tree-optimization/102131 + * tree-ssa-loop-niter.cc (number_of_iterations_cond): Properly + constrain BASE0 + STEP0 cmp BASE1 + STEP1 to + BASE0 + STEP0 - STEP1 cmp BASE1 transform. + +2022-01-24 Jakub Jelinek <jakub@redhat.com> + + PR sanitizer/104158 + * opt-functions.awk (var_set): Handle EnumBitSet property. + * optc-gen.awk: Don't disallow RejectNegative if EnumBitSet is + specified. + * opts.h (enum cl_enum_var_value): New type. + * opts-common.cc (decode_cmdline_option): Use CLEV_* values. + Handle CLEV_BITSET. + (cmdline_handle_error): Handle CLEV_BITSET. + * opts.cc (test_enum_sets): Also test EnumBitSet requirements. + * doc/options.texi (EnumBitSet): Document. + * common.opt (fsanitize-coverage=): Use EnumBitSet instead of + EnumSet. + (trace-pc, trace-cmp): Drop Set properties. + +2022-01-24 Jakub Jelinek <jakub@redhat.com> + + PR sanitizer/104158 + * common.opt (flag_sanitize_coverage): Remove Variable entry. + (fsanitize-coverage=): Remove RejectNegative property, add + Var(flag_sanitize_coverage) and EnumSet properties. + (trace-pc): Add Set(1) property. + (trace-cmp): Add Set(2) property. + * opts.cc (common_handle_option): Don't handle + OPT_fsanitize_coverage_. + +2022-01-24 Jakub Jelinek <jakub@redhat.com> + + PR sanitizer/104158 + * opt-functions.awk (var_set): Handle EnumSet property. + * optc-gen.awk: Don't disallow RejectNegative if EnumSet is + specified. + * opt-read.awk: Handle Set property. + * opts.h (CL_ENUM_SET_SHIFT, CL_ERR_ENUM_SET_ARG): Define. + (struct cl_decoded_option): Mention enum in value description. + Add mask member. + (set_option): Add mask argument defaulted to 0. + * opts.cc (test_enum_sets): New function. + (opts_cc_tests): Call it. + * opts-common.cc (enum_arg_to_value): Change return argument + from bool to int, on success return index into the cl_enum_arg + array, on failure -1. Add len argument, if non-0, use strncmp + instead of strcmp. + (opt_enum_arg_to_value): Adjust caller. + (decode_cmdline_option): Handle EnumSet represented as + CLVC_ENUM with non-zero var_value. Initialize decoded->mask. + (decode_cmdline_options_to_array): CLear opt_array[0].mask. + (handle_option): Pass decoded->mask to set_options last argument. + (generate_option): Clear decoded->mask. + (generate_option_input_file): Likewise. + (cmdline_handle_error): Handle CL_ERR_ENUM_SET_ARG. + (set_option): Add mask argument, use it for CLVC_ENUM. + (control_warning_option): Adjust enum_arg_to_value caller. + * doc/options.texi: Document Set and EnumSet properties. + +2022-01-24 Jakub Jelinek <jakub@redhat.com> + + PR bootstrap/104170 + * config/linux.h (OPTION_GLIBC_P, OPTION_UCLIBC_P, + OPTION_BIONIC_P, OPTION_MUSL_P): Define. + (OPTION_GLIBC, OPTION_UCLIBC, OPTION_BIONIC, OPTION_MUSL): Redefine + using OPTION_*_P macros. + * config/alpha/linux.h (OPTION_GLIBC_P, OPTION_UCLIBC_P, + OPTION_BIONIC_P, OPTION_MUSL_P): Define. + (OPTION_GLIBC, OPTION_UCLIBC, OPTION_BIONIC, OPTION_MUSL): Redefine + using OPTION_*_P macros. + * config/rs6000/linux.h (OPTION_GLIBC_P, OPTION_UCLIBC_P, + OPTION_BIONIC_P, OPTION_MUSL_P): Define. + (OPTION_GLIBC, OPTION_UCLIBC, OPTION_BIONIC, OPTION_MUSL): Redefine + using OPTION_*_P macros. + * config/rs6000/linux64.h (OPTION_GLIBC_P, OPTION_UCLIBC_P, + OPTION_BIONIC_P, OPTION_MUSL_P): Define. + (OPTION_GLIBC, OPTION_UCLIBC, OPTION_BIONIC, OPTION_MUSL): Redefine + using OPTION_*_P macros. + * config/fuchsia.h (OPTION_MUSL_P): Redefine. + * config/glibc-stdint.h (OPTION_MUSL_P): Define if not defined. + * common/config/s390/s390-common.cc (s390_supports_split_stack): Re-add + ATTRIBUTE_UNUSED to opts parameter. If OPTION_GLIBC_P is defined, use + OPTION_GLIBC_P (opts) as condition, otherwise assume if (false). + * common/config/i386/i386-common.cc (ix86_supports_split_stack): If + OPTION_GLIBC_P is defined use !OPTION_GLIBC_P (opts) as condition, + otherwise assume if (true). + +2022-01-24 Kito Cheng <kito.cheng@sifive.com> + + * common/config/riscv/riscv-common.cc (riscv_subset_list::to_string): + Skip zicsr and zifencei if I-ext is 2.0. + +2022-01-24 Jia-Wei Chen <jiawei@iscas.ac.cn> + + * config.gcc: Modify default isa_spec version. + +2022-01-24 Jiufu Guo <guojiufu@linux.ibm.com> + + PR tree-optimization/102087 + * tree-ssa-loop-niter.cc (number_of_iterations_until_wrap): + Correct PLUS result type. + +2022-01-24 H.J. Lu <hjl.tools@gmail.com> + + PR target/104188 + * config/i386/predicates.md (bcst_mem_operand): Also check mode + of memory broadcast. + 2022-01-23 Andrew Pinski <apinski@marvell.com> PR target/64821 diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index da164bf..5f74118 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20220124 +20220128 diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb index c31f5bb..2506c67 100644 --- a/gcc/ada/exp_ch4.adb +++ b/gcc/ada/exp_ch4.adb @@ -14314,9 +14314,13 @@ package body Exp_Ch4 is return; end if; - -- Finally, rewrite the operation in the narrower type + -- Finally, rewrite the operation in the narrower type, but make sure + -- not to perform name resolution for the operator again. Nop := New_Op_Node (Kind, Sloc (N)); + if Nkind (N) in N_Has_Entity then + Set_Entity (Nop, Entity (N)); + end if; if Binary then Set_Left_Opnd (Nop, Convert_To (Ntyp, L)); diff --git a/gcc/analyzer/ChangeLog b/gcc/analyzer/ChangeLog index 4df447d..167f1b8 100644 --- a/gcc/analyzer/ChangeLog +++ b/gcc/analyzer/ChangeLog @@ -1,3 +1,77 @@ +2022-01-27 David Malcolm <dmalcolm@redhat.com> + + * checker-path.cc (event_kind_to_string): Handle + EK_REGION_CREATION. + (region_creation_event::region_creation_event): New. + (region_creation_event::get_desc): New. + (checker_path::add_region_creation_event): New. + * checker-path.h (enum event_kind): Add EK_REGION_CREATION. + (class region_creation_event): New subclass. + (checker_path::add_region_creation_event): New decl. + * diagnostic-manager.cc + (diagnostic_manager::emit_saved_diagnostic): Pass NULL for new + param to add_events_for_eedge when handling trailing eedge. + (diagnostic_manager::build_emission_path): Create an interesting_t + instance, allow the pending diagnostic to populate it, and pass it + to the calls to add_events_for_eedge. + (diagnostic_manager::add_events_for_eedge): Add "interest" param. + Use it to add region_creation_events for on-stack regions created + within at function entry, and when pertinent dynamically-sized + regions are created. + (diagnostic_manager::prune_for_sm_diagnostic): Add case for + EK_REGION_CREATION. + * diagnostic-manager.h (diagnostic_manager::add_events_for_eedge): + Add "interest" param. + * pending-diagnostic.cc: Include "selftest.h", "tristate.h", + "analyzer/call-string.h", "analyzer/program-point.h", + "analyzer/store.h", and "analyzer/region-model.h". + (interesting_t::add_region_creation): New. + (interesting_t::dump_to_pp): New. + * pending-diagnostic.h (struct interesting_t): New. + (pending_diagnostic::mark_interesting_stuff): New vfunc. + * region-model.cc + (poisoned_value_diagnostic::poisoned_value_diagnostic): Add + (poisoned_value_diagnostic::operator==): Compare m_pkind and + m_src_region fields. + (poisoned_value_diagnostic::mark_interesting_stuff): New. + (poisoned_value_diagnostic::m_src_region): New. + (region_model::check_for_poison): Call + get_region_for_poisoned_expr for uninit values and pass the resul + to the diagnostic. + (region_model::get_region_for_poisoned_expr): New. + (region_model::deref_rvalue): Pass NULL for + poisoned_value_diagnostic's src_region. + * region-model.h (region_model::get_region_for_poisoned_expr): New + decl. + * region.h (frame_region::get_fndecl): New. + +2022-01-27 Martin Liska <mliska@suse.cz> + + PR analyzer/104247 + * constraint-manager.cc (bounded_ranges_manager::log_stats): + Cast to long for format purpose. + * region-model-manager.cc (log_uniq_map): Likewise. + +2022-01-26 David Malcolm <dmalcolm@redhat.com> + + PR analyzer/104224 + * region-model.cc (region_model::check_call_args): New. + (region_model::on_call_pre): Call it when ignoring stdio builtins. + * region-model.h (region_model::check_call_args): New decl + +2022-01-26 David Malcolm <dmalcolm@redhat.com> + + PR analyzer/94362 + * constraint-manager.cc (range::add_bound): Fix tests for + discarding redundant constraints. Perform test for rejecting + unsatisfiable constraints earlier so that they don't update + the object on failure. + (selftest::test_range): New. + (selftest::test_constant_comparisons): Add test coverage for + existing constraints becoming narrower until they are + unsatisfiable. + (selftest::run_constraint_manager_tests): Call test_range. + 2022-01-22 David Malcolm <dmalcolm@redhat.com> PR analyzer/104159 diff --git a/gcc/analyzer/checker-path.cc b/gcc/analyzer/checker-path.cc index 89f2cad..779ff80 100644 --- a/gcc/analyzer/checker-path.cc +++ b/gcc/analyzer/checker-path.cc @@ -81,6 +81,8 @@ event_kind_to_string (enum event_kind ek) return "EK_CUSTOM"; case EK_STMT: return "EK_STMT"; + case EK_REGION_CREATION: + return "EK_REGION_CREATION"; case EK_FUNCTION_ENTRY: return "EK_FUNCTION_ENTRY"; case EK_STATE_CHANGE: @@ -199,6 +201,34 @@ statement_event::get_desc (bool) const return label_text::take (xstrdup (pp_formatted_text (&pp))); } +/* class region_creation_event : public checker_event. */ + +region_creation_event::region_creation_event (const region *reg, + location_t loc, + tree fndecl, + int depth) +: checker_event (EK_REGION_CREATION, loc, fndecl, depth), + m_reg (reg) +{ +} + +/* Implementation of diagnostic_event::get_desc vfunc for + region_creation_event. */ + +label_text +region_creation_event::get_desc (bool) const +{ + switch (m_reg->get_memory_space ()) + { + default: + return label_text::borrow ("region created here"); + case MEMSPACE_STACK: + return label_text::borrow ("region created on stack here"); + case MEMSPACE_HEAP: + return label_text::borrow ("region created on heap here"); + } +} + /* class function_entry_event : public checker_event. */ /* Implementation of diagnostic_event::get_desc vfunc for @@ -991,6 +1021,17 @@ checker_path::debug () const } } +/* Add region_creation_event instance to this path for REG, + describing whether REG is on the stack or heap. */ + +void +checker_path::add_region_creation_event (const region *reg, + location_t loc, + tree fndecl, int depth) +{ + add_event (new region_creation_event (reg, loc, fndecl, depth)); +} + /* Add a warning_event to the end of this path. */ void diff --git a/gcc/analyzer/checker-path.h b/gcc/analyzer/checker-path.h index c7bd39d..d37c999 100644 --- a/gcc/analyzer/checker-path.h +++ b/gcc/analyzer/checker-path.h @@ -31,6 +31,7 @@ enum event_kind EK_DEBUG, EK_CUSTOM, EK_STMT, + EK_REGION_CREATION, EK_FUNCTION_ENTRY, EK_STATE_CHANGE, EK_START_CFG_EDGE, @@ -58,6 +59,7 @@ extern const char *event_kind_to_string (enum event_kind ek); custom_event (EK_CUSTOM) precanned_custom_event statement_event (EK_STMT) + region_creation_event (EK_REGION_CREATION) function_entry_event (EK_FUNCTION_ENTRY) state_change_event (EK_STATE_CHANGE) superedge_event @@ -194,6 +196,21 @@ public: const program_state m_dst_state; }; +/* A concrete event subclass describing the creation of a region that + is significant for a diagnostic e.g. "region created on stack here". */ + +class region_creation_event : public checker_event +{ +public: + region_creation_event (const region *reg, + location_t loc, tree fndecl, int depth); + + label_text get_desc (bool) const FINAL OVERRIDE; + +private: + const region *m_reg; +}; + /* An event subclass describing the entry to a function. */ class function_entry_event : public checker_event @@ -561,6 +578,10 @@ public: m_events[idx] = new_event; } + void add_region_creation_event (const region *reg, + location_t loc, + tree fndecl, int depth); + void add_final_event (const state_machine *sm, const exploded_node *enode, const gimple *stmt, tree var, state_machine::state_t state); diff --git a/gcc/analyzer/constraint-manager.cc b/gcc/analyzer/constraint-manager.cc index 7c4a85b..ac1e4fe 100644 --- a/gcc/analyzer/constraint-manager.cc +++ b/gcc/analyzer/constraint-manager.cc @@ -318,35 +318,42 @@ range::add_bound (bound b, enum bound_kind bound_kind) if (m_lower_bound.m_constant) { m_lower_bound.ensure_closed (BK_LOWER); - if (!tree_int_cst_lt (b.m_constant, - m_lower_bound.m_constant)) + if (tree_int_cst_le (b.m_constant, + m_lower_bound.m_constant)) return true; } + if (m_upper_bound.m_constant) + { + m_upper_bound.ensure_closed (BK_UPPER); + /* Reject B <= V <= UPPER when B > UPPER. */ + if (!tree_int_cst_le (b.m_constant, + m_upper_bound.m_constant)) + return false; + } m_lower_bound = b; break; + case BK_UPPER: /* Discard redundant bounds. */ if (m_upper_bound.m_constant) { m_upper_bound.ensure_closed (BK_UPPER); - if (tree_int_cst_le (b.m_constant, - m_upper_bound.m_constant)) + if (!tree_int_cst_lt (b.m_constant, + m_upper_bound.m_constant)) return true; } + if (m_lower_bound.m_constant) + { + m_lower_bound.ensure_closed (BK_LOWER); + /* Reject LOWER <= V <= B when LOWER > B. */ + if (!tree_int_cst_le (m_lower_bound.m_constant, + b.m_constant)) + return false; + } m_upper_bound = b; break; } - if (m_lower_bound.m_constant - && m_upper_bound.m_constant) - { - m_lower_bound.ensure_closed (BK_LOWER); - m_upper_bound.ensure_closed (BK_UPPER); - /* Reject LOWER <= V <= UPPER when LOWER > UPPER. */ - if (!tree_int_cst_le (m_lower_bound.m_constant, - m_upper_bound.m_constant)) - return false; - } return true; } @@ -1024,7 +1031,7 @@ void bounded_ranges_manager::log_stats (logger *logger, bool show_objs) const { LOG_SCOPE (logger); - logger->log (" # %s: %li", "ranges", m_map.elements ()); + logger->log (" # %s: %li", "ranges", (long)m_map.elements ()); if (!show_objs) return; @@ -3093,6 +3100,49 @@ namespace selftest { These have to be written in terms of a region_model, since the latter is responsible for managing svalue instances. */ +/* Verify that range::add_bound works as expected. */ + +static void +test_range () +{ + tree int_0 = build_int_cst (integer_type_node, 0); + tree int_1 = build_int_cst (integer_type_node, 1); + tree int_2 = build_int_cst (integer_type_node, 2); + tree int_5 = build_int_cst (integer_type_node, 5); + + { + range r; + ASSERT_FALSE (r.constrained_to_single_element ()); + + /* (r >= 1). */ + ASSERT_TRUE (r.add_bound (GE_EXPR, int_1)); + + /* Redundant. */ + ASSERT_TRUE (r.add_bound (GE_EXPR, int_0)); + ASSERT_TRUE (r.add_bound (GT_EXPR, int_0)); + + ASSERT_FALSE (r.constrained_to_single_element ()); + + /* Contradiction. */ + ASSERT_FALSE (r.add_bound (LT_EXPR, int_1)); + + /* (r < 5). */ + ASSERT_TRUE (r.add_bound (LT_EXPR, int_5)); + ASSERT_FALSE (r.constrained_to_single_element ()); + + /* Contradiction. */ + ASSERT_FALSE (r.add_bound (GE_EXPR, int_5)); + + /* (r < 2). */ + ASSERT_TRUE (r.add_bound (LT_EXPR, int_2)); + ASSERT_TRUE (r.constrained_to_single_element ()); + + /* Redundant. */ + ASSERT_TRUE (r.add_bound (LE_EXPR, int_1)); + ASSERT_TRUE (r.constrained_to_single_element ()); + } +} + /* Verify that setting and getting simple conditions within a region_model work (thus exercising the underlying constraint_manager). */ @@ -3702,6 +3752,20 @@ test_constant_comparisons () } { region_model model (&mgr); + ADD_SAT_CONSTRAINT (model, int_1, LT_EXPR, a); + ADD_SAT_CONSTRAINT (model, int_3, LT_EXPR, a); + ADD_SAT_CONSTRAINT (model, a, LT_EXPR, int_5); + ADD_UNSAT_CONSTRAINT (model, a, LT_EXPR, int_4); + } + { + region_model model (&mgr); + ADD_SAT_CONSTRAINT (model, int_1, LT_EXPR, a); + ADD_SAT_CONSTRAINT (model, a, LT_EXPR, int_5); + ADD_SAT_CONSTRAINT (model, int_3, LT_EXPR, a); + ADD_UNSAT_CONSTRAINT (model, a, LT_EXPR, int_4); + } + { + region_model model (&mgr); ADD_SAT_CONSTRAINT (model, a, LT_EXPR, int_4); ADD_UNSAT_CONSTRAINT (model, int_3, LT_EXPR, a); } @@ -4323,6 +4387,7 @@ run_constraint_manager_tests (bool transitivity) int saved_flag_analyzer_transitivity = flag_analyzer_transitivity; flag_analyzer_transitivity = transitivity; + test_range (); test_constraint_conditions (); if (flag_analyzer_transitivity) { diff --git a/gcc/analyzer/diagnostic-manager.cc b/gcc/analyzer/diagnostic-manager.cc index 73c133d..80bca6a 100644 --- a/gcc/analyzer/diagnostic-manager.cc +++ b/gcc/analyzer/diagnostic-manager.cc @@ -1222,7 +1222,7 @@ diagnostic_manager::emit_saved_diagnostic (const exploded_graph &eg, trailing eedge stashed, add any events for it. This is for use in handling longjmp, to show where a longjmp is rewinding to. */ if (sd.m_trailing_eedge) - add_events_for_eedge (pb, *sd.m_trailing_eedge, &emission_path); + add_events_for_eedge (pb, *sd.m_trailing_eedge, &emission_path, NULL); emission_path.prepare_for_emission (sd.m_d); @@ -1269,10 +1269,13 @@ diagnostic_manager::build_emission_path (const path_builder &pb, checker_path *emission_path) const { LOG_SCOPE (get_logger ()); + + interesting_t interest; + pb.get_pending_diagnostic ()->mark_interesting_stuff (&interest); for (unsigned i = 0; i < epath.m_edges.length (); i++) { const exploded_edge *eedge = epath.m_edges[i]; - add_events_for_eedge (pb, *eedge, emission_path); + add_events_for_eedge (pb, *eedge, emission_path, &interest); } } @@ -1580,10 +1583,12 @@ struct null_assignment_sm_context : public sm_context void diagnostic_manager::add_events_for_eedge (const path_builder &pb, const exploded_edge &eedge, - checker_path *emission_path) const + checker_path *emission_path, + interesting_t *interest) const { const exploded_node *src_node = eedge.m_src; const program_point &src_point = src_node->get_point (); + const int src_stack_depth = src_point.get_stack_depth (); const exploded_node *dst_node = eedge.m_dest; const program_point &dst_point = dst_node->get_point (); const int dst_stack_depth = dst_point.get_stack_depth (); @@ -1645,6 +1650,29 @@ diagnostic_manager::add_events_for_eedge (const path_builder &pb, (dst_point.get_supernode ()->get_start_location (), dst_point.get_fndecl (), dst_stack_depth)); + /* Create region_creation_events for on-stack regions within + this frame. */ + if (interest) + { + unsigned i; + const region *reg; + FOR_EACH_VEC_ELT (interest->m_region_creation, i, reg) + if (const frame_region *frame = reg->maybe_get_frame_region ()) + if (frame->get_fndecl () == dst_point.get_fndecl ()) + { + const region *base_reg = reg->get_base_region (); + if (tree decl = base_reg->maybe_get_decl ()) + if (DECL_P (decl) + && DECL_SOURCE_LOCATION (decl) != UNKNOWN_LOCATION) + { + emission_path->add_region_creation_event + (reg, + DECL_SOURCE_LOCATION (decl), + dst_point.get_fndecl (), + dst_stack_depth); + } + } + } } break; case PK_BEFORE_STMT: @@ -1700,6 +1728,42 @@ diagnostic_manager::add_events_for_eedge (const path_builder &pb, == dst_node->m_succs[0]->m_dest->get_point ()))) break; } + + /* Look for changes in dynamic extents, which will identify + the creation of heap-based regions and alloca regions. */ + if (interest) + { + const region_model *src_model = src_state.m_region_model; + const region_model *dst_model = dst_state.m_region_model; + if (src_model->get_dynamic_extents () + != dst_model->get_dynamic_extents ()) + { + unsigned i; + const region *reg; + FOR_EACH_VEC_ELT (interest->m_region_creation, i, reg) + { + const region *base_reg = reg->get_base_region (); + const svalue *old_extents + = src_model->get_dynamic_extents (base_reg); + const svalue *new_extents + = dst_model->get_dynamic_extents (base_reg); + if (old_extents == NULL && new_extents != NULL) + switch (base_reg->get_kind ()) + { + default: + break; + case RK_HEAP_ALLOCATED: + case RK_ALLOCA: + emission_path->add_region_creation_event + (reg, + src_point.get_location (), + src_point.get_fndecl (), + src_stack_depth); + break; + } + } + } + } } } break; @@ -2004,6 +2068,10 @@ diagnostic_manager::prune_for_sm_diagnostic (checker_path *path, } break; + case EK_REGION_CREATION: + /* Don't filter these. */ + break; + case EK_FUNCTION_ENTRY: if (m_verbosity < 1) { diff --git a/gcc/analyzer/diagnostic-manager.h b/gcc/analyzer/diagnostic-manager.h index dd89182..cfc0d86 100644 --- a/gcc/analyzer/diagnostic-manager.h +++ b/gcc/analyzer/diagnostic-manager.h @@ -141,7 +141,8 @@ private: void add_events_for_eedge (const path_builder &pb, const exploded_edge &eedge, - checker_path *emission_path) const; + checker_path *emission_path, + interesting_t *interest) const; bool significant_edge_p (const path_builder &pb, const exploded_edge &eedge) const; diff --git a/gcc/analyzer/pending-diagnostic.cc b/gcc/analyzer/pending-diagnostic.cc index e35fb61..5e0ea4c 100644 --- a/gcc/analyzer/pending-diagnostic.cc +++ b/gcc/analyzer/pending-diagnostic.cc @@ -33,11 +33,43 @@ along with GCC; see the file COPYING3. If not see #include "diagnostic-event-id.h" #include "analyzer/sm.h" #include "analyzer/pending-diagnostic.h" +#include "selftest.h" +#include "tristate.h" +#include "analyzer/call-string.h" +#include "analyzer/program-point.h" +#include "analyzer/store.h" +#include "analyzer/region-model.h" #if ENABLE_ANALYZER namespace ana { +/* struct interesting_t. */ + +/* Mark the creation of REG as being interesting. */ + +void +interesting_t::add_region_creation (const region *reg) +{ + gcc_assert (reg); + m_region_creation.safe_push (reg); +} + +void +interesting_t::dump_to_pp (pretty_printer *pp, bool simple) const +{ + pp_string (pp, "{ region creation: ["); + unsigned i; + const region *reg; + FOR_EACH_VEC_ELT (m_region_creation, i, reg) + { + if (i > 0) + pp_string (pp, ", "); + reg->dump_to_pp (pp, simple); + } + pp_string (pp, "]}"); +} + /* Generate a label_text by printing FMT. Use a clone of the global_dc for formatting callbacks. diff --git a/gcc/analyzer/pending-diagnostic.h b/gcc/analyzer/pending-diagnostic.h index 2bc8c1c..5a407c8 100644 --- a/gcc/analyzer/pending-diagnostic.h +++ b/gcc/analyzer/pending-diagnostic.h @@ -23,6 +23,22 @@ along with GCC; see the file COPYING3. If not see namespace ana { +/* A bundle of information about things that are of interest to a + pending_diagnostic. + + For now, merely the set of regions that are pertinent to the + diagnostic, so that we can notify the user about when they + were created. */ + +struct interesting_t +{ + void add_region_creation (const region *reg); + + void dump_to_pp (pretty_printer *pp, bool simple) const; + + auto_vec<const region *> m_region_creation; +}; + /* Various bundles of information used for generating more precise messages for events within a diagnostic_path, for passing to the various "describe_*" vfuncs of pending_diagnostic. See those @@ -282,6 +298,14 @@ class pending_diagnostic { return false; } + + /* Vfunc for registering additional information of interest to this + diagnostic. */ + + virtual void mark_interesting_stuff (interesting_t *) + { + /* Default no-op implementation. */ + } }; /* A template to make it easier to make subclasses of pending_diagnostic. diff --git a/gcc/analyzer/region-model-manager.cc b/gcc/analyzer/region-model-manager.cc index e765e7f..ba835cb 100644 --- a/gcc/analyzer/region-model-manager.cc +++ b/gcc/analyzer/region-model-manager.cc @@ -1573,7 +1573,7 @@ static void log_uniq_map (logger *logger, bool show_objs, const char *title, const hash_map<K, T*> &uniq_map) { - logger->log (" # %s: %li", title, uniq_map.elements ()); + logger->log (" # %s: %li", title, (long)uniq_map.elements ()); if (!show_objs) return; auto_vec<const T *> vec_objs (uniq_map.elements ()); @@ -1597,7 +1597,7 @@ static void log_uniq_map (logger *logger, bool show_objs, const char *title, const consolidation_map<T> &map) { - logger->log (" # %s: %li", title, map.elements ()); + logger->log (" # %s: %li", title, (long)map.elements ()); if (!show_objs) return; diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc index f6b7f98..6810cf5 100644 --- a/gcc/analyzer/region-model.cc +++ b/gcc/analyzer/region-model.cc @@ -454,8 +454,10 @@ class poisoned_value_diagnostic : public pending_diagnostic_subclass<poisoned_value_diagnostic> { public: - poisoned_value_diagnostic (tree expr, enum poison_kind pkind) - : m_expr (expr), m_pkind (pkind) + poisoned_value_diagnostic (tree expr, enum poison_kind pkind, + const region *src_region) + : m_expr (expr), m_pkind (pkind), + m_src_region (src_region) {} const char *get_kind () const FINAL OVERRIDE { return "poisoned_value_diagnostic"; } @@ -467,7 +469,9 @@ public: bool operator== (const poisoned_value_diagnostic &other) const { - return m_expr == other.m_expr; + return (m_expr == other.m_expr + && m_pkind == other.m_pkind + && m_src_region == other.m_src_region); } bool emit (rich_location *rich_loc) FINAL OVERRIDE @@ -528,9 +532,16 @@ public: } } + void mark_interesting_stuff (interesting_t *interest) FINAL OVERRIDE + { + if (m_src_region) + interest->add_region_creation (m_src_region); + } + private: tree m_expr; enum poison_kind m_pkind; + const region *m_src_region; }; /* A subclass of pending_diagnostic for complaining about shifts @@ -839,7 +850,11 @@ region_model::check_for_poison (const svalue *sval, fixup_tree_for_diagnostic. */ tree diag_arg = fixup_tree_for_diagnostic (expr); enum poison_kind pkind = poisoned_sval->get_poison_kind (); - if (ctxt->warn (new poisoned_value_diagnostic (diag_arg, pkind))) + const region *src_region = NULL; + if (pkind == POISON_KIND_UNINIT) + src_region = get_region_for_poisoned_expr (expr); + if (ctxt->warn (new poisoned_value_diagnostic (diag_arg, pkind, + src_region))) { /* We only want to report use of a poisoned value at the first place it gets used; return an unknown value to avoid generating @@ -853,6 +868,24 @@ region_model::check_for_poison (const svalue *sval, return sval; } +/* Attempt to get a region for describing EXPR, the source of region of + a poisoned_svalue for use in a poisoned_value_diagnostic. + Return NULL if there is no good region to use. */ + +const region * +region_model::get_region_for_poisoned_expr (tree expr) const +{ + if (TREE_CODE (expr) == SSA_NAME) + { + tree decl = SSA_NAME_VAR (expr); + if (decl && DECL_P (decl)) + expr = decl; + else + return NULL; + } + return get_lvalue (expr, NULL); +} + /* Update this model for the ASSIGN stmt, using CTXT to report any diagnostics. */ @@ -1044,6 +1077,16 @@ region_model::on_stmt_pre (const gimple *stmt, } } +/* Ensure that all arguments at the call described by CD are checked + for poisoned values, by calling get_rvalue on each argument. */ + +void +region_model::check_call_args (const call_details &cd) const +{ + for (unsigned arg_idx = 0; arg_idx < cd.num_args (); arg_idx++) + cd.get_arg_svalue (arg_idx); +} + /* Update this model for the CALL stmt, using CTXT to report any diagnostics - the first half. @@ -1173,6 +1216,7 @@ region_model::on_call_pre (const gcall *call, region_model_context *ctxt, /* These stdio builtins have external effects that are out of scope for the analyzer: we only want to model the effects on the return value. */ + check_call_args (cd); break; } else if (is_named_call_p (callee_fndecl, "malloc", call, 1)) @@ -2123,7 +2167,7 @@ region_model::deref_rvalue (const svalue *ptr_sval, tree ptr_tree, const poisoned_svalue *poisoned_sval = as_a <const poisoned_svalue *> (ptr_sval); enum poison_kind pkind = poisoned_sval->get_poison_kind (); - ctxt->warn (new poisoned_value_diagnostic (ptr, pkind)); + ctxt->warn (new poisoned_value_diagnostic (ptr, pkind, NULL)); } } } diff --git a/gcc/analyzer/region-model.h b/gcc/analyzer/region-model.h index c78efe8..983d082 100644 --- a/gcc/analyzer/region-model.h +++ b/gcc/analyzer/region-model.h @@ -813,6 +813,7 @@ class region_model const svalue *check_for_poison (const svalue *sval, tree expr, region_model_context *ctxt) const; + const region * get_region_for_poisoned_expr (tree expr) const; void check_dynamic_size_for_taint (enum memory_space mem_space, const svalue *size_in_bytes, @@ -832,6 +833,8 @@ class region_model void check_region_for_read (const region *src_reg, region_model_context *ctxt) const; + void check_call_args (const call_details &cd) const; + /* Storing this here to avoid passing it around everywhere. */ region_model_manager *const m_mgr; diff --git a/gcc/analyzer/region.h b/gcc/analyzer/region.h index d97bbc1..20eca52 100644 --- a/gcc/analyzer/region.h +++ b/gcc/analyzer/region.h @@ -298,6 +298,7 @@ public: /* Accessors. */ const frame_region *get_calling_frame () const { return m_calling_frame; } function *get_function () const { return m_fun; } + tree get_fndecl () const { return get_function ()->decl; } int get_index () const { return m_index; } int get_stack_depth () const { return m_index + 1; } diff --git a/gcc/builtins.cc b/gcc/builtins.cc index bf07341..d784a57 100644 --- a/gcc/builtins.cc +++ b/gcc/builtins.cc @@ -119,6 +119,9 @@ static rtx expand_builtin_mathfn_3 (tree, rtx, rtx); static rtx expand_builtin_mathfn_ternary (tree, rtx, rtx); static rtx expand_builtin_interclass_mathfn (tree, rtx); static rtx expand_builtin_sincos (tree); +static rtx expand_builtin_fegetround (tree, rtx, machine_mode); +static rtx expand_builtin_feclear_feraise_except (tree, rtx, machine_mode, + optab); static rtx expand_builtin_cexpi (tree, rtx); static rtx expand_builtin_int_roundingfn (tree, rtx); static rtx expand_builtin_int_roundingfn_2 (tree, rtx); @@ -2555,6 +2558,62 @@ expand_builtin_sincos (tree exp) return const0_rtx; } +/* Expand call EXP to the fegetround builtin (from C99 fenv.h), returning the + result and setting it in TARGET. Otherwise return NULL_RTX on failure. */ +static rtx +expand_builtin_fegetround (tree exp, rtx target, machine_mode target_mode) +{ + if (!validate_arglist (exp, VOID_TYPE)) + return NULL_RTX; + + insn_code icode = direct_optab_handler (fegetround_optab, SImode); + if (icode == CODE_FOR_nothing) + return NULL_RTX; + + if (target == 0 + || GET_MODE (target) != target_mode + || !(*insn_data[icode].operand[0].predicate) (target, target_mode)) + target = gen_reg_rtx (target_mode); + + rtx pat = GEN_FCN (icode) (target); + if (!pat) + return NULL_RTX; + emit_insn (pat); + + return target; +} + +/* Expand call EXP to either feclearexcept or feraiseexcept builtins (from C99 + fenv.h), returning the result and setting it in TARGET. Otherwise return + NULL_RTX on failure. */ +static rtx +expand_builtin_feclear_feraise_except (tree exp, rtx target, + machine_mode target_mode, optab op_optab) +{ + if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE)) + return NULL_RTX; + rtx op0 = expand_normal (CALL_EXPR_ARG (exp, 0)); + + insn_code icode = direct_optab_handler (op_optab, SImode); + if (icode == CODE_FOR_nothing) + return NULL_RTX; + + if (!(*insn_data[icode].operand[1].predicate) (op0, GET_MODE (op0))) + return NULL_RTX; + + if (target == 0 + || GET_MODE (target) != target_mode + || !(*insn_data[icode].operand[0].predicate) (target, target_mode)) + target = gen_reg_rtx (target_mode); + + rtx pat = GEN_FCN (icode) (target, op0); + if (!pat) + return NULL_RTX; + emit_insn (pat); + + return target; +} + /* Expand a call to the internal cexpi builtin to the sincos math function. EXP is the expression that is a call to the builtin function; if convenient, the result should be placed in TARGET. */ @@ -7056,6 +7115,26 @@ expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode, return target; break; + case BUILT_IN_FEGETROUND: + target = expand_builtin_fegetround (exp, target, target_mode); + if (target) + return target; + break; + + case BUILT_IN_FECLEAREXCEPT: + target = expand_builtin_feclear_feraise_except (exp, target, target_mode, + feclearexcept_optab); + if (target) + return target; + break; + + case BUILT_IN_FERAISEEXCEPT: + target = expand_builtin_feclear_feraise_except (exp, target, target_mode, + feraiseexcept_optab); + if (target) + return target; + break; + case BUILT_IN_APPLY_ARGS: return expand_builtin_apply_args (); diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 5595c8d..e3bf1a7 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,8 @@ +2022-01-24 Marek Polacek <polacek@redhat.com> + + PR preprocessor/104030 + * c.opt (Wbidi-chars): Mark as EnumSet. Also accept =ucn. + 2022-01-21 Jakub Jelinek <jakub@redhat.com> PR c++/104148 diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index db65c14..9cfd2a6 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -379,8 +379,8 @@ C ObjC C++ ObjC++ Warning Alias(Wbidi-chars=,any,none) ; Wbidi-chars= -C ObjC C++ ObjC++ RejectNegative Joined Warning CPP(cpp_warn_bidirectional) CppReason(CPP_W_BIDIRECTIONAL) Var(warn_bidirectional) Init(bidirectional_unpaired) Enum(cpp_bidirectional_level) --Wbidi-chars=[none|unpaired|any] Warn about UTF-8 bidirectional control characters. +C ObjC C++ ObjC++ RejectNegative Joined Warning CPP(cpp_warn_bidirectional) CppReason(CPP_W_BIDIRECTIONAL) Var(warn_bidirectional) Init(bidirectional_unpaired) Enum(cpp_bidirectional_level) EnumSet +-Wbidi-chars=[none|unpaired|any|ucn] Warn about UTF-8 bidirectional control characters. ; Required for these enum values. SourceInclude @@ -390,13 +390,16 @@ Enum Name(cpp_bidirectional_level) Type(int) UnknownError(argument %qs to %<-Wbidi-chars%> not recognized) EnumValue -Enum(cpp_bidirectional_level) String(none) Value(bidirectional_none) +Enum(cpp_bidirectional_level) String(none) Value(bidirectional_none) Set(1) EnumValue -Enum(cpp_bidirectional_level) String(unpaired) Value(bidirectional_unpaired) +Enum(cpp_bidirectional_level) String(unpaired) Value(bidirectional_unpaired) Set(1) EnumValue -Enum(cpp_bidirectional_level) String(any) Value(bidirectional_any) +Enum(cpp_bidirectional_level) String(any) Value(bidirectional_any) Set(1) + +EnumValue +Enum(cpp_bidirectional_level) String(ucn) Value(bidirectional_ucn) Set(2) Wbool-compare C ObjC C++ ObjC++ Var(warn_bool_compare) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall) diff --git a/gcc/cfganal.cc b/gcc/cfganal.cc index e570d27..79c627a 100644 --- a/gcc/cfganal.cc +++ b/gcc/cfganal.cc @@ -58,7 +58,7 @@ private: and heavily borrowed from pre_and_rev_post_order_compute. */ bool -mark_dfs_back_edges (void) +mark_dfs_back_edges (struct function *fun) { int *pre; int *post; @@ -67,20 +67,20 @@ mark_dfs_back_edges (void) bool found = false; /* Allocate the preorder and postorder number arrays. */ - pre = XCNEWVEC (int, last_basic_block_for_fn (cfun)); - post = XCNEWVEC (int, last_basic_block_for_fn (cfun)); + pre = XCNEWVEC (int, last_basic_block_for_fn (fun)); + post = XCNEWVEC (int, last_basic_block_for_fn (fun)); /* Allocate stack for back-tracking up CFG. */ - auto_vec<edge_iterator, 20> stack (n_basic_blocks_for_fn (cfun) + 1); + auto_vec<edge_iterator, 20> stack (n_basic_blocks_for_fn (fun) + 1); /* Allocate bitmap to track nodes that have been visited. */ - auto_sbitmap visited (last_basic_block_for_fn (cfun)); + auto_sbitmap visited (last_basic_block_for_fn (fun)); /* None of the nodes in the CFG have been visited yet. */ bitmap_clear (visited); /* Push the first edge on to the stack. */ - stack.quick_push (ei_start (ENTRY_BLOCK_PTR_FOR_FN (cfun)->succs)); + stack.quick_push (ei_start (ENTRY_BLOCK_PTR_FOR_FN (fun)->succs)); while (!stack.is_empty ()) { @@ -94,8 +94,8 @@ mark_dfs_back_edges (void) ei_edge (ei)->flags &= ~EDGE_DFS_BACK; /* Check if the edge destination has been visited yet. */ - if (dest != EXIT_BLOCK_PTR_FOR_FN (cfun) && ! bitmap_bit_p (visited, - dest->index)) + if (dest != EXIT_BLOCK_PTR_FOR_FN (fun) && ! bitmap_bit_p (visited, + dest->index)) { /* Mark that we have visited the destination. */ bitmap_set_bit (visited, dest->index); @@ -112,14 +112,14 @@ mark_dfs_back_edges (void) } else { - if (dest != EXIT_BLOCK_PTR_FOR_FN (cfun) - && src != ENTRY_BLOCK_PTR_FOR_FN (cfun) + if (dest != EXIT_BLOCK_PTR_FOR_FN (fun) + && src != ENTRY_BLOCK_PTR_FOR_FN (fun) && pre[src->index] >= pre[dest->index] && post[dest->index] == 0) ei_edge (ei)->flags |= EDGE_DFS_BACK, found = true; if (ei_one_before_end_p (ei) - && src != ENTRY_BLOCK_PTR_FOR_FN (cfun)) + && src != ENTRY_BLOCK_PTR_FOR_FN (fun)) post[src->index] = postnum++; if (!ei_one_before_end_p (ei)) @@ -135,6 +135,12 @@ mark_dfs_back_edges (void) return found; } +bool +mark_dfs_back_edges (void) +{ + return mark_dfs_back_edges (cfun); +} + /* Find unreachable blocks. An unreachable block will have 0 in the reachable bit in block->flags. A nonzero value indicates the block is reachable. */ diff --git a/gcc/cfganal.h b/gcc/cfganal.h index 386cfbf..ac637de 100644 --- a/gcc/cfganal.h +++ b/gcc/cfganal.h @@ -49,6 +49,7 @@ private: bitmap_obstack m_bitmaps; }; +extern bool mark_dfs_back_edges (struct function *); extern bool mark_dfs_back_edges (void); extern void find_unreachable_blocks (void); extern void verify_no_unreachable_blocks (void); diff --git a/gcc/cfgrtl.cc b/gcc/cfgrtl.cc index 9ccc65b..5675751 100644 --- a/gcc/cfgrtl.cc +++ b/gcc/cfgrtl.cc @@ -778,6 +778,29 @@ rtl_split_block (basic_block bb, void *insnp) return new_bb; } +/* Return true if LOC1 and LOC2 are equivalent for + unique_locus_on_edge_between_p purposes. */ + +static bool +loc_equal (location_t loc1, location_t loc2) +{ + if (loc1 == loc2) + return true; + + expanded_location loce1 = expand_location (loc1); + expanded_location loce2 = expand_location (loc2); + + if (loce1.line != loce2.line + || loce1.column != loce2.column + || loce1.data != loce2.data) + return false; + if (loce1.file == loce2.file) + return true; + return (loce1.file != NULL + && loce2.file != NULL + && filename_cmp (loce1.file, loce2.file) == 0); +} + /* Return true if the single edge between blocks A and B is the only place in RTL which holds some unique locus. */ @@ -796,7 +819,7 @@ unique_locus_on_edge_between_p (basic_block a, basic_block b) while (insn != end && (!NONDEBUG_INSN_P (insn) || !INSN_HAS_LOCATION (insn))) insn = PREV_INSN (insn); - if (insn != end && INSN_LOCATION (insn) == goto_locus) + if (insn != end && loc_equal (INSN_LOCATION (insn), goto_locus)) return false; /* Then scan block B forward. */ @@ -808,7 +831,7 @@ unique_locus_on_edge_between_p (basic_block a, basic_block b) insn = NEXT_INSN (insn); if (insn != end && INSN_HAS_LOCATION (insn) - && INSN_LOCATION (insn) == goto_locus) + && loc_equal (INSN_LOCATION (insn), goto_locus)) return false; } diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md index 0492392..b3c5bce 100644 --- a/gcc/config/riscv/riscv.md +++ b/gcc/config/riscv/riscv.md @@ -150,6 +150,7 @@ ;; mfc transfer from coprocessor ;; const load constant ;; arith integer arithmetic instructions +;; auipc integer addition to PC ;; logical integer logical instructions ;; shift integer shift instructions ;; slt set less than instructions @@ -167,6 +168,7 @@ ;; multi multiword sequence (or user asm statements) ;; nop no operation ;; ghost an instruction that produces no real code +;; bitmanip bit manipulation instructions (define_attr "type" "unknown,branch,jump,call,load,fpload,store,fpstore, mtc,mfc,const,arith,logical,shift,slt,imul,idiv,move,fmove,fadd,fmul, diff --git a/gcc/config/rs6000/aix.h b/gcc/config/rs6000/aix.h index ad3238b..eb7a0c0 100644 --- a/gcc/config/rs6000/aix.h +++ b/gcc/config/rs6000/aix.h @@ -23,6 +23,7 @@ #define DEFAULT_ABI ABI_AIX #undef TARGET_AIX #define TARGET_AIX 1 +#define OPTION_GLIBC 0 /* Linux64.h wants to redefine TARGET_AIX based on -m64, but it can't be used in the #if conditional in options-default.h, so provide another macro. */ diff --git a/gcc/config/rs6000/bmi2intrin.h b/gcc/config/rs6000/bmi2intrin.h index 9bf36e9..f2d7eb5 100644 --- a/gcc/config/rs6000/bmi2intrin.h +++ b/gcc/config/rs6000/bmi2intrin.h @@ -29,8 +29,8 @@ standard C or GNU C extensions, which are more portable and better optimized across multiple targets. */ -#if !defined _X86INTRIN_H_INCLUDED -# error "Never use <bmi2intrin.h> directly; include <x86intrin.h> instead." +#if !defined _X86GPRINTRIN_H_INCLUDED +# error "Never use <bmi2intrin.h> directly; include <x86gprintrin.h> instead." #endif #ifndef _BMI2INTRIN_H_INCLUDED @@ -118,7 +118,8 @@ _pext_u64 (unsigned long long __X, unsigned long long __M) /* Also if the pext mask is constant, then the popcount is constant, we can evaluate the following loop at compile time and use a constant bit permute vector. */ - for (long i = 0; i < __builtin_popcountl (__M); i++) + long i; + for (i = 0; i < __builtin_popcountl (__M); i++) { c = __builtin_clzl (m); p = (p << 8) | c; diff --git a/gcc/config/rs6000/bmiintrin.h b/gcc/config/rs6000/bmiintrin.h index 8845f70..76cbc47 100644 --- a/gcc/config/rs6000/bmiintrin.h +++ b/gcc/config/rs6000/bmiintrin.h @@ -29,8 +29,8 @@ standard C or GNU C extensions, which are more portable and better optimized across multiple targets. */ -#if !defined _X86INTRIN_H_INCLUDED -# error "Never use <bmiintrin.h> directly; include <x86intrin.h> instead." +#if !defined _X86GPRINTRIN_H_INCLUDED +# error "Never use <bmiintrin.h> directly; include <x86gprintrin.h> instead." #endif #ifndef _BMIINTRIN_H_INCLUDED diff --git a/gcc/config/rs6000/emmintrin.h b/gcc/config/rs6000/emmintrin.h index 6065dc7..71abcca 100644 --- a/gcc/config/rs6000/emmintrin.h +++ b/gcc/config/rs6000/emmintrin.h @@ -2215,7 +2215,7 @@ _mm_sad_epu8 (__m128i __A, __m128i __B) vsum = (__vector signed int) vec_sum4s (vabsdiff, zero); #ifdef __LITTLE_ENDIAN__ /* Sum across four integers with two integer results. */ - asm ("vsum2sws %0,%1,%2" : "=v" (result) : "v" (vsum), "v" (zero)); + __asm__ ("vsum2sws %0,%1,%2" : "=v" (result) : "v" (vsum), "v" (zero)); /* Note: vec_sum2s could be used here, but on little-endian, vector shifts are added that are not needed for this use-case. A vector shift to correctly position the 32-bit integer results diff --git a/gcc/config/rs6000/rs6000-call.cc b/gcc/config/rs6000/rs6000-call.cc index e002e1f..5c870d4 100644 --- a/gcc/config/rs6000/rs6000-call.cc +++ b/gcc/config/rs6000/rs6000-call.cc @@ -755,12 +755,6 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, && (TYPE_MAIN_VARIANT (return_type) == long_double_type_node)))) rs6000_passes_long_double = true; - - /* Note if we passed or return a IEEE 128-bit type. We changed - the mangling for these types, and we may need to make an alias - with the old mangling. */ - if (FLOAT128_IEEE_P (return_mode)) - rs6000_passes_ieee128 = true; } if (ALTIVEC_OR_VSX_VECTOR_MODE (return_mode)) rs6000_passes_vector = true; @@ -1179,12 +1173,6 @@ rs6000_function_arg_advance_1 (CUMULATIVE_ARGS *cum, machine_mode mode, || (type != NULL && TYPE_MAIN_VARIANT (type) == long_double_type_node))) rs6000_passes_long_double = true; - - /* Note if we passed or return a IEEE 128-bit type. We changed the - mangling for these types, and we may need to make an alias with - the old mangling. */ - if (FLOAT128_IEEE_P (mode)) - rs6000_passes_ieee128 = true; } if (named && ALTIVEC_OR_VSX_VECTOR_MODE (mode)) rs6000_passes_vector = true; diff --git a/gcc/config/rs6000/rs6000-internal.h b/gcc/config/rs6000/rs6000-internal.h index 2d1090e..8ee8c98 100644 --- a/gcc/config/rs6000/rs6000-internal.h +++ b/gcc/config/rs6000/rs6000-internal.h @@ -183,9 +183,6 @@ extern tree rs6000_fold_builtin (tree fndecl ATTRIBUTE_UNUSED, tree *args ATTRIBUTE_UNUSED, bool ignore ATTRIBUTE_UNUSED); -#if TARGET_ELF -extern bool rs6000_passes_ieee128; -#endif extern bool rs6000_passes_float; extern bool rs6000_passes_long_double; extern bool rs6000_passes_vector; diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc index 943f53e..a5fd36b 100644 --- a/gcc/config/rs6000/rs6000.cc +++ b/gcc/config/rs6000/rs6000.cc @@ -121,22 +121,9 @@ int dot_symbols; of this machine mode. */ scalar_int_mode rs6000_pmode; -#if TARGET_ELF -/* Note whether IEEE 128-bit floating point was passed or returned, either as - the __float128/_Float128 explicit type, or when long double is IEEE 128-bit - floating point. We changed the default C++ mangling for these types and we - may want to generate a weak alias of the old mangling (U10__float128) to the - new mangling (u9__ieee128). */ -bool rs6000_passes_ieee128 = false; -#endif - /* Track use of r13 in 64bit AIX TLS. */ static bool xcoff_tls_exec_model_detected = false; -/* Generate the manged name (i.e. U10__float128) used in GCC 8.1, and not the - name used in current releases (i.e. u9__ieee128). */ -static bool ieee128_mangling_gcc_8_1; - /* Width in bits of a pointer. */ unsigned rs6000_pointer_size; @@ -1765,11 +1752,6 @@ static const struct attribute_spec rs6000_attribute_table[] = #undef TARGET_STARTING_FRAME_OFFSET #define TARGET_STARTING_FRAME_OFFSET rs6000_starting_frame_offset -#if TARGET_ELF && RS6000_WEAK -#undef TARGET_ASM_GLOBALIZE_DECL_NAME -#define TARGET_ASM_GLOBALIZE_DECL_NAME rs6000_globalize_decl_name -#endif - #undef TARGET_SETJMP_PRESERVES_NONVOLATILE_REGS_P #define TARGET_SETJMP_PRESERVES_NONVOLATILE_REGS_P hook_bool_void_true @@ -5457,8 +5439,11 @@ rs6000_cost_data::update_target_cost_per_stmt (vect_cost_for_stmt kind, { tree vectype = STMT_VINFO_VECTYPE (stmt_info); unsigned int nunits = vect_nunits_for_cost (vectype); - /* We don't expect strided/elementwise loads for just 1 nunit. */ - gcc_assert (nunits > 1); + /* As PR103702 shows, it's possible that vectorizer wants to do + costings for only one unit here, it's no need to do any + penalization for it, so simply early return here. */ + if (nunits == 1) + return; /* i386 port adopts nunits * stmt_cost as the penalized cost for this kind of penalization, we used to follow it but found it could result in an unreliable body cost especially @@ -20262,7 +20247,7 @@ rs6000_mangle_type (const_tree type) if (SCALAR_FLOAT_TYPE_P (type) && FLOAT128_IBM_P (TYPE_MODE (type))) return "g"; if (SCALAR_FLOAT_TYPE_P (type) && FLOAT128_IEEE_P (TYPE_MODE (type))) - return ieee128_mangling_gcc_8_1 ? "U10__float128" : "u9__ieee128"; + return "u9__ieee128"; if (type == vector_pair_type_node) return "u13__vector_pair"; @@ -28159,39 +28144,6 @@ rs6000_starting_frame_offset (void) } -/* Create an alias for a mangled name where we have changed the mangling (in - GCC 8.1, we used U10__float128, and now we use u9__ieee128). This is called - via the target hook TARGET_ASM_GLOBALIZE_DECL_NAME. */ - -#if TARGET_ELF && RS6000_WEAK -static void -rs6000_globalize_decl_name (FILE * stream, tree decl) -{ - const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0); - - targetm.asm_out.globalize_label (stream, name); - - if (rs6000_passes_ieee128 && name[0] == '_' && name[1] == 'Z') - { - tree save_asm_name = DECL_ASSEMBLER_NAME (decl); - const char *old_name; - - ieee128_mangling_gcc_8_1 = true; - lang_hooks.set_decl_assembler_name (decl); - old_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); - SET_DECL_ASSEMBLER_NAME (decl, save_asm_name); - ieee128_mangling_gcc_8_1 = false; - - if (strcmp (name, old_name) != 0) - { - fprintf (stream, "\t.weak %s\n", old_name); - fprintf (stream, "\t.set %s,%s\n", old_name, name); - } - } -} -#endif - - /* On 64-bit Linux and Freebsd systems, possibly switch the long double library function names from <foo>l to <foo>f128 if the default long double type is IEEE 128-bit. Typically, with the C and C++ languages, the standard math.h diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 4e22118..fdfbc65 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -6912,6 +6912,117 @@ [(set_attr "type" "fpload") (set_attr "length" "8") (set_attr "isa" "*,p8v,p8v")]) + +;; int fegetround(void) +;; +;; This expansion for the C99 function only expands for compatible +;; target libcs, because it needs to return one of FE_DOWNWARD, +;; FE_TONEAREST, FE_TOWARDZERO or FE_UPWARD with the values as defined +;; by the target libc, and since the libc is free to choose the values +;; (and they may differ from the hardware) and the expander needs to +;; know then beforehand, this expanded only expands for target libcs +;; that it can handle the values is knows. +;; Because of these restriction, this only expands on the desired +;; case and fallback to a call to libc otherwise. +(define_expand "fegetroundsi" + [(set (match_operand:SI 0 "gpc_reg_operand") + (unspec_volatile:SI [(const_int 0)] UNSPECV_MFFSL))] + "TARGET_HARD_FLOAT" +{ + if (!OPTION_GLIBC) + FAIL; + + rtx tmp_df = gen_reg_rtx (DFmode); + emit_insn (gen_rs6000_mffsl (tmp_df)); + + rtx tmp_di = simplify_gen_subreg (DImode, tmp_df, DFmode, 0); + rtx tmp_di_2 = gen_reg_rtx (DImode); + emit_insn (gen_anddi3 (tmp_di_2, tmp_di, GEN_INT (3))); + rtx tmp_si = gen_reg_rtx (SImode); + tmp_si = gen_lowpart (SImode, tmp_di_2); + emit_move_insn (operands[0], tmp_si); + DONE; +}) + +;; int feclearexcept(int excepts) +;; +;; This expansion for the C99 function only works when EXCEPTS is a +;; constant known at compile time and specifies any one of +;; FE_INEXACT, FE_DIVBYZERO, FE_UNDERFLOW and FE_OVERFLOW flags. +;; It doesn't handle values out of range, and always returns 0. +;; Note that FE_INVALID is unsupported because it maps to more than +;; one bit of the FPSCR register. +;; The FE_* are defined in the target libc, and since they are free to +;; choose the values and the expand needs to know them beforehand, +;; this expander only expands for target libcs that it can handle the +;; values it knows. +;; Because of these restrictions, this only expands on the desired +;; cases and fallback to a call to libc on any other case. +(define_expand "feclearexceptsi" + [(use (match_operand:SI 1 "const_int_operand" "n")) + (set (match_operand:SI 0 "gpc_reg_operand") + (const_int 0))] + "TARGET_HARD_FLOAT" +{ + if (!OPTION_GLIBC) + FAIL; + + unsigned int fe = INTVAL (operands[1]); + if (fe != (fe & 0x1e000000)) + FAIL; + + if (fe & 0x02000000) /* FE_INEXACT */ + emit_insn (gen_rs6000_mtfsb0 (gen_rtx_CONST_INT (SImode, 6))); + if (fe & 0x04000000) /* FE_DIVBYZERO */ + emit_insn (gen_rs6000_mtfsb0 (gen_rtx_CONST_INT (SImode, 5))); + if (fe & 0x08000000) /* FE_UNDERFLOW */ + emit_insn (gen_rs6000_mtfsb0 (gen_rtx_CONST_INT (SImode, 4))); + if (fe & 0x10000000) /* FE_OVERFLOW */ + emit_insn (gen_rs6000_mtfsb0 (gen_rtx_CONST_INT (SImode, 3))); + + emit_move_insn (operands[0], const0_rtx); + DONE; +}) + +;; int feraiseexcept(int excepts) +;; +;; This expansion for the C99 function only works when excepts is a +;; constant known at compile time and specifies any one of +;; FE_INEXACT, FE_DIVBYZERO, FE_UNDERFLOW and FE_OVERFLOW flags. +;; It doesn't handle values out of range, and always returns 0. +;; Note that FE_INVALID is unsupported because it maps to more than +;; one bit of the FPSCR register. +;; The FE_* are defined in the target libc, and since they are free to +;; choose the values and the expand needs to know them beforehand, +;; this expander only expands for target libcs that it can handle the +;; values it knows. +;; Because of these restrictions, this only expands on the desired +;; cases and fallback to a call to libc on any other case. +(define_expand "feraiseexceptsi" + [(use (match_operand:SI 1 "const_int_operand" "n")) + (set (match_operand:SI 0 "gpc_reg_operand") + (const_int 0))] + "TARGET_HARD_FLOAT" +{ + if (!OPTION_GLIBC) + FAIL; + + unsigned int fe = INTVAL (operands[1]); + if (fe != (fe & 0x1e000000)) + FAIL; + + if (fe & 0x02000000) /* FE_INEXACT */ + emit_insn (gen_rs6000_mtfsb1 (gen_rtx_CONST_INT (SImode, 6))); + if (fe & 0x04000000) /* FE_DIVBYZERO */ + emit_insn (gen_rs6000_mtfsb1 (gen_rtx_CONST_INT (SImode, 5))); + if (fe & 0x08000000) /* FE_UNDERFLOW */ + emit_insn (gen_rs6000_mtfsb1 (gen_rtx_CONST_INT (SImode, 4))); + if (fe & 0x10000000) /* FE_OVERFLOW */ + emit_insn (gen_rs6000_mtfsb1 (gen_rtx_CONST_INT (SImode, 3))); + + emit_move_insn (operands[0], const0_rtx); + DONE; +}) ;; Define the TImode operations that can be done in a small number ;; of instructions. The & constraints are to prevent the register diff --git a/gcc/config/rs6000/smmintrin.h b/gcc/config/rs6000/smmintrin.h index 4f90c2e..cca2f7d 100644 --- a/gcc/config/rs6000/smmintrin.h +++ b/gcc/config/rs6000/smmintrin.h @@ -687,7 +687,8 @@ _mm_minpos_epu16 (__m128i __A) union __u __u = { .__m = __A }, __r = { .__m = {0} }; unsigned short __ridx = 0; unsigned short __rmin = __u.__uh[__ridx]; - for (unsigned long __i = 1; __i < 8; __i++) + unsigned long __i; + for (__i = 1; __i < 8; __i++) { if (__u.__uh[__i] < __rmin) { diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 1aadfa9..4301b5c 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,93 @@ +2022-01-27 Jason Merrill <jason@redhat.com> + + PR c++/104245 + PR c++/51344 + * decl2.cc (save_template_attributes): Take late attrs as parm. + (cplus_decl_attributes): Call it after decl_attributes, + splice_template_attributes before. + +2022-01-27 Patrick Palka <ppalka@redhat.com> + + PR c++/99895 + * call.cc (build_over_call): For a non-dependent member call, + build up a CALL_EXPR using a COMPONENT_REF callee, as in + build_new_method_call. + * pt.cc (build_non_dependent_expr): Don't wrap PARM_DECL either. + * tree.cc (build_min_non_dep_op_overload): Adjust accordingly + after the build_over_call change. + +2022-01-27 Patrick Palka <ppalka@redhat.com> + + PR c++/92944 + PR c++/103678 + * parser.cc (cp_parser_class_head): Update 'type' with the result + of maybe_process_partial_specialization in the + nested_name_specifier branch. Refactor nearby code to accomodate + that maybe_process_partial_specialization returns a _TYPE, not a + TYPE_DECL, and eliminate local variable 'class_type' in passing. + +2022-01-27 Marek Polacek <polacek@redhat.com> + + PR c++/101988 + * decl.cc (create_array_type_for_decl): Reject forming an array of + placeholder for a deduced class type. + +2022-01-26 Jason Merrill <jason@redhat.com> + + PR c++/104206 + PR c++/101072 + * semantics.cc (finish_compound_literal): Restore VECTOR_TYPE check. + +2022-01-26 Jakub Jelinek <jakub@redhat.com> + + PR c++/104226 + * constexpr.cc (init_subob_ctx): For vector ctors containing + vector elements, ensure appending to the same ctor instead of + creating another one. + +2022-01-26 Marek Polacek <polacek@redhat.com> + + PR target/104213 + * decl.cc (finish_constructor_body): Suppress -Wuse-after-free. + (finish_destructor_body): Likewise. + * optimize.cc (build_delete_destructor_body): Likewise. + +2022-01-26 Jason Merrill <jason@redhat.com> + + PR c++/104235 + * parser.cc (cp_parser_template_name): Repeat lookup of USING_DECL. + +2022-01-26 Jason Merrill <jason@redhat.com> + + PR c++/103057 + * pt.cc (tsubst_aggr_type): Call tsubst for alias template + specialization. + +2022-01-25 Patrick Palka <ppalka@redhat.com> + + PR c++/101532 + PR c++/104225 + * decl2.cc (mark_used): Don't consider maybe_instantiate_noexcept + on a deleted function. + +2022-01-25 Jason Merrill <jason@redhat.com> + + PR c++/59950 + * call.cc (build_over_call): Use cp_build_indirect_ref. + +2022-01-24 Patrick Palka <ppalka@redhat.com> + + PR c++/104197 + * pt.cc (make_auto_1): Use -1 as a placeholder default argument + for level. + +2022-01-24 Patrick Palka <ppalka@redhat.com> + + PR c++/104173 + * typeck.cc (build_class_member_access_expr): Extend + unary_complex_lvalue result adjustment to preserve all + rvalues, not just xvalues. + 2022-01-23 Will Wray <wjwray@gmail.com> PR c++/55227 diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc index f7f861c..b2e89c5 100644 --- a/gcc/cp/call.cc +++ b/gcc/cp/call.cc @@ -9204,11 +9204,6 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) errors will be deferred until the template is instantiated. */ if (processing_template_decl) { - tree expr, addr; - tree return_type; - const tree *argarray; - unsigned int nargs; - if (undeduced_auto_decl (fn)) mark_used (fn, complain); else @@ -9216,32 +9211,27 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) See PR80598. */ TREE_USED (fn) = 1; - return_type = TREE_TYPE (TREE_TYPE (fn)); - nargs = vec_safe_length (args); + tree return_type = TREE_TYPE (TREE_TYPE (fn)); + tree callee; if (first_arg == NULL_TREE) - argarray = args->address (); + { + callee = build_addr_func (fn, complain); + if (callee == error_mark_node) + return error_mark_node; + } else { - tree *alcarray; - unsigned int ix; - tree arg; - - ++nargs; - alcarray = XALLOCAVEC (tree, nargs); - alcarray[0] = build_this (first_arg); - FOR_EACH_VEC_SAFE_ELT (args, ix, arg) - alcarray[ix + 1] = arg; - argarray = alcarray; + tree binfo = TYPE_BINFO (TREE_TYPE (first_arg)); + callee = build_baselink (binfo, binfo, fn, NULL_TREE); + callee = build_min (COMPONENT_REF, TREE_TYPE (fn), + first_arg, callee, NULL_TREE); } - addr = build_addr_func (fn, complain); - if (addr == error_mark_node) - return error_mark_node; - expr = build_call_array_loc (input_location, return_type, - addr, nargs, argarray); + tree expr = build_call_vec (return_type, callee, args); + SET_EXPR_LOCATION (expr, input_location); if (TREE_THIS_VOLATILE (fn) && cfun) current_function_returns_abnormally = 1; - if (immediate_invocation_p (fn, nargs)) + if (immediate_invocation_p (fn, vec_safe_length (args))) { tree obj_arg = NULL_TREE, exprimm = expr; if (DECL_CONSTRUCTOR_P (fn)) @@ -9789,7 +9779,10 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) && DECL_OVERLOADED_OPERATOR_IS (fn, NOP_EXPR) && trivial_fn_p (fn)) { - tree to = cp_build_fold_indirect_ref (argarray[0]); + /* Don't use cp_build_fold_indirect_ref, op= returns an lvalue even if + the object argument isn't one. */ + tree to = cp_build_indirect_ref (input_location, argarray[0], + RO_ARROW, complain); tree type = TREE_TYPE (to); tree as_base = CLASSTYPE_AS_BASE (type); tree arg = argarray[1]; diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc index dcc1674..7f44253 100644 --- a/gcc/cp/constexpr.cc +++ b/gcc/cp/constexpr.cc @@ -4658,6 +4658,13 @@ init_subob_ctx (const constexpr_ctx *ctx, constexpr_ctx &new_ctx, if (!AGGREGATE_TYPE_P (type) && !VECTOR_TYPE_P (type)) /* A non-aggregate member doesn't get its own CONSTRUCTOR. */ return; + if (VECTOR_TYPE_P (type) + && VECTOR_TYPE_P (TREE_TYPE (ctx->ctor)) + && index == NULL_TREE) + /* A vector inside of a vector CONSTRUCTOR, e.g. when a larger + vector is constructed from smaller vectors, doesn't get its own + CONSTRUCTOR either. */ + return; /* The sub-aggregate initializer might contain a placeholder; update object to refer to the subobject and ctor to refer to diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index 22d3dd1..10e6956 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -11087,6 +11087,18 @@ create_array_type_for_decl (tree name, tree type, tree size, location_t loc) if (type == error_mark_node || size == error_mark_node) return error_mark_node; + /* [dcl.type.class.deduct] prohibits forming an array of placeholder + for a deduced class type. */ + if (is_auto (type) && CLASS_PLACEHOLDER_TEMPLATE (type)) + { + if (name) + error_at (loc, "%qD declared as array of template placeholder " + "type %qT", name, type); + else + error ("creating array of template placeholder type %qT", type); + return error_mark_node; + } + /* If there are some types which cannot be array elements, issue an error-message and return. */ switch (TREE_CODE (type)) @@ -17315,6 +17327,7 @@ finish_constructor_body (void) add_stmt (build_stmt (input_location, LABEL_EXPR, cdtor_label)); val = DECL_ARGUMENTS (current_function_decl); + suppress_warning (val, OPT_Wuse_after_free); val = build2 (MODIFY_EXPR, TREE_TYPE (val), DECL_RESULT (current_function_decl), val); /* Return the address of the object. */ @@ -17408,6 +17421,7 @@ finish_destructor_body (void) tree val; val = DECL_ARGUMENTS (current_function_decl); + suppress_warning (val, OPT_Wuse_after_free); val = build2 (MODIFY_EXPR, TREE_TYPE (val), DECL_RESULT (current_function_decl), val); /* Return the address of the object. */ diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc index 69b9744..a2aa5f1 100644 --- a/gcc/cp/decl2.cc +++ b/gcc/cp/decl2.cc @@ -1352,18 +1352,14 @@ splice_template_attributes (tree *attr_p, tree decl) return late_attrs; } -/* Remove any late attributes from the list in ATTR_P and attach them to - DECL_P. */ +/* Attach any LATE_ATTRS to DECL_P, after the non-dependent attributes have + been applied by a previous call to decl_attributes. */ static void -save_template_attributes (tree *attr_p, tree *decl_p, int flags) +save_template_attributes (tree late_attrs, tree *decl_p, int flags) { tree *q; - if (attr_p && *attr_p == error_mark_node) - return; - - tree late_attrs = splice_template_attributes (attr_p, *decl_p); if (!late_attrs) return; @@ -1666,12 +1662,12 @@ cplus_decl_attributes (tree *decl, tree attributes, int flags) } } + tree late_attrs = NULL_TREE; if (processing_template_decl) { if (check_for_bare_parameter_packs (attributes)) return; - - save_template_attributes (&attributes, decl, flags); + late_attrs = splice_template_attributes (&attributes, *decl); } cp_check_const_attributes (attributes); @@ -1717,6 +1713,9 @@ cplus_decl_attributes (tree *decl, tree attributes, int flags) decl_attributes (decl, attributes, flags, last_decl); } + if (late_attrs) + save_template_attributes (late_attrs, decl, flags); + /* Propagate deprecation out to the template. */ if (TREE_DEPRECATED (*decl)) if (tree ti = get_template_info (*decl)) @@ -5774,6 +5773,7 @@ mark_used (tree decl, tsubst_flags_t complain) used_types_insert (DECL_CONTEXT (decl)); if (TREE_CODE (decl) == FUNCTION_DECL + && !DECL_DELETED_FN (decl) && !maybe_instantiate_noexcept (decl, complain)) return false; diff --git a/gcc/cp/optimize.cc b/gcc/cp/optimize.cc index 4ad3f1d..13ab8b7 100644 --- a/gcc/cp/optimize.cc +++ b/gcc/cp/optimize.cc @@ -166,6 +166,7 @@ build_delete_destructor_body (tree delete_dtor, tree complete_dtor) if (targetm.cxx.cdtor_returns_this ()) { tree val = DECL_ARGUMENTS (delete_dtor); + suppress_warning (val, OPT_Wuse_after_free); val = build2 (MODIFY_EXPR, TREE_TYPE (val), DECL_RESULT (delete_dtor), val); add_stmt (build_stmt (0, RETURN_EXPR, val)); diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index ed219d7..94a5c64 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -18680,7 +18680,8 @@ cp_parser_template_name (cp_parser* parser, cp_parser_error (parser, "expected template-name"); return error_mark_node; } - else if (!DECL_P (decl) && !is_overloaded_fn (decl)) + else if ((!DECL_P (decl) && !is_overloaded_fn (decl)) + || TREE_CODE (decl) == USING_DECL) /* Repeat the lookup at instantiation time. */ decl = identifier; } @@ -21145,7 +21146,16 @@ cp_parser_enumerator_definition (cp_parser* parser, tree type) /* If we are processing a template, make sure the initializer of the enumerator doesn't contain any bare template parameter pack. */ - if (check_for_bare_parameter_packs (value)) + if (current_lambda_expr ()) + { + /* In a lambda it should work, but doesn't currently. */ + if (uses_parameter_packs (value)) + { + sorry ("unexpanded parameter pack in enumerator in lambda"); + value = error_mark_node; + } + } + else if (check_for_bare_parameter_packs (value)) value = error_mark_node; /* Create the enumerator. */ @@ -26534,7 +26544,7 @@ cp_parser_class_head (cp_parser* parser, } else if (nested_name_specifier) { - tree class_type; + type = TREE_TYPE (type); /* Given: @@ -26544,31 +26554,27 @@ cp_parser_class_head (cp_parser* parser, we will get a TYPENAME_TYPE when processing the definition of `S::T'. We need to resolve it to the actual type before we try to define it. */ - if (TREE_CODE (TREE_TYPE (type)) == TYPENAME_TYPE) + if (TREE_CODE (type) == TYPENAME_TYPE) { - class_type = resolve_typename_type (TREE_TYPE (type), - /*only_current_p=*/false); - if (TREE_CODE (class_type) != TYPENAME_TYPE) - type = TYPE_NAME (class_type); - else + type = resolve_typename_type (type, /*only_current_p=*/false); + if (TREE_CODE (type) == TYPENAME_TYPE) { cp_parser_error (parser, "could not resolve typename type"); type = error_mark_node; } } - if (maybe_process_partial_specialization (TREE_TYPE (type)) - == error_mark_node) + type = maybe_process_partial_specialization (type); + if (type == error_mark_node) { type = NULL_TREE; goto done; } - class_type = current_class_type; /* Enter the scope indicated by the nested-name-specifier. */ pushed_scope = push_scope (nested_name_specifier); /* Get the canonical version of this type. */ - type = TYPE_MAIN_DECL (TREE_TYPE (type)); + type = TYPE_MAIN_DECL (type); /* Call push_template_decl if it seems like we should be defining a template either from the template headers or the type we're defining, so that we diagnose both extra and missing headers. */ @@ -26627,6 +26633,14 @@ cp_parser_class_head (cp_parser* parser, if (type) { + if (current_lambda_expr () + && uses_parameter_packs (attributes)) + { + /* In a lambda this should work, but doesn't currently. */ + sorry ("unexpanded parameter pack in local class in lambda"); + attributes = NULL_TREE; + } + /* Apply attributes now, before any use of the class as a template argument in its base list. */ cplus_decl_attributes (&type, attributes, (int)ATTR_FLAG_TYPE_IN_PLACE); diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index bba62a5..f46a7ad 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -4273,10 +4273,27 @@ check_for_bare_parameter_packs (tree t, location_t loc /* = UNKNOWN_LOCATION */) cp_walk_tree (&t, &find_parameter_packs_r, &ppd, ppd.visited); delete ppd.visited; + if (!parameter_packs) + return false; + + if (loc == UNKNOWN_LOCATION) + loc = cp_expr_loc_or_input_loc (t); + /* It's OK for a lambda to have an unexpanded parameter pack from the containing context, but do complain about unexpanded capture packs. */ - if (current_class_type && LAMBDA_TYPE_P (current_class_type) - && CLASSTYPE_TEMPLATE_INFO (current_class_type)) + tree lam = current_lambda_expr (); + if (lam) + lam = TREE_TYPE (lam); + + if (lam && lam != current_class_type) + { + /* We're in a lambda, but it isn't the innermost class. + This should work, but currently doesn't. */ + sorry_at (loc, "unexpanded parameter pack in local class in lambda"); + return true; + } + + if (lam && CLASSTYPE_TEMPLATE_INFO (lam)) for (; parameter_packs; parameter_packs = TREE_CHAIN (parameter_packs)) { @@ -4287,8 +4304,6 @@ check_for_bare_parameter_packs (tree t, location_t loc /* = UNKNOWN_LOCATION */) if (parameter_packs) { - if (loc == UNKNOWN_LOCATION) - loc = cp_expr_loc_or_input_loc (t); error_at (loc, "parameter packs not expanded with %<...%>:"); while (parameter_packs) { @@ -13585,6 +13600,14 @@ tsubst_aggr_type (tree t, if (t == NULL_TREE) return NULL_TREE; + /* If T is an alias template specialization, we want to substitute that + rather than strip it, especially if it's dependent_alias_template_spec_p. + It should be OK not to handle entering_scope in this case, since + DECL_CONTEXT will never be an alias template specialization. We only get + here with an alias when tsubst calls us for TYPENAME_TYPE. */ + if (alias_template_specialization_p (t, nt_transparent)) + return tsubst (t, args, complain, in_decl); + switch (TREE_CODE (t)) { case RECORD_TYPE: @@ -28402,8 +28425,10 @@ build_non_dependent_expr (tree expr) if (is_overloaded_fn (inner_expr) || TREE_CODE (inner_expr) == OFFSET_REF) return orig_expr; - /* There is no need to return a proxy for a variable or enumerator. */ - if (VAR_P (expr) || TREE_CODE (expr) == CONST_DECL) + /* There is no need to return a proxy for a variable, parameter + or enumerator. */ + if (VAR_P (expr) || TREE_CODE (expr) == PARM_DECL + || TREE_CODE (expr) == CONST_DECL) return orig_expr; /* Preserve string constants; conversions from string constants to "char *" are allowed, even though normally a "const char *" @@ -28477,9 +28502,10 @@ make_args_non_dependent (vec<tree, va_gc> *args) by default. If set_canonical is true, we set TYPE_CANONICAL on it. */ static tree -make_auto_1 (tree name, bool set_canonical, - int level = current_template_depth + 1) +make_auto_1 (tree name, bool set_canonical, int level = -1) { + if (level == -1) + level = current_template_depth + 1; tree au = cxx_make_type (TEMPLATE_TYPE_PARM); TYPE_NAME (au) = build_decl (input_location, TYPE_DECL, name, au); TYPE_STUB_DECL (au) = TYPE_NAME (au); diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc index 07c2b33..466d6b5 100644 --- a/gcc/cp/semantics.cc +++ b/gcc/cp/semantics.cc @@ -3272,8 +3272,9 @@ finish_compound_literal (tree type, tree compound_literal, /* Represent other compound literals with TARGET_EXPR so we produce a prvalue, and can elide copies. */ - if (TREE_CODE (compound_literal) == CONSTRUCTOR - || TREE_CODE (compound_literal) == VEC_INIT_EXPR) + if (!VECTOR_TYPE_P (type) + && (TREE_CODE (compound_literal) == CONSTRUCTOR + || TREE_CODE (compound_literal) == VEC_INIT_EXPR)) { /* The CONSTRUCTOR is now an initializer, not a compound literal. */ if (TREE_CODE (compound_literal) == CONSTRUCTOR) diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc index 5d453e4..056f10f 100644 --- a/gcc/cp/tree.cc +++ b/gcc/cp/tree.cc @@ -3661,6 +3661,8 @@ build_min_non_dep_op_overload (enum tree_code op, nargs = call_expr_nargs (non_dep); expected_nargs = cp_tree_code_length (op); + if (TREE_CODE (TREE_TYPE (overload)) == METHOD_TYPE) + expected_nargs -= 1; if ((op == POSTINCREMENT_EXPR || op == POSTDECREMENT_EXPR) /* With -fpermissive non_dep could be operator++(). */ @@ -3687,7 +3689,7 @@ build_min_non_dep_op_overload (enum tree_code op, tree method = build_baselink (binfo, binfo, overload, NULL_TREE); fn = build_min (COMPONENT_REF, TREE_TYPE (overload), object, method, NULL_TREE); - for (int i = 1; i < nargs; i++) + for (int i = 0; i < nargs; i++) { tree arg = va_arg (p, tree); vec_safe_push (args, arg); @@ -3723,7 +3725,6 @@ build_min_non_dep_op_overload (tree non_dep, tree overload, tree object, tree method = build_baselink (binfo, binfo, overload, NULL_TREE); tree fn = build_min (COMPONENT_REF, TREE_TYPE (overload), object, method, NULL_TREE); - nargs--; gcc_assert (vec_safe_length (args) == nargs); tree call = build_min_non_dep_call_vec (non_dep, fn, args); diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc index 3a28d63..11c9d8a 100644 --- a/gcc/cp/typeck.cc +++ b/gcc/cp/typeck.cc @@ -2726,17 +2726,14 @@ build_class_member_access_expr (cp_expr object, tree member, /* Transform `(a, b).x' into `(*(a, &b)).x', `(a ? b : c).x' into `(*(a ? &b : &c)).x', and so on. A COND_EXPR is only an lvalue in the front end; only _DECLs and _REFs are lvalues in the back end. */ - { - tree temp = unary_complex_lvalue (ADDR_EXPR, object); - if (temp) - { - temp = cp_build_fold_indirect_ref (temp); - if (xvalue_p (object) && !xvalue_p (temp)) - /* Preserve xvalue kind. */ - temp = move (temp); - object = temp; - } - } + if (tree temp = unary_complex_lvalue (ADDR_EXPR, object)) + { + temp = cp_build_fold_indirect_ref (temp); + if (!lvalue_p (object) && lvalue_p (temp)) + /* Preserve rvalueness. */ + temp = move (temp); + object = temp; + } /* In [expr.ref], there is an explicit list of the valid choices for MEMBER. We check for each of those cases here. */ diff --git a/gcc/diagnostic.cc b/gcc/diagnostic.cc index f5f43d5..1047204 100644 --- a/gcc/diagnostic.cc +++ b/gcc/diagnostic.cc @@ -219,6 +219,8 @@ diagnostic_initialize (diagnostic_context *context, int n_opts) context->show_line_numbers_p = false; context->min_margin_width = 0; context->show_ruler_p = false; + context->report_bug = false; + if (const char *var = getenv ("GCC_EXTRA_DIAGNOSTIC_OUTPUT")) { if (!strcmp (var, "fixits-v1")) @@ -665,12 +667,16 @@ diagnostic_action_after_output (diagnostic_context *context, if (context->abort_on_error) real_abort (); - fnotice (stderr, "Please submit a full bug report,\n" - "with preprocessed source if appropriate.\n"); + if (context->report_bug) + fnotice (stderr, "\nPlease submit a full bug report, " + "with preprocessed source.\n"); + else + fnotice (stderr, "\nPlease submit a full bug report, " + "with preprocessed source (by using -freport-bug).\n"); + if (count > 0) - fnotice (stderr, - ("Please include the complete backtrace " - "with any bug report.\n")); + fnotice (stderr, "Please include the complete backtrace " + "with any bug report.\n"); fnotice (stderr, "See %s for instructions.\n", bug_report_url); exit (ICE_EXIT_CODE); @@ -1437,8 +1443,8 @@ num_digits (int value) /* Given a partial pathname as input, return another pathname that shares no directory elements with the pathname of __FILE__. This - is used by fancy_abort() to print `Internal compiler error in expr.cc' - instead of `Internal compiler error in ../../GCC/gcc/expr.cc'. */ + is used by fancy_abort() to print `internal compiler error in expr.cc' + instead of `internal compiler error in ../../GCC/gcc/expr.cc'. */ const char * trim_filename (const char *name) @@ -1988,7 +1994,7 @@ error_recursion (diagnostic_context *context) pp_newline_and_flush (context->printer); fnotice (stderr, - "Internal compiler error: Error reporting routines re-entered.\n"); + "internal compiler error: error reporting routines re-entered.\n"); /* Call diagnostic_action_after_output to get the "please submit a bug report" message. */ diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h index ccaa33b..3ca3297 100644 --- a/gcc/diagnostic.h +++ b/gcc/diagnostic.h @@ -340,6 +340,9 @@ struct diagnostic_context source output. */ bool show_ruler_p; + /* True if -freport-bug option is used. */ + bool report_bug; + /* Used to specify additional diagnostic output to be emitted after the rest of the diagnostic. This is for implementing -fdiagnostics-parseable-fixits and GCC_EXTRA_DIAGNOSTIC_OUTPUT. */ diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index bbde66c..854e297 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -13501,6 +13501,14 @@ In the same fashion, GCC provides @code{fpclassify}, @code{isfinite}, @code{__builtin_} prefixed. The @code{isinf} and @code{isnan} built-in functions appear both with and without the @code{__builtin_} prefix. +GCC provides built-in versions of the ISO C99 floating-point rounding and +exceptions handling functions @code{fegetround}, @code{feclearexcept} and +@code{feraiseexcept}. They may not be available for all targets, and because +they need close interaction with libc internal values, they may not be available +for all target libcs, but in all cases they will gracefully fallback to libc +calls. This built-in functions appear both with and without the +@code{__builtin_} prefix. + @deftypefn {Built-in Function} void *__builtin_alloca (size_t size) The @code{__builtin_alloca} function must be called at block scope. The function allocates an object @var{size} bytes large on the stack diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index ce3d78d..817c940 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -291,7 +291,7 @@ Objective-C and Objective-C++ Dialects}. -Warray-bounds -Warray-bounds=@var{n} -Warray-compare @gol -Wno-attributes -Wattribute-alias=@var{n} -Wno-attribute-alias @gol -Wno-attribute-warning @gol --Wbidi-chars=@r{[}none@r{|}unpaired@r{|}any@r{]} @gol +-Wbidi-chars=@r{[}none@r{|}unpaired@r{|}any@r{|}ucn@r{]} @gol -Wbool-compare -Wbool-operation @gol -Wno-builtin-declaration-mismatch @gol -Wno-builtin-macro-redefined -Wc90-c99-compat -Wc99-c11-compat @gol @@ -7766,7 +7766,7 @@ Attributes considered include @code{alloc_align}, @code{alloc_size}, This is the default. You can disable these warnings with either @option{-Wno-attribute-alias} or @option{-Wattribute-alias=0}. -@item -Wbidi-chars=@r{[}none@r{|}unpaired@r{|}any@r{]} +@item -Wbidi-chars=@r{[}none@r{|}unpaired@r{|}any@r{|}ucn@r{]} @opindex Wbidi-chars= @opindex Wbidi-chars @opindex Wno-bidi-chars @@ -7783,6 +7783,10 @@ bidi contexts. @option{-Wbidi-chars=none} turns the warning off. @option{-Wbidi-chars=any} warns about any use of bidirectional control characters. +By default, this warning does not warn about UCNs. It is, however, possible +to turn on such checking by using @option{-Wbidi-chars=unpaired,ucn} or +@option{-Wbidi-chars=any,ucn}. + @item -Wbool-compare @opindex Wno-bool-compare @opindex Wbool-compare diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index 7f0aab9..feacb12 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -6087,6 +6087,23 @@ mode @var{m}, which is a scalar or vector floating-point mode. This pattern is not allowed to @code{FAIL}. +@cindex @code{fegetround@var{m}} instruction pattern +@item @samp{fegetround@var{m}} +Store the current machine floating-point rounding mode into operand 0. +Operand 0 has mode @var{m}, which is scalar. This pattern is used to +implement the @code{fegetround} function from the ISO C99 standard. + +@cindex @code{feclearexcept@var{m}} instruction pattern +@cindex @code{feraiseexcept@var{m}} instruction pattern +@item @samp{feclearexcept@var{m}} +@item @samp{feraiseexcept@var{m}} +Clears or raises the supported machine floating-point exceptions +represented by the bits in operand 1. Error status is stored as +nonzero value in operand 0. Both operands have mode @var{m}, which is +a scalar. These patterns are used to implement the +@code{feclearexcept} and @code{feraiseexcept} functions from the ISO +C99 standard. + @cindex @code{exp@var{m}2} instruction pattern @item @samp{exp@var{m}2} Raise e (the base of natural logarithms) to the power of operand 1 diff --git a/gcc/dwarf2out.cc b/gcc/dwarf2out.cc index a5a7f63..ad1d804 100644 --- a/gcc/dwarf2out.cc +++ b/gcc/dwarf2out.cc @@ -13568,6 +13568,47 @@ qualified_die_p (dw_die_ref die, int *mask, unsigned int depth) return type; } +/* If TYPE is long double or complex long double that + should be emitted as artificial typedef to _Float128 or + complex _Float128, return the type it should be emitted as. + This is done in case the target already supports 16-byte + composite floating point type (ibm_extended_format). */ + +static tree +long_double_as_float128 (tree type) +{ + if (type != long_double_type_node + && type != complex_long_double_type_node) + return NULL_TREE; + + machine_mode mode, fmode; + if (TREE_CODE (type) == COMPLEX_TYPE) + mode = TYPE_MODE (TREE_TYPE (type)); + else + mode = TYPE_MODE (type); + if (known_eq (GET_MODE_SIZE (mode), 16) && !MODE_COMPOSITE_P (mode)) + FOR_EACH_MODE_IN_CLASS (fmode, MODE_FLOAT) + if (known_eq (GET_MODE_SIZE (fmode), 16) + && MODE_COMPOSITE_P (fmode)) + { + if (type == long_double_type_node) + { + if (float128_type_node + && (TYPE_MODE (float128_type_node) + == TYPE_MODE (type))) + return float128_type_node; + return NULL_TREE; + } + for (int i = 0; i < NUM_FLOATN_NX_TYPES; i++) + if (COMPLEX_FLOATN_NX_TYPE_NODE (i) != NULL_TREE + && (TYPE_MODE (COMPLEX_FLOATN_NX_TYPE_NODE (i)) + == TYPE_MODE (type))) + return COMPLEX_FLOATN_NX_TYPE_NODE (i); + } + + return NULL_TREE; +} + /* Given a pointer to an arbitrary ..._TYPE tree node, return a debugging entry that chains the modifiers specified by CV_QUALS in front of the given type. REVERSE is true if the type is to be interpreted in the @@ -13848,7 +13889,32 @@ modified_type_die (tree type, int cv_quals, bool reverse, } else if (is_base_type (type)) { - mod_type_die = base_type_die (type, reverse); + /* If a target supports long double as different floating point + modes with the same 16-byte size, use normal DW_TAG_base_type + only for the composite (ibm_extended_real_format) type and + for the other for the time being emit instead a "_Float128" + or "complex _Float128" DW_TAG_base_type and a "long double" + or "complex long double" typedef to it. */ + if (tree other_type = long_double_as_float128 (type)) + { + dw_die_ref other_die; + if (TYPE_NAME (other_type)) + other_die + = modified_type_die (other_type, TYPE_UNQUALIFIED, reverse, + context_die); + else + { + other_die = base_type_die (type, reverse); + add_child_die (comp_unit_die (), other_die); + add_name_attribute (other_die, + TREE_CODE (type) == COMPLEX_TYPE + ? "complex _Float128" : "_Float128"); + } + mod_type_die = new_die_raw (DW_TAG_typedef); + add_AT_die_ref (mod_type_die, DW_AT_type, other_die); + } + else + mod_type_die = base_type_die (type, reverse); /* The DIE with DW_AT_endianity is placed right after the naked DIE. */ if (reverse_base_type) diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index ea90c19..877f345 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,44 @@ +2022-01-27 Harald Anlauf <anlauf@gmx.de> + + PR fortran/104128 + * expr.cc (gfc_copy_expr): Convert internal representation of + string to wide char in value only for default character kind. + * target-memory.cc (interpret_array): Pass flag for conversion of + wide chars. + (gfc_target_interpret_expr): Likewise. + +2022-01-27 Harald Anlauf <anlauf@gmx.de> + + PR fortran/84784 + * trans-intrinsic.cc (conv_intrinsic_image_status): Convert result + to resulting (default) integer type. + (conv_intrinsic_team_number): Likewise. + (gfc_conv_intrinsic_popcnt_poppar): Likewise. + +2022-01-25 Harald Anlauf <anlauf@gmx.de> + + PR fortran/104227 + * check.cc (gfc_calculate_transfer_sizes): Fix checking of arrays + passed as MOLD argument to the TRANSFER intrinsic for having + storage size zero. + +2022-01-25 Harald Anlauf <anlauf@gmx.de> + + PR fortran/104212 + * check.cc (gfc_check_norm2): Check that optional argument DIM is + scalar. + (gfc_check_parity): Likewise. + +2022-01-24 Jakub Jelinek <jakub@redhat.com> + + * lang.opt (fconvert=): Add EnumSet property and mention also + r16_ieee and r16_ibm arguments. + (big-endian, little-endian, native, swap): Add Set(1) property. + (r16_ieee, r16_ibm): New EnumValue entries with Set(2) property. + * trans-types.cc (gfc_init_kinds): Emit gfc_fatal_error for + -fconvert=r16_ieee or -fconvert=r16_ibm when R16_IEEE <=> R16_IBM + conversions aren't supported. + 2022-01-22 Harald Anlauf <anlauf@gmx.de> PR fortran/104127 diff --git a/gcc/fortran/check.cc b/gcc/fortran/check.cc index 5fe8d45..d6c6767 100644 --- a/gcc/fortran/check.cc +++ b/gcc/fortran/check.cc @@ -4338,6 +4338,9 @@ gfc_check_norm2 (gfc_expr *array, gfc_expr *dim) if (!array_check (array, 0)) return false; + if (!dim_check (dim, 1, false)) + return false; + if (!dim_rank_check (dim, array, false)) return false; @@ -4476,6 +4479,9 @@ gfc_check_parity (gfc_expr *mask, gfc_expr *dim) if (!array_check (mask, 0)) return false; + if (!dim_check (dim, 1, false)) + return false; + if (!dim_rank_check (dim, mask, false)) return false; @@ -6145,7 +6151,7 @@ gfc_calculate_transfer_sizes (gfc_expr *source, gfc_expr *mold, gfc_expr *size, * If SIZE is present, the result is an array of rank one and size SIZE. */ if (result_elt_size == 0 && *source_size > 0 && !size - && mold->expr_type == EXPR_ARRAY) + && (mold->expr_type == EXPR_ARRAY || mold->rank)) { gfc_error ("%<MOLD%> argument of %<TRANSFER%> intrinsic at %L is an " "array and shall not have storage size 0 when %<SOURCE%> " diff --git a/gcc/fortran/expr.cc b/gcc/fortran/expr.cc index 279d9b3..ed82a94 100644 --- a/gcc/fortran/expr.cc +++ b/gcc/fortran/expr.cc @@ -312,7 +312,8 @@ gfc_copy_expr (gfc_expr *p) break; case BT_CHARACTER: - if (p->representation.string) + if (p->representation.string + && p->ts.kind == gfc_default_character_kind) q->value.character.string = gfc_char_to_widechar (q->representation.string); else diff --git a/gcc/fortran/target-memory.cc b/gcc/fortran/target-memory.cc index 361907b..7ce7d73 100644 --- a/gcc/fortran/target-memory.cc +++ b/gcc/fortran/target-memory.cc @@ -365,7 +365,8 @@ gfc_target_encode_expr (gfc_expr *source, unsigned char *buffer, static size_t -interpret_array (unsigned char *buffer, size_t buffer_size, gfc_expr *result) +interpret_array (unsigned char *buffer, size_t buffer_size, gfc_expr *result, + bool convert_widechar) { gfc_constructor_base base = NULL; size_t array_size = 1; @@ -390,7 +391,7 @@ interpret_array (unsigned char *buffer, size_t buffer_size, gfc_expr *result) gfc_constructor_append_expr (&base, e, &result->where); ptr += gfc_target_interpret_expr (&buffer[ptr], buffer_size - ptr, e, - true); + convert_widechar); } result->value.constructor = base; @@ -580,7 +581,7 @@ gfc_target_interpret_expr (unsigned char *buffer, size_t buffer_size, gfc_expr *result, bool convert_widechar) { if (result->expr_type == EXPR_ARRAY) - return interpret_array (buffer, buffer_size, result); + return interpret_array (buffer, buffer_size, result, convert_widechar); switch (result->ts.type) { diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc index 2f0c8a4..cfb6eac 100644 --- a/gcc/fortran/trans-array.cc +++ b/gcc/fortran/trans-array.cc @@ -9102,6 +9102,10 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl, continue; } + /* Do not broadcast a caf_token. These are local to the image. */ + if (attr->caf_token) + continue; + add_when_allocated = NULL_TREE; if (cmp_has_alloc_comps && !c->attr.pointer && !c->attr.proc_pointer) @@ -9134,10 +9138,13 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl, if (attr->dimension) { tmp = gfc_get_element_type (TREE_TYPE (comp)); - ubound = gfc_full_array_size (&tmpblock, comp, - c->ts.type == BT_CLASS - ? CLASS_DATA (c)->as->rank - : c->as->rank); + if (!GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (comp))) + ubound = GFC_TYPE_ARRAY_SIZE (TREE_TYPE (comp)); + else + ubound = gfc_full_array_size (&tmpblock, comp, + c->ts.type == BT_CLASS + ? CLASS_DATA (c)->as->rank + : c->as->rank); } else { @@ -9145,26 +9152,39 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl, ubound = build_int_cst (gfc_array_index_type, 1); } - cdesc = gfc_get_array_type_bounds (tmp, 1, 0, &gfc_index_one_node, - &ubound, 1, - GFC_ARRAY_ALLOCATABLE, false); + /* Treat strings like arrays. Or the other way around, do not + * generate an additional array layer for scalar components. */ + if (attr->dimension || c->ts.type == BT_CHARACTER) + { + cdesc = gfc_get_array_type_bounds (tmp, 1, 0, &gfc_index_one_node, + &ubound, 1, + GFC_ARRAY_ALLOCATABLE, false); - cdesc = gfc_create_var (cdesc, "cdesc"); - DECL_ARTIFICIAL (cdesc) = 1; + cdesc = gfc_create_var (cdesc, "cdesc"); + DECL_ARTIFICIAL (cdesc) = 1; - gfc_add_modify (&tmpblock, gfc_conv_descriptor_dtype (cdesc), - gfc_get_dtype_rank_type (1, tmp)); - gfc_conv_descriptor_lbound_set (&tmpblock, cdesc, - gfc_index_zero_node, - gfc_index_one_node); - gfc_conv_descriptor_stride_set (&tmpblock, cdesc, - gfc_index_zero_node, - gfc_index_one_node); - gfc_conv_descriptor_ubound_set (&tmpblock, cdesc, - gfc_index_zero_node, ubound); + gfc_add_modify (&tmpblock, gfc_conv_descriptor_dtype (cdesc), + gfc_get_dtype_rank_type (1, tmp)); + gfc_conv_descriptor_lbound_set (&tmpblock, cdesc, + gfc_index_zero_node, + gfc_index_one_node); + gfc_conv_descriptor_stride_set (&tmpblock, cdesc, + gfc_index_zero_node, + gfc_index_one_node); + gfc_conv_descriptor_ubound_set (&tmpblock, cdesc, + gfc_index_zero_node, ubound); + } + else + /* Prevent warning. */ + cdesc = NULL_TREE; if (attr->dimension) - comp = gfc_conv_descriptor_data_get (comp); + { + if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (comp))) + comp = gfc_conv_descriptor_data_get (comp); + else + comp = gfc_build_addr_expr (NULL_TREE, comp); + } else { gfc_se se; @@ -9172,14 +9192,18 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl, gfc_init_se (&se, NULL); comp = gfc_conv_scalar_to_descriptor (&se, comp, - c->ts.type == BT_CLASS - ? CLASS_DATA (c)->attr - : c->attr); - comp = gfc_build_addr_expr (NULL_TREE, comp); + c->ts.type == BT_CLASS + ? CLASS_DATA (c)->attr + : c->attr); + if (c->ts.type == BT_CHARACTER) + comp = gfc_build_addr_expr (NULL_TREE, comp); gfc_add_block_to_block (&tmpblock, &se.pre); } - gfc_conv_descriptor_data_set (&tmpblock, cdesc, comp); + if (attr->dimension || c->ts.type == BT_CHARACTER) + gfc_conv_descriptor_data_set (&tmpblock, cdesc, comp); + else + cdesc = comp; tree fndecl; diff --git a/gcc/fortran/trans-intrinsic.cc b/gcc/fortran/trans-intrinsic.cc index fccf0a9..e680de1 100644 --- a/gcc/fortran/trans-intrinsic.cc +++ b/gcc/fortran/trans-intrinsic.cc @@ -2620,7 +2620,7 @@ conv_intrinsic_image_status (gfc_se *se, gfc_expr *expr) else gcc_unreachable (); - se->expr = tmp; + se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind), tmp); } static void @@ -2662,7 +2662,7 @@ conv_intrinsic_team_number (gfc_se *se, gfc_expr *expr) else gcc_unreachable (); - se->expr = tmp; + se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind), tmp); } @@ -7255,12 +7255,13 @@ gfc_conv_intrinsic_popcnt_poppar (gfc_se * se, gfc_expr *expr, int parity) /* Combine the results. */ if (parity) - se->expr = fold_build2_loc (input_location, BIT_XOR_EXPR, result_type, - call1, call2); + se->expr = fold_build2_loc (input_location, BIT_XOR_EXPR, + integer_type_node, call1, call2); else - se->expr = fold_build2_loc (input_location, PLUS_EXPR, result_type, - call1, call2); + se->expr = fold_build2_loc (input_location, PLUS_EXPR, + integer_type_node, call1, call2); + se->expr = convert (result_type, se->expr); return; } @@ -11211,24 +11212,31 @@ conv_co_collective (gfc_code *code) return gfc_finish_block (&block); } + gfc_symbol *derived = code->ext.actual->expr->ts.type == BT_DERIVED + ? code->ext.actual->expr->ts.u.derived : NULL; + /* Handle the array. */ gfc_init_se (&argse, NULL); - if (code->ext.actual->expr->rank == 0) - { - symbol_attribute attr; - gfc_clear_attr (&attr); - gfc_init_se (&argse, NULL); - gfc_conv_expr (&argse, code->ext.actual->expr); - gfc_add_block_to_block (&block, &argse.pre); - gfc_add_block_to_block (&post_block, &argse.post); - array = gfc_conv_scalar_to_descriptor (&argse, argse.expr, attr); - array = gfc_build_addr_expr (NULL_TREE, array); - } - else + if (!derived || !derived->attr.alloc_comp + || code->resolved_isym->id != GFC_ISYM_CO_BROADCAST) { - argse.want_pointer = 1; - gfc_conv_expr_descriptor (&argse, code->ext.actual->expr); - array = argse.expr; + if (code->ext.actual->expr->rank == 0) + { + symbol_attribute attr; + gfc_clear_attr (&attr); + gfc_init_se (&argse, NULL); + gfc_conv_expr (&argse, code->ext.actual->expr); + gfc_add_block_to_block (&block, &argse.pre); + gfc_add_block_to_block (&post_block, &argse.post); + array = gfc_conv_scalar_to_descriptor (&argse, argse.expr, attr); + array = gfc_build_addr_expr (NULL_TREE, array); + } + else + { + argse.want_pointer = 1; + gfc_conv_expr_descriptor (&argse, code->ext.actual->expr); + array = argse.expr; + } } gfc_add_block_to_block (&block, &argse.pre); @@ -11289,9 +11297,6 @@ conv_co_collective (gfc_code *code) gcc_unreachable (); } - gfc_symbol *derived = code->ext.actual->expr->ts.type == BT_DERIVED - ? code->ext.actual->expr->ts.u.derived : NULL; - if (derived && derived->attr.alloc_comp && code->resolved_isym->id == GFC_ISYM_CO_BROADCAST) /* The derived type has the attribute 'alloc_comp'. */ diff --git a/gcc/gimple-fold.cc b/gcc/gimple-fold.cc index 3639aa2..9e0c01d 100644 --- a/gcc/gimple-fold.cc +++ b/gcc/gimple-fold.cc @@ -8539,11 +8539,12 @@ arith_code_with_undefined_signed_overflow (tree_code code) its operand, carrying out the operation in the corresponding unsigned type and converting the result back to the original type. - Returns a sequence of statements that replace STMT and also contain - a modified form of STMT itself. */ + If IN_PLACE is true, adjust the stmt in place and return NULL. + Otherwise returns a sequence of statements that replace STMT and also + contain a modified form of STMT itself. */ gimple_seq -rewrite_to_defined_overflow (gimple *stmt) +rewrite_to_defined_overflow (gimple *stmt, bool in_place /* = false */) { if (dump_file && (dump_flags & TDF_DETAILS)) { @@ -8568,9 +8569,24 @@ rewrite_to_defined_overflow (gimple *stmt) if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR) gimple_assign_set_rhs_code (stmt, PLUS_EXPR); gimple_set_modified (stmt, true); - gimple_seq_add_stmt (&stmts, stmt); + if (in_place) + { + gimple_stmt_iterator gsi = gsi_for_stmt (stmt); + if (stmts) + gsi_insert_seq_before (&gsi, stmts, GSI_SAME_STMT); + stmts = NULL; + } + else + gimple_seq_add_stmt (&stmts, stmt); gimple *cvt = gimple_build_assign (lhs, NOP_EXPR, gimple_assign_lhs (stmt)); - gimple_seq_add_stmt (&stmts, cvt); + if (in_place) + { + gimple_stmt_iterator gsi = gsi_for_stmt (stmt); + gsi_insert_after (&gsi, cvt, GSI_SAME_STMT); + update_stmt (stmt); + } + else + gimple_seq_add_stmt (&stmts, cvt); return stmts; } diff --git a/gcc/gimple-fold.h b/gcc/gimple-fold.h index 11e5732..82631a4 100644 --- a/gcc/gimple-fold.h +++ b/gcc/gimple-fold.h @@ -62,7 +62,7 @@ extern tree gimple_fold_indirect_ref (tree); extern bool gimple_fold_builtin_sprintf (gimple_stmt_iterator *); extern bool gimple_fold_builtin_snprintf (gimple_stmt_iterator *); extern bool arith_code_with_undefined_signed_overflow (tree_code); -extern gimple_seq rewrite_to_defined_overflow (gimple *); +extern gimple_seq rewrite_to_defined_overflow (gimple *, bool = false); extern void replace_call_with_value (gimple_stmt_iterator *, tree); extern tree tree_vec_extract (gimple_stmt_iterator *, tree, tree, tree, tree); diff --git a/gcc/gimple-ssa-warn-access.cc b/gcc/gimple-ssa-warn-access.cc index 8bc33ee..3dcaf42 100644 --- a/gcc/gimple-ssa-warn-access.cc +++ b/gcc/gimple-ssa-warn-access.cc @@ -2053,7 +2053,7 @@ const pass_data pass_data_waccess = { GIMPLE_PASS, "waccess", OPTGROUP_NONE, - TV_NONE, + TV_WARN_ACCESS, /* timer variable */ PROP_cfg, /* properties_required */ 0, /* properties_provided */ 0, /* properties_destroyed */ @@ -3880,9 +3880,17 @@ pass_waccess::warn_invalid_pointer (tree ref, gimple *use_stmt, bool maybe, bool equality /* = false */) { /* Avoid printing the unhelpful "<unknown>" in the diagnostics. */ - if (ref && TREE_CODE (ref) == SSA_NAME - && (!SSA_NAME_VAR (ref) || DECL_ARTIFICIAL (SSA_NAME_VAR (ref)))) - ref = NULL_TREE; + if (ref && TREE_CODE (ref) == SSA_NAME) + { + tree var = SSA_NAME_VAR (ref); + if (!var) + ref = NULL_TREE; + /* Don't warn for cases like when a cdtor returns 'this' on ARM. */ + else if (warning_suppressed_p (var, OPT_Wuse_after_free)) + return; + else if (DECL_ARTIFICIAL (var)) + ref = NULL_TREE; + } location_t use_loc = gimple_location (use_stmt); if (use_loc == UNKNOWN_LOCATION) diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc index bf2f60c..cd4b613 100644 --- a/gcc/gimplify.cc +++ b/gcc/gimplify.cc @@ -9552,7 +9552,10 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, == REFERENCE_TYPE)) decl = TREE_OPERAND (decl, 0); } - if (decl != orig_decl && DECL_P (decl) && indir_p) + if (decl != orig_decl && DECL_P (decl) && indir_p + && (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE + || (decl_ref + && TREE_CODE (TREE_TYPE (decl_ref)) == POINTER_TYPE))) { gomp_map_kind k = ((code == OACC_EXIT_DATA || code == OMP_TARGET_EXIT_DATA) diff --git a/gcc/graph.cc b/gcc/graph.cc index 9990c8e..bc29862 100644 --- a/gcc/graph.cc +++ b/gcc/graph.cc @@ -169,14 +169,14 @@ draw_cfg_nodes_no_loops (pretty_printer *pp, struct function *fun) int *rpo = XNEWVEC (int, n_basic_blocks_for_fn (fun)); int i, n; - auto_sbitmap visited (last_basic_block_for_fn (cfun)); + auto_sbitmap visited (last_basic_block_for_fn (fun)); bitmap_clear (visited); n = pre_and_rev_post_order_compute_fn (fun, NULL, rpo, true); for (i = n_basic_blocks_for_fn (fun) - n; i < n_basic_blocks_for_fn (fun); i++) { - basic_block bb = BASIC_BLOCK_FOR_FN (cfun, rpo[i]); + basic_block bb = BASIC_BLOCK_FOR_FN (fun, rpo[i]); draw_cfg_node (pp, fun->funcdef_no, bb); bitmap_set_bit (visited, bb->index); } @@ -248,7 +248,8 @@ draw_cfg_nodes_for_loop (pretty_printer *pp, int funcdef_no, static void draw_cfg_nodes (pretty_printer *pp, struct function *fun) { - if (loops_for_fn (fun)) + /* ??? The loop and dominance APIs are dependent on fun == cfun. */ + if (fun == cfun && loops_for_fn (fun)) draw_cfg_nodes_for_loop (pp, fun->funcdef_no, get_loop (fun, 0)); else draw_cfg_nodes_no_loops (pp, fun); @@ -267,7 +268,7 @@ draw_cfg_edges (pretty_printer *pp, struct function *fun) edge e; edge_iterator ei; unsigned int idx = 0; - FOR_EACH_BB_FN (bb, cfun) + FOR_EACH_BB_FN (bb, fun) FOR_EACH_EDGE (e, ei, bb->succs) { if (e->flags & EDGE_DFS_BACK) @@ -275,13 +276,13 @@ draw_cfg_edges (pretty_printer *pp, struct function *fun) idx++; } - mark_dfs_back_edges (); - FOR_ALL_BB_FN (bb, cfun) + mark_dfs_back_edges (fun); + FOR_ALL_BB_FN (bb, fun) draw_cfg_node_succ_edges (pp, fun->funcdef_no, bb); /* Restore EDGE_DFS_BACK flag from dfs_back. */ idx = 0; - FOR_EACH_BB_FN (bb, cfun) + FOR_EACH_BB_FN (bb, fun) FOR_EACH_EDGE (e, ei, bb->succs) { if (bitmap_bit_p (dfs_back, idx)) diff --git a/gcc/ipa-modref-tree.cc b/gcc/ipa-modref-tree.cc index 97e497a..828994f 100644 --- a/gcc/ipa-modref-tree.cc +++ b/gcc/ipa-modref-tree.cc @@ -130,8 +130,7 @@ modref_access_node::update (poly_int64 parm_offset1, else { if (dump_file) - fprintf (dump_file, - "--param param=modref-max-adjustments limit reached:"); + fprintf (dump_file, "--param modref-max-adjustments limit reached:"); if (!known_eq (parm_offset, parm_offset1)) { if (dump_file) @@ -594,11 +593,11 @@ modref_access_node::insert (vec <modref_access_node, va_gc> *&accesses, return -1; if (dump_file && best2 >= 0) fprintf (dump_file, - "--param param=modref-max-accesses limit reached;" + "--param modref-max-accesses limit reached;" " merging %i and %i\n", best1, best2); else if (dump_file) fprintf (dump_file, - "--param param=modref-max-accesses limit reached;" + "--param modref-max-accesses limit reached;" " merging with %i\n", best1); modref_access_node::try_merge_with (accesses, best1); if (best2 >= 0) @@ -825,8 +824,7 @@ modref_access_node::insert_kill (vec<modref_access_node> &kills, if ((int)kills.length () >= param_modref_max_accesses) { if (dump_file) - fprintf (dump_file, - "--param param=modref-max-accesses limit reached:"); + fprintf (dump_file, "--param modref-max-accesses limit reached:"); return false; } a.adjustments = 0; diff --git a/gcc/ipa-modref-tree.h b/gcc/ipa-modref-tree.h index edb3b49..fdaa961 100644 --- a/gcc/ipa-modref-tree.h +++ b/gcc/ipa-modref-tree.h @@ -197,8 +197,7 @@ struct GTY((user)) modref_ref_node { if (dump_file) fprintf (dump_file, - "--param param=modref-max-accesses limit reached;" - " collapsing\n"); + "--param modref-max-accesses limit reached; collapsing\n"); collapse (); } return ret != 0; @@ -252,7 +251,7 @@ struct GTY((user)) modref_base_node if (ref && refs && refs->length () >= max_refs) { if (dump_file) - fprintf (dump_file, "--param param=modref-max-refs limit reached;" + fprintf (dump_file, "--param modref-max-refs limit reached;" " using 0\n"); ref = 0; ref_node = search (ref); @@ -344,12 +343,12 @@ struct GTY((user)) modref_tree if (base_node) { if (dump_file) - fprintf (dump_file, "--param param=modref-max-bases" + fprintf (dump_file, "--param modref-max-bases" " limit reached; using ref\n"); return base_node; } if (dump_file) - fprintf (dump_file, "--param param=modref-max-bases" + fprintf (dump_file, "--param modref-max-bases" " limit reached; using 0\n"); base = 0; base_node = search (base); diff --git a/gcc/optabs.def b/gcc/optabs.def index bb46083..801310e 100644 --- a/gcc/optabs.def +++ b/gcc/optabs.def @@ -331,6 +331,10 @@ OPTAB_D (sinh_optab, "sinh$a2") OPTAB_D (tan_optab, "tan$a2") OPTAB_D (tanh_optab, "tanh$a2") +OPTAB_D (fegetround_optab, "fegetround$a") +OPTAB_D (feclearexcept_optab, "feclearexcept$a") +OPTAB_D (feraiseexcept_optab, "feraiseexcept$a") + /* C99 implementations of fmax/fmin. */ OPTAB_D (fmax_optab, "fmax$a3") OPTAB_D (fmin_optab, "fmin$a3") diff --git a/gcc/opts.cc b/gcc/opts.cc index f21c821..7d30deb 100644 --- a/gcc/opts.cc +++ b/gcc/opts.cc @@ -3158,6 +3158,10 @@ common_handle_option (struct gcc_options *opts, dc->tabstop = value; break; + case OPT_freport_bug: + dc->report_bug = value; + break; + default: /* If the flag was handled in a standard way, assume the lack of processing here is intentional. */ diff --git a/gcc/pointer-query.cc b/gcc/pointer-query.cc index a61ac89..b092ef4 100644 --- a/gcc/pointer-query.cc +++ b/gcc/pointer-query.cc @@ -629,7 +629,7 @@ access_ref::phi () const ARG refers to the null pointer. Return true on success and false on failure. */ -bool +void access_ref::merge_ref (vec<access_ref> *all_refs, tree arg, gimple *stmt, int ostype, bool skip_null, ssa_name_limit_t &snlim, pointer_query &qry) @@ -637,8 +637,16 @@ access_ref::merge_ref (vec<access_ref> *all_refs, tree arg, gimple *stmt, access_ref aref; if (!compute_objsize_r (arg, stmt, false, ostype, &aref, snlim, &qry) || aref.sizrng[0] < 0) - /* This may be a PHI with all null pointer arguments. */ - return false; + { + /* This may be a PHI with all null pointer arguments. Handle it + conservatively by setting all properties to the most permissive + values. */ + base0 = false; + offrng[0] = offrng[1] = 0; + add_max_offset (); + set_max_size_range (); + return; + } if (all_refs) { @@ -675,13 +683,13 @@ access_ref::merge_ref (vec<access_ref> *all_refs, tree arg, gimple *stmt, if (arg_known_size) sizrng[0] = aref.sizrng[0]; - return true; + return; } /* Disregard null pointers in PHIs with two or more arguments. TODO: Handle this better! */ if (nullp) - return true; + return; const bool known_size = (sizrng[0] != 0 || sizrng[1] != maxobjsize); @@ -717,7 +725,7 @@ access_ref::merge_ref (vec<access_ref> *all_refs, tree arg, gimple *stmt, sizrng[0] = minsize; parmarray = merged_parmarray; - return true; + return; } /* Determine and return the largest object to which *THIS refers. If @@ -755,14 +763,12 @@ access_ref::get_ref (vec<access_ref> *all_refs, access_ref aref; tree arg1 = gimple_assign_rhs1 (def_stmt); - if (!aref.merge_ref (all_refs, arg1, def_stmt, ostype, false, - *psnlim, *qry)) - return NULL_TREE; + aref.merge_ref (all_refs, arg1, def_stmt, ostype, false, + *psnlim, *qry); tree arg2 = gimple_assign_rhs2 (def_stmt); - if (!aref.merge_ref (all_refs, arg2, def_stmt, ostype, false, - *psnlim, *qry)) - return NULL_TREE; + aref.merge_ref (all_refs, arg2, def_stmt, ostype, false, + *psnlim, *qry); if (pref && pref != this) { @@ -801,15 +807,23 @@ access_ref::get_ref (vec<access_ref> *all_refs, phi_ref = *pref; } + const offset_int maxobjsize = wi::to_offset (max_object_size ()); const unsigned nargs = gimple_phi_num_args (phi_stmt); for (unsigned i = 0; i < nargs; ++i) { access_ref phi_arg_ref; bool skip_null = i || i + 1 < nargs; tree arg = gimple_phi_arg_def (phi_stmt, i); - if (!phi_ref.merge_ref (all_refs, arg, phi_stmt, ostype, skip_null, - *psnlim, *qry)) - return NULL_TREE; + phi_ref.merge_ref (all_refs, arg, phi_stmt, ostype, skip_null, + *psnlim, *qry); + + if (!phi_ref.base0 + && phi_ref.sizrng[0] == 0 + && phi_ref.sizrng[1] >= maxobjsize) + /* When an argument results in the most permissive result, + the remaining arguments cannot constrain it. Short-circuit + the evaluation. */ + break; } if (phi_ref.sizrng[0] < 0) @@ -1627,36 +1641,6 @@ pointer_query::dump (FILE *dump_file, bool contents /* = false */) } fputc ('\n', dump_file); - - { - fputs ("\npointer_query cache contents (again):\n", dump_file); - - tree var; - unsigned i; - FOR_EACH_SSA_NAME (i, var, cfun) - { - if (TREE_CODE (TREE_TYPE (var)) != POINTER_TYPE) - continue; - - for (unsigned ost = 0; ost != 2; ++ost) - { - if (const access_ref *cache_ref = get_ref (var, ost)) - { - unsigned ver = SSA_NAME_VERSION (var); - fprintf (dump_file, " %u.%u: ", ver, ost); - if (tree name = ssa_name (ver)) - { - print_generic_expr (dump_file, name); - fputs (" = ", dump_file); - } - else - fprintf (dump_file, " _%u = ", ver); - - cache_ref->dump (dump_file); - } - } - } - } } /* A helper of compute_objsize_r() to determine the size from an assignment diff --git a/gcc/pointer-query.h b/gcc/pointer-query.h index 7dc965b..dbdcd59 100644 --- a/gcc/pointer-query.h +++ b/gcc/pointer-query.h @@ -67,7 +67,7 @@ struct access_ref gphi *phi () const; /* Merge the result for a pointer with *THIS. */ - bool merge_ref (vec<access_ref> *all_refs, tree, gimple *, int, bool, + void merge_ref (vec<access_ref> *all_refs, tree, gimple *, int, bool, ssa_name_limit_t &, pointer_query &); /* Return the object to which REF refers. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6d22984..012e2c3 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,274 @@ +2022-01-27 David Malcolm <dmalcolm@redhat.com> + + * gcc.dg/analyzer/data-model-1.c: Add dg-message directives for + expected region creation events. + * gcc.dg/analyzer/malloc-1.c: Likewise. + * gcc.dg/analyzer/memset-CVE-2017-18549-1.c: Likewise. + * gcc.dg/analyzer/pr101547.c: Likewise. + * gcc.dg/analyzer/pr101875.c: Likewise. + * gcc.dg/analyzer/pr101962.c: Likewise. + * gcc.dg/analyzer/pr104224.c: Likewise. + * gcc.dg/analyzer/pr94047.c: Likewise. + * gcc.dg/analyzer/symbolic-1.c: Likewise. + * gcc.dg/analyzer/uninit-1.c: Likewise. + * gcc.dg/analyzer/uninit-4.c: Likewise. + * gcc.dg/analyzer/uninit-alloca.c: New test. + * gcc.dg/analyzer/uninit-pr94713.c: Add dg-message directive for + expected region creation event. + * gcc.dg/analyzer/uninit-pr94714.c: Likewise. + * gcc.dg/analyzer/zlib-3.c: Likewise. + +2022-01-27 Jason Merrill <jason@redhat.com> + + PR c++/104245 + PR c++/51344 + * g++.dg/lto/alignas1_0.C: New test. + +2022-01-27 Uroš Bizjak <ubizjak@gmail.com> + + * gfortran.dg/ieee/signaling_1.f90 (dg-do): + Run only on non-ia32 targets. + * gfortran.dg/ieee/signaling_2.f90 (dg-do): Ditto. + * gfortran.dg/ieee/signaling_3.f90 (dg-do): Ditto. + +2022-01-27 Harald Anlauf <anlauf@gmx.de> + + PR fortran/104128 + * gfortran.dg/transfer_simplify_14.f90: New test. + +2022-01-27 Patrick Palka <ppalka@redhat.com> + + PR c++/82632 + * g++.dg/cpp1z/class-deduction104.C: New test. + * g++.dg/cpp1z/class-deduction105.C: New test. + +2022-01-27 Harald Anlauf <anlauf@gmx.de> + + PR fortran/84784 + * gfortran.dg/pr84784.f90: New test. + +2022-01-27 Patrick Palka <ppalka@redhat.com> + + PR c++/99895 + * g++.dg/cpp2a/consteval-memfn1.C: New test. + * g++.dg/cpp2a/consteval-memfn2.C: New test. + * g++.dg/cpp2a/consteval28.C: New test. + +2022-01-27 Patrick Palka <ppalka@redhat.com> + + PR c++/92944 + PR c++/103678 + * g++.dg/cpp2a/concepts-partial-spec10.C: New test. + * g++.dg/cpp2a/concepts-partial-spec11.C: New test. + +2022-01-27 Marek Polacek <polacek@redhat.com> + + PR c++/101988 + * g++.dg/cpp1z/class-deduction-new1.C: New test. + * g++.dg/cpp23/auto-array2.C: New test. + +2022-01-27 Kewen Lin <linkw@linux.ibm.com> + + PR target/103702 + * gcc.target/powerpc/pr103702.c: New test. + +2022-01-27 Chung-Lin Tang <cltang@codesourcery.com> + + PR middle-end/103642 + * c-c++-common/gomp/pr103642.c: New test. + +2022-01-27 Andrew Pinski <apinski@marvell.com> + + PR target/104201 + * gcc.target/aarch64/branch-protection-attr.c: Fix quoting for + the expected error message on line 5 of leaf. + +2022-01-27 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/104196 + * gcc.c-torture/execute/pr104196.c: New test. + +2022-01-26 Jakub Jelinek <jakub@redhat.com> + + PR target/104239 + * gcc.target/powerpc/pr104239-3.c: New test. + +2022-01-26 Jakub Jelinek <jakub@redhat.com> + + PR target/104239 + * gcc.target/powerpc/pr104239-1.c: New test. + * gcc.target/powerpc/pr104239-2.c: New test. + +2022-01-26 Jakub Jelinek <jakub@redhat.com> + + PR c++/104226 + * g++.dg/cpp0x/constexpr-104226.C: New test. + +2022-01-26 Marek Polacek <polacek@redhat.com> + + PR target/104213 + * g++.dg/warn/Wuse-after-free2.C: New test. + * g++.dg/warn/Wuse-after-free3.C: New test. + +2022-01-26 Jason Merrill <jason@redhat.com> + + PR c++/104235 + * g++.dg/parse/template-keyword2.C: New test. + +2022-01-26 Martin Liska <mliska@suse.cz> + + * gcc.dg/tree-ssa/modref-7.c: Update scanned patterns. + * gcc.dg/tree-ssa/modref-8.c: Likewise. + +2022-01-26 David Malcolm <dmalcolm@redhat.com> + + PR analyzer/104224 + * gcc.dg/analyzer/pr104224.c: New test. + +2022-01-26 Jakub Jelinek <jakub@redhat.com> + + PR target/104188 + * gcc.target/i386/pr104188.c: Add dg-require-effective-target + sse2_runtime. Add -msse2 to dg-options. + +2022-01-26 Jason Merrill <jason@redhat.com> + + PR c++/103057 + * g++.dg/cpp0x/alias-decl-void1.C: New test. + +2022-01-25 Harald Anlauf <anlauf@gmx.de> + + PR fortran/104227 + * gfortran.dg/transfer_check_6.f90: New test. + +2022-01-25 Harald Anlauf <anlauf@gmx.de> + + PR fortran/104212 + * gfortran.dg/argument_checking_26.f90: New test. + +2022-01-25 Patrick Palka <ppalka@redhat.com> + + PR c++/101532 + PR c++/104225 + * g++.dg/cpp0x/nsdmi-template21.C: New test. + * g++.dg/cpp0x/nsdmi-template21a.C: New test. + +2022-01-25 Jason Merrill <jason@redhat.com> + + PR c++/59950 + * g++.dg/init/assign2.C: New test. + +2022-01-25 Richard Biener <rguenther@suse.de> + + PR tree-optimization/104214 + * gcc.dg/vect/pr81196-2.c: New variant testcase only + requiring vect_int. + +2022-01-25 Francois-Xavier Coudert <fxcoudert@gmail.com> + + * gfortran.dg/ieee/signaling_3.f90: Skip test on 32-bit x86/x86_64. + +2022-01-25 Francois-Xavier Coudert <fxcoudert@gmail.com> + + * gfortran.dg/ieee/signaling_1.f90: Fix test. + +2022-01-24 Marek Polacek <polacek@redhat.com> + + PR preprocessor/104030 + * c-c++-common/Wbidi-chars-10.c: Turn on UCN checking. + * c-c++-common/Wbidi-chars-11.c: Likewise. + * c-c++-common/Wbidi-chars-14.c: Likewise. + * c-c++-common/Wbidi-chars-16.c: Likewise. + * c-c++-common/Wbidi-chars-17.c: Likewise. + * c-c++-common/Wbidi-chars-4.c: Likewise. + * c-c++-common/Wbidi-chars-5.c: Likewise. + * c-c++-common/Wbidi-chars-6.c: Likewise. + * c-c++-common/Wbidi-chars-7.c: Likewise. + * c-c++-common/Wbidi-chars-8.c: Likewise. + * c-c++-common/Wbidi-chars-9.c: Likewise. + * c-c++-common/Wbidi-chars-ranges.c: Likewise. + * c-c++-common/Wbidi-chars-18.c: New test. + * c-c++-common/Wbidi-chars-19.c: New test. + * c-c++-common/Wbidi-chars-20.c: New test. + * c-c++-common/Wbidi-chars-21.c: New test. + * c-c++-common/Wbidi-chars-22.c: New test. + * c-c++-common/Wbidi-chars-23.c: New test. + +2022-01-24 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> + + * gfortran.dg/ieee/signaling_1.f90: Do not require issignaling. + * gfortran.dg/ieee/signaling_2.f90: Add comment. + * gfortran.dg/ieee/signaling_3.f90: New test. + +2022-01-24 Raoni Fassina Firmino <raoni@linux.ibm.com> + + PR target/94193 + * gcc.target/powerpc/builtin-feclearexcept-feraiseexcept-1.c: New test. + * gcc.target/powerpc/builtin-feclearexcept-feraiseexcept-2.c: New test. + * gcc.target/powerpc/builtin-fegetround.c: New test. + +2022-01-24 Patrick Palka <ppalka@redhat.com> + + PR c++/104173 + * g++.dg/cpp0x/ref-qual21.C: New test. + +2022-01-24 Richard Biener <rguenther@suse.de> + Jiufu Guo <guojiufu@linux.ibm.com> + + PR tree-optimization/100740 + PR tree-optimization/101508 + PR tree-optimization/101972 + PR tree-optimization/102131 + * gcc.dg/torture/pr100740.c: New testcase. + * gcc.dg/torture/pr101508.c: Likewise. + * gcc.dg/torture/pr101972.c: Likewise. + * gcc.dg/torture/pr102131-1.c: Likewise. + * gcc.dg/torture/pr102131-2.c: Likewise. + * gcc.dg/torture/pr102131-3.c: Likewise. + * gcc.dg/torture/pr102131-4.c: Likewise. + +2022-01-24 Jakub Jelinek <jakub@redhat.com> + + PR sanitizer/104158 + * gcc.dg/sancov/pr104158-7.c: Adjust for repeating of arguments + being allowed. + +2022-01-24 Jakub Jelinek <jakub@redhat.com> + + PR sanitizer/104158 + * gcc.dg/spellcheck-options-24.c: New test. + * gcc.dg/sancov/pr104158-1.c: New test. + * gcc.dg/sancov/pr104158-2.c: New test. + * gcc.dg/sancov/pr104158-3.c: New test. + * gcc.dg/sancov/pr104158-4.c: New test. + * gcc.dg/sancov/pr104158-5.c: New test. + * gcc.dg/sancov/pr104158-6.c: New test. + * gcc.dg/sancov/pr104158-7.c: New test. + +2022-01-24 Kito Cheng <kito.cheng@sifive.com> + + * gcc.target/riscv/attribute-19.c: Add -misa-spec=2.2 + +2022-01-24 Jiufu Guo <guojiufu@linux.ibm.com> + + PR tree-optimization/102087 + * gcc.dg/pr102087_1.c: New test. + +2022-01-24 LiaoShihua <shihua@iscas.ac.cn> + + * gcc.target/riscv/arch-9.c: Update the check info. + * gcc.target/riscv/arch-10.c: Ditto. + * gcc.target/riscv/arch-12.c: Ditto. + +2022-01-24 David Edelsohn <dje.gcc@gmail.com> + + * gcc.dg/analyzer/torture/pr104159.c: Ignore psabi warning. + +2022-01-24 H.J. Lu <hjl.tools@gmail.com> + + PR target/104188 + * gcc.target/i386/pr104188.c: New test. + 2022-01-23 Will Wray <wjwray@gmail.com> PR c++/55227 diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-10.c b/gcc/testsuite/c-c++-common/Wbidi-chars-10.c index 3f851b6..cdcdce2 100644 --- a/gcc/testsuite/c-c++-common/Wbidi-chars-10.c +++ b/gcc/testsuite/c-c++-common/Wbidi-chars-10.c @@ -1,6 +1,6 @@ /* PR preprocessor/103026 */ /* { dg-do compile } */ -/* { dg-options "-Wbidi-chars=unpaired" } */ +/* { dg-options "-Wbidi-chars=unpaired,ucn" } */ /* More nesting testing. */ /* RLE LRI PDF PDI*/ diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-11.c b/gcc/testsuite/c-c++-common/Wbidi-chars-11.c index 270ce23..ea83029 100644 --- a/gcc/testsuite/c-c++-common/Wbidi-chars-11.c +++ b/gcc/testsuite/c-c++-common/Wbidi-chars-11.c @@ -1,6 +1,6 @@ /* PR preprocessor/103026 */ /* { dg-do compile } */ -/* { dg-options "-Wbidi-chars=unpaired" } */ +/* { dg-options "-Wbidi-chars=unpaired,ucn" } */ /* Test that we warn when mixing UCN and UTF-8. */ int LRE__PDF_\u202c; diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-14.c b/gcc/testsuite/c-c++-common/Wbidi-chars-14.c index ba5f75d..cb6b05e 100644 --- a/gcc/testsuite/c-c++-common/Wbidi-chars-14.c +++ b/gcc/testsuite/c-c++-common/Wbidi-chars-14.c @@ -1,6 +1,6 @@ /* PR preprocessor/103026 */ /* { dg-do compile } */ -/* { dg-options "-Wbidi-chars=unpaired" } */ +/* { dg-options "-Wbidi-chars=unpaired,ucn" } */ /* Test PDI handling, which also pops any subsequent LREs, RLEs, LROs, or RLOs. */ diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-16.c b/gcc/testsuite/c-c++-common/Wbidi-chars-16.c index baa0159..eaf0ec9 100644 --- a/gcc/testsuite/c-c++-common/Wbidi-chars-16.c +++ b/gcc/testsuite/c-c++-common/Wbidi-chars-16.c @@ -1,6 +1,6 @@ /* PR preprocessor/103026 */ /* { dg-do compile } */ -/* { dg-options "-Wbidi-chars=any" } */ +/* { dg-options "-Wbidi-chars=any,ucn" } */ /* Test LTR/RTL chars. */ /* LTR<> */ diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-17.c b/gcc/testsuite/c-c++-common/Wbidi-chars-17.c index 07cb432..3419221 100644 --- a/gcc/testsuite/c-c++-common/Wbidi-chars-17.c +++ b/gcc/testsuite/c-c++-common/Wbidi-chars-17.c @@ -1,6 +1,6 @@ /* PR preprocessor/103026 */ /* { dg-do compile } */ -/* { dg-options "-Wbidi-chars=unpaired" } */ +/* { dg-options "-Wbidi-chars=unpaired,ucn" } */ /* Test LTR/RTL chars. */ /* LTR<> */ diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-18.c b/gcc/testsuite/c-c++-common/Wbidi-chars-18.c new file mode 100644 index 0000000..ae586d5 --- /dev/null +++ b/gcc/testsuite/c-c++-common/Wbidi-chars-18.c @@ -0,0 +1,11 @@ +/* PR preprocessor/104030 */ +/* { dg-do compile } */ +/* By default, don't warn about UCNs. */ + +const char * +fn () +{ + const char *aText = "\u202D" "abc"; +/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */ + return aText; +} diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-19.c b/gcc/testsuite/c-c++-common/Wbidi-chars-19.c new file mode 100644 index 0000000..9985c3b --- /dev/null +++ b/gcc/testsuite/c-c++-common/Wbidi-chars-19.c @@ -0,0 +1,11 @@ +/* PR preprocessor/104030 */ +/* { dg-do compile } */ +/* { dg-options "-Wbidi-chars=unpaired,ucn" } */ + +const char * +fn () +{ + const char *aText = "\u202D" "abc"; +/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ + return aText; +} diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-20.c b/gcc/testsuite/c-c++-common/Wbidi-chars-20.c new file mode 100644 index 0000000..859f3d5 --- /dev/null +++ b/gcc/testsuite/c-c++-common/Wbidi-chars-20.c @@ -0,0 +1,11 @@ +/* PR preprocessor/104030 */ +/* { dg-do compile } */ +/* { dg-options "-Wbidi-chars=any" } */ + +const char * +fn () +{ + const char *aText = "\u202D" "abc"; +/* { dg-bogus "U\\+202D" "" { target *-*-* } .-1 } */ + return aText; +} diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-21.c b/gcc/testsuite/c-c++-common/Wbidi-chars-21.c new file mode 100644 index 0000000..2720b8a --- /dev/null +++ b/gcc/testsuite/c-c++-common/Wbidi-chars-21.c @@ -0,0 +1,11 @@ +/* PR preprocessor/104030 */ +/* { dg-do compile } */ +/* { dg-options "-Wbidi-chars=ucn,any" } */ + +const char * +fn () +{ + const char *aText = "\u202D" "abc"; +/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */ + return aText; +} diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-22.c b/gcc/testsuite/c-c++-common/Wbidi-chars-22.c new file mode 100644 index 0000000..f960e59 --- /dev/null +++ b/gcc/testsuite/c-c++-common/Wbidi-chars-22.c @@ -0,0 +1,11 @@ +/* PR preprocessor/104030 */ +/* { dg-do compile } */ +/* { dg-options "-Wbidi-chars=none,ucn" } */ + +const char * +fn () +{ + const char *aText = "\u202D" "abc"; +/* { dg-bogus "" "" { target *-*-* } .-1 } */ + return aText; +} diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-23.c b/gcc/testsuite/c-c++-common/Wbidi-chars-23.c new file mode 100644 index 0000000..7de0a11 --- /dev/null +++ b/gcc/testsuite/c-c++-common/Wbidi-chars-23.c @@ -0,0 +1,11 @@ +/* PR preprocessor/104030 */ +/* { dg-do compile } */ +/* { dg-options "-Wbidi-chars=ucn" } */ + +const char * +fn () +{ + const char *aText = "\u202D" "abc"; +/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ + return aText; +} diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-4.c b/gcc/testsuite/c-c++-common/Wbidi-chars-4.c index 639e5c6..d2f0739 100644 --- a/gcc/testsuite/c-c++-common/Wbidi-chars-4.c +++ b/gcc/testsuite/c-c++-common/Wbidi-chars-4.c @@ -1,6 +1,6 @@ /* PR preprocessor/103026 */ /* { dg-do compile } */ -/* { dg-options "-Wbidi-chars=any -Wno-multichar -Wno-overflow" } */ +/* { dg-options "-Wbidi-chars=any,ucn -Wno-multichar -Wno-overflow" } */ /* Test all bidi chars in various contexts (identifiers, comments, string literals, character constants), both UCN and UTF-8. The bidi chars here are properly terminated, except for the character constants. */ diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-5.c b/gcc/testsuite/c-c++-common/Wbidi-chars-5.c index 68cb053..ad49498 100644 --- a/gcc/testsuite/c-c++-common/Wbidi-chars-5.c +++ b/gcc/testsuite/c-c++-common/Wbidi-chars-5.c @@ -1,6 +1,6 @@ /* PR preprocessor/103026 */ /* { dg-do compile } */ -/* { dg-options "-Wbidi-chars=unpaired -Wno-multichar -Wno-overflow" } */ +/* { dg-options "-Wbidi-chars=unpaired,ucn -Wno-multichar -Wno-overflow" } */ /* Test all bidi chars in various contexts (identifiers, comments, string literals, character constants), both UCN and UTF-8. The bidi chars here are properly terminated, except for the character constants. */ diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-6.c b/gcc/testsuite/c-c++-common/Wbidi-chars-6.c index 0ce6fff..8c1c1b2 100644 --- a/gcc/testsuite/c-c++-common/Wbidi-chars-6.c +++ b/gcc/testsuite/c-c++-common/Wbidi-chars-6.c @@ -1,6 +1,6 @@ /* PR preprocessor/103026 */ /* { dg-do compile } */ -/* { dg-options "-Wbidi-chars=unpaired" } */ +/* { dg-options "-Wbidi-chars=ucn,unpaired" } */ /* Test nesting of bidi chars in various contexts. */ /* Terminated by the wrong char: */ diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-7.c b/gcc/testsuite/c-c++-common/Wbidi-chars-7.c index d012d42..3270952 100644 --- a/gcc/testsuite/c-c++-common/Wbidi-chars-7.c +++ b/gcc/testsuite/c-c++-common/Wbidi-chars-7.c @@ -1,6 +1,6 @@ /* PR preprocessor/103026 */ /* { dg-do compile } */ -/* { dg-options "-Wbidi-chars=any" } */ +/* { dg-options "-Wbidi-chars=any,ucn" } */ /* Test we ignore UCNs in comments. */ // a b c \u202a 1 2 3 diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-8.c b/gcc/testsuite/c-c++-common/Wbidi-chars-8.c index 4f54c50..3983168 100644 --- a/gcc/testsuite/c-c++-common/Wbidi-chars-8.c +++ b/gcc/testsuite/c-c++-common/Wbidi-chars-8.c @@ -1,6 +1,6 @@ /* PR preprocessor/103026 */ /* { dg-do compile } */ -/* { dg-options "-Wbidi-chars=any" } */ +/* { dg-options "-Wbidi-chars=any,ucn" } */ /* Test \u vs \U. */ int a_\u202A; diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-9.c b/gcc/testsuite/c-c++-common/Wbidi-chars-9.c index e2af1b1..0ddb0d9 100644 --- a/gcc/testsuite/c-c++-common/Wbidi-chars-9.c +++ b/gcc/testsuite/c-c++-common/Wbidi-chars-9.c @@ -1,6 +1,6 @@ /* PR preprocessor/103026 */ /* { dg-do compile } */ -/* { dg-options "-Wbidi-chars=unpaired" } */ +/* { dg-options "-Wbidi-chars=unpaired,ucn" } */ /* Test that we properly separate bidi contexts (comment/identifier/character constant/string literal). */ diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-ranges.c b/gcc/testsuite/c-c++-common/Wbidi-chars-ranges.c index 298750a..0c71f30 100644 --- a/gcc/testsuite/c-c++-common/Wbidi-chars-ranges.c +++ b/gcc/testsuite/c-c++-common/Wbidi-chars-ranges.c @@ -1,6 +1,6 @@ /* PR preprocessor/103026 */ /* { dg-do compile } */ -/* { dg-options "-Wbidi-chars=unpaired -fdiagnostics-show-caret" } */ +/* { dg-options "-Wbidi-chars=unpaired,ucn -fdiagnostics-show-caret" } */ /* Verify that we escape and underline pertinent bidirectional control characters when quoting the source. */ diff --git a/gcc/testsuite/c-c++-common/gomp/pr103642.c b/gcc/testsuite/c-c++-common/gomp/pr103642.c new file mode 100644 index 0000000..bbd0896 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/pr103642.c @@ -0,0 +1,34 @@ +/* PR middle-end/103642 */ +/* { dg-do compile } */ + +#include <stdlib.h> + +typedef struct +{ + int *a; +} S; + +typedef struct +{ + S *s; + int *ptr; +} T; + +#define N 10 + +int main (void) +{ + T t; + t.s = (S *) malloc (sizeof (S)); + t.s->a = (int *) malloc (sizeof(int) * N); + + #pragma omp target map(from: t.s->a[:N]) + { + t.s->a[0] = 1; + } + + free (t.s->a); + free (t.s); + + return 0; +} diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-void1.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-void1.C new file mode 100644 index 0000000..accc1a4 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-void1.C @@ -0,0 +1,18 @@ +// PR c++/103057 +// { dg-do compile { target c++11 } } + +template <class T> struct A { }; +template <class T> struct B { using type = A<T>; }; +template <class T> struct C { + using type = typename T::foo; // { dg-error "int" } +}; +template <class T> using L = B<void>; + +template <class T> +typename L<typename C<T>::type>::type +f(T) { }; + +int main() +{ + f(42); // { dg-error "no match" } +} diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-104226.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-104226.C new file mode 100644 index 0000000..a44f417 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-104226.C @@ -0,0 +1,15 @@ +// PR c++/104226 +// { dg-do compile } +// { dg-options "-Wno-psabi" } + +typedef unsigned short __attribute__((__vector_size__(16))) U; +typedef unsigned int __attribute__((__vector_size__(16))) V; +typedef unsigned int __attribute__((__vector_size__(32))) W; + +U +foo (void) +{ + return __builtin_convertvector (__builtin_shufflevector ((V){}, (W){}, + 0, 0, 1, 0, + 5, 5, 0, 2), U); +} diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-variadic13.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-variadic13.C index ac4e631..3df8829 100644 --- a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-variadic13.C +++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-variadic13.C @@ -3,7 +3,7 @@ template <class... Ts> void f() { - [] { struct S : Ts { }; }; // { dg-error "not expanded" } + [] { struct S : Ts { }; }; // { dg-message "" } } int main() { diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-variadic14.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-variadic14.C index 185aa03..4634f16 100644 --- a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-variadic14.C +++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-variadic14.C @@ -3,6 +3,6 @@ template <int... E> void f() { - [] { enum e { e = E }; }; // { dg-error "not expanded" } + [] { enum e { e = E }; }; // { dg-message "" } } template void f<>(); diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-variadic14a.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-variadic14a.C new file mode 100644 index 0000000..810b4a4 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-variadic14a.C @@ -0,0 +1,9 @@ +// PR c++/100198 +// { dg-do compile { target c++11 } } + +template <int... E> +void f() { + ([] { enum e { e = E }; }(), ...); // { dg-bogus "" "" { xfail *-*-* } } +} + +template void f<0>(); diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-variadic15.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-variadic15.C new file mode 100644 index 0000000..730215a --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-variadic15.C @@ -0,0 +1,14 @@ +// PR c++/100030 +// { dg-do compile { target c++11 } } + +template <class... Ts> +void sink(Ts...); + +template <class... Ts> +void f(Ts...) { + sink([] { struct alignas(Ts) S {}; }...); // { dg-bogus "" "" { xfail *-*-* } } +} + +int main() { + f(0); +} diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-variadic16.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-variadic16.C new file mode 100644 index 0000000..8e48e38 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-variadic16.C @@ -0,0 +1,13 @@ +// PR c++/100282 +// { dg-do compile { target c++11 } } + +template <typename... Ts> +void +local_class () +{ + int { []{ struct ZZ : Ts {}; }... }; // { dg-bogus "" "" { xfail *-*-* } } +} + +template // <> +void +local_class<int> (); diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-template21.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template21.C new file mode 100644 index 0000000..79d43a5 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template21.C @@ -0,0 +1,8 @@ +// PR c++/101532 +// { dg-do compile { target c++11 } } + +struct A { private: ~A(); }; + +template<class> struct B { A a = A(); }; // { dg-error "private" } + +B<int> b; // { dg-error "deleted" } diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-template21a.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template21a.C new file mode 100644 index 0000000..08fd37b --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template21a.C @@ -0,0 +1,10 @@ +// PR c++/104225 +// { dg-do compile { target c++11 } } + +struct A { private: ~A(); }; + +template<class> struct B { A a = A(); }; // { dg-error "private" } + +int main() { + new B<int>; // { dg-error "deleted" } +} diff --git a/gcc/testsuite/g++.dg/cpp0x/ref-qual21.C b/gcc/testsuite/g++.dg/cpp0x/ref-qual21.C new file mode 100644 index 0000000..7f867c2 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/ref-qual21.C @@ -0,0 +1,23 @@ +// PR c++/104173 +// { dg-do compile { target c++11 } } + +struct QString { + QString toLower() &&; +}; + +struct QCoreApplication { + static QString applicationName(); +}; + +QCoreApplication* instance(); + +void f() { + instance()->applicationName().toLower(); +} + +template<class...> +void g() { + instance()->applicationName().toLower(); +} + +template void g<>(); diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction-new1.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction-new1.C new file mode 100644 index 0000000..7028335 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction-new1.C @@ -0,0 +1,16 @@ +// PR c++/101988 +// { dg-do compile { target c++17 } } + +template<typename T> +struct A { + A(T); + A(); +}; +auto p1 = new A[]{1}; // { dg-error "creating array of template placeholder type" } +auto p2 = new A[1]{1}; // { dg-error "invalid use of placeholder" } +auto p3 = new A<int>[]{1}; +auto p4 = new A<int>[1]{1}; +auto p5 = new A[]{1, 2}; // { dg-error "creating array of template placeholder type" } +auto p6 = new A<int>[]{1, 2}; +auto p7 = new A<int>[]{A(1), A(1)}; +auto p8 = new A<int>[2]{A(1), A(1)}; diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction104.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction104.C new file mode 100644 index 0000000..a34dea0 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction104.C @@ -0,0 +1,17 @@ +// PR c++/82632 +// { dg-do compile { target c++17 } } + +template<class T> struct Optional { + template<class U> Optional(U&&); +}; + +template<class A> Optional(A) -> Optional<A>; + +Optional opt(1729); +Optional dupe(opt); + +using ty1 = decltype(opt); +using ty1 = Optional<int>; + +using ty2 = decltype(dupe); +using ty2 = Optional<int>; diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction105.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction105.C new file mode 100644 index 0000000..73a9c6b --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction105.C @@ -0,0 +1,17 @@ +// PR c++/82632 +// { dg-do compile { target c++17 } } + +template<class T, int = 1> +struct Foo { + Foo() = default; + Foo(const Foo&) = delete; + + template<int I> + Foo(const Foo<T, I>&); +}; + +template<class T, int I> +Foo(Foo<T,I>) -> Foo<T,I+1>; + +Foo<int> a; +Foo b = a; diff --git a/gcc/testsuite/g++.dg/cpp23/auto-array2.C b/gcc/testsuite/g++.dg/cpp23/auto-array2.C new file mode 100644 index 0000000..0643168 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/auto-array2.C @@ -0,0 +1,11 @@ +// PR c++/101988 +// { dg-do compile { target c++17 } } + +template<class T> struct A { A(); }; +A<int> a[3]; +auto (*p)[3] = &a; +A<int> (*p2)[3] = &a; +A (*p3)[3] = &a; // { dg-error "template placeholder type" } +auto (&r)[3] = a; +A<int> (&r2)[3] = a; +A (&r3)[3] = a; // { dg-error "template placeholder type" } diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-partial-spec10.C b/gcc/testsuite/g++.dg/cpp2a/concepts-partial-spec10.C new file mode 100644 index 0000000..d45a1b0 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-partial-spec10.C @@ -0,0 +1,17 @@ +// PR c++/92944 +// { dg-do compile { target c++20 } } + +namespace ns { template<class T> struct A { }; } + +template<class T> requires true struct ns::A<T> { using type = T; }; +template<class T> requires false struct ns::A<T> { }; + +template<class T> struct ns::A<T*> { }; +template<class T> requires true struct ns::A<T*> { using type = T; }; +template<class T> requires false struct ns::A<T*> { }; + +using ty1 = ns::A<int>::type; +using ty1 = int; + +using ty2 = ns::A<int*>::type; +using ty2 = int; diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-partial-spec11.C b/gcc/testsuite/g++.dg/cpp2a/concepts-partial-spec11.C new file mode 100644 index 0000000..0333450 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-partial-spec11.C @@ -0,0 +1,19 @@ +// PR c++/103678 +// { dg-do compile { target c++20 } } + +template<class> +struct A { + template<class...> + struct B; +}; + +template<class A_t> +template<class B_t> +struct A<A_t>::B<B_t> {}; + +template<class A_t> +template<class B_t> +requires requires { + typename B_t; +} +struct A<A_t>::B<B_t> {}; diff --git a/gcc/testsuite/g++.dg/cpp2a/consteval-memfn1.C b/gcc/testsuite/g++.dg/cpp2a/consteval-memfn1.C new file mode 100644 index 0000000..910e7a1 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/consteval-memfn1.C @@ -0,0 +1,27 @@ +// PR c++/99895 +// { dg-do compile { target c++20 } } + +struct fixed_string { + consteval int size(int n) const { + if (n < 0) throw; // { dg-error "not a constant" } + return n; + } + + static consteval int size_static(int n) { + if (n < 0) throw; // { dg-error "not a constant" } + return n; + } + + consteval void operator()() const { } +}; + +template<class> +void VerifyHash(fixed_string s) { + s.size(0); // { dg-bogus "" } + s.size(-1); // { dg-message "expansion of" } + s.size_static(0); // { dg-bogus "" } + s.size_static(-1); // { dg-message "expansion of" } + fixed_string::size_static(0); // { dg-bogus "" } + fixed_string::size_static(-1); // { dg-message "expansion of" } + s(); // { dg-bogus "" } +} diff --git a/gcc/testsuite/g++.dg/cpp2a/consteval-memfn2.C b/gcc/testsuite/g++.dg/cpp2a/consteval-memfn2.C new file mode 100644 index 0000000..71748f4 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/consteval-memfn2.C @@ -0,0 +1,34 @@ +// PR c++/99895 +// { dg-do compile { target c++20 } } + +static constexpr unsigned hash(const char* s, unsigned length) +{ + s=s; + return length; +} +template<unsigned N> +struct fixed_string +{ + constexpr fixed_string(const char (&s)[N]) + { + for (int i = 0; i < N; i++) + str[i] = s[i]; + } + consteval const char* data() const { return str; } + consteval unsigned size() const { return N-1; } + char str[N]; +}; +template<unsigned expected_hash, fixed_string... s> +static consteval void VerifyHash() +{ + ( + [](auto){static_assert(hash(s.data(), s.size()) == expected_hash);}(s) + ,...); + // The compiler mistakenly translates s.data() into s.data(&s) + // and then complains that the call is not valid, because + // the function expects 0 parameters and 1 "was provided". +} +void foo() +{ + VerifyHash<5, "khaki", "plums">(); +} diff --git a/gcc/testsuite/g++.dg/cpp2a/consteval28.C b/gcc/testsuite/g++.dg/cpp2a/consteval28.C new file mode 100644 index 0000000..293a6be --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/consteval28.C @@ -0,0 +1,10 @@ +// { dg-do compile { target c++20 } } + +struct empty { }; + +consteval void f(empty) { } + +template<class> +void g(empty e) { + f(e); +} diff --git a/gcc/testsuite/g++.dg/init/assign2.C b/gcc/testsuite/g++.dg/init/assign2.C new file mode 100644 index 0000000..72d1264 --- /dev/null +++ b/gcc/testsuite/g++.dg/init/assign2.C @@ -0,0 +1,6 @@ +// PR c++/59950 + + struct Foo {}; + + int f(Foo *p); + int n = f(&(Foo() = Foo())); diff --git a/gcc/testsuite/g++.dg/lto/alignas1_0.C b/gcc/testsuite/g++.dg/lto/alignas1_0.C new file mode 100644 index 0000000..a2fc72a --- /dev/null +++ b/gcc/testsuite/g++.dg/lto/alignas1_0.C @@ -0,0 +1,7 @@ +// PR c++/104245 +// { dg-lto-do assemble } +// { dg-require-effective-target c++11 } + +template <typename T> struct A { alignas(T) alignas(int) int a; }; +struct B { B(const char *, const char *, int, int); A<int> b; }; +B c {"", "", 0, 0}; diff --git a/gcc/testsuite/g++.dg/parse/template-keyword2.C b/gcc/testsuite/g++.dg/parse/template-keyword2.C new file mode 100644 index 0000000..ecd0667 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/template-keyword2.C @@ -0,0 +1,8 @@ +// PR c++/104235 + +template <class M> +struct L: M { + using M::a; + void a(); + void p() { this->template a<>(); } +}; diff --git a/gcc/testsuite/g++.dg/warn/Wuse-after-free2.C b/gcc/testsuite/g++.dg/warn/Wuse-after-free2.C new file mode 100644 index 0000000..6d5f2bf --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wuse-after-free2.C @@ -0,0 +1,10 @@ +// PR target/104213 +// { dg-do compile } +// { dg-options "-Wuse-after-free" } + +class C +{ + virtual ~C(); +}; + +C::~C() {} // { dg-bogus "used after" } diff --git a/gcc/testsuite/g++.dg/warn/Wuse-after-free3.C b/gcc/testsuite/g++.dg/warn/Wuse-after-free3.C new file mode 100644 index 0000000..1862ac8 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wuse-after-free3.C @@ -0,0 +1,16 @@ +// PR target/104213 +// { dg-do compile } +// { dg-options "-Wuse-after-free" } +// FIXME: We should not output the warning twice. + +struct A +{ + virtual ~A (); + void f (); +}; + +A::~A () +{ + operator delete (this); + f (); // { dg-warning "used after" } +} // { dg-warning "used after" } diff --git a/gcc/testsuite/gcc.c-torture/execute/pr104196.c b/gcc/testsuite/gcc.c-torture/execute/pr104196.c new file mode 100644 index 0000000..80f267a --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr104196.c @@ -0,0 +1,19 @@ +/* PR tree-optimization/104196 */ + +int a = 6; + +int +main () +{ + while (1) + { + int b = a < 0 && 0 < -__INT_MAX__ - a ? 0 : a; + if (b != 4096 - __INT_MAX__) + { + if (a < 6) + __builtin_abort (); + break; + } + } + return 0; +} diff --git a/gcc/testsuite/gcc.dg/analyzer/data-model-1.c b/gcc/testsuite/gcc.dg/analyzer/data-model-1.c index 511ed4b..4318191 100644 --- a/gcc/testsuite/gcc.dg/analyzer/data-model-1.c +++ b/gcc/testsuite/gcc.dg/analyzer/data-model-1.c @@ -152,7 +152,7 @@ int test_12 (void) /* Use of uninit value. */ int test_12a (void) { - int i; + int i; /* { dg-message "region created on stack here" } */ return i; /* { dg-warning "use of uninitialized value 'i'" } */ } @@ -163,7 +163,7 @@ void test_12b (void *p, void *q) int test_12c (void) { - int i; + int i; /* { dg-message "region created on stack here" } */ int j; j = i; /* { dg-warning "use of uninitialized value 'i'" } */ @@ -349,7 +349,7 @@ void test_18 (int i) void test_19 (void) { - int i, j; + int i, j; /* { dg-message "region created on stack here" } */ /* Compare two uninitialized locals. */ __analyzer_eval (i == j); /* { dg-warning "UNKNOWN" "unknown " } */ /* { dg-warning "use of uninitialized value 'i'" "uninit i" { target *-*-* } .-1 } */ @@ -633,7 +633,7 @@ void test_29a (struct coord p[]) void test_29b (void) { - struct coord p[11]; + struct coord p[11]; /* { dg-message "region created on stack here" } */ struct coord *q; p[0].x = 100024; @@ -819,7 +819,7 @@ void test_36 (int i) int test_37 (void) { - int *ptr; + int *ptr; /* { dg-message "region created on stack here" } */ return *ptr; /* { dg-warning "use of uninitialized value 'ptr'" } */ } @@ -827,7 +827,7 @@ int test_37 (void) void test_37a (int i) { - int *ptr; + int *ptr; /* { dg-message "region created on stack here" } */ *ptr = i; /* { dg-warning "use of uninitialized value 'ptr'" } */ } diff --git a/gcc/testsuite/gcc.dg/analyzer/malloc-1.c b/gcc/testsuite/gcc.dg/analyzer/malloc-1.c index df2fc9c..3219f85 100644 --- a/gcc/testsuite/gcc.dg/analyzer/malloc-1.c +++ b/gcc/testsuite/gcc.dg/analyzer/malloc-1.c @@ -189,7 +189,7 @@ void test_15 (void) void test_16 (void) { - void *p, *q; + void *p, *q; /* { dg-message "region created on stack here" } */ p = malloc (1024); if (!p) @@ -457,7 +457,7 @@ test_39 (int i) int * test_40 (int i) { - int *p = (int*)malloc(sizeof(int*)); + int *p = (int*)malloc(sizeof(int*)); /* { dg-message "region created on heap here" } */ i = *p; /* { dg-warning "dereference of possibly-NULL 'p' \\\[CWE-690\\\]" "possibly-null" } */ /* { dg-warning "use of uninitialized value '\\*p'" "uninit" { target *-*-*} .-1 } */ return p; diff --git a/gcc/testsuite/gcc.dg/analyzer/memset-CVE-2017-18549-1.c b/gcc/testsuite/gcc.dg/analyzer/memset-CVE-2017-18549-1.c index de9b5e3..b12408a 100644 --- a/gcc/testsuite/gcc.dg/analyzer/memset-CVE-2017-18549-1.c +++ b/gcc/testsuite/gcc.dg/analyzer/memset-CVE-2017-18549-1.c @@ -47,7 +47,7 @@ static int aac_send_raw_srb(/* [...snip...] */) /* [...snip...] */ - struct aac_srb_reply reply; + struct aac_srb_reply reply; /* { dg-message "region created on stack here" } */ reply.status = ST_OK; diff --git a/gcc/testsuite/gcc.dg/analyzer/pr101547.c b/gcc/testsuite/gcc.dg/analyzer/pr101547.c index 8791cff..b42e64c 100644 --- a/gcc/testsuite/gcc.dg/analyzer/pr101547.c +++ b/gcc/testsuite/gcc.dg/analyzer/pr101547.c @@ -5,7 +5,7 @@ void k2 (void) { char *setfiles[1]; - int i; + int i; /* { dg-message "region created on stack here" } */ setfiles[i] = fopen ("", ""); /* { dg-warning "use of uninitialized value 'i'" } */ } /* { dg-warning "leak of FILE" } */ diff --git a/gcc/testsuite/gcc.dg/analyzer/pr101875.c b/gcc/testsuite/gcc.dg/analyzer/pr101875.c index 5988b8e..7700c7d 100644 --- a/gcc/testsuite/gcc.dg/analyzer/pr101875.c +++ b/gcc/testsuite/gcc.dg/analyzer/pr101875.c @@ -8,7 +8,7 @@ void k2 (void) { char *setfiles[1]; - int i; + int i; /* { dg-message "region created on stack here" } */ setfiles[i] = fopen("", ""); /* { dg-warning "use of uninitialized value 'i'" } */ if (!setfiles[i]) /* { dg-warning "use of uninitialized value 'i'" } */ diff --git a/gcc/testsuite/gcc.dg/analyzer/pr101962.c b/gcc/testsuite/gcc.dg/analyzer/pr101962.c index 7b83d03..d15820a 100644 --- a/gcc/testsuite/gcc.dg/analyzer/pr101962.c +++ b/gcc/testsuite/gcc.dg/analyzer/pr101962.c @@ -16,7 +16,7 @@ maybe_inc_int_ptr (int *ptr) int test_1 (void) { - int stack; + int stack; /* { dg-message "region created on stack here" } */ int *a = &stack; a = maybe_inc_int_ptr (a); a = maybe_inc_int_ptr (a); diff --git a/gcc/testsuite/gcc.dg/analyzer/pr104224.c b/gcc/testsuite/gcc.dg/analyzer/pr104224.c new file mode 100644 index 0000000..b047c4c --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr104224.c @@ -0,0 +1,106 @@ +#include <stdio.h> + +struct test { + int one; + int two; +}; + +void func2(const struct test *t) +{ + if (t->one == 0) + printf("init func2\n"); + + if (t->two == 0) /* { dg-warning "uninitialized" } */ + printf("uninit func2\n"); +} + +void func1(struct test *t) +{ + t->one = 1; + func2(t); +} + +int func3(int num) +{ + if (num) + return num; + else + return 0; +} + +void func4(int *a, int max) +{ + int i; + // skip the first + for (i=1; i<max; i++) + a[i] = 0; +} + +void func5(const int *a, int max) +{ + /* a[0] is uninitialized, but the rest of the array is initialized. */ + int i; + for (i=0; i<max; i++) { + if (a[i]) /* { dg-warning "uninitialized" "" { xfail *-*-* } } */ + printf("func5: %d\n", i); + } +} + +int func6(const int *num) +{ + if (*num) /* { dg-warning "uninitialized" } */ + return *num; /* { dg-warning "uninitialized" } */ + else + return 0; +} + +int j; +int func7(void) +{ + return j; /* { dg-bogus "uninitialized" } */ +} + +void func8(const int *a, int max) +{ + int i; + for (i=0; i<max; i++) { + if (a[i]) /* { dg-warning "uninitialized" } */ + printf("func8: %d\n", i); + } +} + +enum {RED, AMBER, GREEN, BLACK}; + +int main(void) +{ + struct test t; /* { dg-message "region created on stack here" } */ + int num; /* { dg-message "region created on stack here" } */ + int arry[10]; + int arry_2[10]; /* { dg-message "region created on stack here" } */ + int go; /* { dg-message "region created on stack here" } */ + int color = BLACK; + + func1(&t); + func3(num); /* { dg-warning "use of uninitialized value 'num'" } */ + func4(arry, 10); + func5(arry, 10); + func6(&num); + + printf("num: %d\n", num); /* { dg-warning "use of uninitialized value 'num'" } */ + printf("func7: %d\n", func7()); + func8(arry_2, 10); + + switch (color) { + case RED: + case AMBER: + go = 0; + break; + case GREEN: + go = 1; + break; + } + + printf("go :%d\n", go); /* { dg-warning "use of uninitialized value 'go'" } */ + + return 0; +} diff --git a/gcc/testsuite/gcc.dg/analyzer/pr94047.c b/gcc/testsuite/gcc.dg/analyzer/pr94047.c index d13da3e..a579673 100644 --- a/gcc/testsuite/gcc.dg/analyzer/pr94047.c +++ b/gcc/testsuite/gcc.dg/analyzer/pr94047.c @@ -12,7 +12,7 @@ bar (struct list *l) void foo (void) { - struct list l; + struct list l; /* { dg-message "region created on stack here" } */ tlist t = l; /* { dg-warning "use of uninitialized value 'l'" } */ for (;;) bar (&t); diff --git a/gcc/testsuite/gcc.dg/analyzer/symbolic-1.c b/gcc/testsuite/gcc.dg/analyzer/symbolic-1.c index 0eba646..2f4e00b 100644 --- a/gcc/testsuite/gcc.dg/analyzer/symbolic-1.c +++ b/gcc/testsuite/gcc.dg/analyzer/symbolic-1.c @@ -5,7 +5,7 @@ void test_1 (char a, char b, char c, char d, char e, char f, int i, int j) { - char arr[1024]; + char arr[1024]; /* { dg-message "region created on stack here" } */ arr[2] = a; /* (1) */ arr[3] = b; /* (2) */ diff --git a/gcc/testsuite/gcc.dg/analyzer/uninit-1.c b/gcc/testsuite/gcc.dg/analyzer/uninit-1.c index 8fcdcd6..cb7b252 100644 --- a/gcc/testsuite/gcc.dg/analyzer/uninit-1.c +++ b/gcc/testsuite/gcc.dg/analyzer/uninit-1.c @@ -2,13 +2,13 @@ int test_1 (void) { - int i; + int i; /* { dg-message "region created on stack here" } */ return i; /* { dg-warning "use of uninitialized value 'i'" } */ } int test_2 (void) { - int i; + int i; /* { dg-message "region created on stack here" } */ return i * 2; /* { dg-warning "use of uninitialized value 'i'" } */ } @@ -20,13 +20,13 @@ int test_3 (void) int test_4 (void) { - int *p; + int *p; /* { dg-message "region created on stack here" } */ return *p; /* { dg-warning "use of uninitialized value 'p'" } */ } int test_5 (int flag, int *q) { - int *p; + int *p; /* { dg-message "region created on stack here" } */ if (flag) /* { dg-message "following 'false' branch" } */ p = q; @@ -39,6 +39,6 @@ int test_5 (int flag, int *q) int test_6 (int i) { - int arr[10]; + int arr[10]; /* { dg-message "region created on stack here" } */ return arr[i]; /* { dg-warning "use of uninitialized value 'arr\\\[i\\\]'" } */ } diff --git a/gcc/testsuite/gcc.dg/analyzer/uninit-4.c b/gcc/testsuite/gcc.dg/analyzer/uninit-4.c index 791b111..616cb34 100644 --- a/gcc/testsuite/gcc.dg/analyzer/uninit-4.c +++ b/gcc/testsuite/gcc.dg/analyzer/uninit-4.c @@ -14,7 +14,7 @@ struct foo struct foo *__attribute__((noinline)) alloc_foo (int a, int b) { - struct foo *p = malloc (sizeof (struct foo)); + struct foo *p = malloc (sizeof (struct foo)); /* { dg-message "region created on heap here" } */ if (!p) return NULL; p->i = a; diff --git a/gcc/testsuite/gcc.dg/analyzer/uninit-alloca.c b/gcc/testsuite/gcc.dg/analyzer/uninit-alloca.c new file mode 100644 index 0000000..5dd3f85 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/uninit-alloca.c @@ -0,0 +1,7 @@ +/* { dg-require-effective-target alloca } */ + +int test_1 (void) +{ + int *p = __builtin_alloca (sizeof (int)); /* { dg-message "region created on stack here" } */ + return *p; /* { dg-warning "use of uninitialized value '\\*p'" } */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/uninit-pr94713.c b/gcc/testsuite/gcc.dg/analyzer/uninit-pr94713.c index cc337dc..e3bb8ce 100644 --- a/gcc/testsuite/gcc.dg/analyzer/uninit-pr94713.c +++ b/gcc/testsuite/gcc.dg/analyzer/uninit-pr94713.c @@ -3,7 +3,7 @@ void f2 (int); int foo (void) { - int *p; + int *p; /* { dg-message "region created on stack here" } */ f1 (p); /* { dg-warning "use of uninitialized value 'p'" } */ f2 (p[0]); /* { dg-warning "use of uninitialized value 'p'" } */ diff --git a/gcc/testsuite/gcc.dg/analyzer/uninit-pr94714.c b/gcc/testsuite/gcc.dg/analyzer/uninit-pr94714.c index df07f98..f120901 100644 --- a/gcc/testsuite/gcc.dg/analyzer/uninit-pr94714.c +++ b/gcc/testsuite/gcc.dg/analyzer/uninit-pr94714.c @@ -3,7 +3,7 @@ int main (void) { int *p; - int i; + int i; /* { dg-message "region created on stack here" } */ p = &i; /* { dg-bogus "uninitialized" } */ printf ("%d\n", p[0]); /* { dg-warning "use of uninitialized value '\\*p'" } */ diff --git a/gcc/testsuite/gcc.dg/analyzer/zlib-3.c b/gcc/testsuite/gcc.dg/analyzer/zlib-3.c index 57f5dcd..5098b4f 100644 --- a/gcc/testsuite/gcc.dg/analyzer/zlib-3.c +++ b/gcc/testsuite/gcc.dg/analyzer/zlib-3.c @@ -46,7 +46,7 @@ static int huft_build(uInt *b, uInt n, uInt s, const uInt *d, const uInt *e, uInt mask; register uInt *p; inflate_huft *q; - struct inflate_huft_s r; + struct inflate_huft_s r; /* { dg-message "region created on stack here" } */ inflate_huft *u[15]; register int w; uInt x[15 + 1]; diff --git a/gcc/testsuite/gcc.dg/tree-ssa/inline-13.c b/gcc/testsuite/gcc.dg/tree-ssa/inline-13.c new file mode 100644 index 0000000..94d8a9c --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/inline-13.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fno-early-inlining -fdump-tree-fixup_cfg3" } */ + +int n; + +static int +bar (void) +{ + int a; + + n = 0; + a = 0; + + return n; +} + +__attribute__ ((pure, returns_twice)) int +foo (void) +{ + n = bar () + 1; + foo (); + + return 0; +} + +/* Abnormal edges should be properly elided after IPA inlining of bar. */ +/* { dg-final { scan-tree-dump-times "bb" 1 "fixup_cfg3" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/modref-7.c b/gcc/testsuite/gcc.dg/tree-ssa/modref-7.c index 53ffa1c..b55d706 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/modref-7.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/modref-7.c @@ -10,4 +10,4 @@ int test(struct a *a, int p) a->array[0] = 1; } /* All three accesses combine to one bigger access. */ -/* { dg-final { scan-tree-dump-not "param=modref-max-accesses" "modref1" } } */ +/* { dg-final { scan-tree-dump-not "--param modref-max-accesses" "modref1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/modref-8.c b/gcc/testsuite/gcc.dg/tree-ssa/modref-8.c index 4a18e34..c51590f 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/modref-8.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/modref-8.c @@ -17,8 +17,8 @@ recurse (char *p, int n) if (n) recurse (p+1,n-1); } -/* { dg-final { scan-tree-dump-not "param=modref-max-accesses" "modref1" } } */ -/* { dg-final { scan-tree-dump "param=modref-max-adjustments" "modref1" } } */ +/* { dg-final { scan-tree-dump-not "--param modref-max-accesses" "modref1" } } */ +/* { dg-final { scan-tree-dump "--param modref-max-adjustments" "modref1" } } */ /* In set all accesses should merge together. */ /* { dg-final { scan-tree-dump "access: Parm 0 param offset:0 offset:0 size:8 max_size:40" "modref1" } } */ /* In recurse we should cap the recrusion after 8 attempts and set max_size to -1. */ diff --git a/gcc/testsuite/gcc.dg/vect/pr81196-2.c b/gcc/testsuite/gcc.dg/vect/pr81196-2.c new file mode 100644 index 0000000..8d5ce6b --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr81196-2.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target vect_int } */ + +void b (int *p) +{ + p = (int *)__builtin_assume_aligned(p, __BIGGEST_ALIGNMENT__); + int *q = p + 255; + for(; p < q; ++p, --q) + { + int t = *p; + *p = *q; + *q = t; + } +} + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/branch-protection-attr.c b/gcc/testsuite/gcc.target/aarch64/branch-protection-attr.c index 229ce1c..1d6e55f 100644 --- a/gcc/testsuite/gcc.target/aarch64/branch-protection-attr.c +++ b/gcc/testsuite/gcc.target/aarch64/branch-protection-attr.c @@ -4,7 +4,7 @@ void __attribute__ ((target("branch-protection=leaf"))) foo1 () { } -/* { dg-error {invalid protection type \("leaf"\) in 'target\("branch-protection="\)' pragma or attribute} "" { target *-*-* } 5 } */ +/* { dg-error {invalid protection type \('leaf'\) in 'target\("branch-protection="\)' pragma or attribute} "" { target *-*-* } 5 } */ /* { dg-error {pragma or attribute 'target\("branch-protection=leaf"\)' is not valid} "" { target *-*-* } 5 } */ void __attribute__ ((target("branch-protection=none+pac-ret"))) diff --git a/gcc/testsuite/gcc.target/i386/pr104188.c b/gcc/testsuite/gcc.target/i386/pr104188.c index c6f615b..3ddd3bc 100644 --- a/gcc/testsuite/gcc.target/i386/pr104188.c +++ b/gcc/testsuite/gcc.target/i386/pr104188.c @@ -1,5 +1,6 @@ /* { dg-do run { target avx512f } } */ -/* { dg-options "-O2 -mfpmath=sse" } */ +/* { dg-require-effective-target sse2_runtime } */ +/* { dg-options "-O2 -msse2 -mfpmath=sse" } */ #include <x86intrin.h> diff --git a/gcc/testsuite/gcc.target/powerpc/builtin-feclearexcept-feraiseexcept-1.c b/gcc/testsuite/gcc.target/powerpc/builtin-feclearexcept-feraiseexcept-1.c new file mode 100644 index 0000000..4482e89 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/builtin-feclearexcept-feraiseexcept-1.c @@ -0,0 +1,76 @@ +/* { dg-do run } */ +/* { dg-require-effective-target fenv_exceptions } */ +/* { dg-options "-lm -fno-builtin" } */ + +/* This testcase ensures that the builtins expand with the matching arguments + or otherwise fallback gracefully to a function call, and don't ICE during + compilation. + "-fno-builtin" option is used to enable calls to libc implementation of the + gcc builtins tested when not using __builtin_ prefix. */ + +#include <fenv.h> + +int +main () +{ + int rsi = 0; + long rsl = 0; + short rss = 0; + char rsc = 0; + + unsigned int rui = 0; + unsigned long rul = 0; + unsigned short rus = 0; + unsigned char ruc = 0; + + int e = FE_DIVBYZERO; + + __builtin_feclearexcept(e); // CALL + __builtin_feclearexcept(FE_ALL_EXCEPT); // CALL + __builtin_feclearexcept(FE_INVALID); // CALL + __builtin_feclearexcept(FE_INVALID | FE_INEXACT); // CALL + + __builtin_feclearexcept(FE_INEXACT | FE_DIVBYZERO | + FE_UNDERFLOW | FE_OVERFLOW); // EXPAND + __builtin_feclearexcept(FE_INEXACT | FE_OVERFLOW); // EXPAND + __builtin_feclearexcept(FE_INEXACT); // EXPAND + __builtin_feclearexcept(FE_DIVBYZERO); // EXPAND + __builtin_feclearexcept(FE_UNDERFLOW); // EXPAND + __builtin_feclearexcept(FE_OVERFLOW); // EXPAND + __builtin_feclearexcept(0); // EXPAND + + rsi = __builtin_feclearexcept(FE_DIVBYZERO); // EXPAND + rsl = __builtin_feclearexcept(FE_DIVBYZERO); // EXPAND + rss = __builtin_feclearexcept(FE_DIVBYZERO); // EXPAND + rsc = __builtin_feclearexcept(FE_DIVBYZERO); // EXPAND + rui = __builtin_feclearexcept(FE_DIVBYZERO); // EXPAND + rul = __builtin_feclearexcept(FE_DIVBYZERO); // EXPAND + rus = __builtin_feclearexcept(FE_DIVBYZERO); // EXPAND + ruc = __builtin_feclearexcept(FE_DIVBYZERO); // EXPAND + + + __builtin_feraiseexcept(e); // CALL + __builtin_feraiseexcept(FE_ALL_EXCEPT); // CALL + __builtin_feraiseexcept(FE_INVALID); // CALL + __builtin_feraiseexcept(FE_INVALID | FE_INEXACT); // CALL + + __builtin_feraiseexcept(FE_INEXACT | FE_DIVBYZERO | + FE_UNDERFLOW | FE_OVERFLOW); // EXPAND + __builtin_feraiseexcept(FE_INEXACT | FE_OVERFLOW); // EXPAND + __builtin_feraiseexcept(FE_INEXACT); // EXPAND + __builtin_feraiseexcept(FE_DIVBYZERO); // EXPAND + __builtin_feraiseexcept(FE_UNDERFLOW); // EXPAND + __builtin_feraiseexcept(FE_OVERFLOW); // EXPAND + __builtin_feraiseexcept(0); // EXPAND + + rsi = __builtin_feraiseexcept(FE_DIVBYZERO); // EXPAND + rsl = __builtin_feraiseexcept(FE_DIVBYZERO); // EXPAND + rss = __builtin_feraiseexcept(FE_DIVBYZERO); // EXPAND + rsc = __builtin_feraiseexcept(FE_DIVBYZERO); // EXPAND + rui = __builtin_feraiseexcept(FE_DIVBYZERO); // EXPAND + rul = __builtin_feraiseexcept(FE_DIVBYZERO); // EXPAND + rus = __builtin_feraiseexcept(FE_DIVBYZERO); // EXPAND + ruc = __builtin_feraiseexcept(FE_DIVBYZERO); // EXPAND + + return 0; +} diff --git a/gcc/testsuite/gcc.target/powerpc/builtin-feclearexcept-feraiseexcept-2.c b/gcc/testsuite/gcc.target/powerpc/builtin-feclearexcept-feraiseexcept-2.c new file mode 100644 index 0000000..28c2a00 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/builtin-feclearexcept-feraiseexcept-2.c @@ -0,0 +1,91 @@ +/* { dg-do run } */ +/* { dg-require-effective-target fenv_exceptions } */ +/* { dg-options "-lm -fno-builtin" } */ + +/* This testcase ensures that the builtins are correctly expanded and match the + expected result. + "-fno-builtin" option is used to enable calls to libc implementation of the + gcc builtins tested when not using __builtin_ prefix. + The excepts parameter needs to be passed as constant to + __builtin_feclearexcept and __builtin_feraiseexcept because some bultins only + expand on constant input. */ + +#include <fenv.h> + +#ifdef DEBUG +#include <stdio.h> +#define INFO(...) printf(__VA_ARGS__) +#define FAIL(ret, raised, expected, excepts, excepts_str, func) \ + printf("ERROR [l %d] testing %s (%x): %s returned %d." \ + " Raised except bits %x, expecected %x\n", \ + __LINE__, excepts_str, excepts, func, ret, raised, expected) +#else +void abort (void); +#define INFO(...) +#define FAIL(ret, raised, expected, excepts, excepts_str, func) abort() +#endif + +#define TEST(excepts) \ + do { \ + int ret = 0; \ + int raised = 0; \ + \ + INFO("test: %s (%x)\n", #excepts, excepts); \ + \ + feclearexcept(FE_ALL_EXCEPT); \ + ret = __builtin_feraiseexcept(excepts); \ + raised = fetestexcept(FE_ALL_EXCEPT); \ + if (ret != 0 || raised != (excepts)) \ + FAIL(ret, raised, excepts, excepts, #excepts, \ + "__builtin_feraiseexcept"); \ + \ + feraiseexcept(FE_ALL_EXCEPT); \ + ret = __builtin_feclearexcept(excepts); \ + raised = fetestexcept(FE_ALL_EXCEPT); \ + if (ret != 0 || raised != (FE_ALL_EXCEPT & ~(excepts))) \ + FAIL(ret, raised, FE_ALL_EXCEPT & ~(excepts), excepts, #excepts, \ + "__builtin_feclearexcept"); \ + } while (0) + +int +main () +{ + TEST(0); + TEST(FE_ALL_EXCEPT); + + TEST(FE_INVALID); + TEST(FE_DIVBYZERO); + TEST(FE_INEXACT); + TEST(FE_OVERFLOW); + TEST(FE_UNDERFLOW); + + TEST(FE_INVALID | FE_DIVBYZERO); + TEST(FE_INVALID | FE_INEXACT); + TEST(FE_INVALID | FE_OVERFLOW); + TEST(FE_INVALID | FE_UNDERFLOW); + TEST(FE_DIVBYZERO | FE_INEXACT); + TEST(FE_DIVBYZERO | FE_OVERFLOW); + TEST(FE_DIVBYZERO | FE_UNDERFLOW); + TEST(FE_INEXACT | FE_OVERFLOW); + TEST(FE_INEXACT | FE_UNDERFLOW); + TEST(FE_OVERFLOW | FE_UNDERFLOW); + + TEST(FE_INVALID | FE_DIVBYZERO | FE_INEXACT); + TEST(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW); + TEST(FE_INVALID | FE_DIVBYZERO | FE_UNDERFLOW); + TEST(FE_INVALID | FE_INEXACT | FE_OVERFLOW); + TEST(FE_INVALID | FE_INEXACT | FE_UNDERFLOW); + TEST(FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW); + TEST(FE_DIVBYZERO | FE_INEXACT | FE_OVERFLOW); + TEST(FE_DIVBYZERO | FE_INEXACT | FE_UNDERFLOW); + TEST(FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW); + TEST(FE_INEXACT | FE_OVERFLOW | FE_UNDERFLOW); + + TEST(FE_INVALID | FE_DIVBYZERO | FE_INEXACT | FE_UNDERFLOW); + TEST(FE_INVALID | FE_DIVBYZERO | FE_INEXACT | FE_OVERFLOW); + TEST(FE_INVALID | FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW); + TEST(FE_INVALID | FE_INEXACT | FE_UNDERFLOW | FE_OVERFLOW); + TEST(FE_DIVBYZERO | FE_INEXACT | FE_UNDERFLOW | FE_OVERFLOW); + + return 0; +} diff --git a/gcc/testsuite/gcc.target/powerpc/builtin-fegetround.c b/gcc/testsuite/gcc.target/powerpc/builtin-fegetround.c new file mode 100644 index 0000000..56ffc50 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/builtin-fegetround.c @@ -0,0 +1,36 @@ +/* { dg-do run } */ +/* { dg-require-effective-target fenv_exceptions } */ +/* { dg-options "-lm -fno-builtin" } */ + +/* This testcase ensures that the builtins is correctly expanded and match the + expected result from the standard function. + "-fno-builtin" option is used to enable calls to libc implementation of the + gcc builtins tested when not using __builtin_ prefix. */ + +#include <fenv.h> + +#ifdef DEBUG +#include <stdio.h> +#define FAIL(v, e) printf("ERROR, __builtin_fegetround() returned %d," \ + " not the expecected value %d\n", v, e); +#else +void abort (void); +#define FAIL(v, e) abort() +#endif + +int +main () +{ + int i, rounding, expected; + const int rm[] = {FE_TONEAREST, FE_TOWARDZERO, FE_UPWARD, FE_DOWNWARD}; + for (i = 0; i < sizeof rm / sizeof rm[0]; i++) + { + fesetround(rm[i]); + rounding = __builtin_fegetround(); + expected = fegetround(); + if (rounding != expected) + FAIL(rounding, expected); + } + + return 0; +} diff --git a/gcc/testsuite/gcc.target/powerpc/pr103702.c b/gcc/testsuite/gcc.target/powerpc/pr103702.c new file mode 100644 index 0000000..585946f --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr103702.c @@ -0,0 +1,24 @@ +/* We don't have one powerpc.*_ok for Power6, use altivec_ok conservatively. */ +/* { dg-require-effective-target powerpc_altivec_ok } */ +/* { dg-options "-mdejagnu-cpu=power6 -O2 -ftree-loop-vectorize -fno-tree-scev-cprop" } */ + +/* Verify there is no ICE. */ + +unsigned short a, e; +int *b, *d; +int c; +extern int fn2 (); +void +fn1 () +{ + void *f; + for (;;) + { + fn2 (); + b = f; + e = 0; + for (; e < a; ++e) + b[e] = d[e * c]; + } +} + diff --git a/gcc/testsuite/gcc.target/powerpc/pr104239-1.c b/gcc/testsuite/gcc.target/powerpc/pr104239-1.c new file mode 100644 index 0000000..eacdedd --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr104239-1.c @@ -0,0 +1,10 @@ +/* PR target/104239 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -mdejagnu-cpu=power8 -DNO_WARN_X86_INTRINSICS" } */ +/* { dg-require-effective-target powerpc_p8vector_ok } */ + +#if __has_include(<immintrin.h>) +#include <immintrin.h> +#endif + +int i; diff --git a/gcc/testsuite/gcc.target/powerpc/pr104239-2.c b/gcc/testsuite/gcc.target/powerpc/pr104239-2.c new file mode 100644 index 0000000..1bf316f --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr104239-2.c @@ -0,0 +1,10 @@ +/* PR target/104239 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -mdejagnu-cpu=power8 -DNO_WARN_X86_INTRINSICS" } */ +/* { dg-require-effective-target powerpc_p8vector_ok } */ + +#if __has_include(<x86gprintrin.h>) +#include <x86gprintrin.h> +#endif + +int i; diff --git a/gcc/testsuite/gcc.target/powerpc/pr104239-3.c b/gcc/testsuite/gcc.target/powerpc/pr104239-3.c new file mode 100644 index 0000000..6d64e5d --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr104239-3.c @@ -0,0 +1,8 @@ +/* PR target/104239 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -mdejagnu-cpu=power8 -DNO_WARN_X86_INTRINSICS -std=c89" } */ +/* { dg-require-effective-target powerpc_p8vector_ok } */ + +#include <x86intrin.h> + +int i; diff --git a/gcc/testsuite/gfortran.dg/argument_checking_26.f90 b/gcc/testsuite/gfortran.dg/argument_checking_26.f90 new file mode 100644 index 0000000..2b765c5 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/argument_checking_26.f90 @@ -0,0 +1,14 @@ +! { dg-do compile } +! PR fortran/104212 - ICE in transformational_result +! Contributed by G.Steinmetz + +program p + logical, parameter :: a(*,*) = reshape([.true.,.false.], shape=[1,2]) + real, parameter :: r(*,*) = reshape([1.,2.], shape=[1,2]) + print *, parity(a) + print *, parity(a, dim=1) + print *, parity(a, dim=[1]) ! { dg-error "must be a scalar" } + print *, norm2 (r) + print *, norm2 (r, dim=1) + print *, norm2 (r, dim=[1]) ! { dg-error "must be a scalar" } +end diff --git a/gcc/testsuite/gfortran.dg/coarray_collectives_18.f90 b/gcc/testsuite/gfortran.dg/coarray_collectives_18.f90 new file mode 100644 index 0000000..c83899d --- /dev/null +++ b/gcc/testsuite/gfortran.dg/coarray_collectives_18.f90 @@ -0,0 +1,37 @@ +! { dg-do compile } +! { dg-additional-options "-fdump-tree-original -fcoarray=lib" } +! +! PR 103970 +! Test case inspired by code submitted by Damian Rousson + +program main + + implicit none + + type foo_t + integer i + integer, allocatable :: j + end type + + type(foo_t) foo + integer, parameter :: source_image = 1 + + if (this_image() == source_image) then + foo = foo_t(2,3) + else + allocate(foo%j) + end if + call co_broadcast(foo, source_image) + + if ((foo%i /= 2) .or. (foo%j /= 3)) error stop 1 + sync all + +end program + +! Wrong code generation produced too many temp descriptors +! leading to stacked descriptors handed to the co_broadcast. +! This lead to access to non exsitant memory in opencoarrays. +! In single image mode just checking for reduced number of +! descriptors is possible, i.e., execute always works. +! { dg-final { scan-tree-dump-times "desc\\.\[0-9\]+" 12 "original" } } + diff --git a/gcc/testsuite/gfortran.dg/ieee/signaling_1.f90 b/gcc/testsuite/gfortran.dg/ieee/signaling_1.f90 index 94ece3a..19fee28 100644 --- a/gcc/testsuite/gfortran.dg/ieee/signaling_1.f90 +++ b/gcc/testsuite/gfortran.dg/ieee/signaling_1.f90 @@ -1,7 +1,6 @@ -! { dg-do run { xfail { { i?86-*-* x86_64-*-* } && ilp32 } } } +! { dg-do run { target { ! ia32 } } } ! x87 / x86-32 ABI is unsuitable for signaling NaNs ! -! { dg-require-effective-target issignaling } */ ! { dg-additional-sources signaling_1_c.c } ! { dg-additional-options "-w" } ! The -w option is needed to make cc1 not report a warning for @@ -40,7 +39,7 @@ program test if (.not. ieee_unordered(x, x)) stop 105 if (.not. ieee_unordered(x, 1._c_float)) stop 106 - x = ieee_value(y, ieee_quiet_nan) + x = ieee_value(x, ieee_quiet_nan) if (ieee_class(x) /= ieee_quiet_nan) stop 107 if (.not. ieee_is_nan(x)) stop 108 if (ieee_is_negative(x)) stop 109 @@ -80,7 +79,7 @@ program test if (.not. ieee_unordered(z, z)) stop 305 if (.not. ieee_unordered(z, 1._c_long_double)) stop 306 - z = ieee_value(y, ieee_quiet_nan) + z = ieee_value(z, ieee_quiet_nan) if (ieee_class(z) /= ieee_quiet_nan) stop 307 if (.not. ieee_is_nan(z)) stop 308 if (ieee_is_negative(z)) stop 309 diff --git a/gcc/testsuite/gfortran.dg/ieee/signaling_2.f90 b/gcc/testsuite/gfortran.dg/ieee/signaling_2.f90 index ff37ab6..03b04c7 100644 --- a/gcc/testsuite/gfortran.dg/ieee/signaling_2.f90 +++ b/gcc/testsuite/gfortran.dg/ieee/signaling_2.f90 @@ -1,7 +1,9 @@ -! { dg-do run { xfail { { i?86-*-* x86_64-*-* } && ilp32 } } } +! { dg-do run { target { ! ia32 } } } ! x87 / x86-32 ABI is unsuitable for signaling NaNs ! ! { dg-require-effective-target issignaling } */ +! The companion C source needs access to the issignaling macro. +! ! { dg-additional-sources signaling_2_c.c } ! { dg-additional-options "-w" } ! The -w option is needed to make cc1 not report a warning for diff --git a/gcc/testsuite/gfortran.dg/ieee/signaling_3.f90 b/gcc/testsuite/gfortran.dg/ieee/signaling_3.f90 new file mode 100644 index 0000000..ff2585d --- /dev/null +++ b/gcc/testsuite/gfortran.dg/ieee/signaling_3.f90 @@ -0,0 +1,43 @@ +! { dg-do run { target { ! ia32 } } } +! x87 / x86-32 ABI is unsuitable for signaling NaNs +! +program test + use, intrinsic :: iso_c_binding + use, intrinsic :: ieee_arithmetic + implicit none + + real(kind=c_float) :: x + real(kind=c_double) :: y + real(kind=c_long_double) :: z + + if (ieee_support_nan(x)) then + x = ieee_value(x, ieee_signaling_nan) + if (ieee_class(x) /= ieee_signaling_nan) stop 100 + if (.not. ieee_is_nan(x)) stop 101 + + x = ieee_value(x, ieee_quiet_nan) + if (ieee_class(x) /= ieee_quiet_nan) stop 103 + if (.not. ieee_is_nan(x)) stop 104 + end if + + if (ieee_support_nan(y)) then + y = ieee_value(y, ieee_signaling_nan) + if (ieee_class(y) /= ieee_signaling_nan) stop 100 + if (.not. ieee_is_nan(y)) stop 101 + + y = ieee_value(y, ieee_quiet_nan) + if (ieee_class(y) /= ieee_quiet_nan) stop 103 + if (.not. ieee_is_nan(y)) stop 104 + end if + + if (ieee_support_nan(z)) then + z = ieee_value(z, ieee_signaling_nan) + if (ieee_class(z) /= ieee_signaling_nan) stop 100 + if (.not. ieee_is_nan(z)) stop 101 + + z = ieee_value(z, ieee_quiet_nan) + if (ieee_class(z) /= ieee_quiet_nan) stop 103 + if (.not. ieee_is_nan(z)) stop 104 + end if + +end program test diff --git a/gcc/testsuite/gfortran.dg/pr84784.f90 b/gcc/testsuite/gfortran.dg/pr84784.f90 new file mode 100644 index 0000000..3129b92 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pr84784.f90 @@ -0,0 +1,27 @@ +! { dg-do compile } +! { dg-options "-fcoarray=lib -fdefault-integer-8" } +! { dg-require-effective-target fortran_integer_16 } +! PR fortran/84784 - ICEs: verify_gimple failed with -fdefault-integer-8 + + use iso_fortran_env, only : team_type, STAT_FAILED_IMAGE + implicit none + type(team_type) :: team + integer :: new_team + new_team = mod(this_image(),2)+1 + form team (new_team,team) + change team (team) + if (team_number() /= new_team) STOP 1 + end team + if (image_status (1) == STAT_FAILED_IMAGE) ERROR STOP "cannot recover" + if (runtime_popcnt(0_16) /= 0) STOP 2 + if (runtime_poppar(1_16) /= 1) STOP 3 +contains + integer function runtime_popcnt (i) + integer(kind=16), intent(in) :: i + runtime_popcnt = popcnt(i) + end function + integer function runtime_poppar (i) + integer(kind=16), intent(in) :: i + runtime_poppar = poppar(i) + end function +end diff --git a/gcc/testsuite/gfortran.dg/transfer_check_6.f90 b/gcc/testsuite/gfortran.dg/transfer_check_6.f90 new file mode 100644 index 0000000..dffd091 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/transfer_check_6.f90 @@ -0,0 +1,11 @@ +! { dg-do compile } +! PR fortran/104227 - ICE virtual memory exhausted +! Contributed by G.Steinmetz + +program p + type t + end type + type(t) :: x(2) + print *, transfer(1, x) ! { dg-error "shall not have storage size 0" } + x = transfer(1, x) ! { dg-error "shall not have storage size 0" } +end diff --git a/gcc/testsuite/gfortran.dg/transfer_simplify_14.f90 b/gcc/testsuite/gfortran.dg/transfer_simplify_14.f90 new file mode 100644 index 0000000..dfb997d --- /dev/null +++ b/gcc/testsuite/gfortran.dg/transfer_simplify_14.f90 @@ -0,0 +1,27 @@ +! { dg-do compile } +! { dg-options "-fdump-tree-original" } +! PR fortran/104128 - ICE in gfc_widechar_to_char +! Contributed by G.Steinmetz + +program p + implicit none + integer, parameter :: k = 4 + character(*), parameter :: a = 'abc' + character(*,kind=4), parameter :: b = 'abc' + character(2,kind=k), parameter :: s = k_"FG" + character(*,kind=1), parameter :: x = transfer (s, 'abcdefgh') + character(2,kind=k), parameter :: t = transfer (x, s) + character(2,kind=k) :: u = transfer (x, s) + logical, parameter :: l = (s == t) + print *, transfer (a , 4_'xy', size=2) + print *, transfer ('xyz', [b], size=2) + print *, s + print *, t + print *, u + if (.not. l) stop 1 + if (t /= s) stop 2 + if (u /= s) stop 3 ! not optimized away +end + +! { dg-final { scan-tree-dump-times "_gfortran_stop_numeric" 1 "original" } } +! { dg-final { scan-tree-dump "_gfortran_stop_numeric \\(3, 0\\);" "original" } } diff --git a/gcc/testsuite/gnat.dg/generic_comp.adb b/gcc/testsuite/gnat.dg/generic_comp.adb new file mode 100644 index 0000000..8c7b16f --- /dev/null +++ b/gcc/testsuite/gnat.dg/generic_comp.adb @@ -0,0 +1,39 @@ +-- { dg-do run } + +procedure Generic_Comp is + + generic + type Element_Type is private; + type Index_Type is (<>); + type Array_Type is array (Index_Type range <>) of Element_Type; + with function ">" (Left, Right : Element_Type) return Boolean is <>; + procedure Gen (Data: in out Array_Type); + + procedure Gen (Data: in out Array_Type) is + begin + if not (Data'Length > 1) + or else not (Integer'(Data'Length) > 1) + or else not Standard.">" (Data'Length, 1) + or else not Standard.">" (Integer'(Data'Length), 1) + then + raise Program_Error; + end if; + end; + + type My_Array is array (Positive range <>) of Integer; + + function Less_Than (L, R : Integer) return Boolean is + begin + return L < R; + end; + + procedure Chk_Down is new Gen (Element_Type => Integer, + Index_Type => Positive, + Array_Type => My_Array, + ">" => Less_Than); + + Data : My_Array (1 .. 2); + +begin + Chk_Down (Data); +end; diff --git a/gcc/timevar.def b/gcc/timevar.def index c239e8e..2dae5e1 100644 --- a/gcc/timevar.def +++ b/gcc/timevar.def @@ -307,6 +307,7 @@ DEFTIMEVAR (TV_TREE_UBSAN , "tree ubsan") DEFTIMEVAR (TV_INITIALIZE_RTL , "initialize rtl") DEFTIMEVAR (TV_GIMPLE_LADDRESS , "address lowering") DEFTIMEVAR (TV_TREE_LOOP_IFCVT , "tree loop if-conversion") +DEFTIMEVAR (TV_WARN_ACCESS , "access analysis") /* Everything else in rest_of_compilation not included above. */ DEFTIMEVAR (TV_EARLY_LOCAL , "early local passes") diff --git a/gcc/tree-cfg.cc b/gcc/tree-cfg.cc index 77178a6..efd1033 100644 --- a/gcc/tree-cfg.cc +++ b/gcc/tree-cfg.cc @@ -8915,10 +8915,6 @@ gimple_purge_dead_abnormal_call_edges (basic_block bb) edge_iterator ei; gimple *stmt = last_stmt (bb); - if (!cfun->has_nonlocal_label - && !cfun->calls_setjmp) - return false; - if (stmt && stmt_can_make_abnormal_goto (stmt)) return false; diff --git a/gcc/tree-ssa-loop-niter.cc b/gcc/tree-ssa-loop-niter.cc index 04c2095..d33095b 100644 --- a/gcc/tree-ssa-loop-niter.cc +++ b/gcc/tree-ssa-loop-niter.cc @@ -1915,14 +1915,23 @@ number_of_iterations_cond (class loop *loop, } /* If the new step of IV0 has changed sign or is of greater magnitude then we do not know whether IV0 does overflow - and thus the transform is not valid for code other than NE_EXPR */ + and thus the transform is not valid for code other than NE_EXPR. */ else if (tree_int_cst_sign_bit (step) != tree_int_cst_sign_bit (iv0->step) || wi::gtu_p (wi::abs (wi::to_widest (step)), wi::abs (wi::to_widest (iv0->step)))) { - if (code != NE_EXPR) + if (POINTER_TYPE_P (type) && code != NE_EXPR) + /* For relational pointer compares we have further guarantees + that the pointers always point to the same object (or one + after it) and that objects do not cross the zero page. So + not only is the transform always valid for relational + pointer compares, we also know the resulting IV does not + overflow. */ + ; + else if (code != NE_EXPR) return false; - iv0->no_overflow = false; + else + iv0->no_overflow = false; } iv0->step = step; diff --git a/gcc/tree-ssa-reassoc.cc b/gcc/tree-ssa-reassoc.cc index 756ba6b..7ee5094 100644 --- a/gcc/tree-ssa-reassoc.cc +++ b/gcc/tree-ssa-reassoc.cc @@ -2768,7 +2768,49 @@ update_range_test (struct range_entry *range, struct range_entry *otherrange, vec<operand_entry *> *ops, tree exp, gimple_seq seq, bool in_p, tree low, tree high, bool strict_overflow_p) { - operand_entry *oe = (*ops)[range->idx]; + unsigned int idx = range->idx; + struct range_entry *swap_with = NULL; + basic_block rewrite_bb_first = NULL, rewrite_bb_last = NULL; + if (opcode == ERROR_MARK) + { + /* For inter-bb range test optimization, pick from the range tests + the one which is tested in the earliest condition (one dominating + the others), because otherwise there could be some UB (e.g. signed + overflow) in following bbs that we'd expose which wasn't there in + the original program. See PR104196. */ + basic_block orig_range_bb = BASIC_BLOCK_FOR_FN (cfun, (*ops)[idx]->id); + basic_block range_bb = orig_range_bb; + for (unsigned int i = 0; i < count; i++) + { + struct range_entry *this_range; + if (otherrange) + this_range = otherrange + i; + else + this_range = otherrangep[i]; + operand_entry *oe = (*ops)[this_range->idx]; + basic_block this_bb = BASIC_BLOCK_FOR_FN (cfun, oe->id); + if (range_bb != this_bb + && dominated_by_p (CDI_DOMINATORS, range_bb, this_bb)) + { + swap_with = this_range; + range_bb = this_bb; + idx = this_range->idx; + } + } + /* If seq is non-NULL, it can contain statements that use SSA_NAMEs + only defined in later blocks. In this case we can't move the + merged comparison earlier, so instead check if there are any stmts + that might trigger signed integer overflow in between and rewrite + them. But only after we check if the optimization is possible. */ + if (seq && swap_with) + { + rewrite_bb_first = range_bb; + rewrite_bb_last = orig_range_bb; + idx = range->idx; + swap_with = NULL; + } + } + operand_entry *oe = (*ops)[idx]; tree op = oe->op; gimple *stmt = op ? SSA_NAME_DEF_STMT (op) : last_stmt (BASIC_BLOCK_FOR_FN (cfun, oe->id)); @@ -2805,6 +2847,9 @@ update_range_test (struct range_entry *range, struct range_entry *otherrange, return false; } + if (swap_with) + std::swap (range->idx, swap_with->idx); + if (strict_overflow_p && issue_strict_overflow_warning (wc)) warning_at (loc, OPT_Wstrict_overflow, "assuming signed overflow does not occur " @@ -2839,6 +2884,42 @@ update_range_test (struct range_entry *range, struct range_entry *otherrange, fprintf (dump_file, "\n"); } + /* In inter-bb range optimization mode, if we have a seq, we can't + move the merged comparison to the earliest bb from the comparisons + being replaced, so instead rewrite stmts that could trigger signed + integer overflow. */ + for (basic_block bb = rewrite_bb_last; + bb != rewrite_bb_first; bb = single_pred (bb)) + for (gimple_stmt_iterator gsi = gsi_start_bb (bb); + !gsi_end_p (gsi); gsi_next (&gsi)) + { + gimple *stmt = gsi_stmt (gsi); + if (is_gimple_assign (stmt)) + if (tree lhs = gimple_assign_lhs (stmt)) + if ((INTEGRAL_TYPE_P (TREE_TYPE (lhs)) + || POINTER_TYPE_P (TREE_TYPE (lhs))) + && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (lhs))) + { + enum tree_code code = gimple_assign_rhs_code (stmt); + if (arith_code_with_undefined_signed_overflow (code)) + { + gimple_stmt_iterator gsip = gsi; + gimple_stmt_iterator gsin = gsi; + gsi_prev (&gsip); + gsi_next (&gsin); + rewrite_to_defined_overflow (stmt, true); + unsigned uid = gimple_uid (stmt); + if (gsi_end_p (gsip)) + gsip = gsi_after_labels (bb); + else + gsi_next (&gsip); + for (; gsi_stmt (gsip) != gsi_stmt (gsin); + gsi_next (&gsip)) + gimple_set_uid (gsi_stmt (gsip), uid); + } + } + } + if (opcode == BIT_IOR_EXPR || (opcode == ERROR_MARK && oe->rank == BIT_IOR_EXPR)) tem = invert_truthvalue_loc (loc, tem); @@ -4755,7 +4836,7 @@ maybe_optimize_range_tests (gimple *stmt) && (TREE_CODE_CLASS (gimple_assign_rhs_code (stmt)) != tcc_comparison) && !get_ops (rhs, code, &ops, - loop_containing_stmt (stmt)) + loop_containing_stmt (stmt)) && has_single_use (rhs)) { /* Otherwise, push the _234 range test itself. */ @@ -4792,6 +4873,8 @@ maybe_optimize_range_tests (gimple *stmt) bb_ent.op = rhs; } bbinfo.safe_push (bb_ent); + for (unsigned int i = bb_ent.first_idx; i < bb_ent.last_idx; ++i) + ops[i]->id = bb->index; continue; } else if (bb == last_bb) @@ -4855,6 +4938,8 @@ maybe_optimize_range_tests (gimple *stmt) bb_ent.last_idx = ops.length (); } bbinfo.safe_push (bb_ent); + for (unsigned int i = bb_ent.first_idx; i < bb_ent.last_idx; ++i) + ops[i]->id = bb->index; if (bb == first_bb) break; } diff --git a/gcc/tree-vect-stmts.cc b/gcc/tree-vect-stmts.cc index 824ebb6..000a0f4 100644 --- a/gcc/tree-vect-stmts.cc +++ b/gcc/tree-vect-stmts.cc @@ -3444,7 +3444,9 @@ vectorizable_call (vec_info *vinfo, { if (slp_node) for (i = 0; i < nargs; ++i) - if (!vect_maybe_update_slp_op_vectype (slp_op[i], vectype_in)) + if (!vect_maybe_update_slp_op_vectype (slp_op[i], + vectypes[i] + ? vectypes[i] : vectype_in)) { if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, diff --git a/gcc/tree.cc b/gcc/tree.cc index c4b3661..9d445b2 100644 --- a/gcc/tree.cc +++ b/gcc/tree.cc @@ -10492,7 +10492,7 @@ build_call_array_loc (location_t loc, tree return_type, tree fn, /* Like build_call_array, but takes a vec. */ tree -build_call_vec (tree return_type, tree fn, vec<tree, va_gc> *args) +build_call_vec (tree return_type, tree fn, const vec<tree, va_gc> *args) { tree ret, t; unsigned int ix; @@ -4589,7 +4589,7 @@ extern tree build_call_valist (tree, tree, int, va_list); #define build_call_array(T1,T2,N,T3)\ build_call_array_loc (UNKNOWN_LOCATION, T1, T2, N, T3) extern tree build_call_array_loc (location_t, tree, tree, int, const tree *); -extern tree build_call_vec (tree, tree, vec<tree, va_gc> *); +extern tree build_call_vec (tree, tree, const vec<tree, va_gc> *); extern tree build_call_expr_loc_array (location_t, tree, int, tree *); extern tree build_call_expr_loc_vec (location_t, tree, vec<tree, va_gc> *); extern tree build_call_expr_loc (location_t, tree, int, ...); |