[format] Attach docstrings to be warning 50 clean, other doc fixes

Summary: Fix (most of?) the docstrings in code converted from Reason.

Reviewed By: jvillard

Differential Revision: D5413793

fbshipit-source-id: 004b305
master
Josh Berdine 7 years ago committed by Facebook Github Bot
parent 8c6615963f
commit 6bbb186ce2

@ -15,42 +15,35 @@ module F = Format
type parameters = string list type parameters = string list
(** Type to represent one @Annotation. *) (** Type to represent one @Annotation. *)
type t = type t =
{ class_name: string (** name of the annotation *) { class_name: string (** name of the annotation *)
; parameters: parameters (** currently only one string parameter *) } ; parameters: parameters (** currently only one string parameter *) }
[@@deriving compare] [@@deriving compare]
(** annotation for fields/methods marked with the "volatile" keyword *)
val volatile : t val volatile : t
(** annotation for fields/methods marked with the "volatile" keyword *)
(** Pretty print an annotation. *)
val pp : F.formatter -> t -> unit val pp : F.formatter -> t -> unit
(** Pretty print an annotation. *)
module Map : PrettyPrintable.PPMap with type key = t module Map : PrettyPrintable.PPMap with type key = t
module Item : sig 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 equal : t -> t -> bool
(** Pretty print an item annotation. *)
val pp : F.formatter -> t -> unit val pp : F.formatter -> t -> unit
(** Pretty print an item annotation. *)
val to_string : t -> string val to_string : t -> string
(** Empty item annotation. *)
val empty : t val empty : t
(** Empty item annotation. *)
(** Check if the item annodation is empty. *)
val is_empty : t -> bool val is_empty : t -> bool
(** Check if the item annodation is empty. *)
end end
module Class : sig module Class : sig
@ -61,18 +54,14 @@ end
module Method : sig module Method : sig
(** Annotation for a method: return value and list of parameters. *) (** Annotation for a method: return value and list of parameters. *)
type t = Item.t * Item.t list [@@deriving compare] type t = Item.t * Item.t list [@@deriving compare]
(** Empty method annotation. *)
val empty : t val empty : t
(** Empty method annotation. *)
(** Check if the method annodation is empty. *)
val is_empty : t -> bool val is_empty : t -> bool
(** Check if the method annodation is empty. *)
(** Pretty print a method annotation. *)
val pp : string -> F.formatter -> t -> unit val pp : string -> F.formatter -> t -> unit
(** Pretty print a method annotation. *)
end end

@ -11,33 +11,28 @@
open! IStd open! IStd
(** Save .attr file for the procedure into the attributes database. *)
val store_attributes : ProcAttributes.t -> unit val store_attributes : ProcAttributes.t -> unit
(** Save .attr file for the procedure into the attributes database. *)
val load_attributes : cache:bool -> Typ.Procname.t -> ProcAttributes.t option
(** Load the attributes for the procedure from the attributes database. (** Load the attributes for the procedure from the attributes database.
If cache is true, add the attribute to the global cache *) If cache is true, add the attribute to the global cache *)
val load_attributes : cache:bool -> Typ.Procname.t -> ProcAttributes.t option
(** Load attrubutes for the procedure but only if is_defined is true *)
val load_defined_attributes : cache_none:bool -> Typ.Procname.t -> ProcAttributes.t option val load_defined_attributes : cache_none:bool -> Typ.Procname.t -> ProcAttributes.t option
(** Load attrubutes for the procedure but only if is_defined is true *)
val get_correct_type_from_objc_class_name : Typ.Name.t -> Typ.t option
(** Given the name of an ObjC class, extract the type from the tenv where the class was defined. We (** Given the name of an ObjC class, extract the type from the tenv where the class was defined. We
do this by adding a method that is unique to each class, and then finding the tenv that do this by adding a method that is unique to each class, and then finding the tenv that
corresponds to the class definition. *) corresponds to the class definition. *)
val get_correct_type_from_objc_class_name : Typ.Name.t -> Typ.t option val find_file_capturing_procedure :
?cache:bool -> Typ.Procname.t -> (SourceFile.t * [`Include | `Source]) option
(* Find the file where the procedure was captured, if a cfg for that file exists. (** Find the file where the procedure was captured, if a cfg for that file exists.
Return also a boolean indicating whether the procedure is defined in an Return also a boolean indicating whether the procedure is defined in an
include file. include file.
If cache is true, add the attribute to the global cache *) If cache is true, add the attribute to the global cache *)
val find_file_capturing_procedure :
?cache:bool -> Typ.Procname.t -> (SourceFile.t * [`Include | `Source]) option
type t type t
val stats : unit -> t val stats : unit -> t

@ -14,7 +14,6 @@ module L = Logging
module F = Format module F = Format
(** Binary operations *) (** Binary operations *)
type t = type t =
| PlusA (** arithmetic + *) | PlusA (** arithmetic + *)
| PlusPI (** pointer + integer *) | PlusPI (** pointer + integer *)
@ -41,26 +40,21 @@ type t =
val equal : t -> t -> bool val equal : t -> t -> bool
val injective : t -> bool
(** This function returns true if the operation is injective (** This function returns true if the operation is injective
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 injective : t -> bool
(** This function returns true if the operation can be inverted. *)
val invertible : t -> bool 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. (** This function inverts an invertible injective binary operator.
If the [binop] operation is not invertible, the function raises Assert_failure. *) If the [binop] operation is not invertible, the function raises Assert_failure. *)
val invert : t -> t 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". *)
val is_zero_runit : t -> bool
(** String representation of a binary operator. *)
val str : Pp.env -> t -> string val str : Pp.env -> t -> string
(** String representation of a binary operator. *)

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

@ -9,6 +9,7 @@
*) *)
(** The Smallfoot Intermediate Language: Call Flags *) (** The Smallfoot Intermediate Language: Call Flags *)
open! IStd open! IStd
module L = Logging module L = Logging
module F = Format module F = Format

@ -9,12 +9,12 @@
*) *)
(** The Smallfoot Intermediate Language: Call Flags *) (** The Smallfoot Intermediate Language: Call Flags *)
open! IStd open! IStd
module L = Logging module L = Logging
module F = Format module F = Format
(** Flags for a procedure call *) (** Flags for a procedure call *)
type t = type t =
{ cf_virtual: bool { cf_virtual: bool
; cf_interface: bool ; cf_interface: bool
@ -25,6 +25,5 @@ type t =
val pp : F.formatter -> t -> unit val pp : F.formatter -> t -> unit
(** Default value where all fields are set to false *)
val default : t val default : t
(** Default value where all fields are set to false *)

@ -7,12 +7,13 @@
* LICENSE file in the root directory of this source tree. An additional grant * LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory. * of patent rights can be found in the PATENTS file in the same directory.
*) *)
open! IStd open! IStd
module L = Logging module L = Logging
module F = Format module F = Format
(** data type for the control flow graph *) (** data type for the control flow graph *)
type cfg = {proc_desc_table: (** Map proc name to procdesc *) Procdesc.t Typ.Procname.Hash.t} type cfg = {proc_desc_table: Procdesc.t Typ.Procname.Hash.t (** Map proc name to procdesc *)}
(** create a new empty cfg *) (** create a new empty cfg *)
let create_cfg () = {proc_desc_table= Typ.Procname.Hash.create 16} let create_cfg () = {proc_desc_table= Typ.Procname.Hash.create 16}

@ -13,60 +13,47 @@ open! IStd
(** Control Flow Graph for Interprocedural Analysis *) (** Control Flow Graph for Interprocedural Analysis *)
(** A control-flow graph *) (** A control-flow graph *)
type cfg type cfg
(** Load a cfg from a file *)
val load_cfg_from_file : DB.filename -> cfg option val load_cfg_from_file : DB.filename -> cfg option
(** Load a cfg from a file *)
(** Save a cfg into a file, and save a copy of the source files if the boolean is true *)
val store_cfg_to_file : source_file:SourceFile.t -> DB.filename -> cfg -> unit val store_cfg_to_file : source_file:SourceFile.t -> DB.filename -> cfg -> unit
(** Save a cfg into a file, and save a copy of the source files if the boolean is true *)
(** {2 Functions for manipulating an interprocedural CFG} *) (** {2 Functions for manipulating an interprocedural CFG} *)
(** create a new empty cfg *)
val create_cfg : unit -> cfg val create_cfg : unit -> cfg
(** create a new empty cfg *)
(** Create a new procdesc *)
val create_proc_desc : cfg -> ProcAttributes.t -> Procdesc.t val create_proc_desc : cfg -> ProcAttributes.t -> Procdesc.t
(** Create a new procdesc *)
(** Iterate over all the procdesc's *)
val iter_proc_desc : cfg -> (Typ.Procname.t -> Procdesc.t -> unit) -> unit val iter_proc_desc : cfg -> (Typ.Procname.t -> Procdesc.t -> unit) -> unit
(** Iterate over all the procdesc's *)
(** Find the procdesc given the proc name. Return None if not found. *)
val find_proc_desc_from_name : cfg -> Typ.Procname.t -> Procdesc.t option val find_proc_desc_from_name : cfg -> Typ.Procname.t -> Procdesc.t option
(** Find the procdesc given the proc name. Return None if not found. *)
(** Get all the procedures (defined and declared) *)
val get_all_procs : cfg -> Procdesc.t list val get_all_procs : cfg -> Procdesc.t list
(** Get all the procedures (defined and declared) *)
(** Get the procedures whose body is defined in this cfg *)
val get_defined_procs : cfg -> Procdesc.t list val get_defined_procs : cfg -> Procdesc.t list
(** Get the procedures whose body is defined in this cfg *)
(** Iterate over all the nodes in the cfg *)
val iter_all_nodes : ?sorted:bool -> (Procdesc.t -> Procdesc.Node.t -> unit) -> cfg -> unit val iter_all_nodes : ?sorted:bool -> (Procdesc.t -> Procdesc.Node.t -> unit) -> cfg -> unit
(** Iterate over all the nodes in the cfg *)
(** checks whether a cfg is connected or not *)
val check_cfg_connectedness : cfg -> unit val check_cfg_connectedness : cfg -> unit
(** checks whether a cfg is connected or not *)
(** Remove the procdesc from the control flow graph. *)
val remove_proc_desc : cfg -> Typ.Procname.t -> unit val remove_proc_desc : cfg -> Typ.Procname.t -> unit
(** Remove the procdesc from the control flow graph. *)
val specialize_types : Procdesc.t -> Typ.Procname.t -> (Exp.t * Typ.t) list -> Procdesc.t
(** Creates a copy of a procedure description and a list of type substitutions of the form (** Creates a copy of a procedure description and a list of type substitutions of the form
(name, typ) where name is a parameter. The resulting procdesc is isomorphic but (name, typ) where name is a parameter. The resulting procdesc is isomorphic but
all the type of the parameters are replaced in the instructions according to the list. all the type of the parameters are replaced in the instructions according to the list.
The virtual calls are also replaced to match the parameter types *) The virtual calls are also replaced to match the parameter types *)
val specialize_types : Procdesc.t -> Typ.Procname.t -> (Exp.t * Typ.t) list -> Procdesc.t
val pp_proc_signatures : Format.formatter -> cfg -> unit val pp_proc_signatures : Format.formatter -> cfg -> unit

@ -9,6 +9,7 @@
*) *)
(** Module for call graphs *) (** Module for call graphs *)
open! IStd open! IStd
module Hashtbl = Caml.Hashtbl module Hashtbl = Caml.Hashtbl
module L = Logging module L = Logging
@ -21,19 +22,19 @@ type in_out_calls =
; out_calls: int (** total number of out calls transitively *) } ; out_calls: int (** total number of out calls transitively *) }
type node_info = type node_info =
{ (** defined procedure as opposed to just declared *) { mutable defined: bool (** defined procedure as opposed to just declared *)
mutable defined: bool
; mutable parents: Typ.Procname.Set.t ; mutable parents: Typ.Procname.Set.t
; mutable children: Typ.Procname.Set.t (** ancestors are computed lazily *) ; mutable children: Typ.Procname.Set.t
; mutable ancestors: Typ.Procname.Set.t option (** heirs are computed lazily *) ; mutable ancestors: Typ.Procname.Set.t option (** ancestors are computed lazily *)
; mutable heirs: Typ.Procname.Set.t option (** recursive dependents are computed lazily *) ; mutable heirs: Typ.Procname.Set.t option (** heirs are computed lazily *)
; mutable recursive_dependents: Typ.Procname.Set.t option (** calls are computed lazily *) ; mutable recursive_dependents: Typ.Procname.Set.t option
; mutable in_out_calls: in_out_calls option } (** recursive dependents are computed lazily *)
; mutable in_out_calls: in_out_calls option (** calls are computed lazily *) }
(** Type for call graph *) (** Type for call graph *)
type t = type t =
{ source: SourceFile.t (** path for the source file *) { source: SourceFile.t (** path for the source file *)
; node_map: (** map from node to node_info *) node_info Typ.Procname.Hash.t } ; node_map: node_info Typ.Procname.Hash.t (** map from node to node_info *) }
let create source = {source; node_map= Typ.Procname.Hash.create 3} let create source = {source; node_map= Typ.Procname.Hash.create 3}

@ -16,9 +16,8 @@ type in_out_calls =
{ in_calls: int (** total number of in calls transitively *) { in_calls: int (** total number of in calls transitively *)
; out_calls: int (** total number of out calls transitively *) } ; out_calls: int (** total number of out calls transitively *) }
type t
(** the type of a call graph *) (** the type of a call graph *)
type t
(** A call graph consists of a set of nodes (Typ.Procname.t), and edges between them. (** A call graph consists of a set of nodes (Typ.Procname.t), and edges between them.
A node can be defined or undefined (to represent whether we have code for it). A node can be defined or undefined (to represent whether we have code for it).
@ -27,101 +26,77 @@ type t
Node [n1] is dependent on [n2] if there is a path from [n1] to [n2] Node [n1] is dependent on [n2] if there is a path from [n1] to [n2]
using the child relationship. *) using the child relationship. *)
val add_edge : t -> Typ.Procname.t -> Typ.Procname.t -> unit
(** [add_edge cg f t] adds an edge from [f] to [t] in the call graph [cg]. (** [add_edge cg f t] adds an edge from [f] to [t] in the call graph [cg].
The nodes are also added as undefined, unless already present. *) The nodes are also added as undefined, unless already present. *)
val add_edge : t -> Typ.Procname.t -> Typ.Procname.t -> unit
(** Add a node to the call graph as defined *)
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 *)
(** Check if [source] recursively calls [dest] *)
val calls_recursively : t -> Typ.Procname.t -> Typ.Procname.t -> bool val calls_recursively : t -> Typ.Procname.t -> Typ.Procname.t -> bool
(** Check if [source] recursively calls [dest] *)
(** Create an empty call graph *)
val create : SourceFile.t -> t val create : SourceFile.t -> t
(** Create an empty call graph *)
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 extend : t -> t -> unit
(** Return all the children of [n], whether defined or not *)
val get_all_children : t -> Typ.Procname.t -> Typ.Procname.Set.t val get_all_children : t -> Typ.Procname.t -> Typ.Procname.Set.t
(** Return all the children of [n], whether defined or not *)
(** Compute the ancestors of the node, if not pre-computed already *)
val get_ancestors : t -> Typ.Procname.t -> Typ.Procname.Set.t val get_ancestors : t -> Typ.Procname.t -> Typ.Procname.Set.t
(** Compute the ancestors of the node, if not pre-computed already *)
(** Compute the heirs of the node, if not pre-computed already *)
val get_heirs : t -> Typ.Procname.t -> Typ.Procname.Set.t val get_heirs : t -> Typ.Procname.t -> Typ.Procname.Set.t
(** Compute the heirs of the node, if not pre-computed already *)
(** Return the in/out calls of the node *)
val get_calls : t -> Typ.Procname.t -> in_out_calls val get_calls : t -> Typ.Procname.t -> in_out_calls
(** Return the in/out calls of the node *)
(** Return the list of nodes which are defined *)
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 children of [n] which are defined *)
val get_defined_children : t -> Typ.Procname.t -> Typ.Procname.Set.t val get_defined_children : t -> Typ.Procname.t -> Typ.Procname.Set.t
(** Return the children of [n] which are defined *)
(** Return the nodes dependent on [n] *)
val get_dependents : t -> Typ.Procname.t -> Typ.Procname.Set.t val get_dependents : t -> Typ.Procname.t -> Typ.Procname.Set.t
(** Return the nodes dependent on [n] *)
(** Return the list of nodes with calls *)
val get_nodes_and_calls : t -> (Typ.Procname.t * in_out_calls) list val get_nodes_and_calls : t -> (Typ.Procname.t * in_out_calls) list
(** Return the list of nodes with calls *)
(** Return all the nodes with their defined children *)
val get_nodes_and_defined_children : t -> (Typ.Procname.t * Typ.Procname.Set.t) list val get_nodes_and_defined_children : t -> (Typ.Procname.t * Typ.Procname.Set.t) list
(** Return all the nodes with their defined children *)
(** Return the list of nodes, with defined flag, and the list of edges *)
val get_nodes_and_edges : val get_nodes_and_edges :
t -> (Typ.Procname.t * bool) list * (Typ.Procname.t * Typ.Procname.t) list 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 *)
(** Return the children of [n] which are not heirs of [n] and are defined *)
val get_nonrecursive_dependents : t -> Typ.Procname.t -> Typ.Procname.Set.t 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 *)
(** Return the parents of [n] *)
val get_parents : t -> Typ.Procname.t -> Typ.Procname.Set.t val get_parents : t -> Typ.Procname.t -> Typ.Procname.Set.t
(** Return the parents of [n] *)
(** Return the ancestors of [n] which are also heirs of [n] *)
val get_recursive_dependents : t -> Typ.Procname.t -> Typ.Procname.Set.t val get_recursive_dependents : t -> Typ.Procname.t -> Typ.Procname.Set.t
(** Return the ancestors of [n] which are also heirs of [n] *)
(** Return the path of the source file *)
val get_source : t -> SourceFile.t val get_source : t -> SourceFile.t
(** Return the path of the source file *)
(** Load a call graph from a file *)
val load_from_file : DB.filename -> t option val load_from_file : DB.filename -> t option
(** Load a call graph from a file *)
(** Returns true if the node is defined *)
val node_defined : t -> Typ.Procname.t -> bool val node_defined : t -> Typ.Procname.t -> bool
(** Returns true if the node is defined *)
(** Remove the defined flag from a node, if it exists. *)
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. *)
(** Print the call graph as a dotty file. *)
val save_call_graph_dotty : SourceFile.t -> t -> unit val save_call_graph_dotty : SourceFile.t -> t -> unit
(** Print the call graph as a dotty file. *)
(** Save a call graph into a file *)
val store_to_file : DB.filename -> t -> unit val store_to_file : DB.filename -> t -> unit
(** Save a call graph into a file *)

@ -9,6 +9,7 @@
*) *)
(** The Smallfoot Intermediate Language: Constants *) (** The Smallfoot Intermediate Language: Constants *)
open! IStd open! IStd
module L = Logging module L = Logging
module F = Format module F = Format

@ -9,12 +9,12 @@
*) *)
(** The Smallfoot Intermediate Language: Constants *) (** The Smallfoot Intermediate Language: Constants *)
open! IStd open! IStd
module L = Logging module L = Logging
module F = Format module F = Format
(** Constants *) (** Constants *)
type t = type t =
| Cint of IntLit.t (** integer constants *) | Cint of IntLit.t (** integer constants *)
| Cfun of Typ.Procname.t (** function names *) | Cfun of Typ.Procname.t (** function names *)
@ -25,13 +25,11 @@ type t =
val equal : t -> t -> bool val equal : t -> t -> bool
(** Return true if the constants have the same kind (both integers, ...) *)
val kind_equal : t -> t -> bool val kind_equal : t -> t -> bool
(** Return true if the constants have the same kind (both integers, ...) *)
(** Pretty print a const *)
val pp : Pp.env -> F.formatter -> t -> unit val pp : Pp.env -> F.formatter -> t -> unit
(** Pretty print a const *)
val to_string : t -> string val to_string : t -> string

@ -9,6 +9,7 @@
*) *)
(** The Smallfoot Intermediate Language: Decompiled Expressions *) (** The Smallfoot Intermediate Language: Decompiled Expressions *)
open! IStd open! IStd
module L = Logging module L = Logging
module F = Format module F = Format

@ -9,12 +9,12 @@
*) *)
(** The Smallfoot Intermediate Language: Decompiled Expressions *) (** The Smallfoot Intermediate Language: Decompiled Expressions *)
open! IStd open! IStd
module L = Logging module L = Logging
module F = Format module F = Format
(** expression representing the result of decompilation *) (** expression representing the result of decompilation *)
type t = type t =
| Darray of t * t | Darray of t * t
| Dbinop of Binop.t * t * t | Dbinop of Binop.t * t * t
@ -32,21 +32,16 @@ type t =
(** Value paths: identify an occurrence of a value in a symbolic heap (** Value paths: identify an occurrence of a value in a symbolic heap
each expression represents a path, with Dpvar being the simplest one *) each expression represents a path, with Dpvar being the simplest one *)
type vpath = t option type vpath = t option
(** convert to a string *)
val to_string : t -> string val to_string : t -> string
(** convert to a string *)
(** pretty print *)
val pp : F.formatter -> t -> unit val pp : F.formatter -> t -> unit
(** pretty print *)
(** Pretty print a value path *)
val pp_vpath : Pp.env -> F.formatter -> vpath -> unit val pp_vpath : Pp.env -> F.formatter -> vpath -> unit
(** Pretty print a value path *)
(** return true if [dexp] contains a temporary pvar *)
val has_tmp_var : t -> bool val has_tmp_var : t -> bool
(** return true if [dexp] contains a temporary pvar *)

