@ -810,6 +810,11 @@ let combine_conditional_unconditional_writes conditional_writes unconditional_wr
conditional_writes
unconditional_writes
let equal_locs ( sink1 : ThreadSafetyDomain . TraceElem . t )
( sink2 : ThreadSafetyDomain . TraceElem . t ) =
Location . equal
( CallSite . loc ( ThreadSafetyDomain . TraceElem . call_site sink1 ) )
( CallSite . loc ( ThreadSafetyDomain . TraceElem . call_site sink2 ) )
let equal_accesses ( sink1 : ThreadSafetyDomain . TraceElem . t )
( sink2 : ThreadSafetyDomain . TraceElem . t ) =
@ -855,26 +860,35 @@ let collect_conflicting_writes sink tab =
)
procs_and_writes
(* keep only the first copy of an access per procedure *)
(* keep only the first copy of an access per procedure,
and keep at most one warning per line ( they are usually interprocedural accesses
to different fields generated by the same call ) * )
let de_dup trace =
let original_sinks = ThreadSafetyDomain . PathDomain . sinks trace in
let select_representatives original_sinks predicate =
let list_of_original_sinks = ThreadSafetyDomain . PathDomain . Sinks . elements original_sinks in
let de_duped_sinks =
ThreadSafetyDomain . PathDomain . Sinks . filter
( fun sink ->
(* for each sink we will keep one in the equivalence class of those
with same access path . We select that by using find_exn to get
satisfying predicate . We select that by using find_exn to get
the first element equivalent ot sink in a list of sinks . This
first element is the dedup representative , and it happens to
typically be the first such access in a method . * )
let first_sink =
List . find_exn
~ f : ( fun sink2 -> equal_accesses sink sink2 )
~ f : ( fun sink2 -> predicate sink sink2 )
list_of_original_sinks in
Int . equal ( ThreadSafetyDomain . TraceElem . compare sink first_sink ) 0
)
original_sinks in
ThreadSafetyDomain . PathDomain . update_sinks trace de_duped_sinks
let de_duped_sinks_by_accesses = select_representatives
( ThreadSafetyDomain . PathDomain . sinks trace )
equal_accesses in
let de_duped_sinks_by_locs_and_accesses = select_representatives
de_duped_sinks_by_accesses
equal_locs in
ThreadSafetyDomain . PathDomain . update_sinks trace de_duped_sinks_by_locs_and_accesses
(* A helper function used in the error reporting *)
let pp_accesses_sink fmt ~ is_write_access sink =