diff --git a/infer/src/checkers/annotations.ml b/infer/src/checkers/annotations.ml index 4b97bb2be..3caa41fbb 100644 --- a/infer/src/checkers/annotations.ml +++ b/infer/src/checkers/annotations.ml @@ -251,5 +251,3 @@ let ia_is_mainthread ia = ia_ends_with ia mainthread let ia_is_thread_confined ia = ia_ends_with ia thread_confined let ia_is_worker_thread ia = ia_ends_with ia worker_thread - -let ia_is_guardedby ia = ia_ends_with ia guarded_by diff --git a/infer/src/checkers/annotations.mli b/infer/src/checkers/annotations.mli index 32265cab6..c1d5d6e64 100644 --- a/infer/src/checkers/annotations.mli +++ b/infer/src/checkers/annotations.mli @@ -84,8 +84,6 @@ val ia_is_expensive : Annot.Item.t -> bool val ia_is_functional : Annot.Item.t -> bool -val ia_is_guardedby : Annot.Item.t -> bool - val ia_is_propagates_nullable : Annot.Item.t -> bool val ia_is_ignore_allocations : Annot.Item.t -> bool diff --git a/infer/src/concurrency/RacerD.ml b/infer/src/concurrency/RacerD.ml index 85e93655d..07a5f9083 100644 --- a/infer/src/concurrency/RacerD.ml +++ b/infer/src/concurrency/RacerD.ml @@ -938,6 +938,19 @@ let should_report_on_proc tenv procdesc = let should_report_guardedby_violation classname_str ({snapshot; tenv; procdesc} : reported_access) = + let is_uitthread param = + match String.lowercase param with + | "ui thread" | "ui-thread" | "ui_thread" | "uithread" -> + true + | _ -> + false + in + let field_is_annotated_guardedby field_name (f, _, a) = + Typ.Fieldname.equal f field_name + && List.exists a ~f:(fun ((annot : Annot.t), _) -> + Annotations.annot_ends_with annot Annotations.guarded_by + && match annot.parameters with [param] -> not (is_uitthread param) | _ -> false ) + in (not snapshot.lock) && RacerDDomain.TraceElem.is_write snapshot.access && Procdesc.get_proc_name procdesc |> Typ.Procname.is_java @@ -945,15 +958,16 @@ let should_report_guardedby_violation classname_str ({snapshot; tenv; procdesc} (* restrict check to access paths of length one *) match RacerDDomain.Access.get_access_path snapshot.access.elem with | Some ((_, base_type), [AccessPath.FieldAccess field_name]) -> ( - Typ.Struct.get_field_type_and_annotation ~lookup:(Tenv.lookup tenv) field_name base_type - |> Option.exists ~f:(fun (_, annotlist) -> Annotations.ia_is_guardedby annotlist) - && - (* is the base class a subclass of the one containing the GuardedBy annotation? *) - match base_type.Typ.desc with - | Tstruct base_name | Tptr ({Typ.desc= Tstruct base_name}, _) -> - PatternMatch.is_subtype tenv base_name (Typ.Name.Java.from_string classname_str) - | _ -> - false ) + match base_type.desc with + | Tstruct base_name | Tptr ({desc= Tstruct base_name}, _) -> + (* is the base class a subclass of the one containing the GuardedBy annotation? *) + PatternMatch.is_subtype tenv base_name (Typ.Name.Java.from_string classname_str) + && Tenv.lookup tenv base_name + |> Option.exists ~f:(fun ({fields; statics} : Typ.Struct.t) -> + let f fld = field_is_annotated_guardedby field_name fld in + List.exists fields ~f || List.exists statics ~f ) + | _ -> + false ) | _ -> false diff --git a/infer/tests/codetoanalyze/java/racerd/GuardedByTests.java b/infer/tests/codetoanalyze/java/racerd/GuardedByTests.java index 1891cbd34..74e5403a9 100644 --- a/infer/tests/codetoanalyze/java/racerd/GuardedByTests.java +++ b/infer/tests/codetoanalyze/java/racerd/GuardedByTests.java @@ -128,3 +128,21 @@ class GuardedByOther { x = 0; } } + +class GuardedByUiThread { + @GuardedBy("UiThReAd") + int a; + + @GuardedBy("ui-thread") + int b; + + @GuardedBy("UI thread") + int c; + + @GuardedBy("UI_THREAD") + int d; + + void uithreadOk() { + a = b = c = d = 0; + } +}