@ -9,6 +9,7 @@
*) *)
(** The Smallfoot Intermediate Language: Expressions *) (** The Smallfoot Intermediate Language: Expressions *)
open! IStd open! IStd
module Hashtbl = Caml.Hashtbl module Hashtbl = Caml.Hashtbl
module L = Logging module L = Logging
@ -35,17 +36,17 @@ and sizeof_data = {typ: Typ.t; nbytes: int option; dynamic_length: t option; sub
(** Program expressions. *) (** Program expressions. *)
and t = and t =
(** Pure variable: it is not an lvalue *) | Var of _ident (** Pure variable: it is not an lvalue *)
| Var of _ident (** Unary operator with type of the result if known *) | UnOp of Unop.t * t * Typ.t option (** Unary operator with type of the result if known *)
| UnOp of Unop.t * t * Typ.t option (** Binary operator *) | BinOp of Binop.t * t * t (** Binary operator *)
| BinOp of Binop.t * t * t (** Exception *) | Exn of t (** Exception *)
| Exn of t (** Anonymous function *) | Closure of closure (** Anonymous function *)
| Closure of closure (** Constants *) | Const of Const.t (** Constants *)
| Const of Const.t (** Type cast *) | Cast of Typ.t * t (** Type cast *)
| Cast of Typ.t * t (** The address of a program variable *) | Lvar of Pvar.t (** The address of a program variable *)
| Lvar of Pvar.t (** A field offset, the type is the surrounding struct type *) | Lfield of t * Typ.Fieldname.t * Typ.t
| Lfield of t * Typ.Fieldname.t * Typ.t (** An array index offset: [exp1\[exp2\]] *) (** A field offset, the type is the surrounding struct type *)
| Lindex of t * t | Lindex of t * t (** An array index offset: [exp1\[exp2\]] *)
| Sizeof of sizeof_data | Sizeof of sizeof_data
[@@deriving compare] [@@deriving compare]

@ -9,6 +9,7 @@
*) *)
(** The Smallfoot Intermediate Language: Expressions *) (** The Smallfoot Intermediate Language: Expressions *)
open! IStd open! IStd
module L = Logging module L = Logging
module F = Format module F = Format
@ -29,128 +30,103 @@ and sizeof_data = {typ: Typ.t; nbytes: int option; dynamic_length: t option; sub
(** Program expressions. *) (** Program expressions. *)
and t = and t =
(** Pure variable: it is not an lvalue *) | Var of Ident.t (** Pure variable: it is not an lvalue *)
| Var of Ident.t (** Unary operator with type of the result if known *) | UnOp of Unop.t * t * Typ.t option (** Unary operator with type of the result if known *)
| UnOp of Unop.t * t * Typ.t option (** Binary operator *) | BinOp of Binop.t * t * t (** Binary operator *)
| BinOp of Binop.t * t * t (** Exception *) | Exn of t (** Exception *)
| Exn of t (** Anonymous function *) | Closure of closure (** Anonymous function *)
| Closure of closure (** Constants *) | Const of Const.t (** Constants *)
| Const of Const.t (** Type cast *) | Cast of Typ.t * t (** Type cast *)
| Cast of Typ.t * t (** The address of a program variable *) | Lvar of Pvar.t (** The address of a program variable *)
| Lvar of Pvar.t (** A field offset, the type is the surrounding struct type *) | Lfield of t * Typ.Fieldname.t * Typ.t
| Lfield of t * Typ.Fieldname.t * Typ.t (** An array index offset: [exp1\[exp2\]] *) (** A field offset, the type is the surrounding struct type *)
| Lindex of t * t | Lindex of t * t (** An array index offset: [exp1\[exp2\]] *)
| Sizeof of sizeof_data | Sizeof of sizeof_data
[@@deriving compare] [@@deriving compare]
(** Equality for expressions. *)
val equal : t -> t -> bool val equal : t -> t -> bool
(** Equality for expressions. *)
(** Hash function for expressions. *)
val hash : t -> int 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
(** Map with expression keys. *) (** Map with expression keys. *)
module Map : Caml.Map.S with type key = t 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
(** returns true is index is an array index of arr. *)
val is_array_index_of : t -> t -> bool 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
(** return true if [exp] is the special this/self expression *)
val is_this : t -> bool val is_this : t -> bool
(** return true if [exp] is the special this/self expression *)
val is_zero : t -> bool val is_zero : t -> bool
(** {2 Utility Functions for Expressions} *) (** {2 Utility Functions for Expressions} *)
val texp_to_typ : Typ.t option -> t -> Typ.t
(** Turn an expression representing a type into the type it represents (** Turn an expression representing a type into the type it represents
If not a sizeof, return the default type if given, otherwise raise an exception *) If not a sizeof, return the default type if given, otherwise raise an exception *)
val texp_to_typ : Typ.t option -> t -> Typ.t
(** Return the root of [lexp]. *)
val root_of_lexp : t -> t val root_of_lexp : t -> t
(** Return the root of [lexp]. *)
val get_undefined : bool -> t
(** Get an expression "undefined", the boolean indicates (** Get an expression "undefined", the boolean indicates
whether the undefined value goest into the footprint *) whether the undefined value goest into the footprint *)
val get_undefined : bool -> t 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 pointer_arith : t -> bool
(** returns true if the expression represents a stack-directed address *)
val is_stack_addr : t -> bool val is_stack_addr : t -> bool
(** returns true if the expression represents a stack-directed address *)
(** returns true if the expression operates on address of local variable *)
val has_local_addr : t -> bool val has_local_addr : t -> bool
(** returns true if the expression operates on address of local variable *)
(** Integer constant 0 *)
val zero : t val zero : t
(** Integer constant 0 *)
(** Null constant *)
val null : t val null : t
(** Null constant *)
(** Integer constant 1 *)
val one : t val one : t
(** Integer constant 1 *)
(** Integer constant -1 *)
val minus_one : t val minus_one : t
(** Integer constant -1 *)
(** Create integer constant *)
val int : IntLit.t -> t val int : IntLit.t -> t
(** Create integer constant *)
(** Create float constant *)
val float : float -> t val float : float -> t
(** Create float constant *)
(** Create integer constant corresponding to the boolean value *)
val bool : bool -> t val bool : bool -> t
(** Create integer constant corresponding to the boolean value *)
(** Create expresstion [e1 == e2] *)
val eq : t -> t -> t val eq : t -> t -> t
(** Create expresstion [e1 == e2] *)
(** Create expresstion [e1 != e2] *)
val ne : t -> t -> t val ne : t -> t -> t
(** Create expresstion [e1 != e2] *)
(** Create expresstion [e1 <= e2] *)
val le : t -> t -> t val le : t -> t -> t
(** Create expresstion [e1 <= e2] *)
(** Create expression [e1 < e2] *)
val lt : t -> t -> t val lt : t -> t -> t
(** Create expression [e1 < e2] *)
(** Extract the ids and pvars from an expression *)
val get_vars : t -> Ident.t list * Pvar.t list val get_vars : t -> Ident.t list * Pvar.t list
(** Extract the ids and pvars from an expression *)
val pp_printenv : Pp.env -> (Pp.env -> F.formatter -> Typ.t -> unit) -> F.formatter -> t -> unit val pp_printenv : Pp.env -> (Pp.env -> F.formatter -> Typ.t -> unit) -> F.formatter -> t -> unit

@ -9,6 +9,7 @@
*) *)
(** Module for Names and Identifiers *) (** Module for Names and Identifiers *)
open! IStd open! IStd
module Hashtbl = Caml.Hashtbl module Hashtbl = Caml.Hashtbl
module L = Logging module L = Logging

@ -8,65 +8,52 @@
* of patent rights can be found in the PATENTS file in the same directory. * of patent rights can be found in the PATENTS file in the same directory.
*) *)
open! IStd
(** Identifiers: program variables and logical variables *) (** Identifiers: program variables and logical variables *)
(** Program and logical variables. *) open! IStd
(** Program and logical variables. *)
type t [@@deriving compare] type t [@@deriving compare]
(** Equality for identifiers. *)
val equal : t -> t -> bool val equal : t -> t -> bool
(** Equality for identifiers. *)
(** Names used to replace strings. *) (** Names used to replace strings. *)
type name [@@deriving compare] type name [@@deriving compare]
(** Equality for names. *)
val equal_name : name -> name -> bool val equal_name : name -> name -> bool
(** Equality for names. *)
(** Kind of identifiers. *) (** Kind of identifiers. *)
type kind [@@deriving compare] type kind [@@deriving compare]
(** Equality for kind. *)
val equal_kind : kind -> kind -> bool val equal_kind : kind -> kind -> bool
(** Equality for kind. *)
(** Set for identifiers. *) (** Set for identifiers. *)
module IdentSet : Caml.Set.S with type elt = t module IdentSet : Caml.Set.S with type elt = t
(** Hash table with ident as key. *) (** Hash table with ident as key. *)
module IdentHash : Caml.Hashtbl.S with type key = t module IdentHash : Caml.Hashtbl.S with type key = t
(** Map with ident as key. *) (** Map with ident as key. *)
module IdentMap : Caml.Map.S with type key = t module IdentMap : Caml.Map.S with type key = t
module NameGenerator : sig module NameGenerator : sig
type t type t
(** Get the current name generator. *)
val get_current : unit -> t val get_current : unit -> t
(** Get the current name generator. *)
(** Reset the name generator. *)
val reset : unit -> unit val reset : unit -> unit
(** Reset the name generator. *)
(** Set the current name generator. *)
val set_current : t -> unit val set_current : t -> unit
(** Set the current name generator. *)
end end
(** Convert an identfier list to an identifier set *)
val idlist_to_idset : t list -> IdentSet.t val idlist_to_idset : t list -> IdentSet.t
(** Convert an identfier list to an identifier set *)
val kprimed : kind val kprimed : kind
@ -75,119 +62,90 @@ val knormal : kind
val kfootprint : kind 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
(** Name used for primed tmp variables *)
val name_primed : name val name_primed : name
(** Name used for primed tmp variables *)
(** Name used for spec variables *)
val name_spec : name val name_spec : name
(** Name used for spec variables *)
(** Name used for the return variable *)
val name_return : Mangled.t val name_return : Mangled.t
(** Name used for the return variable *)
(** Convert a string to a name. *)
val string_to_name : string -> name val string_to_name : string -> name
(** Convert a string to a name. *)
(** Convert a name to a string. *)
val name_to_string : name -> string val name_to_string : name -> string
(** Convert a name to a string. *)
(** Name of the identifier. *)
val get_name : t -> name val get_name : t -> name
(** Name of the identifier. *)
(** Create an identifier with default name for the given kind *)
val create : kind -> int -> t val create : kind -> int -> t
(** Create an identifier with default name for the given kind *)
(** Generate a normal identifier with the given name and stamp. *)
val create_normal : name -> int -> t val create_normal : name -> int -> t
(** Generate a normal identifier with the given name and stamp. *)
(** Create a "null" identifier for situations where the IR requires an id that will never be read *)
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 *)
(** Generate a primed identifier with the given name and stamp. *)
val create_primed : name -> int -> t val create_primed : name -> int -> t
(** Generate a primed identifier with the given name and stamp. *)
(** Generate a footprint 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. *)
(** Update the name generator so that the given id's are not generated again *)
val update_name_generator : t list -> unit val update_name_generator : t list -> unit
(** Update the name generator so that the given id's are not generated again *)
(** Create a fresh identifier with default name for the given kind. *)
val create_fresh : kind -> t val create_fresh : kind -> t
(** Create a fresh identifier with default name for the given kind. *)
(** Generate a normal identifier whose name encodes a path given as a string. *)
val create_path : string -> t val create_path : string -> t
(** Generate a normal identifier whose name encodes a path given as a string. *)
(** Check whether an identifier is primed or not. *)
val is_primed : t -> bool val is_primed : t -> bool
(** Check whether an identifier is primed or not. *)
(** Check whether an identifier is normal or not. *)
val is_normal : t -> bool val is_normal : t -> bool
(** Check whether an identifier is normal or not. *)
(** Check whether an identifier is footprint or not. *)
val is_footprint : t -> bool val is_footprint : t -> bool
(** Check whether an identifier is footprint or not. *)
(** Check whether an identifier represents a path or not. *)
val is_path : t -> bool val is_path : t -> bool
(** Check whether an identifier represents a path or not. *)
(** Check whether an identifier is the special "none" identifier *)
val is_none : t -> bool val is_none : t -> bool
(** Check whether an identifier is the special "none" identifier *)
(** Convert a primed ident into a nonprimed one, keeping the stamp. *)
val make_unprimed : t -> t val make_unprimed : t -> t
(** Convert a primed ident into a nonprimed one, keeping the stamp. *)
(** Get the stamp of the identifier *)
val get_stamp : t -> int val get_stamp : t -> int
(** Get the stamp of the identifier *)
(** Set the stamp of the identifier *)
val set_stamp : t -> int -> t val set_stamp : t -> int -> t
(** Set the stamp of the identifier *)
(** {2 Pretty Printing} *) (** {2 Pretty Printing} *)
(** Pretty print a name. *)
val pp_name : Format.formatter -> name -> unit val pp_name : Format.formatter -> name -> unit
(** Pretty print a name. *)
(** Pretty print a name in latex. *)
val pp_name_latex : Latex.style -> Format.formatter -> name -> unit val pp_name_latex : Latex.style -> Format.formatter -> name -> unit
(** Pretty print a name in latex. *)
(** Pretty print an identifier. *)
val pp : Pp.env -> Format.formatter -> t -> unit val pp : Pp.env -> Format.formatter -> t -> unit
(** Pretty print an identifier. *)
(** Convert an identifier to a string. *)
val to_string : t -> string val to_string : t -> string
(** Convert an identifier to a string. *)
(** Pretty print a list of identifiers. *)
val pp_list : Pp.env -> Format.formatter -> t list -> unit val pp_list : Pp.env -> Format.formatter -> t list -> unit
(** Pretty print a list of identifiers. *)
(** Pretty print a list of names. *)
val pp_name_list : Format.formatter -> name list -> unit val pp_name_list : Format.formatter -> name list -> unit
(** Pretty print a list of names. *)

@ -10,29 +10,24 @@
open! IStd open! IStd
module F = Format module F = Format
(* the first bool indicates whether this is an unsigned value,
and the second whether it is a pointer *)
(** signed and unsigned integer literals *) (** signed and unsigned integer literals *)
type t = bool * Int64.t * bool type t = bool * Int64.t * bool
(* the first bool indicates whether this is an unsigned value,
and the second whether it is a pointer *)
let area u i = let area u i =
match (i < 0L, u) with match (i < 0L, u) with
| true, false | true, false
-> 1 -> (* only representable as signed *) 1
(* only representable as signed *)
| false, _ | false, _
-> 2 -> (* in the intersection between signed and unsigned *) 2
(* in the intersection between signed and unsigned *)
| true, true | true, true
-> 3 -> (* only representable as unsigned *) 3
(* only representable as unsigned *)
let to_signed (unsigned, i, ptr) = let to_signed (unsigned, i, ptr) =
if Int.equal (area unsigned i) 3 then None if Int.equal (area unsigned i) 3 then None
else Some (* not representable as signed *) else (* not representable as signed *) Some (false, i, ptr)
(false, i, ptr)
let compare (unsigned1, i1, _) (unsigned2, i2, _) = let compare (unsigned1, i1, _) (unsigned2, i2, _) =
let n = Bool.compare unsigned1 unsigned2 in let n = Bool.compare unsigned1 unsigned2 in

@ -12,20 +12,17 @@ open! IStd
module F = Format module F = Format
(** signed and unsigned integer literals *) (** signed and unsigned integer literals *)
type t type t
val add : t -> t -> t val add : t -> t -> t
(** compare integers ignoring the distinction between pointers and non-pointers *)
val compare : t -> t -> int val compare : t -> t -> int
(** compare integers ignoring the distinction between pointers and non-pointers *)
val compare_value : t -> t -> int
(** compare the value of the integers, notice this is different from const compare, (** compare the value of the integers, notice this is different from const compare,
which distinguished between signed and unsigned +1 *) which distinguished between signed and unsigned +1 *)
val compare_value : t -> t -> int
val div : t -> t -> t val div : t -> t -> t
val eq : t -> t -> bool val eq : t -> t -> bool
@ -73,7 +70,6 @@ val neg : t -> t
val neq : t -> t -> bool val neq : t -> t -> bool
val null : t val null : t
(** null behaves like zero except for the function isnull *) (** null behaves like zero except for the function isnull *)
val one : t val one : t
@ -88,9 +84,8 @@ val to_int : t -> int
val to_signed : t -> t option val to_signed : t -> t option
(** convert to signed if the value is representable *)
val to_string : t -> string val to_string : t -> string
(** convert to signed if the value is representable *)
val two : t val two : t

@ -181,13 +181,11 @@ module Tags : sig
val tag_value_records_of_tags : t -> Jsonbug_t.tag_value_record list val tag_value_records_of_tags : t -> Jsonbug_t.tag_value_record list
(** convert error description's tags to atd-serializable format *) (** convert error description's tags to atd-serializable format *)
(* convert atd-serializable format to error description's tags *)
val tags_of_tag_value_records : Jsonbug_t.tag_value_record list -> t val tags_of_tag_value_records : Jsonbug_t.tag_value_record list -> t
(** convert atd-serializable format to error description's tags *)
(* collect all lines from tags *)
val lines_of_tags : t -> int list val lines_of_tags : t -> int list
(** collect all lines from tags *)
end end
(** description field of error messages *) (** description field of error messages *)
@ -209,8 +207,7 @@ val custom_desc_with_advice : string -> string -> (string * string) list -> erro
module BucketLevel : sig module BucketLevel : sig
val b1 : string val b1 : string
(** highest likelyhood *)
(* highest likelyhood *)
val b2 : string val b2 : string
@ -219,7 +216,7 @@ module BucketLevel : sig
val b4 : string val b4 : string
val b5 : string val b5 : string
(* lowest likelyhood *) (** lowest likelyhood *)
end end
val error_desc_extract_tag_value : error_desc -> string -> string val error_desc_extract_tag_value : error_desc -> string -> string
@ -295,10 +292,8 @@ val deref_str_pointer_size_mismatch : Typ.t -> Typ.t -> deref_str
(** type of access *) (** type of access *)
type access = type access =
| Last_assigned of int * bool | Last_assigned of int * bool (** line, null_case_flag *)
(* line, null_case_flag *) | Last_accessed of int * bool (** line, is_nullable flag *)
| Last_accessed of int * bool
(* line, is_nullable flag *)
| Initialized_automatically | Initialized_automatically
| Returned_from_call of int | Returned_from_call of int
@ -358,9 +353,8 @@ val desc_context_leak :
val desc_fragment_retains_view : Typ.t -> Typ.Fieldname.t -> Typ.t -> Typ.Procname.t -> error_desc val desc_fragment_retains_view : Typ.t -> Typ.Fieldname.t -> Typ.t -> Typ.Procname.t -> error_desc
(* Create human-readable error description for assertion failures *)
val desc_custom_error : Location.t -> error_desc val desc_custom_error : Location.t -> error_desc
(** Create human-readable error description for assertion failures *)
(** kind of precondition not met *) (** kind of precondition not met *)
type pnm_kind = Pnm_bounds | Pnm_dangling type pnm_kind = Pnm_bounds | Pnm_dangling

@ -10,7 +10,6 @@
open! IStd open! IStd
(** Location in the original source file *) (** Location in the original source file *)
type t = type t =
{ line: int (** The line number. -1 means "do not know" *) { line: int (** The line number. -1 means "do not know" *)
; col: int (** The column number. -1 means "do not know" *) ; col: int (** The column number. -1 means "do not know" *)
@ -19,26 +18,20 @@ type t =
val equal : t -> t -> bool val equal : t -> t -> bool
(** Dump a location. *)
val d : t -> unit val d : t -> unit
(** Dump a location. *)
(** Dummy source location for the given file *)
val none : SourceFile.t -> t val none : SourceFile.t -> t
(** Dummy source location for the given file *)
(** Dummy location with no source file *)
val dummy : t val dummy : t
(** Dummy location with no source file *)
(** Pretty print a location. *)
val pp : Format.formatter -> t -> unit val pp : Format.formatter -> t -> unit
(** Pretty print a location. *)
(** String representation of a location. *)
val to_string : t -> string val to_string : t -> string
(** String representation of a location. *)
(** Pretty print a file-position of a location *)
val pp_file_pos : Format.formatter -> t -> unit val pp_file_pos : Format.formatter -> t -> unit
(** Pretty print a file-position of a location *)

@ -9,6 +9,7 @@
*) *)
(** Module for Mangled Names *) (** Module for Mangled Names *)
open! IStd open! IStd
module F = Format module F = Format

@ -13,41 +13,31 @@ open! IStd
(** Module for Mangled Names *) (** Module for Mangled Names *)
(** Type of mangled names *) (** Type of mangled names *)
type t [@@deriving compare] type t [@@deriving compare]
(** Equality for mangled names *)
val equal : t -> t -> bool val equal : t -> t -> bool
(** Equality for mangled names *)
(** Convert a string to a mangled name *)
val from_string : string -> t val from_string : string -> t
(** Convert a string to a mangled name *)
(** Create a mangled name from a plain and mangled string *)
val mangled : string -> string -> t val mangled : string -> string -> t
(** Create a mangled name from a plain and mangled string *)
(** Convert a mangled name to a string *)
val to_string : t -> string val to_string : t -> string
(** Convert a mangled name to a string *)
(** Convert a full mangled name to a string *)
val to_string_full : t -> string val to_string_full : t -> string
(** Convert a full mangled name to a string *)
(** Get mangled string if given *)
val get_mangled : t -> string val get_mangled : t -> string
(** Get mangled string if given *)
(** Pretty print a mangled name *)
val pp : Format.formatter -> t -> unit val pp : Format.formatter -> t -> unit
(** Pretty print a mangled name *)
(** Set of Mangled. *) (** Set of Mangled. *)
module Set : Caml.Set.S with type elt = t module Set : Caml.Set.S with type elt = t
(** Map with Mangled as key *) (** Map with Mangled as key *)
module Map : Caml.Map.S with type key = t module Map : Caml.Map.S with type key = t

@ -9,9 +9,6 @@
open! IStd open! IStd
(** This module models special c struct types from the Apple's Core Foundation libraries
for which there are particular rules for memory management. *)
(** 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. *)

@ -9,6 +9,7 @@
*) *)
(** The Smallfoot Intermediate Language: Predicate Symbols *) (** The Smallfoot Intermediate Language: Predicate Symbols *)
open! IStd open! IStd
module L = Logging module L = Logging
module F = Format module F = Format
@ -47,12 +48,11 @@ let equal_res_act_kind = [%compare.equal : res_act_kind]
(** kind of dangling pointers *) (** kind of dangling pointers *)
type dangling_kind = type dangling_kind =
(** pointer is dangling because it is uninitialized *) | DAuninit (** pointer is dangling because it is uninitialized *)
| DAuninit | DAaddr_stack_var
(** pointer is dangling because it is the address (** pointer is dangling because it is the address
of a stack variable which went out of scope *) of a stack variable which went out of scope *)
| DAaddr_stack_var (** pointer is -1 *) | DAminusone (** pointer is -1 *)
| DAminusone
[@@deriving compare] [@@deriving compare]
(** position in a path: proc name, node id *) (** position in a path: proc name, node id *)
@ -107,20 +107,20 @@ type t =
| Aresource of res_action (** resource acquire/release *) | Aresource of res_action (** resource acquire/release *)
| Aautorelease | Aautorelease
| Adangling of dangling_kind (** dangling pointer *) | Adangling of dangling_kind (** dangling pointer *)
(** undefined value obtained by calling the given procedure, plus its return value annots *)
| Aundef of Typ.Procname.t * _annot_item * _location * _path_pos | Aundef of Typ.Procname.t * _annot_item * _location * _path_pos
(** undefined value obtained by calling the given procedure, plus its return value annots *)
| Ataint of taint_info | Ataint of taint_info
| Auntaint of taint_info | Auntaint of taint_info
| Alocked | Alocked
| Aunlocked (** value appeared in second argument of division at given path position *) | Aunlocked
| Adiv0 of path_pos | Adiv0 of path_pos (** value appeared in second argument of division at given path position *)
(** attributed exp is null due to a call to a method with given path as null receiver *)
| Aobjc_null | Aobjc_null
(** value was returned from a call to the given procedure, plus the annots of the return value *) (** attributed exp is null due to a call to a method with given path as null receiver *)
| Aretval of Typ.Procname.t * Annot.Item.t | Aretval of Typ.Procname.t * Annot.Item.t
(** denotes an object registered as an observers to a notification center *) (** value was returned from a call to the given procedure, plus the annots of the return value *)
| Aobserver (** denotes an object unsubscribed from observers of a notification center *) | Aobserver (** denotes an object registered as an observers to a notification center *)
| Aunsubscribed_observer | Aunsubscribed_observer
(** denotes an object unsubscribed from observers of a notification center *)
[@@deriving compare] [@@deriving compare]
let equal = [%compare.equal : t] let equal = [%compare.equal : t]

@ -9,6 +9,7 @@
*) *)
(** The Smallfoot Intermediate Language: Predicate Symbols *) (** The Smallfoot Intermediate Language: Predicate Symbols *)
open! IStd open! IStd
module L = Logging module L = Logging
module F = Format module F = Format
@ -17,12 +18,10 @@ module F = Format
type func_attribute = FA_sentinel of int * int [@@deriving compare] type func_attribute = FA_sentinel of int * int [@@deriving compare]
(** Return the value of the FA_sentinel attribute in [attr_list] if it is found *)
val get_sentinel_func_attribute_value : func_attribute list -> (int * int) option val get_sentinel_func_attribute_value : func_attribute list -> (int * int) option
(** Return the value of the FA_sentinel attribute in [attr_list] if it is found *)
(** Visibility modifiers. *) (** Visibility modifiers. *)
type access = Default | Public | Private | Protected [@@deriving compare] type access = Default | Public | Private | Protected [@@deriving compare]
val equal_access : access -> access -> bool val equal_access : access -> access -> bool
@ -35,26 +34,21 @@ type mem_kind =
[@@deriving compare] [@@deriving compare]
(** resource that can be allocated *) (** resource that can be allocated *)
type resource = Rmemory of mem_kind | Rfile | Rignore | Rlock [@@deriving compare] type resource = Rmemory of mem_kind | Rfile | Rignore | Rlock [@@deriving compare]
(** kind of resource action *) (** kind of resource action *)
type res_act_kind = Racquire | Rrelease [@@deriving compare] type res_act_kind = Racquire | Rrelease [@@deriving compare]
val equal_res_act_kind : res_act_kind -> res_act_kind -> bool val equal_res_act_kind : res_act_kind -> res_act_kind -> bool
(** kind of dangling pointers *) (** kind of dangling pointers *)
type dangling_kind = type dangling_kind =
(** pointer is dangling because it is uninitialized *) | DAuninit (** pointer is dangling because it is uninitialized *)
| DAuninit | DAaddr_stack_var
(** pointer is dangling because it is the address of a stack variable which went out of scope *) (** pointer is dangling because it is the address of a stack variable which went out of scope *)
| DAaddr_stack_var (** pointer is -1 *) | DAminusone (** pointer is -1 *)
| DAminusone
(** position in a path: proc name, node id *) (** position in a path: proc name, node id *)
type path_pos = Typ.Procname.t * int [@@deriving compare] type path_pos = Typ.Procname.t * int [@@deriving compare]
val equal_path_pos : path_pos -> path_pos -> bool val equal_path_pos : path_pos -> path_pos -> bool
@ -69,7 +63,6 @@ type taint_kind =
type taint_info = {taint_source: Typ.Procname.t; taint_kind: taint_kind} type taint_info = {taint_source: Typ.Procname.t; taint_kind: taint_kind}
(** acquire/release action on a resource *) (** acquire/release action on a resource *)
type res_action = type res_action =
{ ra_kind: res_act_kind (** kind of action *) { ra_kind: res_act_kind (** kind of action *)
; ra_res: resource (** kind of resource *) ; ra_res: resource (** kind of resource *)
@ -85,39 +78,35 @@ type res_action =
specially and maintain more information on it than other arguments. Therefore when attaching an specially and maintain more information on it than other arguments. Therefore when attaching an
attribute to an expression, that expression should be the first argument, optionally followed by attribute to an expression, that expression should be the first argument, optionally followed by
additional related expressions. *) additional related expressions. *)
type t = type t =
| Aresource of res_action (** resource acquire/release *) | Aresource of res_action (** resource acquire/release *)
| Aautorelease | Aautorelease
| Adangling of dangling_kind (** dangling pointer *) | Adangling of dangling_kind (** dangling pointer *)
(** undefined value obtained by calling the given procedure, plus its return value annots *)
| Aundef of Typ.Procname.t * Annot.Item.t * Location.t * path_pos | Aundef of Typ.Procname.t * Annot.Item.t * Location.t * path_pos
(** undefined value obtained by calling the given procedure, plus its return value annots *)
| Ataint of taint_info | Ataint of taint_info
| Auntaint of taint_info | Auntaint of taint_info
| Alocked | Alocked
| Aunlocked (** value appeared in second argument of division at given path position *) | Aunlocked
| Adiv0 of path_pos | Adiv0 of path_pos (** value appeared in second argument of division at given path position *)
(** attributed exp is null due to a call to a method with given path as null receiver *)
| Aobjc_null | Aobjc_null
(** value was returned from a call to the given procedure, plus the annots of the return value *) (** attributed exp is null due to a call to a method with given path as null receiver *)
| Aretval of Typ.Procname.t * Annot.Item.t | Aretval of Typ.Procname.t * Annot.Item.t
(** denotes an object registered as an observers to a notification center *) (** value was returned from a call to the given procedure, plus the annots of the return value *)
| Aobserver (** denotes an object unsubscribed from observers of a notification center *) | Aobserver (** denotes an object registered as an observers to a notification center *)
| Aunsubscribed_observer | Aunsubscribed_observer
(** denotes an object unsubscribed from observers of a notification center *)
[@@deriving compare] [@@deriving compare]
val equal : t -> t -> bool val equal : t -> t -> bool
(** name of the allocation function for the given memory kind *)
val mem_alloc_pname : mem_kind -> Typ.Procname.t val mem_alloc_pname : mem_kind -> Typ.Procname.t
(** name of the allocation function for the given memory kind *)
(** name of the deallocation function for the given memory kind *)
val mem_dealloc_pname : mem_kind -> Typ.Procname.t val mem_dealloc_pname : mem_kind -> Typ.Procname.t
(** name of the deallocation function for the given memory kind *)
(** Categories of attributes *) (** Categories of attributes *)
type category = type category =
| ACresource | ACresource
| ACautorelease | ACautorelease
@ -132,16 +121,13 @@ type category =
val equal_category : category -> category -> bool val equal_category : category -> category -> bool
(** Return the category to which the attribute belongs. *)
val to_category : t -> category val to_category : t -> category
(** Return the category to which the attribute belongs. *)
val is_undef : t -> bool val is_undef : t -> bool
(** convert the attribute to a string *)
val to_string : Pp.env -> t -> string val to_string : Pp.env -> t -> string
(** convert the attribute to a string *)
(** Dump an attribute. *)
val d_attribute : t -> unit val d_attribute : t -> unit
(** Dump an attribute. *)

