From 20c33f15c93846daaf012551e6b759c294f1cb05 Mon Sep 17 00:00:00 2001 From: Cristiano Calcagno Date: Fri, 2 Sep 2016 07:46:55 -0700 Subject: [PATCH] Fix flakiness in the analysis when a procedure is defined in more than one file. Reviewed By: jberdine Differential Revision: D3804399 fbshipit-source-id: e347927 --- infer/src/IR/Cfg.re | 1 - infer/src/IR/Cfg.rei | 3 --- infer/src/backend/InferAnalyze.re | 7 ++----- infer/src/backend/InferPrint.re | 3 ++- infer/src/backend/exe_env.ml | 32 ++++++++++++++++++++----------- 5 files changed, 25 insertions(+), 21 deletions(-) diff --git a/infer/src/IR/Cfg.re b/infer/src/IR/Cfg.re index ccb4030e4..3c539f066 100644 --- a/infer/src/IR/Cfg.re +++ b/infer/src/IR/Cfg.re @@ -250,7 +250,6 @@ let module Node = { NodeSet.elements (slice_nodes node.nd_preds) }; let get_exn node => node.nd_exn; - let set_proc_desc node proc => node.nd_proc = Some proc; /** Get the proc desc of the node */ let get_proc_desc node => diff --git a/infer/src/IR/Cfg.rei b/infer/src/IR/Cfg.rei index b4abd3b09..e87fb3925 100644 --- a/infer/src/IR/Cfg.rei +++ b/infer/src/IR/Cfg.rei @@ -259,9 +259,6 @@ let module Node: { /** Set the source location of the node */ let set_loc: t => Location.t => unit; - /** Set the proc desc associated to the node */ - let set_proc_desc: t => Procdesc.t => unit; - /** Set the successor nodes and exception nodes, and build predecessor links */ let set_succs_exn: cfg => t => list t => list t => unit; }; diff --git a/infer/src/backend/InferAnalyze.re b/infer/src/backend/InferAnalyze.re index f41aa9012..6a76494a7 100644 --- a/infer/src/backend/InferAnalyze.re +++ b/infer/src/backend/InferAnalyze.re @@ -54,11 +54,8 @@ let analyze_exe_env exe_env => { /** Create an exe_env from a cluster. */ let exe_env_from_cluster cluster => { let _exe_env = Exe_env.create (); - let source_dirs = [cluster]; - let sorted_dirs = IList.sort DB.source_dir_compare source_dirs; - IList.iter (fun src_dir => ignore (Exe_env.add_cg _exe_env src_dir)) sorted_dirs; - let exe_env = Exe_env.freeze _exe_env; - exe_env + ignore (Exe_env.add_cg _exe_env cluster); + Exe_env.freeze _exe_env }; diff --git a/infer/src/backend/InferPrint.re b/infer/src/backend/InferPrint.re index 1df6d28b0..210369b5a 100644 --- a/infer/src/backend/InferPrint.re +++ b/infer/src/backend/InferPrint.re @@ -1288,8 +1288,9 @@ let init_files format_list_by_kind => { let init_files_of_report_kind (report_kind, format_list) => { let init_files_of_format (format_kind, outfile) => switch (format_kind, report_kind) { - | (Csv, Stats) => Report.pp_header outfile.fmt () | (Csv, Issues) => IssuesCsv.pp_header outfile.fmt () + | (Csv, Procs) => ProcsCsv.pp_header outfile.fmt () + | (Csv, Stats) => Report.pp_header outfile.fmt () | (Json, Issues) => IssuesJson.pp_json_open outfile.fmt () | (Xml, Issues) => IssuesXml.pp_issues_open outfile.fmt () | (Xml, Procs) => ProcsXml.pp_procs_open outfile.fmt () diff --git a/infer/src/backend/exe_env.ml b/infer/src/backend/exe_env.ml index e884d3cd1..9baeacbdd 100644 --- a/infer/src/backend/exe_env.ml +++ b/infer/src/backend/exe_env.ml @@ -82,17 +82,27 @@ let add_cg (exe_env: t) (source_dir : DB.source_dir) = Cg.extend exe_env.cg cg; let file_data = new_file_data source nLOC cg_fname in let defined_procs = Cg.get_defined_nodes cg in - IList.iter (fun pname -> - let should_update = - if Procname.Hash.mem exe_env.proc_map pname then - let old_source = - (Procname.Hash.find exe_env.proc_map pname).source in - (* when a procedure is defined in several files, *) - (* map to the first alphabetically *) - source < old_source - else true in - if should_update - then Procname.Hash.replace exe_env.proc_map pname file_data) + + (* Find the file where `pname` is defined according to the attributes, + if a cfg for that file exist. *) + let defined_in_according_to_attributes pname = + match AttributesTable.load_attributes pname with + | None -> + None + | Some proc_attributes -> + let loc = proc_attributes.ProcAttributes.loc in + let source_file = loc.Location.file in + let source_dir = DB.source_dir_from_source_file source_file in + let cfg_fname = DB.source_dir_get_internal_file source_dir ".cfg" in + let cfg_fname_exists = Sys.file_exists (DB.filename_to_string cfg_fname) in + if cfg_fname_exists + then Some source_file + else None in + + IList.iter + (fun pname -> + if (defined_in_according_to_attributes pname = None) + then Procname.Hash.replace exe_env.proc_map pname file_data) defined_procs; Some cg