let interp_call stmt lval_to_assign funcexp argl d_value =
    let call_site_loc = CurrentLoc.get () in
    let with_alarms = warn_all_quiet_mode () in
    let return_type_funcexp =
      match unrollType (typeOf funcexp) with
        TFun (t, _, _, _) -> t
      | _ -> assert false
    in
    let bitssizeofreturntypefuncexp =
      bitsSizeOf return_type_funcexp
    in
    let state_after_call state =
      try
        let functions, _ = resolv_func_vinfo ~with_alarms None state funcexp in
        let is_library_function kf = not (Kernel_function.is_definition kf) in
        let calling_at_least_one_library_function =
          Kernel_function.Hptset.exists is_library_function functions
        in
        let calling_only_library_functions =
          calling_at_least_one_library_function &&
            (Kernel_function.Hptset.for_all is_library_function functions)
        in
        let compute_actual = compute_actual ~with_alarms
          (calling_at_least_one_library_function,
           calling_only_library_functions)
        in
        let actuals = List.map (compute_actual state) argl in
        let treat_one_call f (acc_rt,acc_res,acc_clobbered_set as acc) =
          try
            let return_type = Kernel_function.get_return_type f in
            if bitsSizeOf return_type <> bitssizeofreturntypefuncexp
            then raise Wrong_function_type;

            let return, result, clobbered_set =
              !compute_call_ref f ~call_kinstr:(Kstmt stmt) state actuals
            in
            let caller = current_kf (), stmt in
            Kf_state.add_caller f ~caller;
            CurrentLoc.set call_site_loc;
            (match acc_rt,return with
            | None,_ -> return
            | Some _, None -> acc_rt
            | Some acc_rt, Some return ->
                Some (snd (V_Offsetmap.join acc_rt return))),
            Cvalue.Model.join acc_res result,
            Location_Bits.Top_Param.join acc_clobbered_set clobbered_set
          with Wrong_function_type ->
            warning_once_current
              "Pointed function type must match function pointer type when dereferenced: assert(Ook)";
            CilE.stop_if_stop_at_first_alarm_mode ();
            acc
        in
        let return,new_state,clobbered_set =
          Kernel_function.Hptset.fold treat_one_call
            functions
            empty_interpretation_result
        in
        bases_containing_locals :=
          Location_Bits.Top_Param.join !bases_containing_locals clobbered_set;
        match lval_to_assign with
          | None -> new_state
          | Some lv ->
              match return with
                | Some return ->
                    assign_return_to_lv ~with_alarms funcexp lv return new_state
                | None ->
                  if Cvalue.Model.is_reachable new_state
                  then
                    warning_once_current
                      "In function %t: called function returns void but returned value is assigned; ignoring assignment"
                      pretty_current_cfunction_name;
                  new_state
      with
        | Got_bottom ->
            CurrentLoc.set call_site_loc;
            Cvalue.Model.bottom
        | Leaf ->
            CurrentLoc.set call_site_loc;
            (match lval_to_assign with
              | None ->  state
              | Some lv ->
                  let evaled_exp = V.top_leaf_origin () in
                  do_assign_abstract_value ~with_alarms state lv evaled_exp)
    in
    State_set.fold
      (fun acc state -> State_set.add (state_after_call state) acc)
      State_set.empty
      d_value