@ -8,6 +8,7 @@
*) *)
(** Attributes of a procedure. *) (** Attributes of a procedure. *)
open! IStd open! IStd
module Hashtbl = Caml.Hashtbl module Hashtbl = Caml.Hashtbl
module L = Logging module L = Logging

@ -12,30 +12,24 @@ open! IStd
(** Attributes of a procedure. *) (** Attributes of a procedure. *)
(** 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]
(** keys for proc_flags *)
val proc_flag_skip : string val proc_flag_skip : string
(** keys for proc_flags *)
(** key to specify that a function should be treated as a skip function *)
val proc_flag_ignore_return : string 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 *) (** key to specify that it is OK to ignore the return value *)
(** empty proc flags *)
val proc_flags_empty : unit -> proc_flags val proc_flags_empty : unit -> proc_flags
(** empty proc flags *)
(** add a key value pair to a proc flags *)
val proc_flags_add : proc_flags -> string -> string -> unit val proc_flags_add : proc_flags -> string -> string -> unit
(** add a key value pair to a proc flags *)
(** find a value for a key in the proc flags *)
val proc_flags_find : proc_flags -> string -> string 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.Fieldname.t | Objc_getter of Typ.Fieldname.t
@ -73,6 +67,5 @@ type t =
; source_file_captured: SourceFile.t (** source file where the procedure was captured *) } ; source_file_captured: SourceFile.t (** source file where the procedure was captured *) }
[@@deriving compare] [@@deriving compare]
(** Create a proc_attributes with default values. *)
val default : Typ.Procname.t -> Config.language -> t val default : Typ.Procname.t -> Config.language -> t
(** Create a proc_attributes with default values. *)

@ -7,6 +7,7 @@
* LICENSE file in the root directory of this source tree. An additional grant * LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory. * of patent rights can be found in the PATENTS file in the same directory.
*) *)
open! IStd open! IStd
module Hashtbl = Caml.Hashtbl module Hashtbl = Caml.Hashtbl
module L = Logging module L = Logging
@ -31,16 +32,15 @@ module Node = struct
(** a node *) (** a node *)
type t = type t =
{ (** unique id of the node *) { id: id (** unique id of the node *)
id: id (** distance to the exit node *) ; mutable dist_exit: int option (** distance to the exit node *)
; mutable dist_exit: int option (** exception nodes in the cfg *) ; mutable exn: t list (** exception nodes in the cfg *)
; mutable exn: t list (** instructions for symbolic execution *) ; mutable instrs: Sil.instr list (** instructions for symbolic execution *)
; mutable instrs: Sil.instr list (** kind of node *) ; kind: nodekind (** kind of node *)
; kind: nodekind (** location in the source code *) ; loc: Location.t (** location in the source code *)
; loc: Location.t (** predecessor nodes in the cfg *) ; mutable preds: t list (** predecessor nodes in the cfg *)
; mutable preds: t list (** name of the procedure the node belongs to *) ; pname_opt: Typ.Procname.t option (** name of the procedure the node belongs to *)
; pname_opt: Typ.Procname.t option (** successor nodes in the cfg *) ; mutable succs: t list (** successor nodes in the cfg *) }
; mutable succs: t list }
let exn_handler_kind = Stmt_node "exception handler" let exn_handler_kind = Stmt_node "exception handler"
@ -240,11 +240,14 @@ end
(* =============== END of module Node =============== *) (* =============== END of module Node =============== *)
(** Map over nodes *) (** Map over nodes *)
module NodeMap = Caml.Map.Make (Node) (** Hash table with nodes as keys. *) module NodeMap = Caml.Map.Make (Node)
(** Hash table with nodes as keys. *) (** Hash table with nodes as keys. *)
module NodeHash = Hashtbl.Make (Node) (** Set of nodes. *) module NodeHash = Hashtbl.Make (Node)
(** Set of nodes. *) (** Set of nodes. *)
module NodeSet = Node.NodeSet (** Map with node id keys. *) module NodeSet = Node.NodeSet
(** Map with node id keys. *) (** Map with node id keys. *)
module IdMap = Node.IdMap module IdMap = Node.IdMap
@ -255,7 +258,7 @@ type t =
; mutable nodes_num: int (** number of nodes *) ; mutable nodes_num: int (** number of nodes *)
; mutable start_node: Node.t (** start node of this procedure *) ; mutable start_node: Node.t (** start node of this procedure *)
; mutable exit_node: Node.t (** exit node of ths procedure *) ; mutable exit_node: Node.t (** exit node of ths procedure *)
; mutable loop_heads: (** loop head nodes of this procedure *) NodeSet.t option } ; mutable loop_heads: NodeSet.t option (** loop head nodes of this procedure *) }
[@@deriving compare] [@@deriving compare]
(** Only call from Cfg *) (** Only call from Cfg *)

@ -11,20 +11,16 @@
open! IStd open! IStd
(** node of the control flow graph *) (** node of the control flow graph *)
module Node : sig module Node : sig
(** type of nodes *) (** type of nodes *)
type t [@@deriving compare] type t [@@deriving compare]
(** node id *) (** node id *)
type id = private int [@@deriving compare] type id = private int [@@deriving compare]
val equal_id : id -> id -> bool val equal_id : id -> id -> bool
(** kind of cfg node *) (** kind of cfg node *)
type nodekind = type nodekind =
| Start_node of Typ.Procname.t | Start_node of Typ.Procname.t
| Exit_node of Typ.Procname.t | Exit_node of Typ.Procname.t
@ -36,281 +32,217 @@ module Node : sig
val equal_nodekind : nodekind -> nodekind -> bool val equal_nodekind : nodekind -> nodekind -> bool
(** kind of Stmt_node for an exception handler. *)
val exn_handler_kind : nodekind val exn_handler_kind : nodekind
(** kind of Stmt_node for an exception handler. *)
(** kind of Stmt_node for an exceptions sink. *)
val exn_sink_kind : nodekind val exn_sink_kind : nodekind
(** kind of Stmt_node for an exceptions sink. *)
(** kind of Stmt_node for a throw instruction. *)
val throw_kind : nodekind val throw_kind : nodekind
(** kind of Stmt_node for a throw instruction. *)
(** Add declarations for local variables and return variable to the node *)
val add_locals_ret_declaration : t -> ProcAttributes.t -> (Mangled.t * Typ.t) list -> unit val add_locals_ret_declaration : t -> ProcAttributes.t -> (Mangled.t * Typ.t) list -> unit
(** Add declarations for local variables and return variable to the node *)
(** Append the instructions to the list of instructions to execute *)
val append_instrs : t -> Sil.instr list -> unit val append_instrs : t -> Sil.instr list -> unit
(** Append the instructions to the list of instructions to execute *)
(** Dump extended instructions for the node *)
val d_instrs : sub_instrs:bool -> Sil.instr option -> t -> unit val d_instrs : sub_instrs:bool -> Sil.instr option -> t -> unit
(** Dump extended instructions for the node *)
(** Create a dummy node *)
val dummy : Typ.Procname.t option -> t val dummy : Typ.Procname.t option -> t
(** Create a dummy node *)
(** Check if two nodes are equal *)
val equal : t -> t -> bool val equal : t -> t -> bool
(** Check if two nodes are equal *)
(** Get the list of callee procnames from the node *)
val get_callees : t -> Typ.Procname.t list val get_callees : t -> Typ.Procname.t list
(** Get the list of callee procnames from the node *)
(** Return a description of the node *)
val get_description : Pp.env -> t -> string val get_description : Pp.env -> t -> string
(** Return a description of the node *)
(** Get the distance to the exit node, if it has been computed *)
val get_distance_to_exit : t -> int option val get_distance_to_exit : t -> int option
(** Get the distance to the exit node, if it has been computed *)
(** Get the exception nodes from the current node *)
val get_exn : t -> t list val get_exn : t -> t list
(** 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 (** Get a list of unique nodes until the first branch starting
from a node with subsequent applications of a generator function *) from a node with subsequent applications of a generator function *)
val get_generated_slope : t -> (t -> t list) -> t list
(** Get the unique id of the node *)
val get_id : t -> id val get_id : t -> id
(** Get the unique id of the node *)
(** Get the instructions to be executed *)
val get_instrs : t -> Sil.instr list val get_instrs : t -> Sil.instr list
(** Get the instructions to be executed *)
(** Get the kind of the current node *)
val get_kind : t -> nodekind val get_kind : t -> nodekind
(** Get the kind of the current node *)
(** Get the source location of the last instruction in the node *)
val get_last_loc : t -> Location.t val get_last_loc : t -> Location.t
(** Get the source location of the last instruction in the node *)
(** Get the source location of the node *)
val get_loc : t -> Location.t val get_loc : t -> Location.t
(** Get the source location of the node *)
(** Get the predecessor nodes of the current node *)
val get_preds : t -> t list val get_preds : t -> t list
(** Get the predecessor nodes of the current node *)
(** Get the name of the procedure the node belongs to *)
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 predecessor nodes of a node where the given predicate evaluates to true *)
val get_sliced_preds : t -> (t -> bool) -> t list val get_sliced_preds : t -> (t -> bool) -> t list
(** Get the predecessor nodes of a node where the given predicate evaluates to true *)
(** Get the successor nodes of a node where the given predicate evaluates to true *)
val get_sliced_succs : t -> (t -> bool) -> t list val get_sliced_succs : t -> (t -> bool) -> t list
(** Get the successor nodes of a node where the given predicate evaluates to true *)
(** Get the successor nodes of the current node *)
val get_succs : t -> t list val get_succs : t -> t list
(** Get the successor nodes of the current node *)
(** Hash function for nodes *)
val hash : t -> int val hash : t -> int
(** Hash function for nodes *)
(** Pretty print the node *)
val pp : Format.formatter -> t -> unit val pp : Format.formatter -> t -> unit
(** Pretty print the node *)
(** Pretty print a node id *)
val pp_id : Format.formatter -> id -> unit val pp_id : Format.formatter -> id -> unit
(** Pretty print a node id *)
val pp_instrs : Pp.env -> sub_instrs:bool -> Sil.instr option -> Format.formatter -> t -> unit
(** Print extended instructions for the node, (** Print extended instructions for the node,
highlighting the given subinstruction if present *) highlighting the given subinstruction if present *)
val pp_instrs : Pp.env -> sub_instrs:bool -> Sil.instr option -> Format.formatter -> t -> unit
(** Replace the instructions to be executed. *)
val replace_instrs : t -> Sil.instr list -> unit val replace_instrs : t -> Sil.instr list -> unit
(** Replace the instructions to be executed. *)
end end
(** Map with node id keys. *) (** Map with node id keys. *)
module IdMap : Caml.Map.S with type key = Node.id module IdMap : Caml.Map.S with type key = Node.id
(** Hash table with nodes as keys. *) (** Hash table with nodes as keys. *)
module NodeHash : Caml.Hashtbl.S with type key = Node.t module NodeHash : Caml.Hashtbl.S with type key = Node.t
(** Map over nodes. *) (** Map over nodes. *)
module NodeMap : Caml.Map.S with type key = Node.t module NodeMap : Caml.Map.S with type key = Node.t
(** Set of nodes. *) (** Set of nodes. *)
module NodeSet : Caml.Set.S with type elt = Node.t module NodeSet : Caml.Set.S with type elt = Node.t
(** procedure descriptions *) (** procedure descriptions *)
(** proc description *) (** proc description *)
type t [@@deriving compare] type t [@@deriving compare]
(** append a list of new local variables to the existing list of local variables *)
val append_locals : t -> (Mangled.t * Typ.t) list -> unit val append_locals : t -> (Mangled.t * Typ.t) list -> unit
(** append a list of new local variables to the existing list of local variables *)
(** Compute the distance of each node to the exit node, if not computed already *)
val compute_distance_to_exit_node : t -> unit val compute_distance_to_exit_node : t -> unit
(** Compute the distance of each node to the exit node, if not computed already *)
val create_node : t -> Location.t -> Node.nodekind -> Sil.instr list -> Node.t
(** Create a new cfg node with the given location, kind, list of instructions, (** Create a new cfg node with the given location, kind, list of instructions,
and add it to the procdesc. *) and add it to the procdesc. *)
val create_node : t -> Location.t -> Node.nodekind -> Sil.instr list -> Node.t
(** true if we ran the preanalysis on the CFG associated with [t] *)
val did_preanalysis : t -> bool val did_preanalysis : t -> bool
(** true if we ran the preanalysis on the CFG associated with [t] *)
(** fold over the calls from the procedure: (callee, location) pairs *)
val fold_calls : ('a -> Typ.Procname.t * Location.t -> 'a) -> 'a -> t -> 'a val fold_calls : ('a -> Typ.Procname.t * Location.t -> 'a) -> 'a -> t -> 'a
(** fold over the calls from the procedure: (callee, location) pairs *)
(** fold over all nodes and their instructions *)
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 *)
val fold_nodes : ('a -> Node.t -> 'a) -> 'a -> t -> 'a val fold_nodes : ('a -> Node.t -> 'a) -> 'a -> t -> 'a
(** fold over all nodes *)
(** Only call from Cfg. *)
val from_proc_attributes : called_from_cfg:bool -> ProcAttributes.t -> t val from_proc_attributes : called_from_cfg:bool -> ProcAttributes.t -> t
(** Only call from Cfg. *)
(** Return the visibility attribute *)
val get_access : t -> PredSymb.access val get_access : t -> PredSymb.access
(** Return the visibility attribute *)
(** Get the attributes of the procedure. *)
val get_attributes : t -> ProcAttributes.t val get_attributes : t -> ProcAttributes.t
(** Get the attributes of the procedure. *)
(** Return name and type of block's captured variables *)
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 *)
val get_err_log : t -> Errlog.t val get_err_log : t -> Errlog.t
val get_exit_node : t -> Node.t val get_exit_node : t -> Node.t
(** Get flags for the proc desc *)
val get_flags : t -> ProcAttributes.proc_flags val get_flags : t -> ProcAttributes.proc_flags
(** Get flags for the proc desc *)
(** Return name and type of formal parameters *)
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 loc information for the procedure *)
val get_loc : t -> Location.t val get_loc : t -> Location.t
(** Return loc information for the procedure *)
(** Return name and type of local variables *)
val get_locals : t -> (Mangled.t * Typ.t) list val get_locals : t -> (Mangled.t * Typ.t) list
(** Return name and type of local variables *)
val get_nodes : t -> Node.t list val get_nodes : t -> Node.t list
val get_proc_name : t -> Typ.Procname.t val get_proc_name : t -> Typ.Procname.t
(** Return the return type of the procedure and type string *)
val get_ret_type : t -> Typ.t val get_ret_type : t -> Typ.t
(** Return the return type of the procedure and type string *)
val get_ret_var : t -> Pvar.t val get_ret_var : t -> Pvar.t
(** Get the sliced procedure's nodes up until the first branching *)
val get_sliced_slope : t -> (Node.t -> bool) -> Node.t list val get_sliced_slope : t -> (Node.t -> bool) -> Node.t list
(** Get the sliced procedure's nodes up until the first branching *)
(** Get the procedure's nodes up until the first branching *)
val get_slope : t -> Node.t list 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
(** Return [true] iff the procedure is defined, and not just declared *)
val is_defined : t -> bool val is_defined : t -> bool
(** Return [true] iff the procedure is defined, and not just declared *)
(** Return [true] if the body of the procdesc is empty (no instructions) *)
val is_body_empty : t -> bool val is_body_empty : t -> bool
(** Return [true] if the body of the procdesc is empty (no instructions) *)
(** Return [true] if the procedure signature has the Java synchronized keyword *)
val is_java_synchronized : t -> bool val is_java_synchronized : t -> bool
(** Return [true] if the procedure signature has the Java synchronized keyword *)
(** iterate over the calls from the procedure: (callee, location) pairs *)
val iter_calls : (Typ.Procname.t * Location.t -> unit) -> t -> unit val iter_calls : (Typ.Procname.t * Location.t -> unit) -> t -> unit
(** iterate over the calls from the procedure: (callee, location) pairs *)
(** iterate over all nodes and their instructions *)
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 the nodes of a procedure *)
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 nodes until we reach a branching structure *)
val iter_slope : (Node.t -> unit) -> t -> unit val iter_slope : (Node.t -> unit) -> t -> unit
(** iterate over all nodes until we reach a branching structure *)
(** iterate over all calls until we reach a branching structure *)
val iter_slope_calls : (Typ.Procname.t -> unit) -> t -> unit val iter_slope_calls : (Typ.Procname.t -> unit) -> t -> unit
(** iterate over all calls until we reach a branching structure *)
(** iterate between two nodes or 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 *)
(** Set the successor nodes and exception nodes, and build predecessor links *)
val node_set_succs_exn : t -> Node.t -> Node.t list -> Node.t list -> unit val node_set_succs_exn : t -> Node.t -> Node.t list -> Node.t list -> unit
(** Set the successor nodes and exception nodes, and build predecessor links *)
(** Set the exit node of the procedure *)
val set_exit_node : t -> Node.t -> unit val set_exit_node : t -> Node.t -> unit
(** Set the exit node of the procedure *)
(** Set a flag for the proc desc *)
val set_flag : t -> string -> string -> unit 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
(** indicate that we have performed preanalysis on the CFG assoociated with [t] *)
val signal_did_preanalysis : t -> unit val signal_did_preanalysis : t -> unit
(** indicate that we have performed preanalysis on the CFG assoociated with [t] *)
val is_loop_head : t -> Node.t -> bool val is_loop_head : t -> Node.t -> bool

@ -9,6 +9,7 @@
*) *)
(** The Smallfoot Intermediate Language *) (** The Smallfoot Intermediate Language *)
open! IStd open! IStd
module L = Logging module L = Logging
module F = Format module F = Format

