aboutsummaryrefslogtreecommitdiff
path: root/gcc/analyzer/checker-event.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/analyzer/checker-event.cc')
-rw-r--r--gcc/analyzer/checker-event.cc278
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