@ -196,7 +196,7 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
then
then
(* TODO: check for constants, which are functional? *)
(* TODO: check for constants, which are functional? *)
let attribute_map =
let attribute_map =
AttributeMapDomain . add _attribute ( AccessExpression . base ret_base ) Functional
AttributeMapDomain . add ( AccessExpression . base ret_base ) Functional
astate . attribute_map
astate . attribute_map
in
in
{ astate with attribute_map }
{ astate with attribute_map }
@ -269,8 +269,7 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
{ astate with threads = ThreadsDomain . AnyThreadButSelf }
{ astate with threads = ThreadsDomain . AnyThreadButSelf }
| MainThreadIfTrue ->
| MainThreadIfTrue ->
let attribute_map =
let attribute_map =
AttributeMapDomain . add_attribute ret_access_exp Attribute . OnMainThread
AttributeMapDomain . add ret_access_exp Attribute . OnMainThread astate . attribute_map
astate . attribute_map
in
in
{ astate with attribute_map }
{ astate with attribute_map }
| UnknownThread ->
| UnknownThread ->
@ -301,8 +300,7 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
; threads = update_for_lock_use astate . threads }
; threads = update_for_lock_use astate . threads }
| LockedIfTrue _ | GuardLockedIfTrue _ ->
| LockedIfTrue _ | GuardLockedIfTrue _ ->
let attribute_map =
let attribute_map =
AttributeMapDomain . add_attribute ret_access_exp Attribute . LockHeld
AttributeMapDomain . add ret_access_exp Attribute . LockHeld astate . attribute_map
astate . attribute_map
in
in
{ astate with attribute_map ; threads = update_for_lock_use astate . threads }
{ astate with attribute_map ; threads = update_for_lock_use astate . threads }
| GuardConstruct { acquire_now = false } ->
| GuardConstruct { acquire_now = false } ->
@ -318,7 +316,7 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
{ summary with accesses = rebased_accesses } )
{ summary with accesses = rebased_accesses } )
in
in
match rebased_summary_opt with
match rebased_summary_opt with
| Some { threads ; locks ; accesses ; return_ownership ; return_attribute s } ->
| Some { threads ; locks ; accesses ; return_ownership ; return_attribute } ->
let locks =
let locks =
LocksDomain . integrate_summary ~ caller_astate : astate . locks ~ callee_astate : locks
LocksDomain . integrate_summary ~ caller_astate : astate . locks ~ callee_astate : locks
in
in
@ -330,7 +328,7 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
astate . ownership
astate . ownership
in
in
let attribute_map =
let attribute_map =
AttributeMapDomain . add ret_access_exp return_attribute s astate . attribute_map
AttributeMapDomain . add ret_access_exp return_attribute astate . attribute_map
in
in
let threads =
let threads =
ThreadsDomain . integrate_summary ~ caller_astate : astate . threads
ThreadsDomain . integrate_summary ~ caller_astate : astate . threads
@ -342,7 +340,7 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
in
in
let add_if_annotated predicate attribute attribute_map =
let add_if_annotated predicate attribute attribute_map =
if PatternMatch . override_exists predicate tenv callee_pname then
if PatternMatch . override_exists predicate tenv callee_pname then
AttributeMapDomain . add _attribute ret_access_exp attribute attribute_map
AttributeMapDomain . add ret_access_exp attribute attribute_map
else attribute_map
else attribute_map
in
in
let attribute_map = add_if_annotated is_functional Functional astate_callee . attribute_map in
let attribute_map = add_if_annotated is_functional Functional astate_callee . attribute_map in
@ -409,7 +407,7 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
if bool_value then ThreadsDomain . AnyThreadButSelf else ThreadsDomain . AnyThread
if bool_value then ThreadsDomain . AnyThreadButSelf else ThreadsDomain . AnyThread
in
in
{ acc with threads }
{ acc with threads }
| Attribute . Functional ->
| Attribute . ( Functional | Nothing ) ->
acc
acc
in
in
let accesses =
let accesses =
@ -420,11 +418,11 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
match HilExp . get_access_exprs assume_exp with
match HilExp . get_access_exprs assume_exp with
| [ access_expr ] ->
| [ access_expr ] ->
HilExp . eval_boolean_exp access_expr assume_exp
HilExp . eval_boolean_exp access_expr assume_exp
| > Option . fold ~ init : astate ~ f : ( fun init bool_value ->
| > Option . value_map ~ default : astate ~ f : ( fun bool_value ->
let choices = AttributeMapDomain . get_choices access_expr astate . attribute_map in
(* prune ( prune_exp ) can only evaluate to true if the choice is [bool_value].
(* prune ( prune_exp ) can only evaluate to true if the choice is [bool_value].
add the constraint that the choice must be [ bool_value ] to the state * )
add the constraint that the choice must be [ bool_value ] to the state * )
List . fold ~ f : ( apply_choice bool_value ) ~ init choices )
AttributeMapDomain . find access_expr astate . attribute_map
| > apply_choice bool_value astate )
| _ ->
| _ ->
astate
astate
in
in
@ -548,15 +546,12 @@ let analyze_procedure {Callbacks.exe_env; summary} =
( Var . of_pvar ( Pvar . get_ret_pvar proc_name ) , Procdesc . get_ret_type proc_desc )
( Var . of_pvar ( Pvar . get_ret_pvar proc_name ) , Procdesc . get_ret_type proc_desc )
in
in
let return_ownership = OwnershipDomain . get_owned return_var_exp ownership in
let return_ownership = OwnershipDomain . get_owned return_var_exp ownership in
let return_attributes =
let return_attribute = AttributeMapDomain . find return_var_exp attribute_map in
try AttributeMapDomain . find return_var_exp attribute_map
with Caml . Not_found -> AttributeSetDomain . empty
in
let locks =
let locks =
(* if method is [synchronized] released the lock once. *)
(* if method is [synchronized] released the lock once. *)
if Procdesc . is_java_synchronized proc_desc then LocksDomain . release_lock locks else locks
if Procdesc . is_java_synchronized proc_desc then LocksDomain . release_lock locks else locks
in
in
let post = { threads ; locks ; accesses ; return_ownership ; return_attribute s } in
let post = { threads ; locks ; accesses ; return_ownership ; return_attribute } in
Payload . update_summary post summary
Payload . update_summary post summary
| None ->
| None ->
summary
summary