@ -9,6 +9,7 @@
*) *)
(** Program variables. *) (** Program variables. *)
open! IStd open! IStd
module F = Format module F = Format
@ -20,148 +21,113 @@ type translation_unit = TUFile of SourceFile.t | TUExtern [@@deriving compare]
3) global variables 3) global variables
4) seed variables, used to store the initial value of formal parameters 4) seed variables, used to store the initial value of formal parameters
*) *)
type t [@@deriving compare] type t [@@deriving compare]
(** Equality for pvar's *)
val equal : t -> t -> bool val equal : t -> t -> bool
(** Equality for pvar's *)
(** Dump a program variable. *)
val d : t -> unit val d : t -> unit
(** Dump a program variable. *)
(** Dump a list of program variables. *)
val d_list : t list -> unit val d_list : t list -> unit
(** Dump a list of program variables. *)
(** Get the name component of a program variable. *)
val get_name : t -> Mangled.t val get_name : t -> Mangled.t
(** Get the name component of a program variable. *)
(** [get_ret_pvar proc_name] retuns the return pvar associated with the procedure name *)
val get_ret_pvar : Typ.Procname.t -> t val get_ret_pvar : Typ.Procname.t -> t
(** [get_ret_pvar proc_name] retuns the return pvar associated with the procedure name *)
(** Get a simplified version of the name component of a program variable. *)
val get_simplified_name : t -> string val get_simplified_name : t -> string
(** Get a simplified version of the name component of a program variable. *)
(** Check if the pvar is an abduced return var or param passed by ref *)
val is_abduced : t -> bool val is_abduced : t -> bool
(** Check if the pvar is an abduced return var or param passed by ref *)
(** Check if the pvar is a callee var *)
val is_callee : t -> bool val is_callee : t -> bool
(** Check if the pvar is a callee var *)
(** Check if the pvar is a global var or a static local var *)
val is_global : t -> bool val is_global : t -> bool
(** Check if the pvar is a global var or a static local var *)
(** Check if the pvar is a static variable declared inside a function *)
val is_static_local : t -> bool val is_static_local : t -> bool
(** Check if the pvar is a static variable declared inside a function *)
(** Check if the pvar is a (non-static) local var *)
val is_local : t -> bool val is_local : t -> bool
(** Check if the pvar is a (non-static) local var *)
(** Check if the pvar is a seed var *)
val is_seed : t -> bool val is_seed : t -> bool
(** Check if the pvar is a seed var *)
(** Check if the pvar is a return var *)
val is_return : t -> bool val is_return : t -> bool
(** Check if the pvar is a return var *)
(** Check if a pvar is the special "this" var *)
val is_this : t -> bool val is_this : t -> bool
(** Check if a pvar is the special "this" var *)
(** Check if a pvar is the special "self" var *)
val is_self : t -> bool val is_self : t -> bool
(** Check if a pvar is the special "self" var *)
(** return true if [pvar] is a temporary variable generated by the frontend *)
val is_frontend_tmp : t -> bool val is_frontend_tmp : t -> bool
(** return true if [pvar] is a temporary variable generated by the frontend *)
val is_ssa_frontend_tmp : t -> bool
(** return true if [pvar] is a temporary variable generated by the frontend and is only assigned (** return true if [pvar] is a temporary variable generated by the frontend and is only assigned
once on a non-looping control-flow path *) once on a non-looping control-flow path *)
val is_ssa_frontend_tmp : t -> bool
(** [mk name proc_name suffix] creates a program var with the given function name and suffix *)
val mk : Mangled.t -> Typ.Procname.t -> t val mk : Mangled.t -> Typ.Procname.t -> t
(** [mk name proc_name suffix] creates a program var with the given function name and suffix *)
(** create an abduced variable for a parameter passed by reference *)
val mk_abduced_ref_param : Typ.Procname.t -> t -> Location.t -> t val mk_abduced_ref_param : Typ.Procname.t -> t -> Location.t -> t
(** create an abduced variable for a parameter passed by reference *) (** create an abduced variable for a parameter passed by reference *)
val mk_abduced_ref_param_val : Typ.Procname.t -> Ident.t -> Location.t -> t val mk_abduced_ref_param_val : Typ.Procname.t -> Ident.t -> Location.t -> t
(** create an abduced variable for a parameter passed by reference *)
(** create an abduced return variable for a call to [proc_name] at [loc] *)
val mk_abduced_ret : Typ.Procname.t -> Location.t -> t val mk_abduced_ret : Typ.Procname.t -> Location.t -> t
(** create an abduced return variable for a call to [proc_name] at [loc] *)
val mk_callee : Mangled.t -> Typ.Procname.t -> t
(** [mk_callee name proc_name] creates a program var (** [mk_callee name proc_name] creates a program var
for a callee function with the given function name *) for a callee function with the given function name *)
val mk_callee : Mangled.t -> Typ.Procname.t -> t
(** create a global variable with the given name *)
val mk_global : val mk_global :
?is_constexpr:bool -> ?is_pod:bool -> ?is_static_local:bool -> Mangled.t -> translation_unit -> t ?is_constexpr:bool -> ?is_pod:bool -> ?is_static_local:bool -> Mangled.t -> translation_unit -> t
(** create a global variable with the given name *)
(** create a fresh temporary variable local to procedure [pname]. for use in the frontends only! *)
val mk_tmp : string -> Typ.Procname.t -> t val mk_tmp : string -> Typ.Procname.t -> t
(** create a fresh temporary variable local to procedure [pname]. for use in the frontends only! *)
(** Pretty print a program variable. *)
val pp : Pp.env -> F.formatter -> t -> unit val pp : Pp.env -> F.formatter -> t -> unit
(** Pretty print a program variable. *)
(** Pretty print a list of program variables. *)
val pp_list : Pp.env -> F.formatter -> t list -> unit val pp_list : Pp.env -> F.formatter -> t list -> unit
(** Pretty print a list of program variables. *)
(** Pretty print a pvar which denotes a value, not an address *)
val pp_value : Pp.env -> F.formatter -> t -> unit val pp_value : Pp.env -> F.formatter -> t -> unit
(** Pretty print a pvar which denotes a value, not an address *)
val pp_translation_unit : F.formatter -> translation_unit -> unit val pp_translation_unit : F.formatter -> translation_unit -> unit
(** Turn an ordinary program variable into a callee program variable *)
val to_callee : Typ.Procname.t -> t -> t val to_callee : Typ.Procname.t -> t -> t
(** Turn an ordinary program variable into a callee program variable *)
(** Turn a pvar into a seed pvar (which stores the initial value of a stack var) *)
val to_seed : t -> t val to_seed : t -> t
(** Turn a pvar into a seed pvar (which stores the initial value of a stack var) *)
(** Convert a pvar to string. *)
val to_string : t -> string val to_string : t -> string
(** Convert a pvar to string. *)
(** Get the translation unit corresponding to a global. Raises Invalid_arg if not a global. *)
val get_translation_unit : t -> translation_unit val get_translation_unit : t -> translation_unit
(** Get the translation unit corresponding to a global. Raises Invalid_arg if not a global. *)
val is_compile_constant : t -> bool
(** Is the variable's value a compile-time constant? Always (potentially incorrectly) returns (** Is the variable's value a compile-time constant? Always (potentially incorrectly) returns
[false] for non-globals. *) [false] for non-globals. *)
val is_compile_constant : t -> bool val is_pod : t -> bool
(** Is the variable's type a "Plain Old Data" type (C++)? Always (potentially incorrectly) returns (** Is the variable's type a "Plain Old Data" type (C++)? Always (potentially incorrectly) returns
[true] for non-globals. *) [true] for non-globals. *)
val is_pod : t -> bool
(** Get the procname of the initializer function for the given global variable *)
val get_initializer_pname : t -> Typ.Procname.t option val get_initializer_pname : t -> Typ.Procname.t option
(** Get the procname of the initializer function for the given global variable *)

@ -6,6 +6,7 @@
* LICENSE file in the root directory of this source tree. An additional grant * LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory. * of patent rights can be found in the PATENTS file in the same directory.
*) *)
open! IStd open! IStd
(* 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"]*)

@ -11,58 +11,47 @@ open! IStd
type t [@@deriving compare] type t [@@deriving compare]
(** empty qualified name *)
val empty : t val empty : t
(** empty qualified name *)
val equal : t -> t -> bool val equal : t -> t -> bool
(** attempts to parse the argument into a list::of::possibly::templated<T>::qualifiers *)
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 *)
(** returns qualified name as a string with "::" as a separator between qualifiers *)
val to_qual_string : t -> string val to_qual_string : t -> string
(** returns qualified name as a string with "::" as a separator between qualifiers *)
(** append qualifier to the end (innermost scope) of the qualified name *)
val append_qualifier : t -> qual:string -> t val append_qualifier : t -> qual:string -> t
(** append qualifier to the end (innermost scope) of the qualified name *)
(** returns last (innermost scope) qualifier and qualified name without last qualifier *)
val extract_last : t -> (string * t) option val extract_last : t -> (string * t) option
(** returns last (innermost scope) qualifier and qualified name without last qualifier *)
val strip_template_args : t -> t
(** returns qualified name without template arguments. For example: (** returns qualified name without template arguments. For example:
input: std::shared_ptr<int>::shared_ptr<long> input: std::shared_ptr<int>::shared_ptr<long>
output: std::shared_ptr::shared_ptr *) output: std::shared_ptr::shared_ptr *)
val strip_template_args : t -> t val append_template_args_to_last : t -> args:string -> t
(** append template arguments to the last qualifier. Fails if qualified name is empty or it already has (** append template arguments to the last qualifier. Fails if qualified name is empty or it already has
template args *) template args *)
val append_template_args_to_last : t -> args:string -> t
(** returns list of qualifers *)
val to_list : t -> string list val to_list : t -> string list
(** returns list of qualifers *)
(** returns reversed list of qualifiers, ie innermost scope is the first element *)
val to_rev_list : t -> string list val to_rev_list : t -> string list
(** returns reversed list of qualifiers, ie innermost scope is the first element *)
(** given list of qualifiers in normal order produce qualified name ["std", "move"] *)
val of_list : string list -> t val of_list : string list -> t
(** given list of qualifiers in normal order produce qualified name ["std", "move"] *)
(** given reversed list of qualifiers, produce qualified name (ie. ["move", "std"] for std::move )*)
val of_rev_list : string list -> t val of_rev_list : string list -> t
(** given reversed list of qualifiers, produce qualified name (ie. ["move", "std"] for std::move )*)
val pp : Format.formatter -> t -> unit val pp : Format.formatter -> t -> unit
(* Module to match qualified C++ procnames "fuzzily", that is up to namescapes and templating. In (** Module to match qualified C++ procnames "fuzzily", that is up to namescapes and templating. In
particular, this deals with the following issues: particular, this deals with the following issues:
1. 'std::' namespace may have inline namespace afterwards: std::move becomes std::__1::move. This 1. 'std::' namespace may have inline namespace afterwards: std::move becomes std::__1::move. This
@ -89,7 +78,6 @@ val pp : Format.formatter -> t -> unit
qualifiers to match qualifiers to match
does not match: ["folly","someFunction<int>", "BAD"] - same as previous example does not match: ["folly","someFunction<int>", "BAD"] - same as previous example
*) *)
module Match : sig module Match : sig
type quals_matcher type quals_matcher

