diff --git a/infer/src/backend/callbacks.ml b/infer/src/backend/callbacks.ml index abca4c4c5..ccff7cefe 100644 --- a/infer/src/backend/callbacks.ml +++ b/infer/src/backend/callbacks.ml @@ -12,7 +12,6 @@ module L = Logging (** Module to register and invoke callbacks *) type proc_callback_args = { - get_cfg : Procname.t -> Cfg.cfg option; get_proc_desc : Procname.t -> Cfg.Procdesc.t option; get_procs_in_file : Procname.t -> Procname.t list; idenv : Idenv.t; @@ -60,9 +59,6 @@ let iterate_procedure_callbacks exe_env caller_pname = let procedure_language = get_language caller_pname in Config.curr_language := procedure_language; - let get_cfg proc_name = - Exe_env.get_cfg exe_env proc_name in - let get_proc_desc proc_name = Exe_env.get_proc_desc exe_env proc_name in @@ -94,7 +90,6 @@ let iterate_procedure_callbacks exe_env caller_pname = let init_time = Unix.gettimeofday () in proc_callback { - get_cfg; get_proc_desc; get_procs_in_file; idenv; diff --git a/infer/src/backend/callbacks.mli b/infer/src/backend/callbacks.mli index e4cc897a7..5b9020f37 100644 --- a/infer/src/backend/callbacks.mli +++ b/infer/src/backend/callbacks.mli @@ -10,7 +10,6 @@ (** Module to register and invoke callbacks *) type proc_callback_args = { - get_cfg : Procname.t -> Cfg.cfg option; get_proc_desc : Procname.t -> Cfg.Procdesc.t option; get_procs_in_file : Procname.t -> Procname.t list; idenv : Idenv.t; diff --git a/infer/src/backend/cfg.ml b/infer/src/backend/cfg.ml index eb7c72938..bd84e415f 100644 --- a/infer/src/backend/cfg.ml +++ b/infer/src/backend/cfg.ml @@ -606,7 +606,8 @@ module Node = struct (* clone a procedure description and apply the type substitutions where the parameters are used *) - let proc_desc_specialize_types cfg callee_proc_desc resolved_attributes substitutions = + let proc_desc_specialize_types callee_proc_desc resolved_attributes substitutions = + let cfg = create_cfg () in let resolved_proc_desc = proc_desc_create cfg resolved_attributes in let resolved_proc_name = proc_desc_get_proc_name resolved_proc_desc and callee_start_node = proc_desc_get_start_node callee_proc_desc @@ -1144,28 +1145,22 @@ let store_cfg_to_file (filename : DB.filename) (save_sources : bool) (cfg : cfg) (** Creates a copy of a procedure description and a list of type substitutions of the form - (name, typ) where name is a parameter. The resulting procedure CFG is isomorphic but + (name, typ) where name is a parameter. The resulting proc desc is isomorphic but all the type of the parameters are replaced in the instructions according to the list. The virtual calls are also replaced to match the parameter types *) -let specialize_types caller_cfg callee_proc_name resolved_proc_name args = +let specialize_types callee_proc_desc resolved_proc_name args = (** TODO (#9333890): This currently only works when the callee is defined in the same file. Add support to search for the callee procedure description in the execution environment *) - match Procdesc.find_from_name caller_cfg resolved_proc_name with - | Some pdesc -> Some pdesc - | None -> - Option.map - (fun callee_proc_desc -> - let callee_attributes = Procdesc.get_attributes callee_proc_desc in - let resolved_formals = - IList.fold_left2 - (fun accu (name, _) (_, arg_typ) -> (name, arg_typ) :: accu) - [] callee_attributes.ProcAttributes.formals args |> IList.rev in - let resolved_attributes = - { callee_attributes with - ProcAttributes.formals = resolved_formals; - proc_name = resolved_proc_name; - } in - AttributesTable.store_attributes resolved_attributes; - Procdesc.specialize_types - caller_cfg callee_proc_desc resolved_attributes resolved_formals) - (Procdesc.find_from_name caller_cfg callee_proc_name) + let callee_attributes = Procdesc.get_attributes callee_proc_desc in + let resolved_formals = + IList.fold_left2 + (fun accu (name, _) (_, arg_typ) -> (name, arg_typ) :: accu) + [] callee_attributes.ProcAttributes.formals args |> IList.rev in + let resolved_attributes = + { callee_attributes with + ProcAttributes.formals = resolved_formals; + proc_name = resolved_proc_name; + } in + AttributesTable.store_attributes resolved_attributes; + Procdesc.specialize_types + callee_proc_desc resolved_attributes resolved_formals diff --git a/infer/src/backend/cfg.mli b/infer/src/backend/cfg.mli index c8e3de0de..6b9886590 100644 --- a/infer/src/backend/cfg.mli +++ b/infer/src/backend/cfg.mli @@ -314,8 +314,8 @@ val check_cfg_connectedness : cfg -> unit val remove_seed_captured_vars_block : Mangled.t list -> Prop.normal Prop.t -> Prop.normal Prop.t (** Creates a copy of a procedure description and a list of type substitutions of the form - (name, typ) where name is a parameter. The resulting procedure CFG is isomorphic but + (name, typ) where name is a parameter. The resulting procdesc is isomorphic but all the type of the parameters are replaced in the instructions according to the list. The virtual calls are also replaced to match the parameter types *) val specialize_types : - cfg -> Procname.t -> Procname.t -> (Sil.exp * Sil.typ) list -> Procdesc.t option + Procdesc.t -> Procname.t -> (Sil.exp * Sil.typ) list -> Procdesc.t diff --git a/infer/src/backend/exe_env.ml b/infer/src/backend/exe_env.ml index c9bbe83bf..c5e32dce9 100644 --- a/infer/src/backend/exe_env.ml +++ b/infer/src/backend/exe_env.ml @@ -100,13 +100,13 @@ let get_cg exe_env = let get_file_data exe_env pname = try - Procname.Hash.find exe_env.proc_map pname + Some (Procname.Hash.find exe_env.proc_map pname) with Not_found -> begin match AttributesTable.load_attributes pname with | None -> L.err "can't find tenv_cfg_object for %a@." Procname.pp pname; - raise Not_found + None | Some proc_attributes -> let loc = proc_attributes.ProcAttributes.loc in let source_file = loc.Location.file in @@ -115,12 +115,14 @@ let get_file_data exe_env pname = let cg_fname = DB.source_dir_get_internal_file source_dir ".cg" in let file_data = new_file_data source_file nLOC cg_fname in Procname.Hash.replace exe_env.proc_map pname file_data; - file_data + Some file_data end (** return the source file associated to the procedure *) let get_source exe_env pname = - (get_file_data exe_env pname).source + Option.map + (fun file_data -> file_data.source) + (get_file_data exe_env pname) let file_data_to_tenv file_data = if file_data.tenv == None @@ -134,17 +136,25 @@ let file_data_to_cfg file_data = (** return the type environment associated to the procedure *) let get_tenv exe_env proc_name : Sil.tenv = - let file_data = get_file_data exe_env proc_name in - match file_data_to_tenv file_data with - | Some tenv -> - tenv + match get_file_data exe_env proc_name with | None -> - failwith ("get_tenv: tenv not found for" ^ Procname.to_string proc_name) + failwith ("get_tenv: file_data not found for" ^ Procname.to_string proc_name) + | Some file_data -> + begin + match file_data_to_tenv file_data with + | Some tenv -> + tenv + | None -> + failwith ("get_tenv: tenv not found for" ^ Procname.to_string proc_name) + end (** return the cfg associated to the procedure *) let get_cfg exe_env pname = - let file_data = get_file_data exe_env pname in - file_data_to_cfg file_data + match get_file_data exe_env pname with + | None -> + None + | Some file_data -> + file_data_to_cfg file_data (** return the proc desc associated to the procedure *) let get_proc_desc exe_env pname = diff --git a/infer/src/backend/exe_env.mli b/infer/src/backend/exe_env.mli index 29099f4d0..1314deb1f 100644 --- a/infer/src/backend/exe_env.mli +++ b/infer/src/backend/exe_env.mli @@ -30,7 +30,7 @@ val add_cg : initial -> DB.source_dir -> Cg.t option val get_cg : t -> Cg.t (** return the source file associated to the procedure *) -val get_source : t -> Procname.t -> DB.source_file +val get_source : t -> Procname.t -> DB.source_file option (** return the type environment associated to the procedure *) val get_tenv : t -> Procname.t -> Sil.tenv diff --git a/infer/src/backend/interproc.ml b/infer/src/backend/interproc.ml index fe358b928..5fe1d8757 100644 --- a/infer/src/backend/interproc.ml +++ b/infer/src/backend/interproc.ml @@ -1320,8 +1320,6 @@ let do_analysis exe_env = procs_and_defined_children; let callbacks = - let get_cfg proc_name = - Exe_env.get_cfg exe_env proc_name in let get_proc_desc proc_name = Exe_env.get_proc_desc exe_env proc_name in let analyze_ondemand proc_desc = @@ -1338,7 +1336,6 @@ let do_analysis exe_env = Specs.add_summary proc_name summaryre in { Ondemand.analyze_ondemand; - get_cfg; get_proc_desc; } in @@ -1451,6 +1448,6 @@ let print_stats exe_env = let proc_shadowed proc_desc = (** return true if a proc with the same name in another module was analyzed instead *) let proc_name = Cfg.Procdesc.get_proc_name proc_desc in - Exe_env.get_source exe_env proc_name <> fname in + Exe_env.get_source exe_env proc_name <> Some fname in print_stats_cfg proc_shadowed cfg) exe_env diff --git a/infer/src/backend/ondemand.ml b/infer/src/backend/ondemand.ml index 77f012058..09a850084 100644 --- a/infer/src/backend/ondemand.ml +++ b/infer/src/backend/ondemand.ml @@ -41,14 +41,11 @@ let dirs_to_analyze = type analyze_ondemand = Cfg.Procdesc.t -> unit -type get_cfg = Procname.t -> Cfg.cfg option - type get_proc_desc = Procname.t -> Cfg.Procdesc.t option type callbacks = { analyze_ondemand : analyze_ondemand; - get_cfg : get_cfg; get_proc_desc : get_proc_desc; } @@ -230,10 +227,10 @@ let analyze_proc_name ~propagate_exceptions curr_pdesc callee_pname = | _ -> () (* skipping *) -(** Find a cfg for the procedure, perhaps loading it from disk. *) -let get_cfg callee_pname = +(** Find a proc desc for the procedure, perhaps loading it from disk. *) +let get_proc_desc callee_pname = match !callbacks_ref with | Some callbacks -> - callbacks.get_cfg callee_pname + callbacks.get_proc_desc callee_pname | None -> None diff --git a/infer/src/backend/ondemand.mli b/infer/src/backend/ondemand.mli index 2c20500f5..3b5ef8698 100644 --- a/infer/src/backend/ondemand.mli +++ b/infer/src/backend/ondemand.mli @@ -14,19 +14,16 @@ val dirs_to_analyze : StringSet.t option Lazy.t type analyze_ondemand = Cfg.Procdesc.t -> unit -type get_cfg = Procname.t -> Cfg.cfg option - type get_proc_desc = Procname.t -> Cfg.Procdesc.t option type callbacks = { analyze_ondemand : analyze_ondemand; - get_cfg : get_cfg; get_proc_desc : get_proc_desc; } -(** Find a cfg for the procedure, perhaps loading it from disk. *) -val get_cfg : get_cfg +(** Find a proc desc for the procedure, perhaps loading it from disk. *) +val get_proc_desc : get_proc_desc (** analyze_proc_desc curr_pdesc callee_pdesc performs an on-demand analysis of callee_pdesc diff --git a/infer/src/backend/symExec.ml b/infer/src/backend/symExec.ml index 95d69fed6..f5137405b 100644 --- a/infer/src/backend/symExec.ml +++ b/infer/src/backend/symExec.ml @@ -54,14 +54,9 @@ let check_block_retain_cycle tenv caller_pname prop block_nullified = let mblock = Sil.pvar_get_name block_nullified in let block_pname = Procname.mangled_objc_block (Mangled.to_string mblock) in let block_captured = - let block_pdesc_opt = match Ondemand.get_cfg caller_pname with - | Some caller_cfg -> - Cfg.Procdesc.find_from_name caller_cfg block_pname - | None -> - None in - match block_pdesc_opt with - | Some block_pdesc -> - fst (IList.split (Cfg.Procdesc.get_captured block_pdesc)) + match AttributesTable.load_attributes block_pname with + | Some attributes -> + fst (IList.split attributes.ProcAttributes.captured) | None -> [] in let prop' = Cfg.remove_seed_captured_vars_block block_captured prop in @@ -715,24 +710,30 @@ let resolve_java_pname tenv prop args pname call_flags : Procname.t = (** Resolve the procedure name and run the analysis of the resolved procedure if not already analyzed *) let resolve_and_analyze - tenv caller_pdesc prop args callee_pname call_flags : Procname.t * Specs.summary option = + tenv caller_pdesc prop args callee_proc_name call_flags : Procname.t * Specs.summary option = (* TODO (#9333890): Fix conflict with method overloading by encoding in the procedure name whether the method is defined or generated by the specialization *) - let analyze_ondemand caller_cfg resolved_pname : unit = - if Procname.equal resolved_pname callee_pname then - Ondemand.analyze_proc_name ~propagate_exceptions:true caller_pdesc callee_pname + let analyze_ondemand resolved_pname : unit = + if Procname.equal resolved_pname callee_proc_name then + Ondemand.analyze_proc_name ~propagate_exceptions:true caller_pdesc callee_proc_name else (* Create the type sprecialized procedure description and analyze it directly *) Option.may (fun specialized_pdesc -> Ondemand.analyze_proc_desc ~propagate_exceptions:true caller_pdesc specialized_pdesc) - (Cfg.specialize_types caller_cfg callee_pname resolved_pname args) in + (match Ondemand.get_proc_desc resolved_pname with + | Some resolved_proc_desc -> + Some resolved_proc_desc + | None -> + begin + Option.map + (fun callee_proc_desc -> + Cfg.specialize_types callee_proc_desc resolved_pname args) + (Ondemand.get_proc_desc callee_proc_name) + end) in let resolved_pname = - resolve_java_pname tenv prop args callee_pname call_flags in - Option.may - (fun caller_cfg -> - analyze_ondemand caller_cfg resolved_pname) - (Ondemand.get_cfg (Cfg.Procdesc.get_proc_name caller_pdesc)); + resolve_java_pname tenv prop args callee_proc_name call_flags in + analyze_ondemand resolved_pname; resolved_pname, Specs.get_summary resolved_pname @@ -1137,12 +1138,7 @@ let rec sym_exec tenv pdesc _instr (prop_: Prop.normal Prop.t) path Ondemand.analyze_proc_name ~propagate_exceptions:true pdesc resolved_pname; - let callee_pdesc_opt = - match Ondemand.get_cfg pname with - | Some caller_cfg -> - Cfg.Procdesc.find_from_name caller_cfg resolved_pname - | None -> - None in + let callee_pdesc_opt = Ondemand.get_proc_desc resolved_pname in let ret_typ_opt = Option.map Cfg.Procdesc.get_ret_type callee_pdesc_opt in let sentinel_result = diff --git a/infer/src/checkers/performanceCritical.ml b/infer/src/checkers/performanceCritical.ml index db2f95b09..5c562a4fe 100644 --- a/infer/src/checkers/performanceCritical.ml +++ b/infer/src/checkers/performanceCritical.ml @@ -315,13 +315,12 @@ let check_one_procedure tenv pname pdesc = let callback_performance_checker - { Callbacks.get_cfg; get_proc_desc; proc_desc; proc_name; tenv } = + { Callbacks.get_proc_desc; proc_desc; proc_name; tenv } = let callbacks = let analyze_ondemand pdesc = check_one_procedure tenv (Cfg.Procdesc.get_proc_name pdesc) pdesc in { Ondemand.analyze_ondemand; - get_cfg; get_proc_desc; } in if Ondemand.procedure_should_be_analyzed proc_name diff --git a/infer/src/eradicate/eradicate.ml b/infer/src/eradicate/eradicate.ml index 282fd1b94..723ee8ba4 100644 --- a/infer/src/eradicate/eradicate.ml +++ b/infer/src/eradicate/eradicate.ml @@ -386,7 +386,7 @@ module Main = (** Eradicate checker for Java @Nullable annotations. *) let callback_eradicate - ({ Callbacks.get_cfg; get_proc_desc; idenv; proc_name } as callback_args) = + ({ Callbacks.get_proc_desc; idenv; proc_name } as callback_args) = let checks = { TypeCheck.eradicate = true; @@ -403,7 +403,6 @@ let callback_eradicate proc_desc = pdesc; } in { Ondemand.analyze_ondemand; - get_cfg; get_proc_desc; } in