diff options
Diffstat (limited to 'gcc/analyzer/checker-event.cc')
-rw-r--r-- | gcc/analyzer/checker-event.cc | 278 |
1 files changed, 185 insertions, 93 deletions
diff --git a/gcc/analyzer/checker-event.cc b/gcc/analyzer/checker-event.cc index 5d7647c..8cc5ac2 100644 --- a/gcc/analyzer/checker-event.cc +++ b/gcc/analyzer/checker-event.cc @@ -18,45 +18,32 @@ You should have received a copy of the GNU General Public License along with GCC; see the file COPYING3. If not see <http://www.gnu.org/licenses/>. */ -#include "config.h" -#define INCLUDE_VECTOR -#include "system.h" -#include "coretypes.h" -#include "tree.h" -#include "function.h" -#include "basic-block.h" -#include "gimple.h" -#include "diagnostic-core.h" +#include "analyzer/common.h" + #include "gimple-pretty-print.h" +#include "sbitmap.h" +#include "ordered-hash-map.h" #include "fold-const.h" -#include "diagnostic-path.h" -#include "options.h" -#include "cgraph.h" -#include "cfg.h" -#include "digraph.h" -#include "diagnostic-event-id.h" -#include "analyzer/analyzer.h" +#include "gimple-iterator.h" +#include "inlining-iterator.h" +#include "tree-logical-location.h" +#include "diagnostic-format-sarif.h" +#include "diagnostic-state-graphs.h" + #include "analyzer/analyzer-logging.h" #include "analyzer/sm.h" -#include "sbitmap.h" -#include "bitmap.h" -#include "ordered-hash-map.h" #include "analyzer/call-string.h" #include "analyzer/program-point.h" #include "analyzer/store.h" #include "analyzer/region-model.h" #include "analyzer/program-state.h" #include "analyzer/checker-path.h" -#include "gimple-iterator.h" -#include "inlining-iterator.h" #include "analyzer/supergraph.h" #include "analyzer/pending-diagnostic.h" #include "analyzer/diagnostic-manager.h" #include "analyzer/constraint-manager.h" #include "analyzer/checker-event.h" #include "analyzer/exploded-graph.h" -#include "diagnostic-format-sarif.h" -#include "tree-logical-location.h" #if ENABLE_ANALYZER @@ -71,40 +58,46 @@ event_kind_to_string (enum event_kind ek) { default: gcc_unreachable (); - case EK_DEBUG: - return "EK_DEBUG"; - case EK_CUSTOM: - return "EK_CUSTOM"; - case EK_STMT: - return "EK_STMT"; - case EK_REGION_CREATION: - return "EK_REGION_CREATION"; - case EK_FUNCTION_ENTRY: - return "EK_FUNCTION_ENTRY"; - case EK_STATE_CHANGE: - return "EK_STATE_CHANGE"; - case EK_START_CFG_EDGE: - return "EK_START_CFG_EDGE"; - case EK_END_CFG_EDGE: - return "EK_END_CFG_EDGE"; - case EK_CALL_EDGE: - return "EK_CALL_EDGE"; - case EK_RETURN_EDGE: - return "EK_RETURN_EDGE"; - case EK_START_CONSOLIDATED_CFG_EDGES: - return "EK_START_CONSOLIDATED_CFG_EDGES"; - case EK_END_CONSOLIDATED_CFG_EDGES: - return "EK_END_CONSOLIDATED_CFG_EDGES"; - case EK_INLINED_CALL: - return "EK_INLINED_CALL"; - case EK_SETJMP: - return "EK_SETJMP"; - case EK_REWIND_FROM_LONGJMP: - return "EK_REWIND_FROM_LONGJMP"; - case EK_REWIND_TO_SETJMP: - return "EK_REWIND_TO_SETJMP"; - case EK_WARNING: - return "EK_WARNING"; + case event_kind::debug: + return "debug"; + case event_kind::custom: + return "custom"; + case event_kind::stmt: + return "stmt"; + case event_kind::region_creation: + return "region_creation"; + case event_kind::function_entry: + return "function_entry"; + case event_kind::state_change: + return "state_change"; + case event_kind::start_cfg_edge: + return "start_cfg_edge"; + case event_kind::end_cfg_edge: + return "end_cfg_edge"; + case event_kind::catch_: + return "catch"; + case event_kind::call_edge: + return "call_edge"; + case event_kind::return_edge: + return "return_edge"; + case event_kind::start_consolidated_cfg_edges: + return "start_consolidated_cfg_edges"; + case event_kind::end_consolidated_cfg_edges: + return "end_consolidated_cfg_edges"; + case event_kind::inlined_call: + return "inlined_call"; + case event_kind::setjmp_: + return "setjmp"; + case event_kind::rewind_from_longjmp: + return "rewind_from_longjmp"; + case event_kind::rewind_to_setjmp: + return "rewind_to_setjmp"; + case event_kind::throw_: + return "throw"; + case event_kind::unwind: + return "unwind"; + case event_kind::warning: + return "warning"; } } @@ -114,13 +107,15 @@ event_kind_to_string (enum event_kind ek) checker_event::checker_event (enum event_kind kind, const event_loc_info &loc_info) -: m_kind (kind), m_loc (loc_info.m_loc), +: m_path (nullptr), + m_kind (kind), m_loc (loc_info.m_loc), m_original_fndecl (loc_info.m_fndecl), m_effective_fndecl (loc_info.m_fndecl), m_original_depth (loc_info.m_depth), m_effective_depth (loc_info.m_depth), - m_pending_diagnostic (NULL), m_emission_id (), - m_logical_loc (loc_info.m_fndecl) + m_pending_diagnostic (nullptr), m_emission_id (), + m_logical_loc + (tree_logical_location_manager::key_from_tree (loc_info.m_fndecl)) { /* Update effective fndecl and depth if inlining has been recorded. */ if (flag_analyzer_undo_inlining) @@ -130,7 +125,8 @@ checker_event::checker_event (enum event_kind kind, { m_effective_fndecl = info.get_inner_fndecl (); m_effective_depth += info.get_extra_frames (); - m_logical_loc = tree_logical_location (m_effective_fndecl); + m_logical_loc + = tree_logical_location_manager::key_from_tree (m_effective_fndecl); } } } @@ -149,7 +145,8 @@ checker_event::get_meaning () const void checker_event:: -maybe_add_sarif_properties (sarif_object &thread_flow_loc_obj) const +maybe_add_sarif_properties (sarif_builder &builder, + sarif_object &thread_flow_loc_obj) const { sarif_property_bag &props = thread_flow_loc_obj.get_or_create_properties (); #define PROPERTY_PREFIX "gcc/analyzer/checker_event/" @@ -158,12 +155,11 @@ maybe_add_sarif_properties (sarif_object &thread_flow_loc_obj) const props.set_string (PROPERTY_PREFIX "kind", event_kind_to_string (m_kind)); if (m_original_fndecl != m_effective_fndecl) - { - tree_logical_location logical_loc (m_original_fndecl); - props.set<sarif_logical_location> - (PROPERTY_PREFIX "original_fndecl", - make_sarif_logical_location_object (logical_loc)); - } + props.set_logical_location + (PROPERTY_PREFIX "original_fndecl", + builder, + tree_logical_location_manager::key_from_tree (m_original_fndecl)); + if (m_original_depth != m_effective_depth) props.set_integer (PROPERTY_PREFIX "original_depth", m_original_depth); #undef PROPERTY_PREFIX @@ -217,10 +213,11 @@ checker_event::debug () const pertinent data within the sm-state). */ void -checker_event::prepare_for_emission (checker_path *, +checker_event::prepare_for_emission (checker_path *path, pending_diagnostic *pd, diagnostic_event_id_t emission_id) { + m_path = path; m_pending_diagnostic = pd; m_emission_id = emission_id; @@ -228,6 +225,31 @@ checker_event::prepare_for_emission (checker_path *, print_desc (*pp.get ()); } +std::unique_ptr<diagnostics::digraphs::digraph> +checker_event::maybe_make_diagnostic_state_graph (bool debug) const +{ + const program_state *state = get_program_state (); + if (!state) + return nullptr; + + gcc_assert (m_path); + const extrinsic_state &ext_state = m_path->get_ext_state (); + + auto result = state->make_diagnostic_state_graph (ext_state); + + if (debug) + { + pretty_printer pp; + text_art::theme *theme = global_dc->get_diagram_theme (); + text_art::dump_to_pp (*state, theme, &pp); + result->set_attr (STATE_GRAPH_PREFIX, + "analyzer/program_state/", + pp_formatted_text (&pp)); + } + + return result; +} + /* class debug_event : public checker_event. */ /* Implementation of diagnostic_event::print_desc vfunc for @@ -258,7 +280,7 @@ precanned_custom_event::print_desc (pretty_printer &pp) const statement_event::statement_event (const gimple *stmt, tree fndecl, int depth, const program_state &dst_state) -: checker_event (EK_STMT, +: checker_event (event_kind::stmt, event_loc_info (gimple_location (stmt), fndecl, depth)), m_stmt (stmt), m_dst_state (dst_state) @@ -279,7 +301,7 @@ statement_event::print_desc (pretty_printer &pp) const /* class region_creation_event : public checker_event. */ region_creation_event::region_creation_event (const event_loc_info &loc_info) -: checker_event (EK_REGION_CREATION, loc_info) +: checker_event (event_kind::region_creation, loc_info) { } @@ -350,12 +372,14 @@ region_creation_event_debug::print_desc (pretty_printer &pp) const /* class function_entry_event : public checker_event. */ -function_entry_event::function_entry_event (const program_point &dst_point) -: checker_event (EK_FUNCTION_ENTRY, +function_entry_event::function_entry_event (const program_point &dst_point, + const program_state &state) +: checker_event (event_kind::function_entry, event_loc_info (dst_point.get_supernode ()->get_start_location (), dst_point.get_fndecl (), - dst_point.get_stack_depth ())) + dst_point.get_stack_depth ())), + m_state (state) { } @@ -376,7 +400,7 @@ function_entry_event::print_desc (pretty_printer &pp) const diagnostic_event::meaning function_entry_event::get_meaning () const { - return meaning (VERB_enter, NOUN_function); + return meaning (verb::enter, noun::function); } /* class state_change_event : public checker_event. */ @@ -393,7 +417,7 @@ state_change_event::state_change_event (const supernode *node, const svalue *origin, const program_state &dst_state, const exploded_node *enode) -: checker_event (EK_STATE_CHANGE, +: checker_event (event_kind::state_change, event_loc_info (stmt->location, node->m_fun->decl, stack_depth)), @@ -476,7 +500,7 @@ state_change_event::print_desc (pretty_printer &pp) const } else { - gcc_assert (m_origin == NULL); + gcc_assert (m_origin == nullptr); pp_printf (&pp, "global state: %qs -> %qs", m_from->get_name (), @@ -510,10 +534,11 @@ state_change_event::get_meaning () const for superedge_event. */ void -superedge_event::maybe_add_sarif_properties (sarif_object &thread_flow_loc_obj) +superedge_event::maybe_add_sarif_properties (sarif_builder &builder, + sarif_object &thread_flow_loc_obj) const { - checker_event::maybe_add_sarif_properties (thread_flow_loc_obj); + checker_event::maybe_add_sarif_properties (builder, thread_flow_loc_obj); sarif_property_bag &props = thread_flow_loc_obj.get_or_create_properties (); #define PROPERTY_PREFIX "gcc/analyzer/superedge_event/" if (m_sedge) @@ -562,6 +587,12 @@ superedge_event::should_filter_p (int verbosity) const return false; } +const program_state * +superedge_event::get_program_state () const +{ + return &m_eedge.m_dest->get_state (); +} + /* superedge_event's ctor. */ superedge_event::superedge_event (enum event_kind kind, @@ -603,9 +634,9 @@ cfg_edge_event::get_meaning () const { const cfg_superedge& cfg_sedge = get_cfg_superedge (); if (cfg_sedge.true_value_p ()) - return meaning (VERB_branch, PROPERTY_true); + return meaning (verb::branch, property::true_); else if (cfg_sedge.false_value_p ()) - return meaning (VERB_branch, PROPERTY_false); + return meaning (verb::branch, property::false_); else return meaning (); } @@ -715,7 +746,7 @@ start_cfg_edge_event::maybe_describe_condition (bool can_colorize) const lhs, op, rhs); } } - return label_text::borrow (NULL); + return label_text::borrow (nullptr); } /* Subroutine of maybe_describe_condition above. @@ -741,7 +772,7 @@ start_cfg_edge_event::maybe_describe_condition (bool can_colorize, && zerop (rhs)) { if (gcall *call = dyn_cast <gcall *> (SSA_NAME_DEF_STMT (lhs))) - if (is_special_named_call_p (call, "strcmp", 2)) + if (is_special_named_call_p (*call, "strcmp", 2)) { if (op == EQ_EXPR) return label_text::borrow ("when the strings are equal"); @@ -752,9 +783,9 @@ start_cfg_edge_event::maybe_describe_condition (bool can_colorize, /* Only attempt to generate text for sufficiently simple expressions. */ if (!should_print_expr_p (lhs)) - return label_text::borrow (NULL); + return label_text::borrow (nullptr); if (!should_print_expr_p (rhs)) - return label_text::borrow (NULL); + return label_text::borrow (nullptr); /* Special cases for pointer comparisons against NULL. */ if (POINTER_TYPE_P (TREE_TYPE (lhs)) @@ -804,7 +835,7 @@ start_cfg_edge_event::should_print_expr_p (tree expr) call_event::call_event (const exploded_edge &eedge, const event_loc_info &loc_info) -: superedge_event (EK_CALL_EDGE, eedge, loc_info) +: superedge_event (event_kind::call_edge, eedge, loc_info) { if (eedge.m_sedge) gcc_assert (eedge.m_sedge->m_kind == SUPEREDGE_CALL); @@ -851,7 +882,7 @@ call_event::print_desc (pretty_printer &pp) const diagnostic_event::meaning call_event::get_meaning () const { - return meaning (VERB_call, NOUN_function); + return meaning (verb::call, noun::function); } /* Override of checker_event::is_call_p for calls. */ @@ -874,13 +905,21 @@ call_event::get_callee_fndecl () const return m_dest_snode->m_fun->decl; } +const program_state * +call_event::get_program_state () const +{ + /* Use the state at the source (at the caller), + rather than the one at the dest, which has a frame for the callee. */ + return &m_eedge.m_src->get_state (); +} + /* class return_event : public superedge_event. */ /* return_event's ctor. */ return_event::return_event (const exploded_edge &eedge, const event_loc_info &loc_info) -: superedge_event (EK_RETURN_EDGE, eedge, loc_info) +: superedge_event (event_kind::return_edge, eedge, loc_info) { if (eedge.m_sedge) gcc_assert (eedge.m_sedge->m_kind == SUPEREDGE_RETURN); @@ -927,7 +966,7 @@ return_event::print_desc (pretty_printer &pp) const diagnostic_event::meaning return_event::get_meaning () const { - return meaning (VERB_return, NOUN_function); + return meaning (verb::return_, noun::function); } /* Override of checker_event::is_return_p for returns. */ @@ -954,8 +993,8 @@ start_consolidated_cfg_edges_event::print_desc (pretty_printer &pp) const diagnostic_event::meaning start_consolidated_cfg_edges_event::get_meaning () const { - return meaning (VERB_branch, - (m_edge_sense ? PROPERTY_true : PROPERTY_false)); + return meaning (verb::branch, + (m_edge_sense ? property::true_ : property::false_)); } /* class inlined_call_event : public checker_event. */ @@ -975,7 +1014,7 @@ inlined_call_event::print_desc (pretty_printer &pp) const diagnostic_event::meaning inlined_call_event::get_meaning () const { - return meaning (VERB_call, NOUN_function); + return meaning (verb::call, noun::function); } /* class setjmp_event : public checker_event. */ @@ -1118,6 +1157,50 @@ rewind_to_setjmp_event::prepare_for_emission (checker_path *path, &m_original_setjmp_event_id); } +/* class throw_event : public checker_event. */ + +/* class explicit_throw_event : public throw_event. */ +void +explicit_throw_event::print_desc (pretty_printer &pp) const +{ + if (m_is_rethrow) + { + if (m_type) + pp_printf (&pp, "rethrowing exception of type %qT here...", m_type); + else + pp_printf (&pp, "rethrowing exception here..."); + } + else + { + if (m_type) + pp_printf (&pp, "throwing exception of type %qT here...", m_type); + else + pp_printf (&pp, "throwing exception here..."); + } +} + +/* class throw_from_call_to_external_fn_event : public throw_event. */ + +void +throw_from_call_to_external_fn_event::print_desc (pretty_printer &pp) const +{ + if (m_fndecl) + pp_printf (&pp, "if %qD throws an exception...", m_fndecl); + else + pp_printf (&pp, "if the called function throws an exception..."); +} + +// class unwind_event : public checker_event + +void +unwind_event::print_desc (pretty_printer &pp) const +{ + if (m_num_frames > 1) + pp_printf (&pp, "unwinding %i stack frames", m_num_frames); + else + pp_printf (&pp, "unwinding stack frame"); +} + /* class warning_event : public checker_event. */ /* Implementation of diagnostic_event::print_desc vfunc for @@ -1171,7 +1254,16 @@ warning_event::print_desc (pretty_printer &pp) const diagnostic_event::meaning warning_event::get_meaning () const { - return meaning (VERB_danger, NOUN_unknown); + return meaning (verb::danger, noun::unknown); +} + +const program_state * +warning_event::get_program_state () const +{ + if (m_program_state) + return m_program_state.get (); + else + return &m_enode->get_state (); } } // namespace ana |