@ -9,6 +9,7 @@
*) *)
(** The Smallfoot Intermediate Language *) (** The Smallfoot Intermediate Language *)
open! IStd open! IStd
module Hashtbl = Caml.Hashtbl module Hashtbl = Caml.Hashtbl
module L = Logging module L = Logging
@ -18,40 +19,37 @@ module F = Format
(** Kind of prune instruction *) (** Kind of prune instruction *)
type if_kind = type if_kind =
| Ik_bexp | Ik_bexp (** boolean expressions, and exp ? exp : exp *)
(* boolean expressions, and exp ? exp : exp *)
| Ik_dowhile | Ik_dowhile
| Ik_for | Ik_for
| Ik_if | Ik_if
| Ik_land_lor | Ik_land_lor (** obtained from translation of && or || *)
(* obtained from translation of && or || *)
| Ik_while | Ik_while
| Ik_switch | Ik_switch
[@@deriving compare] [@@deriving compare]
(** An instruction. *) (** An instruction. *)
type instr = type instr =
(** Load a value from the heap into an identifier.
[x = *lexp:typ] where
[lexp] is an expression denoting a heap address
[typ] is the root type of [lexp]. *)
(* Note for frontend writers: (* Note for frontend writers:
[x] must be used in a subsequent instruction, otherwise the entire [x] must be used in a subsequent instruction, otherwise the entire
`Load` instruction may be eliminated by copy-propagation. *) `Load` instruction may be eliminated by copy-propagation. *)
| Load of Ident.t * Exp.t * Typ.t * Location.t | Load of Ident.t * Exp.t * Typ.t * Location.t
(** Load a value from the heap into an identifier.
[x = *lexp:typ] where
[lexp] is an expression denoting a heap address
[typ] is the root type of [lexp]. *)
| Store of Exp.t * Typ.t * Exp.t * Location.t
(** Store the value of an expression into the heap. (** Store the value of an expression into the heap.
[*lexp1:typ = exp2] where [*lexp1:typ = exp2] where
[lexp1] is an expression denoting a heap address [lexp1] is an expression denoting a heap address
[typ] is the root type of [lexp1] [typ] is the root type of [lexp1]
[exp2] is the expression whose value is store. *) [exp2] is the expression whose value is store. *)
| Store of Exp.t * Typ.t * Exp.t * Location.t
(** prune the state based on [exp=1], the boolean indicates whether true branch *)
| Prune of Exp.t * Location.t * bool * if_kind | Prune of Exp.t * Location.t * bool * if_kind
(** prune the state based on [exp=1], the boolean indicates whether true branch *)
| Call of (Ident.t * Typ.t) option * Exp.t * (Exp.t * Typ.t) list * Location.t * CallFlags.t
(** [Call (ret_id, e_fun, arg_ts, loc, call_flags)] represents an instruction (** [Call (ret_id, e_fun, arg_ts, loc, call_flags)] represents an instruction
[ret_id = e_fun(arg_ts);]. The return value is ignored when [ret_id = None]. *) [ret_id = e_fun(arg_ts);]. The return value is ignored when [ret_id = None]. *)
| Call of (Ident.t * Typ.t) option * Exp.t * (Exp.t * Typ.t) list * Location.t * CallFlags.t | Nullify of Pvar.t * Location.t (** nullify stack variable *)
(** nullify stack variable *)
| Nullify of Pvar.t * Location.t
| Abstract of Location.t (** apply abstraction *) | Abstract of Location.t (** apply abstraction *)
| Remove_temps of Ident.t list * Location.t (** remove temporaries *) | Remove_temps of Ident.t list * Location.t (** remove temporaries *)
| Declare_locals of (Pvar.t * Typ.t) list * Location.t (** declare local variables *) | Declare_locals of (Pvar.t * Typ.t) list * Location.t (** declare local variables *)
@ -77,8 +75,8 @@ type offset = Off_fld of Typ.Fieldname.t * Typ.t | Off_index of Exp.t
type atom = type atom =
| Aeq of Exp.t * Exp.t (** equality *) | Aeq of Exp.t * Exp.t (** equality *)
| Aneq of Exp.t * Exp.t (** disequality *) | Aneq of Exp.t * Exp.t (** disequality *)
| Apred of PredSymb.t * (** predicate symbol applied to exps *) Exp.t list | Apred of PredSymb.t * Exp.t list (** predicate symbol applied to exps *)
| Anpred of PredSymb.t * (** negated predicate symbol applied to exps *) Exp.t list | Anpred of PredSymb.t * Exp.t list (** negated predicate symbol applied to exps *)
[@@deriving compare] [@@deriving compare]
let equal_atom = [%compare.equal : atom] let equal_atom = [%compare.equal : atom]
@ -126,6 +124,7 @@ let equal_inst = [%compare.equal : inst]
type 'inst strexp0 = type 'inst strexp0 =
| Eexp of Exp.t * 'inst (** Base case: expression with instrumentation *) | Eexp of Exp.t * 'inst (** Base case: expression with instrumentation *)
| Estruct of (Typ.Fieldname.t * 'inst strexp0) list * 'inst (** C structure *) | Estruct of (Typ.Fieldname.t * 'inst strexp0) list * 'inst (** C structure *)
| Earray of Exp.t * (Exp.t * 'inst strexp0) list * 'inst
(** Array of given length (** Array of given length
There are two conditions imposed / used in the array case. There are two conditions imposed / used in the array case.
First, if some index and value pair appears inside an array First, if some index and value pair appears inside an array
@ -133,7 +132,6 @@ type 'inst strexp0 =
For instance, x |->[10 | e1: v1] implies that e1 <= 9. For instance, x |->[10 | e1: v1] implies that e1 <= 9.
Second, if two indices appear in an array, they should be different. Second, if two indices appear in an array, they should be different.
For instance, x |->[10 | e1: v1, e2: v2] implies that e1 != e2. *) For instance, x |->[10 | e1: v1, e2: v2] implies that e1 != e2. *)
| Earray of Exp.t * (Exp.t * 'inst strexp0) list * 'inst
[@@deriving compare] [@@deriving compare]
type strexp = inst strexp0 type strexp = inst strexp0
@ -261,8 +259,8 @@ let color_pre_wrapper pe f x =
else Latex.pp_color ) else Latex.pp_color )
f color ; f color ;
if Pp.equal_color color Pp.Red then if Pp.equal_color color Pp.Red then
(Pp.{(** All subexpressiona red *) (* All subexpressions red *)
pe with cmap_norm= colormap_red; color= Red}, true) (Pp.{pe with cmap_norm= colormap_red; color= Red}, true)
else (Pp.{pe with color}, true) ) else (Pp.{pe with color}, true) )
else (pe, false) else (pe, false)
else (pe, false) else (pe, false)
@ -295,7 +293,7 @@ let pp_exp_printenv pe0 f e0 =
let e = let e =
match pe.Pp.obj_sub with match pe.Pp.obj_sub with
| Some sub | Some sub
-> Obj.obj (sub (Obj.repr e0) (* apply object substitution to expression *)) -> (* apply object substitution to expression *) Obj.obj (sub (Obj.repr e0))
| None | None
-> e0 -> e0
in in
@ -424,7 +422,7 @@ let pp_instr pe0 f instr =
(** Check if a pvar is a local pointing to a block in objc *) (** Check if a pvar is a local pointing to a block in objc *)
let is_block_pvar pvar = Typ.has_block_prefix (Mangled.to_string (Pvar.get_name pvar)) let is_block_pvar pvar = Typ.has_block_prefix (Mangled.to_string (Pvar.get_name pvar))
(* A block pvar used to explain retain cycles *) (** A block pvar used to explain retain cycles *)
let block_pvar = Pvar.mk (Mangled.from_string "block") (Typ.Procname.from_string_c_fun "") let block_pvar = Pvar.mk (Mangled.from_string "block") (Typ.Procname.from_string_c_fun "")
(** Dump an instruction. *) (** Dump an instruction. *)
@ -480,8 +478,6 @@ let rec pp_star_seq pp f = function
| x :: l | x :: l
-> F.fprintf f "%a * %a" pp x (pp_star_seq pp) l -> F.fprintf f "%a * %a" pp x (pp_star_seq pp) l
(********* START OF MODULE Predicates **********)
(** Module Predicates records the occurrences of predicates as parameters (** Module Predicates records the occurrences of predicates as parameters
of (doubly -)linked lists and Epara. Provides unique numbering of (doubly -)linked lists and Epara. Provides unique numbering
for predicates and an iterator. *) for predicates and an iterator. *)
@ -612,7 +608,6 @@ end = struct
done done
end end
(********* END OF MODULE Predicates **********)
let pp_texp_simple pe = 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
@ -848,7 +843,7 @@ let rec pp_hpred_env pe0 envo f hpred =
let pe' = let pe' =
match (e, se) with match (e, se) with
| Lvar pvar, Eexp (Var _, _) when not (Pvar.is_global pvar) | Lvar pvar, Eexp (Var _, _) when not (Pvar.is_global pvar)
-> Pp.{pe with obj_sub= None (* dont use obj sub on the var defining it *)} -> Pp.{pe with obj_sub= None} (* dont use obj sub on the var defining it *)
| _ | _
-> pe -> pe
in in
@ -963,6 +958,7 @@ let rec pp_hpara_dll_list pe f = function
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)
(** {2 Functions for traversing SIL data types} *) (** {2 Functions for traversing SIL data types} *)
let rec strexp_expmap (f: Exp.t * inst option -> Exp.t * inst option) = let rec strexp_expmap (f: Exp.t * inst option -> Exp.t * inst option) =
let fe e = fst (f (e, None)) in let fe e = fst (f (e, None)) in
let fei (e, inst) = let fei (e, inst) =
@ -1047,6 +1043,7 @@ let atom_expmap (f: Exp.t -> Exp.t) = function
let atom_list_expmap (f: Exp.t -> Exp.t) (alist: atom list) = List.map ~f:(atom_expmap f) alist 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
| Hpointsto (e, _, _) | Hpointsto (e, _, _)
-> e :: acc -> e :: acc
@ -1235,8 +1232,7 @@ let rec exp_fav_add fav e =
-> exp_fav_add fav e1 ; exp_fav_add fav e2 -> exp_fav_add fav e1 ; exp_fav_add fav e2
| Lvar _ | Lvar _
-> () -> ()
| Lfield (* do nothing since we only count non-program variables *) | Lfield (e, _, _) (* do nothing since we only count non-program variables *)
(e, _, _)
-> exp_fav_add fav e -> exp_fav_add fav e
| Lindex (e1, e2) | Lindex (e1, e2)
-> exp_fav_add fav e1 ; exp_fav_add fav e2 -> exp_fav_add fav e1 ; exp_fav_add fav e2
@ -1364,6 +1360,7 @@ let hpara_shallow_av = fav_imperative_to_functional hpara_shallow_av_add
let hpara_dll_shallow_av = fav_imperative_to_functional hpara_dll_shallow_av_add let hpara_dll_shallow_av = fav_imperative_to_functional hpara_dll_shallow_av_add
(** {2 Functions for Substitution} *) (** {2 Functions for Substitution} *)
let rec reverse_with_base base = function [] -> base | x :: l -> reverse_with_base (x :: base) l let rec reverse_with_base base = function [] -> base | x :: l -> reverse_with_base (x :: base) l
let sorted_list_merge compare l1_in l2_in = let sorted_list_merge compare l1_in l2_in =
@ -1527,8 +1524,8 @@ let rec exp_sub_ids (f: subst_fun) exp =
| `Exp f_exp -> ( | `Exp f_exp -> (
match f_exp id with match f_exp id with
| Exp.Var id' when Ident.equal id id' | Exp.Var id' when Ident.equal id id'
-> exp -> exp (* it will preserve physical equality when needed *)
(* it will preserve physical equality when needed *) | exp' | exp'
-> exp' ) -> exp' )
| _ | _
-> exp ) -> exp )

