let do_return call kf lvopt p_after =
    let t_result = Kernel_function.get_return_type kf in
    if Ctypes.is_void t_result then
      ( p_after , None )
    else
      let x_result = D.fresh "result"
        (Formula.Acsl ((WpModel.tau_of_object (Ctypes.object_of t_result)),
                      Ctype t_result)) in
      match lvopt with
        | None -> p_after , Some x_result
        | Some lv ->
            let lv_t = Ctypes.object_of t_result in
            let casted_result =
              cast t_result (Cil.typeOfLval lv)
                (WpModel.value_of_logic lv_t (F.var x_result))
            in
            let v_result = match casted_result with
              | Warning(source,reason) ->
                  Datalib.Collector.add_warning
                    ~severe:true ~source ~reason
                    "Can not cast the returned value" ;
                  raise Failed
              | Result res -> res
            in

            let p_with_result =
              begin
                (* TODO : check memory for computing return loc *)
                match addr call.m_post lv with
                  | Warning(source, reason) ->
                      Datalib.Collector.add_warning
                        ~severe:true ~source ~reason
                        "Can not assign the returned value, no translation for l-value" ;
                      raise Failed
                  | Result loc ->
                      WpModel.subst_lval call.m_post lv_t loc v_result p_after
              end
            in
            p_with_result , Some x_result