[DB.source_file] Explicitly specify what path is relative to, keep cpp model paths relative

Summary:
1. Always store cpp model source_file with relative path. This will make them cache friendly independent of infer location
2. Distinguish between "relative to project root" and "relative to infer models src"
3. Unify `source_file_from_path` used by java and C frontends into one function. There are no improvements to that logic yet
4. Move `is_cpp_model_file` to use `source_file` instead of `filename`

Reviewed By: jberdine

Differential Revision: D4204548

fbshipit-source-id: 6e21771
master
Andrzej Kotulski 8 years ago committed by Facebook Github Bot
parent ccb51912e1
commit 7a0a89e567

@ -112,9 +112,7 @@ let get_correct_type_from_objc_class_name type_name =>
/** Returns true if the method is defined as a C++ model */
let pname_is_cpp_model callee_pname =>
switch (load_attributes callee_pname) {
| Some attrs =>
let file = DB.source_file_to_string attrs.ProcAttributes.loc.Location.file;
DB.file_is_in_cpp_model file
| Some attrs => DB.source_file_is_cpp_model attrs.ProcAttributes.loc.Location.file
| None => false
};

@ -489,18 +489,6 @@ let module IssuesJson = {
} else {
file
};
let make_cpp_models_path_relative file => {
let abs_file = DB.source_file_to_abs_path file;
if (Utils.string_is_prefix Config.cpp_models_dir abs_file) {
if (Config.debug_mode || Config.debug_exceptions) {
Some (DB.rel_source_file_from_abs_path Config.cpp_models_dir abs_file)
} else {
None
}
} else {
Some file
}
};
/** Write bug report in JSON format */
let pp_issues_of_error_log fmt error_filter _ proc_loc_opt procname err_log => {
@ -522,16 +510,19 @@ let module IssuesJson = {
| Some proc_loc => (proc_loc.Location.file, proc_loc.Location.line)
| None => (loc.Location.file, 0)
};
let file_opt = make_cpp_models_path_relative source_file;
let should_report_source_file =
not (DB.source_file_is_infer_model source_file) ||
Config.debug_mode || Config.debug_exceptions;
if (
in_footprint &&
error_filter source_file error_desc error_name &&
Option.is_some file_opt && should_report ekind error_name error_desc && is_file source_file
should_report_source_file &&
should_report ekind error_name error_desc && is_file source_file
) {
let kind = Exceptions.err_kind_string ekind;
let bug_type = Localise.to_string error_name;
let procedure_id = Procname.to_filename procname;
let file = expand_links_under_buck_out (DB.source_file_to_string (Option.get file_opt));
let file = expand_links_under_buck_out (DB.source_file_to_string source_file);
let json_ml_loc =
switch ml_loc_opt {
| Some (file, lnum, cnum, enum) when Config.reports_include_ml_loc =>

@ -259,12 +259,16 @@ let models_dir =
let models_jar =
lib_dir // "java" // "models.jar"
let cpp_extra_include_dir =
let dir = bin_dir // Filename.parent_dir_name // "models" // "cpp" // "include" in
let models_src_dir =
let dir = bin_dir // Filename.parent_dir_name // "models" in
Utils.filename_to_absolute dir (* Normalize the path *)
let cpp_models_dir =
cpp_extra_include_dir // "infer_model"
let relative_cpp_extra_include_dir = "cpp" // "include"
let cpp_extra_include_dir = models_src_dir // relative_cpp_extra_include_dir
let relative_cpp_models_dir =
relative_cpp_extra_include_dir // "infer_model"
let wrappers_dir =
lib_dir // "wrappers"

@ -62,7 +62,7 @@ val captured_dir_name : string
val checks_disabled_by_default : string list
val clang_initializer_prefix : string
val cpp_extra_include_dir : string
val cpp_models_dir : string
val relative_cpp_models_dir : string
val csl_analysis : bool
val current_exe : CommandLineOption.exe
val default_failure_name : string
@ -93,6 +93,7 @@ val max_recursion : int
val meet_level : int
val models_dir : string
val models_jar : string
val models_src_dir : string
val multicore_dir_name : string
val ncpu : int
val nsnotification_center_checker_backend : bool

@ -24,14 +24,18 @@ let count_newlines (path: string): int =
type source_file =
| Absolute of string
| Relative of string
| RelativeProjectRoot of string (* relative to project root *)
| RelativeInferModel of string (* relative to infer models *)
let source_file_compare sf1 sf2 =
match sf1, sf2 with
| Absolute p1, Absolute p2 -> string_compare p1 p2
| Absolute _, _ -> -1
| _, Absolute _ -> 1
| Relative p1, Relative p2 -> string_compare p1 p2
| RelativeProjectRoot p1, RelativeProjectRoot p2 -> string_compare p1 p2
| RelativeProjectRoot _, _ -> -1
| _, RelativeProjectRoot _ -> 1
| RelativeInferModel p1, RelativeInferModel p2 -> string_compare p1 p2
let source_file_equal sf1 sf2 =
(source_file_compare sf1 sf2) = 0
@ -48,7 +52,7 @@ module SourceFileSet = Set.Make(OrderedSourceFile)
let source_file_from_string path =
if Filename.is_relative path then
Relative path
RelativeProjectRoot path
else
Absolute path
@ -56,27 +60,40 @@ let source_file_from_string path =
let abs_source_file_from_path fname =
Absolute (filename_to_absolute fname)
(** convert a project root directory and a full path to a rooted source file *)
let rel_source_file_from_abs_path root fname =
let rel_path_from_abs_path root fname =
let relative_complemented_fname = filename_to_relative root fname in
if string_is_prefix root fname &&
Filename.is_relative relative_complemented_fname then
Relative relative_complemented_fname
else
(* The project root is not a prefix of the file name *)
abs_source_file_from_path fname
Some relative_complemented_fname
else None (* The project root is not a prefix of the file name *)
(** convert a project root directory and a full path to a rooted source file *)
let source_file_from_abs_path fname =
if Filename.is_relative fname then
(failwithf
"ERROR: Path %s is relative, when absolute path was expected .@."
fname);
match rel_path_from_abs_path Config.project_root fname with
| Some path -> RelativeProjectRoot path
| None -> (
match rel_path_from_abs_path Config.models_src_dir fname with
| Some path -> RelativeInferModel path
| None -> Absolute fname (* fname is absolute already *)
)
let curr_encoding = `Enc_crc
let source_file_to_string fname =
match fname with
| Relative path
| RelativeProjectRoot path
| RelativeInferModel path
| Absolute path -> path
(* Checking if the path exists may be needed only in some cases, hence the flag check_exists *)
let source_file_to_abs_path fname =
match fname with
| Relative path -> Filename.concat Config.project_root path
| RelativeProjectRoot path -> Filename.concat Config.project_root path
| RelativeInferModel path -> Filename.concat Config.models_src_dir path
| Absolute path -> path
let source_file_line_count source_file =
@ -90,24 +107,39 @@ let inode_equal sf1 sf2 =
let source_file_to_rel_path fname =
match fname with
| Relative path -> path
| Absolute path -> filename_to_relative Config.project_root path
| RelativeProjectRoot path -> path
| _ -> source_file_to_abs_path fname |> filename_to_relative Config.project_root
(** string encoding of a source file (including path) as a single filename *)
let source_file_encoding source_file =
let prefix = match source_file with
| RelativeProjectRoot _ -> "P"
| RelativeInferModel _ -> "MOD"
| Absolute _ -> "ABS" in
let source_file_s = source_file_to_string source_file in
match curr_encoding with
| `Enc_base ->
Filename.basename source_file_s
| `Enc_path_with_underscores ->
Escape.escape_path source_file_s
prefix ^ Escape.escape_path source_file_s
| `Enc_crc ->
let base = Filename.basename source_file_s in
let dir = Filename.dirname source_file_s in
let dir = prefix ^ Filename.dirname source_file_s in
string_append_crc_cutoff ~key:dir base
let source_file_empty = Absolute ""
let source_file_is_infer_model source_file = match source_file with
| RelativeProjectRoot _ | Absolute _ -> false
| RelativeInferModel _ -> true
(** Returns true if the file is a C++ model *)
let source_file_is_cpp_model file =
match file with
| RelativeInferModel path ->
string_is_prefix Config.relative_cpp_models_dir path
| _ -> false
(** {2 Source Dirs} *)
(** source directory: the directory inside the results dir corresponding to a source file *)
@ -347,13 +379,6 @@ let mark_file_updated fname =
let near_future = Unix.gettimeofday () +. 1. in
Unix.utimes fname near_future near_future
(** Returns true if the file is a C++ model *)
let file_is_in_cpp_model file =
let normalized_file_dir = filename_to_absolute (Filename.dirname file) in
let normalized_cpp_models_dir = filename_to_absolute Config.cpp_models_dir in
string_is_prefix normalized_cpp_models_dir normalized_file_dir
(** Fold over all file paths recursively under [dir] which match [p]. *)
let fold_paths_matching ~dir ~p ~init ~f =
let rec paths path_list dir =

@ -104,8 +104,7 @@ val source_file_empty : source_file
(** convert a path to a source file, turning it into an absolute path if necessary *)
val abs_source_file_from_path : string -> source_file
(** convert a project root directory and an absolute path to a source file *)
val rel_source_file_from_abs_path : string -> string -> source_file
val source_file_from_abs_path : string -> source_file
(** string encoding of a source file (including path) as a single filename *)
val source_file_encoding : source_file -> string
@ -122,6 +121,11 @@ val source_file_to_abs_path : source_file -> string
(** get the relative path of a source file *)
val source_file_to_rel_path : source_file -> string
val source_file_is_infer_model : source_file -> bool
(** Returns true if the file is a C++ model *)
val source_file_is_cpp_model : source_file -> bool
(** {2 Source Dirs} *)
(** source directory: the directory inside the results dir corresponding to a source file *)
@ -162,9 +166,6 @@ val global_tenv_fname : filename
(** Check if a path is a Java, C, C++ or Objectve C source file according to the file extention *)
val is_source_file: string -> bool
(** Returns true if the file is a C++ model *)
val file_is_in_cpp_model : string -> bool
(** Fold over all file paths recursively under [dir] which match [p]. *)
val fold_paths_matching :
dir:filename -> p:(filename -> bool) -> init:'a -> f:(filename -> 'a -> 'a) -> 'a

@ -67,7 +67,7 @@ let run_clang_frontend ast_source => {
switch ast_decl {
| Clang_ast_t.TranslationUnitDecl (_, _, _, info) =>
Config.arc_mode := info.Clang_ast_t.tudi_arc_enabled;
let source_file = CLocation.source_file_from_path info.Clang_ast_t.tudi_input_path;
let source_file = DB.source_file_from_abs_path info.Clang_ast_t.tudi_input_path;
init_global_state_for_capture_and_linters source_file;
let lang =
switch info.Clang_ast_t.tudi_input_kind {

@ -26,7 +26,7 @@ let is_in_main_file translation_unit_context an =
false
| Some file ->
DB.source_file_equal
(CLocation.source_file_from_path file)
(DB.source_file_from_abs_path file)
translation_unit_context.CFrontend_config.source_file
let is_ck_context (context: CLintersContext.context) an =

@ -658,7 +658,7 @@ struct
let get_rel_file_path file_opt =
match file_opt with
| Some file ->
DB.source_file_to_rel_path (DB.rel_source_file_from_abs_path Config.project_root file)
DB.source_file_to_string (DB.source_file_from_abs_path file)
| None -> ""
let is_cpp_translation translation_unit_context =

@ -11,21 +11,10 @@ open! Utils
(** Module for function to retrieve the location (file, line, etc) of instructions *)
let source_file_from_path path =
if Filename.is_relative path then
(failwithf
"ERROR: Path %s is relative. Please pass an absolute path in the -c argument.@."
path);
try
DB.rel_source_file_from_abs_path Config.project_root path
with Failure _ ->
Logging.err_debug "ERROR: %s should be a prefix of %s.@." Config.project_root path;
DB.source_file_from_string path
let clang_to_sil_location trans_unit_ctx clang_loc =
let line = Option.default (-1) clang_loc.Clang_ast_t.sl_line in
let col = Option.default (-1) clang_loc.Clang_ast_t.sl_column in
let file = Option.map_default source_file_from_path
let file = Option.map_default DB.source_file_from_abs_path
trans_unit_ctx.CFrontend_config.source_file clang_loc.Clang_ast_t.sl_file in
Location.{line; col; file}
@ -45,7 +34,7 @@ let should_do_frontend_check trans_unit_ctx (loc_start, _) =
match loc_start.Clang_ast_t.sl_file with
| Some file ->
let equal_current_source file =
DB.source_file_equal (source_file_from_path file)
DB.source_file_equal (DB.source_file_from_abs_path file)
trans_unit_ctx.CFrontend_config.source_file in
equal_current_source file ||
(file_in_project file && not Config.testing_mode)
@ -62,7 +51,7 @@ let should_translate trans_unit_ctx (loc_start, loc_end) decl_trans_context ~tra
| None -> false
in
let map_file_of pred loc =
let path_pred path = pred (source_file_from_path path) in
let path_pred path = pred (DB.source_file_from_abs_path path) in
map_path_of path_pred loc
in
(* it's not necessary to compare inodes here because both files come from
@ -73,8 +62,8 @@ let should_translate trans_unit_ctx (loc_start, loc_end) decl_trans_context ~tra
let file_in_project = map_path_of file_in_project loc_end
|| map_path_of file_in_project loc_start in
let translate_on_demand = translate_when_used || file_in_project || Config.models_mode in
let file_in_models = map_path_of DB.file_is_in_cpp_model loc_end
|| map_path_of DB.file_is_in_cpp_model loc_start in
let file_in_models = map_file_of DB.source_file_is_cpp_model loc_end
|| map_file_of DB.source_file_is_cpp_model loc_start in
map_file_of equal_current_source loc_end
|| map_file_of equal_current_source loc_start
|| file_in_models

@ -24,7 +24,5 @@ val should_do_frontend_check : CFrontend_config.translation_unit_context ->
val is_file_blacklisted : string -> bool
val source_file_from_path : string -> DB.source_file
val get_sil_location_from_range : CFrontend_config.translation_unit_context ->
Clang_ast_t.source_range -> bool -> Location.t

@ -72,13 +72,6 @@ let is_model procname =
let split_classpath cp = Str.split (Str.regexp JFile.sep) cp
let java_source_file_from_path path =
if Filename.is_relative path then
failwith "Expect absolute path for java source files"
else
DB.rel_source_file_from_abs_path Config.project_root path
(** Add the android.jar containing bytecode at the beginning of the class path *)
let add_android_jar paths =
AndroidFramework.non_stub_android_jar () :: paths
@ -130,7 +123,7 @@ let add_source_file path map =
let basename = Filename.basename path in
let entry =
let current_source_file =
java_source_file_from_path (convert_to_absolute path) in
DB.source_file_from_abs_path (convert_to_absolute path) in
try
match StringMap.find basename map with
| Singleton previous_source_file ->

@ -25,10 +25,6 @@ val add_models : string -> unit
(** Check if there is a model for the given procname *)
val is_model : Procname.t -> bool
(** create a source file from an absolute path.
Source files are relative if the project root is specified and absolute otherwise *)
val java_source_file_from_path : string -> DB.source_file
val split_classpath : string -> string list
(** map entry for source files with potential basname collision within the same compiler call *)

@ -81,7 +81,7 @@ let capture_libs linereader program tenv =
| Javalib.JClass _ ->
begin
let fake_source_file =
JClasspath.java_source_file_from_path (JFrontend.path_of_cached_classname cn) in
DB.source_file_from_abs_path (JFrontend.path_of_cached_classname cn) in
init_global_state fake_source_file;
let call_graph, cfg =
JFrontend.compute_class_icfg fake_source_file linereader program tenv node in

Loading…
Cancel
Save