@ -14,48 +14,42 @@ module F = Format
(** {2 Programs and Types} *) (** {2 Programs and Types} *)
(** Convert expression lists to expression sets. *)
val elist_to_eset : Exp.t list -> Exp.Set.t val elist_to_eset : Exp.t list -> Exp.Set.t
(** Convert expression lists to expression sets. *)
(** Kind of prune instruction *) (** Kind of prune instruction *)
type if_kind = type if_kind =
| Ik_bexp | Ik_bexp (** boolean expressions, and exp ? exp : exp *)
(* boolean expressions, and exp ? exp : exp *)
| Ik_dowhile | Ik_dowhile
| Ik_for | Ik_for
| Ik_if | Ik_if
| Ik_land_lor | Ik_land_lor (** obtained from translation of && or || *)
(* obtained from translation of && or || *)
| Ik_while | Ik_while
| Ik_switch | Ik_switch
[@@deriving compare] [@@deriving compare]
(** An instruction. *) (** An instruction. *)
type instr = type instr =
(** Load a value from the heap into an identifier.
[x = *lexp:typ] where
[lexp] is an expression denoting a heap address
[typ] is the root type of [lexp]. *)
(* Note for frontend writers: (* Note for frontend writers:
[x] must be used in a subsequent instruction, otherwise the entire [x] must be used in a subsequent instruction, otherwise the entire
`Load` instruction may be eliminated by copy-propagation. *) `Load` instruction may be eliminated by copy-propagation. *)
| Load of Ident.t * Exp.t * Typ.t * Location.t | Load of Ident.t * Exp.t * Typ.t * Location.t
(** Load a value from the heap into an identifier.
[x = *lexp:typ] where
[lexp] is an expression denoting a heap address
[typ] is the root type of [lexp]. *)
| Store of Exp.t * Typ.t * Exp.t * Location.t
(** Store the value of an expression into the heap. (** Store the value of an expression into the heap.
[*lexp1:typ = exp2] where [*lexp1:typ = exp2] where
[lexp1] is an expression denoting a heap address [lexp1] is an expression denoting a heap address
[typ] is the root type of [lexp1] [typ] is the root type of [lexp1]
[exp2] is the expression whose value is store. *) [exp2] is the expression whose value is store. *)
| Store of Exp.t * Typ.t * Exp.t * Location.t
(** prune the state based on [exp=1], the boolean indicates whether true branch *)
| Prune of Exp.t * Location.t * bool * if_kind | Prune of Exp.t * Location.t * bool * if_kind
(** prune the state based on [exp=1], the boolean indicates whether true branch *)
| Call of (Ident.t * Typ.t) option * Exp.t * (Exp.t * Typ.t) list * Location.t * CallFlags.t
(** [Call (ret_id, e_fun, arg_ts, loc, call_flags)] represents an instruction (** [Call (ret_id, e_fun, arg_ts, loc, call_flags)] represents an instruction
[ret_id = e_fun(arg_ts);]. The return value is ignored when [ret_id = None]. *) [ret_id = e_fun(arg_ts);]. The return value is ignored when [ret_id = None]. *)
| Call of (Ident.t * Typ.t) option * Exp.t * (Exp.t * Typ.t) list * Location.t * CallFlags.t | Nullify of Pvar.t * Location.t (** nullify stack variable *)
(** nullify stack variable *)
| Nullify of Pvar.t * Location.t
| Abstract of Location.t (** apply abstraction *) | Abstract of Location.t (** apply abstraction *)
| Remove_temps of Ident.t list * Location.t (** remove temporaries *) | Remove_temps of Ident.t list * Location.t (** remove temporaries *)
| Declare_locals of (Pvar.t * Typ.t) list * Location.t (** declare local variables *) | Declare_locals of (Pvar.t * Typ.t) list * Location.t (** declare local variables *)
@ -63,31 +57,27 @@ type instr =
val equal_instr : instr -> instr -> bool val equal_instr : instr -> instr -> bool
val compare_structural_instr : instr -> instr -> Exp.t Exp.Map.t -> int * Exp.t Exp.Map.t
(** compare instructions from different procedures without considering loc's, ident's, and pvar's. (** compare instructions from different procedures without considering loc's, ident's, and pvar's.
the [exp_map] param gives a mapping of names used in the procedure of [instr1] to identifiers the [exp_map] param gives a mapping of names used in the procedure of [instr1] to identifiers
used in the procedure of [instr2] *) used in the procedure of [instr2] *)
val compare_structural_instr : instr -> instr -> Exp.t Exp.Map.t -> int * Exp.t Exp.Map.t
val skip_instr : instr val skip_instr : instr
(** Check if an instruction is auxiliary, or if it comes from source instructions. *)
val instr_is_auxiliary : instr -> bool val instr_is_auxiliary : instr -> bool
(** Check if an instruction is auxiliary, or if it comes from source instructions. *)
(** Offset for an lvalue. *) (** Offset for an lvalue. *)
type offset = Off_fld of Typ.Fieldname.t * Typ.t | Off_index of Exp.t type offset = Off_fld of Typ.Fieldname.t * Typ.t | Off_index of Exp.t
(** {2 Components of Propositions} *) (** {2 Components of Propositions} *)
(** an atom is a pure atomic formula *) (** an atom is a pure atomic formula *)
type atom = type atom =
| Aeq of Exp.t * Exp.t (** equality *) | Aeq of Exp.t * Exp.t (** equality *)
| Aneq of Exp.t * Exp.t (** disequality *) | Aneq of Exp.t * Exp.t (** disequality *)
| Apred of PredSymb.t * (** predicate symbol applied to exps *) Exp.t list | Apred of PredSymb.t * Exp.t list (** predicate symbol applied to exps *)
| Anpred of PredSymb.t * (** negated predicate symbol applied to exps *) Exp.t list | Anpred of PredSymb.t * Exp.t list (** negated predicate symbol applied to exps *)
[@@deriving compare] [@@deriving compare]
val equal_atom : atom -> atom -> bool val equal_atom : atom -> atom -> bool
@ -95,7 +85,6 @@ val equal_atom : atom -> atom -> bool
val atom_has_local_addr : atom -> bool val atom_has_local_addr : atom -> bool
(** kind of lseg or dllseg predicates *) (** kind of lseg or dllseg predicates *)
type lseg_kind = type lseg_kind =
| Lseg_NE (** nonempty (possibly circular) listseg *) | Lseg_NE (** nonempty (possibly circular) listseg *)
| Lseg_PE (** possibly empty (possibly circular) listseg *) | Lseg_PE (** possibly empty (possibly circular) listseg *)
@ -104,15 +93,12 @@ type lseg_kind =
val equal_lseg_kind : lseg_kind -> lseg_kind -> bool val equal_lseg_kind : lseg_kind -> lseg_kind -> bool
(** The boolean is true when the pointer was dereferenced without testing for zero. *) (** The boolean is true when the pointer was dereferenced without testing for zero. *)
type zero_flag = bool option type zero_flag = bool option
(** True when the value was obtained by doing case analysis on null in a procedure call. *) (** True when the value was obtained by doing case analysis on null in a procedure call. *)
type null_case_flag = bool type null_case_flag = bool
(** instrumentation of heap values *) (** instrumentation of heap values *)
type inst = type inst =
| Iabstraction | Iabstraction
| Iactual_precondition | Iactual_precondition
@ -138,57 +124,48 @@ val inst_alloc : inst
val inst_formal : inst val inst_formal : inst
(** for formal parameters and heap values at the beginning of the function *)
val inst_initial : inst val inst_initial : inst
(** for formal parameters and heap values at the beginning of the function *)
(** for initial values *)
val inst_lookup : inst val inst_lookup : inst
(** for initial values *)
val inst_none : inst val inst_none : inst
val inst_nullify : inst val inst_nullify : inst
(** the boolean indicates whether the pointer is known nonzero *)
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 *)
val inst_taint : inst val inst_taint : inst
val inst_update : Location.t -> PredSymb.path_pos -> inst val inst_update : Location.t -> PredSymb.path_pos -> inst
(** Get the null case flag of the inst. *)
val inst_get_null_case_flag : inst -> bool option val inst_get_null_case_flag : inst -> bool option
(** Get the null case flag of the inst. *)
(** Set 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. *)
(** update the location of the instrumentation *)
val inst_new_loc : Location.t -> inst -> inst val inst_new_loc : Location.t -> inst -> inst
(** update the location of the instrumentation *)
(** Update [inst_old] to [inst_new] preserving the zero flag *)
val update_inst : inst -> inst -> inst val update_inst : inst -> inst -> inst
(** Update [inst_old] to [inst_new] preserving the zero flag *)
exception JoinFail exception JoinFail
(** join of instrumentations, can raise JoinFail *)
val inst_partial_join : inst -> inst -> inst val inst_partial_join : inst -> inst -> inst
(** join of instrumentations, can raise JoinFail *)
(** meet of instrumentations *)
val inst_partial_meet : inst -> inst -> inst val inst_partial_meet : inst -> inst -> inst
(** meet of instrumentations *)
(** structured expressions represent a value of structured type, such as an array or a struct. *) (** structured expressions represent a value of structured type, such as an array or a struct. *)
type 'inst strexp0 = type 'inst strexp0 =
| Eexp of Exp.t * 'inst (** Base case: expression with instrumentation *) | Eexp of Exp.t * 'inst (** Base case: expression with instrumentation *)
| Estruct of (Typ.Fieldname.t * 'inst strexp0) list * 'inst (** C structure *) | Estruct of (Typ.Fieldname.t * 'inst strexp0) list * 'inst (** C structure *)
| Earray of Exp.t * (Exp.t * 'inst strexp0) list * 'inst
(** Array of given length (** Array of given length
There are two conditions imposed / used in the array case. There are two conditions imposed / used in the array case.
First, if some index and value pair appears inside an array First, if some index and value pair appears inside an array
@ -196,25 +173,21 @@ type 'inst strexp0 =
For instance, x |->[10 | e1: v1] implies that e1 <= 9. For instance, x |->[10 | e1: v1] implies that e1 <= 9.
Second, if two indices appear in an array, they should be different. Second, if two indices appear in an array, they should be different.
For instance, x |->[10 | e1: v1, e2: v2] implies that e1 != e2. *) For instance, x |->[10 | e1: v1, e2: v2] implies that e1 != e2. *)
| Earray of Exp.t * (Exp.t * 'inst strexp0) list * 'inst
[@@deriving compare] [@@deriving compare]
type strexp = inst strexp0 type strexp = inst strexp0
val compare_strexp : ?inst:bool -> strexp -> strexp -> int
(** Comparison function for strexp. (** Comparison function for strexp.
The inst:: parameter specifies whether instumentations should also The inst:: parameter specifies whether instumentations should also
be considered (false by default). *) be considered (false by default). *)
val compare_strexp : ?inst:bool -> strexp -> strexp -> int val equal_strexp : ?inst:bool -> strexp -> strexp -> bool
(** Equality function for strexp. (** Equality function for strexp.
The inst:: parameter specifies whether instumentations should also The inst:: parameter specifies whether instumentations should also
be considered (false by default). *) be considered (false by default). *)
val equal_strexp : ?inst:bool -> strexp -> strexp -> bool
(** an atomic heap predicate *) (** an atomic heap predicate *)
type 'inst hpred0 = type 'inst hpred0 =
| Hpointsto of Exp.t * 'inst strexp0 * Exp.t | Hpointsto of Exp.t * 'inst strexp0 * Exp.t
(** represents [exp|->strexp:typexp] where [typexp] (** represents [exp|->strexp:typexp] where [typexp]
@ -256,299 +229,230 @@ type hpara = inst hpara0
type hpara_dll = inst hpara_dll0 type hpara_dll = inst hpara_dll0
val compare_hpred : ?inst:bool -> hpred -> hpred -> int
(** Comparison function for hpred. (** Comparison function for hpred.
The inst:: parameter specifies whether instumentations should also The inst:: parameter specifies whether instumentations should also
be considered (false by default). *) be considered (false by default). *)
val compare_hpred : ?inst:bool -> hpred -> hpred -> int val equal_hpred : ?inst:bool -> hpred -> hpred -> bool
(** Equality function for hpred. (** Equality function for hpred.
The inst:: parameter specifies whether instumentations should also The inst:: parameter specifies whether instumentations should also
be considered (false by default). *) be considered (false by default). *)
val equal_hpred : ?inst:bool -> hpred -> hpred -> bool
(** Sets of heap predicates *) (** Sets of heap predicates *)
module HpredSet : Caml.Set.S with type elt = hpred module HpredSet : Caml.Set.S with type elt = hpred
(** {2 Compaction} *) (** {2 Compaction} *)
type sharing_env type sharing_env
(** Create a sharing env to store canonical representations *)
val create_sharing_env : unit -> sharing_env val create_sharing_env : unit -> sharing_env
(** Create a sharing env to store canonical representations *)
(** Return a canonical representation of the exp *)
val exp_compact : sharing_env -> Exp.t -> Exp.t val exp_compact : sharing_env -> Exp.t -> Exp.t
(** Return a canonical representation of the exp *)
(** Return a compact 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 *)
(** {2 Comparision And Inspection Functions} *)
val has_objc_ref_counter : Tenv.t -> hpred -> bool val has_objc_ref_counter : Tenv.t -> hpred -> bool
(** {2 Comparision And Inspection Functions} *)
(** Returns the zero value of a type, for int, float and ptr types, None othwewise *)
val zero_value_of_numerical_type_option : Typ.t -> Exp.t option val zero_value_of_numerical_type_option : Typ.t -> Exp.t option
(** Returns the zero value of a type, for int, float and ptr types, None othwewise *)
(** Returns the zero value of a type, for int, float and ptr types, fail otherwise *)
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 *)
(** Make a static local name in objc *)
val mk_static_local_name : string -> string -> string val mk_static_local_name : string -> string -> string
(** Make a static local name in objc *)
(** Check if a pvar is a local static 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 *)
(* A block pvar used to explain retain cycles *)
val block_pvar : Pvar.t val block_pvar : Pvar.t
(** A block pvar used to explain retain cycles *)
(** Check if a pvar is a local pointing to a block in objc *)
val is_block_pvar : Pvar.t -> bool val is_block_pvar : Pvar.t -> bool
(** Check if a pvar is a local pointing to a block in objc *)
(** Return the lhs expression of a hpred *)
val hpred_get_lhs : hpred -> Exp.t val hpred_get_lhs : hpred -> Exp.t
(** Return the lhs expression of a hpred *)
(** {2 Pretty Printing} *) (** {2 Pretty Printing} *)
(** Begin change color if using diff printing, return updated printenv and change status *)
val color_pre_wrapper : Pp.env -> F.formatter -> 'a -> Pp.env * bool val color_pre_wrapper : Pp.env -> F.formatter -> 'a -> Pp.env * bool
(** Begin change color if using diff printing, return updated printenv and change status *)
(** Close color annotation if changed *)
val color_post_wrapper : bool -> Pp.env -> F.formatter -> unit val color_post_wrapper : bool -> Pp.env -> F.formatter -> unit
(** Close color annotation if changed *)
(** Pretty print an expression. *)
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 with type. *)
val pp_exp_typ : Pp.env -> F.formatter -> Exp.t * Typ.t -> unit val pp_exp_typ : Pp.env -> F.formatter -> Exp.t * Typ.t -> unit
(** Pretty print an expression with type. *)
(** dump an expression. *)
val d_exp : Exp.t -> unit val d_exp : Exp.t -> unit
(** dump an expression. *)
(** Pretty print a type. *)
val pp_texp : Pp.env -> F.formatter -> Exp.t -> unit val pp_texp : Pp.env -> F.formatter -> Exp.t -> unit
(** Pretty print a type. *)
(** Pretty print a type with all the details. *)
val pp_texp_full : Pp.env -> F.formatter -> Exp.t -> unit val pp_texp_full : Pp.env -> F.formatter -> Exp.t -> unit
(** Pretty print a type with all the details. *)
(** Dump a type expression with all the details. *)
val d_texp_full : Exp.t -> unit val d_texp_full : Exp.t -> unit
(** Dump a type expression with all the details. *)
(** Pretty print a list of expressions. *)
val pp_exp_list : Pp.env -> F.formatter -> Exp.t list -> unit val pp_exp_list : Pp.env -> F.formatter -> Exp.t list -> unit
(** Pretty print a list of expressions. *)
(** Dump a list of expressions. *)
val d_exp_list : Exp.t list -> unit val d_exp_list : Exp.t list -> unit
(** Dump a list of expressions. *)
(** Pretty print an offset *)
val pp_offset : Pp.env -> F.formatter -> offset -> unit val pp_offset : Pp.env -> F.formatter -> offset -> unit
(** Pretty print an offset *)
(** Convert an offset to a string *)
val offset_to_string : offset -> string val offset_to_string : offset -> string
(** Convert an offset to a string *)
(** Dump an offset *)
val d_offset : offset -> unit val d_offset : offset -> unit
(** Dump an offset *)
(** Pretty print a list of offsets *)
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 *)
(** Dump a list of offsets *)
val d_offset_list : offset list -> unit val d_offset_list : offset list -> unit
(** Dump a list of offsets *)
(** Get the location of the instruction *)
val instr_get_loc : instr -> Location.t val instr_get_loc : instr -> Location.t
(** Get the location of the instruction *)
(** get the expressions occurring in the instruction *)
val instr_get_exps : instr -> Exp.t list val instr_get_exps : instr -> Exp.t list
(** get the expressions occurring in the instruction *)
(** Pretty print an instruction. *)
val pp_instr : Pp.env -> F.formatter -> instr -> unit val pp_instr : Pp.env -> F.formatter -> instr -> unit
(** Pretty print an instruction. *)
(** Dump an instruction. *)
val d_instr : instr -> unit val d_instr : instr -> unit
(** Dump an instruction. *)
(** Pretty print a list of instructions. *)
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. *)
(** Dump a list of instructions. *)
val d_instr_list : instr list -> unit val d_instr_list : instr list -> unit
(** Dump a list of instructions. *)
(** Pretty print an atom. *)
val pp_atom : Pp.env -> F.formatter -> atom -> unit val pp_atom : Pp.env -> F.formatter -> atom -> unit
(** Pretty print an atom. *)
(** Dump an atom. *)
val d_atom : atom -> unit val d_atom : atom -> unit
(** Dump an atom. *)
(** return a string representing the inst *)
val inst_to_string : inst -> string val inst_to_string : inst -> string
(** return a string representing the inst *)
(** Pretty print a strexp. *)
val pp_sexp : Pp.env -> F.formatter -> strexp -> unit val pp_sexp : Pp.env -> F.formatter -> strexp -> unit
(** Pretty print a strexp. *)
(** Dump a strexp. *)
val d_sexp : strexp -> unit val d_sexp : strexp -> unit
(** Dump a strexp. *)
(** Pretty print a strexp list. *)
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. *)
(** Dump a strexp. *)
val d_sexp_list : strexp list -> unit val d_sexp_list : strexp list -> unit
(** Dump a strexp. *)
(** Pretty print a hpred. *)
val pp_hpred : Pp.env -> F.formatter -> hpred -> unit val pp_hpred : Pp.env -> F.formatter -> hpred -> unit
(** Pretty print a hpred. *)
(** Dump a hpred. *)
val d_hpred : hpred -> unit val d_hpred : hpred -> unit
(** Dump a hpred. *)
(** Pretty print a hpara. *)
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 list of hparas. *)
val pp_hpara_list : Pp.env -> F.formatter -> hpara list -> unit val pp_hpara_list : Pp.env -> F.formatter -> hpara list -> unit
(** Pretty print a list of hparas. *)
(** Pretty print a hpara_dll. *)
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 list of hpara_dlls. *)
val pp_hpara_dll_list : Pp.env -> F.formatter -> hpara_dll list -> unit 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. *)
module Predicates : sig module Predicates : sig
(** predicate environment *) (** predicate environment *)
type env type env
(** create an empty predicate environment *)
val empty_env : unit -> env val empty_env : unit -> env
(** create an empty predicate environment *)
(** return true if the environment is empty *)
val is_empty : env -> bool val is_empty : env -> bool
(** return true if the environment is empty *)
(** return the id of the hpara *)
val get_hpara_id : env -> hpara -> int val get_hpara_id : env -> hpara -> int
(** return the id of the hpara *)
(** return the id of the hpara_dll *)
val get_hpara_dll_id : env -> hpara_dll -> int 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
(** [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. *)
val iter : env -> (int -> hpara -> unit) -> (int -> hpara_dll -> unit) -> unit
(** Process one hpred, updating the predicate environment *)
val process_hpred : env -> hpred -> unit val process_hpred : env -> hpred -> unit
(** Process one hpred, updating the predicate environment *)
end end
(** Pretty print a hpred with optional predicate env *)
val pp_hpred_env : Pp.env -> Predicates.env option -> F.formatter -> hpred -> unit val pp_hpred_env : Pp.env -> Predicates.env option -> F.formatter -> hpred -> unit
(** Pretty print a hpred with optional predicate env *)
(** {2 Functions for traversing SIL data types} *) (** {2 Functions for traversing SIL data types} *)
val array_clean_new_index : bool -> Exp.t -> Exp.t
(** This function should be used before adding a new (** This function should be used before adding a new
index to Earray. The [exp] is the newly created index to Earray. The [exp] is the newly created
index. This function "cleans" [exp] according to whether it is the index. This function "cleans" [exp] according to whether it is the
footprint or current part of the prop. footprint or current part of the prop.
The function faults in the re - execution mode, as an internal check of the tool. *) The function faults in the re - execution mode, as an internal check of the tool. *)
val array_clean_new_index : bool -> Exp.t -> Exp.t
(** Change exps in strexp using [f]. *)
(** WARNING: the result might not be normalized. *)
val strexp_expmap : (Exp.t * inst option -> Exp.t * inst option) -> strexp -> strexp val strexp_expmap : (Exp.t * inst option -> Exp.t * inst option) -> strexp -> strexp
(** Change exps in strexp using [f].
(** Change exps in hpred by [f]. *) WARNING: the result might not be normalized. *)
(** WARNING: the result might not be normalized. *)
val hpred_expmap : (Exp.t * inst option -> Exp.t * inst option) -> hpred -> hpred val hpred_expmap : (Exp.t * inst option -> Exp.t * inst option) -> hpred -> hpred
(** Change exps in hpred by [f].
(** Change instrumentations in hpred using [f]. *) WARNING: the result might not be normalized. *)
val hpred_instmap : (inst -> inst) -> hpred -> hpred val hpred_instmap : (inst -> inst) -> hpred -> hpred
(** Change instrumentations in hpred using [f]. *)
(** Change exps in hpred list by [f]. *)
(** WARNING: the result might not be normalized. *)
val hpred_list_expmap : (Exp.t * inst option -> Exp.t * inst option) -> hpred list -> hpred list val hpred_list_expmap : (Exp.t * inst option -> Exp.t * inst option) -> hpred list -> hpred list
(** Change exps in hpred list by [f].
(** Change exps in atom by [f]. *) WARNING: the result might not be normalized. *)
(** WARNING: the result might not be normalized. *)
val atom_expmap : (Exp.t -> Exp.t) -> atom -> atom val atom_expmap : (Exp.t -> Exp.t) -> atom -> atom
(** Change exps in atom by [f].
(** Change exps in atom list 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 val atom_list_expmap : (Exp.t -> Exp.t) -> atom list -> atom list
(** Change exps in atom list by [f].
(** {2 Function for computing lexps in sigma} *) 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
(** {2 Functions for computing program variables} *) (** {2 Function for computing lexps in sigma} *)
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 strexp_fpv : strexp -> Pvar.t list
val atom_fpv : atom -> Pvar.t list val atom_fpv : atom -> Pvar.t list
@ -561,75 +465,58 @@ val hpara_fpv : hpara -> Pvar.t list
(** Type of free variables. These include primed, normal and footprint variables. (** Type of free variables. These include primed, normal and footprint variables.
We remember the order in which variables are added. *) We remember the order in which variables are added. *)
type fav type fav
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 fav_duplicates : bool ref
(** Pretty print a fav. *)
val pp_fav : Pp.env -> F.formatter -> fav -> unit val pp_fav : Pp.env -> F.formatter -> fav -> unit
(** Pretty print a fav. *)
(** Create a new [fav]. *)
val fav_new : unit -> fav val fav_new : unit -> fav
(** Create a new [fav]. *)
(** Emptyness check. *)
val fav_is_empty : fav -> bool val fav_is_empty : fav -> bool
(** Emptyness check. *)
(** Check whether a predicate holds for all elements. *)
val fav_for_all : fav -> (Ident.t -> bool) -> bool val fav_for_all : fav -> (Ident.t -> bool) -> bool
(** Check whether a predicate holds for all elements. *)
(** Check whether a predicate holds for some elements. *)
val fav_exists : fav -> (Ident.t -> bool) -> bool val fav_exists : fav -> (Ident.t -> bool) -> bool
(** Check whether a predicate holds for some elements. *)
(** Membership test fot [fav] *)
val fav_mem : fav -> Ident.t -> bool val fav_mem : fav -> Ident.t -> bool
(** Membership test fot [fav] *)
(** Convert a list to a fav. *)
val fav_from_list : Ident.t list -> fav val fav_from_list : Ident.t list -> fav
(** Convert a list to a fav. *)
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_to_list : fav -> Ident.t list
(** Copy a [fav]. *)
val fav_copy : fav -> fav val fav_copy : fav -> fav
(** Copy a [fav]. *)
(** Turn a xxx_fav_add function into a xxx_fav function *)
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 *)
(** [fav_filter_ident fav f] only keeps [id] if [f id] is true. *)
val fav_filter_ident : fav -> (Ident.t -> bool) -> unit val fav_filter_ident : fav -> (Ident.t -> bool) -> unit
(** [fav_filter_ident fav f] only keeps [id] if [f id] is true. *)
(** Like [fav_filter_ident] but return a copy. *)
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. *)
val fav_subset_ident : fav -> fav -> bool
(** [fav_subset_ident fav1 fav2] returns true if every ident in [fav1] (** [fav_subset_ident fav1 fav2] returns true if every ident in [fav1]
is in [fav2].*) is in [fav2].*)
val fav_subset_ident : fav -> fav -> bool
(** add identifier list to fav *)
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 *)
(** [exp_fav_add fav exp] extends [fav] with the free variables of [exp] *)
val exp_fav_add : fav -> Exp.t -> unit val exp_fav_add : fav -> Exp.t -> unit
(** [exp_fav_add fav exp] extends [fav] with the free variables of [exp] *)
val exp_fav : Exp.t -> fav val exp_fav : Exp.t -> fav
@ -647,23 +534,20 @@ val hpred_fav_add : fav -> hpred -> unit
val hpred_fav : hpred -> fav val hpred_fav : hpred -> fav
(** Variables in hpara, excluding bound vars in the body *)
val hpara_shallow_av : hpara -> fav val hpara_shallow_av : hpara -> fav
(** Variables in hpara, excluding bound vars in the body *)
(** Variables in hpara_dll, excluding bound vars in the body *)
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 *)
(** {2 Functions for computing all free or bound non-program variables} *) (** {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 (** Non-program variables include all of primed, normal and footprint
variables. Thus, the functions essentially compute all the variables. Thus, the functions essentially compute all the
identifiers occuring in a parameter. Some variables can appear more identifiers occuring in a parameter. Some variables can appear more
than once in the result. *) than once in the result. *)
val exp_av_add : fav -> Exp.t -> unit
val strexp_av_add : fav -> strexp -> unit val strexp_av_add : fav -> strexp -> unit
val atom_av_add : fav -> atom -> unit val atom_av_add : fav -> atom -> unit
@ -680,29 +564,24 @@ 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)] type subst_fun = [`Exp of Ident.t -> Exp.t | `Typ of (Typ.t -> Typ.t) * (Typ.Name.t -> Typ.Name.t)]
(** Equality for substitutions. *)
val equal_exp_subst : exp_subst -> exp_subst -> bool val equal_exp_subst : exp_subst -> exp_subst -> bool
(** Equality for substitutions. *)
val exp_subst_of_list : (Ident.t * Exp.t) list -> exp_subst
(** Create a substitution from a list of pairs. (** Create a substitution from a list of pairs.
For all (id1, e1), (id2, e2) in the input list, For all (id1, e1), (id2, e2) in the input list,
if id1 = id2, then e1 = e2. *) if id1 = id2, then e1 = e2. *)
val exp_subst_of_list : (Ident.t * Exp.t) list -> exp_subst
val subst_of_list : (Ident.t * Exp.t) list -> subst val subst_of_list : (Ident.t * Exp.t) list -> subst
(** like exp_subst_of_list, but allow duplicate ids and only keep the first occurrence *)
val exp_subst_of_list_duplicates : (Ident.t * Exp.t) list -> exp_subst val exp_subst_of_list_duplicates : (Ident.t * Exp.t) list -> exp_subst
(** like exp_subst_of_list, but allow duplicate ids and only keep the first occurrence *)
(** Convert a subst to a list of pairs. *)
val sub_to_list : exp_subst -> (Ident.t * Exp.t) list val sub_to_list : exp_subst -> (Ident.t * Exp.t) list
(** Convert a subst to a list of pairs. *)
(** The empty substitution. *)
val sub_empty : subst val sub_empty : subst
(** The empty substitution. *)
val exp_sub_empty : exp_subst val exp_sub_empty : exp_subst
@ -710,106 +589,87 @@ val is_sub_empty : subst -> bool
(* let to_exp_subst : [< `Exp exp_subst] => exp_subst; *) (* let to_exp_subst : [< `Exp exp_subst] => exp_subst; *)
val sub_join : exp_subst -> exp_subst -> exp_subst
(** Compute the common id-exp part of two inputs [subst1] and [subst2]. (** Compute the common id-exp part of two inputs [subst1] and [subst2].
The first component of the output is this common part. The first component of the output is this common part.
The second and third components are the remainder of [subst1] The second and third components are the remainder of [subst1]
and [subst2], respectively. *) and [subst2], respectively. *)
val sub_join : exp_subst -> exp_subst -> exp_subst val sub_symmetric_difference : exp_subst -> exp_subst -> exp_subst * exp_subst * exp_subst
(** Compute the common id-exp part of two inputs [subst1] and [subst2]. (** Compute the common id-exp part of two inputs [subst1] and [subst2].
The first component of the output is this common part. The first component of the output is this common part.
The second and third components are the remainder of [subst1] The second and third components are the remainder of [subst1]
and [subst2], respectively. *) and [subst2], respectively. *)
val sub_symmetric_difference : exp_subst -> exp_subst -> exp_subst * exp_subst * exp_subst val sub_find : (Ident.t -> bool) -> exp_subst -> Exp.t
(** [sub_find filter sub] returns the expression associated to the first identifier (** [sub_find filter sub] returns the expression associated to the first identifier
that satisfies [filter]. that satisfies [filter].
Raise [Not_found] if there isn't one. *) Raise [Not_found] if there isn't one. *)
val sub_find : (Ident.t -> bool) -> exp_subst -> Exp.t val sub_filter : (Ident.t -> bool) -> exp_subst -> exp_subst
(** [sub_filter filter sub] restricts the domain of [sub] to the (** [sub_filter filter sub] restricts the domain of [sub] to the
identifiers satisfying [filter]. *) identifiers satisfying [filter]. *)
val sub_filter : (Ident.t -> bool) -> exp_subst -> exp_subst val sub_filter_pair : exp_subst -> f:(Ident.t * Exp.t -> bool) -> exp_subst
(** [sub_filter_exp filter sub] restricts the domain of [sub] to the (** [sub_filter_exp filter sub] restricts the domain of [sub] to the
identifiers satisfying [filter(id, sub(id))]. *) identifiers satisfying [filter(id, sub(id))]. *)
val sub_filter_pair : exp_subst -> f:(Ident.t * Exp.t -> bool) -> exp_subst val sub_range_partition : (Exp.t -> bool) -> exp_subst -> exp_subst * exp_subst
(** [sub_range_partition filter sub] partitions [sub] according to (** [sub_range_partition filter sub] partitions [sub] according to
whether range expressions satisfy [filter]. *) whether range expressions satisfy [filter]. *)
val sub_range_partition : (Exp.t -> bool) -> exp_subst -> exp_subst * exp_subst val sub_domain_partition : (Ident.t -> bool) -> exp_subst -> exp_subst * exp_subst
(** [sub_domain_partition filter sub] partitions [sub] according to (** [sub_domain_partition filter sub] partitions [sub] according to
whether domain identifiers satisfy [filter]. *) whether domain identifiers satisfy [filter]. *)
val sub_domain_partition : (Ident.t -> bool) -> exp_subst -> exp_subst * exp_subst
(** Return the list of identifiers in the domain of the substitution. *)
val sub_domain : exp_subst -> Ident.t list val sub_domain : exp_subst -> Ident.t list
(** Return the list of identifiers in the domain of the substitution. *)
(** Return the list of expressions in the range of the substitution. *)
val sub_range : exp_subst -> Exp.t list val sub_range : exp_subst -> Exp.t list
(** Return the list of expressions in the range of the substitution. *)
(** [sub_range_map f sub] applies [f] to the expressions in the range of [sub]. *)
val sub_range_map : (Exp.t -> Exp.t) -> exp_subst -> exp_subst val sub_range_map : (Exp.t -> Exp.t) -> exp_subst -> exp_subst
(** [sub_range_map f sub] applies [f] to the expressions in the range of [sub]. *)
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 sub_map : (Ident.t -> Ident.t) -> (Exp.t -> Exp.t) -> exp_subst -> exp_subst
(** Checks whether [id] belongs to the domain of [subst]. *)
val mem_sub : Ident.t -> exp_subst -> bool val mem_sub : Ident.t -> exp_subst -> bool
(** Checks whether [id] belongs to the domain of [subst]. *)
(** Extend substitution and return [None] if not possible. *)
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. *)
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_fav_add : fav -> exp_subst -> unit val sub_av_add : fav -> exp_subst -> unit
(** Free or bound auxilary variables in the domain and range of the (** Free or bound auxilary variables in the domain and range of the
substitution. *) substitution. *)
val sub_av_add : fav -> exp_subst -> unit (** substitution functions
WARNING: these functions do not ensure that the results are normalized. *)
(** substitution functions *)
(** WARNING: these functions do not ensure that the results are normalized. *)
val exp_sub : subst -> Exp.t -> Exp.t val exp_sub : subst -> Exp.t -> Exp.t
val atom_sub : subst -> atom -> atom val atom_sub : subst -> atom -> atom
(** apply [subst] to all id's in [instr], including LHS id's *)
val instr_sub : subst -> instr -> instr val instr_sub : subst -> instr -> instr
(** apply [subst] to all id's in [instr], including LHS id's *)
val hpred_sub : subst -> hpred -> hpred val hpred_sub : subst -> hpred -> hpred
(** apply [f] to id's in [instr]. if [sub_id_binders] is false, [f] is only applied to bound id's *)
val instr_sub_ids : sub_id_binders:bool -> subst_fun -> instr -> instr 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. (** The first parameter should define a partial function.
No parts of hpara are replaced by these functions. *) No parts of hpara are replaced by these functions. *)
val exp_replace_exp : (Exp.t * Exp.t) list -> Exp.t -> Exp.t
val strexp_replace_exp : (Exp.t * Exp.t) list -> strexp -> strexp 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
@ -818,30 +678,26 @@ val hpred_replace_exp : (Exp.t * Exp.t) list -> hpred -> hpred
(** {2 Functions for constructing or destructing entities in this module} *) (** {2 Functions for constructing or destructing entities in this module} *)
(** Compute the offset list of an expression *)
val exp_get_offsets : Exp.t -> offset list val exp_get_offsets : Exp.t -> offset list
(** Compute the offset list of an expression *)
(** Add the offset list to an expression *)
val exp_add_offsets : Exp.t -> offset list -> Exp.t val exp_add_offsets : Exp.t -> offset list -> Exp.t
(** Add the offset list to an expression *)
val sigma_to_sigma_ne : hpred list -> (atom list * hpred list) list val sigma_to_sigma_ne : hpred list -> (atom list * hpred list) list
val hpara_instantiate : hpara -> Exp.t -> Exp.t -> Exp.t list -> Ident.t list * hpred list
(** [hpara_instantiate para e1 e2 elist] instantiates [para] with [e1], (** [hpara_instantiate para e1 e2 elist] instantiates [para] with [e1],
[e2] and [elist]. If [para = lambda (x, y, xs). exists zs. b], [e2] and [elist]. If [para = lambda (x, y, xs). exists zs. b],
then the result of the instantiation is [b\[e1 / x, e2 / y, elist / xs, _zs'/ zs\]] then the result of the instantiation is [b\[e1 / x, e2 / y, elist / xs, _zs'/ zs\]]
for some fresh [_zs'].*) for some fresh [_zs'].*)
val hpara_instantiate : hpara -> Exp.t -> Exp.t -> Exp.t list -> Ident.t list * hpred list val hpara_dll_instantiate :
hpara_dll -> Exp.t -> Exp.t -> Exp.t -> Exp.t list -> Ident.t list * hpred list
(** [hpara_dll_instantiate para cell blink flink elist] instantiates [para] with [cell], (** [hpara_dll_instantiate para cell blink flink elist] instantiates [para] with [cell],
[blink], [flink], and [elist]. If [para = lambda (x, y, z, xs). exists zs. b], [blink], [flink], and [elist]. If [para = lambda (x, y, z, xs). exists zs. b],
then the result of the instantiation is then the result of the instantiation is
[b\[cell / x, blink / y, flink / z, elist / xs, _zs'/ zs\]] [b\[cell / x, blink / y, flink / z, elist / xs, _zs'/ zs\]]
for some fresh [_zs'].*) for some fresh [_zs'].*)
val hpara_dll_instantiate :
hpara_dll -> Exp.t -> Exp.t -> Exp.t -> Exp.t list -> Ident.t list * hpred list
val custom_error : Pvar.t val custom_error : Pvar.t

@ -9,6 +9,7 @@
*) *)
(** The Smallfoot Intermediate Language: Subtypes *) (** The Smallfoot Intermediate Language: Subtypes *)
open! IStd open! IStd
module L = Logging module L = Logging
module F = Format module F = Format

