[cleanup] remove dead code

Summary:
Found the dead code with the script in the next commit, iteratively until no
warnings remained.

Methodology:
1. I kept pretty-printers for values, which can be useful to use from infer's REPL (or
   when printf-debugging infer in general)
2. I kept functions that formed some consistent API (but not often, so YMMV), for instance if it looked like `Set.S`, or if it provides utility functions for stuff in development (mostly the procname dispatcher functions)
3. I tried not to lose comments associated with values no longer exported: if the value is commented in the .mli and not the .ml, I moved the comment
4. Some comments needed updating (not claiming I caught all of those)
5. Sometimes I rewrote the comments a bit when I noticed mis-attached comments

Reviewed By: mbouaziz

Differential Revision: D6723482

fbshipit-source-id: eabaafd
master
Jules Villard 7 years ago committed by Facebook Github Bot
parent 92e3d56f2e
commit 4b1a7b1771

@ -233,11 +233,6 @@ module Abs = struct
None None
let get_footprint_index access_path =
let base, _ = extract access_path in
get_footprint_index_base base
let is_exact = function Exact _ -> true | Abstracted _ -> false let is_exact = function Exact _ -> true | Abstracted _ -> false
let ( <= ) ~lhs ~rhs = let ( <= ) ~lhs ~rhs =

@ -40,9 +40,6 @@ val get_typ : t -> Tenv.t -> Typ.t option
val base_of_pvar : Pvar.t -> Typ.t -> base val base_of_pvar : Pvar.t -> Typ.t -> base
(** create a base from a pvar *) (** create a base from a pvar *)
val base_of_id : Ident.t -> Typ.t -> base
(** create a base from an ident *)
val of_pvar : Pvar.t -> Typ.t -> t val of_pvar : Pvar.t -> Typ.t -> t
(** create an access path from a pvar *) (** create an access path from a pvar *)
@ -78,8 +75,6 @@ val pp_base : Format.formatter -> base -> unit
val pp_access : Format.formatter -> access -> unit val pp_access : Format.formatter -> access -> unit
val pp_access_list : Format.formatter -> access list -> unit
module Abs : sig module Abs : sig
type raw = t type raw = t
@ -97,10 +92,6 @@ module Abs : sig
(** return the formal index associated with the base of this access path if there is one, or None (** return the formal index associated with the base of this access path if there is one, or None
otherwise *) otherwise *)
val get_footprint_index : t -> int option
(** return the formal index associated with the base of this access path if there is one, or None
otherwise *)
val with_base : base -> t -> t val with_base : base -> t -> t
(** swap base of existing access path for [base_var] (e.g., `with_base_bvar x y.f.g` produces (** swap base of existing access path for [base_var] (e.g., `with_base_bvar x y.f.g` produces
`x.f.g` *) `x.f.g` *)

@ -46,19 +46,12 @@ module Item = struct
type t = t_ [@@deriving compare] type t = t_ [@@deriving compare]
let equal = [%compare.equal : t]
(** Pretty print an item annotation. *) (** Pretty print an item annotation. *)
let pp fmt ann = let pp fmt ann =
let pp fmt (a, _) = pp fmt a in let pp fmt (a, _) = pp fmt a in
F.fprintf fmt "<%a>" (Pp.seq pp) ann F.fprintf fmt "<%a>" (Pp.seq pp) ann
let to_string ann =
let pp fmt = pp fmt ann in
F.asprintf "%t" pp
(** Empty item annotation. *) (** Empty item annotation. *)
let empty = [] let empty = []

@ -35,18 +35,11 @@ module Item : sig
(** Annotation for one item: a list of annotations with visibility. *) (** Annotation for one item: a list of annotations with visibility. *)
type nonrec t = (t * bool) list [@@deriving compare] type nonrec t = (t * bool) list [@@deriving compare]
val equal : t -> t -> bool
val pp : F.formatter -> t -> unit val pp : F.formatter -> t -> unit
(** Pretty print an item annotation. *) (** Pretty print an item annotation. *)
val to_string : t -> string
val empty : t val empty : t
(** Empty item annotation. *) (** Empty item annotation. *)
val is_empty : t -> bool
(** Check if the item annodation is empty. *)
end end
module Class : sig module Class : sig

@ -45,25 +45,6 @@ let equal = [%compare.equal : t]
The return value false means "don't know". *) The return value false means "don't know". *)
let injective = function PlusA | PlusPI | MinusA | MinusPI | MinusPP -> true | _ -> false let injective = function PlusA | PlusPI | MinusA | MinusPI | MinusPP -> true | _ -> false
(** This function returns true if the operation can be inverted. *)
let invertible = function PlusA | PlusPI | MinusA | MinusPI -> true | _ -> false
(** This function inverts an invertible injective binary operator.
If the [binop] operation is not invertible, the function raises Assert_failure. *)
let invert bop =
match bop with
| PlusA ->
MinusA
| PlusPI ->
MinusPI
| MinusA ->
PlusA
| MinusPI ->
PlusPI
| _ ->
assert false
(** This function returns true if 0 is the right unit of [binop]. (** This function returns true if 0 is the right unit of [binop].
The return value false means "don't know". *) The return value false means "don't know". *)
let is_zero_runit = function PlusA | PlusPI | MinusA | MinusPI | MinusPP -> true | _ -> false let is_zero_runit = function PlusA | PlusPI | MinusA | MinusPI | MinusPP -> true | _ -> false

@ -45,13 +45,6 @@ val injective : t -> bool
wrt. each argument: op(e,-) and op(-, e) is injective for all e. wrt. each argument: op(e,-) and op(-, e) is injective for all e.
The return value false means "don't know". *) The return value false means "don't know". *)
val invertible : t -> bool
(** This function returns true if the operation can be inverted. *)
val invert : t -> t
(** This function inverts an invertible injective binary operator.
If the [binop] operation is not invertible, the function raises Assert_failure. *)
val is_zero_runit : t -> bool val is_zero_runit : t -> bool
(** This function returns true if 0 is the right unit of [binop]. (** This function returns true if 0 is the right unit of [binop].
The return value false means "don't know". *) The return value false means "don't know". *)

@ -29,9 +29,6 @@ val create_cfg : unit -> t
val create_proc_desc : t -> ProcAttributes.t -> Procdesc.t val create_proc_desc : t -> ProcAttributes.t -> Procdesc.t
(** Create a new procdesc *) (** Create a new procdesc *)
val iter_proc_desc : t -> (Typ.Procname.t -> Procdesc.t -> unit) -> unit
(** Iterate over all the procdesc's *)
val fold_proc_desc : t -> (Typ.Procname.t -> Procdesc.t -> 'a -> 'a) -> 'a -> 'a val fold_proc_desc : t -> (Typ.Procname.t -> Procdesc.t -> 'a -> 'a) -> 'a -> 'a
(** Fold over all the procdesc's *) (** Fold over all the procdesc's *)

@ -189,8 +189,6 @@ let get_all_nodes (g: t) =
List.map ~f:(fun node -> (node, get_calls g node)) nodes List.map ~f:(fun node -> (node, get_calls g node)) nodes
let get_nodes_and_calls (g: t) = List.filter ~f:(fun (n, _) -> node_defined g n) (get_all_nodes g)
let node_get_num_ancestors g n = (n, Typ.Procname.Set.cardinal (get_ancestors g n)) let node_get_num_ancestors g n = (n, Typ.Procname.Set.cardinal (get_ancestors g n))
let get_edges (g: t) : ((node * int) * (node * int)) list = let get_edges (g: t) : ((node * int) * (node * int)) list =
@ -203,59 +201,6 @@ let get_edges (g: t) : ((node * int) * (node * int)) list =
node_map_iter f g ; !edges node_map_iter f g ; !edges
(** Return all the children of [n], whether defined or not *)
let get_all_children (g: t) n = (Typ.Procname.Hash.find g.node_map n).children
(** Return the children of [n] which are defined *)
let get_defined_children (g: t) n = Typ.Procname.Set.filter (node_defined g) (get_all_children g n)
(** Return the parents of [n] *)
let get_parents (g: t) n = (Typ.Procname.Hash.find g.node_map n).parents
(** Check if [source] recursively calls [dest] *)
let calls_recursively (g: t) source dest = Typ.Procname.Set.mem source (get_ancestors g dest)
(** Return the children of [n] which are not heirs of [n] *)
let get_nonrecursive_dependents (g: t) n =
let is_not_recursive pn = not (Typ.Procname.Set.mem pn (get_ancestors g n)) in
let res0 = Typ.Procname.Set.filter is_not_recursive (get_all_children g n) in
let res = Typ.Procname.Set.filter (node_defined g) res0 in
res
(** Return the ancestors of [n] which are also heirs of [n] *)
let compute_recursive_dependents (g: t) n =
let reached_from_n pn = Typ.Procname.Set.mem n (get_ancestors g pn) in
let res0 = Typ.Procname.Set.filter reached_from_n (get_ancestors g n) in
let res = Typ.Procname.Set.filter (node_defined g) res0 in
res
(** Compute the ancestors of [n] which are also heirs of [n], if not pre-computed already *)
let get_recursive_dependents (g: t) n =
let info = Typ.Procname.Hash.find g.node_map n in
match info.recursive_dependents with
| None ->
let recursive_dependents = compute_recursive_dependents g n in
info.recursive_dependents <- Some recursive_dependents ;
recursive_dependents
| Some recursive_dependents ->
recursive_dependents
(** Return the nodes dependent on [n] *)
let get_dependents (g: t) n =
Typ.Procname.Set.union (get_nonrecursive_dependents g n) (get_recursive_dependents g n)
(** Return all the nodes with their defined children *)
let get_nodes_and_defined_children (g: t) =
let nodes = ref Typ.Procname.Set.empty in
node_map_iter (fun n info -> if info.defined then nodes := Typ.Procname.Set.add n !nodes) g ;
let nodes_list = Typ.Procname.Set.elements !nodes in
List.map ~f:(fun n -> (n, get_defined_children g n)) nodes_list
(** nodes with defined flag, and edges *) (** nodes with defined flag, and edges *)
type nodes_and_edges = (node * bool) list * (node * node) list type nodes_and_edges = (node * bool) list * (node * node) list
@ -278,9 +223,6 @@ let get_defined_nodes (g: t) =
List.map ~f:get_node (List.filter ~f:(fun (_, defined) -> defined) nodes) List.map ~f:get_node (List.filter ~f:(fun (_, defined) -> defined) nodes)
(** Return the path of the source file *)
let get_source (g: t) = g.source
(** [extend cg1 gc2] extends [cg1] in place with nodes and edges from [gc2]; (** [extend cg1 gc2] extends [cg1] in place with nodes and edges from [gc2];
undefined nodes become defined if at least one side is. *) undefined nodes become defined if at least one side is. *)
let extend cg_old cg_new = let extend cg_old cg_new =

@ -12,10 +12,6 @@ open! IStd
(** Module for call graphs *) (** Module for call graphs *)
type in_out_calls =
{ in_calls: int (** total number of in calls transitively *)
; out_calls: int (** total number of out calls transitively *) }
(** the type of a call graph *) (** the type of a call graph *)
type t type t
@ -33,9 +29,6 @@ val add_edge : t -> Typ.Procname.t -> Typ.Procname.t -> unit
val add_defined_node : t -> Typ.Procname.t -> unit val add_defined_node : t -> Typ.Procname.t -> unit
(** Add a node to the call graph as defined *) (** Add a node to the call graph as defined *)
val calls_recursively : t -> Typ.Procname.t -> Typ.Procname.t -> bool
(** Check if [source] recursively calls [dest] *)
val create : SourceFile.t -> t val create : SourceFile.t -> t
(** Create an empty call graph *) (** Create an empty call graph *)
@ -43,55 +36,12 @@ val extend : t -> t -> unit
(** [extend cg1 gc2] extends [cg1] in place with nodes and edges from [gc2]; (** [extend cg1 gc2] extends [cg1] in place with nodes and edges from [gc2];
undefined nodes become defined if at least one side is. *) undefined nodes become defined if at least one side is. *)
val get_all_children : t -> Typ.Procname.t -> Typ.Procname.Set.t
(** Return all the children of [n], whether defined or not *)
val get_ancestors : t -> Typ.Procname.t -> Typ.Procname.Set.t
(** Compute the ancestors of the node, if not pre-computed already *)
val get_heirs : t -> Typ.Procname.t -> Typ.Procname.Set.t
(** Compute the heirs of the node, if not pre-computed already *)
val get_calls : t -> Typ.Procname.t -> in_out_calls
(** Return the in/out calls of the node *)
val get_defined_nodes : t -> Typ.Procname.t list val get_defined_nodes : t -> Typ.Procname.t list
(** Return the list of nodes which are defined *) (** Return the list of nodes which are defined *)
val get_defined_children : t -> Typ.Procname.t -> Typ.Procname.Set.t
(** Return the children of [n] which are defined *)
val get_dependents : t -> Typ.Procname.t -> Typ.Procname.Set.t
(** Return the nodes dependent on [n] *)
val get_nodes_and_calls : t -> (Typ.Procname.t * in_out_calls) list
(** Return the list of nodes with calls *)
val get_nodes_and_defined_children : t -> (Typ.Procname.t * Typ.Procname.Set.t) list
(** Return all the nodes with their defined children *)
val get_nodes_and_edges :
t -> (Typ.Procname.t * bool) list * (Typ.Procname.t * Typ.Procname.t) list
(** Return the list of nodes, with defined flag, and the list of edges *)
val get_nonrecursive_dependents : t -> Typ.Procname.t -> Typ.Procname.Set.t
(** Return the children of [n] which are not heirs of [n] and are defined *)
val get_parents : t -> Typ.Procname.t -> Typ.Procname.Set.t
(** Return the parents of [n] *)
val get_recursive_dependents : t -> Typ.Procname.t -> Typ.Procname.Set.t
(** Return the ancestors of [n] which are also heirs of [n] *)
val get_source : t -> SourceFile.t
(** Return the path of the source file *)
val load_from_file : DB.filename -> t option val load_from_file : DB.filename -> t option
(** Load a call graph from a file *) (** Load a call graph from a file *)
val node_defined : t -> Typ.Procname.t -> bool
(** Returns true if the node is defined *)
val remove_node_defined : t -> Typ.Procname.t -> unit val remove_node_defined : t -> Typ.Procname.t -> unit
(** Remove the defined flag from a node, if it exists. *) (** Remove the defined flag from a node, if it exists. *)

@ -37,9 +37,6 @@ type vpath = t option
val to_string : t -> string val to_string : t -> string
(** convert to a string *) (** convert to a string *)
val pp : F.formatter -> t -> unit
(** pretty print *)
val pp_vpath : Pp.env -> F.formatter -> vpath -> unit val pp_vpath : Pp.env -> F.formatter -> vpath -> unit
(** Pretty print a value path *) (** Pretty print a value path *)

@ -305,117 +305,3 @@ let log_issue err_kind err_log loc (node_id, node_key) session ltr ?linters_def_
d warn_str ; L.d_ln () d warn_str ; L.d_ln ()
in in
if should_print_now then print_now () if should_print_now then print_now ()
type err_log = t
(** Global per-file error table *)
module Err_table = struct
type t = err_log
let create = empty
let count_err err_table err_name locs = ignore (add_issue err_table err_name locs)
let table_size filter (err_table: t) = size filter err_table
let pp_stats_footprint ekind fmt (err_table: err_log) =
let err_name_map = ref String.Map.empty in
(* map error name to count *)
let count_err (err_name: IssueType.t) n =
let err_string = err_name.IssueType.unique_id in
let count = try String.Map.find_exn !err_name_map err_string with Not_found -> 0 in
err_name_map := String.Map.set ~key:err_string ~data:(count + n) !err_name_map
in
let count key err_datas =
if Exceptions.equal_err_kind ekind key.err_kind && key.in_footprint then
count_err key.err_name (ErrDataSet.cardinal err_datas)
in
ErrLogHash.iter count err_table ;
let pp ~key:err_string ~data:count = F.fprintf fmt " %s:%d" err_string count in
String.Map.iteri ~f:pp !err_name_map
module LocMap = Caml.Map.Make (struct
type t = ErrDataSet.elt
let compare = compare_err_data
end)
let print_err_table_details fmt err_table =
let map_err_fp = ref LocMap.empty in
let map_err_re = ref LocMap.empty in
let map_warn_fp = ref LocMap.empty in
let map_warn_re = ref LocMap.empty in
let map_info = ref LocMap.empty in
let map_advice = ref LocMap.empty in
let map_likes = ref LocMap.empty in
let add_err nslm key =
let map =
match (key.in_footprint, key.err_kind) with
| true, Exceptions.Kerror ->
map_err_fp
| false, Exceptions.Kerror ->
map_err_re
| true, Exceptions.Kwarning ->
map_warn_fp
| false, Exceptions.Kwarning ->
map_warn_re
| _, Exceptions.Kinfo ->
map_info
| _, Exceptions.Kadvice ->
map_advice
| _, Exceptions.Klike ->
map_likes
in
try
let err_list = LocMap.find nslm !map in
map := LocMap.add nslm ((key.err_name, key.err_desc) :: err_list) !map
with Not_found -> map := LocMap.add nslm [(key.err_name, key.err_desc)] !map
in
let f err_name eds = ErrDataSet.iter (fun loc -> add_err loc err_name) eds in
ErrLogHash.iter f err_table ;
let pp ekind err_data fmt err_names =
List.iter
~f:(fun (err_name, desc) ->
Exceptions.pp_err ~node_key:err_data.node_id_key.node_key err_data.loc ekind err_name
desc err_data.loc_in_ml_source fmt () )
err_names
in
F.fprintf fmt "@.Detailed errors during footprint phase:@." ;
LocMap.iter
(fun nslm err_names -> F.fprintf fmt "%a" (pp Exceptions.Kerror nslm) err_names)
!map_err_fp ;
F.fprintf fmt "@.Detailed errors during re-execution phase:@." ;
LocMap.iter
(fun nslm err_names -> F.fprintf fmt "%a" (pp Exceptions.Kerror nslm) err_names)
!map_err_re ;
F.fprintf fmt "@.Detailed warnings during footprint phase:@." ;
LocMap.iter
(fun nslm err_names -> F.fprintf fmt "%a" (pp Exceptions.Kwarning nslm) err_names)
!map_warn_fp ;
F.fprintf fmt "@.Detailed warnings during re-execution phase:@." ;
LocMap.iter
(fun nslm err_names -> F.fprintf fmt "%a" (pp Exceptions.Kwarning nslm) err_names)
!map_warn_re
end
type err_table = Err_table.t
(** Create an error table *)
let create_err_table = Err_table.create
(** Print an error log and add it to the global per-file table *)
let extend_table err_table err_log = ErrLogHash.iter (Err_table.count_err err_table) err_log
(** Size of the global per-file error table for the footprint phase *)
let err_table_size_footprint ekind =
let filter ekind' in_footprint = Exceptions.equal_err_kind ekind ekind' && in_footprint in
Err_table.table_size filter
(** Print stats for the global per-file error table *)
let pp_err_table_stats ekind = Err_table.pp_stats_footprint ekind
(** Print details of the global per-file error table *)
let print_err_table_details = Err_table.print_err_table_details

@ -73,7 +73,7 @@ val iter : iter_fun -> t -> unit
val fold : (err_key -> err_data -> 'a -> 'a) -> t -> 'a -> 'a val fold : (err_key -> err_data -> 'a -> 'a) -> t -> 'a -> 'a
val pp_loc_trace_elem : Format.formatter -> loc_trace_elem -> unit val pp_loc_trace_elem : Format.formatter -> loc_trace_elem -> unit [@@warning "-32"]
val pp_loc_trace : Format.formatter -> loc_trace -> unit val pp_loc_trace : Format.formatter -> loc_trace -> unit
@ -95,23 +95,3 @@ val update : t -> t -> unit
val log_issue : val log_issue :
Exceptions.err_kind -> t -> Location.t -> int * Caml.Digest.t -> int -> loc_trace Exceptions.err_kind -> t -> Location.t -> int * Caml.Digest.t -> int -> loc_trace
-> ?linters_def_file:string -> ?doc_url:string -> ?access:string -> exn -> unit -> ?linters_def_file:string -> ?doc_url:string -> ?access:string -> exn -> unit
(** {2 Functions for manipulating per-file error tables} *)
(** Type for per-file error tables *)
type err_table
val create_err_table : unit -> err_table
(** Create an error table *)
val extend_table : err_table -> t -> unit
(** Add an error log to the global per-file table *)
val err_table_size_footprint : Exceptions.err_kind -> err_table -> int
(** Size of the global per-file error table for the footprint phase *)
val pp_err_table_stats : Exceptions.err_kind -> Format.formatter -> err_table -> unit
(** Print stats for the global per-file error table *)
val print_err_table_details : Format.formatter -> err_table -> unit
(** Print details of the global per-file error table *)

@ -74,10 +74,6 @@ module Hash = Hashtbl.Make (struct
let hash = hash let hash = hash
end) end)
let rec is_array_index_of exp1 exp2 =
match exp1 with Lindex (exp, _) -> is_array_index_of exp exp2 | _ -> equal exp1 exp2
let is_null_literal = function Const Cint n -> IntLit.isnull n | _ -> false let is_null_literal = function Const Cint n -> IntLit.isnull n | _ -> false
let is_this = function Lvar pvar -> Pvar.is_this pvar | _ -> false let is_this = function Lvar pvar -> Pvar.is_this pvar | _ -> false
@ -131,17 +127,6 @@ let get_undefined footprint =
Var (Ident.create_fresh (if footprint then Ident.kfootprint else Ident.kprimed)) Var (Ident.create_fresh (if footprint then Ident.kfootprint else Ident.kprimed))
(** returns true if the expression represents a stack-directed address *)
let rec is_stack_addr e =
match (e : t) with
| Lvar pv ->
not (Pvar.is_global pv)
| UnOp (_, e', _) | Cast (_, e') | Lfield (e', _, _) | Lindex (e', _) ->
is_stack_addr e'
| _ ->
false
(** returns true if the express operates on address of local variable *) (** returns true if the express operates on address of local variable *)
let rec has_local_addr e = let rec has_local_addr e =
match (e : t) with match (e : t) with

@ -47,9 +47,6 @@ and t =
val equal : t -> t -> bool val equal : t -> t -> bool
(** Equality for expressions. *) (** Equality for expressions. *)
val hash : t -> int
(** Hash function for expressions. *)
(** Set of expressions. *) (** Set of expressions. *)
module Set : Caml.Set.S with type elt = t module Set : Caml.Set.S with type elt = t
@ -59,9 +56,6 @@ module Map : Caml.Map.S with type key = t
(** Hashtable with expression keys. *) (** Hashtable with expression keys. *)
module Hash : Caml.Hashtbl.S with type key = t module Hash : Caml.Hashtbl.S with type key = t
val is_array_index_of : t -> t -> bool
(** returns true is index is an array index of arr. *)
val is_null_literal : t -> bool val is_null_literal : t -> bool
val is_this : t -> bool val is_this : t -> bool
@ -86,9 +80,6 @@ val pointer_arith : t -> bool
(** Checks whether an expression denotes a location using pointer arithmetic. (** Checks whether an expression denotes a location using pointer arithmetic.
Currently, catches array - indexing expressions such as a[i] only. *) Currently, catches array - indexing expressions such as a[i] only. *)
val is_stack_addr : t -> bool
(** returns true if the expression represents a stack-directed address *)
val has_local_addr : t -> bool val has_local_addr : t -> bool
(** returns true if the expression operates on address of local variable *) (** returns true if the expression operates on address of local variable *)

@ -13,8 +13,6 @@ 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 AccessPath.t [@@deriving compare] type call = Direct of Typ.Procname.t | Indirect of AccessPath.t [@@deriving compare]
val pp_call : F.formatter -> call -> unit
type t = type t =
| Assign of AccessPath.t * HilExp.t * Location.t (** LHS access path, RHS expression *) | Assign of AccessPath.t * HilExp.t * Location.t (** LHS access path, RHS expression *)
| Assume of HilExp.t * [`Then | `Else] * Sil.if_kind * Location.t | Assume of HilExp.t * [`Then | `Else] * Sil.if_kind * Location.t

