diff --git a/infer/src/backend/CommandLineOption.ml b/infer/src/backend/CommandLineOption.ml index 08e25520b..149c7605f 100644 --- a/infer/src/backend/CommandLineOption.ml +++ b/infer/src/backend/CommandLineOption.ml @@ -297,6 +297,14 @@ let mk_symbol_seq ?(default=[]) ~symbols ?(deprecated=[]) ~long ?short ?exes ?(m String.concat "," (YBU.convert_each YBU.to_string json)]) ~mk_spec:(fun set -> Arg.String set) +let mk_set_from_json ~default ~default_to_string ~f + ?(deprecated=[]) ~long ?short ?exes ?(meta="json") doc = + mk ~deprecated ~long ?short ?exes ~meta doc + ~default ~default_to_string + ~mk_setter:(fun var json -> var := f (Yojson.Basic.from_string json)) + ~decode_json:(fun json -> [dashdash long; Yojson.Basic.to_string json]) + ~mk_spec:(fun set -> Arg.String set) + let anon_fun = ref (fun arg -> raise (Arg.Bad ("unexpected anonymous argument: " ^ arg))) let mk_anon () = diff --git a/infer/src/backend/CommandLineOption.mli b/infer/src/backend/CommandLineOption.mli index 574816cf0..ee4694440 100644 --- a/infer/src/backend/CommandLineOption.mli +++ b/infer/src/backend/CommandLineOption.mli @@ -85,6 +85,9 @@ val mk_symbol_opt : symbols:(string * 'a) list -> 'a option ref t element of [symbols]. *) val mk_symbol_seq : ?default:'a list -> symbols:(string * 'a) list -> 'a list ref t +val mk_set_from_json : default:'a -> default_to_string:('a -> string) + -> f:(Yojson.Basic.json -> 'a) -> 'a ref t + (** [mk_anon ()] defines a [string list ref] of the anonymous command line arguments, in the reverse order they appeared on the command line. *) val mk_anon : diff --git a/infer/src/backend/config.ml b/infer/src/backend/config.ml index e8d946467..332701348 100644 --- a/infer/src/backend/config.ml +++ b/infer/src/backend/config.ml @@ -19,6 +19,16 @@ module F = Format type language = Clang | Java +type method_pattern = { + class_name : string; + method_name : string option; + parameters : (string list) option; +} + +type pattern = + | Method_pattern of language * method_pattern + | Source_contains of language * string + let string_of_language = function | Java -> "Java" | Clang -> "C_CPP" @@ -198,6 +208,104 @@ let os_type = match Sys.os_type with | "Cygwin" -> Cygwin | _ -> Unix +let patterns_of_json_with_key json_key json = + let default_method_pattern = { + class_name = ""; + method_name = None; + parameters = None + } in + + let default_source_contains = "" in + + let language_of_string json_key = function + | "Java" -> + Ok Java + | l -> + Error ("Inferconfig JSON key " ^ json_key ^ " not supported for language " ^ l) in + + let detect_language json_key assoc = + let rec loop = function + | [] -> + Error ("No language found for " ^ json_key ^ " in " ^ inferconfig_file) + | ("language", `String s) :: _ -> + language_of_string json_key s + | _:: tl -> loop tl in + loop assoc in + + (* Detect the kind of pattern, method pattern or pattern based on the content of the source file. + Detecting the kind of patterns in a first step makes it easier to parse the parts of the + pattern in a second step *) + let detect_pattern json_key assoc = + match detect_language json_key assoc with + | Ok language -> + let is_method_pattern key = IList.exists (string_equal key) ["class"; "method"] + and is_source_contains key = IList.exists (string_equal key) ["source_contains"] in + let rec loop = function + | [] -> + Error ("Unknown pattern for " ^ json_key ^ " in " ^ inferconfig_file) + | (key, _) :: _ when is_method_pattern key -> + Ok (Method_pattern (language, default_method_pattern)) + | (key, _) :: _ when is_source_contains key -> + Ok (Source_contains (language, default_source_contains)) + | _:: tl -> loop tl in + loop assoc + | Error _ as error -> + error in + + (* Translate a JSON entry into a matching pattern *) + let create_pattern json_key (assoc : (string * Yojson.Basic.json) list) = + let collect_params l = + let collect accu = function + | `String s -> s:: accu + | _ -> failwith ("Unrecognised parameters in " ^ Yojson.Basic.to_string (`Assoc assoc)) in + IList.rev (IList.fold_left collect [] l) in + let create_method_pattern assoc = + let loop mp = function + | (key, `String s) when key = "class" -> + { mp with class_name = s } + | (key, `String s) when key = "method" -> + { mp with method_name = Some s } + | (key, `List l) when key = "parameters" -> + { mp with parameters = Some (collect_params l) } + | (key, _) when key = "language" -> mp + | _ -> failwith ("Fails to parse " ^ Yojson.Basic.to_string (`Assoc assoc)) in + IList.fold_left loop default_method_pattern assoc + and create_string_contains assoc = + let loop sc = function + | (key, `String pattern) when key = "source_contains" -> pattern + | (key, _) when key = "language" -> sc + | _ -> failwith ("Fails to parse " ^ Yojson.Basic.to_string (`Assoc assoc)) in + IList.fold_left loop default_source_contains assoc in + match detect_pattern json_key assoc with + | Ok (Method_pattern (language, _)) -> + Ok (Method_pattern (language, create_method_pattern assoc)) + | Ok (Source_contains (language, _)) -> + Ok (Source_contains (language, create_string_contains assoc)) + | Error _ as error -> + error in + + let warn_user key msg = + F.eprintf "WARNING: in file %s: error parsing option %s@\n%s" inferconfig_file json_key msg in + + (* Translate all the JSON entries into matching patterns *) + let rec translate json_key accu = function + | `Assoc l -> ( + match create_pattern json_key l with + | Ok pattern -> + pattern :: accu + | Error msg -> + warn_user json_key msg; + accu) + | `List l -> + IList.fold_left (translate json_key) accu l + | json -> + warn_user json_key + (Printf.sprintf "expected list or assoc json type, but got value %s" + (Yojson.Basic.to_string json)); + accu in + + translate json_key [] json + (** Command Line options *) @@ -819,6 +927,23 @@ and zip_specs_library = ~exes:CLOpt.[A] ~meta:"zip file" "add a zip file containing library spec files" +and ( + patterns_never_returning_null, + patterns_skip_translation, + patterns_modeled_expensive) = + let mk_option ~deprecated ~long doc = + CLOpt.mk_set_from_json ~deprecated ~long ~default:[] ~default_to_string:(fun _ -> "[]") + ~exes:CLOpt.[J] + ~f:(patterns_of_json_with_key long) doc in + ( + mk_option ~deprecated:["never_returning_null"] ~long:"never-returning-null" + "Matcher or list of matchers for functions that never return `null`.", + mk_option ~deprecated:["skip_translation"] ~long:"skip-translation" + "Matcher or list of matchers for names of files that should be analyzed at all.", + mk_option ~deprecated:["modeled_expensive"] ~long:"modeled-expensive" + ("Matcher or list of matchers for methods that should be considered expensive " ^ + "by the performance critical checker.")) + (** Global variables *) let set_reference_and_call_function reference value f x = @@ -1077,6 +1202,9 @@ and objc_memory_model_on = !objc_memory_model and only_footprint = !only_footprint and optimistic_cast = !optimistic_cast and out_file_cmdline = !out_file +and patterns_never_returning_null = !patterns_never_returning_null +and patterns_skip_translation = !patterns_skip_translation +and patterns_modeled_expensive = !patterns_modeled_expensive and precondition_stats = !precondition_stats and print_builtins = !print_builtins and print_types = !print_types @@ -1144,4 +1272,14 @@ and suppress_warnings_json = lazy ( | Ok json -> json | Error msg -> error ("Could not read or parse the supplied " ^ path ^ ":\n" ^ msg)) | None -> - error ("Error: The option " ^ suppress_warnings_annotations_long ^ " was not provided")) + if CLOpt.(current_exe <> J) then `Null + else error ("Error: The option " ^ suppress_warnings_annotations_long ^ " was not provided")) + +let patterns_suppress_warnings = + let json_key = "suppress_warnings" in + match Lazy.force suppress_warnings_json with + | `Null -> [] + | json -> + match Yojson.Basic.Util.member json_key json with + | `Null -> [] + | json -> patterns_of_json_with_key json_key json diff --git a/infer/src/backend/config.mli b/infer/src/backend/config.mli index bdf54638a..ae8d0bca6 100644 --- a/infer/src/backend/config.mli +++ b/infer/src/backend/config.mli @@ -18,6 +18,16 @@ type language = Clang | Java val string_of_language : language -> string +type method_pattern = { + class_name : string; + method_name : string option; + parameters : (string list) option; +} + +type pattern = + | Method_pattern of language * method_pattern + | Source_contains of language * string + type clang_lang = C | CPP | OBJC | OBJCPP type os_type = Unix | Win32 | Cygwin @@ -64,6 +74,10 @@ val cpp_models_dir : string val nsnotification_center_checker_backend : bool val objc_method_call_semantics : bool val os_type : os_type +val patterns_never_returning_null : pattern list +val patterns_suppress_warnings : pattern list +val patterns_skip_translation : pattern list +val patterns_modeled_expensive : pattern list val perf_stats_prefix : string val proc_stats_filename : string val property_attributes : string diff --git a/infer/src/backend/inferconfig.ml b/infer/src/backend/inferconfig.ml index 5c40bbd13..0105b3bdf 100644 --- a/infer/src/backend/inferconfig.ml +++ b/infer/src/backend/inferconfig.ml @@ -52,101 +52,6 @@ let is_matching patterns = patterns -type method_pattern = { - class_name : string; - method_name : string option; - parameters : (string list) option -} - -let default_method_pattern = { - class_name = ""; - method_name = None; - parameters = None -} - -let default_source_contains = "" - -type pattern = - | Method_pattern of Config.language * method_pattern - | Source_contains of Config.language * string - -let language_of_string json_key = function - | "Java" -> Config.Java - | l -> failwith ("Inferconfig JSON key " ^ json_key ^ " not supported for language " ^ l) - -let detect_language json_key assoc = - let rec loop = function - | [] -> - failwith - ("No language found for " ^ json_key ^ " in " ^ Config.inferconfig_file) - | (key, `String s) :: _ when key = "language" -> - language_of_string json_key s - | _:: tl -> loop tl in - loop assoc - -(* Detect the kind of pattern, method pattern or pattern based on the content of the source file. - Detecting the kind of patterns in a first step makes it easier to parse the parts of the - pattern in a second step *) -let detect_pattern json_key assoc = - let language = detect_language json_key assoc in - let is_method_pattern key = IList.exists (string_equal key) ["class"; "method"] - and is_source_contains key = IList.exists (string_equal key) ["source_contains"] in - let rec loop = function - | [] -> - failwith ("Unknown pattern for " ^ json_key ^ " in " ^ Config.inferconfig_file) - | (key, _) :: _ when is_method_pattern key -> - Method_pattern (language, default_method_pattern) - | (key, _) :: _ when is_source_contains key -> - Source_contains (language, default_source_contains) - | _:: tl -> loop tl in - loop assoc - -(* Translate a JSON entry into a matching pattern *) -let create_pattern json_key (assoc : (string * Yojson.Basic.json) list) = - let collect_params l = - let collect accu = function - | `String s -> s:: accu - | _ -> failwith ("Unrecognised parameters in " ^ Yojson.Basic.to_string (`Assoc assoc)) in - IList.rev (IList.fold_left collect [] l) in - let create_method_pattern assoc = - let loop mp = function - | (key, `String s) when key = "class" -> - { mp with class_name = s } - | (key, `String s) when key = "method" -> - { mp with method_name = Some s } - | (key, `List l) when key = "parameters" -> - { mp with parameters = Some (collect_params l) } - | (key, _) when key = "language" -> mp - | _ -> failwith ("Fails to parse " ^ Yojson.Basic.to_string (`Assoc assoc)) in - IList.fold_left loop default_method_pattern assoc - and create_string_contains assoc = - let loop sc = function - | (key, `String pattern) when key = "source_contains" -> pattern - | (key, _) when key = "language" -> sc - | _ -> failwith ("Fails to parse " ^ Yojson.Basic.to_string (`Assoc assoc)) in - IList.fold_left loop default_source_contains assoc in - match detect_pattern json_key assoc with - | Method_pattern (language, _) -> - Method_pattern (language, create_method_pattern assoc) - | Source_contains (language, _) -> - Source_contains (language, create_string_contains assoc) - -(* Translate all the JSON entries into matching patterns *) -let rec translate json_key accu (json : Yojson.Basic.json) : pattern list = - match json with - | `Assoc l -> (create_pattern json_key l):: accu - | `List l -> IList.fold_left (translate json_key) accu l - | _ -> assert false - -(* Creates a list of matching patterns for the given inferconfig file *) -let load_patterns json_key json = - let found = - Yojson.Basic.Util.filter_member - json_key - [json] in - IList.fold_left (translate json_key) [] found - - (** Check if a proc name is matching the name given as string. *) let match_method language proc_name method_name = not (Builtin.is_registered proc_name) && @@ -188,18 +93,8 @@ module FileContainsStringMatcher = struct with Sys_error _ -> false end -module type MATCHABLE_JSON = sig - val json_key : string -end - -module type Matcher = sig - type matcher = DB.source_file -> Procname.t -> bool - val load_matcher : Yojson.Basic.json Lazy.t -> matcher -end - (* Module to create matcher based on source file names or class names and method names *) -module FileOrProcMatcher = functor (M : MATCHABLE_JSON) -> -struct +module FileOrProcMatcher = struct type matcher = DB.source_file -> Procname.t -> bool @@ -215,9 +110,9 @@ struct (fun map pattern -> let previous = try - StringMap.find pattern.class_name map + StringMap.find pattern.Config.class_name map with Not_found -> [] in - StringMap.add pattern.class_name (pattern:: previous) map) + StringMap.add pattern.Config.class_name (pattern:: previous) map) StringMap.empty m_patterns in let do_java pname_java = @@ -227,7 +122,7 @@ struct let class_patterns = StringMap.find class_name pattern_map in IList.exists (fun p -> - match p.method_name with + match p.Config.method_name with | None -> true | Some m -> string_equal m method_name) class_patterns @@ -243,8 +138,8 @@ struct let create_file_matcher patterns = let s_patterns, m_patterns = let collect (s_patterns, m_patterns) = function - | Source_contains (_, s) -> (s:: s_patterns, m_patterns) - | Method_pattern (_, mp) -> (s_patterns, mp :: m_patterns) in + | Config.Source_contains (_, s) -> (s:: s_patterns, m_patterns) + | Config.Method_pattern (_, mp) -> (s_patterns, mp :: m_patterns) in IList.fold_left collect ([], []) patterns in let s_matcher = let matcher = FileContainsStringMatcher.create_matcher s_patterns in @@ -253,8 +148,7 @@ struct fun source_file proc_name -> m_matcher source_file proc_name || s_matcher source_file proc_name - let load_matcher json = - create_file_matcher (load_patterns M.json_key (Lazy.force json)) + let load_matcher = create_file_matcher let _pp_pattern fmt pattern = let pp_string fmt s = @@ -269,54 +163,39 @@ struct Format.fprintf fmt "[%a]" (pp_semicolon_seq_oneline pe_text pp_string) l in Format.fprintf fmt "%a%a%a" - (pp_key_value pp_string) ("class", Some mp.class_name) - (pp_key_value pp_string) ("method", mp.method_name) - (pp_key_value pp_params) ("parameters", mp.parameters) + (pp_key_value pp_string) ("class", Some mp.Config.class_name) + (pp_key_value pp_string) ("method", mp.Config.method_name) + (pp_key_value pp_params) ("parameters", mp.Config.parameters) and pp_source_contains fmt sc = Format.fprintf fmt " pattern: %s\n" sc in match pattern with - | Method_pattern (language, mp) -> + | Config.Method_pattern (language, mp) -> Format.fprintf fmt "Method pattern (%s) {\n%a}\n" (Config.string_of_language language) pp_method_pattern mp - | Source_contains (language, sc) -> + | Config.Source_contains (language, sc) -> Format.fprintf fmt "Source contains (%s) {\n%a}\n" (Config.string_of_language language) pp_source_contains sc end (* of module FileOrProcMatcher *) (* Module to create patterns that will match all overriding methods in the pattern *) -module OverridesMatcher = functor (M : MATCHABLE_JSON) -> -struct - - type matcher = (string -> bool) -> Procname.t -> bool +module OverridesMatcher = struct - let load_matcher json = - let patterns = load_patterns M.json_key (Lazy.force json) in + let load_matcher patterns = fun is_subtype proc_name -> let is_matching = function - | Method_pattern (language, mp) -> - is_subtype mp.class_name - && Option.map_default (match_method language proc_name) false mp.method_name + | Config.Method_pattern (language, mp) -> + is_subtype mp.Config.class_name + && Option.map_default (match_method language proc_name) false mp.Config.method_name | _ -> failwith "Expecting method pattern" in IList.exists is_matching patterns end -module NeverReturnNull = FileOrProcMatcher(struct - let json_key = "never_returning_null" - end) - -module SuppressWarningsMatcher = FileOrProcMatcher(struct - let json_key = "suppress_warnings" - end) - -module SkipTranslationMatcher = FileOrProcMatcher(struct - let json_key = "skip_translation" - end) - -module ModeledExpensiveMatcher = OverridesMatcher(struct - let json_key = "modeled_expensive" - end) +let never_return_null_matcher = FileOrProcMatcher.load_matcher Config.patterns_never_returning_null +let skip_translation_matcher = FileOrProcMatcher.load_matcher Config.patterns_skip_translation +let suppress_warnings_matcher = FileOrProcMatcher.load_matcher Config.patterns_suppress_warnings +let modeled_expensive_matcher = OverridesMatcher.load_matcher Config.patterns_modeled_expensive let load_filters analyzer = { diff --git a/infer/src/backend/inferconfig.mli b/infer/src/backend/inferconfig.mli index 3ed74021c..e7d5d3953 100644 --- a/infer/src/backend/inferconfig.mli +++ b/infer/src/backend/inferconfig.mli @@ -31,21 +31,10 @@ val do_not_filter : filters (** Create filters based on the config file *) val create_filters : analyzer -> filters -module type Matcher = sig - type matcher = DB.source_file -> Procname.t -> bool - val load_matcher : Yojson.Basic.json Lazy.t -> matcher -end - -module NeverReturnNull : Matcher - -module SkipTranslationMatcher : Matcher - -module SuppressWarningsMatcher : Matcher - -module ModeledExpensiveMatcher : sig - type matcher = (string -> bool) -> Procname.t -> bool - val load_matcher : Yojson.Basic.json Lazy.t -> matcher -end +val never_return_null_matcher : DB.source_file -> Procname.t -> bool +val suppress_warnings_matcher : DB.source_file -> Procname.t -> bool +val skip_translation_matcher : DB.source_file -> Procname.t -> bool +val modeled_expensive_matcher : (string -> bool) -> Procname.t -> bool (** Load the config file and list the files to report on *) val test: unit -> unit diff --git a/infer/src/checkers/annotationReachability.ml b/infer/src/checkers/annotationReachability.ml index 8ae15a729..1fbb2ceda 100644 --- a/infer/src/checkers/annotationReachability.ml +++ b/infer/src/checkers/annotationReachability.ml @@ -110,17 +110,15 @@ let expensive_overrides_unexpensive = let annotation_reachability_error = "CHECKERS_ANNOTATION_REACHABILITY_ERROR" -let is_modeled_expensive = - let matcher = - lazy (Inferconfig.ModeledExpensiveMatcher.load_matcher Config.inferconfig_json) in - fun tenv proc_name -> match proc_name with - | Procname.Java proc_name_java -> - not (Builtin.is_registered proc_name) && - let classname = - Typename.Java.from_string (Procname.java_get_class_name proc_name_java) in - (Lazy.force matcher) (PatternMatch.is_subtype_of_str tenv classname) proc_name - | _ -> - false +let is_modeled_expensive tenv = function + | Procname.Java proc_name_java as proc_name -> + not (Builtin.is_registered proc_name) && + let is_subclass = + let classname = Typename.Java.from_string (Procname.java_get_class_name proc_name_java) in + PatternMatch.is_subtype_of_str tenv classname in + Inferconfig.modeled_expensive_matcher is_subclass proc_name + | _ -> + false let is_allocator tenv pname = match pname with diff --git a/infer/src/java/jAnnotation.ml b/infer/src/java/jAnnotation.ml index 9a8471007..23a495216 100644 --- a/infer/src/java/jAnnotation.ml +++ b/infer/src/java/jAnnotation.ml @@ -14,12 +14,7 @@ open Javalib_pack let is_suppress_warnings_annotated = - let matcher = lazy ( - Inferconfig.SuppressWarningsMatcher.load_matcher Config.suppress_warnings_json - DB.source_file_empty) in - fun proc_name -> - (Lazy.force matcher) proc_name - + Inferconfig.suppress_warnings_matcher DB.source_file_empty let suppress_warnings = ({ Sil.class_name = Annotations.suppress_warnings; diff --git a/infer/src/java/jContext.ml b/infer/src/java/jContext.ml index 3fa675f17..f8bdd93c3 100644 --- a/infer/src/java/jContext.ml +++ b/infer/src/java/jContext.ml @@ -42,10 +42,9 @@ type t = meth_kind : meth_kind; node : JCode.jcode Javalib.interface_or_class; program : JClasspath.program; - never_null_matcher: Inferconfig.NeverReturnNull.matcher; } -let create_context never_null_matcher icfg procdesc impl cn meth_kind node program = +let create_context icfg procdesc impl cn meth_kind node program = { icfg = icfg; procdesc = procdesc; impl = impl; @@ -56,7 +55,6 @@ let create_context never_null_matcher icfg procdesc impl cn meth_kind node progr meth_kind = meth_kind; node = node; program = program; - never_null_matcher = never_null_matcher; } let get_icfg context = context.icfg @@ -71,7 +69,6 @@ let get_impl context = context.impl let get_var_map context = context.var_map let set_var_map context var_map = context.var_map <- var_map let get_meth_kind context = context.meth_kind -let get_never_null_matcher context = context.never_null_matcher let get_or_set_pvar_type context var typ = let var_map = get_var_map context in diff --git a/infer/src/java/jContext.mli b/infer/src/java/jContext.mli index a93164bda..0843ea602 100644 --- a/infer/src/java/jContext.mli +++ b/infer/src/java/jContext.mli @@ -45,7 +45,6 @@ type t (** cretes a context for a given method. *) val create_context : - Inferconfig.NeverReturnNull.matcher -> icfg -> Cfg.Procdesc.t -> JBir.t -> @@ -103,10 +102,6 @@ val get_program : t -> JClasspath.program (** returns the current node *) val get_node : t -> JCode.jcode Javalib.interface_or_class -(** returns a match function for procedures that are never returning null - according to .inferfonfig *) -val get_never_null_matcher : t -> Inferconfig.NeverReturnNull.matcher - (** [set_pvar context var type] adds a variable with a type to the context *) val set_pvar : t -> JBir.var -> Sil.typ -> Pvar.t diff --git a/infer/src/java/jFrontend.ml b/infer/src/java/jFrontend.ml index bf57971fd..3169d6185 100644 --- a/infer/src/java/jFrontend.ml +++ b/infer/src/java/jFrontend.ml @@ -73,7 +73,7 @@ let add_edges context start_node exn_node exit_nodes method_body_nodes impl supe Array.iteri connect_nodes method_body_nodes (** Add a concrete method. *) -let add_cmethod never_null_matcher program icfg node cm is_static = +let add_cmethod program icfg node cm is_static = let cfg = icfg.JContext.cfg in let tenv = icfg.JContext.tenv in let cn, ms = JBasics.cms_split cm.Javalib.cm_class_method_signature in @@ -101,8 +101,7 @@ let add_cmethod never_null_matcher program icfg node cm is_static = (instrs, JContext.Init) else (JBir.code impl), JContext.Normal in let context = - JContext.create_context - never_null_matcher icfg procdesc impl cn meth_kind node program in + JContext.create_context icfg procdesc impl cn meth_kind node program in let method_body_nodes = Array.mapi (JTrans.instruction context) instrs in let procname = Cfg.Procdesc.get_proc_name procdesc in add_edges context start_node exn_node [exit_node] method_body_nodes impl false; @@ -158,7 +157,7 @@ let is_classname_cached cn = (* Given a source file and a class, translates the code of this class. In init - mode, finds out whether this class contains initializers at all, in this case translates it. In standard mode, all methods are translated *) -let create_icfg never_null_matcher linereader program icfg cn node = +let create_icfg linereader program icfg cn node = JUtils.log "\tclassname: %s@." (JBasics.cn_name cn); cache_classname cn; let cfg = icfg.JContext.cfg in @@ -171,7 +170,7 @@ let create_icfg never_null_matcher linereader program icfg cn node = let method_kind = JTransType.get_method_kind m in match m with | Javalib.ConcreteMethod cm -> - add_cmethod never_null_matcher program icfg node cm method_kind + add_cmethod program icfg node cm method_kind | Javalib.AbstractMethod am -> add_amethod program icfg am method_kind ) node @@ -213,7 +212,7 @@ let should_capture classes package_opt source_basename node = In the standard - mode, it translated all the classes that correspond to this source file. *) let compute_source_icfg - never_null_matcher linereader classes program tenv + linereader classes program tenv source_basename package_opt = let icfg = { JContext.cg = Cg.create (); @@ -230,19 +229,18 @@ let compute_source_icfg JBasics.ClassMap.iter (select (should_capture classes package_opt source_basename) - (create_icfg never_null_matcher linereader program icfg)) + (create_icfg linereader program icfg)) (JClasspath.get_classmap program) in (icfg.JContext.cg, icfg.JContext.cfg) -let compute_class_icfg never_null_matcher linereader program tenv node = +let compute_class_icfg linereader program tenv node = let icfg = { JContext.cg = Cg.create (); JContext.cfg = Cfg.Node.create_cfg (); JContext.tenv = tenv } in begin try - create_icfg - never_null_matcher linereader program icfg (Javalib.get_name node) node + create_icfg linereader program icfg (Javalib.get_name node) node with | Bir.Subroutine -> () | e -> raise e diff --git a/infer/src/java/jFrontend.mli b/infer/src/java/jFrontend.mli index 6a6a329cd..5c4518cc9 100644 --- a/infer/src/java/jFrontend.mli +++ b/infer/src/java/jFrontend.mli @@ -23,7 +23,6 @@ val is_classname_cached : JBasics.class_name -> bool (** [compute_icfg linereader classes program tenv source_basename source_file] create the call graph and control flow graph for the file [source_file] by translating all the classes in [program] originating from [source_file] *) val compute_source_icfg : - Inferconfig.NeverReturnNull.matcher -> Printer.LineReader.t -> JBasics.ClassSet.t -> JClasspath.program -> @@ -34,7 +33,6 @@ val compute_source_icfg : (** Compute the CFG for a class *) val compute_class_icfg : - Inferconfig.NeverReturnNull.matcher -> Printer.LineReader.t -> JClasspath.program -> Tenv.t -> diff --git a/infer/src/java/jMain.ml b/infer/src/java/jMain.ml index aa4697cc6..e6ad71e63 100644 --- a/infer/src/java/jMain.ml +++ b/infer/src/java/jMain.ml @@ -65,18 +65,18 @@ let store_icfg tenv cg cfg program = (* Given a source file, its code is translated, and the call-graph, control-flow-graph and type *) (* environment are obtained and saved. *) let do_source_file - never_null_matcher linereader classes program tenv + linereader classes program tenv source_basename (package_opt, source_file) = JUtils.log "\nfilename: %s (%s)@." (DB.source_file_to_string source_file) source_basename; let call_graph, cfg = JFrontend.compute_source_icfg - never_null_matcher linereader classes program tenv + linereader classes program tenv source_basename package_opt in store_icfg tenv call_graph cfg program -let capture_libs never_null_matcher linereader program tenv = +let capture_libs linereader program tenv = let capture_class tenv cn node = match node with | Javalib.JInterface _ -> () @@ -87,7 +87,7 @@ let capture_libs never_null_matcher linereader program tenv = JClasspath.java_source_file_from_path (JFrontend.path_of_cached_classname cn) in init_global_state fake_source_file; let call_graph, cfg = - JFrontend.compute_class_icfg never_null_matcher linereader program tenv node in + JFrontend.compute_class_icfg linereader program tenv node in store_icfg tenv call_graph cfg program; JFrontend.cache_classname cn; end in @@ -135,16 +135,11 @@ let do_all_files classpath sources classes = let program = JClasspath.load_program classpath classes in let tenv = load_tenv () in let linereader = Printer.LineReader.create () in - let skip_translation_matcher = - Inferconfig.SkipTranslationMatcher.load_matcher Config.inferconfig_json in - let never_null_matcher = Inferconfig.NeverReturnNull.load_matcher Config.inferconfig_json in - let skip source_file = - skip_translation_matcher source_file Procname.empty_block in + let skip source_file = Inferconfig.skip_translation_matcher source_file Procname.empty_block in let translate_source_file basename (package_opt, _) source_file = init_global_state source_file; if not (skip source_file) then - do_source_file - never_null_matcher linereader classes program tenv basename (package_opt, source_file) in + do_source_file linereader classes program tenv basename (package_opt, source_file) in StringMap.iter (fun basename file_entry -> match file_entry with @@ -157,7 +152,7 @@ let do_all_files classpath sources classes = source_files) sources; if Config.dependency_mode then - capture_libs never_null_matcher linereader program tenv; + capture_libs linereader program tenv; save_tenv tenv; JClasspath.cleanup program; JUtils.log "done @." diff --git a/infer/src/java/jTrans.ml b/infer/src/java/jTrans.ml index b27bf8ed4..e370eaf51 100644 --- a/infer/src/java/jTrans.ml +++ b/infer/src/java/jTrans.ml @@ -784,7 +784,7 @@ let rec instruction context pc instr : translation = let ret_var = Pvar.get_ret_pvar proc_name in let ret_type = Cfg.Procdesc.get_ret_type (JContext.get_procdesc context) in let loc = get_location (JContext.get_impl context) pc meth_kind cn in - let match_never_null = JContext.get_never_null_matcher context in + let match_never_null = Inferconfig.never_return_null_matcher in let create_node node_kind sil_instrs = Cfg.Node.create cfg