let doStmt (s: stmt) (d: t) =
let reachable, _ = reachables d in
let kinstr = Kstmt s in
CilE.start_stmt kinstr;
let changed =
try
update_current_exn !(d.value);
true
with State_set.Unchanged -> false
in
CilE.end_stmt ();
let annots_before,annots_after,contract = Db.Properties.predicates_on_stmt s
in
CilE.start_stmt kinstr;
d.value := interp_annot !(d.value) annots_before;
let valid_behaviors =
match contract with
None -> []
| Some c -> extract_valid_behaviors !(d.value) c
in
CilE.end_stmt ();
let states = !(d.value) in
d.value := State_set.empty;
if (not reachable) || (not changed) then
Dataflow.SDefault
else begin
let current = find_current kinstr in
let d =
if d.counter_unroll >= Value_parameters.SemanticUnrollingLevel.get ()
then begin
let state = State_set.join states in
let joined =
Relations_type.Model.join
current.widening_state
state
in
let r =
if (REACH.is_natural_loop s) &&
(current.widening = 0)
then
let wh_key_set, wh_hints = getWidenHints s in
let widen_hints =
true, wh_key_set,
wh_hints
in
let _,result = Relations_type.Model.widen
widen_hints
current.widening_state
joined
in
result
else
joined
in
let new_widening =
if current.widening = 0 then 1 else pred current.widening
in
InstrHashtbl.replace current_table kinstr
{ current with widening = new_widening ; widening_state = r };
{
counter_unroll = d.counter_unroll;
value = ref (State_set.singleton r);
}
end
else { d with value = ref states }
in
CilE.start_stmt kinstr;
d.value := interp_annot !(d.value) annots_after;
d.value := check_postconditions "statement" !(d.value) valid_behaviors;
update_current !(d.value);
CilE.end_stmt ();
match s.skind with
| Return _ ->
Dataflow.SUse d
| Loop _ ->
if d.counter_unroll >= Value_parameters.SemanticUnrollingLevel.get () then
Value_parameters.result ~once:true ~current:true
"entering loop for the first time";
Dataflow.SUse d
| UnspecifiedSequence seq ->
CilE.start_stmt kinstr;
State_set.iter
(fun state -> check_unspecified_sequence state seq) states;
CilE.end_stmt ();
Dataflow.SUse d
| _ -> Dataflow.SUse d
end