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(* no longer used thanks to 0/1 widening*),
                    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
              (* Try to correct over-widenings *)
                CilE.start_stmt kinstr;
                let new_states =
                (* Do *not* record the status after interpreting the annotation
                   here. Possible unproven assertions have already been
                   recorded when the assertion has been interpreted the first
                   time higher in this function. *)

                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