|  |  |  | @ -9,7 +9,11 @@ open! IStd | 
			
		
	
		
			
				
					|  |  |  |  | module F = Format | 
			
		
	
		
			
				
					|  |  |  |  | module MF = MarkupFormatter | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | type lock = Lock | Unlock | LockedIfTrue | NoEffect | 
			
		
	
		
			
				
					|  |  |  |  | type lock_effect = | 
			
		
	
		
			
				
					|  |  |  |  |   | Lock of HilExp.t list | 
			
		
	
		
			
				
					|  |  |  |  |   | Unlock of HilExp.t list | 
			
		
	
		
			
				
					|  |  |  |  |   | LockedIfTrue of HilExp.t list | 
			
		
	
		
			
				
					|  |  |  |  |   | NoEffect | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | type thread = BackgroundThread | MainThread | MainThreadIfTrue | UnknownThread | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -41,116 +45,179 @@ let get_thread = function | 
			
		
	
		
			
				
					|  |  |  |  |       UnknownThread | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | let cpp_lock_types_matcher = | 
			
		
	
		
			
				
					|  |  |  |  |   QualifiedCppName.Match.of_fuzzy_qual_names | 
			
		
	
		
			
				
					|  |  |  |  |     [ "apache::thrift::concurrency::ReadWriteMutex" | 
			
		
	
		
			
				
					|  |  |  |  |     ; "folly::LockedPtr" | 
			
		
	
		
			
				
					|  |  |  |  |     ; "folly::MicroSpinLock" | 
			
		
	
		
			
				
					|  |  |  |  |     ; "folly::RWSpinLock" | 
			
		
	
		
			
				
					|  |  |  |  |     ; "folly::SharedMutex" | 
			
		
	
		
			
				
					|  |  |  |  |       (* NB not impl as in [matcher_lock] as this is just a type, not a call *) | 
			
		
	
		
			
				
					|  |  |  |  |     ; "folly::SpinLock" | 
			
		
	
		
			
				
					|  |  |  |  |     ; "folly::SpinLockGuard" | 
			
		
	
		
			
				
					|  |  |  |  |     ; "std::mutex" ] | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | let get_lock = | 
			
		
	
		
			
				
					|  |  |  |  |   let is_cpp_lock = | 
			
		
	
		
			
				
					|  |  |  |  |     let matcher_lock = | 
			
		
	
		
			
				
					|  |  |  |  |       QualifiedCppName.Match.of_fuzzy_qual_names | 
			
		
	
		
			
				
					|  |  |  |  |         [ "apache::thrift::concurrency::ReadWriteMutex::acquireRead" | 
			
		
	
		
			
				
					|  |  |  |  |         ; "apache::thrift::concurrency::ReadWriteMutex::acquireWrite" | 
			
		
	
		
			
				
					|  |  |  |  |         ; "folly::MicroSpinLock::lock" | 
			
		
	
		
			
				
					|  |  |  |  |         ; "folly::RWSpinLock::lock" | 
			
		
	
		
			
				
					|  |  |  |  |         ; "folly::RWSpinLock::lock_shared" | 
			
		
	
		
			
				
					|  |  |  |  |         ; "folly::SharedMutexImpl::lockExclusiveImpl" | 
			
		
	
		
			
				
					|  |  |  |  |         ; "folly::SharedMutexImpl::lockSharedImpl" | 
			
		
	
		
			
				
					|  |  |  |  |         ; "folly::SpinLock::lock" | 
			
		
	
		
			
				
					|  |  |  |  |         ; "std::lock" | 
			
		
	
		
			
				
					|  |  |  |  |         ; "std::mutex::lock" | 
			
		
	
		
			
				
					|  |  |  |  |         ; "std::unique_lock::lock" ] | 
			
		
	
		
			
				
					|  |  |  |  | module Clang : sig | 
			
		
	
		
			
				
					|  |  |  |  |   val get_lock_effect : Typ.Procname.t -> HilExp.t list -> lock_effect | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   val lock_types_matcher : QualifiedCppName.Match.quals_matcher | 
			
		
	
		
			
				
					|  |  |  |  | end = struct | 
			
		
	
		
			
				
					|  |  |  |  |   type lock_model = {cls: string; lck: string list; tlk: string list; unl: string list} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   let lock_models = | 
			
		
	
		
			
				
					|  |  |  |  |     let def = {cls= ""; lck= ["lock"]; tlk= ["try_lock"]; unl= ["unlock"]} in | 
			
		
	
		
			
				
					|  |  |  |  |     let shd = | 
			
		
	
		
			
				
					|  |  |  |  |       { cls= "std::shared_mutex" | 
			
		
	
		
			
				
					|  |  |  |  |       ; lck= "lock_shared" :: def.lck | 
			
		
	
		
			
				
					|  |  |  |  |       ; tlk= "try_lock_shared" :: def.tlk | 
			
		
	
		
			
				
					|  |  |  |  |       ; unl= "unlock_shared" :: def.unl } | 
			
		
	
		
			
				
					|  |  |  |  |     in | 
			
		
	
		
			
				
					|  |  |  |  |     let matcher_lock_constructor = | 
			
		
	
		
			
				
					|  |  |  |  |       QualifiedCppName.Match.of_fuzzy_qual_names | 
			
		
	
		
			
				
					|  |  |  |  |         [ "folly::LockedPtr::LockedPtr" | 
			
		
	
		
			
				
					|  |  |  |  |         ; "folly::SpinLockGuard::SpinLockGuard" | 
			
		
	
		
			
				
					|  |  |  |  |         ; "std::lock_guard::lock_guard" | 
			
		
	
		
			
				
					|  |  |  |  |         ; "std::unique_lock::unique_lock" ] | 
			
		
	
		
			
				
					|  |  |  |  |     let rwm = | 
			
		
	
		
			
				
					|  |  |  |  |       { cls= "apache::thrift::concurrency::ReadWriteMutex" | 
			
		
	
		
			
				
					|  |  |  |  |       ; lck= ["acquireRead"; "acquireWrite"] | 
			
		
	
		
			
				
					|  |  |  |  |       ; tlk= ["attemptRead"; "attemptWrite"] | 
			
		
	
		
			
				
					|  |  |  |  |       ; unl= ["release"] } | 
			
		
	
		
			
				
					|  |  |  |  |     in | 
			
		
	
		
			
				
					|  |  |  |  |     fun pname actuals -> | 
			
		
	
		
			
				
					|  |  |  |  |       QualifiedCppName.Match.match_qualifiers matcher_lock (Typ.Procname.get_qualifiers pname) | 
			
		
	
		
			
				
					|  |  |  |  |       || QualifiedCppName.Match.match_qualifiers matcher_lock_constructor | 
			
		
	
		
			
				
					|  |  |  |  |            (Typ.Procname.get_qualifiers pname) | 
			
		
	
		
			
				
					|  |  |  |  |          (* Passing additional parameter allows to defer the lock *) | 
			
		
	
		
			
				
					|  |  |  |  |          && Int.equal 2 (List.length actuals) | 
			
		
	
		
			
				
					|  |  |  |  |   and is_cpp_unlock = | 
			
		
	
		
			
				
					|  |  |  |  |     let matcher = | 
			
		
	
		
			
				
					|  |  |  |  |       QualifiedCppName.Match.of_fuzzy_qual_names | 
			
		
	
		
			
				
					|  |  |  |  |         [ "apache::thrift::concurrency::ReadWriteMutex::release" | 
			
		
	
		
			
				
					|  |  |  |  |         ; "folly::LockedPtr::~LockedPtr" | 
			
		
	
		
			
				
					|  |  |  |  |         ; "folly::MicroSpinLock::unlock" | 
			
		
	
		
			
				
					|  |  |  |  |         ; "folly::RWSpinLock::unlock" | 
			
		
	
		
			
				
					|  |  |  |  |         ; "folly::RWSpinLock::unlock_shared" | 
			
		
	
		
			
				
					|  |  |  |  |         ; "folly::SharedMutexImpl::unlock" | 
			
		
	
		
			
				
					|  |  |  |  |         ; "folly::SharedMutexImpl::unlock_shared" | 
			
		
	
		
			
				
					|  |  |  |  |         ; "folly::SpinLock::unlock" | 
			
		
	
		
			
				
					|  |  |  |  |         ; "folly::SpinLockGuard::~SpinLockGuard" | 
			
		
	
		
			
				
					|  |  |  |  |         ; "std::lock_guard::~lock_guard" | 
			
		
	
		
			
				
					|  |  |  |  |         ; "std::mutex::unlock" | 
			
		
	
		
			
				
					|  |  |  |  |         ; "std::unique_lock::unlock" | 
			
		
	
		
			
				
					|  |  |  |  |         ; "std::unique_lock::~unique_lock" ] | 
			
		
	
		
			
				
					|  |  |  |  |     [ {def with cls= "apache::thrift::concurrency::Monitor"; tlk= "timedlock" :: def.tlk} | 
			
		
	
		
			
				
					|  |  |  |  |     ; {def with cls= "apache::thrift::concurrency::Mutex"; tlk= "timedlock" :: def.tlk} | 
			
		
	
		
			
				
					|  |  |  |  |     ; {rwm with cls= "apache::thrift::concurrency::NoStarveReadWriteMutex"} | 
			
		
	
		
			
				
					|  |  |  |  |     ; rwm | 
			
		
	
		
			
				
					|  |  |  |  |     ; {shd with cls= "boost::shared_mutex"} | 
			
		
	
		
			
				
					|  |  |  |  |     ; {def with cls= "boost::mutex"} | 
			
		
	
		
			
				
					|  |  |  |  |     ; {def with cls= "folly::MicroSpinLock"} | 
			
		
	
		
			
				
					|  |  |  |  |     ; {shd with cls= "folly::RWSpinLock"} | 
			
		
	
		
			
				
					|  |  |  |  |     ; {shd with cls= "folly::SharedMutex"} | 
			
		
	
		
			
				
					|  |  |  |  |     ; {shd with cls= "folly::SharedMutexImpl"} | 
			
		
	
		
			
				
					|  |  |  |  |     ; {def with cls= "folly::SpinLock"} | 
			
		
	
		
			
				
					|  |  |  |  |     ; {def with cls= "std::shared_lock"} | 
			
		
	
		
			
				
					|  |  |  |  |     ; {def with cls= "std::mutex"} | 
			
		
	
		
			
				
					|  |  |  |  |     ; shd | 
			
		
	
		
			
				
					|  |  |  |  |     ; {def with cls= "std::unique_lock"; tlk= "owns_lock" :: def.tlk} ] | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   let mk_model_matcher ~f = | 
			
		
	
		
			
				
					|  |  |  |  |     let lock_methods = | 
			
		
	
		
			
				
					|  |  |  |  |       List.concat_map lock_models ~f:(fun mdl -> | 
			
		
	
		
			
				
					|  |  |  |  |           List.map (f mdl) ~f:(fun mtd -> mdl.cls ^ "::" ^ mtd) ) | 
			
		
	
		
			
				
					|  |  |  |  |     in | 
			
		
	
		
			
				
					|  |  |  |  |     let matcher = QualifiedCppName.Match.of_fuzzy_qual_names lock_methods in | 
			
		
	
		
			
				
					|  |  |  |  |     fun pname -> | 
			
		
	
		
			
				
					|  |  |  |  |       QualifiedCppName.Match.match_qualifiers matcher (Typ.Procname.get_qualifiers pname) | 
			
		
	
		
			
				
					|  |  |  |  |   and is_cpp_trylock = | 
			
		
	
		
			
				
					|  |  |  |  |     let matcher = | 
			
		
	
		
			
				
					|  |  |  |  |       QualifiedCppName.Match.of_fuzzy_qual_names | 
			
		
	
		
			
				
					|  |  |  |  |         ["folly::SpinLock::try_lock"; "std::unique_lock::owns_lock"; "std::unique_lock::try_lock"] | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   let is_lock = mk_model_matcher ~f:(fun mdl -> mdl.lck) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   let is_unlock = mk_model_matcher ~f:(fun mdl -> mdl.unl) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   let is_trylock = mk_model_matcher ~f:(fun mdl -> mdl.tlk) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   let lock_types_matcher = | 
			
		
	
		
			
				
					|  |  |  |  |     let class_names = List.map lock_models ~f:(fun mdl -> mdl.cls) in | 
			
		
	
		
			
				
					|  |  |  |  |     QualifiedCppName.Match.of_fuzzy_qual_names class_names | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   (* TODO std::scoped_lock *) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   let guards = | 
			
		
	
		
			
				
					|  |  |  |  |     [ "apache::thrift::concurrency::Guard" | 
			
		
	
		
			
				
					|  |  |  |  |     ; "apache::thrift::concurrency::Synchronized" | 
			
		
	
		
			
				
					|  |  |  |  |     ; "apache::thrift::concurrency::RWGuard" | 
			
		
	
		
			
				
					|  |  |  |  |     ; "folly::SharedMutex::ReadHolder" | 
			
		
	
		
			
				
					|  |  |  |  |     ; "folly::SharedMutex::WriteHolder" | 
			
		
	
		
			
				
					|  |  |  |  |     ; "folly::LockedPtr" | 
			
		
	
		
			
				
					|  |  |  |  |     ; "folly::SpinLockGuard" | 
			
		
	
		
			
				
					|  |  |  |  |     ; "std::lock_guard" | 
			
		
	
		
			
				
					|  |  |  |  |     ; "std::shared_lock" | 
			
		
	
		
			
				
					|  |  |  |  |     ; "std::unique_lock" ] | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   let get_guard_constructor, get_guard_destructor = | 
			
		
	
		
			
				
					|  |  |  |  |     let get_class_and_qual_name guard = | 
			
		
	
		
			
				
					|  |  |  |  |       let qual_name = QualifiedCppName.of_qual_string guard in | 
			
		
	
		
			
				
					|  |  |  |  |       let class_name, _ = Option.value_exn (QualifiedCppName.extract_last qual_name) in | 
			
		
	
		
			
				
					|  |  |  |  |       (class_name, qual_name) | 
			
		
	
		
			
				
					|  |  |  |  |     in | 
			
		
	
		
			
				
					|  |  |  |  |     ( (fun guard -> | 
			
		
	
		
			
				
					|  |  |  |  |         let class_name, qual_name = get_class_and_qual_name guard in | 
			
		
	
		
			
				
					|  |  |  |  |         let qual_constructor = QualifiedCppName.append_qualifier qual_name ~qual:class_name in | 
			
		
	
		
			
				
					|  |  |  |  |         QualifiedCppName.to_qual_string qual_constructor ) | 
			
		
	
		
			
				
					|  |  |  |  |     , fun guard -> | 
			
		
	
		
			
				
					|  |  |  |  |         let class_name, qual_name = get_class_and_qual_name guard in | 
			
		
	
		
			
				
					|  |  |  |  |         let qual_destructor = | 
			
		
	
		
			
				
					|  |  |  |  |           QualifiedCppName.append_qualifier qual_name ~qual:("~" ^ class_name) | 
			
		
	
		
			
				
					|  |  |  |  |         in | 
			
		
	
		
			
				
					|  |  |  |  |         QualifiedCppName.to_qual_string qual_destructor ) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   let is_guard_lock = | 
			
		
	
		
			
				
					|  |  |  |  |     let constructors = List.map guards ~f:get_guard_constructor in | 
			
		
	
		
			
				
					|  |  |  |  |     let matcher = QualifiedCppName.Match.of_fuzzy_qual_names constructors in | 
			
		
	
		
			
				
					|  |  |  |  |     fun pname actuals -> | 
			
		
	
		
			
				
					|  |  |  |  |       QualifiedCppName.Match.match_qualifiers matcher (Typ.Procname.get_qualifiers pname) | 
			
		
	
		
			
				
					|  |  |  |  |       (* Passing additional parameter allows to defer the lock *) | 
			
		
	
		
			
				
					|  |  |  |  |       && Int.equal 2 (List.length actuals) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   let is_guard_unlock = | 
			
		
	
		
			
				
					|  |  |  |  |     let destructors = List.map guards ~f:get_guard_destructor in | 
			
		
	
		
			
				
					|  |  |  |  |     let matcher = QualifiedCppName.Match.of_fuzzy_qual_names destructors in | 
			
		
	
		
			
				
					|  |  |  |  |     fun pname -> | 
			
		
	
		
			
				
					|  |  |  |  |       QualifiedCppName.Match.match_qualifiers matcher (Typ.Procname.get_qualifiers pname) | 
			
		
	
		
			
				
					|  |  |  |  |   in | 
			
		
	
		
			
				
					|  |  |  |  |   fun pname actuals -> | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   let is_std_lock = | 
			
		
	
		
			
				
					|  |  |  |  |     let matcher = QualifiedCppName.Match.of_fuzzy_qual_names ["std::lock"] in | 
			
		
	
		
			
				
					|  |  |  |  |     fun pname -> | 
			
		
	
		
			
				
					|  |  |  |  |       QualifiedCppName.Match.match_qualifiers matcher (Typ.Procname.get_qualifiers pname) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   let get_lock_effect pname actuals = | 
			
		
	
		
			
				
					|  |  |  |  |     let fst_arg = match actuals with x :: _ -> [x] | _ -> [] in | 
			
		
	
		
			
				
					|  |  |  |  |     let snd_arg = match actuals with _ :: x :: _ -> [x] | _ -> [] in | 
			
		
	
		
			
				
					|  |  |  |  |     if is_std_lock pname then Lock actuals | 
			
		
	
		
			
				
					|  |  |  |  |     else if is_lock pname then Lock fst_arg | 
			
		
	
		
			
				
					|  |  |  |  |     else if is_guard_lock pname actuals then Lock snd_arg | 
			
		
	
		
			
				
					|  |  |  |  |     else if is_unlock pname then Unlock fst_arg | 
			
		
	
		
			
				
					|  |  |  |  |     else if is_guard_unlock pname then Unlock snd_arg | 
			
		
	
		
			
				
					|  |  |  |  |     else if is_trylock pname then LockedIfTrue fst_arg | 
			
		
	
		
			
				
					|  |  |  |  |     else NoEffect | 
			
		
	
		
			
				
					|  |  |  |  | end | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | module Java : sig | 
			
		
	
		
			
				
					|  |  |  |  |   val get_lock_effect : Typ.Procname.t -> Typ.Procname.Java.t -> HilExp.t list -> lock_effect | 
			
		
	
		
			
				
					|  |  |  |  | end = struct | 
			
		
	
		
			
				
					|  |  |  |  |   let std_locks = | 
			
		
	
		
			
				
					|  |  |  |  |     [ "java.util.concurrent.locks.Lock" | 
			
		
	
		
			
				
					|  |  |  |  |     ; "java.util.concurrent.locks.ReentrantLock" | 
			
		
	
		
			
				
					|  |  |  |  |     ; "java.util.concurrent.locks.ReentrantReadWriteLock$ReadLock" | 
			
		
	
		
			
				
					|  |  |  |  |     ; "java.util.concurrent.locks.ReentrantReadWriteLock$WriteLock" ] | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   let is_lock classname methodname = | 
			
		
	
		
			
				
					|  |  |  |  |     List.mem std_locks classname ~equal:String.equal | 
			
		
	
		
			
				
					|  |  |  |  |     && List.mem ["lock"; "lockInterruptibly"] methodname ~equal:String.equal | 
			
		
	
		
			
				
					|  |  |  |  |     || String.equal classname "com.facebook.buck.util.concurrent.AutoCloseableReadWriteUpdateLock" | 
			
		
	
		
			
				
					|  |  |  |  |        && List.mem ["readLock"; "updateLock"; "writeLock"] methodname ~equal:String.equal | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   let is_unlock classname methodname = | 
			
		
	
		
			
				
					|  |  |  |  |     String.equal methodname "unlock" && List.mem std_locks classname ~equal:String.equal | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   let is_trylock classname methodname = | 
			
		
	
		
			
				
					|  |  |  |  |     String.equal methodname "tryLock" && List.mem std_locks classname ~equal:String.equal | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   let get_lock_effect pname java_pname actuals = | 
			
		
	
		
			
				
					|  |  |  |  |     let fst_arg = match actuals with x :: _ -> [x] | _ -> [] in | 
			
		
	
		
			
				
					|  |  |  |  |     if is_thread_utils_method "assertHoldsLock" pname then Lock fst_arg | 
			
		
	
		
			
				
					|  |  |  |  |     else | 
			
		
	
		
			
				
					|  |  |  |  |       let classname = Typ.Procname.Java.get_class_name java_pname in | 
			
		
	
		
			
				
					|  |  |  |  |       let methodname = Typ.Procname.Java.get_method java_pname in | 
			
		
	
		
			
				
					|  |  |  |  |       if is_lock classname methodname then Lock fst_arg | 
			
		
	
		
			
				
					|  |  |  |  |       else if is_unlock classname methodname then Unlock fst_arg | 
			
		
	
		
			
				
					|  |  |  |  |       else if is_trylock classname methodname then LockedIfTrue fst_arg | 
			
		
	
		
			
				
					|  |  |  |  |       else NoEffect | 
			
		
	
		
			
				
					|  |  |  |  | end | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | let get_lock_effect pname actuals = | 
			
		
	
		
			
				
					|  |  |  |  |   let fst_arg = match actuals with x :: _ -> [x] | _ -> [] in | 
			
		
	
		
			
				
					|  |  |  |  |   if Typ.Procname.equal pname BuiltinDecl.__set_locked_attribute then Lock fst_arg | 
			
		
	
		
			
				
					|  |  |  |  |   else if Typ.Procname.equal pname BuiltinDecl.__delete_locked_attribute then Unlock fst_arg | 
			
		
	
		
			
				
					|  |  |  |  |   else | 
			
		
	
		
			
				
					|  |  |  |  |     match pname with | 
			
		
	
		
			
				
					|  |  |  |  |     | Typ.Procname.Java java_pname -> ( | 
			
		
	
		
			
				
					|  |  |  |  |         if is_thread_utils_method "assertHoldsLock" (Typ.Procname.Java java_pname) then Lock | 
			
		
	
		
			
				
					|  |  |  |  |         else | 
			
		
	
		
			
				
					|  |  |  |  |           match | 
			
		
	
		
			
				
					|  |  |  |  |             (Typ.Procname.Java.get_class_name java_pname, Typ.Procname.Java.get_method java_pname) | 
			
		
	
		
			
				
					|  |  |  |  |           with | 
			
		
	
		
			
				
					|  |  |  |  |           | ( ( "java.util.concurrent.locks.Lock" | 
			
		
	
		
			
				
					|  |  |  |  |               | "java.util.concurrent.locks.ReentrantLock" | 
			
		
	
		
			
				
					|  |  |  |  |               | "java.util.concurrent.locks.ReentrantReadWriteLock$ReadLock" | 
			
		
	
		
			
				
					|  |  |  |  |               | "java.util.concurrent.locks.ReentrantReadWriteLock$WriteLock" ) | 
			
		
	
		
			
				
					|  |  |  |  |             , ("lock" | "lockInterruptibly") ) -> | 
			
		
	
		
			
				
					|  |  |  |  |               Lock | 
			
		
	
		
			
				
					|  |  |  |  |           | ( ( "java.util.concurrent.locks.Lock" | 
			
		
	
		
			
				
					|  |  |  |  |               | "java.util.concurrent.locks.ReentrantLock" | 
			
		
	
		
			
				
					|  |  |  |  |               | "java.util.concurrent.locks.ReentrantReadWriteLock$ReadLock" | 
			
		
	
		
			
				
					|  |  |  |  |               | "java.util.concurrent.locks.ReentrantReadWriteLock$WriteLock" ) | 
			
		
	
		
			
				
					|  |  |  |  |             , "unlock" ) -> | 
			
		
	
		
			
				
					|  |  |  |  |               Unlock | 
			
		
	
		
			
				
					|  |  |  |  |           | ( ( "java.util.concurrent.locks.Lock" | 
			
		
	
		
			
				
					|  |  |  |  |               | "java.util.concurrent.locks.ReentrantLock" | 
			
		
	
		
			
				
					|  |  |  |  |               | "java.util.concurrent.locks.ReentrantReadWriteLock$ReadLock" | 
			
		
	
		
			
				
					|  |  |  |  |               | "java.util.concurrent.locks.ReentrantReadWriteLock$WriteLock" ) | 
			
		
	
		
			
				
					|  |  |  |  |             , "tryLock" ) -> | 
			
		
	
		
			
				
					|  |  |  |  |               LockedIfTrue | 
			
		
	
		
			
				
					|  |  |  |  |           | ( "com.facebook.buck.util.concurrent.AutoCloseableReadWriteUpdateLock" | 
			
		
	
		
			
				
					|  |  |  |  |             , ("readLock" | "updateLock" | "writeLock") ) -> | 
			
		
	
		
			
				
					|  |  |  |  |               Lock | 
			
		
	
		
			
				
					|  |  |  |  |           | _ -> | 
			
		
	
		
			
				
					|  |  |  |  |               NoEffect ) | 
			
		
	
		
			
				
					|  |  |  |  |     | (Typ.Procname.ObjC_Cpp _ | C _) as pname when is_cpp_lock pname actuals -> | 
			
		
	
		
			
				
					|  |  |  |  |         Lock | 
			
		
	
		
			
				
					|  |  |  |  |     | (Typ.Procname.ObjC_Cpp _ | C _) as pname when is_cpp_unlock pname -> | 
			
		
	
		
			
				
					|  |  |  |  |         Unlock | 
			
		
	
		
			
				
					|  |  |  |  |     | (Typ.Procname.ObjC_Cpp _ | C _) as pname when is_cpp_trylock pname -> | 
			
		
	
		
			
				
					|  |  |  |  |         LockedIfTrue | 
			
		
	
		
			
				
					|  |  |  |  |     | pname when Typ.Procname.equal pname BuiltinDecl.__set_locked_attribute -> | 
			
		
	
		
			
				
					|  |  |  |  |         Lock | 
			
		
	
		
			
				
					|  |  |  |  |     | pname when Typ.Procname.equal pname BuiltinDecl.__delete_locked_attribute -> | 
			
		
	
		
			
				
					|  |  |  |  |         Unlock | 
			
		
	
		
			
				
					|  |  |  |  |     | Typ.Procname.Java java_pname -> | 
			
		
	
		
			
				
					|  |  |  |  |         Java.get_lock_effect pname java_pname actuals | 
			
		
	
		
			
				
					|  |  |  |  |     | Typ.Procname.(ObjC_Cpp _ | C _) -> | 
			
		
	
		
			
				
					|  |  |  |  |         Clang.get_lock_effect pname actuals | 
			
		
	
		
			
				
					|  |  |  |  |     | _ -> | 
			
		
	
		
			
				
					|  |  |  |  |         NoEffect | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -269,3 +336,6 @@ let runs_on_ui_thread = | 
			
		
	
		
			
				
					|  |  |  |  |                  (MF.monospaced_to_string Annotations.ui_thread)) | 
			
		
	
		
			
				
					|  |  |  |  |         | _ -> | 
			
		
	
		
			
				
					|  |  |  |  |             None ) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | let cpp_lock_types_matcher = Clang.lock_types_matcher | 
			
		
	
	
		
			
				
					|  |  |  | 
 |