diff --git a/infer/src/concurrency/RacerD.ml b/infer/src/concurrency/RacerD.ml index 3d77505d5..351cba561 100644 --- a/infer/src/concurrency/RacerD.ml +++ b/infer/src/concurrency/RacerD.ml @@ -162,12 +162,15 @@ module TransferFunctions (CFG : ProcCfg.S) = struct let add_unannotated_call_access pname (call_flags: CallFlags.t) loc tenv ~locks ~threads attribute_map (proc_data: extras ProcData.t) = + let thread_safe_or_thread_confined annot = + Annotations.ia_is_thread_safe annot || Annotations.ia_is_thread_confined annot + in if call_flags.cf_interface && Typ.Procname.is_java pname && not (is_java_library pname || is_builder_function pname) (* can't ask anyone to annotate interfaces in library code, and Builder's should always be thread-safe (would be unreasonable to ask everyone to annotate them) *) - && not (PatternMatch.check_class_attributes Annotations.ia_is_thread_safe tenv pname) - && not (has_return_annot Annotations.ia_is_thread_safe pname) + && not (PatternMatch.check_class_attributes thread_safe_or_thread_confined tenv pname) + && not (has_return_annot thread_safe_or_thread_confined pname) then let open Domain in let pre = AccessPrecondition.make locks threads proc_data.pdesc in diff --git a/infer/tests/codetoanalyze/java/racerd/Dispatch.java b/infer/tests/codetoanalyze/java/racerd/Dispatch.java index 187144fb7..3d8605430 100644 --- a/infer/tests/codetoanalyze/java/racerd/Dispatch.java +++ b/infer/tests/codetoanalyze/java/racerd/Dispatch.java @@ -9,6 +9,7 @@ package codetoanalyze.java.checkers; +import com.facebook.infer.annotation.ThreadConfined; import com.facebook.infer.annotation.ThreadSafe; interface UnannotatedInterface { @@ -31,6 +32,17 @@ class NotThreadSafe { } } +@ThreadConfined(ThreadConfined.ANY) +interface ThreadConfinedInterface { + void foo(); +} + + +interface ThreadConfinedMethod { + + @ThreadConfined(ThreadConfined.ANY) + void foo(); +} @ThreadSafe public class Dispatch { @@ -55,4 +67,12 @@ public class Dispatch { i.foo(); } + void callThreadConfinedInterfaceOk(ThreadConfinedInterface t) { + t.foo(); + } + + void callThreadConfinedInterfaceMethodOk(ThreadConfinedMethod t) { + t.foo(); + } + }