aboutsummaryrefslogtreecommitdiff
path: root/gcc/analyzer/program-state.h
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/analyzer/program-state.h')
-rw-r--r--gcc/analyzer/program-state.h240
1 files changed, 69 insertions, 171 deletions
diff --git a/gcc/analyzer/program-state.h b/gcc/analyzer/program-state.h
index 3637516..cb0df8c 100644
--- a/gcc/analyzer/program-state.h
+++ b/gcc/analyzer/program-state.h
@@ -28,8 +28,10 @@ namespace ana {
class extrinsic_state
{
public:
- extrinsic_state (auto_delete_vec <state_machine> &checkers)
- : m_checkers (checkers)
+ extrinsic_state (auto_delete_vec <state_machine> &checkers,
+ logger *logger = NULL,
+ engine *eng = NULL)
+ : m_checkers (checkers), m_logger (logger), m_engine (eng)
{
}
@@ -45,65 +47,24 @@ public:
unsigned get_num_checkers () const { return m_checkers.length (); }
+ logger *get_logger () const { return m_logger; }
+
void dump_to_pp (pretty_printer *pp) const;
void dump_to_file (FILE *outf) const;
void dump () const;
+ engine *get_engine () const { return m_engine; }
+ region_model_manager *get_model_manager () const;
+
private:
/* The state machines. */
auto_delete_vec <state_machine> &m_checkers;
-};
-} // namespace ana
-
-template <> struct default_hash_traits<svalue_id>
-: public pod_hash_traits<svalue_id>
-{
- static const bool empty_zero_p = false;
+ logger *m_logger;
+ engine *m_engine;
};
-template <>
-inline hashval_t
-pod_hash_traits<svalue_id>::hash (value_type v)
-{
- return v.as_int ();
-}
-
-template <>
-inline bool
-pod_hash_traits<svalue_id>::equal (const value_type &existing,
- const value_type &candidate)
-{
- return existing == candidate;
-}
-template <>
-inline void
-pod_hash_traits<svalue_id>::mark_deleted (value_type &v)
-{
- v = svalue_id::from_int (-2);
-}
-template <>
-inline void
-pod_hash_traits<svalue_id>::mark_empty (value_type &v)
-{
- v = svalue_id::null ();
-}
-template <>
-inline bool
-pod_hash_traits<svalue_id>::is_deleted (value_type v)
-{
- return v.as_int () == -2;
-}
-template <>
-inline bool
-pod_hash_traits<svalue_id>::is_empty (value_type v)
-{
- return v.null_p ();
-}
-
-namespace ana {
-
-/* Map from svalue_id to state machine state, also capturing the origin of
+/* Map from svalue * to state machine state, also capturing the origin of
each state. */
class sm_state_map
@@ -114,12 +75,12 @@ public:
{
/* Default ctor needed by hash_map::empty. */
entry_t ()
- : m_state (0), m_origin (svalue_id::null ())
+ : m_state (0), m_origin (NULL)
{
}
entry_t (state_machine::state_t state,
- svalue_id origin)
+ const svalue *origin)
: m_state (state), m_origin (origin)
{}
@@ -134,21 +95,19 @@ public:
}
state_machine::state_t m_state;
- svalue_id m_origin;
+ const svalue *m_origin;
};
- typedef hash_map <svalue_id, entry_t> map_t;
+ typedef hash_map <const svalue *, entry_t> map_t;
typedef map_t::iterator iterator_t;
- sm_state_map ();
+ sm_state_map (const state_machine &sm, int m_sm_idx);
sm_state_map *clone () const;
- sm_state_map *
- clone_with_remapping (const one_way_svalue_id_map &id_map) const;
-
- void print (const state_machine &sm, const region_model *model,
+ void print (const region_model *model,
+ bool simple, bool multiline,
pretty_printer *pp) const;
- void dump (const state_machine &sm) const;
+ void dump (bool simple) const;
bool is_empty_p () const;
@@ -160,51 +119,47 @@ public:
return !(*this == other);
}
- state_machine::state_t get_state (svalue_id sid) const;
- svalue_id get_origin (svalue_id sid) const;
+ state_machine::state_t get_state (const svalue *sval,
+ const extrinsic_state &ext_state) const;
+ const svalue *get_origin (const svalue *sval,
+ const extrinsic_state &ext_state) const;
void set_state (region_model *model,
- svalue_id sid,
+ const svalue *sval,
state_machine::state_t state,
- svalue_id origin);
+ const svalue *origin,
+ const extrinsic_state &ext_state);
bool set_state (const equiv_class &ec,
state_machine::state_t state,
- svalue_id origin);
- bool impl_set_state (svalue_id sid,
+ const svalue *origin,
+ const extrinsic_state &ext_state);
+ bool impl_set_state (const svalue *sval,
state_machine::state_t state,
- svalue_id origin);
+ const svalue *origin,
+ const extrinsic_state &ext_state);
void set_global_state (state_machine::state_t state);
state_machine::state_t get_global_state () const;
- void purge_for_unknown_fncall (const exploded_graph &eg,
- const state_machine &sm,
- const gcall *call, tree fndecl,
- region_model *new_model,
- region_model_context *ctxt);
-
- void remap_svalue_ids (const svalue_id_map &map);
-
- int on_svalue_purge (const state_machine &sm,
- int sm_idx,
- svalue_id first_unused_sid,
- const svalue_id_map &map,
+ void on_svalue_leak (const svalue *sval,
impl_region_model_context *ctxt);
+ void on_liveness_change (const svalue_set &live_svalues,
+ const region_model *model,
+ impl_region_model_context *ctxt);
- void on_inherited_svalue (svalue_id parent_sid,
- svalue_id child_sid);
-
- void on_cast (svalue_id src_sid,
- svalue_id dst_sid);
-
- void on_unknown_change (svalue_id sid);
-
- void validate (const state_machine &sm, int num_svalues) const;
+ void on_unknown_change (const svalue *sval,
+ bool is_mutable,
+ const extrinsic_state &ext_state);
iterator_t begin () const { return m_map.begin (); }
iterator_t end () const { return m_map.end (); }
+ static const svalue *
+ canonicalize_svalue (const svalue *sval, const extrinsic_state &ext_state);
+
private:
+ const state_machine &m_sm;
+ int m_sm_idx;
map_t m_map;
state_machine::state_t m_global_state;
};
@@ -229,7 +184,6 @@ public:
#if __cplusplus >= 201103
program_state (program_state &&other);
- program_state& operator= (program_state &&other); // doesn't seem to be used
#endif
~program_state ();
@@ -244,27 +198,27 @@ public:
void print (const extrinsic_state &ext_state,
pretty_printer *pp) const;
- void dump_to_pp (const extrinsic_state &ext_state, bool summarize,
- pretty_printer *pp) const;
- void dump_to_file (const extrinsic_state &ext_state, bool summarize,
- FILE *outf) const;
- void dump (const extrinsic_state &ext_state, bool summarize) const;
+ void dump_to_pp (const extrinsic_state &ext_state, bool simple,
+ bool multiline, pretty_printer *pp) const;
+ void dump_to_file (const extrinsic_state &ext_state, bool simple,
+ bool multiline, FILE *outf) const;
+ void dump (const extrinsic_state &ext_state, bool simple) const;
+
+ void push_frame (const extrinsic_state &ext_state, function *fun);
+ function * get_current_function () const;
bool on_edge (exploded_graph &eg,
const exploded_node &enode,
- const superedge *succ,
- state_change *change);
+ const superedge *succ);
program_state prune_for_point (exploded_graph &eg,
const program_point &point,
- state_change *change) const;
+ const exploded_node *enode_for_diag) const;
- void remap_svalue_ids (const svalue_id_map &map);
-
- tree get_representative_tree (svalue_id sid) const;
+ tree get_representative_tree (const svalue *sval) const;
bool can_purge_p (const extrinsic_state &ext_state,
- svalue_id sid)
+ const svalue *sval)
{
/* Don't purge vars that have non-purgeable sm state, to avoid
generating false "leak" complaints. */
@@ -273,18 +227,24 @@ public:
FOR_EACH_VEC_ELT (m_checker_states, i, smap)
{
const state_machine &sm = ext_state.get_sm (i);
- if (!sm.can_purge_p (smap->get_state (sid)))
+ if (!sm.can_purge_p (smap->get_state (sval, ext_state)))
return false;
}
return true;
}
bool can_merge_with_p (const program_state &other,
- const extrinsic_state &ext_state,
+ const program_point &point,
program_state *out) const;
void validate (const extrinsic_state &ext_state) const;
+ static void detect_leaks (const program_state &src_state,
+ const program_state &dest_state,
+ const svalue *extra_sval,
+ const extrinsic_state &ext_state,
+ region_model_context *ctxt);
+
/* TODO: lose the pointer here (const-correctness issues?). */
region_model *m_region_model;
auto_delete_vec<sm_state_map> m_checker_states;
@@ -311,76 +271,14 @@ public:
virtual bool on_state_change (const state_machine &sm,
state_machine::state_t src_sm_val,
state_machine::state_t dst_sm_val,
- tree dst_rep,
- svalue_id dst_origin_sid) = 0;
+ const svalue *dst_sval,
+ const svalue *dst_origin_sval) = 0;
};
extern bool for_each_state_change (const program_state &src_state,
- const program_state &dst_state,
- const extrinsic_state &ext_state,
- state_change_visitor *visitor);
-
-/* A class for recording "interesting" state changes.
- This is used for annotating edges in the GraphViz output of the
- exploded_graph, and for recording sm-state-changes, so that
- values that change aren't purged (to make it easier to generate
- state_change_event instances in the diagnostic_path). */
-
-class state_change
-{
- public:
- struct sm_change
- {
- sm_change (int sm_idx,
- svalue_id new_sid,
- state_machine::state_t old_state,
- state_machine::state_t new_state)
- : m_sm_idx (sm_idx),
- m_new_sid (new_sid),
- m_old_state (old_state), m_new_state (new_state)
- {}
-
- const state_machine &get_sm (const extrinsic_state &ext_state) const
- {
- return ext_state.get_sm (m_sm_idx);
- }
-
- void dump (pretty_printer *pp, const extrinsic_state &ext_state) const;
-
- void remap_svalue_ids (const svalue_id_map &map);
- int on_svalue_purge (svalue_id first_unused_sid);
-
- void validate (const program_state &new_state,
- const extrinsic_state &ext_state) const;
-
- int m_sm_idx;
- svalue_id m_new_sid;
- state_machine::state_t m_old_state;
- state_machine::state_t m_new_state;
- };
-
- state_change ();
- state_change (const state_change &other);
-
- void add_sm_change (int sm_idx,
- svalue_id new_sid,
- state_machine::state_t old_state,
- state_machine::state_t new_state);
-
- bool affects_p (svalue_id sid) const;
-
- void dump (pretty_printer *pp, const extrinsic_state &ext_state) const;
- void dump (const extrinsic_state &ext_state) const;
-
- void remap_svalue_ids (const svalue_id_map &map);
- int on_svalue_purge (svalue_id first_unused_sid);
-
- void validate (const program_state &new_state,
- const extrinsic_state &ext_state) const;
-
- private:
- auto_vec<sm_change> m_sm_changes;
-};
+ const program_state &dst_state,
+ const extrinsic_state &ext_state,
+ state_change_visitor *visitor);
} // namespace ana