[typ] extract Procname from Typ

Summary: No reason for this to be in Typ

Reviewed By: skcho

Differential Revision: D19162727

fbshipit-source-id: d6940637a
master
Nikos Gorogiannis 5 years ago committed by Facebook Github Bot
parent 33352623a5
commit 91fa6a5404

@ -33,10 +33,10 @@ let proc_kind_of_attr (proc_attributes : ProcAttributes.t) =
let replace pname pname_blob akind source_file attributes proc_desc callees = let replace pname pname_blob akind source_file attributes proc_desc callees =
let pname_str = Typ.Procname.to_string pname in let pname_str = Procname.to_string pname in
let akind_int64 = int64_of_attributes_kind akind in let akind_int64 = int64_of_attributes_kind akind in
let proc_desc_blob = Procdesc.SQLite.serialize proc_desc in let proc_desc_blob = Procdesc.SQLite.serialize proc_desc in
let callees_blob = Typ.Procname.SQLiteList.serialize callees in let callees_blob = Procname.SQLiteList.serialize callees in
DBWriter.replace_attributes ~pname_str ~pname:pname_blob ~akind:akind_int64 ~source_file DBWriter.replace_attributes ~pname_str ~pname:pname_blob ~akind:akind_int64 ~source_file
~attributes ~proc_desc:proc_desc_blob ~callees:callees_blob ~attributes ~proc_desc:proc_desc_blob ~callees:callees_blob
@ -82,11 +82,11 @@ let find ~defined pname_blob =
|> Option.map ~f:ProcAttributes.SQLite.deserialize ) |> Option.map ~f:ProcAttributes.SQLite.deserialize )
let load pname = Typ.Procname.SQLite.serialize pname |> find ~defined:false let load pname = Procname.SQLite.serialize pname |> find ~defined:false
let store ~proc_desc (attr : ProcAttributes.t) = let store ~proc_desc (attr : ProcAttributes.t) =
let pkind = proc_kind_of_attr attr in let pkind = proc_kind_of_attr attr in
let key = Typ.Procname.SQLite.serialize attr.proc_name in let key = Procname.SQLite.serialize attr.proc_name in
if should_try_to_update key pkind then if should_try_to_update key pkind then
replace attr.proc_name key pkind replace attr.proc_name key pkind
(SourceFile.SQLite.serialize attr.loc.Location.file) (SourceFile.SQLite.serialize attr.loc.Location.file)
@ -95,7 +95,7 @@ let store ~proc_desc (attr : ProcAttributes.t) =
(Option.map proc_desc ~f:Procdesc.get_static_callees |> Option.value ~default:[]) (Option.map proc_desc ~f:Procdesc.get_static_callees |> Option.value ~default:[])
let load_defined pname = Typ.Procname.SQLite.serialize pname |> find ~defined:true let load_defined pname = Procname.SQLite.serialize pname |> find ~defined:true
let find_file_capturing_procedure pname = let find_file_capturing_procedure pname =
Option.map (load pname) ~f:(fun proc_attributes -> Option.map (load pname) ~f:(fun proc_attributes ->

@ -16,13 +16,13 @@ val deserialize_attributes_kind : Sqlite3.Data.t -> attributes_kind
val store : proc_desc:Procdesc.t option -> ProcAttributes.t -> unit val store : proc_desc:Procdesc.t option -> ProcAttributes.t -> unit
(** Save .attr file for the procedure into the attributes database. *) (** Save .attr file for the procedure into the attributes database. *)
val load : Typ.Procname.t -> ProcAttributes.t option val load : Procname.t -> ProcAttributes.t option
(** Load the attributes for the procedure from the attributes database. *) (** Load the attributes for the procedure from the attributes database. *)
val load_defined : Typ.Procname.t -> ProcAttributes.t option val load_defined : Procname.t -> ProcAttributes.t option
(** Load attributes for the procedure but only if is_defined is true *) (** Load attributes for the procedure but only if is_defined is true *)
val find_file_capturing_procedure : Typ.Procname.t -> (SourceFile.t * [`Include | `Source]) option val find_file_capturing_procedure : Procname.t -> (SourceFile.t * [`Include | `Source]) option
(** Find the file where the procedure was captured, if a cfg for that file exists. Return also a (** 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 include file. *) boolean indicating whether the procedure is defined in an include file. *)

@ -7,28 +7,28 @@
open! IStd open! IStd
type t = Typ.Procname.t type t = Procname.t
let builtin_decls = ref Typ.Procname.Set.empty let builtin_decls = ref Procname.Set.empty
let register pname = builtin_decls := Typ.Procname.Set.add pname !builtin_decls let register pname = builtin_decls := Procname.Set.add pname !builtin_decls
let create_procname name = let create_procname name =
let pname = Typ.Procname.from_string_c_fun name in let pname = Procname.from_string_c_fun name in
register pname ; pname register pname ; pname
let create_objc_class_method class_name method_name parameters = let create_objc_class_method class_name method_name parameters =
let method_kind = Typ.Procname.ObjC_Cpp.ObjCClassMethod in let method_kind = Procname.ObjC_Cpp.ObjCClassMethod in
let tname = Typ.Name.Objc.from_string class_name in let tname = Typ.Name.Objc.from_string class_name in
let pname = let pname =
Typ.Procname.ObjC_Cpp Procname.ObjC_Cpp
(Typ.Procname.ObjC_Cpp.make tname method_name method_kind Typ.NoTemplate parameters) (Procname.ObjC_Cpp.make tname method_name method_kind Typ.NoTemplate parameters)
in in
register pname ; pname register pname ; pname
let is_declared pname = Typ.Procname.Set.mem pname !builtin_decls let is_declared pname = Procname.Set.mem pname !builtin_decls
let __array_access = create_procname "__array_access" let __array_access = create_procname "__array_access"

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

@ -8,7 +8,7 @@
open! IStd open! IStd
module F = Format module F = Format
type t = {pname: Typ.Procname.t; loc: Location.t} [@@deriving compare] type t = {pname: Procname.t; loc: Location.t} [@@deriving compare]
let equal = [%compare.equal: t] let equal = [%compare.equal: t]
@ -18,9 +18,9 @@ let loc t = t.loc
let make pname loc = {pname; loc} let make pname loc = {pname; loc}
let dummy = make Typ.Procname.empty_block Location.dummy let dummy = make Procname.empty_block Location.dummy
let pp fmt t = F.fprintf fmt "%a at %a" Typ.Procname.pp t.pname Location.pp t.loc let pp fmt t = F.fprintf fmt "%a at %a" 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

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

@ -11,15 +11,15 @@ module L = Logging
module F = Format module F = Format
(** data type for the control flow graph *) (** data type for the control flow graph *)
type t = Procdesc.t Typ.Procname.Hash.t type t = Procdesc.t Procname.Hash.t
let create () = Typ.Procname.Hash.create 16 let create () = Procname.Hash.create 16
let iter_over_sorted_procs cfg ~f = let iter_over_sorted_procs cfg ~f =
let compare_proc_desc_by_proc_name pdesc1 pdesc2 = let compare_proc_desc_by_proc_name pdesc1 pdesc2 =
Typ.Procname.compare (Procdesc.get_proc_name pdesc1) (Procdesc.get_proc_name pdesc2) Procname.compare (Procdesc.get_proc_name pdesc1) (Procdesc.get_proc_name pdesc2)
in in
Typ.Procname.Hash.fold (fun _ pdesc acc -> pdesc :: acc) cfg [] Procname.Hash.fold (fun _ pdesc acc -> pdesc :: acc) cfg []
|> List.sort ~compare:compare_proc_desc_by_proc_name |> List.sort ~compare:compare_proc_desc_by_proc_name
|> List.iter ~f |> List.iter ~f
@ -27,16 +27,16 @@ let iter_over_sorted_procs cfg ~f =
let get_all_defined_proc_names cfg = let get_all_defined_proc_names cfg =
let procs = ref [] in let procs = ref [] in
let f pname pdesc = if Procdesc.is_defined pdesc then procs := pname :: !procs in let f pname pdesc = if Procdesc.is_defined pdesc then procs := pname :: !procs in
Typ.Procname.Hash.iter f cfg ; !procs Procname.Hash.iter f cfg ; !procs
(** Create a new procdesc *) (** Create a new procdesc *)
let create_proc_desc cfg (proc_attributes : ProcAttributes.t) = let create_proc_desc cfg (proc_attributes : ProcAttributes.t) =
let pdesc = Procdesc.from_proc_attributes proc_attributes in let pdesc = Procdesc.from_proc_attributes proc_attributes in
let pname = proc_attributes.proc_name in let pname = proc_attributes.proc_name in
if Typ.Procname.Hash.mem cfg pname then if Procname.Hash.mem cfg pname then
L.die InternalError "Creating two procdescs for the same procname." ; L.die InternalError "Creating two procdescs for the same procname." ;
Typ.Procname.Hash.add cfg pname pdesc ; Procname.Hash.add cfg pname pdesc ;
pdesc pdesc
@ -53,7 +53,7 @@ let store source_file cfg =
Procdesc.set_attributes proc_desc attributes' ; Procdesc.set_attributes proc_desc attributes' ;
Attributes.store ~proc_desc:(Some proc_desc) attributes' Attributes.store ~proc_desc:(Some proc_desc) attributes'
in in
Typ.Procname.Hash.iter save_proc cfg Procname.Hash.iter save_proc cfg
(** Inline a synthetic (access or bridge) method. *) (** Inline a synthetic (access or bridge) method. *)
@ -121,11 +121,10 @@ let inline_synthetic_method ((ret_id, _) as ret) etl pdesc loc_call : Sil.instr
let proc_inline_synthetic_methods cfg pdesc : unit = let proc_inline_synthetic_methods cfg pdesc : unit =
let instr_inline_synthetic_method _node instr = let instr_inline_synthetic_method _node instr =
match instr with match instr with
| Sil.Call (ret_id_typ, Exp.Const (Const.Cfun (Typ.Procname.Java java_pn as pn)), etl, loc, _) | Sil.Call (ret_id_typ, Exp.Const (Const.Cfun (Procname.Java java_pn as pn)), etl, loc, _) -> (
-> ( match Procname.Hash.find cfg pn with
match Typ.Procname.Hash.find cfg pn with
| pd -> | pd ->
let is_access = Typ.Procname.Java.is_access_method java_pn in let is_access = Procname.Java.is_access_method java_pn in
let attributes = Procdesc.get_attributes pd in let attributes = Procdesc.get_attributes pd in
let is_synthetic = attributes.is_synthetic_method in let is_synthetic = attributes.is_synthetic_method in
let is_bridge = attributes.is_bridge_method in let is_bridge = attributes.is_bridge_method in
@ -142,8 +141,8 @@ let proc_inline_synthetic_methods cfg pdesc : unit =
let inline_java_synthetic_methods cfg = let inline_java_synthetic_methods cfg =
let f pname pdesc = if Typ.Procname.is_java pname then proc_inline_synthetic_methods cfg pdesc in let f pname pdesc = if Procname.is_java pname then proc_inline_synthetic_methods cfg pdesc in
Typ.Procname.Hash.iter f cfg Procname.Hash.iter f cfg
let pp_proc_signatures fmt cfg = let pp_proc_signatures fmt cfg =

@ -11,9 +11,9 @@ open! IStd
(** Control Flow Graph for Interprocedural Analysis *) (** Control Flow Graph for Interprocedural Analysis *)
(** A control-flow graph is a collection of all the CFGs for the procedure names in a file *) (** A control-flow graph is a collection of all the CFGs for the procedure names in a file *)
type t = Procdesc.t Typ.Procname.Hash.t type t = Procdesc.t Procname.Hash.t
val get_all_defined_proc_names : t -> Typ.Procname.t list val get_all_defined_proc_names : t -> Procname.t list
(** get all the procedure names that are defined in the current file *) (** get all the procedure names that are defined in the current file *)
val store : SourceFile.t -> t -> unit val store : SourceFile.t -> t -> unit

@ -13,7 +13,7 @@ module F = Format
type t = type t =
| Cint of IntLit.t (** integer constants *) | Cint of IntLit.t (** integer constants *)
| Cfun of Typ.Procname.t (** function names *) | Cfun of Procname.t (** function names *)
| Cstr of string (** string constants *) | Cstr of string (** string constants *)
| Cfloat of float (** float constants *) | Cfloat of float (** float constants *)
| Cclass of Ident.name (** class constant *) | Cclass of Ident.name (** class constant *)
@ -43,9 +43,9 @@ let pp pe f = function
| Cfun fn -> ( | Cfun fn -> (
match pe.Pp.kind with match pe.Pp.kind with
| HTML -> | HTML ->
F.fprintf f "_fun_%s" (Escape.escape_xml (F.asprintf "%a" Typ.Procname.pp fn)) F.fprintf f "_fun_%s" (Escape.escape_xml (F.asprintf "%a" Procname.pp fn))
| _ -> | _ ->
F.fprintf f "_fun_%a" Typ.Procname.pp fn ) F.fprintf f "_fun_%a" Procname.pp fn )
| Cstr s -> | Cstr s ->
F.fprintf f "\"%s\"" (String.escaped s) F.fprintf f "\"%s\"" (String.escaped s)
| Cfloat v -> | Cfloat v ->

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

@ -38,7 +38,7 @@ let split_var_clang var_name =
let builtin_functions_to_string pn = let builtin_functions_to_string pn =
if Typ.Procname.equal pn BuiltinDecl.__objc_alloc_no_fail then Some "alloc" else None if Procname.equal pn BuiltinDecl.__objc_alloc_no_fail then Some "alloc" else None
let rec pp fmt = function let rec pp fmt = function
@ -51,10 +51,10 @@ let rec pp fmt = function
| Some str -> | Some str ->
F.pp_print_string fmt str F.pp_print_string fmt str
| None -> ( | None -> (
let procname_str = Typ.Procname.to_simplified_string pn in let procname_str = Procname.to_simplified_string pn in
match pn with match pn with
| Typ.Procname.ObjC_Cpp {kind= ObjCInstanceMethod} | Procname.ObjC_Cpp {kind= ObjCInstanceMethod} | Procname.ObjC_Cpp {kind= ObjCClassMethod}
| Typ.Procname.ObjC_Cpp {kind= ObjCClassMethod} -> ( -> (
match String.lsplit2 ~on:':' procname_str with match String.lsplit2 ~on:':' procname_str with
| Some (base_name, _) -> | Some (base_name, _) ->
F.pp_print_string fmt base_name F.pp_print_string fmt base_name
@ -75,10 +75,10 @@ let rec pp fmt = function
| Dconst (Cfun pname) -> | Dconst (Cfun pname) ->
let s = let s =
match pname with match pname with
| Typ.Procname.Java pname_java -> | Procname.Java pname_java ->
Typ.Procname.Java.get_method pname_java Procname.Java.get_method pname_java
| _ -> | _ ->
Typ.Procname.to_string pname Procname.to_string pname
in in
F.pp_print_string fmt s F.pp_print_string fmt s
| de -> | de ->

@ -11,7 +11,7 @@ module F = Format
let pp_cfgnodename pname fmt (n : Procdesc.Node.t) = let pp_cfgnodename pname fmt (n : Procdesc.Node.t) =
F.fprintf fmt "\"%s_%d\"" F.fprintf fmt "\"%s_%d\""
(Escape.escape_dotty (Typ.Procname.to_filename pname)) (Escape.escape_dotty (Procname.to_filename pname))
(Procdesc.Node.get_id n :> int) (Procdesc.Node.get_id n :> int)
@ -32,7 +32,7 @@ let pp_cfgnodelabel pdesc fmt (n : Procdesc.Node.t) =
match Procdesc.Node.get_kind n with match Procdesc.Node.get_kind n with
| Start_node -> | Start_node ->
let pname = Procdesc.Node.get_proc_name n in let pname = Procdesc.Node.get_proc_name n in
let pname_string = Escape.escape_dotty (Typ.Procname.to_string pname) in let pname_string = Escape.escape_dotty (Procname.to_string pname) in
let attributes = Procdesc.get_attributes pdesc in let attributes = Procdesc.get_attributes pdesc in
Format.fprintf fmt "Start %s\\nFormals: %a\\nLocals: %a" pname_string pp_etlist Format.fprintf fmt "Start %s\\nFormals: %a\\nLocals: %a" pname_string pp_etlist
(Procdesc.get_formals pdesc) pp_local_list (Procdesc.get_locals pdesc) ; (Procdesc.get_formals pdesc) pp_local_list (Procdesc.get_locals pdesc) ;
@ -43,7 +43,7 @@ let pp_cfgnodelabel pdesc fmt (n : Procdesc.Node.t) =
Format.fprintf fmt "\\nAnnotation: %a" (Annot.Method.pp pname_string) method_annotation Format.fprintf fmt "\\nAnnotation: %a" (Annot.Method.pp pname_string) method_annotation
| Exit_node -> | Exit_node ->
let pname = Procdesc.Node.get_proc_name n in let pname = Procdesc.Node.get_proc_name n in
Format.fprintf fmt "Exit %s" (Escape.escape_dotty (Typ.Procname.to_string pname)) Format.fprintf fmt "Exit %s" (Escape.escape_dotty (Procname.to_string pname))
| Join_node -> | Join_node ->
Format.pp_print_char fmt '+' Format.pp_print_char fmt '+'
| Prune_node (is_true_branch, if_kind, _) -> | Prune_node (is_true_branch, if_kind, _) ->
@ -135,7 +135,7 @@ let emit_proc_desc source proc_desc =
let filename = let filename =
let db_name = let db_name =
DB.Results_dir.path_to_filename (DB.Results_dir.Abs_source_dir source) DB.Results_dir.path_to_filename (DB.Results_dir.Abs_source_dir source)
[Typ.Procname.to_filename (Procdesc.get_proc_name proc_desc)] [Procname.to_filename (Procdesc.get_proc_name proc_desc)]
in in
DB.filename_to_string db_name ^ ".dot" DB.filename_to_string db_name ^ ".dot"
in in

@ -13,8 +13,8 @@ module F = Format
type node_tag = type node_tag =
| Condition of bool | Condition of bool
| Exception of Typ.name | Exception of Typ.name
| Procedure_start of Typ.Procname.t | Procedure_start of Procname.t
| Procedure_end of Typ.Procname.t | Procedure_end of Procname.t
(** Element of a loc trace *) (** Element of a loc trace *)
type loc_trace_elem = type loc_trace_elem =
@ -261,7 +261,7 @@ let log_issue procname ~clang_method_kind severity err_log ~loc ~node ~session ~
in in
( if exn_developer then ( if exn_developer then
let issue = let issue =
let lang = Typ.Procname.get_language procname in let lang = Procname.get_language procname in
let clang_method_kind = let clang_method_kind =
match lang with match lang with
| Language.Clang -> | Language.Clang ->
@ -275,7 +275,7 @@ let log_issue procname ~clang_method_kind severity err_log ~loc ~node ~session ~
; clang_method_kind ; clang_method_kind
; exception_triggered_location= error.ocaml_pos ; exception_triggered_location= error.ocaml_pos
; lang= Language.to_explicit_string lang ; lang= Language.to_explicit_string lang
; procedure_name= Typ.Procname.to_string procname ; procedure_name= Procname.to_string procname
; source_location= loc } ; source_location= loc }
in in
EventLogger.log issue ) ; EventLogger.log issue ) ;

@ -12,8 +12,8 @@ open! IStd
type node_tag = type node_tag =
| Condition of bool | Condition of bool
| Exception of Typ.name | Exception of Typ.name
| Procedure_start of Typ.Procname.t | Procedure_start of Procname.t
| Procedure_end of Typ.Procname.t | Procedure_end of Procname.t
(** Element of a loc trace *) (** Element of a loc trace *)
type loc_trace_elem = private type loc_trace_elem = private
@ -109,7 +109,7 @@ val update : t -> t -> unit
(** Update an old error log with a new one *) (** Update an old error log with a new one *)
val log_issue : val log_issue :
Typ.Procname.t Procname.t
-> clang_method_kind:ClangMethodKind.t option -> clang_method_kind:ClangMethodKind.t option
-> Exceptions.severity -> Exceptions.severity
-> t -> t

@ -18,7 +18,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: Typ.Procname.t; captured_vars: (t * Pvar.t * Typ.t) list} type closure = {name: Procname.t; captured_vars: (t * Pvar.t * Typ.t) list}
(** This records information about a [sizeof(typ)] expression. (** This records information about a [sizeof(typ)] expression.
@ -319,12 +319,7 @@ let pp_texp_full pe f = function
(** Dump a type expression with all the details. *) (** Dump a type expression with all the details. *)
let d_texp_full (te : t) = L.d_pp_with_pe pp_texp_full te let d_texp_full (te : t) = L.d_pp_with_pe pp_texp_full te
let is_objc_block_closure = function let is_objc_block_closure = function Closure {name} -> Procname.is_objc_block name | _ -> false
| Closure {name} ->
Typ.Procname.is_objc_block name
| _ ->
false
let rec gen_free_vars = let rec gen_free_vars =
let open Sequence.Generator in let open Sequence.Generator in
@ -416,11 +411,7 @@ let rec get_java_class_initializer tenv = function
match Struct.get_field_type_and_annotation ~lookup:(Tenv.lookup tenv) fn typ with match Struct.get_field_type_and_annotation ~lookup:(Tenv.lookup tenv) fn typ with
| Some (field_typ, annot) when Annot.Item.is_final annot -> | Some (field_typ, annot) when Annot.Item.is_final annot ->
let java_class = Typ.JavaClass (Pvar.get_name pvar) in let java_class = Typ.JavaClass (Pvar.get_name pvar) in
Some Some (Procname.Java (Procname.Java.get_class_initializer java_class), pvar, fn, field_typ)
( Typ.Procname.Java (Typ.Procname.Java.get_class_initializer java_class)
, pvar
, fn
, field_typ )
| _ -> | _ ->
None ) None )
| Cast (_, e) | Lfield (e, _, _) -> | Cast (_, e) | Lfield (e, _, _) ->

@ -13,7 +13,7 @@
open! IStd open! IStd
module F = Format module F = Format
type closure = {name: Typ.Procname.t; captured_vars: (t * Pvar.t * Typ.t) list} type closure = {name: Procname.t; captured_vars: (t * Pvar.t * Typ.t) list}
(** This records information about a [sizeof(typ)] expression. (** This records information about a [sizeof(typ)] expression.
@ -170,6 +170,5 @@ val ignore_cast : t -> t
val ignore_integer_cast : t -> t val ignore_integer_cast : t -> t
val get_java_class_initializer : val get_java_class_initializer : Tenv.t -> t -> (Procname.t * Pvar.t * Fieldname.t * Typ.t) option
Tenv.t -> t -> (Typ.Procname.t * Pvar.t * Fieldname.t * Typ.t) option
(** Returns the class initializer of the given expression in Java *) (** Returns the class initializer of the given expression in Java *)

@ -8,7 +8,7 @@ open! IStd
type source_files_filter = SourceFile.t -> bool type source_files_filter = SourceFile.t -> bool
type procedures_filter = SourceFile.t -> Typ.Procname.t -> bool type procedures_filter = SourceFile.t -> Procname.t -> bool
let filter_of_regexp_opt ~to_string r = let filter_of_regexp_opt ~to_string r =
match r with match r with
@ -44,7 +44,7 @@ let mk_procedure_name_filter ~filter =
let source_file_filter = let source_file_filter =
filter_of_regexp_opt ~to_string:SourceFile.to_string source_file_regexp filter_of_regexp_opt ~to_string:SourceFile.to_string source_file_regexp
in in
let proc_name_filter = filter_of_regexp_opt ~to_string:Typ.Procname.to_string proc_name_regexp in let proc_name_filter = filter_of_regexp_opt ~to_string:Procname.to_string proc_name_regexp in
source_file_filter &&& proc_name_filter source_file_filter &&& proc_name_filter

@ -9,7 +9,7 @@ open! IStd
type source_files_filter = SourceFile.t -> bool type source_files_filter = SourceFile.t -> bool
type procedures_filter = SourceFile.t -> Typ.Procname.t -> bool type procedures_filter = SourceFile.t -> Procname.t -> bool
val source_files_filter : source_files_filter Lazy.t val source_files_filter : source_files_filter Lazy.t
(** filter corresponding to `--source-files-filter` *) (** filter corresponding to `--source-files-filter` *)

@ -48,7 +48,7 @@ module T : sig
| UnaryOperator of Unop.t * t * Typ.t option | UnaryOperator of Unop.t * t * Typ.t option
| BinaryOperator of Binop.t * t * t | BinaryOperator of Binop.t * t * t
| Exception of t | Exception of t
| Closure of Typ.Procname.t * (AccessPath.base * t) list | Closure of Procname.t * (AccessPath.base * t) list
| Constant of Const.t | Constant of Const.t
| Cast of Typ.t * t | Cast of Typ.t * t
| Sizeof of Typ.t * t option | Sizeof of Typ.t * t option
@ -83,7 +83,7 @@ end = struct
| UnaryOperator of Unop.t * t * Typ.t option | UnaryOperator of Unop.t * t * Typ.t option
| BinaryOperator of Binop.t * t * t | BinaryOperator of Binop.t * t * t
| Exception of t | Exception of t
| Closure of Typ.Procname.t * (AccessPath.base * t) list | Closure of Procname.t * (AccessPath.base * t) list
| Constant of Const.t | Constant of Const.t
| Cast of Typ.t * t | Cast of Typ.t * t
| Sizeof of Typ.t * t option | Sizeof of Typ.t * t option
@ -181,7 +181,7 @@ and pp fmt = function
| _ -> | _ ->
F.fprintf fmt "%a captured as %a" AccessPath.pp_base base pp exp F.fprintf fmt "%a captured as %a" AccessPath.pp_base base pp exp
in in
F.fprintf fmt "closure(%a, %a)" Typ.Procname.pp pname F.fprintf fmt "closure(%a, %a)" Procname.pp pname
(PrettyPrintable.pp_collection ~pp_item) (PrettyPrintable.pp_collection ~pp_item)
captured captured
| Constant c -> | Constant c ->

@ -27,7 +27,7 @@ type t =
(** Unary operator with type of the result if known *) (** Unary operator with type of the result if known *)
| BinaryOperator of Binop.t * t * t (** Binary operator *) | BinaryOperator of Binop.t * t * t (** Binary operator *)
| Exception of t (** Exception *) | Exception of t (** Exception *)
| Closure of Typ.Procname.t * (AccessPath.base * t) list (** Name of function + environment *) | Closure of Procname.t * (AccessPath.base * t) list (** Name of function + environment *)
| Constant of Const.t (** Constants *) | Constant of Const.t (** Constants *)
| Cast of Typ.t * t (** Type cast *) | Cast of Typ.t * t (** Type cast *)
| Sizeof of Typ.t * t option | Sizeof of Typ.t * t option

@ -9,11 +9,11 @@ open! IStd
module F = Format module F = Format
module L = Logging module L = Logging
type call = Direct of Typ.Procname.t | Indirect of HilExp.AccessExpression.t [@@deriving compare] type call = Direct of Procname.t | Indirect of HilExp.AccessExpression.t [@@deriving compare]
let pp_call fmt = function let pp_call fmt = function
| Direct pname -> | Direct pname ->
Typ.Procname.pp fmt pname Procname.pp fmt pname
| Indirect access_expr -> | Indirect access_expr ->
F.fprintf fmt "*%a" HilExp.AccessExpression.pp access_expr F.fprintf fmt "*%a" HilExp.AccessExpression.pp access_expr
@ -70,7 +70,7 @@ let of_sil ~include_array_indexes ~f_resolve_id (instr : Sil.instr) =
, (target_exp, _) :: (Sizeof {typ= cast_typ}, _) :: _ , (target_exp, _) :: (Sizeof {typ= cast_typ}, _) :: _
, loc , loc
, _ ) , _ )
when Typ.Procname.equal callee_pname BuiltinDecl.__cast -> when Procname.equal callee_pname BuiltinDecl.__cast ->
analyze_id_assignment (Var.of_id ret_id) target_exp cast_typ loc analyze_id_assignment (Var.of_id ret_id) target_exp cast_typ loc
| Store {e1= lhs_exp; typ; e2= rhs_exp; loc} -> | Store {e1= lhs_exp; typ; e2= rhs_exp; loc} ->
let lhs_access_expr = let lhs_access_expr =

@ -9,7 +9,7 @@ open! IStd
module F = Format module F = Format
(** type of a procedure call; either direct or via function pointer *) (** type of a procedure call; either direct or via function pointer *)
type call = Direct of Typ.Procname.t | Indirect of HilExp.AccessExpression.t [@@deriving compare] type call = Direct of Procname.t | Indirect of HilExp.AccessExpression.t [@@deriving compare]
val pp_call : F.formatter -> call -> unit [@@warning "-32"] val pp_call : F.formatter -> call -> unit [@@warning "-32"]

@ -109,7 +109,7 @@ h1 { font-size:14pt }
(** 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 = F.sprintf "%s_node%d" (Typ.Procname.to_filename pname) id let node_filename pname id = F.sprintf "%s_node%d" (Procname.to_filename pname) 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 fmt id = let pp_node_link path_to_root pname ~description ~preds ~succs ~exn ~isvisited fmt id =
@ -129,7 +129,7 @@ h1 { font-size:14pt }
(** 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 @ [Typ.Procname.to_filename proc_name]) fmt text pp_link ~path:(path_to_root @ [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 *)

@ -20,7 +20,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
(** Return true if the html file was modified since the beginning of the analysis *) (** Return true if the html file was modified since the beginning of the analysis *)
val node_filename : Typ.Procname.t -> int -> string val node_filename : Procname.t -> int -> string
(** 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 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
@ -41,7 +41,7 @@ module Html : sig
val pp_node_link : val pp_node_link :
DB.Results_dir.path DB.Results_dir.path
-> Typ.Procname.t -> Procname.t
-> description:string -> description:string
-> preds:int list -> preds:int list
-> succs:int list -> succs:int list
@ -54,12 +54,12 @@ module Html : sig
[path_to_root] is the path to the dir for the procedure in the spec db. [id] is the node [path_to_root] is the path to the dir for the procedure in the spec db. [id] is the node
identifier. *) identifier. *)
val pp_proc_link : DB.Results_dir.path -> Typ.Procname.t -> Format.formatter -> string -> unit val pp_proc_link : DB.Results_dir.path -> Procname.t -> Format.formatter -> string -> unit
(** Print an html link to the given proc *) (** Print an html link to the given proc *)
val pp_session_link : val pp_session_link :
?with_name:bool ?with_name:bool
-> ?proc_name:Typ.Procname.t -> ?proc_name:Procname.t
-> SourceFile.t -> SourceFile.t
-> string list -> string list
-> Format.formatter -> Format.formatter

@ -9,28 +9,28 @@
open! IStd open! IStd
type t = Errlog.t Typ.Procname.Map.t type t = Errlog.t Procname.Map.t
let empty = Typ.Procname.Map.empty let empty = Procname.Map.empty
let get_or_add ~proc m = let get_or_add ~proc m =
match Typ.Procname.Map.find_opt proc m with match Procname.Map.find_opt proc m with
| Some errlog -> | Some errlog ->
(m, errlog) (m, errlog)
| None -> | None ->
let errlog = Errlog.empty () in let errlog = Errlog.empty () in
let m = Typ.Procname.Map.add proc errlog m in let m = Procname.Map.add proc errlog m in
(m, errlog) (m, errlog)
let issues_serializer : Errlog.t Typ.Procname.Map.t Serialization.serializer = let issues_serializer : Errlog.t Procname.Map.t Serialization.serializer =
Serialization.create_serializer Serialization.Key.issues Serialization.create_serializer Serialization.Key.issues
let iter ~f m = Typ.Procname.Map.iter f m let iter ~f m = Procname.Map.iter f m
let store ~dir ~file m = let store ~dir ~file m =
if not (Typ.Procname.Map.is_empty m) then ( if not (Procname.Map.is_empty m) then (
let abbrev_source_file = DB.source_file_encoding file in let abbrev_source_file = DB.source_file_encoding file in
let issues_dir = Config.results_dir ^/ dir in let issues_dir = Config.results_dir ^/ dir in
Utils.create_dir issues_dir ; Utils.create_dir issues_dir ;
@ -51,7 +51,7 @@ let load 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
load_issues file load_issues file
|> Option.fold ~init ~f:(fun acc map -> |> Option.fold ~init ~f:(fun acc map ->
Typ.Procname.Map.merge 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 ->

@ -12,10 +12,10 @@ type t
val empty : t val empty : t
val iter : f:(Typ.Procname.t -> Errlog.t -> unit) -> t -> unit val iter : f:(Procname.t -> Errlog.t -> unit) -> t -> unit
(** iterate a function on map contents *) (** iterate a function on map contents *)
val get_or_add : proc:Typ.Procname.t -> t -> t * Errlog.t val get_or_add : proc:Procname.t -> t -> t * Errlog.t
(** Get the error log for a given procname. If there is none, add an empty one to the map. Return (** Get the error log for a given procname. If there is none, add an empty one to the map. Return
the resulting map together with the errlog. *) the resulting map together with the errlog. *)

@ -138,7 +138,7 @@ let line_ tags loc = line_tag_ tags Tags.line loc
let at_line tags loc = at_line_tag tags Tags.line loc let at_line tags loc = at_line_tag tags Tags.line loc
let call_to proc_name = let call_to proc_name =
let proc_name_str = Typ.Procname.to_simplified_string proc_name in let proc_name_str = Procname.to_simplified_string proc_name in
"call to " ^ MF.monospaced_to_string proc_name_str "call to " ^ MF.monospaced_to_string proc_name_str
@ -203,14 +203,14 @@ let deref_str_nullable proc_name_opt nullable_obj_str =
(** dereference strings for nonterminal nil arguments in c/objc variadic methods *) (** dereference strings for nonterminal nil arguments in c/objc variadic methods *)
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 function_method, nil_null = let function_method, nil_null =
if Typ.Procname.is_c_method pn then ("method", "nil") else ("function", "null") if Procname.is_c_method pn then ("method", "nil") else ("function", "null")
in 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 (%s indicates \ "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)" that the last argument of this variadic %s has been reached)"
nil_null nil_null
(Typ.Procname.to_simplified_string pn) (Procname.to_simplified_string pn)
arg_number (total_args - 1) nil_null function_method arg_number (total_args - 1) nil_null function_method
in in
deref_str_null_ None problem_str deref_str_null_ None problem_str
@ -219,7 +219,7 @@ let deref_str_nil_argument_in_variadic_method pn total_args arg_number =
(** 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 = Typ.Procname.to_simplified_string proc_name in let proc_name_str = Procname.to_simplified_string proc_name in
{ tags { tags
; value_pre= Some (pointer_or_object ()) ; value_pre= Some (pointer_or_object ())
; value_post= None ; value_post= None
@ -345,7 +345,7 @@ let nullable_annotation_name proc_name =
match Config.nullable_annotation with match Config.nullable_annotation with
| Some name -> | Some name ->
name name
| None when Typ.Procname.is_java proc_name -> | None when Procname.is_java proc_name ->
"@Nullable" "@Nullable"
| None (* default Clang annotation name *) -> | None (* default Clang annotation name *) ->
"_Nullable" "_Nullable"
@ -460,11 +460,11 @@ let desc_allocation_mismatch alloc dealloc =
let tags = Tags.create () in let tags = Tags.create () in
let using (primitive_pname, called_pname, loc) = let using (primitive_pname, called_pname, loc) =
let by_call = let by_call =
if Typ.Procname.equal primitive_pname called_pname then "" if Procname.equal primitive_pname called_pname then ""
else " by call to " ^ MF.monospaced_to_string (Typ.Procname.to_simplified_string called_pname) else " by call to " ^ MF.monospaced_to_string (Procname.to_simplified_string called_pname)
in in
"using " "using "
^ MF.monospaced_to_string (Typ.Procname.to_simplified_string primitive_pname) ^ MF.monospaced_to_string (Procname.to_simplified_string primitive_pname)
^ by_call ^ " " ^ by_call ^ " "
^ at_line (Tags.create ()) (* ignore the tag *) loc ^ at_line (Tags.create ()) (* ignore the tag *) loc
in in
@ -688,13 +688,13 @@ 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 = Typ.Procname.to_string proc_name in let proc_name_str = Procname.to_string proc_name in
Tags.update tags Tags.value proc_name_str ; Tags.update 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 = Typ.Procname.to_string proc_name in let proc_name_str = Procname.to_string proc_name in
let tags = Tags.create () in let tags = Tags.create () in
Tags.update tags Tags.value proc_name_str ; Tags.update tags Tags.value proc_name_str ;
{no_desc with descriptions= [MF.monospaced_to_string proc_name_str]; tags= !tags} {no_desc with descriptions= [MF.monospaced_to_string proc_name_str]; tags= !tags}

@ -63,13 +63,13 @@ val error_desc_get_dotty : error_desc -> string option
(** dereference strings used to explain a dereference action in an error message *) (** dereference strings used to explain a dereference action in an error message *)
type deref_str type deref_str
val deref_str_null : Typ.Procname.t option -> deref_str val deref_str_null : Procname.t option -> deref_str
(** dereference strings for null dereference *) (** dereference strings for null dereference *)
val deref_str_nullable : Typ.Procname.t option -> string -> deref_str val deref_str_nullable : Procname.t option -> string -> deref_str
(** dereference strings for null dereference due to Nullable annotation *) (** dereference strings for null dereference due to Nullable annotation *)
val deref_str_undef : Typ.Procname.t * Location.t -> deref_str val deref_str_undef : Procname.t * Location.t -> 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_freed : PredSymb.res_action -> deref_str val deref_str_freed : PredSymb.res_action -> deref_str
@ -81,7 +81,7 @@ val deref_str_dangling : PredSymb.dangling_kind option -> deref_str
val deref_str_array_bound : IntLit.t option -> IntLit.t option -> deref_str val deref_str_array_bound : IntLit.t option -> IntLit.t option -> deref_str
(** dereference strings for an array out of bound access *) (** dereference strings for an array out of bound access *)
val deref_str_nil_argument_in_variadic_method : Typ.Procname.t -> int -> int -> deref_str val deref_str_nil_argument_in_variadic_method : Procname.t -> int -> int -> 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_pointer_size_mismatch : Typ.t -> Typ.t -> deref_str val deref_str_pointer_size_mismatch : Typ.t -> Typ.t -> deref_str
@ -94,11 +94,11 @@ type access =
| Initialized_automatically | Initialized_automatically
| Returned_from_call of int | Returned_from_call of int
val nullable_annotation_name : Typ.Procname.t -> string val nullable_annotation_name : Procname.t -> string
(** Name of the nullable annotation *) (** Name of the nullable annotation *)
val dereference_string : val dereference_string :
Typ.Procname.t -> deref_str -> string -> access option -> Location.t -> error_desc Procname.t -> deref_str -> string -> access option -> Location.t -> error_desc
val parameter_field_not_null_checked_desc : error_desc -> Exp.t -> error_desc val parameter_field_not_null_checked_desc : error_desc -> Exp.t -> error_desc
@ -107,22 +107,20 @@ val is_parameter_not_null_checked_desc : error_desc -> bool
val is_field_not_null_checked_desc : error_desc -> bool val is_field_not_null_checked_desc : error_desc -> bool
val desc_allocation_mismatch : val desc_allocation_mismatch :
Typ.Procname.t * Typ.Procname.t * Location.t Procname.t * Procname.t * Location.t -> Procname.t * Procname.t * Location.t -> error_desc
-> Typ.Procname.t * Typ.Procname.t * Location.t
-> error_desc
val desc_class_cast_exception : val desc_class_cast_exception :
Typ.Procname.t option -> string -> string -> string option -> Location.t -> error_desc Procname.t option -> string -> string -> string option -> 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 -> Typ.Procname.t -> Location.t -> error_desc val desc_deallocate_stack_variable : string -> Procname.t -> Location.t -> error_desc
val desc_deallocate_static_memory : string -> Typ.Procname.t -> Location.t -> error_desc val desc_deallocate_static_memory : string -> 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 : Typ.Procname.t option -> string -> Location.t -> error_desc val desc_empty_vector_access : 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
@ -145,7 +143,7 @@ val desc_custom_error : Location.t -> error_desc
(** kind of precondition not met *) (** kind of precondition not met *)
type pnm_kind = Pnm_bounds | Pnm_dangling type pnm_kind = Pnm_bounds | Pnm_dangling
val desc_precondition_not_met : pnm_kind option -> Typ.Procname.t -> Location.t -> error_desc val desc_precondition_not_met : pnm_kind option -> Procname.t -> Location.t -> error_desc
val desc_retain_cycle : string -> Location.t -> string option -> error_desc val desc_retain_cycle : string -> Location.t -> string option -> error_desc
@ -153,9 +151,9 @@ val desc_registered_observer_being_deallocated : Pvar.t -> Location.t -> error_d
val desc_stack_variable_address_escape : Pvar.t -> string option -> Location.t -> error_desc val desc_stack_variable_address_escape : Pvar.t -> string option -> Location.t -> error_desc
val desc_skip_function : Typ.Procname.t -> error_desc val desc_skip_function : Procname.t -> error_desc
val desc_inherently_dangerous_function : Typ.Procname.t -> error_desc val desc_inherently_dangerous_function : 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

@ -196,4 +196,4 @@ end
let is_core_lib_type typ = Core_foundation_model.is_core_lib_type typ let is_core_lib_type typ = Core_foundation_model.is_core_lib_type typ
let is_malloc_model return_type pname = let is_malloc_model return_type pname =
Core_foundation_model.is_core_lib_create return_type (Typ.Procname.to_string pname) Core_foundation_model.is_core_lib_create return_type (Procname.to_string pname)

@ -12,4 +12,4 @@ open! IStd
val is_core_lib_type : Typ.t -> bool val is_core_lib_type : Typ.t -> bool
val is_malloc_model : Typ.t -> Typ.Procname.t -> bool val is_malloc_model : Typ.t -> Procname.t -> bool

@ -52,7 +52,7 @@ type dangling_kind =
[@@deriving compare] [@@deriving compare]
(** position in a path: proc name, node id *) (** position in a path: proc name, node id *)
type path_pos = Typ.Procname.t * int [@@deriving compare] type path_pos = Procname.t * int [@@deriving compare]
let equal_path_pos = [%compare.equal: path_pos] let equal_path_pos = [%compare.equal: path_pos]
@ -60,7 +60,7 @@ let equal_path_pos = [%compare.equal: path_pos]
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: Typ.Procname.t (** name of the procedure used to acquire/release the resource *) ; ra_pname: 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 *) }
@ -94,13 +94,13 @@ type t =
| Aresource of res_action (** resource acquire/release *) | Aresource of res_action (** resource acquire/release *)
| Aautorelease | Aautorelease
| Adangling of dangling_kind (** dangling pointer *) | Adangling of dangling_kind (** dangling pointer *)
| Aundef of Typ.Procname.t * annot_item_ * location_ * path_pos_ | Aundef of Procname.t * annot_item_ * location_ * path_pos_
| Alocked | Alocked
| Aunlocked | Aunlocked
| Adiv0 of path_pos (** value appeared in second argument of division at given path position *) | Adiv0 of path_pos (** value appeared in second argument of division at given path position *)
| Aobjc_null | Aobjc_null
(** 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 *)
| Aretval of Typ.Procname.t * Annot.Item.t | Aretval of Procname.t * Annot.Item.t
(** 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 *)
| Aobserver (** denotes an object registered as an observers to a notification center *) | Aobserver (** denotes an object registered as an observers to a notification center *)
| Aunsubscribed_observer | Aunsubscribed_observer
@ -113,25 +113,25 @@ 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 = function let mem_alloc_pname = function
| Mmalloc -> | Mmalloc ->
Typ.Procname.from_string_c_fun "malloc" Procname.from_string_c_fun "malloc"
| Mnew -> | Mnew ->
Typ.Procname.from_string_c_fun "new" Procname.from_string_c_fun "new"
| Mnew_array -> | Mnew_array ->
Typ.Procname.from_string_c_fun "new[]" Procname.from_string_c_fun "new[]"
| Mobjc -> | Mobjc ->
Typ.Procname.from_string_c_fun "alloc" 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 = function let mem_dealloc_pname = function
| Mmalloc -> | Mmalloc ->
Typ.Procname.from_string_c_fun "free" Procname.from_string_c_fun "free"
| Mnew -> | Mnew ->
Typ.Procname.from_string_c_fun "delete" Procname.from_string_c_fun "delete"
| Mnew_array -> | Mnew_array ->
Typ.Procname.from_string_c_fun "delete[]" Procname.from_string_c_fun "delete[]"
| Mobjc -> | Mobjc ->
Typ.Procname.from_string_c_fun "dealloc" Procname.from_string_c_fun "dealloc"
(** Categories of attributes *) (** Categories of attributes *)
@ -206,9 +206,7 @@ let to_string pe = function
let str_vpath = let str_vpath =
if Config.trace_error then F.asprintf "%a" (DecompiledExp.pp_vpath pe) ra.ra_vpath else "" if Config.trace_error then F.asprintf "%a" (DecompiledExp.pp_vpath pe) ra.ra_vpath else ""
in in
name ^ Binop.str pe Lt name ^ 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 ^ string_of_int ra.ra_loc.Location.line
^ Binop.str pe Gt ^ str_vpath ^ Binop.str pe Gt ^ str_vpath
| Aautorelease -> | Aautorelease ->
@ -225,7 +223,7 @@ let to_string pe = function
in in
"DANGL" ^ Binop.str pe Lt ^ dks ^ Binop.str pe Gt "DANGL" ^ Binop.str pe Lt ^ dks ^ Binop.str pe Gt
| Aundef (pn, _, loc, _) -> | Aundef (pn, _, loc, _) ->
"UND" ^ Binop.str pe Lt ^ Typ.Procname.to_string pn ^ Binop.str pe Gt ^ ":" "UND" ^ Binop.str pe Lt ^ Procname.to_string pn ^ Binop.str pe Gt ^ ":"
^ string_of_int loc.Location.line ^ string_of_int loc.Location.line
| Alocked -> | Alocked ->
"LOCKED" "LOCKED"
@ -236,7 +234,7 @@ let to_string pe = function
| Aobjc_null -> | Aobjc_null ->
"OBJC_NULL" "OBJC_NULL"
| Aretval (pn, _) -> | Aretval (pn, _) ->
"RET" ^ Binop.str pe Lt ^ Typ.Procname.to_string pn ^ Binop.str pe Gt "RET" ^ Binop.str pe Lt ^ Procname.to_string pn ^ Binop.str pe Gt
| Aobserver -> | Aobserver ->
"OBSERVER" "OBSERVER"
| Aunsubscribed_observer -> | Aunsubscribed_observer ->

@ -42,7 +42,7 @@ type dangling_kind =
| DAminusone (** pointer is -1 *) | DAminusone (** pointer is -1 *)
(** position in a path: proc name, node id *) (** position in a path: proc name, node id *)
type path_pos = Typ.Procname.t * int [@@deriving compare] type path_pos = Procname.t * int [@@deriving compare]
val equal_path_pos : path_pos -> path_pos -> bool val equal_path_pos : path_pos -> path_pos -> bool
@ -50,7 +50,7 @@ val equal_path_pos : path_pos -> path_pos -> bool
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: Typ.Procname.t (** name of the procedure used to acquire/release the resource *) ; ra_pname: 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 *) }
@ -66,13 +66,13 @@ type t =
| Aresource of res_action (** resource acquire/release *) | Aresource of res_action (** resource acquire/release *)
| Aautorelease | Aautorelease
| Adangling of dangling_kind (** dangling pointer *) | Adangling of dangling_kind (** dangling pointer *)
| Aundef of Typ.Procname.t * Annot.Item.t * Location.t * path_pos | Aundef of Procname.t * Annot.Item.t * Location.t * path_pos
| Alocked | Alocked
| Aunlocked | Aunlocked
| Adiv0 of path_pos (** value appeared in second argument of division at given path position *) | Adiv0 of path_pos (** value appeared in second argument of division at given path position *)
| Aobjc_null | Aobjc_null
(** 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 *)
| Aretval of Typ.Procname.t * Annot.Item.t | Aretval of Procname.t * Annot.Item.t
(** 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 *)
| Aobserver (** denotes an object registered as an observers to a notification center *) | Aobserver (** denotes an object registered as an observers to a notification center *)
| Aunsubscribed_observer | Aunsubscribed_observer
@ -82,10 +82,10 @@ type t =
val equal : t -> t -> bool val equal : t -> t -> bool
val mem_alloc_pname : mem_kind -> Typ.Procname.t val mem_alloc_pname : mem_kind -> Procname.t
(** name of the allocation function for the given memory kind *) (** name of the allocation function for the given memory kind *)
val mem_dealloc_pname : mem_kind -> Typ.Procname.t val mem_dealloc_pname : mem_kind -> Procname.t
(** name of the deallocation function for the given memory kind *) (** name of the deallocation function for the given memory kind *)
(** Categories of attributes *) (** Categories of attributes *)

@ -60,7 +60,7 @@ type t =
; mutable locals: var_data list (** name, type and attributes of local variables *) ; mutable locals: var_data list (** name, type and attributes of local variables *)
; method_annotation: Annot.Method.t (** annotations for all methods *) ; method_annotation: Annot.Method.t (** annotations for all methods *)
; objc_accessor: objc_accessor_type option (** type of ObjC accessor, if any *) ; objc_accessor: objc_accessor_type option (** type of ObjC accessor, if any *)
; proc_name: Typ.Procname.t (** name of the procedure *) ; proc_name: Procname.t (** name of the procedure *)
; ret_type: Typ.t (** return type *) ; ret_type: Typ.t (** return type *)
; has_added_return_param: bool (** whether or not a return param was added *) } ; has_added_return_param: bool (** whether or not a return param was added *) }
@ -126,8 +126,8 @@ let pp f
let pp_bool_default ~default title b f () = let pp_bool_default ~default title b f () =
if not (Bool.equal default b) then F.fprintf f "; %s= %b@," title b if not (Bool.equal default b) then F.fprintf f "; %s= %b@," title b
in in
F.fprintf f "@[<v>{ proc_name= %a@,; translation_unit= %a@," Typ.Procname.pp proc_name F.fprintf f "@[<v>{ proc_name= %a@,; translation_unit= %a@," Procname.pp proc_name SourceFile.pp
SourceFile.pp translation_unit ; translation_unit ;
if not (PredSymb.equal_access default.access access) then if not (PredSymb.equal_access default.access access) then
F.fprintf f "; access= %a@," (Pp.of_string ~f:PredSymb.string_of_access) access ; F.fprintf f "; access= %a@," (Pp.of_string ~f:PredSymb.string_of_access) access ;
if not ([%compare.equal: (Mangled.t * Typ.t) list] default.captured captured) then if not ([%compare.equal: (Mangled.t * Typ.t) list] default.captured captured) then
@ -173,7 +173,7 @@ let pp f
F.fprintf f "; objc_accessor= %a@," (Pp.option pp_objc_accessor_type) objc_accessor ; F.fprintf f "; objc_accessor= %a@," (Pp.option pp_objc_accessor_type) objc_accessor ;
(* always print ret type *) (* always print ret type *)
F.fprintf f "; ret_type= %a @," (Typ.pp_full Pp.text) ret_type ; F.fprintf f "; ret_type= %a @," (Typ.pp_full Pp.text) ret_type ;
F.fprintf f "; proc_id= %a }@]" Typ.Procname.pp_unique_id proc_name F.fprintf f "; proc_id= %a }@]" Procname.pp_unique_id proc_name
module SQLite = SqliteUtils.MarshalledDataNOTForComparison (struct module SQLite = SqliteUtils.MarshalledDataNOTForComparison (struct

@ -44,11 +44,11 @@ type t =
; mutable locals: var_data list (** name, type and attributes of local variables *) ; mutable locals: var_data list (** name, type and attributes of local variables *)
; method_annotation: Annot.Method.t (** annotations for all methods *) ; method_annotation: Annot.Method.t (** annotations for all methods *)
; objc_accessor: objc_accessor_type option (** type of ObjC accessor, if any *) ; objc_accessor: objc_accessor_type option (** type of ObjC accessor, if any *)
; proc_name: Typ.Procname.t (** name of the procedure *) ; proc_name: Procname.t (** name of the procedure *)
; ret_type: Typ.t (** return type *) ; ret_type: Typ.t (** return type *)
; has_added_return_param: bool (** whether or not a return param was added *) } ; has_added_return_param: bool (** whether or not a return param was added *) }
val default : SourceFile.t -> Typ.Procname.t -> t val default : SourceFile.t -> Procname.t -> t
(** Create a proc_attributes with default values. *) (** Create a proc_attributes with default values. *)
val pp : Format.formatter -> t -> unit val pp : Format.formatter -> t -> unit

@ -132,7 +132,7 @@ module Node = struct
; kind: nodekind (** kind of node *) ; kind: nodekind (** kind of node *)
; loc: Location.t (** location in the source code *) ; loc: Location.t (** location in the source code *)
; mutable preds: t list (** predecessor nodes in the cfg *) ; mutable preds: t list (** predecessor nodes in the cfg *)
; pname: Typ.Procname.t (** name of the procedure the node belongs to *) ; pname: Procname.t (** name of the procedure the node belongs to *)
; mutable succs: t list (** successor nodes in the cfg *) } ; mutable succs: t list (** successor nodes in the cfg *) }
let exn_handler_kind = Stmt_node ExceptionHandler let exn_handler_kind = Stmt_node ExceptionHandler
@ -534,14 +534,14 @@ let fold_instrs pdesc ~init ~f =
let get_static_callees pdesc = let get_static_callees pdesc =
let callees = let callees =
fold_instrs pdesc ~init:Typ.Procname.Set.empty ~f:(fun acc _node instr -> fold_instrs pdesc ~init:Procname.Set.empty ~f:(fun acc _node instr ->
match instr with match instr with
| Sil.Call (_, Exp.Const (Const.Cfun callee_pn), _, _, _) -> | Sil.Call (_, Exp.Const (Const.Cfun callee_pn), _, _, _) ->
Typ.Procname.Set.add callee_pn acc Procname.Set.add callee_pn acc
| _ -> | _ ->
acc ) acc )
in in
Typ.Procname.Set.remove (get_proc_name pdesc) callees |> Typ.Procname.Set.elements Procname.Set.remove (get_proc_name pdesc) callees |> Procname.Set.elements
let find_map_nodes pdesc ~f = List.find_map ~f (get_nodes pdesc) let find_map_nodes pdesc ~f = List.find_map ~f (get_nodes pdesc)
@ -741,7 +741,7 @@ let pp_signature fmt pdesc =
let attributes = get_attributes pdesc in let attributes = get_attributes pdesc in
let pname = get_proc_name pdesc in let pname = get_proc_name pdesc in
let defined_string = match is_defined pdesc with true -> "defined" | false -> "undefined" in let defined_string = match is_defined pdesc with true -> "defined" | false -> "undefined" in
Format.fprintf fmt "@[%a [%s, Return type: %a, %aFormals: %a, Locals: %a" Typ.Procname.pp pname Format.fprintf fmt "@[%a [%s, Return type: %a, %aFormals: %a, Locals: %a" Procname.pp pname
defined_string (Typ.pp_full Pp.text) (get_ret_type pdesc) pp_objc_accessor defined_string (Typ.pp_full Pp.text) (get_ret_type pdesc) pp_objc_accessor
attributes.ProcAttributes.objc_accessor pp_variable_list (get_formals pdesc) pp_locals_list attributes.ProcAttributes.objc_accessor pp_variable_list (get_formals pdesc) pp_locals_list
(get_locals pdesc) ; (get_locals pdesc) ;
@ -749,7 +749,7 @@ let pp_signature fmt pdesc =
Format.fprintf fmt ", Captured: %a" pp_variable_list (get_captured pdesc) ; Format.fprintf fmt ", Captured: %a" pp_variable_list (get_captured pdesc) ;
let method_annotation = attributes.ProcAttributes.method_annotation in let method_annotation = attributes.ProcAttributes.method_annotation in
( if not (Annot.Method.is_empty method_annotation) then ( if not (Annot.Method.is_empty method_annotation) then
let pname_string = Typ.Procname.to_string pname in let pname_string = Procname.to_string pname in
Format.fprintf fmt ", Annotation: %a" (Annot.Method.pp pname_string) method_annotation ) ; Format.fprintf fmt ", Annotation: %a" (Annot.Method.pp pname_string) method_annotation ) ;
Format.fprintf fmt "]@]@;" Format.fprintf fmt "]@]@;"
@ -769,9 +769,9 @@ let is_captured_pvar procdesc pvar =
let pvar_matches (name, _) = Mangled.equal name pvar_name in let pvar_matches (name, _) = Mangled.equal name pvar_name in
let is_captured_var_cpp_lambda = let is_captured_var_cpp_lambda =
match procname with match procname with
| Typ.Procname.ObjC_Cpp cpp_pname -> | Procname.ObjC_Cpp cpp_pname ->
(* var is captured if the procedure is a lambda and the var is not in the locals or formals *) (* var is captured if the procedure is a lambda and the var is not in the locals or formals *)
Typ.Procname.ObjC_Cpp.is_cpp_lambda cpp_pname Procname.ObjC_Cpp.is_cpp_lambda cpp_pname
&& not && not
( List.exists ~f:pvar_local_matches (get_locals procdesc) ( List.exists ~f:pvar_local_matches (get_locals procdesc)
|| List.exists ~f:pvar_matches (get_formals procdesc) ) || List.exists ~f:pvar_matches (get_formals procdesc) )
@ -780,7 +780,7 @@ let is_captured_pvar procdesc pvar =
in in
let is_captured_var_objc_block = let is_captured_var_objc_block =
(* var is captured if the procedure is a objc block and the var is in the captured *) (* var is captured if the procedure is a objc block and the var is in the captured *)
Typ.Procname.is_objc_block procname && List.exists ~f:pvar_matches (get_captured procdesc) Procname.is_objc_block procname && List.exists ~f:pvar_matches (get_captured procdesc)
in in
is_captured_var_cpp_lambda || is_captured_var_objc_block is_captured_var_cpp_lambda || is_captured_var_objc_block
@ -871,8 +871,7 @@ let load_statement =
let load pname = let load pname =
ResultsDatabase.with_registered_statement load_statement ~f:(fun db stmt -> ResultsDatabase.with_registered_statement load_statement ~f:(fun db stmt ->
Typ.Procname.SQLite.serialize pname Procname.SQLite.serialize pname |> Sqlite3.bind stmt 1
|> Sqlite3.bind stmt 1
|> SqliteUtils.check_result_code db ~log:"load bind proc name" ; |> SqliteUtils.check_result_code db ~log:"load bind proc name" ;
SqliteUtils.result_single_column_option ~finalize:false ~log:"Procdesc.load" db stmt SqliteUtils.result_single_column_option ~finalize:false ~log:"Procdesc.load" db stmt
|> Option.bind ~f:SQLite.deserialize ) |> Option.bind ~f:SQLite.deserialize )

@ -117,7 +117,7 @@ module Node : sig
val d_instrs : highlight:Sil.instr option -> t -> unit val d_instrs : highlight:Sil.instr option -> t -> unit
(** Dump instructions for the node, highlighting the given subinstruction if present *) (** Dump instructions for the node, highlighting the given subinstruction if present *)
val dummy : Typ.Procname.t -> t val dummy : Procname.t -> t
(** Create a dummy node *) (** Create a dummy node *)
val equal : t -> t -> bool val equal : t -> t -> bool
@ -156,7 +156,7 @@ module Node : sig
val get_siblings : t -> t Sequence.t val get_siblings : t -> t Sequence.t
(** Get siblings of the current node *) (** Get siblings of the current node *)
val get_proc_name : t -> Typ.Procname.t val get_proc_name : t -> Procname.t
(** Get the name of the procedure the node belongs to *) (** Get the name of the procedure the node belongs to *)
val get_succs : t -> t list val get_succs : t -> t list
@ -245,7 +245,7 @@ val get_nodes : t -> Node.t list
val get_nodes_num : t -> int val get_nodes_num : t -> int
val get_proc_name : t -> Typ.Procname.t val get_proc_name : t -> Procname.t
val get_ret_type : t -> Typ.t val get_ret_type : t -> Typ.t
(** Return the return type of the procedure and type string *) (** Return the return type of the procedure and type string *)
@ -256,7 +256,7 @@ val get_ret_var : t -> Pvar.t
val get_start_node : t -> Node.t val get_start_node : t -> Node.t
val get_static_callees : t -> Typ.Procname.t list val get_static_callees : t -> Procname.t list
(** get a list of unique static callees excluding self *) (** get a list of unique static callees excluding self *)
val is_defined : t -> bool val is_defined : t -> bool
@ -321,4 +321,4 @@ module SQLite : SqliteUtils.Data with type t = t option
(** per-procedure CFGs are stored in the SQLite "procedures" table as NULL if the procedure has no (** per-procedure CFGs are stored in the SQLite "procedures" table as NULL if the procedure has no
CFG *) CFG *)
val load : Typ.Procname.t -> t option val load : Procname.t -> t option

@ -0,0 +1,810 @@
(*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*)
open! IStd
module Hashtbl = Caml.Hashtbl
module F = Format
(** Level of verbosity of some to_string functions. *)
type detail_level = Verbose | Non_verbose | Simple [@@deriving compare, equal]
let is_verbose v = match v with Verbose -> true | _ -> false
module Java = struct
type kind =
| Non_Static
(** in Java, procedures called with invokevirtual, invokespecial, and invokeinterface *)
| Static (** in Java, procedures called with invokestatic *)
[@@deriving compare]
(* TODO: use Mangled.t here *)
type java_type = Typ.Name.Java.Split.t [@@deriving compare]
let java_void = Typ.Name.Java.Split.make "void"
(** Type of java procedure names. *)
type t =
{ method_name: string
; parameters: java_type list
; class_name: Typ.Name.t
; return_type: java_type option (* option because constructors have no return type *)
; kind: kind }
[@@deriving compare]
let make class_name return_type method_name parameters kind =
{class_name; return_type; method_name; parameters; kind}
let pp_type_verbosity verbosity fmt java_type =
Typ.Name.Java.Split.pp_type_verbosity ~verbose:(is_verbose verbosity) fmt java_type
(** Given a list of types, it creates a unique string of types separated by commas *)
let rec pp_param_list verbosity fmt inputList =
match inputList with
| [] ->
()
| [head] ->
pp_type_verbosity verbosity fmt head
| head :: rest ->
pp_type_verbosity verbosity fmt head ;
F.pp_print_string fmt "," ;
pp_param_list verbosity fmt rest
let java_type_of_name class_name = Typ.Name.Java.Split.of_string (Typ.Name.name class_name)
(** It is the same as java_type_to_string_verbosity, but Java return types are optional because of
constructors without type *)
let pp_return_type verbosity fmt j =
match j.return_type with None -> () | Some typ -> pp_type_verbosity verbosity fmt typ
let get_class_name j = Typ.Name.name j.class_name
let get_class_type_name j = j.class_name
let get_simple_class_name j = Typ.Name.Java.Split.(j |> get_class_name |> of_string |> type_name)
let get_package j = Typ.Name.Java.Split.(j |> get_class_name |> of_string |> package)
let get_method j = j.method_name
let replace_method_name method_name j = {j with method_name}
let replace_parameters parameters j = {j with parameters}
let replace_return_type ret_type j = {j with return_type= Some ret_type}
let get_parameters j = j.parameters
(** Prints a string of a java procname with the given level of verbosity *)
let pp ?(withclass = false) verbosity fmt j =
match verbosity with
| 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 pp_class_name verbosity fmt j =
pp_type_verbosity verbosity fmt (Typ.Name.Java.split_typename j.class_name)
in
let separator =
match (j.return_type, verbosity) with None, _ -> "" | Some _, Verbose -> ":" | _ -> " "
in
if not (equal_detail_level verbosity Verbose) then
F.fprintf fmt "%a%s" (pp_return_type verbosity) j separator ;
F.fprintf fmt "%a.%s(%a)" (pp_class_name verbosity) j j.method_name
(pp_param_list verbosity) j.parameters ;
if equal_detail_level verbosity Verbose then
F.fprintf fmt "%s%a" separator (pp_return_type verbosity) j
| Simple ->
(* methodname(...) or without ... if there are no parameters *)
let pp_class_prefix ~withclass verbosity fmt j =
if withclass then
F.fprintf fmt "%a." (pp_type_verbosity verbosity)
(Typ.Name.Java.split_typename j.class_name)
in
let params = match j.parameters with [] -> "" | _ -> "..." in
let pp_method_name ~withclass verbosity fmt j =
if String.equal j.method_name "<init>" then
F.pp_print_string fmt (get_simple_class_name j)
else F.fprintf fmt "%a%s" (pp_class_prefix ~withclass verbosity) j j.method_name
in
F.fprintf fmt "%a(%s)" (pp_method_name ~withclass verbosity) j params
let get_return_typ pname_java =
let rec java_from_string = function
| "" | "void" ->
Typ.void
| "int" ->
Typ.int
| "byte" ->
Typ.java_byte
| "short" ->
Typ.java_short
| "boolean" ->
Typ.boolean
| "char" ->
Typ.char
| "long" ->
Typ.long
| "float" ->
Typ.float
| "double" ->
Typ.double
| typ_str when String.contains typ_str '[' ->
let stripped_typ = String.sub typ_str ~pos:0 ~len:(String.length typ_str - 2) in
Typ.mk (Tptr (Typ.mk_array (java_from_string stripped_typ), Pk_pointer))
| typ_str ->
Typ.mk (Tstruct (Typ.Name.Java.from_string typ_str))
in
let typ = java_from_string (F.asprintf "%a" (pp_return_type Verbose) pname_java) in
match typ.desc with Tstruct _ -> Typ.mk (Tptr (typ, Pk_pointer)) | _ -> typ
let is_close {method_name} = String.equal method_name "close"
let constructor_method_name = "<init>"
let class_initializer_method_name = "<clinit>"
let is_class_initializer {method_name} = String.equal method_name class_initializer_method_name
let get_class_initializer class_name =
{ method_name= class_initializer_method_name
; parameters= []
; class_name
; return_type= Some java_void
; kind= Static }
let is_constructor {method_name} = String.equal method_name constructor_method_name
let is_anonymous_inner_class_constructor {class_name} =
Typ.Name.Java.is_anonymous_inner_class_name class_name
let is_static {kind} = match kind with Static -> true | _ -> false
let is_lambda {method_name} = String.is_prefix ~prefix:"lambda$" method_name
let is_generated {method_name} = String.is_prefix ~prefix:"$" method_name
let is_access_method {method_name} =
match String.rsplit2 method_name ~on:'$' with
| Some ("access", s) ->
let is_int =
try
ignore (int_of_string s) ;
true
with Failure _ -> false
in
is_int
| _ ->
false
let is_autogen_method {method_name} = String.contains method_name '$'
(** Check if the proc name has the type of a java vararg. Note: currently only checks that the
last argument has type Object[]. *)
let is_vararg {parameters} =
(* FIXME this looks wrong due to the dot in the type name *)
List.last parameters
|> Option.exists ~f:(fun java_type ->
String.equal "java.lang.Object[]" (Typ.Name.Java.Split.type_name java_type) )
let is_external java_pname =
let package = get_package java_pname in
Option.exists ~f:Config.java_package_is_external package
end
module Parameter = struct
(** Type for parameters in clang procnames, [Some name] means the parameter is of type pointer to
struct, with [name] being the name of the struct, [None] means the parameter is of some other
type. *)
type clang_parameter = Typ.Name.t option [@@deriving compare]
(** Type for parameters in procnames, for java and clang. *)
type t = JavaParameter of Java.java_type | ClangParameter of clang_parameter
[@@deriving compare]
let of_typ typ =
match typ.Typ.desc with Typ.Tptr ({desc= Tstruct name}, Pk_pointer) -> Some name | _ -> None
let pp_parameters fmt parameters =
if List.exists ~f:Option.is_some parameters then
(* the tests rely on the fact that we discard non-pointer-to-struct types for some reason,
hence the slight re-implementation of [Pp.seq] to avoid building the list of [Some] items
explicitly *)
let rec pp_parameters_aux fmt = function
| [] ->
()
| [Some param] ->
F.pp_print_string fmt (Typ.Name.to_string param)
| None :: parameters ->
pp_parameters_aux fmt parameters
| (Some _ as param_some) :: None :: parameters ->
pp_parameters_aux fmt (param_some :: parameters)
| Some param :: (Some _ :: _ as parameters) ->
F.fprintf fmt "%s," (Typ.Name.to_string param) ;
pp_parameters_aux fmt parameters
in
F.fprintf fmt "(%a)" pp_parameters_aux parameters
let clang_param_of_name class_name : clang_parameter = Some class_name
end
module ObjC_Cpp = struct
type kind =
| CPPMethod of {mangled: string option}
| CPPConstructor of {mangled: string option; is_constexpr: bool}
| CPPDestructor of {mangled: string option}
| ObjCClassMethod
| ObjCInstanceMethod
| ObjCInternalMethod
[@@deriving compare]
type t =
{ class_name: Typ.Name.t
; kind: kind
; method_name: string
; parameters: Parameter.clang_parameter list
; template_args: Typ.template_spec_info }
[@@deriving compare]
let make class_name method_name kind template_args parameters =
{class_name; method_name; kind; template_args; parameters}
let get_class_name objc_cpp = Typ.Name.name objc_cpp.class_name
let get_class_type_name objc_cpp = objc_cpp.class_name
let get_class_qualifiers objc_cpp = Typ.Name.qual_name objc_cpp.class_name
let objc_method_kind_of_bool is_instance =
if is_instance then ObjCInstanceMethod else ObjCClassMethod
let is_objc_constructor method_name =
String.equal method_name "new" || String.is_prefix ~prefix:"init" method_name
let is_objc_kind = function
| ObjCClassMethod | ObjCInstanceMethod | ObjCInternalMethod ->
true
| _ ->
false
let is_objc_method {kind} = is_objc_kind kind
let is_objc_dealloc method_name = String.equal method_name "dealloc"
let is_destructor = function
| {kind= CPPDestructor _} ->
true
| name ->
is_objc_dealloc name.method_name
let is_inner_destructor ({method_name} as pname) =
is_destructor pname && String.is_prefix ~prefix:Config.clang_inner_destructor_prefix method_name
let is_constexpr = function {kind= CPPConstructor {is_constexpr= true}} -> true | _ -> false
let is_cpp_lambda {method_name} = String.is_substring ~substring:"operator()" method_name
let pp_verbose_kind fmt = function
| CPPMethod {mangled} | CPPDestructor {mangled} ->
F.fprintf fmt "(%s)" (Option.value ~default:"" mangled)
| CPPConstructor {mangled; is_constexpr} ->
F.fprintf fmt "{%s%s}"
(Option.value ~default:"" mangled)
(if is_constexpr then "|constexpr" else "")
| ObjCClassMethod ->
F.pp_print_string fmt "class"
| ObjCInstanceMethod ->
F.pp_print_string fmt "instance"
| ObjCInternalMethod ->
F.pp_print_string fmt "internal"
let pp verbosity fmt osig =
match verbosity with
| Simple ->
F.pp_print_string fmt osig.method_name
| Non_verbose ->
F.fprintf fmt "%s::%s" (Typ.Name.name osig.class_name) osig.method_name
| Verbose ->
F.fprintf fmt "%s::%s%a%a" (Typ.Name.name osig.class_name) osig.method_name
Parameter.pp_parameters osig.parameters pp_verbose_kind osig.kind
let get_parameters osig = osig.parameters
let replace_parameters new_parameters osig = {osig with parameters= new_parameters}
end
module C = struct
(** Type of c procedure names. *)
type t =
{ name: QualifiedCppName.t
; mangled: string option
; parameters: Parameter.clang_parameter list
; template_args: Typ.template_spec_info }
[@@deriving compare]
let c name mangled parameters template_args =
{name; mangled= Some mangled; parameters; template_args}
let from_string name =
{ name= QualifiedCppName.of_qual_string name
; mangled= None
; parameters= []
; template_args= NoTemplate }
let pp verbosity fmt {name; mangled; parameters} =
let plain = QualifiedCppName.to_qual_string name in
match verbosity with
| Simple ->
F.fprintf fmt "%s()" plain
| Non_verbose ->
F.pp_print_string fmt plain
| Verbose ->
let pp_mangled fmt = function None -> () | Some s -> F.fprintf fmt "{%s}" s in
F.fprintf fmt "%s%a%a" plain Parameter.pp_parameters parameters pp_mangled mangled
let get_parameters c = c.parameters
let replace_parameters new_parameters c = {c with parameters= new_parameters}
end
module Block = struct
(** Type of Objective C block names. *)
type block_name = string [@@deriving compare]
type t = {name: block_name; parameters: Parameter.clang_parameter list} [@@deriving compare]
let make name parameters = {name; parameters}
let pp verbosity fmt bsig =
match verbosity with
| Simple ->
F.pp_print_string fmt "block"
| Non_verbose ->
F.pp_print_string fmt bsig.name
| Verbose ->
F.fprintf fmt "%s%a" bsig.name Parameter.pp_parameters bsig.parameters
let get_parameters block = block.parameters
let replace_parameters new_parameters block = {block with parameters= new_parameters}
end
(** Type of procedure names. *)
type t =
| Java of Java.t
| C of C.t
| Linters_dummy_method
| Block of Block.t
| ObjC_Cpp of ObjC_Cpp.t
| WithBlockParameters of t * Block.block_name list
[@@deriving compare]
let equal = [%compare.equal: t]
(** hash function for procname *)
let hash = Hashtbl.hash
let with_block_parameters base blocks = WithBlockParameters (base, blocks)
let is_java = function Java _ -> true | _ -> false
(* TODO: deprecate this unfortunately named function and use is_clang instead *)
let is_c_method = function ObjC_Cpp _ -> true | _ -> false
let is_c_function = function C _ -> true | _ -> false
let is_clang = function ObjC_Cpp name -> ObjC_Cpp.is_objc_method name | name -> is_c_function name
let is_java_lift f = function Java java_pname -> f java_pname | _ -> false
let is_java_access_method = is_java_lift Java.is_access_method
let is_java_class_initializer = is_java_lift Java.is_class_initializer
let is_objc_method procname =
match procname with ObjC_Cpp name -> ObjC_Cpp.is_objc_method name | _ -> false
let block_name_of_procname procname =
match procname with
| Block block ->
block.name
| _ ->
Logging.die InternalError "Only to be called with Objective-C block names"
let empty_block = Block {name= ""; parameters= []}
(** Replace the class name component of a procedure name. In case of Java, replace package and class
name. *)
let rec replace_class t (new_class : Typ.Name.t) =
match t with
| Java j ->
Java {j with class_name= new_class}
| ObjC_Cpp osig ->
ObjC_Cpp {osig with class_name= new_class}
| WithBlockParameters (base, blocks) ->
WithBlockParameters (replace_class base new_class, blocks)
| C _ | Block _ | Linters_dummy_method ->
t
let get_class_type_name = function
| Java java_pname ->
Some (Java.get_class_type_name java_pname)
| ObjC_Cpp objc_pname ->
Some (ObjC_Cpp.get_class_type_name objc_pname)
| _ ->
None
let get_class_name = function
| Java java_pname ->
Some (Java.get_class_name java_pname)
| ObjC_Cpp objc_pname ->
Some (ObjC_Cpp.get_class_name objc_pname)
| _ ->
None
let is_method_in_objc_protocol t =
match t with ObjC_Cpp osig -> Typ.Name.is_objc_protocol osig.class_name | _ -> false
let rec objc_cpp_replace_method_name t (new_method_name : string) =
match t with
| ObjC_Cpp osig ->
ObjC_Cpp {osig with method_name= new_method_name}
| WithBlockParameters (base, blocks) ->
WithBlockParameters (objc_cpp_replace_method_name base new_method_name, blocks)
| C _ | Block _ | Linters_dummy_method | Java _ ->
t
(** Return the method/function of a procname. *)
let rec get_method = function
| ObjC_Cpp name ->
name.method_name
| WithBlockParameters (base, _) ->
get_method base
| C {name} ->
QualifiedCppName.to_qual_string name
| Block {name} ->
name
| Java j ->
j.method_name
| Linters_dummy_method ->
"Linters_dummy_method"
(** Return whether the procname is a block procname. *)
let is_objc_block = function Block _ -> true | _ -> false
(** Return the language of the procedure. *)
let get_language = function
| ObjC_Cpp _ ->
Language.Clang
| C _ ->
Language.Clang
| Block _ ->
Language.Clang
| Linters_dummy_method ->
Language.Clang
| WithBlockParameters _ ->
Language.Clang
| Java _ ->
Language.Java
(** [is_constructor pname] returns true if [pname] is a constructor *)
let is_constructor = function
| Java js ->
String.equal js.method_name Java.constructor_method_name
| ObjC_Cpp {kind= CPPConstructor _} ->
true
| ObjC_Cpp {kind; method_name} when ObjC_Cpp.is_objc_kind kind ->
ObjC_Cpp.is_objc_constructor method_name
| _ ->
false
(** [is_infer_undefined pn] returns true if [pn] is a special Infer undefined proc *)
let is_infer_undefined pn =
match pn with
| Java j ->
let regexp = Str.regexp_string "com.facebook.infer.builtins.InferUndefined" in
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 = function
| C {name}
when String.is_prefix ~prefix:Config.clang_initializer_prefix
(QualifiedCppName.to_qual_string name) ->
let name_str = QualifiedCppName.to_qual_string name in
let prefix_len = String.length Config.clang_initializer_prefix in
Some (String.sub name_str ~pos:prefix_len ~len:(String.length name_str - prefix_len))
| _ ->
None
(** Very verbose representation of an existing Procname.t *)
let rec pp_unique_id fmt = function
| Java j ->
Java.pp Verbose fmt j
| C osig ->
C.pp Verbose fmt osig
| ObjC_Cpp osig ->
ObjC_Cpp.pp Verbose fmt osig
| Block bsig ->
Block.pp Verbose fmt bsig
| WithBlockParameters (base, []) ->
pp_unique_id fmt base
| WithBlockParameters (base, (_ :: _ as blocks)) ->
pp_unique_id fmt base ;
F.pp_print_string fmt "_" ;
Pp.seq ~sep:"_" F.pp_print_string fmt blocks
| Linters_dummy_method ->
F.pp_print_string fmt "Linters_dummy_method"
let to_unique_id proc_name = F.asprintf "%a" pp_unique_id proc_name
(** Convert a proc name to a string for the user to see *)
let rec pp fmt = function
| Java j ->
Java.pp Non_verbose fmt j
| C osig ->
C.pp Non_verbose fmt osig
| ObjC_Cpp osig ->
ObjC_Cpp.pp Non_verbose fmt osig
| Block bsig ->
Block.pp Non_verbose fmt bsig
| WithBlockParameters (base, []) ->
pp fmt base
| WithBlockParameters (base, (_ :: _ as blocks)) ->
pp fmt base ;
F.pp_print_string fmt "_" ;
Pp.seq ~sep:"_" F.pp_print_string fmt blocks
| Linters_dummy_method ->
pp_unique_id fmt Linters_dummy_method
let to_string proc_name = F.asprintf "%a" pp proc_name
(** Convenient representation of a procname for external tools (e.g. eclipse plugin) *)
let rec pp_simplified_string ?(withclass = false) fmt = function
| Java j ->
Java.pp ~withclass Simple fmt j
| C osig ->
C.pp Simple fmt osig
| ObjC_Cpp osig ->
ObjC_Cpp.pp Simple fmt osig
| Block bsig ->
Block.pp Simple fmt bsig
| WithBlockParameters (base, _) ->
pp_simplified_string fmt base
| Linters_dummy_method ->
pp_unique_id fmt Linters_dummy_method
let to_simplified_string ?withclass proc_name =
F.asprintf "%a" (pp_simplified_string ?withclass) proc_name
let from_string_c_fun func = C (C.from_string func)
let java_inner_class_prefix_regex = Str.regexp "\\$[0-9]+"
let hashable_name proc_name =
match proc_name with
| Java pname -> (
(* Strip autogenerated anonymous inner class numbers in order to keep the bug hash
invariant when introducing new anonymous classes *)
let name = F.asprintf "%a" (Java.pp ~withclass:true Simple) pname in
match Str.search_forward java_inner_class_prefix_regex name 0 with
| _ ->
Str.global_replace java_inner_class_prefix_regex "$_" name
| exception Caml.Not_found ->
name )
| ObjC_Cpp m when ObjC_Cpp.is_objc_method m ->
(* In Objective C, the list of parameters is part of the method name. To prevent the bug
hash to change when a parameter is introduced or removed, only the part of the name
before the first colon is used for the bug hash *)
let name = F.asprintf "%a" (pp_simplified_string ~withclass:true) proc_name in
List.hd_exn (String.split_on_chars name ~on:[':'])
| _ ->
(* Other cases for C and C++ method names *)
F.asprintf "%a" (pp_simplified_string ~withclass:true) proc_name
let rec get_parameters procname =
let clang_param_to_param clang_params =
List.map ~f:(fun par -> Parameter.ClangParameter par) clang_params
in
match procname with
| Java j ->
List.map ~f:(fun par -> Parameter.JavaParameter par) (Java.get_parameters j)
| C osig ->
clang_param_to_param (C.get_parameters osig)
| ObjC_Cpp osig ->
clang_param_to_param (ObjC_Cpp.get_parameters osig)
| Block bsig ->
clang_param_to_param (Block.get_parameters bsig)
| WithBlockParameters (base, _) ->
get_parameters base
| Linters_dummy_method ->
[]
let rec replace_parameters new_parameters procname =
let params_to_java_params params =
List.map
~f:(fun param ->
match param with
| Parameter.JavaParameter par ->
par
| _ ->
Logging.(die InternalError)
"Expected Java parameters in Java procname, but got Clang parameters" params )
params
in
let params_to_clang_params params =
List.map
~f:(fun param ->
match param with
| Parameter.ClangParameter par ->
par
| _ ->
Logging.(die InternalError)
"Expected Clang parameters in Clang procname, but got Java parameters" params )
params
in
match procname with
| Java j ->
Java (Java.replace_parameters (params_to_java_params new_parameters) j)
| C osig ->
C (C.replace_parameters (params_to_clang_params new_parameters) osig)
| ObjC_Cpp osig ->
ObjC_Cpp (ObjC_Cpp.replace_parameters (params_to_clang_params new_parameters) osig)
| Block bsig ->
Block (Block.replace_parameters (params_to_clang_params new_parameters) bsig)
| WithBlockParameters (base, blocks) ->
WithBlockParameters (replace_parameters new_parameters base, blocks)
| Linters_dummy_method ->
procname
let parameter_of_name procname class_name =
match procname with
| Java _ ->
Parameter.JavaParameter (Java.java_type_of_name class_name)
| _ ->
Parameter.ClangParameter (Parameter.clang_param_of_name class_name)
let describe f pn =
let name = hashable_name pn in
match String.lsplit2 ~on:'<' name with
| Some (name_without_template, _template_part) ->
F.pp_print_string f name_without_template
| None ->
F.pp_print_string f name
module Hashable = struct
type nonrec t = t
let equal = equal
let hash = hash
end
module Hash = Hashtbl.Make (Hashable)
module Map = PrettyPrintable.MakePPMap (struct
type nonrec t = t
let compare = compare
let pp = pp
end)
module Set = PrettyPrintable.MakePPSet (struct
type nonrec t = t
let compare = compare
let pp = pp
end)
let get_qualifiers pname =
match pname with
| C {name} ->
name
| ObjC_Cpp objc_cpp ->
ObjC_Cpp.get_class_qualifiers objc_cpp
|> QualifiedCppName.append_qualifier ~qual:objc_cpp.method_name
| _ ->
QualifiedCppName.empty
(** Convert a proc name to a filename *)
let to_filename ?crc_only pname =
(* filenames for clang procs are REVERSED qualifiers with '#' as separator *)
let pp_rev_qualified fmt pname =
let rev_qualifiers = get_qualifiers pname |> QualifiedCppName.to_rev_list in
Pp.seq ~sep:"#" F.pp_print_string fmt rev_qualifiers
in
let proc_id =
match pname with
| C {parameters; mangled} ->
let pp_mangled fmt = function None -> () | Some mangled -> F.fprintf fmt "#%s" mangled in
F.asprintf "%a%a%a" pp_rev_qualified pname Parameter.pp_parameters parameters pp_mangled
mangled
| ObjC_Cpp objc_cpp ->
F.asprintf "%a%a#%a" pp_rev_qualified pname Parameter.pp_parameters objc_cpp.parameters
ObjC_Cpp.pp_verbose_kind objc_cpp.kind
| _ ->
F.asprintf "%a" pp_unique_id pname
in
Escape.escape_filename @@ DB.append_crc_cutoff ?crc_only proc_id
module SQLite = struct
module T = struct
type nonrec t = t
let compare = compare
let hash = hash
let sexp_of_t p = Sexp.Atom (F.asprintf "%a" pp p)
end
module Serializer = SqliteUtils.MarshalledDataForComparison (T)
let pname_to_key = Base.Hashtbl.create (module T)
let serialize pname =
let default () = Serializer.serialize pname in
Base.Hashtbl.find_or_add pname_to_key pname ~default
let deserialize = Serializer.deserialize
let clear_cache () = Base.Hashtbl.clear pname_to_key
end
module SQLiteList = SqliteUtils.MarshalledDataNOTForComparison (struct
type nonrec t = t list
end)

@ -0,0 +1,316 @@
(*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*)
open! IStd
module F = Format
(** Module for Procedure Names. *)
(** Type of java procedure names. *)
module Java : sig
type kind =
| Non_Static
(** in Java, procedures called with invokevirtual, invokespecial, and invokeinterface *)
| Static (** in Java, procedures called with invokestatic *)
type t [@@deriving compare]
type java_type = Typ.Name.Java.Split.t
val constructor_method_name : string
val class_initializer_method_name : string
val compare_java_type : java_type -> java_type -> int
val make : Typ.Name.t -> java_type option -> string -> java_type list -> kind -> t
(** Create a Java procedure name from its class_name method_name args_type_name return_type_name
method_kind. *)
val replace_method_name : string -> t -> t
(** Replace the method name of an existing java procname. *)
val replace_parameters : java_type list -> t -> t
(** Replace the parameters of a java procname. *)
val replace_return_type : java_type -> t -> t
(** Replace the method of a java procname. *)
val get_class_name : t -> string
(** Return the fully qualified class name of a java procedure name (package + class name) *)
val get_class_type_name : t -> Typ.Name.t
(** Return the class name as a typename of a java procedure name. *)
val get_simple_class_name : t -> string
(** Return the simple class name of a java procedure name (i.e. name without the package info). *)
val get_package : t -> string option
(** Return the package name of a java procedure name. *)
val get_method : t -> string
(** Return the method name of a java procedure name. *)
val get_parameters : t -> java_type list
(** Return the parameters of a java procedure name. *)
val get_return_typ : t -> Typ.t
(** Return the return type of [pname_java]. return Tvoid if there's no return type *)
val is_constructor : t -> bool
(** Whether the method is constructor *)
val is_access_method : t -> bool
(** Check if the procedure name is an acess method (e.g. access$100 used to access private members
from a nested class. *)
val is_autogen_method : t -> bool
(** Check if the procedure name is of an auto-generated method containing '$'. *)
val is_anonymous_inner_class_constructor : t -> bool
(** Check if the procedure name is an anonymous inner class constructor. *)
val is_close : t -> bool
(** Check if the method name is "close". *)
val is_static : t -> bool
(** Check if the java procedure is static. *)
val is_vararg : 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[]. *)
val is_lambda : t -> bool
(** Check if the proc name comes from a lambda expression *)
val is_generated : t -> bool
(** Check if the proc name comes from generated code *)
val is_class_initializer : t -> bool
(** Check if this is a class initializer. *)
val get_class_initializer : Typ.Name.t -> t
(** Given a java class, generate the procname of its static initializer. *)
val is_external : t -> bool
(** Check if the method belongs to one of the specified external packages *)
end
module Parameter : sig
(** Type for parameters in clang procnames, [Some name] means the parameter is of type pointer to
struct, with [name] being the name of the struct, [None] means the parameter is of some other
type. *)
type clang_parameter = Typ.Name.t option [@@deriving compare]
(** Type for parameters in procnames, for java and clang. *)
type t = JavaParameter of Java.java_type | ClangParameter of clang_parameter
[@@deriving compare]
val of_typ : Typ.t -> clang_parameter
end
module ObjC_Cpp : sig
type kind =
| CPPMethod of {mangled: string option}
| CPPConstructor of {mangled: string option; is_constexpr: bool}
| CPPDestructor of {mangled: string option}
| ObjCClassMethod
| ObjCInstanceMethod
| ObjCInternalMethod
[@@deriving compare]
(** Type of Objective C and C++ procedure names: method signatures. *)
type t =
{ class_name: Typ.Name.t
; kind: kind
; method_name: string
; parameters: Parameter.clang_parameter list
; template_args: Typ.template_spec_info }
[@@deriving compare]
val make :
Typ.Name.t -> string -> kind -> Typ.template_spec_info -> Parameter.clang_parameter list -> t
(** Create an objc procedure name from a class_name and method_name. *)
val get_class_name : t -> string
val get_class_type_name : t -> Typ.Name.t [@@warning "-32"]
val get_class_qualifiers : t -> QualifiedCppName.t
val objc_method_kind_of_bool : bool -> kind
(** Create ObjC method type from a bool is_instance. *)
val is_objc_constructor : string -> bool
(** Check if this is a constructor method in Objective-C. *)
val is_objc_dealloc : string -> bool
(** Check if this is a dealloc method in Objective-C. *)
val is_destructor : t -> bool
(** Check if this is a dealloc method. *)
val is_inner_destructor : t -> bool
(** Check if this is a frontend-generated "inner" destructor (see D5834555/D7189239) *)
val is_constexpr : t -> bool
(** Check if this is a constexpr function. *)
val is_cpp_lambda : t -> bool
(** Return whether the procname is a cpp lambda. *)
end
module C : sig
(** Type of c procedure names. *)
type t = private
{ name: QualifiedCppName.t
; mangled: string option
; parameters: Parameter.clang_parameter list
; template_args: Typ.template_spec_info }
val c :
QualifiedCppName.t -> string -> Parameter.clang_parameter list -> Typ.template_spec_info -> t
(** Create a C procedure name from plain and mangled name. *)
end
module Block : sig
(** Type of Objective C block names. *)
type block_name = string
type t = {name: block_name; parameters: Parameter.clang_parameter list} [@@deriving compare]
val make : block_name -> Parameter.clang_parameter list -> t
end
(** Type of procedure names. WithBlockParameters is used for creating an instantiation of a method
that contains block parameters and it's called with concrete blocks. For example:
[foo(Block block) {block();}] [bar() {foo(my_block)}] is executed as
[foo_my_block() {my_block(); }] where foo_my_block is created with WithBlockParameters (foo,
[my_block]) *)
type t =
| Java of Java.t
| C of C.t
| Linters_dummy_method
| Block of Block.t
| ObjC_Cpp of ObjC_Cpp.t
| WithBlockParameters of t * Block.block_name list
[@@deriving compare]
val block_name_of_procname : t -> Block.block_name
val equal : t -> t -> bool
val get_class_type_name : t -> Typ.Name.t option
val get_class_name : t -> string option
val get_parameters : t -> Parameter.t list
val replace_parameters : Parameter.t list -> t -> t
val parameter_of_name : t -> Typ.Name.t -> Parameter.t
val is_java_access_method : t -> bool
val is_java_class_initializer : t -> bool
val is_objc_method : t -> bool
module Hash : Caml.Hashtbl.S with type key = t
(** Hash tables with proc names as keys. *)
module Map : PrettyPrintable.PPMap with type key = t
(** Maps from proc names. *)
module Set : PrettyPrintable.PPSet with type elt = t
(** Sets of proc names. *)
module SQLite : sig
val serialize : t -> Sqlite3.Data.t
val deserialize : Sqlite3.Data.t -> t
val clear_cache : unit -> unit
end
module SQLiteList : SqliteUtils.Data with type t = t list
val empty_block : t
(** Empty block name. *)
val get_language : t -> Language.t
(** Return the language of the procedure. *)
val get_method : t -> string
(** Return the method/function of a procname. *)
val is_objc_block : t -> bool
(** Return whether the procname is a block procname. *)
val is_c_method : t -> bool
(** Return true this is an Objective-C/C++ method name. *)
val is_clang : t -> bool
(** Return true if this is a C, C++, or Objective-C procedure name *)
val is_constructor : t -> bool
(** Check if this is a constructor. *)
val is_java : t -> bool
(** Check if this is a Java procedure name. *)
val with_block_parameters : t -> Block.block_name list -> t
(** Create a procedure name instantiated with block parameters from a base procedure name and a list
of block procedure names (the arguments). *)
val objc_cpp_replace_method_name : t -> string -> t
val is_infer_undefined : t -> bool
(** Check if this is a special Infer undefined procedure. *)
val get_global_name_of_initializer : t -> string option
(** Return the name of the global for which this procedure is the initializer if this is an
initializer, None otherwise. *)
val pp : Format.formatter -> t -> unit
(** Pretty print a proc name for the user to see. *)
val to_string : t -> string
(** Convert a proc name into a string for the user to see. *)
val describe : Format.formatter -> t -> unit
(** to use in user messages *)
val replace_class : t -> Typ.Name.t -> t
(** Replace the class name component of a procedure name. In case of Java, replace package and class
name. *)
val is_method_in_objc_protocol : t -> bool
val pp_simplified_string : ?withclass:bool -> F.formatter -> t -> unit
(** Pretty print a proc name as an easy string for the user to see in an IDE. *)
val to_simplified_string : ?withclass:bool -> t -> string
(** Convert a proc name into an easy string for the user to see in an IDE. *)
val from_string_c_fun : string -> t
(** Convert a string to a c function name. *)
val hashable_name : t -> string
(** Convert the procedure name in a format suitable for computing the bug hash. *)
val pp_unique_id : F.formatter -> t -> unit
(** Print a proc name as a unique identifier. *)
val to_unique_id : t -> string
(** Convert a proc name into a unique identifier. *)
val to_filename : ?crc_only:bool -> t -> string
(** Convert a proc name to a filename or only to its crc. *)
val get_qualifiers : t -> QualifiedCppName.t
(** get qualifiers of C/objc/C++ method/function *)

@ -21,11 +21,11 @@ and non_empty
type typ = Typ.t type typ = Typ.t
type c = Typ.Procname.C.t type c = Procname.C.t
type objc_cpp = Typ.Procname.ObjC_Cpp.t type objc_cpp = Procname.ObjC_Cpp.t
type java = Typ.Procname.Java.t type java = Procname.Java.t
type qual_name = QualifiedCppName.t type qual_name = QualifiedCppName.t
@ -53,8 +53,7 @@ let templated_name_of_class_name class_name =
let templated_name_of_java java = let templated_name_of_java java =
let qual_name = let qual_name =
QualifiedCppName.of_list QualifiedCppName.of_list [Procname.Java.get_class_name java; Procname.Java.get_method java]
[Typ.Procname.Java.get_class_name java; Typ.Procname.Java.get_method java]
in in
(qual_name, []) (qual_name, [])
@ -117,7 +116,7 @@ let name_cons :
| _ -> | _ ->
None None
in in
let on_objc_cpp context f (objc_cpp : Typ.Procname.ObjC_Cpp.t) = let on_objc_cpp context f (objc_cpp : Procname.ObjC_Cpp.t) =
if match_fuzzy_name objc_cpp.method_name then if match_fuzzy_name objc_cpp.method_name then
on_templated_name context f (templated_name_of_class_name objc_cpp.class_name) on_templated_name context f (templated_name_of_class_name objc_cpp.class_name)
else None else None
@ -138,7 +137,7 @@ let name_cons_f :
| _ -> | _ ->
None None
in in
let on_objc_cpp context f (objc_cpp : Typ.Procname.ObjC_Cpp.t) = let on_objc_cpp context f (objc_cpp : Procname.ObjC_Cpp.t) =
if f_name context objc_cpp.method_name then if f_name context objc_cpp.method_name then
on_templated_name context f (templated_name_of_class_name objc_cpp.class_name) on_templated_name context f (templated_name_of_class_name objc_cpp.class_name)
else None else None
@ -164,7 +163,7 @@ let all_names_cons :
on_templated_name_rec context f (rest, []) ) on_templated_name_rec context f (rest, []) )
in in
let on_templated_name = on_templated_name_rec in let on_templated_name = on_templated_name_rec in
let on_objc_cpp context f (objc_cpp : Typ.Procname.ObjC_Cpp.t) = let on_objc_cpp context f (objc_cpp : Procname.ObjC_Cpp.t) =
match on_objc_cpp context f objc_cpp with match on_objc_cpp context f objc_cpp with
| Some _ as some -> | Some _ as some ->
some some
@ -182,7 +181,7 @@ let templ_begin :
let on_templated_name context f (qual_name, template_args) = let on_templated_name context f (qual_name, template_args) =
match on_qual_name context f qual_name with None -> None | Some f -> Some (f, template_args) match on_qual_name context f qual_name with None -> None | Some f -> Some (f, template_args)
in in
let on_objc_cpp context f (objc_cpp : Typ.Procname.ObjC_Cpp.t) = let on_objc_cpp context f (objc_cpp : Procname.ObjC_Cpp.t) =
match on_objc_cpp context f objc_cpp with match on_objc_cpp context f objc_cpp with
| None -> | None ->
None None
@ -468,7 +467,7 @@ module Call = struct
-> ('context, 'f_out, 'arg_payload) pre_result } -> ('context, 'f_out, 'arg_payload) pre_result }
type ('context, 'f, 'arg_payload) dispatcher = type ('context, 'f, 'arg_payload) dispatcher =
'context -> Typ.Procname.t -> 'arg_payload FuncArg.t list -> 'f option 'context -> Procname.t -> 'arg_payload FuncArg.t list -> 'f option
let args_begin : let args_begin :
('context, 'f_in, 'f_out, non_empty, 'arg_payload) path_matcher ('context, 'f_in, 'f_out, non_empty, 'arg_payload) path_matcher
@ -785,8 +784,7 @@ module Call = struct
let wrong_args_internal_error : _ matcher = let wrong_args_internal_error : _ matcher =
let on_procname procname = let on_procname procname =
Logging.(die InternalError) Logging.(die InternalError) "Unexpected number/types of arguments for %a" Procname.pp procname
"Unexpected number/types of arguments for %a" Typ.Procname.pp procname
in in
let on_c _context c _args = on_procname (C c) in let on_c _context c _args = on_procname (C c) in
let on_java _context java _args = on_procname (Java java) in let on_java _context java _args = on_procname (Java java) in
@ -907,7 +905,7 @@ end
module ProcName = struct module ProcName = struct
include NameCommon include NameCommon
type ('context, 'f, 'arg_payload) dispatcher = 'context -> Typ.Procname.t -> 'f option type ('context, 'f, 'arg_payload) dispatcher = 'context -> Procname.t -> 'f option
let make_dispatcher : let make_dispatcher :
('context, 'f, 'arg_payload) matcher list -> ('context, 'f, 'arg_payload) dispatcher = ('context, 'f, 'arg_payload) matcher list -> ('context, 'f, 'arg_payload) dispatcher =
@ -919,7 +917,7 @@ module ProcName = struct
List.find_map matchers ~f:(fun (matcher : _ matcher) -> List.find_map matchers ~f:(fun (matcher : _ matcher) ->
matcher.on_templated_name context templated_name ) matcher.on_templated_name context templated_name )
in in
let on_java context (java : Typ.Procname.Java.t) = let on_java context (java : Procname.Java.t) =
let templated_name = templated_name_of_java java in let templated_name = templated_name_of_java java in
on_templated_name context templated_name on_templated_name context templated_name
in in

@ -141,8 +141,7 @@ module type NameCommon = sig
end end
module ProcName : module ProcName :
NameCommon NameCommon with type ('context, 'f, 'arg_payload) dispatcher = 'context -> Procname.t -> 'f option
with type ('context, 'f, 'arg_payload) dispatcher = 'context -> Typ.Procname.t -> 'f option
module TypName : module TypName :
NameCommon with type ('context, 'f, 'arg_payload) dispatcher = 'context -> Typ.name -> 'f option NameCommon with type ('context, 'f, 'arg_payload) dispatcher = 'context -> Typ.name -> 'f option
@ -156,7 +155,7 @@ module Call : sig
include include
Common Common
with type ('context, 'f, 'arg_payload) dispatcher = with type ('context, 'f, 'arg_payload) dispatcher =
'context -> Typ.Procname.t -> 'arg_payload FuncArg.t list -> 'f option 'context -> Procname.t -> 'arg_payload FuncArg.t list -> 'f option
val merge_dispatchers : val merge_dispatchers :
('context, 'f, 'arg_payload) dispatcher ('context, 'f, 'arg_payload) dispatcher

@ -16,11 +16,10 @@ type translation_unit = SourceFile.t option [@@deriving compare]
(** Kind of global variables *) (** Kind of global variables *)
type pvar_kind = type pvar_kind =
| Local_var of Typ.Procname.t (** local variable belonging to a function *) | Local_var of Procname.t (** local variable belonging to a function *)
| Callee_var of Typ.Procname.t (** local variable belonging to a callee *) | Callee_var of Procname.t (** local variable belonging to a callee *)
| Abduced_retvar of Typ.Procname.t * Location.t | Abduced_retvar of Procname.t * Location.t (** synthetic variable to represent return value *)
(** synthetic variable to represent return value *) | Abduced_ref_param of Procname.t * int * Location.t
| Abduced_ref_param of Typ.Procname.t * int * Location.t
(** synthetic variable to represent param passed by reference *) (** synthetic variable to represent param passed by reference *)
| Global_var of | Global_var of
{ translation_unit: translation_unit { translation_unit: translation_unit
@ -38,7 +37,7 @@ type t = {pv_hash: int; pv_name: Mangled.t; pv_kind: pvar_kind} [@@deriving comp
let get_name_of_local_with_procname var = let get_name_of_local_with_procname var =
match var.pv_kind with match var.pv_kind with
| Local_var pname -> | Local_var pname ->
Mangled.from_string (F.asprintf "%s_%a" (Mangled.to_string var.pv_name) Typ.Procname.pp pname) Mangled.from_string (F.asprintf "%s_%a" (Mangled.to_string var.pv_name) Procname.pp pname)
| _ -> | _ ->
var.pv_name var.pv_name
@ -131,7 +130,7 @@ let is_frontend_tmp pvar =
|| ||
match pvar.pv_kind with match pvar.pv_kind with
| Local_var pname -> | Local_var pname ->
Typ.Procname.is_java pname && is_bytecode_tmp name Procname.is_java pname && is_bytecode_tmp name
| _ -> | _ ->
false false
@ -218,7 +217,7 @@ let to_callee pname pvar =
let name_hash (name : Mangled.t) = Hashtbl.hash name 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 : Typ.Procname.t) : t = let mk (name : Mangled.t) (proc_name : Procname.t) : t =
{pv_hash= name_hash name; pv_name= name; pv_kind= Local_var proc_name} {pv_hash= name_hash name; pv_name= name; pv_kind= Local_var proc_name}
@ -228,7 +227,7 @@ let get_ret_param_pvar pname = mk Ident.name_return_param pname
(** [mk_callee name proc_name] creates a program var for a callee function with the given function (** [mk_callee name proc_name] creates a program var for a callee function with the given function
name *) name *)
let mk_callee (name : Mangled.t) (proc_name : Typ.Procname.t) : t = let mk_callee (name : Mangled.t) (proc_name : Procname.t) : t =
{pv_hash= name_hash name; pv_name= name; pv_kind= Callee_var proc_name} {pv_hash= name_hash name; pv_name= name; pv_kind= Callee_var proc_name}
@ -250,15 +249,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 : Typ.Procname.t) (loc : Location.t) : t = let mk_abduced_ret (proc_name : Procname.t) (loc : Location.t) : t =
let name = Mangled.from_string (F.asprintf "$RET_%a" Typ.Procname.pp_unique_id proc_name) in let name = Mangled.from_string (F.asprintf "$RET_%a" Procname.pp_unique_id proc_name) in
{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 : Typ.Procname.t) (index : int) (loc : Location.t) : t = let mk_abduced_ref_param (proc_name : Procname.t) (index : int) (loc : Location.t) : t =
let name = let name = Mangled.from_string (F.asprintf "$REF_PARAM_VAL_%a" Procname.pp_unique_id proc_name) in
Mangled.from_string (F.asprintf "$REF_PARAM_VAL_%a" Typ.Procname.pp_unique_id proc_name)
in
{pv_hash= name_hash name; pv_name= name; pv_kind= Abduced_ref_param (proc_name, index, loc)} {pv_hash= name_hash name; pv_name= name; pv_kind= Abduced_ref_param (proc_name, index, loc)}
@ -286,12 +283,12 @@ let get_initializer_pname {pv_name; pv_kind} =
match translation_unit with match translation_unit with
| Some file -> | Some file ->
let mangled = SourceFile.to_string file |> Utils.string_crc_hex32 in let mangled = SourceFile.to_string file |> Utils.string_crc_hex32 in
Typ.Procname.C Procname.C
(Typ.Procname.C.c (QualifiedCppName.of_qual_string name) mangled [] Typ.NoTemplate) (Procname.C.c (QualifiedCppName.of_qual_string name) mangled [] Typ.NoTemplate)
|> Option.return |> Option.return
| None -> | None ->
None None
else Some (Typ.Procname.from_string_c_fun name) else Some (Procname.from_string_c_fun name)
| _ -> | _ ->
None None

@ -27,7 +27,7 @@ val compare_modulo_this : t -> t -> int
val equal : t -> t -> bool val equal : t -> t -> bool
(** Equality for pvar's *) (** Equality for pvar's *)
val get_declaring_function : t -> Typ.Procname.t option val get_declaring_function : t -> Procname.t option
(** if not a global, return function declaring var *) (** if not a global, return function declaring var *)
val d : t -> unit val d : t -> unit
@ -36,10 +36,10 @@ val d : t -> unit
val get_name : t -> Mangled.t val get_name : t -> Mangled.t
(** Get the name component of a program variable. *) (** Get the name component of a program variable. *)
val get_ret_pvar : Typ.Procname.t -> t val get_ret_pvar : Procname.t -> 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 *)
val get_ret_param_pvar : Typ.Procname.t -> t val get_ret_param_pvar : Procname.t -> t
(** [get_ret_param_pvar proc_name] retuns the return_param pvar associated with the procedure name *) (** [get_ret_param_pvar proc_name] retuns the return_param pvar associated with the procedure name *)
val get_simplified_name : t -> string val get_simplified_name : t -> string
@ -92,16 +92,16 @@ val is_objc_static_local_of_proc_name : string -> t -> bool
val is_block_pvar : t -> bool val is_block_pvar : t -> bool
(** Check if a pvar is a local pointing to a block in objc *) (** Check if a pvar is a local pointing to a block in objc *)
val mk : Mangled.t -> Typ.Procname.t -> t val mk : Mangled.t -> Procname.t -> t
(** [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 *)
val mk_abduced_ref_param : Typ.Procname.t -> int -> Location.t -> t val mk_abduced_ref_param : Procname.t -> int -> Location.t -> t
(** create an abduced variable for a parameter passed by reference *) (** create an abduced variable for a parameter passed by reference *)
val mk_abduced_ret : Typ.Procname.t -> Location.t -> t val mk_abduced_ret : Procname.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] *)
val mk_callee : Mangled.t -> Typ.Procname.t -> t val mk_callee : Mangled.t -> Procname.t -> t
(** [mk_callee name proc_name] creates a program var for a callee function with the given function (** [mk_callee name proc_name] creates a program var for a callee function with the given function
name *) name *)
@ -116,7 +116,7 @@ val mk_global :
-> t -> t
(** create a global variable with the given name *) (** create a global variable with the given name *)
val mk_tmp : string -> Typ.Procname.t -> t val mk_tmp : string -> Procname.t -> t
(** 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! *)
val pp : Pp.env -> F.formatter -> t -> unit val pp : Pp.env -> F.formatter -> t -> unit
@ -130,7 +130,7 @@ val pp_value_non_verbose : F.formatter -> t -> unit
val pp_translation_unit : F.formatter -> translation_unit -> unit val pp_translation_unit : F.formatter -> translation_unit -> unit
val to_callee : Typ.Procname.t -> t -> t val to_callee : Procname.t -> t -> t
(** Turn an ordinary program variable into a callee program variable *) (** Turn an ordinary program variable into a callee program variable *)
val to_seed : t -> t val to_seed : t -> t
@ -154,7 +154,7 @@ val is_pod : t -> bool
(** Is the variable's type a "Plain Old Data" type (C++)? Always (potentially incorrectly) returns (** Is the variable's type a "Plain Old Data" type (C++)? Always (potentially incorrectly) returns
[true] for non-globals. *) [true] for non-globals. *)
val get_initializer_pname : t -> Typ.Procname.t option val get_initializer_pname : t -> Procname.t option
(** Get the procname of the initializer function for the given global variable *) (** Get the procname of the initializer function for the given global variable *)
val get_name_of_local_with_procname : t -> Mangled.t val get_name_of_local_with_procname : t -> Mangled.t

@ -194,7 +194,7 @@ let add_with_block_parameters_flag instr =
| Call (ret_id_typ, Exp.Const (Const.Cfun pname), arg_ts, loc, cf) -> | Call (ret_id_typ, Exp.Const (Const.Cfun pname), arg_ts, loc, cf) ->
if if
List.exists ~f:(fun (exp, _) -> Exp.is_objc_block_closure exp) arg_ts List.exists ~f:(fun (exp, _) -> Exp.is_objc_block_closure exp) arg_ts
&& Typ.Procname.is_clang pname && Procname.is_clang pname
(* to be extended to other methods *) (* to be extended to other methods *)
then then
let cf' = {cf with cf_with_block_parameters= true} in let cf' = {cf with cf_with_block_parameters= true} in

@ -23,7 +23,7 @@ let get_existing_data source_file =
SqliteUtils.result_option ~finalize:false db ~log:"looking for pre-existing source file data" SqliteUtils.result_option ~finalize:false db ~log:"looking for pre-existing source file data"
stmt ~read_row:(fun stmt -> stmt ~read_row:(fun stmt ->
let tenv = Sqlite3.column stmt 0 |> Tenv.SQLite.deserialize let tenv = Sqlite3.column stmt 0 |> Tenv.SQLite.deserialize
and proc_names = Sqlite3.column stmt 1 |> Typ.Procname.SQLiteList.deserialize in and proc_names = Sqlite3.column stmt 1 |> Procname.SQLiteList.deserialize in
(tenv, proc_names) ) ) (tenv, proc_names) ) )
@ -64,7 +64,7 @@ let add source_file cfg tenv integer_type_widths =
~source_file:(SourceFile.SQLite.serialize source_file) ~source_file:(SourceFile.SQLite.serialize source_file)
~tenv:(Tenv.SQLite.serialize tenv) ~tenv:(Tenv.SQLite.serialize tenv)
~integer_type_widths:(Typ.IntegerWidths.SQLite.serialize integer_type_widths) ~integer_type_widths:(Typ.IntegerWidths.SQLite.serialize integer_type_widths)
~proc_names:(Typ.Procname.SQLiteList.serialize proc_names) ~proc_names:(Procname.SQLiteList.serialize proc_names)
let get_all ~filter () = let get_all ~filter () =
@ -91,7 +91,7 @@ let proc_names_of_source source =
|> SqliteUtils.check_result_code db ~log:"load bind source file" ; |> SqliteUtils.check_result_code db ~log:"load bind source file" ;
SqliteUtils.result_single_column_option ~finalize:false db SqliteUtils.result_single_column_option ~finalize:false db
~log:"SourceFiles.proc_names_of_source" load_stmt ~log:"SourceFiles.proc_names_of_source" load_stmt
|> Option.value_map ~default:[] ~f:Typ.Procname.SQLiteList.deserialize ) |> Option.value_map ~default:[] ~f:Procname.SQLiteList.deserialize )
let exists_source_statement = let exists_source_statement =
@ -152,7 +152,7 @@ let select_all_source_files_statement =
let pp_all ~filter ~type_environment ~procedure_names ~freshly_captured fmt () = let pp_all ~filter ~type_environment ~procedure_names ~freshly_captured fmt () =
let pp_procnames fmt procs = let pp_procnames fmt procs =
F.fprintf fmt "@[<v>" ; F.fprintf fmt "@[<v>" ;
List.iter ~f:(F.fprintf fmt "%a@," Typ.Procname.pp) procs ; List.iter ~f:(F.fprintf fmt "%a@," Procname.pp) procs ;
F.fprintf fmt "@]" F.fprintf fmt "@]"
in in
let pp_if stmt title condition deserialize pp fmt column = let pp_if stmt title condition deserialize pp fmt column =
@ -163,8 +163,7 @@ let pp_all ~filter ~type_environment ~procedure_names ~freshly_captured fmt () =
F.fprintf fmt "%a@,%a%a%a" SourceFile.pp source_file F.fprintf fmt "%a@,%a%a%a" SourceFile.pp source_file
(pp_if stmt "type_environment" type_environment Tenv.SQLite.deserialize Tenv.pp_per_file) (pp_if stmt "type_environment" type_environment Tenv.SQLite.deserialize Tenv.pp_per_file)
1 1
(pp_if stmt "procedure_names" procedure_names Typ.Procname.SQLiteList.deserialize (pp_if stmt "procedure_names" procedure_names Procname.SQLiteList.deserialize pp_procnames)
pp_procnames)
2 2
(pp_if stmt "freshly_captured" freshly_captured deserialize_freshly_captured (pp_if stmt "freshly_captured" freshly_captured deserialize_freshly_captured
Format.pp_print_bool) Format.pp_print_bool)

