diff options
author | David Malcolm <dmalcolm@redhat.com> | 2020-08-28 07:07:18 -0400 |
---|---|---|
committer | David Malcolm <dmalcolm@redhat.com> | 2020-09-09 16:58:13 -0400 |
commit | 6d9ca8c8604e2e7c2403794baf691b260cc71fb9 (patch) | |
tree | 542b2ef585bc007f0cacb7ad6145a0e66659ebe3 /gcc | |
parent | 10fc42a8396072912e9d9d940fba25950b3fdfc5 (diff) | |
download | gcc-6d9ca8c8604e2e7c2403794baf691b260cc71fb9.zip gcc-6d9ca8c8604e2e7c2403794baf691b260cc71fb9.tar.gz gcc-6d9ca8c8604e2e7c2403794baf691b260cc71fb9.tar.bz2 |
analyzer: reimplement on_transition in terms of get_state/set_next_state
This patch is further preliminary work towards generalizing sm-malloc.cc
beyond just malloc/free.
Reimplement sm_context's on_transition vfunc in terms of new get_state
and set_next_state vfuncs, so that in followup patches we can implement
richer transitions (e.g. where the states are parametrized by
allocator).
gcc/analyzer/ChangeLog:
* diagnostic-manager.cc
(null_assignment_sm_context::null_assignment_sm_context): Add old_state
and ext_state params, initializing m_old_state and m_ext_state.
(null_assignment_sm_context::on_transition): Split into...
(null_assignment_sm_context::get_state): ...this new vfunc
implementation and...
(null_assignment_sm_context::set_next_state): ...this new vfunc
implementation.
(null_assignment_sm_context::m_old_state): New field.
(null_assignment_sm_context::m_ext_state): New field.
(diagnostic_manager::add_events_for_eedge): Pass in old state and
ext_state when creating sm_ctxt.
* engine.cc (impl_sm_context::on_transition): Split into...
(impl_sm_context::get_state): ...this new vfunc
implementation and...
(impl_sm_context::set_next_state): ...this new vfunc
implementation.
* sm.h (sm_context::get_state): New pure virtual function.
(sm_context::set_next_state): Likewise.
(sm_context::on_transition): Convert from a pure virtual function
to a regular function implemented in terms of get_state and
set_next_state.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/analyzer/diagnostic-manager.cc | 41 | ||||
-rw-r--r-- | gcc/analyzer/engine.cc | 45 | ||||
-rw-r--r-- | gcc/analyzer/sm.h | 27 |
3 files changed, 80 insertions, 33 deletions
diff --git a/gcc/analyzer/diagnostic-manager.cc b/gcc/analyzer/diagnostic-manager.cc index 04c7d2a..6fd15c2 100644 --- a/gcc/analyzer/diagnostic-manager.cc +++ b/gcc/analyzer/diagnostic-manager.cc @@ -754,12 +754,15 @@ struct null_assignment_sm_context : public sm_context { null_assignment_sm_context (int sm_idx, const state_machine &sm, + const program_state *old_state, const program_state *new_state, const gimple *stmt, const program_point *point, - checker_path *emission_path) - : sm_context (sm_idx, sm), m_new_state (new_state), - m_stmt (stmt), m_point (point), m_emission_path (emission_path) + checker_path *emission_path, + const extrinsic_state &ext_state) + : sm_context (sm_idx, sm), m_old_state (old_state), m_new_state (new_state), + m_stmt (stmt), m_point (point), m_emission_path (emission_path), + m_ext_state (ext_state) { } @@ -768,13 +771,25 @@ struct null_assignment_sm_context : public sm_context return NULL_TREE; } - void on_transition (const supernode *node ATTRIBUTE_UNUSED, - const gimple *stmt ATTRIBUTE_UNUSED, - tree var, - state_machine::state_t from, - state_machine::state_t to, - tree origin ATTRIBUTE_UNUSED) FINAL OVERRIDE + state_machine::state_t get_state (const gimple *stmt ATTRIBUTE_UNUSED, + tree var) FINAL OVERRIDE { + const svalue *var_old_sval + = m_old_state->m_region_model->get_rvalue (var, NULL); + const sm_state_map *old_smap = m_old_state->m_checker_states[m_sm_idx]; + + state_machine::state_t current + = old_smap->get_state (var_old_sval, m_ext_state); + + return current; + } + + void set_next_state (const gimple *stmt, + tree var, + state_machine::state_t to, + tree origin ATTRIBUTE_UNUSED) FINAL OVERRIDE + { + state_machine::state_t from = get_state (stmt, var); if (from != m_sm.get_start_state ()) return; @@ -791,7 +806,6 @@ struct null_assignment_sm_context : public sm_context from, to, NULL, *m_new_state)); - } void warn_for_state (const supernode *, const gimple *, @@ -833,11 +847,13 @@ struct null_assignment_sm_context : public sm_context return NULL_TREE; } + const program_state *m_old_state; const program_state *m_new_state; const gimple *m_stmt; const program_point *m_point; state_change_visitor *m_visitor; checker_path *m_emission_path; + const extrinsic_state &m_ext_state; }; /* Subroutine of diagnostic_manager::build_emission_path. @@ -943,15 +959,18 @@ diagnostic_manager::add_events_for_eedge (const path_builder &pb, if (const gassign *assign = dyn_cast<const gassign *> (stmt)) { const extrinsic_state &ext_state = pb.get_ext_state (); + program_state old_state (iter_state); iter_state.m_region_model->on_assignment (assign, NULL); for (unsigned i = 0; i < ext_state.get_num_checkers (); i++) { const state_machine &sm = ext_state.get_sm (i); null_assignment_sm_context sm_ctxt (i, sm, + &old_state, &iter_state, stmt, &iter_point, - emission_path); + emission_path, + pb.get_ext_state ()); sm.on_stmt (&sm_ctxt, dst_point.get_supernode (), stmt); // TODO: what about phi nodes? } diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc index 05121e3..07b1b15 100644 --- a/gcc/analyzer/engine.cc +++ b/gcc/analyzer/engine.cc @@ -205,12 +205,26 @@ public: return model->get_fndecl_for_call (call, &old_ctxt); } - void on_transition (const supernode *node ATTRIBUTE_UNUSED, - const gimple *stmt, - tree var, - state_machine::state_t from, - state_machine::state_t to, - tree origin) FINAL OVERRIDE + state_machine::state_t get_state (const gimple *stmt, + tree var) + { + logger * const logger = get_logger (); + LOG_FUNC (logger); + impl_region_model_context old_ctxt + (m_eg, m_enode_for_diag, NULL, NULL/*m_enode->get_state ()*/, + stmt); + const svalue *var_old_sval + = m_old_state->m_region_model->get_rvalue (var, &old_ctxt); + + state_machine::state_t current + = m_old_smap->get_state (var_old_sval, m_eg.get_ext_state ()); + return current; + } + + void set_next_state (const gimple *stmt, + tree var, + state_machine::state_t to, + tree origin) { logger * const logger = get_logger (); LOG_FUNC (logger); @@ -230,17 +244,14 @@ public: state_machine::state_t current = m_old_smap->get_state (var_old_sval, m_eg.get_ext_state ()); - if (current == from) - { - if (logger) - logger->log ("%s: state transition of %qE: %s -> %s", - m_sm.get_name (), - var, - from->get_name (), - to->get_name ()); - m_new_smap->set_state (m_new_state->m_region_model, var_new_sval, - to, origin_new_sval, m_eg.get_ext_state ()); - } + if (logger) + logger->log ("%s: state transition of %qE: %s -> %s", + m_sm.get_name (), + var, + current->get_name (), + to->get_name ()); + m_new_smap->set_state (m_new_state->m_region_model, var_new_sval, + to, origin_new_sval, m_eg.get_ext_state ()); } void warn_for_state (const supernode *snode, const gimple *stmt, diff --git a/gcc/analyzer/sm.h b/gcc/analyzer/sm.h index 769d2a4..c507146 100644 --- a/gcc/analyzer/sm.h +++ b/gcc/analyzer/sm.h @@ -170,15 +170,32 @@ public: other callback handling. */ virtual tree get_fndecl_for_call (const gcall *call) = 0; + /* Get the old state of VAR at STMT. */ + virtual state_machine::state_t get_state (const gimple *stmt, + tree var) = 0; + /* Set the next state of VAR to be TO, recording the "origin" of the + state as ORIGIN. + Use STMT for location information. */ + virtual void set_next_state (const gimple *stmt, + tree var, + state_machine::state_t to, + tree origin = NULL_TREE) = 0; + /* Called by state_machine in response to pattern matches: if VAR is in state FROM, transition it to state TO, potentially recording the "origin" of the state as ORIGIN. Use NODE and STMT for location information. */ - virtual void on_transition (const supernode *node, const gimple *stmt, - tree var, - state_machine::state_t from, - state_machine::state_t to, - tree origin = NULL_TREE) = 0; + void on_transition (const supernode *node ATTRIBUTE_UNUSED, + const gimple *stmt, + tree var, + state_machine::state_t from, + state_machine::state_t to, + tree origin = NULL_TREE) + { + state_machine::state_t current = get_state (stmt, var); + if (current == from) + set_next_state (stmt, var, to, origin); + } /* Called by state_machine in response to pattern matches: issue a diagnostic D if VAR is in state STATE, using NODE and STMT |