@ -64,6 +64,10 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
try Some ( IdAccessPathMapDomain . find id id_map )
try Some ( IdAccessPathMapDomain . find id id_map )
with Not_found -> None
with Not_found -> None
let is_constant = function
| Exp . Const _ -> true
| _ -> false
let is_owned access_path owned_set =
let is_owned access_path owned_set =
Domain . AccessPathSetDomain . mem access_path owned_set
Domain . AccessPathSetDomain . mem access_path owned_set
@ -105,13 +109,17 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
is_thread_safe_write ( snd access_path ) tenv in
is_thread_safe_write ( snd access_path ) tenv in
let f_resolve_id = resolve_id id_map in
let f_resolve_id = resolve_id id_map in
IList . fold_left
if is_constant exp
( fun acc rawpath ->
then
if not ( is_owned ( truncate rawpath ) owned ) && not ( is_safe_write rawpath pname tenv )
then Domain . PathDomain . add_sink ( Domain . make_access rawpath loc ) acc
else acc )
path_state
path_state
( AccessPath . of_exp exp typ ~ f_resolve_id )
else
IList . fold_left
( fun acc rawpath ->
if not ( is_owned ( truncate rawpath ) owned ) && not ( is_safe_write rawpath pname tenv )
then Domain . PathDomain . add_sink ( Domain . make_access rawpath loc ) acc
else acc )
path_state
( AccessPath . of_exp exp typ ~ f_resolve_id )
let analyze_id_assignment lhs_id rhs_exp rhs_typ { Domain . id_map ; } =
let analyze_id_assignment lhs_id rhs_exp rhs_typ { Domain . id_map ; } =
let f_resolve_id = resolve_id id_map in
let f_resolve_id = resolve_id id_map in
@ -215,51 +223,55 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
the current state * )
the current state * )
let add_conditional_writes
let add_conditional_writes
( ( cond_writes , uncond_writes ) as acc ) index ( actual_exp , actual_typ ) =
( ( cond_writes , uncond_writes ) as acc ) index ( actual_exp , actual_typ ) =
try
if is_constant actual_exp
let callee_cond_writes_for_index' =
then
let callee_cond_writes_for_index =
acc
ConditionalWritesDomain . find index callee_conditional_writes in
else
PathDomain . with_callsite callee_cond_writes_for_index call_site in
try
begin
let callee_cond_writes_for_index' =
match AccessPath . of_lhs_exp actual_exp actual_typ ~ f_resolve_id with
let callee_cond_writes_for_index =
| Some actual_access_path ->
ConditionalWritesDomain . find index callee_conditional_writes in
if is_owned actual_access_path astate . owned
PathDomain . with_callsite callee_cond_writes_for_index call_site in
then
begin
(* the actual passed to the current callee is owned. drop all
match AccessPath . of_lhs_exp actual_exp actual_typ ~ f_resolve_id with
the conditional writes for that actual , since they're all
| Some actual_access_path ->
safe * )
if is_owned actual_access_path astate . owned
acc
then
else
(* the actual passed to the current callee is owned. drop all
let base = fst actual_access_path in
the conditional writes for that actual , since they're all
begin
safe * )
match FormalMap . get_formal_index base extras with
acc
| Some formal_index ->
else
(* the actual passed to the current callee is rooted in
let base = fst actual_access_path in
a formal . add to conditional writes * )
begin
let conditional_writes' =
match FormalMap . get_formal_index base extras with
try
| Some formal_index ->
ConditionalWritesDomain . find
(* the actual passed to the current callee is rooted in
formal_index cond_writes
a formal . add to conditional writes * )
| > PathDomain . join callee_cond_writes_for_index'
let conditional_writes' =
with Not_found ->
try
callee_cond_writes_for_index' in
ConditionalWritesDomain . find
let cond_writes' =
formal_index cond_writes
ConditionalWritesDomain . add
| > PathDomain . join callee_cond_writes_for_index'
formal_index conditional_writes' cond_writes in
with Not_found ->
cond_writes' , uncond_writes
callee_cond_writes_for_index' in
| None ->
let cond_writes' =
(* access path not owned and not rooted in a formal. add
ConditionalWritesDomain . add
to unconditional writes * )
formal_index conditional_writes' cond_writes in
cond_writes ,
cond_writes' , uncond_writes
PathDomain . join
| None ->
uncond_writes callee_cond_writes_for_index'
(* access path not owned and not rooted in a formal. add
end
to unconditional writes * )
| _ ->
cond_writes ,
cond_writes ,
PathDomain . join
PathDomain . join uncond_writes callee_cond_writes_for_index'
uncond_writes callee_cond_writes_for_index'
end
end
with Not_found ->
| _ ->
acc in
cond_writes ,
PathDomain . join uncond_writes callee_cond_writes_for_index'
end
with Not_found ->
acc in
let conditional_writes , unconditional_writes =
let conditional_writes , unconditional_writes =
let combined_unconditional_writes =
let combined_unconditional_writes =
PathDomain . with_callsite callee_unconditional_writes call_site
PathDomain . with_callsite callee_unconditional_writes call_site
@ -361,7 +373,9 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
then AccessPathSetDomain . add lhs_access_path access_path_set
then AccessPathSetDomain . add lhs_access_path access_path_set
else AccessPathSetDomain . remove lhs_access_path access_path_set
else AccessPathSetDomain . remove lhs_access_path access_path_set
| Some lhs_access_path , None ->
| Some lhs_access_path , None ->
AccessPathSetDomain . remove lhs_access_path access_path_set
if is_constant rhs_exp
then AccessPathSetDomain . add lhs_access_path access_path_set
else AccessPathSetDomain . remove lhs_access_path access_path_set
| _ ->
| _ ->
access_path_set in
access_path_set in
let owned = update_access_path_set astate . owned in
let owned = update_access_path_set astate . owned in
@ -387,7 +401,12 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
else access_path_set in
else access_path_set in
propagate_to_lhs astate . owned , propagate_to_lhs astate . functional
propagate_to_lhs astate . owned , propagate_to_lhs astate . functional
| _ ->
| _ ->
astate . owned , astate . functional in
if is_constant rhs_exp
then
AccessPathSetDomain . add ( AccessPath . of_id lhs_id rhs_typ ) astate . owned ,
astate . functional
else
astate . owned , astate . functional in
{ astate with Domain . reads ; id_map ; owned ; functional ; }
{ astate with Domain . reads ; id_map ; owned ; functional ; }
| Sil . Remove_temps ( ids , _ ) ->
| Sil . Remove_temps ( ids , _ ) ->