{
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)
{
}
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;
from, to,
NULL,
*m_new_state));
-
}
void warn_for_state (const supernode *, const gimple *,
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.
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?
}
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);
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,
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