99b1c316ec
gcc/c/ChangeLog: PR c++/61339 * c-decl.c (xref_tag): Change class-key of PODs to struct and others to class. (field_decl_cmp): Same. * c-parser.c (c_parser_struct_or_union_specifier): Same. * c-tree.h: Same. * gimple-parser.c (c_parser_gimple_compound_statement): Same. gcc/c-family/ChangeLog: PR c++/61339 * c-opts.c (handle_deferred_opts): : Change class-key of PODs to struct and others to class. * c-pretty-print.h: Same. gcc/cp/ChangeLog: PR c++/61339 * cp-tree.h: Change class-key of PODs to struct and others to class. * search.c: Same. * semantics.c (finalize_nrv_r): Same. gcc/lto/ChangeLog: PR c++/61339 * lto-common.c (lto_splay_tree_new): : Change class-key of PODs to struct and others to class. (mentions_vars_p): Same. (register_resolution): Same. (lto_register_var_decl_in_symtab): Same. (lto_register_function_decl_in_symtab): Same. (cmp_tree): Same. (lto_read_decls): Same. gcc/ChangeLog: PR c++/61339 * auto-profile.c: Change class-key of PODs to struct and others to class. * basic-block.h: Same. * bitmap.c (bitmap_alloc): Same. * bitmap.h: Same. * builtins.c (expand_builtin_prefetch): Same. (expand_builtin_interclass_mathfn): Same. (expand_builtin_strlen): Same. (expand_builtin_mempcpy_args): Same. (expand_cmpstr): Same. (expand_builtin___clear_cache): Same. (expand_ifn_atomic_bit_test_and): Same. (expand_builtin_thread_pointer): Same. (expand_builtin_set_thread_pointer): Same. * caller-save.c (setup_save_areas): Same. (replace_reg_with_saved_mem): Same. (insert_restore): Same. (insert_save): Same. (add_used_regs): Same. * cfg.c (get_bb_copy): Same. (set_loop_copy): Same. * cfg.h: Same. * cfganal.h: Same. * cfgexpand.c (alloc_stack_frame_space): Same. (add_stack_var): Same. (add_stack_var_conflict): Same. (add_scope_conflicts_1): Same. (update_alias_info_with_stack_vars): Same. (expand_used_vars): Same. * cfghooks.c (redirect_edge_and_branch_force): Same. (delete_basic_block): Same. (split_edge): Same. (make_forwarder_block): Same. (force_nonfallthru): Same. (duplicate_block): Same. (lv_flush_pending_stmts): Same. * cfghooks.h: Same. * cfgloop.c (flow_loops_cfg_dump): Same. (flow_loop_nested_p): Same. (superloop_at_depth): Same. (get_loop_latch_edges): Same. (flow_loop_dump): Same. (flow_loops_dump): Same. (flow_loops_free): Same. (flow_loop_nodes_find): Same. (establish_preds): Same. (flow_loop_tree_node_add): Same. (flow_loop_tree_node_remove): Same. (flow_loops_find): Same. (find_subloop_latch_edge_by_profile): Same. (find_subloop_latch_edge_by_ivs): Same. (mfb_redirect_edges_in_set): Same. (form_subloop): Same. (merge_latch_edges): Same. (disambiguate_multiple_latches): Same. (disambiguate_loops_with_multiple_latches): Same. (flow_bb_inside_loop_p): Same. (glb_enum_p): Same. (get_loop_body_with_size): Same. (get_loop_body): Same. (fill_sons_in_loop): Same. (get_loop_body_in_dom_order): Same. (get_loop_body_in_custom_order): Same. (release_recorded_exits): Same. (get_loop_exit_edges): Same. (num_loop_branches): Same. (remove_bb_from_loops): Same. (find_common_loop): Same. (delete_loop): Same. (cancel_loop): Same. (verify_loop_structure): Same. (loop_preheader_edge): Same. (loop_exit_edge_p): Same. (single_exit): Same. (loop_exits_to_bb_p): Same. (loop_exits_from_bb_p): Same. (get_loop_location): Same. (record_niter_bound): Same. (get_estimated_loop_iterations_int): Same. (max_stmt_executions_int): Same. (likely_max_stmt_executions_int): Same. (get_estimated_loop_iterations): Same. (get_max_loop_iterations): Same. (get_max_loop_iterations_int): Same. (get_likely_max_loop_iterations): Same. * cfgloop.h (simple_loop_desc): Same. (get_loop): Same. (loop_depth): Same. (loop_outer): Same. (loop_iterator::next): Same. (loop_outermost): Same. * cfgloopanal.c (mark_irreducible_loops): Same. (num_loop_insns): Same. (average_num_loop_insns): Same. (expected_loop_iterations_unbounded): Same. (expected_loop_iterations): Same. (mark_loop_exit_edges): Same. (single_likely_exit): Same. * cfgloopmanip.c (fix_bb_placement): Same. (fix_bb_placements): Same. (remove_path): Same. (place_new_loop): Same. (add_loop): Same. (scale_loop_frequencies): Same. (scale_loop_profile): Same. (create_empty_if_region_on_edge): Same. (create_empty_loop_on_edge): Same. (loopify): Same. (unloop): Same. (fix_loop_placements): Same. (copy_loop_info): Same. (duplicate_loop): Same. (duplicate_subloops): Same. (loop_redirect_edge): Same. (can_duplicate_loop_p): Same. (duplicate_loop_to_header_edge): Same. (mfb_keep_just): Same. (has_preds_from_loop): Same. (create_preheader): Same. (create_preheaders): Same. (lv_adjust_loop_entry_edge): Same. (loop_version): Same. * cfgloopmanip.h: Same. * cgraph.h: Same. * cgraphbuild.c: Same. * combine.c (make_extraction): Same. * config/i386/i386-features.c: Same. * config/i386/i386-features.h: Same. * config/i386/i386.c (ix86_emit_outlined_ms2sysv_save): Same. (ix86_emit_outlined_ms2sysv_restore): Same. (ix86_noce_conversion_profitable_p): Same. (ix86_init_cost): Same. (ix86_simd_clone_usable): Same. * configure.ac: Same. * coretypes.h: Same. * data-streamer-in.c (string_for_index): Same. (streamer_read_indexed_string): Same. (streamer_read_string): Same. (bp_unpack_indexed_string): Same. (bp_unpack_string): Same. (streamer_read_uhwi): Same. (streamer_read_hwi): Same. (streamer_read_gcov_count): Same. (streamer_read_wide_int): Same. * data-streamer.h (streamer_write_bitpack): Same. (bp_unpack_value): Same. (streamer_write_char_stream): Same. (streamer_write_hwi_in_range): Same. (streamer_write_record_start): Same. * ddg.c (create_ddg_dep_from_intra_loop_link): Same. (add_cross_iteration_register_deps): Same. (build_intra_loop_deps): Same. * df-core.c (df_analyze): Same. (loop_post_order_compute): Same. (loop_inverted_post_order_compute): Same. * df-problems.c (df_rd_alloc): Same. (df_rd_simulate_one_insn): Same. (df_rd_local_compute): Same. (df_rd_init_solution): Same. (df_rd_confluence_n): Same. (df_rd_transfer_function): Same. (df_rd_free): Same. (df_rd_dump_defs_set): Same. (df_rd_top_dump): Same. (df_lr_alloc): Same. (df_lr_reset): Same. (df_lr_local_compute): Same. (df_lr_init): Same. (df_lr_confluence_n): Same. (df_lr_free): Same. (df_lr_top_dump): Same. (df_lr_verify_transfer_functions): Same. (df_live_alloc): Same. (df_live_reset): Same. (df_live_init): Same. (df_live_confluence_n): Same. (df_live_finalize): Same. (df_live_free): Same. (df_live_top_dump): Same. (df_live_verify_transfer_functions): Same. (df_mir_alloc): Same. (df_mir_reset): Same. (df_mir_init): Same. (df_mir_confluence_n): Same. (df_mir_free): Same. (df_mir_top_dump): Same. (df_word_lr_alloc): Same. (df_word_lr_reset): Same. (df_word_lr_init): Same. (df_word_lr_confluence_n): Same. (df_word_lr_free): Same. (df_word_lr_top_dump): Same. (df_md_alloc): Same. (df_md_simulate_one_insn): Same. (df_md_reset): Same. (df_md_init): Same. (df_md_free): Same. (df_md_top_dump): Same. * df-scan.c (df_insn_delete): Same. (df_insn_rescan): Same. (df_notes_rescan): Same. (df_sort_and_compress_mws): Same. (df_install_mws): Same. (df_refs_add_to_chains): Same. (df_ref_create_structure): Same. (df_ref_record): Same. (df_def_record_1): Same. (df_find_hard_reg_defs): Same. (df_uses_record): Same. (df_get_conditional_uses): Same. (df_get_call_refs): Same. (df_recompute_luids): Same. (df_get_entry_block_def_set): Same. (df_entry_block_defs_collect): Same. (df_get_exit_block_use_set): Same. (df_exit_block_uses_collect): Same. (df_mws_verify): Same. (df_bb_verify): Same. * df.h (df_scan_get_bb_info): Same. * doc/tm.texi: Same. * dse.c (record_store): Same. * dumpfile.h: Same. * emit-rtl.c (const_fixed_hasher::equal): Same. (set_mem_attributes_minus_bitpos): Same. (change_address): Same. (adjust_address_1): Same. (offset_address): Same. * emit-rtl.h: Same. * except.c (dw2_build_landing_pads): Same. (sjlj_emit_dispatch_table): Same. * explow.c (allocate_dynamic_stack_space): Same. (emit_stack_probe): Same. (probe_stack_range): Same. * expmed.c (store_bit_field_using_insv): Same. (store_bit_field_1): Same. (store_integral_bit_field): Same. (extract_bit_field_using_extv): Same. (extract_bit_field_1): Same. (emit_cstore): Same. * expr.c (emit_block_move_via_cpymem): Same. (expand_cmpstrn_or_cmpmem): Same. (set_storage_via_setmem): Same. (emit_single_push_insn_1): Same. (expand_assignment): Same. (store_constructor): Same. (expand_expr_real_2): Same. (expand_expr_real_1): Same. (try_casesi): Same. * flags.h: Same. * function.c (try_fit_stack_local): Same. (assign_stack_local_1): Same. (assign_stack_local): Same. (cut_slot_from_list): Same. (insert_slot_to_list): Same. (max_slot_level): Same. (move_slot_to_level): Same. (temp_address_hasher::equal): Same. (remove_unused_temp_slot_addresses): Same. (assign_temp): Same. (combine_temp_slots): Same. (update_temp_slot_address): Same. (preserve_temp_slots): Same. * function.h: Same. * fwprop.c: Same. * gcc-rich-location.h: Same. * gcov.c: Same. * genattrtab.c (check_attr_test): Same. (check_attr_value): Same. (convert_set_attr_alternative): Same. (convert_set_attr): Same. (check_defs): Same. (copy_boolean): Same. (get_attr_value): Same. (expand_delays): Same. (make_length_attrs): Same. (min_fn): Same. (make_alternative_compare): Same. (simplify_test_exp): Same. (tests_attr_p): Same. (get_attr_order): Same. (clear_struct_flag): Same. (gen_attr): Same. (compares_alternatives_p): Same. (gen_insn): Same. (gen_delay): Same. (find_attrs_to_cache): Same. (write_test_expr): Same. (walk_attr_value): Same. (write_attr_get): Same. (eliminate_known_true): Same. (write_insn_cases): Same. (write_attr_case): Same. (write_attr_valueq): Same. (write_attr_value): Same. (write_dummy_eligible_delay): Same. (next_comma_elt): Same. (find_attr): Same. (make_internal_attr): Same. (copy_rtx_unchanging): Same. (gen_insn_reserv): Same. (check_tune_attr): Same. (make_automaton_attrs): Same. (handle_arg): Same. * genextract.c (gen_insn): Same. (VEC_char_to_string): Same. * genmatch.c (print_operand): Same. (lower): Same. (parser::parse_operation): Same. (parser::parse_capture): Same. (parser::parse_c_expr): Same. (parser::parse_simplify): Same. (main): Same. * genoutput.c (output_operand_data): Same. (output_get_insn_name): Same. (compare_operands): Same. (place_operands): Same. (process_template): Same. (validate_insn_alternatives): Same. (validate_insn_operands): Same. (gen_expand): Same. (note_constraint): Same. * genpreds.c (write_one_predicate_function): Same. (add_constraint): Same. (process_define_register_constraint): Same. (write_lookup_constraint_1): Same. (write_lookup_constraint_array): Same. (write_insn_constraint_len): Same. (write_reg_class_for_constraint_1): Same. (write_constraint_satisfied_p_array): Same. * genrecog.c (optimize_subroutine_group): Same. * gensupport.c (process_define_predicate): Same. (queue_pattern): Same. (remove_from_queue): Same. (process_rtx): Same. (is_predicable): Same. (change_subst_attribute): Same. (subst_pattern_match): Same. (alter_constraints): Same. (alter_attrs_for_insn): Same. (shift_output_template): Same. (alter_output_for_subst_insn): Same. (process_one_cond_exec): Same. (subst_dup): Same. (process_define_cond_exec): Same. (mnemonic_htab_callback): Same. (gen_mnemonic_attr): Same. (read_md_rtx): Same. * ggc-page.c: Same. * gimple-loop-interchange.cc (dump_reduction): Same. (dump_induction): Same. (loop_cand::~loop_cand): Same. (free_data_refs_with_aux): Same. (tree_loop_interchange::interchange_loops): Same. (tree_loop_interchange::map_inductions_to_loop): Same. (tree_loop_interchange::move_code_to_inner_loop): Same. (compute_access_stride): Same. (compute_access_strides): Same. (proper_loop_form_for_interchange): Same. (tree_loop_interchange_compute_ddrs): Same. (prune_datarefs_not_in_loop): Same. (prepare_data_references): Same. (pass_linterchange::execute): Same. * gimple-loop-jam.c (bb_prevents_fusion_p): Same. (unroll_jam_possible_p): Same. (fuse_loops): Same. (adjust_unroll_factor): Same. (tree_loop_unroll_and_jam): Same. * gimple-loop-versioning.cc (loop_versioning::~loop_versioning): Same. (loop_versioning::expensive_stmt_p): Same. (loop_versioning::version_for_unity): Same. (loop_versioning::dump_inner_likelihood): Same. (loop_versioning::find_per_loop_multiplication): Same. (loop_versioning::analyze_term_using_scevs): Same. (loop_versioning::record_address_fragment): Same. (loop_versioning::analyze_expr): Same. (loop_versioning::analyze_blocks): Same. (loop_versioning::prune_conditions): Same. (loop_versioning::merge_loop_info): Same. (loop_versioning::add_loop_to_queue): Same. (loop_versioning::decide_whether_loop_is_versionable): Same. (loop_versioning::make_versioning_decisions): Same. (loop_versioning::implement_versioning_decisions): Same. * gimple-ssa-evrp-analyze.c (evrp_range_analyzer::record_ranges_from_phis): Same. * gimple-ssa-store-merging.c (split_store::split_store): Same. (count_multiple_uses): Same. (split_group): Same. (imm_store_chain_info::output_merged_store): Same. (pass_store_merging::process_store): Same. * gimple-ssa-strength-reduction.c (slsr_process_phi): Same. * gimple-ssa-warn-alloca.c (adjusted_warn_limit): Same. (is_max): Same. (alloca_call_type): Same. (pass_walloca::execute): Same. * gimple-streamer-in.c (input_phi): Same. (input_gimple_stmt): Same. * gimple-streamer.h: Same. * godump.c (go_force_record_alignment): Same. (go_format_type): Same. (go_output_type): Same. (go_output_fndecl): Same. (go_output_typedef): Same. (keyword_hash_init): Same. (find_dummy_types): Same. * graph.c (draw_cfg_nodes_no_loops): Same. (draw_cfg_nodes_for_loop): Same. * hard-reg-set.h (hard_reg_set_iter_next): Same. * hsa-brig.c: Same. * hsa-common.h (hsa_internal_fn_hasher::equal): Same. * hsa-dump.c (dump_hsa_cfun): Same. * hsa-gen.c (gen_function_def_parameters): Same. * hsa-regalloc.c (dump_hsa_cfun_regalloc): Same. * input.c (dump_line_table_statistics): Same. (test_lexer): Same. * input.h: Same. * internal-fn.c (get_multi_vector_move): Same. (expand_load_lanes_optab_fn): Same. (expand_GOMP_SIMT_ENTER_ALLOC): Same. (expand_GOMP_SIMT_EXIT): Same. (expand_GOMP_SIMT_LAST_LANE): Same. (expand_GOMP_SIMT_ORDERED_PRED): Same. (expand_GOMP_SIMT_VOTE_ANY): Same. (expand_GOMP_SIMT_XCHG_BFLY): Same. (expand_GOMP_SIMT_XCHG_IDX): Same. (expand_addsub_overflow): Same. (expand_neg_overflow): Same. (expand_mul_overflow): Same. (expand_call_mem_ref): Same. (expand_mask_load_optab_fn): Same. (expand_scatter_store_optab_fn): Same. (expand_gather_load_optab_fn): Same. * ipa-cp.c (ipa_get_parm_lattices): Same. (print_all_lattices): Same. (ignore_edge_p): Same. (build_toporder_info): Same. (free_toporder_info): Same. (push_node_to_stack): Same. (ipcp_lattice<valtype>::set_contains_variable): Same. (set_agg_lats_to_bottom): Same. (ipcp_bits_lattice::meet_with): Same. (set_single_call_flag): Same. (initialize_node_lattices): Same. (ipa_get_jf_ancestor_result): Same. (ipcp_verify_propagated_values): Same. (propagate_scalar_across_jump_function): Same. (propagate_context_across_jump_function): Same. (propagate_bits_across_jump_function): Same. (ipa_vr_operation_and_type_effects): Same. (propagate_vr_across_jump_function): Same. (set_check_aggs_by_ref): Same. (set_chain_of_aglats_contains_variable): Same. (merge_aggregate_lattices): Same. (agg_pass_through_permissible_p): Same. (propagate_aggs_across_jump_function): Same. (call_passes_through_thunk_p): Same. (propagate_constants_across_call): Same. (devirtualization_time_bonus): Same. (good_cloning_opportunity_p): Same. (context_independent_aggregate_values): Same. (gather_context_independent_values): Same. (perform_estimation_of_a_value): Same. (estimate_local_effects): Same. (value_topo_info<valtype>::add_val): Same. (add_all_node_vals_to_toposort): Same. (value_topo_info<valtype>::propagate_effects): Same. (ipcp_propagate_stage): Same. (ipcp_discover_new_direct_edges): Same. (same_node_or_its_all_contexts_clone_p): Same. (cgraph_edge_brings_value_p): Same. (gather_edges_for_value): Same. (create_specialized_node): Same. (find_more_scalar_values_for_callers_subset): Same. (find_more_contexts_for_caller_subset): Same. (copy_plats_to_inter): Same. (intersect_aggregates_with_edge): Same. (find_aggregate_values_for_callers_subset): Same. (cgraph_edge_brings_all_agg_vals_for_node): Same. (decide_about_value): Same. (decide_whether_version_node): Same. (spread_undeadness): Same. (identify_dead_nodes): Same. (ipcp_store_vr_results): Same. * ipa-devirt.c (final_warning_record::grow_type_warnings): Same. * ipa-fnsummary.c (ipa_fn_summary::account_size_time): Same. (redirect_to_unreachable): Same. (edge_set_predicate): Same. (evaluate_conditions_for_known_args): Same. (evaluate_properties_for_edge): Same. (ipa_fn_summary_t::duplicate): Same. (ipa_call_summary_t::duplicate): Same. (dump_ipa_call_summary): Same. (ipa_dump_fn_summary): Same. (eliminated_by_inlining_prob): Same. (set_cond_stmt_execution_predicate): Same. (set_switch_stmt_execution_predicate): Same. (compute_bb_predicates): Same. (will_be_nonconstant_expr_predicate): Same. (phi_result_unknown_predicate): Same. (analyze_function_body): Same. (compute_fn_summary): Same. (estimate_edge_devirt_benefit): Same. (estimate_edge_size_and_time): Same. (estimate_calls_size_and_time): Same. (estimate_node_size_and_time): Same. (remap_edge_change_prob): Same. (remap_edge_summaries): Same. (ipa_merge_fn_summary_after_inlining): Same. (ipa_fn_summary_generate): Same. (inline_read_section): Same. (ipa_fn_summary_read): Same. (ipa_fn_summary_write): Same. * ipa-fnsummary.h: Same. * ipa-hsa.c (ipa_hsa_read_section): Same. * ipa-icf-gimple.c (func_checker::compare_loops): Same. * ipa-icf.c (sem_function::param_used_p): Same. * ipa-inline-analysis.c (do_estimate_edge_time): Same. * ipa-inline.c (edge_badness): Same. (inline_small_functions): Same. * ipa-polymorphic-call.c (ipa_polymorphic_call_context::stream_out): Same. * ipa-predicate.c (predicate::remap_after_duplication): Same. (predicate::remap_after_inlining): Same. (predicate::stream_out): Same. * ipa-predicate.h: Same. * ipa-profile.c (ipa_profile_read_summary): Same. * ipa-prop.c (ipa_get_param_decl_index_1): Same. (count_formal_params): Same. (ipa_dump_param): Same. (ipa_alloc_node_params): Same. (ipa_print_node_jump_functions_for_edge): Same. (ipa_print_node_jump_functions): Same. (ipa_load_from_parm_agg): Same. (get_ancestor_addr_info): Same. (ipa_compute_jump_functions_for_edge): Same. (ipa_analyze_virtual_call_uses): Same. (ipa_analyze_stmt_uses): Same. (ipa_analyze_params_uses_in_bb): Same. (update_jump_functions_after_inlining): Same. (try_decrement_rdesc_refcount): Same. (ipa_impossible_devirt_target): Same. (update_indirect_edges_after_inlining): Same. (combine_controlled_uses_counters): Same. (ipa_edge_args_sum_t::duplicate): Same. (ipa_write_jump_function): Same. (ipa_write_indirect_edge_info): Same. (ipa_write_node_info): Same. (ipa_read_edge_info): Same. (ipa_prop_read_section): Same. (read_replacements_section): Same. * ipa-prop.h (ipa_get_param_count): Same. (ipa_get_param): Same. (ipa_get_type): Same. (ipa_get_param_move_cost): Same. (ipa_set_param_used): Same. (ipa_get_controlled_uses): Same. (ipa_set_controlled_uses): Same. (ipa_get_cs_argument_count): Same. * ipa-pure-const.c (analyze_function): Same. (pure_const_read_summary): Same. * ipa-ref.h: Same. * ipa-reference.c (ipa_reference_read_optimization_summary): Same. * ipa-split.c (test_nonssa_use): Same. (dump_split_point): Same. (dominated_by_forbidden): Same. (split_part_set_ssa_name_p): Same. (find_split_points): Same. * ira-build.c (finish_loop_tree_nodes): Same. (low_pressure_loop_node_p): Same. * ira-color.c (ira_reuse_stack_slot): Same. * ira-int.h: Same. * ira.c (setup_reg_equiv): Same. (print_insn_chain): Same. (ira): Same. * loop-doloop.c (doloop_condition_get): Same. (add_test): Same. (record_reg_sets): Same. (doloop_optimize): Same. * loop-init.c (loop_optimizer_init): Same. (fix_loop_structure): Same. * loop-invariant.c (merge_identical_invariants): Same. (compute_always_reached): Same. (find_exits): Same. (may_assign_reg_p): Same. (find_invariants_bb): Same. (find_invariants_body): Same. (replace_uses): Same. (can_move_invariant_reg): Same. (free_inv_motion_data): Same. (move_single_loop_invariants): Same. (change_pressure): Same. (mark_ref_regs): Same. (calculate_loop_reg_pressure): Same. * loop-iv.c (biv_entry_hasher::equal): Same. (iv_extend_to_rtx_code): Same. (check_iv_ref_table_size): Same. (clear_iv_info): Same. (latch_dominating_def): Same. (iv_get_reaching_def): Same. (iv_constant): Same. (iv_subreg): Same. (iv_extend): Same. (iv_neg): Same. (iv_add): Same. (iv_mult): Same. (get_biv_step): Same. (record_iv): Same. (analyzed_for_bivness_p): Same. (record_biv): Same. (iv_analyze_biv): Same. (iv_analyze_expr): Same. (iv_analyze_def): Same. (iv_analyze_op): Same. (iv_analyze): Same. (iv_analyze_result): Same. (biv_p): Same. (eliminate_implied_conditions): Same. (simplify_using_initial_values): Same. (shorten_into_mode): Same. (canonicalize_iv_subregs): Same. (determine_max_iter): Same. (check_simple_exit): Same. (find_simple_exit): Same. (get_simple_loop_desc): Same. * loop-unroll.c (report_unroll): Same. (decide_unrolling): Same. (unroll_loops): Same. (loop_exit_at_end_p): Same. (decide_unroll_constant_iterations): Same. (unroll_loop_constant_iterations): Same. (compare_and_jump_seq): Same. (unroll_loop_runtime_iterations): Same. (decide_unroll_stupid): Same. (unroll_loop_stupid): Same. (referenced_in_one_insn_in_loop_p): Same. (reset_debug_uses_in_loop): Same. (analyze_iv_to_split_insn): Same. * lra-eliminations.c (lra_debug_elim_table): Same. (setup_can_eliminate): Same. (form_sum): Same. (lra_get_elimination_hard_regno): Same. (lra_eliminate_regs_1): Same. (eliminate_regs_in_insn): Same. (update_reg_eliminate): Same. (init_elimination): Same. (lra_eliminate): Same. * lra-int.h: Same. * lra-lives.c (initiate_live_solver): Same. * lra-remat.c (create_remat_bb_data): Same. * lra-spills.c (lra_spill): Same. * lra.c (lra_set_insn_recog_data): Same. (lra_set_used_insn_alternative_by_uid): Same. (init_reg_info): Same. (expand_reg_info): Same. * lto-cgraph.c (output_symtab): Same. (read_identifier): Same. (get_alias_symbol): Same. (input_node): Same. (input_varpool_node): Same. (input_ref): Same. (input_edge): Same. (input_cgraph_1): Same. (input_refs): Same. (input_symtab): Same. (input_offload_tables): Same. (output_cgraph_opt_summary): Same. (input_edge_opt_summary): Same. (input_cgraph_opt_section): Same. * lto-section-in.c (lto_free_raw_section_data): Same. (lto_create_simple_input_block): Same. (lto_free_function_in_decl_state_for_node): Same. * lto-streamer-in.c (lto_tag_check_set): Same. (lto_location_cache::revert_location_cache): Same. (lto_location_cache::input_location): Same. (lto_input_location): Same. (stream_input_location_now): Same. (lto_input_tree_ref): Same. (lto_input_eh_catch_list): Same. (input_eh_region): Same. (lto_init_eh): Same. (make_new_block): Same. (input_cfg): Same. (fixup_call_stmt_edges): Same. (input_struct_function_base): Same. (input_function): Same. (lto_read_body_or_constructor): Same. (lto_read_tree_1): Same. (lto_read_tree): Same. (lto_input_scc): Same. (lto_input_tree_1): Same. (lto_input_toplevel_asms): Same. (lto_input_mode_table): Same. (lto_reader_init): Same. (lto_data_in_create): Same. * lto-streamer-out.c (output_cfg): Same. * lto-streamer.h: Same. * modulo-sched.c (duplicate_insns_of_cycles): Same. (generate_prolog_epilog): Same. (mark_loop_unsched): Same. (dump_insn_location): Same. (loop_canon_p): Same. (sms_schedule): Same. * omp-expand.c (expand_omp_for_ordered_loops): Same. (expand_omp_for_generic): Same. (expand_omp_for_static_nochunk): Same. (expand_omp_for_static_chunk): Same. (expand_omp_simd): Same. (expand_omp_taskloop_for_inner): Same. (expand_oacc_for): Same. (expand_omp_atomic_pipeline): Same. (mark_loops_in_oacc_kernels_region): Same. * omp-offload.c (oacc_xform_loop): Same. * omp-simd-clone.c (simd_clone_adjust): Same. * optabs-query.c (get_traditional_extraction_insn): Same. * optabs.c (expand_vector_broadcast): Same. (expand_binop_directly): Same. (expand_twoval_unop): Same. (expand_twoval_binop): Same. (expand_unop_direct): Same. (emit_indirect_jump): Same. (emit_conditional_move): Same. (emit_conditional_neg_or_complement): Same. (emit_conditional_add): Same. (vector_compare_rtx): Same. (expand_vec_perm_1): Same. (expand_vec_perm_const): Same. (expand_vec_cond_expr): Same. (expand_vec_series_expr): Same. (maybe_emit_atomic_exchange): Same. (maybe_emit_sync_lock_test_and_set): Same. (expand_atomic_compare_and_swap): Same. (expand_atomic_load): Same. (expand_atomic_store): Same. (maybe_emit_op): Same. (valid_multiword_target_p): Same. (create_integer_operand): Same. (maybe_legitimize_operand_same_code): Same. (maybe_legitimize_operand): Same. (create_convert_operand_from_type): Same. (can_reuse_operands_p): Same. (maybe_legitimize_operands): Same. (maybe_gen_insn): Same. (maybe_expand_insn): Same. (maybe_expand_jump_insn): Same. (expand_insn): Same. * optabs.h (create_expand_operand): Same. (create_fixed_operand): Same. (create_output_operand): Same. (create_input_operand): Same. (create_convert_operand_to): Same. (create_convert_operand_from): Same. * optinfo.h: Same. * poly-int.h: Same. * predict.c (optimize_insn_for_speed_p): Same. (optimize_loop_for_size_p): Same. (optimize_loop_for_speed_p): Same. (optimize_loop_nest_for_speed_p): Same. (get_base_value): Same. (predicted_by_loop_heuristics_p): Same. (predict_extra_loop_exits): Same. (predict_loops): Same. (predict_paths_for_bb): Same. (predict_paths_leading_to): Same. (propagate_freq): Same. (pass_profile::execute): Same. * predict.h: Same. * profile-count.c (profile_count::differs_from_p): Same. (profile_probability::differs_lot_from_p): Same. * profile-count.h: Same. * profile.c (branch_prob): Same. * regrename.c (free_chain_data): Same. (mark_conflict): Same. (create_new_chain): Same. (merge_overlapping_regs): Same. (init_rename_info): Same. (merge_chains): Same. (regrename_analyze): Same. (regrename_do_replace): Same. (scan_rtx_reg): Same. (record_out_operands): Same. (build_def_use): Same. * regrename.h: Same. * reload.h: Same. * reload1.c (init_reload): Same. (maybe_fix_stack_asms): Same. (copy_reloads): Same. (count_pseudo): Same. (count_spilled_pseudo): Same. (find_reg): Same. (find_reload_regs): Same. (select_reload_regs): Same. (spill_hard_reg): Same. (fixup_eh_region_note): Same. (set_reload_reg): Same. (allocate_reload_reg): Same. (compute_reload_subreg_offset): Same. (reload_adjust_reg_for_icode): Same. (emit_input_reload_insns): Same. (emit_output_reload_insns): Same. (do_input_reload): Same. (inherit_piecemeal_p): Same. * rtl.h: Same. * sanopt.c (maybe_get_dominating_check): Same. (maybe_optimize_ubsan_ptr_ifn): Same. (can_remove_asan_check): Same. (maybe_optimize_asan_check_ifn): Same. (sanopt_optimize_walker): Same. * sched-deps.c (add_dependence_list): Same. (chain_to_prev_insn): Same. (add_insn_mem_dependence): Same. (create_insn_reg_set): Same. (maybe_extend_reg_info_p): Same. (sched_analyze_reg): Same. (sched_analyze_1): Same. (get_implicit_reg_pending_clobbers): Same. (chain_to_prev_insn_p): Same. (deps_analyze_insn): Same. (deps_start_bb): Same. (sched_free_deps): Same. (init_deps): Same. (init_deps_reg_last): Same. (free_deps): Same. * sched-ebb.c: Same. * sched-int.h: Same. * sched-rgn.c (add_branch_dependences): Same. (concat_insn_mem_list): Same. (deps_join): Same. (sched_rgn_compute_dependencies): Same. * sel-sched-ir.c (reset_target_context): Same. (copy_deps_context): Same. (init_id_from_df): Same. (has_dependence_p): Same. (change_loops_latches): Same. (bb_top_order_comparator): Same. (make_region_from_loop_preheader): Same. (sel_init_pipelining): Same. (get_loop_nest_for_rgn): Same. (make_regions_from_the_rest): Same. (sel_is_loop_preheader_p): Same. * sel-sched-ir.h (inner_loop_header_p): Same. (get_all_loop_exits): Same. * selftest.h: Same. * sese.c (sese_build_liveouts): Same. (sese_insert_phis_for_liveouts): Same. * sese.h (defined_in_sese_p): Same. * sreal.c (sreal::stream_out): Same. * sreal.h: Same. * streamer-hooks.h: Same. * target-globals.c (save_target_globals): Same. * target-globals.h: Same. * target.def: Same. * target.h: Same. * targhooks.c (default_has_ifunc_p): Same. (default_empty_mask_is_expensive): Same. (default_init_cost): Same. * targhooks.h: Same. * toplev.c: Same. * tree-affine.c (aff_combination_mult): Same. (aff_combination_expand): Same. (aff_combination_constant_multiple_p): Same. * tree-affine.h: Same. * tree-cfg.c (build_gimple_cfg): Same. (replace_loop_annotate_in_block): Same. (replace_uses_by): Same. (remove_bb): Same. (dump_cfg_stats): Same. (gimple_duplicate_sese_region): Same. (gimple_duplicate_sese_tail): Same. (move_block_to_fn): Same. (replace_block_vars_by_duplicates): Same. (move_sese_region_to_fn): Same. (print_loops_bb): Same. (print_loop): Same. (print_loops): Same. (debug): Same. (debug_loops): Same. * tree-cfg.h: Same. * tree-chrec.c (chrec_fold_plus_poly_poly): Same. (chrec_fold_multiply_poly_poly): Same. (chrec_evaluate): Same. (chrec_component_in_loop_num): Same. (reset_evolution_in_loop): Same. (is_multivariate_chrec): Same. (chrec_contains_symbols): Same. (nb_vars_in_chrec): Same. (chrec_convert_1): Same. (chrec_convert_aggressive): Same. * tree-chrec.h: Same. * tree-core.h: Same. * tree-data-ref.c (dump_data_dependence_relation): Same. (canonicalize_base_object_address): Same. (data_ref_compare_tree): Same. (prune_runtime_alias_test_list): Same. (get_segment_min_max): Same. (create_intersect_range_checks): Same. (conflict_fn_no_dependence): Same. (object_address_invariant_in_loop_p): Same. (analyze_ziv_subscript): Same. (analyze_siv_subscript_cst_affine): Same. (analyze_miv_subscript): Same. (analyze_overlapping_iterations): Same. (build_classic_dist_vector_1): Same. (add_other_self_distances): Same. (same_access_functions): Same. (build_classic_dir_vector): Same. (subscript_dependence_tester_1): Same. (subscript_dependence_tester): Same. (access_functions_are_affine_or_constant_p): Same. (get_references_in_stmt): Same. (loop_nest_has_data_refs): Same. (graphite_find_data_references_in_stmt): Same. (find_data_references_in_bb): Same. (get_base_for_alignment): Same. (find_loop_nest_1): Same. (find_loop_nest): Same. * tree-data-ref.h (dr_alignment): Same. (ddr_dependence_level): Same. * tree-if-conv.c (fold_build_cond_expr): Same. (add_to_predicate_list): Same. (add_to_dst_predicate_list): Same. (phi_convertible_by_degenerating_args): Same. (idx_within_array_bound): Same. (all_preds_critical_p): Same. (pred_blocks_visited_p): Same. (predicate_bbs): Same. (build_region): Same. (if_convertible_loop_p_1): Same. (is_cond_scalar_reduction): Same. (predicate_scalar_phi): Same. (remove_conditions_and_labels): Same. (combine_blocks): Same. (version_loop_for_if_conversion): Same. (versionable_outer_loop_p): Same. (ifcvt_local_dce): Same. (tree_if_conversion): Same. (pass_if_conversion::gate): Same. * tree-if-conv.h: Same. * tree-inline.c (maybe_move_debug_stmts_to_successors): Same. * tree-loop-distribution.c (bb_top_order_cmp): Same. (free_rdg): Same. (stmt_has_scalar_dependences_outside_loop): Same. (copy_loop_before): Same. (create_bb_after_loop): Same. (const_with_all_bytes_same): Same. (generate_memset_builtin): Same. (generate_memcpy_builtin): Same. (destroy_loop): Same. (build_rdg_partition_for_vertex): Same. (compute_access_range): Same. (data_ref_segment_size): Same. (latch_dominated_by_data_ref): Same. (compute_alias_check_pairs): Same. (fuse_memset_builtins): Same. (finalize_partitions): Same. (find_seed_stmts_for_distribution): Same. (prepare_perfect_loop_nest): Same. * tree-parloops.c (lambda_transform_legal_p): Same. (loop_parallel_p): Same. (reduc_stmt_res): Same. (add_field_for_name): Same. (create_call_for_reduction_1): Same. (replace_uses_in_bb_by): Same. (transform_to_exit_first_loop_alt): Same. (try_transform_to_exit_first_loop_alt): Same. (transform_to_exit_first_loop): Same. (num_phis): Same. (gen_parallel_loop): Same. (gather_scalar_reductions): Same. (get_omp_data_i_param): Same. (try_create_reduction_list): Same. (oacc_entry_exit_single_gang): Same. (parallelize_loops): Same. * tree-pass.h: Same. * tree-predcom.c (determine_offset): Same. (last_always_executed_block): Same. (split_data_refs_to_components): Same. (suitable_component_p): Same. (valid_initializer_p): Same. (find_looparound_phi): Same. (insert_looparound_copy): Same. (add_looparound_copies): Same. (determine_roots_comp): Same. (predcom_tmp_var): Same. (initialize_root_vars): Same. (initialize_root_vars_store_elim_1): Same. (initialize_root_vars_store_elim_2): Same. (finalize_eliminated_stores): Same. (initialize_root_vars_lm): Same. (remove_stmt): Same. (determine_unroll_factor): Same. (execute_pred_commoning_cbck): Same. (base_names_in_chain_on): Same. (combine_chains): Same. (pcom_stmt_dominates_stmt_p): Same. (try_combine_chains): Same. (prepare_initializers_chain_store_elim): Same. (prepare_initializers_chain): Same. (prepare_initializers): Same. (prepare_finalizers_chain): Same. (prepare_finalizers): Same. (insert_init_seqs): Same. * tree-scalar-evolution.c (loop_phi_node_p): Same. (compute_overall_effect_of_inner_loop): Same. (add_to_evolution_1): Same. (add_to_evolution): Same. (follow_ssa_edge_binary): Same. (follow_ssa_edge_expr): Same. (backedge_phi_arg_p): Same. (follow_ssa_edge_in_condition_phi_branch): Same. (follow_ssa_edge_in_condition_phi): Same. (follow_ssa_edge_inner_loop_phi): Same. (follow_ssa_edge): Same. (analyze_evolution_in_loop): Same. (analyze_initial_condition): Same. (interpret_loop_phi): Same. (interpret_condition_phi): Same. (interpret_rhs_expr): Same. (interpret_expr): Same. (interpret_gimple_assign): Same. (analyze_scalar_evolution_1): Same. (analyze_scalar_evolution): Same. (analyze_scalar_evolution_for_address_of): Same. (get_instantiated_value_entry): Same. (loop_closed_phi_def): Same. (instantiate_scev_name): Same. (instantiate_scev_poly): Same. (instantiate_scev_binary): Same. (instantiate_scev_convert): Same. (instantiate_scev_not): Same. (instantiate_scev_r): Same. (instantiate_scev): Same. (resolve_mixers): Same. (initialize_scalar_evolutions_analyzer): Same. (scev_reset_htab): Same. (scev_reset): Same. (derive_simple_iv_with_niters): Same. (simple_iv_with_niters): Same. (expression_expensive_p): Same. (final_value_replacement_loop): Same. * tree-scalar-evolution.h (block_before_loop): Same. * tree-ssa-address.h: Same. * tree-ssa-dce.c (find_obviously_necessary_stmts): Same. * tree-ssa-dom.c (edge_info::record_simple_equiv): Same. (record_edge_info): Same. * tree-ssa-live.c (var_map_base_fini): Same. (remove_unused_locals): Same. * tree-ssa-live.h: Same. * tree-ssa-loop-ch.c (should_duplicate_loop_header_p): Same. (pass_ch_vect::execute): Same. (pass_ch::process_loop_p): Same. * tree-ssa-loop-im.c (mem_ref_hasher::hash): Same. (movement_possibility): Same. (outermost_invariant_loop): Same. (stmt_cost): Same. (determine_max_movement): Same. (invariantness_dom_walker::before_dom_children): Same. (move_computations): Same. (may_move_till): Same. (force_move_till_op): Same. (force_move_till): Same. (memref_free): Same. (record_mem_ref_loc): Same. (set_ref_stored_in_loop): Same. (mark_ref_stored): Same. (sort_bbs_in_loop_postorder_cmp): Same. (sort_locs_in_loop_postorder_cmp): Same. (analyze_memory_references): Same. (mem_refs_may_alias_p): Same. (find_ref_loc_in_loop_cmp): Same. (rewrite_mem_ref_loc::operator): Same. (first_mem_ref_loc_1::operator): Same. (sm_set_flag_if_changed::operator): Same. (execute_sm_if_changed_flag_set): Same. (execute_sm): Same. (hoist_memory_references): Same. (ref_always_accessed::operator): Same. (refs_independent_p): Same. (record_dep_loop): Same. (ref_indep_loop_p_1): Same. (ref_indep_loop_p): Same. (can_sm_ref_p): Same. (find_refs_for_sm): Same. (loop_suitable_for_sm): Same. (store_motion_loop): Same. (store_motion): Same. (fill_always_executed_in): Same. * tree-ssa-loop-ivcanon.c (constant_after_peeling): Same. (estimated_unrolled_size): Same. (loop_edge_to_cancel): Same. (remove_exits_and_undefined_stmts): Same. (remove_redundant_iv_tests): Same. (unloop_loops): Same. (estimated_peeled_sequence_size): Same. (try_peel_loop): Same. (canonicalize_loop_induction_variables): Same. (canonicalize_induction_variables): Same. * tree-ssa-loop-ivopts.c (iv_inv_expr_hasher::equal): Same. (name_info): Same. (stmt_after_inc_pos): Same. (contains_abnormal_ssa_name_p): Same. (niter_for_exit): Same. (find_bivs): Same. (mark_bivs): Same. (find_givs_in_bb): Same. (find_induction_variables): Same. (find_interesting_uses_cond): Same. (outermost_invariant_loop_for_expr): Same. (idx_find_step): Same. (add_candidate_1): Same. (add_iv_candidate_derived_from_uses): Same. (alloc_use_cost_map): Same. (prepare_decl_rtl): Same. (generic_predict_doloop_p): Same. (computation_cost): Same. (determine_common_wider_type): Same. (get_computation_aff_1): Same. (get_use_type): Same. (determine_group_iv_cost_address): Same. (iv_period): Same. (difference_cannot_overflow_p): Same. (may_eliminate_iv): Same. (determine_set_costs): Same. (cheaper_cost_pair): Same. (compare_cost_pair): Same. (iv_ca_cand_for_group): Same. (iv_ca_recount_cost): Same. (iv_ca_set_remove_invs): Same. (iv_ca_set_no_cp): Same. (iv_ca_set_add_invs): Same. (iv_ca_set_cp): Same. (iv_ca_add_group): Same. (iv_ca_cost): Same. (iv_ca_compare_deps): Same. (iv_ca_delta_reverse): Same. (iv_ca_delta_commit): Same. (iv_ca_cand_used_p): Same. (iv_ca_delta_free): Same. (iv_ca_new): Same. (iv_ca_free): Same. (iv_ca_dump): Same. (iv_ca_extend): Same. (iv_ca_narrow): Same. (iv_ca_prune): Same. (cheaper_cost_with_cand): Same. (iv_ca_replace): Same. (try_add_cand_for): Same. (get_initial_solution): Same. (try_improve_iv_set): Same. (find_optimal_iv_set_1): Same. (create_new_iv): Same. (rewrite_use_compare): Same. (remove_unused_ivs): Same. (determine_scaling_factor): Same. * tree-ssa-loop-ivopts.h: Same. * tree-ssa-loop-manip.c (create_iv): Same. (compute_live_loop_exits): Same. (add_exit_phi): Same. (add_exit_phis): Same. (find_uses_to_rename_use): Same. (find_uses_to_rename_def): Same. (find_uses_to_rename_in_loop): Same. (rewrite_into_loop_closed_ssa): Same. (check_loop_closed_ssa_bb): Same. (split_loop_exit_edge): Same. (ip_end_pos): Same. (ip_normal_pos): Same. (copy_phi_node_args): Same. (gimple_duplicate_loop_to_header_edge): Same. (can_unroll_loop_p): Same. (determine_exit_conditions): Same. (scale_dominated_blocks_in_loop): Same. (niter_for_unrolled_loop): Same. (tree_transform_and_unroll_loop): Same. (rewrite_all_phi_nodes_with_iv): Same. * tree-ssa-loop-manip.h: Same. * tree-ssa-loop-niter.c (number_of_iterations_ne_max): Same. (number_of_iterations_ne): Same. (assert_no_overflow_lt): Same. (assert_loop_rolls_lt): Same. (number_of_iterations_lt): Same. (adjust_cond_for_loop_until_wrap): Same. (tree_simplify_using_condition): Same. (simplify_using_initial_conditions): Same. (simplify_using_outer_evolutions): Same. (loop_only_exit_p): Same. (ssa_defined_by_minus_one_stmt_p): Same. (number_of_iterations_popcount): Same. (number_of_iterations_exit): Same. (find_loop_niter): Same. (finite_loop_p): Same. (chain_of_csts_start): Same. (get_val_for): Same. (loop_niter_by_eval): Same. (derive_constant_upper_bound_ops): Same. (do_warn_aggressive_loop_optimizations): Same. (record_estimate): Same. (get_cst_init_from_scev): Same. (record_nonwrapping_iv): Same. (idx_infer_loop_bounds): Same. (infer_loop_bounds_from_ref): Same. (infer_loop_bounds_from_array): Same. (infer_loop_bounds_from_pointer_arith): Same. (infer_loop_bounds_from_signedness): Same. (bound_index): Same. (discover_iteration_bound_by_body_walk): Same. (maybe_lower_iteration_bound): Same. (estimate_numbers_of_iterations): Same. (estimated_loop_iterations): Same. (estimated_loop_iterations_int): Same. (max_loop_iterations): Same. (max_loop_iterations_int): Same. (likely_max_loop_iterations): Same. (likely_max_loop_iterations_int): Same. (estimated_stmt_executions_int): Same. (max_stmt_executions): Same. (likely_max_stmt_executions): Same. (estimated_stmt_executions): Same. (stmt_dominates_stmt_p): Same. (nowrap_type_p): Same. (loop_exits_before_overflow): Same. (scev_var_range_cant_overflow): Same. (scev_probably_wraps_p): Same. (free_numbers_of_iterations_estimates): Same. * tree-ssa-loop-niter.h: Same. * tree-ssa-loop-prefetch.c (release_mem_refs): Same. (idx_analyze_ref): Same. (analyze_ref): Same. (gather_memory_references_ref): Same. (mark_nontemporal_store): Same. (emit_mfence_after_loop): Same. (may_use_storent_in_loop_p): Same. (mark_nontemporal_stores): Same. (should_unroll_loop_p): Same. (volume_of_dist_vector): Same. (add_subscript_strides): Same. (self_reuse_distance): Same. (insn_to_prefetch_ratio_too_small_p): Same. * tree-ssa-loop-split.c (split_at_bb_p): Same. (patch_loop_exit): Same. (find_or_create_guard_phi): Same. (easy_exit_values): Same. (connect_loop_phis): Same. (connect_loops): Same. (compute_new_first_bound): Same. (split_loop): Same. (tree_ssa_split_loops): Same. * tree-ssa-loop-unswitch.c (tree_ssa_unswitch_loops): Same. (is_maybe_undefined): Same. (tree_may_unswitch_on): Same. (simplify_using_entry_checks): Same. (tree_unswitch_single_loop): Same. (tree_unswitch_loop): Same. (tree_unswitch_outer_loop): Same. (empty_bb_without_guard_p): Same. (used_outside_loop_p): Same. (get_vop_from_header): Same. (hoist_guard): Same. * tree-ssa-loop.c (gate_oacc_kernels): Same. (get_lsm_tmp_name): Same. * tree-ssa-loop.h: Same. * tree-ssa-reassoc.c (add_repeat_to_ops_vec): Same. (build_and_add_sum): Same. (no_side_effect_bb): Same. (get_ops): Same. (linearize_expr): Same. (should_break_up_subtract): Same. (linearize_expr_tree): Same. * tree-ssa-scopedtables.c: Same. * tree-ssa-scopedtables.h: Same. * tree-ssa-structalias.c (condense_visit): Same. (label_visit): Same. (dump_pred_graph): Same. (perform_var_substitution): Same. (move_complex_constraints): Same. (remove_preds_and_fake_succs): Same. * tree-ssa-threadupdate.c (dbds_continue_enumeration_p): Same. (determine_bb_domination_status): Same. (duplicate_thread_path): Same. (thread_through_all_blocks): Same. * tree-ssa-threadupdate.h: Same. * tree-streamer-in.c (streamer_read_string_cst): Same. (input_identifier): Same. (unpack_ts_type_common_value_fields): Same. (unpack_ts_block_value_fields): Same. (unpack_ts_translation_unit_decl_value_fields): Same. (unpack_ts_omp_clause_value_fields): Same. (streamer_read_tree_bitfields): Same. (streamer_alloc_tree): Same. (lto_input_ts_common_tree_pointers): Same. (lto_input_ts_vector_tree_pointers): Same. (lto_input_ts_poly_tree_pointers): Same. (lto_input_ts_complex_tree_pointers): Same. (lto_input_ts_decl_minimal_tree_pointers): Same. (lto_input_ts_decl_common_tree_pointers): Same. (lto_input_ts_decl_non_common_tree_pointers): Same. (lto_input_ts_decl_with_vis_tree_pointers): Same. (lto_input_ts_field_decl_tree_pointers): Same. (lto_input_ts_function_decl_tree_pointers): Same. (lto_input_ts_type_common_tree_pointers): Same. (lto_input_ts_type_non_common_tree_pointers): Same. (lto_input_ts_list_tree_pointers): Same. (lto_input_ts_vec_tree_pointers): Same. (lto_input_ts_exp_tree_pointers): Same. (lto_input_ts_block_tree_pointers): Same. (lto_input_ts_binfo_tree_pointers): Same. (lto_input_ts_constructor_tree_pointers): Same. (lto_input_ts_omp_clause_tree_pointers): Same. (streamer_read_tree_body): Same. * tree-streamer.h: Same. * tree-switch-conversion.c (bit_test_cluster::is_beneficial): Same. * tree-vect-data-refs.c (vect_get_smallest_scalar_type): Same. (vect_analyze_possibly_independent_ddr): Same. (vect_analyze_data_ref_dependence): Same. (vect_compute_data_ref_alignment): Same. (vect_enhance_data_refs_alignment): Same. (vect_analyze_data_ref_access): Same. (vect_check_gather_scatter): Same. (vect_find_stmt_data_reference): Same. (vect_create_addr_base_for_vector_ref): Same. (vect_setup_realignment): Same. (vect_supportable_dr_alignment): Same. * tree-vect-loop-manip.c (rename_variables_in_bb): Same. (adjust_phi_and_debug_stmts): Same. (vect_set_loop_mask): Same. (add_preheader_seq): Same. (vect_maybe_permute_loop_masks): Same. (vect_set_loop_masks_directly): Same. (vect_set_loop_condition_masked): Same. (vect_set_loop_condition_unmasked): Same. (slpeel_duplicate_current_defs_from_edges): Same. (slpeel_add_loop_guard): Same. (slpeel_can_duplicate_loop_p): Same. (create_lcssa_for_virtual_phi): Same. (iv_phi_p): Same. (vect_update_ivs_after_vectorizer): Same. (vect_gen_vector_loop_niters_mult_vf): Same. (slpeel_update_phi_nodes_for_loops): Same. (slpeel_update_phi_nodes_for_guard1): Same. (find_guard_arg): Same. (slpeel_update_phi_nodes_for_guard2): Same. (slpeel_update_phi_nodes_for_lcssa): Same. (vect_do_peeling): Same. (vect_create_cond_for_alias_checks): Same. (vect_loop_versioning): Same. * tree-vect-loop.c (vect_determine_vf_for_stmt): Same. (vect_inner_phi_in_double_reduction_p): Same. (vect_analyze_scalar_cycles_1): Same. (vect_fixup_scalar_cycles_with_patterns): Same. (vect_get_loop_niters): Same. (bb_in_loop_p): Same. (vect_get_max_nscalars_per_iter): Same. (vect_verify_full_masking): Same. (vect_compute_single_scalar_iteration_cost): Same. (vect_analyze_loop_form_1): Same. (vect_analyze_loop_form): Same. (vect_active_double_reduction_p): Same. (vect_analyze_loop_operations): Same. (neutral_op_for_slp_reduction): Same. (vect_is_simple_reduction): Same. (vect_model_reduction_cost): Same. (get_initial_def_for_reduction): Same. (get_initial_defs_for_reduction): Same. (vect_create_epilog_for_reduction): Same. (vectorize_fold_left_reduction): Same. (vectorizable_reduction): Same. (vectorizable_induction): Same. (vectorizable_live_operation): Same. (loop_niters_no_overflow): Same. (vect_get_loop_mask): Same. (vect_transform_loop_stmt): Same. (vect_transform_loop): Same. * tree-vect-patterns.c (vect_reassociating_reduction_p): Same. (vect_determine_precisions): Same. (vect_pattern_recog_1): Same. * tree-vect-slp.c (vect_analyze_slp_instance): Same. * tree-vect-stmts.c (stmt_vectype): Same. (process_use): Same. (vect_init_vector_1): Same. (vect_truncate_gather_scatter_offset): Same. (get_group_load_store_type): Same. (vect_build_gather_load_calls): Same. (vect_get_strided_load_store_ops): Same. (vectorizable_simd_clone_call): Same. (vectorizable_store): Same. (permute_vec_elements): Same. (vectorizable_load): Same. (vect_transform_stmt): Same. (supportable_widening_operation): Same. * tree-vectorizer.c (vec_info::replace_stmt): Same. (vec_info::free_stmt_vec_info): Same. (vect_free_loop_info_assumptions): Same. (vect_loop_vectorized_call): Same. (set_uid_loop_bbs): Same. (vectorize_loops): Same. * tree-vectorizer.h (STMT_VINFO_BB_VINFO): Same. * tree.c (add_tree_to_fld_list): Same. (fld_type_variant_equal_p): Same. (fld_decl_context): Same. (fld_incomplete_type_of): Same. (free_lang_data_in_binfo): Same. (need_assembler_name_p): Same. (find_decls_types_r): Same. (get_eh_types_for_runtime): Same. (find_decls_types_in_eh_region): Same. (find_decls_types_in_node): Same. (assign_assembler_name_if_needed): Same. * value-prof.c (stream_out_histogram_value): Same. * value-prof.h: Same. * var-tracking.c (use_narrower_mode): Same. (prepare_call_arguments): Same. (vt_expand_loc_callback): Same. (resolve_expansions_pending_recursion): Same. (vt_expand_loc): Same. * varasm.c (const_hash_1): Same. (compare_constant): Same. (tree_output_constant_def): Same. (simplify_subtraction): Same. (get_pool_constant): Same. (output_constant_pool_2): Same. (output_constant_pool_1): Same. (mark_constants_in_pattern): Same. (mark_constant_pool): Same. (get_section_anchor): Same. * vr-values.c (compare_range_with_value): Same. (vr_values::extract_range_from_phi_node): Same. * vr-values.h: Same. * web.c (unionfind_union): Same. * wide-int.h: Same. From-SVN: r273311
2459 lines
74 KiB
C
2459 lines
74 KiB
C
/* Map (unsigned int) keys to (source file, line, column) triples.
|
|
Copyright (C) 2001-2019 Free Software Foundation, Inc.
|
|
|
|
This program is free software; you can redistribute it and/or modify it
|
|
under the terms of the GNU General Public License as published by the
|
|
Free Software Foundation; either version 3, or (at your option) any
|
|
later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; see the file COPYING3. If not see
|
|
<http://www.gnu.org/licenses/>.
|
|
|
|
In other words, you are welcome to use, share and improve this program.
|
|
You are forbidden to forbid anyone else to use, share and improve
|
|
what you give them. Help stamp out software-hoarding! */
|
|
|
|
#include "config.h"
|
|
#include "system.h"
|
|
#include "line-map.h"
|
|
#include "cpplib.h"
|
|
#include "internal.h"
|
|
#include "hashtab.h"
|
|
|
|
static void trace_include (const line_maps *, const line_map_ordinary *);
|
|
static const line_map_ordinary * linemap_ordinary_map_lookup (line_maps *,
|
|
location_t);
|
|
static const line_map_macro* linemap_macro_map_lookup (line_maps *,
|
|
location_t);
|
|
static location_t linemap_macro_map_loc_to_def_point
|
|
(const line_map_macro *, location_t);
|
|
static location_t linemap_macro_map_loc_to_exp_point
|
|
(const line_map_macro *, location_t);
|
|
static location_t linemap_macro_loc_to_spelling_point
|
|
(line_maps *, location_t, const line_map_ordinary **);
|
|
static location_t linemap_macro_loc_to_def_point (line_maps *,
|
|
location_t,
|
|
const line_map_ordinary **);
|
|
static location_t linemap_macro_loc_to_exp_point (line_maps *,
|
|
location_t,
|
|
const line_map_ordinary **);
|
|
|
|
/* Counters defined in macro.c. */
|
|
extern unsigned num_expanded_macros_counter;
|
|
extern unsigned num_macro_tokens_counter;
|
|
|
|
/* Destructor for class line_maps.
|
|
Ensure non-GC-managed memory is released. */
|
|
|
|
line_maps::~line_maps ()
|
|
{
|
|
if (location_adhoc_data_map.htab)
|
|
htab_delete (location_adhoc_data_map.htab);
|
|
}
|
|
|
|
/* Hash function for location_adhoc_data hashtable. */
|
|
|
|
static hashval_t
|
|
location_adhoc_data_hash (const void *l)
|
|
{
|
|
const struct location_adhoc_data *lb =
|
|
(const struct location_adhoc_data *) l;
|
|
return ((hashval_t) lb->locus
|
|
+ (hashval_t) lb->src_range.m_start
|
|
+ (hashval_t) lb->src_range.m_finish
|
|
+ (size_t) lb->data);
|
|
}
|
|
|
|
/* Compare function for location_adhoc_data hashtable. */
|
|
|
|
static int
|
|
location_adhoc_data_eq (const void *l1, const void *l2)
|
|
{
|
|
const struct location_adhoc_data *lb1 =
|
|
(const struct location_adhoc_data *) l1;
|
|
const struct location_adhoc_data *lb2 =
|
|
(const struct location_adhoc_data *) l2;
|
|
return (lb1->locus == lb2->locus
|
|
&& lb1->src_range.m_start == lb2->src_range.m_start
|
|
&& lb1->src_range.m_finish == lb2->src_range.m_finish
|
|
&& lb1->data == lb2->data);
|
|
}
|
|
|
|
/* Update the hashtable when location_adhoc_data is reallocated. */
|
|
|
|
static int
|
|
location_adhoc_data_update (void **slot, void *data)
|
|
{
|
|
*((char **) slot)
|
|
= (char *) ((uintptr_t) *((char **) slot) + *((ptrdiff_t *) data));
|
|
return 1;
|
|
}
|
|
|
|
/* Rebuild the hash table from the location adhoc data. */
|
|
|
|
void
|
|
rebuild_location_adhoc_htab (line_maps *set)
|
|
{
|
|
unsigned i;
|
|
set->location_adhoc_data_map.htab =
|
|
htab_create (100, location_adhoc_data_hash, location_adhoc_data_eq, NULL);
|
|
for (i = 0; i < set->location_adhoc_data_map.curr_loc; i++)
|
|
htab_find_slot (set->location_adhoc_data_map.htab,
|
|
set->location_adhoc_data_map.data + i, INSERT);
|
|
}
|
|
|
|
/* Helper function for get_combined_adhoc_loc.
|
|
Can the given LOCUS + SRC_RANGE and DATA pointer be stored compactly
|
|
within a location_t, without needing to use an ad-hoc location. */
|
|
|
|
static bool
|
|
can_be_stored_compactly_p (line_maps *set,
|
|
location_t locus,
|
|
source_range src_range,
|
|
void *data)
|
|
{
|
|
/* If there's an ad-hoc pointer, we can't store it directly in the
|
|
location_t, we need the lookaside. */
|
|
if (data)
|
|
return false;
|
|
|
|
/* We only store ranges that begin at the locus and that are sufficiently
|
|
"sane". */
|
|
if (src_range.m_start != locus)
|
|
return false;
|
|
|
|
if (src_range.m_finish < src_range.m_start)
|
|
return false;
|
|
|
|
if (src_range.m_start < RESERVED_LOCATION_COUNT)
|
|
return false;
|
|
|
|
if (locus >= LINE_MAP_MAX_LOCATION_WITH_PACKED_RANGES)
|
|
return false;
|
|
|
|
/* All 3 locations must be within ordinary maps, typically, the same
|
|
ordinary map. */
|
|
location_t lowest_macro_loc = LINEMAPS_MACRO_LOWEST_LOCATION (set);
|
|
if (locus >= lowest_macro_loc)
|
|
return false;
|
|
if (src_range.m_start >= lowest_macro_loc)
|
|
return false;
|
|
if (src_range.m_finish >= lowest_macro_loc)
|
|
return false;
|
|
|
|
/* Passed all tests. */
|
|
return true;
|
|
}
|
|
|
|
/* Combine LOCUS and DATA to a combined adhoc loc. */
|
|
|
|
location_t
|
|
get_combined_adhoc_loc (line_maps *set,
|
|
location_t locus,
|
|
source_range src_range,
|
|
void *data)
|
|
{
|
|
struct location_adhoc_data lb;
|
|
struct location_adhoc_data **slot;
|
|
|
|
if (IS_ADHOC_LOC (locus))
|
|
locus = get_location_from_adhoc_loc (set, locus);
|
|
if (locus == 0 && data == NULL)
|
|
return 0;
|
|
|
|
/* Any ordinary locations ought to be "pure" at this point: no
|
|
compressed ranges. */
|
|
linemap_assert (locus < RESERVED_LOCATION_COUNT
|
|
|| locus >= LINE_MAP_MAX_LOCATION_WITH_PACKED_RANGES
|
|
|| locus >= LINEMAPS_MACRO_LOWEST_LOCATION (set)
|
|
|| pure_location_p (set, locus));
|
|
|
|
/* Consider short-range optimization. */
|
|
if (can_be_stored_compactly_p (set, locus, src_range, data))
|
|
{
|
|
/* The low bits ought to be clear. */
|
|
linemap_assert (pure_location_p (set, locus));
|
|
const line_map *map = linemap_lookup (set, locus);
|
|
const line_map_ordinary *ordmap = linemap_check_ordinary (map);
|
|
unsigned int int_diff = src_range.m_finish - src_range.m_start;
|
|
unsigned int col_diff = (int_diff >> ordmap->m_range_bits);
|
|
if (col_diff < (1U << ordmap->m_range_bits))
|
|
{
|
|
location_t packed = locus | col_diff;
|
|
set->num_optimized_ranges++;
|
|
return packed;
|
|
}
|
|
}
|
|
|
|
/* We can also compactly store locations
|
|
when locus == start == finish (and data is NULL). */
|
|
if (locus == src_range.m_start
|
|
&& locus == src_range.m_finish
|
|
&& !data)
|
|
return locus;
|
|
|
|
if (!data)
|
|
set->num_unoptimized_ranges++;
|
|
|
|
lb.locus = locus;
|
|
lb.src_range = src_range;
|
|
lb.data = data;
|
|
slot = (struct location_adhoc_data **)
|
|
htab_find_slot (set->location_adhoc_data_map.htab, &lb, INSERT);
|
|
if (*slot == NULL)
|
|
{
|
|
if (set->location_adhoc_data_map.curr_loc >=
|
|
set->location_adhoc_data_map.allocated)
|
|
{
|
|
char *orig_data = (char *) set->location_adhoc_data_map.data;
|
|
ptrdiff_t offset;
|
|
/* Cast away extern "C" from the type of xrealloc. */
|
|
line_map_realloc reallocator = (set->reallocator
|
|
? set->reallocator
|
|
: (line_map_realloc) xrealloc);
|
|
|
|
if (set->location_adhoc_data_map.allocated == 0)
|
|
set->location_adhoc_data_map.allocated = 128;
|
|
else
|
|
set->location_adhoc_data_map.allocated *= 2;
|
|
set->location_adhoc_data_map.data = (struct location_adhoc_data *)
|
|
reallocator (set->location_adhoc_data_map.data,
|
|
set->location_adhoc_data_map.allocated
|
|
* sizeof (struct location_adhoc_data));
|
|
offset = (char *) (set->location_adhoc_data_map.data) - orig_data;
|
|
if (set->location_adhoc_data_map.allocated > 128)
|
|
htab_traverse (set->location_adhoc_data_map.htab,
|
|
location_adhoc_data_update, &offset);
|
|
}
|
|
*slot = set->location_adhoc_data_map.data
|
|
+ set->location_adhoc_data_map.curr_loc;
|
|
set->location_adhoc_data_map.data[set->location_adhoc_data_map.curr_loc++]
|
|
= lb;
|
|
}
|
|
return ((*slot) - set->location_adhoc_data_map.data) | 0x80000000;
|
|
}
|
|
|
|
/* Return the data for the adhoc loc. */
|
|
|
|
void *
|
|
get_data_from_adhoc_loc (const class line_maps *set, location_t loc)
|
|
{
|
|
linemap_assert (IS_ADHOC_LOC (loc));
|
|
return set->location_adhoc_data_map.data[loc & MAX_LOCATION_T].data;
|
|
}
|
|
|
|
/* Return the location for the adhoc loc. */
|
|
|
|
location_t
|
|
get_location_from_adhoc_loc (const class line_maps *set, location_t loc)
|
|
{
|
|
linemap_assert (IS_ADHOC_LOC (loc));
|
|
return set->location_adhoc_data_map.data[loc & MAX_LOCATION_T].locus;
|
|
}
|
|
|
|
/* Return the source_range for adhoc location LOC. */
|
|
|
|
static source_range
|
|
get_range_from_adhoc_loc (const class line_maps *set, location_t loc)
|
|
{
|
|
linemap_assert (IS_ADHOC_LOC (loc));
|
|
return set->location_adhoc_data_map.data[loc & MAX_LOCATION_T].src_range;
|
|
}
|
|
|
|
/* Get the source_range of location LOC, either from the ad-hoc
|
|
lookaside table, or embedded inside LOC itself. */
|
|
|
|
source_range
|
|
get_range_from_loc (line_maps *set,
|
|
location_t loc)
|
|
{
|
|
if (IS_ADHOC_LOC (loc))
|
|
return get_range_from_adhoc_loc (set, loc);
|
|
|
|
/* For ordinary maps, extract packed range. */
|
|
if (loc >= RESERVED_LOCATION_COUNT
|
|
&& loc < LINEMAPS_MACRO_LOWEST_LOCATION (set)
|
|
&& loc <= LINE_MAP_MAX_LOCATION_WITH_PACKED_RANGES)
|
|
{
|
|
const line_map *map = linemap_lookup (set, loc);
|
|
const line_map_ordinary *ordmap = linemap_check_ordinary (map);
|
|
source_range result;
|
|
int offset = loc & ((1 << ordmap->m_range_bits) - 1);
|
|
result.m_start = loc - offset;
|
|
result.m_finish = result.m_start + (offset << ordmap->m_range_bits);
|
|
return result;
|
|
}
|
|
|
|
return source_range::from_location (loc);
|
|
}
|
|
|
|
/* Get whether location LOC is a "pure" location, or
|
|
whether it is an ad-hoc location, or embeds range information. */
|
|
|
|
bool
|
|
pure_location_p (line_maps *set, location_t loc)
|
|
{
|
|
if (IS_ADHOC_LOC (loc))
|
|
return false;
|
|
|
|
const line_map *map = linemap_lookup (set, loc);
|
|
if (map == NULL)
|
|
return true;
|
|
const line_map_ordinary *ordmap = linemap_check_ordinary (map);
|
|
|
|
if (loc & ((1U << ordmap->m_range_bits) - 1))
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
/* Given location LOC within SET, strip away any packed range information
|
|
or ad-hoc information. */
|
|
|
|
location_t
|
|
get_pure_location (line_maps *set, location_t loc)
|
|
{
|
|
if (IS_ADHOC_LOC (loc))
|
|
loc = get_location_from_adhoc_loc (set, loc);
|
|
|
|
if (loc >= LINEMAPS_MACRO_LOWEST_LOCATION (set))
|
|
return loc;
|
|
|
|
if (loc < RESERVED_LOCATION_COUNT)
|
|
return loc;
|
|
|
|
const line_map *map = linemap_lookup (set, loc);
|
|
const line_map_ordinary *ordmap = linemap_check_ordinary (map);
|
|
|
|
return loc & ~((1 << ordmap->m_range_bits) - 1);
|
|
}
|
|
|
|
/* Initialize a line map set. */
|
|
|
|
void
|
|
linemap_init (line_maps *set,
|
|
location_t builtin_location)
|
|
{
|
|
#if __GNUC__ == 4 && __GNUC_MINOR__ == 2 && !defined (__clang__)
|
|
/* PR33916, needed to fix PR82939. */
|
|
memset (set, 0, sizeof (line_maps));
|
|
#else
|
|
new (set) line_maps();
|
|
#endif
|
|
/* Set default reallocator (used for initial alloc too). */
|
|
set->reallocator = xrealloc;
|
|
set->highest_location = RESERVED_LOCATION_COUNT - 1;
|
|
set->highest_line = RESERVED_LOCATION_COUNT - 1;
|
|
set->location_adhoc_data_map.htab =
|
|
htab_create (100, location_adhoc_data_hash, location_adhoc_data_eq, NULL);
|
|
set->builtin_location = builtin_location;
|
|
}
|
|
|
|
/* Return the ordinary line map from whence MAP was included. Returns
|
|
NULL if MAP was not an include. */
|
|
|
|
const line_map_ordinary *
|
|
linemap_included_from_linemap (line_maps *set, const line_map_ordinary *map)
|
|
{
|
|
return linemap_ordinary_map_lookup (set, linemap_included_from (map));
|
|
}
|
|
|
|
/* Check for and warn about line_maps entered but not exited. */
|
|
|
|
void
|
|
linemap_check_files_exited (line_maps *set)
|
|
{
|
|
/* Depending upon whether we are handling preprocessed input or
|
|
not, this can be a user error or an ICE. */
|
|
for (const line_map_ordinary *map = LINEMAPS_LAST_ORDINARY_MAP (set);
|
|
! MAIN_FILE_P (map);
|
|
map = linemap_included_from_linemap (set, map))
|
|
fprintf (stderr, "line-map.c: file \"%s\" entered but not left\n",
|
|
ORDINARY_MAP_FILE_NAME (map));
|
|
}
|
|
|
|
/* Create a new line map in the line map set SET, and return it.
|
|
REASON is the reason of creating the map. It determines the type
|
|
of map created (ordinary or macro map). Note that ordinary maps and
|
|
macro maps are allocated in different memory location. */
|
|
|
|
static struct line_map *
|
|
new_linemap (line_maps *set, location_t start_location)
|
|
{
|
|
bool macro_p = start_location >= LINE_MAP_MAX_LOCATION;
|
|
unsigned num_maps_allocated = LINEMAPS_ALLOCATED (set, macro_p);
|
|
unsigned num_maps_used = LINEMAPS_USED (set, macro_p);
|
|
|
|
if (num_maps_used == num_maps_allocated)
|
|
{
|
|
/* We need more space! */
|
|
if (!num_maps_allocated)
|
|
num_maps_allocated = 128;
|
|
num_maps_allocated *= 2;
|
|
|
|
size_t size_of_a_map;
|
|
void *buffer;
|
|
if (macro_p)
|
|
{
|
|
size_of_a_map = sizeof (line_map_macro);
|
|
buffer = set->info_macro.maps;
|
|
}
|
|
else
|
|
{
|
|
size_of_a_map = sizeof (line_map_ordinary);
|
|
buffer = set->info_ordinary.maps;
|
|
}
|
|
|
|
/* We are going to execute some dance to try to reduce the
|
|
overhead of the memory allocator, in case we are using the
|
|
ggc-page.c one.
|
|
|
|
The actual size of memory we are going to get back from the
|
|
allocator may well be larger than what we ask for. Use this
|
|
hook to find what that size is. */
|
|
size_t alloc_size
|
|
= set->round_alloc_size (num_maps_allocated * size_of_a_map);
|
|
|
|
/* Now alloc_size contains the exact memory size we would get if
|
|
we have asked for the initial alloc_size amount of memory.
|
|
Let's get back to the number of map that amounts to. */
|
|
unsigned num_maps = alloc_size / size_of_a_map;
|
|
buffer = set->reallocator (buffer, num_maps * size_of_a_map);
|
|
memset ((char *)buffer + num_maps_used * size_of_a_map, 0,
|
|
(num_maps - num_maps_used) * size_of_a_map);
|
|
if (macro_p)
|
|
set->info_macro.maps = (line_map_macro *)buffer;
|
|
else
|
|
set->info_ordinary.maps = (line_map_ordinary *)buffer;
|
|
LINEMAPS_ALLOCATED (set, macro_p) = num_maps;
|
|
}
|
|
|
|
line_map *result = (macro_p ? (line_map *)&set->info_macro.maps[num_maps_used]
|
|
: (line_map *)&set->info_ordinary.maps[num_maps_used]);
|
|
LINEMAPS_USED (set, macro_p)++;
|
|
|
|
result->start_location = start_location;
|
|
|
|
return result;
|
|
}
|
|
|
|
/* Add a mapping of logical source line to physical source file and
|
|
line number.
|
|
|
|
The text pointed to by TO_FILE must have a lifetime
|
|
at least as long as the final call to lookup_line (). An empty
|
|
TO_FILE means standard input. If reason is LC_LEAVE, and
|
|
TO_FILE is NULL, then TO_FILE, TO_LINE and SYSP are given their
|
|
natural values considering the file we are returning to.
|
|
|
|
FROM_LINE should be monotonic increasing across calls to this
|
|
function. A call to this function can relocate the previous set of
|
|
maps, so any stored line_map pointers should not be used. */
|
|
|
|
const struct line_map *
|
|
linemap_add (line_maps *set, enum lc_reason reason,
|
|
unsigned int sysp, const char *to_file, linenum_type to_line)
|
|
{
|
|
/* Generate a start_location above the current highest_location.
|
|
If possible, make the low range bits be zero. */
|
|
location_t start_location;
|
|
if (set->highest_location < LINE_MAP_MAX_LOCATION_WITH_COLS)
|
|
{
|
|
start_location = set->highest_location + (1 << set->default_range_bits);
|
|
if (set->default_range_bits)
|
|
start_location &= ~((1 << set->default_range_bits) - 1);
|
|
linemap_assert (0 == (start_location
|
|
& ((1 << set->default_range_bits) - 1)));
|
|
}
|
|
else
|
|
start_location = set->highest_location + 1;
|
|
|
|
linemap_assert (!LINEMAPS_ORDINARY_USED (set)
|
|
|| (start_location
|
|
>= MAP_START_LOCATION (LINEMAPS_LAST_ORDINARY_MAP (set))));
|
|
|
|
/* When we enter the file for the first time reason cannot be
|
|
LC_RENAME. */
|
|
linemap_assert (!(set->depth == 0 && reason == LC_RENAME));
|
|
|
|
/* If we are leaving the main file, return a NULL map. */
|
|
if (reason == LC_LEAVE
|
|
&& MAIN_FILE_P (LINEMAPS_LAST_ORDINARY_MAP (set))
|
|
&& to_file == NULL)
|
|
{
|
|
set->depth--;
|
|
return NULL;
|
|
}
|
|
|
|
linemap_assert (reason != LC_ENTER_MACRO);
|
|
|
|
if (start_location >= LINE_MAP_MAX_LOCATION)
|
|
/* We ran out of line map space. */
|
|
start_location = 0;
|
|
|
|
line_map_ordinary *map
|
|
= linemap_check_ordinary (new_linemap (set, start_location));
|
|
map->reason = reason;
|
|
|
|
if (to_file && *to_file == '\0' && reason != LC_RENAME_VERBATIM)
|
|
to_file = "<stdin>";
|
|
|
|
if (reason == LC_RENAME_VERBATIM)
|
|
reason = LC_RENAME;
|
|
|
|
const line_map_ordinary *from = NULL;
|
|
if (reason == LC_LEAVE)
|
|
{
|
|
/* When we are just leaving an "included" file, and jump to the next
|
|
location inside the "includer" right after the #include
|
|
"included", this variable points the map in use right before the
|
|
#include "included", inside the same "includer" file. */
|
|
|
|
linemap_assert (!MAIN_FILE_P (map - 1));
|
|
/* (MAP - 1) points to the map we are leaving. The
|
|
map from which (MAP - 1) got included should be the map
|
|
that comes right before MAP in the same file. */
|
|
from = linemap_included_from_linemap (set, map - 1);
|
|
|
|
/* A TO_FILE of NULL is special - we use the natural values. */
|
|
if (to_file == NULL)
|
|
{
|
|
to_file = ORDINARY_MAP_FILE_NAME (from);
|
|
to_line = SOURCE_LINE (from, from[1].start_location);
|
|
sysp = ORDINARY_MAP_IN_SYSTEM_HEADER_P (from);
|
|
}
|
|
else
|
|
linemap_assert (filename_cmp (ORDINARY_MAP_FILE_NAME (from),
|
|
to_file) == 0);
|
|
}
|
|
|
|
map->sysp = sysp;
|
|
map->to_file = to_file;
|
|
map->to_line = to_line;
|
|
LINEMAPS_ORDINARY_CACHE (set) = LINEMAPS_ORDINARY_USED (set) - 1;
|
|
map->m_column_and_range_bits = 0;
|
|
map->m_range_bits = 0;
|
|
set->highest_location = start_location;
|
|
set->highest_line = start_location;
|
|
set->max_column_hint = 0;
|
|
|
|
/* This assertion is placed after set->highest_location has
|
|
been updated, since the latter affects
|
|
linemap_location_from_macro_expansion_p, which ultimately affects
|
|
pure_location_p. */
|
|
linemap_assert (pure_location_p (set, start_location));
|
|
|
|
if (reason == LC_ENTER)
|
|
{
|
|
if (set->depth == 0)
|
|
map->included_from = 0;
|
|
else
|
|
/* The location of the end of the just-closed map. */
|
|
map->included_from
|
|
= (((map[0].start_location - 1 - map[-1].start_location)
|
|
& ~((1 << map[-1].m_column_and_range_bits) - 1))
|
|
+ map[-1].start_location);
|
|
set->depth++;
|
|
if (set->trace_includes)
|
|
trace_include (set, map);
|
|
}
|
|
else if (reason == LC_RENAME)
|
|
map->included_from = linemap_included_from (&map[-1]);
|
|
else if (reason == LC_LEAVE)
|
|
{
|
|
set->depth--;
|
|
map->included_from = linemap_included_from (from);
|
|
}
|
|
|
|
return map;
|
|
}
|
|
|
|
/* Returns TRUE if the line table set tracks token locations across
|
|
macro expansion, FALSE otherwise. */
|
|
|
|
bool
|
|
linemap_tracks_macro_expansion_locs_p (line_maps *set)
|
|
{
|
|
return LINEMAPS_MACRO_MAPS (set) != NULL;
|
|
}
|
|
|
|
/* Create a macro map. A macro map encodes source locations of tokens
|
|
that are part of a macro replacement-list, at a macro expansion
|
|
point. See the extensive comments of struct line_map and struct
|
|
line_map_macro, in line-map.h.
|
|
|
|
This map shall be created when the macro is expanded. The map
|
|
encodes the source location of the expansion point of the macro as
|
|
well as the "original" source location of each token that is part
|
|
of the macro replacement-list. If a macro is defined but never
|
|
expanded, it has no macro map. SET is the set of maps the macro
|
|
map should be part of. MACRO_NODE is the macro which the new macro
|
|
map should encode source locations for. EXPANSION is the location
|
|
of the expansion point of MACRO. For function-like macros
|
|
invocations, it's best to make it point to the closing parenthesis
|
|
of the macro, rather than the the location of the first character
|
|
of the macro. NUM_TOKENS is the number of tokens that are part of
|
|
the replacement-list of MACRO.
|
|
|
|
Note that when we run out of the integer space available for source
|
|
locations, this function returns NULL. In that case, callers of
|
|
this function cannot encode {line,column} pairs into locations of
|
|
macro tokens anymore. */
|
|
|
|
const line_map_macro *
|
|
linemap_enter_macro (class line_maps *set, struct cpp_hashnode *macro_node,
|
|
location_t expansion, unsigned int num_tokens)
|
|
{
|
|
location_t start_location
|
|
= LINEMAPS_MACRO_LOWEST_LOCATION (set) - num_tokens;
|
|
|
|
if (start_location < LINE_MAP_MAX_LOCATION)
|
|
/* We ran out of macro map space. */
|
|
return NULL;
|
|
|
|
line_map_macro *map = linemap_check_macro (new_linemap (set, start_location));
|
|
|
|
map->macro = macro_node;
|
|
map->n_tokens = num_tokens;
|
|
map->macro_locations
|
|
= (location_t*) set->reallocator (NULL,
|
|
2 * num_tokens
|
|
* sizeof (location_t));
|
|
map->expansion = expansion;
|
|
memset (MACRO_MAP_LOCATIONS (map), 0,
|
|
2 * num_tokens * sizeof (location_t));
|
|
|
|
LINEMAPS_MACRO_CACHE (set) = LINEMAPS_MACRO_USED (set) - 1;
|
|
|
|
return map;
|
|
}
|
|
|
|
/* Create and return a virtual location for a token that is part of a
|
|
macro expansion-list at a macro expansion point. See the comment
|
|
inside struct line_map_macro to see what an expansion-list exactly
|
|
is.
|
|
|
|
A call to this function must come after a call to
|
|
linemap_enter_macro.
|
|
|
|
MAP is the map into which the source location is created. TOKEN_NO
|
|
is the index of the token in the macro replacement-list, starting
|
|
at number 0.
|
|
|
|
ORIG_LOC is the location of the token outside of this macro
|
|
expansion. If the token comes originally from the macro
|
|
definition, it is the locus in the macro definition; otherwise it
|
|
is a location in the context of the caller of this macro expansion
|
|
(which is a virtual location or a source location if the caller is
|
|
itself a macro expansion or not).
|
|
|
|
ORIG_PARM_REPLACEMENT_LOC is the location in the macro definition,
|
|
either of the token itself or of a macro parameter that it
|
|
replaces. */
|
|
|
|
location_t
|
|
linemap_add_macro_token (const line_map_macro *map,
|
|
unsigned int token_no,
|
|
location_t orig_loc,
|
|
location_t orig_parm_replacement_loc)
|
|
{
|
|
location_t result;
|
|
|
|
linemap_assert (linemap_macro_expansion_map_p (map));
|
|
linemap_assert (token_no < MACRO_MAP_NUM_MACRO_TOKENS (map));
|
|
|
|
MACRO_MAP_LOCATIONS (map)[2 * token_no] = orig_loc;
|
|
MACRO_MAP_LOCATIONS (map)[2 * token_no + 1] = orig_parm_replacement_loc;
|
|
|
|
result = MAP_START_LOCATION (map) + token_no;
|
|
return result;
|
|
}
|
|
|
|
/* Return a location_t for the start (i.e. column==0) of
|
|
(physical) line TO_LINE in the current source file (as in the
|
|
most recent linemap_add). MAX_COLUMN_HINT is the highest column
|
|
number we expect to use in this line (but it does not change
|
|
the highest_location). */
|
|
|
|
location_t
|
|
linemap_line_start (line_maps *set, linenum_type to_line,
|
|
unsigned int max_column_hint)
|
|
{
|
|
line_map_ordinary *map = LINEMAPS_LAST_ORDINARY_MAP (set);
|
|
location_t highest = set->highest_location;
|
|
location_t r;
|
|
linenum_type last_line =
|
|
SOURCE_LINE (map, set->highest_line);
|
|
int line_delta = to_line - last_line;
|
|
bool add_map = false;
|
|
linemap_assert (map->m_column_and_range_bits >= map->m_range_bits);
|
|
int effective_column_bits = map->m_column_and_range_bits - map->m_range_bits;
|
|
|
|
if (line_delta < 0
|
|
|| (line_delta > 10
|
|
&& line_delta * map->m_column_and_range_bits > 1000)
|
|
|| (max_column_hint >= (1U << effective_column_bits))
|
|
|| (max_column_hint <= 80 && effective_column_bits >= 10)
|
|
|| (highest > LINE_MAP_MAX_LOCATION_WITH_PACKED_RANGES
|
|
&& map->m_range_bits > 0)
|
|
|| (highest > LINE_MAP_MAX_LOCATION_WITH_COLS
|
|
&& (set->max_column_hint || highest >= LINE_MAP_MAX_LOCATION)))
|
|
add_map = true;
|
|
else
|
|
max_column_hint = set->max_column_hint;
|
|
if (add_map)
|
|
{
|
|
int column_bits;
|
|
int range_bits;
|
|
if (max_column_hint > LINE_MAP_MAX_COLUMN_NUMBER
|
|
|| highest > LINE_MAP_MAX_LOCATION_WITH_COLS)
|
|
{
|
|
/* If the column number is ridiculous or we've allocated a huge
|
|
number of location_ts, give up on column numbers
|
|
(and on packed ranges). */
|
|
max_column_hint = 0;
|
|
column_bits = 0;
|
|
range_bits = 0;
|
|
if (highest >= LINE_MAP_MAX_LOCATION)
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
column_bits = 7;
|
|
if (highest <= LINE_MAP_MAX_LOCATION_WITH_PACKED_RANGES)
|
|
range_bits = set->default_range_bits;
|
|
else
|
|
range_bits = 0;
|
|
while (max_column_hint >= (1U << column_bits))
|
|
column_bits++;
|
|
max_column_hint = 1U << column_bits;
|
|
column_bits += range_bits;
|
|
}
|
|
/* Allocate the new line_map. However, if the current map only has a
|
|
single line we can sometimes just increase its column_bits instead. */
|
|
if (line_delta < 0
|
|
|| last_line != ORDINARY_MAP_STARTING_LINE_NUMBER (map)
|
|
|| SOURCE_COLUMN (map, highest) >= (1U << (column_bits - range_bits))
|
|
|| ( /* We can't reuse the map if the line offset is sufficiently
|
|
large to cause overflow when computing location_t values. */
|
|
(to_line - ORDINARY_MAP_STARTING_LINE_NUMBER (map))
|
|
>= (((uint64_t) 1)
|
|
<< (CHAR_BIT * sizeof (linenum_type) - column_bits)))
|
|
|| range_bits < map->m_range_bits)
|
|
map = linemap_check_ordinary
|
|
(const_cast <line_map *>
|
|
(linemap_add (set, LC_RENAME,
|
|
ORDINARY_MAP_IN_SYSTEM_HEADER_P (map),
|
|
ORDINARY_MAP_FILE_NAME (map),
|
|
to_line)));
|
|
map->m_column_and_range_bits = column_bits;
|
|
map->m_range_bits = range_bits;
|
|
r = (MAP_START_LOCATION (map)
|
|
+ ((to_line - ORDINARY_MAP_STARTING_LINE_NUMBER (map))
|
|
<< column_bits));
|
|
}
|
|
else
|
|
r = set->highest_line + (line_delta << map->m_column_and_range_bits);
|
|
|
|
/* Locations of ordinary tokens are always lower than locations of
|
|
macro tokens. */
|
|
if (r >= LINE_MAP_MAX_LOCATION)
|
|
return 0;
|
|
|
|
set->highest_line = r;
|
|
if (r > set->highest_location)
|
|
set->highest_location = r;
|
|
set->max_column_hint = max_column_hint;
|
|
|
|
/* At this point, we expect one of:
|
|
(a) the normal case: a "pure" location with 0 range bits, or
|
|
(b) we've gone past LINE_MAP_MAX_LOCATION_WITH_COLS so can't track
|
|
columns anymore (or ranges), or
|
|
(c) we're in a region with a column hint exceeding
|
|
LINE_MAP_MAX_COLUMN_NUMBER, so column-tracking is off,
|
|
with column_bits == 0. */
|
|
linemap_assert (pure_location_p (set, r)
|
|
|| r >= LINE_MAP_MAX_LOCATION_WITH_COLS
|
|
|| map->m_column_and_range_bits == 0);
|
|
linemap_assert (SOURCE_LINE (map, r) == to_line);
|
|
return r;
|
|
}
|
|
|
|
/* Encode and return a location_t from a column number. The
|
|
source line considered is the last source line used to call
|
|
linemap_line_start, i.e, the last source line which a location was
|
|
encoded from. */
|
|
|
|
location_t
|
|
linemap_position_for_column (line_maps *set, unsigned int to_column)
|
|
{
|
|
location_t r = set->highest_line;
|
|
|
|
linemap_assert
|
|
(!linemap_macro_expansion_map_p (LINEMAPS_LAST_ORDINARY_MAP (set)));
|
|
|
|
if (to_column >= set->max_column_hint)
|
|
{
|
|
if (r > LINE_MAP_MAX_LOCATION_WITH_COLS
|
|
|| to_column > LINE_MAP_MAX_COLUMN_NUMBER)
|
|
{
|
|
/* Running low on location_ts - disable column numbers. */
|
|
return r;
|
|
}
|
|
else
|
|
{
|
|
/* Otherwise, attempt to start a new line that can hold TO_COLUMN,
|
|
with some space to spare. This may or may not lead to a new
|
|
linemap being created. */
|
|
line_map_ordinary *map = LINEMAPS_LAST_ORDINARY_MAP (set);
|
|
r = linemap_line_start (set, SOURCE_LINE (map, r), to_column + 50);
|
|
map = LINEMAPS_LAST_ORDINARY_MAP (set);
|
|
if (map->m_column_and_range_bits == 0)
|
|
{
|
|
/* ...then the linemap has column-tracking disabled,
|
|
presumably due to exceeding either
|
|
LINE_MAP_MAX_LOCATION_WITH_COLS (overall) or
|
|
LINE_MAP_MAX_COLUMN_NUMBER (within this line).
|
|
Return the start of the linemap, which encodes column 0, for
|
|
the whole line. */
|
|
return r;
|
|
}
|
|
}
|
|
}
|
|
line_map_ordinary *map = LINEMAPS_LAST_ORDINARY_MAP (set);
|
|
r = r + (to_column << map->m_range_bits);
|
|
if (r >= set->highest_location)
|
|
set->highest_location = r;
|
|
return r;
|
|
}
|
|
|
|
/* Encode and return a source location from a given line and
|
|
column. */
|
|
|
|
location_t
|
|
linemap_position_for_line_and_column (line_maps *set,
|
|
const line_map_ordinary *ord_map,
|
|
linenum_type line,
|
|
unsigned column)
|
|
{
|
|
linemap_assert (ORDINARY_MAP_STARTING_LINE_NUMBER (ord_map) <= line);
|
|
|
|
location_t r = MAP_START_LOCATION (ord_map);
|
|
r += ((line - ORDINARY_MAP_STARTING_LINE_NUMBER (ord_map))
|
|
<< ord_map->m_column_and_range_bits);
|
|
if (r <= LINE_MAP_MAX_LOCATION_WITH_COLS)
|
|
r += ((column & ((1 << ord_map->m_column_and_range_bits) - 1))
|
|
<< ord_map->m_range_bits);
|
|
location_t upper_limit = LINEMAPS_MACRO_LOWEST_LOCATION (set);
|
|
if (r >= upper_limit)
|
|
r = upper_limit - 1;
|
|
if (r > set->highest_location)
|
|
set->highest_location = r;
|
|
return r;
|
|
}
|
|
|
|
/* Encode and return a location_t starting from location LOC and
|
|
shifting it by COLUMN_OFFSET columns. This function does not support
|
|
virtual locations. */
|
|
|
|
location_t
|
|
linemap_position_for_loc_and_offset (line_maps *set,
|
|
location_t loc,
|
|
unsigned int column_offset)
|
|
{
|
|
const line_map_ordinary * map = NULL;
|
|
|
|
if (IS_ADHOC_LOC (loc))
|
|
loc = get_location_from_adhoc_loc (set, loc);
|
|
|
|
/* This function does not support virtual locations yet. */
|
|
if (linemap_location_from_macro_expansion_p (set, loc))
|
|
return loc;
|
|
|
|
if (column_offset == 0
|
|
/* Adding an offset to a reserved location (like
|
|
UNKNOWN_LOCATION for the C/C++ FEs) does not really make
|
|
sense. So let's leave the location intact in that case. */
|
|
|| loc < RESERVED_LOCATION_COUNT)
|
|
return loc;
|
|
|
|
/* We find the real location and shift it. */
|
|
loc = linemap_resolve_location (set, loc, LRK_SPELLING_LOCATION, &map);
|
|
/* The new location (loc + offset) should be higher than the first
|
|
location encoded by MAP. This can fail if the line information
|
|
is messed up because of line directives (see PR66415). */
|
|
if (MAP_START_LOCATION (map) >= loc + (column_offset << map->m_range_bits))
|
|
return loc;
|
|
|
|
linenum_type line = SOURCE_LINE (map, loc);
|
|
unsigned int column = SOURCE_COLUMN (map, loc);
|
|
|
|
/* If MAP is not the last line map of its set, then the new location
|
|
(loc + offset) should be less than the first location encoded by
|
|
the next line map of the set. Otherwise, we try to encode the
|
|
location in the next map. */
|
|
while (map != LINEMAPS_LAST_ORDINARY_MAP (set)
|
|
&& (loc + (column_offset << map->m_range_bits)
|
|
>= MAP_START_LOCATION (&map[1])))
|
|
{
|
|
map = &map[1];
|
|
/* If the next map starts in a higher line, we cannot encode the
|
|
location there. */
|
|
if (line < ORDINARY_MAP_STARTING_LINE_NUMBER (map))
|
|
return loc;
|
|
}
|
|
|
|
column += column_offset;
|
|
|
|
/* Bail out if the column is not representable within the existing
|
|
linemap. */
|
|
if (column >= (1u << (map->m_column_and_range_bits - map->m_range_bits)))
|
|
return loc;
|
|
|
|
location_t r =
|
|
linemap_position_for_line_and_column (set, map, line, column);
|
|
if (linemap_assert_fails (r <= set->highest_location)
|
|
|| linemap_assert_fails (map == linemap_lookup (set, r)))
|
|
return loc;
|
|
|
|
return r;
|
|
}
|
|
|
|
/* Given a virtual source location yielded by a map (either an
|
|
ordinary or a macro map), returns that map. */
|
|
|
|
const struct line_map*
|
|
linemap_lookup (line_maps *set, location_t line)
|
|
{
|
|
if (IS_ADHOC_LOC (line))
|
|
line = get_location_from_adhoc_loc (set, line);
|
|
if (linemap_location_from_macro_expansion_p (set, line))
|
|
return linemap_macro_map_lookup (set, line);
|
|
return linemap_ordinary_map_lookup (set, line);
|
|
}
|
|
|
|
/* Given a source location yielded by an ordinary map, returns that
|
|
map. Since the set is built chronologically, the logical lines are
|
|
monotonic increasing, and so the list is sorted and we can use a
|
|
binary search. */
|
|
|
|
static const line_map_ordinary *
|
|
linemap_ordinary_map_lookup (line_maps *set, location_t line)
|
|
{
|
|
unsigned int md, mn, mx;
|
|
const line_map_ordinary *cached, *result;
|
|
|
|
if (IS_ADHOC_LOC (line))
|
|
line = get_location_from_adhoc_loc (set, line);
|
|
|
|
if (set == NULL || line < RESERVED_LOCATION_COUNT)
|
|
return NULL;
|
|
|
|
mn = LINEMAPS_ORDINARY_CACHE (set);
|
|
mx = LINEMAPS_ORDINARY_USED (set);
|
|
|
|
cached = LINEMAPS_ORDINARY_MAP_AT (set, mn);
|
|
/* We should get a segfault if no line_maps have been added yet. */
|
|
if (line >= MAP_START_LOCATION (cached))
|
|
{
|
|
if (mn + 1 == mx || line < MAP_START_LOCATION (&cached[1]))
|
|
return cached;
|
|
}
|
|
else
|
|
{
|
|
mx = mn;
|
|
mn = 0;
|
|
}
|
|
|
|
while (mx - mn > 1)
|
|
{
|
|
md = (mn + mx) / 2;
|
|
if (MAP_START_LOCATION (LINEMAPS_ORDINARY_MAP_AT (set, md)) > line)
|
|
mx = md;
|
|
else
|
|
mn = md;
|
|
}
|
|
|
|
LINEMAPS_ORDINARY_CACHE (set) = mn;
|
|
result = LINEMAPS_ORDINARY_MAP_AT (set, mn);
|
|
linemap_assert (line >= MAP_START_LOCATION (result));
|
|
return result;
|
|
}
|
|
|
|
/* Given a source location yielded by a macro map, returns that map.
|
|
Since the set is built chronologically, the logical lines are
|
|
monotonic decreasing, and so the list is sorted and we can use a
|
|
binary search. */
|
|
|
|
static const line_map_macro *
|
|
linemap_macro_map_lookup (line_maps *set, location_t line)
|
|
{
|
|
unsigned int md, mn, mx;
|
|
const struct line_map_macro *cached, *result;
|
|
|
|
if (IS_ADHOC_LOC (line))
|
|
line = get_location_from_adhoc_loc (set, line);
|
|
|
|
linemap_assert (line >= LINEMAPS_MACRO_LOWEST_LOCATION (set));
|
|
|
|
if (set == NULL)
|
|
return NULL;
|
|
|
|
mn = LINEMAPS_MACRO_CACHE (set);
|
|
mx = LINEMAPS_MACRO_USED (set);
|
|
cached = LINEMAPS_MACRO_MAP_AT (set, mn);
|
|
|
|
if (line >= MAP_START_LOCATION (cached))
|
|
{
|
|
if (mn == 0 || line < MAP_START_LOCATION (&cached[-1]))
|
|
return cached;
|
|
mx = mn - 1;
|
|
mn = 0;
|
|
}
|
|
|
|
while (mn < mx)
|
|
{
|
|
md = (mx + mn) / 2;
|
|
if (MAP_START_LOCATION (LINEMAPS_MACRO_MAP_AT (set, md)) > line)
|
|
mn = md + 1;
|
|
else
|
|
mx = md;
|
|
}
|
|
|
|
LINEMAPS_MACRO_CACHE (set) = mx;
|
|
result = LINEMAPS_MACRO_MAP_AT (set, LINEMAPS_MACRO_CACHE (set));
|
|
linemap_assert (MAP_START_LOCATION (result) <= line);
|
|
|
|
return result;
|
|
}
|
|
|
|
/* Return TRUE if MAP encodes locations coming from a macro
|
|
replacement-list at macro expansion point. */
|
|
|
|
bool
|
|
linemap_macro_expansion_map_p (const struct line_map *map)
|
|
{
|
|
return map && !MAP_ORDINARY_P (map);
|
|
}
|
|
|
|
/* If LOCATION is the locus of a token in a replacement-list of a
|
|
macro expansion return the location of the macro expansion point.
|
|
|
|
Read the comments of struct line_map and struct line_map_macro in
|
|
line-map.h to understand what a macro expansion point is. */
|
|
|
|
static location_t
|
|
linemap_macro_map_loc_to_exp_point (const line_map_macro *map,
|
|
location_t location ATTRIBUTE_UNUSED)
|
|
{
|
|
linemap_assert (linemap_macro_expansion_map_p (map)
|
|
&& location >= MAP_START_LOCATION (map));
|
|
|
|
/* Make sure LOCATION is correct. */
|
|
linemap_assert ((location - MAP_START_LOCATION (map))
|
|
< MACRO_MAP_NUM_MACRO_TOKENS (map));
|
|
|
|
return MACRO_MAP_EXPANSION_POINT_LOCATION (map);
|
|
}
|
|
|
|
/* LOCATION is the source location of a token that belongs to a macro
|
|
replacement-list as part of the macro expansion denoted by MAP.
|
|
|
|
Return the location of the token at the definition point of the
|
|
macro. */
|
|
|
|
static location_t
|
|
linemap_macro_map_loc_to_def_point (const line_map_macro *map,
|
|
location_t location)
|
|
{
|
|
unsigned token_no;
|
|
|
|
linemap_assert (linemap_macro_expansion_map_p (map)
|
|
&& location >= MAP_START_LOCATION (map));
|
|
linemap_assert (location >= RESERVED_LOCATION_COUNT);
|
|
|
|
token_no = location - MAP_START_LOCATION (map);
|
|
linemap_assert (token_no < MACRO_MAP_NUM_MACRO_TOKENS (map));
|
|
|
|
location = MACRO_MAP_LOCATIONS (map)[2 * token_no + 1];
|
|
|
|
return location;
|
|
}
|
|
|
|
/* If LOCATION is the locus of a token that is an argument of a
|
|
function-like macro M and appears in the expansion of M, return the
|
|
locus of that argument in the context of the caller of M.
|
|
|
|
In other words, this returns the xI location presented in the
|
|
comments of line_map_macro above. */
|
|
location_t
|
|
linemap_macro_map_loc_unwind_toward_spelling (line_maps *set,
|
|
const line_map_macro* map,
|
|
location_t location)
|
|
{
|
|
unsigned token_no;
|
|
|
|
if (IS_ADHOC_LOC (location))
|
|
location = get_location_from_adhoc_loc (set, location);
|
|
|
|
linemap_assert (linemap_macro_expansion_map_p (map)
|
|
&& location >= MAP_START_LOCATION (map));
|
|
linemap_assert (location >= RESERVED_LOCATION_COUNT);
|
|
linemap_assert (!IS_ADHOC_LOC (location));
|
|
|
|
token_no = location - MAP_START_LOCATION (map);
|
|
linemap_assert (token_no < MACRO_MAP_NUM_MACRO_TOKENS (map));
|
|
|
|
location = MACRO_MAP_LOCATIONS (map)[2 * token_no];
|
|
|
|
return location;
|
|
}
|
|
|
|
/* Return the source line number corresponding to source location
|
|
LOCATION. SET is the line map set LOCATION comes from. If
|
|
LOCATION is the source location of token that is part of the
|
|
replacement-list of a macro expansion return the line number of the
|
|
macro expansion point. */
|
|
|
|
int
|
|
linemap_get_expansion_line (line_maps *set,
|
|
location_t location)
|
|
{
|
|
const line_map_ordinary *map = NULL;
|
|
|
|
if (IS_ADHOC_LOC (location))
|
|
location = get_location_from_adhoc_loc (set, location);
|
|
|
|
if (location < RESERVED_LOCATION_COUNT)
|
|
return 0;
|
|
|
|
location =
|
|
linemap_macro_loc_to_exp_point (set, location, &map);
|
|
|
|
return SOURCE_LINE (map, location);
|
|
}
|
|
|
|
/* Return the path of the file corresponding to source code location
|
|
LOCATION.
|
|
|
|
If LOCATION is the source location of token that is part of the
|
|
replacement-list of a macro expansion return the file path of the
|
|
macro expansion point.
|
|
|
|
SET is the line map set LOCATION comes from. */
|
|
|
|
const char*
|
|
linemap_get_expansion_filename (line_maps *set,
|
|
location_t location)
|
|
{
|
|
const struct line_map_ordinary *map = NULL;
|
|
|
|
if (IS_ADHOC_LOC (location))
|
|
location = get_location_from_adhoc_loc (set, location);
|
|
|
|
if (location < RESERVED_LOCATION_COUNT)
|
|
return NULL;
|
|
|
|
linemap_macro_loc_to_exp_point (set, location, &map);
|
|
|
|
return LINEMAP_FILE (map);
|
|
}
|
|
|
|
/* Return the name of the macro associated to MACRO_MAP. */
|
|
|
|
const char*
|
|
linemap_map_get_macro_name (const line_map_macro *macro_map)
|
|
{
|
|
linemap_assert (macro_map && linemap_macro_expansion_map_p (macro_map));
|
|
return (const char*) NODE_NAME (MACRO_MAP_MACRO (macro_map));
|
|
}
|
|
|
|
/* Return a positive value if LOCATION is the locus of a token that is
|
|
located in a system header, O otherwise. It returns 1 if LOCATION
|
|
is the locus of a token that is located in a system header, and 2
|
|
if LOCATION is the locus of a token located in a C system header
|
|
that therefore needs to be extern "C" protected in C++.
|
|
|
|
Note that this function returns 1 if LOCATION belongs to a token
|
|
that is part of a macro replacement-list defined in a system
|
|
header, but expanded in a non-system file. */
|
|
|
|
int
|
|
linemap_location_in_system_header_p (line_maps *set,
|
|
location_t location)
|
|
{
|
|
const struct line_map *map = NULL;
|
|
|
|
if (IS_ADHOC_LOC (location))
|
|
location = get_location_from_adhoc_loc (set, location);
|
|
|
|
if (location < RESERVED_LOCATION_COUNT)
|
|
return false;
|
|
|
|
/* Let's look at where the token for LOCATION comes from. */
|
|
while (true)
|
|
{
|
|
map = linemap_lookup (set, location);
|
|
if (map != NULL)
|
|
{
|
|
if (!linemap_macro_expansion_map_p (map))
|
|
/* It's a normal token. */
|
|
return LINEMAP_SYSP (linemap_check_ordinary (map));
|
|
else
|
|
{
|
|
const line_map_macro *macro_map = linemap_check_macro (map);
|
|
|
|
/* It's a token resulting from a macro expansion. */
|
|
location_t loc =
|
|
linemap_macro_map_loc_unwind_toward_spelling (set, macro_map, location);
|
|
if (loc < RESERVED_LOCATION_COUNT)
|
|
/* This token might come from a built-in macro. Let's
|
|
look at where that macro got expanded. */
|
|
location = linemap_macro_map_loc_to_exp_point (macro_map, location);
|
|
else
|
|
location = loc;
|
|
}
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/* Return TRUE if LOCATION is a source code location of a token that is part of
|
|
a macro expansion, FALSE otherwise. */
|
|
|
|
bool
|
|
linemap_location_from_macro_expansion_p (const class line_maps *set,
|
|
location_t location)
|
|
{
|
|
if (IS_ADHOC_LOC (location))
|
|
location = get_location_from_adhoc_loc (set, location);
|
|
|
|
return IS_MACRO_LOC (location);
|
|
}
|
|
|
|
/* Given two virtual locations *LOC0 and *LOC1, return the first
|
|
common macro map in their macro expansion histories. Return NULL
|
|
if no common macro was found. *LOC0 (resp. *LOC1) is set to the
|
|
virtual location of the token inside the resulting macro. */
|
|
|
|
static const struct line_map*
|
|
first_map_in_common_1 (line_maps *set,
|
|
location_t *loc0,
|
|
location_t *loc1)
|
|
{
|
|
location_t l0 = *loc0, l1 = *loc1;
|
|
const struct line_map *map0 = linemap_lookup (set, l0);
|
|
if (IS_ADHOC_LOC (l0))
|
|
l0 = get_location_from_adhoc_loc (set, l0);
|
|
|
|
const struct line_map *map1 = linemap_lookup (set, l1);
|
|
if (IS_ADHOC_LOC (l1))
|
|
l1 = get_location_from_adhoc_loc (set, l1);
|
|
|
|
while (linemap_macro_expansion_map_p (map0)
|
|
&& linemap_macro_expansion_map_p (map1)
|
|
&& (map0 != map1))
|
|
{
|
|
if (MAP_START_LOCATION (map0) < MAP_START_LOCATION (map1))
|
|
{
|
|
l0 = linemap_macro_map_loc_to_exp_point (linemap_check_macro (map0),
|
|
l0);
|
|
map0 = linemap_lookup (set, l0);
|
|
}
|
|
else
|
|
{
|
|
l1 = linemap_macro_map_loc_to_exp_point (linemap_check_macro (map1),
|
|
l1);
|
|
map1 = linemap_lookup (set, l1);
|
|
}
|
|
}
|
|
|
|
if (map0 == map1)
|
|
{
|
|
*loc0 = l0;
|
|
*loc1 = l1;
|
|
return map0;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/* Given two virtual locations LOC0 and LOC1, return the first common
|
|
macro map in their macro expansion histories. Return NULL if no
|
|
common macro was found. *RES_LOC0 (resp. *RES_LOC1) is set to the
|
|
virtual location of the token inside the resulting macro, upon
|
|
return of a non-NULL result. */
|
|
|
|
static const struct line_map*
|
|
first_map_in_common (line_maps *set,
|
|
location_t loc0,
|
|
location_t loc1,
|
|
location_t *res_loc0,
|
|
location_t *res_loc1)
|
|
{
|
|
*res_loc0 = loc0;
|
|
*res_loc1 = loc1;
|
|
|
|
return first_map_in_common_1 (set, res_loc0, res_loc1);
|
|
}
|
|
|
|
/* Return a positive value if PRE denotes the location of a token that
|
|
comes before the token of POST, 0 if PRE denotes the location of
|
|
the same token as the token for POST, and a negative value
|
|
otherwise. */
|
|
|
|
int
|
|
linemap_compare_locations (line_maps *set,
|
|
location_t pre,
|
|
location_t post)
|
|
{
|
|
bool pre_virtual_p, post_virtual_p;
|
|
location_t l0 = pre, l1 = post;
|
|
|
|
if (IS_ADHOC_LOC (l0))
|
|
l0 = get_location_from_adhoc_loc (set, l0);
|
|
if (IS_ADHOC_LOC (l1))
|
|
l1 = get_location_from_adhoc_loc (set, l1);
|
|
|
|
if (l0 == l1)
|
|
return 0;
|
|
|
|
if ((pre_virtual_p = linemap_location_from_macro_expansion_p (set, l0)))
|
|
l0 = linemap_resolve_location (set, l0,
|
|
LRK_MACRO_EXPANSION_POINT,
|
|
NULL);
|
|
|
|
if ((post_virtual_p = linemap_location_from_macro_expansion_p (set, l1)))
|
|
l1 = linemap_resolve_location (set, l1,
|
|
LRK_MACRO_EXPANSION_POINT,
|
|
NULL);
|
|
|
|
if (l0 == l1
|
|
&& pre_virtual_p
|
|
&& post_virtual_p)
|
|
{
|
|
/* So pre and post represent two tokens that are present in a
|
|
same macro expansion. Let's see if the token for pre was
|
|
before the token for post in that expansion. */
|
|
unsigned i0, i1;
|
|
const struct line_map *map =
|
|
first_map_in_common (set, pre, post, &l0, &l1);
|
|
|
|
if (map == NULL)
|
|
/* This should not be possible. */
|
|
abort ();
|
|
|
|
i0 = l0 - MAP_START_LOCATION (map);
|
|
i1 = l1 - MAP_START_LOCATION (map);
|
|
return i1 - i0;
|
|
}
|
|
|
|
if (IS_ADHOC_LOC (l0))
|
|
l0 = get_location_from_adhoc_loc (set, l0);
|
|
if (IS_ADHOC_LOC (l1))
|
|
l1 = get_location_from_adhoc_loc (set, l1);
|
|
|
|
return l1 - l0;
|
|
}
|
|
|
|
/* Print an include trace, for e.g. the -H option of the preprocessor. */
|
|
|
|
static void
|
|
trace_include (const class line_maps *set, const line_map_ordinary *map)
|
|
{
|
|
unsigned int i = set->depth;
|
|
|
|
while (--i)
|
|
putc ('.', stderr);
|
|
|
|
fprintf (stderr, " %s\n", ORDINARY_MAP_FILE_NAME (map));
|
|
}
|
|
|
|
/* Return the spelling location of the token wherever it comes from,
|
|
whether part of a macro definition or not.
|
|
|
|
This is a subroutine for linemap_resolve_location. */
|
|
|
|
static location_t
|
|
linemap_macro_loc_to_spelling_point (line_maps *set,
|
|
location_t location,
|
|
const line_map_ordinary **original_map)
|
|
{
|
|
linemap_assert (set && location >= RESERVED_LOCATION_COUNT);
|
|
|
|
while (true)
|
|
{
|
|
const struct line_map *map = linemap_lookup (set, location);
|
|
if (!map || MAP_ORDINARY_P (map))
|
|
{
|
|
if (original_map)
|
|
*original_map = (const line_map_ordinary *)map;
|
|
break;
|
|
}
|
|
|
|
location = linemap_macro_map_loc_unwind_toward_spelling
|
|
(set, linemap_check_macro (map), location);
|
|
}
|
|
|
|
return location;
|
|
}
|
|
|
|
/* If LOCATION is the source location of a token that belongs to a
|
|
macro replacement-list -- as part of a macro expansion -- then
|
|
return the location of the token at the definition point of the
|
|
macro. Otherwise, return LOCATION. SET is the set of maps
|
|
location come from. ORIGINAL_MAP is an output parm. If non NULL,
|
|
the function sets *ORIGINAL_MAP to the ordinary (non-macro) map the
|
|
returned location comes from.
|
|
|
|
This is a subroutine of linemap_resolve_location. */
|
|
|
|
static location_t
|
|
linemap_macro_loc_to_def_point (line_maps *set,
|
|
location_t location,
|
|
const line_map_ordinary **original_map)
|
|
{
|
|
linemap_assert (set && location >= RESERVED_LOCATION_COUNT);
|
|
|
|
for (;;)
|
|
{
|
|
location_t caret_loc = location;
|
|
if (IS_ADHOC_LOC (caret_loc))
|
|
caret_loc = get_location_from_adhoc_loc (set, caret_loc);
|
|
|
|
const line_map *map = linemap_lookup (set, caret_loc);
|
|
if (!map || MAP_ORDINARY_P (map))
|
|
{
|
|
if (original_map)
|
|
*original_map = (const line_map_ordinary *)map;
|
|
break;
|
|
}
|
|
|
|
location = linemap_macro_map_loc_to_def_point
|
|
(linemap_check_macro (map), caret_loc);
|
|
}
|
|
|
|
return location;
|
|
}
|
|
|
|
/* If LOCATION is the source location of a token that belongs to a
|
|
macro replacement-list -- at a macro expansion point -- then return
|
|
the location of the topmost expansion point of the macro. We say
|
|
topmost because if we are in the context of a nested macro
|
|
expansion, the function returns the source location of the first
|
|
macro expansion that triggered the nested expansions.
|
|
|
|
Otherwise, return LOCATION. SET is the set of maps location come
|
|
from. ORIGINAL_MAP is an output parm. If non NULL, the function
|
|
sets *ORIGINAL_MAP to the ordinary (non-macro) map the returned
|
|
location comes from.
|
|
|
|
This is a subroutine of linemap_resolve_location. */
|
|
|
|
static location_t
|
|
linemap_macro_loc_to_exp_point (line_maps *set,
|
|
location_t location,
|
|
const line_map_ordinary **original_map)
|
|
{
|
|
struct line_map *map;
|
|
|
|
if (IS_ADHOC_LOC (location))
|
|
location = get_location_from_adhoc_loc (set, location);
|
|
|
|
linemap_assert (set && location >= RESERVED_LOCATION_COUNT);
|
|
|
|
while (true)
|
|
{
|
|
map = const_cast <line_map *> (linemap_lookup (set, location));
|
|
if (!linemap_macro_expansion_map_p (map))
|
|
break;
|
|
location = linemap_macro_map_loc_to_exp_point (linemap_check_macro (map),
|
|
location);
|
|
}
|
|
|
|
if (original_map)
|
|
*original_map = linemap_check_ordinary (map);
|
|
return location;
|
|
}
|
|
|
|
/* Resolve a virtual location into either a spelling location, an
|
|
expansion point location or a token argument replacement point
|
|
location. Return the map that encodes the virtual location as well
|
|
as the resolved location.
|
|
|
|
If LOC is *NOT* the location of a token resulting from the
|
|
expansion of a macro, then the parameter LRK (which stands for
|
|
Location Resolution Kind) is ignored and the resulting location
|
|
just equals the one given in argument.
|
|
|
|
Now if LOC *IS* the location of a token resulting from the
|
|
expansion of a macro, this is what happens.
|
|
|
|
* If LRK is set to LRK_MACRO_EXPANSION_POINT
|
|
-------------------------------
|
|
|
|
The virtual location is resolved to the first macro expansion point
|
|
that led to this macro expansion.
|
|
|
|
* If LRK is set to LRK_SPELLING_LOCATION
|
|
-------------------------------------
|
|
|
|
The virtual location is resolved to the locus where the token has
|
|
been spelled in the source. This can follow through all the macro
|
|
expansions that led to the token.
|
|
|
|
* If LRK is set to LRK_MACRO_DEFINITION_LOCATION
|
|
--------------------------------------
|
|
|
|
The virtual location is resolved to the locus of the token in the
|
|
context of the macro definition.
|
|
|
|
If LOC is the locus of a token that is an argument of a
|
|
function-like macro [replacing a parameter in the replacement list
|
|
of the macro] the virtual location is resolved to the locus of the
|
|
parameter that is replaced, in the context of the definition of the
|
|
macro.
|
|
|
|
If LOC is the locus of a token that is not an argument of a
|
|
function-like macro, then the function behaves as if LRK was set to
|
|
LRK_SPELLING_LOCATION.
|
|
|
|
If MAP is not NULL, *MAP is set to the map encoding the
|
|
returned location. Note that if the returned location wasn't originally
|
|
encoded by a map, then *MAP is set to NULL. This can happen if LOC
|
|
resolves to a location reserved for the client code, like
|
|
UNKNOWN_LOCATION or BUILTINS_LOCATION in GCC. */
|
|
|
|
location_t
|
|
linemap_resolve_location (line_maps *set,
|
|
location_t loc,
|
|
enum location_resolution_kind lrk,
|
|
const line_map_ordinary **map)
|
|
{
|
|
location_t locus = loc;
|
|
if (IS_ADHOC_LOC (loc))
|
|
locus = get_location_from_adhoc_loc (set, loc);
|
|
|
|
if (locus < RESERVED_LOCATION_COUNT)
|
|
{
|
|
/* A reserved location wasn't encoded in a map. Let's return a
|
|
NULL map here, just like what linemap_ordinary_map_lookup
|
|
does. */
|
|
if (map)
|
|
*map = NULL;
|
|
return loc;
|
|
}
|
|
|
|
switch (lrk)
|
|
{
|
|
case LRK_MACRO_EXPANSION_POINT:
|
|
loc = linemap_macro_loc_to_exp_point (set, loc, map);
|
|
break;
|
|
case LRK_SPELLING_LOCATION:
|
|
loc = linemap_macro_loc_to_spelling_point (set, loc, map);
|
|
break;
|
|
case LRK_MACRO_DEFINITION_LOCATION:
|
|
loc = linemap_macro_loc_to_def_point (set, loc, map);
|
|
break;
|
|
default:
|
|
abort ();
|
|
}
|
|
return loc;
|
|
}
|
|
|
|
/* TRUE if LOCATION is a source code location of a token that is part of the
|
|
definition of a macro, FALSE otherwise. */
|
|
|
|
bool
|
|
linemap_location_from_macro_definition_p (line_maps *set,
|
|
location_t loc)
|
|
{
|
|
if (IS_ADHOC_LOC (loc))
|
|
loc = get_location_from_adhoc_loc (set, loc);
|
|
|
|
if (!linemap_location_from_macro_expansion_p (set, loc))
|
|
return false;
|
|
|
|
while (true)
|
|
{
|
|
const struct line_map_macro *map
|
|
= linemap_check_macro (linemap_lookup (set, loc));
|
|
|
|
location_t s_loc
|
|
= linemap_macro_map_loc_unwind_toward_spelling (set, map, loc);
|
|
if (linemap_location_from_macro_expansion_p (set, s_loc))
|
|
loc = s_loc;
|
|
else
|
|
{
|
|
location_t def_loc
|
|
= linemap_macro_map_loc_to_def_point (map, loc);
|
|
return s_loc == def_loc;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
Suppose that LOC is the virtual location of a token T coming from
|
|
the expansion of a macro M. This function then steps up to get the
|
|
location L of the point where M got expanded. If L is a spelling
|
|
location inside a macro expansion M', then this function returns
|
|
the locus of the point where M' was expanded. Said otherwise, this
|
|
function returns the location of T in the context that triggered
|
|
the expansion of M.
|
|
|
|
*LOC_MAP must be set to the map of LOC. This function then sets it
|
|
to the map of the returned location. */
|
|
|
|
location_t
|
|
linemap_unwind_toward_expansion (line_maps *set,
|
|
location_t loc,
|
|
const struct line_map **map)
|
|
{
|
|
location_t resolved_location;
|
|
const line_map_macro *macro_map = linemap_check_macro (*map);
|
|
const struct line_map *resolved_map;
|
|
|
|
if (IS_ADHOC_LOC (loc))
|
|
loc = get_location_from_adhoc_loc (set, loc);
|
|
|
|
resolved_location =
|
|
linemap_macro_map_loc_unwind_toward_spelling (set, macro_map, loc);
|
|
resolved_map = linemap_lookup (set, resolved_location);
|
|
|
|
if (!linemap_macro_expansion_map_p (resolved_map))
|
|
{
|
|
resolved_location = linemap_macro_map_loc_to_exp_point (macro_map, loc);
|
|
resolved_map = linemap_lookup (set, resolved_location);
|
|
}
|
|
|
|
*map = resolved_map;
|
|
return resolved_location;
|
|
}
|
|
|
|
/* If LOC is the virtual location of a token coming from the expansion
|
|
of a macro M and if its spelling location is reserved (e.g, a
|
|
location for a built-in token), then this function unwinds (using
|
|
linemap_unwind_toward_expansion) the location until a location that
|
|
is not reserved and is not in a system header is reached. In other
|
|
words, this unwinds the reserved location until a location that is
|
|
in real source code is reached.
|
|
|
|
Otherwise, if the spelling location for LOC is not reserved or if
|
|
LOC doesn't come from the expansion of a macro, the function
|
|
returns LOC as is and *MAP is not touched.
|
|
|
|
*MAP is set to the map of the returned location if the later is
|
|
different from LOC. */
|
|
location_t
|
|
linemap_unwind_to_first_non_reserved_loc (line_maps *set,
|
|
location_t loc,
|
|
const struct line_map **map)
|
|
{
|
|
location_t resolved_loc;
|
|
const struct line_map *map0 = NULL;
|
|
const line_map_ordinary *map1 = NULL;
|
|
|
|
if (IS_ADHOC_LOC (loc))
|
|
loc = get_location_from_adhoc_loc (set, loc);
|
|
|
|
map0 = linemap_lookup (set, loc);
|
|
if (!linemap_macro_expansion_map_p (map0))
|
|
return loc;
|
|
|
|
resolved_loc = linemap_resolve_location (set, loc,
|
|
LRK_SPELLING_LOCATION,
|
|
&map1);
|
|
|
|
if (resolved_loc >= RESERVED_LOCATION_COUNT
|
|
&& !LINEMAP_SYSP (map1))
|
|
return loc;
|
|
|
|
while (linemap_macro_expansion_map_p (map0)
|
|
&& (resolved_loc < RESERVED_LOCATION_COUNT
|
|
|| LINEMAP_SYSP (map1)))
|
|
{
|
|
loc = linemap_unwind_toward_expansion (set, loc, &map0);
|
|
resolved_loc = linemap_resolve_location (set, loc,
|
|
LRK_SPELLING_LOCATION,
|
|
&map1);
|
|
}
|
|
|
|
if (map != NULL)
|
|
*map = map0;
|
|
return loc;
|
|
}
|
|
|
|
/* Expand source code location LOC and return a user readable source
|
|
code location. LOC must be a spelling (non-virtual) location. If
|
|
it's a location < RESERVED_LOCATION_COUNT a zeroed expanded source
|
|
location is returned. */
|
|
|
|
expanded_location
|
|
linemap_expand_location (line_maps *set,
|
|
const struct line_map *map,
|
|
location_t loc)
|
|
|
|
{
|
|
expanded_location xloc;
|
|
|
|
memset (&xloc, 0, sizeof (xloc));
|
|
if (IS_ADHOC_LOC (loc))
|
|
{
|
|
xloc.data = get_data_from_adhoc_loc (set, loc);
|
|
loc = get_location_from_adhoc_loc (set, loc);
|
|
}
|
|
|
|
if (loc < RESERVED_LOCATION_COUNT)
|
|
/* The location for this token wasn't generated from a line map.
|
|
It was probably a location for a builtin token, chosen by some
|
|
client code. Let's not try to expand the location in that
|
|
case. */;
|
|
else if (map == NULL)
|
|
/* We shouldn't be getting a NULL map with a location that is not
|
|
reserved by the client code. */
|
|
abort ();
|
|
else
|
|
{
|
|
/* MAP must be an ordinary map and LOC must be non-virtual,
|
|
encoded into this map, obviously; the accessors used on MAP
|
|
below ensure it is ordinary. Let's just assert the
|
|
non-virtualness of LOC here. */
|
|
if (linemap_location_from_macro_expansion_p (set, loc))
|
|
abort ();
|
|
|
|
const line_map_ordinary *ord_map = linemap_check_ordinary (map);
|
|
|
|
xloc.file = LINEMAP_FILE (ord_map);
|
|
xloc.line = SOURCE_LINE (ord_map, loc);
|
|
xloc.column = SOURCE_COLUMN (ord_map, loc);
|
|
xloc.sysp = LINEMAP_SYSP (ord_map) != 0;
|
|
}
|
|
|
|
return xloc;
|
|
}
|
|
|
|
|
|
/* Dump line map at index IX in line table SET to STREAM. If STREAM
|
|
is NULL, use stderr. IS_MACRO is true if the caller wants to
|
|
dump a macro map, false otherwise. */
|
|
|
|
void
|
|
linemap_dump (FILE *stream, class line_maps *set, unsigned ix, bool is_macro)
|
|
{
|
|
const char *const lc_reasons_v[LC_HWM]
|
|
= { "LC_ENTER", "LC_LEAVE", "LC_RENAME", "LC_RENAME_VERBATIM",
|
|
"LC_ENTER_MACRO" };
|
|
const line_map *map;
|
|
unsigned reason;
|
|
|
|
if (stream == NULL)
|
|
stream = stderr;
|
|
|
|
if (!is_macro)
|
|
{
|
|
map = LINEMAPS_ORDINARY_MAP_AT (set, ix);
|
|
reason = linemap_check_ordinary (map)->reason;
|
|
}
|
|
else
|
|
{
|
|
map = LINEMAPS_MACRO_MAP_AT (set, ix);
|
|
reason = LC_ENTER_MACRO;
|
|
}
|
|
|
|
fprintf (stream, "Map #%u [%p] - LOC: %u - REASON: %s - SYSP: %s\n",
|
|
ix, (void *) map, map->start_location,
|
|
reason < LC_HWM ? lc_reasons_v[reason] : "???",
|
|
((!is_macro
|
|
&& ORDINARY_MAP_IN_SYSTEM_HEADER_P (linemap_check_ordinary (map)))
|
|
? "yes" : "no"));
|
|
if (!is_macro)
|
|
{
|
|
const line_map_ordinary *ord_map = linemap_check_ordinary (map);
|
|
const line_map_ordinary *includer_map
|
|
= linemap_included_from_linemap (set, ord_map);
|
|
|
|
fprintf (stream, "File: %s:%d\n", ORDINARY_MAP_FILE_NAME (ord_map),
|
|
ORDINARY_MAP_STARTING_LINE_NUMBER (ord_map));
|
|
fprintf (stream, "Included from: [%d] %s\n",
|
|
includer_map ? int (includer_map - set->info_ordinary.maps) : -1,
|
|
includer_map ? ORDINARY_MAP_FILE_NAME (includer_map) : "None");
|
|
}
|
|
else
|
|
{
|
|
const line_map_macro *macro_map = linemap_check_macro (map);
|
|
fprintf (stream, "Macro: %s (%u tokens)\n",
|
|
linemap_map_get_macro_name (macro_map),
|
|
MACRO_MAP_NUM_MACRO_TOKENS (macro_map));
|
|
}
|
|
|
|
fprintf (stream, "\n");
|
|
}
|
|
|
|
|
|
/* Dump debugging information about source location LOC into the file
|
|
stream STREAM. SET is the line map set LOC comes from. */
|
|
|
|
void
|
|
linemap_dump_location (line_maps *set,
|
|
location_t loc,
|
|
FILE *stream)
|
|
{
|
|
const line_map_ordinary *map;
|
|
location_t location;
|
|
const char *path = "", *from = "";
|
|
int l = -1, c = -1, s = -1, e = -1;
|
|
|
|
if (IS_ADHOC_LOC (loc))
|
|
loc = get_location_from_adhoc_loc (set, loc);
|
|
|
|
if (loc == 0)
|
|
return;
|
|
|
|
location =
|
|
linemap_resolve_location (set, loc, LRK_MACRO_DEFINITION_LOCATION, &map);
|
|
|
|
if (map == NULL)
|
|
/* Only reserved locations can be tolerated in this case. */
|
|
linemap_assert (location < RESERVED_LOCATION_COUNT);
|
|
else
|
|
{
|
|
path = LINEMAP_FILE (map);
|
|
l = SOURCE_LINE (map, location);
|
|
c = SOURCE_COLUMN (map, location);
|
|
s = LINEMAP_SYSP (map) != 0;
|
|
e = location != loc;
|
|
if (e)
|
|
from = "N/A";
|
|
else
|
|
{
|
|
const line_map_ordinary *from_map
|
|
= linemap_included_from_linemap (set, map);
|
|
from = from_map ? LINEMAP_FILE (from_map) : "<NULL>";
|
|
}
|
|
}
|
|
|
|
/* P: path, L: line, C: column, S: in-system-header, M: map address,
|
|
E: macro expansion?, LOC: original location, R: resolved location */
|
|
fprintf (stream, "{P:%s;F:%s;L:%d;C:%d;S:%d;M:%p;E:%d,LOC:%d,R:%d}",
|
|
path, from, l, c, s, (void*)map, e, loc, location);
|
|
}
|
|
|
|
/* Return the highest location emitted for a given file for which
|
|
there is a line map in SET. FILE_NAME is the file name to
|
|
consider. If the function returns TRUE, *LOC is set to the highest
|
|
location emitted for that file. */
|
|
|
|
bool
|
|
linemap_get_file_highest_location (line_maps *set,
|
|
const char *file_name,
|
|
location_t *loc)
|
|
{
|
|
/* If the set is empty or no ordinary map has been created then
|
|
there is no file to look for ... */
|
|
if (set == NULL || set->info_ordinary.used == 0)
|
|
return false;
|
|
|
|
/* Now look for the last ordinary map created for FILE_NAME. */
|
|
int i;
|
|
for (i = set->info_ordinary.used - 1; i >= 0; --i)
|
|
{
|
|
const char *fname = set->info_ordinary.maps[i].to_file;
|
|
if (fname && !filename_cmp (fname, file_name))
|
|
break;
|
|
}
|
|
|
|
if (i < 0)
|
|
return false;
|
|
|
|
/* The highest location for a given map is either the starting
|
|
location of the next map minus one, or -- if the map is the
|
|
latest one -- the highest location of the set. */
|
|
location_t result;
|
|
if (i == (int) set->info_ordinary.used - 1)
|
|
result = set->highest_location;
|
|
else
|
|
result = set->info_ordinary.maps[i + 1].start_location - 1;
|
|
|
|
*loc = result;
|
|
return true;
|
|
}
|
|
|
|
/* Compute and return statistics about the memory consumption of some
|
|
parts of the line table SET. */
|
|
|
|
void
|
|
linemap_get_statistics (line_maps *set,
|
|
struct linemap_stats *s)
|
|
{
|
|
long ordinary_maps_allocated_size, ordinary_maps_used_size,
|
|
macro_maps_allocated_size, macro_maps_used_size,
|
|
macro_maps_locations_size = 0, duplicated_macro_maps_locations_size = 0;
|
|
|
|
const line_map_macro *cur_map;
|
|
|
|
ordinary_maps_allocated_size =
|
|
LINEMAPS_ORDINARY_ALLOCATED (set) * sizeof (struct line_map_ordinary);
|
|
|
|
ordinary_maps_used_size =
|
|
LINEMAPS_ORDINARY_USED (set) * sizeof (struct line_map_ordinary);
|
|
|
|
macro_maps_allocated_size =
|
|
LINEMAPS_MACRO_ALLOCATED (set) * sizeof (struct line_map_macro);
|
|
|
|
for (cur_map = LINEMAPS_MACRO_MAPS (set);
|
|
cur_map && cur_map <= LINEMAPS_LAST_MACRO_MAP (set);
|
|
++cur_map)
|
|
{
|
|
unsigned i;
|
|
|
|
linemap_assert (linemap_macro_expansion_map_p (cur_map));
|
|
|
|
macro_maps_locations_size +=
|
|
2 * MACRO_MAP_NUM_MACRO_TOKENS (cur_map) * sizeof (location_t);
|
|
|
|
for (i = 0; i < 2 * MACRO_MAP_NUM_MACRO_TOKENS (cur_map); i += 2)
|
|
{
|
|
if (MACRO_MAP_LOCATIONS (cur_map)[i] ==
|
|
MACRO_MAP_LOCATIONS (cur_map)[i + 1])
|
|
duplicated_macro_maps_locations_size +=
|
|
sizeof (location_t);
|
|
}
|
|
}
|
|
|
|
macro_maps_used_size =
|
|
LINEMAPS_MACRO_USED (set) * sizeof (struct line_map_macro);
|
|
|
|
s->num_ordinary_maps_allocated = LINEMAPS_ORDINARY_ALLOCATED (set);
|
|
s->num_ordinary_maps_used = LINEMAPS_ORDINARY_USED (set);
|
|
s->ordinary_maps_allocated_size = ordinary_maps_allocated_size;
|
|
s->ordinary_maps_used_size = ordinary_maps_used_size;
|
|
s->num_expanded_macros = num_expanded_macros_counter;
|
|
s->num_macro_tokens = num_macro_tokens_counter;
|
|
s->num_macro_maps_used = LINEMAPS_MACRO_USED (set);
|
|
s->macro_maps_allocated_size = macro_maps_allocated_size;
|
|
s->macro_maps_locations_size = macro_maps_locations_size;
|
|
s->macro_maps_used_size = macro_maps_used_size;
|
|
s->duplicated_macro_maps_locations_size =
|
|
duplicated_macro_maps_locations_size;
|
|
s->adhoc_table_size = (set->location_adhoc_data_map.allocated
|
|
* sizeof (struct location_adhoc_data));
|
|
s->adhoc_table_entries_used = set->location_adhoc_data_map.curr_loc;
|
|
}
|
|
|
|
|
|
/* Dump line table SET to STREAM. If STREAM is NULL, stderr is used.
|
|
NUM_ORDINARY specifies how many ordinary maps to dump. NUM_MACRO
|
|
specifies how many macro maps to dump. */
|
|
|
|
void
|
|
line_table_dump (FILE *stream, class line_maps *set, unsigned int num_ordinary,
|
|
unsigned int num_macro)
|
|
{
|
|
unsigned int i;
|
|
|
|
if (set == NULL)
|
|
return;
|
|
|
|
if (stream == NULL)
|
|
stream = stderr;
|
|
|
|
fprintf (stream, "# of ordinary maps: %d\n", LINEMAPS_ORDINARY_USED (set));
|
|
fprintf (stream, "# of macro maps: %d\n", LINEMAPS_MACRO_USED (set));
|
|
fprintf (stream, "Include stack depth: %d\n", set->depth);
|
|
fprintf (stream, "Highest location: %u\n", set->highest_location);
|
|
|
|
if (num_ordinary)
|
|
{
|
|
fprintf (stream, "\nOrdinary line maps\n");
|
|
for (i = 0; i < num_ordinary && i < LINEMAPS_ORDINARY_USED (set); i++)
|
|
linemap_dump (stream, set, i, false);
|
|
fprintf (stream, "\n");
|
|
}
|
|
|
|
if (num_macro)
|
|
{
|
|
fprintf (stream, "\nMacro line maps\n");
|
|
for (i = 0; i < num_macro && i < LINEMAPS_MACRO_USED (set); i++)
|
|
linemap_dump (stream, set, i, true);
|
|
fprintf (stream, "\n");
|
|
}
|
|
}
|
|
|
|
/* class rich_location. */
|
|
|
|
/* Construct a rich_location with location LOC as its initial range. */
|
|
|
|
rich_location::rich_location (line_maps *set, location_t loc,
|
|
const range_label *label) :
|
|
m_line_table (set),
|
|
m_ranges (),
|
|
m_column_override (0),
|
|
m_have_expanded_location (false),
|
|
m_fixit_hints (),
|
|
m_seen_impossible_fixit (false),
|
|
m_fixits_cannot_be_auto_applied (false)
|
|
{
|
|
add_range (loc, SHOW_RANGE_WITH_CARET, label);
|
|
}
|
|
|
|
/* The destructor for class rich_location. */
|
|
|
|
rich_location::~rich_location ()
|
|
{
|
|
for (unsigned int i = 0; i < m_fixit_hints.count (); i++)
|
|
delete get_fixit_hint (i);
|
|
}
|
|
|
|
/* Get location IDX within this rich_location. */
|
|
|
|
location_t
|
|
rich_location::get_loc (unsigned int idx) const
|
|
{
|
|
const location_range *locrange = get_range (idx);
|
|
return locrange->m_loc;
|
|
}
|
|
|
|
/* Get range IDX within this rich_location. */
|
|
|
|
const location_range *
|
|
rich_location::get_range (unsigned int idx) const
|
|
{
|
|
return &m_ranges[idx];
|
|
}
|
|
|
|
/* Mutable access to range IDX within this rich_location. */
|
|
|
|
location_range *
|
|
rich_location::get_range (unsigned int idx)
|
|
{
|
|
return &m_ranges[idx];
|
|
}
|
|
|
|
/* Expand location IDX within this rich_location. */
|
|
/* Get an expanded_location for this rich_location's primary
|
|
location. */
|
|
|
|
expanded_location
|
|
rich_location::get_expanded_location (unsigned int idx)
|
|
{
|
|
if (idx == 0)
|
|
{
|
|
/* Cache the expansion of the primary location. */
|
|
if (!m_have_expanded_location)
|
|
{
|
|
m_expanded_location
|
|
= linemap_client_expand_location_to_spelling_point
|
|
(get_loc (0), LOCATION_ASPECT_CARET);
|
|
if (m_column_override)
|
|
m_expanded_location.column = m_column_override;
|
|
m_have_expanded_location = true;
|
|
}
|
|
|
|
return m_expanded_location;
|
|
}
|
|
else
|
|
return linemap_client_expand_location_to_spelling_point
|
|
(get_loc (idx), LOCATION_ASPECT_CARET);
|
|
}
|
|
|
|
/* Set the column of the primary location, with 0 meaning
|
|
"don't override it". */
|
|
|
|
void
|
|
rich_location::override_column (int column)
|
|
{
|
|
m_column_override = column;
|
|
m_have_expanded_location = false;
|
|
}
|
|
|
|
/* Add the given range. */
|
|
|
|
void
|
|
rich_location::add_range (location_t loc,
|
|
enum range_display_kind range_display_kind,
|
|
const range_label *label)
|
|
{
|
|
location_range range;
|
|
range.m_loc = loc;
|
|
range.m_range_display_kind = range_display_kind;
|
|
range.m_label = label;
|
|
m_ranges.push (range);
|
|
}
|
|
|
|
/* Add or overwrite the location given by IDX, setting its location to LOC,
|
|
and setting its m_range_display_kind to RANGE_DISPLAY_KIND.
|
|
|
|
It must either overwrite an existing location, or add one *exactly* on
|
|
the end of the array.
|
|
|
|
This is primarily for use by gcc when implementing diagnostic format
|
|
decoders e.g.
|
|
- the "+" in the C/C++ frontends, for handling format codes like "%q+D"
|
|
(which writes the source location of a tree back into location 0 of
|
|
the rich_location), and
|
|
- the "%C" and "%L" format codes in the Fortran frontend. */
|
|
|
|
void
|
|
rich_location::set_range (unsigned int idx, location_t loc,
|
|
enum range_display_kind range_display_kind)
|
|
{
|
|
/* We can either overwrite an existing range, or add one exactly
|
|
on the end of the array. */
|
|
linemap_assert (idx <= m_ranges.count ());
|
|
|
|
if (idx == m_ranges.count ())
|
|
add_range (loc, range_display_kind);
|
|
else
|
|
{
|
|
location_range *locrange = get_range (idx);
|
|
locrange->m_loc = loc;
|
|
locrange->m_range_display_kind = range_display_kind;
|
|
}
|
|
|
|
if (idx == 0)
|
|
/* Mark any cached value here as dirty. */
|
|
m_have_expanded_location = false;
|
|
}
|
|
|
|
/* Methods for adding insertion fix-it hints. */
|
|
|
|
/* Add a fixit-hint, suggesting insertion of NEW_CONTENT
|
|
immediately before the primary range's start location. */
|
|
|
|
void
|
|
rich_location::add_fixit_insert_before (const char *new_content)
|
|
{
|
|
add_fixit_insert_before (get_loc (), new_content);
|
|
}
|
|
|
|
/* Add a fixit-hint, suggesting insertion of NEW_CONTENT
|
|
immediately before the start of WHERE. */
|
|
|
|
void
|
|
rich_location::add_fixit_insert_before (location_t where,
|
|
const char *new_content)
|
|
{
|
|
location_t start = get_range_from_loc (m_line_table, where).m_start;
|
|
maybe_add_fixit (start, start, new_content);
|
|
}
|
|
|
|
/* Add a fixit-hint, suggesting insertion of NEW_CONTENT
|
|
immediately after the primary range's end-point. */
|
|
|
|
void
|
|
rich_location::add_fixit_insert_after (const char *new_content)
|
|
{
|
|
add_fixit_insert_after (get_loc (), new_content);
|
|
}
|
|
|
|
/* Add a fixit-hint, suggesting insertion of NEW_CONTENT
|
|
immediately after the end-point of WHERE. */
|
|
|
|
void
|
|
rich_location::add_fixit_insert_after (location_t where,
|
|
const char *new_content)
|
|
{
|
|
location_t finish = get_range_from_loc (m_line_table, where).m_finish;
|
|
location_t next_loc
|
|
= linemap_position_for_loc_and_offset (m_line_table, finish, 1);
|
|
|
|
/* linemap_position_for_loc_and_offset can fail, if so, it returns
|
|
its input value. */
|
|
if (next_loc == finish)
|
|
{
|
|
stop_supporting_fixits ();
|
|
return;
|
|
}
|
|
|
|
maybe_add_fixit (next_loc, next_loc, new_content);
|
|
}
|
|
|
|
/* Methods for adding removal fix-it hints. */
|
|
|
|
/* Add a fixit-hint, suggesting removal of the content covered
|
|
by range 0. */
|
|
|
|
void
|
|
rich_location::add_fixit_remove ()
|
|
{
|
|
add_fixit_remove (get_loc ());
|
|
}
|
|
|
|
/* Add a fixit-hint, suggesting removal of the content between
|
|
the start and finish of WHERE. */
|
|
|
|
void
|
|
rich_location::add_fixit_remove (location_t where)
|
|
{
|
|
source_range range = get_range_from_loc (m_line_table, where);
|
|
add_fixit_remove (range);
|
|
}
|
|
|
|
/* Add a fixit-hint, suggesting removal of the content at
|
|
SRC_RANGE. */
|
|
|
|
void
|
|
rich_location::add_fixit_remove (source_range src_range)
|
|
{
|
|
add_fixit_replace (src_range, "");
|
|
}
|
|
|
|
/* Add a fixit-hint, suggesting replacement of the content covered
|
|
by range 0 with NEW_CONTENT. */
|
|
|
|
void
|
|
rich_location::add_fixit_replace (const char *new_content)
|
|
{
|
|
add_fixit_replace (get_loc (), new_content);
|
|
}
|
|
|
|
/* Methods for adding "replace" fix-it hints. */
|
|
|
|
/* Add a fixit-hint, suggesting replacement of the content between
|
|
the start and finish of WHERE with NEW_CONTENT. */
|
|
|
|
void
|
|
rich_location::add_fixit_replace (location_t where,
|
|
const char *new_content)
|
|
{
|
|
source_range range = get_range_from_loc (m_line_table, where);
|
|
add_fixit_replace (range, new_content);
|
|
}
|
|
|
|
/* Add a fixit-hint, suggesting replacement of the content at
|
|
SRC_RANGE with NEW_CONTENT. */
|
|
|
|
void
|
|
rich_location::add_fixit_replace (source_range src_range,
|
|
const char *new_content)
|
|
{
|
|
location_t start = get_pure_location (m_line_table, src_range.m_start);
|
|
location_t finish = get_pure_location (m_line_table, src_range.m_finish);
|
|
|
|
/* Fix-it hints use half-closed ranges, so attempt to offset the endpoint. */
|
|
location_t next_loc
|
|
= linemap_position_for_loc_and_offset (m_line_table, finish, 1);
|
|
/* linemap_position_for_loc_and_offset can fail, if so, it returns
|
|
its input value. */
|
|
if (next_loc == finish)
|
|
{
|
|
stop_supporting_fixits ();
|
|
return;
|
|
}
|
|
finish = next_loc;
|
|
|
|
maybe_add_fixit (start, finish, new_content);
|
|
}
|
|
|
|
/* Get the last fix-it hint within this rich_location, or NULL if none. */
|
|
|
|
fixit_hint *
|
|
rich_location::get_last_fixit_hint () const
|
|
{
|
|
if (m_fixit_hints.count () > 0)
|
|
return get_fixit_hint (m_fixit_hints.count () - 1);
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
/* If WHERE is an "awkward" location, then mark this rich_location as not
|
|
supporting fixits, purging any thay were already added, and return true.
|
|
|
|
Otherwise (the common case), return false. */
|
|
|
|
bool
|
|
rich_location::reject_impossible_fixit (location_t where)
|
|
{
|
|
/* Fix-its within a rich_location should either all be suggested, or
|
|
none of them should be suggested.
|
|
Once we've rejected a fixit, we reject any more, even those
|
|
with reasonable locations. */
|
|
if (m_seen_impossible_fixit)
|
|
return true;
|
|
|
|
if (where <= LINE_MAP_MAX_LOCATION_WITH_COLS)
|
|
/* WHERE is a reasonable location for a fix-it; don't reject it. */
|
|
return false;
|
|
|
|
/* Otherwise we have an attempt to add a fix-it with an "awkward"
|
|
location: either one that we can't obtain column information
|
|
for (within an ordinary map), or one within a macro expansion. */
|
|
stop_supporting_fixits ();
|
|
return true;
|
|
}
|
|
|
|
/* Mark this rich_location as not supporting fixits, purging any that were
|
|
already added. */
|
|
|
|
void
|
|
rich_location::stop_supporting_fixits ()
|
|
{
|
|
m_seen_impossible_fixit = true;
|
|
|
|
/* Purge the rich_location of any fix-its that were already added. */
|
|
for (unsigned int i = 0; i < m_fixit_hints.count (); i++)
|
|
delete get_fixit_hint (i);
|
|
m_fixit_hints.truncate (0);
|
|
}
|
|
|
|
/* Add HINT to the fix-it hints in this rich_location,
|
|
consolidating into the prior fixit if possible. */
|
|
|
|
void
|
|
rich_location::maybe_add_fixit (location_t start,
|
|
location_t next_loc,
|
|
const char *new_content)
|
|
{
|
|
if (reject_impossible_fixit (start))
|
|
return;
|
|
if (reject_impossible_fixit (next_loc))
|
|
return;
|
|
|
|
/* Only allow fix-it hints that affect a single line in one file.
|
|
Compare the end-points. */
|
|
expanded_location exploc_start
|
|
= linemap_client_expand_location_to_spelling_point (start,
|
|
LOCATION_ASPECT_START);
|
|
expanded_location exploc_next_loc
|
|
= linemap_client_expand_location_to_spelling_point (next_loc,
|
|
LOCATION_ASPECT_START);
|
|
/* They must be within the same file... */
|
|
if (exploc_start.file != exploc_next_loc.file)
|
|
{
|
|
stop_supporting_fixits ();
|
|
return;
|
|
}
|
|
/* ...and on the same line. */
|
|
if (exploc_start.line != exploc_next_loc.line)
|
|
{
|
|
stop_supporting_fixits ();
|
|
return;
|
|
}
|
|
/* The columns must be in the correct order. This can fail if the
|
|
endpoints straddle the boundary for which the linemap can represent
|
|
columns (PR c/82050). */
|
|
if (exploc_start.column > exploc_next_loc.column)
|
|
{
|
|
stop_supporting_fixits ();
|
|
return;
|
|
}
|
|
|
|
const char *newline = strchr (new_content, '\n');
|
|
if (newline)
|
|
{
|
|
/* For now, we can only support insertion of whole lines
|
|
i.e. starts at start of line, and the newline is at the end of
|
|
the insertion point. */
|
|
|
|
/* It must be an insertion, not a replacement/deletion. */
|
|
if (start != next_loc)
|
|
{
|
|
stop_supporting_fixits ();
|
|
return;
|
|
}
|
|
|
|
/* The insertion must be at the start of a line. */
|
|
if (exploc_start.column != 1)
|
|
{
|
|
stop_supporting_fixits ();
|
|
return;
|
|
}
|
|
|
|
/* The newline must be at end of NEW_CONTENT.
|
|
We could eventually split up fix-its at newlines if we wanted
|
|
to allow more generality (e.g. to allow adding multiple lines
|
|
with one add_fixit call. */
|
|
if (newline[1] != '\0')
|
|
{
|
|
stop_supporting_fixits ();
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* Consolidate neighboring fixits.
|
|
Don't consolidate into newline-insertion fixits. */
|
|
fixit_hint *prev = get_last_fixit_hint ();
|
|
if (prev && !prev->ends_with_newline_p ())
|
|
if (prev->maybe_append (start, next_loc, new_content))
|
|
return;
|
|
|
|
m_fixit_hints.push (new fixit_hint (start, next_loc, new_content));
|
|
}
|
|
|
|
/* class fixit_hint. */
|
|
|
|
fixit_hint::fixit_hint (location_t start,
|
|
location_t next_loc,
|
|
const char *new_content)
|
|
: m_start (start),
|
|
m_next_loc (next_loc),
|
|
m_bytes (xstrdup (new_content)),
|
|
m_len (strlen (new_content))
|
|
{
|
|
}
|
|
|
|
/* Does this fix-it hint affect the given line? */
|
|
|
|
bool
|
|
fixit_hint::affects_line_p (const char *file, int line) const
|
|
{
|
|
expanded_location exploc_start
|
|
= linemap_client_expand_location_to_spelling_point (m_start,
|
|
LOCATION_ASPECT_START);
|
|
if (file != exploc_start.file)
|
|
return false;
|
|
if (line < exploc_start.line)
|
|
return false;
|
|
expanded_location exploc_next_loc
|
|
= linemap_client_expand_location_to_spelling_point (m_next_loc,
|
|
LOCATION_ASPECT_START);
|
|
if (file != exploc_next_loc.file)
|
|
return false;
|
|
if (line > exploc_next_loc.line)
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
/* Method for consolidating fix-it hints, for use by
|
|
rich_location::maybe_add_fixit.
|
|
If possible, merge a pending fix-it hint with the given params
|
|
into this one and return true.
|
|
Otherwise return false. */
|
|
|
|
bool
|
|
fixit_hint::maybe_append (location_t start,
|
|
location_t next_loc,
|
|
const char *new_content)
|
|
{
|
|
/* For consolidation to be possible, START must be at this hint's
|
|
m_next_loc. */
|
|
if (start != m_next_loc)
|
|
return false;
|
|
|
|
/* If so, we have neighboring replacements; merge them. */
|
|
m_next_loc = next_loc;
|
|
size_t extra_len = strlen (new_content);
|
|
m_bytes = (char *)xrealloc (m_bytes, m_len + extra_len + 1);
|
|
memcpy (m_bytes + m_len, new_content, extra_len);
|
|
m_len += extra_len;
|
|
m_bytes[m_len] = '\0';
|
|
return true;
|
|
}
|
|
|
|
/* Return true iff this hint's content ends with a newline. */
|
|
|
|
bool
|
|
fixit_hint::ends_with_newline_p () const
|
|
{
|
|
if (m_len == 0)
|
|
return false;
|
|
return m_bytes[m_len - 1] == '\n';
|
|
}
|