aboutsummaryrefslogtreecommitdiff
path: root/gcc/analyzer/program-state.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/analyzer/program-state.cc')
-rw-r--r--gcc/analyzer/program-state.cc23
1 files changed, 16 insertions, 7 deletions
diff --git a/gcc/analyzer/program-state.cc b/gcc/analyzer/program-state.cc
index a9e300f..f41f105 100644
--- a/gcc/analyzer/program-state.cc
+++ b/gcc/analyzer/program-state.cc
@@ -259,7 +259,8 @@ sm_state_map::set_state (region_model *model,
if (model == NULL)
return;
equiv_class &ec = model->get_constraints ()->get_equiv_class (sid);
- set_state (ec, state, origin);
+ if (!set_state (ec, state, origin))
+ return;
/* Also do it for all svalues that are equal via non-cm, so that
e.g. (void *)&r and (foo *)&r transition together. */
@@ -276,34 +277,42 @@ sm_state_map::set_state (region_model *model,
}
/* Set the state of EC to STATE, recording that the state came from
- ORIGIN. */
+ ORIGIN.
+ Return true if any states of svalue_ids within EC changed. */
-void
+bool
sm_state_map::set_state (const equiv_class &ec,
state_machine::state_t state,
svalue_id origin)
{
int i;
svalue_id *sid;
+ bool any_changed = false;
FOR_EACH_VEC_ELT (ec.m_vars, i, sid)
- impl_set_state (*sid, state, origin);
+ any_changed |= impl_set_state (*sid, state, origin);
+ return any_changed;
}
-/* Set state of PV to STATE, bypassing equivalence classes. */
+/* Set state of SID to STATE, bypassing equivalence classes.
+ Return true if the state changed. */
-void
+bool
sm_state_map::impl_set_state (svalue_id sid, state_machine::state_t state,
svalue_id origin)
{
+ if (get_state (sid) == state)
+ return false;
+
/* Special-case state 0 as the default value. */
if (state == 0)
{
if (m_map.get (sid))
m_map.remove (sid);
- return;
+ return true;
}
gcc_assert (!sid.null_p ());
m_map.put (sid, entry_t (state, origin));
+ return true;
}
/* Set the "global" state within this state map to STATE. */