let doStmt (s: stmt) (d: t) =
let states = d.value in
d.value <- State_set.empty;
let kinstr = Kstmt s in
if State_set.is_empty states
then
Dataflow.SDefault
else
let annots_before =
Annotations.single_fold_stmt
(fun a acc ->
match a with
| User { annot_content = AStmtSpec _ }
| AI (_,{annot_content = AStmtSpec _ }) -> acc
| AI (_, b) | User b -> b :: acc)
s
[]
in
CilE.start_stmt kinstr;
let states =
List.fold_left
(fun states annot -> interp_annot states s annot true)
states
annots_before
in
CilE.end_stmt ();
let not_already_states =
if obviously_terminates
then states
else Current_table.update_and_tell_if_changed current_table s states
in
if State_set.is_empty not_already_states
then Dataflow.SDefault
else
let is_return = match s.skind with Return _ -> true | _ -> false in
let new_states =
if d.counter_unroll >= slevel || (is_return && obviously_terminates)
then
let curr_wcounter, curr_wstate =
Current_table.find_widening_info current_table s
in
let state = State_set.join states in
let joined = Cvalue.Model.join curr_wstate state in
if obviously_terminates
then begin
Current_table.update_widening_info current_table s 0 joined;
states
end
else
let r =
if AnalysisParam.is_natural_loop s && curr_wcounter = 0 then
let wh_key_set, wh_hints = getWidenHints s in
let widen_hints =
true, wh_key_set,
wh_hints
in
snd (Cvalue.Model.widen widen_hints curr_wstate joined)
else
joined
in
let new_widening =
if curr_wcounter = 0
then 1
else pred curr_wcounter
in
let new_state = State_set.singleton r in
if Cvalue.Model.equal r joined then (
Current_table.update_widening_info current_table s new_widening r;
new_state)
else begin
CilE.start_stmt kinstr;
let new_states =
List.fold_left
(fun states annot -> interp_annot states s annot false)
new_state
annots_before
in
CilE.end_stmt ();
let new_joined = State_set.join new_states in
Current_table.update_widening_info
current_table s new_widening new_joined;
State_set.singleton new_joined
end
else states
in
let d = { d with value = new_states }
in
( match s.skind with
| Loop _ ->
if d.counter_unroll >= slevel &&
(Value_parameters.ValShowProgress.get())
then
Value_parameters.result ~level:1 ~once:true ~current:true
"entering loop for the first time"
| UnspecifiedSequence seq ->
if Kernel.UnspecifiedAccess.get ()
then begin
CilE.start_stmt kinstr;
State_set.iter
(fun state -> check_unspecified_sequence state seq) states;
CilE.end_stmt ()
end
| _ -> ());
Dataflow.SUse d