@ -13,7 +13,7 @@ val add : SourceFile.t -> Cfg.t -> Tenv.per_file -> Typ.IntegerWidths.t option -
val get_all : filter:Filtering.source_files_filter -> unit -> SourceFile.t list val get_all : filter:Filtering.source_files_filter -> unit -> SourceFile.t list
(** get all the source files in the database *) (** get all the source files in the database *)
val proc_names_of_source : SourceFile.t -> Typ.Procname.t list val proc_names_of_source : SourceFile.t -> Procname.t list
(** list of all the proc names (declared and defined) found in a source file *) (** list of all the proc names (declared and defined) found in a source file *)
val is_captured : SourceFile.t -> bool val is_captured : SourceFile.t -> bool

@ -104,7 +104,7 @@ let with_formals_types_proc callee_pdesc resolved_pdesc substitutions =
when call_flags.CallFlags.cf_virtual && redirect_typename id <> None -> when call_flags.CallFlags.cf_virtual && redirect_typename id <> None ->
let redirected_typename = Option.value_exn (redirect_typename id) in let redirected_typename = Option.value_exn (redirect_typename id) in
let redirected_typ = mk_ptr_typ redirected_typename in let redirected_typ = mk_ptr_typ redirected_typename in
let redirected_pname = Typ.Procname.replace_class callee_pname redirected_typename in let redirected_pname = Procname.replace_class callee_pname redirected_typename in
let args = let args =
let other_args = List.map ~f:(fun (exp, typ) -> (convert_exp exp, typ)) origin_args in let other_args = List.map ~f:(fun (exp, typ) -> (convert_exp exp, typ)) origin_args in
(Exp.Var id, redirected_typ) :: other_args (Exp.Var id, redirected_typ) :: other_args
@ -152,8 +152,8 @@ let with_formals_types ?(has_clang_model = false) callee_pdesc resolved_pname ar
result result
| Unequal_lengths -> | Unequal_lengths ->
L.(debug Analysis Medium) L.(debug Analysis Medium)
"Call mismatch: method %a has %i paramters but is called with %i arguments@." "Call mismatch: method %a has %i paramters but is called with %i arguments@." Procname.pp
Typ.Procname.pp resolved_pname resolved_pname
(List.length callee_attributes.formals) (List.length callee_attributes.formals)
(List.length args) ; (List.length args) ;
raise UnmatchedParameters raise UnmatchedParameters
@ -171,7 +171,7 @@ let with_formals_types ?(has_clang_model = false) callee_pdesc resolved_pname ar
Logging.die InternalError Logging.die InternalError
"specialize_types should only be called with defined procedures, but we cannot find \ "specialize_types should only be called with defined procedures, but we cannot find \
the captured file of procname %a" the captured file of procname %a"
Typ.Procname.pp pname Procname.pp pname
else callee_attributes.translation_unit else callee_attributes.translation_unit
in in
let resolved_attributes = let resolved_attributes =
@ -185,7 +185,7 @@ let with_formals_types ?(has_clang_model = false) callee_pdesc resolved_pname ar
let resolved_proc_desc = with_formals_types_proc callee_pdesc resolved_proc_desc substitutions in let resolved_proc_desc = with_formals_types_proc callee_pdesc resolved_proc_desc substitutions in
(* The attributes here are used to retrieve the per-file type environment for Clang languages. (* The attributes here are used to retrieve the per-file type environment for Clang languages.
The analysis for Java is using a global type environment *) The analysis for Java is using a global type environment *)
if not (Typ.Procname.is_java resolved_pname) then if not (Procname.is_java resolved_pname) then
Attributes.store ~proc_desc:(Some resolved_proc_desc) resolved_attributes ; Attributes.store ~proc_desc:(Some resolved_proc_desc) resolved_attributes ;
resolved_proc_desc resolved_proc_desc
@ -298,7 +298,7 @@ let with_block_args callee_pdesc pname_with_block_args block_args =
let callee_attributes = Procdesc.get_attributes callee_pdesc in let callee_attributes = Procdesc.get_attributes callee_pdesc in
(* Substitution from a block parameter to the block name and the new formals (* Substitution from a block parameter to the block name and the new formals
that correspond to the captured variables *) that correspond to the captured variables *)
let substitutions : (Typ.Procname.t * (Mangled.t * Typ.t) list) Mangled.Map.t = let substitutions : (Procname.t * (Mangled.t * Typ.t) list) Mangled.Map.t =
List.fold2_exn callee_attributes.formals block_args ~init:Mangled.Map.empty List.fold2_exn callee_attributes.formals block_args ~init:Mangled.Map.empty
~f:(fun subts (param_name, _) block_arg_opt -> ~f:(fun subts (param_name, _) block_arg_opt ->
match block_arg_opt with match block_arg_opt with
@ -341,7 +341,7 @@ let with_block_args callee_pdesc pname_with_block_args block_args =
Logging.die InternalError Logging.die InternalError
"specialize_with_block_args ahould only be called with defined procedures, but we cannot \ "specialize_with_block_args ahould only be called with defined procedures, but we cannot \
find the captured file of procname %a" find the captured file of procname %a"
Typ.Procname.pp pname Procname.pp pname
in in
let resolved_attributes = let resolved_attributes =
{ callee_attributes with { callee_attributes with

@ -10,13 +10,13 @@ open! IStd
exception UnmatchedParameters exception UnmatchedParameters
val with_formals_types : val with_formals_types :
?has_clang_model:bool -> Procdesc.t -> Typ.Procname.t -> (Exp.t * Typ.t) list -> Procdesc.t ?has_clang_model:bool -> Procdesc.t -> Procname.t -> (Exp.t * Typ.t) list -> Procdesc.t
(** Creates a copy of a procedure description and a list of type substitutions of the form (name, (** 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 all the type of the 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. The virtual calls are also parameters are replaced in the instructions according to the list. The virtual calls are also
replaced to match the parameter types *) replaced to match the parameter types *)
val with_block_args : Procdesc.t -> Typ.Procname.t -> Exp.closure option list -> Procdesc.t val with_block_args : Procdesc.t -> Procname.t -> Exp.closure option list -> Procdesc.t
(** Creates a copy of a procedure description given a list of possible closures that are passed as (** Creates a copy of a procedure description given a list of possible closures that are passed as
arguments to the method. The resulting procdesc is isomorphic but arguments to the method. The resulting procdesc is isomorphic but

@ -17,9 +17,8 @@ type t =
{ fields: fields (** non-static fields *) { fields: fields (** non-static fields *)
; statics: fields (** static fields *) ; statics: fields (** static fields *)
; supers: Typ.Name.t list (** superclasses *) ; supers: Typ.Name.t list (** superclasses *)
; methods: Typ.Procname.t list (** methods defined *) ; methods: Procname.t list (** methods defined *)
; exported_objc_methods: Typ.Procname.t list ; exported_objc_methods: Procname.t list (** methods in ObjC interface, subset of [methods] *)
(** methods in ObjC interface, subset of [methods] *)
; annots: Annot.Item.t (** annotations *) ; annots: Annot.Item.t (** annotations *)
; dummy: bool (** dummy struct for class including static method *) } ; dummy: bool (** dummy struct for class including static method *) }
@ -49,9 +48,9 @@ let pp pe name f {fields; supers; methods; exported_objc_methods; annots} =
fields fields
(Pp.seq (fun f n -> F.fprintf f "@\n\t\t%a" Typ.Name.pp n)) (Pp.seq (fun f n -> F.fprintf f "@\n\t\t%a" Typ.Name.pp n))
supers supers
(Pp.seq (fun f m -> F.fprintf f "@\n\t\t%a" Typ.Procname.pp m)) (Pp.seq (fun f m -> F.fprintf f "@\n\t\t%a" Procname.pp m))
methods methods
(Pp.seq (fun f m -> F.fprintf f "@\n\t\t%a" Typ.Procname.pp m)) (Pp.seq (fun f m -> F.fprintf f "@\n\t\t%a" Procname.pp m))
exported_objc_methods Annot.Item.pp annots exported_objc_methods Annot.Item.pp annots
else Typ.Name.pp f name else Typ.Name.pp f name

@ -18,9 +18,8 @@ type t = private
{ fields: fields (** non-static fields *) { fields: fields (** non-static fields *)
; statics: fields (** static fields *) ; statics: fields (** static fields *)
; supers: Typ.Name.t list (** supers *) ; supers: Typ.Name.t list (** supers *)
; methods: Typ.Procname.t list (** methods defined *) ; methods: Procname.t list (** methods defined *)
; exported_objc_methods: Typ.Procname.t list ; exported_objc_methods: Procname.t list (** methods in ObjC interface, subset of [methods] *)
(** methods in ObjC interface, subset of [methods] *)
; annots: Annot.Item.t (** annotations *) ; annots: Annot.Item.t (** annotations *)
; dummy: bool (** dummy struct for class including static method *) } ; dummy: bool (** dummy struct for class including static method *) }
@ -35,8 +34,8 @@ val internal_mk_struct :
?default:t ?default:t
-> ?fields:fields -> ?fields:fields
-> ?statics:fields -> ?statics:fields
-> ?methods:Typ.Procname.t list -> ?methods:Procname.t list
-> ?exported_objc_methods:Typ.Procname.t list -> ?exported_objc_methods:Procname.t list
-> ?supers:Typ.Name.t list -> ?supers:Typ.Name.t list
-> ?annots:Annot.Item.t -> ?annots:Annot.Item.t
-> ?dummy:bool -> ?dummy:bool

@ -37,8 +37,8 @@ val mk_struct :
-> ?default:Struct.t -> ?default:Struct.t
-> ?fields:Struct.fields -> ?fields:Struct.fields
-> ?statics:Struct.fields -> ?statics:Struct.fields
-> ?methods:Typ.Procname.t list -> ?methods:Procname.t list
-> ?exported_objc_methods:Typ.Procname.t list -> ?exported_objc_methods:Procname.t list
-> ?supers:Typ.Name.t list -> ?supers:Typ.Name.t list
-> ?annots:Annot.Item.t -> ?annots:Annot.Item.t
-> ?dummy:bool -> ?dummy:bool

@ -265,8 +265,24 @@ let void = mk Tvoid
let void_star = mk (Tptr (mk Tvoid, Pk_pointer)) let void_star = mk (Tptr (mk Tvoid, Pk_pointer))
let java_byte = mk (Tint IShort)
let java_short = java_byte
let boolean = mk (Tint IBool)
let char = mk (Tint IChar)
let float = mk (Tfloat FFloat)
let double = mk (Tfloat FDouble)
let int = mk (Tint IInt)
let uint = mk (Tint IUInt) let uint = mk (Tint IUInt)
let long = mk (Tint ILong)
let get_ikind_opt {desc} = match desc with Tint ikind -> Some ikind | _ -> None let get_ikind_opt {desc} = match desc with Tint ikind -> Some ikind | _ -> None
(* TODO: size_t should be implementation-dependent. *) (* TODO: size_t should be implementation-dependent. *)
@ -431,7 +447,7 @@ module Name = struct
(** e.g. {type_name="int"; package=None} for primitive types (** e.g. {type_name="int"; package=None} for primitive types
* or {type_name="PrintWriter"; package=Some "java.io"} for objects. * or {type_name="PrintWriter"; package=Some "java.io"} for objects.
*) *)
type t = {package: string option; type_name: string} type t = {package: string option; type_name: string} [@@deriving compare]
let make ?package type_name = {type_name; package} let make ?package type_name = {type_name; package}
@ -454,6 +470,12 @@ module Name = struct
let java_lang_string = make ~package:"java.lang" "String" let java_lang_string = make ~package:"java.lang" "String"
let void = make "void" let void = make "void"
let pp_type_verbosity ~verbose fmt = function
| {package= Some package; type_name} when verbose ->
F.fprintf fmt "%s.%s" package type_name
| {type_name} ->
F.pp_print_string fmt type_name
end end
let from_string name_str = JavaClass (Mangled.from_string name_str) let from_string name_str = JavaClass (Mangled.from_string name_str)
@ -597,826 +619,3 @@ let has_block_prefix s =
type typ = t type typ = t
module Procname = struct
(** 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 is_verbose v = match v with Verbose -> true | _ -> false
module Java = struct
type kind =
| Non_Static
(** in Java, procedures called with invokevirtual, invokespecial, and invokeinterface *)
| Static (** in Java, procedures called with invokestatic *)
[@@deriving compare]
(* TODO: use Mangled.t here *)
type java_type = Name.Java.Split.t = {package: string option; type_name: string}
[@@deriving compare]
let java_void = {package= None; type_name= "void"}
(** Type of java procedure names. *)
type t =
{ method_name: string
; parameters: java_type list
; class_name: Name.t
; return_type: java_type option (* option because constructors have no return type *)
; kind: kind }
[@@deriving compare]
let make class_name return_type method_name parameters kind =
{class_name; return_type; method_name; parameters; kind}
(** A type is a pair (package, type_name) that is translated in a string package.type_name *)
let pp_type_verbosity verbosity fmt p =
match p with
| {package= Some package; type_name} when is_verbose verbosity ->
F.fprintf fmt "%s.%s" package type_name
| {type_name} ->
F.pp_print_string fmt type_name
(** Given a list of types, it creates a unique string of types separated by commas *)
let rec pp_param_list verbosity fmt inputList =
match inputList with
| [] ->
()
| [head] ->
pp_type_verbosity verbosity fmt head
| head :: rest ->
pp_type_verbosity verbosity fmt head ;
F.pp_print_string fmt "," ;
pp_param_list verbosity fmt rest
let java_type_of_name class_name = Name.Java.Split.of_string (Name.name class_name)
(** It is the same as java_type_to_string_verbosity, but Java return types are optional because
of constructors without type *)
let pp_return_type verbosity fmt j =
match j.return_type with None -> () | Some typ -> pp_type_verbosity verbosity fmt typ
let get_class_name j = Name.name j.class_name
let get_class_type_name j = j.class_name
let get_simple_class_name j = Name.Java.Split.(j |> get_class_name |> of_string |> type_name)
let get_package j = Name.Java.Split.(j |> get_class_name |> of_string |> package)
let get_method j = j.method_name
let replace_method_name method_name j = {j with method_name}
let replace_parameters parameters j = {j with parameters}
let replace_return_type ret_type j = {j with return_type= Some ret_type}
let get_parameters j = j.parameters
(** Prints a string of a java procname with the given level of verbosity *)
let pp ?(withclass = false) verbosity fmt j =
match verbosity with
| 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 pp_class_name verbosity fmt j =
pp_type_verbosity verbosity fmt (Name.Java.split_typename j.class_name)
in
let separator =
match (j.return_type, verbosity) with
| None, _ ->
""
| Some _, Verbose ->
":"
| _ ->
" "
in
if not (equal_detail_level verbosity Verbose) then
F.fprintf fmt "%a%s" (pp_return_type verbosity) j separator ;
F.fprintf fmt "%a.%s(%a)" (pp_class_name verbosity) j j.method_name
(pp_param_list verbosity) j.parameters ;
if equal_detail_level verbosity Verbose then
F.fprintf fmt "%s%a" separator (pp_return_type verbosity) j
| Simple ->
(* methodname(...) or without ... if there are no parameters *)
let pp_class_prefix ~withclass verbosity fmt j =
if withclass then
F.fprintf fmt "%a." (pp_type_verbosity verbosity)
(Name.Java.split_typename j.class_name)
in
let params = match j.parameters with [] -> "" | _ -> "..." in
let pp_method_name ~withclass verbosity fmt j =
if String.equal j.method_name "<init>" then
F.pp_print_string fmt (get_simple_class_name j)
else F.fprintf fmt "%a%s" (pp_class_prefix ~withclass verbosity) j j.method_name
in
F.fprintf fmt "%a(%s)" (pp_method_name ~withclass verbosity) j params
let get_return_typ pname_java =
let rec java_from_string = function
| "" | "void" ->
mk Tvoid
| "int" ->
mk (Tint IInt)
| "byte" ->
mk (Tint IShort)
| "short" ->
mk (Tint IShort)
| "boolean" ->
mk (Tint IBool)
| "char" ->
mk (Tint IChar)
| "long" ->
mk (Tint ILong)
| "float" ->
mk (Tfloat FFloat)
| "double" ->
mk (Tfloat FDouble)
| typ_str when String.contains typ_str '[' ->
let stripped_typ = String.sub typ_str ~pos:0 ~len:(String.length typ_str - 2) in
mk (Tptr (mk_array (java_from_string stripped_typ), Pk_pointer))
| typ_str ->
mk (Tstruct (Name.Java.from_string typ_str))
in
let typ = java_from_string (F.asprintf "%a" (pp_return_type Verbose) pname_java) in
match typ.desc with Tstruct _ -> mk (Tptr (typ, Pk_pointer)) | _ -> typ
let is_close {method_name} = String.equal method_name "close"
let constructor_method_name = "<init>"
let class_initializer_method_name = "<clinit>"
let is_class_initializer {method_name} = String.equal method_name class_initializer_method_name
let get_class_initializer class_name =
{ method_name= class_initializer_method_name
; parameters= []
; class_name
; return_type= Some java_void
; kind= Static }
let is_constructor {method_name} = String.equal method_name constructor_method_name
let is_anonymous_inner_class_constructor {class_name} =
Name.Java.is_anonymous_inner_class_name class_name
let is_static {kind} = match kind with Static -> true | _ -> false
let is_lambda {method_name} = String.is_prefix ~prefix:"lambda$" method_name
let is_generated {method_name} = String.is_prefix ~prefix:"$" method_name
let is_access_method {method_name} =
match String.rsplit2 method_name ~on:'$' with
| Some ("access", s) ->
let is_int =
try
ignore (int_of_string s) ;
true
with Failure _ -> false
in
is_int
| _ ->
false
let is_autogen_method {method_name} = String.contains method_name '$'
(** Check if the proc name has the type of a java vararg.
Note: currently only checks that the last argument has type Object[]. *)
let is_vararg {parameters} =
match List.last parameters with Some {type_name= "java.lang.Object[]"} -> true | _ -> false
let is_external java_pname =
let package = get_package java_pname in
Option.exists ~f:Config.java_package_is_external package
end
module Parameter = struct
(** Type for parameters in clang procnames, [Some name] means the parameter is of type pointer to struct, with [name]
being the name of the struct, [None] means the parameter is of some other type. *)
type clang_parameter = Name.t option [@@deriving compare]
(** Type for parameters in procnames, for java and clang. *)
type t = JavaParameter of Java.java_type | ClangParameter of clang_parameter
[@@deriving compare]
let of_typ typ =
match typ.T.desc with T.Tptr ({desc= Tstruct name}, Pk_pointer) -> Some name | _ -> None
let pp_parameters fmt parameters =
if List.exists ~f:Option.is_some parameters then
(* the tests rely on the fact that we discard non-pointer-to-struct types for some reason,
hence the slight re-implementation of [Pp.seq] to avoid building the list of [Some] items
explicitly *)
let rec pp_parameters_aux fmt = function
| [] ->
()
| [Some param] ->
F.pp_print_string fmt (Name.to_string param)
| None :: parameters ->
pp_parameters_aux fmt parameters
| (Some _ as param_some) :: None :: parameters ->
pp_parameters_aux fmt (param_some :: parameters)
| Some param :: (Some _ :: _ as parameters) ->
F.fprintf fmt "%s," (Name.to_string param) ;
pp_parameters_aux fmt parameters
in
F.fprintf fmt "(%a)" pp_parameters_aux parameters
let clang_param_of_name class_name : clang_parameter = Some class_name
end
module ObjC_Cpp = struct
type kind =
| CPPMethod of {mangled: string option}
| CPPConstructor of {mangled: string option; is_constexpr: bool}
| CPPDestructor of {mangled: string option}
| ObjCClassMethod
| ObjCInstanceMethod
| ObjCInternalMethod
[@@deriving compare]
type t =
{ class_name: Name.t
; kind: kind
; method_name: string
; parameters: Parameter.clang_parameter list
; template_args: template_spec_info }
[@@deriving compare]
let make class_name method_name kind template_args parameters =
{class_name; method_name; kind; template_args; parameters}
let get_class_name objc_cpp = Name.name objc_cpp.class_name
let get_class_type_name objc_cpp = objc_cpp.class_name
let get_class_qualifiers objc_cpp = Name.qual_name objc_cpp.class_name
let objc_method_kind_of_bool is_instance =
if is_instance then ObjCInstanceMethod else ObjCClassMethod
let is_objc_constructor method_name =
String.equal method_name "new" || String.is_prefix ~prefix:"init" method_name
let is_objc_kind = function
| ObjCClassMethod | ObjCInstanceMethod | ObjCInternalMethod ->
true
| _ ->
false
let is_objc_method {kind} = is_objc_kind kind
let is_objc_dealloc method_name = String.equal method_name "dealloc"
let is_destructor = function
| {kind= CPPDestructor _} ->
true
| name ->
is_objc_dealloc name.method_name
let is_inner_destructor ({method_name} as pname) =
is_destructor pname
&& String.is_prefix ~prefix:Config.clang_inner_destructor_prefix method_name
let is_constexpr = function {kind= CPPConstructor {is_constexpr= true}} -> true | _ -> false
let is_cpp_lambda {method_name} = String.is_substring ~substring:"operator()" method_name
let pp_verbose_kind fmt = function
| CPPMethod {mangled} | CPPDestructor {mangled} ->
F.fprintf fmt "(%s)" (Option.value ~default:"" mangled)
| CPPConstructor {mangled; is_constexpr} ->
F.fprintf fmt "{%s%s}"
(Option.value ~default:"" mangled)
(if is_constexpr then "|constexpr" else "")
| ObjCClassMethod ->
F.pp_print_string fmt "class"
| ObjCInstanceMethod ->
F.pp_print_string fmt "instance"
| ObjCInternalMethod ->
F.pp_print_string fmt "internal"
let pp verbosity fmt osig =
match verbosity with
| Simple ->
F.pp_print_string fmt osig.method_name
| Non_verbose ->
F.fprintf fmt "%s::%s" (Name.name osig.class_name) osig.method_name
| Verbose ->
F.fprintf fmt "%s::%s%a%a" (Name.name osig.class_name) osig.method_name
Parameter.pp_parameters osig.parameters pp_verbose_kind osig.kind
let get_parameters osig = osig.parameters
let replace_parameters new_parameters osig = {osig with parameters= new_parameters}
end
module C = struct
(** Type of c procedure names. *)
type t =
{ name: QualifiedCppName.t
; mangled: string option
; parameters: Parameter.clang_parameter list
; template_args: template_spec_info }
[@@deriving compare]
let c name mangled parameters template_args =
{name; mangled= Some mangled; parameters; template_args}
let from_string name =
{ name= QualifiedCppName.of_qual_string name
; mangled= None
; parameters= []
; template_args= NoTemplate }
let pp verbosity fmt {name; mangled; parameters} =
let plain = QualifiedCppName.to_qual_string name in
match verbosity with
| Simple ->
F.fprintf fmt "%s()" plain
| Non_verbose ->
F.pp_print_string fmt plain
| Verbose ->
let pp_mangled fmt = function None -> () | Some s -> F.fprintf fmt "{%s}" s in
F.fprintf fmt "%s%a%a" plain Parameter.pp_parameters parameters pp_mangled mangled
let get_parameters c = c.parameters
let replace_parameters new_parameters c = {c with parameters= new_parameters}
end
module Block = struct
(** Type of Objective C block names. *)
type block_name = string [@@deriving compare]
type t = {name: block_name; parameters: Parameter.clang_parameter list} [@@deriving compare]
let make name parameters = {name; parameters}
let pp verbosity fmt bsig =
match verbosity with
| Simple ->
F.pp_print_string fmt "block"
| Non_verbose ->
F.pp_print_string fmt bsig.name
| Verbose ->
F.fprintf fmt "%s%a" bsig.name Parameter.pp_parameters bsig.parameters
let get_parameters block = block.parameters
let replace_parameters new_parameters block = {block with parameters= new_parameters}
end
(** Type of procedure names. *)
type t =
| Java of Java.t
| C of C.t
| Linters_dummy_method
| Block of Block.t
| ObjC_Cpp of ObjC_Cpp.t
| WithBlockParameters of t * Block.block_name list
[@@deriving compare]
let equal = [%compare.equal: t]
(** hash function for procname *)
let hash = Hashtbl.hash
let with_block_parameters base blocks = WithBlockParameters (base, blocks)
let is_java = function Java _ -> true | _ -> false
(* TODO: deprecate this unfortunately named function and use is_clang instead *)
let is_c_method = function ObjC_Cpp _ -> true | _ -> false
let is_c_function = function C _ -> true | _ -> false
let is_clang = function
| ObjC_Cpp name ->
ObjC_Cpp.is_objc_method name
| name ->
is_c_function name
let is_java_lift f = function Java java_pname -> f java_pname | _ -> false
let is_java_access_method = is_java_lift Java.is_access_method
let is_java_class_initializer = is_java_lift Java.is_class_initializer
let is_objc_method procname =
match procname with ObjC_Cpp name -> ObjC_Cpp.is_objc_method name | _ -> false
let block_name_of_procname procname =
match procname with
| Block block ->
block.name
| _ ->
Logging.die InternalError "Only to be called with Objective-C block names"
let empty_block = Block {name= ""; parameters= []}
(** Replace the class name component of a procedure name.
In case of Java, replace package and class name. *)
let rec replace_class t (new_class : Name.t) =
match t with
| Java j ->
Java {j with class_name= new_class}
| ObjC_Cpp osig ->
ObjC_Cpp {osig with class_name= new_class}
| WithBlockParameters (base, blocks) ->
WithBlockParameters (replace_class base new_class, blocks)
| C _ | Block _ | Linters_dummy_method ->
t
let get_class_type_name = function
| Java java_pname ->
Some (Java.get_class_type_name java_pname)
| ObjC_Cpp objc_pname ->
Some (ObjC_Cpp.get_class_type_name objc_pname)
| _ ->
None
let get_class_name = function
| Java java_pname ->
Some (Java.get_class_name java_pname)
| ObjC_Cpp objc_pname ->
Some (ObjC_Cpp.get_class_name objc_pname)
| _ ->
None
let is_method_in_objc_protocol t =
match t with ObjC_Cpp osig -> Name.is_objc_protocol osig.class_name | _ -> false
let rec objc_cpp_replace_method_name t (new_method_name : string) =
match t with
| ObjC_Cpp osig ->
ObjC_Cpp {osig with method_name= new_method_name}
| WithBlockParameters (base, blocks) ->
WithBlockParameters (objc_cpp_replace_method_name base new_method_name, blocks)
| C _ | Block _ | Linters_dummy_method | Java _ ->
t
(** Return the method/function of a procname. *)
let rec get_method = function
| ObjC_Cpp name ->
name.method_name
| WithBlockParameters (base, _) ->
get_method base
| C {name} ->
QualifiedCppName.to_qual_string name
| Block {name} ->
name
| Java j ->
j.method_name
| Linters_dummy_method ->
"Linters_dummy_method"
(** Return whether the procname is a block procname. *)
let is_objc_block = function Block _ -> true | _ -> false
(** Return the language of the procedure. *)
let get_language = function
| ObjC_Cpp _ ->
Language.Clang
| C _ ->
Language.Clang
| Block _ ->
Language.Clang
| Linters_dummy_method ->
Language.Clang
| WithBlockParameters _ ->
Language.Clang
| Java _ ->
Language.Java
(** [is_constructor pname] returns true if [pname] is a constructor *)
let is_constructor = function
| Java js ->
String.equal js.method_name Java.constructor_method_name
| ObjC_Cpp {kind= CPPConstructor _} ->
true
| ObjC_Cpp {kind; method_name} when ObjC_Cpp.is_objc_kind kind ->
ObjC_Cpp.is_objc_constructor method_name
| _ ->
false
(** [is_infer_undefined pn] returns true if [pn] is a special Infer undefined proc *)
let is_infer_undefined pn =
match pn with
| Java j ->
let regexp = Str.regexp_string "com.facebook.infer.builtins.InferUndefined" in
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 = function
| C {name}
when String.is_prefix ~prefix:Config.clang_initializer_prefix
(QualifiedCppName.to_qual_string name) ->
let name_str = QualifiedCppName.to_qual_string name in
let prefix_len = String.length Config.clang_initializer_prefix in
Some (String.sub name_str ~pos:prefix_len ~len:(String.length name_str - prefix_len))
| _ ->
None
(** Very verbose representation of an existing Procname.t *)
let rec pp_unique_id fmt = function
| Java j ->
Java.pp Verbose fmt j
| C osig ->
C.pp Verbose fmt osig
| ObjC_Cpp osig ->
ObjC_Cpp.pp Verbose fmt osig
| Block bsig ->
Block.pp Verbose fmt bsig
| WithBlockParameters (base, []) ->
pp_unique_id fmt base
| WithBlockParameters (base, (_ :: _ as blocks)) ->
pp_unique_id fmt base ;
F.pp_print_string fmt "_" ;
Pp.seq ~sep:"_" F.pp_print_string fmt blocks
| Linters_dummy_method ->
F.pp_print_string fmt "Linters_dummy_method"
let to_unique_id proc_name = F.asprintf "%a" pp_unique_id proc_name
(** Convert a proc name to a string for the user to see *)
let rec pp fmt = function
| Java j ->
Java.pp Non_verbose fmt j
| C osig ->
C.pp Non_verbose fmt osig
| ObjC_Cpp osig ->
ObjC_Cpp.pp Non_verbose fmt osig
| Block bsig ->
Block.pp Non_verbose fmt bsig
| WithBlockParameters (base, []) ->
pp fmt base
| WithBlockParameters (base, (_ :: _ as blocks)) ->
pp fmt base ;
F.pp_print_string fmt "_" ;
Pp.seq ~sep:"_" F.pp_print_string fmt blocks
| Linters_dummy_method ->
pp_unique_id fmt Linters_dummy_method
let to_string proc_name = F.asprintf "%a" pp proc_name
(** Convenient representation of a procname for external tools (e.g. eclipse plugin) *)
let rec pp_simplified_string ?(withclass = false) fmt = function
| Java j ->
Java.pp ~withclass Simple fmt j
| C osig ->
C.pp Simple fmt osig
| ObjC_Cpp osig ->
ObjC_Cpp.pp Simple fmt osig
| Block bsig ->
Block.pp Simple fmt bsig
| WithBlockParameters (base, _) ->
pp_simplified_string fmt base
| Linters_dummy_method ->
pp_unique_id fmt Linters_dummy_method
let to_simplified_string ?withclass proc_name =
F.asprintf "%a" (pp_simplified_string ?withclass) proc_name
let from_string_c_fun func = C (C.from_string func)
let java_inner_class_prefix_regex = Str.regexp "\\$[0-9]+"
let hashable_name proc_name =
match proc_name with
| Java pname -> (
(* Strip autogenerated anonymous inner class numbers in order to keep the bug hash
invariant when introducing new anonymous classes *)
let name = F.asprintf "%a" (Java.pp ~withclass:true Simple) pname in
match Str.search_forward java_inner_class_prefix_regex name 0 with
| _ ->
Str.global_replace java_inner_class_prefix_regex "$_" name
| exception Caml.Not_found ->
name )
| ObjC_Cpp m when ObjC_Cpp.is_objc_method m ->
(* In Objective C, the list of parameters is part of the method name. To prevent the bug
hash to change when a parameter is introduced or removed, only the part of the name
before the first colon is used for the bug hash *)
let name = F.asprintf "%a" (pp_simplified_string ~withclass:true) proc_name in
List.hd_exn (String.split_on_chars name ~on:[':'])
| _ ->
(* Other cases for C and C++ method names *)
F.asprintf "%a" (pp_simplified_string ~withclass:true) proc_name
let rec get_parameters procname =
let clang_param_to_param clang_params =
List.map ~f:(fun par -> Parameter.ClangParameter par) clang_params
in
match procname with
| Java j ->
List.map ~f:(fun par -> Parameter.JavaParameter par) (Java.get_parameters j)
| C osig ->
clang_param_to_param (C.get_parameters osig)
| ObjC_Cpp osig ->
clang_param_to_param (ObjC_Cpp.get_parameters osig)
| Block bsig ->
clang_param_to_param (Block.get_parameters bsig)
| WithBlockParameters (base, _) ->
get_parameters base
| Linters_dummy_method ->
[]
let rec replace_parameters new_parameters procname =
let params_to_java_params params =
List.map
~f:(fun param ->
match param with
| Parameter.JavaParameter par ->
par
| _ ->
Logging.(die InternalError)
"Expected Java parameters in Java procname, but got Clang parameters" params )
params
in
let params_to_clang_params params =
List.map
~f:(fun param ->
match param with
| Parameter.ClangParameter par ->
par
| _ ->
Logging.(die InternalError)
"Expected Clang parameters in Clang procname, but got Java parameters" params )
params
in
match procname with
| Java j ->
Java (Java.replace_parameters (params_to_java_params new_parameters) j)
| C osig ->
C (C.replace_parameters (params_to_clang_params new_parameters) osig)
| ObjC_Cpp osig ->
ObjC_Cpp (ObjC_Cpp.replace_parameters (params_to_clang_params new_parameters) osig)
| Block bsig ->
Block (Block.replace_parameters (params_to_clang_params new_parameters) bsig)
| WithBlockParameters (base, blocks) ->
WithBlockParameters (replace_parameters new_parameters base, blocks)
| Linters_dummy_method ->
procname
let parameter_of_name procname class_name =
match procname with
| Java _ ->
Parameter.JavaParameter (Java.java_type_of_name class_name)
| _ ->
Parameter.ClangParameter (Parameter.clang_param_of_name class_name)
let describe f pn =
let name = hashable_name pn in
match String.lsplit2 ~on:'<' name with
| Some (name_without_template, _template_part) ->
F.pp_print_string f name_without_template
| None ->
F.pp_print_string f name
module Hashable = struct
type nonrec t = t
let equal = equal
let hash = hash
end
module Hash = Hashtbl.Make (Hashable)
module Map = PrettyPrintable.MakePPMap (struct
type nonrec t = t
let compare = compare
let pp = pp
end)
module Set = PrettyPrintable.MakePPSet (struct
type nonrec t = t
let compare = compare
let pp = pp
end)
let get_qualifiers pname =
match pname with
| C {name} ->
name
| ObjC_Cpp objc_cpp ->
ObjC_Cpp.get_class_qualifiers objc_cpp
|> QualifiedCppName.append_qualifier ~qual:objc_cpp.method_name
| _ ->
QualifiedCppName.empty
(** Convert a proc name to a filename *)
let to_filename ?crc_only pname =
(* filenames for clang procs are REVERSED qualifiers with '#' as separator *)
let pp_rev_qualified fmt pname =
let rev_qualifiers = get_qualifiers pname |> QualifiedCppName.to_rev_list in
Pp.seq ~sep:"#" F.pp_print_string fmt rev_qualifiers
in
let proc_id =
match pname with
| C {parameters; mangled} ->
let pp_mangled fmt = function
| None ->
()
| Some mangled ->
F.fprintf fmt "#%s" mangled
in
F.asprintf "%a%a%a" pp_rev_qualified pname Parameter.pp_parameters parameters pp_mangled
mangled
| ObjC_Cpp objc_cpp ->
F.asprintf "%a%a#%a" pp_rev_qualified pname Parameter.pp_parameters objc_cpp.parameters
ObjC_Cpp.pp_verbose_kind objc_cpp.kind
| _ ->
F.asprintf "%a" pp_unique_id pname
in
Escape.escape_filename @@ DB.append_crc_cutoff ?crc_only proc_id
module SQLite = struct
module T = struct
type nonrec t = t
let compare = compare
let hash = hash
let sexp_of_t p = Sexp.Atom (F.asprintf "%a" pp p)
end
module Serializer = SqliteUtils.MarshalledDataForComparison (T)
let pname_to_key = Base.Hashtbl.create (module T)
let serialize pname =
let default () = Serializer.serialize pname in
Base.Hashtbl.find_or_add pname_to_key pname ~default
let deserialize = Serializer.deserialize
let clear_cache () = Base.Hashtbl.clear pname_to_key
end
module SQLiteList = SqliteUtils.MarshalledDataNOTForComparison (struct
type nonrec t = t list
end)
end

@ -137,9 +137,26 @@ val mk_array : ?default:t -> ?quals:type_quals -> ?length:IntLit.t -> ?stride:In
val void : t val void : t
(** void type *) (** void type *)
val java_byte : t
val java_short : t
val boolean : t
val char : t
val int : t
(** signed int type *)
val uint : t val uint : t
(** unsigned int type *) (** unsigned int type *)
val long : t
val float : t
val double : t
val void_star : t val void_star : t
(** void* type *) (** void* type *)
@ -186,6 +203,8 @@ module Name : sig
val get_template_spec_info : t -> template_spec_info option val get_template_spec_info : t -> template_spec_info option
val is_objc_protocol : t -> bool
module C : sig module C : sig
val from_string : string -> t val from_string : string -> t
@ -196,10 +215,12 @@ module Name : sig
module Java : sig module Java : sig
module Split : sig module Split : sig
type t type t [@@deriving compare]
val make : ?package:string -> string -> t val make : ?package:string -> string -> t
val of_string : string -> t
val java_lang_object : t val java_lang_object : t
val java_lang_string : t val java_lang_string : t
@ -209,6 +230,8 @@ module Name : sig
val package : t -> string option val package : t -> string option
val type_name : t -> string val type_name : t -> string
val pp_type_verbosity : verbose:bool -> F.formatter -> t -> unit
end end
val from_string : string -> t val from_string : string -> t
@ -230,6 +253,10 @@ module Name : sig
(** Given an inner classname like C$Inner1$Inner2, return Some C$Inner1. If the class is not an (** Given an inner classname like C$Inner1$Inner2, return Some C$Inner1. If the class is not an
inner class, return None *) inner class, return None *)
val is_anonymous_inner_class_name : t -> bool
val split_typename : t -> Split.t
val java_lang_object : t val java_lang_object : t
val java_io_serializable : t val java_io_serializable : t
@ -326,311 +353,3 @@ val has_block_prefix : string -> bool
val unsome : string -> t option -> t val unsome : string -> t option -> t
type typ = t type typ = t
module Procname : sig
(** Module for Procedure Names. *)
(** Type of java procedure names. *)
module Java : sig
type kind =
| Non_Static
(** in Java, procedures called with invokevirtual, invokespecial, and invokeinterface *)
| Static (** in Java, procedures called with invokestatic *)
type t [@@deriving compare]
type java_type = Name.Java.Split.t
val constructor_method_name : string
val class_initializer_method_name : string
val compare_java_type : java_type -> java_type -> int
val make : Name.t -> java_type option -> string -> java_type list -> kind -> t
(** Create a Java procedure name from its
class_name method_name args_type_name return_type_name method_kind. *)
val replace_method_name : string -> t -> t
(** Replace the method name of an existing java procname. *)
val replace_parameters : java_type list -> t -> t
(** Replace the parameters of a java procname. *)
val replace_return_type : java_type -> t -> t
(** Replace the method of a java procname. *)
val get_class_name : t -> string
(** Return the fully qualified class name of a java procedure name (package + class name) *)
val get_class_type_name : t -> Name.t
(** Return the class name as a typename of a java procedure name. *)
val get_simple_class_name : t -> string
(** Return the simple class name of a java procedure name (i.e. name without the package info). *)
val get_package : t -> string option
(** Return the package name of a java procedure name. *)
val get_method : t -> string
(** Return the method name of a java procedure name. *)
val get_parameters : t -> java_type list
(** Return the parameters of a java procedure name. *)
val get_return_typ : t -> typ
(** Return the return type of [pname_java]. return Tvoid if there's no return type *)
val is_constructor : t -> bool
(** Whether the method is constructor *)
val is_access_method : t -> bool
(** Check if the procedure name is an acess method (e.g. access$100 used to
access private members from a nested class. *)
val is_autogen_method : t -> bool
(** Check if the procedure name is of an auto-generated method containing '$'. *)
val is_anonymous_inner_class_constructor : t -> bool
(** Check if the procedure name is an anonymous inner class constructor. *)
val is_close : t -> bool
(** Check if the method name is "close". *)
val is_static : t -> bool
(** Check if the java procedure is static. *)
val is_vararg : 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[]. *)
val is_lambda : t -> bool
(** Check if the proc name comes from a lambda expression *)
val is_generated : t -> bool
(** Check if the proc name comes from generated code *)
val is_class_initializer : t -> bool
(** Check if this is a class initializer. *)
val get_class_initializer : Name.t -> t
(** Given a java class, generate the procname of its static initializer. *)
val is_external : t -> bool
(** Check if the method belongs to one of the specified external packages *)
end
module Parameter : sig
(** Type for parameters in clang procnames, [Some name] means the parameter is of type pointer to struct, with [name]
being the name of the struct, [None] means the parameter is of some other type. *)
type clang_parameter = Name.t option [@@deriving compare]
(** Type for parameters in procnames, for java and clang. *)
type t = JavaParameter of Java.java_type | ClangParameter of clang_parameter
[@@deriving compare]
val of_typ : typ -> clang_parameter
end
module ObjC_Cpp : sig
type kind =
| CPPMethod of {mangled: string option}
| CPPConstructor of {mangled: string option; is_constexpr: bool}
| CPPDestructor of {mangled: string option}
| ObjCClassMethod
| ObjCInstanceMethod
| ObjCInternalMethod
[@@deriving compare]
(** Type of Objective C and C++ procedure names: method signatures. *)
type t =
{ class_name: Name.t
; kind: kind
; method_name: string
; parameters: Parameter.clang_parameter list
; template_args: template_spec_info }
[@@deriving compare]
val make : Name.t -> string -> kind -> template_spec_info -> Parameter.clang_parameter list -> t
(** Create an objc procedure name from a class_name and method_name. *)
val get_class_name : t -> string
val get_class_type_name : t -> Name.t [@@warning "-32"]
val get_class_qualifiers : t -> QualifiedCppName.t
val objc_method_kind_of_bool : bool -> kind
(** Create ObjC method type from a bool is_instance. *)
val is_objc_constructor : string -> bool
(** Check if this is a constructor method in Objective-C. *)
val is_objc_dealloc : string -> bool
(** Check if this is a dealloc method in Objective-C. *)
val is_destructor : t -> bool
(** Check if this is a dealloc method. *)
val is_inner_destructor : t -> bool
(** Check if this is a frontend-generated "inner" destructor (see D5834555/D7189239) *)
val is_constexpr : t -> bool
(** Check if this is a constexpr function. *)
val is_cpp_lambda : t -> bool
(** Return whether the procname is a cpp lambda. *)
end
module C : sig
(** Type of c procedure names. *)
type t = private
{ name: QualifiedCppName.t
; mangled: string option
; parameters: Parameter.clang_parameter list
; template_args: template_spec_info }
val c :
QualifiedCppName.t -> string -> Parameter.clang_parameter list -> template_spec_info -> t
(** Create a C procedure name from plain and mangled name. *)
end
module Block : sig
(** Type of Objective C block names. *)
type block_name = string
type t = {name: block_name; parameters: Parameter.clang_parameter list} [@@deriving compare]
val make : block_name -> Parameter.clang_parameter list -> t
end
(** Type of procedure names.
WithBlockParameters is used for creating an instantiation of a method that contains block parameters
and it's called with concrete blocks. For example:
foo(Block block) {block();}
bar() {foo(my_block)} is executed as foo_my_block() {my_block(); }
where foo_my_block is created with WithBlockParameters (foo, [my_block]) *)
type t =
| Java of Java.t
| C of C.t
| Linters_dummy_method
| Block of Block.t
| ObjC_Cpp of ObjC_Cpp.t
| WithBlockParameters of t * Block.block_name list
[@@deriving compare]
val block_name_of_procname : t -> Block.block_name
val equal : t -> t -> bool
val get_class_type_name : t -> Name.t option
val get_class_name : t -> string option
val get_parameters : t -> Parameter.t list
val replace_parameters : Parameter.t list -> t -> t
val parameter_of_name : t -> Name.t -> Parameter.t
val is_java_access_method : t -> bool
val is_java_class_initializer : t -> bool
val is_objc_method : t -> bool
module Hash : Caml.Hashtbl.S with type key = t
(** Hash tables with proc names as keys. *)
module Map : PrettyPrintable.PPMap with type key = t
(** Maps from proc names. *)
module Set : PrettyPrintable.PPSet with type elt = t
(** Sets of proc names. *)
module SQLite : sig
val serialize : t -> Sqlite3.Data.t
val deserialize : Sqlite3.Data.t -> t
val clear_cache : unit -> unit
end
module SQLiteList : SqliteUtils.Data with type t = t list
val empty_block : t
(** Empty block name. *)
val get_language : t -> Language.t
(** Return the language of the procedure. *)
val get_method : t -> string
(** Return the method/function of a procname. *)
val is_objc_block : t -> bool
(** Return whether the procname is a block procname. *)
val is_c_method : t -> bool
(** Return true this is an Objective-C/C++ method name. *)
val is_clang : t -> bool
(** Return true if this is a C, C++, or Objective-C procedure name *)
val is_constructor : t -> bool
(** Check if this is a constructor. *)
val is_java : t -> bool
(** Check if this is a Java procedure name. *)
val with_block_parameters : t -> Block.block_name list -> t
(** Create a procedure name instantiated with block parameters from a base procedure name
and a list of block procedure names (the arguments). *)
val objc_cpp_replace_method_name : t -> string -> t
val is_infer_undefined : t -> bool
(** Check if this is a special Infer undefined procedure. *)
val get_global_name_of_initializer : t -> string option
(** Return the name of the global for which this procedure is the initializer if this is an
initializer, None otherwise. *)
val pp : Format.formatter -> t -> unit
(** Pretty print a proc name for the user to see. *)
val to_string : t -> string
(** Convert a proc name into a string for the user to see. *)
val describe : Format.formatter -> t -> unit
(** to use in user messages *)
val replace_class : t -> Name.t -> t
(** Replace the class name component of a procedure name.
In case of Java, replace package and class name. *)
val is_method_in_objc_protocol : t -> bool
val pp_simplified_string : ?withclass:bool -> F.formatter -> t -> unit
(** Pretty print a proc name as an easy string for the user to see in an IDE. *)
val to_simplified_string : ?withclass:bool -> t -> string
(** Convert a proc name into an easy string for the user to see in an IDE. *)
val from_string_c_fun : string -> t
(** Convert a string to a c function name. *)
val hashable_name : t -> string
(** Convert the procedure name in a format suitable for computing the bug hash. *)
val pp_unique_id : F.formatter -> t -> unit
(** Print a proc name as a unique identifier. *)
val to_unique_id : t -> string
(** Convert a proc name into a unique identifier. *)
val to_filename : ?crc_only:bool -> t -> string
(** Convert a proc name to a filename or only to its crc. *)
val get_qualifiers : t -> QualifiedCppName.t
(** get qualifiers of C/objc/C++ method/function *)
end

@ -54,7 +54,7 @@ let get_declaring_function = function
let is_local_to_procedure proc_name var = let is_local_to_procedure proc_name var =
get_declaring_function var |> Option.exists ~f:(Typ.Procname.equal proc_name) get_declaring_function var |> Option.exists ~f:(Procname.equal proc_name)
let get_all_vars_in_exp e = let get_all_vars_in_exp e =

@ -33,7 +33,7 @@ val get_pvar : t -> Pvar.t option
val is_global : t -> bool val is_global : t -> bool
val is_local_to_procedure : Typ.Procname.t -> t -> bool val is_local_to_procedure : Procname.t -> t -> bool
val is_return : t -> bool val is_return : t -> bool

@ -29,7 +29,7 @@ end = struct
L.(die InternalError) L.(die InternalError)
"Exceeded max widening threshold %d while analyzing %a. Please check your widening \ "Exceeded max widening threshold %d while analyzing %a. Please check your widening \
operator or increase the threshold" operator or increase the threshold"
Config.max_widens Typ.Procname.pp (Procdesc.get_proc_name pdesc) ; Config.max_widens Procname.pp (Procdesc.get_proc_name pdesc) ;
visit_count' visit_count'
end end
@ -217,7 +217,7 @@ module AbstractInterpreterCommon (TransferFunctions : TransferFunctions.SIL) = s
else if is_narrowing && not (Domain.leq ~lhs:new_pre ~rhs:old_state.State.pre) then ( else if is_narrowing && not (Domain.leq ~lhs:new_pre ~rhs:old_state.State.pre) then (
L.(debug Analysis Verbose) L.(debug Analysis Verbose)
"Terminate narrowing because old and new states are not comparable at %a:%a@." "Terminate narrowing because old and new states are not comparable at %a:%a@."
Typ.Procname.pp (Summary.get_proc_name summary) Node.pp_id node_id ; Procname.pp (Summary.get_proc_name summary) Node.pp_id node_id ;
(inv_map, ReachedFixPoint) ) (inv_map, ReachedFixPoint) )
else else
let visit_count' = let visit_count' =

@ -36,7 +36,7 @@ module Make (TransferFunctions : TransferFunctions.HIL) (HilConfig : HilConfig)
let is_java_unlock pname actuals = let is_java_unlock pname actuals =
(* would check is_java, but we want to include builtins too *) (* would check is_java, but we want to include builtins too *)
(not (Typ.Procname.is_c_method pname)) (not (Procname.is_c_method pname))
&& match ConcurrencyModels.get_lock_effect pname actuals with Unlock _ -> true | _ -> false && match ConcurrencyModels.get_lock_effect pname actuals with Unlock _ -> true | _ -> false

@ -178,8 +178,7 @@ let get_vararg_type_names tenv (call_node : Procdesc.Node.t) (ivar : Pvar.t) : s
|> Option.exists ~f:(fun t2 -> |> Option.exists ~f:(fun t2 ->
Instrs.exists instrs ~f:(function Instrs.exists instrs ~f:(function
| Sil.Call ((t1, _), Exp.Const (Const.Cfun pn), _, _, _) -> | Sil.Call ((t1, _), Exp.Const (Const.Cfun pn), _, _, _) ->
Ident.equal t1 t2 Ident.equal t1 t2 && Procname.equal pn (Procname.from_string_c_fun "__new_array")
&& Typ.Procname.equal pn (Typ.Procname.from_string_c_fun "__new_array")
| _ -> | _ ->
false ) ) false ) )
in in
@ -283,8 +282,8 @@ let method_is_initializer (tenv : Tenv.t) (proc_attributes : ProcAttributes.t) :
| Some this_type -> | Some this_type ->
if type_has_initializer tenv this_type then if type_has_initializer tenv this_type then
match proc_attributes.ProcAttributes.proc_name with match proc_attributes.ProcAttributes.proc_name with
| Typ.Procname.Java pname_java -> | Procname.Java pname_java ->
let mname = Typ.Procname.Java.get_method pname_java in let mname = Procname.Java.get_method pname_java in
List.exists ~f:(String.equal mname) initializer_methods List.exists ~f:(String.equal mname) initializer_methods
| _ -> | _ ->
false false
@ -313,7 +312,7 @@ let java_get_vararg_values node pvar idenv =
[] []
let proc_calls resolve_attributes pdesc filter : (Typ.Procname.t * ProcAttributes.t) list = let proc_calls resolve_attributes pdesc filter : (Procname.t * ProcAttributes.t) list =
let res = ref [] in let res = ref [] in
let do_instruction _ instr = let do_instruction _ instr =
match instr with match instr with
@ -335,13 +334,13 @@ let proc_calls resolve_attributes pdesc filter : (Typ.Procname.t * ProcAttribute
let is_override_of proc_name = let is_override_of proc_name =
let method_name = Typ.Procname.get_method proc_name in let method_name = Procname.get_method proc_name in
let parameter_length = List.length (Typ.Procname.get_parameters proc_name) in let parameter_length = List.length (Procname.get_parameters proc_name) in
Staged.stage (fun pname -> Staged.stage (fun pname ->
(not (Typ.Procname.is_constructor pname)) (not (Procname.is_constructor pname))
&& String.equal (Typ.Procname.get_method pname) method_name && String.equal (Procname.get_method pname) method_name
(* TODO (T32979782): match parameter types, taking subtyping and type erasure into account *) (* TODO (T32979782): match parameter types, taking subtyping and type erasure into account *)
&& Int.equal (List.length (Typ.Procname.get_parameters pname)) parameter_length ) && Int.equal (List.length (Procname.get_parameters pname)) parameter_length )
let override_find ?(check_current_type = true) f tenv proc_name = let override_find ?(check_current_type = true) f tenv proc_name =
@ -361,11 +360,10 @@ let override_find ?(check_current_type = true) f tenv proc_name =
if check_current_type && f proc_name then Some proc_name if check_current_type && f proc_name then Some proc_name
else else
match proc_name with match proc_name with
| Typ.Procname.Java proc_name_java -> | Procname.Java proc_name_java ->
find_super_type find_super_type (Typ.Name.Java.from_string (Procname.Java.get_class_name proc_name_java))
(Typ.Name.Java.from_string (Typ.Procname.Java.get_class_name proc_name_java)) | Procname.ObjC_Cpp proc_name_cpp ->
| Typ.Procname.ObjC_Cpp proc_name_cpp -> find_super_type (Procname.ObjC_Cpp.get_class_type_name proc_name_cpp)
find_super_type (Typ.Procname.ObjC_Cpp.get_class_type_name proc_name_cpp)
| _ -> | _ ->
None None
@ -421,9 +419,9 @@ let is_java_enum tenv typename = is_subtype_of_str tenv typename "java.lang.Enum
(** tests whether any class attributes (e.g., [@ThreadSafe]) pass check of first argument, including (** tests whether any class attributes (e.g., [@ThreadSafe]) pass check of first argument, including
for supertypes*) for supertypes*)
let check_class_attributes check tenv = function let check_class_attributes check tenv = function
| Typ.Procname.Java java_pname -> | Procname.Java java_pname ->
let check_class_annots _ {Struct.annots} = check annots in let check_class_annots _ {Struct.annots} = check annots in
supertype_exists tenv check_class_annots (Typ.Procname.Java.get_class_type_name java_pname) supertype_exists tenv check_class_annots (Procname.Java.get_class_type_name java_pname)
| _ -> | _ ->
false false
@ -431,8 +429,8 @@ let check_class_attributes check tenv = function
(** tests whether any class attributes (e.g., [@ThreadSafe]) pass check of first argument, for the (** tests whether any class attributes (e.g., [@ThreadSafe]) pass check of first argument, for the
current class only*) current class only*)
let check_current_class_attributes check tenv = function let check_current_class_attributes check tenv = function
| Typ.Procname.Java java_pname -> ( | Procname.Java java_pname -> (
match Tenv.lookup tenv (Typ.Procname.Java.get_class_type_name java_pname) with match Tenv.lookup tenv (Procname.Java.get_class_type_name java_pname) with
| Some struct_typ -> | Some struct_typ ->
check struct_typ.annots check struct_typ.annots
| _ -> | _ ->

@ -105,22 +105,22 @@ val java_get_vararg_values : Procdesc.Node.t -> Pvar.t -> Idenv.t -> Exp.t list
(** Get the values of a vararg parameter given the pvar used to assign the elements. *) (** Get the values of a vararg parameter given the pvar used to assign the elements. *)
val proc_calls : val proc_calls :
(Typ.Procname.t -> ProcAttributes.t option) (Procname.t -> ProcAttributes.t option)
-> Procdesc.t -> Procdesc.t
-> (Typ.Procname.t -> ProcAttributes.t -> bool) -> (Procname.t -> ProcAttributes.t -> bool)
-> (Typ.Procname.t * ProcAttributes.t) list -> (Procname.t * ProcAttributes.t) list
(** Return the callees that satisfy [filter]. *) (** Return the callees that satisfy [filter]. *)
val override_exists : val override_exists :
?check_current_type:bool -> (Typ.Procname.t -> bool) -> Tenv.t -> Typ.Procname.t -> bool ?check_current_type:bool -> (Procname.t -> bool) -> Tenv.t -> Procname.t -> bool
(** Return true if applying the given predicate to an override of [procname] (including [procname] (** Return true if applying the given predicate to an override of [procname] (including [procname]
itself when [check_current_type] is true, which it is by default) returns true. *) itself when [check_current_type] is true, which it is by default) returns true. *)
val override_iter : (Typ.Procname.t -> unit) -> Tenv.t -> Typ.Procname.t -> unit val override_iter : (Procname.t -> unit) -> Tenv.t -> Procname.t -> unit
(** Apply the given predicate to procname and each override of [procname]. For the moment, this only (** Apply the given predicate to procname and each override of [procname]. For the moment, this only
works for Java *) works for Java *)
val lookup_attributes : Tenv.t -> Typ.Procname.t -> ProcAttributes.t option val lookup_attributes : Tenv.t -> Procname.t -> ProcAttributes.t option
val type_get_annotation : Tenv.t -> Typ.t -> Annot.Item.t option val type_get_annotation : Tenv.t -> Typ.t -> Annot.Item.t option
@ -139,11 +139,11 @@ val is_throwable : Tenv.t -> Typ.Name.t -> bool
val is_java_enum : Tenv.t -> Typ.Name.t -> bool val is_java_enum : Tenv.t -> Typ.Name.t -> bool
(** Checks if the type is Java enum (extends java.lang.Enum) *) (** Checks if the type is Java enum (extends java.lang.Enum) *)
val check_class_attributes : (Annot.Item.t -> bool) -> Tenv.t -> Typ.Procname.t -> bool val check_class_attributes : (Annot.Item.t -> bool) -> Tenv.t -> Procname.t -> bool
(** tests whether any class attributes (e.g., [@ThreadSafe]) pass check of first argument, including (** tests whether any class attributes (e.g., [@ThreadSafe]) pass check of first argument, including
supertypes*) supertypes*)
val check_current_class_attributes : (Annot.Item.t -> bool) -> Tenv.t -> Typ.Procname.t -> bool val check_current_class_attributes : (Annot.Item.t -> bool) -> Tenv.t -> Procname.t -> bool
(** tests whether any class attributes (e.g., [@ThreadSafe]) pass check of first argument, for (** tests whether any class attributes (e.g., [@ThreadSafe]) pass check of first argument, for
current class only*) current class only*)
@ -151,4 +151,4 @@ val find_superclasses_with_attributes :
(Annot.Item.t -> bool) -> Tenv.t -> Typ.Name.t -> Typ.Name.t list (Annot.Item.t -> bool) -> Tenv.t -> Typ.Name.t -> Typ.Name.t list
(** find superclasss with attributes (e.g., [@ThreadSafe]), including current class*) (** find superclasss with attributes (e.g., [@ThreadSafe]), including current class*)
val is_override_of : Typ.Procname.t -> (Typ.Procname.t -> bool) Staged.t val is_override_of : Procname.t -> (Procname.t -> bool) Staged.t

@ -20,11 +20,11 @@ module type S = sig
val of_summary : Summary.t -> t option val of_summary : Summary.t -> t option
val read_full : caller_summary:Summary.t -> callee_pname:Typ.Procname.t -> (Procdesc.t * t) option val read_full : caller_summary:Summary.t -> callee_pname:Procname.t -> (Procdesc.t * t) option
val read : caller_summary:Summary.t -> callee_pname:Typ.Procname.t -> t option val read : caller_summary:Summary.t -> callee_pname:Procname.t -> t option
val read_toplevel_procedure : Typ.Procname.t -> t option val read_toplevel_procedure : Procname.t -> t option
end end
module Make (P : Payload) : S with type t = P.t = struct module Make (P : Payload) : S with type t = P.t = struct

@ -22,14 +22,14 @@ module type S = sig
val of_summary : Summary.t -> t option val of_summary : Summary.t -> t option
(** Read the corresponding part of the payload from the procedure summary *) (** Read the corresponding part of the payload from the procedure summary *)
val read_full : caller_summary:Summary.t -> callee_pname:Typ.Procname.t -> (Procdesc.t * t) option val read_full : caller_summary:Summary.t -> callee_pname:Procname.t -> (Procdesc.t * t) option
(** Return the proc desc and payload for the given procedure. Runs the analysis on-demand if (** Return the proc desc and payload for the given procedure. Runs the analysis on-demand if
necessary. *) necessary. *)
val read : caller_summary:Summary.t -> callee_pname:Typ.Procname.t -> t option val read : caller_summary:Summary.t -> callee_pname:Procname.t -> t option
(** Return the payload for the given procedure. Runs the analysis on-demand if necessary. *) (** Return the payload for the given procedure. Runs the analysis on-demand if necessary. *)
val read_toplevel_procedure : Typ.Procname.t -> t option val read_toplevel_procedure : Procname.t -> t option
end end
module Make (P : Payload) : S with type t = P.t module Make (P : Payload) : S with type t = P.t

@ -480,7 +480,7 @@ let log_frontend_issue method_decl_opt (node : Ctl_parser_types.ast_node)
| Some method_decl -> | Some method_decl ->
CType_decl.CProcname.from_decl_for_linters method_decl CType_decl.CProcname.from_decl_for_linters method_decl
| None -> | None ->
Typ.Procname.Linters_dummy_method Procname.Linters_dummy_method
in in
let issue_log', errlog = IssueLog.get_or_add ~proc:procname !issue_log in let issue_log', errlog = IssueLog.get_or_add ~proc:procname !issue_log in
issue_log := issue_log' ; issue_log := issue_log' ;

@ -768,11 +768,11 @@ let get_method_name_from_context context =
let is_objc_constructor context = let is_objc_constructor context =
Typ.Procname.ObjC_Cpp.is_objc_constructor (get_method_name_from_context context) Procname.ObjC_Cpp.is_objc_constructor (get_method_name_from_context context)
let is_objc_dealloc context = let is_objc_dealloc context =
Typ.Procname.ObjC_Cpp.is_objc_dealloc (get_method_name_from_context context) Procname.ObjC_Cpp.is_objc_dealloc (get_method_name_from_context context)
let is_in_method context name = let is_in_method context name =

@ -8,9 +8,9 @@ open! IStd
module F = Format module F = Format
module type NodeSig = sig module type NodeSig = sig
type t = private {id: int; pname: Typ.Procname.t; mutable successors: int list; mutable flag: bool} type t = private {id: int; pname: Procname.t; mutable successors: int list; mutable flag: bool}
val make : int -> Typ.Procname.t -> int list -> t val make : int -> Procname.t -> int list -> t
val add_successor : t -> int -> unit val add_successor : t -> int -> unit
@ -22,7 +22,7 @@ module type NodeSig = sig
end end
module Node : NodeSig = struct module Node : NodeSig = struct
type t = {id: int; pname: Typ.Procname.t; mutable successors: int list; mutable flag: bool} type t = {id: int; pname: Procname.t; mutable successors: int list; mutable flag: bool}
let make id pname successors = {id; pname; successors; flag= false} let make id pname successors = {id; pname; successors; flag= false}
@ -37,13 +37,13 @@ module Node : NodeSig = struct
let pp_edge fmt src dst = F.fprintf fmt " %a -> %a ;@\n" pp_id src pp_id dst in let pp_edge fmt src dst = F.fprintf fmt " %a -> %a ;@\n" pp_id src pp_id dst in
let pp_flag fmt flag = F.fprintf fmt "%B" flag in let pp_flag fmt flag = F.fprintf fmt "%B" flag in
F.fprintf fmt " %a [ label = %S, flag = %a ];@\n" pp_id id F.fprintf fmt " %a [ label = %S, flag = %a ];@\n" pp_id id
(F.asprintf "%a" Typ.Procname.pp pname) (F.asprintf "%a" Procname.pp pname)
pp_flag flag ; pp_flag flag ;
List.iter successors ~f:(pp_edge fmt id) ; List.iter successors ~f:(pp_edge fmt id) ;
F.pp_print_newline fmt () F.pp_print_newline fmt ()
end end
module IdMap = Typ.Procname.Hash module IdMap = Procname.Hash
module NodeMap = Caml.Hashtbl.Make (Int) module NodeMap = Caml.Hashtbl.Make (Int)
(** [node_map] is a map from ids (unique ints) to nodes corresponding to defined procedures. (** [node_map] is a map from ids (unique ints) to nodes corresponding to defined procedures.

@ -8,9 +8,9 @@ open! IStd
module F = Format module F = Format
module type NodeSig = sig module type NodeSig = sig
type t = private {id: int; pname: Typ.Procname.t; mutable successors: int list; mutable flag: bool} type t = private {id: int; pname: Procname.t; mutable successors: int list; mutable flag: bool}
val make : int -> Typ.Procname.t -> int list -> t val make : int -> Procname.t -> int list -> t
val add_successor : t -> int -> unit val add_successor : t -> int -> unit
@ -37,15 +37,15 @@ val n_procs : t -> int
val mem : t -> int -> bool val mem : t -> int -> bool
(** is an int [id] the index of a node in the graph? *) (** is an int [id] the index of a node in the graph? *)
val flag : t -> Typ.Procname.t -> unit val flag : t -> Procname.t -> unit
val flag_reachable : t -> Typ.Procname.t -> unit val flag_reachable : t -> Procname.t -> unit
(** flag all nodes reachable from the node of the given procname, if it exists *) (** flag all nodes reachable from the node of the given procname, if it exists *)
val get_unflagged_leaves : t -> Node.t list val get_unflagged_leaves : t -> Node.t list
(** get all leaves that have their flag set to false *) (** get all leaves that have their flag set to false *)
val remove : t -> Typ.Procname.t -> unit val remove : t -> Procname.t -> unit
val to_dotty : t -> string -> unit val to_dotty : t -> string -> unit
(** output call graph in dotty format with the given filename in results dir *) (** output call graph in dotty format with the given filename in results dir *)
@ -56,11 +56,11 @@ val trim_id_map : t -> unit
val remove_unflagged_and_unflag_all : t -> unit val remove_unflagged_and_unflag_all : t -> unit
(** remove all nodes with flag set to false, and set flag to false on all remaining nodes *) (** remove all nodes with flag set to false, and set flag to false on all remaining nodes *)
val add_edge : t -> pname:Typ.Procname.t -> successor_pname:Typ.Procname.t -> unit val add_edge : t -> pname:Procname.t -> successor_pname:Procname.t -> unit
(** add an edge from [pname] to [successor_pname] in the graph, creating a node for [pname] if there (** add an edge from [pname] to [successor_pname] in the graph, creating a node for [pname] if there
isn't one already *) isn't one already *)
val create_node : t -> Typ.Procname.t -> Typ.Procname.t list -> unit val create_node : t -> Procname.t -> Procname.t list -> unit
(** create a new node with edges from [pname] to [successor_pnames] in the graph *) (** create a new node with edges from [pname] to [successor_pnames] in the graph *)
val fold_flagged : t -> f:(Node.t -> 'a -> 'a) -> 'a -> 'a val fold_flagged : t -> f:(Node.t -> 'a -> 'a) -> 'a -> 'a

@ -259,8 +259,8 @@ let issue_of_cost kind CostIssues.{complexity_increase_issue; zero_issue; infini
in in
let msg = let msg =
(* Java Only *) (* Java Only *)
if String.equal method_name Typ.Procname.Java.constructor_method_name then "constructor" if String.equal method_name Procname.Java.constructor_method_name then "constructor"
else if String.equal method_name Typ.Procname.Java.class_initializer_method_name then else if String.equal method_name Procname.Java.class_initializer_method_name then
"class initializer" "class initializer"
else "this function" else "this function"
in in

@ -8,9 +8,9 @@ open! IStd
module L = Logging module L = Logging
module PerfProfilerDataMap = Caml.Map.Make (struct module PerfProfilerDataMap = Caml.Map.Make (struct
type t = Typ.Procname.t type t = Procname.t
let compare = Typ.Procname.compare let compare = Procname.compare
end) end)
let global_perf_profiler_data : Perf_profiler_t.perf_profiler_item PerfProfilerDataMap.t ref = let global_perf_profiler_data : Perf_profiler_t.perf_profiler_item PerfProfilerDataMap.t ref =

@ -7,4 +7,4 @@
open! IStd open! IStd
val in_profiler_data_map : Typ.Procname.t -> bool val in_profiler_data_map : Procname.t -> bool

@ -13,9 +13,7 @@ module F = Format
module L = Logging module L = Logging
let clear_caches () = let clear_caches () =
Ondemand.LocalCache.clear () ; Ondemand.LocalCache.clear () ; Summary.OnDisk.clear_cache () ; Procname.SQLite.clear_cache ()
Summary.OnDisk.clear_cache () ;
Typ.Procname.SQLite.clear_cache ()
let analyze_target : SchedulerTypes.target Tasks.doer = let analyze_target : SchedulerTypes.target Tasks.doer =
@ -37,7 +35,7 @@ let analyze_target : SchedulerTypes.target Tasks.doer =
decr procs_left ; decr procs_left ;
if Int.( <= ) !procs_left 0 then ( if Int.( <= ) !procs_left 0 then (
L.log_task "Analysing block of %d procs, starting with %a@." per_procedure_logging_granularity L.log_task "Analysing block of %d procs, starting with %a@." per_procedure_logging_granularity
Typ.Procname.pp proc_name ; Procname.pp proc_name ;
procs_left := per_procedure_logging_granularity ) ; procs_left := per_procedure_logging_granularity ) ;
Ondemand.analyze_proc_name_toplevel exe_env proc_name Ondemand.analyze_proc_name_toplevel exe_env proc_name
in in

@ -23,16 +23,16 @@ let error_desc_to_plain_string error_desc =
let error_desc_to_dotty_string error_desc = Localise.error_desc_get_dotty error_desc let error_desc_to_dotty_string error_desc = Localise.error_desc_get_dotty error_desc
let compute_key (bug_type : string) (proc_name : Typ.Procname.t) (filename : string) = let compute_key (bug_type : string) (proc_name : Procname.t) (filename : string) =
let base_filename = Filename.basename filename let base_filename = Filename.basename filename
and simple_procedure_name = Typ.Procname.get_method proc_name in and simple_procedure_name = Procname.get_method proc_name in
String.concat ~sep:"|" [base_filename; simple_procedure_name; bug_type] String.concat ~sep:"|" [base_filename; simple_procedure_name; bug_type]
let compute_hash ~(severity : string) ~(bug_type : string) ~(proc_name : Typ.Procname.t) let compute_hash ~(severity : string) ~(bug_type : string) ~(proc_name : Procname.t)
~(file : string) ~(qualifier : string) = ~(file : string) ~(qualifier : string) =
let base_filename = Filename.basename file in let base_filename = Filename.basename file in
let hashable_procedure_name = Typ.Procname.hashable_name proc_name in let hashable_procedure_name = Procname.hashable_name proc_name in
let location_independent_qualifier = let location_independent_qualifier =
(* Removing the line,column, and infer temporary variable (e.g., n$67) information from the (* Removing the line,column, and infer temporary variable (e.g., n$67) information from the
error message as well as the index of the annonymmous class to make the hash invariant error message as well as the index of the annonymmous class to make the hash invariant
@ -97,8 +97,8 @@ let summary_values summary =
let pp fmt = Pp.seq pp_line fmt lines_visited in let pp fmt = Pp.seq pp_line fmt lines_visited in
F.asprintf "%t" pp F.asprintf "%t" pp
in in
{ vname= Typ.Procname.to_string proc_name { vname= Procname.to_string proc_name
; vname_id= Typ.Procname.to_filename proc_name ; vname_id= Procname.to_filename proc_name
; vspecs= List.length specs ; vspecs= List.length specs
; vto= Summary.Stats.failure_kind_to_string stats ; vto= Summary.Stats.failure_kind_to_string stats
; vsymop= Summary.Stats.symops stats ; vsymop= Summary.Stats.symops stats
@ -213,17 +213,17 @@ end
type json_issue_printer_typ = type json_issue_printer_typ =
{ error_filter: SourceFile.t -> IssueType.t -> bool { error_filter: SourceFile.t -> IssueType.t -> bool
; proc_name: Typ.Procname.t ; proc_name: Procname.t
; proc_loc_opt: Location.t option ; proc_loc_opt: Location.t option
; err_key: Errlog.err_key ; err_key: Errlog.err_key
; err_data: Errlog.err_data } ; err_data: Errlog.err_data }
let procedure_id_of_procname proc_name = let procedure_id_of_procname proc_name =
match Typ.Procname.get_language proc_name with match Procname.get_language proc_name with
| Language.Java -> | Language.Java ->
Typ.Procname.to_unique_id proc_name Procname.to_unique_id proc_name
| _ -> | _ ->
Typ.Procname.to_string proc_name Procname.to_string proc_name
module JsonIssuePrinter = MakeJsonListPrinter (struct module JsonIssuePrinter = MakeJsonListPrinter (struct
@ -314,14 +314,14 @@ module IssuesJson = struct
end end
type json_costs_printer_typ = type json_costs_printer_typ =
{loc: Location.t; proc_name: Typ.Procname.t; cost_opt: CostDomain.summary option} {loc: Location.t; proc_name: Procname.t; cost_opt: CostDomain.summary option}
module JsonCostsPrinter = MakeJsonListPrinter (struct module JsonCostsPrinter = MakeJsonListPrinter (struct
type elt = json_costs_printer_typ type elt = json_costs_printer_typ
let to_string {loc; proc_name; cost_opt} = let to_string {loc; proc_name; cost_opt} =
match cost_opt with match cost_opt with
| Some {post; is_on_ui_thread} when not (Typ.Procname.is_java_access_method proc_name) -> | Some {post; is_on_ui_thread} when not (Procname.is_java_access_method proc_name) ->
let hum cost = let hum cost =
let degree_with_term = CostDomain.BasicCost.get_degree_with_term cost in let degree_with_term = CostDomain.BasicCost.get_degree_with_term cost in
{ Jsonbug_t.hum_polynomial= Format.asprintf "%a" CostDomain.BasicCost.pp_hum cost { Jsonbug_t.hum_polynomial= Format.asprintf "%a" CostDomain.BasicCost.pp_hum cost
@ -344,7 +344,7 @@ module JsonCostsPrinter = MakeJsonListPrinter (struct
let file = SourceFile.to_rel_path loc.Location.file in let file = SourceFile.to_rel_path loc.Location.file in
{ Jsonbug_t.hash= compute_hash ~severity:"" ~bug_type:"" ~proc_name ~file ~qualifier:"" { Jsonbug_t.hash= compute_hash ~severity:"" ~bug_type:"" ~proc_name ~file ~qualifier:""
; loc= {file; lnum= loc.Location.line; cnum= loc.Location.col; enum= -1} ; loc= {file; lnum= loc.Location.line; cnum= loc.Location.col; enum= -1}
; procedure_name= Typ.Procname.get_method proc_name ; procedure_name= Procname.get_method proc_name
; procedure_id= procedure_id_of_procname proc_name ; procedure_id= procedure_id_of_procname proc_name
; is_on_ui_thread ; is_on_ui_thread
; exec_cost= cost_info (CostDomain.get_cost_kind CostKind.OperationCost post) ; exec_cost= cost_info (CostDomain.get_cost_kind CostKind.OperationCost post)
@ -599,7 +599,7 @@ module StatsLogs = struct
ClangMethodKind.to_string (Summary.get_attributes summary).clang_method_kind ClangMethodKind.to_string (Summary.get_attributes summary).clang_method_kind
in in
let proc_name = Summary.get_proc_name summary in let proc_name = Summary.get_proc_name summary in
let lang = Typ.Procname.get_language proc_name in let lang = Procname.get_language proc_name in
let stats = let stats =
EventLogger.AnalysisStats EventLogger.AnalysisStats
{ analysis_nodes_visited= Summary.Stats.nb_visited summary.stats { analysis_nodes_visited= Summary.Stats.nb_visited summary.stats
@ -608,7 +608,7 @@ module StatsLogs = struct
; clang_method_kind= (match lang with Language.Clang -> Some clang_method_kind | _ -> None) ; clang_method_kind= (match lang with Language.Clang -> Some clang_method_kind | _ -> None)
; lang= Language.to_explicit_string lang ; lang= Language.to_explicit_string lang
; method_location= Summary.get_loc summary ; method_location= Summary.get_loc summary
; method_name= Typ.Procname.to_string proc_name ; method_name= Procname.to_string proc_name
; num_preposts ; num_preposts
; symops= Summary.Stats.symops summary.stats } ; symops= Summary.Stats.symops summary.stats }
in in
@ -642,16 +642,16 @@ module PreconditionStats = struct
match Prop.CategorizePreconditions.categorize preconditions with match Prop.CategorizePreconditions.categorize preconditions with
| Prop.CategorizePreconditions.Empty -> | Prop.CategorizePreconditions.Empty ->
incr nr_empty ; incr nr_empty ;
L.result "Procedure: %a footprint:Empty@." Typ.Procname.pp proc_name L.result "Procedure: %a footprint:Empty@." Procname.pp proc_name
| Prop.CategorizePreconditions.OnlyAllocation -> | Prop.CategorizePreconditions.OnlyAllocation ->
incr nr_onlyallocation ; incr nr_onlyallocation ;
L.result "Procedure: %a footprint:OnlyAllocation@." Typ.Procname.pp proc_name L.result "Procedure: %a footprint:OnlyAllocation@." Procname.pp proc_name
| Prop.CategorizePreconditions.NoPres -> | Prop.CategorizePreconditions.NoPres ->
incr nr_nopres ; incr nr_nopres ;
L.result "Procedure: %a footprint:NoPres@." Typ.Procname.pp proc_name L.result "Procedure: %a footprint:NoPres@." Procname.pp proc_name
| Prop.CategorizePreconditions.DataConstraints -> | Prop.CategorizePreconditions.DataConstraints ->
incr nr_dataconstraints ; incr nr_dataconstraints ;
L.result "Procedure: %a footprint:DataConstraints@." Typ.Procname.pp proc_name L.result "Procedure: %a footprint:DataConstraints@." Procname.pp proc_name
let pp_stats () = let pp_stats () =
@ -819,7 +819,7 @@ module SummaryStats = struct
let do_summary proc_name summary = results := MetricResults.add !results proc_name summary let do_summary proc_name summary = results := MetricResults.add !results proc_name summary
let pp_stats () = L.result "%a@\n" (MetricResults.pp ~pp_k:Typ.Procname.pp) !results let pp_stats () = L.result "%a@\n" (MetricResults.pp ~pp_k:Procname.pp) !results
end end
let error_filter filters proc_name file error_name = let error_filter filters proc_name file error_name =
@ -953,7 +953,7 @@ let pp_stats error_filter linereader summary stats stats_format_list =
let pp_summary summary = let pp_summary summary =
L.result "Procedure: %a@\n%a@." Typ.Procname.pp (Summary.get_proc_name summary) Summary.pp_text L.result "Procedure: %a@\n%a@." Procname.pp (Summary.get_proc_name summary) Summary.pp_text
summary summary

@ -9,7 +9,7 @@ open! IStd
module L = Logging module L = Logging
type t = type t =
{ proc_name: Typ.Procname.t { proc_name: Procname.t
; proc_location: Location.t ; proc_location: Location.t
; err_key: Errlog.err_key ; err_key: Errlog.err_key
; err_data: Errlog.err_data } ; err_data: Errlog.err_data }
@ -23,7 +23,7 @@ let compare_err_data_ (err_data1 : Errlog.err_data) (err_data2 : Errlog.err_data
Location.compare err_data1.loc err_data2.loc Location.compare err_data1.loc err_data2.loc
type proc_name_ = Typ.Procname.t type proc_name_ = Procname.t
(* ignore proc name *) (* ignore proc name *)
let compare_proc_name_ _ _ = 0 let compare_proc_name_ _ _ = 0

@ -8,7 +8,7 @@
open! IStd open! IStd
type t = type t =
{ proc_name: Typ.Procname.t { proc_name: Procname.t
; proc_location: Location.t ; proc_location: Location.t
; err_key: Errlog.err_key ; err_key: Errlog.err_key
; err_data: Errlog.err_data } ; err_data: Errlog.err_data }

@ -32,17 +32,17 @@ let try_capture (attributes : ProcAttributes.t) : ProcAttributes.t option =
(* peek at the results to know if capture succeeded, but only in debug mode *) (* peek at the results to know if capture succeeded, but only in debug mode *)
L.(debug Capture Verbose) L.(debug Capture Verbose)
"Captured file %a to get procedure %a but it wasn't found there@\n" SourceFile.pp "Captured file %a to get procedure %a but it wasn't found there@\n" SourceFile.pp
definition_file Typ.Procname.pp attributes.proc_name ) definition_file Procname.pp attributes.proc_name )
else else
L.(debug Capture Verbose) L.(debug Capture Verbose)
"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 Typ.Procname.pp attributes.proc_name SourceFile.pp definition_file Procname.pp attributes.proc_name
in in
match definition_file_opt with match definition_file_opt with
| None -> | None ->
L.(debug Capture Medium) L.(debug Capture Medium)
"Couldn't find source file for %a (declared in %a)@\n" Typ.Procname.pp "Couldn't find source file for %a (declared in %a)@\n" Procname.pp attributes.proc_name
attributes.proc_name SourceFile.pp decl_file SourceFile.pp decl_file
| Some file -> | Some file ->
try_compile file ) ; try_compile file ) ;
(* It's important to call load_defined_attributes again in all cases to make sure we try (* It's important to call load_defined_attributes again in all cases to make sure we try

@ -13,7 +13,7 @@ let get_all ~filter () =
SqliteUtils.result_fold_rows db ~log:"reading all procedure names" stmt ~init:[] SqliteUtils.result_fold_rows db ~log:"reading all procedure names" stmt ~init:[]
~f:(fun rev_results stmt -> ~f:(fun rev_results stmt ->
let source_file = Sqlite3.column stmt 0 |> SourceFile.SQLite.deserialize in let source_file = Sqlite3.column stmt 0 |> SourceFile.SQLite.deserialize in
let proc_name = Sqlite3.column stmt 1 |> Typ.Procname.SQLite.deserialize in let proc_name = Sqlite3.column stmt 1 |> Procname.SQLite.deserialize in
if filter source_file proc_name then proc_name :: rev_results else rev_results ) if filter source_file proc_name then proc_name :: rev_results else rev_results )
@ -35,7 +35,7 @@ let pp_all ~filter ~proc_name:proc_name_cond ~attr_kind ~source_file:source_file
Format.fprintf fmt "@[<v2>%s@,%a%a%a%a@]@\n" proc_name_hum Format.fprintf fmt "@[<v2>%s@,%a%a%a%a@]@\n" proc_name_hum
(pp_if source_file_cond "source_file" SourceFile.pp) (pp_if source_file_cond "source_file" SourceFile.pp)
source_file source_file
(pp_if proc_name_cond "proc_name" Typ.Procname.pp) (pp_if proc_name_cond "proc_name" Procname.pp)
proc_name proc_name
(pp_column_if stmt attr_kind "attribute_kind" Attributes.deserialize_attributes_kind (pp_column_if stmt attr_kind "attribute_kind" Attributes.deserialize_attributes_kind
Attributes.pp_attributes_kind) Attributes.pp_attributes_kind)
@ -50,6 +50,6 @@ let pp_all ~filter ~proc_name:proc_name_cond ~attr_kind ~source_file:source_file
"SELECT proc_name, proc_name_hum, attr_kind, source_file, proc_attributes FROM procedures" "SELECT proc_name, proc_name_hum, attr_kind, source_file, proc_attributes FROM procedures"
|> Container.iter ~fold:(SqliteUtils.result_fold_rows db ~log:"print all procedures") |> Container.iter ~fold:(SqliteUtils.result_fold_rows db ~log:"print all procedures")
~f:(fun stmt -> ~f:(fun stmt ->
let proc_name = Sqlite3.column stmt 0 |> Typ.Procname.SQLite.deserialize in let proc_name = Sqlite3.column stmt 0 |> Procname.SQLite.deserialize in
let source_file = Sqlite3.column stmt 3 |> SourceFile.SQLite.deserialize in let source_file = Sqlite3.column stmt 3 |> SourceFile.SQLite.deserialize in
if filter source_file proc_name then pp_row stmt fmt source_file proc_name ) if filter source_file proc_name then pp_row stmt fmt source_file proc_name )

@ -7,7 +7,7 @@
open! IStd open! IStd
val get_all : filter:Filtering.procedures_filter -> unit -> Typ.Procname.t list val get_all : filter:Filtering.procedures_filter -> unit -> Procname.t list
val pp_all : val pp_all :
filter:Filtering.procedures_filter filter:Filtering.procedures_filter

@ -9,7 +9,7 @@ open! IStd
let register_summary graph summary = let register_summary graph summary =
let caller_pname = Summary.get_proc_name summary in let caller_pname = Summary.get_proc_name summary in
let callee_pnames = summary.Summary.callee_pnames in let callee_pnames = summary.Summary.callee_pnames in
Typ.Procname.Set.iter Procname.Set.iter
(fun callee_pname -> CallGraph.add_edge graph ~pname:callee_pname ~successor_pname:caller_pname) (fun callee_pname -> CallGraph.add_edge graph ~pname:callee_pname ~successor_pname:caller_pname)
callee_pnames callee_pnames

@ -6,4 +6,4 @@
*) *)
open! IStd open! IStd
type target = Procname of Typ.Procname.t | File of SourceFile.t type target = Procname of Procname.t | File of SourceFile.t

@ -14,6 +14,6 @@ val iter_from_config : f:(Summary.t -> unit) -> unit
(** Iterates over all sumaries from the .specs files unless a list of specs files has been passed on (** Iterates over all sumaries from the .specs files unless a list of specs files has been passed on
the command line *) the command line *)
val delete : Typ.Procname.t -> unit val delete : Procname.t -> unit
(** Delete the .specs file associated with a summary and remove the summary from the caches in (** Delete the .specs file associated with a summary and remove the summary from the caches in
Summary.ml and ondemand.ml *) Summary.ml and ondemand.ml *)

@ -71,7 +71,7 @@ include struct
; status: Status.t ; status: Status.t
; proc_desc: Procdesc.t ; proc_desc: Procdesc.t
; err_log: Errlog.t ; err_log: Errlog.t
; mutable callee_pnames: Typ.Procname.Set.t } ; mutable callee_pnames: Procname.Set.t }
[@@deriving fields] [@@deriving fields]
end end
@ -102,7 +102,7 @@ let pp_errlog fmt err_log =
let pp_signature fmt summary = let pp_signature fmt summary =
let pp_formal fmt (p, typ) = F.fprintf fmt "%a %a" (Typ.pp_full Pp.text) typ Mangled.pp p in let pp_formal fmt (p, typ) = F.fprintf fmt "%a %a" (Typ.pp_full Pp.text) typ Mangled.pp p in
F.fprintf fmt "%a %a(%a)" (Typ.pp_full Pp.text) (get_ret_type summary) Typ.Procname.pp F.fprintf fmt "%a %a(%a)" (Typ.pp_full Pp.text) (get_ret_type summary) Procname.pp
(get_proc_name summary) (Pp.seq ~sep:", " pp_formal) (get_formals summary) (get_proc_name summary) (Pp.seq ~sep:", " pp_formal) (get_formals summary)
@ -133,21 +133,21 @@ let pp_html source fmt summary =
module OnDisk = struct module OnDisk = struct
open PolyVariantEqual open PolyVariantEqual
type cache = t Typ.Procname.Hash.t type cache = t Procname.Hash.t
let cache : cache = Typ.Procname.Hash.create 128 let cache : cache = Procname.Hash.create 128
let clear_cache () = Typ.Procname.Hash.clear cache let clear_cache () = Procname.Hash.clear cache
let remove_from_cache pname = Typ.Procname.Hash.remove cache pname let remove_from_cache pname = Procname.Hash.remove cache pname
(** Add the summary to the table for the given function *) (** Add the summary to the table for the given function *)
let add (proc_name : Typ.Procname.t) (summary : t) : unit = let add (proc_name : Procname.t) (summary : t) : unit =
Typ.Procname.Hash.replace cache proc_name summary Procname.Hash.replace cache proc_name summary
let specs_filename pname = let specs_filename pname =
let pname_file = Typ.Procname.to_filename pname in let pname_file = Procname.to_filename pname in
pname_file ^ Config.specs_files_suffix pname_file ^ Config.specs_files_suffix
@ -213,7 +213,7 @@ module OnDisk = struct
let get proc_name = let get proc_name =
match Typ.Procname.Hash.find cache proc_name with match Procname.Hash.find cache proc_name with
| summary -> | summary ->
BackendStats.incr_summary_cache_hits () ; BackendStats.incr_summary_cache_hits () ;
Some summary Some summary
@ -258,15 +258,15 @@ module OnDisk = struct
; status= Status.Pending ; status= Status.Pending
; proc_desc ; proc_desc
; err_log= Errlog.empty () ; err_log= Errlog.empty ()
; callee_pnames= Typ.Procname.Set.empty } ; callee_pnames= Procname.Set.empty }
in in
Typ.Procname.Hash.replace cache (Procdesc.get_proc_name proc_desc) summary ; Procname.Hash.replace cache (Procdesc.get_proc_name proc_desc) summary ;
summary summary
let dummy = let dummy =
let dummy_attributes = let dummy_attributes =
ProcAttributes.default (SourceFile.invalid __FILE__) Typ.Procname.empty_block ProcAttributes.default (SourceFile.invalid __FILE__) Procname.empty_block
in in
let dummy_proc_desc = Procdesc.from_proc_attributes dummy_attributes in let dummy_proc_desc = Procdesc.from_proc_attributes dummy_attributes in
reset dummy_proc_desc reset dummy_proc_desc

@ -47,11 +47,11 @@ type t =
; status: Status.t ; status: Status.t
; proc_desc: Procdesc.t ; proc_desc: Procdesc.t
; err_log: Errlog.t ; err_log: Errlog.t
; mutable callee_pnames: Typ.Procname.Set.t } ; mutable callee_pnames: Procname.Set.t }
val poly_fields : t PolyFields.t val poly_fields : t PolyFields.t
val get_proc_name : t -> Typ.Procname.t val get_proc_name : t -> Procname.t
(** Get the procedure name *) (** Get the procedure name *)
val get_proc_desc : t -> Procdesc.t val get_proc_desc : t -> Procdesc.t
@ -79,29 +79,29 @@ val pp_text : Format.formatter -> t -> unit
(** Print the summary in text format *) (** Print the summary in text format *)
module OnDisk : sig module OnDisk : sig
val has_model : Typ.Procname.t -> bool val has_model : Procname.t -> bool
(** 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 clear_cache : unit -> unit val clear_cache : unit -> unit
(** Remove all the elements from the cache of summaries *) (** Remove all the elements from the cache of summaries *)
val remove_from_cache : Typ.Procname.t -> unit val remove_from_cache : Procname.t -> unit
(** Remove an element from the cache of summaries. Contrast to reset which re-initializes a (** Remove an element from the cache of summaries. Contrast to reset which re-initializes a
summary keeping the same Procdesc and updates the cache accordingly. *) summary keeping the same Procdesc and updates the cache accordingly. *)
val get : Typ.Procname.t -> t option val get : Procname.t -> t option
(** Return the summary option for the procedure name *) (** Return the summary option for the procedure name *)
val reset : Procdesc.t -> t val reset : Procdesc.t -> t
(** 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 specs_filename_of_procname : Typ.Procname.t -> DB.filename val specs_filename_of_procname : Procname.t -> DB.filename
(** Return the path to the .specs file for the given procedure in the current results directory *) (** Return the path to the .specs file for the given procedure in the current results directory *)
val load_from_file : DB.filename -> t option val load_from_file : DB.filename -> t option
(** Load procedure summary from the given file *) (** Load procedure summary from the given file *)
val proc_resolve_attributes : Typ.Procname.t -> ProcAttributes.t option val proc_resolve_attributes : Procname.t -> ProcAttributes.t option
(** Try to find the attributes for a defined proc. First look at specs (to get attributes computed (** Try to find the attributes for a defined proc. First look at specs (to get attributes computed
by analysis) then look at the attributes table. If no attributes can be found, return None. *) by analysis) then look at the attributes table. If no attributes can be found, return None. *)

@ -6,11 +6,11 @@
*) *)
open! IStd open! IStd
module L = Logging module L = Logging
module IdMap = Typ.Procname.Hash module IdMap = Procname.Hash
let build_from_captured_procs g = let build_from_captured_procs g =
let hashcons_pname = let hashcons_pname =
let pname_tbl : Typ.Procname.t IdMap.t = IdMap.create 1001 in let pname_tbl : Procname.t IdMap.t = IdMap.create 1001 in
fun pname -> fun pname ->
match IdMap.find_opt pname_tbl pname with match IdMap.find_opt pname_tbl pname with
| Some pname' -> | Some pname' ->
@ -21,9 +21,9 @@ let build_from_captured_procs g =
let db = ResultsDatabase.get_database () in let db = ResultsDatabase.get_database () in
let stmt = Sqlite3.prepare db "SELECT proc_name, callees FROM procedures" in let stmt = Sqlite3.prepare db "SELECT proc_name, callees FROM procedures" in
SqliteUtils.result_fold_rows db ~log:"creating call graph" stmt ~init:() ~f:(fun () stmt -> SqliteUtils.result_fold_rows db ~log:"creating call graph" stmt ~init:() ~f:(fun () stmt ->
let proc_name = Sqlite3.column stmt 0 |> Typ.Procname.SQLite.deserialize |> hashcons_pname in let proc_name = Sqlite3.column stmt 0 |> Procname.SQLite.deserialize |> hashcons_pname in
let callees = let callees =
Sqlite3.column stmt 1 |> Typ.Procname.SQLiteList.deserialize |> List.map ~f:hashcons_pname Sqlite3.column stmt 1 |> Procname.SQLiteList.deserialize |> List.map ~f:hashcons_pname
in in
CallGraph.create_node g proc_name callees ) CallGraph.create_node g proc_name callees )
@ -66,9 +66,9 @@ let bottom_up sources : SchedulerTypes.target ProcessPool.TaskGenerator.t =
let syntactic_call_graph = CallGraph.create CallGraph.default_initial_capacity in let syntactic_call_graph = CallGraph.create CallGraph.default_initial_capacity in
let initialized = ref false in let initialized = ref false in
let pending : CallGraph.Node.t list ref = ref [] in let pending : CallGraph.Node.t list ref = ref [] in
let scheduled = ref Typ.Procname.Set.empty in let scheduled = ref Procname.Set.empty in
let is_empty () = let is_empty () =
let empty = !initialized && List.is_empty !pending && Typ.Procname.Set.is_empty !scheduled in let empty = !initialized && List.is_empty !pending && Procname.Set.is_empty !scheduled in
if empty then ( if empty then (
remaining := 0 ; remaining := 0 ;
L.progress "Finished call graph scheduling, %d procs remaining (in, or reaching, cycles).@." L.progress "Finished call graph scheduling, %d procs remaining (in, or reaching, cycles).@."
@ -88,7 +88,7 @@ let bottom_up sources : SchedulerTypes.target ProcessPool.TaskGenerator.t =
next_aux () next_aux ()
| n :: ns -> | n :: ns ->
pending := ns ; pending := ns ;
scheduled := Typ.Procname.Set.add n.pname !scheduled ; scheduled := Procname.Set.add n.pname !scheduled ;
CallGraph.flag syntactic_call_graph n.pname ; CallGraph.flag syntactic_call_graph n.pname ;
Some (Procname n.pname) Some (Procname n.pname)
in in
@ -97,7 +97,7 @@ let bottom_up sources : SchedulerTypes.target ProcessPool.TaskGenerator.t =
assert false assert false
| Procname pname -> | Procname pname ->
decr remaining ; decr remaining ;
scheduled := Typ.Procname.Set.remove pname !scheduled ; scheduled := Procname.Set.remove pname !scheduled ;
CallGraph.remove syntactic_call_graph pname CallGraph.remove syntactic_call_graph pname
in in
let next () = let next () =

@ -10,7 +10,7 @@ open! IStd
(** Module to register and invoke callbacks *) (** Module to register and invoke callbacks *)
type proc_callback_args = type proc_callback_args =
{get_procs_in_file: Typ.Procname.t -> Typ.Procname.t list; summary: Summary.t; exe_env: Exe_env.t} {get_procs_in_file: Procname.t -> Procname.t list; summary: Summary.t; exe_env: Exe_env.t}
type proc_callback_t = proc_callback_args -> Summary.t type proc_callback_t = proc_callback_args -> Summary.t
@ -49,7 +49,7 @@ let get_procedure_definition exe_env proc_name =
let iterate_procedure_callbacks exe_env summary = let iterate_procedure_callbacks exe_env summary =
let proc_desc = Summary.get_proc_desc summary in let proc_desc = Summary.get_proc_desc summary in
let proc_name = Procdesc.get_proc_name proc_desc in let proc_name = Procdesc.get_proc_name proc_desc in
let procedure_language = Typ.Procname.get_language proc_name in let procedure_language = Procname.get_language proc_name in
Language.curr_language := procedure_language ; Language.curr_language := procedure_language ;
let get_procs_in_file proc_name = let get_procs_in_file proc_name =
let source_file = let source_file =
@ -68,7 +68,7 @@ let iterate_procedure_callbacks exe_env summary =
PerfEvent.( PerfEvent.(
log (fun logger -> log (fun logger ->
log_begin_event logger ~name ~categories:["backend"] log_begin_event logger ~name ~categories:["backend"]
~arguments:[("proc", `String (Typ.Procname.to_string proc_name))] ~arguments:[("proc", `String (Procname.to_string proc_name))]
() )) ; () )) ;
let summary = callback {get_procs_in_file; summary; exe_env} in let summary = callback {get_procs_in_file; summary; exe_env} in
PerfEvent.(log (fun logger -> log_end_event logger ())) ; PerfEvent.(log (fun logger -> log_end_event logger ())) ;
@ -85,7 +85,7 @@ let iterate_cluster_callbacks all_procs exe_env source_file =
let language_matches language = let language_matches language =
match procedures with match procedures with
| (_, summary) :: _ -> | (_, summary) :: _ ->
Language.equal language (Typ.Procname.get_language (Summary.get_proc_name summary)) Language.equal language (Procname.get_language (Summary.get_proc_name summary))
| _ -> | _ ->
true true
in in

@ -10,7 +10,7 @@ open! IStd
(** Module to register and invoke callbacks *) (** Module to register and invoke callbacks *)
type proc_callback_args = type proc_callback_args =
{get_procs_in_file: Typ.Procname.t -> Typ.Procname.t list; summary: Summary.t; exe_env: Exe_env.t} {get_procs_in_file: Procname.t -> Procname.t list; summary: Summary.t; exe_env: Exe_env.t}
(** Type of a procedure callback: (** Type of a procedure callback:
@ -35,5 +35,5 @@ val register_cluster_callback : name:string -> Language.t -> cluster_callback_t
val iterate_procedure_callbacks : Exe_env.t -> Summary.t -> Summary.t val iterate_procedure_callbacks : Exe_env.t -> Summary.t -> Summary.t
(** Invoke all registered procedure callbacks on the given procedure. *) (** Invoke all registered procedure callbacks on the given procedure. *)
val iterate_cluster_callbacks : Typ.Procname.t list -> Exe_env.t -> SourceFile.t -> unit val iterate_cluster_callbacks : Procname.t list -> Exe_env.t -> SourceFile.t -> unit
(** Invoke all registered cluster callbacks on a cluster of procedures. *) (** Invoke all registered cluster callbacks on a cluster of procedures. *)

@ -22,8 +22,8 @@ let is_one_of_classes = QualifiedCppName.Match.match_qualifiers
let is_method_of_objc_cpp_class pname matcher = let is_method_of_objc_cpp_class pname matcher =
match pname with match pname with
| Typ.Procname.ObjC_Cpp objc_cpp -> | Procname.ObjC_Cpp objc_cpp ->
let class_qual_opt = Typ.Procname.ObjC_Cpp.get_class_qualifiers objc_cpp in let class_qual_opt = Procname.ObjC_Cpp.get_class_qualifiers objc_cpp in
is_one_of_classes matcher class_qual_opt is_one_of_classes matcher class_qual_opt
| _ -> | _ ->
false false
@ -166,7 +166,7 @@ let rec find_normal_variable_load_ tenv (seen : Exp.Set.t) node id : DExp.t opti
L.d_ln () ) ; L.d_ln () ) ;
exp_lv_dexp_ tenv seen node e exp_lv_dexp_ tenv seen node e
| Sil.Call ((id0, _), Exp.Const (Const.Cfun pn), (e, _) :: _, _, _) | Sil.Call ((id0, _), Exp.Const (Const.Cfun pn), (e, _) :: _, _, _)
when Ident.equal id id0 && Typ.Procname.equal pn (Typ.Procname.from_string_c_fun "__cast") -> when Ident.equal id id0 && Procname.equal pn (Procname.from_string_c_fun "__cast") ->
if verbose then ( if verbose then (
L.d_str "find_normal_variable_load cast on " ; L.d_str "find_normal_variable_load cast on " ;
Exp.d_exp e ; Exp.d_exp e ;
@ -962,7 +962,7 @@ let explain_access_ proc_name tenv ?(use_buckets = false) ?(outermost_array = fa
L.d_ln () ) ; 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 List.exists ~f:(Typ.Procname.equal fn) when List.exists ~f:(Procname.equal fn)
[BuiltinDecl.free; BuiltinDecl.__delete; BuiltinDecl.__delete_array] -> [BuiltinDecl.free; BuiltinDecl.__delete; BuiltinDecl.__delete_array] ->
if verbose then ( if verbose then (
L.d_str "explain_dereference Sil.Call " ; L.d_str "explain_dereference Sil.Call " ;

@ -40,12 +40,12 @@ val explain_allocation_mismatch : PredSymb.res_action -> PredSymb.res_action ->
(** 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 *)
val explain_array_access : val explain_array_access :
Typ.Procname.t -> Tenv.t -> Localise.deref_str -> 'a Prop.t -> Location.t -> Localise.error_desc Procname.t -> Tenv.t -> Localise.deref_str -> 'a Prop.t -> Location.t -> Localise.error_desc
(** Produce a description of the array access performed in the current instruction, if any. *) (** Produce a description of the array access performed in the current instruction, if any. *)
val explain_class_cast_exception : val explain_class_cast_exception :
Tenv.t Tenv.t
-> Typ.Procname.t option -> Procname.t option
-> Exp.t -> Exp.t
-> Exp.t -> Exp.t
-> Exp.t -> Exp.t
@ -61,7 +61,7 @@ val explain_deallocate_constant_string : string -> PredSymb.res_action -> Locali
(** Explain a deallocate constant string error *) (** Explain a deallocate constant string error *)
val explain_dereference : val explain_dereference :
Typ.Procname.t Procname.t
-> Tenv.t -> Tenv.t
-> ?use_buckets:bool -> ?use_buckets:bool
-> ?is_nullable:bool -> ?is_nullable:bool
@ -73,7 +73,7 @@ val explain_dereference :
(** Produce a description of which expression is dereferenced in the current instruction, if any. *) (** Produce a description of which expression is dereferenced in the current instruction, if any. *)
val explain_dereference_as_caller_expression : val explain_dereference_as_caller_expression :
Typ.Procname.t Procname.t
-> Tenv.t -> Tenv.t
-> ?use_buckets:bool -> ?use_buckets:bool
-> Localise.deref_str -> Localise.deref_str

@ -38,16 +38,16 @@ let create_file_data table source =
type t = type t =
{ proc_map: file_data Typ.Procname.Hash.t (** map from procedure name to file data *) { proc_map: file_data Procname.Hash.t (** map from procedure name to file data *)
; file_map: file_data SourceFile.Hash.t (** map from source files to file data *) } ; file_map: file_data SourceFile.Hash.t (** map from source files to file data *) }
let get_file_data exe_env pname = let get_file_data exe_env pname =
try Some (Typ.Procname.Hash.find exe_env.proc_map pname) try Some (Procname.Hash.find exe_env.proc_map pname)
with Caml.Not_found -> with Caml.Not_found ->
let source_file_opt = let source_file_opt =
match Attributes.load pname with match Attributes.load pname with
| None -> | None ->
L.debug Analysis Medium "can't find attributes for %a@." Typ.Procname.pp pname ; L.debug Analysis Medium "can't find attributes for %a@." Procname.pp pname ;
None None
| Some proc_attributes when Config.reactive_capture -> | Some proc_attributes when Config.reactive_capture ->
let get_captured_file {ProcAttributes.translation_unit} = translation_unit in let get_captured_file {ProcAttributes.translation_unit} = translation_unit in
@ -57,7 +57,7 @@ let get_file_data exe_env pname =
in in
let get_file_data_for_source source_file = let get_file_data_for_source source_file =
let file_data = create_file_data exe_env.file_map source_file in let file_data = create_file_data exe_env.file_map source_file in
Typ.Procname.Hash.replace exe_env.proc_map pname file_data ; Procname.Hash.replace exe_env.proc_map pname file_data ;
file_data file_data
in in
Option.map ~f:get_file_data_for_source source_file_opt Option.map ~f:get_file_data_for_source source_file_opt
@ -92,7 +92,7 @@ let get_column_value ~value_on_java ~file_data_to_value ~column_name exe_env pro
() ()
in in
match proc_name with match proc_name with
| Typ.Procname.Java _ -> | Procname.Java _ ->
Lazy.force value_on_java Lazy.force value_on_java
| _ -> ( | _ -> (
match get_file_data exe_env proc_name with match get_file_data exe_env proc_name with
@ -102,12 +102,12 @@ let get_column_value ~value_on_java ~file_data_to_value ~column_name exe_env pro
v v
| None -> | None ->
let loc_opt = State.get_loc () in let loc_opt = State.get_loc () in
L.die InternalError "get_column_value: %s not found for %a%a" column_name Typ.Procname.pp L.die InternalError "get_column_value: %s not found for %a%a" column_name Procname.pp
proc_name pp_loc_opt loc_opt ) proc_name pp_loc_opt loc_opt )
| None -> | None ->
let loc_opt = State.get_loc () in let loc_opt = State.get_loc () in
L.die InternalError "get_column_value: file_data not found for %a%a" Typ.Procname.pp L.die InternalError "get_column_value: file_data not found for %a%a" Procname.pp proc_name
proc_name pp_loc_opt loc_opt ) pp_loc_opt loc_opt )
(** return the type environment associated to the procedure *) (** return the type environment associated to the procedure *)
@ -123,4 +123,4 @@ let get_integer_type_widths =
~file_data_to_value:file_data_to_integer_type_widths ~column_name:"integer type widths" ~file_data_to_value:file_data_to_integer_type_widths ~column_name:"integer type widths"
let mk () = {proc_map= Typ.Procname.Hash.create 17; file_map= SourceFile.Hash.create 1} let mk () = {proc_map= Procname.Hash.create 17; file_map= SourceFile.Hash.create 1}

@ -14,14 +14,14 @@ open! IStd
type file_data type file_data
type t = private type t = private
{ proc_map: file_data Typ.Procname.Hash.t (** map from procedure name to file data *) { proc_map: file_data Procname.Hash.t (** map from procedure name to file data *)
; file_map: file_data SourceFile.Hash.t (** map from source files to file data *) } ; file_map: file_data SourceFile.Hash.t (** map from source files to file data *) }
val mk : unit -> t val mk : unit -> t
(** Create a new cache *) (** Create a new cache *)
val get_tenv : t -> Typ.Procname.t -> Tenv.t val get_tenv : t -> Procname.t -> Tenv.t
(** return the type environment associated with the procedure *) (** return the type environment associated with the procedure *)
val get_integer_type_widths : t -> Typ.Procname.t -> Typ.IntegerWidths.t val get_integer_type_widths : t -> Procname.t -> Typ.IntegerWidths.t
(** return the integer type widths associated with the procedure *) (** return the integer type widths associated with the procedure *)

@ -13,7 +13,7 @@ type path_filter = SourceFile.t -> bool
type error_filter = IssueType.t -> bool type error_filter = IssueType.t -> bool
type proc_filter = Typ.Procname.t -> bool type proc_filter = Procname.t -> bool
type filters = {path_filter: path_filter; error_filter: error_filter; proc_filter: proc_filter} type filters = {path_filter: path_filter; error_filter: error_filter; proc_filter: proc_filter}
@ -46,8 +46,8 @@ let is_matching patterns source_file =
(** 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))
&& Language.equal (Typ.Procname.get_language proc_name) language && Language.equal (Procname.get_language proc_name) language
&& String.equal (Typ.Procname.get_method proc_name) method_name && String.equal (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 *)
@ -92,7 +92,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 -> Typ.Procname.t -> bool type matcher = SourceFile.t -> Procname.t -> bool
let default_matcher : matcher = fun _ _ -> false let default_matcher : matcher = fun _ _ -> false
@ -110,8 +110,8 @@ module FileOrProcMatcher = struct
~init:String.Map.empty m_patterns ~init:String.Map.empty m_patterns
in in
let do_java pname_java = let do_java pname_java =
let class_name = Typ.Procname.Java.get_class_name pname_java let class_name = Procname.Java.get_class_name pname_java
and method_name = Typ.Procname.Java.get_method pname_java in and method_name = 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
@ -121,7 +121,7 @@ module FileOrProcMatcher = struct
with Not_found_s _ | Caml.Not_found -> false with Not_found_s _ | Caml.Not_found -> false
in in
fun _ proc_name -> fun _ proc_name ->
match proc_name with Typ.Procname.Java pname_java -> do_java pname_java | _ -> false match proc_name with Procname.Java pname_java -> do_java pname_java | _ -> false
let create_file_matcher patterns = let create_file_matcher patterns =

@ -14,20 +14,20 @@ type path_filter = SourceFile.t -> bool
type error_filter = IssueType.t -> bool type error_filter = IssueType.t -> bool
(** Filter type for a procedure name *) (** Filter type for a procedure name *)
type proc_filter = Typ.Procname.t -> bool type proc_filter = Procname.t -> bool
type filters = {path_filter: path_filter; error_filter: error_filter; proc_filter: proc_filter} type filters = {path_filter: path_filter; error_filter: error_filter; proc_filter: proc_filter}
val create_filters : unit -> filters val create_filters : unit -> filters
(** Create filters based on the config file *) (** Create filters based on the config file *)
val never_return_null_matcher : SourceFile.t -> Typ.Procname.t -> bool val never_return_null_matcher : SourceFile.t -> Procname.t -> bool
val skip_translation_matcher : SourceFile.t -> Typ.Procname.t -> bool val skip_translation_matcher : SourceFile.t -> Procname.t -> bool
val skip_implementation_matcher : SourceFile.t -> Typ.Procname.t -> bool val skip_implementation_matcher : SourceFile.t -> Procname.t -> bool
val modeled_expensive_matcher : (string -> bool) -> Typ.Procname.t -> bool val modeled_expensive_matcher : (string -> bool) -> Procname.t -> bool
val test : unit -> unit val test : unit -> unit
(** Load the config file and list the files to report on *) (** Load the config file and list the files to report on *)

@ -15,21 +15,20 @@ module F = Format
let exe_env_ref = ref None let exe_env_ref = ref None
module LocalCache = struct module LocalCache = struct
let results = lazy (Typ.Procname.Hash.create 128) let results = lazy (Procname.Hash.create 128)
let clear () = Typ.Procname.Hash.clear (Lazy.force results) let clear () = Procname.Hash.clear (Lazy.force results)
let remove pname = Typ.Procname.Hash.remove (Lazy.force results) pname let remove pname = Procname.Hash.remove (Lazy.force results) pname
let get proc_name = let get proc_name =
let summ_opt_opt = Typ.Procname.Hash.find_opt (Lazy.force results) proc_name in let summ_opt_opt = Procname.Hash.find_opt (Lazy.force results) proc_name in
if Option.is_some summ_opt_opt then BackendStats.incr_ondemand_local_cache_hits () if Option.is_some summ_opt_opt then BackendStats.incr_ondemand_local_cache_hits ()
else BackendStats.incr_ondemand_local_cache_misses () ; else BackendStats.incr_ondemand_local_cache_misses () ;
summ_opt_opt summ_opt_opt
let add proc_name summary_option = let add proc_name summary_option = Procname.Hash.add (Lazy.force results) proc_name summary_option
Typ.Procname.Hash.add (Lazy.force results) proc_name summary_option
end end
let set_exe_env (env : Exe_env.t) = exe_env_ref := Some env let set_exe_env (env : Exe_env.t) = exe_env_ref := Some env
@ -46,12 +45,11 @@ let max_nesting_to_print = 8
let current_taskbar_status : (Mtime.t * string) option ref = ref None let current_taskbar_status : (Mtime.t * string) option ref = ref None
let is_active, add_active, remove_active = let is_active, add_active, remove_active =
let currently_analyzed = ref Typ.Procname.Set.empty in let currently_analyzed = ref Procname.Set.empty in
let is_active proc_name = Typ.Procname.Set.mem proc_name !currently_analyzed let is_active proc_name = Procname.Set.mem proc_name !currently_analyzed
and add_active proc_name = and add_active proc_name = currently_analyzed := Procname.Set.add proc_name !currently_analyzed
currently_analyzed := Typ.Procname.Set.add proc_name !currently_analyzed
and remove_active proc_name = and remove_active proc_name =
currently_analyzed := Typ.Procname.Set.remove proc_name !currently_analyzed currently_analyzed := Procname.Set.remove proc_name !currently_analyzed
in in
(is_active, add_active, remove_active) (is_active, add_active, remove_active)
@ -151,7 +149,7 @@ let analyze callee_summary =
if !nesting <= max_nesting_to_print then String.make !nesting '>' if !nesting <= max_nesting_to_print then String.make !nesting '>'
else Printf.sprintf "%d>" !nesting else Printf.sprintf "%d>" !nesting
in in
F.asprintf "%s%a: %a" nesting SourceFile.pp source_file Typ.Procname.pp proc_name F.asprintf "%s%a: %a" nesting SourceFile.pp source_file Procname.pp proc_name
in in
current_taskbar_status := Some (t0, status) ; current_taskbar_status := Some (t0, status) ;
!ProcessPoolState.update_status t0 status ; !ProcessPoolState.update_status t0 status ;
@ -166,13 +164,13 @@ let run_proc_analysis ~caller_pdesc callee_pdesc =
let start_time = Mtime_clock.counter () in let start_time = Mtime_clock.counter () in
fun () -> fun () ->
L.(debug Analysis Medium) L.(debug Analysis Medium)
"Elapsed analysis time: %a: %a@\n" Typ.Procname.pp callee_pname Mtime.Span.pp "Elapsed analysis time: %a: %a@\n" Procname.pp callee_pname Mtime.Span.pp
(Mtime_clock.count start_time) (Mtime_clock.count start_time)
in in
if Config.trace_ondemand then if Config.trace_ondemand then
L.progress "[%d] run_proc_analysis %a -> %a@." !nesting (Pp.option Typ.Procname.pp) L.progress "[%d] run_proc_analysis %a -> %a@." !nesting (Pp.option Procname.pp)
(Option.map caller_pdesc ~f:Procdesc.get_proc_name) (Option.map caller_pdesc ~f:Procdesc.get_proc_name)
Typ.Procname.pp callee_pname ; Procname.pp callee_pname ;
let preprocess () = let preprocess () =
incr nesting ; incr nesting ;
Preanal.do_preanalysis (Option.value_exn !exe_env_ref) callee_pdesc ; Preanal.do_preanalysis (Option.value_exn !exe_env_ref) callee_pdesc ;
@ -224,11 +222,11 @@ let run_proc_analysis ~caller_pdesc callee_pdesc =
let source_file = attributes.ProcAttributes.translation_unit in let source_file = attributes.ProcAttributes.translation_unit in
let location = attributes.ProcAttributes.loc in let location = attributes.ProcAttributes.loc in
L.internal_error "While analysing function %a:%a at %a@\n" SourceFile.pp source_file L.internal_error "While analysing function %a:%a at %a@\n" SourceFile.pp source_file
Typ.Procname.pp callee_pname Location.pp_file_pos location ; Procname.pp callee_pname Location.pp_file_pos location ;
logged_error := true ) ; logged_error := true ) ;
restore_global_state old_state ; restore_global_state old_state ;
not Config.keep_going ) ; not Config.keep_going ) ;
L.internal_error "@\nERROR RUNNING BACKEND: %a %s@\n@\nBACK TRACE@\n%s@?" Typ.Procname.pp L.internal_error "@\nERROR RUNNING BACKEND: %a %s@\n@\nBACK TRACE@\n%s@?" Procname.pp
callee_pname (Exn.to_string exn) backtrace ; callee_pname (Exn.to_string exn) backtrace ;
match exn with match exn with
| SymOp.Analysis_failure_exe kind -> | SymOp.Analysis_failure_exe kind ->
@ -246,7 +244,7 @@ let run_proc_analysis ~caller_pdesc callee_pdesc =
log (fun logger -> log (fun logger ->
let callee_pname = Procdesc.get_proc_name callee_pdesc in let callee_pname = Procdesc.get_proc_name callee_pdesc in
log_begin_event logger ~name:"ondemand" ~categories:["backend"] log_begin_event logger ~name:"ondemand" ~categories:["backend"]
~arguments:[("proc", `String (Typ.Procname.to_string callee_pname))] ~arguments:[("proc", `String (Procname.to_string callee_pname))]
() )) ; () )) ;
let summary = run_proc_analysis ~caller_pdesc callee_pdesc in let summary = run_proc_analysis ~caller_pdesc callee_pdesc in
PerfEvent.(log (fun logger -> log_end_event logger ())) ; PerfEvent.(log (fun logger -> log_end_event logger ())) ;
@ -278,7 +276,7 @@ let dump_duplicate_procs source_file procs =
let fmt = F.formatter_of_out_channel outc in let fmt = F.formatter_of_out_channel outc in
List.iter duplicate_procs ~f:(fun (pname, source_captured) -> List.iter duplicate_procs ~f:(fun (pname, source_captured) ->
F.fprintf fmt "DUPLICATE_SYMBOLS source:%a source_captured:%a pname:%a@\n" SourceFile.pp F.fprintf fmt "DUPLICATE_SYMBOLS source:%a source_captured:%a pname:%a@\n" SourceFile.pp
source_file SourceFile.pp source_captured Typ.Procname.pp pname ) ; source_file SourceFile.pp source_captured Procname.pp pname ) ;
F.pp_print_flush fmt () ) F.pp_print_flush fmt () )
in in
if not (List.is_empty duplicate_procs) then output_to_file duplicate_procs if not (List.is_empty duplicate_procs) then output_to_file duplicate_procs
@ -292,7 +290,7 @@ let create_perf_stats_report source_file =
let register_callee ?caller_summary callee_pname = let register_callee ?caller_summary callee_pname =
Option.iter Option.iter
~f:(fun (summary : Summary.t) -> ~f:(fun (summary : Summary.t) ->
summary.callee_pnames <- Typ.Procname.Set.add callee_pname summary.callee_pnames ) summary.callee_pnames <- Procname.Set.add callee_pname summary.callee_pnames )
caller_summary caller_summary
@ -303,7 +301,7 @@ let get_proc_desc callee_pname =
; lazy (Topl.get_proc_desc callee_pname) ] ; lazy (Topl.get_proc_desc callee_pname) ]
type callee = ProcName of Typ.Procname.t | ProcDesc of Procdesc.t type callee = ProcName of Procname.t | ProcDesc of Procdesc.t
let proc_name_of_callee = function let proc_name_of_callee = function
| ProcName proc_name -> | ProcName proc_name ->
@ -346,7 +344,7 @@ let analyze_callee ?caller_summary callee =
| None -> | None ->
Summary.OnDisk.get callee_pname Summary.OnDisk.get callee_pname
else ( else (
EventLogger.log_skipped_pname (F.asprintf "%a" Typ.Procname.pp callee_pname) ; EventLogger.log_skipped_pname (F.asprintf "%a" Procname.pp callee_pname) ;
Summary.OnDisk.get callee_pname ) Summary.OnDisk.get callee_pname )
in in
LocalCache.add callee_pname summ_opt ; LocalCache.add callee_pname summ_opt ;

@ -9,18 +9,18 @@ open! IStd
(** Module for on-demand analysis. *) (** Module for on-demand analysis. *)
val get_proc_desc : Typ.Procname.t -> Procdesc.t option val get_proc_desc : Procname.t -> Procdesc.t option
(** Find a proc desc for the procedure, perhaps loading it from disk. *) (** Find a proc desc for the procedure, perhaps loading it from disk. *)
val analyze_proc_desc : caller_summary:Summary.t -> Procdesc.t -> Summary.t option val analyze_proc_desc : caller_summary:Summary.t -> Procdesc.t -> Summary.t option
(** [analyze_proc_desc ~caller_summary callee_pdesc] performs an on-demand analysis of callee_pdesc (** [analyze_proc_desc ~caller_summary callee_pdesc] performs an on-demand analysis of callee_pdesc
triggered during the analysis of caller_summary *) triggered during the analysis of caller_summary *)
val analyze_proc_name : caller_summary:Summary.t -> Typ.Procname.t -> Summary.t option val analyze_proc_name : caller_summary:Summary.t -> Procname.t -> Summary.t option
(** [analyze_proc_name ~caller_summary callee_pname] performs an on-demand analysis of callee_pname (** [analyze_proc_name ~caller_summary callee_pname] performs an on-demand analysis of callee_pname
triggered during the analysis of caller_summary *) triggered during the analysis of caller_summary *)
val analyze_proc_name_no_caller : Typ.Procname.t -> Summary.t option val analyze_proc_name_no_caller : Procname.t -> Summary.t option
(** [analyze_proc_name_no_caller callee_pname] performs an on-demand analysis of callee_pname (** [analyze_proc_name_no_caller callee_pname] performs an on-demand analysis of callee_pname
triggered by the top-level of a cluster checker *) triggered by the top-level of a cluster checker *)
@ -31,12 +31,12 @@ module LocalCache : sig
val clear : unit -> unit val clear : unit -> unit
(** Empty the cache of ondemand results *) (** Empty the cache of ondemand results *)
val remove : Typ.Procname.t -> unit val remove : Procname.t -> unit
(** Remove an element from the cache of ondemand results *) (** Remove an element from the cache of ondemand results *)
end end
val analyze_file : Exe_env.t -> SourceFile.t -> unit val analyze_file : Exe_env.t -> SourceFile.t -> unit
(** Invoke all the callbacks registered in {!Callbacks} on the given file. *) (** Invoke all the callbacks registered in {!Callbacks} on the given file. *)
val analyze_proc_name_toplevel : Exe_env.t -> Typ.Procname.t -> unit val analyze_proc_name_toplevel : Exe_env.t -> Procname.t -> unit
(** Invoke all the callbacks registered in {!Callbacks} on the given procedure. *) (** Invoke all the callbacks registered in {!Callbacks} on the given procedure. *)

@ -74,7 +74,7 @@ module Liveness = struct
astate astate
let cache_node = ref (Procdesc.Node.dummy Typ.Procname.Linters_dummy_method) let cache_node = ref (Procdesc.Node.dummy Procname.Linters_dummy_method)
let cache_instr = ref Sil.skip_instr let cache_instr = ref Sil.skip_instr
@ -129,7 +129,7 @@ module Liveness = struct
let add_nullify_instrs summary tenv liveness_inv_map = let add_nullify_instrs summary tenv liveness_inv_map =
let address_taken_vars = let address_taken_vars =
if Typ.Procname.is_java (Summary.get_proc_name summary) then AddressTaken.Domain.empty if Procname.is_java (Summary.get_proc_name summary) then AddressTaken.Domain.empty
(* can't take the address of a variable in Java *) (* can't take the address of a variable in Java *)
else else
let initial = AddressTaken.Domain.empty in let initial = AddressTaken.Domain.empty in
@ -236,9 +236,7 @@ end
let do_preanalysis exe_env pdesc = let do_preanalysis exe_env pdesc =
let summary = Summary.OnDisk.reset pdesc in let summary = Summary.OnDisk.reset pdesc in
let tenv = Exe_env.get_tenv exe_env (Procdesc.get_proc_name pdesc) in let tenv = Exe_env.get_tenv exe_env (Procdesc.get_proc_name pdesc) in
if if Config.function_pointer_specialization && not (Procname.is_java (Procdesc.get_proc_name pdesc))
Config.function_pointer_specialization
&& not (Typ.Procname.is_java (Procdesc.get_proc_name pdesc))
then FunctionPointerSubstitution.process summary tenv ; then FunctionPointerSubstitution.process summary tenv ;
Liveness.process summary tenv ; Liveness.process summary tenv ;
AddAbstractionInstructions.process pdesc ; AddAbstractionInstructions.process pdesc ;

@ -131,7 +131,7 @@ end = struct
line ; 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 (Typ.Procname.to_string proc_name)) (Escape.escape_xml (Procname.to_string proc_name))
(Io_infer.Html.pp_line_link source [".."]) (Io_infer.Html.pp_line_link source [".."])
line ; line ;
F.fprintf fmt "<br>PREDS:@\n" ; F.fprintf fmt "<br>PREDS:@\n" ;
@ -174,10 +174,10 @@ end = struct
let source = loc.file in let source = loc.file in
let nodes = List.sort ~compare:Procdesc.Node.compare (Procdesc.get_nodes pdesc) in let nodes = List.sort ~compare:Procdesc.Node.compare (Procdesc.get_nodes pdesc) in
let linenum = loc.Location.line in let linenum = loc.Location.line in
let fd, fmt = Io_infer.Html.create source [Typ.Procname.to_filename pname] in let fd, fmt = Io_infer.Html.create source [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 (Typ.Procname.to_string pname))) ~text:(Some (Escape.escape_xml (Procname.to_string pname)))
[]) [])
linenum ; linenum ;
pp_node_link_seq [] ~description:true fmt nodes ; pp_node_link_seq [] ~description:true fmt nodes ;
@ -257,7 +257,7 @@ end = struct
match Procdesc.Node.get_kind n with match Procdesc.Node.get_kind n with
| Procdesc.Node.Start_node -> | Procdesc.Node.Start_node ->
let proc_name = Procdesc.Node.get_proc_name n in let proc_name = Procdesc.Node.get_proc_name n in
let proc_name_escaped = Escape.escape_xml (Typ.Procname.to_string proc_name) in let proc_name_escaped = Escape.escape_xml (Procname.to_string proc_name) in
if Summary.OnDisk.get proc_name |> Option.is_some then ( if Summary.OnDisk.get proc_name |> Option.is_some then (
F.pp_print_char fmt ' ' ; F.pp_print_char fmt ' ' ;
let label = F.asprintf "summary for %s" proc_name_escaped in let label = F.asprintf "summary for %s" proc_name_escaped in
@ -309,9 +309,9 @@ end = struct
if is_whitelisted file then ( if is_whitelisted file then (
let pdescs_in_file = let pdescs_in_file =
try Hashtbl.find pdescs_in_source file try Hashtbl.find pdescs_in_source file
with Caml.Not_found -> Typ.Procname.Map.empty with Caml.Not_found -> Procname.Map.empty
in in
let pdescs_in_file = Typ.Procname.Map.add proc_name proc_desc pdescs_in_file in let pdescs_in_file = Procname.Map.add proc_name proc_desc pdescs_in_file in
Hashtbl.replace pdescs_in_source file pdescs_in_file ; Hashtbl.replace pdescs_in_source file pdescs_in_file ;
SourceFile.Set.add file files ) SourceFile.Set.add file files )
else files else files
@ -324,7 +324,7 @@ end = struct
let pdescs_in_file = let pdescs_in_file =
match Hashtbl.find pdescs_in_source file with match Hashtbl.find pdescs_in_source file with
| pdescs_map -> | pdescs_map ->
Typ.Procname.Map.bindings pdescs_map |> List.map ~f:snd Procname.Map.bindings pdescs_map |> List.map ~f:snd
| exception Caml.Not_found -> | exception Caml.Not_found ->
[] []
in in

@ -31,15 +31,15 @@ let log_issue_from_summary severity summary ~node ~session ~loc ~ltr ?extras exn
let procname = attrs.proc_name in let procname = attrs.proc_name in
let is_java_generated_method = let is_java_generated_method =
match procname with match procname with
| Typ.Procname.Java java_pname -> | Procname.Java java_pname ->
Typ.Procname.Java.is_generated java_pname Procname.Java.is_generated java_pname
| _ -> | _ ->
false false
in in
let is_java_external_package = let is_java_external_package =
match procname with match procname with
| Typ.Procname.Java java_pname -> | Procname.Java java_pname ->
Typ.Procname.Java.is_external java_pname Procname.Java.is_external java_pname
| _ -> | _ ->
false false
in in
@ -73,7 +73,7 @@ let log_issue_deprecated_using_state severity proc_name ?node ?loc ?ltr exn =
L.(die InternalError) L.(die InternalError)
"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?"
Typ.Procname.pp proc_name Typ.Procname.pp proc_name Procname.pp proc_name Procname.pp proc_name
let checker_exception issue_type error_message = let checker_exception issue_type error_message =

@ -13,7 +13,7 @@ type log_t = ?ltr:Errlog.loc_trace -> ?extras:Jsonbug_t.extra -> IssueType.t ->
val log_issue_deprecated_using_state : val log_issue_deprecated_using_state :
Exceptions.severity Exceptions.severity
-> Typ.Procname.t -> Procname.t
-> ?node:Procdesc.Node.t -> ?node:Procdesc.Node.t
-> ?loc:Location.t -> ?loc:Location.t
-> ?ltr:Errlog.loc_trace -> ?ltr:Errlog.loc_trace
@ -23,7 +23,7 @@ val log_issue_deprecated_using_state :
DEPRECATED as it can create race conditions between checkers. Use log_error/warning instead *) DEPRECATED as it can create race conditions between checkers. Use log_error/warning instead *)
val log_frontend_issue : val log_frontend_issue :
Typ.Procname.t Procname.t
-> Exceptions.severity -> Exceptions.severity
-> Errlog.t -> Errlog.t
-> loc:Location.t -> loc:Location.t
@ -43,7 +43,7 @@ val log_error_using_state : Summary.t -> exn -> unit
(** Add an error to the given summary using biabduction state (DO NOT USE ELSEWHERE). *) (** Add an error to the given summary using biabduction state (DO NOT USE ELSEWHERE). *)
val log_issue_external : val log_issue_external :
Typ.Procname.t Procname.t
-> issue_log:IssueLog.t -> issue_log:IssueLog.t
-> Exceptions.severity -> Exceptions.severity
-> loc:Location.t -> loc:Location.t

@ -13,29 +13,29 @@ open! IStd
(** Abstraction rules discovered *) (** Abstraction rules discovered *)
type rules type rules
val abstract : Typ.Procname.t -> Tenv.t -> Prop.normal Prop.t -> Prop.normal Prop.t val abstract : Procname.t -> Tenv.t -> Prop.normal Prop.t -> Prop.normal Prop.t
(** Abstract a proposition. *) (** Abstract a proposition. *)
val abstract_spec : val abstract_spec :
Typ.Procname.t -> Tenv.t -> Prop.normal BiabductionSummary.spec -> BiabductionSummary.NormSpec.t Procname.t -> Tenv.t -> Prop.normal BiabductionSummary.spec -> BiabductionSummary.NormSpec.t
(** Normalizes names and applies simplifications, soem of which require looking at both pre and (** Normalizes names and applies simplifications, soem of which require looking at both pre and
post. *) post. *)
val abstract_junk : Typ.Procname.t -> Tenv.t -> Prop.normal Prop.t -> Prop.normal Prop.t val abstract_junk : Procname.t -> Tenv.t -> Prop.normal Prop.t -> Prop.normal Prop.t
(** Check whether the prop contains junk. If it does, and [Config.allowleak] is true, remove the (** Check whether the prop contains junk. If it does, and [Config.allowleak] is true, remove the
junk, otherwise raise a Leak exception. *) junk, otherwise raise a Leak exception. *)
val abstract_no_symop : Typ.Procname.t -> Tenv.t -> Prop.normal Prop.t -> Prop.normal Prop.t val abstract_no_symop : 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 get_current_rules : unit -> rules val get_current_rules : unit -> rules
(** Get the current rules discoveres *) (** Get the current rules discoveres *)
val lifted_abstract : Typ.Procname.t -> Tenv.t -> Propset.t -> Propset.t val lifted_abstract : Procname.t -> Tenv.t -> Propset.t -> Propset.t
(** Abstract each proposition in [propset] *) (** Abstract each proposition in [propset] *)
val remove_redundant_array_elements : val remove_redundant_array_elements :
Typ.Procname.t -> Tenv.t -> Prop.normal Prop.t -> Prop.normal Prop.t Procname.t -> Tenv.t -> Prop.normal Prop.t -> Prop.normal Prop.t
(** Remove redundant elements in an array, and check for junk afterwards *) (** Remove redundant elements in an array, and check for junk afterwards *)
val reset_current_rules : unit -> unit val reset_current_rules : unit -> unit

@ -89,7 +89,7 @@ val mark_vars_as_undefined :
-> Prop.normal Prop.t -> Prop.normal Prop.t
-> ret_exp:Exp.t -> ret_exp:Exp.t
-> undefined_actuals_by_ref:Exp.t list -> undefined_actuals_by_ref:Exp.t list
-> Typ.Procname.t -> Procname.t
-> Annot.Item.t -> Annot.Item.t
-> Location.t -> Location.t
-> PredSymb.path_pos -> PredSymb.path_pos

@ -18,7 +18,7 @@ type args =
; path: Paths.Path.t ; path: Paths.Path.t
; ret_id_typ: Ident.t * Typ.t ; ret_id_typ: Ident.t * Typ.t
; args: (Exp.t * Typ.t) list ; args: (Exp.t * Typ.t) list
; proc_name: Typ.Procname.t ; proc_name: Procname.t
; loc: Location.t ; loc: Location.t
; exe_env: Exe_env.t } ; exe_env: Exe_env.t }
@ -29,32 +29,32 @@ 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 = Typ.Procname.Hash.create 4 let builtin_functions = 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 (Typ.Procname.Hash.length builtin_functions) 0 then if Int.equal (Procname.Hash.length builtin_functions) 0 then
L.(die InternalError) "Builtins were not initialized" L.(die InternalError) "Builtins were not initialized"
(** 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 (Typ.Procname.Hash.find builtin_functions name) try Some (Procname.Hash.find builtin_functions name)
with Caml.Not_found -> check_register_populated () ; None with Caml.Not_found -> check_register_populated () ; None
(** register a builtin [Typ.Procname.t] and symbolic execution handler *) (** register a builtin [Procname.t] and symbolic execution handler *)
let register proc_name sym_exe_fun : registered = let register proc_name sym_exe_fun : registered =
Typ.Procname.Hash.replace builtin_functions proc_name sym_exe_fun ; 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
Typ.Procname.Hash.iter (fun name _ -> builtin_names := name :: !builtin_names) builtin_functions ; Procname.Hash.iter (fun name _ -> builtin_names := name :: !builtin_names) builtin_functions ;
builtin_names := List.sort ~compare:Typ.Procname.compare !builtin_names ; builtin_names := List.sort ~compare:Procname.compare !builtin_names ;
let pp pname = Format.fprintf fmt "%a@\n" Typ.Procname.pp pname in let pp pname = Format.fprintf fmt "%a@\n" 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 "@]@."

@ -17,7 +17,7 @@ type args =
; path: Paths.Path.t ; path: Paths.Path.t
; ret_id_typ: Ident.t * Typ.t ; ret_id_typ: Ident.t * Typ.t
; args: (Exp.t * Typ.t) list ; args: (Exp.t * Typ.t) list
; proc_name: Typ.Procname.t ; proc_name: Procname.t
; loc: Location.t ; loc: Location.t
; exe_env: Exe_env.t } ; exe_env: Exe_env.t }
@ -27,10 +27,10 @@ type t = args -> ret_typ
type registered type registered
val register : Typ.Procname.t -> t -> registered val register : Procname.t -> t -> registered
(** Register a builtin [Typ.Procname.t] and symbolic execution handler *) (** Register a builtin [Procname.t] and symbolic execution handler *)
val get : Typ.Procname.t -> t option val get : 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

@ -647,7 +647,7 @@ let execute_pthread_create ({Builtin.tenv; summary; prop_; path; args; exe_env}
| Exp.Lvar pvar, _ -> | Exp.Lvar pvar, _ ->
let fun_name = Pvar.get_name pvar in let fun_name = Pvar.get_name pvar in
let fun_string = Mangled.to_string fun_name in let fun_string = Mangled.to_string fun_name in
Some (Typ.Procname.from_string_c_fun fun_string) Some (Procname.from_string_c_fun fun_string)
| Exp.Const (Cfun pname), _ -> | Exp.Const (Cfun pname), _ ->
Some pname Some pname
| _ -> | _ ->
@ -660,7 +660,7 @@ let execute_pthread_create ({Builtin.tenv; summary; prop_; path; args; exe_env}
L.d_strln ", skipping call." ; L.d_strln ", skipping call." ;
[(prop_, path)] [(prop_, path)]
| Some pname -> ( | Some pname -> (
L.d_printfln "pthread_create: calling function %a" Typ.Procname.pp pname ; L.d_printfln "pthread_create: calling function %a" Procname.pp pname ;
match Ondemand.analyze_proc_name ~caller_summary:summary pname with match Ondemand.analyze_proc_name ~caller_summary:summary pname with
| None -> | None ->
(* no precondition to check, skip *) (* no precondition to check, skip *)

@ -13,11 +13,7 @@ open! IStd
(** {2 Join Operators} *) (** {2 Join Operators} *)
val pathset_join : val pathset_join :
Typ.Procname.t Procname.t -> Tenv.t -> Paths.PathSet.t -> Paths.PathSet.t -> Paths.PathSet.t * Paths.PathSet.t
-> Tenv.t
-> Paths.PathSet.t
-> Paths.PathSet.t
-> Paths.PathSet.t * Paths.PathSet.t
(** Join two pathsets *) (** Join two pathsets *)
val proplist_collapse_pre : val proplist_collapse_pre :

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

Loading…
Cancel
Save