@@ -65,6 +65,7 @@ class analysis_plan;
class state_purge_map;
class state_purge_per_ssa_name;
class state_change;
+class rewind_info_t;
////////////////////////////////////////////////////////////////////////////
@@ -705,7 +705,7 @@ rewind_event::rewind_event (const exploded_edge *eedge,
: checker_event (kind, loc, fndecl, depth),
m_eedge (eedge)
{
- gcc_assert (m_eedge->m_rewind_info);
+ gcc_assert (m_eedge->m_custom_info); // a rewind_info_t
}
////////////////////////////////////////////////////////////////////////////
@@ -789,7 +789,7 @@ rewind_to_setjmp_event::prepare_for_emission (checker_path *path,
diagnostic_event_id_t emission_id)
{
checker_event::prepare_for_emission (path, pd, emission_id);
- path->get_setjmp_event (get_eedge ()->m_rewind_info->get_enode_origin (),
+ path->get_setjmp_event (m_rewind_info->get_enode_origin (),
&m_original_setjmp_event_id);
}
@@ -428,8 +428,10 @@ class rewind_to_setjmp_event : public rewind_event
{
public:
rewind_to_setjmp_event (const exploded_edge *eedge,
- location_t loc, tree fndecl, int depth)
- : rewind_event (eedge, EK_REWIND_TO_SETJMP, loc, fndecl, depth)
+ location_t loc, tree fndecl, int depth,
+ const rewind_info_t *rewind_info)
+ : rewind_event (eedge, EK_REWIND_TO_SETJMP, loc, fndecl, depth),
+ m_rewind_info (rewind_info)
{
}
@@ -438,7 +440,8 @@ public:
rewind_to_setjmp_event *clone () const FINAL OVERRIDE
{
return new rewind_to_setjmp_event (get_eedge (),
- m_loc, m_fndecl, m_depth);
+ m_loc, m_fndecl, m_depth,
+ m_rewind_info);
}
void prepare_for_emission (checker_path *path,
@@ -447,6 +450,7 @@ public:
private:
diagnostic_event_id_t m_original_setjmp_event_id;
+ const rewind_info_t *m_rewind_info;
};
/* Concrete subclass of checker_event for use at the end of a path:
@@ -655,7 +655,6 @@ diagnostic_manager::add_events_for_eedge (const exploded_edge &eedge,
{
const exploded_node *src_node = eedge.m_src;
const program_point &src_point = src_node->get_point ();
- const int src_stack_depth = src_point.get_stack_depth ();
const exploded_node *dst_node = eedge.m_dest;
const program_point &dst_point = dst_node->get_point ();
const int dst_stack_depth = dst_point.get_stack_depth ();
@@ -693,20 +692,10 @@ diagnostic_manager::add_events_for_eedge (const exploded_edge &eedge,
for_each_state_change (src_state, dst_state, ext_state,
&visitor);
- /* Add events for rewinding from a longjmp to a setjmp. */
- if (eedge.m_rewind_info)
- {
- emission_path->add_event
- (new rewind_from_longjmp_event
- (&eedge, src_point.get_supernode ()->get_end_location (),
- src_point.get_fndecl (),
- src_stack_depth));
- emission_path->add_event
- (new rewind_to_setjmp_event
- (&eedge, eedge.m_rewind_info->get_setjmp_call ()->location,
- dst_point.get_fndecl (),
- dst_stack_depth));
- }
+ /* Allow non-standard edges to add events, e.g. when rewinding from
+ longjmp to a setjmp. */
+ if (eedge.m_custom_info)
+ eedge.m_custom_info->add_events_to_path (emission_path, eedge);
/* Add events for superedges, function entries, and for statements. */
switch (dst_point.get_kind ())
@@ -26,6 +26,7 @@ along with GCC; see the file COPYING3. If not see
#include "gcc-rich-location.h"
#include "analyzer/exploded-graph.h"
#include "analyzer/analysis-plan.h"
+#include "analyzer/checker-path.h"
#include "analyzer/state-purge.h"
/* For an overview, see gcc/doc/analyzer.texi. */
@@ -1247,6 +1248,66 @@ exploded_node::dump_succs_and_preds (FILE *outf) const
////////////////////////////////////////////////////////////////////////////
+/* class rewind_info_t : public exploded_edge::custom_info_t. */
+
+/* Implementation of exploded_edge::custom_info_t::update_model vfunc
+ for rewind_info_t.
+
+ Update state for the special-case of a rewind of a longjmp
+ to a setjmp (which doesn't have a superedge, but does affect
+ state). */
+
+void
+rewind_info_t::update_model (region_model *model,
+ const exploded_edge &eedge)
+{
+ const exploded_node &src_enode = *eedge.m_src;
+ const program_point &src_point = src_enode.get_point ();
+
+ const gimple *last_stmt
+ = src_point.get_supernode ()->get_last_stmt ();
+ gcc_assert (last_stmt);
+ const gcall *longjmp_call = as_a <const gcall *> (last_stmt);
+
+ const program_point &longjmp_point = eedge.m_src->get_point ();
+ const program_point &setjmp_point = eedge.m_dest->get_point ();
+
+ gcc_assert (longjmp_point.get_stack_depth ()
+ >= setjmp_point.get_stack_depth ());
+
+ model->on_longjmp (longjmp_call,
+ get_setjmp_call (),
+ setjmp_point.get_stack_depth (), NULL);
+}
+
+/* Implementation of exploded_edge::custom_info_t::add_events_to_path vfunc
+ for rewind_info_t. */
+
+void
+rewind_info_t::add_events_to_path (checker_path *emission_path,
+ const exploded_edge &eedge)
+{
+ const exploded_node *src_node = eedge.m_src;
+ const program_point &src_point = src_node->get_point ();
+ const int src_stack_depth = src_point.get_stack_depth ();
+ const exploded_node *dst_node = eedge.m_dest;
+ const program_point &dst_point = dst_node->get_point ();
+ const int dst_stack_depth = dst_point.get_stack_depth ();
+
+ emission_path->add_event
+ (new rewind_from_longjmp_event
+ (&eedge, src_point.get_supernode ()->get_end_location (),
+ src_point.get_fndecl (),
+ src_stack_depth));
+ emission_path->add_event
+ (new rewind_to_setjmp_event
+ (&eedge, get_setjmp_call ()->location,
+ dst_point.get_fndecl (),
+ dst_stack_depth, this));
+}
+
+////////////////////////////////////////////////////////////////////////////
+
/* class exploded_edge : public dedge. */
/* exploded_edge's ctor. */
@@ -1254,9 +1315,9 @@ exploded_node::dump_succs_and_preds (FILE *outf) const
exploded_edge::exploded_edge (exploded_node *src, exploded_node *dest,
const superedge *sedge,
const state_change &change,
- rewind_info_t *rewind_info)
+ custom_info_t *custom_info)
: dedge (src, dest), m_sedge (sedge), m_change (change),
- m_rewind_info (rewind_info)
+ m_custom_info (custom_info)
{
change.validate (dest->get_state ());
}
@@ -1265,7 +1326,7 @@ exploded_edge::exploded_edge (exploded_node *src, exploded_node *dest,
exploded_edge::~exploded_edge ()
{
- delete m_rewind_info;
+ delete m_custom_info;
}
/* Implementation of dedge::dump_dot vfunc for exploded_edge.
@@ -1300,7 +1361,7 @@ exploded_edge::dump_dot (graphviz_out *gv, const dump_args_t &args) const
style = "\"dotted\"";
break;
}
- if (m_rewind_info)
+ if (m_custom_info)
{
color = "red";
style = "\"dotted\"";
@@ -1316,8 +1377,8 @@ exploded_edge::dump_dot (graphviz_out *gv, const dump_args_t &args) const
if (m_sedge)
m_sedge->dump_label_to_pp (pp, false);
- else if (m_rewind_info)
- pp_string (pp, "rewind");
+ else if (m_custom_info)
+ m_custom_info->print (pp);
m_change.dump (pp, args.m_eg.get_ext_state ());
//pp_write_text_as_dot_label_to_stream (pp, /*for_record=*/false);
@@ -1859,9 +1920,9 @@ exploded_edge *
exploded_graph::add_edge (exploded_node *src, exploded_node *dest,
const superedge *sedge,
const state_change &change,
- rewind_info_t *rewind_info)
+ exploded_edge::custom_info_t *custom_info)
{
- exploded_edge *e = new exploded_edge (src, dest, sedge, change, rewind_info);
+ exploded_edge *e = new exploded_edge (src, dest, sedge, change, custom_info);
digraph::add_edge (e);
return e;
}
@@ -2569,7 +2630,10 @@ exploded_path::feasible_p (logger *logger) const
if (!model.maybe_update_for_edge (*sedge, last_stmt, NULL))
{
if (logger)
- logger->log ("rejecting due to region model");
+ {
+ logger->log ("rejecting due to region model");
+ model.dump_to_pp (logger->get_printer (), false);
+ }
return false;
}
}
@@ -2589,26 +2653,8 @@ exploded_path::feasible_p (logger *logger) const
if (logger)
logger->log (" pushing frame for %qD", fun->decl);
}
- else if (eedge->m_rewind_info)
- {
- /* Update state for the special-case of a rewind of a longjmp
- to a setjmp (which doesn't have a superedge, but does affect
- state). */
- const gimple *last_stmt
- = src_point.get_supernode ()->get_last_stmt ();
- gcc_assert (last_stmt);
- const gcall *longjmp_call = as_a <const gcall *> (last_stmt);
-
- const program_point &longjmp_point = eedge->m_src->get_point ();
- const program_point &setjmp_point = eedge->m_dest->get_point ();
-
- gcc_assert (longjmp_point.get_stack_depth ()
- >= setjmp_point.get_stack_depth ());
-
- model.on_longjmp (longjmp_call,
- eedge->m_rewind_info->get_setjmp_call (),
- setjmp_point.get_stack_depth (), NULL);
- }
+ else if (eedge->m_custom_info)
+ eedge->m_custom_info->update_model (&model, *eedge);
}
/* Handle phi nodes on an edge leaving a PK_BEFORE_SUPERNODE (to
@@ -252,16 +252,73 @@ public:
const int m_index;
};
+/* An edge within the exploded graph.
+ Some exploded_edges have an underlying superedge; others don't. */
+
+class exploded_edge : public dedge<eg_traits>
+{
+ public:
+ /* Abstract base class for associating custom data with an
+ exploded_edge, for handling non-standard edges such as
+ rewinding from a longjmp, signal handlers, etc. */
+ class custom_info_t
+ {
+ public:
+ virtual ~custom_info_t () {}
+
+ /* Hook for making .dot label more readable . */
+ virtual void print (pretty_printer *pp) = 0;
+
+ /* Hook for updating MODEL within exploded_path::feasible_p. */
+ virtual void update_model (region_model *model,
+ const exploded_edge &eedge) = 0;
+
+ virtual void add_events_to_path (checker_path *emission_path,
+ const exploded_edge &eedge) = 0;
+ };
+
+ exploded_edge (exploded_node *src, exploded_node *dest,
+ const superedge *sedge,
+ const state_change &change,
+ custom_info_t *custom_info);
+ ~exploded_edge ();
+ void dump_dot (graphviz_out *gv, const dump_args_t &args)
+ const FINAL OVERRIDE;
+
+ //private:
+ const superedge *const m_sedge;
+
+ const state_change m_change;
+
+ /* NULL for most edges; will be non-NULL for special cases
+ such as an unwind from a longjmp to a setjmp, or when
+ a signal is delivered to a signal-handler.
+
+ Owned by this class. */
+ custom_info_t *m_custom_info;
+};
+
/* Extra data for an exploded_edge that represents a rewind from a
longjmp to a setjmp. */
-class rewind_info_t
+class rewind_info_t : public exploded_edge::custom_info_t
{
public:
rewind_info_t (const exploded_node *enode_origin)
: m_enode_origin (enode_origin)
{}
+ void print (pretty_printer *pp) FINAL OVERRIDE
+ {
+ pp_string (pp, "rewind");
+ }
+
+ void update_model (region_model *model,
+ const exploded_edge &eedge) FINAL OVERRIDE;
+
+ void add_events_to_path (checker_path *emission_path,
+ const exploded_edge &eedge) FINAL OVERRIDE;
+
const program_point &get_setjmp_point () const
{
const program_point &origin_point = m_enode_origin->get_point ();
@@ -285,30 +342,6 @@ private:
const exploded_node *m_enode_origin;
};
-/* An edge within the exploded graph.
- Some exploded_edges have an underlying superedge; others don't. */
-
-class exploded_edge : public dedge<eg_traits>
-{
- public:
- exploded_edge (exploded_node *src, exploded_node *dest,
- const superedge *sedge,
- const state_change &change,
- rewind_info_t *rewind_info);
- ~exploded_edge ();
- void dump_dot (graphviz_out *gv, const dump_args_t &args)
- const FINAL OVERRIDE;
-
- //private:
- const superedge *const m_sedge;
-
- const state_change m_change;
-
- /* NULL for most edges; will be non-NULL for an unwind from a longjmp
- to a setjmp (owned by this class). */
- rewind_info_t *m_rewind_info;
-};
-
/* Statistics about aspects of an exploded_graph. */
struct stats
@@ -665,7 +698,7 @@ public:
exploded_edge *add_edge (exploded_node *src, exploded_node *dest,
const superedge *sedge,
const state_change &change,
- rewind_info_t *rewind_info = NULL);
+ exploded_edge::custom_info_t *custom = NULL);
per_program_point_data *
get_or_create_per_program_point_data (const program_point &);