aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2020-08-28 07:07:18 -0400
committerDavid Malcolm <dmalcolm@redhat.com>2020-09-09 16:58:13 -0400
commit6d9ca8c8604e2e7c2403794baf691b260cc71fb9 (patch)
tree542b2ef585bc007f0cacb7ad6145a0e66659ebe3 /gcc
parent10fc42a8396072912e9d9d940fba25950b3fdfc5 (diff)
downloadgcc-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.cc41
-rw-r--r--gcc/analyzer/engine.cc45
-rw-r--r--gcc/analyzer/sm.h27
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