let compute_using_prototype kf ~active_behaviors ~state_with_formals =
let vi = Kernel_function.get_vi kf in
if Cil.hasAttribute "noreturn" vi.vattr then
None, Cvalue.Model.bottom, Location_Bits.Top_Param.bottom
else
let return_type,_formals_type,_inline,_attr =
splitFunctionType (Kernel_function.get_type kf)
in
let behaviors =
Eval_logic.ActiveBehaviors.active_behaviors active_behaviors in
let assigns = Ast_info.merge_assigns behaviors in
let returned_value, state_with_formals =
Library_functions.returned_value kf return_type state_with_formals
in
let returned_value = ref returned_value in
let clobbered_set = ref Location_Bits.Top_Param.bottom in
let state =
match assigns with
| WritesAny ->
warning_once_current "Cannot handle empty assigns clause. Assuming assigns \\nothing: be aware this is probably incorrect.";
state_with_formals
| Writes [] -> state_with_formals
| Writes l ->
let treat_assign acc (out, ins) =
let input_contents =
try
match ins with
| FromAny -> Cvalue.V.top_int
| From l ->
List.fold_left
(fun acc term ->
let input_loc =
!Db.Properties.Interp.loc_to_loc
~result:None
state_with_formals
term.it_content
in
let r =
Cvalue.V.topify_arith_origin(
Cvalue.Model.find
~conflate_bottom:true
~with_alarms:CilE.warn_none_mode
state_with_formals
input_loc
) in
Cvalue.V.join acc r)
Cvalue.V.top_int
l
with Invalid_argument "not an lvalue" ->
warning_once_current
"cannot interpret@ assigns@ in function %a"
Kernel_function.pretty kf;
Cvalue.V.top
in
let treat_output_loc loc acc =
remember_bases_with_locals
clobbered_set
loc
input_contents;
let state =
Cvalue.Model.add_binding
~with_alarms:CilE.warn_none_mode
~exact:false acc loc input_contents
in
if Cvalue.Model.is_reachable state
then state
else acc
in
try
let loc = !Db.Properties.Interp.loc_to_loc
~result:None acc out.it_content
in
let st = treat_output_loc loc acc in
if Cvalue.Model.equal Cvalue.Model.top st then (
Value_parameters.error ~once:true ~current:true
"Cannot@ handle@ assigns@ for %a,@ location@ is@ too@ imprecise@ (%a).@ Assuming@ it@ is@ not@ assigned,@ but@ be@ aware@ this@ is@ incorrect."
d_term out.it_content Locations.pretty loc;
acc)
else st
with
| Invalid_argument "not an lvalue" ->
if Logic_utils.is_result out.it_content then begin
returned_value :=
Cvalue.V.join input_contents !returned_value;
acc
end else begin
warning_once_current
"Cannot interpret assigns in function %a; effects will be ignored"
Kernel_function.pretty kf; acc
end
in
(List.fold_left treat_assign state_with_formals l)
in
let retres_vi, state =
if isVoidType return_type
then None, state
else
let offsetmap =
V_Offsetmap.update_ival
~with_alarms:CilE.warn_none_mode
~validity:Base.All
~offsets:Ival.zero
~exact:true
~size:(Int.of_int (bitsSizeOf return_type))
V_Offsetmap.empty
(Cvalue.V_Or_Uninitialized.initialized !returned_value)
in
let rvi, state = Library_functions.add_retres_to_state
~with_alarms:CilE.warn_none_mode kf offsetmap state
in
Some rvi, state
in
retres_vi, state, !clobbered_set