@ -1790,9 +1790,9 @@ let prop_reset_inst inst_map prop =
(* * {2 Attributes} *)
(* * Return the exp and attribute marked in the atom if any, and return None otherwise *)
let atom_get_exp_attribute = function
| Sil . Apred ( a , e ) -> Some ( true , a , e )
| Sil . A npred ( a , e ) -> Some ( false , a , e )
let atom_get_exp_attribute atom =
match atom with
| Sil . A pred _ | Anpred _ -> Some atom
| _ -> None
(* * Check whether an atom is used to mark an attribute *)
@ -1804,8 +1804,7 @@ let get_exp_attributes prop exp =
let nexp = exp_normalize_prop prop exp in
let atom_get_attr attributes atom =
match atom with
| Sil . Apred ( att , e ) when Sil . exp_equal e nexp -> ( true , att ) :: attributes
| Sil . Anpred ( att , e ) when Sil . exp_equal e nexp -> ( false , att ) :: attributes
| Sil . Apred ( _ , e ) | Anpred ( _ , e ) when Sil . exp_equal e nexp -> atom :: attributes
| _ -> attributes in
IList . fold_left atom_get_attr [] prop . pi
@ -1816,11 +1815,13 @@ let attributes_in_same_category attr1 attr2 =
let get_attribute prop exp category =
let atts = get_exp_attributes prop exp in
try Some ( IList . find
( fun ( _ , att ) ->
Sil . attribute_category_equal
( Sil . attribute_to_category att ) category )
atts )
try
Some
( IList . find ( function
| Sil . Apred ( att , _ ) | Anpred ( att , _ ) ->
Sil . attribute_category_equal ( Sil . attribute_to_category att ) category
| _ -> false
) atts )
with Not_found -> None
let get_undef_attribute prop exp =
@ -1849,7 +1850,10 @@ let get_retval_attribute prop exp =
let has_dangling_uninit_attribute prop exp =
let la = get_exp_attributes prop exp in
IList . exists ( fun ( pol , a ) -> pol && Sil . attribute_equal a ( Adangling DAuninit ) ) la
IList . exists ( function
| Sil . Apred ( a , _ ) -> Sil . attribute_equal a ( Adangling DAuninit )
| _ -> false
) la
(* * Get all the attributes of the prop *)
let get_all_attributes prop =
@ -1866,77 +1870,76 @@ let set_exp_attribute ?(footprint = false) ?(polarity = true) prop attr exp =
( if polarity then Sil . Apred ( attr , exp ) else Sil . Anpred ( attr , exp ) )
(* * Replace an attribute associated to the expression *)
let add_or_replace_exp_attribute_check_changed check_attribute_change prop pol0 att0 exp =
let nexp = exp_normalize_prop prop exp in
let atom_map a = match a with
| Sil . Apred ( att , e ) | Anpred ( att , e ) ->
if Sil . exp_equal nexp e && attributes_in_same_category att att0 then
begin
let add_or_replace_exp_attribute_check_changed check_attribute_change prop atom0 =
match atom0 with
| Sil . Apred ( att0 , exp0 ) | Anpred ( att0 , exp0 ) ->
let nexp = exp_normalize_prop prop exp0 in
let atom = Sil . atom_replace_exp [ ( exp0 , nexp ) ] atom0 in
let atom_map = function
| Sil . Apred ( att , exp ) | Anpred ( att , exp )
when Sil . exp_equal nexp exp && attributes_in_same_category att att0 ->
check_attribute_change att att0 ;
if pol0 then Sil . Apred ( att0 , e ) else Sil . Anpred ( att0 , e )
end
else a
| _ -> a in
let pi = get_pi prop in
let pi' = IList . map_changed atom_map pi in
if pi = = pi'
then set_exp_attribute prop ~ polarity : pol0 att0 nexp
else replace_pi pi' prop
let add_or_replace_exp_attribute prop pol att exp =
atom
| a ->
a in
let pi = get_pi prop in
let pi' = IList . map_changed atom_map pi in
if pi = = pi'
then prop_atom_and prop atom
else replace_pi pi' prop
| _ ->
prop
let add_or_replace_exp_attribute prop atom =
(* wrapper for the most common case: do nothing *)
let check_attr_changed = ( fun _ _ -> () ) in
add_or_replace_exp_attribute_check_changed check_attr_changed prop pol att exp
add_or_replace_exp_attribute_check_changed check_attr_changed prop atom
(* * mark Sil.Var's or Sil.Lvar's as undefined *)
let mark_vars_as_undefined prop vars_to_mark callee_pname ret_annots loc path_pos =
let att_undef = Sil . Aundef ( callee_pname , ret_annots , loc , path_pos ) in
let mark_var_as_undefined exp prop =
match exp with
| Sil . Var _ | Sil . Lvar _ -> add_or_replace_exp_attribute prop true att_undef exp
| Sil . Var _ | Lvar _ -> add_or_replace_exp_attribute prop ( Apred ( att_undef , exp ) )
| _ -> prop in
IList . fold_left ( fun prop id -> mark_var_as_undefined id prop ) prop vars_to_mark
let remove_attribute_by_filter ~ f prop =
let atom_remove atom pi = match atom with
| Sil . Apred ( att_old , exp ) ->
if f true att_old exp then
pi
else atom :: pi
| Sil . Anpred ( att_old , exp ) ->
if f false att_old exp then
pi
else atom :: pi
| _ -> atom :: pi in
let pi' = IList . fold_right atom_remove ( get_pi prop ) [] in
replace_pi pi' prop
let filter_atoms ~ f prop =
replace_pi ( IList . filter f ( get_pi prop ) ) prop
(* * Remove an attribute from all the atoms in the heap *)
let remove_attribute prop pol0 att0 =
let f pol att _ = bool_equal pol0 pol && Sil . attribute_equal att0 att in
remove_attribute_by_filter ~ f prop
let remove_attribute prop att0 =
let f = function
| Sil . Apred ( att , _ ) | Anpred ( att , _ ) -> not ( Sil . attribute_equal att0 att )
| _ -> true in
filter_atoms ~ f prop
let remove_resource_attribute ra_kind ra_res =
let f pol att_old _ = match att_old with
| Sil . Aresource res_action when pol ->
Sil . res_act_kind_compare res_action . Sil . ra_kind ra_kind = = 0
&& Sil . resource_compare res_action . Sil . ra_res ra_res = = 0
| _ -> false in
remove_attribute_by_filter ~ f
let remove_attribute_from_exp prop pol att exp =
let nexp = exp_normalize_prop prop exp in
let f pol_old att_old e =
bool_equal pol pol_old && Sil . attribute_equal att_old att && Sil . exp_equal nexp e in
remove_attribute_by_filter ~ f prop
let f = function
| Sil . Apred ( Aresource res_action , _ ) ->
Sil . res_act_kind_compare res_action . ra_kind ra_kind < > 0
| | Sil . resource_compare res_action . ra_res ra_res < > 0
| _ -> true in
filter_atoms ~ f
let remove_attribute_from_exp prop atom =
match atom with
| Sil . Apred ( _ , exp ) | Anpred ( _ , exp ) ->
let nexp = exp_normalize_prop prop exp in
let natom = Sil . atom_replace_exp [ ( exp , nexp ) ] atom in
let f a = not ( Sil . atom_equal natom a ) in
filter_atoms ~ f prop
| _ ->
replace_pi ( get_pi prop ) prop
(* Replace an attribute OBJC_NULL ( $n1 ) with OBJC_NULL ( var ) when var = $n1, and also sets $n1 = 0 *)
let replace_objc_null prop lhs_exp rhs_exp =
match get_objc_null_attribute prop rhs_exp , rhs_exp with
| Some ( pol , att ) , Sil . Var _ ->
let prop = remove_attribute_from_exp prop pol att rhs_exp in
| Some atom , Sil . Var _ ->
let prop = remove_attribute_from_exp prop atom in
let prop = conjoin_eq rhs_exp Sil . exp_zero prop in
add_or_replace_exp_attribute prop true att lhs_exp
let natom = Sil . atom_replace_exp [ ( rhs_exp , lhs_exp ) ] atom in
add_or_replace_exp_attribute prop natom
| _ -> prop
let rec nullify_exp_with_objc_null prop exp =
@ -1948,8 +1951,8 @@ let rec nullify_exp_with_objc_null prop exp =
nullify_exp_with_objc_null prop exp
| Sil . Var _ ->
( match get_objc_null_attribute prop exp with
| Some ( pol , att ) ->
let prop' = remove_attribute_from_exp prop pol att exp in
| Some atom ->
let prop' = remove_attribute_from_exp prop atom in
conjoin_eq exp Sil . exp_zero prop'
| _ -> prop )
| _ -> prop
@ -1992,7 +1995,7 @@ let find_arithmetic_problem proc_node_session prop exp =
match exp_normalize_prop prop e with
| Sil . Const c when iszero_int_float c -> true
| _ ->
res := add_or_replace_exp_attribute ! res true ( Adiv0 proc_node_session ) e ;
res := add_or_replace_exp_attribute ! res ( Apred ( Adiv0 proc_node_session , e ) ) ;
false in
let rec walk = function
| Sil . Var _ -> ()
@ -2050,7 +2053,7 @@ let deallocate_stack_vars p pvars =
if Sil . fav_mem p'_fav freshv then (* the address of a de-allocated stack var in in the post *)
begin
stack_vars_address_in_post := v :: ! stack_vars_address_in_post ;
res := add_or_replace_exp_attribute ! res true ( Adangling DAaddr_stack_var ) ( Var freshv )
res := add_or_replace_exp_attribute ! res ( Apred ( Adangling DAaddr_stack_var , Var freshv ) )
end in
IList . iter do_var ! fresh_address_vars ;
! res in
@ -2850,7 +2853,7 @@ let find_equal_formal_path e prop =
| Some ( v , rev_fs ) -> Some ( v , IList . rev rev_fs )
| None ->
match get_objc_null_attribute prop e with
| Some ( true , Aobjc_null ( v , fs ) ) -> Some ( v , fs )
| Some ( Apred ( Aobjc_null ( v , fs ) , _ ) ) -> Some ( v , fs )
| _ -> None
(* * translate an if-then-else expression *)