@@ -13,7 +13,7 @@ let pname_pp = MF.wrap_monospaced Typ.Procname.pp
13
13
14
14
let debug fmt = L. (debug Analysis Verbose fmt)
15
15
16
- let is_on_ui_thread pn =
16
+ let is_ui_thread_model pn =
17
17
ConcurrencyModels. (match get_thread pn with MainThread -> true | _ -> false )
18
18
19
19
@@ -25,7 +25,7 @@ let is_nonblocking tenv proc_desc =
25
25
let is_class_suppressed =
26
26
PatternMatch. get_this_type proc_attributes
27
27
|> Option. bind ~f: (PatternMatch. type_get_annotation tenv)
28
- |> Option. value_map ~default: false ~f: Annotations. ia_is_nonblocking
28
+ |> Option. exists ~f: Annotations. ia_is_nonblocking
29
29
in
30
30
is_method_suppressed || is_class_suppressed
31
31
@@ -39,13 +39,14 @@ module Payload = SummaryPayload.Make (struct
39
39
end )
40
40
41
41
(* using an indentifier for a class object, create an access path representing that lock;
42
- this is for synchronizing on class objects only *)
43
- let lock_of_class class_id =
44
- let ident = Ident. create_normal class_id 0 in
42
+ this is for synchronizing on Java class objects only *)
43
+ let lock_of_class =
45
44
let type_name = Typ.Name.Java. from_string " java.lang.Class" in
46
45
let typ = Typ. mk (Typ. Tstruct type_name) in
47
46
let typ' = Typ. mk (Typ. Tptr (typ, Typ. Pk_pointer )) in
48
- AccessPath. of_id ident typ'
47
+ fun class_id ->
48
+ let ident = Ident. create_normal class_id 0 in
49
+ AccessPath. of_id ident typ'
49
50
50
51
51
52
module TransferFunctions (CFG : ProcCfg.S ) = struct
@@ -57,13 +58,11 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
57
58
let exec_instr (astate : Domain.astate ) {ProcData. pdesc; tenv; extras} _ (instr : HilInstr.t ) =
58
59
let open ConcurrencyModels in
59
60
let open StarvationModels in
60
- let is_formal base = FormalMap. is_formal base extras in
61
- let get_lock_path actuals =
62
- match actuals with
61
+ let get_lock_path = function
63
62
| HilExp. AccessExpression access_exp -> (
64
63
match AccessExpression. to_access_path access_exp with
65
64
| (((Var. ProgramVar pvar, _) as base), _) as path
66
- when is_formal base || Pvar. is_global pvar ->
65
+ when FormalMap. is_formal base extras || Pvar. is_global pvar ->
67
66
Some (AccessPath. inner_class_normalize path)
68
67
| _ ->
69
68
(* ignore paths on local or logical variables *)
@@ -78,6 +77,11 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
78
77
List. filter_map ~f: get_lock_path locks |> Domain. acquire astate loc
79
78
in
80
79
let do_unlock locks astate = List. filter_map ~f: get_lock_path locks |> Domain. release astate in
80
+ let do_call callee loc =
81
+ Payload. read pdesc callee
82
+ |> Option. value_map ~default: astate ~f: (Domain. integrate_summary astate callee loc)
83
+ in
84
+ let is_java = Procdesc. get_proc_name pdesc |> Typ.Procname. is_java in
81
85
match instr with
82
86
| Call (_ , Direct callee , actuals , _ , loc ) -> (
83
87
match get_lock_effect callee actuals with
@@ -91,19 +95,22 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
91
95
astate
92
96
| NoEffect when is_synchronized_library_call tenv callee ->
93
97
(* model a synchronized call without visible internal behaviour *)
94
- do_lock actuals loc astate |> do_unlock actuals
95
- | NoEffect when is_on_ui_thread callee ->
98
+ let locks = List. hd actuals |> Option. to_list in
99
+ do_lock locks loc astate |> do_unlock locks
100
+ | NoEffect when is_java && is_ui_thread_model callee ->
96
101
let explanation = F. asprintf " it calls %a" pname_pp callee in
97
102
Domain. set_on_ui_thread astate loc explanation
98
- | NoEffect when StarvationModels. is_strict_mode_violation tenv callee actuals ->
103
+ | NoEffect when is_java && StarvationModels. is_strict_mode_violation tenv callee actuals ->
99
104
Domain. strict_mode_call callee loc astate
100
- | NoEffect -> (
105
+ | NoEffect when is_java -> (
101
106
match may_block tenv callee actuals with
102
107
| Some sev ->
103
108
Domain. blocking_call callee sev loc astate
104
109
| None ->
105
- Payload. read pdesc callee
106
- |> Option. value_map ~default: astate ~f: (Domain. integrate_summary astate callee loc) ) )
110
+ do_call callee loc )
111
+ | NoEffect ->
112
+ (* in C++/Obj C we only care about deadlocks, not starvation errors *)
113
+ do_call callee loc )
107
114
| _ ->
108
115
astate
109
116
113
120
114
121
module Analyzer = LowerHil. MakeAbstractInterpreter (ProcCfg. Normal ) (TransferFunctions )
115
122
116
- let die_if_not_java proc_desc =
117
- let is_java =
118
- Procdesc. get_proc_name proc_desc |> Typ.Procname. get_language |> Language. (equal Java )
119
- in
120
- if not is_java then L. (die InternalError " Not supposed to run on non-Java code yet." )
121
-
122
-
123
123
let analyze_procedure {Callbacks. proc_desc; tenv; summary} =
124
124
let open StarvationDomain in
125
- die_if_not_java proc_desc ;
126
125
let pname = Procdesc. get_proc_name proc_desc in
127
126
let formals = FormalMap. make proc_desc in
128
127
let proc_data = ProcData. make proc_desc tenv formals in
@@ -295,13 +294,16 @@ let should_report_deadlock_on_current_proc current_elem endpoint_elem =
295
294
296
295
297
296
let should_report pdesc =
297
+ Procdesc. get_access pdesc <> PredSymb. Private
298
+ &&
298
299
match Procdesc. get_proc_name pdesc with
299
300
| Typ.Procname. Java java_pname ->
300
- Procdesc. get_access pdesc <> PredSymb. Private
301
- && (not (Typ.Procname.Java. is_autogen_method java_pname))
301
+ (not (Typ.Procname.Java. is_autogen_method java_pname))
302
302
&& not (Typ.Procname.Java. is_class_initializer java_pname)
303
+ | Typ.Procname. ObjC_Cpp _ ->
304
+ true
303
305
| _ ->
304
- L. (die InternalError " Not supposed to run on non-Java code. " )
306
+ false
305
307
306
308
307
309
let fold_reportable_summaries (tenv , current_pdesc ) clazz ~init ~f =
@@ -474,7 +476,6 @@ let report_starvation env {StarvationDomain.events; ui} report_map' =
474
476
475
477
let reporting {Callbacks. procedures; source_file} =
476
478
let report_procedure ((tenv , proc_desc ) as env ) =
477
- die_if_not_java proc_desc ;
478
479
if should_report proc_desc then
479
480
Payload. read proc_desc (Procdesc. get_proc_name proc_desc)
480
481
|> Option. iter ~f: (fun summary ->
0 commit comments