@ -45,8 +45,6 @@ type name = Name.t [@@deriving compare]
let name_spec = Name.Spec let name_spec = Name.Spec
let name_primed = Name.Primed
let equal_name = [%compare.equal : name] let equal_name = [%compare.equal : name]
type kind = type kind =
@ -187,9 +185,6 @@ let create_fresh kind = NameGenerator.create_fresh_ident kind (standard_name kin
let create_none () = create_fresh KNone let create_none () = create_fresh KNone
(** Generate a primed identifier with the given name and stamp *)
let create_primed name stamp = create_with_stamp KPrimed name stamp
(** Generate a footprint identifier with the given name and stamp *) (** Generate a footprint identifier with the given name and stamp *)
let create_footprint name stamp = create_with_stamp KFootprint name stamp let create_footprint name stamp = create_with_stamp KFootprint name stamp
@ -210,12 +205,6 @@ let is_none (id: t) = has_kind id KNone
let is_path (id: t) = has_kind id KNormal && Int.equal id.stamp path_ident_stamp let is_path (id: t) = has_kind id KNormal && Int.equal id.stamp path_ident_stamp
let make_unprimed id =
if not (has_kind id KPrimed) then assert false
else if has_kind id KNone then {id with kind= KNone}
else {id with kind= KNormal}
(** Update the name generator so that the given id's are not generated again *) (** Update the name generator so that the given id's are not generated again *)
let update_name_generator ids = let update_name_generator ids =
let upd id = ignore (create_with_stamp id.kind id.name id.stamp) in let upd id = ignore (create_with_stamp id.kind id.name id.stamp) in
@ -247,6 +236,3 @@ let pp f id = F.fprintf f "%s" (to_string id)
(** pretty printer for lists of identifiers *) (** pretty printer for lists of identifiers *)
let pp_list = Pp.comma_seq pp let pp_list = Pp.comma_seq pp
(** pretty printer for lists of names *)
let pp_name_list = Pp.comma_seq pp_name

@ -64,9 +64,6 @@ val kfootprint : kind
(** hash table with names as keys *) (** hash table with names as keys *)
module NameHash : Caml.Hashtbl.S with type key = name module NameHash : Caml.Hashtbl.S with type key = name
val name_primed : name
(** Name used for primed tmp variables *)
val name_spec : name val name_spec : name
(** Name used for spec variables *) (** Name used for spec variables *)
@ -91,9 +88,6 @@ val create_normal : name -> int -> t
val create_none : unit -> t val create_none : unit -> t
(** Create a "null" identifier for situations where the IR requires an id that will never be read *) (** Create a "null" identifier for situations where the IR requires an id that will never be read *)
val create_primed : name -> int -> t
(** Generate a primed identifier with the given name and stamp. *)
val create_footprint : name -> int -> t val create_footprint : name -> int -> t
(** Generate a footprint identifier with the given name and stamp. *) (** Generate a footprint identifier with the given name and stamp. *)
@ -121,9 +115,6 @@ val is_path : t -> bool
val is_none : t -> bool val is_none : t -> bool
(** Check whether an identifier is the special "none" identifier *) (** Check whether an identifier is the special "none" identifier *)
val make_unprimed : t -> t
(** Convert a primed ident into a nonprimed one, keeping the stamp. *)
val get_stamp : t -> int val get_stamp : t -> int
(** Get the stamp of the identifier *) (** Get the stamp of the identifier *)
@ -143,6 +134,3 @@ val to_string : t -> string
val pp_list : Format.formatter -> t list -> unit val pp_list : Format.formatter -> t list -> unit
(** Pretty print a list of identifiers. *) (** Pretty print a list of identifiers. *)
val pp_name_list : Format.formatter -> name list -> unit
(** Pretty print a list of names. *)

@ -59,8 +59,6 @@ let of_int64 i = (false, i, false)
let of_int32 i = of_int64 (Int64.of_int32 i) let of_int32 i = of_int64 (Int64.of_int32 i)
let of_int64_unsigned i unsigned = (unsigned, i, false)
let of_int i = of_int64 (Int64.of_int i) let of_int i = of_int64 (Int64.of_int i)
let to_int (_, i, _) = Int64.to_int_exn i let to_int (_, i, _) = Int64.to_int_exn i

@ -35,11 +35,9 @@ val of_int32 : int32 -> t
val of_int64 : int64 -> t val of_int64 : int64 -> t
val of_int64_unsigned : int64 -> bool -> t
val geq : t -> t -> bool val geq : t -> t -> bool
val gt : t -> t -> bool val gt : t -> t -> bool [@@warning "-32"]
val isminusone : t -> bool val isminusone : t -> bool

@ -212,38 +212,14 @@ end
module Xml = struct module Xml = struct
let tag_branch = "branch" let tag_branch = "branch"
let tag_call_trace = "call_trace"
let tag_callee = "callee"
let tag_callee_id = "callee_id"
let tag_caller = "caller"
let tag_caller_id = "caller_id"
let tag_class = "class"
let tag_code = "code"
let tag_description = "description"
let tag_err = "err" let tag_err = "err"
let tag_flags = "flags"
let tag_file = "file" let tag_file = "file"
let tag_hash = "hash"
let tag_in_calls = "in_calls" let tag_in_calls = "in_calls"
let tag_key = "key"
let tag_kind = "kind" let tag_kind = "kind"
let tag_level = "level"
let tag_line = "line" let tag_line = "line"
let tag_loc = "loc" let tag_loc = "loc"
@ -252,28 +228,14 @@ module Xml = struct
let tag_name_id = "name_id" let tag_name_id = "name_id"
let tag_node = "node"
let tag_out_calls = "out_calls" let tag_out_calls = "out_calls"
let tag_precondition = "precondition"
let tag_procedure = "procedure"
let tag_procedure_id = "procedure_id"
let tag_proof_coverage = "proof_coverage" let tag_proof_coverage = "proof_coverage"
let tag_proof_trace = "proof_trace" let tag_proof_trace = "proof_trace"
let tag_qualifier = "qualifier"
let tag_qualifier_tags = "qualifier_tags"
let tag_rank = "rank" let tag_rank = "rank"
let tag_severity = "severity"
let tag_signature = "signature" let tag_signature = "signature"
let tag_specs = "specs" let tag_specs = "specs"
@ -286,60 +248,7 @@ module Xml = struct
let tag_top = "top" let tag_top = "top"
let tag_trace = "trace"
let tag_type = "type"
let tag_weight = "weight" let tag_weight = "weight"
type tree = {name: string; attributes: (string * string) list; forest: node list}
and node = Tree of tree | String of string
let pp = F.fprintf
let create_tree name attributes forest = Tree {name; attributes; forest}
let pp_attribute fmt (name, value) = pp fmt "%s=\"%s\"" name value
let pp_attributes fmt l = Pp.seq pp_attribute fmt l
(** print an xml node *)
let rec pp_node newline indent fmt = function
| Tree {name; attributes; forest} ->
let indent' = if String.equal newline "" then "" else indent ^ " " in
let space = if List.is_empty attributes then "" else " " in
let pp_inside fmt () =
match forest with
| [] ->
()
| [(String s)] ->
pp fmt "%s" s
| _ ->
pp fmt "%s%a%s" newline (pp_forest newline indent') forest indent
in
pp fmt "%s<%s%s%a>%a</%s>%s" indent name space pp_attributes attributes pp_inside () name
newline
| String s ->
F.fprintf fmt "%s%s%s" indent s newline
and pp_forest newline indent fmt forest = List.iter ~f:(pp_node newline indent fmt) forest
let pp_prelude fmt = pp fmt "%s" "<?xml version=\"1.0\" encoding=\"UTF-8\"?>@\n"
let pp_open fmt name = pp_prelude fmt ; pp fmt "<%s>@\n" name
let pp_close fmt name = pp fmt "</%s>@." name
let pp_inner_node fmt node = pp_node "\n" "" fmt node
(** print an xml document, if the first parameter is false on a single line without preamble *)
let pp_document on_several_lines fmt node =
let newline = if on_several_lines then "\n" else "" in
if on_several_lines then pp_prelude fmt ;
pp_node newline "" fmt node ;
if on_several_lines then pp fmt "@."
end end
(* =============== END of module Xml =============== *) (* =============== END of module Xml =============== *)

@ -64,38 +64,14 @@ end
module Xml : sig module Xml : sig
val tag_branch : string val tag_branch : string
val tag_call_trace : string
val tag_callee : string
val tag_callee_id : string
val tag_caller : string
val tag_caller_id : string
val tag_class : string
val tag_code : string
val tag_description : string
val tag_err : string val tag_err : string
val tag_file : string val tag_file : string
val tag_flags : string
val tag_hash : string
val tag_in_calls : string val tag_in_calls : string
val tag_key : string
val tag_kind : string val tag_kind : string
val tag_level : string
val tag_line : string val tag_line : string
val tag_loc : string val tag_loc : string
@ -104,28 +80,14 @@ module Xml : sig
val tag_name_id : string val tag_name_id : string
val tag_node : string
val tag_out_calls : string val tag_out_calls : string
val tag_precondition : string
val tag_procedure : string
val tag_procedure_id : string
val tag_proof_coverage : string val tag_proof_coverage : string
val tag_proof_trace : string val tag_proof_trace : string
val tag_qualifier : string
val tag_qualifier_tags : string
val tag_rank : string val tag_rank : string
val tag_severity : string
val tag_signature : string val tag_signature : string
val tag_specs : string val tag_specs : string
@ -138,27 +100,5 @@ module Xml : sig
val tag_top : string val tag_top : string
val tag_trace : string
val tag_type : string
val tag_weight : string val tag_weight : string
type tree = {name: string; attributes: (string * string) list; forest: node list}
and node = Tree of tree | String of string (** create a tree *)
val create_tree : string -> (string * string) list -> node list -> node
val pp_document : bool -> Format.formatter -> node -> unit
(** print an xml document, if the first parameter is false on a single line without preamble *)
val pp_open : Format.formatter -> string -> unit
(** print the opening lines of an xml document consisting of a main tree with the given name *)
val pp_close : Format.formatter -> string -> unit
(** print the closing lines of an xml document consisting of a main tree with the given name *)
val pp_inner_node : Format.formatter -> node -> unit
(** print a node between a [pp_open] and a [pp_close] *)
end end

@ -128,8 +128,6 @@ let no_desc : error_desc = {descriptions= []; advice= None; tags= []; dotty= Non
(** verbatim desc from a string, not to be used for user-visible descs *) (** verbatim desc from a string, not to be used for user-visible descs *)
let verbatim_desc s = {no_desc with descriptions= [s]} let verbatim_desc s = {no_desc with descriptions= [s]}
let custom_desc s tags = {no_desc with descriptions= [s]; tags}
let custom_desc_with_advice description advice tags = let custom_desc_with_advice description advice tags =
{no_desc with descriptions= [description]; advice= Some advice; tags} {no_desc with descriptions= [description]; advice= Some advice; tags}
@ -140,14 +138,6 @@ let pp_error_desc fmt err_desc =
Pp.seq pp_item fmt err_desc.descriptions Pp.seq pp_item fmt err_desc.descriptions
(** pretty print an error advice *)
let pp_error_advice fmt err_desc =
match err_desc.advice with Some advice -> F.fprintf fmt "%s" advice | None -> ()
(** get tags of error description *)
let error_desc_get_tags err_desc = err_desc.tags
let error_desc_get_dotty err_desc = err_desc.dotty let error_desc_get_dotty err_desc = err_desc.dotty
module BucketLevel = struct module BucketLevel = struct
@ -171,16 +161,6 @@ let error_desc_extract_tag_value err_desc tag_to_extract =
match List.find ~f:(find_value tag_to_extract) err_desc.tags with Some (_, s) -> s | None -> "" match List.find ~f:(find_value tag_to_extract) err_desc.tags with Some (_, s) -> s | None -> ""
let error_desc_to_tag_value_pairs err_desc = err_desc.tags
(** returns the content of the value tag of the error_desc *)
let error_desc_get_tag_value error_desc = error_desc_extract_tag_value error_desc Tags.value
(** returns the content of the call_procedure tag of the error_desc *)
let error_desc_get_tag_call_procedure error_desc =
error_desc_extract_tag_value error_desc Tags.call_procedure
(** get the bucket value of an error_desc, if any *) (** get the bucket value of an error_desc, if any *)
let error_desc_get_bucket err_desc = Tags.get err_desc.tags Tags.bucket let error_desc_get_bucket err_desc = Tags.get err_desc.tags Tags.bucket
@ -445,22 +425,6 @@ let deref_str_array_bound size_opt index_opt =
; problem_str= "could be accessed with " ^ index_str ^ " out of bounds" } ; problem_str= "could be accessed with " ^ index_str ^ " out of bounds" }
(** dereference strings for an uninitialized access whose lhs has the given attribute *)
let deref_str_uninitialized alloc_att_opt =
let tags = Tags.create () in
let creation_str =
match alloc_att_opt with
| Some Sil.Apred (Aresource ({ra_kind= Racquire} as ra), _) ->
"after allocation " ^ by_call_to_ra tags ra
| _ ->
"after declaration"
in
{ tags
; value_pre= Some "value"
; value_post= None
; problem_str= "was not initialized " ^ creation_str ^ " and is used" }
(** Java unchecked exceptions errors *) (** Java unchecked exceptions errors *)
let java_unchecked_exn_desc proc_name exn_name pre_str : error_desc = let java_unchecked_exn_desc proc_name exn_name pre_str : error_desc =
{ no_desc with { no_desc with
@ -673,10 +637,6 @@ let is_parameter_not_null_checked_desc desc = has_tag desc Tags.parameter_not_nu
let is_field_not_null_checked_desc desc = has_tag desc Tags.field_not_null_checked let is_field_not_null_checked_desc desc = has_tag desc Tags.field_not_null_checked
let is_parameter_field_not_null_checked_desc desc =
is_parameter_not_null_checked_desc desc || is_field_not_null_checked_desc desc
let is_double_lock_desc desc = has_tag desc Tags.double_lock let is_double_lock_desc desc = has_tag desc Tags.double_lock
let desc_allocation_mismatch alloc dealloc = let desc_allocation_mismatch alloc dealloc =
@ -704,11 +664,6 @@ let desc_allocation_mismatch alloc dealloc =
{no_desc with descriptions= [description]; tags= !tags} {no_desc with descriptions= [description]; tags= !tags}
let desc_comparing_floats_for_equality loc =
let tags = Tags.create () in
{no_desc with descriptions= ["Comparing floats for equality " ^ at_line tags loc]; tags= !tags}
let desc_condition_always_true_false i cond_str_opt loc = let desc_condition_always_true_false i cond_str_opt loc =
let tags = Tags.create () in let tags = Tags.create () in
let value = match cond_str_opt with None -> "" | Some s -> s in let value = match cond_str_opt with None -> "" | Some s -> s in
@ -889,16 +844,6 @@ let desc_null_test_after_dereference expr_str line loc =
{no_desc with descriptions= [description]; tags= !tags} {no_desc with descriptions= [description]; tags= !tags}
let desc_return_expression_required typ_str loc =
let tags = Tags.create () in
Tags.update tags Tags.value typ_str ;
let description =
Format.sprintf "Return statement requires an expression of type %s %s" typ_str
(at_line tags loc)
in
{no_desc with descriptions= [description]; tags= !tags}
let desc_retain_cycle cycle_str loc cycle_dotty = let desc_retain_cycle cycle_str loc cycle_dotty =
Logging.d_strln "Proposition with retain cycle:" ; Logging.d_strln "Proposition with retain cycle:" ;
let tags = Tags.create () in let tags = Tags.create () in
@ -925,16 +870,6 @@ let desc_registered_observer_being_deallocated pvar loc =
; tags= !tags } ; tags= !tags }
let desc_return_statement_missing loc =
let tags = Tags.create () in
{no_desc with descriptions= ["Return statement missing " ^ at_line tags loc]; tags= !tags}
let desc_return_value_ignored proc_name loc =
let tags = Tags.create () in
{no_desc with descriptions= ["after " ^ call_to_at_line tags proc_name loc]; tags= !tags}
let desc_unary_minus_applied_to_unsigned_expression expr_str_opt typ_str loc = let desc_unary_minus_applied_to_unsigned_expression expr_str_opt typ_str loc =
let tags = Tags.create () in let tags = Tags.create () in
let expression = let expression =

@ -36,9 +36,6 @@ val no_desc : error_desc
val verbatim_desc : string -> error_desc val verbatim_desc : string -> error_desc
(** verbatim desc from a string, not to be used for user-visible descs *) (** verbatim desc from a string, not to be used for user-visible descs *)
val custom_desc : string -> (string * string) list -> error_desc
(** verbatim desc with custom tags *)
val custom_desc_with_advice : string -> string -> (string * string) list -> error_desc val custom_desc_with_advice : string -> string -> (string * string) list -> error_desc
(** verbatim desc with advice and custom tags *) (** verbatim desc with advice and custom tags *)
@ -50,7 +47,7 @@ module BucketLevel : sig
val b3 : string val b3 : string
val b4 : string val b4 : string [@@warning "-32"]
val b5 : string val b5 : string
(** lowest likelihood *) (** lowest likelihood *)
@ -59,15 +56,6 @@ end
val error_desc_extract_tag_value : error_desc -> string -> string val error_desc_extract_tag_value : error_desc -> string -> string
(** returns the value of a tag or the empty string *) (** returns the value of a tag or the empty string *)
val error_desc_to_tag_value_pairs : error_desc -> (string * string) list
(** returns all the tuples (tag, value) of an error_desc *)
val error_desc_get_tag_value : error_desc -> string
(** returns the content of the value tag of the error_desc *)
val error_desc_get_tag_call_procedure : error_desc -> string
(** returns the content of the call_procedure tag of the error_desc *)
val error_desc_get_bucket : error_desc -> string option val error_desc_get_bucket : error_desc -> string option
(** get the bucket value of an error_desc, if any *) (** get the bucket value of an error_desc, if any *)
@ -86,12 +74,6 @@ val error_desc_equal : error_desc -> error_desc -> bool
val pp_error_desc : Format.formatter -> error_desc -> unit val pp_error_desc : Format.formatter -> error_desc -> unit
(** pretty print an error description *) (** pretty print an error description *)
val pp_error_advice : Format.formatter -> error_desc -> unit
(** pretty print an error advice *)
val error_desc_get_tags : error_desc -> (string * string) list
(** get tags of error description *)
val error_desc_get_dotty : error_desc -> string option val error_desc_get_dotty : error_desc -> string option
(** Description functions for error messages *) (** Description functions for error messages *)
@ -120,9 +102,6 @@ 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_uninitialized : Sil.atom option -> deref_str
(** dereference strings for an uninitialized access whose lhs has the given attribute *)
val deref_str_nil_argument_in_variadic_method : Typ.Procname.t -> int -> int -> deref_str val deref_str_nil_argument_in_variadic_method : Typ.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 *)
@ -148,8 +127,6 @@ 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 is_parameter_field_not_null_checked_desc : error_desc -> bool
val desc_allocation_mismatch : val desc_allocation_mismatch :
Typ.Procname.t * Typ.Procname.t * Location.t -> Typ.Procname.t * Typ.Procname.t * Location.t Typ.Procname.t * Typ.Procname.t * Location.t -> Typ.Procname.t * Typ.Procname.t * Location.t
-> error_desc -> error_desc
@ -157,8 +134,6 @@ val desc_allocation_mismatch :
val desc_class_cast_exception : val desc_class_cast_exception :
Typ.Procname.t option -> string -> string -> string option -> Location.t -> error_desc Typ.Procname.t option -> string -> string -> string option -> Location.t -> error_desc
val desc_comparing_floats_for_equality : Location.t -> error_desc
val desc_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_unreachable_code_after : Location.t -> error_desc val desc_unreachable_code_after : Location.t -> error_desc
@ -202,18 +177,10 @@ 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 -> Typ.Procname.t -> Location.t -> error_desc
val desc_return_expression_required : string -> 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
val registered_observer_being_deallocated_str : string -> string
val desc_registered_observer_being_deallocated : Pvar.t -> Location.t -> error_desc val desc_registered_observer_being_deallocated : Pvar.t -> Location.t -> error_desc
val desc_return_statement_missing : Location.t -> error_desc
val desc_return_value_ignored : Typ.Procname.t -> Location.t -> error_desc
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 : Typ.Procname.t -> error_desc

@ -19,9 +19,6 @@ type t =
let equal = [%compare.equal : t] let equal = [%compare.equal : t]
(** Dump a location *)
let d (loc: t) = L.add_print_action (L.PTloc, Obj.repr loc)
let none file = {line= -1; col= -1; file} let none file = {line= -1; col= -1; file}
let dummy = none (SourceFile.invalid __FILE__) let dummy = none (SourceFile.invalid __FILE__)

@ -18,9 +18,6 @@ type t =
val equal : t -> t -> bool val equal : t -> t -> bool
val d : t -> unit
(** Dump a location. *)
val none : SourceFile.t -> t val none : SourceFile.t -> t
(** Dummy source location for the given file *) (** Dummy source location for the given file *)

@ -31,9 +31,6 @@ let to_string_full (pn: t) =
match pn.mangled with Some mangled -> pn.plain ^ "{" ^ mangled ^ "}" | None -> pn.plain match pn.mangled with Some mangled -> pn.plain ^ "{" ^ mangled ^ "}" | None -> pn.plain
(** Get mangled string if given *)
let get_mangled pn = match pn.mangled with Some s -> s | None -> pn.plain
(** Pretty print a mangled name *) (** Pretty print a mangled name *)
let pp f pn = F.fprintf f "%s" (to_string pn) let pp f pn = F.fprintf f "%s" (to_string pn)

@ -30,9 +30,6 @@ val to_string : t -> string
val to_string_full : t -> string val to_string_full : t -> string
(** Convert a full mangled name to a string *) (** Convert a full mangled name to a string *)
val get_mangled : t -> string
(** Get mangled string if given *)
val pp : Format.formatter -> t -> unit val pp : Format.formatter -> t -> unit
(** Pretty print a mangled name *) (** Pretty print a mangled name *)

@ -176,11 +176,6 @@ module Core_foundation_model = struct
core_graphics_types core_graphics_types
let is_objc_memory_model_controlled o =
List.mem ~equal:String.equal core_foundation_types o
|| List.mem ~equal:String.equal core_graphics_types o
let rec is_core_lib lib typ = let rec is_core_lib lib typ =
match typ.Typ.desc with match typ.Typ.desc with
| Typ.Tptr (styp, _) -> | Typ.Tptr (styp, _) ->

@ -12,12 +12,6 @@ open! IStd
(** This module models special c struct types from the Apple's Core Foundation libraries (** This module models special c struct types from the Apple's Core Foundation libraries
for which there are particular rules for memory management. *) for which there are particular rules for memory management. *)
module Core_foundation_model : sig
val is_core_lib_create : Typ.t -> string -> bool
val is_objc_memory_model_controlled : string -> bool
end
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 -> Typ.Procname.t -> bool

@ -178,8 +178,6 @@ let to_category att =
let is_undef = function Aundef _ -> true | _ -> false let is_undef = function Aundef _ -> true | _ -> false
let is_wont_leak = function Awont_leak -> true | _ -> false
(** convert the attribute to a string *) (** convert the attribute to a string *)
let to_string pe = function let to_string pe = function
| Aresource ra -> | Aresource ra ->

@ -115,8 +115,6 @@ val to_category : t -> category
val is_undef : t -> bool val is_undef : t -> bool
val is_wont_leak : t -> bool
val to_string : Pp.env -> t -> string val to_string : Pp.env -> t -> string
(** convert the attribute to a string *) (** convert the attribute to a string *)

@ -24,12 +24,6 @@ let compare_proc_flags x y =
let proc_flags_empty () : proc_flags = Hashtbl.create 1 let proc_flags_empty () : proc_flags = Hashtbl.create 1
let proc_flag_ignore_return = "ignore_return"
let proc_flags_add proc_flags key value = Hashtbl.replace proc_flags key value
let proc_flags_find proc_flags key = Hashtbl.find proc_flags key
(** Type for ObjC accessors *) (** Type for ObjC accessors *)
type objc_accessor_type = type objc_accessor_type =
| Objc_getter of Typ.Struct.field | Objc_getter of Typ.Struct.field

@ -14,20 +14,6 @@ open! IStd
(** flags for a procedure *) (** flags for a procedure *)
type proc_flags = (string, string) Caml.Hashtbl.t [@@deriving compare] type proc_flags = (string, string) Caml.Hashtbl.t [@@deriving compare]
val proc_flag_ignore_return : string
(** key to specify that a function should be treated as a skip function *)
(** key to specify that it is OK to ignore the return value *)
val proc_flags_empty : unit -> proc_flags
(** empty proc flags *)
val proc_flags_add : proc_flags -> string -> string -> unit
(** add a key value pair to a proc flags *)
val proc_flags_find : proc_flags -> string -> string
(** find a value for a key in the proc flags *)
type objc_accessor_type = type objc_accessor_type =
| Objc_getter of Typ.Struct.field | Objc_getter of Typ.Struct.field
| Objc_setter of Typ.Struct.field | Objc_setter of Typ.Struct.field

@ -85,36 +85,6 @@ module Node = struct
let compare = compare_id let compare = compare_id
end) end)
let get_sliced_succs node f =
let visited = ref NodeSet.empty in
let rec slice_nodes nodes : NodeSet.t =
let do_node acc n =
visited := NodeSet.add n !visited ;
if f n then NodeSet.singleton n
else
NodeSet.union acc
(slice_nodes (List.filter ~f:(fun s -> not (NodeSet.mem s !visited)) n.succs))
in
List.fold ~f:do_node ~init:NodeSet.empty nodes
in
NodeSet.elements (slice_nodes node.succs)
let get_sliced_preds node f =
let visited = ref NodeSet.empty in
let rec slice_nodes nodes : NodeSet.t =
let do_node acc n =
visited := NodeSet.add n !visited ;
if f n then NodeSet.singleton n
else
NodeSet.union acc
(slice_nodes (List.filter ~f:(fun s -> not (NodeSet.mem s !visited)) n.preds))
in
List.fold ~f:do_node ~init:NodeSet.empty nodes
in
NodeSet.elements (slice_nodes node.preds)
let get_exn node = node.exn let get_exn node = node.exn
(** Get the name of the procedure the node belongs to *) (** Get the name of the procedure the node belongs to *)
@ -130,36 +100,12 @@ module Node = struct
(** Get the predecessors of the node *) (** Get the predecessors of the node *)
let get_preds node = node.preds let get_preds node = node.preds
(** Generates a list of nodes starting at a given node
and recursively adding the results of the generator *)
let get_generated_slope start_node generator =
let visited = ref NodeSet.empty in
let rec nodes n =
visited := NodeSet.add n !visited ;
let succs = List.filter ~f:(fun n -> not (NodeSet.mem n !visited)) (generator n) in
match succs with [hd] -> n :: nodes hd | _ -> [n]
in
nodes start_node
(** Get the node kind *) (** Get the node kind *)
let get_kind node = node.kind let get_kind node = node.kind
(** Get the instructions to be executed *) (** Get the instructions to be executed *)
let get_instrs node = node.instrs let get_instrs node = node.instrs
(** Get the list of callee procnames from the node *)
let get_callees node =
let collect callees instr =
match instr with
| Sil.Call (_, exp, _, _, _) -> (
match exp with Exp.Const Const.Cfun procname -> procname :: callees | _ -> callees )
| _ ->
callees
in
List.fold ~f:collect ~init:[] (get_instrs node)
(** Get the location of the node *) (** Get the location of the node *)
let get_loc n = n.loc let get_loc n = n.loc
@ -312,13 +258,8 @@ let signal_did_preanalysis pdesc = (pdesc.attributes).did_preanalysis <- true
let get_attributes pdesc = pdesc.attributes let get_attributes pdesc = pdesc.attributes
let get_err_log pdesc = pdesc.attributes.err_log
let get_exit_node pdesc = pdesc.exit_node let get_exit_node pdesc = pdesc.exit_node
(** Get flags for the proc desc *)
let get_flags pdesc = pdesc.attributes.proc_flags
(** Return name and type of formal parameters *) (** Return name and type of formal parameters *)
let get_formals pdesc = pdesc.attributes.formals let get_formals pdesc = pdesc.attributes.formals
@ -344,35 +285,13 @@ let get_ret_var pdesc = Pvar.mk Ident.name_return (get_proc_name pdesc)
let get_start_node pdesc = pdesc.start_node let get_start_node pdesc = pdesc.start_node
(** List of nodes in the procedure sliced by a predicate up to the first branching *)
let get_sliced_slope pdesc f =
Node.get_generated_slope (get_start_node pdesc) (fun n -> Node.get_sliced_succs n f)
(** List of nodes in the procedure up to the first branching *)
let get_slope pdesc = Node.get_generated_slope (get_start_node pdesc) Node.get_succs
(** Return [true] iff the procedure is defined, and not just declared *) (** Return [true] iff the procedure is defined, and not just declared *)
let is_defined pdesc = pdesc.attributes.is_defined let is_defined pdesc = pdesc.attributes.is_defined
let is_body_empty pdesc = List.is_empty (Node.get_succs (get_start_node pdesc))
let is_java_synchronized pdesc = pdesc.attributes.is_java_synchronized_method let is_java_synchronized pdesc = pdesc.attributes.is_java_synchronized_method
let iter_nodes f pdesc = List.iter ~f (List.rev (get_nodes pdesc)) let iter_nodes f pdesc = List.iter ~f (List.rev (get_nodes pdesc))
let fold_calls f acc pdesc =
let do_node a node =
List.fold
~f:(fun b callee_pname -> f b (callee_pname, Node.get_loc node))
~init:a (Node.get_callees node)
in
List.fold ~f:do_node ~init:acc (get_nodes pdesc)
(** iterate over the calls from the procedure: (callee,location) pairs *)
let iter_calls f pdesc = fold_calls (fun _ call -> f call) () pdesc
let iter_instrs f pdesc = let iter_instrs f pdesc =
let do_node node = List.iter ~f:(fun i -> f node i) (Node.get_instrs node) in let do_node node = List.iter ~f:(fun i -> f node i) (Node.get_instrs node) in
iter_nodes do_node pdesc iter_nodes do_node pdesc
@ -387,25 +306,6 @@ let fold_instrs f acc pdesc =
fold_nodes fold_node acc pdesc fold_nodes fold_node acc pdesc
let iter_slope f pdesc =
let visited = ref NodeSet.empty in
let rec do_node node =
visited := NodeSet.add node !visited ;
f node ;
match Node.get_succs node with
| [n] ->
if not (NodeSet.mem n !visited) then do_node n
| _ ->
()
in
do_node (get_start_node pdesc)
let iter_slope_calls f pdesc =
let do_node node = List.iter ~f:(fun callee_pname -> f callee_pname) (Node.get_callees node) in
iter_slope do_node pdesc
(** iterate between two nodes or until we reach a branching structure *) (** iterate between two nodes or until we reach a branching structure *)
let iter_slope_range f src_node dst_node = let iter_slope_range f src_node dst_node =
let visited = ref NodeSet.empty in let visited = ref NodeSet.empty in
@ -424,9 +324,6 @@ let iter_slope_range f src_node dst_node =
(** Set the exit node of the proc desc *) (** Set the exit node of the proc desc *)
let set_exit_node pdesc node = pdesc.exit_node <- node let set_exit_node pdesc node = pdesc.exit_node <- node
(** Set a flag for the proc desc *)
let set_flag pdesc key value = ProcAttributes.proc_flags_add pdesc.attributes.proc_flags key value
(** Set the start node of the proc desc *) (** Set the start node of the proc desc *)
let set_start_node pdesc node = pdesc.start_node <- node let set_start_node pdesc node = pdesc.start_node <- node

