let assign_return_to_lv ~with_alarms funcexp lv return new_state =
let loc = lval_to_loc ~with_alarms new_state lv in
let rtype = getReturnType (typeOf funcexp) in
let lvtyp = typeOfLval lv in
let is_bitfield = is_bitfield lv ~sizebf:loc.size ~sizelv:(sizeof lvtyp) () in
let default () =
let value_with_init =
V_Offsetmap.find_ival
~conflate_bottom:false
~validity:Base.All
~with_alarms:CilE.warn_none_mode
Ival.zero
return
(Int.of_int (bitsSizeOf rtype))
in
let flags = V_Or_Uninitialized.get_flags value_with_init in
let init = V_Or_Uninitialized.is_initialized flags in
let no_esc = V_Or_Uninitialized.is_noesc flags in
let value = V_Or_Uninitialized.get_v value_with_init in
if not init then CilE.warn_uninitialized with_alarms;
if not no_esc then CilE.warn_escapingaddr with_alarms;
if Cvalue.V.is_bottom value && not (init && no_esc)
then
Value_parameters.result ~current:true
"Function call returned an unspecified value. This path is assumed to be dead.";
let exact = valid_cardinal_zero_or_one ~for_writing:true loc in
let evaled_exp =
do_cast ~with_alarms:CilE.warn_none_mode rtype value in
let evaled_exp =
if is_bitfield
then cast_lval_bitfield lv (Int_Base.project loc.size) evaled_exp
else do_cast ~with_alarms:CilE.warn_none_mode lvtyp evaled_exp
in
remember_bases_with_locals loc evaled_exp;
Cvalue.Model.add_binding
~with_alarms:CilE.warn_none_mode
~exact
new_state
loc
evaled_exp
in
if is_bitfield || (need_cast lvtyp rtype)
then default ()
else
(try
let result =
Cvalue.Model.paste_offsetmap with_alarms
return
loc.loc
Int.zero
(Int_Base.project loc.size)
true
new_state
in
let evaled_exp=
Cvalue.V_Or_Uninitialized.get_v
(V_Offsetmap.find_ival
~conflate_bottom:false
~validity:Base.All
~with_alarms:CilE.warn_none_mode
Ival.zero
return
(Int.of_int (bitsSizeOf rtype))
)
in
remember_bases_with_locals loc evaled_exp;
result
with Lmap.Cannot_copy -> default ())