diff --git a/infer/src/backend/InferAnalyze.ml b/infer/src/backend/InferAnalyze.ml index 3441b0634..38daee123 100644 --- a/infer/src/backend/InferAnalyze.ml +++ b/infer/src/backend/InferAnalyze.ml @@ -17,13 +17,13 @@ let create_exe_env_tasks source_file exe_env : Tasks.t = Typ.Procname.SQLite.clear_cache () ; Random.self_init () ; [ (fun () -> - Callbacks.iterate_callbacks exe_env ; + Callbacks.analyze_file exe_env source_file ; if Config.write_html then Printer.write_all_html_files source_file ) ] (** Create tasks to analyze a cluster *) let create_source_file_tasks (source_file: SourceFile.t) : Tasks.t = - let exe_env = Exe_env.mk source_file in + let exe_env = Exe_env.mk () in L.(debug Analysis Medium) "@\nProcessing '%a'@." SourceFile.pp source_file ; create_exe_env_tasks source_file exe_env diff --git a/infer/src/backend/callbacks.ml b/infer/src/backend/callbacks.ml index be4c6d267..494590b1b 100644 --- a/infer/src/backend/callbacks.ml +++ b/infer/src/backend/callbacks.ml @@ -22,6 +22,7 @@ type proc_callback_t = proc_callback_args -> Summary.t type cluster_callback_args = { procedures: (Tenv.t * Procdesc.t) list + ; source_file: SourceFile.t ; get_proc_desc: Typ.Procname.t -> Procdesc.t option ; exe_env: Exe_env.t } @@ -75,10 +76,10 @@ let iterate_procedure_callbacks get_proc_desc exe_env summary proc_desc = (** Invoke all registered cluster callbacks on a cluster of procedures. *) -let iterate_cluster_callbacks all_procs exe_env get_proc_desc = +let iterate_cluster_callbacks all_procs exe_env source_file get_proc_desc = if !cluster_callbacks <> [] then let procedures = List.filter_map ~f:(get_procedure_definition exe_env) all_procs in - let environment = {procedures; get_proc_desc; exe_env} in + let environment = {procedures; source_file; get_proc_desc; exe_env} in let language_matches language = match procedures with | (_, pdesc) :: _ -> @@ -91,7 +92,7 @@ let iterate_cluster_callbacks all_procs exe_env get_proc_desc = !cluster_callbacks -let dump_duplicate_procs (exe_env: Exe_env.t) procs = +let dump_duplicate_procs (exe_env: Exe_env.t) source_file procs = let duplicate_procs = List.filter_map procs ~f:(fun pname -> match Exe_env.get_proc_desc exe_env pname with @@ -99,9 +100,9 @@ let dump_duplicate_procs (exe_env: Exe_env.t) procs = match Attributes.load pname with | Some {translation_unit; loc} when (* defined in another file *) - not (SourceFile.equal exe_env.source_file translation_unit) + not (SourceFile.equal source_file translation_unit) && (* really defined in the current file and not in an include *) - SourceFile.equal exe_env.source_file loc.file -> + SourceFile.equal source_file loc.file -> Some (pname, translation_unit) | _ -> None ) @@ -114,8 +115,7 @@ let dump_duplicate_procs (exe_env: Exe_env.t) procs = let fmt = F.formatter_of_out_channel outc in List.iter duplicate_procs ~f:(fun (pname, source_captured) -> F.fprintf fmt "@.DUPLICATE_SYMBOLS source:%a source_captured:%a pname:%a@." - SourceFile.pp exe_env.source_file SourceFile.pp source_captured Typ.Procname.pp pname - ) ) + SourceFile.pp source_file SourceFile.pp source_captured Typ.Procname.pp pname ) ) in if not (List.is_empty duplicate_procs) then output_to_file duplicate_procs @@ -126,7 +126,7 @@ let create_perf_stats_report source_file = (** Invoke all procedure and cluster callbacks on a given environment. *) -let iterate_callbacks (exe_env: Exe_env.t) = +let analyze_file (exe_env: Exe_env.t) source_file = let saved_language = !Language.curr_language in let get_proc_desc proc_name = match Exe_env.get_proc_desc exe_env proc_name with @@ -142,15 +142,15 @@ let iterate_callbacks (exe_env: Exe_env.t) = (* Invoke procedure callbacks using on-demand analysis schedulling *) let procs_to_analyze = (* analyze all the currently defined procedures *) - SourceFiles.proc_names_of_source exe_env.source_file + SourceFiles.proc_names_of_source source_file in - if Config.dump_duplicate_symbols then dump_duplicate_procs exe_env procs_to_analyze ; + if Config.dump_duplicate_symbols then dump_duplicate_procs exe_env source_file procs_to_analyze ; let analyze_proc_name pname = ignore (Ondemand.analyze_proc_name pname : Summary.t option) in List.iter ~f:analyze_proc_name procs_to_analyze ; (* Invoke cluster callbacks. *) - iterate_cluster_callbacks procs_to_analyze exe_env get_proc_desc ; + iterate_cluster_callbacks procs_to_analyze exe_env source_file get_proc_desc ; (* Perf logging needs to remain at the end - after analysis work is complete *) - create_perf_stats_report exe_env.source_file ; + create_perf_stats_report source_file ; (* Unregister callbacks *) Ondemand.unset_callbacks () ; Language.curr_language := saved_language diff --git a/infer/src/backend/callbacks.mli b/infer/src/backend/callbacks.mli index ba80511b4..5b679fe74 100644 --- a/infer/src/backend/callbacks.mli +++ b/infer/src/backend/callbacks.mli @@ -26,6 +26,7 @@ type proc_callback_t = proc_callback_args -> Summary.t type cluster_callback_args = { procedures: (Tenv.t * Procdesc.t) list + ; source_file: SourceFile.t ; get_proc_desc: Typ.Procname.t -> Procdesc.t option ; exe_env: Exe_env.t } @@ -37,5 +38,5 @@ val register_procedure_callback : ?dynamic_dispatch:bool -> Language.t -> proc_c val register_cluster_callback : Language.t -> cluster_callback_t -> unit (** register a cluster callback *) -val iterate_callbacks : Exe_env.t -> unit -(** Invoke all the registered callbacks. *) +val analyze_file : Exe_env.t -> SourceFile.t -> unit +(** Invoke all the registered callbacks on the given file. *) diff --git a/infer/src/backend/exe_env.ml b/infer/src/backend/exe_env.ml index 7f574ce36..4e810db5a 100644 --- a/infer/src/backend/exe_env.ml +++ b/infer/src/backend/exe_env.ml @@ -8,7 +8,8 @@ open! IStd -(** Support for Execution environments *) +(** Execution environments: basically a cache of where procedures are and what is their CFG and type + environment *) module L = Logging @@ -36,8 +37,7 @@ let create_file_data table source = type t = { proc_map: file_data Typ.Procname.Hash.t (** map from procedure name to file data *) - ; file_map: file_data SourceFile.Hash.t (** map from source files to file data *) - ; source_file: SourceFile.t (** source file being analyzed *) } + ; file_map: file_data SourceFile.Hash.t (** map from source files to file data *) } let get_file_data exe_env pname = try Some (Typ.Procname.Hash.find exe_env.proc_map pname) with Caml.Not_found -> @@ -91,13 +91,14 @@ let get_tenv exe_env proc_name = | Some tenv -> tenv | None -> + let loc = State.get_loc () in L.(die InternalError) - "get_tenv: tenv not found for %a in file '%a'" Typ.Procname.pp proc_name SourceFile.pp - exe_env.source_file ) + "get_tenv: tenv not found for %a in file '%a' at %a" Typ.Procname.pp proc_name + SourceFile.pp loc.Location.file Location.pp loc ) | None -> let loc = State.get_loc () in L.(die InternalError) - "get_tenv: file_data not found for %a in file %a at %a" Typ.Procname.pp proc_name + "get_tenv: file_data not found for %a in file '%a' at %a" Typ.Procname.pp proc_name SourceFile.pp loc.Location.file Location.pp loc @@ -119,12 +120,4 @@ let get_proc_desc exe_env pname = None -let mk source_file = - {proc_map= Typ.Procname.Hash.create 17; file_map= SourceFile.Hash.create 1; source_file} - - -(** [iter_files f exe_env] applies [f] to the filename and tenv and cfg for each file in [exe_env] *) -let iter_files f exe_env = - let source = exe_env.source_file in - let cfg = Cfg.load source in - Option.iter ~f:(f source) cfg +let mk () = {proc_map= Typ.Procname.Hash.create 17; file_map= SourceFile.Hash.create 1} diff --git a/infer/src/backend/exe_env.mli b/infer/src/backend/exe_env.mli index 22a237814..819dc8655 100644 --- a/infer/src/backend/exe_env.mli +++ b/infer/src/backend/exe_env.mli @@ -8,26 +8,23 @@ open! IStd -(** Support for Execution environments *) +(** Execution environments: basically a cache of where procedures are and what is their CFG and type + environment *) type file_data type t = private { proc_map: file_data Typ.Procname.Hash.t (** map from procedure name to file data *) - ; file_map: file_data SourceFile.Hash.t (** map from source files to file data *) - ; source_file: SourceFile.t (** source file being analyzed *) } + ; file_map: file_data SourceFile.Hash.t (** map from source files to file data *) } -val mk : SourceFile.t -> t -(** Create an exe_env from a source file *) +val mk : unit -> t +(** Create a new cache *) val get_tenv : t -> Typ.Procname.t -> Tenv.t -(** return the type environment associated to the procedure *) +(** return the type environment associated with the procedure *) val get_cfg : t -> Typ.Procname.t -> Cfg.t option -(** return the cfg associated to the procedure *) +(** return the cfg associated with the procedure *) val get_proc_desc : t -> Typ.Procname.t -> Procdesc.t option -(** return the proc desc associated to the procedure *) - -val iter_files : (SourceFile.t -> Cfg.t -> unit) -> t -> unit -(** [iter_files f exe_env] applies [f] to the source file and tenv and cfg for each file in [exe_env] *) +(** return the proc desc associated with the procedure *) diff --git a/infer/src/backend/printer.ml b/infer/src/backend/printer.ml index e3186f3d3..b328aa685 100644 --- a/infer/src/backend/printer.ml +++ b/infer/src/backend/printer.ml @@ -366,7 +366,6 @@ let write_html_file linereader filename procs = (** Create filename.ext.html for each file in the cluster. *) let write_all_html_files cluster = - let exe_env = Exe_env.mk cluster in let opt_whitelist_regex = match Config.write_html_whitelist_regex with | [] -> @@ -380,8 +379,8 @@ let write_all_html_files cluster = Str.string_match regex fname 0 ) in let linereader = LineReader.create () in - Exe_env.iter_files - (fun _ cfg -> + let cfg = Cfg.load cluster in + Option.iter cfg ~f:(fun cfg -> let source_files_in_cfg, pdescs_in_cfg = Typ.Procname.Hash.fold (fun _ proc_desc (files, pdescs) -> @@ -397,4 +396,3 @@ let write_all_html_files cluster = SourceFile.Set.iter (fun file -> write_html_file linereader file pdescs_in_cfg) source_files_in_cfg ) - exe_env diff --git a/infer/src/concurrency/RacerD.ml b/infer/src/concurrency/RacerD.ml index 16e89bf96..8caeaa9e6 100644 --- a/infer/src/concurrency/RacerD.ml +++ b/infer/src/concurrency/RacerD.ml @@ -1483,7 +1483,7 @@ let aggregate_by_class file_env = (* Gathers results by analyzing all the methods in a file, then post-processes the results to check an (approximation of) thread safety *) -let file_analysis {Callbacks.procedures; exe_env} = +let file_analysis {Callbacks.procedures; source_file} = String.Map.iter ~f:(fun class_env -> let tenv = fst (List.hd_exn class_env) in @@ -1493,5 +1493,4 @@ let file_analysis {Callbacks.procedures; exe_env} = else (module MayAliasQuotientedAccessListMap) ) class_env) ) (aggregate_by_class procedures) ; - let sourcefile = exe_env.Exe_env.source_file in - IssueLog.store Config.racerd_issues_dir_name sourcefile + IssueLog.store Config.racerd_issues_dir_name source_file diff --git a/infer/src/concurrency/starvation.ml b/infer/src/concurrency/starvation.ml index 0b018f19c..e3e088824 100644 --- a/infer/src/concurrency/starvation.ml +++ b/infer/src/concurrency/starvation.ml @@ -436,7 +436,7 @@ let report_starvation env get_proc_desc {StarvationDomain.events; ui} report_map EventDomain.fold (report_on_current_elem ui_explain) events report_map' -let reporting {Callbacks.procedures; get_proc_desc; exe_env} = +let reporting {Callbacks.procedures; source_file; get_proc_desc} = let report_procedure ((_, proc_desc) as env) = die_if_not_java proc_desc ; if should_report proc_desc then @@ -446,5 +446,4 @@ let reporting {Callbacks.procedures; get_proc_desc; exe_env} = |> report_starvation env get_proc_desc summary |> ReportMap.log ) in List.iter procedures ~f:report_procedure ; - let sourcefile = exe_env.Exe_env.source_file in - IssueLog.store Config.starvation_issues_dir_name sourcefile + IssueLog.store Config.starvation_issues_dir_name source_file