[codemod] Move `Procname` into `Typ.Procname`

Summary:
`Procname` needs to depend on `Typ.t` and `Typ.Struct` depends on `Procname.t`.
To resolve this circular dependency issue, move `Procname` into `Typ`

steps:
1. Move everything from `Procname` to `Typ.Procname`, remove `Procname.re(i)`
2. search & replace `Procname.` with `Typ.Procname.`
3. fix outstanding compilation issues manually
4. `yes | arc lint`

Reviewed By: jberdine

Differential Revision: D4681509

fbshipit-source-id: b07af63
master
Andrzej Kotulski 8 years ago committed by Facebook Github Bot
parent 6125632af3
commit e363958d34

@ -39,7 +39,7 @@ let attributes_filename proc_kind::proc_kind pname_file => {
/** path to the .attr file for the given procedure in the current results directory */ /** path to the .attr file for the given procedure in the current results directory */
let res_dir_attr_filename proc_kind::proc_kind pname => { let res_dir_attr_filename proc_kind::proc_kind pname => {
let pname_file = Procname.to_filename pname; let pname_file = Typ.Procname.to_filename pname;
let attr_fname = attributes_filename proc_kind::proc_kind pname_file; let attr_fname = attributes_filename proc_kind::proc_kind pname_file;
let bucket_dir = { let bucket_dir = {
let base = pname_file; let base = pname_file;
@ -154,19 +154,19 @@ let store_attributes (proc_attributes: ProcAttributes.t) => {
} }
}; };
let attr_tbl = Procname.Hash.create 16; let attr_tbl = Typ.Procname.Hash.create 16;
let defined_attr_tbl = Procname.Hash.create 16; let defined_attr_tbl = Typ.Procname.Hash.create 16;
let load_attributes proc_name => let load_attributes proc_name =>
try (Procname.Hash.find attr_tbl proc_name) { try (Typ.Procname.Hash.find attr_tbl proc_name) {
| Not_found => | Not_found =>
let proc_attributes = load_attr defined_only::false proc_name; let proc_attributes = load_attr defined_only::false proc_name;
switch proc_attributes { switch proc_attributes {
| Some attrs => | Some attrs =>
Procname.Hash.add attr_tbl proc_name proc_attributes; Typ.Procname.Hash.add attr_tbl proc_name proc_attributes;
if attrs.is_defined { if attrs.is_defined {
Procname.Hash.add defined_attr_tbl proc_name proc_attributes Typ.Procname.Hash.add defined_attr_tbl proc_name proc_attributes
} }
| None => () | None => ()
}; };
@ -174,15 +174,15 @@ let load_attributes proc_name =>
}; };
let load_defined_attributes cache_none::cache_none proc_name => let load_defined_attributes cache_none::cache_none proc_name =>
try (Procname.Hash.find defined_attr_tbl proc_name) { try (Typ.Procname.Hash.find defined_attr_tbl proc_name) {
| Not_found => | Not_found =>
let proc_attributes = load_attr defined_only::true proc_name; let proc_attributes = load_attr defined_only::true proc_name;
if (proc_attributes != None) { if (proc_attributes != None) {
/* procedure just got defined, replace attribute in attr_tbl with defined version */ /* procedure just got defined, replace attribute in attr_tbl with defined version */
Procname.Hash.replace attr_tbl proc_name proc_attributes; Typ.Procname.Hash.replace attr_tbl proc_name proc_attributes;
Procname.Hash.add defined_attr_tbl proc_name proc_attributes Typ.Procname.Hash.add defined_attr_tbl proc_name proc_attributes
} else if cache_none { } else if cache_none {
Procname.Hash.add defined_attr_tbl proc_name proc_attributes Typ.Procname.Hash.add defined_attr_tbl proc_name proc_attributes
}; };
proc_attributes proc_attributes
}; };
@ -193,7 +193,7 @@ let load_defined_attributes cache_none::cache_none proc_name =>
corresponds to the class definition. */ corresponds to the class definition. */
let get_correct_type_from_objc_class_name type_name => let get_correct_type_from_objc_class_name type_name =>
/* ToDo: this function should return a type that includes a reference to the tenv computed by: /* ToDo: this function should return a type that includes a reference to the tenv computed by:
let class_method = Procname.get_default_objc_class_method (Typename.name type_name); let class_method = Typ.Procname.get_default_objc_class_method (Typename.name type_name);
switch (find_tenv_from_class_of_proc class_method) { switch (find_tenv_from_class_of_proc class_method) {
| Some tenv => | Some tenv =>
*/ */
@ -246,7 +246,7 @@ let aggregate s => {
}; };
let stats () => { let stats () => {
let stats = Procname.Hash.stats attr_tbl; let stats = Typ.Procname.Hash.stats attr_tbl;
let {Hashtbl.num_bindings: num_bindings, num_buckets, max_bucket_length} = stats; let {Hashtbl.num_bindings: num_bindings, num_buckets, max_bucket_length} = stats;
let serialized_size_kb = let serialized_size_kb =
Config.developer_mode ? Config.developer_mode ?

@ -16,11 +16,11 @@ let store_attributes: ProcAttributes.t => unit;
/** Load the attributes for the procedure from the attributes database. */ /** Load the attributes for the procedure from the attributes database. */
let load_attributes: Procname.t => option ProcAttributes.t; let load_attributes: Typ.Procname.t => option ProcAttributes.t;
/** Load attrubutes for the procedure but only if is_defined is true */ /** Load attrubutes for the procedure but only if is_defined is true */
let load_defined_attributes: cache_none::bool => Procname.t => option ProcAttributes.t; let load_defined_attributes: cache_none::bool => Typ.Procname.t => option ProcAttributes.t;
/** Given the name of an ObjC class, extract the type from the tenv where the class was defined. We /** Given the name of an ObjC class, extract the type from the tenv where the class was defined. We
@ -31,7 +31,8 @@ let get_correct_type_from_objc_class_name: Typename.t => option Typ.t;
/* Find the file where the procedure was captured, if a cfg for that file exists. /* Find the file where the procedure was captured, if a cfg for that file exists.
Return also a boolean indicating whether the procedure is defined in an Return also a boolean indicating whether the procedure is defined in an
include file. */ include file. */
let find_file_capturing_procedure: Procname.t => option (SourceFile.t, [ | `Include | `Source]); let find_file_capturing_procedure:
Typ.Procname.t => option (SourceFile.t, [ | `Include | `Source]);
type t; type t;

@ -9,26 +9,26 @@
open! IStd open! IStd
type t = Procname.t type t = Typ.Procname.t
let builtin_decls = ref Procname.Set.empty let builtin_decls = ref Typ.Procname.Set.empty
let register pname = let register pname =
builtin_decls := Procname.Set.add pname !builtin_decls builtin_decls := Typ.Procname.Set.add pname !builtin_decls
let create_procname name = let create_procname name =
let pname = Procname.from_string_c_fun name in let pname = Typ.Procname.from_string_c_fun name in
register pname; register pname;
pname pname
let create_objc_class_method class_name method_name = let create_objc_class_method class_name method_name =
let method_kind = Procname.ObjCClassMethod in let method_kind = Typ.Procname.ObjCClassMethod in
let tname = Typename.Objc.from_string class_name in let tname = Typename.Objc.from_string class_name in
let pname = Procname.ObjC_Cpp (Procname.objc_cpp tname method_name method_kind) in let pname = Typ.Procname.ObjC_Cpp (Typ.Procname.objc_cpp tname method_name method_kind) in
register pname; register pname;
pname pname
let is_declared pname = Procname.Set.mem pname !builtin_decls let is_declared pname = Typ.Procname.Set.mem pname !builtin_decls
let __assert_fail = create_procname "__assert_fail" let __assert_fail = create_procname "__assert_fail"
let __builtin_va_arg = create_procname "__builtin_va_arg" let __builtin_va_arg = create_procname "__builtin_va_arg"

@ -10,6 +10,6 @@
open! IStd open! IStd
(** Procnames for the builtin functions supported *) (** Procnames for the builtin functions supported *)
include BUILTINS.S with type t = Procname.t include BUILTINS.S with type t = Typ.Procname.t
val is_declared : Procname.t -> bool val is_declared : Typ.Procname.t -> bool

@ -22,7 +22,7 @@ type t = {
cf_interface: bool, cf_interface: bool,
cf_noreturn: bool, cf_noreturn: bool,
cf_is_objc_block: bool, cf_is_objc_block: bool,
cf_targets: list Procname.t cf_targets: list Typ.Procname.t
} }
[@@deriving compare]; [@@deriving compare];

@ -22,7 +22,7 @@ type t = {
cf_interface: bool, cf_interface: bool,
cf_noreturn: bool, cf_noreturn: bool,
cf_is_objc_block: bool, cf_is_objc_block: bool,
cf_targets: list Procname.t cf_targets: list Typ.Procname.t
} }
[@@deriving compare]; [@@deriving compare];

@ -13,7 +13,7 @@ module F = Format
type t = type t =
{ {
pname : Procname.t; pname : Typ.Procname.t;
loc : Location.t; loc : Location.t;
} }
[@@deriving compare] [@@deriving compare]
@ -30,10 +30,10 @@ let make pname loc =
{ pname; loc; } { pname; loc; }
let dummy = let dummy =
make Procname.empty_block Location.dummy make Typ.Procname.empty_block Location.dummy
let pp fmt t = let pp fmt t =
F.fprintf fmt "%a at %a" Procname.pp t.pname Location.pp t.loc F.fprintf fmt "%a at %a" Typ.Procname.pp t.pname Location.pp t.loc
module Set = PrettyPrintable.MakePPSet(struct module Set = PrettyPrintable.MakePPSet(struct
type nonrec t = t type nonrec t = t

@ -15,11 +15,11 @@ type t [@@deriving compare]
val equal : t -> t -> bool val equal : t -> t -> bool
val pname : t -> Procname.t val pname : t -> Typ.Procname.t
val loc : t -> Location.t val loc : t -> Location.t
val make : Procname.t -> Location.t -> t val make : Typ.Procname.t -> Location.t -> t
val dummy : t val dummy : t

@ -15,20 +15,20 @@ let module F = Format;
/** data type for the control flow graph */ /** data type for the control flow graph */
type cfg = {proc_desc_table: Procname.Hash.t Procdesc.t /** Map proc name to procdesc */}; type cfg = {proc_desc_table: Typ.Procname.Hash.t Procdesc.t /** Map proc name to procdesc */};
/** create a new empty cfg */ /** create a new empty cfg */
let create_cfg () => {proc_desc_table: Procname.Hash.create 16}; let create_cfg () => {proc_desc_table: Typ.Procname.Hash.create 16};
let add_proc_desc cfg pname pdesc => Procname.Hash.add cfg.proc_desc_table pname pdesc; let add_proc_desc cfg pname pdesc => Typ.Procname.Hash.add cfg.proc_desc_table pname pdesc;
let remove_proc_desc cfg pname => Procname.Hash.remove cfg.proc_desc_table pname; let remove_proc_desc cfg pname => Typ.Procname.Hash.remove cfg.proc_desc_table pname;
let iter_proc_desc cfg f => Procname.Hash.iter f cfg.proc_desc_table; let iter_proc_desc cfg f => Typ.Procname.Hash.iter f cfg.proc_desc_table;
let find_proc_desc_from_name cfg pname => let find_proc_desc_from_name cfg pname =>
try (Some (Procname.Hash.find cfg.proc_desc_table pname)) { try (Some (Typ.Procname.Hash.find cfg.proc_desc_table pname)) {
| Not_found => None | Not_found => None
}; };
@ -48,7 +48,7 @@ let iter_all_nodes sorted::sorted=false f cfg => {
if (not sorted) { if (not sorted) {
iter_proc_desc cfg do_proc_desc iter_proc_desc cfg do_proc_desc
} else { } else {
Procname.Hash.fold Typ.Procname.Hash.fold
( (
fun _ pdesc desc_nodes => fun _ pdesc desc_nodes =>
List.fold List.fold
@ -105,7 +105,7 @@ let check_cfg_connectedness cfg => {
} }
}; };
let do_pdesc pd => { let do_pdesc pd => {
let pname = Procname.to_string (Procdesc.get_proc_name pd); let pname = Typ.Procname.to_string (Procdesc.get_proc_name pd);
let nodes = Procdesc.get_nodes pd; let nodes = Procdesc.get_nodes pd;
let broken = List.exists f::broken_node nodes; let broken = List.exists f::broken_node nodes;
if broken { if broken {
@ -212,7 +212,7 @@ let proc_inline_synthetic_methods cfg pdesc :unit => {
| Sil.Call ret_id (Exp.Const (Const.Cfun pn)) etl loc _ => | Sil.Call ret_id (Exp.Const (Const.Cfun pn)) etl loc _ =>
switch (find_proc_desc_from_name cfg pn) { switch (find_proc_desc_from_name cfg pn) {
| Some pd => | Some pd =>
let is_access = Procname.java_is_access_method pn; let is_access = Typ.Procname.java_is_access_method pn;
let attributes = Procdesc.get_attributes pd; let attributes = Procdesc.get_attributes pd;
let is_synthetic = attributes.is_synthetic_method; let is_synthetic = attributes.is_synthetic_method;
let is_bridge = attributes.is_bridge_method; let is_bridge = attributes.is_bridge_method;
@ -246,7 +246,7 @@ let proc_inline_synthetic_methods cfg pdesc :unit => {
/** Inline the java synthetic methods in the cfg */ /** Inline the java synthetic methods in the cfg */
let inline_java_synthetic_methods cfg => { let inline_java_synthetic_methods cfg => {
let f pname pdesc => let f pname pdesc =>
if (Procname.is_java pname) { if (Typ.Procname.is_java pname) {
proc_inline_synthetic_methods cfg pdesc proc_inline_synthetic_methods cfg pdesc
}; };
iter_proc_desc cfg f iter_proc_desc cfg f
@ -310,7 +310,7 @@ let mark_unchanged_pdescs cfg_new cfg_old => {
let new_procs = cfg_new.proc_desc_table; let new_procs = cfg_new.proc_desc_table;
let mark_pdesc_if_unchanged pname (new_pdesc: Procdesc.t) => let mark_pdesc_if_unchanged pname (new_pdesc: Procdesc.t) =>
try { try {
let old_pdesc = Procname.Hash.find old_procs pname; let old_pdesc = Typ.Procname.Hash.find old_procs pname;
let changed = let changed =
/* in continue_capture mode keep the old changed bit */ /* in continue_capture mode keep the old changed bit */
Config.continue_capture && (Procdesc.get_attributes old_pdesc).changed || Config.continue_capture && (Procdesc.get_attributes old_pdesc).changed ||
@ -319,7 +319,7 @@ let mark_unchanged_pdescs cfg_new cfg_old => {
} { } {
| Not_found => () | Not_found => ()
}; };
Procname.Hash.iter mark_pdesc_if_unchanged new_procs Typ.Procname.Hash.iter mark_pdesc_if_unchanged new_procs
}; };
@ -388,7 +388,7 @@ let specialize_types_proc callee_pdesc resolved_pdesc substitutions => {
} }
| Sil.Call | Sil.Call
return_ids return_ids
(Exp.Const (Const.Cfun (Procname.Java callee_pname_java))) (Exp.Const (Const.Cfun (Typ.Procname.Java callee_pname_java)))
[(Exp.Var id, _), ...origin_args] [(Exp.Var id, _), ...origin_args]
loc loc
call_flags call_flags
@ -396,7 +396,7 @@ let specialize_types_proc callee_pdesc resolved_pdesc substitutions => {
let redirected_typename = Option.value_exn (redirect_typename id); let redirected_typename = Option.value_exn (redirect_typename id);
let redirected_typ = mk_ptr_typ redirected_typename; let redirected_typ = mk_ptr_typ redirected_typename;
let redirected_pname = let redirected_pname =
Procname.replace_class (Procname.Java callee_pname_java) redirected_typename; Typ.Procname.replace_class (Typ.Procname.Java callee_pname_java) redirected_typename;
let args = { let args = {
let other_args = List.map f::(fun (exp, typ) => (convert_exp exp, typ)) origin_args; let other_args = List.map f::(fun (exp, typ) => (convert_exp exp, typ)) origin_args;
[(Exp.Var id, redirected_typ), ...other_args] [(Exp.Var id, redirected_typ), ...other_args]

@ -35,11 +35,11 @@ let create_proc_desc: cfg => ProcAttributes.t => Procdesc.t;
/** Iterate over all the procdesc's */ /** Iterate over all the procdesc's */
let iter_proc_desc: cfg => (Procname.t => Procdesc.t => unit) => unit; let iter_proc_desc: cfg => (Typ.Procname.t => Procdesc.t => unit) => unit;
/** Find the procdesc given the proc name. Return None if not found. */ /** Find the procdesc given the proc name. Return None if not found. */
let find_proc_desc_from_name: cfg => Procname.t => option Procdesc.t; let find_proc_desc_from_name: cfg => Typ.Procname.t => option Procdesc.t;
/** Get all the procedures (defined and declared) */ /** Get all the procedures (defined and declared) */
@ -59,13 +59,13 @@ let check_cfg_connectedness: cfg => unit;
/** Remove the procdesc from the control flow graph. */ /** Remove the procdesc from the control flow graph. */
let remove_proc_desc: cfg => Procname.t => unit; let remove_proc_desc: cfg => Typ.Procname.t => unit;
/** Creates a copy of a procedure description and a list of type substitutions of the form /** Creates a copy of a procedure description and a list of type substitutions of the form
(name, typ) where name is a parameter. The resulting procdesc is isomorphic but (name, typ) where name is a parameter. The resulting procdesc is isomorphic but
all the type of the parameters are replaced in the instructions according to the list. all the type of the parameters are replaced in the instructions according to the list.
The virtual calls are also replaced to match the parameter types */ The virtual calls are also replaced to match the parameter types */
let specialize_types: Procdesc.t => Procname.t => list (Exp.t, Typ.t) => Procdesc.t; let specialize_types: Procdesc.t => Typ.Procname.t => list (Exp.t, Typ.t) => Procdesc.t;
let pp_proc_signatures: Format.formatter => cfg => unit; let pp_proc_signatures: Format.formatter => cfg => unit;

@ -17,7 +17,7 @@ let module L = Logging;
let module F = Format; let module F = Format;
type node = Procname.t; type node = Typ.Procname.t;
type in_out_calls = { type in_out_calls = {
in_calls: int, /** total number of in calls transitively */ in_calls: int, /** total number of in calls transitively */
@ -27,14 +27,14 @@ type in_out_calls = {
type node_info = { type node_info = {
/** defined procedure as opposed to just declared */ /** defined procedure as opposed to just declared */
mutable defined: bool, mutable defined: bool,
mutable parents: Procname.Set.t, mutable parents: Typ.Procname.Set.t,
mutable children: Procname.Set.t, mutable children: Typ.Procname.Set.t,
/** ancestors are computed lazily */ /** ancestors are computed lazily */
mutable ancestors: option Procname.Set.t, mutable ancestors: option Typ.Procname.Set.t,
/** heirs are computed lazily */ /** heirs are computed lazily */
mutable heirs: option Procname.Set.t, mutable heirs: option Typ.Procname.Set.t,
/** recursive dependents are computed lazily */ /** recursive dependents are computed lazily */
mutable recursive_dependents: option Procname.Set.t, mutable recursive_dependents: option Typ.Procname.Set.t,
/** calls are computed lazily */ /** calls are computed lazily */
mutable in_out_calls: option in_out_calls mutable in_out_calls: option in_out_calls
}; };
@ -43,7 +43,7 @@ type node_info = {
/** Type for call graph */ /** Type for call graph */
type t = { type t = {
source: SourceFile.t, /** path for the source file */ source: SourceFile.t, /** path for the source file */
node_map: Procname.Hash.t node_info /** map from node to node_info */ node_map: Typ.Procname.Hash.t node_info /** map from node to node_info */
}; };
let create source_opt => { let create source_opt => {
@ -52,12 +52,12 @@ let create source_opt => {
| None => SourceFile.empty | None => SourceFile.empty
| Some source => source | Some source => source
}; };
{source, node_map: Procname.Hash.create 3} {source, node_map: Typ.Procname.Hash.create 3}
}; };
let add_node g n defined::defined => let add_node g n defined::defined =>
try { try {
let info = Procname.Hash.find g.node_map n; let info = Typ.Procname.Hash.find g.node_map n;
/* defined and disabled only go from false to true /* defined and disabled only go from false to true
to avoid accidental overwrite to false by calling add_edge */ to avoid accidental overwrite to false by calling add_edge */
if defined { if defined {
@ -67,19 +67,19 @@ let add_node g n defined::defined =>
| Not_found => | Not_found =>
let info = { let info = {
defined, defined,
parents: Procname.Set.empty, parents: Typ.Procname.Set.empty,
children: Procname.Set.empty, children: Typ.Procname.Set.empty,
ancestors: None, ancestors: None,
heirs: None, heirs: None,
recursive_dependents: None, recursive_dependents: None,
in_out_calls: None in_out_calls: None
}; };
Procname.Hash.add g.node_map n info Typ.Procname.Hash.add g.node_map n info
}; };
let remove_node_defined g n => let remove_node_defined g n =>
try { try {
let info = Procname.Hash.find g.node_map n; let info = Typ.Procname.Hash.find g.node_map n;
info.defined = false info.defined = false
} { } {
| Not_found => () | Not_found => ()
@ -90,20 +90,20 @@ let add_defined_node g n => add_node g n defined::true;
/** Compute the ancestors of the node, if not already computed */ /** Compute the ancestors of the node, if not already computed */
let compute_ancestors g node => { let compute_ancestors g node => {
let todo = ref (Procname.Set.singleton node); let todo = ref (Typ.Procname.Set.singleton node);
let seen = ref Procname.Set.empty; let seen = ref Typ.Procname.Set.empty;
let result = ref Procname.Set.empty; let result = ref Typ.Procname.Set.empty;
while (not (Procname.Set.is_empty !todo)) { while (not (Typ.Procname.Set.is_empty !todo)) {
let current = Procname.Set.choose !todo; let current = Typ.Procname.Set.choose !todo;
todo := Procname.Set.remove current !todo; todo := Typ.Procname.Set.remove current !todo;
if (not (Procname.Set.mem current !seen)) { if (not (Typ.Procname.Set.mem current !seen)) {
seen := Procname.Set.add current !seen; seen := Typ.Procname.Set.add current !seen;
let info = Procname.Hash.find g current; let info = Typ.Procname.Hash.find g current;
switch info.ancestors { switch info.ancestors {
| Some ancestors => result := Procname.Set.union !result ancestors | Some ancestors => result := Typ.Procname.Set.union !result ancestors
| None => | None =>
result := Procname.Set.union !result info.parents; result := Typ.Procname.Set.union !result info.parents;
todo := Procname.Set.union !todo info.parents todo := Typ.Procname.Set.union !todo info.parents
} }
} }
}; };
@ -113,20 +113,20 @@ let compute_ancestors g node => {
/** Compute the heirs of the node, if not already computed */ /** Compute the heirs of the node, if not already computed */
let compute_heirs g node => { let compute_heirs g node => {
let todo = ref (Procname.Set.singleton node); let todo = ref (Typ.Procname.Set.singleton node);
let seen = ref Procname.Set.empty; let seen = ref Typ.Procname.Set.empty;
let result = ref Procname.Set.empty; let result = ref Typ.Procname.Set.empty;
while (not (Procname.Set.is_empty !todo)) { while (not (Typ.Procname.Set.is_empty !todo)) {
let current = Procname.Set.choose !todo; let current = Typ.Procname.Set.choose !todo;
todo := Procname.Set.remove current !todo; todo := Typ.Procname.Set.remove current !todo;
if (not (Procname.Set.mem current !seen)) { if (not (Typ.Procname.Set.mem current !seen)) {
seen := Procname.Set.add current !seen; seen := Typ.Procname.Set.add current !seen;
let info = Procname.Hash.find g current; let info = Typ.Procname.Hash.find g current;
switch info.heirs { switch info.heirs {
| Some heirs => result := Procname.Set.union !result heirs | Some heirs => result := Typ.Procname.Set.union !result heirs
| None => | None =>
result := Procname.Set.union !result info.children; result := Typ.Procname.Set.union !result info.children;
todo := Procname.Set.union !todo info.children todo := Typ.Procname.Set.union !todo info.children
} }
} }
}; };
@ -136,14 +136,14 @@ let compute_heirs g node => {
/** Compute the ancestors of the node, if not pre-computed already */ /** Compute the ancestors of the node, if not pre-computed already */
let get_ancestors (g: t) node => { let get_ancestors (g: t) node => {
let info = Procname.Hash.find g.node_map node; let info = Typ.Procname.Hash.find g.node_map node;
switch info.ancestors { switch info.ancestors {
| None => | None =>
let ancestors = compute_ancestors g.node_map node; let ancestors = compute_ancestors g.node_map node;
info.ancestors = Some ancestors; info.ancestors = Some ancestors;
let size = Procname.Set.cardinal ancestors; let size = Typ.Procname.Set.cardinal ancestors;
if (size > 1000) { if (size > 1000) {
L.err "%a has %d ancestors@." Procname.pp node size L.err "%a has %d ancestors@." Typ.Procname.pp node size
}; };
ancestors ancestors
| Some ancestors => ancestors | Some ancestors => ancestors
@ -153,14 +153,14 @@ let get_ancestors (g: t) node => {
/** Compute the heirs of the node, if not pre-computed already */ /** Compute the heirs of the node, if not pre-computed already */
let get_heirs (g: t) node => { let get_heirs (g: t) node => {
let info = Procname.Hash.find g.node_map node; let info = Typ.Procname.Hash.find g.node_map node;
switch info.heirs { switch info.heirs {
| None => | None =>
let heirs = compute_heirs g.node_map node; let heirs = compute_heirs g.node_map node;
info.heirs = Some heirs; info.heirs = Some heirs;
let size = Procname.Set.cardinal heirs; let size = Typ.Procname.Set.cardinal heirs;
if (size > 1000) { if (size > 1000) {
L.err "%a has %d heirs@." Procname.pp node size L.err "%a has %d heirs@." Typ.Procname.pp node size
}; };
heirs heirs
| Some heirs => heirs | Some heirs => heirs
@ -169,7 +169,7 @@ let get_heirs (g: t) node => {
let node_defined (g: t) n => let node_defined (g: t) n =>
try { try {
let info = Procname.Hash.find g.node_map n; let info = Typ.Procname.Hash.find g.node_map n;
info.defined info.defined
} { } {
| Not_found => false | Not_found => false
@ -178,37 +178,37 @@ let node_defined (g: t) n =>
let add_edge g nfrom nto => { let add_edge g nfrom nto => {
add_node g nfrom defined::false; add_node g nfrom defined::false;
add_node g nto defined::false; add_node g nto defined::false;
let info_from = Procname.Hash.find g.node_map nfrom; let info_from = Typ.Procname.Hash.find g.node_map nfrom;
let info_to = Procname.Hash.find g.node_map nto; let info_to = Typ.Procname.Hash.find g.node_map nto;
info_from.children = Procname.Set.add nto info_from.children; info_from.children = Typ.Procname.Set.add nto info_from.children;
info_to.parents = Procname.Set.add nfrom info_to.parents info_to.parents = Typ.Procname.Set.add nfrom info_to.parents
}; };
/** iterate over the elements of a node_map in node order */ /** iterate over the elements of a node_map in node order */
let node_map_iter f g => { let node_map_iter f g => {
let table = ref []; let table = ref [];
Procname.Hash.iter (fun node info => table := [(node, info), ...!table]) g.node_map; Typ.Procname.Hash.iter (fun node info => table := [(node, info), ...!table]) g.node_map;
let cmp (n1: Procname.t, _) (n2: Procname.t, _) => Procname.compare n1 n2; let cmp (n1: Typ.Procname.t, _) (n2: Typ.Procname.t, _) => Typ.Procname.compare n1 n2;
List.iter f::(fun (n, info) => f n info) (List.sort cmp::cmp !table) List.iter f::(fun (n, info) => f n info) (List.sort cmp::cmp !table)
}; };
let get_nodes (g: t) => { let get_nodes (g: t) => {
let nodes = ref Procname.Set.empty; let nodes = ref Typ.Procname.Set.empty;
let f node _ => nodes := Procname.Set.add node !nodes; let f node _ => nodes := Typ.Procname.Set.add node !nodes;
node_map_iter f g; node_map_iter f g;
!nodes !nodes
}; };
let compute_calls g node => { let compute_calls g node => {
in_calls: Procname.Set.cardinal (get_ancestors g node), in_calls: Typ.Procname.Set.cardinal (get_ancestors g node),
out_calls: Procname.Set.cardinal (get_heirs g node) out_calls: Typ.Procname.Set.cardinal (get_heirs g node)
}; };
/** Compute the calls of the node, if not pre-computed already */ /** Compute the calls of the node, if not pre-computed already */
let get_calls (g: t) node => { let get_calls (g: t) node => {
let info = Procname.Hash.find g.node_map node; let info = Typ.Procname.Hash.find g.node_map node;
switch info.in_out_calls { switch info.in_out_calls {
| None => | None =>
let calls = compute_calls g node; let calls = compute_calls g node;
@ -219,19 +219,19 @@ let get_calls (g: t) node => {
}; };
let get_all_nodes (g: t) => { let get_all_nodes (g: t) => {
let nodes = Procname.Set.elements (get_nodes g); let nodes = Typ.Procname.Set.elements (get_nodes g);
List.map f::(fun node => (node, get_calls g node)) nodes List.map f::(fun node => (node, get_calls g node)) nodes
}; };
let get_nodes_and_calls (g: t) => let get_nodes_and_calls (g: t) =>
List.filter f::(fun (n, _) => node_defined g n) (get_all_nodes g); List.filter f::(fun (n, _) => node_defined g n) (get_all_nodes g);
let node_get_num_ancestors g n => (n, Procname.Set.cardinal (get_ancestors g n)); let node_get_num_ancestors g n => (n, Typ.Procname.Set.cardinal (get_ancestors g n));
let get_edges (g: t) :list ((node, int), (node, int)) => { let get_edges (g: t) :list ((node, int), (node, int)) => {
let edges = ref []; let edges = ref [];
let f node info => let f node info =>
Procname.Set.iter Typ.Procname.Set.iter
( (
fun nto => fun nto =>
edges := [(node_get_num_ancestors g node, node_get_num_ancestors g nto), ...!edges] edges := [(node_get_num_ancestors g node, node_get_num_ancestors g nto), ...!edges]
@ -243,42 +243,43 @@ let get_edges (g: t) :list ((node, int), (node, int)) => {
/** Return all the children of [n], whether defined or not */ /** Return all the children of [n], whether defined or not */
let get_all_children (g: t) n => (Procname.Hash.find g.node_map n).children; let get_all_children (g: t) n => (Typ.Procname.Hash.find g.node_map n).children;
/** Return the children of [n] which are defined */ /** Return the children of [n] which are defined */
let get_defined_children (g: t) n => Procname.Set.filter (node_defined g) (get_all_children g n); let get_defined_children (g: t) n =>
Typ.Procname.Set.filter (node_defined g) (get_all_children g n);
/** Return the parents of [n] */ /** Return the parents of [n] */
let get_parents (g: t) n => (Procname.Hash.find g.node_map n).parents; let get_parents (g: t) n => (Typ.Procname.Hash.find g.node_map n).parents;
/** Check if [source] recursively calls [dest] */ /** Check if [source] recursively calls [dest] */
let calls_recursively (g: t) source dest => Procname.Set.mem source (get_ancestors g dest); let calls_recursively (g: t) source dest => Typ.Procname.Set.mem source (get_ancestors g dest);
/** Return the children of [n] which are not heirs of [n] */ /** Return the children of [n] which are not heirs of [n] */
let get_nonrecursive_dependents (g: t) n => { let get_nonrecursive_dependents (g: t) n => {
let is_not_recursive pn => not (Procname.Set.mem pn (get_ancestors g n)); let is_not_recursive pn => not (Typ.Procname.Set.mem pn (get_ancestors g n));
let res0 = Procname.Set.filter is_not_recursive (get_all_children g n); let res0 = Typ.Procname.Set.filter is_not_recursive (get_all_children g n);
let res = Procname.Set.filter (node_defined g) res0; let res = Typ.Procname.Set.filter (node_defined g) res0;
res res
}; };
/** Return the ancestors of [n] which are also heirs of [n] */ /** Return the ancestors of [n] which are also heirs of [n] */
let compute_recursive_dependents (g: t) n => { let compute_recursive_dependents (g: t) n => {
let reached_from_n pn => Procname.Set.mem n (get_ancestors g pn); let reached_from_n pn => Typ.Procname.Set.mem n (get_ancestors g pn);
let res0 = Procname.Set.filter reached_from_n (get_ancestors g n); let res0 = Typ.Procname.Set.filter reached_from_n (get_ancestors g n);
let res = Procname.Set.filter (node_defined g) res0; let res = Typ.Procname.Set.filter (node_defined g) res0;
res res
}; };
/** Compute the ancestors of [n] which are also heirs of [n], if not pre-computed already */ /** Compute the ancestors of [n] which are also heirs of [n], if not pre-computed already */
let get_recursive_dependents (g: t) n => { let get_recursive_dependents (g: t) n => {
let info = Procname.Hash.find g.node_map n; let info = Typ.Procname.Hash.find g.node_map n;
switch info.recursive_dependents { switch info.recursive_dependents {
| None => | None =>
let recursive_dependents = compute_recursive_dependents g n; let recursive_dependents = compute_recursive_dependents g n;
@ -291,21 +292,21 @@ let get_recursive_dependents (g: t) n => {
/** Return the nodes dependent on [n] */ /** Return the nodes dependent on [n] */
let get_dependents (g: t) n => let get_dependents (g: t) n =>
Procname.Set.union (get_nonrecursive_dependents g n) (get_recursive_dependents g n); Typ.Procname.Set.union (get_nonrecursive_dependents g n) (get_recursive_dependents g n);
/** Return all the nodes with their defined children */ /** Return all the nodes with their defined children */
let get_nodes_and_defined_children (g: t) => { let get_nodes_and_defined_children (g: t) => {
let nodes = ref Procname.Set.empty; let nodes = ref Typ.Procname.Set.empty;
node_map_iter node_map_iter
( (
fun n info => fun n info =>
if info.defined { if info.defined {
nodes := Procname.Set.add n !nodes nodes := Typ.Procname.Set.add n !nodes
} }
) )
g; g;
let nodes_list = Procname.Set.elements !nodes; let nodes_list = Typ.Procname.Set.elements !nodes;
List.map f::(fun n => (n, get_defined_children g n)) nodes_list List.map f::(fun n => (n, get_defined_children g n)) nodes_list
}; };
@ -321,7 +322,7 @@ let get_nodes_and_edges (g: t) :nodes_and_edges => {
let do_children node nto => edges := [(node, nto), ...!edges]; let do_children node nto => edges := [(node, nto), ...!edges];
let f node info => { let f node info => {
nodes := [(node, info.defined), ...!nodes]; nodes := [(node, info.defined), ...!nodes];
Procname.Set.iter (do_children node) info.children Typ.Procname.Set.iter (do_children node) info.children
}; };
node_map_iter f g; node_map_iter f g;
(!nodes, !edges) (!nodes, !edges)
@ -395,12 +396,12 @@ let pp_graph_dotty get_specs (g: t) fmt => {
} else { } else {
"diamond" "diamond"
}; };
let pp_node fmt (n, _) => F.fprintf fmt "\"%s\"" (Procname.to_filename n); let pp_node fmt (n, _) => F.fprintf fmt "\"%s\"" (Typ.Procname.to_filename n);
let pp_node_label fmt (n, calls) => let pp_node_label fmt (n, calls) =>
F.fprintf F.fprintf
fmt fmt
"\"%a | calls=%d %d | specs=%d)\"" "\"%a | calls=%d %d | specs=%d)\""
Procname.pp Typ.Procname.pp
n n
calls.in_calls calls.in_calls
calls.out_calls calls.out_calls

@ -19,7 +19,7 @@ type in_out_calls = {
type t; /** the type of a call graph */ type t; /** the type of a call graph */
/** A call graph consists of a set of nodes (Procname.t), and edges between them. /** A call graph consists of a set of nodes (Typ.Procname.t), and edges between them.
A node can be defined or undefined (to represent whether we have code for it). A node can be defined or undefined (to represent whether we have code for it).
In an edge from [n1] to [n2], indicating that [n1] calls [n2], In an edge from [n1] to [n2], indicating that [n1] calls [n2],
[n1] is the parent and [n2] is the child. [n1] is the parent and [n2] is the child.
@ -28,15 +28,15 @@ type t; /** the type of a call graph */
/** [add_edge cg f t] adds an edge from [f] to [t] in the call graph [cg]. /** [add_edge cg f t] adds an edge from [f] to [t] in the call graph [cg].
The nodes are also added as undefined, unless already present. */ The nodes are also added as undefined, unless already present. */
let add_edge: t => Procname.t => Procname.t => unit; let add_edge: t => Typ.Procname.t => Typ.Procname.t => unit;
/** Add a node to the call graph as defined */ /** Add a node to the call graph as defined */
let add_defined_node: t => Procname.t => unit; let add_defined_node: t => Typ.Procname.t => unit;
/** Check if [source] recursively calls [dest] */ /** Check if [source] recursively calls [dest] */
let calls_recursively: t => Procname.t => Procname.t => bool; let calls_recursively: t => Typ.Procname.t => Typ.Procname.t => bool;
/** Create an empty call graph */ /** Create an empty call graph */
@ -49,55 +49,55 @@ let extend: t => t => unit;
/** Return all the children of [n], whether defined or not */ /** Return all the children of [n], whether defined or not */
let get_all_children: t => Procname.t => Procname.Set.t; let get_all_children: t => Typ.Procname.t => Typ.Procname.Set.t;
/** Compute the ancestors of the node, if not pre-computed already */ /** Compute the ancestors of the node, if not pre-computed already */
let get_ancestors: t => Procname.t => Procname.Set.t; let get_ancestors: t => Typ.Procname.t => Typ.Procname.Set.t;
/** Compute the heirs of the node, if not pre-computed already */ /** Compute the heirs of the node, if not pre-computed already */
let get_heirs: t => Procname.t => Procname.Set.t; let get_heirs: t => Typ.Procname.t => Typ.Procname.Set.t;
/** Return the in/out calls of the node */ /** Return the in/out calls of the node */
let get_calls: t => Procname.t => in_out_calls; let get_calls: t => Typ.Procname.t => in_out_calls;
/** Return the list of nodes which are defined */ /** Return the list of nodes which are defined */
let get_defined_nodes: t => list Procname.t; let get_defined_nodes: t => list Typ.Procname.t;
/** Return the children of [n] which are defined */ /** Return the children of [n] which are defined */
let get_defined_children: t => Procname.t => Procname.Set.t; let get_defined_children: t => Typ.Procname.t => Typ.Procname.Set.t;
/** Return the nodes dependent on [n] */ /** Return the nodes dependent on [n] */
let get_dependents: t => Procname.t => Procname.Set.t; let get_dependents: t => Typ.Procname.t => Typ.Procname.Set.t;
/** Return the list of nodes with calls */ /** Return the list of nodes with calls */
let get_nodes_and_calls: t => list (Procname.t, in_out_calls); let get_nodes_and_calls: t => list (Typ.Procname.t, in_out_calls);
/** Return all the nodes with their defined children */ /** Return all the nodes with their defined children */
let get_nodes_and_defined_children: t => list (Procname.t, Procname.Set.t); let get_nodes_and_defined_children: t => list (Typ.Procname.t, Typ.Procname.Set.t);
/** Return the list of nodes, with defined flag, and the list of edges */ /** Return the list of nodes, with defined flag, and the list of edges */
let get_nodes_and_edges: t => (list (Procname.t, bool), list (Procname.t, Procname.t)); let get_nodes_and_edges: t => (list (Typ.Procname.t, bool), list (Typ.Procname.t, Typ.Procname.t));
/** Return the children of [n] which are not heirs of [n] and are defined */ /** Return the children of [n] which are not heirs of [n] and are defined */
let get_nonrecursive_dependents: t => Procname.t => Procname.Set.t; let get_nonrecursive_dependents: t => Typ.Procname.t => Typ.Procname.Set.t;
/** Return the parents of [n] */ /** Return the parents of [n] */
let get_parents: t => Procname.t => Procname.Set.t; let get_parents: t => Typ.Procname.t => Typ.Procname.Set.t;
/** Return the ancestors of [n] which are also heirs of [n] */ /** Return the ancestors of [n] which are also heirs of [n] */
let get_recursive_dependents: t => Procname.t => Procname.Set.t; let get_recursive_dependents: t => Typ.Procname.t => Typ.Procname.Set.t;
/** Return the path of the source file */ /** Return the path of the source file */
@ -109,15 +109,15 @@ let load_from_file: DB.filename => option t;
/** Returns true if the node is defined */ /** Returns true if the node is defined */
let node_defined: t => Procname.t => bool; let node_defined: t => Typ.Procname.t => bool;
/** Remove the defined flag from a node, if it exists. */ /** Remove the defined flag from a node, if it exists. */
let remove_node_defined: t => Procname.t => unit; let remove_node_defined: t => Typ.Procname.t => unit;
/** Print the call graph as a dotty file. */ /** Print the call graph as a dotty file. */
let save_call_graph_dotty: SourceFile.t => (Procname.t => list 'a) => t => unit; let save_call_graph_dotty: SourceFile.t => (Typ.Procname.t => list 'a) => t => unit;
/** Save a call graph into a file */ /** Save a call graph into a file */

@ -17,7 +17,7 @@ let module F = Format;
type t = type t =
| Cint IntLit.t /** integer constants */ | Cint IntLit.t /** integer constants */
| Cfun Procname.t /** function names */ | Cfun Typ.Procname.t /** function names */
| Cstr string /** string constants */ | Cstr string /** string constants */
| Cfloat float /** float constants */ | Cfloat float /** float constants */
| Cclass Ident.name /** class constant */ | Cclass Ident.name /** class constant */
@ -43,8 +43,8 @@ let pp pe f =>
| Cint i => IntLit.pp f i | Cint i => IntLit.pp f i
| Cfun fn => | Cfun fn =>
switch pe.Pp.kind { switch pe.Pp.kind {
| HTML => F.fprintf f "_fun_%s" (Escape.escape_xml (Procname.to_string fn)) | HTML => F.fprintf f "_fun_%s" (Escape.escape_xml (Typ.Procname.to_string fn))
| _ => F.fprintf f "_fun_%s" (Procname.to_string fn) | _ => F.fprintf f "_fun_%s" (Typ.Procname.to_string fn)
} }
| Cstr s => F.fprintf f "\"%s\"" (String.escaped s) | Cstr s => F.fprintf f "\"%s\"" (String.escaped s)
| Cfloat v => F.fprintf f "%f" v | Cfloat v => F.fprintf f "%f" v

@ -19,7 +19,7 @@ let module F = Format;
/** Constants */ /** Constants */
type t = type t =
| Cint IntLit.t /** integer constants */ | Cint IntLit.t /** integer constants */
| Cfun Procname.t /** function names */ | Cfun Typ.Procname.t /** function names */
| Cstr string /** string constants */ | Cstr string /** string constants */
| Cfloat float /** float constants */ | Cfloat float /** float constants */
| Cclass Ident.name /** class constant */ | Cclass Ident.name /** class constant */

@ -47,7 +47,7 @@ let rec to_string =
fun fun
| Darray de1 de2 => to_string de1 ^ "[" ^ to_string de2 ^ "]" | Darray de1 de2 => to_string de1 ^ "[" ^ to_string de2 ^ "]"
| Dbinop op de1 de2 => "(" ^ to_string de1 ^ Binop.str Pp.text op ^ to_string de2 ^ ")" | Dbinop op de1 de2 => "(" ^ to_string de1 ^ Binop.str Pp.text op ^ to_string de2 ^ ")"
| Dconst (Cfun pn) => Procname.to_simplified_string pn | Dconst (Cfun pn) => Typ.Procname.to_simplified_string pn
| Dconst c => Const.to_string c | Dconst c => Const.to_string c
| Dderef de => "*" ^ to_string de | Dderef de => "*" ^ to_string de
| Dfcall fun_dexp args _ {cf_virtual: isvirtual} => { | Dfcall fun_dexp args _ {cf_virtual: isvirtual} => {
@ -65,8 +65,8 @@ let rec to_string =
| Dconst (Cfun pname) => { | Dconst (Cfun pname) => {
let s = let s =
switch pname { switch pname {
| Procname.Java pname_java => Procname.java_get_method pname_java | Typ.Procname.Java pname_java => Typ.Procname.java_get_method pname_java
| _ => Procname.to_string pname | _ => Typ.Procname.to_string pname
}; };
F.fprintf fmt "%s" s F.fprintf fmt "%s" s
} }

@ -22,7 +22,7 @@ type _ident = Ident.t;
let compare__ident x y => Ident.compare y x; let compare__ident x y => Ident.compare y x;
type closure = {name: Procname.t, captured_vars: list (t, Pvar.t, Typ.t)} [@@deriving compare] type closure = {name: Typ.Procname.t, captured_vars: list (t, Pvar.t, Typ.t)} [@@deriving compare]
/** dynamically determined length of an array value, if any */ /** dynamically determined length of an array value, if any */
and dynamic_length = option t [@@deriving compare] and dynamic_length = option t [@@deriving compare]
/** Program expressions. */ /** Program expressions. */

@ -15,7 +15,7 @@ let module L = Logging;
let module F = Format; let module F = Format;
type closure = {name: Procname.t, captured_vars: list (t, Pvar.t, Typ.t)} [@@deriving compare] type closure = {name: Typ.Procname.t, captured_vars: list (t, Pvar.t, Typ.t)} [@@deriving compare]
/** dynamically determined length of an array value, if any */ /** dynamically determined length of an array value, if any */
and dynamic_length = option t [@@deriving compare] and dynamic_length = option t [@@deriving compare]
/** Program expressions. */ /** Program expressions. */

@ -185,7 +185,7 @@ struct
F.fprintf fmt " %s" pr_str F.fprintf fmt " %s" pr_str
(** File name for the node, given the procedure name and node id *) (** File name for the node, given the procedure name and node id *)
let node_filename pname id = (Procname.to_filename pname) ^ "_node" ^ string_of_int id let node_filename pname id = (Typ.Procname.to_filename pname) ^ "_node" ^ string_of_int id
(** Print an html link to the given node. *) (** Print an html link to the given node. *)
let pp_node_link path_to_root pname ~description ~preds ~succs ~exn ~isvisited ~isproof fmt id = let pp_node_link path_to_root pname ~description ~preds ~succs ~exn ~isvisited ~isproof fmt id =
@ -219,7 +219,7 @@ struct
(** Print an html link to the given proc *) (** Print an html link to the given proc *)
let pp_proc_link path_to_root proc_name fmt text = let pp_proc_link path_to_root proc_name fmt text =
pp_link ~path: (path_to_root @ [Procname.to_filename proc_name]) fmt text pp_link ~path: (path_to_root @ [Typ.Procname.to_filename proc_name]) fmt text
(** Print an html link to the given line number of the current source file *) (** Print an html link to the given line number of the current source file *)
let pp_line_link ?(with_name = false) ?(text = None) source path_to_root fmt linenum = let pp_line_link ?(with_name = false) ?(text = None) source path_to_root fmt linenum =

@ -24,7 +24,7 @@ module Html : sig
val modified_during_analysis : SourceFile.t -> DB.Results_dir.path -> bool val modified_during_analysis : SourceFile.t -> DB.Results_dir.path -> bool
(** File name for the node, given the procedure name and node id *) (** File name for the node, given the procedure name and node id *)
val node_filename : Procname.t -> int -> string val node_filename : Typ.Procname.t -> int -> string
(** Open an Html file to append data *) (** Open an Html file to append data *)
val open_out : SourceFile.t -> DB.Results_dir.path -> Unix.File_descr.t * Format.formatter val open_out : SourceFile.t -> DB.Results_dir.path -> Unix.File_descr.t * Format.formatter
@ -45,13 +45,13 @@ module Html : sig
[path_to_root] is the path to the dir for the procedure in the spec db. [path_to_root] is the path to the dir for the procedure in the spec db.
[id] is the node identifier. *) [id] is the node identifier. *)
val pp_node_link : val pp_node_link :
DB.Results_dir.path -> Procname.t -> DB.Results_dir.path -> Typ.Procname.t ->
description:string -> preds:int list -> succs:int list -> exn:int list -> description:string -> preds:int list -> succs:int list -> exn:int list ->
isvisited:bool -> isproof:bool -> Format.formatter -> int -> unit isvisited:bool -> isproof:bool -> Format.formatter -> int -> unit
(** Print an html link to the given proc *) (** Print an html link to the given proc *)
val pp_proc_link : val pp_proc_link :
DB.Results_dir.path -> Procname.t -> Format.formatter -> string -> unit DB.Results_dir.path -> Typ.Procname.t -> Format.formatter -> string -> unit
(** Print an html link given node id and session *) (** Print an html link given node id and session *)
val pp_session_link : val pp_session_link :

@ -11,18 +11,18 @@
open! IStd open! IStd
let errLogMap = ref Procname.Map.empty let errLogMap = ref Typ.Procname.Map.empty
let exists_issues () = let exists_issues () =
not (Procname.Map.is_empty !errLogMap) not (Typ.Procname.Map.is_empty !errLogMap)
let get_err_log procname = let get_err_log procname =
try Procname.Map.find procname !errLogMap try Typ.Procname.Map.find procname !errLogMap
with Not_found -> with Not_found ->
let errlog = Errlog.empty () in let errlog = Errlog.empty () in
errLogMap := Procname.Map.add procname errlog !errLogMap; errlog errLogMap := Typ.Procname.Map.add procname errlog !errLogMap; errlog
let lint_issues_serializer : (Errlog.t Procname.Map.t) Serialization.serializer = let lint_issues_serializer : (Errlog.t Typ.Procname.Map.t) Serialization.serializer =
Serialization.create_serializer Serialization.Key.lint_issues Serialization.create_serializer Serialization.Key.lint_issues
(** Save issues to a file *) (** Save issues to a file *)
@ -41,7 +41,7 @@ let load_issues_to_errlog_map dir =
let file = DB.filename_from_string (Filename.concat issues_dir issues_file) in let file = DB.filename_from_string (Filename.concat issues_dir issues_file) in
match load_issues file with match load_issues file with
| Some map -> | Some map ->
errLogMap := Procname.Map.merge ( errLogMap := Typ.Procname.Map.merge (
fun _ issues1 issues2 -> fun _ issues1 issues2 ->
match issues1, issues2 with match issues1, issues2 with
| Some issues1, Some issues2 -> | Some issues1, Some issues2 ->

@ -11,15 +11,15 @@ open! IStd
(** Module to store a set of issues per procedure *) (** Module to store a set of issues per procedure *)
val errLogMap : Errlog.t Procname.Map.t ref val errLogMap : Errlog.t Typ.Procname.Map.t ref
val exists_issues : unit -> bool val exists_issues : unit -> bool
(** Save issues to a file *) (** Save issues to a file *)
val get_err_log : Procname.t -> Errlog.t val get_err_log : Typ.Procname.t -> Errlog.t
(** Load issues from the given file *) (** Load issues from the given file *)
val store_issues : DB.filename -> Errlog.t Procname.Map.t -> unit val store_issues : DB.filename -> Errlog.t Typ.Procname.Map.t -> unit
(** Load all the lint issues in the given dir and update the issues map *) (** Load all the lint issues in the given dir and update the issues map *)
val load_issues_to_errlog_map : string -> unit val load_issues_to_errlog_map : string -> unit

@ -230,7 +230,7 @@ let at_line tags loc =
at_line_tag tags Tags.line loc at_line_tag tags Tags.line loc
let call_to tags proc_name = let call_to tags proc_name =
let proc_name_str = Procname.to_simplified_string proc_name in let proc_name_str = Typ.Procname.to_simplified_string proc_name in
Tags.add tags Tags.call_procedure proc_name_str; Tags.add tags Tags.call_procedure proc_name_str;
"call to " ^ proc_name_str "call to " ^ proc_name_str
@ -258,10 +258,10 @@ let format_field f =
let format_method pname = let format_method pname =
match pname with match pname with
| Procname.Java pname_java -> | Typ.Procname.Java pname_java ->
Procname.java_get_method pname_java Typ.Procname.java_get_method pname_java
| _ -> | _ ->
Procname.to_string pname Typ.Procname.to_string pname
let mem_dyn_allocated = "memory dynamically allocated" let mem_dyn_allocated = "memory dynamically allocated"
let lock_acquired = "lock acquired" let lock_acquired = "lock acquired"
@ -316,18 +316,18 @@ let deref_str_weak_variable_in_block proc_name_opt nullable_obj_str =
let deref_str_nil_argument_in_variadic_method pn total_args arg_number = let deref_str_nil_argument_in_variadic_method pn total_args arg_number =
let tags = Tags.create () in let tags = Tags.create () in
let function_method, nil_null = let function_method, nil_null =
if Procname.is_c_method pn then ("method", "nil") else ("function", "null") in if Typ.Procname.is_c_method pn then ("method", "nil") else ("function", "null") in
let problem_str = let problem_str =
Printf.sprintf Printf.sprintf
"could be %s which results in a call to %s with %d arguments instead of %d \ "could be %s which results in a call to %s with %d arguments instead of %d \
(%s indicates that the last argument of this variadic %s has been reached)" (%s indicates that the last argument of this variadic %s has been reached)"
nil_null (Procname.to_simplified_string pn) arg_number (total_args - 1) nil_null function_method in nil_null (Typ.Procname.to_simplified_string pn) arg_number (total_args - 1) nil_null function_method in
_deref_str_null None problem_str tags _deref_str_null None problem_str tags
(** dereference strings for an undefined value coming from the given procedure *) (** dereference strings for an undefined value coming from the given procedure *)
let deref_str_undef (proc_name, loc) = let deref_str_undef (proc_name, loc) =
let tags = Tags.create () in let tags = Tags.create () in
let proc_name_str = Procname.to_simplified_string proc_name in let proc_name_str = Typ.Procname.to_simplified_string proc_name in
Tags.add tags Tags.call_procedure proc_name_str; Tags.add tags Tags.call_procedure proc_name_str;
{ tags = tags; { tags = tags;
value_pre = Some (pointer_or_object ()); value_pre = Some (pointer_or_object ());
@ -407,7 +407,7 @@ let deref_str_uninitialized alloc_att_opt =
(** Java unchecked exceptions errors *) (** Java unchecked exceptions errors *)
let java_unchecked_exn_desc proc_name exn_name pre_str : error_desc = let java_unchecked_exn_desc proc_name exn_name pre_str : error_desc =
{ no_desc with descriptions = [ { no_desc with descriptions = [
Procname.to_string proc_name; Typ.Procname.to_string proc_name;
"can throw " ^ (Typename.name exn_name); "can throw " ^ (Typename.name exn_name);
"whenever " ^ pre_str]; "whenever " ^ pre_str];
} }
@ -429,10 +429,10 @@ let desc_context_leak pname context_typ fieldname leak_path : error_desc =
path_prefix ^ context_str in path_prefix ^ context_str in
let preamble = let preamble =
let pname_str = match pname with let pname_str = match pname with
| Procname.Java pname_java -> | Typ.Procname.Java pname_java ->
Printf.sprintf "%s.%s" Printf.sprintf "%s.%s"
(Procname.java_get_class_name pname_java) (Typ.Procname.java_get_class_name pname_java)
(Procname.java_get_method pname_java) (Typ.Procname.java_get_method pname_java)
| _ -> | _ ->
"" in "" in
"Context " ^ context_str ^ " may leak during method " ^ pname_str ^ ":\n" in "Context " ^ context_str ^ " may leak during method " ^ pname_str ^ ":\n" in
@ -450,7 +450,7 @@ let desc_unsafe_guarded_by_access pname accessed_fld guarded_by_str loc =
guarded_by_str guarded_by_str
line_info line_info
guarded_by_str guarded_by_str
(Procname.to_string pname) (Typ.Procname.to_string pname)
annot_str in annot_str in
{ no_desc with descriptions = [msg]; } { no_desc with descriptions = [msg]; }
@ -565,13 +565,13 @@ let desc_allocation_mismatch alloc dealloc =
let tag_fun, tag_call, tag_line = let tag_fun, tag_call, tag_line =
if is_alloc then Tags.alloc_function, Tags.alloc_call, Tags.alloc_line if is_alloc then Tags.alloc_function, Tags.alloc_call, Tags.alloc_line
else Tags.dealloc_function, Tags.dealloc_call, Tags.dealloc_line in else Tags.dealloc_function, Tags.dealloc_call, Tags.dealloc_line in
Tags.add tags tag_fun (Procname.to_simplified_string primitive_pname); Tags.add tags tag_fun (Typ.Procname.to_simplified_string primitive_pname);
Tags.add tags tag_call (Procname.to_simplified_string called_pname); Tags.add tags tag_call (Typ.Procname.to_simplified_string called_pname);
Tags.add tags tag_line (string_of_int loc.Location.line); Tags.add tags tag_line (string_of_int loc.Location.line);
let by_call = let by_call =
if Procname.equal primitive_pname called_pname then "" if Typ.Procname.equal primitive_pname called_pname then ""
else " by call to " ^ Procname.to_simplified_string called_pname in else " by call to " ^ Typ.Procname.to_simplified_string called_pname in
"using " ^ Procname.to_simplified_string primitive_pname ^ by_call ^ " " ^ at_line (Tags.create ()) (* ignore the tag *) loc in "using " ^ Typ.Procname.to_simplified_string primitive_pname ^ by_call ^ " " ^ at_line (Tags.create ()) (* ignore the tag *) loc in
let description = Format.sprintf let description = Format.sprintf
"%s %s is deallocated %s" "%s %s is deallocated %s"
mem_dyn_allocated mem_dyn_allocated
@ -823,12 +823,12 @@ let desc_unary_minus_applied_to_unsigned_expression expr_str_opt typ_str loc =
let desc_skip_function proc_name = let desc_skip_function proc_name =
let tags = Tags.create () in let tags = Tags.create () in
let proc_name_str = Procname.to_string proc_name in let proc_name_str = Typ.Procname.to_string proc_name in
Tags.add tags Tags.value proc_name_str; Tags.add tags Tags.value proc_name_str;
{ no_desc with descriptions = [proc_name_str]; tags = !tags } { no_desc with descriptions = [proc_name_str]; tags = !tags }
let desc_inherently_dangerous_function proc_name = let desc_inherently_dangerous_function proc_name =
let proc_name_str = Procname.to_string proc_name in let proc_name_str = Typ.Procname.to_string proc_name in
let tags = Tags.create () in let tags = Tags.create () in
Tags.add tags Tags.value proc_name_str; Tags.add tags Tags.value proc_name_str;
{ no_desc with descriptions = [proc_name_str]; tags = !tags } { no_desc with descriptions = [proc_name_str]; tags = !tags }

@ -141,16 +141,16 @@ val error_desc_get_dotty : error_desc -> string option
type deref_str type deref_str
(** dereference strings for null dereference *) (** dereference strings for null dereference *)
val deref_str_null : Procname.t option -> deref_str val deref_str_null : Typ.Procname.t option -> deref_str
(** dereference strings for null dereference due to Nullable annotation *) (** dereference strings for null dereference due to Nullable annotation *)
val deref_str_nullable : Procname.t option -> string -> deref_str val deref_str_nullable : Typ.Procname.t option -> string -> deref_str
(** dereference strings for null dereference due to weak captured variable in block *) (** dereference strings for null dereference due to weak captured variable in block *)
val deref_str_weak_variable_in_block : Procname.t option -> string -> deref_str val deref_str_weak_variable_in_block : Typ.Procname.t option -> string -> deref_str
(** dereference strings for an undefined value coming from the given procedure *) (** dereference strings for an undefined value coming from the given procedure *)
val deref_str_undef : Procname.t * Location.t -> deref_str val deref_str_undef : Typ.Procname.t * Location.t -> deref_str
(** dereference strings for a freed pointer dereference *) (** dereference strings for a freed pointer dereference *)
val deref_str_freed : PredSymb.res_action -> deref_str val deref_str_freed : PredSymb.res_action -> deref_str
@ -165,7 +165,7 @@ val deref_str_array_bound : IntLit.t option -> IntLit.t option -> deref_str
val deref_str_uninitialized : Sil.atom option -> deref_str val deref_str_uninitialized : Sil.atom option -> deref_str
(** dereference strings for nonterminal nil arguments in c/objc variadic methods *) (** dereference strings for nonterminal nil arguments in c/objc variadic methods *)
val deref_str_nil_argument_in_variadic_method : Procname.t -> int -> int -> deref_str val deref_str_nil_argument_in_variadic_method : Typ.Procname.t -> int -> int -> deref_str
(** dereference strings for a pointer size mismatch *) (** dereference strings for a pointer size mismatch *)
val deref_str_pointer_size_mismatch : Typ.t -> Typ.t -> deref_str val deref_str_pointer_size_mismatch : Typ.t -> Typ.t -> deref_str
@ -188,10 +188,10 @@ val is_field_not_null_checked_desc : error_desc -> bool
val is_parameter_field_not_null_checked_desc : error_desc -> bool val is_parameter_field_not_null_checked_desc : error_desc -> bool
val desc_allocation_mismatch : val desc_allocation_mismatch :
Procname.t * Procname.t * Location.t -> Procname.t * Procname.t * Location.t -> error_desc Typ.Procname.t * Typ.Procname.t * Location.t -> Typ.Procname.t * Typ.Procname.t * Location.t -> error_desc
val desc_class_cast_exception : val desc_class_cast_exception :
Procname.t option -> string -> string -> string option -> Location.t -> error_desc Typ.Procname.t option -> string -> string -> string option -> Location.t -> error_desc
val desc_comparing_floats_for_equality : Location.t -> error_desc val desc_comparing_floats_for_equality : Location.t -> error_desc
@ -199,13 +199,13 @@ val desc_condition_is_assignment : Location.t -> error_desc
val desc_condition_always_true_false : IntLit.t -> string option -> Location.t -> error_desc val desc_condition_always_true_false : IntLit.t -> string option -> Location.t -> error_desc
val desc_deallocate_stack_variable : string -> Procname.t -> Location.t -> error_desc val desc_deallocate_stack_variable : string -> Typ.Procname.t -> Location.t -> error_desc
val desc_deallocate_static_memory : string -> Procname.t -> Location.t -> error_desc val desc_deallocate_static_memory : string -> Typ.Procname.t -> Location.t -> error_desc
val desc_divide_by_zero : string -> Location.t -> error_desc val desc_divide_by_zero : string -> Location.t -> error_desc
val desc_empty_vector_access : Procname.t option -> string -> Location.t -> error_desc val desc_empty_vector_access : Typ.Procname.t option -> string -> Location.t -> error_desc
val is_empty_vector_access_desc : error_desc -> bool val is_empty_vector_access_desc : error_desc -> bool
@ -219,14 +219,14 @@ val desc_buffer_overrun : string -> string -> error_desc
val desc_null_test_after_dereference : string -> int -> Location.t -> error_desc val desc_null_test_after_dereference : string -> int -> Location.t -> error_desc
val java_unchecked_exn_desc : Procname.t -> Typename.t -> string -> error_desc val java_unchecked_exn_desc : Typ.Procname.t -> Typename.t -> string -> error_desc
val desc_context_leak : val desc_context_leak :
Procname.t -> Typ.t -> Ident.fieldname -> Typ.Procname.t -> Typ.t -> Ident.fieldname ->
(Ident.fieldname option * Typ.t) list -> error_desc (Ident.fieldname option * Typ.t) list -> error_desc
val desc_fragment_retains_view : val desc_fragment_retains_view :
Typ.t -> Ident.fieldname -> Typ.t -> Procname.t -> error_desc Typ.t -> Ident.fieldname -> Typ.t -> Typ.Procname.t -> error_desc
(* Create human-readable error description for assertion failures *) (* Create human-readable error description for assertion failures *)
val desc_custom_error : Location.t -> error_desc val desc_custom_error : Location.t -> error_desc
@ -236,7 +236,7 @@ type pnm_kind =
| Pnm_bounds | Pnm_bounds
| Pnm_dangling | Pnm_dangling
val desc_precondition_not_met : pnm_kind option -> Procname.t -> Location.t -> error_desc val desc_precondition_not_met : pnm_kind option -> Typ.Procname.t -> Location.t -> error_desc
val desc_return_expression_required : string -> Location.t -> error_desc val desc_return_expression_required : string -> Location.t -> error_desc
@ -250,21 +250,21 @@ val desc_registered_observer_being_deallocated : Pvar.t -> Location.t -> error_d
val desc_return_statement_missing : Location.t -> error_desc val desc_return_statement_missing : Location.t -> error_desc
val desc_return_value_ignored : Procname.t -> Location.t -> error_desc val desc_return_value_ignored : Typ.Procname.t -> Location.t -> error_desc
val desc_stack_variable_address_escape : string -> string option -> Location.t -> error_desc val desc_stack_variable_address_escape : string -> string option -> Location.t -> error_desc
val desc_skip_function : Procname.t -> error_desc val desc_skip_function : Typ.Procname.t -> error_desc
val desc_inherently_dangerous_function : Procname.t -> error_desc val desc_inherently_dangerous_function : Typ.Procname.t -> error_desc
val desc_unary_minus_applied_to_unsigned_expression : val desc_unary_minus_applied_to_unsigned_expression :
string option -> string -> Location.t -> error_desc string option -> string -> Location.t -> error_desc
val desc_unsafe_guarded_by_access : val desc_unsafe_guarded_by_access :
Procname.t -> Ident.fieldname -> string -> Location.t -> error_desc Typ.Procname.t -> Ident.fieldname -> string -> Location.t -> error_desc
val desc_tainted_value_reaching_sensitive_function : val desc_tainted_value_reaching_sensitive_function :
PredSymb.taint_kind -> string -> Procname.t -> Procname.t -> Location.t -> error_desc PredSymb.taint_kind -> string -> Typ.Procname.t -> Typ.Procname.t -> Location.t -> error_desc
val desc_uninitialized_dangling_pointer_deref : deref_str -> string -> Location.t -> error_desc val desc_uninitialized_dangling_pointer_deref : deref_str -> string -> Location.t -> error_desc

@ -84,7 +84,7 @@ type dangling_kind =
/** position in a path: proc name, node id */ /** position in a path: proc name, node id */
type path_pos = (Procname.t, int) [@@deriving compare]; type path_pos = (Typ.Procname.t, int) [@@deriving compare];
let equal_path_pos = [%compare.equal : path_pos]; let equal_path_pos = [%compare.equal : path_pos];
@ -96,14 +96,14 @@ type taint_kind =
| Tk_unknown | Tk_unknown
[@@deriving compare]; [@@deriving compare];
type taint_info = {taint_source: Procname.t, taint_kind: taint_kind} [@@deriving compare]; type taint_info = {taint_source: Typ.Procname.t, taint_kind: taint_kind} [@@deriving compare];
/** acquire/release action on a resource */ /** acquire/release action on a resource */
type res_action = { type res_action = {
ra_kind: res_act_kind, /** kind of action */ ra_kind: res_act_kind, /** kind of action */
ra_res: resource, /** kind of resource */ ra_res: resource, /** kind of resource */
ra_pname: Procname.t, /** name of the procedure used to acquire/release the resource */ ra_pname: Typ.Procname.t, /** name of the procedure used to acquire/release the resource */
ra_loc: Location.t, /** location of the acquire/release */ ra_loc: Location.t, /** location of the acquire/release */
ra_vpath: DecompiledExp.vpath /** vpath of the resource value */ ra_vpath: DecompiledExp.vpath /** vpath of the resource value */
}; };
@ -139,7 +139,7 @@ type t =
| Aautorelease | Aautorelease
| Adangling dangling_kind /** dangling pointer */ | Adangling dangling_kind /** dangling pointer */
/** undefined value obtained by calling the given procedure, plus its return value annots */ /** undefined value obtained by calling the given procedure, plus its return value annots */
| Aundef Procname.t _annot_item _location _path_pos | Aundef Typ.Procname.t _annot_item _location _path_pos
| Ataint taint_info | Ataint taint_info
| Auntaint taint_info | Auntaint taint_info
| Alocked | Alocked
@ -149,7 +149,7 @@ type t =
/** attributed exp is null due to a call to a method with given path as null receiver */ /** attributed exp is null due to a call to a method with given path as null receiver */
| Aobjc_null | Aobjc_null
/** value was returned from a call to the given procedure, plus the annots of the return value */ /** value was returned from a call to the given procedure, plus the annots of the return value */
| Aretval Procname.t Annot.Item.t | Aretval Typ.Procname.t Annot.Item.t
/** denotes an object registered as an observers to a notification center */ /** denotes an object registered as an observers to a notification center */
| Aobserver | Aobserver
/** denotes an object unsubscribed from observers of a notification center */ /** denotes an object unsubscribed from observers of a notification center */
@ -162,19 +162,19 @@ let equal = [%compare.equal : t];
/** name of the allocation function for the given memory kind */ /** name of the allocation function for the given memory kind */
let mem_alloc_pname = let mem_alloc_pname =
fun fun
| Mmalloc => Procname.from_string_c_fun "malloc" | Mmalloc => Typ.Procname.from_string_c_fun "malloc"
| Mnew => Procname.from_string_c_fun "new" | Mnew => Typ.Procname.from_string_c_fun "new"
| Mnew_array => Procname.from_string_c_fun "new[]" | Mnew_array => Typ.Procname.from_string_c_fun "new[]"
| Mobjc => Procname.from_string_c_fun "alloc"; | Mobjc => Typ.Procname.from_string_c_fun "alloc";
/** name of the deallocation function for the given memory kind */ /** name of the deallocation function for the given memory kind */
let mem_dealloc_pname = let mem_dealloc_pname =
fun fun
| Mmalloc => Procname.from_string_c_fun "free" | Mmalloc => Typ.Procname.from_string_c_fun "free"
| Mnew => Procname.from_string_c_fun "delete" | Mnew => Typ.Procname.from_string_c_fun "delete"
| Mnew_array => Procname.from_string_c_fun "delete[]" | Mnew_array => Typ.Procname.from_string_c_fun "delete[]"
| Mobjc => Procname.from_string_c_fun "dealloc"; | Mobjc => Typ.Procname.from_string_c_fun "dealloc";
/** Categories of attributes */ /** Categories of attributes */
@ -244,7 +244,7 @@ let to_string pe =>
}; };
name ^ name ^
Binop.str pe Lt ^ Binop.str pe Lt ^
Procname.to_string ra.ra_pname ^ Typ.Procname.to_string ra.ra_pname ^
":" ^ string_of_int ra.ra_loc.Location.line ^ Binop.str pe Gt ^ str_vpath ":" ^ string_of_int ra.ra_loc.Location.line ^ Binop.str pe Gt ^ str_vpath
} }
| Aautorelease => "AUTORELEASE" | Aautorelease => "AUTORELEASE"
@ -260,14 +260,14 @@ let to_string pe =>
| Aundef pn _ loc _ => | Aundef pn _ loc _ =>
"UND" ^ "UND" ^
Binop.str pe Lt ^ Binop.str pe Lt ^
Procname.to_string pn ^ Binop.str pe Gt ^ ":" ^ string_of_int loc.Location.line Typ.Procname.to_string pn ^ Binop.str pe Gt ^ ":" ^ string_of_int loc.Location.line
| Ataint {taint_source} => "TAINTED[" ^ Procname.to_string taint_source ^ "]" | Ataint {taint_source} => "TAINTED[" ^ Typ.Procname.to_string taint_source ^ "]"
| Auntaint _ => "UNTAINTED" | Auntaint _ => "UNTAINTED"
| Alocked => "LOCKED" | Alocked => "LOCKED"
| Aunlocked => "UNLOCKED" | Aunlocked => "UNLOCKED"
| Adiv0 (_, _) => "DIV0" | Adiv0 (_, _) => "DIV0"
| Aobjc_null => "OBJC_NULL" | Aobjc_null => "OBJC_NULL"
| Aretval pn _ => "RET" ^ Binop.str pe Lt ^ Procname.to_string pn ^ Binop.str pe Gt | Aretval pn _ => "RET" ^ Binop.str pe Lt ^ Typ.Procname.to_string pn ^ Binop.str pe Gt
| Aobserver => "OBSERVER" | Aobserver => "OBSERVER"
| Aunsubscribed_observer => "UNSUBSCRIBED_OBSERVER"; | Aunsubscribed_observer => "UNSUBSCRIBED_OBSERVER";

@ -73,7 +73,7 @@ type dangling_kind =
/** position in a path: proc name, node id */ /** position in a path: proc name, node id */
type path_pos = (Procname.t, int) [@@deriving compare]; type path_pos = (Typ.Procname.t, int) [@@deriving compare];
let equal_path_pos: path_pos => path_pos => bool; let equal_path_pos: path_pos => path_pos => bool;
@ -84,14 +84,14 @@ type taint_kind =
| Tk_integrity_annotation | Tk_integrity_annotation
| Tk_unknown; | Tk_unknown;
type taint_info = {taint_source: Procname.t, taint_kind: taint_kind}; type taint_info = {taint_source: Typ.Procname.t, taint_kind: taint_kind};
/** acquire/release action on a resource */ /** acquire/release action on a resource */
type res_action = { type res_action = {
ra_kind: res_act_kind, /** kind of action */ ra_kind: res_act_kind, /** kind of action */
ra_res: resource, /** kind of resource */ ra_res: resource, /** kind of resource */
ra_pname: Procname.t, /** name of the procedure used to acquire/release the resource */ ra_pname: Typ.Procname.t, /** name of the procedure used to acquire/release the resource */
ra_loc: Location.t, /** location of the acquire/release */ ra_loc: Location.t, /** location of the acquire/release */
ra_vpath: DecompiledExp.vpath /** vpath of the resource value */ ra_vpath: DecompiledExp.vpath /** vpath of the resource value */
}; };
@ -110,7 +110,7 @@ type t =
| Aautorelease | Aautorelease
| Adangling dangling_kind /** dangling pointer */ | Adangling dangling_kind /** dangling pointer */
/** undefined value obtained by calling the given procedure, plus its return value annots */ /** undefined value obtained by calling the given procedure, plus its return value annots */
| Aundef Procname.t Annot.Item.t Location.t path_pos | Aundef Typ.Procname.t Annot.Item.t Location.t path_pos
| Ataint taint_info | Ataint taint_info
| Auntaint taint_info | Auntaint taint_info
| Alocked | Alocked
@ -120,7 +120,7 @@ type t =
/** attributed exp is null due to a call to a method with given path as null receiver */ /** attributed exp is null due to a call to a method with given path as null receiver */
| Aobjc_null | Aobjc_null
/** value was returned from a call to the given procedure, plus the annots of the return value */ /** value was returned from a call to the given procedure, plus the annots of the return value */
| Aretval Procname.t Annot.Item.t | Aretval Typ.Procname.t Annot.Item.t
/** denotes an object registered as an observers to a notification center */ /** denotes an object registered as an observers to a notification center */
| Aobserver | Aobserver
/** denotes an object unsubscribed from observers of a notification center */ /** denotes an object unsubscribed from observers of a notification center */
@ -131,11 +131,11 @@ let equal: t => t => bool;
/** name of the allocation function for the given memory kind */ /** name of the allocation function for the given memory kind */
let mem_alloc_pname: mem_kind => Procname.t; let mem_alloc_pname: mem_kind => Typ.Procname.t;
/** name of the deallocation function for the given memory kind */ /** name of the deallocation function for the given memory kind */
let mem_dealloc_pname: mem_kind => Procname.t; let mem_dealloc_pname: mem_kind => Typ.Procname.t;
/** Categories of attributes */ /** Categories of attributes */

@ -67,7 +67,7 @@ type t = {
method_annotation: Annot.Method.t, /** annotations for java methods */ method_annotation: Annot.Method.t, /** annotations for java methods */
objc_accessor: option objc_accessor_type, /** type of ObjC accessor, if any */ objc_accessor: option objc_accessor_type, /** type of ObjC accessor, if any */
proc_flags: proc_flags, /** flags of the procedure */ proc_flags: proc_flags, /** flags of the procedure */
proc_name: Procname.t, /** name of the procedure */ proc_name: Typ.Procname.t, /** name of the procedure */
ret_type: Typ.t, /** return type */ ret_type: Typ.t, /** return type */
source_file_captured: SourceFile.t /** source file where the procedure was captured */ source_file_captured: SourceFile.t /** source file where the procedure was captured */
} }

@ -62,7 +62,7 @@ type t = {
method_annotation: Annot.Method.t, /** annotations for java methods */ method_annotation: Annot.Method.t, /** annotations for java methods */
objc_accessor: option objc_accessor_type, /** type of ObjC accessor, if any */ objc_accessor: option objc_accessor_type, /** type of ObjC accessor, if any */
proc_flags: proc_flags, /** flags of the procedure */ proc_flags: proc_flags, /** flags of the procedure */
proc_name: Procname.t, /** name of the procedure */ proc_name: Typ.Procname.t, /** name of the procedure */
ret_type: Typ.t, /** return type */ ret_type: Typ.t, /** return type */
source_file_captured: SourceFile.t /** source file where the procedure was captured */ source_file_captured: SourceFile.t /** source file where the procedure was captured */
} }
@ -70,4 +70,4 @@ type t = {
/** Create a proc_attributes with default values. */ /** Create a proc_attributes with default values. */
let default: Procname.t => Config.language => t; let default: Typ.Procname.t => Config.language => t;

@ -20,8 +20,8 @@ let module Node = {
type id = int [@@deriving compare]; type id = int [@@deriving compare];
let equal_id = [%compare.equal : id]; let equal_id = [%compare.equal : id];
type nodekind = type nodekind =
| Start_node Procname.t | Start_node Typ.Procname.t
| Exit_node Procname.t | Exit_node Typ.Procname.t
| Stmt_node string | Stmt_node string
| Join_node | Join_node
| Prune_node bool Sil.if_kind string /** (true/false branch, if_kind, comment) */ | Prune_node bool Sil.if_kind string /** (true/false branch, if_kind, comment) */
@ -46,7 +46,7 @@ let module Node = {
/** predecessor nodes in the cfg */ /** predecessor nodes in the cfg */
mutable preds: list t, mutable preds: list t,
/** name of the procedure the node belongs to */ /** name of the procedure the node belongs to */
pname_opt: option Procname.t, pname_opt: option Typ.Procname.t,
/** successor nodes in the cfg */ /** successor nodes in the cfg */
mutable succs: list t mutable succs: list t
}; };
@ -580,7 +580,7 @@ let pp_objc_accessor fmt accessor =>
let pp_signature fmt pdesc => { let pp_signature fmt pdesc => {
let attributes = get_attributes pdesc; let attributes = get_attributes pdesc;
let pname = get_proc_name pdesc; let pname = get_proc_name pdesc;
let pname_string = Procname.to_string pname; let pname_string = Typ.Procname.to_string pname;
let defined_string = is_defined pdesc ? "defined" : "undefined"; let defined_string = is_defined pdesc ? "defined" : "undefined";
Format.fprintf Format.fprintf
fmt fmt

@ -22,8 +22,8 @@ let module Node: {
/** kind of cfg node */ /** kind of cfg node */
type nodekind = type nodekind =
| Start_node Procname.t | Start_node Typ.Procname.t
| Exit_node Procname.t | Exit_node Typ.Procname.t
| Stmt_node string | Stmt_node string
| Join_node | Join_node
| Prune_node bool Sil.if_kind string /** (true/false branch, if_kind, comment) */ | Prune_node bool Sil.if_kind string /** (true/false branch, if_kind, comment) */
@ -50,13 +50,13 @@ let module Node: {
let d_instrs: sub_instrs::bool => option Sil.instr => t => unit; let d_instrs: sub_instrs::bool => option Sil.instr => t => unit;
/** Create a dummy node */ /** Create a dummy node */
let dummy: option Procname.t => t; let dummy: option Typ.Procname.t => t;
/** Check if two nodes are equal */ /** Check if two nodes are equal */
let equal: t => t => bool; let equal: t => t => bool;
/** Get the list of callee procnames from the node */ /** Get the list of callee procnames from the node */
let get_callees: t => list Procname.t; let get_callees: t => list Typ.Procname.t;
/** Return a description of the node */ /** Return a description of the node */
let get_description: Pp.env => t => string; let get_description: Pp.env => t => string;
@ -90,7 +90,7 @@ let module Node: {
let get_preds: t => list t; let get_preds: t => list t;
/** Get the name of the procedure the node belongs to */ /** Get the name of the procedure the node belongs to */
let get_proc_name: t => Procname.t; let get_proc_name: t => Typ.Procname.t;
/** Get the predecessor nodes of a node where the given predicate evaluates to true */ /** Get the predecessor nodes of a node where the given predicate evaluates to true */
let get_sliced_preds: t => (t => bool) => list t; let get_sliced_preds: t => (t => bool) => list t;
@ -159,7 +159,7 @@ let did_preanalysis: t => bool;
/** fold over the calls from the procedure: (callee, location) pairs */ /** fold over the calls from the procedure: (callee, location) pairs */
let fold_calls: ('a => (Procname.t, Location.t) => 'a) => 'a => t => 'a; let fold_calls: ('a => (Typ.Procname.t, Location.t) => 'a) => 'a => t => 'a;
/** fold over all nodes and their instructions */ /** fold over all nodes and their instructions */
@ -207,7 +207,7 @@ let get_locals: t => list (Mangled.t, Typ.t);
let get_nodes: t => list Node.t; let get_nodes: t => list Node.t;
let get_proc_name: t => Procname.t; let get_proc_name: t => Typ.Procname.t;
/** Return the return type of the procedure and type string */ /** Return the return type of the procedure and type string */
@ -239,7 +239,7 @@ let is_java_synchronized: t => bool;
/** iterate over the calls from the procedure: (callee, location) pairs */ /** iterate over the calls from the procedure: (callee, location) pairs */
let iter_calls: ((Procname.t, Location.t) => unit) => t => unit; let iter_calls: ((Typ.Procname.t, Location.t) => unit) => t => unit;
/** iterate over all nodes and their instructions */ /** iterate over all nodes and their instructions */
@ -255,7 +255,7 @@ let iter_slope: (Node.t => unit) => t => unit;
/** iterate over all calls until we reach a branching structure */ /** iterate over all calls until we reach a branching structure */
let iter_slope_calls: (Procname.t => unit) => t => unit; let iter_slope_calls: (Typ.Procname.t => unit) => t => unit;
/** iterate between two nodes or until we reach a branching structure */ /** iterate between two nodes or until we reach a branching structure */

@ -1,587 +0,0 @@
/*
* Copyright (c) 2009 - 2013 Monoidics ltd.
* Copyright (c) 2013 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
open! IStd;
let module Hashtbl = Caml.Hashtbl;
/** Module for Procedure Names */
let module L = Logging;
let module F = Format;
/* e.g. ("", "int") for primitive types or ("java.io", "PrintWriter") for objects */
type java_type = (option string, string);
/* compare in inverse order */
let compare_java_type (p1, c1) (p2, c2) => [%compare : (string, option string)] (c1, p1) (c2, p2);
type method_kind =
| Non_Static /* in Java, procedures called with invokevirtual, invokespecial, and invokeinterface */
| Static /* in Java, procedures called with invokestatic */
[@@deriving compare];
let equal_method_kind = [%compare.equal : method_kind];
/** Type of java procedure names. */
type java = {
method_name: string,
parameters: list java_type,
class_name: Typename.t,
return_type: option java_type, /* option because constructors have no return type */
kind: method_kind
}
[@@deriving compare];
/** Type of c procedure names. */
type c = (string, option string) [@@deriving compare];
type objc_cpp_method_kind =
| CPPMethod (option string) /** with mangling */
| CPPConstructor (option string, bool) /** with mangling + is it constexpr? */
| ObjCClassMethod
| ObjCInstanceMethod
| ObjCInternalMethod
[@@deriving compare];
/** Type of Objective C and C++ procedure names: method signatures. */
type objc_cpp = {method_name: string, class_name: Typename.t, kind: objc_cpp_method_kind}
[@@deriving compare];
/** Type of Objective C block names. */
type block = string [@@deriving compare];
/** Type of procedure names. */
type t =
| Java java
| C c
| Linters_dummy_method
| Block block
| ObjC_Cpp objc_cpp
[@@deriving compare];
let equal = [%compare.equal : t];
/** Level of verbosity of some to_string functions. */
type detail_level =
| Verbose
| Non_verbose
| Simple
[@@deriving compare];
let equal_detail_level = [%compare.equal : detail_level];
let objc_method_kind_of_bool is_instance =>
if is_instance {ObjCInstanceMethod} else {ObjCClassMethod};
let empty_block = Block "";
let is_verbose v =>
switch v {
| Verbose => true
| _ => false
};
/** A type is a pair (package, type_name) that is translated in a string package.type_name */
let java_type_to_string_verbosity p verbosity =>
switch p {
| (None, typ) => typ
| (Some p, cls) =>
if (is_verbose verbosity) {
p ^ "." ^ cls
} else {
cls
}
};
let java_type_to_string p => java_type_to_string_verbosity p Verbose;
/** Given a list of types, it creates a unique string of types separated by commas */
let rec java_param_list_to_string inputList verbosity =>
switch inputList {
| [] => ""
| [head] => java_type_to_string_verbosity head verbosity
| [head, ...rest] =>
java_type_to_string_verbosity head verbosity ^ "," ^ java_param_list_to_string rest verbosity
};
/** It is the same as java_type_to_string, but Java return types are optional because of constructors without type */
let java_return_type_to_string j verbosity =>
switch j.return_type {
| None => ""
| Some typ => java_type_to_string_verbosity typ verbosity
};
/** Given a package.class_name string, it looks for the latest dot and split the string
in two (package, class_name) */
let split_classname package_classname =>
switch (String.rsplit2 package_classname on::'.') {
| Some (x, y) => (Some x, y)
| None => (None, package_classname)
};
let split_typename typename => split_classname (Typename.name typename);
let from_string_c_fun (s: string) => C (s, None);
let c (plain: string) (mangled: string) => (plain, Some mangled);
let java class_name return_type method_name parameters kind => {
class_name,
return_type,
method_name,
parameters,
kind
};
/** Create an objc procedure name from a class_name and method_name. */
let objc_cpp class_name method_name kind => {class_name, method_name, kind};
let get_default_objc_class_method objc_class => {
let objc_cpp = objc_cpp objc_class "__find_class_" ObjCInternalMethod;
ObjC_Cpp objc_cpp
};
/** Create an objc procedure name from a class_name and method_name. */
let mangled_objc_block name => Block name;
let is_java =
fun
| Java _ => true
| _ => false;
let is_c_method =
fun
| ObjC_Cpp _ => true
| _ => false;
let is_constexpr =
fun
| ObjC_Cpp {kind: CPPConstructor (_, true)} => true
| _ => false;
/** Replace the class name component of a procedure name.
In case of Java, replace package and class name. */
let replace_class t (new_class: Typename.t) =>
switch t {
| Java j => Java {...j, class_name: new_class}
| ObjC_Cpp osig => ObjC_Cpp {...osig, class_name: new_class}
| C _
| Block _
| Linters_dummy_method => t
};
/** Get the class name of a Objective-C/C++ procedure name. */
let objc_cpp_get_class_name objc_cpp => Typename.name objc_cpp.class_name;
let objc_cpp_get_class_type_name objc_cpp => objc_cpp.class_name;
/** Return the package.classname of a java procname. */
let java_get_class_name (j: java) => Typename.name j.class_name;
/** Return the package.classname as a typename of a java procname. */
let java_get_class_type_name (j: java) => j.class_name;
/** Return the class name of a java procedure name. */
let java_get_simple_class_name (j: java) => snd (split_classname (java_get_class_name j));
/** Return the package of a java procname. */
let java_get_package (j: java) => fst (split_classname (java_get_class_name j));
/** Return the method of a java procname. */
let java_get_method (j: java) => j.method_name;
/** Replace the method of a java procname. */
let java_replace_method (j: java) mname => {...j, method_name: mname};
/** Replace the return type of a java procname. */
let java_replace_return_type j ret_type => {...j, return_type: Some ret_type};
/** Replace the parameters of a java procname. */
let java_replace_parameters j parameters => {...j, parameters};
/** Return the method/function of a procname. */
let get_method =
fun
| ObjC_Cpp name => name.method_name
| C (name, _) => name
| Block name => name
| Java j => j.method_name
| Linters_dummy_method => "Linters_dummy_method";
/** Return the language of the procedure. */
let get_language =
fun
| ObjC_Cpp _ => Config.Clang
| C _ => Config.Clang
| Block _ => Config.Clang
| Linters_dummy_method => Config.Clang
| Java _ => Config.Java;
/** Return the return type of a java procname. */
let java_get_return_type (j: java) => java_return_type_to_string j Verbose;
/** Return the parameters of a java procname. */
let java_get_parameters j => j.parameters;
/** Return the parameters of a java procname as strings. */
let java_get_parameters_as_strings j =>
List.map f::(fun param => java_type_to_string param) j.parameters;
/** Return true if the java procedure is static */
let java_is_static =
fun
| Java j => equal_method_kind j.kind Static
| _ => false;
/** Prints a string of a java procname with the given level of verbosity */
let java_to_string withclass::withclass=false (j: java) verbosity =>
switch verbosity {
| Verbose
| Non_verbose =>
/* if verbose, then package.class.method(params): rtype,
else rtype package.class.method(params)
verbose is used for example to create unique filenames, non_verbose to create reports */
let return_type = java_return_type_to_string j verbosity;
let params = java_param_list_to_string j.parameters verbosity;
let class_name = java_type_to_string_verbosity (split_typename j.class_name) verbosity;
let separator =
switch (j.return_type, verbosity) {
| (None, _) => ""
| (Some _, Verbose) => ":"
| _ => " "
};
let output = class_name ^ "." ^ j.method_name ^ "(" ^ params ^ ")";
if (equal_detail_level verbosity Verbose) {
output ^ separator ^ return_type
} else {
return_type ^ separator ^ output
}
| Simple =>
/* methodname(...) or without ... if there are no parameters */
let cls_prefix =
if withclass {
java_type_to_string_verbosity (split_typename j.class_name) verbosity ^ "."
} else {
""
};
let params =
switch j.parameters {
| [] => ""
| _ => "..."
};
let method_name =
if (String.equal j.method_name "<init>") {
java_get_simple_class_name j
} else {
cls_prefix ^ j.method_name
};
method_name ^ "(" ^ params ^ ")"
};
/** Check if the class name is for an anonymous inner class. */
let is_anonymous_inner_class_name class_name => {
let class_name_no_package = snd (split_typename class_name);
switch (String.rsplit2 class_name_no_package on::'$') {
| Some (_, s) =>
let is_int =
try {
ignore (int_of_string (String.strip s));
true
} {
| Failure _ => false
};
is_int
| None => false
}
};
/** Check if the procedure belongs to an anonymous inner class. */
let java_is_anonymous_inner_class =
fun
| Java j => is_anonymous_inner_class_name j.class_name
| _ => false;
/** Check if the last parameter is a hidden inner class, and remove it if present.
This is used in private constructors, where a proxy constructor is generated
with an extra parameter and calls the normal constructor. */
let java_remove_hidden_inner_class_parameter =
fun
| Java js =>
switch (List.rev js.parameters) {
| [(_, s), ...par'] =>
if (is_anonymous_inner_class_name (Typename.Java.from_string s)) {
Some (Java {...js, parameters: List.rev par'})
} else {
None
}
| [] => None
}
| _ => None;
/** Check if the procedure name is an anonymous inner class constructor. */
let java_is_anonymous_inner_class_constructor =
fun
| Java js => is_anonymous_inner_class_name js.class_name
| _ => false;
/** Check if the procedure name is an acess method (e.g. access$100 used to
access private members from a nested class. */
let java_is_access_method =
fun
| Java js =>
switch (String.rsplit2 js.method_name on::'$') {
| Some ("access", s) =>
let is_int =
try {
ignore (int_of_string s);
true
} {
| Failure _ => false
};
is_int
| _ => false
}
| _ => false;
/** Check if the procedure name is of an auto-generated method containing '$'. */
let java_is_autogen_method =
fun
| Java js => String.contains js.method_name '$'
| _ => false;
/** Check if the proc name has the type of a java vararg.
Note: currently only checks that the last argument has type Object[]. */
let java_is_vararg =
fun
| Java js =>
switch (List.rev js.parameters) {
| [(_, "java.lang.Object[]"), ..._] => true
| _ => false
}
| _ => false;
let is_objc_constructor method_name =>
String.equal method_name "new" || String.is_prefix prefix::"init" method_name;
let is_objc_kind =
fun
| ObjCClassMethod
| ObjCInstanceMethod
| ObjCInternalMethod => true
| _ => false;
/** [is_constructor pname] returns true if [pname] is a constructor */
let is_constructor =
fun
| Java js => String.equal js.method_name "<init>"
| ObjC_Cpp {kind: CPPConstructor _} => true
| ObjC_Cpp {kind, method_name} when is_objc_kind kind => is_objc_constructor method_name
| _ => false;
let is_objc_dealloc method_name => String.equal method_name "dealloc";
/** [is_dealloc pname] returns true if [pname] is the dealloc method in Objective-C
TODO: add case for C++ */
let is_destructor =
fun
| ObjC_Cpp name => is_objc_dealloc name.method_name
| _ => false;
let java_is_close =
fun
| Java js => String.equal js.method_name "close"
| _ => false;
/** [is_class_initializer pname] returns true if [pname] is a class initializer */
let is_class_initializer =
fun
| Java js => String.equal js.method_name "<clinit>"
| _ => false;
/** [is_infer_undefined pn] returns true if [pn] is a special Infer undefined proc */
let is_infer_undefined pn =>
switch pn {
| Java j =>
let regexp = Str.regexp "com.facebook.infer.builtins.InferUndefined";
Str.string_match regexp (java_get_class_name j) 0
| _ =>
/* TODO: add cases for obj-c, c, c++ */
false
};
let get_global_name_of_initializer =
fun
| C (name, _) when String.is_prefix prefix::Config.clang_initializer_prefix name => {
let prefix_len = String.length Config.clang_initializer_prefix;
Some (String.sub name pos::prefix_len len::(String.length name - prefix_len))
}
| _ => None;
/** to_string for C_function type */
let to_readable_string (c1, c2) verbose => {
let plain = c1;
if verbose {
switch c2 {
| None => plain
| Some s => plain ^ "{" ^ s ^ "}"
}
} else {
plain
}
};
let c_method_to_string osig detail_level =>
switch detail_level {
| Simple => osig.method_name
| Non_verbose => Typename.name osig.class_name ^ "_" ^ osig.method_name
| Verbose =>
let m_str =
switch osig.kind {
| CPPMethod m =>
"(" ^
(
switch m {
| None => ""
| Some s => s
}
) ^ ")"
| CPPConstructor (m, is_constexpr) =>
"{" ^
(
switch m {
| None => ""
| Some s => s
}
) ^
(if is_constexpr {"|constexpr"} else {""}) ^ "}"
| ObjCClassMethod => "class"
| ObjCInstanceMethod => "instance"
| ObjCInternalMethod => "internal"
};
Typename.name osig.class_name ^ "_" ^ osig.method_name ^ m_str
};
/** Very verbose representation of an existing Procname.t */
let to_unique_id pn =>
switch pn {
| Java j => java_to_string j Verbose
| C (c1, c2) => to_readable_string (c1, c2) true
| ObjC_Cpp osig => c_method_to_string osig Verbose
| Block name => name
| Linters_dummy_method => "Linters_dummy_method"
};
/** Convert a proc name to a string for the user to see */
let to_string p =>
switch p {
| Java j => java_to_string j Non_verbose
| C (c1, c2) => to_readable_string (c1, c2) false
| ObjC_Cpp osig => c_method_to_string osig Non_verbose
| Block name => name
| Linters_dummy_method => to_unique_id p
};
/** Convenient representation of a procname for external tools (e.g. eclipse plugin) */
let to_simplified_string withclass::withclass=false p =>
switch p {
| Java j => java_to_string withclass::withclass j Simple
| C (c1, c2) => to_readable_string (c1, c2) false ^ "()"
| ObjC_Cpp osig => c_method_to_string osig Simple
| Block _ => "block"
| Linters_dummy_method => to_unique_id p
};
/** Convert a proc name to a filename */
let to_filename proc_name =>
Escape.escape_filename @@ SourceFile.append_crc_cutoff @@ to_unique_id proc_name;
/** Pretty print a proc name */
let pp f pn => F.fprintf f "%s" (to_string pn);
/** hash function for procname */
let hash_pname = Hashtbl.hash;
let module Hash = Hashtbl.Make {
type nonrec t = t;
let equal = equal;
let hash = hash_pname;
};
let module Map = Caml.Map.Make {
type nonrec t = t;
let compare = compare;
};
let module Set = Caml.Set.Make {
type nonrec t = t;
let compare = compare;
};
/** Pretty print a set of proc names */
let pp_set fmt set => Set.iter (fun pname => F.fprintf fmt "%a " pp pname) set;
let get_qualifiers pname =>
switch pname {
| C c => fst c |> QualifiedCppName.qualifiers_of_qual_name
| ObjC_Cpp objc_cpp =>
List.append
(QualifiedCppName.qualifiers_of_qual_name (Typename.name objc_cpp.class_name))
[objc_cpp.method_name]
| _ => []
};

@ -1,281 +0,0 @@
/*
* Copyright (c) 2009 - 2013 Monoidics ltd.
* Copyright (c) 2013 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
open! IStd;
/** Module for Procedure Names. */
/** Type of java procedure names. */
type java;
/** Type of c procedure names. */
type c;
/** Type of Objective C and C++ procedure names. */
type objc_cpp;
/** Type of Objective C block names. */
type block;
/** Type of procedure names. */
type t =
| Java java
| C c
| Linters_dummy_method
| Block block
| ObjC_Cpp objc_cpp
[@@deriving compare];
/** Equality for proc names. */
let equal: t => t => bool;
type java_type = (option string, string);
type method_kind =
| Non_Static /* in Java, procedures called with invokevirtual, invokespecial, and invokeinterface */
| Static /* in Java, procedures called with invokestatic */;
type objc_cpp_method_kind =
| CPPMethod (option string) /** with mangling */
| CPPConstructor (option string, bool) /** with mangling + is it constexpr? */
| ObjCClassMethod
| ObjCInstanceMethod
| ObjCInternalMethod;
/** Hash tables with proc names as keys. */
let module Hash: Caml.Hashtbl.S with type key = t;
/** Maps from proc names. */
let module Map: Caml.Map.S with type key = t;
/** Sets of proc names. */
let module Set: Caml.Set.S with type elt = t;
/** Create a C procedure name from plain and mangled name. */
let c: string => string => c;
/** Empty block name. */
let empty_block: t;
/** Convert a string to a proc name. */
let from_string_c_fun: string => t;
/** Return the language of the procedure. */
let get_language: t => Config.language;
/** Return the method/function of a procname. */
let get_method: t => string;
/** Hash function for procname. */
let hash_pname: t => int;
/** Check if a class string is an anoynmous inner class name. */
let is_anonymous_inner_class_name: Typename.t => bool;
/** Check if this is an Objective-C/C++ method name. */
let is_c_method: t => bool;
/** Check if this is a constructor method in Objective-C. */
let is_objc_constructor: string => bool;
/** Check if this is a constructor. */
let is_constructor: t => bool;
/** Check if this is a constexpr function. */
let is_constexpr: t => bool;
/** Check if this is a Java procedure name. */
let is_java: t => bool;
/** Check if this is a dealloc method in Objective-C. */
let is_objc_dealloc: string => bool;
/** Check if this is a dealloc method. */
let is_destructor: t => bool;
/** Create a Java procedure name from its
class_name method_name args_type_name return_type_name method_kind. */
let java: Typename.t => option java_type => string => list java_type => method_kind => java;
/** Replace the parameters of a java procname. */
let java_replace_parameters: java => list java_type => java;
/** Replace the method of a java procname. */
let java_replace_return_type: java => java_type => java;
/** Create an objc block name. */
let mangled_objc_block: string => t;
/** Create an objc procedure name from a class_name and method_name. */
let objc_cpp: Typename.t => string => objc_cpp_method_kind => objc_cpp;
let get_default_objc_class_method: Typename.t => t;
/** Get the class name of a Objective-C/C++ procedure name. */
let objc_cpp_get_class_name: objc_cpp => string;
let objc_cpp_get_class_type_name: objc_cpp => Typename.t;
/** Create ObjC method type from a bool is_instance. */
let objc_method_kind_of_bool: bool => objc_cpp_method_kind;
/** Return the class name of a java procedure name. */
let java_get_class_name: java => string;
/** Return the class name as a typename of a java procedure name. */
let java_get_class_type_name: java => Typename.t;
/** Return the simple class name of a java procedure name. */
let java_get_simple_class_name: java => string;
/** Return the package name of a java procedure name. */
let java_get_package: java => option string;
/** Return the method name of a java procedure name. */
let java_get_method: java => string;
/** Return the return type of a java procedure name. */
let java_get_return_type: java => string;
/** Return the parameters of a java procedure name. */
let java_get_parameters: java => list java_type;
/** Return the parameters of a java procname as strings. */
let java_get_parameters_as_strings: java => list string;
/** Check if the procedure name is an acess method (e.g. access$100 used to
access private members from a nested class. */
let java_is_access_method: t => bool;
/** Check if the procedure name is of an auto-generated method containing '$'. */
let java_is_autogen_method: t => bool;
/** Check if the procedure belongs to an anonymous inner class. */
let java_is_anonymous_inner_class: t => bool;
/** Check if the procedure name is an anonymous inner class constructor. */
let java_is_anonymous_inner_class_constructor: t => bool;
/** Check if the method name is "close". */
let java_is_close: t => bool;
/** Check if the java procedure is static. */
let java_is_static: t => bool;
/** Check if the proc name has the type of a java vararg.
Note: currently only checks that the last argument has type Object[]. */
let java_is_vararg: t => bool;
/** Check if the last parameter is a hidden inner class, and remove it if present.
This is used in private constructors, where a proxy constructor is generated
with an extra parameter and calls the normal constructor. */
let java_remove_hidden_inner_class_parameter: t => option t;
/** Replace the method name of an existing java procname. */
let java_replace_method: java => string => java;
/** Convert a java type to a string. */
let java_type_to_string: java_type => string;
/** Check if this is a class initializer. */
let is_class_initializer: t => bool;
/** Check if this is a special Infer undefined procedure. */
let is_infer_undefined: t => bool;
/** Return the name of the global for which this procedure is the initializer if this is an
initializer, None otherwise. */
let get_global_name_of_initializer: t => option string;
/** Pretty print a proc name. */
let pp: Format.formatter => t => unit;
/** Pretty print a set of proc names. */
let pp_set: Format.formatter => Set.t => unit;
/** Replace the class name component of a procedure name.
In case of Java, replace package and class name. */
let replace_class: t => Typename.t => t;
/** Given a package.class_name string, look for the latest dot and split the string
in two (package, class_name). */
let split_classname: string => (option string, string);
/** Convert a proc name to a string for the user to see. */
let to_string: t => string;
/** Convert a proc name into a easy string for the user to see in an IDE. */
let to_simplified_string: withclass::bool? => t => string;
/** Convert a proc name into a unique identifier. */
let to_unique_id: t => string;
/** Convert a proc name to a filename. */
let to_filename: t => string;
let get_qualifiers: t => list string;

@ -18,10 +18,10 @@ let module F = Format;
/** Kind of global variables */ /** Kind of global variables */
type pvar_kind = type pvar_kind =
| Local_var Procname.t /** local variable belonging to a function */ | Local_var Typ.Procname.t /** local variable belonging to a function */
| Callee_var Procname.t /** local variable belonging to a callee */ | Callee_var Typ.Procname.t /** local variable belonging to a callee */
| Abduced_retvar Procname.t Location.t /** synthetic variable to represent return value */ | Abduced_retvar Typ.Procname.t Location.t /** synthetic variable to represent return value */
| Abduced_ref_param Procname.t t Location.t | Abduced_ref_param Typ.Procname.t t Location.t
/** synthetic variable to represent param passed by reference */ /** synthetic variable to represent param passed by reference */
| Global_var (SourceFile.t, bool, bool, bool) | Global_var (SourceFile.t, bool, bool, bool)
/** global variable: translation unit + is it compile constant? + is it POD? + is it a static /** global variable: translation unit + is it compile constant? + is it POD? + is it a static
@ -43,25 +43,25 @@ let rec _pp f pv => {
if !Config.pp_simple { if !Config.pp_simple {
F.fprintf f "%a" Mangled.pp name F.fprintf f "%a" Mangled.pp name
} else { } else {
F.fprintf f "%a$%a" Procname.pp n Mangled.pp name F.fprintf f "%a$%a" Typ.Procname.pp n Mangled.pp name
} }
| Callee_var n => | Callee_var n =>
if !Config.pp_simple { if !Config.pp_simple {
F.fprintf f "%a|callee" Mangled.pp name F.fprintf f "%a|callee" Mangled.pp name
} else { } else {
F.fprintf f "%a$%a|callee" Procname.pp n Mangled.pp name F.fprintf f "%a$%a|callee" Typ.Procname.pp n Mangled.pp name
} }
| Abduced_retvar n l => | Abduced_retvar n l =>
if !Config.pp_simple { if !Config.pp_simple {
F.fprintf f "%a|abducedRetvar" Mangled.pp name F.fprintf f "%a|abducedRetvar" Mangled.pp name
} else { } else {
F.fprintf f "%a$%a%a|abducedRetvar" Procname.pp n Location.pp l Mangled.pp name F.fprintf f "%a$%a%a|abducedRetvar" Typ.Procname.pp n Location.pp l Mangled.pp name
} }
| Abduced_ref_param n pv l => | Abduced_ref_param n pv l =>
if !Config.pp_simple { if !Config.pp_simple {
F.fprintf f "%a|%a|abducedRefParam" _pp pv Mangled.pp name F.fprintf f "%a|%a|abducedRefParam" _pp pv Mangled.pp name
} else { } else {
F.fprintf f "%a$%a%a|abducedRefParam" Procname.pp n Location.pp l Mangled.pp name F.fprintf f "%a$%a%a|abducedRefParam" Typ.Procname.pp n Location.pp l Mangled.pp name
} }
| Global_var (fname, is_const, is_pod, _) => | Global_var (fname, is_const, is_pod, _) =>
F.fprintf F.fprintf
@ -256,7 +256,7 @@ let is_frontend_tmp pvar => {
let name = to_string pvar; let name = to_string pvar;
is_sil_tmp name || ( is_sil_tmp name || (
switch pvar.pv_kind { switch pvar.pv_kind {
| Local_var pname => Procname.is_java pname && is_bytecode_tmp name | Local_var pname => Typ.Procname.is_java pname && is_bytecode_tmp name
| _ => false | _ => false
} }
) )
@ -282,7 +282,7 @@ let name_hash (name: Mangled.t) => Hashtbl.hash name;
/** [mk name proc_name] creates a program var with the given function name */ /** [mk name proc_name] creates a program var with the given function name */
let mk (name: Mangled.t) (proc_name: Procname.t) :t => { let mk (name: Mangled.t) (proc_name: Typ.Procname.t) :t => {
pv_hash: name_hash name, pv_hash: name_hash name,
pv_name: name, pv_name: name,
pv_kind: Local_var proc_name pv_kind: Local_var proc_name
@ -293,7 +293,7 @@ let get_ret_pvar pname => mk Ident.name_return pname;
/** [mk_callee name proc_name] creates a program var /** [mk_callee name proc_name] creates a program var
for a callee function with the given function name */ for a callee function with the given function name */
let mk_callee (name: Mangled.t) (proc_name: Procname.t) :t => { let mk_callee (name: Mangled.t) (proc_name: Typ.Procname.t) :t => {
pv_hash: name_hash name, pv_hash: name_hash name,
pv_name: name, pv_name: name,
pv_kind: Callee_var proc_name pv_kind: Callee_var proc_name
@ -323,13 +323,13 @@ let mk_tmp name pname => {
/** create an abduced return variable for a call to [proc_name] at [loc] */ /** create an abduced return variable for a call to [proc_name] at [loc] */
let mk_abduced_ret (proc_name: Procname.t) (loc: Location.t) :t => { let mk_abduced_ret (proc_name: Typ.Procname.t) (loc: Location.t) :t => {
let name = Mangled.from_string ("$RET_" ^ Procname.to_unique_id proc_name); let name = Mangled.from_string ("$RET_" ^ Typ.Procname.to_unique_id proc_name);
{pv_hash: name_hash name, pv_name: name, pv_kind: Abduced_retvar proc_name loc} {pv_hash: name_hash name, pv_name: name, pv_kind: Abduced_retvar proc_name loc}
}; };
let mk_abduced_ref_param (proc_name: Procname.t) (pv: t) (loc: Location.t) :t => { let mk_abduced_ref_param (proc_name: Typ.Procname.t) (pv: t) (loc: Location.t) :t => {
let name = Mangled.from_string ("$REF_PARAM_" ^ Procname.to_unique_id proc_name); let name = Mangled.from_string ("$REF_PARAM_" ^ Typ.Procname.to_unique_id proc_name);
{pv_hash: name_hash name, pv_name: name, pv_kind: Abduced_ref_param proc_name pv loc} {pv_hash: name_hash name, pv_name: name, pv_kind: Abduced_ref_param proc_name pv loc}
}; };
@ -355,7 +355,9 @@ let get_initializer_pname {pv_name, pv_kind} =>
switch pv_kind { switch pv_kind {
| Global_var _ => | Global_var _ =>
Some ( Some (
Procname.from_string_c_fun (Config.clang_initializer_prefix ^ Mangled.to_string_full pv_name) Typ.Procname.from_string_c_fun (
Config.clang_initializer_prefix ^ Mangled.to_string_full pv_name
)
) )
| _ => None | _ => None
}; };

@ -44,7 +44,7 @@ let get_name: t => Mangled.t;
/** [get_ret_pvar proc_name] retuns the return pvar associated with the procedure name */ /** [get_ret_pvar proc_name] retuns the return pvar associated with the procedure name */
let get_ret_pvar: Procname.t => t; let get_ret_pvar: Typ.Procname.t => t;
/** Get a simplified version of the name component of a program variable. */ /** Get a simplified version of the name component of a program variable. */
@ -88,20 +88,20 @@ let is_frontend_tmp: t => bool;
/** [mk name proc_name suffix] creates a program var with the given function name and suffix */ /** [mk name proc_name suffix] creates a program var with the given function name and suffix */
let mk: Mangled.t => Procname.t => t; let mk: Mangled.t => Typ.Procname.t => t;
/** create an abduced variable for a parameter passed by reference */ /** create an abduced variable for a parameter passed by reference */
let mk_abduced_ref_param: Procname.t => t => Location.t => t; let mk_abduced_ref_param: Typ.Procname.t => t => Location.t => t;
/** create an abduced return variable for a call to [proc_name] at [loc] */ /** create an abduced return variable for a call to [proc_name] at [loc] */
let mk_abduced_ret: Procname.t => Location.t => t; let mk_abduced_ret: Typ.Procname.t => Location.t => t;
/** [mk_callee name proc_name] creates a program var /** [mk_callee name proc_name] creates a program var
for a callee function with the given function name */ for a callee function with the given function name */
let mk_callee: Mangled.t => Procname.t => t; let mk_callee: Mangled.t => Typ.Procname.t => t;
/** create a global variable with the given name */ /** create a global variable with the given name */
@ -110,7 +110,7 @@ let mk_global:
/** create a fresh temporary variable local to procedure [pname]. for use in the frontends only! */ /** create a fresh temporary variable local to procedure [pname]. for use in the frontends only! */
let mk_tmp: string => Procname.t => t; let mk_tmp: string => Typ.Procname.t => t;
/** Pretty print a program variable. */ /** Pretty print a program variable. */
@ -126,7 +126,7 @@ let pp_value: Pp.env => F.formatter => t => unit;
/** Turn an ordinary program variable into a callee program variable */ /** Turn an ordinary program variable into a callee program variable */
let to_callee: Procname.t => t => t; let to_callee: Typ.Procname.t => t => t;
/** Turn a pvar into a seed pvar (which stores the initial value of a stack var) */ /** Turn a pvar into a seed pvar (which stores the initial value of a stack var) */
@ -152,6 +152,6 @@ let is_pod: t => bool;
/** Get the procname of the initializer function for the given global variable */ /** Get the procname of the initializer function for the given global variable */
let get_initializer_pname: t => option Procname.t; let get_initializer_pname: t => option Typ.Procname.t;
let module Set: PrettyPrintable.PPSet with type elt = t; let module Set: PrettyPrintable.PPSet with type elt = t;

@ -515,7 +515,7 @@ let pp_instr pe0 f instr => {
let is_block_pvar pvar => Typ.has_block_prefix (Mangled.to_string (Pvar.get_name pvar)); let is_block_pvar pvar => Typ.has_block_prefix (Mangled.to_string (Pvar.get_name pvar));
/* A block pvar used to explain retain cycles */ /* A block pvar used to explain retain cycles */
let block_pvar = Pvar.mk (Mangled.from_string "block") (Procname.from_string_c_fun ""); let block_pvar = Pvar.mk (Mangled.from_string "block") (Typ.Procname.from_string_c_fun "");
/** Dump an instruction. */ /** Dump an instruction. */

@ -96,20 +96,22 @@ let add tenv name struct_typ => TypenameHash.replace tenv name struct_typ;
let get_overriden_method tenv pname_java => { let get_overriden_method tenv pname_java => {
let struct_typ_get_method_by_name (struct_typ: Typ.Struct.t) method_name => let struct_typ_get_method_by_name (struct_typ: Typ.Struct.t) method_name =>
List.find_exn List.find_exn
f::(fun meth => String.equal method_name (Procname.get_method meth)) struct_typ.methods; f::(fun meth => String.equal method_name (Typ.Procname.get_method meth)) struct_typ.methods;
let rec get_overriden_method_in_supers pname_java supers => let rec get_overriden_method_in_supers pname_java supers =>
switch supers { switch supers {
| [superclass, ...supers_tail] => | [superclass, ...supers_tail] =>
switch (lookup tenv superclass) { switch (lookup tenv superclass) {
| Some struct_typ => | Some struct_typ =>
try (Some (struct_typ_get_method_by_name struct_typ (Procname.java_get_method pname_java))) { try (
Some (struct_typ_get_method_by_name struct_typ (Typ.Procname.java_get_method pname_java))
) {
| Not_found => get_overriden_method_in_supers pname_java (supers_tail @ struct_typ.supers) | Not_found => get_overriden_method_in_supers pname_java (supers_tail @ struct_typ.supers)
} }
| None => get_overriden_method_in_supers pname_java supers_tail | None => get_overriden_method_in_supers pname_java supers_tail
} }
| [] => None | [] => None
}; };
switch (lookup tenv (Procname.java_get_class_type_name pname_java)) { switch (lookup tenv (Typ.Procname.java_get_class_type_name pname_java)) {
| Some {supers} => get_overriden_method_in_supers pname_java supers | Some {supers} => get_overriden_method_in_supers pname_java supers
| _ => None | _ => None
} }

@ -43,7 +43,7 @@ let mk_struct:
default::Typ.Struct.t? => default::Typ.Struct.t? =>
fields::Typ.Struct.fields? => fields::Typ.Struct.fields? =>
statics::Typ.Struct.fields? => statics::Typ.Struct.fields? =>
methods::list Procname.t? => methods::list Typ.Procname.t? =>
supers::list Typename.t? => supers::list Typename.t? =>
annots::Annot.Item.t? => annots::Annot.Item.t? =>
specialization::Typ.template_spec_info? => specialization::Typ.template_spec_info? =>
@ -64,4 +64,4 @@ let store_to_file: DB.filename => t => unit;
/** Get method that is being overriden by java_pname (if any) **/ /** Get method that is being overriden by java_pname (if any) **/
let get_overriden_method: t => Procname.java => option Procname.t; let get_overriden_method: t => Typ.Procname.java => option Typ.Procname.t;

@ -288,14 +288,6 @@ let rec java_from_string =
} }
| typ_str => Tstruct (Typename.Java.from_string typ_str); | typ_str => Tstruct (Typename.Java.from_string typ_str);
/** Return the return type of [pname_java]. */
let java_proc_return_typ pname_java =>
switch (java_from_string (Procname.java_get_return_type pname_java)) {
| Tstruct _ as typ => Tptr typ Pk_pointer
| typ => typ
};
type typ = t [@@deriving compare]; type typ = t [@@deriving compare];
/* template instantiation arguments */ /* template instantiation arguments */
@ -304,6 +296,509 @@ type template_spec_info =
| Template (string, list (option t)) | Template (string, list (option t))
[@@deriving compare]; [@@deriving compare];
let module Procname = {
/* e.g. ("", "int") for primitive types or ("java.io", "PrintWriter") for objects */
type java_type = (option string, string);
/* compare in inverse order */
let compare_java_type (p1, c1) (p2, c2) =>
[%compare : (string, option string)] (c1, p1) (c2, p2);
type method_kind =
| Non_Static /* in Java, procedures called with invokevirtual, invokespecial, and invokeinterface */
| Static /* in Java, procedures called with invokestatic */
[@@deriving compare];
let equal_method_kind = [%compare.equal : method_kind];
/** Type of java procedure names. */
type java = {
method_name: string,
parameters: list java_type,
class_name: Typename.t,
return_type: option java_type, /* option because constructors have no return type */
kind: method_kind
}
[@@deriving compare];
/** Type of c procedure names. */
type c = (string, option string) [@@deriving compare];
type objc_cpp_method_kind =
| CPPMethod (option string) /** with mangling */
| CPPConstructor (option string, bool) /** with mangling + is it constexpr? */
| ObjCClassMethod
| ObjCInstanceMethod
| ObjCInternalMethod
[@@deriving compare];
/** Type of Objective C and C++ procedure names: method signatures. */
type objc_cpp = {method_name: string, class_name: Typename.t, kind: objc_cpp_method_kind}
[@@deriving compare];
/** Type of Objective C block names. */
type block = string [@@deriving compare];
/** Type of procedure names. */
type t =
| Java java
| C c
| Linters_dummy_method
| Block block
| ObjC_Cpp objc_cpp
[@@deriving compare];
let equal = [%compare.equal : t];
/** Level of verbosity of some to_string functions. */
type detail_level =
| Verbose
| Non_verbose
| Simple
[@@deriving compare];
let equal_detail_level = [%compare.equal : detail_level];
let objc_method_kind_of_bool is_instance =>
if is_instance {ObjCInstanceMethod} else {ObjCClassMethod};
let empty_block = Block "";
let is_verbose v =>
switch v {
| Verbose => true
| _ => false
};
/** A type is a pair (package, type_name) that is translated in a string package.type_name */
let java_type_to_string_verbosity p verbosity =>
switch p {
| (None, typ) => typ
| (Some p, cls) =>
if (is_verbose verbosity) {
p ^ "." ^ cls
} else {
cls
}
};
let java_type_to_string p => java_type_to_string_verbosity p Verbose;
/** Given a list of types, it creates a unique string of types separated by commas */
let rec java_param_list_to_string inputList verbosity =>
switch inputList {
| [] => ""
| [head] => java_type_to_string_verbosity head verbosity
| [head, ...rest] =>
java_type_to_string_verbosity head verbosity ^ "," ^ java_param_list_to_string rest verbosity
};
/** It is the same as java_type_to_string, but Java return types are optional because of constructors without type */
let java_return_type_to_string j verbosity =>
switch j.return_type {
| None => ""
| Some typ => java_type_to_string_verbosity typ verbosity
};
/** Given a package.class_name string, it looks for the latest dot and split the string
in two (package, class_name) */
let split_classname package_classname =>
switch (String.rsplit2 package_classname on::'.') {
| Some (x, y) => (Some x, y)
| None => (None, package_classname)
};
let split_typename typename => split_classname (Typename.name typename);
let from_string_c_fun (s: string) => C (s, None);
let c (plain: string) (mangled: string) => (plain, Some mangled);
let java class_name return_type method_name parameters kind => {
class_name,
return_type,
method_name,
parameters,
kind
};
/** Create an objc procedure name from a class_name and method_name. */
let objc_cpp class_name method_name kind => {class_name, method_name, kind};
let get_default_objc_class_method objc_class => {
let objc_cpp = objc_cpp objc_class "__find_class_" ObjCInternalMethod;
ObjC_Cpp objc_cpp
};
/** Create an objc procedure name from a class_name and method_name. */
let mangled_objc_block name => Block name;
let is_java =
fun
| Java _ => true
| _ => false;
let is_c_method =
fun
| ObjC_Cpp _ => true
| _ => false;
let is_constexpr =
fun
| ObjC_Cpp {kind: CPPConstructor (_, true)} => true
| _ => false;
/** Replace the class name component of a procedure name.
In case of Java, replace package and class name. */
let replace_class t (new_class: Typename.t) =>
switch t {
| Java j => Java {...j, class_name: new_class}
| ObjC_Cpp osig => ObjC_Cpp {...osig, class_name: new_class}
| C _
| Block _
| Linters_dummy_method => t
};
/** Get the class name of a Objective-C/C++ procedure name. */
let objc_cpp_get_class_name objc_cpp => Typename.name objc_cpp.class_name;
let objc_cpp_get_class_type_name objc_cpp => objc_cpp.class_name;
/** Return the package.classname of a java procname. */
let java_get_class_name (j: java) => Typename.name j.class_name;
/** Return the package.classname as a typename of a java procname. */
let java_get_class_type_name (j: java) => j.class_name;
/** Return the class name of a java procedure name. */
let java_get_simple_class_name (j: java) => snd (split_classname (java_get_class_name j));
/** Return the package of a java procname. */
let java_get_package (j: java) => fst (split_classname (java_get_class_name j));
/** Return the method of a java procname. */
let java_get_method (j: java) => j.method_name;
/** Replace the method of a java procname. */
let java_replace_method (j: java) mname => {...j, method_name: mname};
/** Replace the return type of a java procname. */
let java_replace_return_type j ret_type => {...j, return_type: Some ret_type};
/** Replace the parameters of a java procname. */
let java_replace_parameters j parameters => {...j, parameters};
/** Return the method/function of a procname. */
let get_method =
fun
| ObjC_Cpp name => name.method_name
| C (name, _) => name
| Block name => name
| Java j => j.method_name
| Linters_dummy_method => "Linters_dummy_method";
/** Return the language of the procedure. */
let get_language =
fun
| ObjC_Cpp _ => Config.Clang
| C _ => Config.Clang
| Block _ => Config.Clang
| Linters_dummy_method => Config.Clang
| Java _ => Config.Java;
/** Return the return type of a java procname. */
let java_get_return_type (j: java) => java_return_type_to_string j Verbose;
/** Return the parameters of a java procname. */
let java_get_parameters j => j.parameters;
/** Return the parameters of a java procname as strings. */
let java_get_parameters_as_strings j =>
List.map f::(fun param => java_type_to_string param) j.parameters;
/** Return true if the java procedure is static */
let java_is_static =
fun
| Java j => equal_method_kind j.kind Static
| _ => false;
/** Prints a string of a java procname with the given level of verbosity */
let java_to_string withclass::withclass=false (j: java) verbosity =>
switch verbosity {
| Verbose
| Non_verbose =>
/* if verbose, then package.class.method(params): rtype,
else rtype package.class.method(params)
verbose is used for example to create unique filenames, non_verbose to create reports */
let return_type = java_return_type_to_string j verbosity;
let params = java_param_list_to_string j.parameters verbosity;
let class_name = java_type_to_string_verbosity (split_typename j.class_name) verbosity;
let separator =
switch (j.return_type, verbosity) {
| (None, _) => ""
| (Some _, Verbose) => ":"
| _ => " "
};
let output = class_name ^ "." ^ j.method_name ^ "(" ^ params ^ ")";
if (equal_detail_level verbosity Verbose) {
output ^ separator ^ return_type
} else {
return_type ^ separator ^ output
}
| Simple =>
/* methodname(...) or without ... if there are no parameters */
let cls_prefix =
if withclass {
java_type_to_string_verbosity (split_typename j.class_name) verbosity ^ "."
} else {
""
};
let params =
switch j.parameters {
| [] => ""
| _ => "..."
};
let method_name =
if (String.equal j.method_name "<init>") {
java_get_simple_class_name j
} else {
cls_prefix ^ j.method_name
};
method_name ^ "(" ^ params ^ ")"
};
/** Check if the class name is for an anonymous inner class. */
let is_anonymous_inner_class_name class_name => {
let class_name_no_package = snd (split_typename class_name);
switch (String.rsplit2 class_name_no_package on::'$') {
| Some (_, s) =>
let is_int =
try {
ignore (int_of_string (String.strip s));
true
} {
| Failure _ => false
};
is_int
| None => false
}
};
/** Check if the procedure belongs to an anonymous inner class. */
let java_is_anonymous_inner_class =
fun
| Java j => is_anonymous_inner_class_name j.class_name
| _ => false;
/** Check if the last parameter is a hidden inner class, and remove it if present.
This is used in private constructors, where a proxy constructor is generated
with an extra parameter and calls the normal constructor. */
let java_remove_hidden_inner_class_parameter =
fun
| Java js =>
switch (List.rev js.parameters) {
| [(_, s), ...par'] =>
if (is_anonymous_inner_class_name (Typename.Java.from_string s)) {
Some (Java {...js, parameters: List.rev par'})
} else {
None
}
| [] => None
}
| _ => None;
/** Check if the procedure name is an anonymous inner class constructor. */
let java_is_anonymous_inner_class_constructor =
fun
| Java js => is_anonymous_inner_class_name js.class_name
| _ => false;
/** Check if the procedure name is an acess method (e.g. access$100 used to
access private members from a nested class. */
let java_is_access_method =
fun
| Java js =>
switch (String.rsplit2 js.method_name on::'$') {
| Some ("access", s) =>
let is_int =
try {
ignore (int_of_string s);
true
} {
| Failure _ => false
};
is_int
| _ => false
}
| _ => false;
/** Check if the procedure name is of an auto-generated method containing '$'. */
let java_is_autogen_method =
fun
| Java js => String.contains js.method_name '$'
| _ => false;
/** Check if the proc name has the type of a java vararg.
Note: currently only checks that the last argument has type Object[]. */
let java_is_vararg =
fun
| Java js =>
switch (List.rev js.parameters) {
| [(_, "java.lang.Object[]"), ..._] => true
| _ => false
}
| _ => false;
let is_objc_constructor method_name =>
String.equal method_name "new" || String.is_prefix prefix::"init" method_name;
let is_objc_kind =
fun
| ObjCClassMethod
| ObjCInstanceMethod
| ObjCInternalMethod => true
| _ => false;
/** [is_constructor pname] returns true if [pname] is a constructor */
let is_constructor =
fun
| Java js => String.equal js.method_name "<init>"
| ObjC_Cpp {kind: CPPConstructor _} => true
| ObjC_Cpp {kind, method_name} when is_objc_kind kind => is_objc_constructor method_name
| _ => false;
let is_objc_dealloc method_name => String.equal method_name "dealloc";
/** [is_dealloc pname] returns true if [pname] is the dealloc method in Objective-C
TODO: add case for C++ */
let is_destructor =
fun
| ObjC_Cpp name => is_objc_dealloc name.method_name
| _ => false;
let java_is_close =
fun
| Java js => String.equal js.method_name "close"
| _ => false;
/** [is_class_initializer pname] returns true if [pname] is a class initializer */
let is_class_initializer =
fun
| Java js => String.equal js.method_name "<clinit>"
| _ => false;
/** [is_infer_undefined pn] returns true if [pn] is a special Infer undefined proc */
let is_infer_undefined pn =>
switch pn {
| Java j =>
let regexp = Str.regexp "com.facebook.infer.builtins.InferUndefined";
Str.string_match regexp (java_get_class_name j) 0
| _ =>
/* TODO: add cases for obj-c, c, c++ */
false
};
let get_global_name_of_initializer =
fun
| C (name, _) when String.is_prefix prefix::Config.clang_initializer_prefix name => {
let prefix_len = String.length Config.clang_initializer_prefix;
Some (String.sub name pos::prefix_len len::(String.length name - prefix_len))
}
| _ => None;
/** to_string for C_function type */
let to_readable_string (c1, c2) verbose => {
let plain = c1;
if verbose {
switch c2 {
| None => plain
| Some s => plain ^ "{" ^ s ^ "}"
}
} else {
plain
}
};
let c_method_to_string osig detail_level =>
switch detail_level {
| Simple => osig.method_name
| Non_verbose => Typename.name osig.class_name ^ "_" ^ osig.method_name
| Verbose =>
let m_str =
switch osig.kind {
| CPPMethod m =>
"(" ^
(
switch m {
| None => ""
| Some s => s
}
) ^ ")"
| CPPConstructor (m, is_constexpr) =>
"{" ^
(
switch m {
| None => ""
| Some s => s
}
) ^
(if is_constexpr {"|constexpr"} else {""}) ^ "}"
| ObjCClassMethod => "class"
| ObjCInstanceMethod => "instance"
| ObjCInternalMethod => "internal"
};
Typename.name osig.class_name ^ "_" ^ osig.method_name ^ m_str
};
/** Very verbose representation of an existing Procname.t */
let to_unique_id pn =>
switch pn {
| Java j => java_to_string j Verbose
| C (c1, c2) => to_readable_string (c1, c2) true
| ObjC_Cpp osig => c_method_to_string osig Verbose
| Block name => name
| Linters_dummy_method => "Linters_dummy_method"
};
/** Convert a proc name to a string for the user to see */
let to_string p =>
switch p {
| Java j => java_to_string j Non_verbose
| C (c1, c2) => to_readable_string (c1, c2) false
| ObjC_Cpp osig => c_method_to_string osig Non_verbose
| Block name => name
| Linters_dummy_method => to_unique_id p
};
/** Convenient representation of a procname for external tools (e.g. eclipse plugin) */
let to_simplified_string withclass::withclass=false p =>
switch p {
| Java j => java_to_string withclass::withclass j Simple
| C (c1, c2) => to_readable_string (c1, c2) false ^ "()"
| ObjC_Cpp osig => c_method_to_string osig Simple
| Block _ => "block"
| Linters_dummy_method => to_unique_id p
};
/** Convert a proc name to a filename */
let to_filename proc_name =>
Escape.escape_filename @@ SourceFile.append_crc_cutoff @@ to_unique_id proc_name;
/** Pretty print a proc name */
let pp f pn => F.fprintf f "%s" (to_string pn);
/** hash function for procname */
let hash_pname = Hashtbl.hash;
let module Hash = Hashtbl.Make {
type nonrec t = t;
let equal = equal;
let hash = hash_pname;
};
let module Map = Caml.Map.Make {
type nonrec t = t;
let compare = compare;
};
let module Set = Caml.Set.Make {
type nonrec t = t;
let compare = compare;
};
/** Pretty print a set of proc names */
let pp_set fmt set => Set.iter (fun pname => F.fprintf fmt "%a " pp pname) set;
let get_qualifiers pname =>
switch pname {
| C c => fst c |> QualifiedCppName.qualifiers_of_qual_name
| ObjC_Cpp objc_cpp =>
List.append
(QualifiedCppName.qualifiers_of_qual_name (Typename.name objc_cpp.class_name))
[objc_cpp.method_name]
| _ => []
};
};
/** Return the return type of [pname_java]. */
let java_proc_return_typ pname_java =>
switch (java_from_string (Procname.java_get_return_type pname_java)) {
| Tstruct _ as typ => Tptr typ Pk_pointer
| typ => typ
};
let module Struct = { let module Struct = {
type field = (Ident.fieldname, T.t, Annot.Item.t) [@@deriving compare]; type field = (Ident.fieldname, T.t, Annot.Item.t) [@@deriving compare];
type fields = list field; type fields = list field;

@ -148,10 +148,6 @@ let is_block_type: t => bool;
let unsome: string => option t => t; let unsome: string => option t => t;
/** Return the return type of [pname_java]. */
let java_proc_return_typ: Procname.java => t;
type typ = t; type typ = t;
/* template instantiation arguments */ /* template instantiation arguments */
@ -160,6 +156,219 @@ type template_spec_info =
| Template (string, list (option t)) | Template (string, list (option t))
[@@deriving compare]; [@@deriving compare];
let module Procname: {
/** Module for Procedure Names. */
/** Type of java procedure names. */
type java;
/** Type of c procedure names. */
type c;
/** Type of Objective C and C++ procedure names. */
type objc_cpp;
/** Type of Objective C block names. */
type block;
/** Type of procedure names. */
type t =
| Java java
| C c
| Linters_dummy_method
| Block block
| ObjC_Cpp objc_cpp
[@@deriving compare];
/** Equality for proc names. */
let equal: t => t => bool;
type java_type = (option string, string);
type method_kind =
| Non_Static /* in Java, procedures called with invokevirtual, invokespecial, and invokeinterface */
| Static /* in Java, procedures called with invokestatic */;
type objc_cpp_method_kind =
| CPPMethod (option string) /** with mangling */
| CPPConstructor (option string, bool) /** with mangling + is it constexpr? */
| ObjCClassMethod
| ObjCInstanceMethod
| ObjCInternalMethod;
/** Hash tables with proc names as keys. */
let module Hash: Caml.Hashtbl.S with type key = t;
/** Maps from proc names. */
let module Map: Caml.Map.S with type key = t;
/** Sets of proc names. */
let module Set: Caml.Set.S with type elt = t;
/** Create a C procedure name from plain and mangled name. */
let c: string => string => c;
/** Empty block name. */
let empty_block: t;
/** Convert a string to a proc name. */
let from_string_c_fun: string => t;
/** Return the language of the procedure. */
let get_language: t => Config.language;
/** Return the method/function of a procname. */
let get_method: t => string;
/** Hash function for procname. */
let hash_pname: t => int;
/** Check if a class string is an anoynmous inner class name. */
let is_anonymous_inner_class_name: Typename.t => bool;
/** Check if this is an Objective-C/C++ method name. */
let is_c_method: t => bool;
/** Check if this is a constructor method in Objective-C. */
let is_objc_constructor: string => bool;
/** Check if this is a constructor. */
let is_constructor: t => bool;
/** Check if this is a constexpr function. */
let is_constexpr: t => bool;
/** Check if this is a Java procedure name. */
let is_java: t => bool;
/** Check if this is a dealloc method in Objective-C. */
let is_objc_dealloc: string => bool;
/** Check if this is a dealloc method. */
let is_destructor: t => bool;
/** Create a Java procedure name from its
class_name method_name args_type_name return_type_name method_kind. */
let java: Typename.t => option java_type => string => list java_type => method_kind => java;
/** Replace the parameters of a java procname. */
let java_replace_parameters: java => list java_type => java;
/** Replace the method of a java procname. */
let java_replace_return_type: java => java_type => java;
/** Create an objc block name. */
let mangled_objc_block: string => t;
/** Create an objc procedure name from a class_name and method_name. */
let objc_cpp: Typename.t => string => objc_cpp_method_kind => objc_cpp;
let get_default_objc_class_method: Typename.t => t;
/** Get the class name of a Objective-C/C++ procedure name. */
let objc_cpp_get_class_name: objc_cpp => string;
let objc_cpp_get_class_type_name: objc_cpp => Typename.t;
/** Create ObjC method type from a bool is_instance. */
let objc_method_kind_of_bool: bool => objc_cpp_method_kind;
/** Return the class name of a java procedure name. */
let java_get_class_name: java => string;
/** Return the class name as a typename of a java procedure name. */
let java_get_class_type_name: java => Typename.t;
/** Return the simple class name of a java procedure name. */
let java_get_simple_class_name: java => string;
/** Return the package name of a java procedure name. */
let java_get_package: java => option string;
/** Return the method name of a java procedure name. */
let java_get_method: java => string;
/** Return the return type of a java procedure name. */
let java_get_return_type: java => string;
/** Return the parameters of a java procedure name. */
let java_get_parameters: java => list java_type;
/** Return the parameters of a java procname as strings. */
let java_get_parameters_as_strings: java => list string;
/** Check if the procedure name is an acess method (e.g. access$100 used to
access private members from a nested class. */
let java_is_access_method: t => bool;
/** Check if the procedure name is of an auto-generated method containing '$'. */
let java_is_autogen_method: t => bool;
/** Check if the procedure belongs to an anonymous inner class. */
let java_is_anonymous_inner_class: t => bool;
/** Check if the procedure name is an anonymous inner class constructor. */
let java_is_anonymous_inner_class_constructor: t => bool;
/** Check if the method name is "close". */
let java_is_close: t => bool;
/** Check if the java procedure is static. */
let java_is_static: t => bool;
/** Check if the proc name has the type of a java vararg.
Note: currently only checks that the last argument has type Object[]. */
let java_is_vararg: t => bool;
/** Check if the last parameter is a hidden inner class, and remove it if present.
This is used in private constructors, where a proxy constructor is generated
with an extra parameter and calls the normal constructor. */
let java_remove_hidden_inner_class_parameter: t => option t;
/** Replace the method name of an existing java procname. */
let java_replace_method: java => string => java;
/** Convert a java type to a string. */
let java_type_to_string: java_type => string;
/** Check if this is a class initializer. */
let is_class_initializer: t => bool;
/** Check if this is a special Infer undefined procedure. */
let is_infer_undefined: t => bool;
/** Return the name of the global for which this procedure is the initializer if this is an
initializer, None otherwise. */
let get_global_name_of_initializer: t => option string;
/** Pretty print a proc name. */
let pp: Format.formatter => t => unit;
/** Pretty print a set of proc names. */
let pp_set: Format.formatter => Set.t => unit;
/** Replace the class name component of a procedure name.
In case of Java, replace package and class name. */
let replace_class: t => Typename.t => t;
/** Given a package.class_name string, look for the latest dot and split the string
in two (package, class_name). */
let split_classname: string => (option string, string);
/** Convert a proc name to a string for the user to see. */
let to_string: t => string;
/** Convert a proc name into a easy string for the user to see in an IDE. */
let to_simplified_string: withclass::bool? => t => string;
/** Convert a proc name into a unique identifier. */
let to_unique_id: t => string;
/** Convert a proc name to a filename. */
let to_filename: t => string;
let get_qualifiers: t => list string;
};
/** Return the return type of [pname_java]. */
let java_proc_return_typ: Procname.java => t;
let module Struct: { let module Struct: {
type field = (Ident.fieldname, typ, Annot.Item.t) [@@deriving compare]; type field = (Ident.fieldname, typ, Annot.Item.t) [@@deriving compare];
type fields = list field; type fields = list field;

@ -91,7 +91,7 @@ val nullify_exp_with_objc_null : Tenv.t -> Prop.normal Prop.t -> Exp.t -> Prop.n
(** mark Exp.Var's or Exp.Lvar's as undefined *) (** mark Exp.Var's or Exp.Lvar's as undefined *)
val mark_vars_as_undefined : val mark_vars_as_undefined :
Tenv.t -> Prop.normal Prop.t -> Exp.t list -> Procname.t -> Annot.Item.t -> Tenv.t -> Prop.normal Prop.t -> Exp.t list -> Typ.Procname.t -> Annot.Item.t ->
Location.t -> PredSymb.path_pos -> Prop.normal Prop.t Location.t -> PredSymb.path_pos -> Prop.normal Prop.t
(** type for arithmetic problems *) (** type for arithmetic problems *)

@ -669,7 +669,7 @@ let execute_abort { Builtin.proc_name; }
: Builtin.ret_typ = : Builtin.ret_typ =
raise raise
(Exceptions.Precondition_not_found (Exceptions.Precondition_not_found
(Localise.verbatim_desc (Procname.to_string proc_name), __POS__)) (Localise.verbatim_desc (Typ.Procname.to_string proc_name), __POS__))
let execute_exit { Builtin.prop_; path; } let execute_exit { Builtin.prop_; path; }
: Builtin.ret_typ = : Builtin.ret_typ =
@ -834,7 +834,7 @@ let execute_pthread_create ({ Builtin.tenv; prop_; path; args; } as builtin_args
let fun_string = Mangled.to_string fun_name in let fun_string = Mangled.to_string fun_name in
L.d_strln ("pthread_create: calling function " ^ fun_string); L.d_strln ("pthread_create: calling function " ^ fun_string);
begin begin
match Specs.get_summary (Procname.from_string_c_fun fun_string) with match Specs.get_summary (Typ.Procname.from_string_c_fun fun_string) with
| None -> assert false | None -> assert false
| Some callee_summary -> | Some callee_summary ->
SymExec.proc_call callee_summary SymExec.proc_call callee_summary

@ -170,8 +170,8 @@ let summary_values summary => {
}; };
let pp_failure failure => F.asprintf "%a" SymOp.pp_failure_kind failure; let pp_failure failure => F.asprintf "%a" SymOp.pp_failure_kind failure;
{ {
vname: Procname.to_string proc_name, vname: Typ.Procname.to_string proc_name,
vname_id: Procname.to_filename proc_name, vname_id: Typ.Procname.to_filename proc_name,
vspecs: List.length specs, vspecs: List.length specs,
vtime: Printf.sprintf "%.0f" stats.Specs.stats_time, vtime: Printf.sprintf "%.0f" stats.Specs.stats_time,
vto: Option.value_map f::pp_failure default::"NONE" stats.Specs.stats_failure, vto: Option.value_map f::pp_failure default::"NONE" stats.Specs.stats_failure,
@ -401,7 +401,7 @@ let module IssuesCsv = {
}; };
let kind = Exceptions.err_kind_string ekind; let kind = Exceptions.err_kind_string ekind;
let type_str = Localise.to_string error_name; let type_str = Localise.to_string error_name;
let procedure_id = Procname.to_filename procname; let procedure_id = Typ.Procname.to_filename procname;
let filename = SourceFile.to_string source_file; let filename = SourceFile.to_string source_file;
let always_report = let always_report =
switch (Localise.error_desc_extract_tag_value error_desc "always_report") { switch (Localise.error_desc_extract_tag_value error_desc "always_report") {
@ -416,7 +416,7 @@ let module IssuesCsv = {
pp "\"%s\"," err_desc_string; pp "\"%s\"," err_desc_string;
pp "%s," severity; pp "%s," severity;
pp "%d," loc.Location.line; pp "%d," loc.Location.line;
pp "\"%s\"," (Escape.escape_csv (Procname.to_string procname)); pp "\"%s\"," (Escape.escape_csv (Typ.Procname.to_string procname));
pp "\"%s\"," (Escape.escape_csv procedure_id); pp "\"%s\"," (Escape.escape_csv procedure_id);
pp "%s," filename; pp "%s," filename;
pp "\"%s\"," (Escape.escape_csv trace); pp "\"%s\"," (Escape.escape_csv trace);
@ -467,7 +467,7 @@ let module IssuesJson = {
) { ) {
let kind = Exceptions.err_kind_string ekind; let kind = Exceptions.err_kind_string ekind;
let bug_type = Localise.to_string error_name; let bug_type = Localise.to_string error_name;
let procedure_id = Procname.to_filename procname; let procedure_id = Typ.Procname.to_filename procname;
let file = SourceFile.to_string source_file; let file = SourceFile.to_string source_file;
let json_ml_loc = let json_ml_loc =
switch ml_loc_opt { switch ml_loc_opt {
@ -485,7 +485,7 @@ let module IssuesJson = {
visibility, visibility,
line: loc.Location.line, line: loc.Location.line,
column: loc.Location.col, column: loc.Location.col,
procedure: Procname.to_string procname, procedure: Typ.Procname.to_string procname,
procedure_id, procedure_id,
procedure_start_line, procedure_start_line,
file, file,
@ -651,8 +651,8 @@ let module IssuesXml = {
let attributes = [("id", string_of_int !xml_issues_id)]; let attributes = [("id", string_of_int !xml_issues_id)];
let error_class = Exceptions.err_class_string eclass; let error_class = Exceptions.err_class_string eclass;
let error_line = string_of_int loc.Location.line; let error_line = string_of_int loc.Location.line;
let procedure_name = Procname.to_string proc_name; let procedure_name = Typ.Procname.to_string proc_name;
let procedure_id = Procname.to_filename proc_name; let procedure_id = Typ.Procname.to_filename proc_name;
let filename = SourceFile.to_string source_file; let filename = SourceFile.to_string source_file;
let bug_hash = get_bug_hash kind type_str procedure_id filename node_key error_desc; let bug_hash = get_bug_hash kind type_str procedure_id filename node_key error_desc;
let forest = [ let forest = [
@ -694,10 +694,10 @@ let module CallsCsv = {
let stats = summary.Specs.stats; let stats = summary.Specs.stats;
let caller_name = Specs.get_proc_name summary; let caller_name = Specs.get_proc_name summary;
let do_call (callee_name, loc) trace => { let do_call (callee_name, loc) trace => {
pp "\"%s\"," (Escape.escape_csv (Procname.to_string caller_name)); pp "\"%s\"," (Escape.escape_csv (Typ.Procname.to_string caller_name));
pp "\"%s\"," (Escape.escape_csv (Procname.to_filename caller_name)); pp "\"%s\"," (Escape.escape_csv (Typ.Procname.to_filename caller_name));
pp "\"%s\"," (Escape.escape_csv (Procname.to_string callee_name)); pp "\"%s\"," (Escape.escape_csv (Typ.Procname.to_string callee_name));
pp "\"%s\"," (Escape.escape_csv (Procname.to_filename callee_name)); pp "\"%s\"," (Escape.escape_csv (Typ.Procname.to_filename callee_name));
pp "%s," (SourceFile.to_string summary.Specs.attributes.ProcAttributes.loc.Location.file); pp "%s," (SourceFile.to_string summary.Specs.attributes.ProcAttributes.loc.Location.file);
pp "%d," loc.Location.line; pp "%d," loc.Location.line;
pp "%a@\n" Specs.CallStats.pp_trace trace pp "%a@\n" Specs.CallStats.pp_trace trace
@ -864,7 +864,7 @@ let module Summary = {
} else { } else {
L.stdout L.stdout
"Procedure: %a@\n%a@." "Procedure: %a@\n%a@."
Procname.pp Typ.Procname.pp
proc_name proc_name
(Specs.pp_summary_text whole_seconds::Config.whole_seconds) (Specs.pp_summary_text whole_seconds::Config.whole_seconds)
summary summary
@ -875,7 +875,7 @@ let module Summary = {
let write_summary_latex fmt summary => { let write_summary_latex fmt summary => {
let proc_name = Specs.get_proc_name summary; let proc_name = Specs.get_proc_name summary;
Latex.pp_section Latex.pp_section
fmt ("Analysis of function " ^ Latex.convert_string (Procname.to_string proc_name)); fmt ("Analysis of function " ^ Latex.convert_string (Typ.Procname.to_string proc_name));
F.fprintf F.fprintf
fmt "@[<v>%a@]" (Specs.pp_summary_latex Black whole_seconds::Config.whole_seconds) summary fmt "@[<v>%a@]" (Specs.pp_summary_latex Black whole_seconds::Config.whole_seconds) summary
}; };
@ -942,16 +942,16 @@ let module PreconditionStats = {
switch (Prop.CategorizePreconditions.categorize preconditions) { switch (Prop.CategorizePreconditions.categorize preconditions) {
| Prop.CategorizePreconditions.Empty => | Prop.CategorizePreconditions.Empty =>
incr nr_empty; incr nr_empty;
L.stdout "Procedure: %a footprint:Empty@." Procname.pp proc_name L.stdout "Procedure: %a footprint:Empty@." Typ.Procname.pp proc_name
| Prop.CategorizePreconditions.OnlyAllocation => | Prop.CategorizePreconditions.OnlyAllocation =>
incr nr_onlyallocation; incr nr_onlyallocation;
L.stdout "Procedure: %a footprint:OnlyAllocation@." Procname.pp proc_name L.stdout "Procedure: %a footprint:OnlyAllocation@." Typ.Procname.pp proc_name
| Prop.CategorizePreconditions.NoPres => | Prop.CategorizePreconditions.NoPres =>
incr nr_nopres; incr nr_nopres;
L.stdout "Procedure: %a footprint:NoPres@." Procname.pp proc_name L.stdout "Procedure: %a footprint:NoPres@." Typ.Procname.pp proc_name
| Prop.CategorizePreconditions.DataConstraints => | Prop.CategorizePreconditions.DataConstraints =>
incr nr_dataconstraints; incr nr_dataconstraints;
L.stdout "Procedure: %a footprint:DataConstraints@." Procname.pp proc_name L.stdout "Procedure: %a footprint:DataConstraints@." Typ.Procname.pp proc_name
} }
}; };
let pp_stats () => { let pp_stats () => {
@ -1379,7 +1379,7 @@ let pp_summary_and_issues formats_by_report_kind => {
}; };
{ {
LintIssues.load_issues_to_errlog_map Config.lint_issues_dir_name; LintIssues.load_issues_to_errlog_map Config.lint_issues_dir_name;
Procname.Map.iter Typ.Procname.Map.iter
(pp_lint_issues filters formats_by_report_kind linereader) !LintIssues.errLogMap (pp_lint_issues filters formats_by_report_kind linereader) !LintIssues.errLogMap
}; };
finalize_and_close_files formats_by_report_kind stats pdflatex finalize_and_close_files formats_by_report_kind stats pdflatex

@ -40,19 +40,19 @@ let try_capture (attributes : ProcAttributes.t) : ProcAttributes.t option =
Logging.out Logging.out
"Captured file %a to get procedure %a but it wasn't found there@\n" "Captured file %a to get procedure %a but it wasn't found there@\n"
SourceFile.pp definition_file SourceFile.pp definition_file
Procname.pp attributes.proc_name Typ.Procname.pp attributes.proc_name
) )
) else ( ) else (
Logging.out Logging.out
"Wanted to capture file %a to get procedure %a but file was already captured@\n" "Wanted to capture file %a to get procedure %a but file was already captured@\n"
SourceFile.pp definition_file SourceFile.pp definition_file
Procname.pp attributes.proc_name Typ.Procname.pp attributes.proc_name
) )
in in
match definition_file_opt with match definition_file_opt with
| None -> | None ->
Logging.out "Couldn't find source file for %a (declared in %a)@\n" Logging.out "Couldn't find source file for %a (declared in %a)@\n"
Procname.pp attributes.proc_name Typ.Procname.pp attributes.proc_name
SourceFile.pp decl_file SourceFile.pp decl_file
| Some file -> try_compile file | Some file -> try_compile file
); );

@ -12,7 +12,7 @@ let get_name_of_local (curr_f: Procdesc.t) (x, _) => Pvar.mk x (Procdesc.get_pro
/* returns a list of local static variables (ie local variables defined static) in a proposition */ /* returns a list of local static variables (ie local variables defined static) in a proposition */
let get_name_of_objc_static_locals (curr_f: Procdesc.t) p => { let get_name_of_objc_static_locals (curr_f: Procdesc.t) p => {
let pname = Procname.to_string (Procdesc.get_proc_name curr_f); let pname = Typ.Procname.to_string (Procdesc.get_proc_name curr_f);
let local_static e => let local_static e =>
switch e { switch e {
/* is a local static if it's a global and it has a static local name */ /* is a local static if it's a global and it has a static local name */

@ -16,27 +16,27 @@ open! IStd
type rules type rules
(** Abstract a proposition. *) (** Abstract a proposition. *)
val abstract : Procname.t -> Tenv.t -> Prop.normal Prop.t -> Prop.normal Prop.t val abstract : Typ.Procname.t -> Tenv.t -> Prop.normal Prop.t -> Prop.normal Prop.t
(** Check whether the prop contains junk. (** Check whether the prop contains junk.
If it does, and [Config.allowleak] is true, remove the junk, If it does, and [Config.allowleak] is true, remove the junk,
otherwise raise a Leak exception. *) otherwise raise a Leak exception. *)
val abstract_junk : val abstract_junk :
?original_prop:Prop.normal Prop.t -> ?original_prop:Prop.normal Prop.t ->
Procname.t -> Tenv.t -> Prop.normal Prop.t -> Prop.normal Prop.t Typ.Procname.t -> Tenv.t -> Prop.normal Prop.t -> Prop.normal Prop.t
(** Abstract a proposition but don't pay a SymOp *) (** Abstract a proposition but don't pay a SymOp *)
val abstract_no_symop : Procname.t -> Tenv.t -> Prop.normal Prop.t -> Prop.normal Prop.t val abstract_no_symop : Typ.Procname.t -> Tenv.t -> Prop.normal Prop.t -> Prop.normal Prop.t
(** Get the current rules discoveres *) (** Get the current rules discoveres *)
val get_current_rules : unit -> rules val get_current_rules : unit -> rules
(** Abstract each proposition in [propset] *) (** Abstract each proposition in [propset] *)
val lifted_abstract : Procname.t -> Tenv.t -> Propset.t -> Propset.t val lifted_abstract : Typ.Procname.t -> Tenv.t -> Propset.t -> Propset.t
(** Remove redundant elements in an array, and check for junk afterwards *) (** Remove redundant elements in an array, and check for junk afterwards *)
val remove_redundant_array_elements : val remove_redundant_array_elements :
Procname.t -> Tenv.t -> Prop.normal Prop.t -> Prop.normal Prop.t Typ.Procname.t -> Tenv.t -> Prop.normal Prop.t -> Prop.normal Prop.t
(** Reset the abstraction rules discovered *) (** Reset the abstraction rules discovered *)
val reset_current_rules : unit -> unit val reset_current_rules : unit -> unit

@ -19,7 +19,7 @@ type args = {
path : Paths.Path.t; path : Paths.Path.t;
ret_id : (Ident.t * Typ.t) option; ret_id : (Ident.t * Typ.t) option;
args : (Exp.t * Typ.t) list; args : (Exp.t * Typ.t) list;
proc_name : Procname.t; proc_name : Typ.Procname.t;
loc : Location.t; loc : Location.t;
} }
@ -30,33 +30,33 @@ type t = args -> ret_typ
type registered = t type registered = t
(** builtin function names for which we do symbolic execution *) (** builtin function names for which we do symbolic execution *)
let builtin_functions = Procname.Hash.create 4 let builtin_functions = Typ.Procname.Hash.create 4
let check_register_populated () = let check_register_populated () =
(* check if BuiltinDefn were loaded before accessing register *) (* check if BuiltinDefn were loaded before accessing register *)
if Int.equal (Procname.Hash.length builtin_functions) 0 then if Int.equal (Typ.Procname.Hash.length builtin_functions) 0 then
failwith "Builtins were not initialized" failwith "Builtins were not initialized"
(** check if the function is a builtin *) (** check if the function is a builtin *)
let is_registered name = let is_registered name =
Procname.Hash.mem builtin_functions name || (check_register_populated (); false) Typ.Procname.Hash.mem builtin_functions name || (check_register_populated (); false)
(** get the symbolic execution handler associated to the builtin function name *) (** get the symbolic execution handler associated to the builtin function name *)
let get name : t option = let get name : t option =
try Some (Procname.Hash.find builtin_functions name) try Some (Typ.Procname.Hash.find builtin_functions name)
with Not_found -> (check_register_populated (); None) with Not_found -> (check_register_populated (); None)
(** register a builtin [Procname.t] and symbolic execution handler *) (** register a builtin [Typ.Procname.t] and symbolic execution handler *)
let register proc_name sym_exe_fun : registered = let register proc_name sym_exe_fun : registered =
Procname.Hash.replace builtin_functions proc_name sym_exe_fun; Typ.Procname.Hash.replace builtin_functions proc_name sym_exe_fun;
sym_exe_fun sym_exe_fun
(** print the functions registered *) (** print the functions registered *)
let pp_registered fmt () = let pp_registered fmt () =
let builtin_names = ref [] in let builtin_names = ref [] in
Procname.Hash.iter (fun name _ -> builtin_names := name :: !builtin_names) builtin_functions; Typ.Procname.Hash.iter (fun name _ -> builtin_names := name :: !builtin_names) builtin_functions;
builtin_names := List.sort ~cmp:Procname.compare !builtin_names; builtin_names := List.sort ~cmp:Typ.Procname.compare !builtin_names;
let pp pname = Format.fprintf fmt "%a@\n" Procname.pp pname in let pp pname = Format.fprintf fmt "%a@\n" Typ.Procname.pp pname in
Format.fprintf fmt "Registered builtins:@\n @["; Format.fprintf fmt "Registered builtins:@\n @[";
List.iter ~f:pp !builtin_names; List.iter ~f:pp !builtin_names;
Format.fprintf fmt "@]@." Format.fprintf fmt "@]@."

@ -19,7 +19,7 @@ type args = {
path : Paths.Path.t; path : Paths.Path.t;
ret_id : (Ident.t * Typ.t) option; ret_id : (Ident.t * Typ.t) option;
args : (Exp.t * Typ.t) list; args : (Exp.t * Typ.t) list;
proc_name : Procname.t; proc_name : Typ.Procname.t;
loc : Location.t; loc : Location.t;
} }
@ -29,13 +29,13 @@ type t = args -> ret_typ
type registered type registered
val register : Procname.t -> t -> registered val register : Typ.Procname.t -> t -> registered
(** Register a builtin [Procname.t] and symbolic execution handler *) (** Register a builtin [Typ.Procname.t] and symbolic execution handler *)
val is_registered : Procname.t -> bool val is_registered : Typ.Procname.t -> bool
(** Check if the function is a builtin *) (** Check if the function is a builtin *)
val get : Procname.t -> t option val get : Typ.Procname.t -> t option
(** Get the symbolic execution handler associated to the builtin function name *) (** Get the symbolic execution handler associated to the builtin function name *)
val print_and_exit : unit -> 'a val print_and_exit : unit -> 'a

@ -14,11 +14,11 @@ module L = Logging
(** Module to register and invoke callbacks *) (** Module to register and invoke callbacks *)
type proc_callback_args = { type proc_callback_args = {
get_proc_desc : Procname.t -> Procdesc.t option; get_proc_desc : Typ.Procname.t -> Procdesc.t option;
get_procs_in_file : Procname.t -> Procname.t list; get_procs_in_file : Typ.Procname.t -> Typ.Procname.t list;
idenv : Idenv.t; idenv : Idenv.t;
tenv : Tenv.t; tenv : Tenv.t;
proc_name : Procname.t; proc_name : Typ.Procname.t;
proc_desc : Procdesc.t; proc_desc : Procdesc.t;
} }
@ -26,9 +26,9 @@ type proc_callback_t = proc_callback_args -> unit
type cluster_callback_t = type cluster_callback_t =
Exe_env.t -> Exe_env.t ->
Procname.t list -> Typ.Procname.t list ->
(Procname.t -> Procdesc.t option) -> (Typ.Procname.t -> Procdesc.t option) ->
(Idenv.t * Tenv.t * Procname.t * Procdesc.t) list -> (Idenv.t * Tenv.t * Typ.Procname.t * Procdesc.t) list ->
unit unit
let procedure_callbacks = ref [] let procedure_callbacks = ref []
@ -54,7 +54,7 @@ let get_procedure_definition exe_env proc_name =
(idenv, tenv, proc_name, proc_desc, language)) (idenv, tenv, proc_name, proc_desc, language))
(Exe_env.get_proc_desc exe_env proc_name) (Exe_env.get_proc_desc exe_env proc_name)
let get_language proc_name = if Procname.is_java proc_name then Config.Java else Config.Clang let get_language proc_name = if Typ.Procname.is_java proc_name then Config.Java else Config.Clang
let reset_summary proc_name = let reset_summary proc_name =
@ -163,8 +163,8 @@ let iterate_callbacks call_graph exe_env =
let cluster_id proc_name = let cluster_id proc_name =
match proc_name with match proc_name with
| Procname.Java pname_java -> | Typ.Procname.Java pname_java ->
Procname.java_get_class_name pname_java Typ.Procname.java_get_class_name pname_java
| _ -> | _ ->
"unknown" in "unknown" in
let cluster proc_names = let cluster proc_names =

@ -12,11 +12,11 @@ open! IStd
(** Module to register and invoke callbacks *) (** Module to register and invoke callbacks *)
type proc_callback_args = { type proc_callback_args = {
get_proc_desc : Procname.t -> Procdesc.t option; get_proc_desc : Typ.Procname.t -> Procdesc.t option;
get_procs_in_file : Procname.t -> Procname.t list; get_procs_in_file : Typ.Procname.t -> Typ.Procname.t list;
idenv : Idenv.t; idenv : Idenv.t;
tenv : Tenv.t; tenv : Tenv.t;
proc_name : Procname.t; proc_name : Typ.Procname.t;
proc_desc : Procdesc.t; proc_desc : Procdesc.t;
} }
@ -30,9 +30,9 @@ type proc_callback_t = proc_callback_args -> unit
type cluster_callback_t = type cluster_callback_t =
Exe_env.t -> Exe_env.t ->
Procname.t list -> Typ.Procname.t list ->
(Procname.t -> Procdesc.t option) -> (Typ.Procname.t -> Procdesc.t option) ->
(Idenv.t * Tenv.t * Procname.t * Procdesc.t) list -> (Idenv.t * Tenv.t * Typ.Procname.t * Procdesc.t) list ->
unit unit
(** register a procedure callback *) (** register a procedure callback *)

@ -16,7 +16,7 @@ open! IStd
(** Join two pathsets *) (** Join two pathsets *)
val pathset_join : val pathset_join :
Procname.t -> Tenv.t -> Paths.PathSet.t -> Paths.PathSet.t -> Paths.PathSet.t * Paths.PathSet.t Typ.Procname.t -> Tenv.t -> Paths.PathSet.t -> Paths.PathSet.t -> Paths.PathSet.t * Paths.PathSet.t
val join_time : float ref val join_time : float ref
@ -25,7 +25,7 @@ val proplist_collapse_pre : Tenv.t -> Prop.normal Prop.t list -> Prop.normal Spe
val pathset_collapse : Tenv.t -> Paths.PathSet.t -> Paths.PathSet.t val pathset_collapse : Tenv.t -> Paths.PathSet.t -> Paths.PathSet.t
(** reduce the pathset only based on implication checking. *) (** reduce the pathset only based on implication checking. *)
val pathset_collapse_impl : Procname.t -> Tenv.t -> Paths.PathSet.t -> Paths.PathSet.t val pathset_collapse_impl : Typ.Procname.t -> Tenv.t -> Paths.PathSet.t -> Paths.PathSet.t
(** {2 Meet Operators} *) (** {2 Meet Operators} *)

@ -951,7 +951,7 @@ let pp_proplist_parsed2dotty_file filename plist =
(* channel. You have to compute an interprocedural cfg first *) (* channel. You have to compute an interprocedural cfg first *)
let pp_cfgnodename pname fmt (n : Procdesc.Node.t) = let pp_cfgnodename pname fmt (n : Procdesc.Node.t) =
F.fprintf fmt "\"%s_%d\"" (Procname.to_filename pname) (Procdesc.Node.get_id n :> int) F.fprintf fmt "\"%s_%d\"" (Typ.Procname.to_filename pname) (Procdesc.Node.get_id n :> int)
let pp_etlist fmt etl = let pp_etlist fmt etl =
List.iter ~f:(fun (id, ty) -> List.iter ~f:(fun (id, ty) ->
@ -965,7 +965,7 @@ let pp_cfgnodelabel pdesc fmt (n : Procdesc.Node.t) =
let pp_label fmt n = let pp_label fmt n =
match Procdesc.Node.get_kind n with match Procdesc.Node.get_kind n with
| Procdesc.Node.Start_node pname -> | Procdesc.Node.Start_node pname ->
let pname_string = Procname.to_string pname in let pname_string = Typ.Procname.to_string pname in
Format.fprintf fmt "Start %s\\nFormals: %a\\nLocals: %a" Format.fprintf fmt "Start %s\\nFormals: %a\\nLocals: %a"
pname_string pname_string
pp_etlist (Procdesc.get_formals pdesc) pp_etlist (Procdesc.get_formals pdesc)
@ -978,7 +978,7 @@ let pp_cfgnodelabel pdesc fmt (n : Procdesc.Node.t) =
if not (Annot.Method.is_empty method_annotation) then if not (Annot.Method.is_empty method_annotation) then
Format.fprintf fmt "\\nAnnotation: %a" (Annot.Method.pp pname_string) method_annotation Format.fprintf fmt "\\nAnnotation: %a" (Annot.Method.pp pname_string) method_annotation
| Procdesc.Node.Exit_node pname -> | Procdesc.Node.Exit_node pname ->
Format.fprintf fmt "Exit %s" (Procname.to_string pname) Format.fprintf fmt "Exit %s" (Typ.Procname.to_string pname)
| Procdesc.Node.Join_node -> | Procdesc.Node.Join_node ->
Format.fprintf fmt "+" Format.fprintf fmt "+"
| Procdesc.Node.Prune_node (is_true_branch, _, _) -> | Procdesc.Node.Prune_node (is_true_branch, _, _) ->

@ -26,8 +26,8 @@ let is_one_of_classes class_name classes =
let is_method_of_objc_cpp_class pname classes = let is_method_of_objc_cpp_class pname classes =
match pname with match pname with
| Procname.ObjC_Cpp name -> | Typ.Procname.ObjC_Cpp name ->
let class_name = Procname.objc_cpp_get_class_name name in let class_name = Typ.Procname.objc_cpp_get_class_name name in
is_one_of_classes class_name classes is_one_of_classes class_name classes
| _ -> false | _ -> false
@ -219,7 +219,7 @@ let rec _find_normal_variable_load tenv (seen : Exp.Set.t) node id : DExp.t opti
Sil.d_exp e; L.d_ln ()); Sil.d_exp e; L.d_ln ());
_exp_lv_dexp tenv seen node e _exp_lv_dexp tenv seen node e
| Sil.Call (Some (id0, _), Exp.Const (Const.Cfun pn), (e, _):: _, _, _) | Sil.Call (Some (id0, _), Exp.Const (Const.Cfun pn), (e, _):: _, _, _)
when Ident.equal id id0 && Procname.equal pn (Procname.from_string_c_fun "__cast") -> when Ident.equal id id0 && Typ.Procname.equal pn (Typ.Procname.from_string_c_fun "__cast") ->
if verbose if verbose
then then
(L.d_str "find_normal_variable_load cast on "; (L.d_str "find_normal_variable_load cast on ";
@ -897,7 +897,7 @@ let _explain_access tenv
if verbose then (L.d_str "explain_dereference Binop.Leteref "; Sil.d_exp e; L.d_ln ()); if verbose then (L.d_str "explain_dereference Binop.Leteref "; Sil.d_exp e; L.d_ln ());
Some e Some e
| Some Sil.Call (_, Exp.Const (Const.Cfun fn), [(e, _)], _, _) | Some Sil.Call (_, Exp.Const (Const.Cfun fn), [(e, _)], _, _)
when String.equal (Procname.to_string fn) "free" -> when String.equal (Typ.Procname.to_string fn) "free" ->
if verbose then (L.d_str "explain_dereference Sil.Call "; Sil.d_exp e; L.d_ln ()); if verbose then (L.d_str "explain_dereference Sil.Call "; Sil.d_exp e; L.d_ln ());
Some e Some e
| Some Sil.Call (_, (Exp.Var _ as e), _, _, _) -> | Some Sil.Call (_, (Exp.Var _ as e), _, _, _) ->

@ -42,7 +42,7 @@ val find_boolean_assignment : Procdesc.Node.t -> Pvar.t -> bool -> Procdesc.Node
val exp_rv_dexp : Tenv.t -> Procdesc.Node.t -> Exp.t -> DecompiledExp.t option val exp_rv_dexp : Tenv.t -> Procdesc.Node.t -> Exp.t -> DecompiledExp.t option
(** Produce a description of a persistent reference to an Android Context *) (** Produce a description of a persistent reference to an Android Context *)
val explain_context_leak : Procname.t -> Typ.t -> Ident.fieldname -> val explain_context_leak : Typ.Procname.t -> Typ.t -> Ident.fieldname ->
(Ident.fieldname option * Typ.t) list -> Localise.error_desc (Ident.fieldname option * Typ.t) list -> Localise.error_desc
(** Produce a description of a mismatch between an allocation function and a deallocation function *) (** Produce a description of a mismatch between an allocation function and a deallocation function *)
@ -54,7 +54,7 @@ val explain_array_access : Tenv.t -> Localise.deref_str -> 'a Prop.t -> Location
(** explain a class cast exception *) (** explain a class cast exception *)
val explain_class_cast_exception : val explain_class_cast_exception :
Tenv.t -> Procname.t option -> Exp.t -> Exp.t -> Exp.t -> Tenv.t -> Typ.Procname.t option -> Exp.t -> Exp.t -> Exp.t ->
Procdesc.Node.t -> Location.t -> Localise.error_desc Procdesc.Node.t -> Location.t -> Localise.error_desc
(** Explain a deallocate stack variable error *) (** Explain a deallocate stack variable error *)
@ -112,7 +112,7 @@ val explain_unary_minus_applied_to_unsigned_expression :
(** Explain a tainted value error *) (** Explain a tainted value error *)
val explain_tainted_value_reaching_sensitive_function : val explain_tainted_value_reaching_sensitive_function :
Prop.normal Prop.t -> Exp.t -> PredSymb.taint_info -> Procname.t -> Location.t -> Prop.normal Prop.t -> Exp.t -> PredSymb.taint_info -> Typ.Procname.t -> Location.t ->
Localise.error_desc Localise.error_desc
(** Produce a description of a leak by looking at the current state. (** Produce a description of a leak by looking at the current state.

@ -64,7 +64,7 @@ let create_file_data table source cg_fname =
(** execution environment *) (** execution environment *)
type t = type t =
{ cg: Cg.t; (** global call graph *) { cg: Cg.t; (** global call graph *)
proc_map: file_data Procname.Hash.t; (** map from procedure name to file data *) proc_map: file_data Typ.Procname.Hash.t; (** map from procedure name to file data *)
file_map: file_data FilenameHash.t; (** map from cg fname to file data *) file_map: file_data FilenameHash.t; (** map from cg fname to file data *)
mutable source_files : SourceFile.Set.t; (** Source files in the execution environment *) mutable source_files : SourceFile.Set.t; (** Source files in the execution environment *)
} }
@ -78,7 +78,7 @@ let freeze exe_env = exe_env (* TODO: unclear what this function is used for *)
(** create a new execution environment *) (** create a new execution environment *)
let create () = let create () =
{ cg = Cg.create None; { cg = Cg.create None;
proc_map = Procname.Hash.create 17; proc_map = Typ.Procname.Hash.create 17;
file_map = FilenameHash.create 1; file_map = FilenameHash.create 1;
source_files = SourceFile.Set.empty; source_files = SourceFile.Set.empty;
} }
@ -97,20 +97,20 @@ let add_cg (exe_env: t) (source_dir : DB.source_dir) =
List.iter List.iter
~f:(fun pname -> ~f:(fun pname ->
(match AttributesTable.find_file_capturing_procedure pname with (match AttributesTable.find_file_capturing_procedure pname with
| None -> | None ->
() ()
| Some (source_captured, origin) -> | Some (source_captured, origin) ->
let multiply_defined = SourceFile.compare source source_captured <> 0 in let multiply_defined = SourceFile.compare source source_captured <> 0 in
if multiply_defined then Cg.remove_node_defined cg pname; if multiply_defined then Cg.remove_node_defined cg pname;
if Config.check_duplicate_symbols && if Config.check_duplicate_symbols &&
multiply_defined && multiply_defined &&
origin <> `Include then origin <> `Include then
L.stderr "@.DUPLICATE_SYMBOLS source: %a source_captured:%a pname:%a@." L.stderr "@.DUPLICATE_SYMBOLS source: %a source_captured:%a pname:%a@."
SourceFile.pp source SourceFile.pp source
SourceFile.pp source_captured SourceFile.pp source_captured
Procname.pp pname Typ.Procname.pp pname
)) ))
defined_procs; defined_procs;
Cg.extend exe_env.cg cg Cg.extend exe_env.cg cg
@ -120,13 +120,13 @@ let get_cg exe_env =
let get_file_data exe_env pname = let get_file_data exe_env pname =
try try
Some (Procname.Hash.find exe_env.proc_map pname) Some (Typ.Procname.Hash.find exe_env.proc_map pname)
with Not_found -> with Not_found ->
begin begin
let source_file_opt = let source_file_opt =
match AttributesTable.load_attributes pname with match AttributesTable.load_attributes pname with
| None -> | None ->
L.err "can't find tenv_cfg_object for %a@." Procname.pp pname; L.err "can't find tenv_cfg_object for %a@." Typ.Procname.pp pname;
None None
| Some proc_attributes when Config.reactive_capture -> | Some proc_attributes when Config.reactive_capture ->
let get_captured_file {ProcAttributes.source_file_captured} = source_file_captured in let get_captured_file {ProcAttributes.source_file_captured} = source_file_captured in
@ -137,7 +137,7 @@ let get_file_data exe_env pname =
let source_dir = DB.source_dir_from_source_file source_file in let source_dir = DB.source_dir_from_source_file source_file in
let cg_fname = DB.source_dir_get_internal_file source_dir ".cg" in let cg_fname = DB.source_dir_get_internal_file source_dir ".cg" in
let file_data = create_file_data exe_env.file_map source_file cg_fname in let file_data = create_file_data exe_env.file_map source_file cg_fname in
Procname.Hash.replace exe_env.proc_map pname file_data; Typ.Procname.Hash.replace exe_env.proc_map pname file_data;
file_data in file_data in
Option.map ~f:get_file_data_for_source source_file_opt Option.map ~f:get_file_data_for_source source_file_opt
end end
@ -167,10 +167,10 @@ let get_tenv exe_env proc_name =
tenv tenv
| None -> | None ->
failwithf "get_tenv: tenv not found for %a in file %s" failwithf "get_tenv: tenv not found for %a in file %s"
Procname.pp proc_name (DB.filename_to_string file_data.tenv_file) Typ.Procname.pp proc_name (DB.filename_to_string file_data.tenv_file)
) )
| None -> | None ->
failwithf "get_tenv: file_data not found for %a" Procname.pp proc_name failwithf "get_tenv: file_data not found for %a" Typ.Procname.pp proc_name
(** return the cfg associated to the procedure *) (** return the cfg associated to the procedure *)
let get_cfg exe_env pname = let get_cfg exe_env pname =
@ -201,4 +201,4 @@ let iter_files f exe_env =
Option.iter ~f:(fun cfg -> f fname cfg) (file_data_to_cfg file_data); Option.iter ~f:(fun cfg -> f fname cfg) (file_data_to_cfg file_data);
SourceFile.Set.add fname seen_files_acc SourceFile.Set.add fname seen_files_acc
end in end in
ignore (Procname.Hash.fold do_file exe_env.proc_map SourceFile.Set.empty) ignore (Typ.Procname.Hash.fold do_file exe_env.proc_map SourceFile.Set.empty)

@ -32,16 +32,16 @@ val add_cg : initial -> DB.source_dir -> unit
val get_cg : t -> Cg.t val get_cg : t -> Cg.t
(** return the source file associated to the procedure *) (** return the source file associated to the procedure *)
val get_source : t -> Procname.t -> SourceFile.t option val get_source : t -> Typ.Procname.t -> SourceFile.t option
(** return the type environment associated to the procedure *) (** return the type environment associated to the procedure *)
val get_tenv : t -> Procname.t -> Tenv.t val get_tenv : t -> Typ.Procname.t -> Tenv.t
(** return the cfg associated to the procedure *) (** return the cfg associated to the procedure *)
val get_cfg : t -> Procname.t -> Cfg.cfg option val get_cfg : t -> Typ.Procname.t -> Cfg.cfg option
(** return the proc desc associated to the procedure *) (** return the proc desc associated to the procedure *)
val get_proc_desc : t -> Procname.t -> Procdesc.t option val get_proc_desc : t -> Typ.Procname.t -> Procdesc.t option
(** [iter_files f exe_env] applies [f] to the source file and tenv and cfg for each file in [exe_env] *) (** [iter_files f exe_env] applies [f] to the source file and tenv and cfg for each file in [exe_env] *)
val iter_files : (SourceFile.t -> Cfg.cfg -> unit) -> t -> unit val iter_files : (SourceFile.t -> Cfg.cfg -> unit) -> t -> unit

@ -15,7 +15,7 @@ module L = Logging
type path_filter = SourceFile.t -> bool type path_filter = SourceFile.t -> bool
type error_filter = Localise.t -> bool type error_filter = Localise.t -> bool
type proc_filter = Procname.t -> bool type proc_filter = Typ.Procname.t -> bool
type filters = type filters =
{ {
@ -57,8 +57,8 @@ let is_matching patterns =
(** Check if a proc name is matching the name given as string. *) (** Check if a proc name is matching the name given as string. *)
let match_method language proc_name method_name = let match_method language proc_name method_name =
not (BuiltinDecl.is_declared proc_name) && not (BuiltinDecl.is_declared proc_name) &&
Config.equal_language (Procname.get_language proc_name) language && Config.equal_language (Typ.Procname.get_language proc_name) language &&
String.equal (Procname.get_method proc_name) method_name String.equal (Typ.Procname.get_method proc_name) method_name
(* Module to create matcher based on strings present in the source file *) (* Module to create matcher based on strings present in the source file *)
module FileContainsStringMatcher = struct module FileContainsStringMatcher = struct
@ -108,7 +108,7 @@ type pattern =
(* Module to create matcher based on source file names or class names and method names *) (* Module to create matcher based on source file names or class names and method names *)
module FileOrProcMatcher = struct module FileOrProcMatcher = struct
type matcher = SourceFile.t -> Procname.t -> bool type matcher = SourceFile.t -> Typ.Procname.t -> bool
let default_matcher : matcher = let default_matcher : matcher =
fun _ _ -> false fun _ _ -> false
@ -128,8 +128,8 @@ module FileOrProcMatcher = struct
~init:String.Map.empty ~init:String.Map.empty
m_patterns in m_patterns in
let do_java pname_java = let do_java pname_java =
let class_name = Procname.java_get_class_name pname_java let class_name = Typ.Procname.java_get_class_name pname_java
and method_name = Procname.java_get_method pname_java in and method_name = Typ.Procname.java_get_method pname_java in
try try
let class_patterns = String.Map.find_exn pattern_map class_name in let class_patterns = String.Map.find_exn pattern_map class_name in
List.exists List.exists
@ -142,7 +142,7 @@ module FileOrProcMatcher = struct
fun _ proc_name -> fun _ proc_name ->
match proc_name with match proc_name with
| Procname.Java pname_java -> | Typ.Procname.Java pname_java ->
do_java pname_java do_java pname_java
| _ -> | _ ->
false false

@ -16,7 +16,7 @@ type path_filter = SourceFile.t -> bool
type error_filter = Localise.t -> bool type error_filter = Localise.t -> bool
(** Filter type for a procedure name *) (** Filter type for a procedure name *)
type proc_filter = Procname.t -> bool type proc_filter = Typ.Procname.t -> bool
type filters = type filters =
{ {
@ -31,9 +31,9 @@ val do_not_filter : filters
(** Create filters based on the config file *) (** Create filters based on the config file *)
val create_filters : Config.analyzer -> filters val create_filters : Config.analyzer -> filters
val never_return_null_matcher : SourceFile.t -> Procname.t -> bool val never_return_null_matcher : SourceFile.t -> Typ.Procname.t -> bool
val skip_translation_matcher : SourceFile.t -> Procname.t -> bool val skip_translation_matcher : SourceFile.t -> Typ.Procname.t -> bool
val modeled_expensive_matcher : (string -> bool) -> Procname.t -> bool val modeled_expensive_matcher : (string -> bool) -> Typ.Procname.t -> bool
(** Load the config file and list the files to report on *) (** Load the config file and list the files to report on *)
val test: unit -> unit val test: unit -> unit

@ -223,30 +223,30 @@ let collect_preconditions tenv proc_name : Prop.normal Specs.Jprop.t list =
let f p = Prop.prop_normal_vars_to_primed_vars tenv p in let f p = Prop.prop_normal_vars_to_primed_vars tenv p in
Propset.map tenv f pset in Propset.map tenv f pset in
L.d_strln ("#### Extracted footprint of " ^ Procname.to_string proc_name ^ ": ####"); L.d_strln ("#### Extracted footprint of " ^ Typ.Procname.to_string proc_name ^ ": ####");
L.d_increase_indent 1; Propset.d Prop.prop_emp pset'; L.d_decrease_indent 1; L.d_ln (); L.d_increase_indent 1; Propset.d Prop.prop_emp pset'; L.d_decrease_indent 1; L.d_ln ();
L.d_ln (); L.d_ln ();
let pset'' = collect_do_abstract_pre proc_name tenv pset' in let pset'' = collect_do_abstract_pre proc_name tenv pset' in
let plist_meet = do_meet_pre tenv pset'' in let plist_meet = do_meet_pre tenv pset'' in
L.d_strln ("#### Footprint of " ^ Procname.to_string proc_name ^ " after Meet ####"); L.d_strln ("#### Footprint of " ^ Typ.Procname.to_string proc_name ^ " after Meet ####");
L.d_increase_indent 1; Propgraph.d_proplist Prop.prop_emp plist_meet; L.d_increase_indent 1; Propgraph.d_proplist Prop.prop_emp plist_meet;
L.d_decrease_indent 1; L.d_ln (); L.d_decrease_indent 1; L.d_ln ();
L.d_ln (); L.d_ln ();
L.d_increase_indent 2; (* Indent for the join output *) L.d_increase_indent 2; (* Indent for the join output *)
let jplist = do_join_pre tenv plist_meet in let jplist = do_join_pre tenv plist_meet in
L.d_decrease_indent 2; L.d_ln (); L.d_decrease_indent 2; L.d_ln ();
L.d_strln ("#### Footprint of " ^ Procname.to_string proc_name ^ " after Join ####"); L.d_strln ("#### Footprint of " ^ Typ.Procname.to_string proc_name ^ " after Join ####");
L.d_increase_indent 1; Specs.Jprop.d_list false jplist; L.d_decrease_indent 1; L.d_ln (); L.d_increase_indent 1; Specs.Jprop.d_list false jplist; L.d_decrease_indent 1; L.d_ln ();
let jplist' = let jplist' =
List.map ~f:(Specs.Jprop.map (Prop.prop_rename_primed_footprint_vars tenv)) jplist in List.map ~f:(Specs.Jprop.map (Prop.prop_rename_primed_footprint_vars tenv)) jplist in
L.d_strln ("#### Renamed footprint of " ^ Procname.to_string proc_name ^ ": ####"); L.d_strln ("#### Renamed footprint of " ^ Typ.Procname.to_string proc_name ^ ": ####");
L.d_increase_indent 1; Specs.Jprop.d_list false jplist'; L.d_decrease_indent 1; L.d_ln (); L.d_increase_indent 1; Specs.Jprop.d_list false jplist'; L.d_decrease_indent 1; L.d_ln ();
let jplist'' = let jplist'' =
let f p = let f p =
Prop.prop_primed_vars_to_normal_vars tenv Prop.prop_primed_vars_to_normal_vars tenv
(collect_do_abstract_one proc_name tenv p) in (collect_do_abstract_one proc_name tenv p) in
List.map ~f:(Specs.Jprop.map f) jplist' in List.map ~f:(Specs.Jprop.map f) jplist' in
L.d_strln ("#### Abstracted footprint of " ^ Procname.to_string proc_name ^ ": ####"); L.d_strln ("#### Abstracted footprint of " ^ Typ.Procname.to_string proc_name ^ ": ####");
L.d_increase_indent 1; Specs.Jprop.d_list false jplist''; L.d_decrease_indent 1; L.d_ln(); L.d_increase_indent 1; Specs.Jprop.d_list false jplist''; L.d_decrease_indent 1; L.d_ln();
jplist'' jplist''
@ -535,10 +535,10 @@ let forward_tabulate tenv pdesc wl source =
if Specs.equal_phase (Specs.get_phase summary) Specs.FOOTPRINT then "FP" else "RE" in if Specs.equal_phase (Specs.get_phase summary) Specs.FOOTPRINT then "FP" else "RE" in
let status = Specs.get_status summary in let status = Specs.get_status summary in
F.sprintf F.sprintf
"[%s:%s] %s" phase_string (Specs.string_of_status status) (Procname.to_string proc_name) in "[%s:%s] %s" phase_string (Specs.string_of_status status) (Typ.Procname.to_string proc_name) in
L.d_strln ("**** " ^ (log_string pname) ^ " " ^ L.d_strln ("**** " ^ (log_string pname) ^ " " ^
"Node: " ^ string_of_int (Procdesc.Node.get_id curr_node :> int) ^ ", " ^ "Node: " ^ string_of_int (Procdesc.Node.get_id curr_node :> int) ^ ", " ^
"Procedure: " ^ Procname.to_string pname ^ ", " ^ "Procedure: " ^ Typ.Procname.to_string pname ^ ", " ^
"Session: " ^ string_of_int session ^ ", " ^ "Session: " ^ string_of_int session ^ ", " ^
"Todo: " ^ string_of_int (Paths.PathSet.size pathset_todo) ^ " ****"); "Todo: " ^ string_of_int (Paths.PathSet.size pathset_todo) ^ " ****");
L.d_increase_indent 1; L.d_increase_indent 1;
@ -803,8 +803,8 @@ let collect_postconditions wl tenv pdesc : Paths.PathSet.t * Specs.Visitedset.t
(* Assuming C++ developers use RAII, remove resources from the constructor posts *) (* Assuming C++ developers use RAII, remove resources from the constructor posts *)
let pathset = match pname with let pathset = match pname with
| Procname.ObjC_Cpp _ -> | Typ.Procname.ObjC_Cpp _ ->
if (Procname.is_constructor pname) then if (Typ.Procname.is_constructor pname) then
Paths.PathSet.map (fun prop -> Paths.PathSet.map (fun prop ->
Attribute.remove_resource tenv Racquire (Rmemory Mobjc) Attribute.remove_resource tenv Racquire (Rmemory Mobjc)
(Attribute.remove_resource tenv Racquire (Rmemory Mmalloc) (Attribute.remove_resource tenv Racquire (Rmemory Mmalloc)
@ -814,7 +814,7 @@ let collect_postconditions wl tenv pdesc : Paths.PathSet.t * Specs.Visitedset.t
| _ -> pathset in | _ -> pathset in
L.d_strln L.d_strln
("#### [FUNCTION " ^ Procname.to_string pname ^ "] Analysis result ####"); ("#### [FUNCTION " ^ Typ.Procname.to_string pname ^ "] Analysis result ####");
Propset.d Prop.prop_emp (Paths.PathSet.to_propset tenv pathset); Propset.d Prop.prop_emp (Paths.PathSet.to_propset tenv pathset);
L.d_ln (); L.d_ln ();
let res = let res =
@ -831,7 +831,7 @@ let collect_postconditions wl tenv pdesc : Paths.PathSet.t * Specs.Visitedset.t
| exn when (match exn with Exceptions.Leak _ -> true | _ -> false) -> | exn when (match exn with Exceptions.Leak _ -> true | _ -> false) ->
L.d_strln"Leak in post collection"; assert false in L.d_strln"Leak in post collection"; assert false in
L.d_strln L.d_strln
("#### [FUNCTION " ^ Procname.to_string pname ^ "] Postconditions after join ####"); ("#### [FUNCTION " ^ Typ.Procname.to_string pname ^ "] Postconditions after join ####");
L.d_increase_indent 1; L.d_increase_indent 1;
Propset.d Prop.prop_emp (Paths.PathSet.to_propset tenv (fst res)); Propset.d Prop.prop_emp (Paths.PathSet.to_propset tenv (fst res));
L.d_decrease_indent 1; L.d_decrease_indent 1;
@ -912,7 +912,7 @@ let execute_filter_prop wl tenv pdesc init_node (precondition : Prop.normal Spec
: Prop.normal Specs.spec option = : Prop.normal Specs.spec option =
let pname = Procdesc.get_proc_name pdesc in let pname = Procdesc.get_proc_name pdesc in
do_before_node source 0 init_node; do_before_node source 0 init_node;
L.d_strln ("#### Start: RE-execution for " ^ Procname.to_string pname ^ " ####"); L.d_strln ("#### Start: RE-execution for " ^ Typ.Procname.to_string pname ^ " ####");
L.d_indent 1; L.d_indent 1;
L.d_strln "Precond:"; Specs.Jprop.d_shallow precondition; L.d_strln "Precond:"; Specs.Jprop.d_shallow precondition;
L.d_ln (); L.d_ln (); L.d_ln (); L.d_ln ();
@ -930,7 +930,7 @@ let execute_filter_prop wl tenv pdesc init_node (precondition : Prop.normal Spec
forward_tabulate tenv pdesc wl source; forward_tabulate tenv pdesc wl source;
do_before_node source 0 init_node; do_before_node source 0 init_node;
L.d_strln_color Green L.d_strln_color Green
("#### Finished: RE-execution for " ^ Procname.to_string pname ^ " ####"); ("#### Finished: RE-execution for " ^ Typ.Procname.to_string pname ^ " ####");
L.d_increase_indent 1; L.d_increase_indent 1;
L.d_strln "Precond:"; Prop.d_prop (Specs.Jprop.to_prop precondition); L.d_strln "Precond:"; Prop.d_prop (Specs.Jprop.to_prop precondition);
L.d_ln (); L.d_ln ();
@ -953,7 +953,7 @@ let execute_filter_prop wl tenv pdesc init_node (precondition : Prop.normal Spec
with RE_EXE_ERROR -> with RE_EXE_ERROR ->
do_before_node source 0 init_node; do_before_node source 0 init_node;
Printer.force_delayed_prints (); Printer.force_delayed_prints ();
L.d_strln_color Red ("#### [FUNCTION " ^ Procname.to_string pname ^ "] ...ERROR"); L.d_strln_color Red ("#### [FUNCTION " ^ Typ.Procname.to_string pname ^ "] ...ERROR");
L.d_increase_indent 1; L.d_increase_indent 1;
L.d_strln "when starting from pre:"; L.d_strln "when starting from pre:";
Prop.d_prop (Specs.Jprop.to_prop precondition); Prop.d_prop (Specs.Jprop.to_prop precondition);
@ -966,7 +966,7 @@ let execute_filter_prop wl tenv pdesc init_node (precondition : Prop.normal Spec
let get_procs_and_defined_children call_graph = let get_procs_and_defined_children call_graph =
List.map List.map
~f:(fun (n, ns) -> ~f:(fun (n, ns) ->
(n, Procname.Set.elements ns)) (n, Typ.Procname.Set.elements ns))
(Cg.get_nodes_and_defined_children call_graph) (Cg.get_nodes_and_defined_children call_graph)
let pp_intra_stats wl proc_desc fmt _ = let pp_intra_stats wl proc_desc fmt _ =
@ -988,7 +988,7 @@ type exe_phase = (unit -> unit) * (unit -> Prop.normal Specs.spec list * Specs.p
and [get_results ()] returns the results computed. and [get_results ()] returns the results computed.
This function is architected so that [get_results ()] can be called even after This function is architected so that [get_results ()] can be called even after
[go ()] was interrupted by and exception. *) [go ()] was interrupted by and exception. *)
let perform_analysis_phase tenv (pname : Procname.t) (pdesc : Procdesc.t) source let perform_analysis_phase tenv (pname : Typ.Procname.t) (pdesc : Procdesc.t) source
: exe_phase = : exe_phase =
let summary = Specs.get_summary_unsafe "perform_analysis_phase" pname in let summary = Specs.get_summary_unsafe "perform_analysis_phase" pname in
let start_node = Procdesc.get_start_node pdesc in let start_node = Procdesc.get_start_node pdesc in
@ -1008,7 +1008,7 @@ let perform_analysis_phase tenv (pname : Procname.t) (pdesc : Procdesc.t) source
let add pset prop = let add pset prop =
Paths.PathSet.add_renamed_prop prop (Paths.Path.start start_node) pset in Paths.PathSet.add_renamed_prop prop (Paths.Path.start start_node) pset in
Propset.fold add Paths.PathSet.empty init_props in Propset.fold add Paths.PathSet.empty init_props in
L.out "@.#### Start: Footprint Computation for %a ####@." Procname.pp pname; L.out "@.#### Start: Footprint Computation for %a ####@." Typ.Procname.pp pname;
L.d_increase_indent 1; L.d_increase_indent 1;
L.d_strln "initial props ="; L.d_strln "initial props =";
Propset.d Prop.prop_emp init_props; L.d_ln (); L.d_ln(); Propset.d Prop.prop_emp init_props; L.d_ln (); L.d_ln();
@ -1023,12 +1023,12 @@ let perform_analysis_phase tenv (pname : Procname.t) (pdesc : Procdesc.t) source
let get_results (wl : Worklist.t) () = let get_results (wl : Worklist.t) () =
State.process_execution_failures Reporting.log_warning pname; State.process_execution_failures Reporting.log_warning pname;
let results = collect_analysis_result tenv wl pdesc in let results = collect_analysis_result tenv wl pdesc in
L.out "#### [FUNCTION %a] ... OK #####@\n" Procname.pp pname; L.out "#### [FUNCTION %a] ... OK #####@\n" Typ.Procname.pp pname;
L.out "#### Finished: Footprint Computation for %a %a ####@." L.out "#### Finished: Footprint Computation for %a %a ####@."
Procname.pp pname Typ.Procname.pp pname
(pp_intra_stats wl pdesc) pname; (pp_intra_stats wl pdesc) pname;
L.out "#### [FUNCTION %a] Footprint Analysis result ####@\n%a@." L.out "#### [FUNCTION %a] Footprint Analysis result ####@\n%a@."
Procname.pp pname Typ.Procname.pp pname
(Paths.PathSet.pp Pp.text) results; (Paths.PathSet.pp Pp.text) results;
let specs = try extract_specs tenv pdesc results with let specs = try extract_specs tenv pdesc results with
| Exceptions.Leak _ -> | Exceptions.Leak _ ->
@ -1048,7 +1048,7 @@ let perform_analysis_phase tenv (pname : Procname.t) (pdesc : Procdesc.t) source
(Specs.get_specs pname) in (Specs.get_specs pname) in
let valid_specs = ref [] in let valid_specs = ref [] in
let go () = let go () =
L.out "@.#### Start: Re-Execution for %a ####@." Procname.pp pname; L.out "@.#### Start: Re-Execution for %a ####@." Typ.Procname.pp pname;
let filter p = let filter p =
let wl = path_set_create_worklist pdesc in let wl = path_set_create_worklist pdesc in
let speco = execute_filter_prop wl tenv pdesc start_node p source in let speco = execute_filter_prop wl tenv pdesc start_node p source in
@ -1069,22 +1069,22 @@ let perform_analysis_phase tenv (pname : Procname.t) (pdesc : Procdesc.t) source
ignore (List.map ~f:filter candidate_preconditions) in ignore (List.map ~f:filter candidate_preconditions) in
let get_results () = let get_results () =
let specs = !valid_specs in let specs = !valid_specs in
L.out "#### [FUNCTION %a] ... OK #####@\n" Procname.pp pname; L.out "#### [FUNCTION %a] ... OK #####@\n" Typ.Procname.pp pname;
L.out "#### Finished: Re-Execution for %a ####@." Procname.pp pname; L.out "#### Finished: Re-Execution for %a ####@." Typ.Procname.pp pname;
let valid_preconditions = let valid_preconditions =
List.map ~f:(fun spec -> spec.Specs.pre) specs in List.map ~f:(fun spec -> spec.Specs.pre) specs in
let filename = let filename =
DB.Results_dir.path_to_filename DB.Results_dir.path_to_filename
(DB.Results_dir.Abs_source_dir source) (DB.Results_dir.Abs_source_dir source)
[(Procname.to_filename pname)] in [(Typ.Procname.to_filename pname)] in
if Config.write_dotty then if Config.write_dotty then
Dotty.pp_speclist_dotty_file filename specs; Dotty.pp_speclist_dotty_file filename specs;
L.out "@.@.================================================"; L.out "@.@.================================================";
L.out "@. *** CANDIDATE PRECONDITIONS FOR %a: " Procname.pp pname; L.out "@. *** CANDIDATE PRECONDITIONS FOR %a: " Typ.Procname.pp pname;
L.out "@.================================================@."; L.out "@.================================================@.";
L.out "@.%a @.@." (Specs.Jprop.pp_list Pp.text false) candidate_preconditions; L.out "@.%a @.@." (Specs.Jprop.pp_list Pp.text false) candidate_preconditions;
L.out "@.@.================================================"; L.out "@.@.================================================";
L.out "@. *** VALID PRECONDITIONS FOR %a: " Procname.pp pname; L.out "@. *** VALID PRECONDITIONS FOR %a: " Typ.Procname.pp pname;
L.out "@.================================================@."; L.out "@.================================================@.";
L.out "@.%a @.@." (Specs.Jprop.pp_list Pp.text true) valid_preconditions; L.out "@.%a @.@." (Specs.Jprop.pp_list Pp.text true) valid_preconditions;
specs, Specs.RE_EXECUTION in specs, Specs.RE_EXECUTION in
@ -1173,9 +1173,9 @@ let report_runtime_exceptions tenv pdesc summary =
is_public_method is_public_method
&& &&
(match pname with (match pname with
| Procname.Java pname_java -> | Typ.Procname.Java pname_java ->
Procname.java_is_static pname Typ.Procname.java_is_static pname
&& String.equal (Procname.java_get_method pname_java) "main" && String.equal (Typ.Procname.java_get_method pname_java) "main"
| _ -> | _ ->
false) in false) in
let is_annotated pdesc = let is_annotated pdesc =
@ -1324,7 +1324,7 @@ let analyze_proc source exe_env proc_desc : Specs.summary =
(** Perform the transition from [FOOTPRINT] to [RE_EXECUTION] in spec table *) (** Perform the transition from [FOOTPRINT] to [RE_EXECUTION] in spec table *)
let transition_footprint_re_exe tenv proc_name joined_pres = let transition_footprint_re_exe tenv proc_name joined_pres =
L.out "Transition %a from footprint to re-exe@." Procname.pp proc_name; L.out "Transition %a from footprint to re-exe@." Typ.Procname.pp proc_name;
let summary = Specs.get_summary_unsafe "transition_footprint_re_exe" proc_name in let summary = Specs.get_summary_unsafe "transition_footprint_re_exe" proc_name in
let summary' = let summary' =
if Config.only_footprint then if Config.only_footprint then
@ -1375,7 +1375,7 @@ let perform_transition exe_env tenv proc_name source =
with exn when SymOp.exn_not_failure exn -> with exn when SymOp.exn_not_failure exn ->
apply_start_node (do_after_node source); apply_start_node (do_after_node source);
Config.allow_leak := allow_leak; Config.allow_leak := allow_leak;
L.err "Error in collect_preconditions for %a@." Procname.pp proc_name; L.err "Error in collect_preconditions for %a@." Typ.Procname.pp proc_name;
let err_name, _, ml_loc_opt, _, _, _, _ = Exceptions.recognize_exception exn in let err_name, _, ml_loc_opt, _, _, _, _ = Exceptions.recognize_exception exn in
let err_str = "exception raised " ^ (Localise.to_string err_name) in let err_str = "exception raised " ^ (Localise.to_string err_name) in
L.err "Error: %s %a@." err_str L.pp_ml_loc_opt ml_loc_opt; L.err "Error: %s %a@." err_str L.pp_ml_loc_opt ml_loc_opt;
@ -1523,7 +1523,7 @@ let print_stats_cfg proc_shadowed source cfg =
if proc_shadowed proc_desc || if proc_shadowed proc_desc ||
is_none (Specs.get_summary proc_name) then is_none (Specs.get_summary proc_name) then
L.out "print_stats: ignoring function %a which is also defined in another file@." L.out "print_stats: ignoring function %a which is also defined in another file@."
Procname.pp proc_name Typ.Procname.pp proc_name
else else
let summary = Specs.get_summary_unsafe "print_stats_cfg" proc_name in let summary = Specs.get_summary_unsafe "print_stats_cfg" proc_name in
let stats = summary.Specs.stats in let stats = summary.Specs.stats in

@ -29,7 +29,7 @@ let dirs_to_analyze =
type analyze_ondemand = SourceFile.t -> Procdesc.t -> Specs.summary type analyze_ondemand = SourceFile.t -> Procdesc.t -> Specs.summary
type get_proc_desc = Procname.t -> Procdesc.t option type get_proc_desc = Typ.Procname.t -> Procdesc.t option
type callbacks = type callbacks =
{ {
@ -116,8 +116,8 @@ let run_proc_analysis ~propagate_exceptions analyze_proc curr_pdesc callee_pdesc
L.log_progress_procedure (); L.log_progress_procedure ();
if Config.trace_ondemand then L.stderr "[%d] run_proc_analysis %a -> %a@." if Config.trace_ondemand then L.stderr "[%d] run_proc_analysis %a -> %a@."
!nesting !nesting
Procname.pp curr_pname Typ.Procname.pp curr_pname
Procname.pp callee_pname; Typ.Procname.pp callee_pname;
let preprocess () = let preprocess () =
incr nesting; incr nesting;
@ -127,9 +127,9 @@ let run_proc_analysis ~propagate_exceptions analyze_proc curr_pdesc callee_pdesc
Option.value_map Option.value_map
~f:(fun (attributes : ProcAttributes.t) -> ~f:(fun (attributes : ProcAttributes.t) ->
let attribute_pname = attributes.proc_name in let attribute_pname = attributes.proc_name in
if not (Procname.equal callee_pname attribute_pname) then if not (Typ.Procname.equal callee_pname attribute_pname) then
failwith ("ERROR: "^(Procname.to_string callee_pname) failwith ("ERROR: "^(Typ.Procname.to_string callee_pname)
^" not equal to "^(Procname.to_string attribute_pname)); ^" not equal to "^(Typ.Procname.to_string attribute_pname));
attributes.loc.file) attributes.loc.file)
~default:SourceFile.empty ~default:SourceFile.empty
attributes_opt in attributes_opt in
@ -166,7 +166,7 @@ let run_proc_analysis ~propagate_exceptions analyze_proc curr_pdesc callee_pdesc
summary summary
with exn -> with exn ->
L.stderr "@.ONDEMAND EXCEPTION %a %s@.@.BACK TRACE@.%s@?" L.stderr "@.ONDEMAND EXCEPTION %a %s@.@.BACK TRACE@.%s@?"
Procname.pp callee_pname Typ.Procname.pp callee_pname
(Exn.to_string exn) (Exn.to_string exn)
(Printexc.get_backtrace ()); (Printexc.get_backtrace ());
restore_global_state old_state; restore_global_state old_state;

@ -17,7 +17,7 @@ val dirs_to_analyze : String.Set.t option
type analyze_ondemand = SourceFile.t -> Procdesc.t -> Specs.summary type analyze_ondemand = SourceFile.t -> Procdesc.t -> Specs.summary
type get_proc_desc = Procname.t -> Procdesc.t option type get_proc_desc = Typ.Procname.t -> Procdesc.t option
type callbacks = type callbacks =
{ {
@ -38,10 +38,10 @@ val analyze_proc_desc :
performs an on-demand analysis of proc_name performs an on-demand analysis of proc_name
triggered during the analysis of curr_pdesc. *) triggered during the analysis of curr_pdesc. *)
val analyze_proc_name : val analyze_proc_name :
propagate_exceptions:bool -> Procdesc.t -> Procname.t -> Specs.summary option propagate_exceptions:bool -> Procdesc.t -> Typ.Procname.t -> Specs.summary option
(** Check if the procedure called needs to be analyzed. *) (** Check if the procedure called needs to be analyzed. *)
val procedure_should_be_analyzed : Procname.t -> bool val procedure_should_be_analyzed : Typ.Procname.t -> bool
(** Set the callbacks used to perform on-demand analysis. *) (** Set the callbacks used to perform on-demand analysis. *)
val set_callbacks : callbacks -> unit val set_callbacks : callbacks -> unit

@ -24,7 +24,7 @@ module Path : sig
type session = int type session = int
(** add a call with its sub-path, the boolean indicates whether the subtrace for the procedure should be included *) (** add a call with its sub-path, the boolean indicates whether the subtrace for the procedure should be included *)
val add_call : bool -> t -> Procname.t -> t -> t val add_call : bool -> t -> Typ.Procname.t -> t -> t
(** check whether a path contains another path *) (** check whether a path contains another path *)
val contains : t -> t -> bool val contains : t -> t -> bool
@ -84,7 +84,7 @@ end = struct
type _stats = stats type _stats = stats
let compare__stats _ _ = 0 let compare__stats _ _ = 0
type _procname = Procname.t type _procname = Typ.Procname.t
let compare__procname _ _ = 0 let compare__procname _ _ = 0
type _string_option = string option type _string_option = string option
@ -434,9 +434,9 @@ end = struct
match Procdesc.Node.get_kind curr_node with match Procdesc.Node.get_kind curr_node with
| Procdesc.Node.Join_node -> () (* omit join nodes from error traces *) | Procdesc.Node.Join_node -> () (* omit join nodes from error traces *)
| Procdesc.Node.Start_node pname -> | Procdesc.Node.Start_node pname ->
let name = Procname.to_string pname in let name = Typ.Procname.to_string pname in
let name_id = Procname.to_filename pname in let name_id = Typ.Procname.to_filename pname in
let descr = "start of procedure " ^ (Procname.to_simplified_string pname) in let descr = "start of procedure " ^ (Typ.Procname.to_simplified_string pname) in
let node_tags = let node_tags =
[(Io_infer.Xml.tag_kind,"procedure_start"); [(Io_infer.Xml.tag_kind,"procedure_start");
(Io_infer.Xml.tag_name, name); (Io_infer.Xml.tag_name, name);
@ -459,9 +459,9 @@ end = struct
(Io_infer.Xml.tag_branch, if is_true_branch then "true" else "false")] in (Io_infer.Xml.tag_branch, if is_true_branch then "true" else "false")] in
trace := Errlog.make_trace_element level curr_loc descr node_tags :: !trace trace := Errlog.make_trace_element level curr_loc descr node_tags :: !trace
| Procdesc.Node.Exit_node pname -> | Procdesc.Node.Exit_node pname ->
let descr = "return from a call to " ^ (Procname.to_string pname) in let descr = "return from a call to " ^ (Typ.Procname.to_string pname) in
let name = Procname.to_string pname in let name = Typ.Procname.to_string pname in
let name_id = Procname.to_filename pname in let name_id = Typ.Procname.to_filename pname in
let node_tags = let node_tags =
[(Io_infer.Xml.tag_kind,"procedure_end"); [(Io_infer.Xml.tag_kind,"procedure_end");
(Io_infer.Xml.tag_name, name); (Io_infer.Xml.tag_name, name);

@ -19,7 +19,7 @@ module Path : sig
type session = int type session = int
(** add a call with its sub-path, the boolean indicates whether the subtrace for the procedure should be included *) (** add a call with its sub-path, the boolean indicates whether the subtrace for the procedure should be included *)
val add_call : bool -> t -> Procname.t -> t -> t val add_call : bool -> t -> Typ.Procname.t -> t -> t
(** check whether a path contains another path *) (** check whether a path contains another path *)
val contains : t -> t -> bool val contains : t -> t -> bool

@ -37,7 +37,7 @@ let add_dispatch_calls pdesc cg tenv =
receiver_typ in receiver_typ in
let sorted_overrides = let sorted_overrides =
let overrides = Prover.get_overrides_of tenv receiver_typ_no_ptr callee_pname in let overrides = Prover.get_overrides_of tenv receiver_typ_no_ptr callee_pname in
List.sort ~cmp:(fun (_, p1) (_, p2) -> Procname.compare p1 p2) overrides in List.sort ~cmp:(fun (_, p1) (_, p2) -> Typ.Procname.compare p1 p2) overrides in
(match sorted_overrides with (match sorted_overrides with
| ((_, target_pname) :: _) as all_targets -> | ((_, target_pname) :: _) as all_targets ->
let targets_to_add = let targets_to_add =
@ -192,7 +192,7 @@ let remove_dead_frontend_stores pdesc liveness_inv_map =
let add_nullify_instrs pdesc tenv liveness_inv_map = let add_nullify_instrs pdesc tenv liveness_inv_map =
let address_taken_vars = let address_taken_vars =
if Procname.is_java (Procdesc.get_proc_name pdesc) if Typ.Procname.is_java (Procdesc.get_proc_name pdesc)
then AddressTaken.Domain.empty (* can't take the address of a variable in Java *) then AddressTaken.Domain.empty (* can't take the address of a variable in Java *)
else else
let initial = AddressTaken.Domain.empty in let initial = AddressTaken.Domain.empty in
@ -312,7 +312,7 @@ let do_abstraction pdesc =
let do_dynamic_dispatch pdesc cg tenv = let do_dynamic_dispatch pdesc cg tenv =
let pname = Procdesc.get_proc_name pdesc in let pname = Procdesc.get_proc_name pdesc in
if Procname.is_java pname && if Typ.Procname.is_java pname &&
(Config.dynamic_dispatch = `Interface || Config.dynamic_dispatch = `Sound) (Config.dynamic_dispatch = `Interface || Config.dynamic_dispatch = `Sound)
then add_dispatch_calls pdesc cg tenv; then add_dispatch_calls pdesc cg tenv;
Procdesc.signal_did_preanalysis pdesc Procdesc.signal_did_preanalysis pdesc

@ -97,10 +97,10 @@ let is_visited node =
when starting and finishing the processing of a node *) when starting and finishing the processing of a node *)
module NodesHtml : sig module NodesHtml : sig
val start_node : val start_node :
int -> Location.t -> Procname.t -> Procdesc.Node.t list -> int -> Location.t -> Typ.Procname.t -> Procdesc.Node.t list ->
Procdesc.Node.t list -> Procdesc.Node.t list -> Procdesc.Node.t list -> Procdesc.Node.t list ->
SourceFile.t -> bool SourceFile.t -> bool
val finish_node : Procname.t -> int -> SourceFile.t -> unit val finish_node : Typ.Procname.t -> int -> SourceFile.t -> unit
end = struct end = struct
let log_files = Hashtbl.create 11 let log_files = Hashtbl.create 11
@ -123,7 +123,7 @@ end = struct
loc.Location.line; loc.Location.line;
F.fprintf fmt "PROC: %a LINE:%a\n" F.fprintf fmt "PROC: %a LINE:%a\n"
(Io_infer.Html.pp_proc_link [".."] proc_name) (Io_infer.Html.pp_proc_link [".."] proc_name)
(Escape.escape_xml (Procname.to_string proc_name)) (Escape.escape_xml (Typ.Procname.to_string proc_name))
(Io_infer.Html.pp_line_link source [".."]) loc.Location.line; (Io_infer.Html.pp_line_link source [".."]) loc.Location.line;
F.fprintf fmt "<br>PREDS:@\n"; F.fprintf fmt "<br>PREDS:@\n";
List.iter ~f:(fun node -> List.iter ~f:(fun node ->
@ -423,10 +423,10 @@ let write_proc_html source whole_seconds pdesc =
let fd, fmt = let fd, fmt =
Io_infer.Html.create Io_infer.Html.create
(DB.Results_dir.Abs_source_dir source) (DB.Results_dir.Abs_source_dir source)
[Procname.to_filename pname] in [Typ.Procname.to_filename pname] in
F.fprintf fmt "<center><h1>Procedure %a</h1></center>@\n" F.fprintf fmt "<center><h1>Procedure %a</h1></center>@\n"
(Io_infer.Html.pp_line_link source (Io_infer.Html.pp_line_link source
~text: (Some (Escape.escape_xml (Procname.to_string pname))) ~text: (Some (Escape.escape_xml (Typ.Procname.to_string pname)))
[]) [])
linenum; linenum;
List.iter List.iter
@ -556,7 +556,7 @@ let write_html_file linereader filename procs =
| Procdesc.Node.Start_node proc_name -> | Procdesc.Node.Start_node proc_name ->
let num_specs = List.length (Specs.get_specs proc_name) in let num_specs = List.length (Specs.get_specs proc_name) in
let label = let label =
(Escape.escape_xml (Procname.to_string proc_name)) ^ (Escape.escape_xml (Typ.Procname.to_string proc_name)) ^
": " ^ ": " ^
(string_of_int num_specs) ^ (string_of_int num_specs) ^
" specs" in " specs" in

@ -1638,7 +1638,7 @@ let get_overrides_of tenv supertype pname =
| Tstruct name -> ( | Tstruct name -> (
match Tenv.lookup tenv name with match Tenv.lookup tenv name with
| Some { methods } -> | Some { methods } ->
List.exists ~f:(fun m -> Procname.equal pname m) methods List.exists ~f:(fun m -> Typ.Procname.equal pname m) methods
| None -> | None ->
false false
) )
@ -1649,7 +1649,7 @@ let get_overrides_of tenv supertype pname =
if not (Typ.equal typ supertype) && Subtyping_check.check_subtype tenv typ supertype then if not (Typ.equal typ supertype) && Subtyping_check.check_subtype tenv typ supertype then
(* only select the ones that implement [pname] as overrides *) (* only select the ones that implement [pname] as overrides *)
let resolved_pname = let resolved_pname =
Procname.replace_class pname tname in Typ.Procname.replace_class pname tname in
if typ_has_method resolved_pname typ then (typ, resolved_pname) :: overrides_acc if typ_has_method resolved_pname typ then (typ, resolved_pname) :: overrides_acc
else overrides_acc else overrides_acc
else overrides_acc in else overrides_acc in

@ -67,7 +67,7 @@ val get_bounds : Tenv.t -> Prop.normal Prop.t -> Exp.t -> IntLit.t option * IntL
(** {2 Abduction prover} *) (** {2 Abduction prover} *)
(** [check_implication p1 p2] returns true if [p1|-p2] *) (** [check_implication p1 p2] returns true if [p1|-p2] *)
val check_implication : Procname.t -> Tenv.t -> Prop.normal Prop.t -> Prop.exposed Prop.t -> bool val check_implication : Typ.Procname.t -> Tenv.t -> Prop.normal Prop.t -> Prop.exposed Prop.t -> bool
type check = type check =
| Bounds_check | Bounds_check
@ -86,7 +86,7 @@ type implication_result =
frame)] where [sub] is a substitution which instantiates the frame)] where [sub] is a substitution which instantiates the
primed vars of [p1] and [p2], which are assumed to be disjoint. *) primed vars of [p1] and [p2], which are assumed to be disjoint. *)
val check_implication_for_footprint : val check_implication_for_footprint :
Procname.t -> Tenv.t -> Prop.normal Prop.t -> Prop.exposed Prop.t -> implication_result Typ.Procname.t -> Tenv.t -> Prop.normal Prop.t -> Prop.exposed Prop.t -> implication_result
(** {2 Cover: miminum set of pi's whose disjunction is equivalent to true} *) (** {2 Cover: miminum set of pi's whose disjunction is equivalent to true} *)
@ -112,7 +112,7 @@ sig
end end
val get_overrides_of : Tenv.t -> Typ.t -> Procname.t -> (Typ.t * Procname.t) list val get_overrides_of : Tenv.t -> Typ.t -> Typ.Procname.t -> (Typ.t * Typ.Procname.t) list

@ -445,7 +445,7 @@ let mk_ptsto_exp_footprint
| Config.Java -> Subtype.subtypes in | Config.Java -> Subtype.subtypes in
let create_ptsto footprint_part off0 = match root, off0, typ with let create_ptsto footprint_part off0 = match root, off0, typ with
| Exp.Lvar pvar, [], Typ.Tfun _ -> | Exp.Lvar pvar, [], Typ.Tfun _ ->
let fun_name = Procname.from_string_c_fun (Mangled.to_string (Pvar.get_name pvar)) in let fun_name = Typ.Procname.from_string_c_fun (Mangled.to_string (Pvar.get_name pvar)) in
let fun_exp = Exp.Const (Const.Cfun fun_name) in let fun_exp = Exp.Const (Const.Cfun fun_name) in
([], Prop.mk_ptsto tenv root (Sil.Eexp (fun_exp, inst)) (Exp.Sizeof (typ, None, st))) ([], Prop.mk_ptsto tenv root (Sil.Eexp (fun_exp, inst)) (Exp.Sizeof (typ, None, st)))
| _, [], Typ.Tfun _ -> | _, [], Typ.Tfun _ ->
@ -651,9 +651,9 @@ let add_guarded_by_constraints tenv prop lexp pdesc =
let dollar_normalize s = String.map s ~f:(function '$' -> '.' | c -> c) in let dollar_normalize s = String.map s ~f:(function '$' -> '.' | c -> c) in
String.is_suffix ~suffix:(dollar_normalize guarded_by_str) (dollar_normalize (class_str ^ ".class")) in String.is_suffix ~suffix:(dollar_normalize guarded_by_str) (dollar_normalize (class_str ^ ".class")) in
let guarded_by_str_is_current_class guarded_by_str = function let guarded_by_str_is_current_class guarded_by_str = function
| Procname.Java java_pname -> | Typ.Procname.Java java_pname ->
(* programmers write @GuardedBy("MyClass.class") when the field is guarded by the class *) (* programmers write @GuardedBy("MyClass.class") when the field is guarded by the class *)
guarded_by_str_is_class guarded_by_str (Procname.java_get_class_name java_pname) guarded_by_str_is_class guarded_by_str (Typ.Procname.java_get_class_name java_pname)
| _ -> false in | _ -> false in
let guarded_by_str_is_class_this class_name guarded_by_str = let guarded_by_str_is_class_this class_name guarded_by_str =
@ -665,8 +665,8 @@ let add_guarded_by_constraints tenv prop lexp pdesc =
(* return true if [guarded_by_str] is a suffix of "<name_of_super_class>.this" *) (* return true if [guarded_by_str] is a suffix of "<name_of_super_class>.this" *)
let guarded_by_str_is_super_class_this guarded_by_str pname = let guarded_by_str_is_super_class_this guarded_by_str pname =
match pname with match pname with
| Procname.Java java_pname -> | Typ.Procname.Java java_pname ->
let current_class_type_name = (Procname.java_get_class_type_name java_pname) in let current_class_type_name = (Typ.Procname.java_get_class_type_name java_pname) in
let comparison class_type_name _ = let comparison class_type_name _ =
guarded_by_str_is_class_this (Typename.to_string class_type_name) guarded_by_str in guarded_by_str_is_class_this (Typename.to_string class_type_name) guarded_by_str in
PatternMatch.supertype_exists tenv comparison current_class_type_name PatternMatch.supertype_exists tenv comparison current_class_type_name
@ -675,8 +675,8 @@ let add_guarded_by_constraints tenv prop lexp pdesc =
(* return true if [guarded_by_str] is as suffix of "<name_of_current_class>.this" *) (* return true if [guarded_by_str] is as suffix of "<name_of_current_class>.this" *)
let guarded_by_str_is_current_class_this guarded_by_str = function let guarded_by_str_is_current_class_this guarded_by_str = function
| Procname.Java java_pname -> | Typ.Procname.Java java_pname ->
guarded_by_str_is_class_this (Procname.java_get_class_name java_pname) guarded_by_str guarded_by_str_is_class_this (Typ.Procname.java_get_class_name java_pname) guarded_by_str
| _ -> false in | _ -> false in
let extract_guarded_by_str item_annot = let extract_guarded_by_str item_annot =
@ -804,7 +804,7 @@ let add_guarded_by_constraints tenv prop lexp pdesc =
| None -> false in | None -> false in
let is_synchronized_on_class guarded_by_str = let is_synchronized_on_class guarded_by_str =
guarded_by_str_is_current_class guarded_by_str pname && guarded_by_str_is_current_class guarded_by_str pname &&
Procdesc.is_java_synchronized pdesc && Procname.java_is_static pname in Procdesc.is_java_synchronized pdesc && Typ.Procname.java_is_static pname in
let warn accessed_fld guarded_by_str = let warn accessed_fld guarded_by_str =
let loc = State.get_loc () in let loc = State.get_loc () in
let err_desc = let err_desc =
@ -825,7 +825,7 @@ let add_guarded_by_constraints tenv prop lexp pdesc =
Procdesc.is_java_synchronized pdesc) Procdesc.is_java_synchronized pdesc)
|| ||
(guarded_by_str_is_current_class guarded_by_str pname && (guarded_by_str_is_current_class guarded_by_str pname &&
Procdesc.is_java_synchronized pdesc && Procname.java_is_static pname) || Procdesc.is_java_synchronized pdesc && Typ.Procname.java_is_static pname) ||
(* or the prop says we already have the lock *) (* or the prop says we already have the lock *)
List.exists List.exists
~f:(function ~f:(function
@ -862,7 +862,7 @@ let add_guarded_by_constraints tenv prop lexp pdesc =
prop.Prop.sigma in prop.Prop.sigma in
Procdesc.get_access pdesc <> PredSymb.Private && Procdesc.get_access pdesc <> PredSymb.Private &&
not (Annotations.pdesc_return_annot_ends_with pdesc Annotations.visibleForTesting) && not (Annotations.pdesc_return_annot_ends_with pdesc Annotations.visibleForTesting) &&
not (Procname.java_is_access_method (Procdesc.get_proc_name pdesc)) && not (Typ.Procname.java_is_access_method (Procdesc.get_proc_name pdesc)) &&
not (is_accessible_through_local_ref lexp) && not (is_accessible_through_local_ref lexp) &&
not guardedby_is_self_referential && not guardedby_is_self_referential &&
not (proc_has_suppress_guarded_by_annot pdesc) not (proc_has_suppress_guarded_by_annot pdesc)
@ -1320,7 +1320,7 @@ let check_dereference_error tenv pdesc (prop : Prop.normal Prop.t) lexp loc =
let is_nullable_attr = function let is_nullable_attr = function
| Sil.Apred ((Aretval (pname, ret_attr) | Aundef (pname, ret_attr, _, _)), _) | Sil.Apred ((Aretval (pname, ret_attr) | Aundef (pname, ret_attr, _, _)), _)
when Annotations.ia_is_nullable ret_attr -> when Annotations.ia_is_nullable ret_attr ->
nullable_obj_str := Some (Procname.to_string pname); nullable_obj_str := Some (Typ.Procname.to_string pname);
true true
| _ -> false in | _ -> false in
List.exists ~f:is_nullable_attr (Attribute.get_for_exp tenv prop exp) in List.exists ~f:is_nullable_attr (Attribute.get_for_exp tenv prop exp) in
@ -1492,8 +1492,8 @@ let rearrange ?(report_deref_errors=true) pdesc tenv lexp typ prop loc
if report_deref_errors then check_dereference_error tenv pdesc prop nlexp (State.get_loc ()); if report_deref_errors then check_dereference_error tenv pdesc prop nlexp (State.get_loc ());
let pname = Procdesc.get_proc_name pdesc in let pname = Procdesc.get_proc_name pdesc in
let prop' = let prop' =
if Config.csl_analysis && !Config.footprint && Procname.is_java pname && if Config.csl_analysis && !Config.footprint && Typ.Procname.is_java pname &&
not (Procname.is_constructor pname || Procname.is_class_initializer pname) not (Typ.Procname.is_constructor pname || Typ.Procname.is_class_initializer pname)
then add_guarded_by_constraints tenv prop lexp pdesc then add_guarded_by_constraints tenv prop lexp pdesc
else prop in else prop in
match Prop.prop_iter_create prop' with match Prop.prop_iter_create prop' with

@ -19,7 +19,7 @@ type log_t =
exn -> exn ->
unit unit
type log_issue = Procname.t -> log_t type log_issue = Typ.Procname.t -> log_t
type log_issue_from_errlog = Errlog.t -> log_t type log_issue_from_errlog = Errlog.t -> log_t
@ -64,8 +64,8 @@ let log_issue
failwithf failwithf
"Trying to report error on procedure %a, but cannot because no summary exists for this \ "Trying to report error on procedure %a, but cannot because no summary exists for this \
procedure. Did you mean to log the error on the caller of %a instead?" procedure. Did you mean to log the error on the caller of %a instead?"
Procname.pp proc_name Typ.Procname.pp proc_name
Procname.pp proc_name Typ.Procname.pp proc_name
let log_error = log_issue Exceptions.Kerror let log_error = log_issue Exceptions.Kerror
let log_warning = log_issue Exceptions.Kwarning let log_warning = log_issue Exceptions.Kwarning

@ -19,7 +19,7 @@ type log_t =
exn -> exn ->
unit unit
type log_issue = Procname.t -> log_t type log_issue = Typ.Procname.t -> log_t
type log_issue_from_errlog = Errlog.t -> log_t type log_issue_from_errlog = Errlog.t -> log_t

@ -225,9 +225,9 @@ let normalized_specs_to_specs =
module CallStats = struct (** module for tracing stats of function calls *) module CallStats = struct (** module for tracing stats of function calls *)
module PnameLocHash = Hashtbl.Make (struct module PnameLocHash = Hashtbl.Make (struct
type t = Procname.t * Location.t type t = Typ.Procname.t * Location.t
let hash (pname, loc) = Hashtbl.hash (Procname.hash_pname pname, loc.Location.line) let hash (pname, loc) = Hashtbl.hash (Typ.Procname.hash_pname pname, loc.Location.line)
let equal = [%compare.equal: Procname.t * Location.t] let equal = [%compare.equal: Typ.Procname.t * Location.t]
end) end)
(** kind of result of a procedure call *) (** kind of result of a procedure call *)
@ -278,14 +278,14 @@ module CallStats = struct (** module for tracing stats of function calls *)
PnameLocHash.iter (fun x tr -> elems := (x, tr) :: !elems) t; PnameLocHash.iter (fun x tr -> elems := (x, tr) :: !elems) t;
let sorted_elems = let sorted_elems =
let compare (pname_loc1, _) (pname_loc2, _) = let compare (pname_loc1, _) (pname_loc2, _) =
[%compare: Procname.t * Location.t] pname_loc1 pname_loc2 in [%compare: Typ.Procname.t * Location.t] pname_loc1 pname_loc2 in
List.sort ~cmp:compare !elems in List.sort ~cmp:compare !elems in
List.iter ~f:(fun (x, tr) -> f x tr) sorted_elems List.iter ~f:(fun (x, tr) -> f x tr) sorted_elems
(* (*
let pp fmt t = let pp fmt t =
let do_call (pname, loc) tr = let do_call (pname, loc) tr =
F.fprintf fmt "%a %a: %a@\n" Procname.pp pname Location.pp loc pp_trace tr in F.fprintf fmt "%a %a: %a@\n" Typ.Procname.pp pname Location.pp loc pp_trace tr in
iter do_call t iter do_call t
*) *)
end end
@ -347,11 +347,11 @@ type summary = {
proc_desc_option : Procdesc.t option; proc_desc_option : Procdesc.t option;
} }
type spec_tbl = summary Procname.Hash.t type spec_tbl = summary Typ.Procname.Hash.t
let spec_tbl: spec_tbl = Procname.Hash.create 128 let spec_tbl: spec_tbl = Typ.Procname.Hash.create 128
let clear_spec_tbl () = Procname.Hash.clear spec_tbl let clear_spec_tbl () = Typ.Procname.Hash.clear spec_tbl
(** pretty print analysis time; if [whole_seconds] is true, only print time in seconds *) (** pretty print analysis time; if [whole_seconds] is true, only print time in seconds *)
let pp_time whole_seconds fmt t = let pp_time whole_seconds fmt t =
@ -430,7 +430,7 @@ let get_signature summary =
"%a %a" "%a %a"
(Typ.pp_full Pp.text) (Typ.pp_full Pp.text)
summary.attributes.ProcAttributes.ret_type summary.attributes.ProcAttributes.ret_type
Procname.pp summary.attributes.ProcAttributes.proc_name in Typ.Procname.pp summary.attributes.ProcAttributes.proc_name in
let decl = F.asprintf "%t" pp in let decl = F.asprintf "%t" pp in
decl ^ "(" ^ !s ^ ")" decl ^ "(" ^ !s ^ ")"
@ -515,14 +515,14 @@ let summary_compact sh summary =
{ summary with payload = payload_compact sh summary.payload } { summary with payload = payload_compact sh summary.payload }
(** Add the summary to the table for the given function *) (** Add the summary to the table for the given function *)
let add_summary (proc_name : Procname.t) (summary: summary) : unit = let add_summary (proc_name : Typ.Procname.t) (summary: summary) : unit =
L.out "Adding summary for %a@\n@[<v 2> %a@]@." L.out "Adding summary for %a@\n@[<v 2> %a@]@."
Procname.pp proc_name Typ.Procname.pp proc_name
(pp_summary_text ~whole_seconds:false) summary; (pp_summary_text ~whole_seconds:false) summary;
Procname.Hash.replace spec_tbl proc_name summary Typ.Procname.Hash.replace spec_tbl proc_name summary
let specs_filename pname = let specs_filename pname =
let pname_file = Procname.to_filename pname in let pname_file = Typ.Procname.to_filename pname in
pname_file ^ Config.specs_files_suffix pname_file ^ Config.specs_files_suffix
(** path to the .specs file for the given procedure in the current results directory *) (** path to the .specs file for the given procedure in the current results directory *)
@ -582,7 +582,7 @@ let load_summary_to_spec_table proc_name =
let rec get_summary proc_name = let rec get_summary proc_name =
try try
Some (Procname.Hash.find spec_tbl proc_name) Some (Typ.Procname.Hash.find spec_tbl proc_name)
with Not_found -> with Not_found ->
if load_summary_to_spec_table proc_name then if load_summary_to_spec_table proc_name then
get_summary proc_name get_summary proc_name
@ -591,7 +591,7 @@ let rec get_summary proc_name =
let get_summary_unsafe s proc_name = let get_summary_unsafe s proc_name =
match get_summary proc_name with match get_summary proc_name with
| None -> | None ->
failwithf "[%s] Specs.get_summary_unsafe: %a Not found" s Procname.pp proc_name failwithf "[%s] Specs.get_summary_unsafe: %a Not found" s Typ.Procname.pp proc_name
| Some summary -> summary | Some summary -> summary
(** Check if the procedure is from a library: (** Check if the procedure is from a library:
@ -673,7 +673,7 @@ let get_flag summary key =
let get_specs_formals proc_name = let get_specs_formals proc_name =
match get_summary proc_name with match get_summary proc_name with
| None -> | None ->
raise (Failure ("Specs.get_specs_formals: " ^ (Procname.to_string proc_name) ^ "Not_found")) raise (Failure ("Specs.get_specs_formals: " ^ (Typ.Procname.to_string proc_name) ^ "Not_found"))
| Some summary -> | Some summary ->
let specs = get_specs_from_payload summary in let specs = get_specs_from_payload summary in
let formals = get_formals summary in let formals = get_formals summary in
@ -709,7 +709,7 @@ let store_summary (summ1: summary) =
(** Set the current status for the proc *) (** Set the current status for the proc *)
let set_status proc_name status = let set_status proc_name status =
match get_summary proc_name with match get_summary proc_name with
| None -> raise (Failure ("Specs.set_status: " ^ (Procname.to_string proc_name) ^ " Not_found")) | None -> raise (Failure ("Specs.set_status: " ^ (Typ.Procname.to_string proc_name) ^ " Not_found"))
| Some summary -> add_summary proc_name { summary with status = status } | Some summary -> add_summary proc_name { summary with status = status }
let empty_payload = let empty_payload =
@ -745,7 +745,7 @@ let init_summary
ProcAttributes.proc_flags = proc_flags; }; ProcAttributes.proc_flags = proc_flags; };
proc_desc_option; proc_desc_option;
} in } in
Procname.Hash.replace spec_tbl proc_attributes.ProcAttributes.proc_name summary Typ.Procname.Hash.replace spec_tbl proc_attributes.ProcAttributes.proc_name summary
(** Reset a summary rebuilding the dependents and preserving the proc attributes if present. *) (** Reset a summary rebuilding the dependents and preserving the proc attributes if present. *)
let reset_summary proc_name attributes_opt proc_desc_option = let reset_summary proc_name attributes_opt proc_desc_option =

@ -94,10 +94,10 @@ module CallStats : sig
type trace = (call_result * bool) list type trace = (call_result * bool) list
(** iterate over results of procedure calls *) (** iterate over results of procedure calls *)
val iter : (Procname.t * Location.t -> trace -> unit) -> t -> unit val iter : (Typ.Procname.t * Location.t -> trace -> unit) -> t -> unit
(** trace a procedure call *) (** trace a procedure call *)
val trace : t -> Procname.t -> Location.t -> call_result -> bool -> unit val trace : t -> Typ.Procname.t -> Location.t -> call_result -> bool -> unit
(** pretty print a call trace *) (** pretty print a call trace *)
val pp_trace : Format.formatter -> trace -> unit val pp_trace : Format.formatter -> trace -> unit
@ -159,10 +159,10 @@ type summary = {
} }
(** Add the summary to the table for the given function *) (** Add the summary to the table for the given function *)
val add_summary : Procname.t -> summary -> unit val add_summary : Typ.Procname.t -> summary -> unit
(** Check if a summary for a given procedure exists in the models directory *) (** Check if a summary for a given procedure exists in the models directory *)
val summary_exists_in_models : Procname.t -> bool val summary_exists_in_models : Typ.Procname.t -> bool
(** remove all the elements from the spec table *) (** remove all the elements from the spec table *)
val clear_spec_tbl : unit -> unit val clear_spec_tbl : unit -> unit
@ -171,10 +171,10 @@ val clear_spec_tbl : unit -> unit
val d_spec : 'a spec -> unit val d_spec : 'a spec -> unit
(** Return the summary option for the procedure name *) (** Return the summary option for the procedure name *)
val get_summary : Procname.t -> summary option val get_summary : Typ.Procname.t -> summary option
(** Get the procedure name *) (** Get the procedure name *)
val get_proc_name : summary -> Procname.t val get_proc_name : summary -> Typ.Procname.t
(** Get the attributes of the procedure. *) (** Get the attributes of the procedure. *)
val get_attributes : summary -> ProcAttributes.t val get_attributes : summary -> ProcAttributes.t
@ -195,16 +195,16 @@ val get_phase : summary -> phase
val get_signature : summary -> string val get_signature : summary -> string
(** Return the specs for the proc in the spec table *) (** Return the specs for the proc in the spec table *)
val get_specs : Procname.t -> Prop.normal spec list val get_specs : Typ.Procname.t -> Prop.normal spec list
(** Return the specs and formal parameters for the proc in the spec table *) (** Return the specs and formal parameters for the proc in the spec table *)
val get_specs_formals : Procname.t -> Prop.normal spec list * (Mangled.t * Typ.t) list val get_specs_formals : Typ.Procname.t -> Prop.normal spec list * (Mangled.t * Typ.t) list
(** Get the specs from the payload of the summary. *) (** Get the specs from the payload of the summary. *)
val get_specs_from_payload : summary -> Prop.normal spec list val get_specs_from_payload : summary -> Prop.normal spec list
(** @deprecated Return the summary for the procedure name. Raises an exception when not found. *) (** @deprecated Return the summary for the procedure name. Raises an exception when not found. *)
val get_summary_unsafe : string -> Procname.t -> summary val get_summary_unsafe : string -> Typ.Procname.t -> summary
(** Return the status (active v.s. inactive) of a procedure summary *) (** Return the status (active v.s. inactive) of a procedure summary *)
val get_status : summary -> status val get_status : summary -> status
@ -217,19 +217,19 @@ val is_active : summary -> bool
val init_summary : val init_summary :
( Procdesc.Node.id list * (* nodes *) ( Procdesc.Node.id list * (* nodes *)
ProcAttributes.proc_flags * (* procedure flags *) ProcAttributes.proc_flags * (* procedure flags *)
(Procname.t * Location.t) list * (* calls *) (Typ.Procname.t * Location.t) list * (* calls *)
ProcAttributes.t * (* attributes of the procedure *) ProcAttributes.t * (* attributes of the procedure *)
Procdesc.t option) (* procdesc option *) Procdesc.t option) (* procdesc option *)
-> unit -> unit
(** Reset a summary rebuilding the dependents and preserving the proc attributes if present. *) (** Reset a summary rebuilding the dependents and preserving the proc attributes if present. *)
val reset_summary : Procname.t -> ProcAttributes.t option -> Procdesc.t option -> unit val reset_summary : Typ.Procname.t -> ProcAttributes.t option -> Procdesc.t option -> unit
(** Load procedure summary from the given file *) (** Load procedure summary from the given file *)
val load_summary : DB.filename -> summary option val load_summary : DB.filename -> summary option
(** Check if a procedure summary exists for the given procedure name *) (** Check if a procedure summary exists for the given procedure name *)
val summary_exists : Procname.t -> bool val summary_exists : Typ.Procname.t -> bool
(** Cast a list of normalized specs to a list of specs *) (** Cast a list of normalized specs to a list of specs *)
val normalized_specs_to_specs : NormSpec.t list -> Prop.normal spec list val normalized_specs_to_specs : NormSpec.t list -> Prop.normal spec list
@ -258,20 +258,20 @@ val pdesc_resolve_attributes : Procdesc.t -> ProcAttributes.t
then look at the attributes table. then look at the attributes table.
If no attributes can be found, return None. If no attributes can be found, return None.
*) *)
val proc_resolve_attributes : Procname.t -> ProcAttributes.t option val proc_resolve_attributes : Typ.Procname.t -> ProcAttributes.t option
(** Check if the procedure is from a library: (** Check if the procedure is from a library:
It's not defined, and there is no spec file for it. *) It's not defined, and there is no spec file for it. *)
val proc_is_library : ProcAttributes.t -> bool val proc_is_library : ProcAttributes.t -> bool
(** Set the current status for the proc *) (** Set the current status for the proc *)
val set_status : Procname.t -> status -> unit val set_status : Typ.Procname.t -> status -> unit
(** Convert spec into normal form w.r.t. variable renaming *) (** Convert spec into normal form w.r.t. variable renaming *)
val spec_normalize : Tenv.t -> Prop.normal spec -> NormSpec.t val spec_normalize : Tenv.t -> Prop.normal spec -> NormSpec.t
(** path to the .specs file for the given procedure in the current results dir *) (** path to the .specs file for the given procedure in the current results dir *)
val res_dir_specs_filename : Procname.t -> DB.filename val res_dir_specs_filename : Typ.Procname.t -> DB.filename
(** Save summary for the procedure into the spec database *) (** Save summary for the procedure into the spec database *)
val store_summary : summary -> unit val store_summary : summary -> unit

@ -275,7 +275,7 @@ let get_session () =
let get_path_pos () = let get_path_pos () =
let pname = match get_prop_tenv_pdesc () with let pname = match get_prop_tenv_pdesc () with
| Some (_, _, pdesc) -> Procdesc.get_proc_name pdesc | Some (_, _, pdesc) -> Procdesc.get_proc_name pdesc
| None -> Procname.from_string_c_fun "unknown_procedure" in | None -> Typ.Procname.from_string_c_fun "unknown_procedure" in
let nid = get_node_id () in let nid = get_node_id () in
(pname, (nid :> int)) (pname, (nid :> int))
@ -307,7 +307,7 @@ let mark_instr_fail exn =
fs.instr_fail <- fs.instr_fail + 1 fs.instr_fail <- fs.instr_fail + 1
type log_issue = type log_issue =
Procname.t -> Typ.Procname.t ->
?loc: Location.t -> ?loc: Location.t ->
?node_id: (int * int) -> ?node_id: (int * int) ->
?session: int -> ?session: int ->

@ -85,7 +85,7 @@ val mark_instr_ok : unit -> unit
val mk_find_duplicate_nodes: Procdesc.t -> (Procdesc.Node.t -> Procdesc.NodeSet.t) val mk_find_duplicate_nodes: Procdesc.t -> (Procdesc.Node.t -> Procdesc.NodeSet.t)
type log_issue = type log_issue =
Procname.t -> Typ.Procname.t ->
?loc: Location.t -> ?loc: Location.t ->
?node_id: (int * int) -> ?node_id: (int * int) ->
?session: int -> ?session: int ->
@ -94,7 +94,7 @@ type log_issue =
unit unit
(** Process the failures during symbolic execution of a procedure *) (** Process the failures during symbolic execution of a procedure *)
val process_execution_failures : log_issue -> Procname.t -> unit val process_execution_failures : log_issue -> Typ.Procname.t -> unit
(** Reset all the global data. *) (** Reset all the global data. *)
val reset : unit -> unit val reset : unit -> unit

@ -55,7 +55,7 @@ let get_blocks_nullified node =
captured variables in the block we obtain a leak. *) captured variables in the block we obtain a leak. *)
let check_block_retain_cycle tenv caller_pname prop block_nullified = let check_block_retain_cycle tenv caller_pname prop block_nullified =
let mblock = Pvar.get_name block_nullified in let mblock = Pvar.get_name block_nullified in
let block_pname = Procname.mangled_objc_block (Mangled.to_string mblock) in let block_pname = Typ.Procname.mangled_objc_block (Mangled.to_string mblock) in
let block_captured = let block_captured =
match AttributesTable.load_attributes block_pname with match AttributesTable.load_attributes block_pname with
| Some attributes -> | Some attributes ->
@ -366,10 +366,10 @@ and prune_union tenv ~positive condition1 condition2 prop =
let dangerous_functions = let dangerous_functions =
let dangerous_list = ["gets"] in let dangerous_list = ["gets"] in
ref ((List.map ~f:Procname.from_string_c_fun) dangerous_list) ref ((List.map ~f:Typ.Procname.from_string_c_fun) dangerous_list)
let check_inherently_dangerous_function caller_pname callee_pname = let check_inherently_dangerous_function caller_pname callee_pname =
if List.exists ~f:(Procname.equal callee_pname) !dangerous_functions then if List.exists ~f:(Typ.Procname.equal callee_pname) !dangerous_functions then
let exn = let exn =
Exceptions.Inherently_dangerous_function Exceptions.Inherently_dangerous_function
(Localise.desc_inherently_dangerous_function callee_pname) in (Localise.desc_inherently_dangerous_function callee_pname) in
@ -472,7 +472,7 @@ let check_deallocate_static_memory prop_after =
let method_exists right_proc_name methods = let method_exists right_proc_name methods =
if Config.curr_language_is Config.Java then if Config.curr_language_is Config.Java then
List.exists ~f:(fun meth_name -> Procname.equal right_proc_name meth_name) methods List.exists ~f:(fun meth_name -> Typ.Procname.equal right_proc_name meth_name) methods
else (* ObjC/C++ case : The attribute map will only exist when we have code for the method or else (* ObjC/C++ case : The attribute map will only exist when we have code for the method or
the method has been called directly somewhere. It can still be that this is not the the method has been called directly somewhere. It can still be that this is not the
case but we have a model for the method. *) case but we have a model for the method. *)
@ -486,7 +486,7 @@ let resolve_method tenv class_name proc_name =
let rec resolve (class_name: Typename.t) = let rec resolve (class_name: Typename.t) =
visited := Typename.Set.add class_name !visited; visited := Typename.Set.add class_name !visited;
let right_proc_name = let right_proc_name =
Procname.replace_class proc_name class_name in Typ.Procname.replace_class proc_name class_name in
match class_name, Tenv.lookup tenv class_name with match class_name, Tenv.lookup tenv class_name with
| TN_csu (Class _, _), Some { methods; supers } -> | TN_csu (Class _, _), Some { methods; supers } ->
if method_exists right_proc_name methods then if method_exists right_proc_name methods then
@ -521,15 +521,15 @@ let resolve_typename prop receiver_exp =
(** If the dynamic type of the receiver actual T_actual is a subtype of the reciever type T_formal (** If the dynamic type of the receiver actual T_actual is a subtype of the reciever type T_formal
in the signature of [pname], resolve [pname] to T_actual.[pname]. *) in the signature of [pname], resolve [pname] to T_actual.[pname]. *)
let resolve_virtual_pname tenv prop actuals callee_pname call_flags : Procname.t list = let resolve_virtual_pname tenv prop actuals callee_pname call_flags : Typ.Procname.t list =
let resolve receiver_exp pname prop = match resolve_typename prop receiver_exp with let resolve receiver_exp pname prop = match resolve_typename prop receiver_exp with
| Some class_name -> resolve_method tenv class_name pname | Some class_name -> resolve_method tenv class_name pname
| None -> pname in | None -> pname in
let get_receiver_typ pname fallback_typ = let get_receiver_typ pname fallback_typ =
match pname with match pname with
| Procname.Java pname_java -> | Typ.Procname.Java pname_java ->
begin begin
let name = Procname.java_get_class_type_name pname_java in let name = Typ.Procname.java_get_class_type_name pname_java in
match Tenv.lookup tenv name with match Tenv.lookup tenv name with
| Some _ -> Typ.Tptr (Tstruct name, Pk_pointer) | Some _ -> Typ.Tptr (Tstruct name, Pk_pointer)
| None -> fallback_typ | None -> fallback_typ
@ -568,7 +568,7 @@ let resolve_virtual_pname tenv prop actuals callee_pname call_flags : Procname.t
let resolved_pname = do_resolve callee_pname receiver_exp actual_receiver_typ in let resolved_pname = do_resolve callee_pname receiver_exp actual_receiver_typ in
let feasible_targets = List.filter ~f:may_dispatch_to targets in let feasible_targets = List.filter ~f:may_dispatch_to targets in
(* make sure [resolved_pname] is not a duplicate *) (* make sure [resolved_pname] is not a duplicate *)
if List.mem ~equal:Procname.equal feasible_targets resolved_pname if List.mem ~equal:Typ.Procname.equal feasible_targets resolved_pname
then feasible_targets then feasible_targets
else resolved_pname :: feasible_targets else resolved_pname :: feasible_targets
else else
@ -577,7 +577,7 @@ let resolve_virtual_pname tenv prop actuals callee_pname call_flags : Procname.t
match call_flags.CallFlags.cf_targets with match call_flags.CallFlags.cf_targets with
| target :: _ when call_flags.CallFlags.cf_interface && | target :: _ when call_flags.CallFlags.cf_interface &&
receiver_types_equal callee_pname actual_receiver_typ && receiver_types_equal callee_pname actual_receiver_typ &&
Procname.equal resolved_target callee_pname -> Typ.Procname.equal resolved_target callee_pname ->
(* "production mode" of dynamic dispatch for Java: unsound, but faster. the handling (* "production mode" of dynamic dispatch for Java: unsound, but faster. the handling
is restricted to interfaces: if we can't resolve an interface call, we pick the is restricted to interfaces: if we can't resolve an interface call, we pick the
first implementation of the interface and call it *) first implementation of the interface and call it *)
@ -590,9 +590,9 @@ let resolve_virtual_pname tenv prop actuals callee_pname call_flags : Procname.t
(** Resolve the name of the procedure to call based on the type of the arguments *) (** Resolve the name of the procedure to call based on the type of the arguments *)
let resolve_java_pname tenv prop args pname_java call_flags : Procname.java = let resolve_java_pname tenv prop args pname_java call_flags : Typ.Procname.java =
let resolve_from_args resolved_pname_java args = let resolve_from_args resolved_pname_java args =
let parameters = Procname.java_get_parameters resolved_pname_java in let parameters = Typ.Procname.java_get_parameters resolved_pname_java in
if List.length args <> List.length parameters then if List.length args <> List.length parameters then
resolved_pname_java resolved_pname_java
else else
@ -601,10 +601,10 @@ let resolve_java_pname tenv prop args pname_java call_flags : Procname.java =
~f:(fun accu (arg_exp, _) name -> ~f:(fun accu (arg_exp, _) name ->
match resolve_typename prop arg_exp with match resolve_typename prop arg_exp with
| Some class_name -> | Some class_name ->
(Procname.split_classname (Typename.name class_name)) :: accu (Typ.Procname.split_classname (Typename.name class_name)) :: accu
| None -> name :: accu) | None -> name :: accu)
~init:[] args (Procname.java_get_parameters resolved_pname_java) |> List.rev in ~init:[] args (Typ.Procname.java_get_parameters resolved_pname_java) |> List.rev in
Procname.java_replace_parameters resolved_pname_java resolved_params in Typ.Procname.java_replace_parameters resolved_pname_java resolved_params in
let resolved_pname_java, other_args = let resolved_pname_java, other_args =
match args with match args with
| [] -> | [] ->
@ -615,8 +615,8 @@ let resolve_java_pname tenv prop args pname_java call_flags : Procname.java =
match resolve_typename prop first_arg with match resolve_typename prop first_arg with
| Some class_name -> | Some class_name ->
begin begin
match resolve_method tenv class_name (Procname.Java pname_java) with match resolve_method tenv class_name (Typ.Procname.Java pname_java) with
| Procname.Java resolved_pname_java -> | Typ.Procname.Java resolved_pname_java ->
resolved_pname_java resolved_pname_java
| _ -> | _ ->
pname_java pname_java
@ -625,7 +625,7 @@ let resolve_java_pname tenv prop args pname_java call_flags : Procname.java =
pname_java pname_java
end in end in
resolved, other_args resolved, other_args
| _ :: other_args when Procname.is_constructor (Procname.Java pname_java) -> | _ :: other_args when Typ.Procname.is_constructor (Typ.Procname.Java pname_java) ->
pname_java, other_args pname_java, other_args
| args -> | args ->
pname_java, args in pname_java, args in
@ -635,11 +635,11 @@ let resolve_java_pname tenv prop args pname_java call_flags : Procname.java =
(** Resolve the procedure name and run the analysis of the resolved procedure (** Resolve the procedure name and run the analysis of the resolved procedure
if not already analyzed *) if not already analyzed *)
let resolve_and_analyze let resolve_and_analyze
tenv caller_pdesc prop args callee_proc_name call_flags : Procname.t * Specs.summary option = tenv caller_pdesc prop args callee_proc_name call_flags : Typ.Procname.t * Specs.summary option =
(* TODO (#15748878): Fix conflict with method overloading by encoding in the procedure name (* TODO (#15748878): Fix conflict with method overloading by encoding in the procedure name
whether the method is defined or generated by the specialization *) whether the method is defined or generated by the specialization *)
let analyze_ondemand resolved_pname : Specs.summary option = let analyze_ondemand resolved_pname : Specs.summary option =
if Procname.equal resolved_pname callee_proc_name then if Typ.Procname.equal resolved_pname callee_proc_name then
Ondemand.analyze_proc_name ~propagate_exceptions:true caller_pdesc callee_proc_name Ondemand.analyze_proc_name ~propagate_exceptions:true caller_pdesc callee_proc_name
else else
(* Create the type sprecialized procedure description and analyze it directly *) (* Create the type sprecialized procedure description and analyze it directly *)
@ -656,8 +656,8 @@ let resolve_and_analyze
(Ondemand.get_proc_desc callee_proc_name)) in (Ondemand.get_proc_desc callee_proc_name)) in
Option.bind resolved_proc_desc_option analyze in Option.bind resolved_proc_desc_option analyze in
let resolved_pname = match callee_proc_name with let resolved_pname = match callee_proc_name with
| Procname.Java callee_proc_name_java -> | Typ.Procname.Java callee_proc_name_java ->
Procname.Java Typ.Procname.Java
(resolve_java_pname tenv prop args callee_proc_name_java call_flags) (resolve_java_pname tenv prop args callee_proc_name_java call_flags)
| _ -> | _ ->
callee_proc_name in callee_proc_name in
@ -668,11 +668,11 @@ let resolve_and_analyze
to be only the protocol. *) to be only the protocol. *)
let call_constructor_url_update_args pname actual_params = let call_constructor_url_update_args pname actual_params =
let url_pname = let url_pname =
Procname.Java Typ.Procname.Java
(Procname.java (Typ.Procname.java
(Typename.Java.from_string "java.net.URL") None "<init>" (Typename.Java.from_string "java.net.URL") None "<init>"
[(Some "java.lang"), "String"] Procname.Non_Static) in [(Some "java.lang"), "String"] Typ.Procname.Non_Static) in
if (Procname.equal url_pname pname) then if (Typ.Procname.equal url_pname pname) then
(match actual_params with (match actual_params with
| [this; (Exp.Const (Const.Cstr s), atype)] -> | [this; (Exp.Const (Const.Cstr s), atype)] ->
let parts = Str.split (Str.regexp_string "://") s in let parts = Str.split (Str.regexp_string "://") s in
@ -705,9 +705,9 @@ let receiver_self receiver prop =
a check for null, which is considered good practice. *) a check for null, which is considered good practice. *)
let force_objc_init_return_nil pdesc callee_pname tenv ret_id pre path receiver = let force_objc_init_return_nil pdesc callee_pname tenv ret_id pre path receiver =
let current_pname = Procdesc.get_proc_name pdesc in let current_pname = Procdesc.get_proc_name pdesc in
if Procname.is_constructor callee_pname && if Typ.Procname.is_constructor callee_pname &&
receiver_self receiver pre && receiver_self receiver pre &&
!Config.footprint && Procname.is_constructor current_pname then !Config.footprint && Typ.Procname.is_constructor current_pname then
match ret_id with match ret_id with
| Some (ret_id, _) -> | Some (ret_id, _) ->
let propset = prune_ne tenv ~positive:false (Exp.Var ret_id) Exp.zero pre in let propset = prune_ne tenv ~positive:false (Exp.Var ret_id) Exp.zero pre in
@ -728,7 +728,7 @@ let handle_objc_instance_method_call_or_skip pdesc tenv actual_pars path callee_
ret_id res = ret_id res =
let path_description = let path_description =
"Message " ^ "Message " ^
(Procname.to_simplified_string callee_pname) ^ (Typ.Procname.to_simplified_string callee_pname) ^
" with receiver nil returns nil." in " with receiver nil returns nil." in
let receiver = (match actual_pars with let receiver = (match actual_pars with
| (e, _):: _ -> e | (e, _):: _ -> e
@ -756,7 +756,7 @@ let handle_objc_instance_method_call_or_skip pdesc tenv actual_pars path callee_
let path = Paths.Path.add_description path path_description in let path = Paths.Path.add_description path path_description in
L.d_strln L.d_strln
("Object-C method " ^ ("Object-C method " ^
Procname.to_string callee_pname ^ Typ.Procname.to_string callee_pname ^
" called with nil receiver. Returning 0/nil"); " called with nil receiver. Returning 0/nil");
(* We wish to nullify the result. However, in some cases, (* We wish to nullify the result. However, in some cases,
we want to add the attribute OBJC_NULL to it so that we *) we want to add the attribute OBJC_NULL to it so that we *)
@ -826,10 +826,10 @@ let add_struct_value_to_footprint tenv abduced_pv typ prop =
prop', struct_strexp prop', struct_strexp
let add_constraints_on_retval tenv pdesc prop ret_exp ~has_nullable_annot typ callee_pname callee_loc= let add_constraints_on_retval tenv pdesc prop ret_exp ~has_nullable_annot typ callee_pname callee_loc=
if Procname.is_infer_undefined callee_pname then prop if Typ.Procname.is_infer_undefined callee_pname then prop
else else
let is_rec_call pname = (* TODO: (t7147096) extend this to detect mutual recursion *) let is_rec_call pname = (* TODO: (t7147096) extend this to detect mutual recursion *)
Procname.equal pname (Procdesc.get_proc_name pdesc) in Typ.Procname.equal pname (Procdesc.get_proc_name pdesc) in
let already_has_abduced_retval p abduced_ret_pv = let already_has_abduced_retval p abduced_ret_pv =
List.exists List.exists
~f:(fun hpred -> match hpred with ~f:(fun hpred -> match hpred with
@ -1028,7 +1028,7 @@ let rec sym_exec tenv current_pdesc _instr (prop_: Prop.normal Prop.t) path
let exn = Exceptions.Skip_function (Localise.desc_skip_function callee_pname) in let exn = Exceptions.Skip_function (Localise.desc_skip_function callee_pname) in
Reporting.log_info current_pname exn; Reporting.log_info current_pname exn;
L.d_strln L.d_strln
("Undefined function " ^ Procname.to_string callee_pname ("Undefined function " ^ Typ.Procname.to_string callee_pname
^ ", returning undefined value."); ^ ", returning undefined value.");
(match Specs.get_summary current_pname with (match Specs.get_summary current_pname with
| None -> () | None -> ()
@ -1155,8 +1155,8 @@ let rec sym_exec tenv current_pdesc _instr (prop_: Prop.normal Prop.t) path
let attrs_opt = let attrs_opt =
let attr_opt = Option.map ~f:Procdesc.get_attributes callee_pdesc_opt in let attr_opt = Option.map ~f:Procdesc.get_attributes callee_pdesc_opt in
match attr_opt, resolved_pname with match attr_opt, resolved_pname with
| Some attrs, Procname.ObjC_Cpp _ -> Some attrs | Some attrs, Typ.Procname.ObjC_Cpp _ -> Some attrs
| None, Procname.ObjC_Cpp _ -> AttributesTable.load_attributes resolved_pname | None, Typ.Procname.ObjC_Cpp _ -> AttributesTable.load_attributes resolved_pname
| _ -> None in | _ -> None in
let objc_property_accessor_ret_typ_opt = let objc_property_accessor_ret_typ_opt =
match attrs_opt with match attrs_opt with
@ -1203,7 +1203,7 @@ let rec sym_exec tenv current_pdesc _instr (prop_: Prop.normal Prop.t) path
end else begin end else begin
L.d_str "Unknown function pointer "; Sil.d_exp fun_exp; L.d_str "Unknown function pointer "; Sil.d_exp fun_exp;
L.d_strln ", returning undefined value."; L.d_strln ", returning undefined value.";
let callee_pname = Procname.from_string_c_fun "__function_pointer__" in let callee_pname = Typ.Procname.from_string_c_fun "__function_pointer__" in
unknown_or_scan_call ~is_scan:false None Annot.Item.empty Builtin.{ unknown_or_scan_call ~is_scan:false None Annot.Item.empty Builtin.{
pdesc= current_pdesc; instr; tenv; prop_= prop_r; path; ret_id; args= n_actual_params; pdesc= current_pdesc; instr; tenv; prop_= prop_r; path; ret_id; args= n_actual_params;
proc_name= callee_pname; loc; } proc_name= callee_pname; loc; }
@ -1213,8 +1213,8 @@ let rec sym_exec tenv current_pdesc _instr (prop_: Prop.normal Prop.t) path
let eprop = Prop.expose prop_ in let eprop = Prop.expose prop_ in
match List.partition_tf match List.partition_tf
~f:(function ~f:(function
| Sil.Hpointsto (Exp.Lvar pvar', _, _) -> Pvar.equal pvar pvar' | Sil.Hpointsto (Exp.Lvar pvar', _, _) -> Pvar.equal pvar pvar'
| _ -> false) eprop.Prop.sigma with | _ -> false) eprop.Prop.sigma with
| [Sil.Hpointsto(e, se, typ)], sigma' -> | [Sil.Hpointsto(e, se, typ)], sigma' ->
let sigma'' = let sigma'' =
let se' = execute_nullify_se se in let se' = execute_nullify_se se in
@ -1439,7 +1439,7 @@ and unknown_or_scan_call ~is_scan ret_type_option ret_annots
let pre_final = let pre_final =
(* in Java, assume that skip functions close resources passed as params *) (* in Java, assume that skip functions close resources passed as params *)
let pre_1 = let pre_1 =
if Procname.is_java callee_pname if Typ.Procname.is_java callee_pname
then remove_file_attribute pre then remove_file_attribute pre
else pre in else pre in
let pre_2 = match ret_id, ret_type_option with let pre_2 = match ret_id, ret_type_option with
@ -1588,7 +1588,7 @@ and proc_call summary {Builtin.pdesc; tenv; prop_= pre; path; ret_id; args= actu
L.d_str "formal parameters: "; Typ.d_list formal_types; L.d_ln (); L.d_str "formal parameters: "; Typ.d_list formal_types; L.d_ln ();
actual_pars actual_pars
| [], _ -> | [], _ ->
L.d_str ("**** ERROR: Procedure " ^ Procname.to_string callee_pname); L.d_str ("**** ERROR: Procedure " ^ Typ.Procname.to_string callee_pname);
L.d_strln (" mismatch in the number of parameters ****"); L.d_strln (" mismatch in the number of parameters ****");
L.d_str "actual parameters: "; Sil.d_exp_list (List.map ~f:fst actual_pars); L.d_ln (); L.d_str "actual parameters: "; Sil.d_exp_list (List.map ~f:fst actual_pars); L.d_ln ();
L.d_str "formal parameters: "; Typ.d_list formal_types; L.d_ln (); L.d_str "formal parameters: "; Typ.d_list formal_types; L.d_ln ();

@ -32,12 +32,12 @@ val unknown_or_scan_call : is_scan:bool -> Typ.t option -> Annot.Item.t -> Built
val check_variadic_sentinel : ?fails_on_nil:bool -> int -> int * int -> Builtin.t val check_variadic_sentinel : ?fails_on_nil:bool -> int -> int * int -> Builtin.t
val check_untainted : val check_untainted :
Tenv.t -> Exp.t -> PredSymb.taint_kind -> Procname.t -> Procname.t -> Prop.normal Prop.t -> Tenv.t -> Exp.t -> PredSymb.taint_kind -> Typ.Procname.t -> Typ.Procname.t -> Prop.normal Prop.t ->
Prop.normal Prop.t Prop.normal Prop.t
(** Check for arithmetic problems and normalize an expression. *) (** Check for arithmetic problems and normalize an expression. *)
val check_arith_norm_exp : val check_arith_norm_exp :
Tenv.t -> Procname.t -> Exp.t -> Prop.normal Prop.t -> Exp.t * Prop.normal Prop.t Tenv.t -> Typ.Procname.t -> Exp.t -> Prop.normal Prop.t -> Exp.t * Prop.normal Prop.t
val prune : Tenv.t -> positive:bool -> Exp.t -> Prop.normal Prop.t -> Propset.t val prune : Tenv.t -> positive:bool -> Exp.t -> Prop.normal Prop.t -> Propset.t
@ -45,4 +45,4 @@ val prune : Tenv.t -> positive:bool -> Exp.t -> Prop.normal Prop.t -> Propset.t
the procname that the method name will actually resolve to at runtime. For example, if we have a the procname that the method name will actually resolve to at runtime. For example, if we have a
procname like Foo.toString() and Foo does not override toString(), we must resolve the call to procname like Foo.toString() and Foo does not override toString(), we must resolve the call to
toString(). We will end up with Super.toString() where Super is some superclass of Foo. *) toString(). We will end up with Super.toString() where Super is some superclass of Foo. *)
val resolve_method : Tenv.t -> Typename.t -> Procname.t -> Procname.t val resolve_method : Tenv.t -> Typename.t -> Typ.Procname.t -> Typ.Procname.t

@ -30,7 +30,7 @@ type deref_error =
| Deref_freed of PredSymb.res_action (** dereference a freed pointer *) | Deref_freed of PredSymb.res_action (** dereference a freed pointer *)
| Deref_minusone (** dereference -1 *) | Deref_minusone (** dereference -1 *)
| Deref_null of PredSymb.path_pos (** dereference null *) | Deref_null of PredSymb.path_pos (** dereference null *)
| Deref_undef of Procname.t * Location.t * PredSymb.path_pos | Deref_undef of Typ.Procname.t * Location.t * PredSymb.path_pos
(** dereference a value coming from the given undefined function *) (** dereference a value coming from the given undefined function *)
| Deref_undef_exp (** dereference an undefined expression *) | Deref_undef_exp (** dereference an undefined expression *)
@ -116,7 +116,7 @@ let spec_rename_vars pname spec =
(** Find and number the specs for [proc_name], (** Find and number the specs for [proc_name],
after renaming their vars, and also return the parameters *) after renaming their vars, and also return the parameters *)
let spec_find_rename trace_call (proc_name : Procname.t) let spec_find_rename trace_call (proc_name : Typ.Procname.t)
: (int * Prop.exposed Specs.spec) list * Pvar.t list = : (int * Prop.exposed Specs.spec) list * Pvar.t list =
try try
let count = ref 0 in let count = ref 0 in
@ -127,7 +127,7 @@ let spec_find_rename trace_call (proc_name : Procname.t)
begin begin
trace_call Specs.CallStats.CR_not_found; trace_call Specs.CallStats.CR_not_found;
raise (Exceptions.Precondition_not_found raise (Exceptions.Precondition_not_found
(Localise.verbatim_desc (Procname.to_string proc_name), __POS__)) (Localise.verbatim_desc (Typ.Procname.to_string proc_name), __POS__))
end; end;
let formal_parameters = let formal_parameters =
List.map ~f:(fun (x, _) -> Pvar.mk_callee x proc_name) formals in List.map ~f:(fun (x, _) -> Pvar.mk_callee x proc_name) formals in
@ -135,10 +135,10 @@ let spec_find_rename trace_call (proc_name : Procname.t)
with Not_found -> begin with Not_found -> begin
L.d_strln L.d_strln
("ERROR: found no entry for procedure " ^ ("ERROR: found no entry for procedure " ^
Procname.to_string proc_name ^ Typ.Procname.to_string proc_name ^
". Give up..."); ". Give up...");
raise (Exceptions.Precondition_not_found raise (Exceptions.Precondition_not_found
(Localise.verbatim_desc (Procname.to_string proc_name), __POS__)) (Localise.verbatim_desc (Typ.Procname.to_string proc_name), __POS__))
end end
(** Process a splitting coming straight from a call to the prover: (** Process a splitting coming straight from a call to the prover:
@ -898,7 +898,7 @@ let mk_posts tenv ret_id prop callee_pname callee_attrs posts =
let last_call_ret_non_null = let last_call_ret_non_null =
List.exists List.exists
~f:(function ~f:(function
| Sil.Apred (Aretval (pname, _), [exp]) when Procname.equal callee_pname pname -> | Sil.Apred (Aretval (pname, _), [exp]) when Typ.Procname.equal callee_pname pname ->
Prover.check_disequal tenv prop exp Exp.zero Prover.check_disequal tenv prop exp Exp.zero
| _ -> false) | _ -> false)
(Attribute.get_all prop) in (Attribute.get_all prop) in
@ -1264,8 +1264,8 @@ let exe_call_postprocess tenv ret_id trace_call callee_pname callee_attrs loc re
let returns_nullable ret_annot = Annotations.ia_is_nullable ret_annot in let returns_nullable ret_annot = Annotations.ia_is_nullable ret_annot in
let should_add_ret_attr _ = let should_add_ret_attr _ =
let is_likely_getter = function let is_likely_getter = function
| Procname.Java pn_java -> | Typ.Procname.Java pn_java ->
Int.equal (List.length (Procname.java_get_parameters pn_java)) 0 Int.equal (List.length (Typ.Procname.java_get_parameters pn_java)) 0
| _ -> | _ ->
false in false in
(Config.idempotent_getters && (Config.idempotent_getters &&
@ -1298,8 +1298,8 @@ let exe_function_call
("Found " ^ ("Found " ^
string_of_int nspecs ^ string_of_int nspecs ^
" specs for function " ^ " specs for function " ^
Procname.to_string callee_pname); Typ.Procname.to_string callee_pname);
L.d_strln ("START EXECUTING SPECS FOR " ^ Procname.to_string callee_pname ^ " from state"); L.d_strln ("START EXECUTING SPECS FOR " ^ Typ.Procname.to_string callee_pname ^ " from state");
Prop.d_prop prop; L.d_ln (); Prop.d_prop prop; L.d_ln ();
let exe_one_spec (n, spec) = let exe_one_spec (n, spec) =
exe_spec exe_spec

@ -28,13 +28,13 @@ val find_dereference_without_null_check_in_sexp : Sil.strexp -> (int * PredSymb.
(** raise a cast exception *) (** raise a cast exception *)
val create_cast_exception : val create_cast_exception :
Tenv.t -> Logging.ml_loc -> Procname.t option -> Exp.t -> Exp.t -> Exp.t -> exn Tenv.t -> Logging.ml_loc -> Typ.Procname.t option -> Exp.t -> Exp.t -> Exp.t -> exn
(** check if a prop is an exception *) (** check if a prop is an exception *)
val prop_is_exn : Procname.t -> 'a Prop.t -> bool val prop_is_exn : Typ.Procname.t -> 'a Prop.t -> bool
(** when prop is an exception, return the exception name *) (** when prop is an exception, return the exception name *)
val prop_get_exn_name : Procname.t -> 'a Prop.t -> Typename.t option val prop_get_exn_name : Typ.Procname.t -> 'a Prop.t -> Typename.t option
(** search in prop contains an error state *) (** search in prop contains an error state *)
val lookup_custom_errors : 'a Prop.t -> string option val lookup_custom_errors : 'a Prop.t -> string option
@ -44,6 +44,6 @@ val d_splitting : splitting -> unit
(** Execute the function call and return the list of results with return value *) (** Execute the function call and return the list of results with return value *)
val exe_function_call: val exe_function_call:
ProcAttributes.t -> Tenv.t -> (Ident.t * Typ.t) option -> Procdesc.t -> Procname.t -> ProcAttributes.t -> Tenv.t -> (Ident.t * Typ.t) option -> Procdesc.t -> Typ.Procname.t ->
Location.t -> (Exp.t * Typ.t) list -> Prop.normal Prop.t -> Paths.Path.t -> Location.t -> (Exp.t * Typ.t) list -> Prop.normal Prop.t -> Paths.Path.t ->
(Prop.normal Prop.t * Paths.Path.t) list (Prop.normal Prop.t * Paths.Path.t) list

@ -262,20 +262,20 @@ let functions_with_tainted_params = [
(* turn string specificiation of Java method into a procname *) (* turn string specificiation of Java method into a procname *)
let java_method_to_procname java_method = let java_method_to_procname java_method =
Procname.Java Typ.Procname.Java
(Procname.java (Typ.Procname.java
(Typename.Java.from_string java_method.classname) (Typename.Java.from_string java_method.classname)
(Some (Procname.split_classname java_method.ret_type)) (Some (Typ.Procname.split_classname java_method.ret_type))
java_method.method_name java_method.method_name
(List.map ~f:Procname.split_classname java_method.params) (List.map ~f:Typ.Procname.split_classname java_method.params)
(if java_method.is_static then Procname.Static else Procname.Non_Static)) (if java_method.is_static then Typ.Procname.Static else Typ.Procname.Non_Static))
(* turn string specificiation of an objc method into a procname *) (* turn string specificiation of an objc method into a procname *)
let objc_method_to_procname objc_method = let objc_method_to_procname objc_method =
let method_kind = Procname.objc_method_kind_of_bool (not objc_method.is_static) in let method_kind = Typ.Procname.objc_method_kind_of_bool (not objc_method.is_static) in
let typename = Typename.Objc.from_string objc_method.classname in let typename = Typename.Objc.from_string objc_method.classname in
Procname.ObjC_Cpp Typ.Procname.ObjC_Cpp
(Procname.objc_cpp typename objc_method.method_name method_kind) (Typ.Procname.objc_cpp typename objc_method.method_name method_kind)
let taint_spec_to_taint_info taint_spec = let taint_spec_to_taint_info taint_spec =
let taint_source = let taint_source =
@ -306,7 +306,7 @@ let attrs_opt_get_annots = function
(** returns true if [callee_pname] returns a tainted value *) (** returns true if [callee_pname] returns a tainted value *)
let returns_tainted callee_pname callee_attrs_opt = let returns_tainted callee_pname callee_attrs_opt =
let procname_matches taint_info = let procname_matches taint_info =
Procname.equal taint_info.PredSymb.taint_source callee_pname in Typ.Procname.equal taint_info.PredSymb.taint_source callee_pname in
match List.find ~f:procname_matches sources with match List.find ~f:procname_matches sources with
| Some taint_info -> | Some taint_info ->
Some taint_info.PredSymb.taint_kind Some taint_info.PredSymb.taint_kind
@ -320,7 +320,7 @@ let returns_tainted callee_pname callee_attrs_opt =
let find_callee taint_infos callee_pname = let find_callee taint_infos callee_pname =
List.find List.find
~f:(fun (taint_info, _) -> Procname.equal taint_info.PredSymb.taint_source callee_pname) ~f:(fun (taint_info, _) -> Typ.Procname.equal taint_info.PredSymb.taint_source callee_pname)
taint_infos taint_infos
(** returns list of zero-indexed argument numbers of [callee_pname] that may be tainted *) (** returns list of zero-indexed argument numbers of [callee_pname] that may be tainted *)
@ -328,7 +328,7 @@ let accepts_sensitive_params callee_pname callee_attrs_opt =
match find_callee taint_sinks callee_pname with match find_callee taint_sinks callee_pname with
| None -> | None ->
let _, param_annots = attrs_opt_get_annots callee_attrs_opt in let _, param_annots = attrs_opt_get_annots callee_attrs_opt in
let offset = if Procname.java_is_static callee_pname then 0 else 1 in let offset = if Typ.Procname.java_is_static callee_pname then 0 else 1 in
let indices_and_annots = let indices_and_annots =
List.mapi ~f:(fun param_num attr -> param_num + offset, attr) param_annots in List.mapi ~f:(fun param_num attr -> param_num + offset, attr) param_annots in
let tag_tainted_indices acc (index, attr) = let tag_tainted_indices acc (index, attr) =

@ -10,15 +10,15 @@
open! IStd open! IStd
(** returns true if [callee_pname] returns a tainted value *) (** returns true if [callee_pname] returns a tainted value *)
val returns_tainted : Procname.t -> ProcAttributes.t option -> PredSymb.taint_kind option val returns_tainted : Typ.Procname.t -> ProcAttributes.t option -> PredSymb.taint_kind option
(** returns list of zero-indexed argument numbers of [callee_pname] that may be tainted *) (** returns list of zero-indexed argument numbers of [callee_pname] that may be tainted *)
val accepts_sensitive_params : val accepts_sensitive_params :
Procname.t -> ProcAttributes.t option -> (int * PredSymb.taint_kind) list Typ.Procname.t -> ProcAttributes.t option -> (int * PredSymb.taint_kind) list
(** returns list of zero-indexed parameter numbers of [callee_pname] that should be (** returns list of zero-indexed parameter numbers of [callee_pname] that should be
considered tainted during symbolic execution *) considered tainted during symbolic execution *)
val tainted_params : Procname.t -> (int * PredSymb.taint_kind) list val tainted_params : Typ.Procname.t -> (int * PredSymb.taint_kind) list
(** returns the taint_kind of [fieldname] if it has a taint source annotation *) (** returns the taint_kind of [fieldname] if it has a taint source annotation *)
val has_taint_annotation : Ident.fieldname -> Typ.Struct.t -> bool val has_taint_annotation : Ident.fieldname -> Typ.Struct.t -> bool

@ -33,7 +33,7 @@ struct
module Domain = Dom.Mem module Domain = Dom.Mem
module Sem = BufferOverrunSemantics.Make (CFG) module Sem = BufferOverrunSemantics.Make (CFG)
type extras = Procname.t -> Procdesc.t option type extras = Typ.Procname.t -> Procdesc.t option
(* NOTE: heuristic *) (* NOTE: heuristic *)
let get_malloc_info : Exp.t -> Typ.t * Exp.t let get_malloc_info : Exp.t -> Typ.t * Exp.t
@ -44,7 +44,7 @@ struct
| x -> (Typ.Tint Typ.IChar, x) | x -> (Typ.Tint Typ.IChar, x)
let model_malloc let model_malloc
: Procname.t -> (Ident.t * Typ.t) option -> (Exp.t * Typ.t) list -> CFG.node : Typ.Procname.t -> (Ident.t * Typ.t) option -> (Exp.t * Typ.t) list -> CFG.node
-> Dom.Mem.t -> Dom.Mem.t -> Dom.Mem.t -> Dom.Mem.t
= fun pname ret params node mem -> = fun pname ret params node mem ->
match ret with match ret with
@ -56,7 +56,7 @@ struct
| _ -> mem | _ -> mem
let model_realloc let model_realloc
: Procname.t -> (Ident.t * Typ.t) option -> (Exp.t * Typ.t) list -> CFG.node : Typ.Procname.t -> (Ident.t * Typ.t) option -> (Exp.t * Typ.t) list -> CFG.node
-> Dom.Mem.t -> Dom.Mem.t -> Dom.Mem.t -> Dom.Mem.t
= fun pname ret params node mem -> = fun pname ret params node mem ->
model_malloc pname ret (List.tl_exn params) node mem model_malloc pname ret (List.tl_exn params) node mem
@ -87,11 +87,11 @@ struct
| _ -> mem | _ -> mem
let handle_unknown_call let handle_unknown_call
: Procname.t -> (Ident.t * Typ.t) option -> Procname.t : Typ.Procname.t -> (Ident.t * Typ.t) option -> Typ.Procname.t
-> (Exp.t * Typ.t) list -> CFG.node -> Dom.Mem.t -> Location.t -> (Exp.t * Typ.t) list -> CFG.node -> Dom.Mem.t -> Location.t
-> Dom.Mem.t -> Dom.Mem.t
= fun pname ret callee_pname params node mem loc -> = fun pname ret callee_pname params node mem loc ->
match Procname.get_method callee_pname with match Typ.Procname.get_method callee_pname with
| "malloc" | "malloc"
| "__new_array" -> model_malloc pname ret params node mem | "__new_array" -> model_malloc pname ret params node mem
| "realloc" -> model_realloc pname ret params node mem | "realloc" -> model_realloc pname ret params node mem
@ -101,7 +101,7 @@ struct
| _ -> model_unknown_itv ret mem | _ -> model_unknown_itv ret mem
let rec declare_array let rec declare_array
: Procname.t -> CFG.node -> Loc.t -> Typ.t -> IntLit.t -> inst_num:int : Typ.Procname.t -> CFG.node -> Loc.t -> Typ.t -> IntLit.t -> inst_num:int
-> dimension:int -> Dom.Mem.astate -> Dom.Mem.astate -> dimension:int -> Dom.Mem.astate -> Dom.Mem.astate
= fun pname node loc typ len ~inst_num ~dimension mem -> = fun pname node loc typ len ~inst_num ~dimension mem ->
let size = IntLit.to_int len |> Itv.of_int in let size = IntLit.to_int len |> Itv.of_int in
@ -123,7 +123,7 @@ struct
| _ -> mem | _ -> mem
let declare_symbolic_array let declare_symbolic_array
: Procname.t -> Tenv.t -> CFG.node -> Loc.t -> Typ.t -> inst_num:int : Typ.Procname.t -> Tenv.t -> CFG.node -> Loc.t -> Typ.t -> inst_num:int
-> sym_num:int -> dimension:int -> Dom.Mem.astate -> Dom.Mem.astate * int -> sym_num:int -> dimension:int -> Dom.Mem.astate -> Dom.Mem.astate * int
= fun pname tenv node loc typ ~inst_num ~sym_num ~dimension mem -> = fun pname tenv node loc typ ~inst_num ~sym_num ~dimension mem ->
let offset = Itv.make_sym pname sym_num in let offset = Itv.make_sym pname sym_num in
@ -187,7 +187,7 @@ struct
|> fst3 |> fst3
let instantiate_ret let instantiate_ret
: Tenv.t -> Procdesc.t option -> Procname.t -> (Exp.t * Typ.t) list : Tenv.t -> Procdesc.t option -> Typ.Procname.t -> (Exp.t * Typ.t) list
-> Dom.Mem.t -> Dom.Summary.t -> Location.t -> Dom.Val.astate -> Dom.Mem.t -> Dom.Summary.t -> Location.t -> Dom.Val.astate
= fun tenv callee_pdesc callee_pname params caller_mem summary loc -> = fun tenv callee_pdesc callee_pname params caller_mem summary loc ->
let callee_entry_mem = Dom.Summary.get_input summary in let callee_entry_mem = Dom.Summary.get_input summary in
@ -279,10 +279,10 @@ module Sem = BufferOverrunSemantics.Make (CFG)
module Report = module Report =
struct struct
type extras = Procname.t -> Procdesc.t option type extras = Typ.Procname.t -> Procdesc.t option
let add_condition let add_condition
: Procname.t -> CFG.node -> Exp.t -> Location.t -> Dom.Mem.astate : Typ.Procname.t -> CFG.node -> Exp.t -> Location.t -> Dom.Mem.astate
-> Dom.ConditionSet.t -> Dom.ConditionSet.t -> Dom.ConditionSet.t -> Dom.ConditionSet.t
= fun pname node exp loc mem cond_set -> = fun pname node exp loc mem cond_set ->
let array_access = let array_access =
@ -318,7 +318,7 @@ struct
| None -> cond_set | None -> cond_set
let instantiate_cond let instantiate_cond
: Tenv.t -> Procname.t -> Procdesc.t option -> (Exp.t * Typ.t) list : Tenv.t -> Typ.Procname.t -> Procdesc.t option -> (Exp.t * Typ.t) list
-> Dom.Mem.t -> Summary.summary -> Location.t -> Dom.ConditionSet.t -> Dom.Mem.t -> Summary.summary -> Location.t -> Dom.ConditionSet.t
= fun tenv caller_pname callee_pdesc params caller_mem summary loc -> = fun tenv caller_pname callee_pdesc params caller_mem summary loc ->
let callee_entry_mem = Dom.Summary.get_input summary in let callee_entry_mem = Dom.Summary.get_input summary in
@ -402,7 +402,7 @@ struct
in in
match alarm with match alarm with
| None -> () | None -> ()
| Some bucket when Procname.equal pname caller_pname -> | Some bucket when Typ.Procname.equal pname caller_pname ->
let description = Dom.Condition.to_string cond in let description = Dom.Condition.to_string cond in
let error_desc = Localise.desc_buffer_overrun bucket description in let error_desc = Localise.desc_buffer_overrun bucket description in
let exn = Exceptions.Checkers (Localise.to_string Localise.buffer_overrun, error_desc) in let exn = Exceptions.Checkers (Localise.to_string Localise.buffer_overrun, error_desc) in
@ -436,10 +436,10 @@ let compute_post
Some (entry_mem, exit_mem, cond_set) Some (entry_mem, exit_mem, cond_set)
| _ -> None | _ -> None
let print_summary : Procname.t -> Dom.Summary.t -> unit let print_summary : Typ.Procname.t -> Dom.Summary.t -> unit
= fun proc_name s -> = fun proc_name s ->
F.fprintf F.err_formatter "@.@[<v 2>Summary of %a :@," F.fprintf F.err_formatter "@.@[<v 2>Summary of %a :@,"
Procname.pp proc_name; Typ.Procname.pp proc_name;
Dom.Summary.pp_summary F.err_formatter s; Dom.Summary.pp_summary F.err_formatter s;
F.fprintf F.err_formatter "@]@." F.fprintf F.err_formatter "@]@."

@ -21,13 +21,13 @@ struct
type t = type t =
{ idx : Itv.astate; { idx : Itv.astate;
size : Itv.astate; size : Itv.astate;
proc_name : Procname.t; proc_name : Typ.Procname.t;
loc : Location.t; loc : Location.t;
trace : trace; trace : trace;
id : string } id : string }
[@@deriving compare] [@@deriving compare]
and trace = Intra of Procname.t and trace = Intra of Typ.Procname.t
| Inter of Procname.t * Procname.t * Location.t | Inter of Typ.Procname.t * Typ.Procname.t * Location.t
[@@deriving compare] [@@deriving compare]
and astate = t and astate = t
@ -60,7 +60,7 @@ let pp : F.formatter -> t -> unit
else else
match c.trace with match c.trace with
Inter (_, pname, loc) -> Inter (_, pname, loc) ->
let pname = Procname.to_string pname in let pname = Typ.Procname.to_string pname in
F.fprintf fmt "%a < %a at %a by call %s() at %s" F.fprintf fmt "%a < %a at %a by call %s() at %s"
Itv.pp c.idx Itv.pp c.size pp_location c pname (string_of_location loc) Itv.pp c.idx Itv.pp c.size pp_location c pname (string_of_location loc)
| Intra _ -> F.fprintf fmt "%a < %a at %a" Itv.pp c.idx Itv.pp c.size pp_location c | Intra _ -> F.fprintf fmt "%a < %a at %a" Itv.pp c.idx Itv.pp c.size pp_location c
@ -71,10 +71,10 @@ let get_location : t -> Location.t
let get_trace : t -> trace let get_trace : t -> trace
= fun c -> c.trace = fun c -> c.trace
let get_proc_name : t -> Procname.t let get_proc_name : t -> Typ.Procname.t
= fun c -> c.proc_name = fun c -> c.proc_name
let make : Procname.t -> Location.t -> string -> idx:Itv.t -> size:Itv.t -> t let make : Typ.Procname.t -> Location.t -> string -> idx:Itv.t -> size:Itv.t -> t
= fun proc_name loc id ~idx ~size -> = fun proc_name loc id ~idx ~size ->
{ proc_name; idx; size; loc; id ; trace = Intra proc_name } { proc_name; idx; size; loc; id ; trace = Intra proc_name }
@ -129,11 +129,11 @@ let to_string : t -> string
^ (match c.trace with ^ (match c.trace with
Inter (_, pname, _) -> Inter (_, pname, _) ->
" by call " " by call "
^ Procname.to_string pname ^ Typ.Procname.to_string pname
^ "() " ^ "() "
| Intra _ -> "") | Intra _ -> "")
let subst : t -> Itv.Bound.t Itv.SubstMap.t -> Procname.t -> Procname.t -> Location.t -> t let subst : t -> Itv.Bound.t Itv.SubstMap.t -> Typ.Procname.t -> Typ.Procname.t -> Location.t -> t
= fun c subst_map caller_pname callee_pname loc -> = fun c subst_map caller_pname callee_pname loc ->
if Itv.is_symbolic c.idx || Itv.is_symbolic c.size then if Itv.is_symbolic c.idx || Itv.is_symbolic c.size then
{ c with idx = Itv.subst c.idx subst_map; { c with idx = Itv.subst c.idx subst_map;
@ -152,11 +152,11 @@ struct
end) end)
let add_bo_safety let add_bo_safety
: Procname.t -> Location.t -> string -> idx:Itv.t -> size:Itv.t -> t -> t : Typ.Procname.t -> Location.t -> string -> idx:Itv.t -> size:Itv.t -> t -> t
= fun pname loc id ~idx ~size cond -> = fun pname loc id ~idx ~size cond ->
add (Condition.make pname loc id ~idx ~size) cond add (Condition.make pname loc id ~idx ~size) cond
let subst : t -> Itv.Bound.t Itv.SubstMap.t -> Procname.t -> Procname.t -> Location.t -> t let subst : t -> Itv.Bound.t Itv.SubstMap.t -> Typ.Procname.t -> Typ.Procname.t -> Location.t -> t
= fun x subst_map caller_pname callee_pname loc -> = fun x subst_map caller_pname callee_pname loc ->
fold (fun e -> add (Condition.subst e subst_map caller_pname callee_pname loc)) x empty fold (fun e -> add (Condition.subst e subst_map caller_pname callee_pname loc)) x empty
@ -270,7 +270,7 @@ struct
let modify_itv : Itv.t -> t -> t let modify_itv : Itv.t -> t -> t
= fun i x -> { x with itv = i } = fun i x -> { x with itv = i }
let make_sym : Procname.t -> int -> t let make_sym : Typ.Procname.t -> int -> t
= fun pname i -> { bot with itv = Itv.make_sym pname i } = fun pname i -> { bot with itv = Itv.make_sym pname i }
let unknown_bit : t -> t let unknown_bit : t -> t

@ -123,9 +123,9 @@ struct
| Binop.LOr -> Val.lor_sem v1 v2 | Binop.LOr -> Val.lor_sem v1 v2
| Binop.PtrFld -> raise Not_implemented | Binop.PtrFld -> raise Not_implemented
let get_allocsite : Procname.t -> CFG.node -> int -> int -> string let get_allocsite : Typ.Procname.t -> CFG.node -> int -> int -> string
= fun proc_name node inst_num dimension -> = fun proc_name node inst_num dimension ->
let proc_name = Procname.to_string proc_name in let proc_name = Typ.Procname.to_string proc_name in
let node_num = CFG.hash node |> string_of_int in let node_num = CFG.hash node |> string_of_int in
let inst_num = string_of_int inst_num in let inst_num = string_of_int inst_num in
let dimension = string_of_int dimension in let dimension = string_of_int dimension in
@ -133,7 +133,7 @@ struct
|> Allocsite.make |> Allocsite.make
let eval_array_alloc let eval_array_alloc
: Procname.t -> CFG.node -> Typ.t -> Itv.t -> Itv.t -> int -> int -> Val.t : Typ.Procname.t -> CFG.node -> Typ.t -> Itv.t -> Itv.t -> int -> int -> Val.t
= fun pdesc node typ offset size inst_num dimension -> = fun pdesc node typ offset size inst_num dimension ->
let allocsite = get_allocsite pdesc node inst_num dimension in let allocsite = get_allocsite pdesc node inst_num dimension in
let stride = sizeof typ |> Itv.of_int in let stride = sizeof typ |> Itv.of_int in

@ -18,17 +18,17 @@ let sym_size = ref 0
module Symbol = module Symbol =
struct struct
type t = Procname.t * int [@@deriving compare] type t = Typ.Procname.t * int [@@deriving compare]
let eq = [%compare.equal : t] let eq = [%compare.equal : t]
let get_new : Procname.t -> t let get_new : Typ.Procname.t -> t
= fun pname -> = fun pname ->
let i = !sym_size in let i = !sym_size in
sym_size := !sym_size + 1; sym_size := !sym_size + 1;
(pname, i) (pname, i)
let make : Procname.t -> int -> t let make : Typ.Procname.t -> int -> t
= fun pname i -> (pname, i) = fun pname i -> (pname, i)
let pp : F.formatter -> t -> unit let pp : F.formatter -> t -> unit
@ -36,7 +36,7 @@ struct
if Config.bo_debug <= 1 then if Config.bo_debug <= 1 then
F.fprintf fmt "s$%d" (snd x) F.fprintf fmt "s$%d" (snd x)
else else
F.fprintf fmt "%s-s$%d" (fst x |> Procname.to_string) (snd x) F.fprintf fmt "%s-s$%d" (fst x |> Typ.Procname.to_string) (snd x)
end end
module SubstMap = Caml.Map.Make (Symbol) module SubstMap = Caml.Map.Make (Symbol)
@ -76,10 +76,10 @@ struct
let le : t -> t -> bool let le : t -> t -> bool
= fun x y -> M.for_all (fun s v -> v <= find s y) x = fun x y -> M.for_all (fun s v -> v <= find s y) x
let get_new : Procname.t -> t let get_new : Typ.Procname.t -> t
= fun pname -> M.add (Symbol.get_new pname) 1 empty = fun pname -> M.add (Symbol.get_new pname) 1 empty
let make : Procname.t -> int -> t let make : Typ.Procname.t -> int -> t
= fun pname i -> M.add (Symbol.make pname i) 1 empty = fun pname i -> M.add (Symbol.make pname i) 1 empty
let eq : t -> t -> bool let eq : t -> t -> bool
@ -536,13 +536,13 @@ struct
let of_int : int -> t let of_int : int -> t
= fun n -> (Bound.of_int n, Bound.of_int n) = fun n -> (Bound.of_int n, Bound.of_int n)
let get_new_sym : Procname.t -> t let get_new_sym : Typ.Procname.t -> t
= fun pname -> = fun pname ->
let lower = Bound.of_sym (SymLinear.get_new pname) in let lower = Bound.of_sym (SymLinear.get_new pname) in
let upper = Bound.of_sym (SymLinear.get_new pname) in let upper = Bound.of_sym (SymLinear.get_new pname) in
(lower, upper) (lower, upper)
let make_sym : Procname.t -> int -> t let make_sym : Typ.Procname.t -> int -> t
= fun pname i -> = fun pname i ->
let lower = Bound.of_sym (SymLinear.make pname i) in let lower = Bound.of_sym (SymLinear.make pname i) in
let upper = Bound.of_sym (SymLinear.make pname (i+1)) in let upper = Bound.of_sym (SymLinear.make pname (i+1)) in
@ -936,10 +936,10 @@ let plus : t -> t -> t
let minus : t -> t -> t let minus : t -> t -> t
= lift2 ItvPure.minus = lift2 ItvPure.minus
let get_new_sym : Procname.t -> t let get_new_sym : Typ.Procname.t -> t
= fun pname -> NonBottom (ItvPure.get_new_sym pname) = fun pname -> NonBottom (ItvPure.get_new_sym pname)
let make_sym : Procname.t -> int -> t let make_sym : Typ.Procname.t -> int -> t
= fun pname i -> NonBottom (ItvPure.make_sym pname i) = fun pname i -> NonBottom (ItvPure.make_sym pname i)
let neg : t -> t let neg : t -> t

@ -14,7 +14,7 @@ module L = Logging
(** find transitive procedure calls for each procedure *) (** find transitive procedure calls for each procedure *)
module ProcnameSet = PrettyPrintable.MakePPSet(Procname) module ProcnameSet = PrettyPrintable.MakePPSet(Typ.Procname)
module Domain = AbstractDomain.FiniteSet(ProcnameSet) module Domain = AbstractDomain.FiniteSet(ProcnameSet)
@ -33,7 +33,7 @@ module SpecSummary = Summary.Make (struct
end) end)
type extras_t = { type extras_t = {
get_proc_desc : Procname.t -> Procdesc.t option; get_proc_desc : Typ.Procname.t -> Procdesc.t option;
stacktraces : Stacktrace.t list; stacktraces : Stacktrace.t list;
} }
@ -59,12 +59,12 @@ let stacktree_of_pdesc
file = SourceFile.to_string loc.Location.file; file = SourceFile.to_string loc.Location.file;
line = Some loc.Location.line; line = Some loc.Location.line;
blame_range = [line_range_of_pdesc pdesc] } in blame_range = [line_range_of_pdesc pdesc] } in
{ Stacktree_j.method_name = Procname.to_unique_id procname; { Stacktree_j.method_name = Typ.Procname.to_unique_id procname;
location = frame_loc; location = frame_loc;
callees = callees } callees = callees }
let stacktree_stub_of_procname procname = let stacktree_stub_of_procname procname =
{ Stacktree_j.method_name = Procname.to_unique_id procname; { Stacktree_j.method_name = Typ.Procname.to_unique_id procname;
location = None; location = None;
callees = [] } callees = [] }
@ -96,7 +96,7 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
let dir = Filename.concat Config.results_dir "crashcontext" in let dir = Filename.concat Config.results_dir "crashcontext" in
let suffix = F.sprintf "%s_%d" location_type loc.Location.line in let suffix = F.sprintf "%s_%d" location_type loc.Location.line in
let fname = F.sprintf "%s.%s.json" let fname = F.sprintf "%s.%s.json"
(Procname.to_filename caller) (Typ.Procname.to_filename caller)
suffix in suffix in
let fpath = Filename.concat dir fname in let fpath = Filename.concat dir fname in
Utils.create_dir dir; Utils.create_dir dir;
@ -109,18 +109,18 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
let caller = Procdesc.get_proc_name proc_data.ProcData.pdesc in let caller = Procdesc.get_proc_name proc_data.ProcData.pdesc in
let matches_proc frame = let matches_proc frame =
let matches_class pname = match pname with let matches_class pname = match pname with
| Procname.Java java_proc -> | Typ.Procname.Java java_proc ->
String.equal String.equal
frame.Stacktrace.class_str frame.Stacktrace.class_str
(Procname.java_get_class_name java_proc) (Typ.Procname.java_get_class_name java_proc)
| Procname.ObjC_Cpp objc_cpp_prod -> | Typ.Procname.ObjC_Cpp objc_cpp_prod ->
String.equal String.equal
frame.Stacktrace.class_str frame.Stacktrace.class_str
(Procname.objc_cpp_get_class_name objc_cpp_prod) (Typ.Procname.objc_cpp_get_class_name objc_cpp_prod)
| Procname.C _ -> true (* Needed for test code. *) | Typ.Procname.C _ -> true (* Needed for test code. *)
| Procname.Block _ | Procname.Linters_dummy_method -> | Typ.Procname.Block _ | Typ.Procname.Linters_dummy_method ->
failwith "Proc type not supported by crashcontext: block" in failwith "Proc type not supported by crashcontext: block" in
String.equal frame.Stacktrace.method_str (Procname.get_method caller) && String.equal frame.Stacktrace.method_str (Typ.Procname.get_method caller) &&
matches_class caller in matches_class caller in
let all_frames = List.concat let all_frames = List.concat
(List.map ~f:(fun trace -> trace.Stacktrace.frames) traces) in (List.map ~f:(fun trace -> trace.Stacktrace.frames) traces) in

@ -25,12 +25,12 @@ module type Spec = sig
input is the previous state, current instruction, current node kind, current procedure and input is the previous state, current instruction, current node kind, current procedure and
type environment. type environment.
*) *)
val exec_instr : astate -> Sil.instr -> Procdesc.Node.nodekind -> Procname.t -> Tenv.t -> astate val exec_instr : astate -> Sil.instr -> Procdesc.Node.nodekind -> Typ.Procname.t -> Tenv.t -> astate
(** log errors here. (** log errors here.
input is a state, location where the state occurs in the source, and the current procedure. input is a state, location where the state occurs in the source, and the current procedure.
*) *)
val report : astate -> Location.t -> Procname.t -> unit val report : astate -> Location.t -> Typ.Procname.t -> unit
val compare : astate -> astate -> int val compare : astate -> astate -> int
end end

@ -15,8 +15,8 @@ sig
val initial : astate val initial : astate
val exec_instr : val exec_instr :
astate -> astate ->
Sil.instr -> Procdesc.Node.nodekind -> Procname.t -> Tenv.t -> astate Sil.instr -> Procdesc.Node.nodekind -> Typ.Procname.t -> Tenv.t -> astate
val report : astate -> Location.t -> Procname.t -> unit val report : astate -> Location.t -> Typ.Procname.t -> unit
val compare : astate -> astate -> int val compare : astate -> astate -> int
end end

@ -16,7 +16,7 @@ module type Kind = sig
include TraceElem.Kind include TraceElem.Kind
(** return the parameter index and sink kind for the given call site with the given actuals *) (** return the parameter index and sink kind for the given call site with the given actuals *)
val get : Procname.t -> (Exp.t * Typ.t) list -> Tenv.t -> (t * int * bool) list val get : Typ.Procname.t -> (Exp.t * Typ.t) list -> Tenv.t -> (t * int * bool) list
end end
module type S = sig module type S = sig

@ -13,7 +13,7 @@ module type Kind = sig
include TraceElem.Kind include TraceElem.Kind
(** return the parameter index and sink kind for the given call site with the given actuals *) (** return the parameter index and sink kind for the given call site with the given actuals *)
val get : Procname.t -> (Exp.t * Typ.t) list -> Tenv.t -> (t * int * bool) list val get : Typ.Procname.t -> (Exp.t * Typ.t) list -> Tenv.t -> (t * int * bool) list
end end
module type S = sig module type S = sig

@ -20,7 +20,7 @@ module type S = sig
type sink_path = Passthroughs.t * (Sink.t * Passthroughs.t) list type sink_path = Passthroughs.t * (Sink.t * Passthroughs.t) list
(** get a path for each of the reportable flows to a sink in this trace *) (** get a path for each of the reportable flows to a sink in this trace *)
val get_reportable_sink_paths : t -> trace_of_pname:(Procname.t -> t) -> sink_path list val get_reportable_sink_paths : t -> trace_of_pname:(Typ.Procname.t -> t) -> sink_path list
(** update sink with the given call site *) (** update sink with the given call site *)
val with_callsite : t -> CallSite.t -> t val with_callsite : t -> CallSite.t -> t

@ -18,7 +18,7 @@ module type S = sig
type sink_path = Passthrough.Set.t * (Sink.t * Passthrough.Set.t) list type sink_path = Passthrough.Set.t * (Sink.t * Passthrough.Set.t) list
(** get a path for each of the reportable flows to a sink in this trace *) (** get a path for each of the reportable flows to a sink in this trace *)
val get_reportable_sink_paths : t -> trace_of_pname:(Procname.t -> t) -> sink_path list val get_reportable_sink_paths : t -> trace_of_pname:(Typ.Procname.t -> t) -> sink_path list
(** update sink with the given call site *) (** update sink with the given call site *)
val with_callsite : t -> CallSite.t -> t val with_callsite : t -> CallSite.t -> t

@ -16,8 +16,8 @@ module GlobalsAccesses = SiofTrace.GlobalsAccesses
let methods_whitelist = QualifiedCppName.quals_matcher_of_fuzzy_qual_names Config.siof_safe_methods let methods_whitelist = QualifiedCppName.quals_matcher_of_fuzzy_qual_names Config.siof_safe_methods
let is_whitelisted (pname : Procname.t) = let is_whitelisted (pname : Typ.Procname.t) =
Procname.get_qualifiers pname Typ.Procname.get_qualifiers pname
|> QualifiedCppName.match_qualifiers methods_whitelist |> QualifiedCppName.match_qualifiers methods_whitelist
type siof_model = { type siof_model = {
@ -42,7 +42,7 @@ let is_modelled =
List.map models ~f:(fun {qual_name} -> qual_name) List.map models ~f:(fun {qual_name} -> qual_name)
|> QualifiedCppName.quals_matcher_of_fuzzy_qual_names in |> QualifiedCppName.quals_matcher_of_fuzzy_qual_names in
fun pname -> fun pname ->
Procname.get_qualifiers pname Typ.Procname.get_qualifiers pname
|> QualifiedCppName.match_qualifiers models_matcher |> QualifiedCppName.match_qualifiers models_matcher
module Summary = Summary.Make (struct module Summary = Summary.Make (struct
@ -129,15 +129,15 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
~f:(fun {qual_name; initialized_globals} -> ~f:(fun {qual_name; initialized_globals} ->
if QualifiedCppName.quals_matcher_of_fuzzy_qual_names [qual_name] if QualifiedCppName.quals_matcher_of_fuzzy_qual_names [qual_name]
|> Fn.flip QualifiedCppName.match_qualifiers |> Fn.flip QualifiedCppName.match_qualifiers
(Procname.get_qualifiers callee_pname) then (Typ.Procname.get_qualifiers callee_pname) then
Some initialized_globals Some initialized_globals
else else
None) in None) in
Domain.join astate (Domain.BottomSiofTrace.NonBottom SiofTrace.empty, Domain.join astate (Domain.BottomSiofTrace.NonBottom SiofTrace.empty,
Domain.VarNames.of_list init) Domain.VarNames.of_list init)
| Call (_, Const (Cfun callee_pname), _::params_without_self, loc, _) | Call (_, Const (Cfun callee_pname), _::params_without_self, loc, _)
when Procname.is_c_method callee_pname && Procname.is_constructor callee_pname when Typ.Procname.is_c_method callee_pname && Typ.Procname.is_constructor callee_pname
&& Procname.is_constexpr callee_pname -> && Typ.Procname.is_constexpr callee_pname ->
add_params_globals astate pdesc loc params_without_self add_params_globals astate pdesc loc params_without_self
| Call (_, Const (Cfun callee_pname), params, loc, _) -> | Call (_, Const (Cfun callee_pname), params, loc, _) ->
let callsite = CallSite.make callee_pname loc in let callsite = CallSite.make callee_pname loc in
@ -250,7 +250,7 @@ let checker ({ Callbacks.proc_desc; } as callback) =
~make_extras:ProcData.make_empty_extras ~make_extras:ProcData.make_empty_extras
callback in callback in
let pname = Procdesc.get_proc_name proc_desc in let pname = Procdesc.get_proc_name proc_desc in
match Procname.get_global_name_of_initializer pname with match Typ.Procname.get_global_name_of_initializer pname with
| Some gname -> | Some gname ->
siof_check proc_desc gname post siof_check proc_desc gname post
| None -> | None ->

@ -62,7 +62,7 @@ end
include SinkTrace.Make(TraceElem) include SinkTrace.Make(TraceElem)
let make_access kind loc = let make_access kind loc =
let site = CallSite.make Procname.empty_block loc in let site = CallSite.make Typ.Procname.empty_block loc in
{ TraceElem.kind = (`Access, kind); site; } { TraceElem.kind = (`Access, kind); site; }
let is_intraprocedural_access { TraceElem.kind=(kind, _); } = kind = `Access let is_intraprocedural_access { TraceElem.kind=(kind, _); } = kind = `Access
@ -73,7 +73,7 @@ let trace_of_error loc gname path =
if is_intraprocedural_access sink then if is_intraprocedural_access sink then
Format.asprintf "%a" Sink.pp sink Format.asprintf "%a" Sink.pp sink
else else
Format.asprintf "call to %a" Procname.pp (CallSite.pname callsite) in Format.asprintf "call to %a" Typ.Procname.pp (CallSite.pname callsite) in
let sink_should_nest sink = not (is_intraprocedural_access sink) in let sink_should_nest sink = not (is_intraprocedural_access sink) in
let trace_elem_of_global = let trace_elem_of_global =
Errlog.make_trace_element 0 loc Errlog.make_trace_element 0 loc

@ -21,7 +21,7 @@ module type Kind = sig
val unknown : t val unknown : t
val get : Procname.t -> Tenv.t -> t option val get : Typ.Procname.t -> Tenv.t -> t option
val get_tainted_formals : Procdesc.t -> Tenv.t -> (Mangled.t * Typ.t * t option) list val get_tainted_formals : Procdesc.t -> Tenv.t -> (Mangled.t * Typ.t * t option) list
end end

@ -19,7 +19,7 @@ module type Kind = sig
val unknown : t val unknown : t
(** return Some (kind) if the procedure is a taint source, None otherwise *) (** return Some (kind) if the procedure is a taint source, None otherwise *)
val get : Procname.t -> Tenv.t -> t option val get : Typ.Procname.t -> Tenv.t -> t option
(** return each formal of the function paired with either Some(kind) if the formal is a taint (** return each formal of the function paired with either Some(kind) if the formal is a taint
source, or None if the formal is not a taint source *) source, or None if the formal is not a taint source *)

@ -52,9 +52,9 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
| NoEffect | NoEffect
let get_lock_model = function let get_lock_model = function
| Procname.Java java_pname -> | Typ.Procname.Java java_pname ->
begin begin
match Procname.java_get_class_name java_pname, Procname.java_get_method java_pname with match Typ.Procname.java_get_class_name java_pname, Typ.Procname.java_get_method java_pname with
| "java.util.concurrent.locks.Lock", "lock" -> | "java.util.concurrent.locks.Lock", "lock" ->
Lock Lock
| ("java.util.concurrent.locks.ReentrantLock" | ("java.util.concurrent.locks.ReentrantLock"
@ -71,9 +71,9 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
| _ -> | _ ->
NoEffect NoEffect
end end
| pname when Procname.equal pname BuiltinDecl.__set_locked_attribute -> | pname when Typ.Procname.equal pname BuiltinDecl.__set_locked_attribute ->
Lock Lock
| pname when Procname.equal pname BuiltinDecl.__delete_locked_attribute -> | pname when Typ.Procname.equal pname BuiltinDecl.__delete_locked_attribute ->
Unlock Unlock
| _ -> | _ ->
NoEffect NoEffect
@ -211,10 +211,10 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
let is_annotated_functional = let is_annotated_functional =
has_return_annot Annotations.ia_is_functional in has_return_annot Annotations.ia_is_functional in
let is_modeled_functional = function let is_modeled_functional = function
| Procname.Java java_pname -> | Typ.Procname.Java java_pname ->
begin begin
match Procname.java_get_class_name java_pname, match Typ.Procname.java_get_class_name java_pname,
Procname.java_get_method java_pname with Typ.Procname.java_get_method java_pname with
| "android.content.res.Resources", method_name -> | "android.content.res.Resources", method_name ->
(* all methods of Resources are considered @Functional except for the ones in this (* all methods of Resources are considered @Functional except for the ones in this
blacklist *) blacklist *)
@ -236,13 +236,13 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
let acquires_ownership pname tenv = let acquires_ownership pname tenv =
let is_allocation pn = let is_allocation pn =
Procname.equal pn BuiltinDecl.__new || Procname.equal pn BuiltinDecl.__new_array in Typ.Procname.equal pn BuiltinDecl.__new || Typ.Procname.equal pn BuiltinDecl.__new_array in
(* identify library functions that maintain ownership invariants behind the scenes *) (* identify library functions that maintain ownership invariants behind the scenes *)
let is_owned_in_library = function let is_owned_in_library = function
| Procname.Java java_pname -> | Typ.Procname.Java java_pname ->
begin begin
match Procname.java_get_class_name java_pname, match Typ.Procname.java_get_class_name java_pname,
Procname.java_get_method java_pname with Typ.Procname.java_get_method java_pname with
| "javax.inject.Provider", "get" -> | "javax.inject.Provider", "get" ->
(* in dependency injection, the library allocates fresh values behind the scenes *) (* in dependency injection, the library allocates fresh values behind the scenes *)
true true
@ -263,10 +263,10 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
let exec_instr (astate : Domain.astate) { ProcData.pdesc; tenv; extras; } _ = let exec_instr (astate : Domain.astate) { ProcData.pdesc; tenv; extras; } _ =
let is_container_write pn tenv = match pn with let is_container_write pn tenv = match pn with
| Procname.Java java_pname -> | Typ.Procname.Java java_pname ->
let typename = Typename.Java.from_string (Procname.java_get_class_name java_pname) in let typename = Typename.Java.from_string (Typ.Procname.java_get_class_name java_pname) in
let is_container_write_ typename _ = let is_container_write_ typename _ =
match Typename.name typename, Procname.java_get_method java_pname with match Typename.name typename, Typ.Procname.java_get_method java_pname with
| "java.util.List", ("add" | "addAll" | "clear" | "remove" | "set") -> true | "java.util.List", ("add" | "addAll" | "clear" | "remove" | "set") -> true
| "java.util.Map", ("clear" | "put" | "putAll" | "remove") -> true | "java.util.Map", ("clear" | "put" | "putAll" | "remove") -> true
| _ -> false in | _ -> false in
@ -286,7 +286,7 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
let dummy_fieldname = let dummy_fieldname =
Ident.create_fieldname Ident.create_fieldname
(Mangled.from_string (Mangled.from_string
(container_write_string ^ (Procname.get_method callee_pname))) 0 in (container_write_string ^ (Typ.Procname.get_method callee_pname))) 0 in
let dummy_access_exp = Exp.Lfield (receiver_exp, dummy_fieldname, receiver_typ) in let dummy_access_exp = Exp.Lfield (receiver_exp, dummy_fieldname, receiver_typ) in
let callee_writes = let callee_writes =
match AccessPath.of_lhs_exp dummy_access_exp receiver_typ ~f_resolve_id with match AccessPath.of_lhs_exp dummy_access_exp receiver_typ ~f_resolve_id with
@ -301,7 +301,7 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
| _ -> | _ ->
failwithf failwithf
"Call to %a is marked as a container write, but has no receiver" "Call to %a is marked as a container write, but has no receiver"
Procname.pp callee_pname in Typ.Procname.pp callee_pname in
let get_summary caller_pdesc callee_pname actuals ~f_resolve_id callee_loc tenv = let get_summary caller_pdesc callee_pname actuals ~f_resolve_id callee_loc tenv =
if is_container_write callee_pname tenv if is_container_write callee_pname tenv
then then
@ -312,9 +312,9 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
not is_locked && not (Procdesc.is_java_synchronized pdesc) in not is_locked && not (Procdesc.is_java_synchronized pdesc) in
(* return true if the given procname boxes a primitive type into a reference type *) (* return true if the given procname boxes a primitive type into a reference type *)
let is_box = function let is_box = function
| Procname.Java java_pname -> | Typ.Procname.Java java_pname ->
begin begin
match Procname.java_get_class_name java_pname, Procname.java_get_method java_pname with match Typ.Procname.java_get_class_name java_pname, Typ.Procname.java_get_method java_pname with
| ("java.lang.Boolean" | | ("java.lang.Boolean" |
"java.lang.Byte" | "java.lang.Byte" |
"java.lang.Char" | "java.lang.Char" |
@ -348,7 +348,7 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
| Sil.Call (Some (ret_id, _), Const (Cfun callee_pname), | Sil.Call (Some (ret_id, _), Const (Cfun callee_pname),
(target_exp, target_typ) :: (Exp.Sizeof (cast_typ, _, _), _) :: _ , _, _) (target_exp, target_typ) :: (Exp.Sizeof (cast_typ, _, _), _) :: _ , _, _)
when Procname.equal callee_pname BuiltinDecl.__cast -> when Typ.Procname.equal callee_pname BuiltinDecl.__cast ->
let lhs_access_path = AccessPath.of_id ret_id (Typ.Tptr (cast_typ, Pk_pointer)) in let lhs_access_path = AccessPath.of_id ret_id (Typ.Tptr (cast_typ, Pk_pointer)) in
let attribute_map = let attribute_map =
propagate_attributes propagate_attributes
@ -618,11 +618,11 @@ module Analyzer = AbstractInterpreter.Make (ProcCfg.Normal) (TransferFunctions)
module Interprocedural = AbstractInterpreter.Interprocedural (Summary) module Interprocedural = AbstractInterpreter.Interprocedural (Summary)
(* a results table is a Map where a key is an a procedure environment, (* a results table is a Map where a key is an a procedure environment,
i.e., something of type Idenv.t * Tenv.t * Procname.t * Procdesc.t i.e., something of type Idenv.t * Tenv.t * Typ.Procname.t * Procdesc.t
*) *)
module ResultsTableType = Caml.Map.Make (struct module ResultsTableType = Caml.Map.Make (struct
type t = Idenv.t * Tenv.t * Procname.t * Procdesc.t type t = Idenv.t * Tenv.t * Typ.Procname.t * Procdesc.t
let compare (_, _, pn1, _) (_,_,pn2,_) = Procname.compare pn1 pn2 let compare (_, _, pn1, _) (_,_,pn2,_) = Typ.Procname.compare pn1 pn2
end) end)
(* we want to consider Builder classes and other safe immutablility-ensuring patterns as (* we want to consider Builder classes and other safe immutablility-ensuring patterns as
@ -646,12 +646,12 @@ let is_immutable_collection_class class_name tenv =
class_name class_name
let is_call_to_builder_class_method = function let is_call_to_builder_class_method = function
| Procname.Java java_pname -> is_builder_class (Procname.java_get_class_name java_pname) | Typ.Procname.Java java_pname -> is_builder_class (Typ.Procname.java_get_class_name java_pname)
| _ -> false | _ -> false
let is_call_to_immutable_collection_method tenv = function let is_call_to_immutable_collection_method tenv = function
| Procname.Java java_pname -> | Typ.Procname.Java java_pname ->
is_immutable_collection_class (Procname.java_get_class_type_name java_pname) tenv is_immutable_collection_class (Typ.Procname.java_get_class_type_name java_pname) tenv
| _ -> | _ ->
false false
@ -717,7 +717,7 @@ let pdesc_is_assumed_thread_safe pdesc tenv =
find more bugs. this is just a temporary measure to avoid obvious false positives *) find more bugs. this is just a temporary measure to avoid obvious false positives *)
let should_analyze_proc pdesc tenv = let should_analyze_proc pdesc tenv =
let pn = Procdesc.get_proc_name pdesc in let pn = Procdesc.get_proc_name pdesc in
not (Procname.is_class_initializer pn) && not (Typ.Procname.is_class_initializer pn) &&
not (FbThreadSafety.is_logging_method pn) && not (FbThreadSafety.is_logging_method pn) &&
not (is_call_to_builder_class_method pn) && not (is_call_to_builder_class_method pn) &&
not (is_call_to_immutable_collection_method tenv pn) && not (is_call_to_immutable_collection_method tenv pn) &&
@ -727,13 +727,13 @@ let should_analyze_proc pdesc tenv =
(* return true if we should report on unprotected accesses during the procedure *) (* return true if we should report on unprotected accesses during the procedure *)
let should_report_on_proc (_, _, proc_name, proc_desc) = let should_report_on_proc (_, _, proc_name, proc_desc) =
not (Procname.java_is_autogen_method proc_name) && not (Typ.Procname.java_is_autogen_method proc_name) &&
Procdesc.get_access proc_desc <> PredSymb.Private && Procdesc.get_access proc_desc <> PredSymb.Private &&
not (Annotations.pdesc_return_annot_ends_with proc_desc Annotations.visibleForTesting) not (Annotations.pdesc_return_annot_ends_with proc_desc Annotations.visibleForTesting)
let analyze_procedure callback = let analyze_procedure callback =
let is_initializer tenv proc_name = let is_initializer tenv proc_name =
Procname.is_constructor proc_name || FbThreadSafety.is_custom_init tenv proc_name in Typ.Procname.is_constructor proc_name || FbThreadSafety.is_custom_init tenv proc_name in
let open ThreadSafetyDomain in let open ThreadSafetyDomain in
let has_lock = false in let has_lock = false in
let return_attrs = AttributeSetDomain.empty in let return_attrs = AttributeSetDomain.empty in
@ -807,8 +807,8 @@ let make_results_table get_proc_desc file_env =
let get_current_class_and_threadsafe_superclasses tenv pname = let get_current_class_and_threadsafe_superclasses tenv pname =
match pname with match pname with
| Procname.Java java_pname -> | Typ.Procname.Java java_pname ->
let current_class = Procname.java_get_class_type_name java_pname in let current_class = Typ.Procname.java_get_class_type_name java_pname in
let thread_safe_annotated_classes = let thread_safe_annotated_classes =
PatternMatch.find_superclasses_with_attributes PatternMatch.find_superclasses_with_attributes
is_thread_safe tenv current_class is_thread_safe tenv current_class
@ -950,7 +950,7 @@ let report_thread_safety_violations ( _, tenv, pname, pdesc) make_description tr
Format.asprintf "access to %a" (pp_accesses_sink ~is_write_access:true) sink Format.asprintf "access to %a" (pp_accesses_sink ~is_write_access:true) sink
else else
Format.asprintf Format.asprintf
"call to %a" Procname.pp (CallSite.pname (PathDomain.Sink.call_site sink)) in "call to %a" Typ.Procname.pp (CallSite.pname (PathDomain.Sink.call_site sink)) in
let loc = CallSite.loc (PathDomain.Sink.call_site initial_sink) in let loc = CallSite.loc (PathDomain.Sink.call_site initial_sink) in
let ltr = PathDomain.to_sink_loc_trace ~desc_of_sink path in let ltr = PathDomain.to_sink_loc_trace ~desc_of_sink path in
let msg = Localise.to_string Localise.thread_safety_violation in let msg = Localise.to_string Localise.thread_safety_violation in
@ -968,7 +968,7 @@ let make_unprotected_write_description
tenv pname final_sink_site initial_sink_site final_sink _ = tenv pname final_sink_site initial_sink_site final_sink _ =
Format.asprintf Format.asprintf
"Unprotected write. Public method %a%s %s %a outside of synchronization.%s" "Unprotected write. Public method %a%s %s %a outside of synchronization.%s"
Procname.pp pname Typ.Procname.pp pname
(if CallSite.equal final_sink_site initial_sink_site then "" else " indirectly") (if CallSite.equal final_sink_site initial_sink_site then "" else " indirectly")
(if is_container_write_sink final_sink then "mutates" else "writes to field") (if is_container_write_sink final_sink then "mutates" else "writes to field")
(pp_accesses_sink ~is_write_access:true) final_sink (pp_accesses_sink ~is_write_access:true) final_sink
@ -983,13 +983,13 @@ let make_read_write_race_description tenv pname final_sink_site initial_sink_sit
conflicting_proc_envs in conflicting_proc_envs in
let pp_proc_name_list fmt proc_names = let pp_proc_name_list fmt proc_names =
let pp_sep _ _ = F.fprintf fmt " , " in let pp_sep _ _ = F.fprintf fmt " , " in
F.pp_print_list ~pp_sep Procname.pp fmt proc_names in F.pp_print_list ~pp_sep Typ.Procname.pp fmt proc_names in
let conflicts_description = let conflicts_description =
Format.asprintf "Potentially races with writes in method%s %a." Format.asprintf "Potentially races with writes in method%s %a."
(if List.length conflicting_proc_names > 1 then "s" else "") (if List.length conflicting_proc_names > 1 then "s" else "")
pp_proc_name_list conflicting_proc_names in pp_proc_name_list conflicting_proc_names in
Format.asprintf "Read/Write race. Public method %a%s reads from field %a. %s %s" Format.asprintf "Read/Write race. Public method %a%s reads from field %a. %s %s"
Procname.pp pname Typ.Procname.pp pname
(if CallSite.equal final_sink_site initial_sink_site then "" else " indirectly") (if CallSite.equal final_sink_site initial_sink_site then "" else " indirectly")
(pp_accesses_sink ~is_write_access:false) final_sink (pp_accesses_sink ~is_write_access:false) final_sink
conflicts_description conflicts_description

@ -40,7 +40,7 @@ module TraceElem = struct
end end
let make_access kind loc = let make_access kind loc =
let site = CallSite.make Procname.empty_block loc in let site = CallSite.make Typ.Procname.empty_block loc in
TraceElem.make kind site TraceElem.make kind site
module LocksDomain = AbstractDomain.BooleanAnd module LocksDomain = AbstractDomain.BooleanAnd

@ -53,7 +53,7 @@ module type S = sig
(** get a path for each of the reportable source -> sink flows in this trace. specifying (** get a path for each of the reportable source -> sink flows in this trace. specifying
[cur_site] restricts the reported paths to ones introduced by the call at [cur_site] *) [cur_site] restricts the reported paths to ones introduced by the call at [cur_site] *)
val get_reportable_paths : val get_reportable_paths :
?cur_site:CallSite.t -> t -> trace_of_pname:(Procname.t -> t) -> path list ?cur_site:CallSite.t -> t -> trace_of_pname:(Typ.Procname.t -> t) -> path list
(** create a loc_trace from a path; [source_should_nest s] should be true when we are going one (** create a loc_trace from a path; [source_should_nest s] should be true when we are going one
deeper into a call-chain, ie when lt_level should be bumper in the next loc_trace_elem, and deeper into a call-chain, ie when lt_level should be bumper in the next loc_trace_elem, and
@ -87,7 +87,7 @@ module type S = sig
val pp : F.formatter -> t -> unit val pp : F.formatter -> t -> unit
(** pretty-print a path in the context of the given procname *) (** pretty-print a path in the context of the given procname *)
val pp_path : Procname.t -> F.formatter -> path -> unit val pp_path : Typ.Procname.t -> F.formatter -> path -> unit
end end
(** Expand a trace element (i.e., a source or sink) into a list of trace elements bottoming out in (** Expand a trace element (i.e., a source or sink) into a list of trace elements bottoming out in
@ -216,7 +216,7 @@ module Make (Spec : Spec) = struct
Source.pp original_source Source.pp original_source
Sink.pp final_sink Sink.pp final_sink
pp_sources sources_passthroughs pp_sources sources_passthroughs
Procname.pp cur_pname Typ.Procname.pp cur_pname
pp_passthroughs cur_passthroughs pp_passthroughs cur_passthroughs
pp_sinks (List.rev sinks_passthroughs) pp_sinks (List.rev sinks_passthroughs)
@ -269,18 +269,18 @@ module Make (Spec : Spec) = struct
let to_loc_trace let to_loc_trace
?(desc_of_source=fun source -> ?(desc_of_source=fun source ->
let callsite = Source.call_site source in let callsite = Source.call_site source in
Format.asprintf "return from %a" Procname.pp (CallSite.pname callsite)) Format.asprintf "return from %a" Typ.Procname.pp (CallSite.pname callsite))
?(source_should_nest=(fun _ -> true)) ?(source_should_nest=(fun _ -> true))
?(desc_of_sink=fun sink -> ?(desc_of_sink=fun sink ->
let callsite = Sink.call_site sink in let callsite = Sink.call_site sink in
Format.asprintf "call to %a" Procname.pp (CallSite.pname callsite)) Format.asprintf "call to %a" Typ.Procname.pp (CallSite.pname callsite))
?(sink_should_nest=(fun _ -> true)) ?(sink_should_nest=(fun _ -> true))
(passthroughs, sources, sinks) = (passthroughs, sources, sinks) =
let trace_elems_of_passthroughs lt_level passthroughs acc0 = let trace_elems_of_passthroughs lt_level passthroughs acc0 =
let trace_elem_of_passthrough passthrough acc = let trace_elem_of_passthrough passthrough acc =
let passthrough_site = Passthrough.site passthrough in let passthrough_site = Passthrough.site passthrough in
let desc = F.asprintf "flow through %a" Procname.pp (CallSite.pname passthrough_site) in let desc = F.asprintf "flow through %a" Typ.Procname.pp (CallSite.pname passthrough_site) in
(Errlog.make_trace_element lt_level (CallSite.loc passthrough_site) desc []) :: acc in (Errlog.make_trace_element lt_level (CallSite.loc passthrough_site) desc []) :: acc in
(* sort passthroughs by ascending line number to create a coherent trace *) (* sort passthroughs by ascending line number to create a coherent trace *)
let sorted_passthroughs = let sorted_passthroughs =

@ -54,7 +54,7 @@ module type S = sig
(** get a path for each of the reportable source -> sink flows in this trace. specifying (** get a path for each of the reportable source -> sink flows in this trace. specifying
[cur_site] restricts the reported paths to ones introduced by the call at [cur_site] *) [cur_site] restricts the reported paths to ones introduced by the call at [cur_site] *)
val get_reportable_paths : val get_reportable_paths :
?cur_site:CallSite.t -> t -> trace_of_pname:(Procname.t -> t) -> path list ?cur_site:CallSite.t -> t -> trace_of_pname:(Typ.Procname.t -> t) -> path list
(** create a loc_trace from a path; [source_should_nest s] should be true when we are going one (** create a loc_trace from a path; [source_should_nest s] should be true when we are going one
deeper into a call-chain, ie when lt_level should be bumper in the next loc_trace_elem, and deeper into a call-chain, ie when lt_level should be bumper in the next loc_trace_elem, and
@ -89,7 +89,7 @@ module type S = sig
val pp : F.formatter -> t -> unit val pp : F.formatter -> t -> unit
(** pretty-print a path in the context of the given procname *) (** pretty-print a path in the context of the given procname *)
val pp_path : Procname.t -> F.formatter -> path -> unit val pp_path : Typ.Procname.t -> F.formatter -> path -> unit
end end
module Make (Spec : Spec) : S with module Source = Spec.Source and module Sink = Spec.Sink module Make (Spec : Spec) : S with module Source = Spec.Source and module Sink = Spec.Sink

@ -113,10 +113,10 @@ let expensive_overrides_unexpensive =
let annotation_reachability_error = "CHECKERS_ANNOTATION_REACHABILITY_ERROR" let annotation_reachability_error = "CHECKERS_ANNOTATION_REACHABILITY_ERROR"
let is_modeled_expensive tenv = function let is_modeled_expensive tenv = function
| Procname.Java proc_name_java as proc_name -> | Typ.Procname.Java proc_name_java as proc_name ->
not (BuiltinDecl.is_declared proc_name) && not (BuiltinDecl.is_declared proc_name) &&
let is_subclass = let is_subclass =
let classname = Typename.Java.from_string (Procname.java_get_class_name proc_name_java) in let classname = Typename.Java.from_string (Typ.Procname.java_get_class_name proc_name_java) in
PatternMatch.is_subtype_of_str tenv classname in PatternMatch.is_subtype_of_str tenv classname in
Inferconfig.modeled_expensive_matcher is_subclass proc_name Inferconfig.modeled_expensive_matcher is_subclass proc_name
| _ -> | _ ->
@ -124,12 +124,12 @@ let is_modeled_expensive tenv = function
let is_allocator tenv pname = let is_allocator tenv pname =
match pname with match pname with
| Procname.Java pname_java -> | Typ.Procname.Java pname_java ->
let is_throwable () = let is_throwable () =
let class_name = let class_name =
Typename.Java.from_string (Procname.java_get_class_name pname_java) in Typename.Java.from_string (Typ.Procname.java_get_class_name pname_java) in
PatternMatch.is_throwable tenv class_name in PatternMatch.is_throwable tenv class_name in
Procname.is_constructor pname Typ.Procname.is_constructor pname
&& not (BuiltinDecl.is_declared pname) && not (BuiltinDecl.is_declared pname)
&& not (is_throwable ()) && not (is_throwable ())
| _ -> | _ ->
@ -171,7 +171,7 @@ let update_trace loc trace =
Errlog.make_trace_element 0 loc "" [] :: trace Errlog.make_trace_element 0 loc "" [] :: trace
let string_of_pname = let string_of_pname =
Procname.to_simplified_string ~withclass:true Typ.Procname.to_simplified_string ~withclass:true
let report_allocation_stack let report_allocation_stack
src_annot pname fst_call_loc trace stack_str constructor_pname call_loc = src_annot pname fst_call_loc trace stack_str constructor_pname call_loc =
@ -180,7 +180,7 @@ let report_allocation_stack
let description = let description =
Printf.sprintf Printf.sprintf
"Method `%s` annotated with `@%s` allocates `%s` via `%s%s`" "Method `%s` annotated with `@%s` allocates `%s` via `%s%s`"
(Procname.to_simplified_string pname) (Typ.Procname.to_simplified_string pname)
src_annot src_annot
constr_str constr_str
stack_str stack_str
@ -198,7 +198,7 @@ let report_annotation_stack src_annot snk_annot src_pname loc trace stack_str sn
let description = let description =
Printf.sprintf Printf.sprintf
"Method `%s` annotated with `@%s` calls `%s%s` where `%s` is annotated with `@%s`" "Method `%s` annotated with `@%s` calls `%s%s` where `%s` is annotated with `@%s`"
(Procname.to_simplified_string src_pname) (Typ.Procname.to_simplified_string src_pname)
src_annot src_annot
stack_str stack_str
exp_pname_str exp_pname_str
@ -232,8 +232,8 @@ let report_call_stack end_of_stack lookup_next_calls report call_site calls =
~f:(fun (accu, set) call_site -> ~f:(fun (accu, set) call_site ->
let p = CallSite.pname call_site in let p = CallSite.pname call_site in
let loc = CallSite.loc call_site in let loc = CallSite.loc call_site in
if Procname.Set.mem p set then (accu, set) if Typ.Procname.Set.mem p set then (accu, set)
else ((p, loc) :: accu, Procname.Set.add p set)) else ((p, loc) :: accu, Typ.Procname.Set.add p set))
~init:([], visited_pnames) ~init:([], visited_pnames)
next_calls in next_calls in
List.iter ~f:(loop fst_call_loc updated_visited (new_trace, new_stack_str)) unseen_pnames in List.iter ~f:(loop fst_call_loc updated_visited (new_trace, new_stack_str)) unseen_pnames in
@ -242,7 +242,7 @@ let report_call_stack end_of_stack lookup_next_calls report call_site calls =
let fst_callee_pname = CallSite.pname fst_call_site in let fst_callee_pname = CallSite.pname fst_call_site in
let fst_call_loc = CallSite.loc fst_call_site in let fst_call_loc = CallSite.loc fst_call_site in
let start_trace = update_trace (CallSite.loc call_site) [] in let start_trace = update_trace (CallSite.loc call_site) [] in
loop fst_call_loc Procname.Set.empty (start_trace, "") (fst_callee_pname, fst_call_loc)) loop fst_call_loc Typ.Procname.Set.empty (start_trace, "") (fst_callee_pname, fst_call_loc))
calls calls
module TransferFunctions (CFG : ProcCfg.S) = struct module TransferFunctions (CFG : ProcCfg.S) = struct
@ -255,8 +255,8 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
rarely to not affect the performances *) rarely to not affect the performances *)
let is_unlikely pname = let is_unlikely pname =
match pname with match pname with
| Procname.Java java_pname -> | Typ.Procname.Java java_pname ->
String.equal (Procname.java_get_method java_pname) "unlikely" String.equal (Typ.Procname.java_get_method java_pname) "unlikely"
| _ -> false | _ -> false
let is_tracking_exp astate = function let is_tracking_exp astate = function
@ -356,8 +356,8 @@ module Interprocedural = struct
let description = let description =
Printf.sprintf Printf.sprintf
"Method `%s` overrides unannotated method `%s` and cannot be annotated with `@%s`" "Method `%s` overrides unannotated method `%s` and cannot be annotated with `@%s`"
(Procname.to_string proc_name) (Typ.Procname.to_string proc_name)
(Procname.to_string overridden_pname) (Typ.Procname.to_string overridden_pname)
Annotations.expensive in Annotations.expensive in
let exn = let exn =
Exceptions.Checkers Exceptions.Checkers

@ -95,8 +95,8 @@ val pdesc_has_return_annot : Procdesc.t -> (Annot.Item.t -> bool) -> bool
value. the function [attrs_of_pname] should resolve the proc attributes of [pname]. value. the function [attrs_of_pname] should resolve the proc attributes of [pname].
Specs.proc_resolve_attributes is a good choice for this resolution function. *) Specs.proc_resolve_attributes is a good choice for this resolution function. *)
val pname_has_return_annot : val pname_has_return_annot :
Procname.t -> Typ.Procname.t ->
attrs_of_pname:(Procname.t -> ProcAttributes.t option) -> attrs_of_pname:(Typ.Procname.t -> ProcAttributes.t option) ->
(Annot.Item.t -> bool) -> (Annot.Item.t -> bool) ->
bool bool

@ -103,7 +103,7 @@ let callback_check_dead_code { Callbacks.proc_desc; proc_name; tenv } =
let do_check () = let do_check () =
begin begin
if verbose then L.stderr "@.--@.PROC: %a@." Procname.pp proc_name; if verbose then L.stderr "@.--@.PROC: %a@." Typ.Procname.pp proc_name;
let transitions = DFDead.run tenv proc_desc State.initial in let transitions = DFDead.run tenv proc_desc State.initial in
let exit_node = Procdesc.get_exit_node proc_desc in let exit_node = Procdesc.get_exit_node proc_desc in
match transitions exit_node with match transitions exit_node with

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save