diff --git a/infer/src/backend/InferAnalyze.re b/infer/src/backend/InferAnalyze.re index 0b0515298..22b04daf9 100644 --- a/infer/src/backend/InferAnalyze.re +++ b/infer/src/backend/InferAnalyze.re @@ -17,6 +17,7 @@ let module L = Logging; let module F = Format; let () = { + Logging.set_log_file_identifier (Option.map Filename.basename Config.cluster_cmdline); if Config.print_builtins { Builtin.print_and_exit () }; @@ -119,8 +120,8 @@ let register_perf_stats_report () => { }; let stats_base = Config.perf_stats_prefix ^ "_" ^ Filename.basename cluster ^ ".json"; let stats_file = Filename.concat stats_dir stats_base; - DB.create_dir Config.results_dir; - DB.create_dir stats_dir; + create_dir Config.results_dir; + create_dir stats_dir; PerfStats.register_report_at_exit stats_file }; diff --git a/infer/src/backend/InferPrint.re b/infer/src/backend/InferPrint.re index 99a4be03e..2aa69aaaf 100644 --- a/infer/src/backend/InferPrint.re +++ b/infer/src/backend/InferPrint.re @@ -1263,8 +1263,8 @@ let compute_top_procedures = ref false; let register_perf_stats_report () => { let stats_dir = Filename.concat Config.results_dir Config.reporting_stats_dir_name; let stats_file = Filename.concat stats_dir (Config.perf_stats_prefix ^ ".json"); - DB.create_dir Config.results_dir; - DB.create_dir stats_dir; + create_dir Config.results_dir; + create_dir stats_dir; PerfStats.register_report_at_exit stats_file }; diff --git a/infer/src/backend/Process.ml b/infer/src/backend/Process.ml index 56fc7c85f..f89633639 100644 --- a/infer/src/backend/Process.ml +++ b/infer/src/backend/Process.ml @@ -21,8 +21,8 @@ let print_unix_error cmd e = found in that file, and exits, with default code 1 or a given code. *) let print_error_and_exit ?(exit_code=1) f el = Logging.do_err f el; - let log_file = snd (Config.tmp_log_files_of_current_exe ()) in - Logging.stderr "\nAn error occured. Please, find details in %s\n\n%!" log_file; + let log_file = snd (Logging.log_file_names ()) in + Logging.stderr "@\nAn error occured. Please find details in %s@\n@\n%!" log_file; exit exit_code (** Executes a command and catches a potential exeption and prints it. *) diff --git a/infer/src/backend/crashcontext.ml b/infer/src/backend/crashcontext.ml index 4b0aa294b..0aa75c3ff 100644 --- a/infer/src/backend/crashcontext.ml +++ b/infer/src/backend/crashcontext.ml @@ -83,7 +83,7 @@ let collect_all_summaries root_summaries_dir stacktrace_file stacktraces_dir = | None -> None | Some file -> let crashcontext_dir = Config.results_dir // "crashcontext" in - DB.create_dir crashcontext_dir; + create_dir crashcontext_dir; Some (file, crashcontext_dir // "crashcontext.json") in let trace_file_regexp = Str.regexp "\\(.*\\)\\.json" in let pairs_for_stactrace_dir = match stacktraces_dir with diff --git a/infer/src/base/Config.ml b/infer/src/base/Config.ml index 6243798cd..a8665e1e3 100644 --- a/infer/src/base/Config.ml +++ b/infer/src/base/Config.ml @@ -1540,64 +1540,6 @@ let patterns_suppress_warnings = if CLOpt.(current_exe <> Java) then [] else error ("Error: The option " ^ suppress_warnings_annotations_long ^ " was not provided") -(** Name of dir for logging the output in the specific executable *) -let log_dir_of_current_exe = - match CLOpt.current_exe with - | Analyze -> "analyze" - | BuckCompilationDatabase -> "buck_compilation_database" - | Clang -> "clang" - | ClangWrapper -> "clang_wrapper" - | Interactive -> "interactive" - | Java -> "java" - | Llvm -> "llvm" - | Print -> "print" - | StatsAggregator -> "stats_agregator" - | Toplevel -> "top_level" - -let log_identifier_of_current_exe = - match CLOpt.current_exe with - | Analyze -> Option.map Filename.basename cluster_cmdline - | Clang -> Option.map Filename.basename source_file - | ClangWrapper - | Interactive - | Java - | Llvm - | Print - | StatsAggregator - | Toplevel - | BuckCompilationDatabase -> None - -(** Name of files for logging the output in the specific executable *) -let log_files_of_current_exe = - let name_prefix = - match log_identifier_of_current_exe with - | Some name -> name ^ "_" - | None -> "" in - let prefix = log_dir_of_current_exe in - name_prefix ^ prefix ^ "_out_", name_prefix ^ prefix ^ "_err_" - -(** should_log_exe exe = true means that files for logging in the log folder will be created - and uses of Logging.out or Logging.err will log in those files *) -let should_log_current_exe = - match CLOpt.current_exe with - | Analyze - | Clang - | ClangWrapper -> debug_mode || stats_mode - | BuckCompilationDatabase -> true - | _ -> false - -let tmp_log_files_of_current_exe () = - let out_name, err_name = log_files_of_current_exe in - let log_dir = results_dir // log_dir_name // log_dir_of_current_exe in - let out_file = - if out_file_cmdline = "" then - Filename.temp_file ~temp_dir:log_dir out_name ".log" - else out_file_cmdline in - let err_file = - if err_file_cmdline = "" then - Filename.temp_file ~temp_dir:log_dir err_name ".log" - else err_file_cmdline in - out_file, err_file (** Global variables *) diff --git a/infer/src/base/Config.mli b/infer/src/base/Config.mli index 2ca45db14..e329681fc 100644 --- a/infer/src/base/Config.mli +++ b/infer/src/base/Config.mli @@ -310,13 +310,3 @@ val curr_language : language ref (** Command Line Interface Documentation *) val print_usage_exit : unit -> 'a - -(** Name of dir for logging the output in the specific executable *) -val log_dir_of_current_exe : string - -(** Name of current temporary files for logging the output in the current executable *) -val tmp_log_files_of_current_exe : unit -> string * string - -(** should_log_exe = true means that files for logging in the log dir will be created - and uses of Logging.out or Logging.err will log in those files *) -val should_log_current_exe : bool diff --git a/infer/src/base/DB.ml b/infer/src/base/DB.ml index bc2ddc3e6..b880dc9c8 100644 --- a/infer/src/base/DB.ml +++ b/infer/src/base/DB.ml @@ -189,38 +189,11 @@ let file_modified_time ?(symlink=false) fname = Logging.do_err "File %s does not exist." fname; exit 1 -(** Create a directory if it does not exist already. *) -let create_dir dir = - try - if (Unix.stat dir).Unix.st_kind != Unix.S_DIR then - (L.err "@.ERROR: file %s exists and is not a directory@." dir; - assert false) - with Unix.Unix_error _ -> - (try Unix.mkdir dir 0o700 with - Unix.Unix_error _ -> - let created_concurrently = (* check if another process created it meanwhile *) - try (Unix.stat dir).Unix.st_kind = Unix.S_DIR - with Unix.Unix_error _ -> false in - if not created_concurrently then - (L.err "@.ERROR: cannot create directory %s@." dir; - assert false)) - let filename_create_dir fname = let dirname = Filename.dirname fname in if not (Sys.file_exists dirname) then create_dir dirname - -let rec create_path path = - try - Unix.mkdir path 0o700 - with - | Unix.Unix_error (Unix.EEXIST, _, _) -> () - | Unix.Unix_error (Unix.ENOENT, _, _) -> - create_path (Filename.dirname path); - create_path path - - let read_whole_file fd = let stats = Unix.fstat fd in let size = stats.Unix.st_size in diff --git a/infer/src/base/DB.mli b/infer/src/base/DB.mli index 081a93b6f..b201c1a3d 100644 --- a/infer/src/base/DB.mli +++ b/infer/src/base/DB.mli @@ -143,13 +143,6 @@ val filename_create_dir : filename -> unit (** Find the source directories in the current results dir *) val find_source_dirs : unit -> source_dir list -(** create a directory if it does not exist already *) -val create_dir : string -> unit - -(** [make_directory path] will create a directory [path] creating all the - sub directories if non-existing *) -val create_path : string -> unit - (** Read a file using a lock to allow write attempts in parallel. *) val read_file_with_lock : string -> string -> bytes option diff --git a/infer/src/base/Logging.ml b/infer/src/base/Logging.ml index b6b42e6ba..2c966c7f3 100644 --- a/infer/src/base/Logging.ml +++ b/infer/src/base/Logging.ml @@ -14,6 +14,73 @@ open! Utils module F = Format + +(** Name of dir for logging the output in the specific executable *) +let log_dir_of_current_exe = + match CommandLineOption.current_exe with + | Analyze -> "analyze" + | BuckCompilationDatabase -> "buck_compilation_database" + | Clang -> "clang" + | ClangWrapper -> "clang_wrapper" + | Interactive -> "interactive" + | Java -> "java" + | Llvm -> "llvm" + | Print -> "print" + | StatsAggregator -> "stats_agregator" + | Toplevel -> "top_level" + + +let out_file = ref "" +let err_file = ref "" +let out_formatter = ref F.std_formatter +let err_formatter = ref F.err_formatter + +let set_log_file_identifier string_opt = + let should_setup_log_files = + match CommandLineOption.current_exe with + | Analyze + | Clang + | ClangWrapper -> Config.debug_mode || Config.stats_mode + | BuckCompilationDatabase -> true + | _ -> false in + if should_setup_log_files then ( + let name_prefix = (match string_opt with + | Some name -> name ^ "_" + | None -> "") ^ string_of_int (Unix.getpid ()) ^ "_" in + let exe_log_dir = + let log_dir = Config.results_dir // Config.log_dir_name in + log_dir // log_dir_of_current_exe in + create_path exe_log_dir; + let log_file config_opt suffix = + (* the command-line option takes precedence if specified *) + if config_opt <> "" then config_opt + else Filename.temp_file ~temp_dir:exe_log_dir name_prefix suffix in + out_file := log_file Config.out_file_cmdline "-out.log"; + err_file := log_file Config.err_file_cmdline "-err.log"; + let open_output_file fname = + try + let cout = open_out fname in + let fmt = F.formatter_of_out_channel cout in + (fmt, cout) + with Sys_error _ -> + failwithf "@.ERROR: cannot open output file %s@." fname + in + let out_fmt, out_chan = open_output_file !out_file in + let err_fmt, err_chan = open_output_file !err_file in + Pervasives.at_exit (fun () -> + F.pp_print_flush out_fmt () ; + F.pp_print_flush err_fmt () ; + close_out out_chan ; + close_out err_chan + ); + out_formatter := out_fmt; + err_formatter := err_fmt; + ) + +let log_file_names () = (!out_file, !err_file) + (** type of printable elements *) type print_type = | PTatom @@ -64,52 +131,10 @@ let delayed_actions = ref [] (** hook for the current printer of delayed print actions *) let printer_hook = ref (Obj.magic ()) -let out_formatter, err_formatter = - (* Create a directory if it does not exist already. *) - (* This is the same as DB.create_dir, except for logging to stderr *) - let create_dir dir = - try - if (Unix.stat dir).Unix.st_kind != Unix.S_DIR then - failwithf "@.ERROR: file %s exists and is not a directory@." dir - with Unix.Unix_error _ -> - try Unix.mkdir dir 0o700 - with Unix.Unix_error _ -> - let created_concurrently = (* check if another process created it meanwhile *) - (Unix.stat dir).Unix.st_kind = Unix.S_DIR in - if not created_concurrently then - failwithf "@.ERROR: cannot create directory %s@." dir - in - let open_output_file fname = - try - let cout = open_out fname in - let fmt = F.formatter_of_out_channel cout in - (fmt, cout) - with Sys_error _ -> - failwithf "@.ERROR: cannot open output file %s@." fname - in - if Config.should_log_current_exe then - let log_dir = Config.results_dir // Config.log_dir_name in - let exe_log_dir = log_dir // Config.log_dir_of_current_exe in - create_dir Config.results_dir; - create_dir log_dir; - create_dir exe_log_dir; - let out_file, err_file = Config.tmp_log_files_of_current_exe () in - let out_fmt, out_chan = open_output_file out_file in - let err_fmt, err_chan = open_output_file err_file in - Pervasives.at_exit (fun () -> - F.pp_print_flush out_fmt () ; - F.pp_print_flush err_fmt () ; - close_out out_chan ; - close_out err_chan - ); - (out_fmt, err_fmt) - else - (F.std_formatter, F.err_formatter) - (** extend the current print log *) let add_print_action pact = if Config.write_html then delayed_actions := pact :: !delayed_actions - else if not Config.test then !printer_hook out_formatter pact + else if not Config.test then !printer_hook !out_formatter pact (** reset the delayed print actions *) let reset_delayed_prints () = @@ -123,50 +148,41 @@ let get_delayed_prints () = let set_delayed_prints new_delayed_actions = delayed_actions := new_delayed_actions -let do_print fmt fmt_string = - F.fprintf fmt fmt_string +let do_print = F.fprintf -let do_print_in_debug_or_stats_mode fmt fmt_string = +let do_print_in_debug_or_stats_mode = if Config.debug_mode || Config.stats_mode then - F.fprintf fmt fmt_string + F.fprintf else - F.ifprintf fmt fmt_string + F.ifprintf -let do_print_in_debug_mode fmt fmt_string = +let do_print_in_debug_mode = if Config.debug_mode then - F.fprintf fmt fmt_string + F.fprintf else - F.ifprintf fmt fmt_string + F.ifprintf -(** print to the current out stream (note: only prints in debug or stats mode) *) let out fmt_string = - do_print_in_debug_or_stats_mode out_formatter fmt_string + do_print_in_debug_or_stats_mode !out_formatter fmt_string -(** print to the current out stream (note: only prints in debug mode) *) let out_debug fmt_string = - do_print_in_debug_mode out_formatter fmt_string + do_print_in_debug_mode !out_formatter fmt_string -(** print to the current out stream *) let do_out fmt_string = - do_print out_formatter fmt_string + do_print !out_formatter fmt_string -(** print to the current err stream (note: only prints in debug or stats mode) *) let err fmt_string = - do_print_in_debug_or_stats_mode err_formatter fmt_string + do_print_in_debug_or_stats_mode !err_formatter fmt_string -(** print to the current err stream *) let do_err fmt_string = - do_print err_formatter fmt_string + do_print !err_formatter fmt_string -(** print to the current out stream (note: only prints in debug mode) *) let err_debug fmt_string = - do_print_in_debug_mode err_formatter fmt_string + do_print_in_debug_mode !err_formatter fmt_string -(** print immediately to standard error *) let stderr fmt_string = do_print F.err_formatter fmt_string -(** print immediately to standard output *) let stdout fmt_string = do_print F.std_formatter fmt_string diff --git a/infer/src/base/Logging.mli b/infer/src/base/Logging.mli index ff0695503..b918a3056 100644 --- a/infer/src/base/Logging.mli +++ b/infer/src/base/Logging.mli @@ -72,25 +72,29 @@ val set_delayed_prints : print_action list -> unit (** reset the delayed print actions *) val reset_delayed_prints : unit -> unit -(** print to the current out stream +(** Set a custom identifier to be part of the filename of the current logfiles. *) +val set_log_file_identifier : string option -> unit + +(** print to the current out stream, as specified in set_log_file_identifier (note: only prints in debug or in stats mode) *) val out : ('a, Format.formatter, unit) format -> 'a -(** print to the current out stream +(** print to the current out stream, as specified in set_log_file_identifier (note: only prints in debug mode) *) val out_debug : ('a, Format.formatter, unit) format -> 'a -(** print to the current error stream +(** print to the current error stream, as specified in set_log_file_identifier (note: only prints in debug or stats mode) *) val err : ('a, Format.formatter, unit) format -> 'a -(** print to the current error stream (note: only prints in debug mode) *) +(** print to the current error stream, as specified in set_log_file_identifier + (note: only prints in debug mode) *) val err_debug : ('a, Format.formatter, unit) format -> 'a -(** print to the current out stream *) +(** print to the current out stream, as specified in set_log_file_identifier *) val do_out : ('a, Format.formatter, unit) format -> 'a -(** print to the current err stream *) +(** print to the current err stream, as specified in set_log_file_identifier *) val do_err : ('a, Format.formatter, unit) format -> 'a (** print immediately to standard error *) @@ -156,3 +160,6 @@ val log_progress_procedure : unit -> unit (** Progress bar: log a timeout event if in developer mode. *) val log_progress_timeout_event : SymOp.failure_kind -> unit + +(** Name of current temporary files for logging the output in the current executable *) +val log_file_names : unit -> string * string diff --git a/infer/src/base/Utils.ml b/infer/src/base/Utils.ml index 4713bee1a..b8946d2ca 100644 --- a/infer/src/base/Utils.ml +++ b/infer/src/base/Utils.ml @@ -630,3 +630,29 @@ let failwithf fmt = let invalid_argf fmt = Format.kfprintf (fun _ -> invalid_arg (Format.flush_str_formatter ())) Format.str_formatter fmt + + +(** Create a directory if it does not exist already. *) +let create_dir dir = + try + if (Unix.stat dir).Unix.st_kind != Unix.S_DIR then + failwithf "@.ERROR: file %s exists and is not a directory@." dir + with Unix.Unix_error _ -> + try Unix.mkdir dir 0o700 with + Unix.Unix_error _ -> + let created_concurrently = (* check if another process created it meanwhile *) + try (Unix.stat dir).Unix.st_kind = Unix.S_DIR + with Unix.Unix_error _ -> false in + if not created_concurrently then + failwithf "@.ERROR: cannot create directory %s@." dir + +(** [create_path path] will create a directory at [path], creating all the parent directories if + non-existing *) +let rec create_path path = + try + Unix.mkdir path 0o700 + with + | Unix.Unix_error (Unix.EEXIST, _, _) -> () + | Unix.Unix_error (Unix.ENOENT, _, _) -> + create_path (Filename.dirname path); + create_dir path diff --git a/infer/src/base/Utils.mli b/infer/src/base/Utils.mli index 053ad2cff..f1e30711b 100644 --- a/infer/src/base/Utils.mli +++ b/infer/src/base/Utils.mli @@ -287,3 +287,10 @@ val with_process_full: string -> (in_channel -> 'a) -> (in_channel -> 'b) -> val failwithf : ('a, Format.formatter, unit, 'b) format4 -> 'a val invalid_argf : ('a, Format.formatter, unit, 'b) format4 -> 'a + +(** create a directory if it does not exist already *) +val create_dir : string -> unit + +(** [create_path path] will create a directory at [path], creating all the parent directories if + non-existing *) +val create_path : string -> unit diff --git a/infer/src/base/ZipLib.ml b/infer/src/base/ZipLib.ml index 4753d69fb..810abb123 100644 --- a/infer/src/base/ZipLib.ml +++ b/infer/src/base/ZipLib.ml @@ -23,7 +23,7 @@ let load_from_cache serializer zip_path cache_dir zip_library = let extract to_path = if not (Sys.file_exists to_path) then begin - DB.create_path (Filename.dirname to_path); + create_path (Filename.dirname to_path); let lazy zip_channel = zip_library.Config.zip_channel in let entry = Zip.find_entry zip_channel zip_path in Zip.copy_entry_to_file zip_channel entry to_path diff --git a/infer/src/checkers/BoundedCallTree.ml b/infer/src/checkers/BoundedCallTree.ml index 745ee04c5..7205344b2 100644 --- a/infer/src/checkers/BoundedCallTree.ml +++ b/infer/src/checkers/BoundedCallTree.ml @@ -104,7 +104,7 @@ module TransferFunctions (CFG : ProcCfg.S) = struct (Procname.to_filename caller) suffix in let fpath = Filename.concat dir fname in - DB.create_dir dir; + create_dir dir; Ag_util.Json.to_file Stacktree_j.write_stacktree fpath stacktree let exec_instr astate proc_data _ = function diff --git a/infer/src/clang/CLintersContext.ml b/infer/src/clang/CLintersContext.ml index a6a63e5dd..447915565 100644 --- a/infer/src/clang/CLintersContext.ml +++ b/infer/src/clang/CLintersContext.ml @@ -8,6 +8,7 @@ *) type context = { + translation_unit_context : CFrontend_config.translation_unit_context; current_method : Clang_ast_t.decl option; in_synchronized_block: bool; is_ck_translation_unit: bool; @@ -15,8 +16,9 @@ type context = { of CKComponent or CKComponentController. *) } -let empty = { +let empty translation_unit_context = { current_method = None; + translation_unit_context; in_synchronized_block = false; is_ck_translation_unit = false; } diff --git a/infer/src/clang/ComponentKit.ml b/infer/src/clang/ComponentKit.ml index 2ee8b1541..73f0a4345 100644 --- a/infer/src/clang/ComponentKit.ml +++ b/infer/src/clang/ComponentKit.ml @@ -10,10 +10,11 @@ open CFrontend_utils open !Utils -let is_ck_context context decl = - context.CLintersContext.is_ck_translation_unit - && Ast_utils.is_in_main_file decl - && General_utils.is_objc_extension +let is_ck_context {CLintersContext.is_ck_translation_unit; translation_unit_context} decl = + is_ck_translation_unit + && Ast_utils.is_in_main_file translation_unit_context decl + && General_utils.is_objc_extension translation_unit_context + (** Recursively go up the inheritance hierarchy of a given ObjCInterfaceDecl. (Returns false on decls other than that one.) *) @@ -101,7 +102,7 @@ let mutable_local_vars_advice context decl = CIssue.description = "Local variables should be const to avoid reassignment"; CIssue.suggestion = Some "Add a const (after the asterisk for pointer types). \ http://componentkit.org/docs/avoid-local-variables.html"; - CIssue.loc = CFrontend_checkers.location_from_dinfo decl_info + CIssue.loc = CFrontend_checkers.location_from_dinfo context decl_info } else None | _ -> assert false (* Should only be called with a VarDecl *) @@ -130,7 +131,7 @@ let component_factory_function_advice context decl = that return a CKComponent subclass. \ http://componentkit.org/docs/break-out-composites.html" ); - CIssue.loc = CFrontend_checkers.location_from_dinfo decl_info + CIssue.loc = CFrontend_checkers.location_from_dinfo context decl_info } else None | _ -> assert false (* Should only be called with FunctionDecl *) diff --git a/infer/src/clang/cArithmetic_trans.ml b/infer/src/clang/cArithmetic_trans.ml index cf3ac46c6..f272e4cc2 100644 --- a/infer/src/clang/cArithmetic_trans.ml +++ b/infer/src/clang/cArithmetic_trans.ml @@ -136,7 +136,7 @@ let binary_operation_instruction boi e1 typ e2 loc rhs_owning_method = (Clang_ast_j.string_of_binary_operator_kind bok); (Exp.minus_one, []) -let unary_operation_instruction uoi e typ loc = +let unary_operation_instruction translation_unit_context uoi e typ loc = let uok = Clang_ast_j.string_of_unary_operator_kind (uoi.Clang_ast_t.uoi_kind) in let un_exp op = Exp.UnOp(op, e, Some typ) in @@ -150,7 +150,7 @@ let unary_operation_instruction uoi e typ loc = let id = Ident.create_fresh Ident.knormal in let instr1 = Sil.Load (id, e, typ, loc) in let e_plus_1 = Exp.BinOp(Binop.PlusA, Exp.Var id, Exp.Const(Const.Cint (IntLit.one))) in - let exp = if General_utils.is_cpp_translation then + let exp = if General_utils.is_cpp_translation translation_unit_context then e else e_plus_1 in @@ -164,7 +164,7 @@ let unary_operation_instruction uoi e typ loc = let id = Ident.create_fresh Ident.knormal in let instr1 = Sil.Load (id, e, typ, loc) in let e_minus_1 = Exp.BinOp(Binop.MinusA, Exp.Var id, Exp.Const(Const.Cint (IntLit.one))) in - let exp = if General_utils.is_cpp_translation then + let exp = if General_utils.is_cpp_translation translation_unit_context then e else e_minus_1 in diff --git a/infer/src/clang/cArithmetic_trans.mli b/infer/src/clang/cArithmetic_trans.mli index 633cc4e94..60d5ff8bb 100644 --- a/infer/src/clang/cArithmetic_trans.mli +++ b/infer/src/clang/cArithmetic_trans.mli @@ -17,7 +17,7 @@ val binary_operation_instruction : Clang_ast_t.binary_operator_info -> Exp.t -> Typ.t -> Exp.t -> Location.t -> bool -> Exp.t * Sil.instr list -val unary_operation_instruction : +val unary_operation_instruction : CFrontend_config.translation_unit_context -> Clang_ast_t.unary_operator_info -> Exp.t -> Typ.t -> Location.t -> Exp.t * Sil.instr list val assignment_arc_mode : diff --git a/infer/src/clang/cContext.ml b/infer/src/clang/cContext.ml index 4c7678117..d087cb821 100644 --- a/infer/src/clang/cContext.ml +++ b/infer/src/clang/cContext.ml @@ -26,6 +26,7 @@ type str_node_map = (string, Cfg.Node.t) Hashtbl.t type t = { + translation_unit_context : CFrontend_config.translation_unit_context; tenv : Tenv.t; cg : Cg.t; cfg : Cfg.cfg; @@ -33,20 +34,16 @@ type t = is_objc_method : bool; curr_class: curr_class; return_param_typ : Typ.t option; - outer_context : t option; (* in case of objc blocks, the context of the method containing the block *) + outer_context : t option; (** in case of objc blocks, the context of the method containing the + block *) mutable blocks_static_vars : ((Pvar.t * Typ.t) list) Procname.Map.t; label_map : str_node_map; } -let create_context tenv cg cfg procdesc curr_class return_param_typ is_objc_method context_opt = - { tenv = tenv; - cg = cg; - cfg = cfg; - procdesc = procdesc; - curr_class = curr_class; - return_param_typ = return_param_typ; - is_objc_method = is_objc_method; - outer_context = context_opt; +let create_context translation_unit_context tenv cg cfg procdesc curr_class return_param_typ + is_objc_method outer_context = + { translation_unit_context; tenv; cg; cfg; procdesc; curr_class; return_param_typ; + is_objc_method; outer_context; blocks_static_vars = Procname.Map.empty; label_map = Hashtbl.create 17; } diff --git a/infer/src/clang/cContext.mli b/infer/src/clang/cContext.mli index e9137e4d7..e0431b657 100644 --- a/infer/src/clang/cContext.mli +++ b/infer/src/clang/cContext.mli @@ -24,6 +24,7 @@ type str_node_map = (string, Cfg.Node.t) Hashtbl.t type t = { + translation_unit_context : CFrontend_config.translation_unit_context; tenv : Tenv.t; cg : Cg.t; cfg : Cfg.cfg; @@ -31,7 +32,8 @@ type t = is_objc_method : bool; curr_class: curr_class; return_param_typ : Typ.t option; - outer_context : t option; (* in case of objc blocks, the context of the method containing the block *) + outer_context : t option; (** in case of objc blocks, the context of the method containing the + block *) mutable blocks_static_vars : ((Pvar.t * Typ.t) list) Procname.Map.t; label_map : str_node_map; } @@ -58,8 +60,8 @@ val is_objc_method : t -> bool val get_tenv : t -> Tenv.t -val create_context : Tenv.t -> Cg.t -> Cfg.cfg -> Cfg.Procdesc.t -> - curr_class -> Typ.t option -> bool -> t option -> t +val create_context : CFrontend_config.translation_unit_context -> Tenv.t -> Cg.t -> Cfg.cfg -> + Cfg.Procdesc.t -> curr_class -> Typ.t option -> bool -> t option -> t val create_curr_class : Tenv.t -> string -> Csu.class_kind -> curr_class diff --git a/infer/src/clang/cFrontend.ml b/infer/src/clang/cFrontend.ml index 37ef09a3a..b46e3e0f6 100644 --- a/infer/src/clang/cFrontend.ml +++ b/infer/src/clang/cFrontend.ml @@ -20,14 +20,15 @@ and CFrontend_declImpl : CModule_type.CFrontend = CFrontend_decl.CFrontend_decl_funct(CTransImpl) (* Translates a file by translating the ast into a cfg. *) -let compute_icfg source tenv ast = +let compute_icfg trans_unit_ctx tenv ast = match ast with | Clang_ast_t.TranslationUnitDecl(_, decl_list, _, _) -> CFrontend_config.global_translation_unit_decls := decl_list; Logging.out_debug "@\n Start creating icfg@\n"; - let cg = Cg.create (Some source) in + let cg = Cg.create (Some trans_unit_ctx.CFrontend_config.source_file) in let cfg = Cfg.Node.create_cfg () in - IList.iter (CFrontend_declImpl.translate_one_declaration tenv cg cfg `DeclTraversal) + IList.iter + (CFrontend_declImpl.translate_one_declaration trans_unit_ctx tenv cg cfg `DeclTraversal) decl_list; Logging.out_debug "\n Finished creating icfg\n"; (cg, cfg) @@ -38,14 +39,15 @@ let init_global_state_capture () = CFrontend_config.global_translation_unit_decls := []; CFrontend_utils.General_utils.reset_block_counter () -let do_source_file source_file ast = +let do_source_file translation_unit_context ast = let tenv = Tenv.create () in CTypes_decl.add_predefined_types tenv; init_global_state_capture (); + let source_file = translation_unit_context.CFrontend_config.source_file in Config.nLOC := FileLOC.file_get_loc (DB.source_file_to_string source_file); Logging.out_debug "@\n Start building call/cfg graph for '%s'....@\n" (DB.source_file_to_string source_file); - let call_graph, cfg = compute_icfg source_file tenv ast in + let call_graph, cfg = compute_icfg translation_unit_context tenv ast in Logging.out_debug "@\n End building call/cfg graph for '%s'.@\n" (DB.source_file_to_string source_file); (* This part below is a boilerplate in every frontends. *) diff --git a/infer/src/clang/cFrontend.mli b/infer/src/clang/cFrontend.mli index 89f429ea4..9206ffbe9 100644 --- a/infer/src/clang/cFrontend.mli +++ b/infer/src/clang/cFrontend.mli @@ -13,4 +13,4 @@ open! Utils json format. Translate the json file into a cfg by adding all the type and class declarations to the tenv, adding all the functions and methods declarations as procdescs to the cfg, and adding the control flow graph of all the code of those functions and methods to the cfg. *) -val do_source_file : DB.source_file -> Clang_ast_t.decl -> unit +val do_source_file : CFrontend_config.translation_unit_context -> Clang_ast_t.decl -> unit diff --git a/infer/src/clang/cFrontend_checkers.ml b/infer/src/clang/cFrontend_checkers.ml index 180a05baa..87957e880 100644 --- a/infer/src/clang/cFrontend_checkers.ml +++ b/infer/src/clang/cFrontend_checkers.ml @@ -22,16 +22,19 @@ open CFrontend_utils (* - If it is a declaration invoke it from run_frontend_checkers_on_decl *) (* Helper functions *) -let location_from_stmt stmt = +let location_from_stmt lctx stmt = let info, _ = Clang_ast_proj.get_stmt_tuple stmt in - CLocation.get_sil_location_from_range info.Clang_ast_t.si_source_range true + CLocation.get_sil_location_from_range lctx.CLintersContext.translation_unit_context + info.Clang_ast_t.si_source_range true -let location_from_dinfo info = - CLocation.get_sil_location_from_range info.Clang_ast_t.di_source_range true +let location_from_dinfo lctx info = + CLocation.get_sil_location_from_range lctx.CLintersContext.translation_unit_context + info.Clang_ast_t.di_source_range true -let location_from_decl dec = +let location_from_decl lctx dec = let info = Clang_ast_proj.get_decl_tuple dec in - CLocation.get_sil_location_from_range info.Clang_ast_t.di_source_range true + CLocation.get_sil_location_from_range lctx.CLintersContext.translation_unit_context + info.Clang_ast_t.di_source_range true let decl_name dec = match Clang_ast_proj.get_named_decl_tuple dec with @@ -73,7 +76,7 @@ let ctl_makes_an_expensive_call () = ET([ObjCMethodDecl][->Body] EF remove_observer) Or EH([ObjCImplementationDecl, ObjCProtocolDecl] EF remove_observer) *) -let ctl_ns_notification decl = +let ctl_ns_notification lctx decl = let open CTL in let exists_method_calling_addObserver = EF (Atomic ("call_method", ["addObserver:selector:name:object:"])) in @@ -102,13 +105,13 @@ let ctl_ns_notification decl = Localise.registered_observer_being_deallocated_str CFrontend_config.self; CIssue.suggestion = Some "Consider removing the object from the notification center before its deallocation."; - CIssue.loc = location_from_decl decl; + CIssue.loc = location_from_decl lctx decl; } in condition, issue_desc (* BAD_POINTER_COMPARISON: Fires whenever a NSNumber is dangerously coerced to a boolean in a comparison *) -let ctl_bad_pointer_comparison_warning stmt = +let ctl_bad_pointer_comparison_warning lctx stmt = let open CTL in let is_binop = Atomic ("is_stmt", ["BinaryOperator"]) in let is_binop_eq = Atomic ("is_binop_with_kind", ["EQ"]) in @@ -134,12 +137,12 @@ let ctl_bad_pointer_comparison_warning stmt = Some ("Did you mean to compare against the unboxed value instead? " ^ "Please either explicitly compare the NSNumber instance to nil, " ^ "or use one of the NSNumber accessors before the comparison."); - loc = location_from_stmt stmt + loc = location_from_stmt lctx stmt } in condition, issue_desc (* name_contains_delegate AND not name_contains_queue AND is_strong_property *) -let ctl_strong_delegate dec = +let ctl_strong_delegate lctx dec = let open CTL in let name_contains_delegate = Atomic ("property_name_contains_word", ["delegate"]) in @@ -155,14 +158,14 @@ let ctl_strong_delegate dec = CIssue.description = Printf.sprintf "Property or ivar %s declared strong" (decl_name dec); CIssue.suggestion = Some "In general delegates should be declared weak or assign"; - CIssue.loc = location_from_decl dec + CIssue.loc = location_from_decl lctx dec } in condition, issue_desc (* (is_ObjC || is_Objc++) /\ is_global_var /\ not is_const_var /\ ET([VarDecl][->InitExpr] EF ctl_makes_an_expensive_call) *) -let ctl_global_var_init_with_calls_warning decl = +let ctl_global_var_init_with_calls_warning lctx decl = let open CTL in let ctl_is_global_var = And (And (Atomic ("is_objc_extension", []), Atomic ("is_global_var", [])), @@ -177,12 +180,12 @@ let ctl_global_var_init_with_calls_warning decl = (decl_name decl); CIssue.suggestion = Some "If the function/method call is expensive, it can affect the starting time of the app."; - CIssue.loc = location_from_decl decl + CIssue.loc = location_from_decl lctx decl } in condition, issue_desc (* is_assign_property AND is_property_pointer_type *) -let ctl_assign_pointer_warning decl = +let ctl_assign_pointer_warning lctx decl = let open CTL in let condition = And (Atomic("is_assign_property", []), Atomic("is_property_pointer_type", [])) in @@ -193,7 +196,7 @@ let ctl_assign_pointer_warning decl = "Property `%s` is a pointer type marked with the `assign` attribute" (decl_name decl); CIssue.suggestion = Some "Use a different attribute like `strong` or `weak`."; - CIssue.loc = location_from_decl decl + CIssue.loc = location_from_decl lctx decl } in condition, issue_desc @@ -201,7 +204,7 @@ let ctl_assign_pointer_warning decl = not context_in_synchronized_block /\ not is_method_property_accessor_of_ivar /\ not is_objc_constructor /\ not is_objc_dealloc *) -let ctl_direct_atomic_property_access_warning stmt = +let ctl_direct_atomic_property_access_warning lctx stmt = let open CTL in let condition = And (And (And (And (Not (Atomic ("context_in_synchronized_block", [])), @@ -215,11 +218,11 @@ let ctl_direct_atomic_property_access_warning stmt = "Direct access to ivar %s of an atomic property" (ivar_name stmt); CIssue.suggestion = Some "Accessing an ivar of an atomic property makes the property nonatomic"; - CIssue.loc = location_from_stmt stmt + CIssue.loc = location_from_stmt lctx stmt } in condition, issue_desc -let ctl_captured_cxx_ref_in_objc_block_warning stmt = +let ctl_captured_cxx_ref_in_objc_block_warning lctx stmt = (* Fire if the list of captured references is not empty *) let condition = CTL.Atomic ("captures_cxx_references", []) in let issue_desc = { @@ -229,24 +232,24 @@ let ctl_captured_cxx_ref_in_objc_block_warning stmt = (Predicates.var_descs_name stmt); CIssue.suggestion = Some ("C++ References are unmanaged and may be invalid " ^ "by the time the block executes."); - CIssue.loc = location_from_stmt stmt + CIssue.loc = location_from_stmt lctx stmt } in condition, issue_desc (* === Warnings on properties === *) (* Assing Pointer Warning: a property with a pointer type should not be declared `assign` *) -let assign_pointer_warning lcxt decl = +let assign_pointer_warning lctx decl = let open CTL in - let condition, issue_desc = ctl_assign_pointer_warning decl in - if CTL.eval_formula condition (Decl decl) lcxt then + let condition, issue_desc = ctl_assign_pointer_warning lctx decl in + if CTL.eval_formula condition (Decl decl) lctx then Some issue_desc else None (* Strong Delegate Warning: a property with name delegate should not be declared strong *) -let strong_delegate_warning lcxt decl = - let condition, issue_desc = ctl_strong_delegate decl in - if CTL.eval_formula condition (Decl decl) lcxt then +let strong_delegate_warning lctx decl = + let condition, issue_desc = ctl_strong_delegate lctx decl in + if CTL.eval_formula condition (Decl decl) lctx then Some issue_desc else None @@ -254,36 +257,36 @@ let strong_delegate_warning lcxt decl = (* a global variable initialization should not *) (* contain calls to functions or methods as these can be expensive an delay the starting time *) (* of an app *) -let global_var_init_with_calls_warning lcxt decl = - let condition, issue_desc = ctl_global_var_init_with_calls_warning decl in - if CTL.eval_formula condition (CTL.Decl decl) lcxt then +let global_var_init_with_calls_warning lctx decl = + let condition, issue_desc = ctl_global_var_init_with_calls_warning lctx decl in + if CTL.eval_formula condition (CTL.Decl decl) lctx then Some issue_desc else None (* Direct Atomic Property access: a property declared atomic should not be accessed directly via its ivar *) -let direct_atomic_property_access_warning context stmt = - let condition, issue_desc = ctl_direct_atomic_property_access_warning stmt in - if CTL.eval_formula condition (CTL.Stmt stmt) context then +let direct_atomic_property_access_warning lctx stmt = + let condition, issue_desc = ctl_direct_atomic_property_access_warning lctx stmt in + if CTL.eval_formula condition (CTL.Stmt stmt) lctx then Some issue_desc else None (* CXX_REFERENCE_CAPTURED_IN_OBJC_BLOCK: C++ references should not be captured in blocks. *) -let captured_cxx_ref_in_objc_block_warning lcxt stmt = - let condition, issue_desc = ctl_captured_cxx_ref_in_objc_block_warning stmt in - if CTL.eval_formula condition (CTL.Stmt stmt) lcxt then +let captured_cxx_ref_in_objc_block_warning lctx stmt = + let condition, issue_desc = ctl_captured_cxx_ref_in_objc_block_warning lctx stmt in + if CTL.eval_formula condition (CTL.Stmt stmt) lctx then Some issue_desc else None -let checker_NSNotificationCenter lcxt dec = - let condition, issue_desc = ctl_ns_notification dec in - if CTL.eval_formula condition (CTL.Decl dec) lcxt then +let checker_NSNotificationCenter lctx dec = + let condition, issue_desc = ctl_ns_notification lctx dec in + if CTL.eval_formula condition (CTL.Decl dec) lctx then Some issue_desc else None -let bad_pointer_comparison_warning lcxt stmt = - let condition, issue_desc = ctl_bad_pointer_comparison_warning stmt in - if CTL.eval_formula condition (CTL.Stmt stmt) lcxt then +let bad_pointer_comparison_warning lctx stmt = + let condition, issue_desc = ctl_bad_pointer_comparison_warning lctx stmt in + if CTL.eval_formula condition (CTL.Stmt stmt) lctx then Some issue_desc else None diff --git a/infer/src/clang/cFrontend_checkers.mli b/infer/src/clang/cFrontend_checkers.mli index c40f60e0f..00c68ff57 100644 --- a/infer/src/clang/cFrontend_checkers.mli +++ b/infer/src/clang/cFrontend_checkers.mli @@ -44,4 +44,4 @@ val global_var_init_with_calls_warning : CLintersContext.context -> Clang_ast_t.decl -> CIssue.issue_desc option val location_from_dinfo : - Clang_ast_t.decl_info -> Location.t + CLintersContext.context -> Clang_ast_t.decl_info -> Location.t diff --git a/infer/src/clang/cFrontend_checkers_main.ml b/infer/src/clang/cFrontend_checkers_main.ml index 50ee388d5..c835d6a99 100644 --- a/infer/src/clang/cFrontend_checkers_main.ml +++ b/infer/src/clang/cFrontend_checkers_main.ml @@ -27,7 +27,7 @@ let rec do_frontend_checks_stmt (context:CLintersContext.context) stmt = and do_frontend_checks_decl context decl = let open Clang_ast_t in let info = Clang_ast_proj.get_decl_tuple decl in - CLocation.update_curr_file info; + CLocation.update_curr_file context.CLintersContext.translation_unit_context info; let context' = (match decl with | FunctionDecl(_, _, _, fdi) @@ -74,20 +74,22 @@ let context_with_ck_set context decl_list = let store_issues source_file = let abbrev_source_file = DB.source_file_encoding source_file in let lint_issues_dir = Config.results_dir // Config.lint_issues_dir_name in - DB.create_dir lint_issues_dir; + create_dir lint_issues_dir; let lint_issues_file = DB.filename_from_string (Filename.concat lint_issues_dir (abbrev_source_file ^ ".issue")) in LintIssues.store_issues lint_issues_file !LintIssues.errLogMap -let do_frontend_checks source_file ast = +let do_frontend_checks trans_unit_ctx ast = try + let source_file = trans_unit_ctx.CFrontend_config.source_file in Logging.out "Start linting file %s@\n" (DB.source_file_to_string source_file); match ast with | Clang_ast_t.TranslationUnitDecl(_, decl_list, _, _) -> - let context = context_with_ck_set CLintersContext.empty decl_list in + let context = + context_with_ck_set (CLintersContext.empty trans_unit_ctx) decl_list in let is_decl_allowed decl = let decl_info = Clang_ast_proj.get_decl_tuple decl in - CLocation.should_do_frontend_check decl_info.Clang_ast_t.di_source_range in + CLocation.should_do_frontend_check trans_unit_ctx decl_info.Clang_ast_t.di_source_range in let allowed_decls = IList.filter is_decl_allowed decl_list in IList.iter (do_frontend_checks_decl context) allowed_decls; if (LintIssues.exists_issues ()) then diff --git a/infer/src/clang/cFrontend_checkers_main.mli b/infer/src/clang/cFrontend_checkers_main.mli index 86b7f9b86..9091316f9 100644 --- a/infer/src/clang/cFrontend_checkers_main.mli +++ b/infer/src/clang/cFrontend_checkers_main.mli @@ -7,4 +7,4 @@ * of patent rights can be found in the PATENTS file in the same directory. *) -val do_frontend_checks : DB.source_file -> Clang_ast_t.decl -> unit +val do_frontend_checks : CFrontend_config.translation_unit_context -> Clang_ast_t.decl -> unit diff --git a/infer/src/clang/cFrontend_config.ml b/infer/src/clang/cFrontend_config.ml index 6b68468c2..f38aa16dd 100644 --- a/infer/src/clang/cFrontend_config.ml +++ b/infer/src/clang/cFrontend_config.ml @@ -11,6 +11,11 @@ open! Utils (** Module that contains constants and global state used in the frontend *) +type translation_unit_context = { + lang : Config.clang_lang; + source_file : DB.source_file +} + (** Constants *) let alloc = "alloc" @@ -78,7 +83,6 @@ let modeled_function_attributes = [replace_with_deref_first_arg_attr] (** Global state *) -let current_source = ref DB.source_file_empty let enum_map = ref Clang_ast_main.PointerMap.empty let global_translation_unit_decls : Clang_ast_t.decl list ref = ref [] let ivar_to_property_index = ref Clang_ast_main.PointerMap.empty diff --git a/infer/src/clang/cFrontend_config.mli b/infer/src/clang/cFrontend_config.mli index d0df06dc6..40d5067a4 100644 --- a/infer/src/clang/cFrontend_config.mli +++ b/infer/src/clang/cFrontend_config.mli @@ -11,6 +11,11 @@ open! Utils (** Module that contains constants and global state used in the frontend *) +type translation_unit_context = { + lang : Config.clang_lang; + source_file : DB.source_file +} + (** Constants *) val alloc : string @@ -79,8 +84,6 @@ val modeled_function_attributes : string list (** Global state *) -val current_source : DB.source_file ref - (** Map from enum constants pointers to their predecesor and their sil value *) val enum_map : (Clang_ast_t.pointer option * Exp.t option) Clang_ast_main.PointerMap.t ref val global_translation_unit_decls : Clang_ast_t.decl list ref diff --git a/infer/src/clang/cFrontend_decl.ml b/infer/src/clang/cFrontend_decl.ml index 132349e7a..92dc4ab7d 100644 --- a/infer/src/clang/cFrontend_decl.ml +++ b/infer/src/clang/cFrontend_decl.ml @@ -21,8 +21,8 @@ struct Specs.summary_exists_in_models procname && not Config.models_mode (* Translates the method/function's body into nodes of the cfg. *) - let add_method tenv cg cfg class_decl_opt procname body has_return_param is_objc_method - outer_context_opt extra_instrs = + let add_method trans_unit_ctx tenv cg cfg class_decl_opt procname body has_return_param + is_objc_method outer_context_opt extra_instrs = Logging.out_debug "@\n@\n>>---------- ADDING METHOD: '%s' ---------<<@\n@." (Procname.to_string procname); try @@ -30,7 +30,7 @@ struct | Some procdesc -> if (Cfg.Procdesc.is_defined procdesc && not (model_exists procname)) then (let context = - CContext.create_context tenv cg cfg procdesc class_decl_opt + CContext.create_context trans_unit_ctx tenv cg cfg procdesc class_decl_opt has_return_param is_objc_method outer_context_opt in let start_node = Cfg.Procdesc.get_start_node procdesc in let exit_node = Cfg.Procdesc.get_exit_node procdesc in @@ -45,44 +45,49 @@ struct with | Not_found -> () | CTrans_utils.Self.SelfClassException _ -> - assert false (* this shouldn't happen, because self or [a class] should always be arguments of functions. This is to make sure I'm not wrong. *) + (* this shouldn't happen, because self or [a class] should always be arguments of + functions. This is to make sure I'm not wrong. *) + assert false | Assert_failure (file, line, column) -> Logging.out "Fatal error: exception Assert_failure(%s, %d, %d)\n%!" file line column; Cfg.Procdesc.remove cfg procname true; CMethod_trans.create_external_procdesc cfg procname is_objc_method None; () - let function_decl tenv cfg cg func_decl block_data_opt = + let function_decl trans_unit_ctx tenv cfg cg func_decl block_data_opt = let captured_vars, outer_context_opt = match block_data_opt with | Some (outer_context, _, _, captured_vars) -> captured_vars, Some outer_context | None -> [], None in let ms, body_opt, extra_instrs = - CMethod_trans.method_signature_of_decl tenv func_decl block_data_opt in + CMethod_trans.method_signature_of_decl trans_unit_ctx tenv func_decl block_data_opt in match body_opt with - | Some body -> (* Only in the case the function declaration has a defined body we create a procdesc *) + | Some body -> + (* Only in the case the function declaration has a defined body we create a procdesc *) let procname = CMethod_signature.ms_get_name ms in let return_param_typ_opt = CMethod_signature.ms_get_return_param_typ ms in - if CMethod_trans.create_local_procdesc cfg tenv ms [body] captured_vars false then - add_method tenv cg cfg CContext.ContextNoCls procname body return_param_typ_opt false - outer_context_opt extra_instrs + if CMethod_trans.create_local_procdesc + trans_unit_ctx cfg tenv ms [body] captured_vars false then + add_method trans_unit_ctx tenv cg cfg CContext.ContextNoCls procname body + return_param_typ_opt false outer_context_opt extra_instrs | None -> () - let process_method_decl tenv cg cfg curr_class meth_decl ~is_objc = + let process_method_decl trans_unit_ctx tenv cg cfg curr_class meth_decl ~is_objc = let ms, body_opt, extra_instrs = - CMethod_trans.method_signature_of_decl tenv meth_decl None in + CMethod_trans.method_signature_of_decl trans_unit_ctx tenv meth_decl None in match body_opt with | Some body -> let is_instance = CMethod_signature.ms_is_instance ms in let procname = CMethod_signature.ms_get_name ms in let is_objc_inst_method = is_instance && is_objc in let return_param_typ_opt = CMethod_signature.ms_get_return_param_typ ms in - if CMethod_trans.create_local_procdesc cfg tenv ms [body] [] is_objc_inst_method then - add_method tenv cg cfg curr_class procname body return_param_typ_opt is_objc - None extra_instrs + if CMethod_trans.create_local_procdesc + trans_unit_ctx cfg tenv ms [body] [] is_objc_inst_method then + add_method trans_unit_ctx tenv cg cfg curr_class procname body return_param_typ_opt + is_objc None extra_instrs | None -> () - let process_property_implementation obj_c_property_impl_decl_info = + let process_property_implementation trans_unit_ctx obj_c_property_impl_decl_info = let property_decl_opt = obj_c_property_impl_decl_info.Clang_ast_t.opidi_property_decl in match Ast_utils.get_decl_opt_with_decl_ref property_decl_opt with | Some ObjCPropertyDecl (_, _, obj_c_property_decl_info) -> @@ -94,13 +99,14 @@ struct (match Ast_utils.get_decl_opt_with_decl_ref pointer with | Some (ObjCMethodDecl (decl_info, _, _) as d) -> let source_range = decl_info.Clang_ast_t.di_source_range in - let loc = CLocation.get_sil_location_from_range source_range true in + let loc = + CLocation.get_sil_location_from_range trans_unit_ctx source_range true in let property_accessor = if getter then Some (ProcAttributes.Objc_getter field_name) else Some (ProcAttributes.Objc_setter field_name) in - let procname = General_utils.procname_of_decl d in + let procname = General_utils.procname_of_decl trans_unit_ctx d in let attrs = { (ProcAttributes.default procname Config.Clang) with loc = loc; objc_accessor = property_accessor; } in @@ -111,15 +117,15 @@ struct | _ -> ()) | _ -> () - let process_one_method_decl tenv cg cfg curr_class dec = + let process_one_method_decl trans_unit_ctx tenv cg cfg curr_class dec = let open Clang_ast_t in match dec with | CXXMethodDecl _ | CXXConstructorDecl _ | CXXConversionDecl _ | CXXDestructorDecl _ -> - process_method_decl tenv cg cfg curr_class dec ~is_objc:false + process_method_decl trans_unit_ctx tenv cg cfg curr_class dec ~is_objc:false | ObjCMethodDecl _ -> - process_method_decl tenv cg cfg curr_class dec ~is_objc:true + process_method_decl trans_unit_ctx tenv cg cfg curr_class dec ~is_objc:true | ObjCPropertyImplDecl (_, obj_c_property_impl_decl_info) -> - process_property_implementation obj_c_property_impl_decl_info + process_property_implementation trans_unit_ctx obj_c_property_impl_decl_info | EmptyDecl _ | ObjCIvarDecl _ | ObjCPropertyDecl _ -> () | _ -> @@ -127,12 +133,12 @@ struct "\nWARNING: found Method Declaration '%s' skipped. NEED TO BE FIXED\n\n" (Ast_utils.string_of_decl dec); () - let process_methods tenv cg cfg curr_class decl_list = - IList.iter (process_one_method_decl tenv cg cfg curr_class) decl_list + let process_methods trans_unit_ctx tenv cg cfg curr_class decl_list = + IList.iter (process_one_method_decl trans_unit_ctx tenv cg cfg curr_class) decl_list - let should_translate_decl dec decl_trans_context = + let should_translate_decl trans_unit_ctx dec decl_trans_context = let info = Clang_ast_proj.get_decl_tuple dec in - CLocation.update_curr_file info; + CLocation.update_curr_file trans_unit_ctx info; let source_range = info.Clang_ast_t.di_source_range in let translate_when_used = match dec with | Clang_ast_t.FunctionDecl (_, name_info, _, _) @@ -144,7 +150,8 @@ struct AttributesTable.is_whitelisted_cpp_method name | _ -> false in let translate_location = - CLocation.should_translate_lib source_range decl_trans_context ~translate_when_used in + CLocation.should_translate_lib trans_unit_ctx source_range decl_trans_context + ~translate_when_used in let never_translate_decl = match dec with | Clang_ast_t.FunctionDecl (_, name_info, _, _) | Clang_ast_t.CXXMethodDecl (_, name_info, _, _, _) -> @@ -154,49 +161,49 @@ struct (not never_translate_decl) && translate_location (* Translate one global declaration *) - let rec translate_one_declaration tenv cg cfg decl_trans_context dec = + let rec translate_one_declaration trans_unit_ctx tenv cg cfg decl_trans_context dec = let open Clang_ast_t in (* each procedure has different scope: start names from id 0 *) Ident.NameGenerator.reset (); - (if should_translate_decl dec decl_trans_context then + (if should_translate_decl trans_unit_ctx dec decl_trans_context then match dec with | FunctionDecl(_, _, _, _) -> - function_decl tenv cfg cg dec None + function_decl trans_unit_ctx tenv cfg cg dec None | ObjCInterfaceDecl(_, name_info, decl_list, _, oi_decl_info) -> let name = Ast_utils.get_qualified_name name_info in let curr_class = ObjcInterface_decl.get_curr_class name oi_decl_info in ignore (ObjcInterface_decl.interface_declaration CTypes_decl.type_ptr_to_sil_type tenv dec); - process_methods tenv cg cfg curr_class decl_list + process_methods trans_unit_ctx tenv cg cfg curr_class decl_list | ObjCProtocolDecl(_, name_info, decl_list, _, _) -> let name = Ast_utils.get_qualified_name name_info in let curr_class = CContext.ContextProtocol name in ignore (ObjcProtocol_decl.protocol_decl CTypes_decl.type_ptr_to_sil_type tenv dec); - process_methods tenv cg cfg curr_class decl_list + process_methods trans_unit_ctx tenv cg cfg curr_class decl_list | ObjCCategoryDecl(_, name_info, decl_list, _, ocdi) -> let name = Ast_utils.get_qualified_name name_info in let curr_class = ObjcCategory_decl.get_curr_class_from_category_decl name ocdi in ignore (ObjcCategory_decl.category_decl CTypes_decl.type_ptr_to_sil_type tenv dec); - process_methods tenv cg cfg curr_class decl_list + process_methods trans_unit_ctx tenv cg cfg curr_class decl_list | ObjCCategoryImplDecl(_, name_info, decl_list, _, ocidi) -> let name = Ast_utils.get_qualified_name name_info in let curr_class = ObjcCategory_decl.get_curr_class_from_category_impl name ocidi in ignore (ObjcCategory_decl.category_impl_decl CTypes_decl.type_ptr_to_sil_type tenv dec); - process_methods tenv cg cfg curr_class decl_list; + process_methods trans_unit_ctx tenv cg cfg curr_class decl_list; | ObjCImplementationDecl(decl_info, _, decl_list, _, idi) -> let curr_class = ObjcInterface_decl.get_curr_class_impl idi in let class_name = CContext.get_curr_class_name curr_class in let type_ptr_to_sil_type = CTypes_decl.type_ptr_to_sil_type in ignore (ObjcInterface_decl.interface_impl_declaration type_ptr_to_sil_type tenv dec); - CMethod_trans.add_default_method_for_class class_name decl_info; - process_methods tenv cg cfg curr_class decl_list; + CMethod_trans.add_default_method_for_class trans_unit_ctx class_name decl_info; + process_methods trans_unit_ctx tenv cg cfg curr_class decl_list; | CXXMethodDecl (decl_info, _, _, _, _) | CXXConstructorDecl (decl_info, _, _, _, _) @@ -210,11 +217,12 @@ struct | Some (ClassTemplateSpecializationDecl _) -> let curr_class = CContext.ContextClsDeclPtr parent_ptr in if Config.cxx_experimental then - process_methods tenv cg cfg curr_class [dec] + process_methods trans_unit_ctx tenv cg cfg curr_class [dec] | Some dec -> Logging.out "Methods of %s skipped\n" (Ast_utils.string_of_decl dec) | None -> ()) | _ -> ()); + let translate = translate_one_declaration trans_unit_ctx tenv cg cfg decl_trans_context in match dec with (* Note that C and C++ records are treated the same way Skip translating implicit struct declarations, unless they have @@ -229,19 +237,19 @@ struct true | _ -> false in let method_decls, no_method_decls = IList.partition is_method_decl decl_list in - IList.iter (translate_one_declaration tenv cg cfg decl_trans_context) no_method_decls; + IList.iter translate no_method_decls; ignore (CTypes_decl.add_types_from_decl_to_tenv tenv dec); - IList.iter (translate_one_declaration tenv cg cfg decl_trans_context) method_decls + IList.iter translate method_decls | EnumDecl _ -> ignore (CEnum_decl.enum_decl dec) | LinkageSpecDecl (_, decl_list, _) -> - Logging.out_debug "ADDING: LinkageSpecDecl decl list\n"; - IList.iter (translate_one_declaration tenv cg cfg decl_trans_context) decl_list + Logging.out_debug "ADDING: LinkageSpecDecl decl list@\n"; + IList.iter translate decl_list | NamespaceDecl (_, _, decl_list, _, _) -> - IList.iter (translate_one_declaration tenv cg cfg decl_trans_context) decl_list + IList.iter translate decl_list | ClassTemplateDecl (_, _, template_decl_info) | FunctionTemplateDecl (_, _, template_decl_info) -> let decl_list = template_decl_info.Clang_ast_t.tdi_specializations in - IList.iter (translate_one_declaration tenv cg cfg decl_trans_context) decl_list + IList.iter translate decl_list | _ -> () end diff --git a/infer/src/clang/cFrontend_errors.ml b/infer/src/clang/cFrontend_errors.ml index 5e8aec10e..9892dacbf 100644 --- a/infer/src/clang/cFrontend_errors.ml +++ b/infer/src/clang/cFrontend_errors.ml @@ -81,17 +81,17 @@ let function_decl_checker_list = [ComponentKit.component_factory_function_advice let checker_for_function_decl decl checker context = checker context decl -let get_err_log method_decl_opt = +let get_err_log translation_unit_context method_decl_opt = let procname = match method_decl_opt with - | Some method_decl -> General_utils.procname_of_decl method_decl + | Some method_decl -> General_utils.procname_of_decl translation_unit_context method_decl | None -> Procname.Linters_dummy_method in LintIssues.get_err_log procname (* Add a frontend warning with a description desc at location loc to the errlog of a proc desc *) -let log_frontend_issue method_decl_opt key issue_desc = +let log_frontend_issue translation_unit_context method_decl_opt key issue_desc = let issue = issue_desc.CIssue.issue in let loc = issue_desc.CIssue.loc in - let errlog = get_err_log method_decl_opt in + let errlog = get_err_log translation_unit_context method_decl_opt in let err_desc = Errdesc.explain_frontend_warning issue_desc.CIssue.description issue_desc.CIssue.suggestion loc in let name = CIssue.to_string issue in @@ -116,7 +116,8 @@ let invoke_set_of_checkers f context key checkers = IList.iter (fun checker -> match f checker context with | Some issue_desc -> - log_frontend_issue context.CLintersContext.current_method key issue_desc + log_frontend_issue context.CLintersContext.translation_unit_context + context.CLintersContext.current_method key issue_desc | None -> ()) checkers let run_frontend_checkers_on_stmt context instr = diff --git a/infer/src/clang/cFrontend_utils.ml b/infer/src/clang/cFrontend_utils.ml index 27cac18f3..e838089a4 100644 --- a/infer/src/clang/cFrontend_utils.ml +++ b/infer/src/clang/cFrontend_utils.ml @@ -437,10 +437,15 @@ struct | Clang_ast_t.ObjCImplementationDecl (_, _, _, _, idi) -> Some idi | _ -> None - let is_in_main_file decl = + let is_in_main_file translation_unit_context decl = let decl_info = Clang_ast_proj.get_decl_tuple decl in let file_opt = (fst decl_info.Clang_ast_t.di_source_range).Clang_ast_t.sl_file in - opt_equal string_equal file_opt Config.source_file && Option.is_some file_opt + match file_opt with + | None -> false + | Some file -> + DB.source_file_equal + (CLocation.source_file_from_path file) + translation_unit_context.CFrontend_config.source_file let default_blacklist = let open CFrontend_config in @@ -632,11 +637,13 @@ struct | None -> file) | None -> "" - let is_cpp_translation = - Config.clang_lang = Config.CPP || Config.clang_lang = Config.OBJCPP + let is_cpp_translation translation_unit_context = + let lang = translation_unit_context.CFrontend_config.lang in + lang = Config.CPP || lang = Config.OBJCPP - let is_objc_extension = - Config.clang_lang = Config.OBJC || Config.clang_lang = Config.OBJCPP + let is_objc_extension translation_unit_context = + let lang = translation_unit_context.CFrontend_config.lang in + lang = Config.OBJC || lang = Config.OBJCPP let rec get_mangled_method_name function_decl_info method_decl_info = (* For virtual methods return mangled name of the method from most base class @@ -658,7 +665,7 @@ struct get_mangled_method_name fdi mdi | _ -> assert false) - let mk_procname_from_function name function_decl_info_opt = + let mk_procname_from_function translation_unit_context name function_decl_info_opt = let file = match function_decl_info_opt with | Some (decl_info, function_decl_info) -> @@ -673,7 +680,7 @@ struct | _ -> None in let mangled_name = match mangled_opt with - | Some m when is_cpp_translation -> m + | Some m when is_cpp_translation translation_unit_context -> m | _ -> "" in let mangled = (string_crc_hex32 file) ^ mangled_name in if String.length file == 0 && String.length mangled_name == 0 then @@ -700,13 +707,13 @@ struct let method_kind = Procname.objc_method_kind_of_bool is_instance in mk_procname_from_objc_method class_name method_name method_kind - let procname_of_decl meth_decl = + let procname_of_decl translation_unit_context meth_decl = let open Clang_ast_t in match meth_decl with | FunctionDecl (decl_info, name_info, _, fdi) -> let name = Ast_utils.get_qualified_name name_info in let function_info = Some (decl_info, fdi) in - mk_procname_from_function name function_info + mk_procname_from_function translation_unit_context name function_info | CXXMethodDecl (_, name_info, _, fdi, mdi) | CXXConstructorDecl (_, name_info, _, fdi, mdi) | CXXConversionDecl (_, name_info, _, fdi, mdi) diff --git a/infer/src/clang/cFrontend_utils.mli b/infer/src/clang/cFrontend_utils.mli index 0f66528f6..92bfeb245 100644 --- a/infer/src/clang/cFrontend_utils.mli +++ b/infer/src/clang/cFrontend_utils.mli @@ -158,7 +158,7 @@ sig (** Returns true if the declaration or statement is inside the main source file, as opposed to an imported header file. For statements, this refers to the parent decl. *) - val is_in_main_file : Clang_ast_t.decl -> bool + val is_in_main_file : CFrontend_config.translation_unit_context -> Clang_ast_t.decl -> bool (** Recursively go up the inheritance hierarchy of a given ObjCInterfaceDecl. Returns true if the passed in decl is an objc interface decl that's an @@ -224,8 +224,8 @@ sig val mk_procname_from_objc_method : string -> string -> Procname.objc_cpp_method_kind -> Procname.t - val mk_procname_from_function : string -> (Clang_ast_t.decl_info * Clang_ast_t.function_decl_info) - option -> Procname.t + val mk_procname_from_function : CFrontend_config.translation_unit_context -> string + -> (Clang_ast_t.decl_info * Clang_ast_t.function_decl_info) option -> Procname.t val get_mangled_method_name : Clang_ast_t.function_decl_info -> Clang_ast_t.cxx_method_decl_info -> string option @@ -233,7 +233,7 @@ sig val mk_procname_from_cpp_method : string -> string -> ?meth_decl:Clang_ast_t.decl -> string option -> Procname.t - val procname_of_decl : Clang_ast_t.decl -> Procname.t + val procname_of_decl : CFrontend_config.translation_unit_context -> Clang_ast_t.decl -> Procname.t val mk_class_field_name : Clang_ast_t.named_decl_info -> Ident.fieldname @@ -244,9 +244,9 @@ sig Pvar.t (** true if Config.clang_lang is C++ or ObjC++ *) - val is_cpp_translation : bool + val is_cpp_translation : CFrontend_config.translation_unit_context -> bool (** true if Config.clang_lang is ObjC or ObjC++ *) - val is_objc_extension : bool + val is_objc_extension : CFrontend_config.translation_unit_context -> bool end diff --git a/infer/src/clang/cLocation.ml b/infer/src/clang/cLocation.ml index 0dce13780..f74c7b2a7 100644 --- a/infer/src/clang/cLocation.ml +++ b/infer/src/clang/cLocation.ml @@ -11,9 +11,8 @@ open! Utils (** Module for function to retrieve the location (file, line, etc) of instructions *) -(* Inside the json there may be code or type definitions from other files *) -(* than the one passed as an argument. That current file in the translation is saved*) -(* in this variable. *) +(** Inside the AST there may be code or type definitions from other files than the one passed as an + argument. That current file in the translation is saved in this variable. *) let curr_file = ref DB.source_file_empty let source_file_from_path path = @@ -36,20 +35,21 @@ let choose_sloc sloc1 sloc2 = | Some f when not (DB.source_file_equal (source_file_from_path f) !curr_file) -> sloc2 | _ -> sloc1 -let choose_sloc_to_update_curr_file sloc1 sloc2 = +let choose_sloc_to_update_curr_file trans_unit_ctx sloc1 sloc2 = match sloc2.Clang_ast_t.sl_file with - | Some f when DB.source_file_equal (source_file_from_path f) !CFrontend_config.current_source -> + | Some f when DB.source_file_equal (source_file_from_path f) + trans_unit_ctx.CFrontend_config.source_file -> sloc2 | _ -> sloc1 -let update_curr_file di = +let update_curr_file trans_unit_ctx di = let loc_start, loc_end = di.Clang_ast_t.di_source_range in - let loc = choose_sloc_to_update_curr_file loc_start loc_end in + let loc = choose_sloc_to_update_curr_file trans_unit_ctx loc_start loc_end in match loc.Clang_ast_t.sl_file with | Some f -> curr_file := source_file_from_path f | None -> () -let clang_to_sil_location clang_loc procdesc_opt = +let clang_to_sil_location trans_unit_ctx clang_loc procdesc_opt = let line = match clang_loc.Clang_ast_t.sl_line with | Some l -> l | None -> -1 in @@ -68,7 +68,7 @@ let clang_to_sil_location clang_loc procdesc_opt = | Some f -> let file_db = source_file_from_path f in let nloc = - if (DB.source_file_equal file_db !CFrontend_config.current_source) then + if (DB.source_file_equal file_db trans_unit_ctx.CFrontend_config.source_file) then !Config.nLOC else -1 in file_db, nloc @@ -87,22 +87,20 @@ let file_in_project file = file_in_project && not (file_should_be_skipped) | None -> false -let should_do_frontend_check (loc_start, _) = +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) !CFrontend_config.current_source in + let equal_current_source file = DB.source_file_equal (source_file_from_path file) + trans_unit_ctx.CFrontend_config.source_file in equal_current_source file || (file_in_project file && not Config.testing_mode) | None -> false -(* We translate by default the instructions in the current file.*) -(* In C++ development, we also translate the headers that are part *) -(* of the project. However, in testing mode, we don't want to translate *) -(* the headers because the dot files in the frontend tests should contain nothing *) -(* else than the source file to avoid conflicts between different versions of the *) -(* libraries in the CI *) -let should_translate (loc_start, loc_end) decl_trans_context ~translate_when_used = +(** We translate by default the instructions in the current file. In C++ development, we also + translate the headers that are part of the project. However, in testing mode, we don't want to + translate the headers because the dot files in the frontend tests should contain nothing else + than the source file to avoid conflicts between different versions of the libraries. *) +let should_translate trans_unit_ctx (loc_start, loc_end) decl_trans_context ~translate_when_used = let map_path_of pred loc = match loc.Clang_ast_t.sl_file with | Some f -> pred f @@ -112,8 +110,7 @@ let should_translate (loc_start, loc_end) decl_trans_context ~translate_when_use let path_pred path = pred (source_file_from_path path) in map_path_of path_pred loc in - let equal_current_source file = - DB.source_file_equal file !CFrontend_config.current_source + let equal_current_source = DB.source_file_equal trans_unit_ctx.CFrontend_config.source_file in let file_in_project = map_path_of file_in_project loc_end || map_path_of file_in_project loc_start in @@ -127,9 +124,9 @@ let should_translate (loc_start, loc_end) decl_trans_context ~translate_when_use || (Config.cxx_experimental && decl_trans_context = `Translation && translate_on_demand && not Config.testing_mode) -let should_translate_lib source_range decl_trans_context ~translate_when_used = +let should_translate_lib trans_unit_ctx source_range decl_trans_context ~translate_when_used = not Config.no_translate_libs - || should_translate source_range decl_trans_context ~translate_when_used + || should_translate trans_unit_ctx source_range decl_trans_context ~translate_when_used let is_file_blacklisted file = let paths = Config.skip_clang_analysis_in_path in @@ -139,15 +136,16 @@ let is_file_blacklisted file = paths in is_file_blacklisted -let get_sil_location_from_range source_range prefer_first = +let get_sil_location_from_range trans_unit_ctx source_range prefer_first = let sloc1, sloc2 = source_range in let sloc = if not prefer_first then sloc2 else choose_sloc sloc1 sloc2 in - clang_to_sil_location sloc None + clang_to_sil_location trans_unit_ctx sloc None let get_sil_location stmt_info context = let sloc1, sloc2 = stmt_info.Clang_ast_t.si_source_range in let sloc = choose_sloc sloc1 sloc2 in - clang_to_sil_location sloc (Some (CContext.get_procdesc context)) + clang_to_sil_location context.CContext.translation_unit_context sloc + (Some (CContext.get_procdesc context)) let check_source_file source_file = if is_file_blacklisted source_file then diff --git a/infer/src/clang/cLocation.mli b/infer/src/clang/cLocation.mli index 899fb5845..a7195efff 100644 --- a/infer/src/clang/cLocation.mli +++ b/infer/src/clang/cLocation.mli @@ -11,25 +11,27 @@ open! Utils (** Module for function to retrieve the location (file, line, etc) of instructions *) -(* Inside the json there may be code or type definitions from other files *) -(* than the one passed as an argument. That current file in the translation is saved*) -(* in this variable. *) +(** Inside the AST there may be code or type definitions from other files than the one passed as an + argument. That current file in the translation is saved in this variable. *) val curr_file : DB.source_file ref -val clang_to_sil_location : Clang_ast_t.source_location -> Cfg.Procdesc.t option -> +val clang_to_sil_location : CFrontend_config.translation_unit_context -> + Clang_ast_t.source_location -> Cfg.Procdesc.t option -> Location.t val get_sil_location : Clang_ast_t.stmt_info -> CContext.t -> Location.t -val should_translate_lib : Clang_ast_t.source_range -> CModule_type.decl_trans_context -> - translate_when_used:bool -> bool +val should_translate_lib : CFrontend_config.translation_unit_context -> Clang_ast_t.source_range -> + CModule_type.decl_trans_context -> translate_when_used:bool -> bool -val should_do_frontend_check : Clang_ast_t.source_range -> bool +val should_do_frontend_check : CFrontend_config.translation_unit_context -> + Clang_ast_t.source_range -> bool -val update_curr_file : Clang_ast_t.decl_info -> unit +val update_curr_file : CFrontend_config.translation_unit_context -> Clang_ast_t.decl_info -> unit val check_source_file : string -> unit val source_file_from_path : string -> DB.source_file -val get_sil_location_from_range : Clang_ast_t.source_range -> bool -> Location.t +val get_sil_location_from_range : CFrontend_config.translation_unit_context -> + Clang_ast_t.source_range -> bool -> Location.t diff --git a/infer/src/clang/cMain.ml b/infer/src/clang/cMain.ml index 216dd3dbd..518a750af 100644 --- a/infer/src/clang/cMain.ml +++ b/infer/src/clang/cMain.ml @@ -37,17 +37,15 @@ let register_perf_stats_report source_file = let stats_dir = Filename.concat Config.results_dir Config.frontend_stats_dir_name in let abbrev_source_file = DB.source_file_encoding source_file in let stats_file = Config.perf_stats_prefix ^ "_" ^ abbrev_source_file ^ ".json" in - DB.create_dir Config.results_dir ; - DB.create_dir stats_dir ; + create_dir Config.results_dir ; + create_dir stats_dir ; PerfStats.register_report_at_exit (Filename.concat stats_dir stats_file) let init_global_state_for_capture_and_linters source_file = register_perf_stats_report source_file; - Config.curr_language := Config.Clang; - CFrontend_config.current_source := source_file; DB.Results_dir.init source_file -let do_run source_path ast_path = +let do_run source_file ast_path = let init_time = Unix.gettimeofday () in let print_elapsed () = let elapsed = Unix.gettimeofday () -. init_time in @@ -58,8 +56,7 @@ let do_run source_path ast_path = | Some path -> path, validate_decl_from_file path | None -> - "stdin of " ^ source_path, validate_decl_from_stdin () in - + "stdin of " ^ DB.source_file_to_string source_file, validate_decl_from_stdin () in let decl_index, stmt_index, type_index, ivar_to_property_index = Clang_ast_main.index_node_pointers ast_decl in CFrontend_config.pointer_decl_index := decl_index; @@ -67,16 +64,15 @@ let do_run source_path ast_path = CFrontend_config.pointer_type_index := type_index; CFrontend_config.ivar_to_property_index := ivar_to_property_index; CFrontend_config.json := ast_filename; - CLocation.check_source_file source_path; - let source_file = CLocation.source_file_from_path source_path in Logging.out "Clang frontend action is %s\n" Config.clang_frontend_action_string; Logging.out "Start %s of AST from %s\n" Config.clang_frontend_action_string !CFrontend_config.json; init_global_state_for_capture_and_linters source_file; + let translation_unit_context = CFrontend_config.{source_file; lang=Config.clang_lang} in if Config.clang_frontend_do_lint then - CFrontend_checkers_main.do_frontend_checks source_file ast_decl; + CFrontend_checkers_main.do_frontend_checks translation_unit_context ast_decl; if Config.clang_frontend_do_capture then - CFrontend.do_source_file source_file ast_decl; + CFrontend.do_source_file translation_unit_context ast_decl; Logging.out "End translation AST file %s... OK!@\n" !CFrontend_config.json; print_elapsed (); with @@ -86,9 +82,13 @@ let do_run source_path ast_path = raise exc let () = - match Config.source_file with - | Some path -> - do_run path Config.ast_file - | None -> - Logging.err_debug "Incorrect command line arguments\n"; - Config.print_usage_exit () + let source_file = + (match Config.source_file with + | Some path -> + Logging.set_log_file_identifier (Some (Filename.basename path)); + CLocation.check_source_file path; + CLocation.source_file_from_path path + | None -> + Logging.err_debug "Incorrect command line arguments\n"; + Config.print_usage_exit ()) in + do_run source_file Config.ast_file diff --git a/infer/src/clang/cMain.mli b/infer/src/clang/cMain.mli index 0160ff0c5..56af51a4f 100644 --- a/infer/src/clang/cMain.mli +++ b/infer/src/clang/cMain.mli @@ -9,10 +9,8 @@ open! Utils -(** Main module of InferClang. Take as input AST files produced by clang during compilation *) -(** and their corresponding C/C++/ObjectiveC source files. *) -(** Parse the arguments, parse and validate the input AST into a data structure *) -(** and translates it into a cfg. *) +(** Main module of InferClang. Take as input AST files produced by clang during compilation and + their corresponding C/C++/ObjectiveC source files. - -val do_run : string -> string option -> unit + Parse the arguments, parse and validate the input AST into a data structure and translates it + into a cfg. *) diff --git a/infer/src/clang/cMethod_trans.ml b/infer/src/clang/cMethod_trans.ml index 55dff27fb..87ebc9c5d 100644 --- a/infer/src/clang/cMethod_trans.ml +++ b/infer/src/clang/cMethod_trans.ml @@ -89,9 +89,9 @@ let get_param_decls function_method_decl_info = | ObjC_Meth_decl_info (method_decl_info, _) -> method_decl_info.Clang_ast_t.omdi_parameters | Block_decl_info (block_decl_info, _, _) -> block_decl_info.Clang_ast_t.bdi_parameters -let get_language function_method_decl_info = +let get_language trans_unit_ctx function_method_decl_info = match function_method_decl_info with - | Func_decl_info (_, _) -> Config.clang_lang + | Func_decl_info (_, _) -> trans_unit_ctx.CFrontend_config.lang | Cpp_Meth_decl_info _ -> Config.CPP | ObjC_Meth_decl_info _ -> Config.OBJC | Block_decl_info _ -> Config.OBJC @@ -105,7 +105,7 @@ let is_cpp_virtual function_method_decl_info = 1. self/this parameter (optional, only for methods) 2. normal parameters 3. return parameter (optional) *) -let get_parameters tenv function_method_decl_info = +let get_parameters trans_unit_ctx tenv function_method_decl_info = let par_to_ms_par par = match par with | Clang_ast_t.ParmVarDecl (_, name_info, qt, var_decl_info) -> @@ -113,7 +113,7 @@ let get_parameters tenv function_method_decl_info = let param_typ = CTypes_decl.type_ptr_to_sil_type tenv qt.Clang_ast_t.qt_type_ptr in let qt_type_ptr = match param_typ with - | Typ.Tstruct _ when General_utils.is_cpp_translation -> + | Typ.Tstruct _ when General_utils.is_cpp_translation trans_unit_ctx -> Ast_expressions.create_reference_type qt.Clang_ast_t.qt_type_ptr | _ -> qt.Clang_ast_t.qt_type_ptr in (mangled, {qt with qt_type_ptr}) @@ -130,14 +130,14 @@ let get_return_val_and_param_types tenv function_method_decl_info = Ast_expressions.create_void_type, Some (Typ.Tptr (return_typ, Typ.Pk_pointer)) else return_type_ptr, None -let build_method_signature tenv decl_info procname function_method_decl_info +let build_method_signature trans_unit_ctx tenv decl_info procname function_method_decl_info parent_pointer pointer_to_property_opt = let source_range = decl_info.Clang_ast_t.di_source_range in let tp, return_param_type_opt = get_return_val_and_param_types tenv function_method_decl_info in let is_instance_method = is_instance_method function_method_decl_info in - let parameters = get_parameters tenv function_method_decl_info in + let parameters = get_parameters trans_unit_ctx tenv function_method_decl_info in let attributes = decl_info.Clang_ast_t.di_attributes in - let lang = get_language function_method_decl_info in + let lang = get_language trans_unit_ctx function_method_decl_info in let is_cpp_virtual = is_cpp_virtual function_method_decl_info in CMethod_signature.make_ms procname parameters tp attributes source_range is_instance_method ~is_cpp_virtual:is_cpp_virtual @@ -157,29 +157,30 @@ let get_init_list_instrs method_decl_info = let create_custom_instr construct_instr = `CXXConstructorInit construct_instr in IList.map create_custom_instr method_decl_info.Clang_ast_t.xmdi_cxx_ctor_initializers -let method_signature_of_decl tenv meth_decl block_data_opt = +let method_signature_of_decl trans_unit_ctx tenv meth_decl block_data_opt = let open Clang_ast_t in match meth_decl, block_data_opt with | FunctionDecl (decl_info, _, qt, fdi), _ -> let func_decl = Func_decl_info (fdi, qt.Clang_ast_t.qt_type_ptr) in - let procname = General_utils.procname_of_decl meth_decl in - let ms = build_method_signature tenv decl_info procname func_decl None None in + let procname = General_utils.procname_of_decl trans_unit_ctx meth_decl in + let ms = build_method_signature trans_unit_ctx tenv decl_info procname func_decl None None in let extra_instrs = get_assume_not_null_calls fdi.Clang_ast_t.fdi_parameters in ms, fdi.Clang_ast_t.fdi_body, extra_instrs | CXXMethodDecl (decl_info, _, qt, fdi, mdi), _ | CXXConstructorDecl (decl_info, _, qt, fdi, mdi), _ | CXXConversionDecl (decl_info, _, qt, fdi, mdi), _ | CXXDestructorDecl (decl_info, _, qt, fdi, mdi), _ -> - let procname = General_utils.procname_of_decl meth_decl in + let procname = General_utils.procname_of_decl trans_unit_ctx meth_decl in let parent_ptr = Option.get decl_info.di_parent_pointer in let method_decl = Cpp_Meth_decl_info (fdi, mdi, parent_ptr, qt.Clang_ast_t.qt_type_ptr) in let parent_pointer = decl_info.Clang_ast_t.di_parent_pointer in - let ms = build_method_signature tenv decl_info procname method_decl parent_pointer None in + let ms = build_method_signature + trans_unit_ctx tenv decl_info procname method_decl parent_pointer None in let non_null_instrs = get_assume_not_null_calls fdi.Clang_ast_t.fdi_parameters in let init_list_instrs = get_init_list_instrs mdi in (* it will be empty for methods *) ms, fdi.Clang_ast_t.fdi_body, (init_list_instrs @ non_null_instrs) | ObjCMethodDecl (decl_info, _, mdi), _ -> - let procname = General_utils.procname_of_decl meth_decl in + let procname = General_utils.procname_of_decl trans_unit_ctx meth_decl in let parent_ptr = Option.get decl_info.di_parent_pointer in let method_decl = ObjC_Meth_decl_info (mdi, parent_ptr) in let parent_pointer = decl_info.Clang_ast_t.di_parent_pointer in @@ -187,22 +188,22 @@ let method_signature_of_decl tenv meth_decl block_data_opt = match mdi.Clang_ast_t.omdi_property_decl with | Some decl_ref -> Some decl_ref.Clang_ast_t.dr_decl_pointer | None -> None in - let ms = build_method_signature tenv decl_info procname method_decl + let ms = build_method_signature trans_unit_ctx tenv decl_info procname method_decl parent_pointer pointer_to_property_opt in let extra_instrs = get_assume_not_null_calls mdi.omdi_parameters in ms, mdi.omdi_body, extra_instrs | BlockDecl (decl_info, bdi), Some (outer_context, tp, procname, _) -> let func_decl = Block_decl_info (bdi, tp, outer_context) in - let ms = build_method_signature tenv decl_info procname func_decl None None in + let ms = build_method_signature trans_unit_ctx tenv decl_info procname func_decl None None in let extra_instrs = get_assume_not_null_calls bdi.bdi_parameters in ms, bdi.bdi_body, extra_instrs | _ -> raise Invalid_declaration -let method_signature_of_pointer tenv pointer = +let method_signature_of_pointer trans_unit_ctx tenv pointer = try match Ast_utils.get_decl pointer with | Some meth_decl -> - let ms, _, _ = method_signature_of_decl tenv meth_decl None in + let ms, _, _ = method_signature_of_decl trans_unit_ctx tenv meth_decl None in Some ms | None -> None with Invalid_declaration -> None @@ -247,10 +248,10 @@ let get_superclass_curr_class_objc context = | CContext.ContextProtocol _ -> assert false (* Gets the class name from a method signature found by clang, if search is successful *) -let get_class_name_method_call_from_clang tenv obj_c_message_expr_info = +let get_class_name_method_call_from_clang trans_unit_ctx tenv obj_c_message_expr_info = match obj_c_message_expr_info.Clang_ast_t.omei_decl_pointer with | Some pointer -> - (match method_signature_of_pointer tenv pointer with + (match method_signature_of_pointer trans_unit_ctx tenv pointer with | Some ms -> begin match CMethod_signature.ms_get_name ms with @@ -377,7 +378,7 @@ let get_const_args_indices ~shift args = aux [] args (** Creates a procedure description. *) -let create_local_procdesc cfg tenv ms fbody captured is_objc_inst_method = +let create_local_procdesc trans_unit_ctx cfg tenv ms fbody captured is_objc_inst_method = let defined = not ((IList.length fbody) == 0) in let proc_name = CMethod_signature.ms_get_name ms in let pname = Procname.to_string proc_name in @@ -397,8 +398,8 @@ let create_local_procdesc cfg tenv ms fbody captured is_objc_inst_method = let source_range = CMethod_signature.ms_get_loc ms in Logging.out_debug "\nCreating a new procdesc for function: '%s'\n@." pname; Logging.out_debug "\nms = %s\n@." (CMethod_signature.ms_to_string ms); - let loc_start = CLocation.get_sil_location_from_range source_range true in - let loc_exit = CLocation.get_sil_location_from_range source_range false in + let loc_start = CLocation.get_sil_location_from_range trans_unit_ctx source_range true in + let loc_exit = CLocation.get_sil_location_from_range trans_unit_ctx source_range false in let ret_type = get_return_type tenv ms in if skip_property_accessor ms then () else @@ -452,9 +453,10 @@ let create_external_procdesc cfg proc_name is_objc_inst_method type_opt = let create_procdesc_with_pointer context pointer class_name_opt name = let open CContext in - match method_signature_of_pointer context.tenv pointer with + match method_signature_of_pointer context.translation_unit_context context.tenv pointer with | Some callee_ms -> - ignore (create_local_procdesc context.cfg context.tenv callee_ms [] [] false); + ignore (create_local_procdesc context.translation_unit_context context.cfg context.tenv + callee_ms [] [] false); CMethod_signature.ms_get_name callee_ms | None -> let callee_name = @@ -462,12 +464,13 @@ let create_procdesc_with_pointer context pointer class_name_opt name = | Some class_name -> General_utils.mk_procname_from_cpp_method class_name name None | None -> - General_utils.mk_procname_from_function name None in + General_utils.mk_procname_from_function context.translation_unit_context name None in create_external_procdesc context.cfg callee_name false None; callee_name -let add_default_method_for_class class_name decl_info = - let loc = CLocation.get_sil_location_from_range decl_info.Clang_ast_t.di_source_range true in +let add_default_method_for_class trans_unit_ctx class_name decl_info = + let loc = CLocation.get_sil_location_from_range trans_unit_ctx + decl_info.Clang_ast_t.di_source_range true in let proc_name = Procname.get_default_objc_class_method class_name in let attrs = { (ProcAttributes.default proc_name Config.Clang) with loc = loc; } in AttributesTable.store_attributes attrs diff --git a/infer/src/clang/cMethod_trans.mli b/infer/src/clang/cMethod_trans.mli index d504401f6..1be28295a 100644 --- a/infer/src/clang/cMethod_trans.mli +++ b/infer/src/clang/cMethod_trans.mli @@ -23,8 +23,9 @@ type method_call_type = val should_add_return_param : Typ.t -> is_objc_method:bool -> bool -val create_local_procdesc : Cfg.cfg -> Tenv.t -> CMethod_signature.method_signature -> - Clang_ast_t.stmt list -> (Pvar.t * Typ.t) list -> bool -> bool +val create_local_procdesc : CFrontend_config.translation_unit_context -> Cfg.cfg -> Tenv.t -> + CMethod_signature.method_signature -> Clang_ast_t.stmt list -> (Pvar.t * Typ.t) list -> bool -> + bool val create_external_procdesc : Cfg.cfg -> Procname.t -> bool -> (Typ.t * Typ.t list) option -> unit @@ -34,21 +35,23 @@ val get_objc_method_data : Clang_ast_t.obj_c_message_expr_info -> val get_class_name_method_call_from_receiver_kind : CContext.t -> Clang_ast_t.obj_c_message_expr_info -> (Exp.t * Typ.t) list -> string -val get_class_name_method_call_from_clang : Tenv.t -> Clang_ast_t.obj_c_message_expr_info -> - string option +val get_class_name_method_call_from_clang : CFrontend_config.translation_unit_context -> Tenv.t -> + Clang_ast_t.obj_c_message_expr_info -> string option -val method_signature_of_decl : Tenv.t -> Clang_ast_t.decl -> CModule_type.block_data option -> +val method_signature_of_decl : CFrontend_config.translation_unit_context -> Tenv.t -> + Clang_ast_t.decl -> CModule_type.block_data option -> CMethod_signature.method_signature * Clang_ast_t.stmt option * CModule_type.instr_type list -val method_signature_of_pointer : Tenv.t -> Clang_ast_t.pointer -> - CMethod_signature.method_signature option +val method_signature_of_pointer : CFrontend_config.translation_unit_context -> Tenv.t -> + Clang_ast_t.pointer -> CMethod_signature.method_signature option val get_method_name_from_clang : Tenv.t -> CMethod_signature.method_signature option -> CMethod_signature.method_signature option -val create_procdesc_with_pointer : CContext.t -> Clang_ast_t.pointer -> string option -> - string -> Procname.t +val create_procdesc_with_pointer : CContext.t -> Clang_ast_t.pointer -> string option -> string -> + Procname.t -val add_default_method_for_class : string -> Clang_ast_t.decl_info -> unit +val add_default_method_for_class : CFrontend_config.translation_unit_context -> string -> + Clang_ast_t.decl_info -> unit val get_procname_from_cpp_lambda : CContext.t -> Clang_ast_t.decl -> Procname.t diff --git a/infer/src/clang/cModule_type.ml b/infer/src/clang/cModule_type.ml index e0ce86fac..68c75810a 100644 --- a/infer/src/clang/cModule_type.ml +++ b/infer/src/clang/cModule_type.ml @@ -30,9 +30,9 @@ sig end module type CFrontend = sig - val function_decl : Tenv.t -> Cfg.cfg -> Cg.t -> Clang_ast_t.decl -> - block_data option -> unit + val function_decl : CFrontend_config.translation_unit_context -> Tenv.t -> Cfg.cfg -> Cg.t -> + Clang_ast_t.decl -> block_data option -> unit - val translate_one_declaration : Tenv.t -> Cg.t -> Cfg.cfg -> - decl_trans_context -> Clang_ast_t.decl -> unit + val translate_one_declaration : CFrontend_config.translation_unit_context -> Tenv.t -> Cg.t -> + Cfg.cfg -> decl_trans_context -> Clang_ast_t.decl -> unit end diff --git a/infer/src/clang/cTL.ml b/infer/src/clang/cTL.ml index 5f8ec59e4..3069869fb 100644 --- a/infer/src/clang/cTL.ml +++ b/infer/src/clang/cTL.ml @@ -100,7 +100,7 @@ let eval_Atomic pred_name params an lcxt = match pred_name, params, an with | "call_method", [p1], Stmt st -> Predicates.call_method p1 st | "property_name_contains_word", [p1] , Decl d -> Predicates.property_name_contains_word d p1 - | "is_objc_extension", [], _ -> Predicates.is_objc_extension + | "is_objc_extension", [], _ -> Predicates.is_objc_extension lcxt | "is_global_var", [], Decl d -> Predicates.is_syntactically_global_var d | "is_const_var", [], Decl d -> Predicates.is_const_expr_var d | "call_function_named", _, Stmt st -> Predicates.call_function_named st params diff --git a/infer/src/clang/cTrans.ml b/infer/src/clang/cTrans.ml index 7d6eb2367..6e454bcde 100644 --- a/infer/src/clang/cTrans.ml +++ b/infer/src/clang/cTrans.ml @@ -32,7 +32,9 @@ struct let method_kind = Procname.objc_method_kind_of_bool is_instance in let ms_opt = match method_pointer_opt with - | Some pointer -> CMethod_trans.method_signature_of_pointer context.tenv pointer + | Some pointer -> + CMethod_trans.method_signature_of_pointer context.translation_unit_context context.tenv + pointer | None -> None in let proc_name = match CMethod_trans.get_method_name_from_clang context.tenv ms_opt with @@ -51,10 +53,12 @@ struct None in match predefined_ms_opt, ms_opt with | Some ms, _ -> - ignore (CMethod_trans.create_local_procdesc context.cfg context.tenv ms [] [] is_instance); + ignore (CMethod_trans.create_local_procdesc context.translation_unit_context context.cfg + context.tenv ms [] [] is_instance); CMethod_signature.ms_get_name ms, CMethod_trans.MCNoVirtual | None, Some ms -> - ignore (CMethod_trans.create_local_procdesc context.cfg context.tenv ms [] [] is_instance); + ignore (CMethod_trans.create_local_procdesc context.translation_unit_context context.cfg + context.tenv ms [] [] is_instance); if CMethod_signature.ms_is_getter ms || CMethod_signature.ms_is_setter ms then proc_name, CMethod_trans.MCNoVirtual else @@ -235,7 +239,8 @@ struct let open CContext in (* translation will reset Ident counter, save it's state and restore it afterwards *) let ident_state = Ident.NameGenerator.get_current () in - F.translate_one_declaration context.tenv context.cg context.cfg `Translation decl; + F.translate_one_declaration context.translation_unit_context context.tenv context.cg context.cfg + `Translation decl; Ident.NameGenerator.set_current ident_state let mk_temp_sil_var procdesc var_name_suffix = @@ -419,7 +424,7 @@ struct let root_node' = GotoLabel.find_goto_label trans_state.context label_name sil_loc in { empty_res_trans with root_nodes = [root_node']; leaf_nodes = trans_state.succ_nodes } - let get_builtin_pname_opt name decl_opt type_ptr = + let get_builtin_pname_opt trans_unit_ctx name decl_opt type_ptr = let get_deprecated_attr_arg decl = let open Clang_ast_t in let decl_info = Clang_ast_proj.get_decl_tuple decl in @@ -444,7 +449,7 @@ struct | _ when CTrans_models.is_retain_builtin name type_ptr -> Some ModelBuiltins.__objc_retain_cf | _ when name = CFrontend_config.malloc && - General_utils.is_objc_extension -> + General_utils.is_objc_extension trans_unit_ctx -> Some ModelBuiltins.malloc_no_fail | _ -> None @@ -457,7 +462,8 @@ struct Option.may (call_translation context) decl_opt; let name = Ast_utils.get_qualified_name name_info in let typ = CTypes_decl.type_ptr_to_sil_type context.tenv type_ptr in - let pname = match get_builtin_pname_opt name decl_opt type_ptr with + let pname = + match get_builtin_pname_opt context.translation_unit_context name decl_opt type_ptr with | Some builtin_pname -> builtin_pname | None -> CMethod_trans.create_procdesc_with_pointer context decl_ptr None name in { empty_res_trans with exps = [(Exp.Const (Const.Cfun pname), typ)] } @@ -510,7 +516,8 @@ struct let class_name = Ast_utils.get_class_name_from_member name_info in Logging.out_debug "!!!!! Dealing with method '%s' @." method_name; let method_typ = CTypes_decl.type_ptr_to_sil_type context.tenv type_ptr in - let ms_opt = CMethod_trans.method_signature_of_pointer context.tenv decl_ptr in + let ms_opt = CMethod_trans.method_signature_of_pointer + context.translation_unit_context context.tenv decl_ptr in let is_instance_method = match ms_opt with | Some ms -> CMethod_signature.ms_is_instance ms | _ -> true (* might happen for methods that are not exported yet (some templates). *) in @@ -542,7 +549,9 @@ struct (* use qualified method name for builtin matching, but use unqualified name elsewhere *) let qual_method_name = Ast_utils.get_qualified_name name_info in - let pname = match get_builtin_pname_opt qual_method_name decl_opt type_ptr with + let pname = + match get_builtin_pname_opt context.translation_unit_context qual_method_name decl_opt + type_ptr with | Some builtin_pname -> builtin_pname | None -> CMethod_trans.create_procdesc_with_pointer context decl_ptr (Some class_name) @@ -562,7 +571,8 @@ struct cxx_record_info.xrdi_destructor | _ -> None in match destruct_decl_ref_opt with - | Some decl_ref -> method_deref_trans trans_state pvar_trans_result decl_ref si `CXXDestructor + | Some decl_ref -> + method_deref_trans trans_state pvar_trans_result decl_ref si `CXXDestructor | None -> empty_res_trans let this_expr_trans trans_state sil_loc class_type_ptr = @@ -599,7 +609,7 @@ struct let typ = match ast_typ with | Tstruct _ when decl_ref.dr_kind = `ParmVar -> - if General_utils.is_cpp_translation then + if General_utils.is_cpp_translation context.translation_unit_context then Typ.Tptr (ast_typ, Pk_reference) else ast_typ | _ -> ast_typ in @@ -617,7 +627,8 @@ struct match Ast_utils.get_decl decl_ref.dr_decl_pointer with | Some VarDecl (_, _, qual_type, vdi) -> ( match ast_typ with - | Tstruct _ when not General_utils.is_cpp_translation -> + | Tstruct _ + when not (General_utils.is_cpp_translation context.translation_unit_context) -> (* Do not convert a global struct to a local because SIL values do not include structs, they must all be heap-allocated *) false, None @@ -649,7 +660,8 @@ struct match decl_kind with | `EnumConstant -> enum_constant_trans trans_state decl_ref | `Function -> function_deref_trans trans_state decl_ref - | `Var | `ImplicitParam | `ParmVar -> var_deref_trans trans_state stmt_info decl_ref + | `Var | `ImplicitParam | `ParmVar -> + var_deref_trans trans_state stmt_info decl_ref | `Field | `ObjCIvar -> field_deref_trans trans_state stmt_info pre_trans_result decl_ref ~is_constructor_init | `CXXMethod | `CXXConversion | `CXXConstructor | `CXXDestructor -> @@ -790,7 +802,7 @@ struct if (is_binary_assign_op binary_operator_info) (* assignment operator result is lvalue in CPP, rvalue in C, *) (* hence the difference *) - && (not General_utils.is_cpp_translation) + && (not (General_utils.is_cpp_translation context.translation_unit_context)) && ((not creating_node) || (is_return_temp trans_state.continuation)) then ( (* We are in this case when an assignment is inside *) (* another operator that creates a node. Eg. another *) @@ -1005,7 +1017,7 @@ struct | `Class type_ptr -> let class_opt = CMethod_trans.get_class_name_method_call_from_clang - context.CContext.tenv obj_c_message_expr_info in + context.translation_unit_context context.CContext.tenv obj_c_message_expr_info in Some (new_or_alloc_trans trans_state_pri sil_loc si type_ptr class_opt selector) | _ -> None (* assertions *) @@ -1850,7 +1862,8 @@ struct CTypes_decl.type_ptr_to_sil_type context.CContext.tenv expr_info.Clang_ast_t.ei_type_ptr in let exp_op, instr_op = - CArithmetic_trans.unary_operation_instruction unary_operator_info sil_e' ret_typ sil_loc in + CArithmetic_trans.unary_operation_instruction + context.translation_unit_context unary_operator_info sil_e' ret_typ sil_loc in let unary_op_res_trans = { empty_res_trans with instrs = instr_op } in let all_res_trans = [ res_trans_stmt; unary_op_res_trans ] in let nname = "UnaryOperator" in @@ -2004,7 +2017,8 @@ struct let procname = Cfg.Procdesc.get_proc_name context.CContext.procdesc in let loc = (match stmt_info.Clang_ast_t.si_source_range with (l1, _) -> - CLocation.clang_to_sil_location l1 (Some context.CContext.procdesc)) in + CLocation.clang_to_sil_location context.CContext.translation_unit_context l1 + (Some context.CContext.procdesc)) in (* Given a captured var, return the instruction to assign it to a temp *) let assign_captured_var (cvar, typ) = let id = Ident.create_fresh Ident.knormal in @@ -2024,7 +2038,8 @@ struct let ids_instrs = IList.map assign_captured_var captureds in let ids, instrs = IList.split ids_instrs in let block_data = (context, type_ptr, block_pname, captureds) in - F.function_decl context.tenv context.cfg context.cg decl (Some block_data); + F.function_decl context.translation_unit_context context.tenv context.cfg context.cg decl + (Some block_data); let captured_vars = IList.map2 (fun id (pvar, typ) -> (Exp.Var id, pvar, typ)) ids captureds in let closure = Exp.Closure { name=block_pname; captured_vars } in @@ -2622,13 +2637,14 @@ struct (Ast_utils.string_of_stmt s); assert false) - (* Function similar to instruction function, but it takes C++ constructor initializer as *) - (* an input parameter. *) + (* Function similar to instruction function, but it takes C++ constructor initializer as + an input parameter. *) and cxx_constructor_init_trans ctor_init trans_state = - (*let tenv = trans_state.context.CContext.tenv in*) - let class_ptr = CContext.get_curr_class_decl_ptr trans_state.context.CContext.curr_class in + let context = trans_state.context in + let class_ptr = CContext.get_curr_class_decl_ptr context.CContext.curr_class in let source_range = ctor_init.Clang_ast_t.xci_source_range in - let sil_loc = CLocation.get_sil_location_from_range source_range true in + let sil_loc = CLocation.get_sil_location_from_range context.CContext.translation_unit_context + source_range true in (* its pointer will be used in PriorityNode *) let this_stmt_info = Ast_expressions.dummy_stmt_info () in (* this will be used to avoid creating node in init_expr_trans *) diff --git a/infer/src/clang/predicates.ml b/infer/src/clang/predicates.ml index b68b8f7fb..b9a312404 100644 --- a/infer/src/clang/predicates.ml +++ b/infer/src/clang/predicates.ml @@ -71,7 +71,8 @@ let property_name_contains_word decl word = with Not_found -> false) | _ -> false -let is_objc_extension = General_utils.is_objc_extension +let is_objc_extension lcxt = + General_utils.is_objc_extension lcxt.CLintersContext.translation_unit_context let is_syntactically_global_var decl = Ast_utils.is_syntactically_global_var decl diff --git a/infer/src/clang/predicates.mli b/infer/src/clang/predicates.mli index 2b0cdb0ab..7c4468494 100644 --- a/infer/src/clang/predicates.mli +++ b/infer/src/clang/predicates.mli @@ -15,7 +15,7 @@ val call_method : string -> Clang_ast_t.stmt -> bool val property_name_contains_word : Clang_ast_t.decl -> string -> bool -val is_objc_extension : bool +val is_objc_extension : CLintersContext.context -> bool val is_syntactically_global_var : Clang_ast_t.decl -> bool diff --git a/infer/src/integration/BuckCompilationDatabase.ml b/infer/src/integration/BuckCompilationDatabase.ml index 5beee8958..56cb7f00a 100644 --- a/infer/src/integration/BuckCompilationDatabase.ml +++ b/infer/src/integration/BuckCompilationDatabase.ml @@ -192,5 +192,5 @@ let get_compilation_database changed_files = let () = let changed_files = read_files_to_compile () in let compilation_database = get_compilation_database changed_files in - DB.create_dir (Config.results_dir // Config.clang_build_output_dir_name); + create_dir (Config.results_dir // Config.clang_build_output_dir_name); run_compilation_database compilation_database diff --git a/infer/src/java/jMain.ml b/infer/src/java/jMain.ml index 5f9d199f1..26c2f1b47 100644 --- a/infer/src/java/jMain.ml +++ b/infer/src/java/jMain.ml @@ -26,8 +26,8 @@ let register_perf_stats_report source_file = let stats_dir = Filename.concat Config.results_dir Config.frontend_stats_dir_name in let abbrev_source_file = DB.source_file_encoding source_file in let stats_file = Config.perf_stats_prefix ^ "_" ^ abbrev_source_file ^ ".json" in - DB.create_dir Config.results_dir ; - DB.create_dir stats_dir ; + create_dir Config.results_dir ; + create_dir stats_dir ; PerfStats.register_report_at_exit (Filename.concat stats_dir stats_file) diff --git a/infer/src/llvm/lMain.ml b/infer/src/llvm/lMain.ml index e725d9e2d..c1294c22c 100644 --- a/infer/src/llvm/lMain.ml +++ b/infer/src/llvm/lMain.ml @@ -13,8 +13,8 @@ let register_perf_stats_report source_file = let stats_dir = Filename.concat Config.results_dir Config.frontend_stats_dir_name in let abbrev_source_file = DB.source_file_encoding source_file in let stats_file = Config.perf_stats_prefix ^ "_" ^ abbrev_source_file ^ ".json" in - DB.create_dir Config.results_dir ; - DB.create_dir stats_dir ; + create_dir Config.results_dir ; + create_dir stats_dir ; PerfStats.register_report_at_exit (Filename.concat stats_dir stats_file) let init_global_state source_file = diff --git a/infer/src/scripts/StatsAggregator.re b/infer/src/scripts/StatsAggregator.re index 61392acf7..3b8b9e886 100644 --- a/infer/src/scripts/StatsAggregator.re +++ b/infer/src/scripts/StatsAggregator.re @@ -180,9 +180,9 @@ let () = { let aggregated_frontend_stats_dir = Filename.concat infer_out Config.frontend_stats_dir_name; let aggregated_backend_stats_dir = Filename.concat infer_out Config.backend_stats_dir_name; let aggregated_reporting_stats_dir = Filename.concat infer_out Config.reporting_stats_dir_name; - DB.create_dir aggregated_frontend_stats_dir; - DB.create_dir aggregated_backend_stats_dir; - DB.create_dir aggregated_reporting_stats_dir; + create_dir aggregated_frontend_stats_dir; + create_dir aggregated_backend_stats_dir; + create_dir aggregated_reporting_stats_dir; let write_to_json_file_opt destfile json => switch json { | Some j => Utils.write_json_to_file destfile j