aboutsummaryrefslogtreecommitdiff
path: root/gcc/analyzer/diagnostic-manager.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/analyzer/diagnostic-manager.cc')
-rw-r--r--gcc/analyzer/diagnostic-manager.cc414
1 files changed, 251 insertions, 163 deletions
diff --git a/gcc/analyzer/diagnostic-manager.cc b/gcc/analyzer/diagnostic-manager.cc
index 4bf1dce..88f72d1 100644
--- a/gcc/analyzer/diagnostic-manager.cc
+++ b/gcc/analyzer/diagnostic-manager.cc
@@ -18,22 +18,19 @@ 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 "input.h"
-#include "diagnostic-core.h"
-#include "pretty-print.h"
-#include "gcc-rich-location.h"
+#include "analyzer/common.h"
+
+#include "cfg.h"
+#include "basic-block.h"
+#include "gimple.h"
#include "gimple-pretty-print.h"
-#include "function.h"
-#include "diagnostic-event-id.h"
-#include "diagnostic-path.h"
-#include "bitmap.h"
-#include "ordered-hash-map.h"
-#include "analyzer/analyzer.h"
+#include "gimple-iterator.h"
+#include "inlining-iterator.h"
+#include "cgraph.h"
+#include "digraph.h"
+#include "gcc-rich-location.h"
+#include "diagnostics/sarif-sink.h"
+
#include "analyzer/analyzer-logging.h"
#include "analyzer/sm.h"
#include "analyzer/pending-diagnostic.h"
@@ -43,13 +40,6 @@ along with GCC; see the file COPYING3. If not see
#include "analyzer/store.h"
#include "analyzer/region-model.h"
#include "analyzer/constraint-manager.h"
-#include "cfg.h"
-#include "basic-block.h"
-#include "gimple.h"
-#include "gimple-iterator.h"
-#include "inlining-iterator.h"
-#include "cgraph.h"
-#include "digraph.h"
#include "analyzer/supergraph.h"
#include "analyzer/program-state.h"
#include "analyzer/exploded-graph.h"
@@ -57,8 +47,6 @@ along with GCC; see the file COPYING3. If not see
#include "analyzer/feasible-graph.h"
#include "analyzer/checker-path.h"
#include "analyzer/reachability.h"
-#include "make-unique.h"
-#include "diagnostic-format-sarif.h"
#if ENABLE_ANALYZER
@@ -75,7 +63,7 @@ class epath_finder
public:
epath_finder (const exploded_graph &eg)
: m_eg (eg),
- m_sep (NULL)
+ m_sep (nullptr)
{
/* This is shared by all diagnostics, but only needed if
!flag_analyzer_feasibility. */
@@ -137,7 +125,7 @@ private:
within ENODE.
Ideally we want to report the shortest feasible path.
- Return NULL if we could not find a feasible path
+ Return nullptr if we could not find a feasible path
(when flag_analyzer_feasibility is true).
If flag_analyzer_feasibility is false, then simply return the
@@ -189,7 +177,7 @@ epath_finder::get_best_epath (const exploded_node *enode,
logger->log ("rejecting %qs at EN: %i, SN: %i (sd: %i)"
" due to not finding feasible path",
desc, enode->m_index, snode_idx, diag_idx);
- return NULL;
+ return nullptr;
}
}
else
@@ -203,7 +191,7 @@ epath_finder::get_best_epath (const exploded_node *enode,
logger->log ("trying to find shortest path ignoring feasibility");
gcc_assert (m_sep);
std::unique_ptr<exploded_path> epath
- = make_unique<exploded_path> (m_sep->get_shortest_path (enode));
+ = std::make_unique<exploded_path> (m_sep->get_shortest_path (enode));
if (epath->feasible_p (logger, out_problem, m_eg.get_engine (), &m_eg))
{
if (logger)
@@ -233,7 +221,7 @@ class feasible_worklist
{
public:
feasible_worklist (const shortest_paths<eg_traits, exploded_path> &sep)
- : m_queue (key_t (*this, NULL)),
+ : m_queue (key_t (*this, nullptr)),
m_sep (sep)
{
}
@@ -428,7 +416,7 @@ epath_finder::explore_feasible_paths (const exploded_node *target_enode,
a limit. */
/* Set this if we find a feasible path to TARGET_ENODE. */
- std::unique_ptr<exploded_path> best_path = NULL;
+ std::unique_ptr<exploded_path> best_path = nullptr;
{
auto_checking_feasibility sentinel (mgr);
@@ -520,7 +508,7 @@ process_worklist_item (feasible_worklist *worklist,
std::unique_ptr<rejected_constraint> rc;
if (succ_state.maybe_update_for_edge (logger, succ_eedge, nullptr, &rc))
{
- gcc_assert (rc == NULL);
+ gcc_assert (rc == nullptr);
feasible_node *succ_fnode
= fg->add_node (succ_eedge->m_dest,
succ_state,
@@ -624,7 +612,7 @@ dump_trimmed_graph (const exploded_node *target_enode,
pp_printf (&pp, "%s.%s.%i.to-en%i.tg.dot",
dump_base_name, desc, diag_idx, target_enode->m_index);
char *filename = xstrdup (pp_formatted_text (&pp));
- tg.dump_dot (filename, NULL, args);
+ tg.dump_dot (filename, nullptr, args);
free (filename);
}
@@ -642,7 +630,7 @@ epath_finder::dump_feasible_graph (const exploded_node *target_enode,
pp_printf (&pp, "%s.%s.%i.to-en%i.fg.dot",
dump_base_name, desc, diag_idx, target_enode->m_index);
char *filename = xstrdup (pp_formatted_text (&pp));
- fg.dump_dot (filename, NULL, args);
+ fg.dump_dot (filename, nullptr, args);
free (filename);
}
@@ -699,6 +687,11 @@ saved_diagnostic::operator== (const saved_diagnostic &other) const
for (unsigned i = 0; i < m_notes.length (); i++)
if (!m_notes[i]->equal_p (*other.m_notes[i]))
return false;
+
+ // Don't deduplicate dump_path_diagnostic instances
+ if (!strcmp (m_d->get_kind (), "dump_path_diagnostic"))
+ return this == &other;
+
return (m_sm == other.m_sm
/* We don't compare m_enode. */
&& m_snode == other.m_snode
@@ -742,7 +735,7 @@ saved_diagnostic::add_event (std::unique_ptr<checker_event> event)
std::unique_ptr<json::object>
saved_diagnostic::to_json () const
{
- auto sd_obj = ::make_unique<json::object> ();
+ auto sd_obj = std::make_unique<json::object> ();
if (m_sm)
sd_obj->set_string ("sm", m_sm->get_name ());
@@ -834,7 +827,7 @@ saved_diagnostic::dump_as_dot_node (pretty_printer *pp) const
/* Use PF to find the best exploded_path for this saved_diagnostic,
and store it in m_best_epath.
- If we don't have a specific location in m_loc and m_stmt is still NULL,
+ If we don't have a specific location in m_loc and m_stmt is still nullptr,
use m_stmt_finder on the epath to populate m_stmt.
Return true if a best path was found. */
@@ -843,20 +836,20 @@ saved_diagnostic::calc_best_epath (epath_finder *pf)
{
logger *logger = pf->get_logger ();
LOG_SCOPE (logger);
- m_problem = NULL;
+ m_problem = nullptr;
m_best_epath = pf->get_best_epath (m_enode, m_stmt,
*m_d, m_d->get_kind (), m_idx,
&m_problem);
/* Handle failure to find a feasible path. */
- if (m_best_epath == NULL)
+ if (m_best_epath == nullptr)
return false;
gcc_assert (m_best_epath);
if (m_loc == UNKNOWN_LOCATION)
{
- if (m_stmt == NULL)
+ if (m_stmt == nullptr)
{
gcc_assert (m_stmt_finder);
m_stmt = m_stmt_finder->find_stmt (*m_best_epath);
@@ -1024,9 +1017,10 @@ saved_diagnostic::emit_any_notes () const
This extra data is intended for use when debugging the analyzer. */
void
-saved_diagnostic::maybe_add_sarif_properties (sarif_object &result_obj) const
+saved_diagnostic::
+maybe_add_sarif_properties (diagnostics::sarif_object &result_obj) const
{
- sarif_property_bag &props = result_obj.get_or_create_properties ();
+ auto &props = result_obj.get_or_create_properties ();
#define PROPERTY_PREFIX "gcc/analyzer/saved_diagnostic/"
if (m_sm)
props.set_string (PROPERTY_PREFIX "sm", m_sm->get_name ());
@@ -1048,10 +1042,10 @@ saved_diagnostic::maybe_add_sarif_properties (sarif_object &result_obj) const
props.set_integer (PROPERTY_PREFIX "idx", m_idx);
if (m_duplicates.length () > 0)
{
- auto duplicates_arr = ::make_unique<json::array> ();
+ auto duplicates_arr = std::make_unique<json::array> ();
for (auto iter : m_duplicates)
{
- auto sd_obj = ::make_unique<sarif_object> ();
+ auto sd_obj = std::make_unique<diagnostics::sarif_object> ();
iter->maybe_add_sarif_properties (*sd_obj);
duplicates_arr->append (std::move (sd_obj));
}
@@ -1205,7 +1199,7 @@ diagnostic_manager::add_diagnostic (const pending_location &ploc,
std::unique_ptr<pending_diagnostic> d)
{
gcc_assert (ploc.m_enode);
- return add_diagnostic (NULL, ploc, NULL_TREE, NULL, 0, std::move (d));
+ return add_diagnostic (nullptr, ploc, NULL_TREE, nullptr, 0, std::move (d));
}
/* Add PN to the most recent saved_diagnostic. */
@@ -1242,10 +1236,10 @@ diagnostic_manager::add_event (std::unique_ptr<checker_event> event)
std::unique_ptr<json::object>
diagnostic_manager::to_json () const
{
- auto dm_obj = ::make_unique<json::object> ();
+ auto dm_obj = std::make_unique<json::object> ();
{
- auto sd_arr = ::make_unique<json::array> ();
+ auto sd_arr = std::make_unique<json::array> ();
int i;
saved_diagnostic *sd;
FOR_EACH_VEC_ELT (m_saved_diagnostics, i, sd)
@@ -1350,7 +1344,7 @@ public:
template <typename T>
static inline void mark_empty (T &entry)
{
- entry.m_key = NULL;
+ entry.m_key = nullptr;
}
template <typename T>
static inline bool is_deleted (const T &entry)
@@ -1360,7 +1354,7 @@ public:
template <typename T>
static inline bool is_empty (const T &entry)
{
- return entry.m_key == NULL;
+ return entry.m_key == nullptr;
}
static const bool empty_zero_p = true;
};
@@ -1548,12 +1542,12 @@ diagnostic_manager::emit_saved_diagnostics (const exploded_graph &eg)
best_candidates.emit_best (this, eg);
}
-/* Custom subclass of diagnostic_metadata which, for SARIF output,
+/* Custom subclass of diagnostics::metadata which, for SARIF output,
populates the property bag of the diagnostic's "result" object
with information from the saved_diagnostic and the
pending_diagnostic. */
-class pending_diagnostic_metadata : public diagnostic_metadata
+class pending_diagnostic_metadata : public diagnostics::metadata
{
public:
pending_diagnostic_metadata (const saved_diagnostic &sd)
@@ -1562,7 +1556,8 @@ public:
}
void
- maybe_add_sarif_properties (sarif_object &result_obj) const override
+ maybe_add_sarif_properties (diagnostics::sarif_object &result_obj)
+ const override
{
m_sd.maybe_add_sarif_properties (result_obj);
}
@@ -1590,9 +1585,11 @@ diagnostic_manager::emit_saved_diagnostic (const exploded_graph &eg,
/* Precompute all enodes from which the diagnostic is reachable. */
path_builder pb (eg, *epath, sd.get_feasibility_problem (), sd);
- /* This is the diagnostic_path subclass that will be built for
+ /* This is the diagnostics::paths::path subclass that will be built for
the diagnostic. */
- checker_path emission_path (get_logger ());
+ checker_path emission_path (get_logical_location_manager (),
+ eg.get_ext_state (),
+ get_logger ());
/* Populate emission_path with a full description of EPATH. */
build_emission_path (pb, *epath, &emission_path);
@@ -1625,7 +1622,7 @@ diagnostic_manager::emit_saved_diagnostic (const exploded_graph &eg,
trailing eedge stashed, add any events for it. This is for use
in handling longjmp, to show where a longjmp is rewinding to. */
if (sd.m_trailing_eedge)
- add_events_for_eedge (pb, *sd.m_trailing_eedge, &emission_path, NULL);
+ add_events_for_eedge (pb, *sd.m_trailing_eedge, &emission_path, nullptr);
emission_path.inject_any_inlined_call_events (get_logger ());
@@ -1668,6 +1665,15 @@ diagnostic_manager::emit_saved_diagnostic (const exploded_graph &eg,
}
}
+const diagnostics::logical_locations::manager &
+diagnostic_manager::get_logical_location_manager () const
+{
+ gcc_assert (global_dc);
+ auto mgr = global_dc->get_logical_location_manager ();
+ gcc_assert (mgr);
+ return *mgr;
+}
+
/* Emit a "path" of events to EMISSION_PATH describing the exploded path
EPATH within EG. */
@@ -1700,7 +1706,7 @@ diagnostic_manager::build_emission_path (const path_builder &pb,
{
emission_path->add_region_creation_events
(pb.get_pending_diagnostic (),
- reg, NULL,
+ reg, nullptr,
event_loc_info (DECL_SOURCE_LOCATION (decl),
NULL_TREE,
0),
@@ -1759,7 +1765,7 @@ diagnostic_manager::add_event_on_final_node (const path_builder &pb,
= src_model->get_dynamic_extents (base_reg);
const svalue *new_extents
= dst_model->get_dynamic_extents (base_reg);
- if (old_extents == NULL && new_extents != NULL)
+ if (old_extents == nullptr && new_extents != nullptr)
switch (base_reg->get_kind ())
{
default:
@@ -1816,16 +1822,16 @@ public:
int stack_depth = src_stack_depth;
m_emission_path->add_event
- (make_unique<state_change_event> (supernode,
- stmt,
- stack_depth,
- sm,
- nullptr,
- src_sm_val,
- dst_sm_val,
- nullptr,
- dst_state,
- src_node));
+ (std::make_unique<state_change_event> (supernode,
+ stmt,
+ stack_depth,
+ sm,
+ nullptr,
+ src_sm_val,
+ dst_sm_val,
+ nullptr,
+ dst_state,
+ src_node));
return false;
}
@@ -1861,16 +1867,16 @@ public:
return false;
m_emission_path->add_event
- (make_unique<state_change_event> (supernode,
- stmt,
- stack_depth,
- sm,
- sval,
- src_sm_val,
- dst_sm_val,
- dst_origin_sval,
- dst_state,
- src_node));
+ (std::make_unique<state_change_event> (supernode,
+ stmt,
+ stack_depth,
+ sm,
+ sval,
+ src_sm_val,
+ dst_sm_val,
+ dst_origin_sval,
+ dst_state,
+ src_node));
return false;
}
@@ -1963,7 +1969,7 @@ struct null_assignment_sm_context : public sm_context
{
}
- tree get_fndecl_for_call (const gcall */*call*/) final override
+ tree get_fndecl_for_call (const gcall &/*call*/) final override
{
return NULL_TREE;
}
@@ -1972,7 +1978,7 @@ struct null_assignment_sm_context : public sm_context
tree var) final override
{
const svalue *var_old_sval
- = m_old_state->m_region_model->get_rvalue (var, NULL);
+ = m_old_state->m_region_model->get_rvalue (var, nullptr);
const sm_state_map *old_smap = m_old_state->m_checker_states[m_sm_idx];
state_machine::state_t current
@@ -2001,21 +2007,21 @@ struct null_assignment_sm_context : public sm_context
return;
const svalue *var_new_sval
- = m_new_state->m_region_model->get_rvalue (var, NULL);
+ = m_new_state->m_region_model->get_rvalue (var, nullptr);
const supernode *supernode = m_point->get_supernode ();
int stack_depth = m_point->get_stack_depth ();
m_emission_path->add_event
- (make_unique<state_change_event> (supernode,
- m_stmt,
- stack_depth,
- m_sm,
- var_new_sval,
- from, to,
- nullptr,
- *m_new_state,
- nullptr));
+ (std::make_unique<state_change_event> (supernode,
+ m_stmt,
+ stack_depth,
+ m_sm,
+ var_new_sval,
+ from, to,
+ nullptr,
+ *m_new_state,
+ nullptr));
}
void set_next_state (const gimple *stmt,
@@ -2033,15 +2039,15 @@ struct null_assignment_sm_context : public sm_context
int stack_depth = m_point->get_stack_depth ();
m_emission_path->add_event
- (make_unique<state_change_event> (supernode,
- m_stmt,
- stack_depth,
- m_sm,
- sval,
- from, to,
- nullptr,
- *m_new_state,
- nullptr));
+ (std::make_unique<state_change_event> (supernode,
+ m_stmt,
+ stack_depth,
+ m_sm,
+ sval,
+ from, to,
+ nullptr,
+ *m_new_state,
+ nullptr));
}
void warn (const supernode *, const gimple *,
@@ -2088,7 +2094,7 @@ struct null_assignment_sm_context : public sm_context
if (!assign_stmt)
return NULL_TREE;
if (const svalue *sval
- = m_new_state->m_region_model->get_gassign_result (assign_stmt, NULL))
+ = m_new_state->m_region_model->get_gassign_result (assign_stmt, nullptr))
if (tree cst = sval->maybe_get_constant ())
if (::zerop(cst))
return gimple_assign_lhs (assign_stmt);
@@ -2220,18 +2226,19 @@ diagnostic_manager::add_events_for_eedge (const path_builder &pb,
{
const gimple *stmt = dst_point.get_stmt ();
const gcall *call = dyn_cast <const gcall *> (stmt);
- if (call && is_setjmp_call_p (call))
+ if (call && is_setjmp_call_p (*call))
emission_path->add_event
- (make_unique<setjmp_event> (event_loc_info (stmt->location,
- dst_point.get_fndecl (),
- dst_stack_depth),
- dst_node,
- call));
+ (std::make_unique<setjmp_event>
+ (event_loc_info (stmt->location,
+ dst_point.get_fndecl (),
+ dst_stack_depth),
+ dst_node,
+ *call));
else
emission_path->add_event
- (make_unique<statement_event> (stmt,
- dst_point.get_fndecl (),
- dst_stack_depth, dst_state));
+ (std::make_unique<statement_event> (stmt,
+ dst_point.get_fndecl (),
+ dst_stack_depth, dst_state));
/* Create state change events for assignment to NULL.
Iterate through the stmts in dst_enode, adding state change
@@ -2248,7 +2255,7 @@ diagnostic_manager::add_events_for_eedge (const path_builder &pb,
{
const extrinsic_state &ext_state = pb.get_ext_state ();
program_state old_state (iter_state);
- iter_state.m_region_model->on_assignment (assign, NULL);
+ iter_state.m_region_model->on_assignment (assign, nullptr);
for (unsigned i = 0; i < ext_state.get_num_checkers (); i++)
{
const state_machine &sm = ext_state.get_sm (i);
@@ -2294,7 +2301,7 @@ diagnostic_manager::add_events_for_eedge (const path_builder &pb,
= src_model->get_dynamic_extents (base_reg);
const svalue *new_extents
= dst_model->get_dynamic_extents (base_reg);
- if (old_extents == NULL && new_extents != NULL)
+ if (old_extents == nullptr && new_extents != nullptr)
switch (base_reg->get_kind ())
{
default:
@@ -2324,11 +2331,11 @@ diagnostic_manager::add_events_for_eedge (const path_builder &pb,
" at this edge: ");
pb.get_feasibility_problem ()->dump_to_pp (&pp);
emission_path->add_event
- (make_unique<precanned_custom_event>
- (event_loc_info (dst_point.get_location (),
- dst_point.get_fndecl (),
- dst_stack_depth),
- pp_formatted_text (&pp)));
+ (std::make_unique<precanned_custom_event>
+ (event_loc_info (dst_point.get_location (),
+ dst_point.get_fndecl (),
+ dst_stack_depth),
+ pp_formatted_text (&pp)));
}
}
@@ -2438,18 +2445,48 @@ diagnostic_manager::add_events_for_superedge (const path_builder &pb,
{
case SUPEREDGE_CFG_EDGE:
{
+ if (auto eh_dispatch_try_sedge
+ = eedge.m_sedge->dyn_cast_eh_dispatch_try_cfg_superedge ())
+ {
+ if (eh_dispatch_try_sedge->get_eh_catch ())
+ {
+ const region_model *model = src_node->get_state ().m_region_model;
+ auto curr_thrown_exception_node
+ = model->get_current_thrown_exception ();
+ gcc_assert (curr_thrown_exception_node);
+ tree type = curr_thrown_exception_node->maybe_get_type ();
+ emission_path->add_event
+ (std::make_unique<catch_cfg_edge_event>
+ (eedge,
+ event_loc_info (dst_point.get_supernode ()->get_start_location (),
+ dst_point.get_fndecl (),
+ dst_stack_depth),
+ type));
+ return;
+ }
+ else
+ {
+ /* We have the "uncaught exception" sedge, from eh_dispatch
+ to a block containing resx.
+ Don't add any events for this, so that we can consolidate
+ adjacent stack unwinding events. */
+ return;
+ }
+ }
+
emission_path->add_event
- (make_unique<start_cfg_edge_event>
- (eedge,
- event_loc_info (last_stmt ? last_stmt->location : UNKNOWN_LOCATION,
- src_point.get_fndecl (),
- src_stack_depth)));
+ (std::make_unique<start_cfg_edge_event>
+ (eedge,
+ event_loc_info
+ (last_stmt ? last_stmt->location : UNKNOWN_LOCATION,
+ src_point.get_fndecl (),
+ src_stack_depth)));
emission_path->add_event
- (make_unique<end_cfg_edge_event>
- (eedge,
- event_loc_info (dst_point.get_supernode ()->get_start_location (),
- dst_point.get_fndecl (),
- dst_stack_depth)));
+ (std::make_unique<end_cfg_edge_event>
+ (eedge,
+ event_loc_info (dst_point.get_supernode ()->get_start_location (),
+ dst_point.get_fndecl (),
+ dst_stack_depth)));
}
break;
@@ -2462,12 +2499,13 @@ diagnostic_manager::add_events_for_superedge (const path_builder &pb,
/* TODO: add a subclass for this, or generate events for the
summary. */
emission_path->add_event
- (make_unique<debug_event> (event_loc_info (last_stmt
- ? last_stmt->location
- : UNKNOWN_LOCATION,
- src_point.get_fndecl (),
- src_stack_depth),
- "call summary"));
+ (std::make_unique<debug_event>
+ (event_loc_info (last_stmt
+ ? last_stmt->location
+ : UNKNOWN_LOCATION,
+ src_point.get_fndecl (),
+ src_stack_depth),
+ "call summary"));
}
break;
@@ -2476,14 +2514,13 @@ diagnostic_manager::add_events_for_superedge (const path_builder &pb,
const return_superedge *return_edge
= as_a <const return_superedge *> (eedge.m_sedge);
- const gcall *call_stmt = return_edge->get_call_stmt ();
+ const gcall &call_stmt = return_edge->get_call_stmt ();
emission_path->add_event
- (make_unique<return_event> (eedge,
- event_loc_info (call_stmt
- ? call_stmt->location
- : UNKNOWN_LOCATION,
- dst_point.get_fndecl (),
- dst_stack_depth)));
+ (std::make_unique<return_event>
+ (eedge,
+ event_loc_info (call_stmt.location,
+ dst_point.get_fndecl (),
+ dst_stack_depth)));
}
break;
}
@@ -2512,6 +2549,7 @@ diagnostic_manager::prune_path (checker_path *path,
if (! flag_analyzer_show_events_in_system_headers)
prune_system_headers (path);
consolidate_conditions (path);
+ consolidate_unwind_events (path);
finish_pruning (path);
path->maybe_log (get_logger (), "pruned");
}
@@ -2569,24 +2607,24 @@ diagnostic_manager::prune_for_sm_diagnostic (checker_path *path,
{
label_text sval_desc = sval->get_desc ();
log ("considering event %i (%s), with sval: %qs, state: %qs",
- idx, event_kind_to_string (base_event->m_kind),
+ idx, event_kind_to_string (base_event->get_kind ()),
sval_desc.get (), state->get_name ());
}
else
log ("considering event %i (%s), with global state: %qs",
- idx, event_kind_to_string (base_event->m_kind),
+ idx, event_kind_to_string (base_event->get_kind ()),
state->get_name ());
}
else
log ("considering event %i", idx);
}
- switch (base_event->m_kind)
+ switch (base_event->get_kind ())
{
default:
gcc_unreachable ();
- case EK_DEBUG:
+ case event_kind::debug:
if (m_verbosity < 4)
{
log ("filtering event %i: debug event", idx);
@@ -2594,11 +2632,11 @@ diagnostic_manager::prune_for_sm_diagnostic (checker_path *path,
}
break;
- case EK_CUSTOM:
+ case event_kind::custom:
/* Don't filter custom events. */
break;
- case EK_STMT:
+ case event_kind::stmt:
{
if (m_verbosity < 4)
{
@@ -2608,11 +2646,11 @@ diagnostic_manager::prune_for_sm_diagnostic (checker_path *path,
}
break;
- case EK_REGION_CREATION:
+ case event_kind::region_creation:
/* Don't filter these. */
break;
- case EK_FUNCTION_ENTRY:
+ case event_kind::function_entry:
if (m_verbosity < 1)
{
log ("filtering event %i: function entry", idx);
@@ -2620,7 +2658,7 @@ diagnostic_manager::prune_for_sm_diagnostic (checker_path *path,
}
break;
- case EK_STATE_CHANGE:
+ case event_kind::state_change:
{
state_change_event *state_change = (state_change_event *)base_event;
gcc_assert (state_change->m_dst_state.m_region_model);
@@ -2674,7 +2712,7 @@ diagnostic_manager::prune_for_sm_diagnostic (checker_path *path,
}
break;
- case EK_START_CFG_EDGE:
+ case event_kind::start_cfg_edge:
{
cfg_edge_event *event = (cfg_edge_event *)base_event;
@@ -2687,20 +2725,26 @@ diagnostic_manager::prune_for_sm_diagnostic (checker_path *path,
{
log ("filtering events %i and %i: CFG edge", idx, idx + 1);
path->delete_event (idx);
- /* Also delete the corresponding EK_END_CFG_EDGE. */
- gcc_assert (path->get_checker_event (idx)->m_kind
- == EK_END_CFG_EDGE);
+ /* Also delete the corresponding event_kind::end_cfg_edge. */
+ gcc_assert (path->get_checker_event (idx)->get_kind ()
+ == event_kind::end_cfg_edge);
path->delete_event (idx);
}
}
break;
- case EK_END_CFG_EDGE:
- /* These come in pairs with EK_START_CFG_EDGE events and are
+ case event_kind::end_cfg_edge:
+ /* These come in pairs with event_kind::start_cfg_edge events and are
filtered when their start event is filtered. */
break;
- case EK_CALL_EDGE:
+ case event_kind::catch_:
+ case event_kind::throw_:
+ case event_kind::unwind:
+ /* Don't filter these. */
+ break;
+
+ case event_kind::call_edge:
{
call_event *event = (call_event *)base_event;
const region_model *callee_model
@@ -2741,7 +2785,7 @@ diagnostic_manager::prune_for_sm_diagnostic (checker_path *path,
}
break;
- case EK_RETURN_EDGE:
+ case event_kind::return_edge:
{
if (sval)
{
@@ -2785,19 +2829,19 @@ diagnostic_manager::prune_for_sm_diagnostic (checker_path *path,
}
break;
- case EK_INLINED_CALL:
+ case event_kind::inlined_call:
/* We don't expect to see these yet, as they're added later.
We'd want to keep them around. */
break;
- case EK_SETJMP:
+ case event_kind::setjmp_:
/* TODO: only show setjmp_events that matter i.e. those for which
there is a later rewind event using them. */
- case EK_REWIND_FROM_LONGJMP:
- case EK_REWIND_TO_SETJMP:
+ case event_kind::rewind_from_longjmp:
+ case event_kind::rewind_to_setjmp:
break;
- case EK_WARNING:
+ case event_kind::warning:
/* Always show the final "warning" event in the path. */
break;
}
@@ -3002,7 +3046,7 @@ same_line_as_p (const expanded_location &ref_exp_loc,
const checker_event *ev = path->get_checker_event (idx);
expanded_location idx_exp_loc = expand_location (ev->get_location ());
gcc_assert (ref_exp_loc.file);
- if (idx_exp_loc.file == NULL)
+ if (idx_exp_loc.file == nullptr)
return false;
if (strcmp (ref_exp_loc.file, idx_exp_loc.file))
return false;
@@ -3067,13 +3111,13 @@ diagnostic_manager::consolidate_conditions (checker_path *path) const
= path->get_checker_event (start_idx);
expanded_location start_exp_loc
= expand_location (old_start_ev->get_location ());
- if (start_exp_loc.file == NULL)
+ if (start_exp_loc.file == nullptr)
continue;
if (!same_line_as_p (start_exp_loc, path, start_idx + 1))
continue;
/* Are we looking for a run of all TRUE edges, or all FALSE edges? */
- gcc_assert (old_start_ev->m_kind == EK_START_CFG_EDGE);
+ gcc_assert (old_start_ev->get_kind () == event_kind::start_cfg_edge);
const start_cfg_edge_event *old_start_cfg_ev
= (const start_cfg_edge_event *)old_start_ev;
const cfg_superedge& first_cfg_sedge
@@ -3096,7 +3140,7 @@ diagnostic_manager::consolidate_conditions (checker_path *path) const
{
const checker_event *iter_ev
= path->get_checker_event (next_idx);
- gcc_assert (iter_ev->m_kind == EK_START_CFG_EDGE);
+ gcc_assert (iter_ev->get_kind () == event_kind::start_cfg_edge);
const start_cfg_edge_event *iter_cfg_ev
= (const start_cfg_edge_event *)iter_ev;
const cfg_superedge& iter_cfg_sedge
@@ -3140,6 +3184,50 @@ diagnostic_manager::consolidate_conditions (checker_path *path) const
}
}
+/* Consolidate runs of consecutive unwind_event. */
+
+void
+diagnostic_manager::consolidate_unwind_events (checker_path *path) const
+{
+ /* Don't simplify edges if we're debugging them. */
+ if (flag_analyzer_verbose_edges)
+ return;
+
+ for (int start_idx = 0;
+ start_idx < (signed)path->num_events () - 1;
+ start_idx++)
+ {
+ /* Find a run of consecutive unwind_event instances. */
+ if (path->get_checker_event (start_idx)->get_kind ()
+ != event_kind::unwind)
+ continue;
+ int iter_idx = start_idx + 1;
+ while (iter_idx < (int)path->num_events ())
+ if (path->get_checker_event (iter_idx)->get_kind ()
+ == event_kind::unwind)
+ ++iter_idx;
+ else
+ break;
+
+ /* iter_idx should now be one after the last unwind_event in the run. */
+ const int last_idx = iter_idx - 1;
+ if (last_idx == start_idx)
+ continue;
+
+ gcc_assert (last_idx > start_idx);
+
+ log ("consolidating unwind events %i-%i into %i",
+ start_idx, last_idx, start_idx);
+
+ unwind_event *first_event
+ = (unwind_event *)path->get_checker_event (start_idx);
+ const unwind_event *last_event
+ = (const unwind_event *)path->get_checker_event (last_idx);
+ first_event->m_num_frames += last_event->m_num_frames;
+ path->delete_events (start_idx + 1, last_idx - start_idx);
+ }
+}
+
/* Final pass of diagnostic_manager::prune_path.
If all we're left with is in one function, then filter function entry
@@ -3154,7 +3242,7 @@ diagnostic_manager::finish_pruning (checker_path *path) const
while (idx >= 0 && idx < (signed)path->num_events ())
{
checker_event *base_event = path->get_checker_event (idx);
- if (base_event->m_kind == EK_FUNCTION_ENTRY)
+ if (base_event->get_kind () == event_kind::function_entry)
{
log ("filtering event %i:"
" function entry for purely intraprocedural path", idx);