@ -9,6 +9,7 @@
*) *)
(** The Smallfoot Intermediate Language: Subtypes *) (** The Smallfoot Intermediate Language: Subtypes *)
open! IStd open! IStd
module L = Logging module L = Logging
module F = Format module F = Format
@ -21,46 +22,40 @@ val sub_type : (Typ.Name.t -> Typ.Name.t) -> t -> t
val exact : t val exact : t
(** denotes the current type only *)
val subtypes : t val subtypes : t
(** denotes the current type only *)
(** denotes the current type and any subtypes *)
val subtypes_cast : t val subtypes_cast : t
(** denotes the current type and any subtypes *)
val subtypes_instof : t val subtypes_instof : t
val join : t -> t -> t val join : t -> t -> t
val case_analysis : Tenv.t -> Typ.Name.t * t -> Typ.Name.t * t -> t option * t option
(** [case_analysis tenv (c1, st1) (c2, st2)] performs case analysis on [c1 <: c2] according (** [case_analysis tenv (c1, st1) (c2, st2)] performs case analysis on [c1 <: c2] according
to [st1] and [st2]. to [st1] and [st2].
[case_analysis] returns a pair: [case_analysis] returns a pair:
- whether [st1] and [st2] admit [c1 <: c2], and in case returns the updated subtype [st1] - whether [st1] and [st2] admit [c1 <: c2], and in case returns the updated subtype [st1]
- whether [st1] and [st2] admit [not(c1 <: c2)], and in case returns the updated subtype [st1] *) - whether [st1] and [st2] admit [not(c1 <: c2)], and in case returns the updated subtype [st1] *)
val case_analysis : Tenv.t -> Typ.Name.t * t -> Typ.Name.t * t -> t option * t option val is_known_subtype : Tenv.t -> Typ.Name.t -> Typ.Name.t -> bool
(** [is_known_subtype tenv c1 c2] returns true if there is enough information in [tenv] to prove (** [is_known_subtype tenv c1 c2] returns true if there is enough information in [tenv] to prove
that [c1] is a subtype of [c2]. that [c1] is a subtype of [c2].
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_subtype : Tenv.t -> Typ.Name.t -> Typ.Name.t -> bool 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 (** [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]. that [c1] is not a subtype of [c2].
Note that [not (is_known_not_subtype tenv c1 c2) == true] does not imply Note that [not (is_known_not_subtype tenv c1 c2) == true] does not imply
that [is_known_subtype tenv c1 c2 == true] *) that [is_known_subtype tenv c1 c2 == true] *)
val is_known_not_subtype : Tenv.t -> Typ.Name.t -> Typ.Name.t -> bool
val subtypes_to_string : t -> string 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
(** equality ignoring flags in the subtype *)
val equal_modulo_flag : t -> t -> bool val equal_modulo_flag : t -> t -> bool
(** equality ignoring flags in the subtype *)

@ -11,53 +11,41 @@ open! IStd
(** Module for Type Environments. *) (** Module for Type Environments. *)
type t
(** Type for type environment. *) (** Type for type environment. *)
type t
(** Add a (name,typename) pair to the global type environment. *)
val add : t -> Typ.Name.t -> Typ.Struct.t -> unit val add : t -> Typ.Name.t -> Typ.Struct.t -> unit
(** Add a (name,typename) pair to the global type environment. *)
(** Create a new type environment. *)
val create : unit -> t val create : unit -> t
(** Create a new type environment. *)
(** Fold a function over the elements of the type environment. *)
val fold : (Typ.Name.t -> Typ.Struct.t -> 'a -> 'a) -> t -> 'a -> 'a val fold : (Typ.Name.t -> Typ.Struct.t -> 'a -> 'a) -> t -> 'a -> 'a
(** Fold a function over the elements of the type environment. *)
(** iterate over a type environment *)
val iter : (Typ.Name.t -> Typ.Struct.t -> unit) -> t -> unit val iter : (Typ.Name.t -> Typ.Struct.t -> unit) -> t -> unit
(** iterate over a type environment *)
(** Load a type environment from a file *)
val load_from_file : DB.filename -> t option val load_from_file : DB.filename -> t option
(** Load a type environment from a file *)
(** Look up a name in the global type environment. *)
val lookup : t -> Typ.Name.t -> Typ.Struct.t option val lookup : t -> Typ.Name.t -> Typ.Struct.t option
(** Look up a name in the global type environment. *)
(** Construct a struct_typ, normalizing field types *)
val mk_struct : val mk_struct :
t -> ?default:Typ.Struct.t -> ?fields:Typ.Struct.fields -> ?statics:Typ.Struct.fields t -> ?default:Typ.Struct.t -> ?fields:Typ.Struct.fields -> ?statics:Typ.Struct.fields
-> ?methods:Typ.Procname.t list -> ?supers:Typ.Name.t list -> ?annots:Annot.Item.t -> Typ.Name.t -> ?methods:Typ.Procname.t list -> ?supers:Typ.Name.t list -> ?annots:Annot.Item.t -> Typ.Name.t
-> Typ.Struct.t -> Typ.Struct.t
(** Construct a struct_typ, normalizing field types *)
(** Check if typename is found in t *)
val mem : t -> Typ.Name.t -> bool val mem : t -> Typ.Name.t -> bool
(** Check if typename is found in t *)
(** print a type environment *)
val pp : Format.formatter -> t -> unit val pp : Format.formatter -> t -> unit
(** print a type environment *)
(** Save a type environment into a file *)
val store_to_file : DB.filename -> t -> unit val store_to_file : DB.filename -> t -> unit
(** Save a type environment into a file *)
(** Get method that is being overriden by java_pname (if any) **)
val get_overriden_method : t -> Typ.Procname.java -> Typ.Procname.t option val get_overriden_method : t -> Typ.Procname.java -> Typ.Procname.t option
(** Get method that is being overriden by java_pname (if any) **)

@ -9,6 +9,7 @@
*) *)
(** The Smallfoot Intermediate Language: Types *) (** The Smallfoot Intermediate Language: Types *)
open! IStd open! IStd
module Hashtbl = Caml.Hashtbl module Hashtbl = Caml.Hashtbl
module L = Logging module L = Logging
@ -124,10 +125,8 @@ module T = struct
| Tptr of t * ptr_kind (** pointer type *) | Tptr of t * ptr_kind (** pointer type *)
| Tstruct of name (** structured value type name *) | Tstruct of name (** structured value type name *)
| TVar of string (** type variable (ie. C++ template variables) *) | TVar of string (** type variable (ie. C++ template variables) *)
| Tarray of | Tarray of t * IntLit.t option * IntLit.t option
t (** array type with statically fixed length and stride *)
* IntLit.t option
* (** array type with statically fixed length and stride *) IntLit.t option
[@@deriving compare] [@@deriving compare]
and name = and name =
@ -487,9 +486,8 @@ module Procname = struct
{ method_name: string { method_name: string
; parameters: java_type list ; parameters: java_type list
; class_name: Name.t ; class_name: Name.t
; return_type: java_type option ; return_type: java_type option (* option because constructors have no return type *)
; (* option because constructors have no return type *) ; kind: method_kind }
kind: method_kind }
[@@deriving compare] [@@deriving compare]
(** Type of c procedure names. *) (** Type of c procedure names. *)
@ -501,7 +499,7 @@ module Procname = struct
[@@deriving compare] [@@deriving compare]
type objc_cpp_method_kind = type objc_cpp_method_kind =
| CPPMethod of (** with mangling *) string option | CPPMethod of string option (** with mangling *)
| CPPConstructor of (string option * bool) (** with mangling + is it constexpr? *) | CPPConstructor of (string option * bool) (** with mangling + is it constexpr? *)
| ObjCClassMethod | ObjCClassMethod
| ObjCInstanceMethod | ObjCInstanceMethod
@ -1011,8 +1009,8 @@ module Procname = struct
| _ | _
-> to_concrete_filename pname -> to_concrete_filename pname
let get_template_args_mapping generic_procname concrete_procname =
(** given two template arguments, try to generate mapping from generic ones to concrete ones. *) (** 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) = let mapping_for_template_args (generic_name, generic_args) (concrete_name, concrete_args) =
match (generic_args, concrete_args) with match (generic_args, concrete_args) with
| Template generic_typs, Template concrete_typs | Template generic_typs, Template concrete_typs

