@ -659,8 +659,8 @@ type reported_access =
 
			
		
	
		
		
			
				
					
					  ;  tenv :  Tenv . t 
  ;  tenv :  Tenv . t 
 
			
		
	
		
		
			
				
					
					  ;  procname :  Procname . t  } 
  ;  procname :  Procname . t  } 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					let  report_thread_safety_violation  ~ issue_log ~  make_description ~ report_kind let  report_thread_safety_violation  ~ ~ report_kind  
			
				
				
			
		
	
		
		
			
				
					
					    ( { threads ;  snapshot ;  tenv ;  procname =  pname }  :  reported_access )  = 
    ( { threads ;  snapshot ;  tenv ;  procname =  pname }  :  reported_access )  issue_log  = 
 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					  let  open  RacerDDomain  in 
  let  open  RacerDDomain  in 
 
			
		
	
		
		
			
				
					
					  let  final_pname  =  List . last  snapshot . trace  | >  Option . value_map  ~ default : pname  ~ f : CallSite . pname  in 
  let  final_pname  =  List . last  snapshot . trace  | >  Option . value_map  ~ default : pname  ~ f : CallSite . pname  in 
 
			
		
	
		
		
			
				
					
					  let  final_sink_site  =  CallSite . make  final_pname  snapshot . loc  in 
  let  final_sink_site  =  CallSite . make  final_pname  snapshot . loc  in 
 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -677,7 +677,7 @@ let report_thread_safety_violation ~issue_log ~make_description ~report_kind
 
			
		
	
		
		
			
				
					
					  log_issue  pname  ~ issue_log  ~ loc  ~ ltr  ~ access  issue_type  error_message 
  log_issue  pname  ~ issue_log  ~ loc  ~ ltr  ~ access  issue_type  error_message 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					let  report_unannotated_interface_violation  ~ issue_log  reported_pname  reported_access  = let  report_unannotated_interface_violation  reported_pname  reported_access  issue_log   =  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					  match  reported_pname  with 
  match  reported_pname  with 
 
			
		
	
		
		
			
				
					
					  |  Procname . Java  java_pname  -> 
  |  Procname . Java  java_pname  -> 
 
			
		
	
		
		
			
				
					
					      let  class_name  =  Procname . Java . get_class_name  java_pname  in 
      let  class_name  =  Procname . Java . get_class_name  java_pname  in 
 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -687,8 +687,8 @@ let report_unannotated_interface_violation ~issue_log reported_pname reported_ac
 
			
		
	
		
		
			
				
					
					           interface  with  % a  or  adding  a  lock . " 
           interface  with  % a  or  adding  a  lock . " 
 
			
		
	
		
		
			
				
					
					          describe_pname  reported_pname  MF . pp_monospaced  class_name  MF . pp_monospaced  " @ThreadSafe " 
          describe_pname  reported_pname  MF . pp_monospaced  class_name  MF . pp_monospaced  " @ThreadSafe " 
 
			
		
	
		
		
			
				
					
					      in 
      in 
 
			
		
	
		
		
			
				
					
					      report_thread_safety_violation  ~ issue_log ~  make_description ~ report_kind : UnannotatedInterface 
      report_thread_safety_violation  ~ ~ report_kind : UnannotatedInterface 
 
			
				
				
			
		
	
		
		
			
				
					
					        reported_access 
        reported_access  issue_log  
 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					  |  _  -> 
  |  _  -> 
 
			
		
	
		
		
			
				
					
					      (*  skip reporting on C++  *) 
      (*  skip reporting on C++  *) 
 
			
		
	
		
		
			
				
					
					      issue_log 
      issue_log 
 
			
		
	
	
		
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
					@ -728,23 +728,80 @@ let make_read_write_race_description ~read_is_sync (conflict : reported_access)
 
			
		
	
		
		
			
				
					
					    pp_access  final_sink  conflicts_description 
    pp_access  final_sink  conflicts_description 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					(* *  type for remembering what we have already reported to avoid duplicates. our policy is to report module  ReportedSet  :  sig  
			
				
				
			
		
	
		
		
			
				
					
					    each  kind  of  access  ( read / write )  to  the  same  field  reachable  from  the  same  procedure  only  once . 
  (* *  Type for deduplicating and storing reports.  *) 
 
			
				
				
			
		
	
		
		
			
				
					
					    in  addition ,  if  a  call  to  a  procedure  ( transitively )  accesses  multiple  fields ,  we  will  only 
  type  t 
 
			
				
				
			
		
	
		
		
			
				
					
					    report  one  of  each  kind  of  access  * ) 
 
			
				
				
			
		
	
		
		
			
				
					
					type  reported  =   val  reset  :  t  ->  t 
 
			
				
				
			
		
	
		
		
			
				
					
					  {  reported_sites :  CallSite . Set . t 
  (* *  Reset recorded writes and reads, while maintaining the same [IssueLog.t].  *) 
 
			
				
				
			
		
	
		
		
			
				
					
					  ;  reported_writes :  Procname . Set . t 
 
			
				
				
			
		
	
		
		
			
				
					
					  ;  reported_reads :  Procname . Set . t 
  val  empty_of_issue_log  :  IssueLog . t  ->  t 
 
			
				
				
			
		
	
		
		
			
				
					
					  ;  reported_unannotated_calls :  Procname . Set . t  } 
  (* *  Create a set of reports containing the given [IssueLog.t] but otherwise having no records of 
 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					      previous  reports .  * ) 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					  val  to_issue_log  :  t  ->  IssueLog . t 
 
			
		
	
		
		
			
				
					
					  (* *  Recover deduplicated [IssueLog.t] from [t].  *) 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					  val  deduplicate  :  f : ( reported_access  ->  IssueLog . t  ->  IssueLog . t )  ->  reported_access  ->  t  ->  t 
 
			
		
	
		
		
			
				
					
					  (* *  Deduplicate [f].  *) 
 
			
		
	
		
		
			
				
					
					end  =  struct  
			
		
	
		
		
			
				
					
					  type  reported_set  = 
 
			
		
	
		
		
			
				
					
					    {  sites :  CallSite . Set . t 
 
			
		
	
		
		
			
				
					
					    ;  writes :  Procname . Set . t 
 
			
		
	
		
		
			
				
					
					    ;  reads :  Procname . Set . t 
 
			
		
	
		
		
			
				
					
					    ;  unannotated_calls :  Procname . Set . t  } 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					  let  empty_reported_set  = 
 
			
		
	
		
		
			
				
					
					    {  sites =  CallSite . Set . empty 
 
			
		
	
		
		
			
				
					
					    ;  reads =  Procname . Set . empty 
 
			
		
	
		
		
			
				
					
					    ;  writes =  Procname . Set . empty 
 
			
		
	
		
		
			
				
					
					    ;  unannotated_calls =  Procname . Set . empty  } 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					  type  t  =  reported_set  *  IssueLog . t 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					  let  empty_of_issue_log  issue_log  =  ( empty_reported_set ,  issue_log ) 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					  let  to_issue_log  =  snd 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					  let  reset  ( reported_set ,  issue_log )  = 
 
			
		
	
		
		
			
				
					
					    ( { reported_set  with  writes =  Procname . Set . empty ;  reads =  Procname . Set . empty } ,  issue_log ) 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					  let  is_duplicate  { snapshot ;  procname }  ( reported_set ,  _ )  = 
 
			
		
	
		
		
			
				
					
					    let  call_site  =  CallSite . make  procname  ( RacerDDomain . AccessSnapshot . get_loc  snapshot )  in 
 
			
		
	
		
		
			
				
					
					    CallSite . Set . mem  call_site  reported_set . sites 
 
			
		
	
		
		
			
				
					
					    | | 
 
			
		
	
		
		
			
				
					
					    match  snapshot . elem . access  with 
 
			
		
	
		
		
			
				
					
					    |  Write  _  |  ContainerWrite  _  -> 
 
			
		
	
		
		
			
				
					
					        Procname . Set . mem  procname  reported_set . writes 
 
			
		
	
		
		
			
				
					
					    |  Read  _  |  ContainerRead  _  -> 
 
			
		
	
		
		
			
				
					
					        Procname . Set . mem  procname  reported_set . reads 
 
			
		
	
		
		
			
				
					
					    |  InterfaceCall  _  -> 
 
			
		
	
		
		
			
				
					
					        Procname . Set . mem  procname  reported_set . unannotated_calls 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					  let  update  { snapshot ;  procname }  ( reported_set ,  issue_log )  = 
 
			
		
	
		
		
			
				
					
					    let  call_site  =  CallSite . make  procname  ( RacerDDomain . AccessSnapshot . get_loc  snapshot )  in 
 
			
		
	
		
		
			
				
					
					    let  sites  =  CallSite . Set . add  call_site  reported_set . sites  in 
 
			
		
	
		
		
			
				
					
					    let  reported_set  =  { reported_set  with  sites }  in 
 
			
		
	
		
		
			
				
					
					    let  reported_set  = 
 
			
		
	
		
		
			
				
					
					      match  snapshot . elem . access  with 
 
			
		
	
		
		
			
				
					
					      |  Write  _  |  ContainerWrite  _  -> 
 
			
		
	
		
		
			
				
					
					          { reported_set  with  writes =  Procname . Set . add  procname  reported_set . writes } 
 
			
		
	
		
		
			
				
					
					      |  Read  _  |  ContainerRead  _  -> 
 
			
		
	
		
		
			
				
					
					          { reported_set  with  reads =  Procname . Set . add  procname  reported_set . reads } 
 
			
		
	
		
		
			
				
					
					      |  InterfaceCall  _  -> 
 
			
		
	
		
		
			
				
					
					          {  reported_set  with 
 
			
		
	
		
		
			
				
					
					            unannotated_calls =  Procname . Set . add  procname  reported_set . unannotated_calls  } 
 
			
		
	
		
		
			
				
					
					    in 
 
			
		
	
		
		
			
				
					
					    ( reported_set ,  issue_log ) 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					let  empty_reported  =  
			
		
	
		
		
			
				
					
					  let  reported_sites  =  CallSite . Set . empty  in 
 
			
		
	
		
		
			
				
					
					  let  reported_writes  =  Procname . Set . empty  in 
 
			
		
	
		
		
			
				
					
					  let  reported_reads  =  Procname . Set . empty  in 
 
			
		
	
		
		
			
				
					
					  let  reported_unannotated_calls  =  Procname . Set . empty  in 
 
			
		
	
		
		
			
				
					
					  { reported_sites ;  reported_reads ;  reported_writes ;  reported_unannotated_calls } 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					  let  deduplicate  ~ f  reported_access  ( ( reported_set ,  issue_log )  as  acc )  = 
 
			
		
	
		
		
			
				
					
					    if  Config . deduplicate  &&  is_duplicate  reported_access  acc  then  acc 
 
			
		
	
		
		
			
				
					
					    else  update  reported_access  ( reported_set ,  f  reported_access  issue_log ) 
 
			
		
	
		
		
			
				
					
					end  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					(* *  Map containing reported accesses, which groups them in lists, by abstract location. The (* *  Map containing reported accesses, which groups them in lists, by abstract location. The  
			
		
	
		
		
			
				
					
					    equivalence  relation  used  for  grouping  them  is  equality  of  access  paths .  This  is  slightly 
    equivalence  relation  used  for  grouping  them  is  equality  of  access  paths .  This  is  slightly 
 
			
		
	
	
		
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
					@ -895,68 +952,27 @@ let should_report_guardedby_violation classname ({snapshot; tenv; procname} : re
 
			
		
	
		
		
			
				
					
					let  report_unsafe_accesses  ~ issue_log  classname  ( aggregated_access_map  :  ReportMap . t )  = let  report_unsafe_accesses  ~ issue_log  classname  ( aggregated_access_map  :  ReportMap . t )  =  
			
		
	
		
		
			
				
					
					  let  open  RacerDDomain  in 
  let  open  RacerDDomain  in 
 
			
		
	
		
		
			
				
					
					  let  open  RacerDModels  in 
  let  open  RacerDModels  in 
 
			
		
	
		
		
			
				
					
					  let  is_duplicate_report  ( { snapshot ;  procname =  pname }  :  reported_access ) 
 
			
		
	
		
		
			
				
					
					      ( { reported_sites ;  reported_writes ;  reported_reads ;  reported_unannotated_calls } ,  _ )  = 
 
			
		
	
		
		
			
				
					
					    let  call_site  =  CallSite . make  pname  ( AccessSnapshot . get_loc  snapshot )  in 
 
			
		
	
		
		
			
				
					
					    if  Config . deduplicate  then 
 
			
		
	
		
		
			
				
					
					      CallSite . Set . mem  call_site  reported_sites 
 
			
		
	
		
		
			
				
					
					      | | 
 
			
		
	
		
		
			
				
					
					      match  snapshot . elem . access  with 
 
			
		
	
		
		
			
				
					
					      |  Access . Write  _  |  Access . ContainerWrite  _  -> 
 
			
		
	
		
		
			
				
					
					          Procname . Set . mem  pname  reported_writes 
 
			
		
	
		
		
			
				
					
					      |  Access . Read  _  |  Access . ContainerRead  _  -> 
 
			
		
	
		
		
			
				
					
					          Procname . Set . mem  pname  reported_reads 
 
			
		
	
		
		
			
				
					
					      |  Access . InterfaceCall  _  -> 
 
			
		
	
		
		
			
				
					
					          Procname . Set . mem  pname  reported_unannotated_calls 
 
			
		
	
		
		
			
				
					
					    else  false 
 
			
		
	
		
		
			
				
					
					  in 
 
			
		
	
		
		
			
				
					
					  let  update_reported  ( { snapshot ;  procname =  pname }  :  reported_access )  reported  = 
 
			
		
	
		
		
			
				
					
					    if  Config . deduplicate  then 
 
			
		
	
		
		
			
				
					
					      let  call_site  =  CallSite . make  pname  ( AccessSnapshot . get_loc  snapshot )  in 
 
			
		
	
		
		
			
				
					
					      let  reported_sites  =  CallSite . Set . add  call_site  reported . reported_sites  in 
 
			
		
	
		
		
			
				
					
					      match  snapshot . elem . access  with 
 
			
		
	
		
		
			
				
					
					      |  Access . Write  _  |  Access . ContainerWrite  _  -> 
 
			
		
	
		
		
			
				
					
					          let  reported_writes  =  Procname . Set . add  pname  reported . reported_writes  in 
 
			
		
	
		
		
			
				
					
					          { reported  with  reported_writes ;  reported_sites } 
 
			
		
	
		
		
			
				
					
					      |  Access . Read  _  |  Access . ContainerRead  _  -> 
 
			
		
	
		
		
			
				
					
					          let  reported_reads  =  Procname . Set . add  pname  reported . reported_reads  in 
 
			
		
	
		
		
			
				
					
					          { reported  with  reported_reads ;  reported_sites } 
 
			
		
	
		
		
			
				
					
					      |  Access . InterfaceCall  _  -> 
 
			
		
	
		
		
			
				
					
					          let  reported_unannotated_calls  = 
 
			
		
	
		
		
			
				
					
					            Procname . Set . add  pname  reported . reported_unannotated_calls 
 
			
		
	
		
		
			
				
					
					          in 
 
			
		
	
		
		
			
				
					
					          { reported  with  reported_unannotated_calls ;  reported_sites } 
 
			
		
	
		
		
			
				
					
					    else  reported 
 
			
		
	
		
		
			
				
					
					  in 
 
			
		
	
		
		
			
				
					
					  let  report_thread_safety_violation  ~ acc  ~ make_description  ~ report_kind  reported_access  = 
  let  report_thread_safety_violation  ~ acc  ~ make_description  ~ report_kind  reported_access  = 
 
			
		
	
		
		
			
				
					
					    if  is_duplicate_report  reported_access  acc  then  acc 
    ReportedSet . deduplicate 
 
			
				
				
			
		
	
		
		
			
				
					
					    else 
      ~ f : ( report_thread_safety_violation  ~ make_description  ~ report_kind ) 
 
			
				
				
			
		
	
		
		
			
				
					
					      let  reported_acc ,  issue_log  =  acc  in 
      reported_access  acc 
 
			
				
				
			
		
	
		
		
			
				
					
					      let  issue_log  = 
 
			
		
	
		
		
			
				
					
					        report_thread_safety_violation  ~ issue_log  ~ make_description  ~ report_kind  reported_access 
 
			
		
	
		
		
			
				
					
					      in 
 
			
		
	
		
		
			
				
					
					      ( update_reported  reported_access  reported_acc ,  issue_log ) 
 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					  in 
  in 
 
			
		
	
		
		
			
				
					
					  let  report_unannotated_interface_violation  ~ acc  reported_pname  reported_access  = 
  let  report_unannotated_interface_violation  ~ acc  reported_pname  reported_access  = 
 
			
		
	
		
		
			
				
					
					    if  is_duplicate_report  reported_access  acc  then  acc 
    ReportedSet . deduplicate 
 
			
				
				
			
		
	
		
		
			
				
					
					    else 
      ~ f : ( report_unannotated_interface_violation  reported_pname ) 
 
			
				
				
			
		
	
		
		
			
				
					
					      let  reported_acc ,  issue_log  =  acc  in 
      reported_access  acc 
 
			
				
				
			
		
	
		
		
			
				
					
					      let  issue_log  = 
 
			
		
	
		
		
			
				
					
					        report_unannotated_interface_violation  ~ issue_log  reported_pname  reported_access 
 
			
		
	
		
		
			
				
					
					      in 
 
			
		
	
		
		
			
				
					
					      ( update_reported  reported_access  reported_acc ,  issue_log ) 
 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					  in 
  in 
 
			
		
	
		
		
			
				
					
					  let  report_unsafe_access  accesses  acc 
  let  report_unsafe_access  accesses  acc 
 
			
		
	
		
		
			
				
					
					      ( { snapshot ;  threads ;  tenv ;  procname =  pname }  as  reported_access )  = 
      ( { snapshot ;  threads ;  tenv ;  procname =  pname }  as  reported_access )  = 
 
			
		
	
		
		
			
				
					
					    match  snapshot . elem . access  with 
    match  snapshot . elem . access  with 
 
			
		
	
		
		
			
				
					
					    |  Access . InterfaceCall  { pname =  reported_pname } 
    |  InterfaceCall  { pname =  reported_pname } 
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					      when  AccessSnapshot . is_unprotected  snapshot 
      when  AccessSnapshot . is_unprotected  snapshot 
 
			
		
	
		
		
			
				
					
					           &&  ThreadsDomain . is_any  threads  &&  is_marked_thread_safe  pname  tenv  -> 
           &&  ThreadsDomain . is_any  threads  &&  is_marked_thread_safe  pname  tenv  -> 
 
			
		
	
		
		
			
				
					
					        (*  un-annotated interface call + no lock in method marked thread-safe. warn  *) 
        (*  un-annotated interface call + no lock in method marked thread-safe. warn  *) 
 
			
		
	
		
		
			
				
					
					        report_unannotated_interface_violation  ~ acc  reported_pname  reported_access 
        report_unannotated_interface_violation  ~ acc  reported_pname  reported_access 
 
			
		
	
		
		
			
				
					
					    |  Access . InterfaceCall  _  -> 
    |  InterfaceCall  _  -> 
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					        acc 
        acc 
 
			
		
	
		
		
			
				
					
					    |  ( Access . Write  _  |  ContainerWrite  _ )  when  Procname . is_java  pname  -> 
    |  ( Write  _  |  ContainerWrite  _ )  when  Procname . is_java  pname  -> 
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					        let  conflict  = 
        let  conflict  = 
 
			
		
	
		
		
			
				
					
					          if  ThreadsDomain . is_any  threads  then 
          if  ThreadsDomain . is_any  threads  then 
 
			
		
	
		
		
			
				
					
					            (*  unprotected write in method that may run in parallel with itself. warn  *) 
            (*  unprotected write in method that may run in parallel with itself. warn  *) 
 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -977,10 +993,10 @@ let report_unsafe_accesses ~issue_log classname (aggregated_access_map : ReportM
 
			
		
	
		
		
			
				
					
					          report_thread_safety_violation  ~ acc  ~ make_description : make_unprotected_write_description 
          report_thread_safety_violation  ~ acc  ~ make_description : make_unprotected_write_description 
 
			
		
	
		
		
			
				
					
					            ~ report_kind : ( WriteWriteRace  conflict )  reported_access 
            ~ report_kind : ( WriteWriteRace  conflict )  reported_access 
 
			
		
	
		
		
			
				
					
					        else  acc 
        else  acc 
 
			
		
	
		
		
			
				
					
					    |  Access . Write  _  |  ContainerWrite  _  -> 
    |  Write  _  |  ContainerWrite  _  -> 
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					        (*  Do not report unprotected writes for ObjC_Cpp  *) 
        (*  Do not report unprotected writes for ObjC_Cpp  *) 
 
			
		
	
		
		
			
				
					
					        acc 
        acc 
 
			
		
	
		
		
			
				
					
					    |  ( Access . Read  _  |  ContainerRead  _ )  when  AccessSnapshot . is_unprotected  snapshot  -> 
    |  ( Read  _  |  ContainerRead  _ )  when  AccessSnapshot . is_unprotected  snapshot  -> 
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					        (*  unprotected read. report all writes as conflicts for java. for c++ filter out 
        (*  unprotected read. report all writes as conflicts for java. for c++ filter out 
 
			
		
	
		
		
			
				
					
					           unprotected  writes  * ) 
           unprotected  writes  * ) 
 
			
		
	
		
		
			
				
					
					        let  is_conflict  { snapshot ;  threads =  other_threads }  = 
        let  is_conflict  { snapshot ;  threads =  other_threads }  = 
 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -997,7 +1013,7 @@ let report_unsafe_accesses ~issue_log classname (aggregated_access_map : ReportM
 
			
		
	
		
		
			
				
					
					               in 
               in 
 
			
		
	
		
		
			
				
					
					               let  report_kind  =  ReadWriteRace  conflict . snapshot  in 
               let  report_kind  =  ReadWriteRace  conflict . snapshot  in 
 
			
		
	
		
		
			
				
					
					               report_thread_safety_violation  ~ acc  ~ make_description  ~ report_kind  reported_access  ) 
               report_thread_safety_violation  ~ acc  ~ make_description  ~ report_kind  reported_access  ) 
 
			
		
	
		
		
			
				
					
					    |  Access . Read  _  |  ContainerRead  _  -> 
    |  Read  _  |  ContainerRead  _  -> 
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					        (*  protected read. report unprotected writes and opposite protected writes as conflicts  *) 
        (*  protected read. report unprotected writes and opposite protected writes as conflicts  *) 
 
			
		
	
		
		
			
				
					
					        let  can_conflict  ( snapshot1  :  AccessSnapshot . t )  ( snapshot2  :  AccessSnapshot . t )  = 
        let  can_conflict  ( snapshot1  :  AccessSnapshot . t )  ( snapshot2  :  AccessSnapshot . t )  = 
 
			
		
	
		
		
			
				
					
					          if  snapshot1 . elem . lock  &&  snapshot2 . elem . lock  then  false 
          if  snapshot1 . elem . lock  &&  snapshot2 . elem . lock  then  false 
 
			
		
	
	
		
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
					@ -1034,15 +1050,14 @@ let report_unsafe_accesses ~issue_log classname (aggregated_access_map : ReportM
 
			
		
	
		
		
			
				
					
					          else  acc  ) 
          else  acc  ) 
 
			
		
	
		
		
			
				
					
					    else  init 
    else  init 
 
			
		
	
		
		
			
				
					
					  in 
  in 
 
			
		
	
		
		
			
				
					
					  let  report  grouped_accesses  ( reported ,  issue_log ) = 
  let  report  grouped_accesses  acc = 
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					    (*  reset the reported reads and writes for each memory location  *) 
    (*  reset the reported reads and writes for each memory location  *) 
 
			
		
	
		
		
			
				
					
					    let  reported  = 
    ReportedSet . reset  acc 
 
			
				
				
			
		
	
		
		
			
				
					
					      { reported  with  reported_writes =  Procname . Set . empty ;  reported_reads =  Procname . Set . empty } 
    | >  report_guardedby_violations_on_location  grouped_accesses 
 
			
				
				
			
		
	
		
		
			
				
					
					    in 
 
			
		
	
		
		
			
				
					
					    report_guardedby_violations_on_location  grouped_accesses  ( reported ,  issue_log ) 
 
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					    | >  report_accesses_on_location  grouped_accesses 
    | >  report_accesses_on_location  grouped_accesses 
 
			
		
	
		
		
			
				
					
					  in 
  in 
 
			
		
	
		
		
			
				
					
					  ReportMap . fold  report  aggregated_access_map  ( empty_reported ,  issue_log )  | >  snd 
  ReportMap . fold  report  aggregated_access_map  ( ReportedSet . empty_of_issue_log  issue_log ) 
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					  | >  ReportedSet . to_issue_log 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					(*  create a map from [abstraction of a memory loc] -> accesses that (*  create a map from [abstraction of a memory loc] -> accesses that