@ -56,9 +56,6 @@ module Node : sig
val equal : t -> t -> bool val equal : t -> t -> bool
(** Check if two nodes are equal *) (** Check if two nodes are equal *)
val get_callees : t -> Typ.Procname.t list
(** Get the list of callee procnames from the node *)
val get_description : Pp.env -> t -> string val get_description : Pp.env -> t -> string
(** Return a description of the node *) (** Return a description of the node *)
@ -68,10 +65,6 @@ module Node : sig
val get_exn : t -> t list val get_exn : t -> t list
(** Get the exception nodes from the current node *) (** Get the exception nodes from the current node *)
val get_generated_slope : t -> (t -> t list) -> t list
(** Get a list of unique nodes until the first branch starting
from a node with subsequent applications of a generator function *)
val get_id : t -> id val get_id : t -> id
(** Get the unique id of the node *) (** Get the unique id of the node *)
@ -93,12 +86,6 @@ module Node : sig
val get_proc_name : t -> Typ.Procname.t val get_proc_name : t -> Typ.Procname.t
(** Get the name of the procedure the node belongs to *) (** Get the name of the procedure the node belongs to *)
val get_sliced_preds : t -> (t -> bool) -> t list
(** Get the predecessor nodes of a node where the given predicate evaluates to true *)
val get_sliced_succs : t -> (t -> bool) -> t list
(** Get the successor nodes of a node where the given predicate evaluates to true *)
val get_succs : t -> t list val get_succs : t -> t list
(** Get the successor nodes of the current node *) (** Get the successor nodes of the current node *)
@ -149,9 +136,6 @@ val create_node : t -> Location.t -> Node.nodekind -> Sil.instr list -> Node.t
val did_preanalysis : t -> bool val did_preanalysis : t -> bool
(** true if we ran the preanalysis on the CFG associated with [t] *) (** true if we ran the preanalysis on the CFG associated with [t] *)
val fold_calls : ('a -> Typ.Procname.t * Location.t -> 'a) -> 'a -> t -> 'a
(** fold over the calls from the procedure: (callee, location) pairs *)
val fold_instrs : ('a -> Node.t -> Sil.instr -> 'a) -> 'a -> t -> 'a val fold_instrs : ('a -> Node.t -> Sil.instr -> 'a) -> 'a -> t -> 'a
(** fold over all nodes and their instructions *) (** fold over all nodes and their instructions *)
@ -170,13 +154,8 @@ val get_attributes : t -> ProcAttributes.t
val get_captured : t -> (Mangled.t * Typ.t) list val get_captured : t -> (Mangled.t * Typ.t) list
(** Return name and type of block's captured variables *) (** Return name and type of block's captured variables *)
val get_err_log : t -> Errlog.t
val get_exit_node : t -> Node.t val get_exit_node : t -> Node.t
val get_flags : t -> ProcAttributes.proc_flags
(** Get flags for the proc desc *)
val get_formals : t -> (Mangled.t * Typ.t) list val get_formals : t -> (Mangled.t * Typ.t) list
(** Return name and type of formal parameters *) (** Return name and type of formal parameters *)
@ -195,38 +174,20 @@ val get_ret_type : t -> Typ.t
val get_ret_var : t -> Pvar.t val get_ret_var : t -> Pvar.t
val get_sliced_slope : t -> (Node.t -> bool) -> Node.t list
(** Get the sliced procedure's nodes up until the first branching *)
val get_slope : t -> Node.t list
(** Get the procedure's nodes up until the first branching *)
val get_start_node : t -> Node.t val get_start_node : t -> Node.t
val is_defined : t -> bool val is_defined : t -> bool
(** Return [true] iff the procedure is defined, and not just declared *) (** Return [true] iff the procedure is defined, and not just declared *)
val is_body_empty : t -> bool
(** Return [true] if the body of the procdesc is empty (no instructions) *)
val is_java_synchronized : t -> bool val is_java_synchronized : t -> bool
(** Return [true] if the procedure signature has the Java synchronized keyword *) (** Return [true] if the procedure signature has the Java synchronized keyword *)
val iter_calls : (Typ.Procname.t * Location.t -> unit) -> t -> unit
(** iterate over the calls from the procedure: (callee, location) pairs *)
val iter_instrs : (Node.t -> Sil.instr -> unit) -> t -> unit val iter_instrs : (Node.t -> Sil.instr -> unit) -> t -> unit
(** iterate over all nodes and their instructions *) (** iterate over all nodes and their instructions *)
val iter_nodes : (Node.t -> unit) -> t -> unit val iter_nodes : (Node.t -> unit) -> t -> unit
(** iterate over all the nodes of a procedure *) (** iterate over all the nodes of a procedure *)
val iter_slope : (Node.t -> unit) -> t -> unit
(** iterate over all nodes until we reach a branching structure *)
val iter_slope_calls : (Typ.Procname.t -> unit) -> t -> unit
(** iterate over all calls until we reach a branching structure *)
val iter_slope_range : (Node.t -> unit) -> Node.t -> Node.t -> unit val iter_slope_range : (Node.t -> unit) -> Node.t -> Node.t -> unit
(** iterate between two nodes or until we reach a branching structure *) (** iterate between two nodes or until we reach a branching structure *)
@ -236,9 +197,6 @@ val node_set_succs_exn : t -> Node.t -> Node.t list -> Node.t list -> unit
val set_exit_node : t -> Node.t -> unit val set_exit_node : t -> Node.t -> unit
(** Set the exit node of the procedure *) (** Set the exit node of the procedure *)
val set_flag : t -> string -> string -> unit
(** Set a flag for the proc desc *)
val set_start_node : t -> Node.t -> unit val set_start_node : t -> Node.t -> unit
val signal_did_preanalysis : t -> unit val signal_did_preanalysis : t -> unit

@ -11,10 +11,6 @@
type accept_more type accept_more
and end_of_list and end_of_list
(** To be used in 'emptyness *)
type empty
and non_empty
(* Markers are a fool-proofing mechanism to avoid mistaking captured types. (* Markers are a fool-proofing mechanism to avoid mistaking captured types.
Template argument types can be captured with [capt_typ] to be referenced later Template argument types can be captured with [capt_typ] to be referenced later
by their position [typ1], [typ2], [typ3], ... by their position [typ1], [typ2], [typ3], ...
@ -275,6 +271,7 @@ module Procname : sig
If the args do not match, raise an internal error. If the args do not match, raise an internal error.
*) *)
end end
[@@warning "-32"]
module TypName : sig module TypName : sig
include Common include Common
@ -291,3 +288,4 @@ module TypName : sig
val ( &--> ) : val ( &--> ) :
('f_in, 'f_out, 'captured_types, unit, 'markers) name_matcher -> 'f_in -> 'f_out typ_matcher ('f_in, 'f_out, 'captured_types, unit, 'markers) name_matcher -> 'f_in -> 'f_out typ_matcher
end end
[@@warning "-32"]

@ -93,12 +93,6 @@ let pp pe f pv =
(** Dump a program variable. *) (** Dump a program variable. *)
let d (pvar: t) = L.add_print_action (L.PTpvar, Obj.repr pvar) let d (pvar: t) = L.add_print_action (L.PTpvar, Obj.repr pvar)
(** Pretty print a list of program variables. *)
let pp_list pe f pvl = F.fprintf f "%a" (Pp.seq (fun f e -> F.fprintf f "%a" (pp pe) e)) pvl
(** Dump a list of program variables. *)
let d_list pvl = List.iter ~f:(fun pv -> d pv ; L.d_str " ") pvl
let get_name pv = pv.pv_name let get_name pv = pv.pv_name
let to_string pv = Mangled.to_string pv.pv_name let to_string pv = Mangled.to_string pv.pv_name

@ -32,9 +32,6 @@ val equal : t -> t -> bool
val d : t -> unit val d : t -> unit
(** Dump a program variable. *) (** Dump a program variable. *)
val d_list : t list -> unit
(** Dump a list of program variables. *)
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. *)
@ -102,9 +99,6 @@ val mk_tmp : string -> Typ.Procname.t -> t
val pp : Pp.env -> F.formatter -> t -> unit val pp : Pp.env -> F.formatter -> t -> unit
(** Pretty print a program variable. *) (** Pretty print a program variable. *)
val pp_list : Pp.env -> F.formatter -> t list -> unit
(** Pretty print a list of program variables. *)
val pp_value : F.formatter -> t -> unit val pp_value : F.formatter -> t -> unit
(** Pretty print a pvar which denotes a value, not an address *) (** Pretty print a pvar which denotes a value, not an address *)

@ -13,8 +13,6 @@ module L = Logging
(* internally it uses reversed list to store qualified name, for example: ["get", "shared_ptr<int>", "std"]*) (* internally it uses reversed list to store qualified name, for example: ["get", "shared_ptr<int>", "std"]*)
type t = string list [@@deriving compare] type t = string list [@@deriving compare]
let equal = [%compare.equal : t]
let empty = [] let empty = []
let append_qualifier quals ~qual = List.cons qual quals let append_qualifier quals ~qual = List.cons qual quals

@ -14,8 +14,6 @@ type t [@@deriving compare]
val empty : t val empty : t
(** empty qualified name *) (** empty qualified name *)
val equal : t -> t -> bool
val of_qual_string : string -> t val of_qual_string : string -> t
(** attempts to parse the argument into a list::of::possibly::templated<T>::qualifiers *) (** attempts to parse the argument into a list::of::possibly::templated<T>::qualifiers *)

@ -201,11 +201,6 @@ let compare_hpara_dll = compare_hpara_dll0 (fun _ _ -> 0)
let equal_hpara_dll = [%compare.equal : hpara_dll] let equal_hpara_dll = [%compare.equal : hpara_dll]
(** Return the lhs expression of a hpred *)
let hpred_get_lhs h =
match h with Hpointsto (e, _, _) | Hlseg (_, _, e, _, _) | Hdllseg (_, _, e, _, _, _, _) -> e
(** {2 Comparision and Inspection Functions} *) (** {2 Comparision and Inspection Functions} *)
let is_objc_object = function let is_objc_object = function
| Hpointsto (_, _, Sizeof {typ}) -> | Hpointsto (_, _, Sizeof {typ}) ->
@ -230,9 +225,6 @@ let zero_value_of_numerical_type_option typ =
(** Returns the zero value of a type, for int, float and ptr types, fail otherwise *) (** Returns the zero value of a type, for int, float and ptr types, fail otherwise *)
let zero_value_of_numerical_type typ = Option.value_exn (zero_value_of_numerical_type_option typ) let zero_value_of_numerical_type typ = Option.value_exn (zero_value_of_numerical_type_option typ)
(** Make a static local name in objc *)
let mk_static_local_name pname vname = pname ^ "_" ^ vname
(** Check if a pvar is a local static in objc *) (** Check if a pvar is a local static in objc *)
let is_static_local_name pname pvar = let is_static_local_name pname pvar =
(* local static name is of the form procname_varname *) (* local static name is of the form procname_varname *)
@ -346,9 +338,6 @@ let pp_offset pe f = function
(** Convert an offset to a string *) (** Convert an offset to a string *)
let offset_to_string e = F.asprintf "%a" (pp_offset Pp.text) e let offset_to_string e = F.asprintf "%a" (pp_offset Pp.text) e
(** dump an offset. *)
let d_offset (off: offset) = L.add_print_action (L.PToff, Obj.repr off)
(** Pretty print a list of offsets *) (** Pretty print a list of offsets *)
let rec pp_offset_list pe f = function let rec pp_offset_list pe f = function
| [] -> | [] ->
@ -452,9 +441,6 @@ let pp_instr_list pe fmt instrs =
List.iter instrs ~f:(fun instr -> F.fprintf fmt "%a;@\n" (pp_instr pe) instr) List.iter instrs ~f:(fun instr -> F.fprintf fmt "%a;@\n" (pp_instr pe) instr)
(** Dump a list of instructions. *)
let d_instr_list (il: instr list) = L.add_print_action (L.PTinstr_list, Obj.repr il)
let pp_atom pe0 f a = let pp_atom pe0 f a =
let pe, changed = color_pre_wrapper pe0 f a in let pe, changed = color_pre_wrapper pe0 f a in
( match a with ( match a with
@ -625,12 +611,8 @@ let pp_texp_simple pe =
match pe.Pp.opt with SIM_DEFAULT -> pp_texp pe | SIM_WITH_TYP -> pp_texp_full pe match pe.Pp.opt with SIM_DEFAULT -> pp_texp pe | SIM_WITH_TYP -> pp_texp_full pe
let inst_abstraction = Iabstraction
let inst_actual_precondition = Iactual_precondition let inst_actual_precondition = Iactual_precondition
let inst_alloc = Ialloc
(** for formal parameters *) (** for formal parameters *)
let inst_formal = Iformal (None, false) let inst_formal = Iformal (None, false)
@ -645,8 +627,6 @@ let inst_nullify = Inullify
let inst_rearrange b loc pos = Irearrange (Some b, false, loc.Location.line, pos) let inst_rearrange b loc pos = Irearrange (Some b, false, loc.Location.line, pos)
let inst_taint = Itaint
let inst_update loc pos = Iupdate (None, false, loc.Location.line, pos) let inst_update loc pos = Iupdate (None, false, loc.Location.line, pos)
(** update the location of the instrumentation *) (** update the location of the instrumentation *)
@ -775,9 +755,6 @@ let inst_set_null_case_flag = function
inst inst
(** Get the null case flag of the inst. *)
let inst_get_null_case_flag = function Iupdate (_, ncf, _, _) -> Some ncf | _ -> None
(** Update [inst_old] to [inst_new] preserving the zero flag *) (** Update [inst_old] to [inst_new] preserving the zero flag *)
let update_inst inst_old inst_new = let update_inst inst_old inst_new =
let combine_zero_flags z1 z2 = let combine_zero_flags z1 z2 =
@ -927,27 +904,6 @@ let pp_sexp_list pe f sel =
F.fprintf f "%a" (Pp.seq (fun f se -> F.fprintf f "%a" (pp_sexp pe) se)) sel F.fprintf f "%a" (Pp.seq (fun f se -> F.fprintf f "%a" (pp_sexp pe) se)) sel
(** dump a list of expressions. *)
let d_sexp_list (sel: strexp list) = L.add_print_action (L.PTsexp_list, Obj.repr sel)
let rec pp_hpara_list pe f = function
| [] ->
()
| [para] ->
F.fprintf f "PRED: %a" (pp_hpara pe) para
| para :: paras ->
F.fprintf f "PRED: %a@\n@\n%a" (pp_hpara pe) para (pp_hpara_list pe) paras
let rec pp_hpara_dll_list pe f = function
| [] ->
()
| [para] ->
F.fprintf f "PRED: %a" (pp_hpara_dll pe) para
| para :: paras ->
F.fprintf f "PRED: %a@\n@\n%a" (pp_hpara_dll pe) para (pp_hpara_dll_list pe) paras
(** dump a hpred. *) (** dump a hpred. *)
let d_hpred (hpred: hpred) = L.add_print_action (L.PThpred, Obj.repr hpred) let d_hpred (hpred: hpred) = L.add_print_action (L.PThpred, Obj.repr hpred)
@ -1042,8 +998,6 @@ let atom_expmap (f: Exp.t -> Exp.t) = function
Anpred (a, List.map ~f es) Anpred (a, List.map ~f es)
let atom_list_expmap (f: Exp.t -> Exp.t) (alist: atom list) = List.map ~f:(atom_expmap f) alist
(** {2 Function for computing lexps in sigma} *) (** {2 Function for computing lexps in sigma} *)
let hpred_get_lexp acc = function let hpred_get_lexp acc = function
@ -1088,59 +1042,6 @@ let rec exp_fpv e =
[] []
let exp_list_fpv el = List.concat_map ~f:exp_fpv el
let atom_fpv = function
| Aeq (e1, e2) ->
exp_fpv e1 @ exp_fpv e2
| Aneq (e1, e2) ->
exp_fpv e1 @ exp_fpv e2
| Apred (_, es) | Anpred (_, es) ->
List.fold ~f:(fun fpv e -> List.rev_append (exp_fpv e) fpv) ~init:[] es
let rec strexp_fpv = function
| Eexp (e, _) ->
exp_fpv e
| Estruct (fld_se_list, _) ->
let f (_, se) = strexp_fpv se in
List.concat_map ~f fld_se_list
| Earray (len, idx_se_list, _) ->
let fpv_in_len = exp_fpv len in
let f (idx, se) = exp_fpv idx @ strexp_fpv se in
fpv_in_len @ List.concat_map ~f idx_se_list
let rec hpred_fpv = function
| Hpointsto (base, se, te) ->
exp_fpv base @ strexp_fpv se @ exp_fpv te
| Hlseg (_, para, e1, e2, elist) ->
let fpvars_in_elist = exp_list_fpv elist in
hpara_fpv para @ exp_fpv (* This set has to be empty. *) e1 @ exp_fpv e2 @ fpvars_in_elist
| Hdllseg (_, para, e1, e2, e3, e4, elist) ->
let fpvars_in_elist = exp_list_fpv elist in
hpara_dll_fpv para (* This set has to be empty. *)
@ exp_fpv e1 @ exp_fpv e2 @ exp_fpv e3 @ exp_fpv e4 @ fpvars_in_elist
(** hpara should not contain any program variables.
This is because it might cause problems when we do interprocedural
analysis. In interprocedural analysis, we should consider the issue
of scopes of program variables. *)
and hpara_fpv para =
let fpvars_in_body = List.concat_map ~f:hpred_fpv para.body in
match fpvars_in_body with [] -> [] | _ -> assert false
(** hpara_dll should not contain any program variables.
This is because it might cause problems when we do interprocedural
analysis. In interprocedural analysis, we should consider the issue
of scopes of program variables. *)
and hpara_dll_fpv para =
let fpvars_in_body = List.concat_map ~f:hpred_fpv para.body_dll in
match fpvars_in_body with [] -> [] | _ -> assert false
(** {2 Functions for computing free non-program variables} *) (** {2 Functions for computing free non-program variables} *)
(** Type of free variables. These include primed, normal and footprint variables. (** Type of free variables. These include primed, normal and footprint variables.
@ -1187,9 +1088,6 @@ let fav_to_list fav = List.rev !fav
(** Pretty print a fav. *) (** Pretty print a fav. *)
let pp_fav f fav = Pp.seq Ident.pp f (fav_to_list fav) let pp_fav f fav = Pp.seq Ident.pp f (fav_to_list fav)
(** Copy a [fav]. *)
let fav_copy fav = ref (List.map ~f:(fun x -> x) !fav)
(** Turn a xxx_fav_add function into a xxx_fav function *) (** Turn a xxx_fav_add function into a xxx_fav function *)
let fav_imperative_to_functional f x = let fav_imperative_to_functional f x =
let fav = fav_new () in let fav = fav_new () in
@ -1203,24 +1101,6 @@ let fav_filter_ident fav filter = fav := List.filter ~f:filter !fav
(** Like [fav_filter_ident] but return a copy. *) (** Like [fav_filter_ident] but return a copy. *)
let fav_copy_filter_ident fav filter = ref (List.filter ~f:filter !fav) let fav_copy_filter_ident fav filter = ref (List.filter ~f:filter !fav)
(** checks whether every element in l1 appears l2 **)
let rec ident_sorted_list_subset l1 l2 =
match (l1, l2) with
| [], _ ->
true
| _ :: _, [] ->
false
| id1 :: l1, id2 :: l2 ->
let n = Ident.compare id1 id2 in
if Int.equal n 0 then ident_sorted_list_subset l1 (id2 :: l2)
else if n > 0 then ident_sorted_list_subset (id1 :: l1) l2
else false
(** [fav_subset_ident fav1 fav2] returns true if every ident in [fav1]
is in [fav2].*)
let fav_subset_ident fav1 fav2 = ident_sorted_list_subset (fav_to_list fav1) (fav_to_list fav2)
let fav_mem fav id = List.exists ~f:(Ident.equal id) !fav let fav_mem fav id = List.exists ~f:(Ident.equal id) !fav
let rec exp_fav_add fav e = let rec exp_fav_add fav e =
@ -1266,9 +1146,6 @@ let atom_fav_add fav = function
let atom_fav = fav_imperative_to_functional atom_fav_add let atom_fav = fav_imperative_to_functional atom_fav_add
(** Atoms do not contain binders *)
let atom_av_add = atom_fav_add
let rec strexp_fav_add fav = function let rec strexp_fav_add fav = function
| Eexp (e, _) -> | Eexp (e, _) ->
exp_fav_add fav e exp_fav_add fav e
@ -1316,46 +1193,6 @@ let array_clean_new_index footprint_part new_idx =
(** {2 Functions for computing all free or bound non-program variables} *) (** {2 Functions for computing all free or bound non-program variables} *)
(** Expressions do not bind variables *)
let exp_av_add = exp_fav_add
(** Structured expressions do not bind variables *)
let strexp_av_add = strexp_fav_add
let rec hpara_av_add fav para =
List.iter ~f:(hpred_av_add fav) para.body ;
fav ++ para.root ;
fav ++ para.next ;
fav +++ para.svars ;
fav +++ para.evars
and hpara_dll_av_add fav para =
List.iter ~f:(hpred_av_add fav) para.body_dll ;
fav ++ para.cell ;
fav ++ para.blink ;
fav ++ para.flink ;
fav +++ para.svars_dll ;
fav +++ para.evars_dll
and hpred_av_add fav = function
| Hpointsto (base, se, te) ->
exp_av_add fav base ; strexp_av_add fav se ; exp_av_add fav te
| Hlseg (_, para, e1, e2, elist) ->
hpara_av_add fav para ;
exp_av_add fav e1 ;
exp_av_add fav e2 ;
List.iter ~f:(exp_av_add fav) elist
| Hdllseg (_, para, e1, e2, e3, e4, elist) ->
hpara_dll_av_add fav para ;
exp_av_add fav e1 ;
exp_av_add fav e2 ;
exp_av_add fav e3 ;
exp_av_add fav e4 ;
List.iter ~f:(exp_av_add fav) elist
let hpara_shallow_av_add fav para = let hpara_shallow_av_add fav para =
List.iter ~f:(hpred_fav_add fav) para.body ; List.iter ~f:(hpred_fav_add fav) para.body ;
fav ++ para.root ; fav ++ para.root ;
@ -1506,9 +1343,6 @@ let sub_fav_add fav (sub: exp_subst) =
List.iter ~f:(fun (id, e) -> fav ++ id ; exp_fav_add fav e) sub List.iter ~f:(fun (id, e) -> fav ++ id ; exp_fav_add fav e) sub
(** Substitutions do not contain binders *)
let sub_av_add = sub_fav_add
let rec exp_sub_ids (f: subst_fun) exp = let rec exp_sub_ids (f: subst_fun) exp =
let f_typ x = match f with `Exp _ -> x | `Typ (f, _) -> f x in let f_typ x = match f with `Exp _ -> x | `Typ (f, _) -> f x in
let f_tname x = match f with `Exp _ -> x | `Typ (_, f) -> f x in let f_tname x = match f with `Exp _ -> x | `Typ (_, f) -> f x in
@ -1807,6 +1641,9 @@ let hpred_sub subst =
(** {2 Functions for replacing occurrences of expressions.} *) (** {2 Functions for replacing occurrences of expressions.} *)
(** The first parameter should define a partial function.
No parts of hpara are replaced by these functions. *)
let rec exp_replace_exp epairs e = let rec exp_replace_exp epairs e =
(* First we check if there is an exact match *) (* First we check if there is an exact match *)
match List.find ~f:(fun (e1, _) -> Exp.equal e e1) epairs with match List.find ~f:(fun (e1, _) -> Exp.equal e e1) epairs with

@ -116,12 +116,8 @@ type inst =
val equal_inst : inst -> inst -> bool val equal_inst : inst -> inst -> bool
val inst_abstraction : inst
val inst_actual_precondition : inst val inst_actual_precondition : inst
val inst_alloc : inst
val inst_formal : inst val inst_formal : inst
val inst_initial : inst val inst_initial : inst
@ -137,13 +133,8 @@ val inst_nullify : inst
val inst_rearrange : bool -> Location.t -> PredSymb.path_pos -> inst val inst_rearrange : bool -> Location.t -> PredSymb.path_pos -> inst
(** the boolean indicates whether the pointer is known nonzero *) (** the boolean indicates whether the pointer is known nonzero *)
val inst_taint : inst
val inst_update : Location.t -> PredSymb.path_pos -> inst val inst_update : Location.t -> PredSymb.path_pos -> inst
val inst_get_null_case_flag : inst -> bool option
(** Get the null case flag of the inst. *)
val inst_set_null_case_flag : inst -> inst val inst_set_null_case_flag : inst -> inst
(** Set the null case flag of the inst. *) (** Set the null case flag of the inst. *)
@ -249,9 +240,6 @@ type sharing_env
val create_sharing_env : unit -> sharing_env val create_sharing_env : unit -> sharing_env
(** Create a sharing env to store canonical representations *) (** Create a sharing env to store canonical representations *)
val exp_compact : sharing_env -> Exp.t -> Exp.t
(** Return a canonical representation of the exp *)
val hpred_compact : sharing_env -> hpred -> hpred val hpred_compact : sharing_env -> hpred -> hpred
(** Return a compact representation of the exp *) (** Return a compact representation of the exp *)
@ -264,9 +252,6 @@ val zero_value_of_numerical_type_option : Typ.t -> Exp.t option
val zero_value_of_numerical_type : Typ.t -> Exp.t val zero_value_of_numerical_type : Typ.t -> Exp.t
(** Returns the zero value of a type, for int, float and ptr types, fail otherwise *) (** Returns the zero value of a type, for int, float and ptr types, fail otherwise *)
val mk_static_local_name : string -> string -> string
(** Make a static local name in objc *)
val is_static_local_name : string -> Pvar.t -> bool val is_static_local_name : string -> Pvar.t -> bool
(** Check if a pvar is a local static in objc *) (** Check if a pvar is a local static in objc *)
@ -281,9 +266,6 @@ val add_with_block_parameters_flag : instr -> instr
contain an Objective-C block, and the method is an Objective-C method contain an Objective-C block, and the method is an Objective-C method
(to be extended to other methods) *) (to be extended to other methods) *)
val hpred_get_lhs : hpred -> Exp.t
(** Return the lhs expression of a hpred *)
(** {2 Pretty Printing} *) (** {2 Pretty Printing} *)
val color_pre_wrapper : Pp.env -> F.formatter -> 'a -> Pp.env * bool val color_pre_wrapper : Pp.env -> F.formatter -> 'a -> Pp.env * bool
@ -295,9 +277,6 @@ val color_post_wrapper : bool -> F.formatter -> unit
val pp_exp_printenv : Pp.env -> F.formatter -> Exp.t -> unit val pp_exp_printenv : Pp.env -> F.formatter -> Exp.t -> unit
(** Pretty print an expression. *) (** Pretty print an expression. *)
val pp_exp_typ : Pp.env -> F.formatter -> Exp.t * Typ.t -> unit
(** Pretty print an expression with type. *)
val d_exp : Exp.t -> unit val d_exp : Exp.t -> unit
(** dump an expression. *) (** dump an expression. *)
@ -322,9 +301,6 @@ val pp_offset : Pp.env -> F.formatter -> offset -> unit
val offset_to_string : offset -> string val offset_to_string : offset -> string
(** Convert an offset to a string *) (** Convert an offset to a string *)
val d_offset : offset -> unit
(** Dump an offset *)
val pp_offset_list : Pp.env -> F.formatter -> offset list -> unit val pp_offset_list : Pp.env -> F.formatter -> offset list -> unit
(** Pretty print a list of offsets *) (** Pretty print a list of offsets *)
@ -346,9 +322,6 @@ val d_instr : instr -> unit
val pp_instr_list : Pp.env -> F.formatter -> instr list -> unit val pp_instr_list : Pp.env -> F.formatter -> instr list -> unit
(** Pretty print a list of instructions. *) (** Pretty print a list of instructions. *)
val d_instr_list : instr list -> unit
(** Dump a list of instructions. *)
val pp_atom : Pp.env -> F.formatter -> atom -> unit val pp_atom : Pp.env -> F.formatter -> atom -> unit
(** Pretty print an atom. *) (** Pretty print an atom. *)
@ -367,9 +340,6 @@ val d_sexp : strexp -> unit
val pp_sexp_list : Pp.env -> F.formatter -> strexp list -> unit val pp_sexp_list : Pp.env -> F.formatter -> strexp list -> unit
(** Pretty print a strexp list. *) (** Pretty print a strexp list. *)
val d_sexp_list : strexp list -> unit
(** Dump a strexp. *)
val pp_hpred : Pp.env -> F.formatter -> hpred -> unit val pp_hpred : Pp.env -> F.formatter -> hpred -> unit
(** Pretty print a hpred. *) (** Pretty print a hpred. *)
@ -379,15 +349,9 @@ val d_hpred : hpred -> unit
val pp_hpara : Pp.env -> F.formatter -> hpara -> unit val pp_hpara : Pp.env -> F.formatter -> hpara -> unit
(** Pretty print a hpara. *) (** Pretty print a hpara. *)
val pp_hpara_list : Pp.env -> F.formatter -> hpara list -> unit
(** Pretty print a list of hparas. *)
val pp_hpara_dll : Pp.env -> F.formatter -> hpara_dll -> unit val pp_hpara_dll : Pp.env -> F.formatter -> hpara_dll -> unit
(** Pretty print a hpara_dll. *) (** Pretty print a hpara_dll. *)
val pp_hpara_dll_list : Pp.env -> F.formatter -> hpara_dll list -> unit
(** Pretty print a list of hpara_dlls. *)
(** Module Predicates records the occurrences of predicates as parameters (** Module Predicates records the occurrences of predicates as parameters
of (doubly -)linked lists and Epara. of (doubly -)linked lists and Epara.
Provides unique numbering for predicates and an iterator. *) Provides unique numbering for predicates and an iterator. *)
@ -401,12 +365,6 @@ module Predicates : sig
val is_empty : env -> bool val is_empty : env -> bool
(** return true if the environment is empty *) (** return true if the environment is empty *)
val get_hpara_id : env -> hpara -> int
(** return the id of the hpara *)
val get_hpara_dll_id : env -> hpara_dll -> int
(** return the id of the hpara_dll *)
val iter : env -> (int -> hpara -> unit) -> (int -> hpara_dll -> unit) -> unit val iter : env -> (int -> hpara -> unit) -> (int -> hpara_dll -> unit) -> unit
(** [iter env f f_dll] iterates [f] and [f_dll] on all the hpara and hpara_dll, (** [iter env f f_dll] iterates [f] and [f_dll] on all the hpara and hpara_dll,
passing the unique id to the functions. The iterator can only be used once. *) passing the unique id to the functions. The iterator can only be used once. *)
@ -446,10 +404,6 @@ val atom_expmap : (Exp.t -> Exp.t) -> atom -> atom
(** Change exps in atom by [f]. (** Change exps in atom by [f].
WARNING: the result might not be normalized. *) WARNING: the result might not be normalized. *)
val atom_list_expmap : (Exp.t -> Exp.t) -> atom list -> atom list
(** Change exps in atom list by [f].
WARNING: the result might not be normalized. *)
val hpred_list_get_lexps : (Exp.t -> bool) -> hpred list -> Exp.t list val hpred_list_get_lexps : (Exp.t -> bool) -> hpred list -> Exp.t list
val hpred_entries : hpred -> Exp.t list val hpred_entries : hpred -> Exp.t list
@ -458,16 +412,6 @@ val hpred_entries : hpred -> Exp.t list
val exp_fpv : Exp.t -> Pvar.t list val exp_fpv : Exp.t -> Pvar.t list
(** {2 Functions for computing program variables} *)
val strexp_fpv : strexp -> Pvar.t list
val atom_fpv : atom -> Pvar.t list
val hpred_fpv : hpred -> Pvar.t list
val hpara_fpv : hpara -> Pvar.t list
(** {2 Functions for computing free non-program variables} *) (** {2 Functions for computing free non-program variables} *)
(** Type of free variables. These include primed, normal and footprint variables. (** Type of free variables. These include primed, normal and footprint variables.
@ -478,7 +422,7 @@ val fav_duplicates : bool ref
(** flag to indicate whether fav's are stored in duplicate form. (** flag to indicate whether fav's are stored in duplicate form.
Only to be used with fav_to_list *) Only to be used with fav_to_list *)
val pp_fav : F.formatter -> fav -> unit val pp_fav : F.formatter -> fav -> unit [@@warning "-32"]
(** Pretty print a fav. *) (** Pretty print a fav. *)
val fav_new : unit -> fav val fav_new : unit -> fav
@ -503,9 +447,6 @@ val fav_to_list : fav -> Ident.t list
(** Convert a [fav] to a list of identifiers while preserving the order (** Convert a [fav] to a list of identifiers while preserving the order
that identifiers were added to [fav]. *) that identifiers were added to [fav]. *)
val fav_copy : fav -> fav
(** Copy a [fav]. *)
val fav_imperative_to_functional : (fav -> 'a -> unit) -> 'a -> fav val fav_imperative_to_functional : (fav -> 'a -> unit) -> 'a -> fav
(** Turn a xxx_fav_add function into a xxx_fav function *) (** Turn a xxx_fav_add function into a xxx_fav function *)
@ -515,10 +456,6 @@ val fav_filter_ident : fav -> (Ident.t -> bool) -> unit
val fav_copy_filter_ident : fav -> (Ident.t -> bool) -> fav val fav_copy_filter_ident : fav -> (Ident.t -> bool) -> fav
(** Like [fav_filter_ident] but return a copy. *) (** Like [fav_filter_ident] but return a copy. *)
val fav_subset_ident : fav -> fav -> bool
(** [fav_subset_ident fav1 fav2] returns true if every ident in [fav1]
is in [fav2].*)
val ident_list_fav_add : Ident.t list -> fav -> unit val ident_list_fav_add : Ident.t list -> fav -> unit
(** add identifier list to fav *) (** add identifier list to fav *)
@ -547,30 +484,12 @@ val hpara_shallow_av : hpara -> fav
val hpara_dll_shallow_av : hpara_dll -> fav val hpara_dll_shallow_av : hpara_dll -> fav
(** Variables in hpara_dll, excluding bound vars in the body *) (** Variables in hpara_dll, excluding bound vars in the body *)
(** {2 Functions for computing all free or bound non-program variables} *)
val exp_av_add : fav -> Exp.t -> unit
(** Non-program variables include all of primed, normal and footprint
variables. Thus, the functions essentially compute all the
identifiers occuring in a parameter. Some variables can appear more
than once in the result. *)
val strexp_av_add : fav -> strexp -> unit
val atom_av_add : fav -> atom -> unit
val hpred_av_add : fav -> hpred -> unit
val hpara_av_add : fav -> hpara -> unit
(** {2 Substitution} *) (** {2 Substitution} *)
type exp_subst [@@deriving compare] type exp_subst [@@deriving compare]
type subst = [`Exp of exp_subst | `Typ of Typ.type_subst_t] [@@deriving compare] type subst = [`Exp of exp_subst | `Typ of Typ.type_subst_t] [@@deriving compare]
type subst_fun = [`Exp of Ident.t -> Exp.t | `Typ of (Typ.t -> Typ.t) * (Typ.Name.t -> Typ.Name.t)]
val equal_exp_subst : exp_subst -> exp_subst -> bool val equal_exp_subst : exp_subst -> exp_subst -> bool
(** Equality for substitutions. *) (** Equality for substitutions. *)
@ -642,9 +561,6 @@ val sub_map : (Ident.t -> Ident.t) -> (Exp.t -> Exp.t) -> exp_subst -> exp_subst
(** [sub_map f g sub] applies the renaming [f] to identifiers in the domain (** [sub_map f g sub] applies the renaming [f] to identifiers in the domain
of [sub] and the substitution [g] to the expressions in the range of [sub]. *) of [sub] and the substitution [g] to the expressions in the range of [sub]. *)
val mem_sub : Ident.t -> exp_subst -> bool
(** Checks whether [id] belongs to the domain of [subst]. *)
val extend_sub : exp_subst -> Ident.t -> Exp.t -> exp_subst option val extend_sub : exp_subst -> Ident.t -> Exp.t -> exp_subst option
(** Extend substitution and return [None] if not possible. *) (** Extend substitution and return [None] if not possible. *)
@ -652,10 +568,6 @@ val sub_fav_add : fav -> exp_subst -> unit
(** Free auxilary variables in the domain and range of the (** Free auxilary variables in the domain and range of the
substitution. *) substitution. *)
val sub_av_add : fav -> exp_subst -> unit
(** Free or bound auxilary variables in the domain and range of the
substitution. *)
(** substitution functions (** substitution functions
WARNING: these functions do not ensure that the results are normalized. *) WARNING: these functions do not ensure that the results are normalized. *)
@ -668,17 +580,8 @@ val instr_sub : subst -> instr -> instr
val hpred_sub : subst -> hpred -> hpred val hpred_sub : subst -> hpred -> hpred
val instr_sub_ids : sub_id_binders:bool -> subst_fun -> instr -> instr
(** apply [f] to id's in [instr]. if [sub_id_binders] is false, [f] is only applied to bound id's *)
(** {2 Functions for replacing occurrences of expressions.} *) (** {2 Functions for replacing occurrences of expressions.} *)
val exp_replace_exp : (Exp.t * Exp.t) list -> Exp.t -> Exp.t
(** The first parameter should define a partial function.
No parts of hpara are replaced by these functions. *)
val strexp_replace_exp : (Exp.t * Exp.t) list -> strexp -> strexp
val atom_replace_exp : (Exp.t * Exp.t) list -> atom -> atom val atom_replace_exp : (Exp.t * Exp.t) list -> atom -> atom
val hpred_replace_exp : (Exp.t * Exp.t) list -> hpred -> hpred val hpred_replace_exp : (Exp.t * Exp.t) list -> hpred -> hpred

@ -108,8 +108,6 @@ let check_subtype =
let is_known_subtype tenv c1 c2 : bool = equal_result (check_subtype tenv c1 c2) Yes let is_known_subtype tenv c1 c2 : bool = equal_result (check_subtype tenv c1 c2) Yes
let is_known_not_subtype tenv c1 c2 : bool = equal_result (check_subtype tenv c1 c2) No
let flag_to_string flag = match flag with CAST -> "(cast)" | INSTOF -> "(instof)" | NORMAL -> "" let flag_to_string flag = match flag with CAST -> "(cast)" | INSTOF -> "(instof)" | NORMAL -> ""
let pp f (t, flag) = let pp f (t, flag) =
@ -189,14 +187,6 @@ let normalize_subtypes t_opt c1 c2 flag1 flag2 =
None None
let subtypes_to_string t =
match fst t with
| Exact ->
"ex" ^ flag_to_string (snd t)
| Subtypes l ->
list_to_string l ^ flag_to_string (snd t)
(* c is a subtype when it does not appear in the list l of no-subtypes *) (* c is a subtype when it does not appear in the list l of no-subtypes *)
let no_subtype_in_list tenv c l = not (List.exists ~f:(is_known_subtype tenv c) l) let no_subtype_in_list tenv c l = not (List.exists ~f:(is_known_subtype tenv c) l)

@ -45,17 +45,9 @@ val is_known_subtype : Tenv.t -> Typ.Name.t -> Typ.Name.t -> bool
Note that [not (is_known_subtype tenv c1 c2) == true] does not imply Note that [not (is_known_subtype tenv c1 c2) == true] does not imply
that [is_known_not_subtype tenv c1 c2 == true] *) that [is_known_not_subtype tenv c1 c2 == true] *)
val is_known_not_subtype : Tenv.t -> Typ.Name.t -> Typ.Name.t -> bool
(** [is_known_not_subtype tenv c1 c2] returns true if there is enough information in [tenv] to prove
that [c1] is not a subtype of [c2].
Note that [not (is_known_not_subtype tenv c1 c2) == true] does not imply
that [is_known_subtype tenv c1 c2 == true] *)
val subtypes_to_string : t -> string
val is_cast : t -> bool val is_cast : t -> bool
val is_instof : t -> bool val is_instof : t -> bool [@@warning "-32"]
val equal_modulo_flag : t -> t -> bool val equal_modulo_flag : t -> t -> bool
(** equality ignoring flags in the subtype *) (** equality ignoring flags in the subtype *)

@ -25,8 +25,6 @@ type t = Typ.Struct.t TypenameHash.t
let iter f tenv = TypenameHash.iter f tenv let iter f tenv = TypenameHash.iter f tenv
let fold f tenv = TypenameHash.fold f tenv
let pp fmt (tenv: t) = let pp fmt (tenv: t) =
TypenameHash.iter TypenameHash.iter
(fun name typ -> (fun name typ ->
@ -47,9 +45,6 @@ let mk_struct tenv ?default ?fields ?statics ?methods ?supers ?annots name =
struct_typ struct_typ
(** Check if typename is found in tenv *)
let mem tenv name = TypenameHash.mem tenv name
(** Look up a name in the global type environment. *) (** Look up a name in the global type environment. *)
let lookup tenv name : Typ.Struct.t option = let lookup tenv name : Typ.Struct.t option =
try Some (TypenameHash.find tenv name) with Not_found -> try Some (TypenameHash.find tenv name) with Not_found ->
@ -63,9 +58,6 @@ let lookup tenv name : Typ.Struct.t option =
None None
(** Add a (name,type) pair to the global type environment. *)
let add tenv name struct_typ = TypenameHash.replace tenv name struct_typ
let compare_fields (name1, _, _) (name2, _, _) = Typ.Fieldname.compare name1 name2 let compare_fields (name1, _, _) (name2, _, _) = Typ.Fieldname.compare name1 name2
let equal_fields f1 f2 = Int.equal (compare_fields f1 f2) 0 let equal_fields f1 f2 = Int.equal (compare_fields f1 f2) 0
@ -90,34 +82,6 @@ let add_field tenv class_tn_name field =
() ()
(** Get method that is being overriden by java_pname (if any) **)
let get_overriden_method tenv pname_java =
let struct_typ_get_method_by_name (struct_typ: Typ.Struct.t) method_name =
List.find_exn
~f:(fun meth -> String.equal method_name (Typ.Procname.get_method meth))
struct_typ.methods
in
let rec get_overriden_method_in_supers pname_java supers =
match supers with
| superclass :: supers_tail -> (
match lookup tenv superclass with
| Some struct_typ -> (
try
Some (struct_typ_get_method_by_name struct_typ (Typ.Procname.java_get_method pname_java))
with Not_found ->
get_overriden_method_in_supers pname_java (supers_tail @ struct_typ.supers) )
| None ->
get_overriden_method_in_supers pname_java supers_tail )
| [] ->
None
in
match lookup tenv (Typ.Procname.java_get_class_type_name pname_java) with
| Some {supers} ->
get_overriden_method_in_supers pname_java supers
| _ ->
None
(** Serializer for type environments *) (** Serializer for type environments *)
let tenv_serializer : t Serialization.serializer = let tenv_serializer : t Serialization.serializer =
Serialization.create_serializer Serialization.Key.tenv Serialization.create_serializer Serialization.Key.tenv

@ -14,18 +14,9 @@ open! IStd
(** Type for type environment. *) (** Type for type environment. *)
type t type t
val add : t -> Typ.Name.t -> Typ.Struct.t -> unit
(** Add a (name,typename) pair to the global type environment. *)
val create : unit -> t val create : unit -> t
(** Create a new type environment. *) (** Create a new type environment. *)
val fold : (Typ.Name.t -> Typ.Struct.t -> 'a -> 'a) -> t -> 'a -> 'a
(** Fold a function over the elements of the type environment. *)
val iter : (Typ.Name.t -> Typ.Struct.t -> unit) -> t -> unit
(** iterate over a type environment *)
val load_from_file : DB.filename -> t option val load_from_file : DB.filename -> t option
(** Load a type environment from a file *) (** Load a type environment from a file *)
@ -43,17 +34,11 @@ val add_field : t -> Typ.Name.t -> Typ.Struct.field -> unit
val sort_fields_tenv : t -> unit val sort_fields_tenv : t -> unit
val mem : t -> Typ.Name.t -> bool val pp : Format.formatter -> t -> unit [@@warning "-32"]
(** Check if typename is found in t *)
val pp : Format.formatter -> t -> unit
(** print a type environment *) (** print a type environment *)
val store_to_file : DB.filename -> t -> unit val store_to_file : DB.filename -> t -> unit
(** Save a type environment into a file *) (** Save a type environment into a file *)
val get_overriden_method : t -> Typ.Procname.java -> Typ.Procname.t option
(** Get method that is being overriden by java_pname (if any) **)
val language_is : t -> Config.language -> bool val language_is : t -> Config.language -> bool
(** Test the language from which the types in the tenv were translated *) (** Test the language from which the types in the tenv were translated *)

@ -73,8 +73,6 @@ let ikind_is_unsigned = function
false false
let int_of_int64_kind i ik = IntLit.of_int64_unsigned i (ikind_is_unsigned ik)
(** Kinds of floating-point numbers *) (** Kinds of floating-point numbers *)
type fkind = type fkind =
| FFloat (** [float] *) | FFloat (** [float] *)
@ -461,12 +459,6 @@ let is_objc_class = is_class_of_kind Name.Objc.is_class
let is_cpp_class = is_class_of_kind Name.Cpp.is_class let is_cpp_class = is_class_of_kind Name.Cpp.is_class
let is_java_class = is_class_of_kind Name.Java.is_class
let rec is_array_of_cpp_class typ =
match typ.desc with Tarray (typ, _, _) -> is_array_of_cpp_class typ | _ -> is_cpp_class typ
let is_pointer typ = match typ.desc with Tptr _ -> true | _ -> false let is_pointer typ = match typ.desc with Tptr _ -> true | _ -> false
let is_pointer_to_cpp_class typ = match typ.desc with Tptr (t, _) -> is_cpp_class t | _ -> false let is_pointer_to_cpp_class typ = match typ.desc with Tptr (t, _) -> is_cpp_class t | _ -> false
@ -479,9 +471,6 @@ let has_block_prefix s =
false false
(** Check if type is a type for a block in objc *)
let is_block_type typ = has_block_prefix (to_string typ)
(** Java types by name *) (** Java types by name *)
let rec java_from_string : string -> t = function let rec java_from_string : string -> t = function
| "" | "void" -> | "" | "void" ->
@ -565,8 +554,6 @@ module Procname = struct
(** Type of Objective C block names. *) (** Type of Objective C block names. *)
type block_name = string [@@deriving compare] type block_name = string [@@deriving compare]
let block_from_string s = s
(** Type of procedure names. *) (** Type of procedure names. *)
type t = type t =
| Java of java | Java of java
@ -611,8 +598,6 @@ module Procname = struct
if is_verbose verbosity then p ^ "." ^ cls else cls if is_verbose verbosity then p ^ "." ^ cls else cls
let java_type_to_string p = java_type_to_string_verbosity p Verbose
(** Given a list of types, it creates a unique string of types separated by commas *) (** Given a list of types, it creates a unique string of types separated by commas *)
let rec java_param_list_to_string inputList verbosity = let rec java_param_list_to_string inputList verbosity =
match inputList with match inputList with
@ -625,7 +610,8 @@ module Procname = struct
^ java_param_list_to_string rest verbosity ^ java_param_list_to_string rest verbosity
(** It is the same as java_type_to_string, but Java return types are optional because of constructors without type *) (** It is the same as java_type_to_string_verbosity, but Java return types are optional because
of constructors without type *)
let java_return_type_to_string j verbosity = let java_return_type_to_string j verbosity =
match j.return_type with None -> "" | Some typ -> java_type_to_string_verbosity typ verbosity match j.return_type with None -> "" | Some typ -> java_type_to_string_verbosity typ verbosity
@ -674,8 +660,6 @@ module Procname = struct
let is_c_function = function C _ -> true | _ -> false let is_c_function = function C _ -> true | _ -> false
let is_obj_c_pp = function ObjC_Cpp _ | C _ -> true | _ -> false
let is_constexpr = function ObjC_Cpp {kind= CPPConstructor (_, true)} -> true | _ -> false let is_constexpr = function ObjC_Cpp {kind= CPPConstructor (_, true)} -> true | _ -> false
(** Replace the class name component of a procedure name. (** Replace the class name component of a procedure name.
@ -750,8 +734,6 @@ module Procname = struct
(** Return whether the procname is a block procname. *) (** Return whether the procname is a block procname. *)
let is_objc_block = function Block _ -> true | _ -> false let is_objc_block = function Block _ -> true | _ -> false
let is_with_block_parameters = function WithBlockParameters _ -> true | _ -> false
(** Return whether the procname is a cpp lambda. *) (** Return whether the procname is a cpp lambda. *)
let is_cpp_lambda procname = String.is_substring ~substring:"operator()" (get_method procname) let is_cpp_lambda procname = String.is_substring ~substring:"operator()" (get_method procname)
@ -777,11 +759,6 @@ module Procname = struct
(** Return the parameters of a java procname. *) (** Return the parameters of a java procname. *)
let java_get_parameters j = j.parameters let java_get_parameters j = j.parameters
(** Return the parameters of a java procname as strings. *)
let java_get_parameters_as_strings j =
List.map ~f:(fun param -> java_type_to_string param) j.parameters
(** Return true if the java procedure is static *) (** Return true if the java procedure is static *)
let java_is_static = function Java j -> equal_method_kind j.kind Static | _ -> false let java_is_static = function Java j -> equal_method_kind j.kind Static | _ -> false
@ -846,30 +823,6 @@ module Procname = struct
false false
(** Check if the procedure belongs to an anonymous inner class. *)
let java_is_anonymous_inner_class = function
| Java j ->
is_anonymous_inner_class_name j.class_name
| _ ->
false
(** Check if the last parameter is a hidden inner class, and remove it if present.
This is used in private constructors, where a proxy constructor is generated
with an extra parameter and calls the normal constructor. *)
let java_remove_hidden_inner_class_parameter = function
| Java js -> (
match List.rev js.parameters with
| (_, s) :: par' ->
if is_anonymous_inner_class_name (Name.Java.from_string s) then
Some (Java {js with parameters= List.rev par'})
else None
| [] ->
None )
| _ ->
None
(** Check if the procedure name is an anonymous inner class constructor. *) (** Check if the procedure name is an anonymous inner class constructor. *)
let java_is_anonymous_inner_class_constructor = function let java_is_anonymous_inner_class_constructor = function
| Java js -> | Java js ->
@ -1120,9 +1073,6 @@ module Procname = struct
let pp = pp let pp = pp
end) end)
(** Pretty print a set of proc names *)
let pp_set fmt set = Set.iter (fun pname -> F.fprintf fmt "%a " pp pname) set
let objc_cpp_get_class_qualifiers objc_cpp = Name.qual_name objc_cpp.class_name let objc_cpp_get_class_qualifiers objc_cpp = Name.qual_name objc_cpp.class_name
let get_qualifiers pname = let get_qualifiers pname =
@ -1189,60 +1139,6 @@ module Procname = struct
let default () = Sqlite3.Data.TEXT (to_filename pname) in let default () = Sqlite3.Data.TEXT (to_filename pname) in
Base.Hashtbl.find_or_add pname_to_key pname ~default Base.Hashtbl.find_or_add pname_to_key pname ~default
end end
(** given two template arguments, try to generate mapping from generic ones to concrete ones. *)
let get_template_args_mapping generic_procname concrete_procname =
let mapping_for_template_args (generic_name, generic_args) (concrete_name, concrete_args) =
match (generic_args, concrete_args) with
| Template {args= generic_typs}, Template {args= concrete_typs}
when QualifiedCppName.equal generic_name concrete_name -> (
try
`Valid
(List.fold2_exn generic_typs concrete_typs ~init:[] ~f:
(fun (* result will be reversed list. Ordering in template mapping doesn't matter so it's ok *)
result
gtyp
ctyp
->
match (gtyp, ctyp) with
| TType {desc= TVar name}, TType concrete ->
(name, concrete) :: result
| _ ->
result ))
with Invalid_argument _ ->
`Invalid (* fold2_exn throws on length mismatch, we need to handle it *) )
| NoTemplate, NoTemplate ->
`NoTemplate
| _ ->
`Invalid
in
let combine_mappings mapping1 mapping2 =
match (mapping1, mapping2) with
| `Valid m1, `Valid m2 ->
`Valid (List.append m1 m2)
| `NoTemplate, a | a, `NoTemplate ->
a
(* no template is no-op state, simply return the other state *) | _ ->
`Invalid
(* otherwise there is no valid mapping *)
in
let extract_mapping = function `Invalid | `NoTemplate -> None | `Valid m -> Some m in
let empty_qual =
QualifiedCppName.of_qual_string "FIXME"
(* TODO we should look at procedure names *)
in
match (generic_procname, concrete_procname) with
| C {template_args= args1}, C {template_args= args2} (* template function *) ->
mapping_for_template_args (empty_qual, args1) (empty_qual, args2) |> extract_mapping
| ( ObjC_Cpp {template_args= args1; class_name= CppClass (name1, class_args1)}
, ObjC_Cpp {template_args= args2; class_name= CppClass (name2, class_args2)}
(* template methods/template classes/both *) ) ->
combine_mappings
(mapping_for_template_args (name1, class_args1) (name2, class_args2))
(mapping_for_template_args (empty_qual, args1) (empty_qual, args2))
|> extract_mapping
| _ ->
None
end end
(** Return the return type of [pname_java]. *) (** Return the return type of [pname_java]. *)

@ -37,10 +37,6 @@ val ikind_is_char : ikind -> bool
val ikind_is_unsigned : ikind -> bool val ikind_is_unsigned : ikind -> bool
(** Check whether the integer kind is unsigned *) (** Check whether the integer kind is unsigned *)
val int_of_int64_kind : int64 -> ikind -> IntLit.t
(** Convert an int64 into an IntLit.t given the kind:
the int64 is interpreted as unsigned according to the kind *)
(** Kinds of floating-point numbers *) (** Kinds of floating-point numbers *)
type fkind = type fkind =
| FFloat (** [float] *) | FFloat (** [float] *)
@ -185,9 +181,6 @@ module Name : sig
val from_qual_name : QualifiedCppName.t -> t val from_qual_name : QualifiedCppName.t -> t
val protocol_from_qual_name : QualifiedCppName.t -> t val protocol_from_qual_name : QualifiedCppName.t -> t
val is_class : t -> bool
(** [is_class name] holds if [name] names a Objc class *)
end end
module Set : Caml.Set.S with type elt = t module Set : Caml.Set.S with type elt = t
@ -244,19 +237,12 @@ val is_objc_class : t -> bool
val is_cpp_class : t -> bool val is_cpp_class : t -> bool
val is_java_class : t -> bool
val is_array_of_cpp_class : t -> bool
val is_pointer_to_cpp_class : t -> bool val is_pointer_to_cpp_class : t -> bool
val is_pointer : t -> bool val is_pointer : t -> bool
val has_block_prefix : string -> bool val has_block_prefix : string -> bool
val is_block_type : t -> bool
(** Check if type is a type for a block in objc *)
val unsome : string -> t option -> t val unsome : string -> t option -> t
type typ = t type typ = t
@ -308,14 +294,10 @@ module Procname : sig
| WithBlockParameters of t * block_name list | WithBlockParameters of t * block_name list
[@@deriving compare] [@@deriving compare]
val block_from_string : string -> block_name
val block_name_of_procname : t -> block_name val block_name_of_procname : t -> block_name
val equal : t -> t -> bool val equal : t -> t -> bool
val hash : t -> int
type java_type = string option * string type java_type = string option * string
type method_kind = type method_kind =
@ -356,27 +338,18 @@ module Procname : sig
val is_objc_block : t -> bool val is_objc_block : t -> bool
(** Return whether the procname is a block procname. *) (** Return whether the procname is a block procname. *)
val is_with_block_parameters : t -> bool
(** Return whether the procname is a procname instantiated with block parameters. *)
val is_cpp_lambda : t -> bool val is_cpp_lambda : t -> bool
(** Return whether the procname is a cpp lambda. *) (** Return whether the procname is a cpp lambda. *)
val hash_pname : t -> int val hash_pname : t -> int
(** Hash function for procname. *) (** Hash function for procname. *)
val is_anonymous_inner_class_name : Name.t -> bool
(** Check if a class string is an anoynmous inner class name. *)
val is_c_method : t -> bool val is_c_method : t -> bool
(** Check if this is an Objective-C/C++ method name. *) (** Check if this is an Objective-C/C++ method name. *)
val is_c_function : t -> bool val is_c_function : t -> bool
(** Check if this is a C function name. *) (** Check if this is a C function name. *)
val is_obj_c_pp : t -> bool
(** Check if this is an Objective-C/C++ method name or C-style function. *)
val is_objc_constructor : string -> bool val is_objc_constructor : string -> bool
(** Check if this is a constructor method in Objective-C. *) (** Check if this is a constructor method in Objective-C. *)
@ -445,15 +418,9 @@ module Procname : sig
val java_get_method : java -> string val java_get_method : java -> string
(** Return the method name of a java procedure name. *) (** Return the method name of a java procedure name. *)
val java_get_return_type : java -> string
(** Return the return type of a java procedure name. *)
val java_get_parameters : java -> java_type list val java_get_parameters : java -> java_type list
(** Return the parameters of a java procedure name. *) (** Return the parameters of a java procedure name. *)
val java_get_parameters_as_strings : java -> string list
(** Return the parameters of a java procname as strings. *)
val java_is_access_method : t -> bool val java_is_access_method : t -> bool
(** Check if the procedure name is an acess method (e.g. access$100 used to (** Check if the procedure name is an acess method (e.g. access$100 used to
access private members from a nested class. *) access private members from a nested class. *)
@ -461,9 +428,6 @@ module Procname : sig
val java_is_autogen_method : t -> bool val java_is_autogen_method : t -> bool
(** Check if the procedure name is of an auto-generated method containing '$'. *) (** Check if the procedure name is of an auto-generated method containing '$'. *)
val java_is_anonymous_inner_class : t -> bool
(** Check if the procedure belongs to an anonymous inner class. *)
val java_is_anonymous_inner_class_constructor : t -> bool val java_is_anonymous_inner_class_constructor : t -> bool
(** Check if the procedure name is an anonymous inner class constructor. *) (** Check if the procedure name is an anonymous inner class constructor. *)
@ -483,17 +447,9 @@ module Procname : sig
val java_is_generated : t -> bool val java_is_generated : t -> bool
(** Check if the proc name comes from generated code *) (** Check if the proc name comes from generated code *)
val java_remove_hidden_inner_class_parameter : t -> t option
(** Check if the last parameter is a hidden inner class, and remove it if present.
This is used in private constructors, where a proxy constructor is generated
with an extra parameter and calls the normal constructor. *)
val java_replace_method : java -> string -> java val java_replace_method : java -> string -> java
(** Replace the method name of an existing java procname. *) (** Replace the method name of an existing java procname. *)
val java_type_to_string : java_type -> string
(** Convert a java type to a string. *)
val is_class_initializer : t -> bool val is_class_initializer : t -> bool
(** Check if this is a class initializer. *) (** Check if this is a class initializer. *)
@ -507,9 +463,6 @@ module Procname : sig
val pp : Format.formatter -> t -> unit val pp : Format.formatter -> t -> unit
(** Pretty print a proc name. *) (** Pretty print a proc name. *)
val pp_set : Format.formatter -> Set.t -> unit
(** Pretty print a set of proc names. *)
val replace_class : t -> Name.t -> t val replace_class : t -> Name.t -> t
(** Replace the class name component of a procedure name. (** Replace the class name component of a procedure name.
In case of Java, replace package and class name. *) In case of Java, replace package and class name. *)
@ -538,14 +491,6 @@ module Procname : sig
val objc_cpp_get_class_qualifiers : objc_cpp -> QualifiedCppName.t val objc_cpp_get_class_qualifiers : objc_cpp -> QualifiedCppName.t
(** get qualifiers of a class owning objc/C++ method *) (** get qualifiers of a class owning objc/C++ method *)
val get_template_args_mapping : t -> t -> type_subst_t option
(** Return type substitution that would produce concrete procname from generic procname. Returns None if
such substitution doesn't exist
NOTE: this function doesn't check if such substitution is correct in terms of return
type/function parameters.
NOTE: this function doesn't deal with nested template classes, it only extracts mapping for function
and/or direct parent (class that defines the method) if it exists. *)
end end
val java_proc_return_typ : Procname.java -> t val java_proc_return_typ : Procname.java -> t

@ -14,24 +14,6 @@ open! IStd
module L = Logging module L = Logging
module F = Format module F = Format
(** Convenience functions for checkers to print information *)
module PP = struct
(** Print a range of lines of the source file in [loc], including [nbefore] lines before loc
and [nafter] lines after [loc] *)
let pp_loc_range linereader nbefore nafter fmt loc =
let printline n =
match Printer.LineReader.from_loc linereader {loc with Location.line= n} with
| Some s ->
F.fprintf fmt "%s%s@\n" (if Int.equal n loc.Location.line then "-->" else " ") s
| _ ->
()
in
F.fprintf fmt "%a:%d@\n" SourceFile.pp loc.Location.file loc.Location.line ;
for n = loc.Location.line - nbefore to loc.Location.line + nafter do printline n done
end
(* PP *)
(** State that persists in the .specs files. *) (** State that persists in the .specs files. *)
module ST = struct module ST = struct
let report_error tenv proc_name proc_desc kind loc ?(advice= None) ?(field_name= None) let report_error tenv proc_name proc_desc kind loc ?(advice= None) ?(field_name= None)

@ -20,12 +20,3 @@ module ST : sig
-> unit -> unit
(** Report an error. *) (** Report an error. *)
end end
(* ST *)
module PP : sig
val pp_loc_range : Printer.LineReader.t -> int -> int -> Format.formatter -> Location.t -> unit
(** Print a range of lines of the source file in [loc], including [nbefore] lines before loc
and [nafter] lines after [loc] *)
end
(* PP *)

@ -33,4 +33,4 @@ val get_formal_base : int -> t -> AccessPath.base option
val get_formals_indexes : t -> (AccessPath.base * int) list val get_formals_indexes : t -> (AccessPath.base * int) list
(** Get a list of (base * index) pairs. Note: these are sorted by base, not index *) (** Get a list of (base * index) pairs. Note: these are sorted by base, not index *)
val pp : F.formatter -> t -> unit val pp : F.formatter -> t -> unit [@@warning "-32"]

@ -22,13 +22,6 @@ let type_is_object typ =
false false
let java_proc_name_with_class_method pn_java class_with_path method_name =
try
String.equal (Typ.Procname.java_get_class_name pn_java) class_with_path
&& String.equal (Typ.Procname.java_get_method pn_java) method_name
with _ -> false
(** Holds iff the predicate holds on a supertype of the named type, including the type itself *) (** Holds iff the predicate holds on a supertype of the named type, including the type itself *)
let rec supertype_exists tenv pred name = let rec supertype_exists tenv pred name =
match Tenv.lookup tenv name with match Tenv.lookup tenv name with
@ -50,14 +43,6 @@ let rec supertype_find_map_opt tenv f name =
result result
let is_immediate_subtype tenv this_type_name super_type_name =
match Tenv.lookup tenv this_type_name with
| Some {supers} ->
List.exists ~f:(Typ.Name.equal super_type_name) supers
| None ->
false
(** return true if [typ0] <: [typ1] *) (** return true if [typ0] <: [typ1] *)
let is_subtype tenv name0 name1 = let is_subtype tenv name0 name1 =
Typ.Name.equal name0 name1 Typ.Name.equal name0 name1
@ -196,50 +181,10 @@ let get_vararg_type_names tenv (call_node: Procdesc.Node.t) (ivar: Pvar.t) : str
List.rev (type_names call_node) List.rev (type_names call_node)
let has_formal_proc_argument_type_names proc_desc argument_type_names =
let formals = Procdesc.get_formals proc_desc in
let equal_formal_arg (_, typ) arg_type_name = String.equal (get_type_name typ) arg_type_name in
Int.equal (List.length formals) (List.length argument_type_names)
&& List.for_all2_exn ~f:equal_formal_arg formals argument_type_names
let has_formal_method_argument_type_names cfg pname_java argument_type_names =
has_formal_proc_argument_type_names cfg
(Typ.Procname.java_get_class_name pname_java :: argument_type_names)
let is_getter pname_java = let is_getter pname_java =
Str.string_match (Str.regexp "get*") (Typ.Procname.java_get_method pname_java) 0 Str.string_match (Str.regexp "get*") (Typ.Procname.java_get_method pname_java) 0
let is_setter pname_java =
Str.string_match (Str.regexp "set*") (Typ.Procname.java_get_method pname_java) 0
(** Returns the signature of a field access (class name, field name, field type name) *)
let get_java_field_access_signature = function
| Sil.Load (_, Exp.Lfield (_, fn, ft), bt, _) ->
Some (get_type_name bt, Typ.Fieldname.java_get_field fn, get_type_name ft)
| _ ->
None
(** Returns the formal signature (class name, method name,
argument type names and return type name) *)
let get_java_method_call_formal_signature = function
| Sil.Call (_, Exp.Const Const.Cfun pn, (_, tt) :: args, _, _) -> (
match pn with
| Typ.Procname.Java pn_java ->
let arg_names = List.map ~f:(function _, t -> get_type_name t) args in
let rt_name = Typ.Procname.java_get_return_type pn_java in
let m_name = Typ.Procname.java_get_method pn_java in
Some (get_type_name tt, m_name, arg_names, rt_name)
| _ ->
None )
| _ ->
None
let type_is_class typ = let type_is_class typ =
match typ.Typ.desc with match typ.Typ.desc with
| Tptr ({desc= Tstruct _}, _) -> | Tptr ({desc= Tstruct _}, _) ->
@ -392,9 +337,6 @@ let is_runtime_exception tenv typename =
is_subtype_of_str tenv typename "java.lang.RuntimeException" is_subtype_of_str tenv typename "java.lang.RuntimeException"
(** Checks if the class name is a Java exception *)
let is_exception tenv typename = is_subtype_of_str tenv typename "java.lang.Exception"
(** Checks if the class name is a Java exception *) (** Checks if the class name is a Java exception *)
let is_throwable tenv typename = is_subtype_of_str tenv typename "java.lang.Throwable" let is_throwable tenv typename = is_subtype_of_str tenv typename "java.lang.Throwable"

@ -11,14 +11,6 @@ open! IStd
(** Module for Pattern matching. *) (** Module for Pattern matching. *)
val get_java_field_access_signature : Sil.instr -> (string * string * string) option
(** Returns the signature of a field access (class name, field name, field type name) *)
val get_java_method_call_formal_signature :
Sil.instr -> (string * string * string list * string) option
(** Returns the formal signature (class name, method name,
argument type names and return type name) *)
val get_this_type : ProcAttributes.t -> Typ.t option val get_this_type : ProcAttributes.t -> Typ.t option
(** Get the this type of a procedure *) (** Get the this type of a procedure *)
@ -28,20 +20,12 @@ val get_type_name : Typ.t -> string
val get_vararg_type_names : Tenv.t -> Procdesc.Node.t -> Pvar.t -> string list val get_vararg_type_names : Tenv.t -> Procdesc.Node.t -> Pvar.t -> string list
(** Get the type names of a variable argument *) (** Get the type names of a variable argument *)
val has_formal_method_argument_type_names : Procdesc.t -> Typ.Procname.java -> string list -> bool
val method_is_initializer : Tenv.t -> ProcAttributes.t -> bool val method_is_initializer : Tenv.t -> ProcAttributes.t -> bool
(** Check if the method is one of the known initializer methods. *) (** Check if the method is one of the known initializer methods. *)
val is_getter : Typ.Procname.java -> bool val is_getter : Typ.Procname.java -> bool
(** Is this a getter proc name? *) (** Is this a getter proc name? *)
val is_setter : Typ.Procname.java -> bool
(** Is this a setter proc name? *)
val is_immediate_subtype : Tenv.t -> Typ.Name.t -> Typ.Name.t -> bool
(** Is the type a direct subtype of the typename? *)
val is_subtype : Tenv.t -> Typ.Name.t -> Typ.Name.t -> bool val is_subtype : Tenv.t -> Typ.Name.t -> Typ.Name.t -> bool
(** Is the type a transitive subtype of the typename? *) (** Is the type a transitive subtype of the typename? *)
@ -61,8 +45,6 @@ val java_get_const_type_name : Const.t -> string
val java_get_vararg_values : Procdesc.Node.t -> Pvar.t -> Idenv.t -> Exp.t list 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 java_proc_name_with_class_method : Typ.Procname.java -> string -> string -> bool
val proc_calls : val proc_calls :
(Typ.Procname.t -> ProcAttributes.t option) -> Procdesc.t (Typ.Procname.t -> ProcAttributes.t option) -> Procdesc.t
-> (Typ.Procname.t -> ProcAttributes.t -> bool) -> (Typ.Procname.t * ProcAttributes.t) list -> (Typ.Procname.t -> ProcAttributes.t -> bool) -> (Typ.Procname.t * ProcAttributes.t) list
@ -90,9 +72,6 @@ val type_is_object : Typ.t -> bool
val get_fields_nullified : Procdesc.t -> Typ.Fieldname.Set.t val get_fields_nullified : Procdesc.t -> Typ.Fieldname.Set.t
(** return the set of instance fields that are assigned to a null literal in [procdesc] *) (** return the set of instance fields that are assigned to a null literal in [procdesc] *)
val is_exception : Tenv.t -> Typ.Name.t -> bool
(** [is_exception tenv class_name] checks if class_name is of type java.lang.Exception *)
val is_throwable : Tenv.t -> Typ.Name.t -> bool val is_throwable : Tenv.t -> Typ.Name.t -> bool
(** [is_throwable tenv class_name] checks if class_name is of type java.lang.Throwable *) (** [is_throwable tenv class_name] checks if class_name is of type java.lang.Throwable *)

@ -15,8 +15,6 @@ type no_extras = unit
let empty_extras = () let empty_extras = ()
let make_empty_extras _ = ()
let make pdesc tenv extras = {pdesc; tenv; extras} let make pdesc tenv extras = {pdesc; tenv; extras}
let make_default pdesc tenv = make pdesc tenv empty_extras let make_default pdesc tenv = make pdesc tenv empty_extras

@ -17,6 +17,4 @@ val empty_extras : no_extras
val make : Procdesc.t -> Tenv.t -> 'a -> 'a t val make : Procdesc.t -> Tenv.t -> 'a -> 'a t
val make_empty_extras : Procdesc.t -> no_extras
val make_default : Procdesc.t -> Tenv.t -> no_extras t val make_default : Procdesc.t -> Tenv.t -> no_extras t

@ -66,13 +66,6 @@ let get_all (prop: 'a Prop.t) =
List.rev !res List.rev !res
(** Get all the attributes of the prop *)
let get_for_symb prop att =
List.filter
~f:(function Sil.Apred (att', _) | Anpred (att', _) -> PredSymb.equal att' att | _ -> false)
prop.Prop.pi
(** Get the attribute associated to the expression, if any *) (** Get the attribute associated to the expression, if any *)
let get_for_exp tenv (prop: 'a Prop.t) exp = let get_for_exp tenv (prop: 'a Prop.t) exp =
let nexp = Prop.exp_normalize_prop tenv prop exp in let nexp = Prop.exp_normalize_prop tenv prop exp in
@ -101,16 +94,10 @@ let get_undef tenv prop exp = get tenv prop exp ACundef
let get_resource tenv prop exp = get tenv prop exp ACresource let get_resource tenv prop exp = get tenv prop exp ACresource
let get_autorelease tenv prop exp = get tenv prop exp ACautorelease
let get_objc_null tenv prop exp = get tenv prop exp ACobjc_null let get_objc_null tenv prop exp = get tenv prop exp ACobjc_null
let get_div0 tenv prop exp = get tenv prop exp ACdiv0
let get_observer tenv prop exp = get tenv prop exp ACobserver let get_observer tenv prop exp = get tenv prop exp ACobserver
let get_retval tenv prop exp = get tenv prop exp ACretval
let get_wontleak tenv prop exp = get tenv prop exp ACwontleak let get_wontleak tenv prop exp = get tenv prop exp ACwontleak
let has_dangling_uninit tenv prop exp = let has_dangling_uninit tenv prop exp =

@ -38,15 +38,6 @@ val get_all : 'a Prop.t -> Sil.atom list
val get_for_exp : Tenv.t -> 'a Prop.t -> Exp.t -> Sil.atom list val get_for_exp : Tenv.t -> 'a Prop.t -> Exp.t -> Sil.atom list
(** Get the attributes associated to the expression, if any *) (** Get the attributes associated to the expression, if any *)
val get_for_symb : 'a Prop.t -> PredSymb.t -> Sil.atom list
(** Retrieve all the atoms that contain a specific attribute *)
val get_autorelease : Tenv.t -> 'a Prop.t -> Exp.t -> Sil.atom option
(** Get the autorelease attribute associated to the expression, if any *)
val get_div0 : Tenv.t -> 'a Prop.t -> Exp.t -> Sil.atom option
(** Get the div0 attribute associated to the expression, if any *)
val get_objc_null : Tenv.t -> 'a Prop.t -> Exp.t -> Sil.atom option val get_objc_null : Tenv.t -> 'a Prop.t -> Exp.t -> Sil.atom option
(** Get the objc null attribute associated to the expression, if any *) (** Get the objc null attribute associated to the expression, if any *)
@ -56,9 +47,6 @@ val get_observer : Tenv.t -> 'a Prop.t -> Exp.t -> Sil.atom option
val get_resource : Tenv.t -> 'a Prop.t -> Exp.t -> Sil.atom option val get_resource : Tenv.t -> 'a Prop.t -> Exp.t -> Sil.atom option
(** Get the resource attribute associated to the expression, if any *) (** Get the resource attribute associated to the expression, if any *)
val get_retval : Tenv.t -> 'a Prop.t -> Exp.t -> Sil.atom option
(** Get the retval null attribute associated to the expression, if any *)
val get_undef : Tenv.t -> 'a Prop.t -> Exp.t -> Sil.atom option val get_undef : Tenv.t -> 'a Prop.t -> Exp.t -> Sil.atom option
(** Get the undef attribute associated to the expression, if any *) (** Get the undef attribute associated to the expression, if any *)

@ -275,8 +275,6 @@ module VISIBLE_FOR_TESTING_DO_NOT_USE_DIRECTLY = struct
let skip_duplicated_types_on_filenames = skip_duplicated_types_on_filenames let skip_duplicated_types_on_filenames = skip_duplicated_types_on_filenames
let java_anon_class_pattern = java_anon_class_pattern
let value_of_qualifier_tag = value_of_qualifier_tag let value_of_qualifier_tag = value_of_qualifier_tag
let skip_anonymous_class_renamings = skip_anonymous_class_renamings let skip_anonymous_class_renamings = skip_anonymous_class_renamings

@ -42,8 +42,6 @@ module VISIBLE_FOR_TESTING_DO_NOT_USE_DIRECTLY : sig
val skip_duplicated_types_on_filenames : FileRenamings.t -> Differential.t -> Differential.t val skip_duplicated_types_on_filenames : FileRenamings.t -> Differential.t -> Differential.t
val java_anon_class_pattern : Str.regexp
val value_of_qualifier_tag : Jsonbug_t.tag_value_record list -> string -> string option val value_of_qualifier_tag : Jsonbug_t.tag_value_record list -> string -> string option
val skip_anonymous_class_renamings : Differential.t -> Differential.t val skip_anonymous_class_renamings : Differential.t -> Differential.t

@ -9,9 +9,6 @@
open! IStd open! IStd
val remove_ret : Tenv.t -> Procdesc.t -> Prop.normal Prop.t -> Prop.normal Prop.t
(** remove the return variable from the prop *)
val remove_locals_ret : Tenv.t -> Procdesc.t -> Prop.normal Prop.t -> Prop.normal Prop.t val remove_locals_ret : Tenv.t -> Procdesc.t -> Prop.normal Prop.t -> Prop.normal Prop.t
(** remove locals and return variable from the prop *) (** remove locals and return variable from the prop *)

@ -19,8 +19,6 @@ type retain_cycle_edge = {rc_from: retain_cycle_node; rc_field: retain_cycle_fie
to model the cycle structure. The next element from the end of the list is the head. *) to model the cycle structure. The next element from the end of the list is the head. *)
type t = {rc_elements: retain_cycle_edge list; rc_head: retain_cycle_edge} type t = {rc_elements: retain_cycle_edge list; rc_head: retain_cycle_edge}
val retain_cycle_to_string : t -> string
val print_cycle : t -> unit val print_cycle : t -> unit
val create_cycle : retain_cycle_edge list -> t option val create_cycle : retain_cycle_edge list -> t option

@ -15,8 +15,6 @@ type closure = unit -> unit
type t = {closures: closure list; continuations: closure Queue.t} type t = {closures: closure list; continuations: closure Queue.t}
type tasks = t
let create ?(continuation= None) closures = let create ?(continuation= None) closures =
let continuations = let continuations =
match continuation with None -> Queue.create () | Some closure -> Queue.singleton closure match continuation with None -> Queue.create () | Some closure -> Queue.singleton closure
@ -24,8 +22,6 @@ let create ?(continuation= None) closures =
{closures; continuations} {closures; continuations}
let empty = {closures= []; continuations= Queue.create ()}
(* Aggregate closures into groups of the given size *) (* Aggregate closures into groups of the given size *)
let aggregate ~size t = let aggregate ~size t =
let group_to_closure group () = List.iter ~f:(fun closure -> closure ()) group in let group_to_closure group () = List.iter ~f:(fun closure -> closure ()) group in

@ -13,8 +13,6 @@ open! IStd
with a continuation to be executed at the end *) with a continuation to be executed at the end *)
type t type t
type tasks = t
(** Each task/continuation executes a closure *) (** Each task/continuation executes a closure *)
type closure = unit -> unit type closure = unit -> unit
@ -26,9 +24,6 @@ val create : ?continuation:closure option -> closure list -> t
(** Create tasks with a list of closures to be executed in parallel, (** Create tasks with a list of closures to be executed in parallel,
and an optional continuation to be executed afterwards *) and an optional continuation to be executed afterwards *)
val empty : t
(** No-op tasks *)
val run : t -> unit val run : t -> unit
(** Run the closures and continuation *) (** Run the closures and continuation *)

@ -38,11 +38,6 @@ let check_register_populated () =
L.(die InternalError) "Builtins were not initialized" L.(die InternalError) "Builtins were not initialized"
(** check if the function is a builtin *)
let is_registered name =
Typ.Procname.Hash.mem builtin_functions name || (check_register_populated () ; false)
(** get the symbolic execution handler associated to the builtin function name *) (** get the symbolic execution handler associated to the builtin function name *)
let get name : t option = let get name : t option =
try Some (Typ.Procname.Hash.find builtin_functions name) with Not_found -> try Some (Typ.Procname.Hash.find builtin_functions name) with Not_found ->

@ -31,9 +31,6 @@ type registered
val register : Typ.Procname.t -> t -> registered val register : Typ.Procname.t -> t -> registered
(** Register a builtin [Typ.Procname.t] and symbolic execution handler *) (** Register a builtin [Typ.Procname.t] and symbolic execution handler *)
val is_registered : Typ.Procname.t -> bool
(** Check if the function is a builtin *)
val get : Typ.Procname.t -> t option val get : Typ.Procname.t -> t option
(** Get the symbolic execution handler associated to the builtin function name *) (** Get the symbolic execution handler associated to the builtin function name *)

@ -1071,25 +1071,6 @@ let pp_dotty_one_spec f pre posts =
F.fprintf f "@\n } @\n" F.fprintf f "@\n } @\n"
(* this is used to print a list of proposition when considered in a path of nodes *)
let pp_dotty_prop_list_in_path f plist prev_n curr_n =
try
incr proposition_counter ;
incr dotty_state_count ;
F.fprintf f "@\n subgraph cluster_%i { color=blue @\n" !dotty_state_count ;
incr dotty_state_count ;
F.fprintf f "@\n state%iN [label=\"NODE %i \", style=filled, color= lightblue]@\n" curr_n
curr_n ;
List.iter
~f:(fun po ->
incr proposition_counter ;
pp_dotty f Generic_proposition po None )
plist ;
if prev_n <> -1 then F.fprintf f "@\n state%iN ->state%iN@\n" prev_n curr_n ;
F.fprintf f "@\n } @\n"
with exn when SymOp.exn_not_failure exn -> ()
let pp_dotty_prop fmt (prop, cycle) = let pp_dotty_prop fmt (prop, cycle) =
reset_proposition_counter () ; reset_proposition_counter () ;
Format.fprintf fmt "@\n@\n@\ndigraph main { @\nnode [shape=box]; @\n" ; Format.fprintf fmt "@\n@\n@\ndigraph main { @\nnode [shape=box]; @\n" ;
@ -1119,38 +1100,9 @@ let dotty_retain_cycle_to_str prop (cycle: RetainCyclesType.t) =
with exn when SymOp.exn_not_failure exn -> None with exn when SymOp.exn_not_failure exn -> None
(* create a dotty file with a single proposition *)
let dotty_prop_to_dotty_file fname prop cycle =
try
let out_dot = Out_channel.create fname in
let fmt_dot = Format.formatter_of_out_channel out_dot in
pp_dotty_prop fmt_dot (prop, cycle) ;
Out_channel.close out_dot
with exn when SymOp.exn_not_failure exn -> ()
(* This is used only to print a list of prop parsed with the external parser. Basically
deprecated.*)
let pp_proplist_parsed2dotty_file filename plist =
try
let pp_list f plist =
reset_proposition_counter () ;
F.fprintf f "@\n@\n@\ndigraph main { @\nnode [shape=box];@\n" ;
F.fprintf f "@\n compound = true; @\n" ;
F.fprintf f "@\n /* size=\"12,7\"; ratio=fill;*/ @\n" ;
ignore (List.map ~f:(pp_dotty f Generic_proposition) plist) ;
F.fprintf f "@\n}"
in
let outc = Out_channel.create filename in
let fmt = F.formatter_of_out_channel outc in
F.fprintf fmt "#### Dotty version: ####@.%a@.@." pp_list plist ;
Out_channel.close outc
with exn when SymOp.exn_not_failure exn -> ()
(********** START of Print interprocedural cfgs in dotty format *) (********** START of Print interprocedural cfgs in dotty format *)
(********** Print control flow graph (in dot form) for fundec to *) (********** Print control flow graph (in dot form) for fundec to channel. You have to compute an
(* channel. You have to compute an interprocedural cfg first *) interprocedural cfg first. *)
let pp_cfgnodename pname fmt (n: Procdesc.Node.t) = let pp_cfgnodename pname fmt (n: Procdesc.Node.t) =
F.fprintf fmt "\"%s_%d\"" F.fprintf fmt "\"%s_%d\""
@ -1318,418 +1270,3 @@ let pp_speclist_to_file (filename: DB.filename) spec_list =
let pp_speclist_dotty_file (filename: DB.filename) spec_list = let pp_speclist_dotty_file (filename: DB.filename) spec_list =
try pp_speclist_to_file filename spec_list with exn when SymOp.exn_not_failure exn -> () try pp_speclist_to_file filename spec_list with exn when SymOp.exn_not_failure exn -> ()
(**********************************************************************)
(* Code prodicing a xml version of a graph *)
(**********************************************************************)
(* each node has an unique integer identifier *)
type visual_heap_node =
| VH_dangling of int * Exp.t
| VH_pointsto of int * Exp.t * Sil.strexp * Exp.t
(* VH_pointsto(id,address,content,type) *)
| VH_lseg of int * Exp.t * Exp.t * Sil.lseg_kind
(*VH_lseg(id,address,content last cell, kind) *)
(*VH_dllseg(id, address, content first cell, content last cell, address last cell, kind) *)
| VH_dllseg of int * Exp.t * Exp.t * Exp.t * Exp.t * Sil.lseg_kind
(* an edge is a pair of node identifiers*)
type visual_heap_edge = {src: int; trg: int; lab: string}
let mk_visual_heap_edge s t l = {src= s; trg= t; lab= l}
(* used to generate unique identifier for all the nodes in the set of visual graphs used to *)
(* represent a proposition*)
let global_node_counter = ref 0
let working_list = ref []
let set_dangling_nodes = ref []
(* convert an exp into a string which is xml friendly, ie. special character are replaced by*)
(* the proper xml way to visualize them*)
let exp_to_xml_string e = F.asprintf "%a" (Sil.pp_exp_printenv (Pp.html Black)) e
(* convert an atom into an xml-friendly string without special characters *)
let atom_to_xml_string a = F.asprintf "%a" (Sil.pp_atom (Pp.html Black)) a
(* return the dangling node corresponding to an expression it exists or None *)
let exp_dangling_node e =
let entry_e =
List.filter
~f:(fun b -> match b with VH_dangling (_, e') -> Exp.equal e e' | _ -> false)
!set_dangling_nodes
in
match entry_e with
| [] ->
None
| (VH_dangling (n, e')) :: _ ->
Some (VH_dangling (n, e'))
| _ ->
None
(* NOTE: this cannot be possible since entry_e can be composed only by VH_dangling, see def of entry_e*)
(* make nodes and when it finds a list records in the working list *)
(* to do (n, prop) where n is the integer identifier of the list node. *)
(* This allow to keep the connection between the list node and the graph *)
(* that displays its contents. *)
let rec make_visual_heap_nodes sigma =
let n = !global_node_counter in
incr global_node_counter ;
match sigma with
| [] ->
[]
| (Sil.Hpointsto (e, se, t)) :: sigma' ->
VH_pointsto (n, e, se, t) :: make_visual_heap_nodes sigma'
| (Sil.Hlseg (k, hpara, e1, e2, _)) :: sigma' ->
working_list := (n, hpara.Sil.body) :: !working_list ;
VH_lseg (n, e1, e2, k) :: make_visual_heap_nodes sigma'
| (Sil.Hdllseg (k, hpara_dll, e1, e2, e3, e4, _)) :: sigma' ->
working_list := (n, hpara_dll.Sil.body_dll) :: !working_list ;
VH_dllseg (n, e1, e2, e3, e4, k) :: make_visual_heap_nodes sigma'
(* given a node returns its id and address*)
let get_node_id_and_addr node =
match node with
| VH_dangling (n, e)
| VH_pointsto (n, e, _, _)
| VH_lseg (n, e, _, _)
| VH_dllseg (n, e, _, _, _, _) ->
(n, e)
(* return node's id*)
let get_node_id node = fst (get_node_id_and_addr node)
(* return node's address*)
let get_node_addr node = snd (get_node_id_and_addr node)
(* return the nodes corresponding to an address given by an expression *)
let rec select_node_at_address nodes e =
match nodes with
| [] ->
None
| n :: l' ->
let e' = get_node_addr n in
if Exp.equal e e' then Some n else select_node_at_address l' e
(* look-up the ids in the list of nodes corresponding to expression e*)
(* let look_up_nodes_ids nodes e =
List.map ~f:get_node_id (select_nodes_exp nodes e) *)
(* create a list of dangling nodes *)
let make_set_dangling_nodes allocated_nodes (sigma: Sil.hpred list) =
let make_new_dangling e =
let n = !global_node_counter in
incr global_node_counter ; VH_dangling (n, e)
in
let get_rhs_predicate hpred =
match hpred with
| Sil.Hpointsto (_, Sil.Eexp (e, _), _) when not (Exp.equal e Exp.zero) ->
[e]
| Sil.Hlseg (_, _, _, e2, _) when not (Exp.equal e2 Exp.zero) ->
[e2]
| Sil.Hdllseg (_, _, _, e2, e3, _, _) ->
if Exp.equal e2 Exp.zero then if Exp.equal e3 Exp.zero then [] else [e3] else [e2; e3]
| Sil.Hpointsto (_, _, _) | _ ->
[]
(* arrays and struct do not give danglings. CHECK THIS!*)
in
let is_not_allocated e =
let allocated =
List.exists
~f:(fun a ->
match a with
| VH_pointsto (_, e', _, _) | VH_lseg (_, e', _, _) | VH_dllseg (_, e', _, _, _, _) ->
Exp.equal e e'
| _ ->
false )
allocated_nodes
in
not allocated
in
let rec filter_duplicate l seen_exp =
match l with
| [] ->
[]
| e :: l' ->
if List.exists ~f:(Exp.equal e) seen_exp then filter_duplicate l' seen_exp
else e :: filter_duplicate l' (e :: seen_exp)
in
let rhs_exp_list = List.concat_map ~f:get_rhs_predicate sigma in
let candidate_dangling_exps = filter_duplicate rhs_exp_list [] in
(* get rid of allocated ones*)
let dangling_exps = List.filter ~f:is_not_allocated candidate_dangling_exps in
List.map ~f:make_new_dangling dangling_exps
(* return a list of pairs (n,field_lab) where n is a target node*)
(* corresponding to se and is going to be used a target for and edge*)
(* field_lab is the name of the field which points to n (if any)*)
let rec compute_target_nodes_from_sexp nodes se prop field_lab =
match se with
| Sil.Eexp (e, _) when is_nil e prop ->
(* Nil is not represented by a node, it's just a value which should be printed*)
[]
| Sil.Eexp (e, _)
-> (
let e_node = select_node_at_address nodes e in
match e_node with
| None -> (
match exp_dangling_node e with None -> [] | Some dang_node -> [(dang_node, field_lab)] )
| Some n ->
[(n, field_lab)] )
| Sil.Estruct (lfld, inst) -> (
match lfld with
| [] ->
[]
| (fn, se2) :: l' ->
compute_target_nodes_from_sexp nodes se2 prop (Typ.Fieldname.to_string fn)
@ compute_target_nodes_from_sexp nodes (Sil.Estruct (l', inst)) prop "" )
| Sil.Earray (len, lie, inst) ->
match lie with
| [] ->
[]
| (idx, se2) :: l' ->
let lab = "[" ^ exp_to_xml_string idx ^ "]" in
compute_target_nodes_from_sexp nodes se2 prop lab
@ compute_target_nodes_from_sexp nodes (Sil.Earray (len, l', inst)) prop ""
(* build the set of edges between nodes *)
let rec make_visual_heap_edges nodes sigma prop =
let combine_source_target_label n (m, lab) =
mk_visual_heap_edge (get_node_id n) (get_node_id m) lab
in
match sigma with
| [] ->
[]
| (Sil.Hpointsto (e, se, _)) :: sigma'
-> (
let e_node = select_node_at_address nodes e in
match e_node with
| None ->
assert false
| Some n ->
let target_nodes = compute_target_nodes_from_sexp nodes se prop "" in
let ll = List.map ~f:(combine_source_target_label n) target_nodes in
ll @ make_visual_heap_edges nodes sigma' prop )
| (Sil.Hlseg (_, _, e1, e2, _)) :: sigma'
-> (
let e1_node = select_node_at_address nodes e1 in
match e1_node with
| None ->
assert false
| Some n ->
let target_nodes =
compute_target_nodes_from_sexp nodes (Sil.Eexp (e2, Sil.inst_none)) prop ""
in
let ll = List.map ~f:(combine_source_target_label n) target_nodes in
ll @ make_visual_heap_edges nodes sigma' prop )
| (Sil.Hdllseg (_, _, e1, e2, e3, _, _)) :: sigma' ->
let e1_node = select_node_at_address nodes e1 in
match e1_node with
| None ->
assert false
| Some n ->
let target_nodesF =
compute_target_nodes_from_sexp nodes (Sil.Eexp (e3, Sil.inst_none)) prop ""
in
let target_nodesB =
compute_target_nodes_from_sexp nodes (Sil.Eexp (e2, Sil.inst_none)) prop ""
in
let llF = List.map ~f:(combine_source_target_label n) target_nodesF in
let llB = List.map ~f:(combine_source_target_label n) target_nodesB in
llF @ llB @ make_visual_heap_edges nodes sigma' prop
(* from a prop generate and return visual proposition *)
let prop_to_set_of_visual_heaps prop =
let result = ref [] in
working_list := [(!global_node_counter, prop.Prop.sigma)] ;
incr global_node_counter ;
while !working_list <> [] do
set_dangling_nodes := [] ;
let n, h = List.hd_exn !working_list in
working_list := List.tl_exn !working_list ;
let nodes = make_visual_heap_nodes h in
set_dangling_nodes := make_set_dangling_nodes nodes h ;
let edges = make_visual_heap_edges nodes h prop in
result := !result @ [(n, nodes @ !set_dangling_nodes, edges)]
done ;
!result
let rec pointsto_contents_to_xml (co: Sil.strexp) : Io_infer.Xml.node =
match co with
| Sil.Eexp (e, _) ->
Io_infer.Xml.create_tree "cell" [("content-value", exp_to_xml_string e)] []
| Sil.Estruct (fel, _) ->
let f (fld, exp) =
Io_infer.Xml.create_tree "struct-field" [("id", Typ.Fieldname.to_string fld)]
[pointsto_contents_to_xml exp]
in
Io_infer.Xml.create_tree "struct" [] (List.map ~f fel)
| Sil.Earray (len, nel, _) ->
let f (e, se) =
Io_infer.Xml.create_tree "array-element" [("index", exp_to_xml_string e)]
[pointsto_contents_to_xml se]
in
Io_infer.Xml.create_tree "array" [("size", exp_to_xml_string len)] (List.map ~f nel)
(* Convert an atom to xml in a light version. Namely, the expressions are not fully blown-up into *)
(* xml tree but visualized as strings *)
let atom_to_xml_light (a: Sil.atom) : Io_infer.Xml.node =
let kind_info =
match a with
| Sil.Aeq _ when Prop.atom_is_inequality a ->
"inequality"
| Sil.Aeq _ ->
"equality"
| Sil.Aneq _ ->
"disequality"
| Sil.Apred _ ->
"pred"
| Sil.Anpred _ ->
"npred"
in
Io_infer.Xml.create_tree "stack-variable"
[("type", kind_info); ("instance", atom_to_xml_string a)] []
let xml_pure_info prop =
let pure = Prop.get_pure prop in
let xml_atom_list = List.map ~f:atom_to_xml_light pure in
Io_infer.Xml.create_tree "stack" [] xml_atom_list
(** Return a string describing the kind of a pointsto address *)
let pointsto_addr_kind = function
| Exp.Lvar pv ->
if Pvar.is_global pv then "global"
else if Pvar.is_local pv && Mangled.equal (Pvar.get_name pv) Ident.name_return then "return"
else if Pvar.is_local pv then "parameter"
else "other"
| _ ->
"other"
let heap_node_to_xml node =
match node with
| VH_dangling (id, addr) ->
let atts =
[ ("id", string_of_int id)
; ("address", exp_to_xml_string addr)
; ("node-type", "dangling")
; ("memory-type", pointsto_addr_kind addr) ]
in
Io_infer.Xml.create_tree "node" atts []
| VH_pointsto (id, addr, cont, _) ->
let atts =
[ ("id", string_of_int id)
; ("address", exp_to_xml_string addr)
; ("node-type", "allocated")
; ("memory-type", pointsto_addr_kind addr) ]
in
let contents = pointsto_contents_to_xml cont in
Io_infer.Xml.create_tree "node" atts [contents]
| VH_lseg (id, addr, _, Sil.Lseg_NE) ->
let atts =
[ ("id", string_of_int id)
; ("address", exp_to_xml_string addr)
; ("node-type", "single linked list")
; ("list-type", "non-empty")
; ("memory-type", "other") ]
in
Io_infer.Xml.create_tree "node" atts []
| VH_lseg (id, addr, _, Sil.Lseg_PE) ->
let atts =
[ ("id", string_of_int id)
; ("address", exp_to_xml_string addr)
; ("node-type", "single linked list")
; ("list-type", "possibly empty")
; ("memory-type", "other") ]
in
Io_infer.Xml.create_tree "node" atts []
| VH_dllseg (id, addr1, cont1, cont2, addr2, _) ->
let contents1 = pointsto_contents_to_xml (Sil.Eexp (cont1, Sil.inst_none)) in
let contents2 = pointsto_contents_to_xml (Sil.Eexp (cont2, Sil.inst_none)) in
let atts =
[ ("id", string_of_int id)
; ("addr-first", exp_to_xml_string addr1)
; ("addr-last", exp_to_xml_string addr2)
; ("node-type", "double linked list")
; ("memory-type", "other") ]
in
Io_infer.Xml.create_tree "node" atts [contents1; contents2]
let heap_edge_to_xml edge =
let atts =
[("source", string_of_int edge.src); ("target", string_of_int edge.trg); ("label", edge.lab)]
in
Io_infer.Xml.create_tree "edge" atts []
let visual_heap_to_xml heap =
let n, nodes, edges = heap in
let xml_heap_nodes = List.map ~f:heap_node_to_xml nodes in
let xml_heap_edges = List.map ~f:heap_edge_to_xml edges in
Io_infer.Xml.create_tree "heap" [("id", string_of_int n)] (xml_heap_nodes @ xml_heap_edges)
(** convert a proposition to xml with the given tag and id *)
let prop_to_xml prop tag_name id =
let visual_heaps = prop_to_set_of_visual_heaps prop in
let xml_visual_heaps = List.map ~f:visual_heap_to_xml visual_heaps in
let xml_pure_part = xml_pure_info prop in
let xml_graph =
Io_infer.Xml.create_tree tag_name [("id", string_of_int id)]
(xml_visual_heaps @ [xml_pure_part])
in
xml_graph
(** reset the counter used for node and heap identifiers *)
let reset_node_counter () = global_node_counter := 0
let print_specs_xml signature specs loc fmt =
reset_node_counter () ;
let do_one_spec pre posts n =
let add_stack_to_prop prop_ =
(* add stack vars from pre *)
let pre_stack = fst (Prop.sigma_get_stack_nonstack true pre.Prop.sigma) in
let prop'_ = Prop.set prop_ ~sigma:(pre_stack @ prop_.Prop.sigma) in
Prop.normalize (Tenv.create ()) prop'_
in
let jj = ref 0 in
let xml_pre = prop_to_xml pre "precondition" !jj in
let xml_spec =
xml_pre
:: List.map
~f:(fun (po, _) ->
jj := !jj + 1 ;
prop_to_xml (add_stack_to_prop po) "postcondition" !jj )
posts
in
Io_infer.Xml.create_tree "specification" [("id", string_of_int n)] xml_spec
in
let j = ref 0 in
let list_of_specs_xml =
List.map
~f:(fun s ->
j := !j + 1 ;
do_one_spec (Specs.Jprop.to_prop s.Specs.pre) s.Specs.posts !j )
specs
in
let xml_specifications = Io_infer.Xml.create_tree "specifications" [] list_of_specs_xml in
let xml_signature = Io_infer.Xml.create_tree "signature" [("name", signature)] [] in
let proc_summary =
Io_infer.Xml.create_tree "procedure"
[("file", SourceFile.to_string loc.Location.file); ("line", string_of_int loc.Location.line)]
[xml_signature; xml_specifications]
in
Io_infer.Xml.pp_document true fmt proc_summary

@ -12,51 +12,14 @@ open! IStd
(** Pretty printing functions in dot format. *) (** Pretty printing functions in dot format. *)
(** {2 Propositions} *)
type kind_of_dotty_prop =
| Generic_proposition
| Spec_precondition
| Spec_postcondition of Prop.normal Prop.t (** the precondition associated with the post *)
| Lambda_pred of int * int * bool
val reset_proposition_counter : unit -> unit
val pp_dotty :
Format.formatter -> kind_of_dotty_prop -> Prop.normal Prop.t
-> ((Sil.strexp * Typ.t) * Typ.Fieldname.t * Sil.strexp) list option -> unit
(** {2 Sets and lists of propositions} *)
val pp_dotty_prop_list_in_path : Format.formatter -> Prop.normal Prop.t list -> int -> int -> unit
val pp_proplist_parsed2dotty_file : string -> Prop.normal Prop.t list -> unit
(** {2 Contol-Flow Graph} *) (** {2 Contol-Flow Graph} *)
val print_icfg_dotty : SourceFile.t -> Cfg.t -> unit val print_icfg_dotty : SourceFile.t -> Cfg.t -> unit
(** Print the cfg *) (** Print the cfg *)
val reset_dotty_spec_counter : unit -> unit
(** {2 Specs} *) (** {2 Specs} *)
val pp_speclist_dotty_file : DB.filename -> Prop.normal Specs.spec list -> unit val pp_speclist_dotty_file : DB.filename -> Prop.normal Specs.spec list -> unit
(** Dotty printing for specs *) (** Dotty printing for specs *)
(* create a dotty file with a single proposition *)
val dotty_prop_to_dotty_file :
string -> Prop.normal Prop.t -> ((Sil.strexp * Typ.t) * Typ.Fieldname.t * Sil.strexp) list
-> unit
val dotty_retain_cycle_to_str : Prop.normal Prop.t -> RetainCyclesType.t -> string option val dotty_retain_cycle_to_str : Prop.normal Prop.t -> RetainCyclesType.t -> string option
val reset_node_counter : unit -> unit
(** reset the counter used for node and heap identifiers *)
val prop_to_xml : Prop.normal Prop.t -> string -> int -> Io_infer.Xml.node
(** convert a proposition to xml with the given tag and id *)
val print_specs_xml :
string -> Prop.normal Specs.spec list -> Location.t -> Format.formatter -> unit
(** Print a list of specs in XML format *)

@ -101,71 +101,6 @@ let find_in_node_or_preds start_node f_node_instr =
find start_node find start_node
(** Find the Set instruction used to assign [id] to a program variable, if any *)
let find_variable_assigment node id : Sil.instr option =
let find_set _ instr =
match instr with
| Sil.Store (Exp.Lvar _, _, e, _) when Exp.equal (Exp.Var id) e ->
Some instr
| _ ->
None
in
find_in_node_or_preds node find_set
(** Check if a nullify instruction exists for the program variable after the given instruction *)
let find_nullify_after_instr node instr pvar : bool =
let node_instrs = Procdesc.Node.get_instrs node in
let found_instr = ref false in
let find_nullify = function
| Sil.Nullify (pv, _) when !found_instr ->
Pvar.equal pv pvar
| instr_ ->
if Sil.equal_instr instr instr_ then found_instr := true ;
false
in
List.exists ~f:find_nullify node_instrs
(** Find the other prune node of a conditional
(e.g. the false branch given the true branch of a conditional) *)
let find_other_prune_node node =
match Procdesc.Node.get_preds node with
| [n_pre] -> (
match Procdesc.Node.get_succs n_pre with
| [n1; n2] ->
if Procdesc.Node.equal n1 node then Some n2 else Some n1
| _ ->
None )
| _ ->
None
(** Return true if [id] is assigned to a program variable which is then nullified *)
let id_is_assigned_then_dead node id =
match find_variable_assigment node id with
| Some (Sil.Store (Exp.Lvar pvar, _, _, _) as instr)
when Pvar.is_local pvar || Pvar.is_callee pvar ->
let is_prune =
match Procdesc.Node.get_kind node with Procdesc.Node.Prune_node _ -> true | _ -> false
in
let prune_check = function
(* if prune node, check that it's also nullified in the other branch *)
| Some node' -> (
match Procdesc.Node.get_instrs node' with
| instr' :: _ ->
find_nullify_after_instr node' instr' pvar
| _ ->
false )
| _ ->
false
in
find_nullify_after_instr node instr pvar
&& (not is_prune || prune_check (find_other_prune_node node))
| _ ->
false
(** Find the function call instruction used to initialize normal variable [id], (** Find the function call instruction used to initialize normal variable [id],
and return the function name and arguments *) and return the function name and arguments *)
let find_normal_variable_funcall (node: Procdesc.Node.t) (id: Ident.t) let find_normal_variable_funcall (node: Procdesc.Node.t) (id: Ident.t)
@ -1126,9 +1061,6 @@ let explain_array_access tenv deref_str prop loc =
explain_access_ tenv ~outermost_array:true deref_str prop loc explain_access_ tenv ~outermost_array:true deref_str prop loc
(** Produce a description of the memory access performed in the current instruction, if any. *)
let explain_memory_access tenv deref_str prop loc = explain_access_ tenv deref_str prop loc
(* offset of an expression found following a program variable *) (* offset of an expression found following a program variable *)
type pvar_off = type pvar_off =
(* value of a pvar *) (* value of a pvar *)
@ -1264,24 +1196,9 @@ let explain_divide_by_zero tenv exp node loc =
Localise.no_desc Localise.no_desc
(** explain a return expression required *)
let explain_return_expression_required loc typ =
let typ_str =
let pp fmt = Typ.pp_full Pp.text fmt typ in
F.asprintf "%t" pp
in
Localise.desc_return_expression_required typ_str loc
(** explain a return statement missing *)
let explain_return_statement_missing loc = Localise.desc_return_statement_missing loc
(** explain a fronend warning *) (** explain a fronend warning *)
let explain_frontend_warning loc = Localise.desc_frontend_warning loc let explain_frontend_warning loc = Localise.desc_frontend_warning loc
(** explain a comparing floats for equality *)
let explain_comparing_floats_for_equality loc = Localise.desc_comparing_floats_for_equality loc
(** explain a condition which is always true or false *) (** explain a condition which is always true or false *)
let explain_condition_always_true_false tenv i cond node loc = let explain_condition_always_true_false tenv i cond node loc =
let cond_str_opt = let cond_str_opt =

@ -16,9 +16,6 @@ val vpath_find : Tenv.t -> 'a Prop.t -> Exp.t -> DecompiledExp.vpath * Typ.t opt
(** find the dexp, if any, where the given value is stored (** find the dexp, if any, where the given value is stored
also return the type of the value if found *) also return the type of the value if found *)
val id_is_assigned_then_dead : Procdesc.Node.t -> Ident.t -> bool
(** Return true if [id] is assigned to a program variable which is then nullified *)
val hpred_is_open_resource : Tenv.t -> 'a Prop.t -> Sil.hpred -> PredSymb.resource option val hpred_is_open_resource : Tenv.t -> 'a Prop.t -> Sil.hpred -> PredSymb.resource option
(** Check whether the hpred is a |-> representing a resource in the Racquire state *) (** Check whether the hpred is a |-> representing a resource in the Racquire state *)
@ -79,12 +76,6 @@ val explain_divide_by_zero :
Tenv.t -> Exp.t -> Procdesc.Node.t -> Location.t -> Localise.error_desc Tenv.t -> Exp.t -> Procdesc.Node.t -> Location.t -> Localise.error_desc
(** explain a division by zero *) (** explain a division by zero *)
val explain_return_expression_required : Location.t -> Typ.t -> Localise.error_desc
(** explain a return expression required *)
val explain_comparing_floats_for_equality : Location.t -> Localise.error_desc
(** explain a comparing floats for equality *)
val explain_condition_always_true_false : val explain_condition_always_true_false :
Tenv.t -> IntLit.t -> Exp.t -> Procdesc.Node.t -> Location.t -> Localise.error_desc Tenv.t -> IntLit.t -> Exp.t -> Procdesc.Node.t -> Location.t -> Localise.error_desc
(** explain a condition which is always true or false *) (** explain a condition which is always true or false *)
@ -98,9 +89,6 @@ val explain_stack_variable_address_escape :
val explain_frontend_warning : string -> string option -> Location.t -> Localise.error_desc val explain_frontend_warning : string -> string option -> Location.t -> Localise.error_desc
(** explain frontend warning *) (** explain frontend warning *)
val explain_return_statement_missing : Location.t -> Localise.error_desc
(** explain a return statement missing *)
val explain_unary_minus_applied_to_unsigned_expression : val explain_unary_minus_applied_to_unsigned_expression :
Tenv.t -> Exp.t -> Typ.t -> Procdesc.Node.t -> Location.t -> Localise.error_desc Tenv.t -> Exp.t -> Typ.t -> Procdesc.Node.t -> Location.t -> Localise.error_desc
(** explain unary minus applied to unsigned expression *) (** explain unary minus applied to unsigned expression *)
@ -113,10 +101,6 @@ val explain_leak :
If it is an abstraction, blame any variable nullify at the current node. If it is an abstraction, blame any variable nullify at the current node.
If there is an alloc attribute, print the function call and line number. *) If there is an alloc attribute, print the function call and line number. *)
val explain_memory_access :
Typ.Procname.t -> Tenv.t -> Localise.deref_str -> 'a Prop.t -> Location.t -> Localise.error_desc
(** Produce a description of the memory access performed in the current instruction, if any. *)
val explain_null_test_after_dereference : val explain_null_test_after_dereference :
Tenv.t -> Exp.t -> Procdesc.Node.t -> int -> Location.t -> Localise.error_desc Tenv.t -> Exp.t -> Procdesc.Node.t -> int -> Location.t -> Localise.error_desc
(** explain a test for NULL of a dereferenced pointer *) (** explain a test for NULL of a dereferenced pointer *)
@ -124,16 +108,6 @@ val explain_null_test_after_dereference :
val warning_err : Location.t -> ('a, Format.formatter, unit) format -> 'a val warning_err : Location.t -> ('a, Format.formatter, unit) format -> 'a
(** warn at the given location *) (** warn at the given location *)
(* offset of an expression found following a program variable *)
type pvar_off = Fpvar (* value of a pvar *)
| Fstruct of Typ.Fieldname.t list
(* value obtained by dereferencing the pvar and following a sequence of fields *)
val find_with_exp : 'a Prop.t -> Exp.t -> (Pvar.t * pvar_off) option
(** Find a program variable whose value is [exp] or pointing to a struct containing [exp] *)
val find_outermost_dereference : Tenv.t -> Procdesc.Node.t -> Exp.t -> DecompiledExp.t option val find_outermost_dereference : Tenv.t -> Procdesc.Node.t -> Exp.t -> DecompiledExp.t option
val access_opt : ?is_nullable:bool -> Sil.inst -> Localise.access option val access_opt : ?is_nullable:bool -> Sil.inst -> Localise.access option

@ -67,9 +67,6 @@ type t =
; file_map: file_data FilenameHash.t (** map from cg fname to file data *) ; file_map: file_data FilenameHash.t (** map from cg fname to file data *)
; source_file: SourceFile.t (** source file being analyzed *) } ; source_file: SourceFile.t (** source file being analyzed *) }
(** initial state, used to add cg's *)
type initial = t
(** add call graph from fname in the spec db, (** add call graph from fname in the spec db,
with relative tenv and cfg, to the execution environment *) with relative tenv and cfg, to the execution environment *)
let add_cg exe_env source = let add_cg exe_env source =
@ -126,11 +123,6 @@ let get_file_data exe_env pname =
Option.map ~f:get_file_data_for_source source_file_opt Option.map ~f:get_file_data_for_source source_file_opt
(** return the source file associated to the procedure *)
let get_source exe_env pname =
Option.map ~f:(fun file_data -> file_data.source) (get_file_data exe_env pname)
let file_data_to_tenv file_data = let file_data_to_tenv file_data =
if is_none file_data.tenv then file_data.tenv <- Tenv.load_from_file file_data.tenv_file ; if is_none file_data.tenv then file_data.tenv <- Tenv.load_from_file file_data.tenv_file ;
file_data.tenv file_data.tenv

@ -12,9 +12,6 @@ open! IStd
(** Support for Execution environments *) (** Support for Execution environments *)
(** initial state, used to add cg's *)
type initial
(** execution environment: a global call graph, and map from procedure names to cfg and tenv *) (** execution environment: a global call graph, and map from procedure names to cfg and tenv *)
type t type t
@ -24,9 +21,6 @@ val mk : SourceFile.t -> t
val get_cg : t -> Cg.t val get_cg : t -> Cg.t
(** get the global call graph *) (** get the global call graph *)
val get_source : t -> Typ.Procname.t -> SourceFile.t option
(** return the source file associated to the procedure *)
val get_tenv : t -> Typ.Procname.t -> Tenv.t val get_tenv : t -> Typ.Procname.t -> Tenv.t
(** return the type environment associated to the procedure *) (** return the type environment associated to the procedure *)

@ -20,9 +20,6 @@ type proc_filter = Typ.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 do_not_filter : filters
(** Filters that accept everything. *)
val create_filters : Config.analyzer -> filters val create_filters : Config.analyzer -> filters
(** Create filters based on the config file *) (** Create filters based on the config file *)

@ -22,17 +22,6 @@ let mem_idlist i l = List.exists ~f:(Ident.equal i) l
considered during pattern matching *) considered during pattern matching *)
type hpred_pat = {hpred: Sil.hpred; flag: bool} type hpred_pat = {hpred: Sil.hpred; flag: bool}
let pp_hpat pe f hpat = F.fprintf f "%a" (Sil.pp_hpred pe) hpat.hpred
let rec pp_hpat_list pe f = function
| [] ->
()
| [hpat] ->
F.fprintf f "%a" (pp_hpat pe) hpat
| hpat :: hpats ->
F.fprintf f "%a * %a" (pp_hpat pe) hpat (pp_hpat_list pe) hpats
(** Checks e1 = e2[sub ++ sub'] for some sub' with dom(sub') subseteq vars. (** Checks e1 = e2[sub ++ sub'] for some sub' with dom(sub') subseteq vars.
Returns (sub ++ sub', vars - dom(sub')). *) Returns (sub ++ sub', vars - dom(sub')). *)
let rec exp_match e1 sub vars e2 : (Sil.exp_subst * Ident.t list) option = let rec exp_match e1 sub vars e2 : (Sil.exp_subst * Ident.t list) option =
@ -823,25 +812,6 @@ let find_partial_iso tenv eq corres todos sigma =
generic_find_partial_iso tenv Exact update corres init_sigma_corres todos init_sigma_todo generic_find_partial_iso tenv Exact update corres init_sigma_corres todos init_sigma_todo
(** [find_partial_iso_from_two_sigmas] finds isomorphic sub-sigmas inside two
given sigmas. The function returns a partial iso and four sigmas. The first
sigma is the first copy of the two isomorphic sigmas, so it uses expressions in the domain of
the returned isomorphism. The second is the second copy of the two isomorphic sigmas,
and it uses expressions in the range of the isomorphism. The third and fourth
are the unused parts of the two input sigmas. *)
let find_partial_iso_from_two_sigmas tenv mode eq corres todos sigma1 sigma2 =
let update e1 e2 sigma_todo =
let sigma_todo1, sigma_todo2 = sigma_todo in
let hpredo1, sigma_todo1_no_e1 = sigma_remove_hpred eq sigma_todo1 e1 in
let hpredo2, sigma_todo2_no_e2 = sigma_remove_hpred eq sigma_todo2 e2 in
let new_sigma_todo = (sigma_todo1_no_e1, sigma_todo2_no_e2) in
(hpredo1, hpredo2, new_sigma_todo)
in
let init_sigma_corres = ([], []) in
let init_sigma_todo = (sigma1, sigma2) in
generic_find_partial_iso tenv mode update corres init_sigma_corres todos init_sigma_todo
(** Lift the kind of list segment predicates to PE *) (** Lift the kind of list segment predicates to PE *)
let hpred_lift_to_pe hpred = let hpred_lift_to_pe hpred =
match hpred with match hpred with

@ -27,10 +27,6 @@ val hpara_dll_match_with_impl : Tenv.t -> bool -> Sil.hpara_dll -> Sil.hpara_dll
considered during pattern matching. *) considered during pattern matching. *)
type hpred_pat = {hpred: Sil.hpred; flag: bool} type hpred_pat = {hpred: Sil.hpred; flag: bool}
val pp_hpat : Pp.env -> Format.formatter -> hpred_pat -> unit
val pp_hpat_list : Pp.env -> Format.formatter -> hpred_pat list -> unit
type sidecondition = Prop.normal Prop.t -> Sil.exp_subst -> bool type sidecondition = Prop.normal Prop.t -> Sil.exp_subst -> bool
val prop_match_with_impl : val prop_match_with_impl :
@ -54,22 +50,6 @@ val find_partial_iso :
and it uses expressions in the range of the isomorphism. The third is the unused and it uses expressions in the range of the isomorphism. The third is the unused
part of the input sigma. *) part of the input sigma. *)
(** This mode expresses the flexibility allowed during the isomorphism check *)
type iso_mode = Exact | LFieldForget | RFieldForget
val find_partial_iso_from_two_sigmas :
Tenv.t -> iso_mode -> (Exp.t -> Exp.t -> bool) -> (Exp.t * Exp.t) list -> (Exp.t * Exp.t) list
-> Sil.hpred list -> Sil.hpred list
-> ((Exp.t * Exp.t) list * Sil.hpred list * Sil.hpred list * (Sil.hpred list * Sil.hpred list))
option
(** [find_partial_iso_from_two_sigmas] finds isomorphic sub-sigmas inside two
given sigmas. The second argument is an equality checker.
The function returns a partial iso and four sigmas. The first
sigma is the first copy of the two isomorphic sigmas, so it uses expressions in the domain of
the returned isomorphism. The second is the second copy of the two isomorphic sigmas,
and it uses expressions in the range of the isomorphism. The third and fourth
are the unused parts of the two input sigmas. *)
val hpara_iso : Tenv.t -> Sil.hpara -> Sil.hpara -> bool val hpara_iso : Tenv.t -> Sil.hpara -> Sil.hpara -> bool
(** [hpara_iso] soundly checks whether two hparas are isomorphic. *) (** [hpara_iso] soundly checks whether two hparas are isomorphic. *)

@ -30,9 +30,6 @@ val analyze_proc_name : Procdesc.t -> Typ.Procname.t -> Specs.summary option
performs an on-demand analysis of proc_name performs an on-demand analysis of proc_name
triggered during the analysis of curr_pdesc. *) triggered during the analysis of curr_pdesc. *)
val procedure_should_be_analyzed : Typ.Procname.t -> bool
(** Check if the procedure called needs to be analyzed. *)
val set_callbacks : callbacks -> unit val set_callbacks : callbacks -> unit
(** Set the callbacks used to perform on-demand analysis. *) (** Set the callbacks used to perform on-demand analysis. *)

@ -29,9 +29,6 @@ module Path : sig
val add_skipped_call : t -> Typ.Procname.t -> string -> Location.t option -> t val add_skipped_call : t -> Typ.Procname.t -> string -> Location.t option -> t
(** add a call to a procname that's had to be skipped, along with the reason and the location of the procname when known *) (** add a call to a procname that's had to be skipped, along with the reason and the location of the procname when known *)
val contains : t -> t -> bool
(** check whether a path contains another path *)
val contains_position : t -> PredSymb.path_pos -> bool val contains_position : t -> PredSymb.path_pos -> bool
(** check wether the path contains the given position *) (** check wether the path contains the given position *)
@ -454,14 +451,6 @@ end = struct
let d p = L.add_print_action (L.PTpath, Obj.repr p) let d p = L.add_print_action (L.PTpath, Obj.repr p)
let rec contains p1 p2 =
match p2 with
| Pjoin (p2', p2'', _) ->
contains p1 p2' || contains p1 p2''
| _ ->
phys_equal p1 p2
let create_loc_trace path pos_opt : Errlog.loc_trace = let create_loc_trace path pos_opt : Errlog.loc_trace =
let trace = ref [] in let trace = ref [] in
let g level path _ exn_opt = let g level path _ exn_opt =
@ -579,12 +568,6 @@ module PathSet : sig
val equal : t -> t -> bool val equal : t -> t -> bool
(** equality for pathsets *) (** equality for pathsets *)
val filter : (Prop.normal Prop.t -> bool) -> t -> t
(** filter a pathset on the prop component *)
val filter_path : Path.t -> t -> Prop.normal Prop.t list
(** find the list of props whose associated path contains the given path *)
val fold : (Prop.normal Prop.t -> Path.t -> 'a -> 'a) -> t -> 'a -> 'a val fold : (Prop.normal Prop.t -> Path.t -> 'a -> 'a) -> t -> 'a -> 'a
(** fold over a pathset *) (** fold over a pathset *)
@ -639,15 +622,6 @@ end = struct
let to_propset tenv ps = Propset.from_proplist tenv (to_proplist ps) let to_propset tenv ps = Propset.from_proplist tenv (to_proplist ps)
let filter f ps =
let elements = ref [] in
PropMap.iter (fun p _ -> elements := p :: !elements) ps ;
elements := List.filter ~f:(fun p -> not (f p)) !elements ;
let filtered_map = ref ps in
List.iter ~f:(fun p -> filtered_map := PropMap.remove p !filtered_map) !elements ;
!filtered_map
let partition f ps = let partition f ps =
let elements = ref [] in let elements = ref [] in
PropMap.iter (fun p _ -> elements := p :: !elements) ps ; PropMap.iter (fun p _ -> elements := p :: !elements) ps ;
@ -729,12 +703,6 @@ end = struct
let d (ps: t) = L.add_print_action (L.PTpathset, Obj.repr ps) let d (ps: t) = L.add_print_action (L.PTpathset, Obj.repr ps)
let filter_path path ps =
let plist = ref [] in
let f prop path' = if Path.contains path path' then plist := prop :: !plist in
iter f ps ; !plist
(** It's the caller's resposibility to ensure that Prop.prop_rename_primed_footprint_vars was called on the list *) (** It's the caller's resposibility to ensure that Prop.prop_rename_primed_footprint_vars was called on the list *)
let from_renamed_list (pl: ('a Prop.t * Path.t) list) : t = let from_renamed_list (pl: ('a Prop.t * Path.t) list) : t =
List.fold ~f:(fun ps (p, pa) -> add_renamed_prop p pa ps) ~init:empty pl List.fold ~f:(fun ps (p, pa) -> add_renamed_prop p pa ps) ~init:empty pl

@ -24,9 +24,6 @@ module Path : sig
val add_skipped_call : t -> Typ.Procname.t -> string -> Location.t option -> t val add_skipped_call : t -> Typ.Procname.t -> string -> Location.t option -> t
(** add a call to a procname that's had to be skipped, along with the reason and the location of the procname when known *) (** add a call to a procname that's had to be skipped, along with the reason and the location of the procname when known *)
val contains : t -> t -> bool
(** check whether a path contains another path *)
val contains_position : t -> PredSymb.path_pos -> bool val contains_position : t -> PredSymb.path_pos -> bool
(** check wether the path contains the given position *) (** check wether the path contains the given position *)
@ -36,10 +33,10 @@ module Path : sig
val curr_node : t -> Procdesc.Node.t option val curr_node : t -> Procdesc.Node.t option
(** return the current node of the path *) (** return the current node of the path *)
val d : t -> unit val d : t -> unit [@@warning "-32"]
(** dump a path *) (** dump a path *)
val d_stats : t -> unit val d_stats : t -> unit [@@warning "-32"]
(** dump statistics of the path *) (** dump statistics of the path *)
val extend : Procdesc.Node.t -> Typ.Name.t option -> session -> t -> t val extend : Procdesc.Node.t -> Typ.Name.t option -> session -> t -> t
@ -65,6 +62,7 @@ module Path : sig
(** pretty print a path *) (** pretty print a path *)
val pp_stats : Format.formatter -> t -> unit val pp_stats : Format.formatter -> t -> unit
[@@warning "-32"]
(** pretty print statistics of the path *) (** pretty print statistics of the path *)
val start : Procdesc.Node.t -> t val start : Procdesc.Node.t -> t
@ -78,7 +76,7 @@ module PathSet : sig
val add_renamed_prop : Prop.normal Prop.t -> Path.t -> t -> t val add_renamed_prop : Prop.normal Prop.t -> Path.t -> t -> t
(** It's the caller's resposibility to ensure that Prop.prop_rename_primed_footprint_vars was called on the prop *) (** It's the caller's resposibility to ensure that Prop.prop_rename_primed_footprint_vars was called on the prop *)
val d : t -> unit val d : t -> unit [@@warning "-32"]
(** dump the pathset *) (** dump the pathset *)
val diff : t -> t -> t val diff : t -> t -> t
@ -93,12 +91,6 @@ module PathSet : sig
val equal : t -> t -> bool val equal : t -> t -> bool
(** equality for pathsets *) (** equality for pathsets *)
val filter : (Prop.normal Prop.t -> bool) -> t -> t
(** filter a pathset on the prop component *)
val filter_path : Path.t -> t -> Prop.normal Prop.t list
(** find the list of props whose associated path contains the given path *)
val fold : (Prop.normal Prop.t -> Path.t -> 'a -> 'a) -> t -> 'a -> 'a val fold : (Prop.normal Prop.t -> Path.t -> 'a -> 'a) -> t -> 'a -> 'a
(** fold over a pathset *) (** fold over a pathset *)

@ -23,9 +23,6 @@ module LineReader : sig
val from_file_linenum_original : t -> SourceFile.t -> int -> string option val from_file_linenum_original : t -> SourceFile.t -> int -> string option
(** get the line from a source file and line number *) (** get the line from a source file and line number *)
val from_file_linenum : t -> SourceFile.t -> int -> string option
(** get the line from a source file and line number looking for the copy of the file in the results dir *)
val from_loc : t -> Location.t -> string option val from_loc : t -> Location.t -> string option
(** get the line from a location looking for the copy of the file in the results dir *) (** get the line from a location looking for the copy of the file in the results dir *)
end end
@ -39,9 +36,6 @@ val force_delayed_prints : unit -> unit
val node_finish_session : Procdesc.Node.t -> unit val node_finish_session : Procdesc.Node.t -> unit
(** Finish a session, and perform delayed print actions if required *) (** Finish a session, and perform delayed print actions if required *)
val node_is_visited : Procdesc.Node.t -> bool * bool
(** Return true if the node was visited during footprint and during re-execution *)
val node_start_session : Procdesc.Node.t -> int -> unit val node_start_session : Procdesc.Node.t -> int -> unit
(** Start a session, and create a new html fine for the node if it does not exist yet *) (** Start a session, and create a new html fine for the node if it does not exist yet *)

@ -95,9 +95,6 @@ include Core
(** Comparison between propositions. Lexicographical order. *) (** Comparison between propositions. Lexicographical order. *)
let compare_prop p1 p2 = compare (fun _ _ -> 0) p1 p2 let compare_prop p1 p2 = compare (fun _ _ -> 0) p1 p2
(** Check the equality of two propositions *)
let equal_prop p1 p2 = Int.equal (compare_prop p1 p2) 0
(** {1 Functions for Pretty Printing} *) (** {1 Functions for Pretty Printing} *)
(** Pretty print a footprint. *) (** Pretty print a footprint. *)
@ -343,9 +340,6 @@ let pp_prop_with_typ pe f p = pp_prop {pe with opt= SIM_WITH_TYP} f p
(** Dump a proposition. *) (** Dump a proposition. *)
let d_prop (prop: 'a t) = L.add_print_action (PTprop, Obj.repr prop) let d_prop (prop: 'a t) = L.add_print_action (PTprop, Obj.repr prop)
(** Dump a proposition. *)
let d_prop_with_typ (prop: 'a t) = L.add_print_action (PTprop_with_typ, Obj.repr prop)
(** Print a list of propositions, prepending each one with the given string *) (** Print a list of propositions, prepending each one with the given string *)
let pp_proplist_with_typ pe f plist = let pp_proplist_with_typ pe f plist =
let rec pp_seq_newline f = function let rec pp_seq_newline f = function
@ -1738,22 +1732,10 @@ let atom_normalize_prop tenv prop atom =
Config.run_with_abs_val_equal_zero (Normalize.atom_normalize tenv (`Exp prop.sub)) atom Config.run_with_abs_val_equal_zero (Normalize.atom_normalize tenv (`Exp prop.sub)) atom
let strexp_normalize_prop tenv prop strexp =
Config.run_with_abs_val_equal_zero (Normalize.strexp_normalize tenv (`Exp prop.sub)) strexp
let hpred_normalize_prop tenv prop hpred =
Config.run_with_abs_val_equal_zero (Normalize.hpred_normalize tenv (`Exp prop.sub)) hpred
let sigma_normalize_prop tenv prop sigma = let sigma_normalize_prop tenv prop sigma =
Config.run_with_abs_val_equal_zero (Normalize.sigma_normalize tenv (`Exp prop.sub)) sigma Config.run_with_abs_val_equal_zero (Normalize.sigma_normalize tenv (`Exp prop.sub)) sigma
let pi_normalize_prop tenv prop pi =
Config.run_with_abs_val_equal_zero (Normalize.pi_normalize tenv (`Exp prop.sub) prop.sigma) pi
let sigma_replace_exp tenv epairs sigma = let sigma_replace_exp tenv epairs sigma =
let sigma' = List.map ~f:(Sil.hpred_replace_exp epairs) sigma in let sigma' = List.map ~f:(Sil.hpred_replace_exp epairs) sigma in
Normalize.sigma_normalize tenv Sil.sub_empty sigma' Normalize.sigma_normalize tenv Sil.sub_empty sigma'
@ -1790,20 +1772,6 @@ let mk_dllseg tenv k para exp_iF exp_oB exp_oF exp_iB exps_shared : Sil.hpred =
Hdllseg (k, npara, exp_iF, exp_oB, exp_oF, exp_iB, exps_shared) Hdllseg (k, npara, exp_iF, exp_oB, exp_oF, exp_iB, exps_shared)
(** Exp.Construct a hpara *)
let mk_hpara tenv root next svars evars body =
let para = {Sil.root; next; svars; evars; body} in
Normalize.hpara_normalize tenv para
(** Exp.Construct a dll_hpara *)
let mk_dll_hpara tenv iF oB oF svars evars body =
let para =
{Sil.cell= iF; blink= oB; flink= oF; svars_dll= svars; evars_dll= evars; body_dll= body}
in
Normalize.hpara_dll_normalize tenv para
(** Construct a points-to predicate for a single program variable. (** Construct a points-to predicate for a single program variable.
If [expand_structs] is [Fld_init], initialize the fields of structs with fresh variables. *) If [expand_structs] is [Fld_init], initialize the fields of structs with fresh variables. *)
let mk_ptsto_lvar tenv expand_structs inst ((pvar: Pvar.t), texp, expo) : Sil.hpred = let mk_ptsto_lvar tenv expand_structs inst ((pvar: Pvar.t), texp, expo) : Sil.hpred =
@ -1843,14 +1811,6 @@ let extract_spec (p: normal t) : normal t * normal t =
(unsafe_cast_to_normal pre, unsafe_cast_to_normal post) (unsafe_cast_to_normal pre, unsafe_cast_to_normal post)
(** [prop_set_fooprint p p_foot] sets proposition [p_foot] as footprint of [p]. *)
let prop_set_footprint p p_foot =
let pi =
List.map ~f:(fun (i, e) -> Sil.Aeq (Var i, e)) (Sil.sub_to_list p_foot.sub) @ p_foot.pi
in
set p ~pi_fp:pi ~sigma_fp:p_foot.sigma
(** {2 Functions for renaming primed variables by "canonical names"} *) (** {2 Functions for renaming primed variables by "canonical names"} *)
module ExpStack : sig module ExpStack : sig
@ -2434,14 +2394,6 @@ let prop_iter_next iter =
pit_old= iter.pit_curr :: iter.pit_old; pit_curr= hpred'; pit_state= (); pit_new= new' } pit_old= iter.pit_curr :: iter.pit_old; pit_curr= hpred'; pit_state= (); pit_new= new' }
let prop_iter_remove_curr_then_next iter =
match iter.pit_new with
| [] ->
None
| hpred' :: new' ->
Some {iter with pit_old= iter.pit_old; pit_curr= hpred'; pit_state= (); pit_new= new'}
(** Insert before the current element of the iterator. *) (** Insert before the current element of the iterator. *)
let prop_iter_prev_then_insert iter hpred = let prop_iter_prev_then_insert iter hpred =
{iter with pit_new= iter.pit_curr :: iter.pit_new; pit_curr= hpred} {iter with pit_new= iter.pit_curr :: iter.pit_new; pit_curr= hpred}
@ -2621,15 +2573,11 @@ let prop_expand prop =
(*** START of module Metrics ***) (*** START of module Metrics ***)
module Metrics : sig module Metrics : sig
val prop_size : 'a t -> int val prop_size : 'a t -> int
val prop_chain_size : 'a t -> int
end = struct end = struct
let ptsto_weight = 1 let ptsto_weight = 1
and lseg_weight = 3 and lseg_weight = 3
and pi_weight = 1
let rec hpara_size hpara = sigma_size hpara.Sil.body let rec hpara_size hpara = sigma_size hpara.Sil.body
and hpara_dll_size hpara_dll = sigma_size hpara_dll.Sil.body_dll and hpara_dll_size hpara_dll = sigma_size hpara_dll.Sil.body_dll
@ -2650,22 +2598,12 @@ end = struct
!size !size
let pi_size pi = pi_weight * List.length pi
(** Compute a size value for the prop, which indicates its (** Compute a size value for the prop, which indicates its
complexity *) complexity *)
let prop_size p = let prop_size p =
let size_current = sigma_size p.sigma in let size_current = sigma_size p.sigma in
let size_footprint = sigma_size p.sigma_fp in let size_footprint = sigma_size p.sigma_fp in
max size_current size_footprint max size_current size_footprint
(** Approximate the size of the longest chain by counting the max
number of |-> with the same type and whose lhs is primed or
footprint *)
let prop_chain_size p =
let fp_size = pi_size p.pi_fp + sigma_size p.sigma_fp in
pi_size p.pi + sigma_size p.sigma + fp_size
end end
(*** END of module Metrics ***) (*** END of module Metrics ***)

@ -48,9 +48,6 @@ val compare_prop : 'a t -> 'a t -> int
val equal_sigma : sigma -> sigma -> bool val equal_sigma : sigma -> sigma -> bool
(** Check the equality of two sigma's *) (** Check the equality of two sigma's *)
val equal_prop : 'a t -> 'a t -> bool
(** Check the equality of two propositions *)
val pp_sub : Pp.env -> Format.formatter -> subst -> unit val pp_sub : Pp.env -> Format.formatter -> subst -> unit
(** Pretty print a substitution. *) (** Pretty print a substitution. *)
@ -91,9 +88,6 @@ val prop_pred_env : 'a t -> Sil.Predicates.env
val d_prop : 'a t -> unit val d_prop : 'a t -> unit
(** Dump a proposition. *) (** Dump a proposition. *)
val d_prop_with_typ : 'a t -> unit
(** Dump a proposition with type information *)
val pp_proplist_with_typ : Pp.env -> Format.formatter -> normal t list -> unit val pp_proplist_with_typ : Pp.env -> Format.formatter -> normal t list -> unit
(** Pretty print a list propositions with type information *) (** Pretty print a list propositions with type information *)
@ -179,14 +173,8 @@ val lexp_normalize_prop : Tenv.t -> 'a t -> Exp.t -> Exp.t
val atom_normalize_prop : Tenv.t -> 'a t -> atom -> atom val atom_normalize_prop : Tenv.t -> 'a t -> atom -> atom
val strexp_normalize_prop : Tenv.t -> 'a t -> strexp -> strexp
val hpred_normalize_prop : Tenv.t -> 'a t -> hpred -> hpred
val sigma_normalize_prop : Tenv.t -> 'a t -> hpred list -> hpred list val sigma_normalize_prop : Tenv.t -> 'a t -> hpred list -> hpred list
val pi_normalize_prop : Tenv.t -> 'a t -> atom list -> atom list
val normalize : Tenv.t -> exposed t -> normal t val normalize : Tenv.t -> exposed t -> normal t
(** normalize a prop *) (** normalize a prop *)
@ -240,14 +228,6 @@ val mk_dllseg :
Tenv.t -> lseg_kind -> hpara_dll -> Exp.t -> Exp.t -> Exp.t -> Exp.t -> Exp.t list -> hpred Tenv.t -> lseg_kind -> hpara_dll -> Exp.t -> Exp.t -> Exp.t -> Exp.t -> Exp.t list -> hpred
(** Construct a dllseg predicate *) (** Construct a dllseg predicate *)
val mk_hpara : Tenv.t -> Ident.t -> Ident.t -> Ident.t list -> Ident.t list -> hpred list -> hpara
(** Construct a hpara *)
val mk_dll_hpara :
Tenv.t -> Ident.t -> Ident.t -> Ident.t -> Ident.t list -> Ident.t list -> hpred list
-> hpara_dll
(** Construct a dll_hpara *)
val prop_emp : normal t val prop_emp : normal t
(** Proposition [true /\ emp]. *) (** Proposition [true /\ emp]. *)
@ -281,9 +261,6 @@ val extract_footprint : 'a t -> exposed t
val extract_spec : normal t -> normal t * normal t val extract_spec : normal t -> normal t * normal t
(** Extract the (footprint,current) pair *) (** Extract the (footprint,current) pair *)
val prop_set_footprint : 'a t -> 'b t -> exposed t
(** [prop_set_fooprint p p_foot] sets proposition [p_foot] as footprint of [p]. *)
val prop_expand : Tenv.t -> normal t -> normal t list val prop_expand : Tenv.t -> normal t -> normal t list
(** Expand PE listsegs if the flag is on. *) (** Expand PE listsegs if the flag is on. *)
@ -340,9 +317,6 @@ val prop_iter_current : Tenv.t -> 'a prop_iter -> hpred * 'a
val prop_iter_next : 'a prop_iter -> unit prop_iter option val prop_iter_next : 'a prop_iter -> unit prop_iter option
(** Return the next iterator. *) (** Return the next iterator. *)
val prop_iter_remove_curr_then_next : 'a prop_iter -> unit prop_iter option
(** Remove the current hpred and return the next iterator. *)
val prop_iter_update_current : 'a prop_iter -> hpred -> 'a prop_iter val prop_iter_update_current : 'a prop_iter -> hpred -> 'a prop_iter
(** Update the current element of the iterator. *) (** Update the current element of the iterator. *)
@ -379,9 +353,6 @@ val prop_iter_gc_fields : unit prop_iter -> unit prop_iter
val strexp_get_exps : Sil.strexp -> Exp.Set.t val strexp_get_exps : Sil.strexp -> Exp.Set.t
(** return the set of subexpressions of [strexp] *) (** return the set of subexpressions of [strexp] *)
val hpred_get_targets : Sil.hpred -> Exp.Set.t
(** get the set of expressions on the righthand side of [hpred] *)
val compute_reachable_hpreds : hpred list -> Exp.Set.t -> Sil.HpredSet.t * Exp.Set.t val compute_reachable_hpreds : hpred list -> Exp.Set.t -> Sil.HpredSet.t * Exp.Set.t
(** return the set of hpred's and exp's in [sigma] that are reachable from an expression in (** return the set of hpred's and exp's in [sigma] that are reachable from an expression in
[exps] *) [exps] *)
@ -391,11 +362,6 @@ val compute_reachable_hpreds : hpred list -> Exp.Set.t -> Sil.HpredSet.t * Exp.S
module Metrics : sig module Metrics : sig
val prop_size : 'a t -> int val prop_size : 'a t -> int
(** Compute a size value for the prop, which indicates its complexity *) (** Compute a size value for the prop, which indicates its complexity *)
val prop_chain_size : 'a t -> int
(** Approximate the size of the longest chain by counting the max
number of |-> with the same type and whose lhs is primed or
footprint *)
end end
module CategorizePreconditions : sig module CategorizePreconditions : sig

@ -17,31 +17,12 @@ module L = Logging
type t = Prop.normal Prop.t type t = Prop.normal Prop.t
type node = Exp.t
type sub_entry = Ident.t * Exp.t type sub_entry = Ident.t * Exp.t
type edge = Ehpred of Sil.hpred | Eatom of Sil.atom | Esub_entry of sub_entry type edge = Ehpred of Sil.hpred | Eatom of Sil.atom | Esub_entry of sub_entry
let from_prop p = p let from_prop p = p
(** Return [true] if root node *)
let rec is_root = function
| Exp.Var id ->
Ident.is_normal id
| Exp.Exn _ | Exp.Closure _ | Exp.Const _ | Exp.Lvar _ ->
true
| Exp.Cast (_, e) ->
is_root e
| Exp.UnOp _ | Exp.BinOp _ | Exp.Lfield _ | Exp.Lindex _ | Exp.Sizeof _ ->
false
(** Return [true] if the nodes are connected. Used to compute reachability. *)
let nodes_connected n1 n2 = Exp.equal n1 n2
(* Implemented as equality for now, later it might contain offset by a constant *)
(** Return [true] if the edge is an hpred, and [false] if it is an atom *) (** Return [true] if the edge is an hpred, and [false] if it is an atom *)
let edge_is_hpred = function Ehpred _ -> true | Eatom _ -> false | Esub_entry _ -> false let edge_is_hpred = function Ehpred _ -> true | Eatom _ -> false | Esub_entry _ -> false
@ -65,20 +46,6 @@ let edge_get_source = function
Some (Exp.Var x) Some (Exp.Var x)
(** Return the successor nodes of the edge *)
let edge_get_succs = function
| Ehpred hpred ->
Exp.Set.elements (Prop.hpred_get_targets hpred)
| Eatom Sil.Aeq (_, e2) ->
[e2]
| Eatom Sil.Aneq (_, e2) ->
[e2]
| Eatom (Sil.Apred _ | Anpred _) ->
[]
| Esub_entry (_, e) ->
[e]
let get_sigma footprint_part g = if footprint_part then g.Prop.sigma_fp else g.Prop.sigma let get_sigma footprint_part g = if footprint_part then g.Prop.sigma_fp else g.Prop.sigma
let get_pi footprint_part g = if footprint_part then g.Prop.pi_fp else g.Prop.pi let get_pi footprint_part g = if footprint_part then g.Prop.pi_fp else g.Prop.pi
@ -100,12 +67,6 @@ let edge_from_source g n footprint_part is_hpred =
match List.filter ~f:starts_from edges with [] -> None | edge :: _ -> Some edge match List.filter ~f:starts_from edges with [] -> None | edge :: _ -> Some edge
(** [get_succs g n footprint_part is_hpred] returns the successor nodes of [n] in [g].
[footprint_part] indicates whether to search the successors in the footprint part, and [is_pred] whether to follow hpred edges. *)
let get_succs g n footprint_part is_hpred =
match edge_from_source g n footprint_part is_hpred with None -> [] | Some e -> edge_get_succs e
(** [get_edges footprint_part g] returns the list of edges in [g], in the footprint part if [fotprint_part] is true *) (** [get_edges footprint_part g] returns the list of edges in [g], in the footprint part if [fotprint_part] is true *)
let get_edges footprint_part g = let get_edges footprint_part g =
let hpreds = get_sigma footprint_part g in let hpreds = get_sigma footprint_part g in
@ -133,10 +94,6 @@ let contains_edge (footprint_part: bool) (g: t) (e: edge) =
List.exists ~f:(fun e' -> edge_equal e e') (get_edges footprint_part g) List.exists ~f:(fun e' -> edge_equal e e') (get_edges footprint_part g)
(** [iter_edges footprint_part f g] iterates function [f] on the edges in [g] in the same order as returned by [get_edges];
if [footprint_part] is true the edges are taken from the footprint part. *)
let iter_edges footprint_part f g = List.iter ~f (get_edges footprint_part g)
(** Graph annotated with the differences w.r.t. a previous graph *) (** Graph annotated with the differences w.r.t. a previous graph *)
type diff = type diff =
{ diff_newgraph: t (** the new graph *) { diff_newgraph: t (** the new graph *)

@ -15,51 +15,9 @@ open! IStd
(** prop considered as a graph *) (** prop considered as a graph *)
type t type t
(** node of the graph *)
type node
(** multi-edge: one source and many destinations *)
type edge
val from_prop : Prop.normal Prop.t -> t val from_prop : Prop.normal Prop.t -> t
(** create a graph from a prop *) (** create a graph from a prop *)
val is_root : node -> bool
(** Return [true] if root node *)
val nodes_connected : node -> node -> bool
(** Return [true] if the nodes are connected. Used to compute reachability. *)
val edge_get_source : edge -> node option
(** Return the source of the edge *)
val edge_get_succs : edge -> node list
(** Return the successor nodes of the edge *)
val edge_from_source : t -> node -> bool -> bool -> edge option
(** [edge_from_source g n footprint_part is_hpred] finds and edge
with the given source [n] in prop [g].
[footprint_part] indicates whether to search the edge in the footprint part,
and [is_pred] whether it is an hpred edge. *)
val get_succs : t -> node -> bool -> bool -> node list
(** [get_succs g n footprint_part is_hpred] returns the successor nodes of [n] in [g].
[footprint_part] indicates whether to search the successors in the footprint part,
and [is_pred] whether to follow hpred edges. *)
val get_edges : bool -> t -> edge list
(** [get_edges footprint_part g] returns the list of edges in [g],
in the footprint part if [fotprint_part] is true *)
val contains_edge : bool -> t -> edge -> bool
(** [contains_edge footprint_part g e] returns true if the graph [g] contains edge [e],
searching the footprint part if [footprint_part] is true. *)
val iter_edges : bool -> (edge -> unit) -> t -> unit
(** [iter_edges footprint_part f g] iterates function [f] on the edges in [g]
in the same order as returned by [get_edges];
if [footprint_part] is true the edges are taken from the footprint part. *)
(** Graph annotated with the differences w.r.t. a previous graph *) (** Graph annotated with the differences w.r.t. a previous graph *)
type diff type diff

@ -93,12 +93,6 @@ let partition = PropSet.partition
(** {2 Pretty print} *) (** {2 Pretty print} *)
(** Pretty print a set of propositions, obtained from the given prop. *)
let pp pe prop f pset =
let plist = to_proplist pset in
Propgraph.pp_proplist pe "PROP" (prop, false) f plist
let d p ps = let d p ps =
let plist = to_proplist ps in let plist = to_proplist ps in
Propgraph.d_proplist p plist Propgraph.d_proplist p plist

@ -14,6 +14,8 @@ open! IStd
(** {2 Sets of Propositions} *) (** {2 Sets of Propositions} *)
[@@@warning "-32"]
(** Sets of propositions. (** Sets of propositions.
The invariant is maintaned that Prop.prop_rename_primed_footprint_vars is called on any prop added to the set. *) The invariant is maintaned that Prop.prop_rename_primed_footprint_vars is called on any prop added to the set. *)
type t type t
@ -73,10 +75,9 @@ val is_empty : t -> bool
val filter : (Prop.normal Prop.t -> bool) -> t -> t val filter : (Prop.normal Prop.t -> bool) -> t -> t
(** {2 Pretty print} *) [@@@warning "+32"]
val pp : Pp.env -> Prop.normal Prop.t -> Format.formatter -> t -> unit (** {2 Pretty print} *)
(** Pretty print a set of propositions, obtained from the given prop. *)
val d : Prop.normal Prop.t -> t -> unit val d : Prop.normal Prop.t -> t -> unit
(** dump a propset coming form the given initial prop *) (** dump a propset coming form the given initial prop *)

@ -910,12 +910,6 @@ let check_atom tenv prop a0 =
List.exists ~f:(Sil.equal_atom a) prop.Prop.pi List.exists ~f:(Sil.equal_atom a) prop.Prop.pi
(** Check [prop |- e1<=e2]. Result [false] means "don't know". *)
let check_le tenv prop e1 e2 =
let e1_le_e2 = Exp.BinOp (Binop.Le, e1, e2) in
check_atom tenv prop (Prop.mk_inequality tenv e1_le_e2)
(** Check whether [prop |- allocated(e)]. *) (** Check whether [prop |- allocated(e)]. *)
let check_allocatedness tenv prop e = let check_allocatedness tenv prop e =
let n_e = Prop.exp_normalize_prop ~destructive:true tenv prop e in let n_e = Prop.exp_normalize_prop ~destructive:true tenv prop e in
@ -936,12 +930,6 @@ let check_allocatedness tenv prop e =
List.exists ~f spatial_part List.exists ~f spatial_part
(** Compute an upper bound of an expression *)
let compute_upper_bound_of_exp tenv p e =
let ineq = Inequalities.from_prop tenv p in
Inequalities.compute_upper_bound ineq e
(** Check if two hpreds have the same allocated lhs *) (** Check if two hpreds have the same allocated lhs *)
let check_inconsistency_two_hpreds tenv prop = let check_inconsistency_two_hpreds tenv prop =
let sigma = prop.Prop.sigma in let sigma = prop.Prop.sigma in
@ -1951,35 +1939,6 @@ let cast_exception tenv texp1 texp2 e1 subs =
raise (IMPL_EXC ("class cast exception", subs, EXC_FALSE)) raise (IMPL_EXC ("class cast exception", subs, EXC_FALSE))
(** get all methods that override [supertype].[pname] in [tenv].
Note: supertype should be a type T rather than a pointer to type T
Note: [pname] wil never be included in the returned result *)
let get_overrides_of tenv supertype pname =
let typ_has_method pname (typ: Typ.t) =
match typ.desc with
| Tstruct name -> (
match Tenv.lookup tenv name with
| Some {methods} ->
List.exists ~f:(fun m -> Typ.Procname.equal pname m) methods
| None ->
false )
| _ ->
false
in
let gather_overrides tname _ overrides_acc =
let typ = Typ.mk (Tstruct tname) in
(* TODO shouldn't really create type here...*)
(* get all types in the type environment that are non-reflexive subtypes of [supertype] *)
if not (Typ.equal typ supertype) && Subtyping_check.check_subtype tenv typ supertype then
(* only select the ones that implement [pname] as overrides *)
let resolved_pname = Typ.Procname.replace_class pname tname in
if typ_has_method resolved_pname typ then (typ, resolved_pname) :: overrides_acc
else overrides_acc
else overrides_acc
in
Tenv.fold gather_overrides tenv []
(** Check the equality of two types ignoring flags in the subtyping components *) (** Check the equality of two types ignoring flags in the subtyping components *)
let texp_equal_modulo_subtype_flag texp1 texp2 = let texp_equal_modulo_subtype_flag texp1 texp2 =
match (texp1, texp2) with match (texp1, texp2) with

@ -28,17 +28,12 @@ val check_equal : Tenv.t -> Prop.normal Prop.t -> Exp.t -> Exp.t -> bool
val check_disequal : Tenv.t -> Prop.normal Prop.t -> Exp.t -> Exp.t -> bool val check_disequal : Tenv.t -> Prop.normal Prop.t -> Exp.t -> Exp.t -> bool
(** Check whether [prop |- exp1!=exp2]. Result [false] means "don't know". *) (** Check whether [prop |- exp1!=exp2]. Result [false] means "don't know". *)
val check_le : Tenv.t -> Prop.normal Prop.t -> Exp.t -> Exp.t -> bool
val type_size_comparable : Typ.t -> Typ.t -> bool val type_size_comparable : Typ.t -> Typ.t -> bool
(** Return true if the two types have sizes which can be compared *) (** Return true if the two types have sizes which can be compared *)
val check_type_size_leq : Typ.t -> Typ.t -> bool val check_type_size_leq : Typ.t -> Typ.t -> bool
(** Check <= on the size of comparable types *) (** Check <= on the size of comparable types *)
val check_type_size_lt : Typ.t -> Typ.t -> bool
(** Check < on the size of comparable types *)
val check_atom : Tenv.t -> Prop.normal Prop.t -> atom -> bool val check_atom : Tenv.t -> Prop.normal Prop.t -> atom -> bool
(** Check whether [prop |- a]. Result [false] means "don't know". *) (** Check whether [prop |- a]. Result [false] means "don't know". *)
@ -101,11 +96,6 @@ val find_minimum_pure_cover :
Tenv.t -> (Sil.atom list * 'a) list -> (Sil.atom list * 'a) list option Tenv.t -> (Sil.atom list * 'a) list -> (Sil.atom list * 'a) list option
(** Find minimum set of pi's in [cases] whose disjunction covers true *) (** Find minimum set of pi's in [cases] whose disjunction covers true *)
(** {2 Compute various lower or upper bounds} *)
val compute_upper_bound_of_exp : Tenv.t -> Prop.normal Prop.t -> Exp.t -> IntLit.t option
(** Computer an upper bound of an expression *)
(** {2 Subtype checking} *) (** {2 Subtype checking} *)
module Subtyping_check : sig module Subtyping_check : sig
@ -116,5 +106,3 @@ module Subtyping_check : sig
(** subtype_case_analysis tenv tecp1 texp2 performs case analysis on [texp1 <: texp2], (** subtype_case_analysis tenv tecp1 texp2 performs case analysis on [texp1 <: texp2],
and returns the updated types in the true and false case, if they are possible *) and returns the updated types in the true and false case, if they are possible *)
end end
val get_overrides_of : Tenv.t -> Typ.t -> Typ.Procname.t -> (Typ.t * Typ.Procname.t) list

@ -16,10 +16,6 @@ open! IStd
exception ARRAY_ACCESS exception ARRAY_ACCESS
val is_only_pt_by_fld_or_param_with_annot :
?check_weak_captured_var:bool -> Procdesc.t -> Tenv.t -> Prop.normal Prop.t -> Exp.t
-> (Annot.Item.t -> bool) -> string option
val is_only_pt_by_fld_or_param_nonnull : val is_only_pt_by_fld_or_param_nonnull :
Procdesc.t -> Tenv.t -> Prop.normal Prop.t -> Exp.t -> bool Procdesc.t -> Tenv.t -> Prop.normal Prop.t -> Exp.t -> bool

@ -66,18 +66,10 @@ let log_issue_deprecated ?(store_summary= false) err_kind proc_name ?loc ?node_i
Typ.Procname.pp proc_name Typ.Procname.pp proc_name Typ.Procname.pp proc_name Typ.Procname.pp proc_name
let log_error_from_errlog = log_issue_from_errlog Exceptions.Kerror
let log_warning_from_errlog = log_issue_from_errlog Exceptions.Kwarning
let log_info_from_errlog = log_issue_from_errlog Exceptions.Kinfo
let log_error = log_issue_from_summary Exceptions.Kerror let log_error = log_issue_from_summary Exceptions.Kerror
let log_warning = log_issue_from_summary Exceptions.Kwarning let log_warning = log_issue_from_summary Exceptions.Kwarning
let log_info = log_issue_from_summary Exceptions.Kwarning
let log_error_deprecated ?(store_summary= false) = let log_error_deprecated ?(store_summary= false) =
log_issue_deprecated ~store_summary Exceptions.Kerror log_issue_deprecated ~store_summary Exceptions.Kerror

@ -35,20 +35,8 @@ val log_info_deprecated : ?store_summary:bool -> Typ.Procname.t -> log_t
val log_issue_from_errlog : Exceptions.err_kind -> log_issue_from_errlog val log_issue_from_errlog : Exceptions.err_kind -> log_issue_from_errlog
(** Report an issue of a given kind in the given error log. *) (** Report an issue of a given kind in the given error log. *)
val log_error_from_errlog : log_issue_from_errlog
(** Report an error in the given error log. *)
val log_warning_from_errlog : log_issue_from_errlog
(** Report a warning in the given error log. *)
val log_info_from_errlog : log_issue_from_errlog
(** Report an info in the given error log. *)
val log_error : Specs.summary -> log_t val log_error : Specs.summary -> log_t
(** Add an error to the given summary. *) (** Add an error to the given summary. *)
val log_warning : Specs.summary -> log_t val log_warning : Specs.summary -> log_t
(** Add an warning to the given summary. *) (** Add an warning to the given summary. *)
val log_info : Specs.summary -> log_t
(** Add an info to the given summary. *)

@ -40,8 +40,6 @@ module Jprop = struct
let to_prop = function Prop (_, p) -> p | Joined (_, p, _, _) -> p let to_prop = function Prop (_, p) -> p | Joined (_, p, _, _) -> p
let to_number = function Prop (n, _) -> n | Joined (n, _, _, _) -> n
let rec fav_add_dfs tenv fav = function let rec fav_add_dfs tenv fav = function
| Prop (_, p) -> | Prop (_, p) ->
Prop.prop_fav_add_dfs tenv fav p Prop.prop_fav_add_dfs tenv fav p
@ -691,8 +689,6 @@ let pdesc_resolve_attributes proc_desc =
assert false assert false
let summary_exists proc_name = match get_summary proc_name with Some _ -> true | None -> false
(** Save summary for the procedure into the spec database *) (** Save summary for the procedure into the spec database *)
let store_summary (summ1: summary) = let store_summary (summ1: summary) =
let summ2 = let summ2 =

@ -51,9 +51,6 @@ module Jprop : sig
val pp_short : Pp.env -> Format.formatter -> Prop.normal t -> unit val pp_short : Pp.env -> Format.formatter -> Prop.normal t -> unit
(** Print the toplevel prop *) (** Print the toplevel prop *)
val to_number : 'a t -> int
(** Extract the number associated to the toplevel jprop of a prop *)
val to_prop : 'a t -> 'a Prop.t val to_prop : 'a t -> 'a Prop.t
(** Extract the toplevel jprop of a prop *) (** Extract the toplevel jprop of a prop *)
end end
@ -61,9 +58,6 @@ end
(** set of visited nodes: node id and list of lines of all the instructions *) (** set of visited nodes: node id and list of lines of all the instructions *)
module Visitedset : Caml.Set.S with type elt = Procdesc.Node.id * int list module Visitedset : Caml.Set.S with type elt = Procdesc.Node.id * int list
val visited_str : Visitedset.t -> string
(** convert a Visitedset to a string *)
(** A spec consists of: (** A spec consists of:
pre: a joined prop pre: a joined prop
posts: a list of props with path posts: a list of props with path
@ -120,8 +114,6 @@ val equal_status : status -> status -> bool
val string_of_status : status -> string val string_of_status : status -> string
val pp_status : Format.formatter -> status -> unit
type phase = FOOTPRINT | RE_EXECUTION type phase = FOOTPRINT | RE_EXECUTION
val equal_phase : phase -> phase -> bool val equal_phase : phase -> phase -> bool
@ -175,9 +167,6 @@ val get_proc_desc : summary -> Procdesc.t
val get_attributes : summary -> ProcAttributes.t val get_attributes : summary -> ProcAttributes.t
(** Get the attributes of the procedure. *) (** Get the attributes of the procedure. *)
val get_ret_type : summary -> Typ.t
(** Get the return type of the procedure *)
val get_formals : summary -> (Mangled.t * Typ.t) list val get_formals : summary -> (Mangled.t * Typ.t) list
(** Get the formal parameters of the procedure *) (** Get the formal parameters of the procedure *)
@ -206,18 +195,12 @@ val reset_summary : Procdesc.t -> summary
val load_summary : DB.filename -> summary option val load_summary : DB.filename -> summary option
(** Load procedure summary from the given file *) (** Load procedure summary from the given file *)
val summary_exists : Typ.Procname.t -> bool
(** Check if a procedure summary exists for the given procedure name *)
val normalized_specs_to_specs : NormSpec.t list -> Prop.normal spec list val normalized_specs_to_specs : NormSpec.t list -> Prop.normal spec list
(** Cast a list of normalized specs to a list of specs *) (** Cast a list of normalized specs to a list of specs *)
val pp_spec : Pp.env -> (int * int) option -> Format.formatter -> Prop.normal spec -> unit val pp_spec : Pp.env -> (int * int) option -> Format.formatter -> Prop.normal spec -> unit
(** Print the spec *) (** Print the spec *)
val pp_specs : Pp.env -> Format.formatter -> Prop.normal spec list -> unit
(** Print the specs *)
val pp_summary_html : SourceFile.t -> Pp.color -> Format.formatter -> summary -> unit val pp_summary_html : SourceFile.t -> Pp.color -> Format.formatter -> summary -> unit
(** Print the summary in html format *) (** Print the summary in html format *)
@ -241,11 +224,5 @@ val proc_is_library : ProcAttributes.t -> bool
val spec_normalize : Tenv.t -> Prop.normal spec -> NormSpec.t val spec_normalize : Tenv.t -> Prop.normal spec -> NormSpec.t
(** Convert spec into normal form w.r.t. variable renaming *) (** Convert spec into normal form w.r.t. variable renaming *)
val res_dir_specs_filename : Typ.Procname.t -> DB.filename
(** path to the .specs file for the given procedure in the current results dir *)
val store_summary : summary -> unit val store_summary : summary -> unit
(** Save summary for the procedure into the spec database *) (** Save summary for the procedure into the spec database *)
val summary_compact : Sil.sharing_env -> summary -> summary
(** Return a compact representation of the summary *)

@ -39,9 +39,6 @@ val get_loc_trace : unit -> Errlog.loc_trace
val get_node : unit -> Procdesc.Node.t val get_node : unit -> Procdesc.Node.t
(** Get last node seen in symbolic execution *) (** Get last node seen in symbolic execution *)
val get_node_id : unit -> Procdesc.Node.id
(** Get id of last node seen in symbolic execution *)
val get_node_id_key : unit -> Procdesc.Node.id * Caml.Digest.t val get_node_id_key : unit -> Procdesc.Node.id * Caml.Digest.t
(** Get id and key of last node seen in symbolic execution *) (** Get id and key of last node seen in symbolic execution *)

@ -38,9 +38,3 @@ val check_arith_norm_exp :
(** Check for arithmetic problems and normalize an expression. *) (** Check for arithmetic problems and normalize an expression. *)
val prune : Tenv.t -> positive:bool -> Exp.t -> Prop.normal Prop.t -> Propset.t val prune : Tenv.t -> positive:bool -> Exp.t -> Prop.normal Prop.t -> Propset.t
val resolve_method : Tenv.t -> Typ.Name.t -> Typ.Procname.t -> Typ.Procname.t
(** OO method resolution: given a class name and a method name, climb the class hierarchy to find
the procname that the method name will actually resolve to at runtime. For example, if we have a
procname like Foo.toString() and Foo does not override toString(), we must resolve the call to
toString(). We will end up with Super.toString() where Super is some superclass of Foo. *)

@ -12,9 +12,6 @@ open! IStd
(** Interprocedural footprint analysis *) (** Interprocedural footprint analysis *)
(** Frame and anti-frame *)
type splitting
val remove_constant_string_class : Tenv.t -> 'a Prop.t -> Prop.normal Prop.t val remove_constant_string_class : Tenv.t -> 'a Prop.t -> Prop.normal Prop.t
(** Remove constant string or class from a prop *) (** Remove constant string or class from a prop *)

@ -49,7 +49,6 @@ type spec =
| Unit of (unit -> unit) | Unit of (unit -> unit)
| String of (string -> unit) | String of (string -> unit)
| Symbol of string list * (string -> unit) | Symbol of string list * (string -> unit)
| Rest of (string -> unit)
let to_arg_spec = function let to_arg_spec = function
| Unit f -> | Unit f ->
@ -58,8 +57,6 @@ let to_arg_spec = function
Arg.String f Arg.String f
| Symbol (symbols, f) -> | Symbol (symbols, f) ->
Arg.Symbol (symbols, f) Arg.Symbol (symbols, f)
| Rest f ->
Arg.Rest f
let to_arg_spec_triple (x, spec, y) = (x, to_arg_spec spec, y) let to_arg_spec_triple (x, spec, y) = (x, to_arg_spec spec, y)
@ -295,8 +292,6 @@ let deprecate_desc parse_mode ~long ~short ~deprecated doc desc =
String (warn_then_f f) String (warn_then_f f)
| Symbol (symbols, f) -> | Symbol (symbols, f) ->
Symbol (symbols, warn_then_f f) Symbol (symbols, warn_then_f f)
| Rest _ as spec ->
spec
in in
let deprecated_decode_json ~inferconfig_dir j = let deprecated_decode_json ~inferconfig_dir j =
warnf "WARNING: in .inferconfig: '%s' is deprecated. Use '%s' instead." deprecated long ; warnf "WARNING: in .inferconfig: '%s' is deprecated. Use '%s' instead." deprecated long ;
@ -485,14 +480,6 @@ let mk_int_opt ?default ?f:(f0 = Fn.id) ?(deprecated= []) ~long ?short ?parse_mo
mk_option ~deprecated ~long ?short ~default ~default_to_string ~f ?parse_mode ?in_help ~meta doc mk_option ~deprecated ~long ?short ~default ~default_to_string ~f ?parse_mode ?in_help ~meta doc
let mk_float ~default ?(deprecated= []) ~long ?short ?parse_mode ?in_help ?(meta= "float") doc =
mk ~deprecated ~long ?short ~default ?parse_mode ?in_help ~meta doc
~default_to_string:string_of_float
~mk_setter:(fun var str -> var := float_of_string str)
~decode_json:(string_json_decoder ~long)
~mk_spec:(fun set -> String set)
let mk_float_opt ?default ?(deprecated= []) ~long ?short ?parse_mode ?in_help ?(meta= "float") doc = let mk_float_opt ?default ?(deprecated= []) ~long ?short ?parse_mode ?in_help ?(meta= "float") doc =
let default_to_string = function Some f -> string_of_float f | None -> "" in let default_to_string = function Some f -> string_of_float f | None -> "" in
let f s = Some (float_of_string s) in let f s = Some (float_of_string s) in
@ -637,14 +624,6 @@ let mk_symbol_seq ?(default= []) ~symbols ~eq ?(deprecated= []) ~long ?short ?pa
~mk_spec:(fun set -> String set) ~mk_spec:(fun set -> String set)
let mk_set_from_json ~default ~default_to_string ~f ?(deprecated= []) ~long ?short ?parse_mode
?in_help ?(meta= "json") doc =
mk ~deprecated ~long ?short ?parse_mode ?in_help ~meta doc ~default ~default_to_string
~mk_setter:(fun var json -> var := f (Yojson.Basic.from_string json))
~decode_json:(fun ~inferconfig_dir:_ json -> [dashdash long; Yojson.Basic.to_string json])
~mk_spec:(fun set -> String set)
let mk_json ?(deprecated= []) ~long ?short ?parse_mode ?in_help ?(meta= "json") doc = let mk_json ?(deprecated= []) ~long ?short ?parse_mode ?in_help ?(meta= "json") doc =
mk ~deprecated ~long ?short ?parse_mode ?in_help ~meta doc ~default:(`List []) mk ~deprecated ~long ?short ?parse_mode ?in_help ~meta doc ~default:(`List [])
~default_to_string:Yojson.Basic.to_string ~default_to_string:Yojson.Basic.to_string
@ -657,14 +636,6 @@ let mk_json ?(deprecated= []) ~long ?short ?parse_mode ?in_help ?(meta= "json")
[parse_action_accept_unknown_args] is true. *) [parse_action_accept_unknown_args] is true. *)
let mk_anon () = rev_anon_args let mk_anon () = rev_anon_args
let mk_rest ?(parse_mode= InferCommand) ?(in_help= []) doc =
let rest = ref [] in
let spec = Rest (fun arg -> rest := arg :: !rest) in
add parse_mode in_help
{long= "--"; short= ""; meta= ""; doc; spec; decode_json= (fun ~inferconfig_dir:_ _ -> [])} ;
rest
let normalize_desc_list speclist = let normalize_desc_list speclist =
let norm k = let norm k =
let remove_no s = let remove_no s =

@ -53,8 +53,6 @@ val is_originator : bool
val init_work_dir : string val init_work_dir : string
val strict_mode : bool
(** The [mk_*] functions declare command line options, while [parse] parses then according to the (** The [mk_*] functions declare command line options, while [parse] parses then according to the
declared options. declared options.
@ -80,10 +78,6 @@ type 'a t =
val mk_set : 'a ref -> 'a -> unit t val mk_set : 'a ref -> 'a -> unit t
(** [mk_set variable value] defines a command line option which sets [variable] to [value]. *) (** [mk_set variable value] defines a command line option which sets [variable] to [value]. *)
val mk_option :
?default:'a option -> ?default_to_string:('a option -> string) -> f:(string -> 'a option)
-> ?mk_reset:bool -> 'a option ref t
val mk_bool : ?deprecated_no:string list -> ?default:bool -> ?f:(bool -> bool) -> bool ref t val mk_bool : ?deprecated_no:string list -> ?default:bool -> ?f:(bool -> bool) -> bool ref t
(** [mk_bool long short doc] defines a [bool ref] set by the command line flag [--long] (and (** [mk_bool long short doc] defines a [bool ref] set by the command line flag [--long] (and
[-s]), and cleared by the flag [--no-long] (and [-S]). If [long] already has a "no-" prefix, [-s]), and cleared by the flag [--no-long] (and [-S]). If [long] already has a "no-" prefix,
@ -102,8 +96,6 @@ val mk_int : default:int -> ?f:(int -> int) -> int ref t
val mk_int_opt : ?default:int -> ?f:(int -> int) -> int option ref t val mk_int_opt : ?default:int -> ?f:(int -> int) -> int option ref t
val mk_float : default:float -> float ref t
val mk_float_opt : ?default:float -> float option ref t val mk_float_opt : ?default:float -> float option ref t
val mk_string : default:string -> ?f:(string -> string) -> string ref t val mk_string : default:string -> ?f:(string -> string) -> string ref t
@ -146,21 +138,12 @@ val mk_symbol_seq :
[<symbol sequence>] is a comma-separated sequence of [<symbol>]s such that [(<symbol>,_)] is an [<symbol sequence>] is a comma-separated sequence of [<symbol>]s such that [(<symbol>,_)] is an
element of [symbols]. *) element of [symbols]. *)
val mk_set_from_json :
default:'a -> default_to_string:('a -> string) -> f:(Yojson.Basic.json -> 'a) -> 'a ref t
val mk_json : Yojson.Basic.json ref t val mk_json : Yojson.Basic.json ref t
val mk_anon : unit -> string list ref val mk_anon : unit -> string list ref
(** [mk_anon ()] defines a [string list ref] of the anonymous command line arguments, in the reverse (** [mk_anon ()] defines a [string list ref] of the anonymous command line arguments, in the reverse
order they appeared on the command line. *) order they appeared on the command line. *)
val mk_rest :
?parse_mode:parse_mode -> ?in_help:(command * string) list -> string -> string list ref
(** [mk_rest doc] defines a [string list ref] of the command line arguments following ["--"], in the
reverse order they appeared on the command line. For example, calling [mk_rest] and parsing
[exe -opt1 -opt2 -- arg1 arg2] will result in the returned ref containing [arg2; arg1]. *)
val mk_rest_actions : val mk_rest_actions :
?parse_mode:parse_mode -> ?in_help:(command * string) list -> string -> usage:string ?parse_mode:parse_mode -> ?in_help:(command * string) list -> string -> usage:string
-> (string -> parse_mode) -> string list ref -> (string -> parse_mode) -> string list ref

@ -160,8 +160,6 @@ let backend_stats_dir_name = "backend_stats"
continues *) continues *)
let bound_error_allowed_in_procedure_call = true let bound_error_allowed_in_procedure_call = true
let buck_generated_folder = "buck-out/gen"
let buck_infer_deps_file_name = "infer-deps.txt" let buck_infer_deps_file_name = "infer-deps.txt"
let buck_results_dir_name = "infer" let buck_results_dir_name = "infer"
@ -226,8 +224,6 @@ let log_analysis_recursion_timeout = "R"
let log_analysis_crash = "C" let log_analysis_crash = "C"
let log_dir_name = "log"
let manual_buck_compilation_db = "BUCK COMPILATION DATABASE OPTIONS" let manual_buck_compilation_db = "BUCK COMPILATION DATABASE OPTIONS"
let manual_buck_flavors = "BUCK FLAVORS OPTIONS" let manual_buck_flavors = "BUCK FLAVORS OPTIONS"
@ -254,9 +250,6 @@ let manual_racerd = "RACERD CHECKER OPTIONS"
let manual_siof = "SIOF CHECKER OPTIONS" let manual_siof = "SIOF CHECKER OPTIONS"
(** Maximum level of recursion during the analysis, after which a timeout is generated *)
let max_recursion = 5
(** Maximum number of widens that can be performed before the analysis will intentionally crash. (** Maximum number of widens that can be performed before the analysis will intentionally crash.
Used to guard against divergence in the case that someone has implemented a bad widening Used to guard against divergence in the case that someone has implemented a bad widening
operator *) operator *)
@ -824,11 +817,6 @@ and array_level =
|} |}
and ast_file =
CLOpt.mk_path_opt ~deprecated:["ast"] ~long:"ast-file" ~meta:"file"
"AST file for the translation"
and blacklist = and blacklist =
CLOpt.mk_string_opt ~deprecated:["-blacklist-regex"; "-blacklist"] ~long:"buck-blacklist" CLOpt.mk_string_opt ~deprecated:["-blacklist-regex"; "-blacklist"] ~long:"buck-blacklist"
~in_help:CLOpt.([(Run, manual_buck_flavors); (Capture, manual_buck_flavors)]) ~in_help:CLOpt.([(Run, manual_buck_flavors); (Capture, manual_buck_flavors)])
@ -1204,11 +1192,6 @@ and eradicate_optional_present =
CLOpt.mk_bool ~long:"eradicate-optional-present" "Check for @Present annotations" CLOpt.mk_bool ~long:"eradicate-optional-present" "Check for @Present annotations"
and eradicate_propagate_return_nullable =
CLOpt.mk_bool ~long:"eradicate-propagate-return-nullable"
"Propagation of nullable to the return value"
and eradicate_return_over_annotated = and eradicate_return_over_annotated =
CLOpt.mk_bool ~long:"eradicate-return-over-annotated" "Return over-annotated warning" CLOpt.mk_bool ~long:"eradicate-return-over-annotated" "Return over-annotated warning"
@ -1475,9 +1458,6 @@ and load_results =
~meta:"file.iar" "Load analysis results from Infer Analysis Results file file.iar" ~meta:"file.iar" "Load analysis results from Infer Analysis Results file file.iar"
(** name of the makefile to create with clusters and dependencies *)
and makefile = CLOpt.mk_path ~deprecated:["makefile"] ~long:"makefile" ~default:"" ~meta:"file" ""
and margin = and margin =
CLOpt.mk_int ~deprecated:["set_pp_margin"] ~long:"margin" ~default:100 ~meta:"int" CLOpt.mk_int ~deprecated:["set_pp_margin"] ~long:"margin" ~default:100 ~meta:"int"
"Set right margin for the pretty printing functions" "Set right margin for the pretty printing functions"
@ -1521,11 +1501,6 @@ and nullable_annotation =
CLOpt.mk_string_opt ~long:"nullable-annotation-name" "Specify custom nullable annotation name" CLOpt.mk_string_opt ~long:"nullable-annotation-name" "Specify custom nullable annotation name"
(* TODO: document *)
and objc_memory_model =
CLOpt.mk_bool ~deprecated:["objcm"] ~long:"objc-memory-model" "Use ObjC memory model"
and only_footprint = and only_footprint =
CLOpt.mk_bool ~deprecated:["only_footprint"] ~long:"only-footprint" "Skip the re-execution phase" CLOpt.mk_bool ~deprecated:["only_footprint"] ~long:"only-footprint" "Skip the re-execution phase"
@ -1626,11 +1601,6 @@ and procs_csv =
"Write statistics for each procedure in CSV format to a file" "Write statistics for each procedure in CSV format to a file"
and procs_xml =
CLOpt.mk_path_opt ~deprecated:["procs_xml"] ~long:"procs-xml" ~meta:"file"
"Write statistics for each procedure in XML format to a file (as a path relative to $(b,--results-dir))"
and progress_bar = and progress_bar =
CLOpt.mk_bool ~deprecated:["pb"] ~deprecated_no:["no_progress_bar"; "npb"] ~short:'p' CLOpt.mk_bool ~deprecated:["pb"] ~deprecated_no:["no_progress_bar"; "npb"] ~short:'p'
~long:"progress-bar" ~default:true ~long:"progress-bar" ~default:true
@ -1880,8 +1850,6 @@ and subtype_multirange =
"Use the multirange subtyping domain" "Use the multirange subtyping domain"
and svg = CLOpt.mk_bool ~deprecated:["svg"] ~long:"svg" "Generate .dot and .svg files from specs"
and symops_per_iteration = and symops_per_iteration =
CLOpt.mk_int_opt ~deprecated:["symops_per_iteration"] ~long:"symops-per-iteration" ~meta:"int" CLOpt.mk_int_opt ~deprecated:["symops_per_iteration"] ~long:"symops-per-iteration" ~meta:"int"
"Set the number of symbolic operations per iteration (see $(b,--iterations))" "Set the number of symbolic operations per iteration (see $(b,--iterations))"
@ -1947,11 +1915,6 @@ and unsafe_malloc =
"Assume that malloc(3) never returns null." "Assume that malloc(3) never returns null."
(** Set the path to the javac verbose output *)
and verbose_out =
CLOpt.mk_path ~deprecated:["verbose_out"] ~long:"verbose-out" ~default:"" ~meta:"file" ""
and version = and version =
let var = ref `None in let var = ref `None in
CLOpt.mk_set var `Full ~deprecated:["version"] ~long:"version" CLOpt.mk_set var `Full ~deprecated:["version"] ~long:"version"
@ -1964,10 +1927,6 @@ and version =
var var
and whole_seconds =
CLOpt.mk_bool ~deprecated:["whole_seconds"] ~long:"whole-seconds" "Print whole seconds only"
(** visit mode for the worklist: (** visit mode for the worklist:
0 depth - fist visit 0 depth - fist visit
1 bias towards exit node 1 bias towards exit node
@ -1994,11 +1953,6 @@ and xcpretty =
"Infer will use xcpretty together with xcodebuild to analyze an iOS app. xcpretty just needs to be in the path, infer command is still just $(i,`infer -- <xcodebuild command>`)." "Infer will use xcpretty together with xcodebuild to analyze an iOS app. xcpretty just needs to be in the path, infer command is still just $(i,`infer -- <xcodebuild command>`)."
and xml_specs =
CLOpt.mk_bool ~deprecated:["xml"] ~long:"xml-specs"
"Export specs into XML files file1.xml ... filen.xml"
(* The "rest" args must appear after "--" on the command line, and hence after other args, so they (* The "rest" args must appear after "--" on the command line, and hence after other args, so they
are allowed to refer to the other arg variables. *) are allowed to refer to the other arg variables. *)
@ -2279,8 +2233,6 @@ and append_buck_flavors = !append_buck_flavors
and array_level = !array_level and array_level = !array_level
and ast_file = !ast_file
and biabduction = !biabduction and biabduction = !biabduction
and blacklist = !blacklist and blacklist = !blacklist
@ -2384,8 +2336,6 @@ and eradicate_field_over_annotated = !eradicate_field_over_annotated
and eradicate_optional_present = !eradicate_optional_present and eradicate_optional_present = !eradicate_optional_present
and eradicate_propagate_return_nullable = !eradicate_propagate_return_nullable
and eradicate_return_over_annotated = !eradicate_return_over_annotated and eradicate_return_over_annotated = !eradicate_return_over_annotated
and eradicate_debug = !eradicate_debug and eradicate_debug = !eradicate_debug
@ -2437,8 +2387,6 @@ and gen_previous_build_command_script = !gen_previous_build_command_script
and generated_classes = !generated_classes and generated_classes = !generated_classes
and headers = !headers
and html = !html and html = !html
and icfg_dotty_outfile = !icfg_dotty_outfile and icfg_dotty_outfile = !icfg_dotty_outfile
@ -2467,8 +2415,6 @@ and java_jar_compiler = !java_jar_compiler
and javac_classes_out = !javac_classes_out and javac_classes_out = !javac_classes_out
and javac_verbose_out = !verbose_out
and jobs = !jobs and jobs = !jobs
and join_cond = !join_cond and join_cond = !join_cond
@ -2512,8 +2458,6 @@ and log_events = !log_events
and log_file = !log_file and log_file = !log_file
and makefile_cmdline = !makefile
and max_nesting = !max_nesting and max_nesting = !max_nesting
and merge = !merge and merge = !merge
@ -2534,8 +2478,6 @@ and suggest_nullable = !suggest_nullable
and no_translate_libs = not !headers and no_translate_libs = not !headers
and objc_memory_model_on = !objc_memory_model
and only_cheap_debug = !only_cheap_debug and only_cheap_debug = !only_cheap_debug
and only_footprint = !only_footprint and only_footprint = !only_footprint
@ -2578,8 +2520,6 @@ and procedures_per_process = !procedures_per_process
and procs_csv = !procs_csv and procs_csv = !procs_csv
and procs_xml = !procs_xml
and project_root = !project_root and project_root = !project_root
and quandary = !quandary and quandary = !quandary
@ -2658,8 +2598,6 @@ and stats_report = !stats_report
and subtype_multirange = !subtype_multirange and subtype_multirange = !subtype_multirange
and svg = !svg
and symops_per_iteration = !symops_per_iteration and symops_per_iteration = !symops_per_iteration
and keep_going = !keep_going and keep_going = !keep_going
@ -2692,8 +2630,6 @@ and uninit_interproc = !uninit_interproc
and unsafe_malloc = !unsafe_malloc and unsafe_malloc = !unsafe_malloc
and whole_seconds = !whole_seconds
and worklist_mode = !worklist_mode and worklist_mode = !worklist_mode
and write_dotty = !write_dotty and write_dotty = !write_dotty
@ -2706,8 +2642,6 @@ and xcode_developer_dir = !xcode_developer_dir
and xcpretty = !xcpretty and xcpretty = !xcpretty
and xml_specs = !xml_specs
(** Configuration values derived from command-line options *) (** Configuration values derived from command-line options *)
let analysis_path_regex_whitelist analyzer = let analysis_path_regex_whitelist analyzer =

@ -35,32 +35,6 @@ val equal_language : language -> language -> bool
val string_of_language : language -> string val string_of_language : language -> string
val ml_bucket_symbols :
(string * [`MLeak_all | `MLeak_arc | `MLeak_cf | `MLeak_cpp | `MLeak_no_arc | `MLeak_unknown])
list
val issues_fields_symbols :
( string
* [ `Issue_field_bug_class
| `Issue_field_kind
| `Issue_field_bug_type
| `Issue_field_qualifier
| `Issue_field_severity
| `Issue_field_visibility
| `Issue_field_line
| `Issue_field_column
| `Issue_field_procedure
| `Issue_field_procedure_id
| `Issue_field_procedure_start_line
| `Issue_field_file
| `Issue_field_bug_trace
| `Issue_field_key
| `Issue_field_hash
| `Issue_field_line_offset
| `Issue_field_procedure_id_without_crc
| `Issue_field_qualifier_contains_potential_exception_note ] )
list
type os_type = Unix | Win32 | Cygwin type os_type = Unix | Win32 | Cygwin
type compilation_database_dependencies = type compilation_database_dependencies =
@ -109,8 +83,6 @@ val bin_dir : string
val bound_error_allowed_in_procedure_call : bool val bound_error_allowed_in_procedure_call : bool
val buck_generated_folder : string
val buck_infer_deps_file_name : string val buck_infer_deps_file_name : string
val captured_dir_name : string val captured_dir_name : string
@ -181,10 +153,6 @@ val log_analysis_symops_timeout : string
val log_analysis_wallclock_timeout : string val log_analysis_wallclock_timeout : string
val log_dir_name : string
val max_recursion : int
val max_widens : int val max_widens : int
val meet_level : int val meet_level : int
@ -197,8 +165,6 @@ val models_src_dir : string
val multicore_dir_name : string val multicore_dir_name : string
val ncpu : int
val nsnotification_center_checker_backend : bool val nsnotification_center_checker_backend : bool
val os_type : os_type val os_type : os_type
@ -259,8 +225,6 @@ val unsafe_unret : string
val use_jar_cache : bool val use_jar_cache : bool
val version_string : string
val weak : string val weak : string
val whitelisted_cpp_methods : string list val whitelisted_cpp_methods : string list
@ -295,8 +259,6 @@ val annotation_reachability_custom_pairs : Yojson.Basic.json
val array_level : int val array_level : int
val ast_file : string option
val biabduction : bool val biabduction : bool
val blacklist : string option val blacklist : string option
@ -390,8 +352,6 @@ val eradicate_field_over_annotated : bool
val eradicate_optional_present : bool val eradicate_optional_present : bool
val eradicate_propagate_return_nullable : bool
val eradicate_return_over_annotated : bool val eradicate_return_over_annotated : bool
val eradicate_debug : bool val eradicate_debug : bool
@ -430,8 +390,6 @@ val gen_previous_build_command_script : string option
val generated_classes : string option val generated_classes : string option
val headers : bool
val html : bool val html : bool
val icfg_dotty_outfile : string option val icfg_dotty_outfile : string option
@ -485,8 +443,6 @@ val java_jar_compiler : string option
val javac_classes_out : string val javac_classes_out : string
val javac_verbose_out : string
val jobs : int val jobs : int
val join_cond : int val join_cond : int
@ -521,8 +477,6 @@ val log_events : bool
val log_file : string val log_file : string
val makefile_cmdline : string
val max_nesting : int option val max_nesting : int option
val merge : bool val merge : bool
@ -542,8 +496,6 @@ val no_translate_libs : bool
val nullable_annotation : string option val nullable_annotation : string option
val objc_memory_model_on : bool
val only_cheap_debug : bool val only_cheap_debug : bool
val only_footprint : bool val only_footprint : bool
@ -574,8 +526,6 @@ val procedures_per_process : int
val procs_csv : string option val procs_csv : string option
val procs_xml : string option
val project_root : string val project_root : string
val quandary : bool val quandary : bool
@ -650,8 +600,6 @@ val subtype_multirange : bool
val suggest_nullable : bool val suggest_nullable : bool
val svg : bool
val symops_per_iteration : int option val symops_per_iteration : int option
val test_filtering : bool val test_filtering : bool
@ -682,8 +630,6 @@ val uninit_interproc : bool
val unsafe_malloc : bool val unsafe_malloc : bool
val whole_seconds : bool
val worklist_mode : int val worklist_mode : int
val write_dotty : bool val write_dotty : bool
@ -696,8 +642,6 @@ val xcode_developer_dir : string option
val xcpretty : bool val xcpretty : bool
val xml_specs : bool
(** Global variables *) (** Global variables *)
val arc_mode : bool ref val arc_mode : bool ref

@ -36,15 +36,6 @@ let dot_crc_len = 1 + 32
let strip_crc str = String.slice str 0 (-dot_crc_len) let strip_crc str = String.slice str 0 (-dot_crc_len)
let string_crc_has_extension ~ext name_crc =
let name = strip_crc name_crc in
match Filename.split_extension name with
| _, Some ext' ->
String.equal ext ext'
| _, None ->
false
let curr_source_file_encoding = `Enc_crc let curr_source_file_encoding = `Enc_crc
(** string encoding of a source file (including path) as a single filename *) (** string encoding of a source file (including path) as a single filename *)
@ -83,34 +74,12 @@ let source_dir_from_source_file source_file =
Filename.concat Config.captured_dir (source_file_encoding source_file) Filename.concat Config.captured_dir (source_file_encoding source_file)
(** Find the source directories in the results dir *)
let find_source_dirs () =
let source_dirs = ref [] in
let files_in_results_dir = Array.to_list (Sys.readdir Config.captured_dir) in
let add_cg_files_from_dir dir =
let files = Array.to_list (Sys.readdir dir) in
List.iter
~f:(fun fname ->
let path = Filename.concat dir fname in
if Filename.check_suffix path ".cg" then source_dirs := dir :: !source_dirs )
files
in
List.iter
~f:(fun fname ->
let dir = Filename.concat Config.captured_dir fname in
if Sys.is_directory dir = `Yes then add_cg_files_from_dir dir )
files_in_results_dir ;
List.rev !source_dirs
(** {2 Filename} *) (** {2 Filename} *)
type filename = string [@@deriving compare] type filename = string [@@deriving compare]
let equal_filename = [%compare.equal : filename] let equal_filename = [%compare.equal : filename]
let filename_concat = Filename.concat
let filename_to_string s = s let filename_to_string s = s
let filename_from_string s = s let filename_from_string s = s
@ -139,11 +108,6 @@ let file_modified_time ?(symlink= false) fname =
with Unix.Unix_error _ -> L.(die InternalError) "File %s does not exist." fname with Unix.Unix_error _ -> L.(die InternalError) "File %s does not exist." fname
let filename_create_dir fname =
let dirname = Filename.dirname fname in
if Sys.file_exists dirname <> `Yes then Utils.create_dir dirname
let read_whole_file fd = In_channel.input_all (Unix.in_channel_of_descr fd) let read_whole_file fd = In_channel.input_all (Unix.in_channel_of_descr fd)
(** Update the file contents with the update function provided. (** Update the file contents with the update function provided.
@ -269,7 +233,7 @@ end
let global_tenv_fname = let global_tenv_fname =
let basename = Config.global_tenv_filename in let basename = Config.global_tenv_filename in
filename_concat Config.captured_dir basename Config.captured_dir ^/ basename
let is_source_file path = let is_source_file path =

@ -29,8 +29,6 @@ val filename_to_string : filename -> string
val chop_extension : filename -> filename val chop_extension : filename -> filename
val filename_concat : filename -> string -> filename
val filename_add_suffix : filename -> string -> filename val filename_add_suffix : filename -> string -> filename
val file_exists : filename -> bool val file_exists : filename -> bool
@ -82,9 +80,6 @@ val append_crc_cutoff : ?key:string -> ?crc_only:bool -> string -> string
Use an optional key to compute the crc. Use an optional key to compute the crc.
Return only the crc if [crc_only] is true. *) Return only the crc if [crc_only] is true. *)
val string_crc_has_extension : ext:string -> string -> bool
(** Remove the crc from the string, and check if it has the given extension *)
val strip_crc : string -> string val strip_crc : string -> string
(** Strip any crc attached to any string generated by string_append_crc_cutoff *) (** Strip any crc attached to any string generated by string_append_crc_cutoff *)
@ -105,12 +100,6 @@ val source_dir_get_internal_file : source_dir -> string -> filename
val source_dir_from_source_file : SourceFile.t -> source_dir val source_dir_from_source_file : SourceFile.t -> source_dir
(** get the source directory corresponding to a source file *) (** get the source directory corresponding to a source file *)
val filename_create_dir : filename -> unit
(** create the directory containing the file bane *)
val find_source_dirs : unit -> source_dir list
(** Find the source directories in the current results dir *)
val read_file_with_lock : string -> string -> string option val read_file_with_lock : string -> string -> string option
(** Read a file using a lock to allow write attempts in parallel. *) (** Read a file using a lock to allow write attempts in parallel. *)

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

Loading…
Cancel
Save