@ -83,7 +83,10 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
 
			
		
	
		
		
			
				
					
					      path_state 
      path_state 
 
			
		
	
		
		
			
				
					
					      ( AccessPath . of_exp  exp  typ  ~ f_resolve_id : ( fun  _  ->  None ) ) 
      ( AccessPath . of_exp  exp  typ  ~ f_resolve_id : ( fun  _  ->  None ) ) 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					  let  exec_instr  ( ( lockstate ,  ( readstate , writestate ) )  as  astate )  {  ProcData . pdesc ;  tenv ;  }  _  = 
  let  exec_instr 
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					      ( {  ThreadSafetyDomain . locks ;  reads ;  writes ;  }  as  astate ) 
 
			
		
	
		
		
			
				
					
					      {  ProcData . pdesc ;  tenv ;  }  _  = 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					    let  is_unprotected  is_locked  = 
    let  is_unprotected  is_locked  = 
 
			
		
	
		
		
			
				
					
					      not  is_locked  &&  not  ( Procdesc . is_java_synchronized  pdesc )  in 
      not  is_locked  &&  not  ( Procdesc . is_java_synchronized  pdesc )  in 
 
			
		
	
		
		
			
				
					
					    function 
    function 
 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -92,41 +95,44 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
 
			
		
	
		
		
			
				
					
					          (*  assuming that modeled procedures do not have useful summaries  *) 
          (*  assuming that modeled procedures do not have useful summaries  *) 
 
			
		
	
		
		
			
				
					
					          match  get_lock_model  pn  with 
          match  get_lock_model  pn  with 
 
			
		
	
		
		
			
				
					
					          |  Lock  -> 
          |  Lock  -> 
 
			
		
	
		
		
			
				
					
					              true ,  snd  astate 
              {  astate  with  locks  =  true ;  } 
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					          |  Unlock  -> 
          |  Unlock  -> 
 
			
		
	
		
		
			
				
					
					              false ,  snd  astate 
              {  astate  with  locks  =  false ;  } 
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					          |  None  -> 
          |  None  -> 
 
			
		
	
		
		
			
				
					
					              begin 
              begin 
 
			
		
	
		
		
			
				
					
					                match  Summary . read_summary  pdesc  pn  with 
                match  Summary . read_summary  pdesc  pn  with 
 
			
		
	
		
		
			
				
					
					                |  Some  ( callee_lockstate ,  ( callee_reads ,  callee_writes ) ) -> 
                |  Some  callee_astate -> 
 
			
				
				
			
		
	
		
		
			
				
					
					                    let  locks tate ' =  callee_ lockstate  | |  locks tate  in 
                    let  locks ' =  callee_ astate.  locks | |  locks  in 
 
			
				
				
			
		
	
		
		
			
				
					
					                    let  _ ,  re ad_write state' = 
                    let  = 
 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					                      (*  TODO  ( 14842325 ) : report on constructors that aren't threadsafe 
                      (*  TODO  ( 14842325 ) : report on constructors that aren't threadsafe 
 
			
		
	
		
		
			
				
					
					                         ( e . g . ,  constructors  that  access  static  fields )  * ) 
                         ( e . g . ,  constructors  that  access  static  fields )  * ) 
 
			
		
	
		
		
			
				
					
					                      if  is_unprotected  locks tate ' && 
                      if  is_unprotected  locks ' && 
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					                         not  ( is_initializer  tenv  pn )  && 
                         not  ( is_initializer  tenv  pn )  && 
 
			
		
	
		
		
			
				
					
					                         not  ( is_call_to_builder_class_method  pn ) 
                         not  ( is_call_to_builder_class_method  pn ) 
 
			
		
	
		
		
			
				
					
					                      then 
                      then 
 
			
		
	
		
		
			
				
					
					                        let  call_site  =  CallSite . make  pn  loc  in 
                        let  call_site  =  CallSite . make  pn  loc  in 
 
			
		
	
		
		
			
				
					
					                        let  callee_reads tate  = 
                        let  callee_reads  = 
 
			
				
				
			
		
	
		
		
			
				
					
					                          ThreadSafetyDomain . PathDomain . with_callsite  callee_ reads call_site  in 
                          ThreadSafetyDomain . PathDomain . with_callsite  callee_ astate.  reads call_site  in 
 
			
				
				
			
		
	
		
		
			
				
					
					                        let  callee_writes tate  = 
                        let  callee_writes  = 
 
			
				
				
			
		
	
		
		
			
				
					
					                          ThreadSafetyDomain . PathDomain . with_callsite  callee_ writes call_site  in 
                          ThreadSafetyDomain . PathDomain . with_callsite  callee_ astate.  writes call_site  in 
 
			
				
				
			
		
	
		
		
			
				
					
					                        let  callee_astate  = 
                        let  callee_astate '  = 
 
			
				
				
			
		
	
		
		
			
				
					
					                          callee_lockstate ,  ( callee_readstate ,  callee_writestate ) in 
                          {  callee_astate  with  ThreadSafetyDomain . reads  =  callee_reads ;  writes  =  callee_writes ;  } in 
 
			
				
				
			
		
	
		
		
			
				
					
					                        ThreadSafetyDomain . join  callee_astate  astate 
                        ThreadSafetyDomain . join  callee_astate '  astate 
 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					                      else 
                      else 
 
			
		
	
		
		
			
				
					
					                        astate  in 
                        astate  in 
 
			
		
	
		
		
			
				
					
					                    lockstate' ,  read_writestate' 
                    {  astate'  with  locks  =  locks'  } 
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					                |  None  -> 
                |  None  -> 
 
			
		
	
		
		
			
				
					
					                    astate 
                    astate 
 
			
		
	
		
		
			
				
					
					              end 
              end 
 
			
		
	
		
		
			
				
					
					        end 
        end 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					    |  Sil . Store  ( ( Lfield  (  _ ,  _ ,  typ )  as  lhsfield )  ,  _ ,  _ ,  loc )  -> 
    |  Sil . Store  ( ( Lfield  (  _ ,  _ ,  typ )  as  lhsfield )  ,  _ ,  _ ,  loc )  -> 
 
			
		
	
		
		
			
				
					
					        if  is_unprotected  lockstate  then  (*  abstracts no lock being held *) 
        if  is_unprotected  locks  (*  abstracts no lock being held  *) 
 
			
				
				
			
		
	
		
		
			
				
					
					          ( lockstate ,  ( readstate ,  add_path_to_state  lhsfield  typ  loc  writestate ) ) 
        then 
 
			
				
				
			
		
	
		
		
			
				
					
					        else  astate 
          let  writes'  =  add_path_to_state  lhsfield  typ  loc  writes  in 
 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					          {  astate  with  writes  =  writes' ;  } 
 
			
		
	
		
		
			
				
					
					        else 
 
			
		
	
		
		
			
				
					
					          astate 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					    (*  Note: it appears that the third arg of Store is never an Lfield in the targets of, 
    (*  Note: it appears that the third arg of Store is never an Lfield in the targets of, 
 
			
		
	
		
		
			
				
					
					       our  translations ,  which  is  why  we  have  not  covered  that  case .  * ) 
       our  translations ,  which  is  why  we  have  not  covered  that  case .  * ) 
 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -134,9 +140,12 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
 
			
		
	
		
		
			
				
					
					        failwith  " Unexpected store instruction with rhs field " 
        failwith  " Unexpected store instruction with rhs field " 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					    |  Sil . Load  ( _ ,  ( Lfield  (  _ ,  _ ,  typ )  as  rhsfield )  ,  _ ,  loc )  -> 
    |  Sil . Load  ( _ ,  ( Lfield  (  _ ,  _ ,  typ )  as  rhsfield )  ,  _ ,  loc )  -> 
 
			
		
	
		
		
			
				
					
					        if  is_unprotected  lockstate  then  (*  abstracts no lock being held *) 
        if  is_unprotected  locks  (*  abstracts no lock being held  *) 
 
			
				
				
			
		
	
		
		
			
				
					
					          ( lockstate ,  ( add_path_to_state  rhsfield  typ  loc  readstate ,  writestate ) ) 
        then 
 
			
				
				
			
		
	
		
		
			
				
					
					        else  astate 
          let  reads'  =  add_path_to_state  rhsfield  typ  loc  reads  in 
 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					          {  astate  with  reads  =  reads' ;  } 
 
			
		
	
		
		
			
				
					
					        else 
 
			
		
	
		
		
			
				
					
					          astate 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					    |   _   -> 
    |   _   -> 
 
			
		
	
		
		
			
				
					
					        astate 
        astate 
 
			
		
	
	
		
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
					@ -224,7 +233,7 @@ let report_thread_safety_errors ( _, tenv, pname, pdesc) trace =
 
			
		
	
		
		
			
				
					
					  let  open  ThreadSafetyDomain  in 
  let  open  ThreadSafetyDomain  in 
 
			
		
	
		
		
			
				
					
					  let  trace_of_pname  callee_pname  = 
  let  trace_of_pname  callee_pname  = 
 
			
		
	
		
		
			
				
					
					    match  Summary . read_summary  pdesc  callee_pname  with 
    match  Summary . read_summary  pdesc  callee_pname  with 
 
			
		
	
		
		
			
				
					
					    |  Some  ( _ ,  ( _ ,  callee_trace ) )  ->  callee_trace 
    |  Some  astate  ->  astate . writes 
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					    |  _  ->  PathDomain . initial  in 
    |  _  ->  PathDomain . initial  in 
 
			
		
	
		
		
			
				
					
					  let  report_one_path  ( ( _ ,  sinks )  as  path )  = 
  let  report_one_path  ( ( _ ,  sinks )  as  path )  = 
 
			
		
	
		
		
			
				
					
					    let  pp_accesses  fmt  sink  = 
    let  pp_accesses  fmt  sink  = 
 
			
		
	
	
		
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
					@ -261,9 +270,9 @@ let report_thread_safety_errors ( _, tenv, pname, pdesc) trace =
 
			
		
	
		
		
			
				
					
					   This  indicates  that  the  method  races  with  itself .  To  be  refined  later .  * ) 
   This  indicates  that  the  method  races  with  itself .  To  be  refined  later .  * ) 
 
			
		
	
		
		
			
				
					
					let  process_results_table  tab  = let  process_results_table  tab  =  
			
		
	
		
		
			
				
					
					  ResultsTableType . iter    (*  report errors for each method  *) 
  ResultsTableType . iter    (*  report errors for each method  *) 
 
			
		
	
		
		
			
				
					
					    ( fun  proc_env  (  _ , (  _ ,  writestate )  )  -> 
    ( fun  proc_env  ( astate  :  ThreadSafetyDomain . astate )  -> 
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					       if  should_report_on_proc  proc_env  then 
       if  should_report_on_proc  proc_env  then 
 
			
		
	
		
		
			
				
					
					         report_thread_safety_errors  proc_env  tate 
         report_thread_safety_errors  proc_env  astate.  writes
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					       else  () 
       else  () 
 
			
		
	
		
		
			
				
					
					    ) 
    ) 
 
			
		
	
		
		
			
				
					
					    tab 
    tab