From 1449aa6f462dbba827226d25c8be69a3b565fcaf Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Wed, 15 Apr 2020 00:39:00 -0400 Subject: [PATCH 039/179] FIXME: start wiring up region_model2 into program_state --- gcc/analyzer/analyzer.h | 43 +++++++++++ gcc/analyzer/engine.cc | 21 +++++- gcc/analyzer/program-state.cc | 38 +++++++++- gcc/analyzer/program-state.h | 8 ++- gcc/analyzer/region-model.h | 46 ------------ gcc/analyzer/region-model2.cc | 90 +++++++++++------------ gcc/analyzer/region-model2.h | 130 +++++++++++++++------------------- gcc/analyzer/revamp-state.cc | 1 + 8 files changed, 210 insertions(+), 167 deletions(-) diff --git a/gcc/analyzer/analyzer.h b/gcc/analyzer/analyzer.h index a73ffdf5696..a85edb99db0 100644 --- a/gcc/analyzer/analyzer.h +++ b/gcc/analyzer/analyzer.h @@ -90,11 +90,54 @@ class state_change; class rewind_info_t; class engine; +class engine2; /* Forward decls of functions. */ extern void dump_quoted_tree (pretty_printer *pp, tree t); +/* A tree, extended with stack frame information for locals, so that + we can distinguish between different values of locals within a potentially + recursive callstack. */ +// TODO: would this be better as a new tree code? + +class path_var +{ +public: + path_var (tree t, int stack_depth) + : m_tree (t), m_stack_depth (stack_depth) + { + // TODO: ignore stack depth for globals and constants + } + + bool operator== (const path_var &other) const + { + return (m_tree == other.m_tree + && m_stack_depth == other.m_stack_depth); + } + + void dump (pretty_printer *pp) const; + + tree m_tree; + int m_stack_depth; // or -1 for globals? +}; + +/* An enum describing a particular kind of "poisoned" value. */ + +enum poison_kind +{ + /* For use to describe uninitialized memory. */ + POISON_KIND_UNINIT, + + /* For use to describe freed memory. */ + POISON_KIND_FREED, + + /* For use on pointers to regions within popped stack frames. */ + POISON_KIND_POPPED_STACK +}; + +extern const char *poison_kind_to_str (enum poison_kind); + } // namespace ana extern bool is_special_named_call_p (const gcall *call, const char *funcname, diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc index 4a6272e875f..05b607efede 100644 --- a/gcc/analyzer/engine.cc +++ b/gcc/analyzer/engine.cc @@ -40,6 +40,7 @@ along with GCC; see the file COPYING3. If not see #include "analyzer/analyzer.h" #include "analyzer/analyzer-logging.h" #include "analyzer/region-model.h" +#include "analyzer/region-model2.h" #include "analyzer/constraint-manager.h" #include "analyzer/sm.h" #include "analyzer/pending-diagnostic.h" @@ -1022,11 +1023,22 @@ exploded_node::on_stmt (exploded_graph &eg, state_change *change) const { if (state->m_revamp_state) + { + if (state->m_revamp_state->on_stmt (eg.get_ext_state (), snode, stmt)) + return on_stmt_flags (false); + else + return on_stmt_flags::terminate_path (); + } + else if (state->m_region_model2) { - if (state->m_revamp_state->on_stmt (eg.get_ext_state (), snode, stmt)) + // TODO: + gcc_unreachable (); +#if 0 + if (state->m_region_model2->on_stmt (eg.get_ext_state (), snode, stmt)) return on_stmt_flags (false); else return on_stmt_flags::terminate_path (); +#endif } /* Preserve the old state. It is used here for looking @@ -4015,6 +4027,10 @@ impl_run_checkers (logger *logger) if (getenv ("REVAMP")) eng = new engine (); + engine2 *eng2 = NULL; + if (getenv ("REVAMP2")) + eng2 = new engine2 (); + /* Create the supergraph. */ supergraph sg (logger); @@ -4055,7 +4071,7 @@ impl_run_checkers (logger *logger) } /* Extrinsic state shared by nodes in the graph. */ - const extrinsic_state ext_state (checkers, logger, eng); + const extrinsic_state ext_state (checkers, logger, eng, eng2); const analysis_plan plan (sg, logger); @@ -4102,6 +4118,7 @@ impl_run_checkers (logger *logger) } delete purge_map; + delete eng2; delete eng; } diff --git a/gcc/analyzer/program-state.cc b/gcc/analyzer/program-state.cc index a79dc10d448..a9b29efe2f2 100644 --- a/gcc/analyzer/program-state.cc +++ b/gcc/analyzer/program-state.cc @@ -34,6 +34,7 @@ along with GCC; see the file COPYING3. If not see #include "ordered-hash-map.h" #include "selftest.h" #include "analyzer/region-model.h" +#include "analyzer/region-model2.h" #include "analyzer/program-state.h" #include "analyzer/constraint-manager.h" #include "alloc-pool.h" @@ -596,12 +597,15 @@ sm_state_map::validate (const state_machine &sm, program_state::program_state (const extrinsic_state &ext_state) : m_revamp_state (NULL), + m_region_model2 (NULL), m_region_model (NULL), m_checker_states (ext_state.get_num_checkers ()), m_valid (true) { if (ext_state.get_engine ()) m_revamp_state = new revamp_state (ext_state); + else if (ext_state.get_engine2 ()) + m_region_model2 = new region_model2 (); else m_region_model = new region_model (); int num_states = ext_state.get_num_checkers (); @@ -613,10 +617,13 @@ program_state::program_state (const extrinsic_state &ext_state) program_state::program_state (const program_state &other) : m_revamp_state (other.m_revamp_state), + m_region_model2 (NULL), m_region_model (NULL), m_checker_states (other.m_checker_states.length ()), m_valid (true) { + if (other.m_region_model2) + m_region_model2 = new region_model2 (*other.m_region_model2); if (other.m_region_model) m_region_model = new region_model (*other.m_region_model); int i; @@ -631,6 +638,9 @@ program_state& program_state::operator= (const program_state &other) { m_revamp_state = other.m_revamp_state; + delete m_region_model2; + if (other.m_region_model2) + m_region_model2 = new region_model2 (*other.m_region_model2); delete m_region_model; if (other.m_region_model) m_region_model = new region_model (*other.m_region_model); @@ -654,9 +664,11 @@ program_state::operator= (const program_state &other) /* Move constructor for program_state (when building with C++11). */ program_state::program_state (program_state &&other) : m_revamp_state (other.m_revamp_state), + m_region_model2 (other.m_region_model2), m_region_model (other.m_region_model), m_checker_states (other.m_checker_states.length ()) { + other.m_region_model2 = NULL; other.m_region_model = NULL; int i; @@ -673,6 +685,7 @@ program_state::program_state (program_state &&other) program_state::~program_state () { + delete m_region_model2; delete m_region_model; } @@ -683,6 +696,12 @@ program_state::hash () const { hashval_t result = 0; + // TODO: +#if 0 + if (m_region_model2) + result ^= m_region_model2->hash (); +#endif + if (m_region_model) result ^= m_region_model->hash (); @@ -818,6 +837,10 @@ program_state::to_json () const json::object *obj = new json::object (); if (m_revamp_state) obj->set ("revamp_state", m_revamp_state->to_json ()); +#if 0 + if (m_region_model2 + obj->set ("region_model2", m_region_model2->to_json ()); +#endif return obj; } @@ -829,7 +852,11 @@ program_state::push_frame (const extrinsic_state &ext_state, { // TODO } - if (m_region_model) + else if (m_region_model2) + { + // TODO + } + else if (m_region_model) { impl_region_model_context ctxt (this, NULL, ext_state, ext_state.get_logger ()); m_region_model->push_frame (fun, NULL, &ctxt); @@ -871,6 +898,15 @@ program_state::on_edge (exploded_graph &eg, return m_revamp_state->maybe_update_for_edge (*succ, last_stmt); } + else if (m_region_model2) + { + engine2 *eng2 = eg.get_ext_state ().get_engine2 (); + region_model2_manager *mgr = eng2->get_model_manager (); + return m_region_model2->maybe_update_for_edge (mgr, + *succ, + last_stmt, + NULL); // FIXME: ctxt! + } impl_region_model_context ctxt (eg, &enode, &enode.get_state (), diff --git a/gcc/analyzer/program-state.h b/gcc/analyzer/program-state.h index 70ef9656d3a..b1a3b7a5652 100644 --- a/gcc/analyzer/program-state.h +++ b/gcc/analyzer/program-state.h @@ -30,8 +30,9 @@ class extrinsic_state public: extrinsic_state (auto_delete_vec &checkers, logger *logger = NULL, - engine *eng = NULL) - : m_checkers (checkers), m_logger (logger), m_engine (eng) + engine *eng = NULL, + engine2 *eng2 = NULL) + : m_checkers (checkers), m_logger (logger), m_engine (eng), m_engine2 (eng2) { } @@ -54,6 +55,7 @@ public: void dump () const; engine *get_engine () const { return m_engine; } + engine2 *get_engine2 () const { return m_engine2; } private: /* The state machines. */ @@ -61,6 +63,7 @@ private: logger *m_logger; engine *m_engine; + engine2 *m_engine2; }; } // namespace ana @@ -300,6 +303,7 @@ public: void validate (const extrinsic_state &ext_state) const; revamp_state *m_revamp_state; + region_model2 *m_region_model2; /* TODO: lose the pointer here (const-correctness issues?). */ region_model *m_region_model; auto_delete_vec m_checker_states; diff --git a/gcc/analyzer/region-model.h b/gcc/analyzer/region-model.h index 2c9ee39a38d..b1fe3c796bb 100644 --- a/gcc/analyzer/region-model.h +++ b/gcc/analyzer/region-model.h @@ -26,38 +26,8 @@ along with GCC; see the file COPYING3. If not see (Zhongxing Xu, Ted Kremenek, and Jian Zhang) http://lcs.ios.ac.cn/~xuzb/canalyze/memmodel.pdf */ -/* A tree, extended with stack frame information for locals, so that - we can distinguish between different values of locals within a potentially - recursive callstack. */ -// TODO: would this be better as a new tree code? - using namespace ana; -namespace ana { - -class path_var -{ -public: - path_var (tree t, int stack_depth) - : m_tree (t), m_stack_depth (stack_depth) - { - // TODO: ignore stack depth for globals and constants - } - - bool operator== (const path_var &other) const - { - return (m_tree == other.m_tree - && m_stack_depth == other.m_stack_depth); - } - - void dump (pretty_printer *pp) const; - - tree m_tree; - int m_stack_depth; // or -1 for globals? -}; - -} // namespace ana - namespace inchash { extern void add_path_var (path_var pv, hash &hstate); @@ -680,22 +650,6 @@ public: FINAL OVERRIDE; }; -/* An enum describing a particular kind of "poisoned" value. */ - -enum poison_kind -{ - /* For use to describe uninitialized memory. */ - POISON_KIND_UNINIT, - - /* For use to describe freed memory. */ - POISON_KIND_FREED, - - /* For use on pointers to regions within popped stack frames. */ - POISON_KIND_POPPED_STACK -}; - -extern const char *poison_kind_to_str (enum poison_kind); - /* Concrete subclass of svalue representing a value that should not be used (e.g. uninitialized memory, freed memory). */ diff --git a/gcc/analyzer/region-model2.cc b/gcc/analyzer/region-model2.cc index 061b5fa62bf..f94a615508f 100644 --- a/gcc/analyzer/region-model2.cc +++ b/gcc/analyzer/region-model2.cc @@ -2959,10 +2959,10 @@ element_region2::add_to_hash (inchash::hash &hstate) const hstate.add_ptr (m_index); } -/* class binding_key. */ +/* class binding_key2. */ -const binding_key * -binding_key::make (region_model2_manager *mgr, region2 *r, enum kind kind) +const binding_key2 * +binding_key2::make (region_model2_manager *mgr, region2 *r, enum kind kind) { region_offset offset = r->get_offset (); // FIXME: what if symbolic vs concrete? @@ -2973,17 +2973,17 @@ binding_key::make (region_model2_manager *mgr, region2 *r, enum kind kind) /* FIXME. */ int -binding_key::cmp_ptrs (const void *p1, const void *p2) +binding_key2::cmp_ptrs (const void *p1, const void *p2) { - const binding_key * const *pk1 = (const binding_key * const *)p1; - const binding_key * const *pk2 = (const binding_key * const *)p2; + const binding_key2 * const *pk1 = (const binding_key2 * const *)p1; + const binding_key2 * const *pk2 = (const binding_key2 * const *)p2; return cmp (*pk1, *pk2); } /* FIXME. */ int -binding_key::cmp (const binding_key *k1, const binding_key *k2) +binding_key2::cmp (const binding_key2 *k1, const binding_key2 *k2) { if (int reg_cmp = region2::cmp_ids (k1->m_region, k2->m_region)) return reg_cmp; @@ -2999,8 +2999,8 @@ binding_key::cmp (const binding_key *k1, const binding_key *k2) return concrete_cmp; if (concrete1) { - const concrete_binding *b1 = (const concrete_binding *)k1; - const concrete_binding *b2 = (const concrete_binding *)k2; + const concrete_binding2 *b1 = (const concrete_binding2 *)k1; + const concrete_binding2 *b2 = (const concrete_binding2 *)k2; return wi::cmp (b1->get_bit_offset (), b2->get_bit_offset (), SIGNED); } else @@ -3010,24 +3010,24 @@ binding_key::cmp (const binding_key *k1, const binding_key *k2) } } -/* class binding_cluster. */ +/* class binding_cluster2. */ void -binding_cluster::dump_to_pp (pretty_printer *pp, bool simple) const +binding_cluster2::dump_to_pp (pretty_printer *pp, bool simple) const { - auto_vec binding_keys; + auto_vec binding_key2s; for (map_t::iterator iter = m_map.begin (); iter != m_map.end (); ++iter) { - const binding_key *key = (*iter).first; - binding_keys.safe_push (key); + const binding_key2 *key = (*iter).first; + binding_key2s.safe_push (key); } - binding_keys.qsort (binding_key::cmp_ptrs); + binding_key2s.qsort (binding_key2::cmp_ptrs); - const binding_key *key; + const binding_key2 *key; unsigned i; - FOR_EACH_VEC_ELT (binding_keys, i, key) + FOR_EACH_VEC_ELT (binding_key2s, i, key) { if (i > 0) pp_string (pp, ", "); @@ -3041,19 +3041,19 @@ binding_cluster::dump_to_pp (pretty_printer *pp, bool simple) const } void -binding_cluster::bind (region_model2_manager *mgr, +binding_cluster2::bind (region_model2_manager *mgr, region2 *reg, svalue2 *val) { - const binding_key *binding - = binding_key::make (mgr, reg, binding_key::BK_direct); + const binding_key2 *binding + = binding_key2::make (mgr, reg, binding_key2::BK_direct); m_map.put (binding, val); } svalue2 * -binding_cluster::get_binding (region_model2_manager *mgr, region2 *reg, - binding_key::kind kind) const +binding_cluster2::get_binding (region_model2_manager *mgr, region2 *reg, + binding_key2::kind kind) const { - const binding_key *binding = binding_key::make (mgr, reg, kind); + const binding_key2 *binding = binding_key2::make (mgr, reg, kind); svalue2 **slot = const_cast (m_map).get (binding); if (slot) return *slot; @@ -3063,8 +3063,8 @@ binding_cluster::get_binding (region_model2_manager *mgr, region2 *reg, /* Populate OUT with all bindings within this cluster that overlap REG. */ void -binding_cluster::get_overlapping_bindings (region2 *reg, - auto_vec *out) +binding_cluster2::get_overlapping_bindings (region2 *reg, + auto_vec *out) { /* Get the size of REG. */ // TODO @@ -3072,7 +3072,7 @@ binding_cluster::get_overlapping_bindings (region2 *reg, for (map_t::iterator iter = m_map.begin (); iter != m_map.end (); ++iter) { - const binding_key *key = (*iter).first; + const binding_key2 *key = (*iter).first; // TODO } } @@ -3080,10 +3080,10 @@ binding_cluster::get_overlapping_bindings (region2 *reg, /* FIXME. */ void -binding_cluster::remove_overlapping_bindings (region_model2_manager *mgr, +binding_cluster2::remove_overlapping_bindings (region_model2_manager *mgr, region2 *reg) { - auto_vec bindings; + auto_vec bindings; get_overlapping_bindings (reg, &bindings); // TODO //gcc_unreachable (); @@ -3156,22 +3156,22 @@ region_model2_manager::get_element_region (region2 *parent, return const_cast (m_elements.consolidate (element_reg)); } -const concrete_binding * +const concrete_binding2 * region_model2_manager::get_concrete_binding (const region2 *reg, - enum binding_key::kind kind, - concrete_binding::bit_offset_t offset) + enum binding_key2::kind kind, + concrete_binding2::bit_offset_t offset) { - concrete_binding *b = new concrete_binding (reg, kind, offset); + concrete_binding2 *b = new concrete_binding2 (reg, kind, offset); return m_concrete_binding_key_mgr.consolidate (b); } -const symbolic_binding * +const symbolic_binding2 * region_model2_manager::get_symbolic_binding (const region2 *reg, - enum binding_key::kind kind, + enum binding_key2::kind kind, region2 *concrete_offset_region) { - symbolic_binding *b - = new symbolic_binding (reg, kind, concrete_offset_region); + symbolic_binding2 *b + = new symbolic_binding2 (reg, kind, concrete_offset_region); return m_symbolic_binding_key_mgr.consolidate (b); } @@ -3438,7 +3438,7 @@ region_model2::dump_to_pp (pretty_printer *pp, bool summarize) const { if (i > 0) pp_string (pp, ", "); - binding_cluster *cluster + binding_cluster2 *cluster = *const_cast (m_cluster_map).get (base_reg); pp_string (pp, "base region: {"); base_reg->dump_to_pp (pp, summarize); @@ -4878,21 +4878,21 @@ region_model2::get_store_value (region_model2_manager *mgr, region2 *reg) svalue2 * region_model2::get_direct_binding (region_model2_manager *mgr, region2 *reg) { - return get_binding (mgr, reg, binding_key::BK_direct); + return get_binding (mgr, reg, binding_key2::BK_direct); } svalue2 * region_model2::get_default_binding (region_model2_manager *mgr, region2 *reg) { - return get_binding (mgr, reg, binding_key::BK_direct); + return get_binding (mgr, reg, binding_key2::BK_direct); } svalue2 * region_model2::get_binding (region_model2_manager *mgr, region2 *reg, - binding_key::kind kind) + binding_key2::kind kind) { const region2 *base_reg = reg->get_base_region (); - binding_cluster **cluster_slot = m_cluster_map.get (base_reg); + binding_cluster2 **cluster_slot = m_cluster_map.get (base_reg); if (!cluster_slot) return NULL; return (*cluster_slot)->get_binding (mgr, reg, kind); @@ -5235,13 +5235,13 @@ region_model2::set_value (region_model2_manager *mgr, remove_overlapping_bindings (mgr, lhs_reg); const region2 *base_reg = lhs_reg->get_base_region (); - binding_cluster *cluster = NULL; - binding_cluster **slot = m_cluster_map.get (base_reg); + binding_cluster2 *cluster = NULL; + binding_cluster2 **slot = m_cluster_map.get (base_reg); if (slot) cluster = *slot; else { - cluster = new binding_cluster (); + cluster = new binding_cluster2 (); m_cluster_map.put (base_reg, cluster); } cluster->bind (mgr, lhs_reg, rhs_sval); @@ -5264,7 +5264,7 @@ region_model2::remove_overlapping_bindings (region_model2_manager *mgr, m_cluster_map.remove (base_reg); return; } - if (binding_cluster **cluster_slot = m_cluster_map.get (base_reg)) + if (binding_cluster2 **cluster_slot = m_cluster_map.get (base_reg)) (*cluster_slot)->remove_overlapping_bindings (mgr, reg); } diff --git a/gcc/analyzer/region-model2.h b/gcc/analyzer/region-model2.h index 928e609f4ac..e8f105d2bb9 100644 --- a/gcc/analyzer/region-model2.h +++ b/gcc/analyzer/region-model2.h @@ -61,36 +61,6 @@ along with GCC; see the file COPYING3. If not see macros (see e.g. INT_TYPE_SIZE in defaults.h). Remember to test on some other targets. Similarly, big-endian vs little-endian. */ -/* A tree, extended with stack frame information for locals, so that - we can distinguish between different values of locals within a potentially - recursive callstack. */ -// TODO: would this be better as a new tree code? - -namespace ana { - -class path_var -{ -public: - path_var (tree t, int stack_depth) - : m_tree (t), m_stack_depth (stack_depth) - { - // TODO: ignore stack depth for globals and constants - } - - bool operator== (const path_var &other) const - { - return (m_tree == other.m_tree - && m_stack_depth == other.m_stack_depth); - } - - void dump (pretty_printer *pp) const; - - tree m_tree; - int m_stack_depth; // or -1 for globals? -}; - -} // namespace ana - using namespace ana; namespace inchash @@ -111,9 +81,9 @@ namespace ana { This struct tracks how many of each kind of entity were purged (e.g. for selftests, and for debugging). */ -struct purge_stats +struct purge_stats2 { - purge_stats () + purge_stats2 () : m_num_svalues (0), m_num_regions (0), m_num_equiv_classes (0), @@ -373,6 +343,7 @@ public: #endif }; +#if 0 /* An enum describing a particular kind of "poisoned" value. */ enum poison_kind @@ -386,6 +357,7 @@ enum poison_kind /* For use on pointers to regions within popped stack frames. */ POISON_KIND_POPPED_STACK }; +#endif extern const char *poison_kind_to_str (enum poison_kind); @@ -436,6 +408,7 @@ is_a_helper ::test (svalue2 *sval) namespace ana { +#if 0 /* A bundle of information recording a setjmp/sigsetjmp call, corresponding roughly to a jmp_buf. */ @@ -496,6 +469,7 @@ public: setjmp_record m_setjmp_record; }; +#endif /* Concrete subclass of svalue2 representing the initial value of a specific region */ @@ -735,7 +709,7 @@ public: template <> template <> inline bool -is_a_helper ::test (region *) +is_a_helper ::test (region2 *) { return true; } @@ -1316,10 +1290,10 @@ private: /* A binding within a store. */ -class binding_key +class binding_key2 { public: - virtual ~binding_key() {} + virtual ~binding_key2 () {} virtual bool concrete_p () const = 0; enum kind @@ -1332,7 +1306,7 @@ public: return kind == BK_direct ? "direct" : "default"; } - static const binding_key *make (region_model2_manager *mgr, region2 *r, + static const binding_key2 *make (region_model2_manager *mgr, region2 *r, enum kind kind); virtual void dump_to_pp (pretty_printer *pp, bool simple) const @@ -1343,10 +1317,10 @@ public: } static int cmp_ptrs (const void *, const void *); - static int cmp (const binding_key *, const binding_key *); + static int cmp (const binding_key2 *, const binding_key2 *); protected: - binding_key (const region2 *region, enum kind kind) + binding_key2 (const region2 *region, enum kind kind) : m_region (region), m_kind (kind) {} const region2 *get_region () const { return m_region; } @@ -1357,7 +1331,7 @@ protected: { return (long)m_region ^ m_kind; } - bool impl_eq (const binding_key &other) + bool impl_eq (const binding_key2 &other) { return m_region == other.m_region && m_kind == other.m_kind; } @@ -1367,30 +1341,30 @@ private: enum kind m_kind; }; -class concrete_binding : public binding_key +class concrete_binding2 : public binding_key2 { public: typedef region_offset::bit_offset_t bit_offset_t; - concrete_binding (const region2 *region, enum kind kind, bit_offset_t offset) - : binding_key (region, kind), m_offset (offset) + concrete_binding2 (const region2 *region, enum kind kind, bit_offset_t offset) + : binding_key2 (region, kind), m_offset (offset) {} bool concrete_p () const FINAL OVERRIDE { return true; } hashval_t hash () const { - return binding_key::impl_hash (); // FIXME: ^ m_offset; + return binding_key2::impl_hash (); // FIXME: ^ m_offset; } - bool operator== (const concrete_binding &other) + bool operator== (const concrete_binding2 &other) { - if (!binding_key::impl_eq (other)) + if (!binding_key2::impl_eq (other)) return false; return m_offset == other.m_offset; } void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE { - binding_key::dump_to_pp (pp, simple); + binding_key2::dump_to_pp (pp, simple); pp_string (pp, ", offset: "); pp_wide_int (pp, m_offset, SIGNED); } @@ -1401,30 +1375,30 @@ private: bit_offset_t m_offset; }; -class symbolic_binding : public binding_key +class symbolic_binding2 : public binding_key2 { public: - symbolic_binding (const region2 *region, enum kind kind, + symbolic_binding2 (const region2 *region, enum kind kind, const region2 *concrete_offset_region) - : binding_key (region, kind), + : binding_key2 (region, kind), m_concrete_offset_region (concrete_offset_region) {} bool concrete_p () const FINAL OVERRIDE { return false; } hashval_t hash () const { - return binding_key::impl_hash () ^ (long)m_concrete_offset_region; + return binding_key2::impl_hash () ^ (long)m_concrete_offset_region; } - bool operator== (const symbolic_binding &other) + bool operator== (const symbolic_binding2 &other) { - if (!binding_key::impl_eq (other)) + if (!binding_key2::impl_eq (other)) return false; return m_concrete_offset_region == other.m_concrete_offset_region; } void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE { - binding_key::dump_to_pp (pp, simple); + binding_key2::dump_to_pp (pp, simple); pp_string (pp, ", concrete offset region: "); m_concrete_offset_region->dump_to_pp (pp, simple); } @@ -1436,15 +1410,15 @@ private: /* All of the bindings within a store for regions that share the same base region. */ -class binding_cluster +class binding_cluster2 { public: - typedef hash_map map_t; + typedef hash_map map_t; //typedef typename map_t::iterator iterator_t; #if 0 - binding_cluster (); - binding_cluster (const binding_cluster &other); + binding_cluster2 (); + binding_cluster2 (const binding_cluster2 &other); #endif void dump_to_pp (pretty_printer *pp, bool simple) const; @@ -1453,18 +1427,18 @@ public: void bind (region_model2_manager *mgr, region2 *, svalue2 *); #else - const binding_cluster *bind (const extrinsic_state &ext_state, + const binding_cluster2 *bind (const extrinsic_state &ext_state, const region2 *, const svalue2 *) const; #endif svalue2 *get_binding (region_model2_manager *mgr, region2 *reg, - binding_key::kind kind) const; + binding_key2::kind kind) const; void remove_overlapping_bindings (region_model2_manager *mgr, region2 *reg); private: void get_overlapping_bindings (region2 *reg, - auto_vec *out); + auto_vec *out); map_t m_map; }; @@ -1491,14 +1465,14 @@ public: svalue2 *index, region_model2_context *ctxt); - const concrete_binding * + const concrete_binding2 * get_concrete_binding (const region2 *region, - enum binding_key::kind kind, - concrete_binding::bit_offset_t offset); + enum binding_key2::kind kind, + concrete_binding2::bit_offset_t offset); - const symbolic_binding * + const symbolic_binding2 * get_symbolic_binding (const region2 *region, - enum binding_key::kind kind, + enum binding_key2::kind kind, region2 *concrete_offset_region); svalue2 *get_or_create_initial_value (const region2 *reg); @@ -1528,8 +1502,8 @@ private: #endif uniq_manager m_elements; - uniq_manager m_concrete_binding_key_mgr; - uniq_manager m_symbolic_binding_key_mgr; + uniq_manager m_concrete_binding_key_mgr; + uniq_manager m_symbolic_binding_key_mgr; }; /* A region_model2 encapsulates a representation of the state of memory, with @@ -1599,6 +1573,9 @@ class region_model2 tree lhs, tree rhs, bool is_back_edge, region_model2_context *ctxt); + bool on_stmt (const extrinsic_state &ext_state, + const supernode *snode, + const gimple *stmt); bool maybe_update_for_edge (region_model2_manager *mgr, const superedge &edge, const gimple *last_stmt, @@ -1615,7 +1592,7 @@ class region_model2 frame_region2 *get_current_frame () const { return m_current_frame; } function * get_current_function () const; void pop_frame (region2 *result_dst, - bool purge, purge_stats *stats, + bool purge, purge_stats2 *stats, region_model2_context *ctxt); int get_stack_depth () const; function *get_function_at_depth (unsigned depth) const; @@ -1745,7 +1722,7 @@ class region_model2 svalue2 *get_direct_binding (region_model2_manager *mgr, region2 *reg); svalue2 *get_default_binding (region_model2_manager *mgr, region2 *reg); svalue2 *get_binding (region_model2_manager *mgr, region2 *reg, - binding_key::kind kind); + binding_key2::kind kind); void remove_overlapping_bindings (region_model2_manager *mgr, region2 *reg); @@ -1799,7 +1776,7 @@ class region_model2 #if 1 - typedef hash_map cluster_map_t; + typedef hash_map cluster_map_t; cluster_map_t m_cluster_map; // TODO: deep copy of this! #else typedef hash_map store_map_t; @@ -2002,6 +1979,16 @@ struct model_merger }; #endif +class engine2 +{ +public: + region_model2_manager *get_model_manager () { return &m_mgr; } + +private: + region_model2_manager m_mgr; + +}; + } // namespace ana extern void debug (const region_model2 &rmodel); @@ -2066,7 +2053,7 @@ void assert_condition (const location &loc, /* Assert that REGION_MODEL2 evaluates the condition "LHS OP RHS" as "true". */ - +#if 0 #define ASSERT_CONDITION_TRUE(REGION_MODEL2, LHS, OP, RHS) \ SELFTEST_BEGIN_STMT \ assert_condition (SELFTEST_LOCATION, REGION_MODEL2, LHS, OP, RHS, \ @@ -2090,6 +2077,7 @@ void assert_condition (const location &loc, assert_condition (SELFTEST_LOCATION, REGION_MODEL2, LHS, OP, RHS, \ tristate (tristate::TS_UNKNOWN)); \ SELFTEST_END_STMT +#endif } /* end of namespace selftest. */ diff --git a/gcc/analyzer/revamp-state.cc b/gcc/analyzer/revamp-state.cc index 13d3c6fcba8..17f0dbf2acb 100644 --- a/gcc/analyzer/revamp-state.cc +++ b/gcc/analyzer/revamp-state.cc @@ -52,6 +52,7 @@ along with GCC; see the file COPYING3. If not see #include "analyzer/supergraph.h" #include "sbitmap.h" #include "analyzer/region-model.h" +#include "analyzer/revamp-state.h" #include "analyzer/constraint-manager.h" #include "diagnostic-event-id.h" #include "analyzer/sm.h" -- 2.21.0