let doStmt (s: stmt) (d: t) =
let states = !(d.value) in
d.value := State_set.empty;
let kinstr = Kstmt s in
let changed =
Current_table.update_and_tell_if_changed
current_table
kinstr
states
in
if (not changed) then
Dataflow.SDefault
else begin
let annots_before, contract =
Annotations.single_fold_stmt
(fun a (before, spec as acc) -> match a with
| Before
(User { annot_content = AStmtSpec spec' }
| AI (_,{annot_content = AStmtSpec spec' }) )
->
let spec = match spec with
| None -> spec'
| Some s -> Logic_utils.merge_funspec s spec'; s
in
(before, Some spec)
| Before (AI (_, b) | User b) -> b :: before, spec
| After _ -> acc)
s
([], None)
in
CilE.start_stmt kinstr;
let states =
List.fold_left
(fun states annot -> interp_annot states s annot)
states
annots_before
in
let states =
match contract with
Some spec ->
check_preconditions (current_kf()) kinstr
~slevel "statement" states spec
| None -> states
in
CilE.end_stmt ();
let curr_wcounter, curr_wstate =
Current_table.find_widening_info current_table kinstr in
let d =
if d.counter_unroll >= AnalysisParam.slevel
then begin
let state = State_set.join states in
let joined =
Relations_type.Model.join
curr_wstate
state
in
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
let _,result = Relations_type.Model.widen
widen_hints
curr_wstate
joined
in
result
else
joined
in
let new_widening =
if curr_wcounter = 0
then 1
else pred curr_wcounter
in
Current_table.update_widening_info
current_table
kinstr
new_widening
r;
{
counter_unroll = d.counter_unroll;
value = ref (State_set.singleton r);
}
end
else { d with value = ref states }
in
Current_table.update_current current_table kinstr !(d.value);
match s.skind with
| Return _ ->
Dataflow.SUse d
| Loop _ ->
if d.counter_unroll >= AnalysisParam.slevel
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