let doEdge s succ d =
    let kinstr = Kstmt s in
    let states = d.value in
    CilE.start_stmt kinstr;
    (* We store the state after the execution of [s] for the callback
       {Value.Record_Value_After_Callbacks}. This is done here
       because we want to see the values of the variables local to the block *)

    if (Value_parameters.ResultsAfter.get () ||
        not (Db.Value.Record_Value_After_Callbacks.is_empty ()))
      && (store_state_after_during_dataflow s succ)
    then (
      let old =
        try Cil_datatype.Stmt.Hashtbl.find states_after s
        with Not_found -> Cvalue.Model.bottom
      in
      let updated = State_set.fold Cvalue.Model.join old states in
      Cil_datatype.Stmt.Hashtbl.replace states_after s updated
    );

    let states =
      match Kernel_function.blocks_closed_by_edge s succ with
      | [] -> states
      | closed_blocks ->
          let block_top_addresses_of_locals =
            block_top_addresses_of_locals closed_blocks
          in
            State_set.fold
              (fun set state ->
                let state =
                  Cvalue.Model.uninitialize_locals closed_blocks state
                in
                State_set.add (block_top_addresses_of_locals state) set)
              State_set.empty
              states;
    in
    CilE.end_stmt ();
    { d with value =  states }