@ -9,11 +9,11 @@
*) *)
(** The Smallfoot Intermediate Language: Types *) (** The Smallfoot Intermediate Language: Types *)
open! IStd open! IStd
module F = Format module F = Format
(** Kinds of integers *) (** Kinds of integers *)
type ikind = type ikind =
| IChar (** [char] *) | IChar (** [char] *)
| ISChar (** [signed char] *) | ISChar (** [signed char] *)
@ -31,21 +31,17 @@ type ikind =
| IU128 (** [__uint128_t] *) | IU128 (** [__uint128_t] *)
[@@deriving compare] [@@deriving compare]
(** Check wheter the integer kind is a char *)
val ikind_is_char : ikind -> bool val ikind_is_char : ikind -> bool
(** Check whether the integer kind is a char *)
(** Check wheter the integer kind is unsigned *)
val ikind_is_unsigned : ikind -> bool val ikind_is_unsigned : ikind -> bool
(** 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: (** Convert an int64 into an IntLit.t given the kind:
the int64 is interpreted as unsigned according to the kind *) the int64 is interpreted as unsigned according to the kind *)
val int_of_int64_kind : int64 -> ikind -> IntLit.t
(** Kinds of floating-point numbers *) (** Kinds of floating-point numbers *)
type fkind = type fkind =
| FFloat (** [float] *) | FFloat (** [float] *)
| FDouble (** [double] *) | FDouble (** [double] *)
@ -53,7 +49,6 @@ type fkind =
[@@deriving compare] [@@deriving compare]
(** kind of pointer *) (** kind of pointer *)
type ptr_kind = type ptr_kind =
| Pk_pointer (** C/C++, Java, Objc standard/__strong pointer *) | Pk_pointer (** C/C++, Java, Objc standard/__strong pointer *)
| Pk_reference (** C++ reference *) | Pk_reference (** C++ reference *)
@ -77,7 +72,6 @@ val is_restrict : type_quals -> bool
val is_volatile : type_quals -> bool val is_volatile : type_quals -> bool
(** types for sil (structured) expressions *) (** types for sil (structured) expressions *)
type t = {desc: desc; quals: type_quals} [@@deriving compare] type t = {desc: desc; quals: type_quals} [@@deriving compare]
and desc = and desc =
@ -88,10 +82,8 @@ and desc =
| Tptr of t * ptr_kind (** pointer type *) | Tptr of t * ptr_kind (** pointer type *)
| Tstruct of name (** structured value type name *) | Tstruct of name (** structured value type name *)
| TVar of string (** type variable (ie. C++ template variables) *) | TVar of string (** type variable (ie. C++ template variables) *)
| Tarray of | Tarray of t * IntLit.t option * IntLit.t option
t (** array type with statically fixed stride and length *)
* IntLit.t option
* (** array type with statically fixed stride and length *) IntLit.t option
[@@deriving compare] [@@deriving compare]
and name = and name =
@ -108,44 +100,35 @@ and name =
and template_spec_info = NoTemplate | Template of t option list [@@deriving compare] and template_spec_info = NoTemplate | Template of t option list [@@deriving compare]
(** Create Typ.t from given desc. if [default] is passed then use its value to set other fields such as quals *)
val mk : ?default:t -> ?quals:type_quals -> desc -> t val mk : ?default:t -> ?quals:type_quals -> desc -> t
(** Create Typ.t from given desc. if [default] is passed then use its value to set other fields such as quals *)
(** Stores information about type substitution *) (** Stores information about type substitution *)
type type_subst_t [@@deriving compare] type type_subst_t [@@deriving compare]
module Name : sig module Name : sig
(** Named types. *) (** Named types. *)
type t = name [@@deriving compare] type t = name [@@deriving compare]
(** Equality for typenames *)
val equal : t -> t -> bool val equal : t -> t -> bool
(** Equality for typenames *)
(** convert the typename to a string *)
val to_string : t -> string val to_string : t -> string
(** convert the typename to a string *)
val pp : Format.formatter -> t -> unit val pp : Format.formatter -> t -> unit
(** [is_class name] holds if [name] names CPP/Objc/Java class *)
val is_class : t -> bool val is_class : t -> bool
(** [is_class name] holds if [name] names CPP/Objc/Java class *)
(** [is_class name1 name2] holds if [name1] and [name2] name same kind of type *)
val is_same_type : t -> t -> bool val is_same_type : t -> t -> bool
(** [is_class name1 name2] holds if [name1] and [name2] name same kind of type *)
(** name of the typename without qualifier *)
val name : t -> string val name : t -> string
(** name of the typename without qualifier *)
(** qualified name of the type, may return nonsense for Java classes *)
val qual_name : t -> QualifiedCppName.t val qual_name : t -> QualifiedCppName.t
(** qualified name of the type, may return nonsense for Java classes *)
val unqualified_name : t -> QualifiedCppName.t val unqualified_name : t -> QualifiedCppName.t
@ -158,17 +141,14 @@ module Name : sig
end end
module Java : sig module Java : sig
(** Create a typename from a Java classname in the form "package.class" *)
val from_string : string -> t val from_string : string -> t
(** Create a typename from a Java classname in the form "package.class" *)
(** Create a typename from a package name and a class name *)
val from_package_class : string -> string -> t val from_package_class : string -> string -> t
(** Create a typename from a package name and a class name *)
(** [is_class name] holds if [name] names a Java class *)
val is_class : t -> bool val is_class : t -> bool
(** [is_class name] holds if [name] names a Java class *)
val java_lang_object : t val java_lang_object : t
@ -178,35 +158,30 @@ module Name : sig
end end
module Cpp : sig module Cpp : sig
(** Create a typename from a C++ classname *)
val from_qual_name : template_spec_info -> QualifiedCppName.t -> t val from_qual_name : template_spec_info -> QualifiedCppName.t -> t
(** Create a typename from a C++ classname *)
(** [is_class name] holds if [name] names a C++ class *)
val is_class : t -> bool val is_class : t -> bool
(** [is_class name] holds if [name] names a C++ class *)
end end
module Objc : sig module Objc : sig
(** Create a typename from a Objc classname *)
val from_string : string -> t val from_string : string -> t
(** Create a typename from a Objc classname *)
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
(** [is_class name] holds if [name] names a Objc class *)
val is_class : t -> bool 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
end end
(** Equality for types. *)
val equal : t -> t -> bool val equal : t -> t -> bool
(** Equality for types. *)
val equal_desc : desc -> desc -> bool val equal_desc : desc -> desc -> bool
@ -228,37 +203,30 @@ module Map : Caml.Map.S with type key = t
module Tbl : Caml.Hashtbl.S with type key = t module Tbl : Caml.Hashtbl.S with type key = t
(** Pretty print a type with all the details. *)
val pp_full : Pp.env -> F.formatter -> t -> unit val pp_full : Pp.env -> F.formatter -> t -> unit
(** Pretty print a type with all the details. *)
(** Pretty print a type. *)
val pp : Pp.env -> F.formatter -> t -> unit val pp : Pp.env -> F.formatter -> t -> unit
(** Pretty print a type. *)
val to_string : t -> string val to_string : t -> string
(** Dump a type with all the details. *)
val d_full : t -> unit val d_full : t -> unit
(** Dump a type with all the details. *)
(** Dump a list of types. *)
val d_list : t list -> unit val d_list : t list -> unit
(** Dump a list of types. *)
(** The name of a type *)
val name : t -> Name.t option val name : t -> Name.t option
(** The name of a type *)
(** turn a *T into a T. fails if [t] is not a pointer type *)
val strip_ptr : t -> t val strip_ptr : t -> t
(** turn a *T into a T. fails if [t] is not a pointer type *)
val array_elem : t option -> t -> t
(** If an array type, return the type of the element. (** If an array type, return the type of the element.
If not, return the default type if given, otherwise raise an exception *) If not, return the default type if given, otherwise raise an exception *)
val array_elem : t option -> t -> t
val is_objc_class : t -> bool val is_objc_class : t -> bool
val is_cpp_class : t -> bool val is_cpp_class : t -> bool
@ -271,9 +239,8 @@ val is_pointer_to_cpp_class : t -> bool
val has_block_prefix : string -> bool val has_block_prefix : string -> bool
(** Check if type is a type for a block in objc *)
val is_block_type : t -> 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
@ -283,23 +250,18 @@ module Procname : sig
(** Module for Procedure Names. *) (** Module for Procedure Names. *)
(** Type of java procedure names. *) (** Type of java procedure names. *)
type java type java
(** Type of c procedure names. *) (** Type of c procedure names. *)
type c type c
(** Type of Objective C and C++ procedure names. *) (** Type of Objective C and C++ procedure names. *)
type objc_cpp type objc_cpp
(** Type of Objective C block names. *) (** Type of Objective C block names. *)
type block type block
(** Type of procedure names. *) (** Type of procedure names. *)
type t = type t =
| Java of java | Java of java
| C of c | C of c
@ -308,21 +270,18 @@ module Procname : sig
| ObjC_Cpp of objc_cpp | ObjC_Cpp of objc_cpp
[@@deriving compare] [@@deriving compare]
(** Equality for proc names. *)
val equal : t -> t -> bool val equal : t -> t -> bool
(** Equality for proc names. *)
type java_type = string option * string type java_type = string option * string
type method_kind = type method_kind =
| Non_Static | Non_Static
(* in Java, procedures called with invokevirtual, invokespecial, and invokeinterface *) (** in Java, procedures called with invokevirtual, invokespecial, and invokeinterface *)
| Static | Static (** in Java, procedures called with invokestatic *)
(* in Java, procedures called with invokestatic *)
type objc_cpp_method_kind = type objc_cpp_method_kind =
| CPPMethod of (** with mangling *) string option | CPPMethod of string option (** with mangling *)
| CPPConstructor of (string option * bool) (** with mangling + is it constexpr? *) | CPPConstructor of (string option * bool) (** with mangling + is it constexpr? *)
| ObjCClassMethod | ObjCClassMethod
| ObjCInstanceMethod | ObjCInstanceMethod
@ -340,258 +299,200 @@ module Procname : sig
module Set : PrettyPrintable.PPSet with type elt = t module Set : PrettyPrintable.PPSet with type elt = t
(** Create a C procedure name from plain and mangled name. *)
val c : QualifiedCppName.t -> string -> template_spec_info -> is_generic_model:bool -> c val c : QualifiedCppName.t -> string -> template_spec_info -> is_generic_model:bool -> c
(** Create a C procedure name from plain and mangled name. *)
(** Empty block name. *)
val empty_block : t val empty_block : t
(** Empty block name. *)
(** Convert a string to a proc name. *)
val from_string_c_fun : string -> t val from_string_c_fun : string -> t
(** Convert a string to a proc name. *)
(** Return the language of the procedure. *)
val get_language : t -> Config.language val get_language : t -> Config.language
(** Return the language of the procedure. *)
(** Return the method/function of a procname. *)
val get_method : t -> string val get_method : t -> string
(** Return the method/function of a procname. *)
(** Hash function for procname. *)
val hash_pname : t -> int val hash_pname : t -> int
(** Hash function for procname. *)
(** Check if a class string is an anoynmous inner class name. *)
val is_anonymous_inner_class_name : Name.t -> bool val is_anonymous_inner_class_name : Name.t -> bool
(** Check if a class string is an anoynmous inner class name. *)
(** Check if this is an Objective-C/C++ method 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 a constructor method in Objective-C. *)
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. *)
val is_constructor : t -> bool val is_constructor : t -> bool
(** Check if this is a constructor. *)
(** Check if this is a constexpr function. *)
val is_constexpr : t -> bool val is_constexpr : t -> bool
(** Check if this is a constexpr function. *)
(** Check if this is a Java procedure name. *)
val is_java : t -> bool val is_java : t -> bool
(** Check if this is a Java procedure name. *)
(** Check if this is a dealloc method in Objective-C. *)
val is_objc_dealloc : string -> bool val is_objc_dealloc : string -> bool
(** Check if this is a dealloc method in Objective-C. *)
(** Check if this is a dealloc method. *)
val is_destructor : t -> bool val is_destructor : t -> bool
(** Check if this is a dealloc method. *)
val java : Name.t -> java_type option -> string -> java_type list -> method_kind -> java
(** Create a Java procedure name from its (** Create a Java procedure name from its
class_name method_name args_type_name return_type_name method_kind. *) class_name method_name args_type_name return_type_name method_kind. *)
val java : Name.t -> java_type option -> string -> java_type list -> method_kind -> java
(** Replace the parameters of a java procname. *)
val java_replace_parameters : java -> java_type list -> java val java_replace_parameters : java -> java_type list -> java
(** Replace the parameters of a java procname. *)
(** Replace the method of a java procname. *)
val java_replace_return_type : java -> java_type -> java val java_replace_return_type : java -> java_type -> java
(** Replace the method of a java procname. *)
(** Create an objc block name. *)
val mangled_objc_block : string -> t val mangled_objc_block : string -> t
(** Create an objc block name. *)
(** Create an objc procedure name from a class_name and method_name. *)
val objc_cpp : val objc_cpp :
Name.t -> string -> objc_cpp_method_kind -> template_spec_info -> is_generic_model:bool Name.t -> string -> objc_cpp_method_kind -> template_spec_info -> is_generic_model:bool
-> objc_cpp -> objc_cpp
(** Create an objc procedure name from a class_name and method_name. *)
val get_default_objc_class_method : Name.t -> t val get_default_objc_class_method : Name.t -> t
(** Get the class name of a Objective-C/C++ procedure name. *)
val objc_cpp_get_class_name : objc_cpp -> string val objc_cpp_get_class_name : objc_cpp -> string
(** Get the class name of a Objective-C/C++ procedure name. *)
val objc_cpp_get_class_type_name : objc_cpp -> Name.t val objc_cpp_get_class_type_name : objc_cpp -> Name.t
(** Create ObjC method type from a bool is_instance. *)
val objc_method_kind_of_bool : bool -> objc_cpp_method_kind val objc_method_kind_of_bool : bool -> objc_cpp_method_kind
(** Create ObjC method type from a bool is_instance. *)
(** Return the class name of a java procedure name. *)
val java_get_class_name : java -> string val java_get_class_name : java -> string
(** Return the class name of a java procedure name. *)
(** Return the class name as a typename of a java procedure name. *)
val java_get_class_type_name : java -> Name.t val java_get_class_type_name : java -> Name.t
(** Return the class name as a typename of a java procedure name. *)
(** Return the simple class name of a java procedure name. *)
val java_get_simple_class_name : java -> string val java_get_simple_class_name : java -> string
(** Return the simple class name of a java procedure name. *)
(** Return the package name of a java procedure name. *)
val java_get_package : java -> string option val java_get_package : java -> string option
(** Return the package name of a java procedure name. *)
(** Return the method name of a java procedure name. *)
val java_get_method : java -> string val java_get_method : java -> string
(** Return the method name of a java procedure name. *)
(** Return the return type of a java procedure name. *)
val java_get_return_type : java -> string val java_get_return_type : java -> string
(** Return the return type of a java procedure name. *)
(** Return the parameters 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 procname as strings. *)
val java_get_parameters_as_strings : java -> string list 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
(** 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. *)
val java_is_access_method : t -> bool
(** Check if the procedure name is of an auto-generated method containing '$'. *)
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 belongs to an anonymous inner class. *)
val java_is_anonymous_inner_class : t -> bool val java_is_anonymous_inner_class : t -> bool
(** Check if the procedure belongs to an anonymous inner class. *)
(** Check if the procedure name is an anonymous inner class constructor. *)
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 method name is "close". *)
val java_is_close : t -> bool val java_is_close : t -> bool
(** Check if the method name is "close". *)
(** Check if the java procedure is static. *)
val java_is_static : t -> bool val java_is_static : t -> bool
(** Check if the java procedure is static. *)
val java_is_vararg : t -> bool
(** Check if the proc name has the type of a java vararg. (** Check if the proc name has the type of a java vararg.
Note: currently only checks that the last argument has type Object[]. *) Note: currently only checks that the last argument has type Object[]. *)
val java_is_vararg : t -> bool
(** Check if the proc name comes from a lambda expression *)
val java_is_lambda : t -> bool val java_is_lambda : t -> bool
(** Check if the proc name comes from a lambda expression *)
(** Check if the proc name comes from generated code *)
val java_is_generated : t -> bool val java_is_generated : t -> bool
(** 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. (** 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 This is used in private constructors, where a proxy constructor is generated
with an extra parameter and calls the normal constructor. *) with an extra parameter and calls the normal constructor. *)
val java_remove_hidden_inner_class_parameter : t -> t option
(** Replace the method name of an existing java procname. *)
val java_replace_method : java -> string -> java val java_replace_method : java -> string -> java
(** Replace the method name of an existing java procname. *)
(** Convert a java type to a string. *)
val java_type_to_string : java_type -> string val java_type_to_string : java_type -> string
(** Convert a java type to a string. *)
(** Check if this is a class initializer. *)
val is_class_initializer : t -> bool val is_class_initializer : t -> bool
(** Check if this is a class initializer. *)
(** Check if this is a special Infer undefined procedure. *)
val is_infer_undefined : t -> bool val is_infer_undefined : t -> bool
(** Check if this is a special Infer undefined procedure. *)
val get_global_name_of_initializer : t -> string option
(** Return the name of the global for which this procedure is the initializer if this is an (** Return the name of the global for which this procedure is the initializer if this is an
initializer, None otherwise. *) initializer, None otherwise. *)
val get_global_name_of_initializer : t -> string option
(** Pretty print a proc name. *)
val pp : Format.formatter -> t -> unit val pp : Format.formatter -> t -> unit
(** Pretty print a proc name. *)
(** Pretty print a set of proc names. *)
val pp_set : Format.formatter -> Set.t -> unit val pp_set : Format.formatter -> Set.t -> unit
(** Pretty print a set of proc names. *)
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. *)
val replace_class : t -> Name.t -> t val split_classname : string -> string option * string
(** Given a package.class_name string, look for the latest dot and split the string (** Given a package.class_name string, look for the latest dot and split the string
in two (package, class_name). *) in two (package, class_name). *)
val split_classname : string -> string option * string
(** Convert a proc name to a string for the user to see. *)
val to_string : t -> string val to_string : t -> string
(** Convert a proc name to a string for the user to see. *)
(** Convert a proc name into a easy string for the user to see in an IDE. *)
val to_simplified_string : ?withclass:bool -> t -> string val to_simplified_string : ?withclass:bool -> t -> string
(** Convert a proc name into a easy string for the user to see in an IDE. *)
(** Convert a proc name into a unique identifier. *)
val to_unique_id : t -> string val to_unique_id : t -> string
(** Convert a proc name into a unique identifier. *)
(** Convert a proc name to a filename. *)
val to_filename : t -> string val to_filename : t -> string
(** Convert a proc name to a filename. *)
(** get qualifiers of C/objc/C++ method/function *)
val get_qualifiers : t -> QualifiedCppName.t val get_qualifiers : t -> QualifiedCppName.t
(** get qualifiers of C/objc/C++ method/function *)
(** get qualifiers of a class owning objc/C++ method *)
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 *)
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 (** Return type substitution that would produce concrete procname from generic procname. Returns None if
such substitution doesn't exist such substitution doesn't exist
NOTE: this function doesn't check if such substitution is correct in terms of return NOTE: this function doesn't check if such substitution is correct in terms of return
type/function parameters. type/function parameters.
NOTE: this function doesn't deal with nested template classes, it only extracts mapping for function 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. *) and/or direct parent (class that defines the method) if it exists. *)
val get_template_args_mapping : t -> t -> type_subst_t option
end end
(** Return the return type of [pname_java]. *)
val java_proc_return_typ : Procname.java -> t val java_proc_return_typ : Procname.java -> t
(** Return the return type of [pname_java]. *)
module Fieldname : sig module Fieldname : sig
(** Names for fields of class/struct/union *) (** Names for fields of class/struct/union *)
type t [@@deriving compare] type t [@@deriving compare]
(** Equality for field names. *)
val equal : t -> t -> bool val equal : t -> t -> bool
(** Equality for field names. *)
(** Set for fieldnames *) (** Set for fieldnames *)
@ -606,58 +507,46 @@ module Fieldname : sig
end end
module Java : sig module Java : sig
(** Create a java field name from string *)
val from_string : string -> t val from_string : string -> t
(** Create a java field name from string *)
end end
(** Convert a field name to a string. *)
val to_string : t -> string val to_string : t -> string
(** Convert a field name to a string. *)
val to_full_string : t -> string val to_full_string : t -> string
val class_name_replace : t -> f:(Name.t -> Name.t) -> t val class_name_replace : t -> f:(Name.t -> Name.t) -> t
(** Convert a fieldname to a simplified string with at most one-level path. *)
val to_simplified_string : t -> string val to_simplified_string : t -> string
(** Convert a fieldname to a simplified string with at most one-level path. *)
(** Convert a fieldname to a flat string without path. *)
val to_flat_string : t -> string val to_flat_string : t -> string
(** Convert a fieldname to a flat string without path. *)
(** Pretty print a field name. *)
val pp : Format.formatter -> t -> unit val pp : Format.formatter -> t -> unit
(** Pretty print a field name. *)
(** Pretty print a field name in latex. *)
val pp_latex : Latex.style -> Format.formatter -> t -> unit val pp_latex : Latex.style -> Format.formatter -> t -> unit
(** Pretty print a field name in latex. *)
(** The class part of the fieldname *)
val java_get_class : t -> string val java_get_class : t -> string
(** The class part of the fieldname *)
(** The last component of the fieldname *)
val java_get_field : t -> string val java_get_field : t -> string
(** The last component of the fieldname *)
(** Check if the field is the synthetic this$n of a nested class, used to access the n-th outher instance. *)
val java_is_outer_instance : t -> bool val java_is_outer_instance : t -> bool
(** Check if the field is the synthetic this$n of a nested class, used to access the n-th outher instance. *)
(** get qualified classname of a field if it's coming from clang frontend. returns None otherwise *)
val clang_get_qual_class : t -> QualifiedCppName.t option val clang_get_qual_class : t -> QualifiedCppName.t option
(** get qualified classname of a field if it's coming from clang frontend. returns None otherwise *)
(** hidded fieldname constant *)
val hidden : t val hidden : t
(** hidded fieldname constant *) (** hidded fieldname constant *)
val is_hidden : t -> bool val is_hidden : t -> bool
(** hidded fieldname constant *)
end end
module Struct : sig module Struct : sig
@ -666,7 +555,6 @@ module Struct : sig
type fields = field list type fields = field list
(** Type for a structured value. *) (** Type for a structured value. *)
type t = private type t = private
{ fields: fields (** non-static fields *) { fields: fields (** non-static fields *)
; statics: fields (** static fields *) ; statics: fields (** static fields *)
@ -676,33 +564,27 @@ module Struct : sig
type lookup = Name.t -> t option type lookup = Name.t -> t option
(** Pretty print a struct type. *)
val pp : Pp.env -> Name.t -> F.formatter -> t -> unit val pp : Pp.env -> Name.t -> F.formatter -> t -> unit
(** Pretty print a struct type. *)
(** Construct a struct_typ, normalizing field types *)
val internal_mk_struct : val internal_mk_struct :
?default:t -> ?fields:fields -> ?statics:fields -> ?methods:Procname.t list ?default:t -> ?fields:fields -> ?statics:fields -> ?methods:Procname.t list
-> ?supers:Name.t list -> ?annots:Annot.Item.t -> unit -> t -> ?supers:Name.t list -> ?annots:Annot.Item.t -> unit -> t
(** Construct a struct_typ, normalizing field types *)
(** the element typ of the final extensible array in the given typ, if any *)
val get_extensible_array_element_typ : lookup:lookup -> typ -> typ option val get_extensible_array_element_typ : lookup:lookup -> typ -> typ option
(** the element typ of the final extensible array in the given typ, if any *)
val fld_typ : lookup:lookup -> default:typ -> Fieldname.t -> typ -> typ
(** If a struct type with field f, return the type of f. (** If a struct type with field f, return the type of f.
If not, return the default type if given, otherwise raise an exception *) If not, return the default type if given, otherwise raise an exception *)
val fld_typ : lookup:lookup -> default:typ -> Fieldname.t -> typ -> typ
(** Return the type of the field [fn] and its annotation, None if [typ] has no field named [fn] *)
val get_field_type_and_annotation : val get_field_type_and_annotation :
lookup:lookup -> Fieldname.t -> typ -> (typ * Annot.Item.t) option lookup:lookup -> Fieldname.t -> typ -> (typ * Annot.Item.t) option
(** Return the type of the field [fn] and its annotation, None if [typ] has no field named [fn] *)
(** Field used for objective-c reference counting *)
val objc_ref_counter_field : Fieldname.t * typ * Annot.Item.t val objc_ref_counter_field : Fieldname.t * typ * Annot.Item.t
(** Field used for objective-c reference counting *)
val is_objc_ref_counter_field : Fieldname.t * typ * Annot.Item.t -> bool val is_objc_ref_counter_field : Fieldname.t * typ * Annot.Item.t -> bool
end end

@ -9,6 +9,7 @@
*) *)
(** The Smallfoot Intermediate Language: Unary Operators *) (** The Smallfoot Intermediate Language: Unary Operators *)
open! IStd open! IStd
module L = Logging module L = Logging
module F = Format module F = Format

@ -9,12 +9,12 @@
*) *)
(** The Smallfoot Intermediate Language: Unary Operators *) (** The Smallfoot Intermediate Language: Unary Operators *)
open! IStd open! IStd
module L = Logging module L = Logging
module F = Format module F = Format
(** Unary operations *) (** Unary operations *)
type t = type t =
| Neg (** Unary minus *) | Neg (** Unary minus *)
| BNot (** Bitwise complement (~) *) | BNot (** Bitwise complement (~) *)
@ -23,6 +23,5 @@ type t =
val equal : t -> t -> bool val equal : t -> t -> bool
(** String representation of a unary operator. *)
val str : t -> string val str : t -> string
(** String representation of a unary operator. *)

@ -24,7 +24,7 @@ ATDGEN_SUFFIXES = _t.ml _t.mli _j.ml _j.mli
GENERATED_OCAML_SOURCES_GLOB = <*{clang_plugin/*,backend/jsonbug_*,checkers/stacktree_*}> GENERATED_OCAML_SOURCES_GLOB = <*{clang_plugin/*,backend/jsonbug_*,checkers/stacktree_*}>
OCAML_FATAL_WARNINGS = +3+5+6+8+10+11+12+18+19+20+21+23+26+29+27+33+34+35+37+38+39+50+52+57-50 OCAML_FATAL_WARNINGS = +3+5+6+8+10+11+12+18+19+20+21+23+26+29+27+33+34+35+37+38+39+50+52+57
# options for ocamlbuild # options for ocamlbuild
# Notice that use-ocamlfind is used here to avoid a linker bug in ocamlbuild when using -tag thread # Notice that use-ocamlfind is used here to avoid a linker bug in ocamlbuild when using -tag thread

@ -15,9 +15,9 @@ let get_name_of_objc_static_locals (curr_f: Procdesc.t) p =
let pname = Typ.Procname.to_string (Procdesc.get_proc_name curr_f) in let pname = Typ.Procname.to_string (Procdesc.get_proc_name curr_f) in
let local_static e = let local_static e =
match e with match e with
| Exp.Lvar (* is a local static if it's a global and it has a static local name *) | Exp.Lvar pvar
pvar
when Pvar.is_global pvar && Sil.is_static_local_name pname pvar when Pvar.is_global pvar && Sil.is_static_local_name pname pvar
(* is a local static if it's a global and it has a static local name *)
-> [pvar] -> [pvar]
| _ | _
-> [] -> []

@ -9,20 +9,16 @@
open! IStd open! IStd
(** remove the return variable from the prop *)
val remove_ret : Tenv.t -> Procdesc.t -> Prop.normal Prop.t -> Prop.normal Prop.t val remove_ret : Tenv.t -> Procdesc.t -> Prop.normal Prop.t -> Prop.normal Prop.t
(** remove the return variable from the prop *)
(** remove locals and 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 *)
(** Deallocate the stack variables in [pvars], and replace them by normal variables.
Return the list of stack variables whose address was still present after deallocation. *)
val remove_locals_formals : val remove_locals_formals :
Tenv.t -> Procdesc.t -> Prop.normal Prop.t -> Pvar.t list * Prop.normal Prop.t Tenv.t -> Procdesc.t -> Prop.normal Prop.t -> Pvar.t list * Prop.normal Prop.t
(** Deallocate the stack variables in [pvars], and replace them by normal variables.
(** remove seed vars from a prop *) Return the list of stack variables whose address was still present after deallocation. *)
val remove_seed_vars : Tenv.t -> 'a Prop.t -> Prop.normal Prop.t val remove_seed_vars : Tenv.t -> 'a Prop.t -> Prop.normal Prop.t
(** remove seed vars from a prop *)

@ -6,6 +6,7 @@
* LICENSE file in the root directory of this source tree. An additional grant * LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory. * of patent rights can be found in the PATENTS file in the same directory.
*) *)
open! IStd open! IStd
open! PVariant open! PVariant
module F = Format module F = Format

@ -12,35 +12,27 @@ module F = Format
module L = Logging module L = Logging
(** In-memory representation of multilink files. *) (** In-memory representation of multilink files. *)
type t type t
(** Add a link. *)
val add : t -> string -> unit val add : t -> string -> unit
(** Add a link. *)
(** Create a new multilink. *)
val create : unit -> t val create : unit -> t
(** Create a new multilink. *)
val multilink_file_name : string
(** Name of the multilink file. (** Name of the multilink file.
A multilink file is recognized by its file name. *) A multilink file is recognized by its file name. *)
val multilink_file_name : string
(** Read a multilink file from disk. *)
val read : dir:string -> t option val read : dir:string -> t option
(** Read a multilink file from disk. *)
val resolve : DB.filename -> DB.filename
(** Resolve a filename following multilinks. (** Resolve a filename following multilinks.
The cache is updated if a new multilinks file is read. *) The cache is updated if a new multilinks file is read. *)
val resolve : DB.filename -> DB.filename
(** Reset the cache of multilink files *)
val reset_cache : unit -> unit val reset_cache : unit -> unit
(** Reset the cache of multilink files *)
(** Write a multilink file in the given directory *)
val write : t -> dir:string -> unit val write : t -> dir:string -> unit
(** Write a multilink file in the given directory *)

@ -6,6 +6,7 @@
* LICENSE file in the root directory of this source tree. An additional grant * LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory. * of patent rights can be found in the PATENTS file in the same directory.
*) *)
open! IStd open! IStd
module L = Logging module L = Logging
@ -73,8 +74,8 @@ let clang_cc1_cmd_sanitizer cmd =
let mllvm_flags_blacklist = ["-profile-guided-section-prefix"] in let mllvm_flags_blacklist = ["-profile-guided-section-prefix"] in
let replace_option_arg option arg = let replace_option_arg option arg =
if String.equal option "-arch" && String.equal arg "armv7k" then "armv7" if String.equal option "-arch" && String.equal arg "armv7k" then "armv7"
else if (* replace armv7k arch with armv7 *) (* replace armv7k arch with armv7 *)
String.is_suffix arg ~suffix:"dep.tmp" then ( else if String.is_suffix arg ~suffix:"dep.tmp" then (
(* compilation-database Buck integration produces path to `dep.tmp` file that doesn't exist. Create it *) (* compilation-database Buck integration produces path to `dep.tmp` file that doesn't exist. Create it *)
Unix.mkdir_p (Filename.dirname arg) ; Unix.mkdir_p (Filename.dirname arg) ;
arg ) arg )

@ -11,34 +11,28 @@ open! IStd
type t type t
val mk : ClangQuotes.style -> prog:string -> args:string list -> t
(** [mk qs prog args] finds the type of command depending on its arguments [args]. The quoting style (** [mk qs prog args] finds the type of command depending on its arguments [args]. The quoting style
of the arguments have to be provided, so that the command may be run later on. Beware that this of the arguments have to be provided, so that the command may be run later on. Beware that this
doesn't look inside argument files. This can be used to create a "clang -### ..." command on doesn't look inside argument files. This can be used to create a "clang -### ..." command on
which to call [command_to_run], but other functions from the module will not work as expected which to call [command_to_run], but other functions from the module will not work as expected
unless the command has been normalized by "clang -### ...". *) unless the command has been normalized by "clang -### ...". *)
val mk : ClangQuotes.style -> prog:string -> args:string list -> t val command_to_run : t -> string
(** Make a command into a string ready to be passed to a shell to be executed. Fine to call with (** Make a command into a string ready to be passed to a shell to be executed. Fine to call with
clang driver commands. *) clang driver commands. *)
val command_to_run : t -> string
(** Whether the command has this flag set in its arguments. Must be called on normalized commands. *)
val has_flag : t -> string -> bool val has_flag : t -> string -> bool
(** Whether the command has this flag set in its arguments. Must be called on normalized commands. *)
(** The value passed to an option in the arguments of a command. Must be called on normalized commands. *)
val value_of_option : t -> string -> string option val value_of_option : t -> string -> string option
(** The value passed to an option in the arguments of a command. Must be called on normalized commands. *)
(** Whether the command is suitable for attaching the AST exporter. Must be called on normalized commands. *)
val can_attach_ast_exporter : t -> bool val can_attach_ast_exporter : t -> bool
(** Whether the command is suitable for attaching the AST exporter. Must be called on normalized commands. *)
(** Add the arguments needed to attach the facebook-clang-plugins plugin. Must be called on normalized commands. *)
val with_plugin_args : t -> t val with_plugin_args : t -> t
(** Add the arguments needed to attach the facebook-clang-plugins plugin. Must be called on normalized commands. *)
val prepend_arg : string -> t -> t val prepend_arg : string -> t -> t
@ -48,6 +42,5 @@ val append_args : string list -> t -> t
val get_orig_argv : t -> string array val get_orig_argv : t -> string array
(** update the executable to be run *)
val with_exec : string -> t -> t val with_exec : string -> t -> t
(** update the executable to be run *)

@ -6,7 +6,9 @@
* LICENSE file in the root directory of this source tree. An additional grant * LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory. * of patent rights can be found in the PATENTS file in the same directory.
*) *)
(* module for escaping clang arguments on the command line and put them into files *)
(** module for escaping clang arguments on the command line and put them into files *)
open! IStd open! IStd
module L = Logging module L = Logging

@ -7,12 +7,11 @@
* of patent rights can be found in the PATENTS file in the same directory. * of patent rights can be found in the PATENTS file in the same directory.
*) *)
open! IStd (** module for escaping clang arguments on the command line and put them into files *)
(* module for escaping clang arguments on the command line and put them into files *) open! IStd
(** quoting style of the arguments *) (** quoting style of the arguments *)
type style = type style =
| EscapedDoubleQuotes | EscapedDoubleQuotes
(** the arguments should be enclosed in "double quotes" and are already escaped *) (** the arguments should be enclosed in "double quotes" and are already escaped *)

Loading…
Cancel
Save