let compute_using_prototype kf ~state_with_formals =
match kf.fundec with
| Definition (_,_) -> assert false
| Declaration (_spec,varinfo,_,_) ->
if Cil.hasAttribute "noreturn" varinfo.vattr then
None, Relations_type.Model.bottom, Location_Bits.Top_Param.bottom
else begin
let return_type,_formals_type,_inline,_attr =
splitFunctionType (Kernel_function.get_type kf)
in
let behaviors = valid_behaviors kf state_with_formals in
let assigns = Ast_info.merge_assigns behaviors in
let returned_value, state_with_formals =
return_value return_type kf 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
| [] -> state_with_formals
| assigns ->
let treat_assign acc (out, ins) =
let input =
(try
List.fold_left
(fun acc loc ->
List.fold_left
(fun acc lv ->
let _,_,r =
eval_lval ~with_alarms:CilE.warn_none_mode None
state_with_formals
lv
in
Cvalue_type.V.join acc r)
acc
(match loc with
| Location loc ->
!Db.Properties.Interp.loc_to_lval
loc.it_content
| Nothing -> []))
Cvalue_type.V.top_int ins
with Invalid_argument "not a lvalue" ->
Value_parameters.result
~once:true ~current:true
"cannot interpret assigns in function %a"
Kernel_function.pretty_name kf;
Cvalue_type.V.top)
in
try
List.fold_left
(fun acc lval ->
let loc =
lval_to_loc ~with_alarms:CilE.warn_none_mode
state_with_formals lval
in
remember_bases_with_locals clobbered_set loc input;
let bound =
Relations_type.Model.add_binding
~with_alarms:CilE.warn_none_mode
~exact:false acc loc input
in
Relations_type.Model.join bound acc)
acc
(match out with
| Location out ->
!Db.Properties.Interp.loc_to_lval out.it_content
| Nothing -> [])
with
Invalid_argument "not a lvalue" ->
(match out with
Location out when
Logic_utils.is_result out.it_content ->
returned_value :=
Cvalue_type.V.join
(Cvalue_type.V.topify_arith_origin input)
! returned_value;
acc
| Location _ ->
Value_parameters.warning ~once:true ~current:true
"Can not interpret assigns in function %a; effects will be ignored"
Kernel_function.pretty_name kf; acc
| Nothing -> assert false )
in
(List.fold_left treat_assign state_with_formals assigns)
in
(if isVoidType return_type then None 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_type.V_Or_Uninitialized.initialized !returned_value)
in
Some offsetmap),
(Relations_type.Model.filter_base
(fun base -> not (Base.is_formal_of_prototype base varinfo))
state),
!clobbered_set
end