diff --git a/infer/src/IR/Annot.mli b/infer/src/IR/Annot.mli index 0b6b3d87d..187a16828 100644 --- a/infer/src/IR/Annot.mli +++ b/infer/src/IR/Annot.mli @@ -15,42 +15,35 @@ module F = Format type parameters = string list (** Type to represent one @Annotation. *) - type t = { class_name: string (** name of the annotation *) ; parameters: parameters (** currently only one string parameter *) } [@@deriving compare] -(** annotation for fields/methods marked with the "volatile" keyword *) - val volatile : t - -(** Pretty print an annotation. *) +(** annotation for fields/methods marked with the "volatile" keyword *) val pp : F.formatter -> t -> unit +(** Pretty print an annotation. *) module Map : PrettyPrintable.PPMap with type key = t module Item : sig (** Annotation for one item: a list of annotations with visibility. *) - type nonrec t = (t * bool) list [@@deriving compare] val equal : t -> t -> bool - (** Pretty print an item annotation. *) - val pp : F.formatter -> t -> unit + (** Pretty print an item annotation. *) val to_string : t -> string - (** Empty item annotation. *) - val empty : t - - (** Check if the item annodation is empty. *) + (** Empty item annotation. *) val is_empty : t -> bool + (** Check if the item annodation is empty. *) end module Class : sig @@ -61,18 +54,14 @@ end module Method : sig (** Annotation for a method: return value and list of parameters. *) - type t = Item.t * Item.t list [@@deriving compare] - (** Empty method annotation. *) - val empty : t - - (** Check if the method annodation is empty. *) + (** Empty method annotation. *) val is_empty : t -> bool - - (** Pretty print a method annotation. *) + (** Check if the method annodation is empty. *) val pp : string -> F.formatter -> t -> unit + (** Pretty print a method annotation. *) end diff --git a/infer/src/IR/AttributesTable.mli b/infer/src/IR/AttributesTable.mli index de3ef6534..efefabf21 100644 --- a/infer/src/IR/AttributesTable.mli +++ b/infer/src/IR/AttributesTable.mli @@ -11,33 +11,28 @@ open! IStd -(** Save .attr file for the procedure into the attributes database. *) - 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. 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 +(** 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 do this by adding a method that is unique to each class, and then finding the tenv that corresponds to the class definition. *) -val get_correct_type_from_objc_class_name : Typ.Name.t -> Typ.t option - -(* Find the file where the procedure was captured, if a cfg for that file exists. +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. Return also a boolean indicating whether the procedure is defined in an include file. 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 val stats : unit -> t diff --git a/infer/src/IR/Binop.mli b/infer/src/IR/Binop.mli index 567e2877b..25d714bb8 100644 --- a/infer/src/IR/Binop.mli +++ b/infer/src/IR/Binop.mli @@ -14,7 +14,6 @@ module L = Logging module F = Format (** Binary operations *) - type t = | PlusA (** arithmetic + *) | PlusPI (** pointer + integer *) @@ -41,26 +40,21 @@ type t = val equal : t -> t -> bool +val injective : t -> bool (** This function returns true if the operation is injective wrt. each argument: op(e,-) and op(-, e) is injective for all e. 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 +(** This function returns true if the operation can be inverted. *) +val invert : t -> t (** This function inverts an invertible injective binary operator. If the [binop] operation is not invertible, the function raises Assert_failure. *) -val invert : t -> t - +val is_zero_runit : t -> bool (** This function returns true if 0 is the right unit of [binop]. 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 +(** String representation of a binary operator. *) diff --git a/infer/src/IR/BuiltinDecl.mli b/infer/src/IR/BuiltinDecl.mli index 9a05396be..36534f1e2 100644 --- a/infer/src/IR/BuiltinDecl.mli +++ b/infer/src/IR/BuiltinDecl.mli @@ -10,6 +10,7 @@ open! IStd (** Procnames for the builtin functions supported *) + include BUILTINS.S with type t = Typ.Procname.t val is_declared : Typ.Procname.t -> bool diff --git a/infer/src/IR/CallFlags.ml b/infer/src/IR/CallFlags.ml index 8022a20cb..d6fc3dc61 100644 --- a/infer/src/IR/CallFlags.ml +++ b/infer/src/IR/CallFlags.ml @@ -9,6 +9,7 @@ *) (** The Smallfoot Intermediate Language: Call Flags *) + open! IStd module L = Logging module F = Format diff --git a/infer/src/IR/CallFlags.mli b/infer/src/IR/CallFlags.mli index f5b1f6356..e557f4547 100644 --- a/infer/src/IR/CallFlags.mli +++ b/infer/src/IR/CallFlags.mli @@ -9,12 +9,12 @@ *) (** The Smallfoot Intermediate Language: Call Flags *) + open! IStd module L = Logging module F = Format (** Flags for a procedure call *) - type t = { cf_virtual: bool ; cf_interface: bool @@ -25,6 +25,5 @@ type t = val pp : F.formatter -> t -> unit -(** Default value where all fields are set to false *) - val default : t +(** Default value where all fields are set to false *) diff --git a/infer/src/IR/Cfg.ml b/infer/src/IR/Cfg.ml index 79ba477b2..f57a3f308 100644 --- a/infer/src/IR/Cfg.ml +++ b/infer/src/IR/Cfg.ml @@ -7,12 +7,13 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. *) + open! IStd module L = Logging module F = Format (** 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 *) let create_cfg () = {proc_desc_table= Typ.Procname.Hash.create 16} diff --git a/infer/src/IR/Cfg.mli b/infer/src/IR/Cfg.mli index c1c451337..3b4847336 100644 --- a/infer/src/IR/Cfg.mli +++ b/infer/src/IR/Cfg.mli @@ -10,63 +10,50 @@ open! IStd -(** Control Flow Graph for Interprocedural Analysis *) +(** Control Flow Graph for Interprocedural Analysis *) (** A control-flow graph *) - type cfg -(** Load a cfg from a file *) - val load_cfg_from_file : DB.filename -> cfg option - -(** Save a cfg into a file, and save a copy of the source files if the boolean is true *) +(** Load a cfg from a file *) 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} *) -(** create a new empty cfg *) - val create_cfg : unit -> cfg - -(** Create a new procdesc *) +(** create a new empty cfg *) val create_proc_desc : cfg -> ProcAttributes.t -> Procdesc.t - -(** Iterate over all the procdesc's *) +(** Create a new procdesc *) val iter_proc_desc : cfg -> (Typ.Procname.t -> Procdesc.t -> unit) -> unit - -(** Find the procdesc given the proc name. Return None if not found. *) +(** Iterate over all the procdesc's *) val find_proc_desc_from_name : cfg -> Typ.Procname.t -> Procdesc.t option - -(** Get all the procedures (defined and declared) *) +(** Find the procdesc given the proc name. Return None if not found. *) val get_all_procs : cfg -> Procdesc.t list - -(** Get the procedures whose body is defined in this cfg *) +(** Get all the procedures (defined and declared) *) val get_defined_procs : cfg -> Procdesc.t list - -(** Iterate over all the nodes in the cfg *) +(** Get the procedures whose body is defined in this cfg *) val iter_all_nodes : ?sorted:bool -> (Procdesc.t -> Procdesc.Node.t -> unit) -> cfg -> unit - -(** checks whether a cfg is connected or not *) +(** Iterate over all the nodes in the cfg *) val check_cfg_connectedness : cfg -> unit - -(** Remove the procdesc from the control flow graph. *) +(** checks whether a cfg is connected or not *) 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 (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. 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 diff --git a/infer/src/IR/Cg.ml b/infer/src/IR/Cg.ml index 3eead6706..1212b2bf6 100644 --- a/infer/src/IR/Cg.ml +++ b/infer/src/IR/Cg.ml @@ -9,6 +9,7 @@ *) (** Module for call graphs *) + open! IStd module Hashtbl = Caml.Hashtbl module L = Logging @@ -21,19 +22,19 @@ type in_out_calls = ; out_calls: int (** total number of out calls transitively *) } type node_info = - { (** defined procedure as opposed to just declared *) - mutable defined: bool + { mutable defined: bool (** defined procedure as opposed to just declared *) ; mutable parents: Typ.Procname.Set.t - ; mutable children: Typ.Procname.Set.t (** ancestors are computed lazily *) - ; mutable ancestors: Typ.Procname.Set.t option (** heirs are computed lazily *) - ; mutable heirs: Typ.Procname.Set.t option (** recursive dependents are computed lazily *) - ; mutable recursive_dependents: Typ.Procname.Set.t option (** calls are computed lazily *) - ; mutable in_out_calls: in_out_calls option } + ; mutable children: Typ.Procname.Set.t + ; mutable ancestors: Typ.Procname.Set.t option (** ancestors are computed lazily *) + ; mutable heirs: Typ.Procname.Set.t option (** heirs are computed lazily *) + ; mutable recursive_dependents: Typ.Procname.Set.t option + (** recursive dependents are computed lazily *) + ; mutable in_out_calls: in_out_calls option (** calls are computed lazily *) } (** Type for call graph *) type t = { 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} diff --git a/infer/src/IR/Cg.mli b/infer/src/IR/Cg.mli index 86ee4e2d2..2dd4daa7b 100644 --- a/infer/src/IR/Cg.mli +++ b/infer/src/IR/Cg.mli @@ -16,9 +16,8 @@ type in_out_calls = { in_calls: int (** total number of in calls transitively *) ; out_calls: int (** total number of out calls transitively *) } -type t - (** 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 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] 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]. 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 - -(** Check if [source] recursively calls [dest] *) +(** Add a node to the call graph as defined *) val calls_recursively : t -> Typ.Procname.t -> Typ.Procname.t -> bool - -(** Create an empty call graph *) +(** Check if [source] recursively calls [dest] *) 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]; 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 - -(** Compute the ancestors of the node, if not pre-computed already *) +(** Return all the children of [n], whether defined or not *) val get_ancestors : t -> Typ.Procname.t -> Typ.Procname.Set.t - -(** Compute the heirs of the node, if not pre-computed already *) +(** Compute the ancestors of the node, if not pre-computed already *) val get_heirs : t -> Typ.Procname.t -> Typ.Procname.Set.t - -(** Return the in/out calls of the node *) +(** Compute the heirs of the node, if not pre-computed already *) val get_calls : t -> Typ.Procname.t -> in_out_calls - -(** Return the list of nodes which are defined *) +(** Return the in/out calls of the node *) val get_defined_nodes : t -> Typ.Procname.t list - -(** Return the children of [n] which are defined *) +(** Return the list of nodes which are defined *) val get_defined_children : t -> Typ.Procname.t -> Typ.Procname.Set.t - -(** Return the nodes dependent on [n] *) +(** Return the children of [n] which are defined *) val get_dependents : t -> Typ.Procname.t -> Typ.Procname.Set.t - -(** Return the list of nodes with calls *) +(** Return the nodes dependent on [n] *) val get_nodes_and_calls : t -> (Typ.Procname.t * in_out_calls) list - -(** Return all the nodes with their defined children *) +(** Return the list of nodes with calls *) val get_nodes_and_defined_children : t -> (Typ.Procname.t * Typ.Procname.Set.t) list - -(** Return the list of nodes, with defined flag, and the list of edges *) +(** Return all the nodes with their defined children *) val get_nodes_and_edges : t -> (Typ.Procname.t * bool) list * (Typ.Procname.t * Typ.Procname.t) list - -(** Return the children of [n] which are not heirs of [n] and are defined *) +(** Return the list of nodes, with defined flag, and the list of edges *) val get_nonrecursive_dependents : t -> Typ.Procname.t -> Typ.Procname.Set.t - -(** Return the parents of [n] *) +(** Return the children of [n] which are not heirs of [n] and are defined *) val get_parents : t -> Typ.Procname.t -> Typ.Procname.Set.t - -(** Return the ancestors of [n] which are also heirs of [n] *) +(** Return the parents of [n] *) val get_recursive_dependents : t -> Typ.Procname.t -> Typ.Procname.Set.t - -(** Return the path of the source file *) +(** Return the ancestors of [n] which are also heirs of [n] *) val get_source : t -> SourceFile.t - -(** Load a call graph from a file *) +(** Return the path of the source file *) val load_from_file : DB.filename -> t option - -(** Returns true if the node is defined *) +(** Load a call graph from a file *) val node_defined : t -> Typ.Procname.t -> bool - -(** Remove the defined flag from a node, if it exists. *) +(** Returns true if the node is defined *) val remove_node_defined : t -> Typ.Procname.t -> unit - -(** Print the call graph as a dotty file. *) +(** Remove the defined flag from a node, if it exists. *) val save_call_graph_dotty : SourceFile.t -> t -> unit - -(** Save a call graph into a file *) +(** Print the call graph as a dotty file. *) val store_to_file : DB.filename -> t -> unit +(** Save a call graph into a file *) diff --git a/infer/src/IR/Const.ml b/infer/src/IR/Const.ml index 90b177f5b..45f685acd 100644 --- a/infer/src/IR/Const.ml +++ b/infer/src/IR/Const.ml @@ -9,6 +9,7 @@ *) (** The Smallfoot Intermediate Language: Constants *) + open! IStd module L = Logging module F = Format diff --git a/infer/src/IR/Const.mli b/infer/src/IR/Const.mli index 1b53b8b33..34c88b449 100644 --- a/infer/src/IR/Const.mli +++ b/infer/src/IR/Const.mli @@ -9,12 +9,12 @@ *) (** The Smallfoot Intermediate Language: Constants *) + open! IStd module L = Logging module F = Format (** Constants *) - type t = | Cint of IntLit.t (** integer constants *) | Cfun of Typ.Procname.t (** function names *) @@ -25,13 +25,11 @@ type t = val equal : t -> t -> bool -(** Return true if the constants have the same kind (both integers, ...) *) - val kind_equal : t -> t -> bool - -(** Pretty print a const *) +(** Return true if the constants have the same kind (both integers, ...) *) val pp : Pp.env -> F.formatter -> t -> unit +(** Pretty print a const *) val to_string : t -> string diff --git a/infer/src/IR/DecompiledExp.ml b/infer/src/IR/DecompiledExp.ml index 4c3a8807f..caa130408 100644 --- a/infer/src/IR/DecompiledExp.ml +++ b/infer/src/IR/DecompiledExp.ml @@ -9,6 +9,7 @@ *) (** The Smallfoot Intermediate Language: Decompiled Expressions *) + open! IStd module L = Logging module F = Format diff --git a/infer/src/IR/DecompiledExp.mli b/infer/src/IR/DecompiledExp.mli index 92da9c869..52b710d96 100644 --- a/infer/src/IR/DecompiledExp.mli +++ b/infer/src/IR/DecompiledExp.mli @@ -9,12 +9,12 @@ *) (** The Smallfoot Intermediate Language: Decompiled Expressions *) + open! IStd module L = Logging module F = Format (** expression representing the result of decompilation *) - type t = | Darray of 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 each expression represents a path, with Dpvar being the simplest one *) - type vpath = t option -(** convert to a string *) - val to_string : t -> string - -(** pretty print *) +(** convert to a string *) val pp : F.formatter -> t -> unit - -(** Pretty print a value path *) +(** pretty print *) val pp_vpath : Pp.env -> F.formatter -> vpath -> unit - -(** return true if [dexp] contains a temporary pvar *) +(** Pretty print a value path *) val has_tmp_var : t -> bool +(** return true if [dexp] contains a temporary pvar *) diff --git a/infer/src/IR/Exp.ml b/infer/src/IR/Exp.ml index c8a3569da..796d92ca3 100644 --- a/infer/src/IR/Exp.ml +++ b/infer/src/IR/Exp.ml @@ -9,6 +9,7 @@ *) (** The Smallfoot Intermediate Language: Expressions *) + open! IStd module Hashtbl = Caml.Hashtbl module L = Logging @@ -35,17 +36,17 @@ and sizeof_data = {typ: Typ.t; nbytes: int option; dynamic_length: t option; sub (** Program expressions. *) and t = - (** 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 (** Binary operator *) - | BinOp of Binop.t * t * t (** Exception *) - | Exn of t (** Anonymous function *) - | Closure of closure (** Constants *) - | Const of Const.t (** Type cast *) - | Cast of Typ.t * 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 (** An array index offset: [exp1\[exp2\]] *) - | Lindex of t * t + | Var of _ident (** Pure variable: it is not an lvalue *) + | UnOp of Unop.t * t * Typ.t option (** Unary operator with type of the result if known *) + | BinOp of Binop.t * t * t (** Binary operator *) + | Exn of t (** Exception *) + | Closure of closure (** Anonymous function *) + | Const of Const.t (** Constants *) + | Cast of Typ.t * t (** Type cast *) + | Lvar of Pvar.t (** The address of a program variable *) + | Lfield of t * Typ.Fieldname.t * Typ.t + (** A field offset, the type is the surrounding struct type *) + | Lindex of t * t (** An array index offset: [exp1\[exp2\]] *) | Sizeof of sizeof_data [@@deriving compare] diff --git a/infer/src/IR/Exp.mli b/infer/src/IR/Exp.mli index 5dddfd601..a1e3ebe92 100644 --- a/infer/src/IR/Exp.mli +++ b/infer/src/IR/Exp.mli @@ -9,6 +9,7 @@ *) (** The Smallfoot Intermediate Language: Expressions *) + open! IStd module L = Logging module F = Format @@ -29,128 +30,103 @@ and sizeof_data = {typ: Typ.t; nbytes: int option; dynamic_length: t option; sub (** Program expressions. *) and 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 (** Binary operator *) - | BinOp of Binop.t * t * t (** Exception *) - | Exn of t (** Anonymous function *) - | Closure of closure (** Constants *) - | Const of Const.t (** Type cast *) - | Cast of Typ.t * 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 (** An array index offset: [exp1\[exp2\]] *) - | Lindex of t * t + | Var of Ident.t (** Pure variable: it is not an lvalue *) + | UnOp of Unop.t * t * Typ.t option (** Unary operator with type of the result if known *) + | BinOp of Binop.t * t * t (** Binary operator *) + | Exn of t (** Exception *) + | Closure of closure (** Anonymous function *) + | Const of Const.t (** Constants *) + | Cast of Typ.t * t (** Type cast *) + | Lvar of Pvar.t (** The address of a program variable *) + | Lfield of t * Typ.Fieldname.t * Typ.t + (** A field offset, the type is the surrounding struct type *) + | Lindex of t * t (** An array index offset: [exp1\[exp2\]] *) | Sizeof of sizeof_data [@@deriving compare] -(** Equality for expressions. *) - val equal : t -> t -> bool - -(** Hash function for expressions. *) +(** Equality for expressions. *) val hash : t -> int +(** Hash function for expressions. *) (** Set of expressions. *) - module Set : Caml.Set.S with type elt = t (** Map with expression keys. *) - module Map : Caml.Map.S with type key = t (** Hashtable with expression keys. *) - 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 +(** returns true is index is an array index of arr. *) val is_null_literal : t -> bool -(** return true if [exp] is the special this/self expression *) - val is_this : t -> bool +(** return true if [exp] is the special this/self expression *) val is_zero : t -> bool (** {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 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 +(** Return the root of [lexp]. *) +val get_undefined : bool -> t (** Get an expression "undefined", the boolean indicates 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. 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 - -(** returns true if the expression operates on address of local variable *) +(** returns true if the expression represents a stack-directed address *) val has_local_addr : t -> bool - -(** Integer constant 0 *) +(** returns true if the expression operates on address of local variable *) val zero : t - -(** Null constant *) +(** Integer constant 0 *) val null : t - -(** Integer constant 1 *) +(** Null constant *) val one : t - -(** Integer constant -1 *) +(** Integer constant 1 *) val minus_one : t - -(** Create integer constant *) +(** Integer constant -1 *) val int : IntLit.t -> t - -(** Create float constant *) +(** Create integer constant *) val float : float -> t - -(** Create integer constant corresponding to the boolean value *) +(** Create float constant *) val bool : bool -> t - -(** Create expresstion [e1 == e2] *) +(** Create integer constant corresponding to the boolean value *) val eq : t -> t -> t - -(** Create expresstion [e1 != e2] *) +(** Create expresstion [e1 == e2] *) val ne : t -> t -> t - -(** Create expresstion [e1 <= e2] *) +(** Create expresstion [e1 != e2] *) val le : t -> t -> t - -(** Create expression [e1 < e2] *) +(** Create expresstion [e1 <= e2] *) val lt : t -> t -> t - -(** Extract the ids and pvars from an expression *) +(** Create expression [e1 < e2] *) 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 diff --git a/infer/src/IR/Ident.ml b/infer/src/IR/Ident.ml index 8c4ebac5a..2a70134d8 100644 --- a/infer/src/IR/Ident.ml +++ b/infer/src/IR/Ident.ml @@ -9,6 +9,7 @@ *) (** Module for Names and Identifiers *) + open! IStd module Hashtbl = Caml.Hashtbl module L = Logging diff --git a/infer/src/IR/Ident.mli b/infer/src/IR/Ident.mli index f6674ce2d..14009471b 100644 --- a/infer/src/IR/Ident.mli +++ b/infer/src/IR/Ident.mli @@ -8,65 +8,52 @@ * of patent rights can be found in the PATENTS file in the same directory. *) -open! IStd - (** Identifiers: program variables and logical variables *) -(** Program and logical variables. *) +open! IStd +(** Program and logical variables. *) type t [@@deriving compare] -(** Equality for identifiers. *) - val equal : t -> t -> bool +(** Equality for identifiers. *) (** Names used to replace strings. *) - type name [@@deriving compare] -(** Equality for names. *) - val equal_name : name -> name -> bool +(** Equality for names. *) (** Kind of identifiers. *) - type kind [@@deriving compare] -(** Equality for kind. *) - val equal_kind : kind -> kind -> bool +(** Equality for kind. *) (** Set for identifiers. *) - module IdentSet : Caml.Set.S with type elt = t (** Hash table with ident as key. *) - module IdentHash : Caml.Hashtbl.S with type key = t (** Map with ident as key. *) - module IdentMap : Caml.Map.S with type key = t module NameGenerator : sig type t - (** Get the current name generator. *) - val get_current : unit -> t - - (** Reset the name generator. *) + (** Get the current name generator. *) val reset : unit -> unit - - (** Set the current name generator. *) + (** Reset the name generator. *) val set_current : t -> unit + (** Set the current name generator. *) end -(** Convert an identfier list to an identifier set *) - val idlist_to_idset : t list -> IdentSet.t +(** Convert an identfier list to an identifier set *) val kprimed : kind @@ -75,119 +62,90 @@ val knormal : kind val kfootprint : kind (** hash table with names as keys *) - module NameHash : Caml.Hashtbl.S with type key = name -(** Name used for primed tmp variables *) - val name_primed : name - -(** Name used for spec variables *) +(** Name used for primed tmp variables *) val name_spec : name - -(** Name used for the return variable *) +(** Name used for spec variables *) val name_return : Mangled.t - -(** Convert a string to a name. *) +(** Name used for the return variable *) val string_to_name : string -> name - -(** Convert a name to a string. *) +(** Convert a string to a name. *) val name_to_string : name -> string - -(** Name of the identifier. *) +(** Convert a name to a string. *) val get_name : t -> name - -(** Create an identifier with default name for the given kind *) +(** Name of the identifier. *) val create : kind -> int -> t - -(** Generate a normal identifier with the given name and stamp. *) +(** Create an identifier with default name for the given kind *) val create_normal : name -> int -> t - -(** Create a "null" identifier for situations where the IR requires an id that will never be read *) +(** Generate a normal identifier with the given name and stamp. *) val create_none : unit -> t - -(** Generate a primed 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_primed : name -> int -> t - -(** Generate a footprint identifier with the given name and stamp. *) +(** Generate a primed identifier with the given name and stamp. *) val create_footprint : name -> int -> t - -(** Update the name generator so that the given id's are not generated again *) +(** Generate a footprint identifier with the given name and stamp. *) val update_name_generator : t list -> unit - -(** Create a fresh identifier with default name for the given kind. *) +(** Update the name generator so that the given id's are not generated again *) val create_fresh : kind -> t - -(** Generate a normal identifier whose name encodes a path given as a string. *) +(** Create a fresh identifier with default name for the given kind. *) val create_path : string -> t - -(** Check whether an identifier is primed or not. *) +(** Generate a normal identifier whose name encodes a path given as a string. *) val is_primed : t -> bool - -(** Check whether an identifier is normal or not. *) +(** Check whether an identifier is primed or not. *) val is_normal : t -> bool - -(** Check whether an identifier is footprint or not. *) +(** Check whether an identifier is normal or not. *) val is_footprint : t -> bool - -(** Check whether an identifier represents a path or not. *) +(** Check whether an identifier is footprint or not. *) val is_path : t -> bool - -(** Check whether an identifier is the special "none" identifier *) +(** Check whether an identifier represents a path or not. *) val is_none : t -> bool - -(** Convert a primed ident into a nonprimed one, keeping the stamp. *) +(** Check whether an identifier is the special "none" identifier *) val make_unprimed : t -> t - -(** Get the stamp of the identifier *) +(** Convert a primed ident into a nonprimed one, keeping the stamp. *) val get_stamp : t -> int - -(** Set the stamp of the identifier *) +(** Get the stamp of the identifier *) val set_stamp : t -> int -> t +(** Set the stamp of the identifier *) (** {2 Pretty Printing} *) -(** Pretty print a name. *) - val pp_name : Format.formatter -> name -> unit - -(** Pretty print a name in latex. *) +(** Pretty print a name. *) val pp_name_latex : Latex.style -> Format.formatter -> name -> unit - -(** Pretty print an identifier. *) +(** Pretty print a name in latex. *) val pp : Pp.env -> Format.formatter -> t -> unit - -(** Convert an identifier to a string. *) +(** Pretty print an identifier. *) val to_string : t -> string - -(** Pretty print a list of identifiers. *) +(** Convert an identifier to a string. *) val pp_list : Pp.env -> Format.formatter -> t list -> unit - -(** Pretty print a list of names. *) +(** Pretty print a list of identifiers. *) val pp_name_list : Format.formatter -> name list -> unit +(** Pretty print a list of names. *) diff --git a/infer/src/IR/IntLit.ml b/infer/src/IR/IntLit.ml index 665534336..ab1576b37 100644 --- a/infer/src/IR/IntLit.ml +++ b/infer/src/IR/IntLit.ml @@ -10,29 +10,24 @@ open! IStd 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 *) 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 = match (i < 0L, u) with | true, false - -> 1 - (* only representable as signed *) + -> (* only representable as signed *) 1 | false, _ - -> 2 - (* in the intersection between signed and unsigned *) + -> (* in the intersection between signed and unsigned *) 2 | true, true - -> 3 - -(* only representable as unsigned *) + -> (* only representable as unsigned *) 3 let to_signed (unsigned, i, ptr) = if Int.equal (area unsigned i) 3 then None - else Some (* not representable as signed *) - (false, i, ptr) + else (* not representable as signed *) Some (false, i, ptr) let compare (unsigned1, i1, _) (unsigned2, i2, _) = let n = Bool.compare unsigned1 unsigned2 in diff --git a/infer/src/IR/IntLit.mli b/infer/src/IR/IntLit.mli index beb910956..d56b83041 100644 --- a/infer/src/IR/IntLit.mli +++ b/infer/src/IR/IntLit.mli @@ -12,20 +12,17 @@ open! IStd module F = Format (** signed and unsigned integer literals *) - type t val add : t -> t -> t -(** compare integers ignoring the distinction between pointers and non-pointers *) - 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, which distinguished between signed and unsigned +1 *) -val compare_value : t -> t -> int - val div : t -> t -> t val eq : t -> t -> bool @@ -73,7 +70,6 @@ val neg : t -> t val neq : t -> t -> bool val null : t - (** null behaves like zero except for the function isnull *) val one : t @@ -88,9 +84,8 @@ val to_int : t -> int val to_signed : t -> t option -(** convert to signed if the value is representable *) - val to_string : t -> string +(** convert to signed if the value is representable *) val two : t diff --git a/infer/src/IR/Localise.mli b/infer/src/IR/Localise.mli index 5282b516d..6ab412c2b 100644 --- a/infer/src/IR/Localise.mli +++ b/infer/src/IR/Localise.mli @@ -181,13 +181,11 @@ module Tags : sig val tag_value_records_of_tags : t -> Jsonbug_t.tag_value_record list (** 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 - - (* collect all lines from tags *) + (** convert atd-serializable format to error description's tags *) val lines_of_tags : t -> int list + (** collect all lines from tags *) end (** description field of error messages *) @@ -209,8 +207,7 @@ val custom_desc_with_advice : string -> string -> (string * string) list -> erro module BucketLevel : sig val b1 : string - - (* highest likelyhood *) + (** highest likelyhood *) val b2 : string @@ -219,7 +216,7 @@ module BucketLevel : sig val b4 : string val b5 : string - (* lowest likelyhood *) + (** lowest likelyhood *) end 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 access = - | Last_assigned of int * bool - (* line, null_case_flag *) - | Last_accessed of int * bool - (* line, is_nullable flag *) + | Last_assigned of int * bool (** line, null_case_flag *) + | Last_accessed of int * bool (** line, is_nullable flag *) | Initialized_automatically | 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 -(* Create human-readable error description for assertion failures *) - val desc_custom_error : Location.t -> error_desc +(** Create human-readable error description for assertion failures *) (** kind of precondition not met *) type pnm_kind = Pnm_bounds | Pnm_dangling diff --git a/infer/src/IR/Location.mli b/infer/src/IR/Location.mli index ca4da07e1..a05e827f0 100644 --- a/infer/src/IR/Location.mli +++ b/infer/src/IR/Location.mli @@ -10,7 +10,6 @@ open! IStd (** Location in the original source file *) - type t = { line: int (** The line 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 -(** Dump a location. *) - val d : t -> unit - -(** Dummy source location for the given file *) +(** Dump a location. *) val none : SourceFile.t -> t - -(** Dummy location with no source file *) +(** Dummy source location for the given file *) val dummy : t - -(** Pretty print a location. *) +(** Dummy location with no source file *) val pp : Format.formatter -> t -> unit - -(** String representation of a location. *) +(** Pretty print a location. *) val to_string : t -> string - -(** Pretty print a file-position of a location *) +(** String representation of a location. *) val pp_file_pos : Format.formatter -> t -> unit +(** Pretty print a file-position of a location *) diff --git a/infer/src/IR/Mangled.ml b/infer/src/IR/Mangled.ml index d060c484e..95a141184 100644 --- a/infer/src/IR/Mangled.ml +++ b/infer/src/IR/Mangled.ml @@ -9,6 +9,7 @@ *) (** Module for Mangled Names *) + open! IStd module F = Format diff --git a/infer/src/IR/Mangled.mli b/infer/src/IR/Mangled.mli index 314290b9f..224a96597 100644 --- a/infer/src/IR/Mangled.mli +++ b/infer/src/IR/Mangled.mli @@ -13,41 +13,31 @@ open! IStd (** Module for Mangled Names *) (** Type of mangled names *) - type t [@@deriving compare] -(** Equality for mangled names *) - val equal : t -> t -> bool - -(** Convert a string to a mangled name *) +(** Equality for mangled names *) val from_string : string -> t - -(** Create a mangled name from a plain and mangled string *) +(** Convert a string to a mangled name *) val mangled : string -> string -> t - -(** Convert a mangled name to a string *) +(** Create a mangled name from a plain and mangled string *) val to_string : t -> string - -(** Convert a full mangled name to a string *) +(** Convert a mangled name to a string *) val to_string_full : t -> string - -(** Get mangled string if given *) +(** Convert a full mangled name to a string *) val get_mangled : t -> string - -(** Pretty print a mangled name *) +(** Get mangled string if given *) val pp : Format.formatter -> t -> unit +(** Pretty print a mangled name *) (** Set of Mangled. *) - module Set : Caml.Set.S with type elt = t (** Map with Mangled as key *) - module Map : Caml.Map.S with type key = t diff --git a/infer/src/IR/Objc_models.mli b/infer/src/IR/Objc_models.mli index c4b206319..bb0dbe785 100644 --- a/infer/src/IR/Objc_models.mli +++ b/infer/src/IR/Objc_models.mli @@ -9,9 +9,6 @@ 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 for which there are particular rules for memory management. *) diff --git a/infer/src/IR/PredSymb.ml b/infer/src/IR/PredSymb.ml index 83efb837c..ac64c16ed 100644 --- a/infer/src/IR/PredSymb.ml +++ b/infer/src/IR/PredSymb.ml @@ -9,6 +9,7 @@ *) (** The Smallfoot Intermediate Language: Predicate Symbols *) + open! IStd module L = Logging module F = Format @@ -47,12 +48,11 @@ let equal_res_act_kind = [%compare.equal : res_act_kind] (** kind of dangling pointers *) type dangling_kind = - (** pointer is dangling because it is uninitialized *) - | DAuninit + | DAuninit (** pointer is dangling because it is uninitialized *) + | DAaddr_stack_var (** pointer is dangling because it is the address - of a stack variable which went out of scope *) - | DAaddr_stack_var (** pointer is -1 *) - | DAminusone + of a stack variable which went out of scope *) + | DAminusone (** pointer is -1 *) [@@deriving compare] (** position in a path: proc name, node id *) @@ -107,20 +107,20 @@ type t = | Aresource of res_action (** resource acquire/release *) | Aautorelease | 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 + (** undefined value obtained by calling the given procedure, plus its return value annots *) | Ataint of taint_info | Auntaint of taint_info | Alocked - | Aunlocked (** value appeared in second argument of division at given path position *) - | Adiv0 of path_pos - (** attributed exp is null due to a call to a method with given path as null receiver *) + | Aunlocked + | Adiv0 of path_pos (** value appeared in second argument of division at given path position *) | 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 - (** denotes an object registered as an observers to a notification center *) - | Aobserver (** denotes an object unsubscribed from observers of a notification center *) + (** value was returned from a call to the given procedure, plus the annots of the return value *) + | Aobserver (** denotes an object registered as an observers to a notification center *) | Aunsubscribed_observer + (** denotes an object unsubscribed from observers of a notification center *) [@@deriving compare] let equal = [%compare.equal : t] diff --git a/infer/src/IR/PredSymb.mli b/infer/src/IR/PredSymb.mli index 5244c184b..8a39cbcff 100644 --- a/infer/src/IR/PredSymb.mli +++ b/infer/src/IR/PredSymb.mli @@ -9,6 +9,7 @@ *) (** The Smallfoot Intermediate Language: Predicate Symbols *) + open! IStd module L = Logging module F = Format @@ -17,12 +18,10 @@ module F = Format 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 +(** Return the value of the FA_sentinel attribute in [attr_list] if it is found *) (** Visibility modifiers. *) - type access = Default | Public | Private | Protected [@@deriving compare] val equal_access : access -> access -> bool @@ -35,26 +34,21 @@ type mem_kind = [@@deriving compare] (** resource that can be allocated *) - type resource = Rmemory of mem_kind | Rfile | Rignore | Rlock [@@deriving compare] (** kind of resource action *) - type res_act_kind = Racquire | Rrelease [@@deriving compare] val equal_res_act_kind : res_act_kind -> res_act_kind -> bool (** kind of dangling pointers *) - type dangling_kind = - (** pointer is dangling because it is uninitialized *) - | DAuninit + | DAuninit (** pointer is dangling because it is uninitialized *) + | DAaddr_stack_var (** pointer is dangling because it is the address of a stack variable which went out of scope *) - | DAaddr_stack_var (** pointer is -1 *) - | DAminusone + | DAminusone (** pointer is -1 *) (** position in a path: proc name, node id *) - type path_pos = Typ.Procname.t * int [@@deriving compare] 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} (** acquire/release action on a resource *) - type res_action = { ra_kind: res_act_kind (** kind of action *) ; 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 attribute to an expression, that expression should be the first argument, optionally followed by additional related expressions. *) - type t = | Aresource of res_action (** resource acquire/release *) | Aautorelease | 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 + (** undefined value obtained by calling the given procedure, plus its return value annots *) | Ataint of taint_info | Auntaint of taint_info | Alocked - | Aunlocked (** value appeared in second argument of division at given path position *) - | Adiv0 of path_pos - (** attributed exp is null due to a call to a method with given path as null receiver *) + | Aunlocked + | Adiv0 of path_pos (** value appeared in second argument of division at given path position *) | 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 - (** denotes an object registered as an observers to a notification center *) - | Aobserver (** denotes an object unsubscribed from observers of a notification center *) + (** value was returned from a call to the given procedure, plus the annots of the return value *) + | Aobserver (** denotes an object registered as an observers to a notification center *) | Aunsubscribed_observer + (** denotes an object unsubscribed from observers of a notification center *) [@@deriving compare] val equal : t -> t -> bool -(** name of the allocation function for the given memory kind *) - val mem_alloc_pname : mem_kind -> Typ.Procname.t - -(** name of the deallocation function for the given memory kind *) +(** name of the allocation function for the given memory kind *) val mem_dealloc_pname : mem_kind -> Typ.Procname.t +(** name of the deallocation function for the given memory kind *) (** Categories of attributes *) - type category = | ACresource | ACautorelease @@ -132,16 +121,13 @@ type category = val equal_category : category -> category -> bool -(** Return the category to which the attribute belongs. *) - val to_category : t -> category +(** Return the category to which the attribute belongs. *) val is_undef : t -> bool -(** convert the attribute to a string *) - val to_string : Pp.env -> t -> string - -(** Dump an attribute. *) +(** convert the attribute to a string *) val d_attribute : t -> unit +(** Dump an attribute. *) diff --git a/infer/src/IR/ProcAttributes.ml b/infer/src/IR/ProcAttributes.ml index a215999a8..0aea077ee 100644 --- a/infer/src/IR/ProcAttributes.ml +++ b/infer/src/IR/ProcAttributes.ml @@ -8,6 +8,7 @@ *) (** Attributes of a procedure. *) + open! IStd module Hashtbl = Caml.Hashtbl module L = Logging diff --git a/infer/src/IR/ProcAttributes.mli b/infer/src/IR/ProcAttributes.mli index f5c329ec1..e7c439d3f 100644 --- a/infer/src/IR/ProcAttributes.mli +++ b/infer/src/IR/ProcAttributes.mli @@ -12,30 +12,24 @@ open! IStd (** Attributes of a procedure. *) (** flags for a procedure *) - type proc_flags = (string, string) Caml.Hashtbl.t [@@deriving compare] -(** keys for proc_flags *) - val proc_flag_skip : string - -(** key to specify that a function should be treated as a skip function *) +(** keys for proc_flags *) 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 *) -(** empty proc flags *) - val proc_flags_empty : unit -> proc_flags - -(** add a key value pair to a proc flags *) +(** empty proc flags *) val proc_flags_add : proc_flags -> string -> string -> unit - -(** find a value for a key in the proc flags *) +(** add a key value pair to a proc flags *) val proc_flags_find : proc_flags -> string -> string +(** find a value for a key in the proc flags *) type objc_accessor_type = | Objc_getter of Typ.Fieldname.t @@ -73,6 +67,5 @@ type t = ; source_file_captured: SourceFile.t (** source file where the procedure was captured *) } [@@deriving compare] -(** Create a proc_attributes with default values. *) - val default : Typ.Procname.t -> Config.language -> t +(** Create a proc_attributes with default values. *) diff --git a/infer/src/IR/Procdesc.ml b/infer/src/IR/Procdesc.ml index 3bd0646d3..4d7a94791 100644 --- a/infer/src/IR/Procdesc.ml +++ b/infer/src/IR/Procdesc.ml @@ -7,6 +7,7 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. *) + open! IStd module Hashtbl = Caml.Hashtbl module L = Logging @@ -31,16 +32,15 @@ module Node = struct (** a node *) type t = - { (** unique id of the node *) - id: id (** distance to the exit node *) - ; mutable dist_exit: int option (** exception nodes in the cfg *) - ; mutable exn: t list (** instructions for symbolic execution *) - ; mutable instrs: Sil.instr list (** kind of node *) - ; kind: nodekind (** location in the source code *) - ; loc: Location.t (** predecessor nodes in the cfg *) - ; mutable preds: t list (** name of the procedure the node belongs to *) - ; pname_opt: Typ.Procname.t option (** successor nodes in the cfg *) - ; mutable succs: t list } + { id: id (** unique id of the node *) + ; mutable dist_exit: int option (** distance to the exit node *) + ; mutable exn: t list (** exception nodes in the cfg *) + ; mutable instrs: Sil.instr list (** instructions for symbolic execution *) + ; kind: nodekind (** kind of node *) + ; loc: Location.t (** location in the source code *) + ; mutable preds: t list (** predecessor nodes in the cfg *) + ; pname_opt: Typ.Procname.t option (** name of the procedure the node belongs to *) + ; mutable succs: t list (** successor nodes in the cfg *) } let exn_handler_kind = Stmt_node "exception handler" @@ -240,11 +240,14 @@ end (* =============== END of module Node =============== *) (** 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. *) -module NodeHash = Hashtbl.Make (Node) (** Set of nodes. *) +module NodeHash = Hashtbl.Make (Node) + (** Set of nodes. *) -module NodeSet = Node.NodeSet (** Map with node id keys. *) +module NodeSet = Node.NodeSet + (** Map with node id keys. *) module IdMap = Node.IdMap @@ -255,7 +258,7 @@ type t = ; mutable nodes_num: int (** number of nodes *) ; mutable start_node: Node.t (** start node of this 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] (** Only call from Cfg *) diff --git a/infer/src/IR/Procdesc.mli b/infer/src/IR/Procdesc.mli index 6ac5adc87..b445c3ad9 100644 --- a/infer/src/IR/Procdesc.mli +++ b/infer/src/IR/Procdesc.mli @@ -11,20 +11,16 @@ open! IStd (** node of the control flow graph *) - module Node : sig (** type of nodes *) - type t [@@deriving compare] (** node id *) - type id = private int [@@deriving compare] val equal_id : id -> id -> bool (** kind of cfg node *) - type nodekind = | Start_node of Typ.Procname.t | Exit_node of Typ.Procname.t @@ -36,281 +32,217 @@ module Node : sig val equal_nodekind : nodekind -> nodekind -> bool - (** kind of Stmt_node for an exception handler. *) - val exn_handler_kind : nodekind - - (** kind of Stmt_node for an exceptions sink. *) + (** kind of Stmt_node for an exception handler. *) val exn_sink_kind : nodekind - - (** kind of Stmt_node for a throw instruction. *) + (** kind of Stmt_node for an exceptions sink. *) val throw_kind : nodekind - - (** Add declarations for local variables and return variable to the node *) + (** kind of Stmt_node for a throw instruction. *) val add_locals_ret_declaration : t -> ProcAttributes.t -> (Mangled.t * Typ.t) list -> unit - - (** Append the instructions to the list of instructions to execute *) + (** Add declarations for local variables and return variable to the node *) val append_instrs : t -> Sil.instr list -> unit - - (** Dump extended instructions for the node *) + (** Append the instructions to the list of instructions to execute *) val d_instrs : sub_instrs:bool -> Sil.instr option -> t -> unit - - (** Create a dummy node *) + (** Dump extended instructions for the node *) val dummy : Typ.Procname.t option -> t - - (** Check if two nodes are equal *) + (** Create a dummy node *) val equal : t -> t -> bool - - (** Get the list of callee procnames from the node *) + (** Check if two nodes are equal *) val get_callees : t -> Typ.Procname.t list - - (** Return a description of the node *) + (** Get the list of callee procnames from the node *) val get_description : Pp.env -> t -> string - - (** Get the distance to the exit node, if it has been computed *) + (** Return a description of the node *) val get_distance_to_exit : t -> int option - - (** Get the exception nodes from the current node *) + (** Get the distance to the exit node, if it has been computed *) 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 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 - - (** Get the instructions to be executed *) + (** Get the unique id of the node *) val get_instrs : t -> Sil.instr list - - (** Get the kind of the current node *) + (** Get the instructions to be executed *) val get_kind : t -> nodekind - - (** Get the source location of the last instruction in the node *) + (** Get the kind of the current node *) val get_last_loc : t -> Location.t - - (** Get the source location of the node *) + (** Get the source location of the last instruction in the node *) val get_loc : t -> Location.t - - (** Get the predecessor nodes of the current node *) + (** Get the source location of the node *) val get_preds : t -> t list - - (** Get the name of the procedure the node belongs to *) + (** Get the predecessor nodes of the current node *) val get_proc_name : t -> Typ.Procname.t - - (** Get the predecessor nodes of a node where the given predicate evaluates to true *) + (** Get the name of the procedure the node belongs to *) val get_sliced_preds : t -> (t -> bool) -> t list - - (** Get the successor nodes of a node where the given predicate evaluates to true *) + (** Get the predecessor nodes of a node where the given predicate evaluates to true *) val get_sliced_succs : t -> (t -> bool) -> t list - - (** Get the successor nodes of the current node *) + (** Get the successor nodes of a node where the given predicate evaluates to true *) val get_succs : t -> t list - - (** Hash function for nodes *) + (** Get the successor nodes of the current node *) val hash : t -> int - - (** Pretty print the node *) + (** Hash function for nodes *) val pp : Format.formatter -> t -> unit - - (** Pretty print a node id *) + (** Pretty print the node *) 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, 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 + (** Replace the instructions to be executed. *) end (** Map with node id keys. *) - module IdMap : Caml.Map.S with type key = Node.id (** Hash table with nodes as keys. *) - module NodeHash : Caml.Hashtbl.S with type key = Node.t (** Map over nodes. *) - module NodeMap : Caml.Map.S with type key = Node.t (** Set of nodes. *) - module NodeSet : Caml.Set.S with type elt = Node.t (** procedure descriptions *) (** proc description *) - 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 - -(** Compute the distance of each node to the exit node, if not computed already *) +(** append a list of new local variables to the existing list of local variables *) 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, 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 - -(** fold over the calls from the procedure: (callee, location) pairs *) +(** true if we ran the preanalysis on the CFG associated with [t] *) val fold_calls : ('a -> Typ.Procname.t * Location.t -> 'a) -> 'a -> t -> 'a - -(** fold over all nodes and their instructions *) +(** fold over the calls from the procedure: (callee, location) pairs *) val fold_instrs : ('a -> Node.t -> Sil.instr -> 'a) -> 'a -> t -> 'a - -(** fold over all nodes *) +(** fold over all nodes and their instructions *) val fold_nodes : ('a -> Node.t -> 'a) -> 'a -> t -> 'a - -(** Only call from Cfg. *) +(** fold over all nodes *) val from_proc_attributes : called_from_cfg:bool -> ProcAttributes.t -> t - -(** Return the visibility attribute *) +(** Only call from Cfg. *) val get_access : t -> PredSymb.access - -(** Get the attributes of the procedure. *) +(** Return the visibility attribute *) val get_attributes : t -> ProcAttributes.t - -(** Return name and type of block's captured variables *) +(** Get the attributes of the procedure. *) 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_exit_node : t -> Node.t -(** Get flags for the proc desc *) - val get_flags : t -> ProcAttributes.proc_flags - -(** Return name and type of formal parameters *) +(** Get flags for the proc desc *) val get_formals : t -> (Mangled.t * Typ.t) list - -(** Return loc information for the procedure *) +(** Return name and type of formal parameters *) val get_loc : t -> Location.t - -(** Return name and type of local variables *) +(** Return loc information for the procedure *) 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_proc_name : t -> Typ.Procname.t -(** Return the return type of the procedure and type string *) - val get_ret_type : t -> Typ.t +(** Return the return type of the procedure and type string *) 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 - -(** Get the procedure's nodes up until the first branching *) +(** Get the sliced procedure's nodes up until the first branching *) val get_slope : t -> Node.t list +(** Get the procedure's nodes up until the first branching *) val get_start_node : t -> Node.t -(** Return [true] iff the procedure is defined, and not just declared *) - val is_defined : t -> bool - -(** Return [true] if the body of the procdesc is empty (no instructions) *) +(** Return [true] iff the procedure is defined, and not just declared *) val is_body_empty : t -> bool - -(** Return [true] if the procedure signature has the Java synchronized keyword *) +(** Return [true] if the body of the procdesc is empty (no instructions) *) val is_java_synchronized : t -> bool - -(** iterate over the calls from the procedure: (callee, location) pairs *) +(** Return [true] if the procedure signature has the Java synchronized keyword *) val iter_calls : (Typ.Procname.t * Location.t -> unit) -> t -> unit - -(** iterate over all nodes and their instructions *) +(** iterate over the calls from the procedure: (callee, location) pairs *) val iter_instrs : (Node.t -> Sil.instr -> unit) -> t -> unit - -(** iterate over all the nodes of a procedure *) +(** iterate over all nodes and their instructions *) val iter_nodes : (Node.t -> unit) -> t -> unit - -(** iterate over all nodes until we reach a branching structure *) +(** iterate over all the nodes of a procedure *) val iter_slope : (Node.t -> unit) -> t -> unit - -(** iterate over all calls until we reach a branching structure *) +(** iterate over all nodes until we reach a branching structure *) val iter_slope_calls : (Typ.Procname.t -> unit) -> t -> unit - -(** iterate between two nodes or until we reach a branching structure *) +(** iterate over all calls until we reach a branching structure *) val iter_slope_range : (Node.t -> unit) -> Node.t -> Node.t -> unit - -(** Set the successor nodes and exception nodes, and build predecessor links *) +(** iterate between two nodes or until we reach a branching structure *) val node_set_succs_exn : t -> Node.t -> Node.t list -> Node.t list -> unit - -(** Set the exit node of the procedure *) +(** Set the successor nodes and exception nodes, and build predecessor links *) val set_exit_node : t -> Node.t -> unit - -(** Set a flag for the proc desc *) +(** Set the exit node of the procedure *) val set_flag : t -> string -> string -> unit +(** Set a flag for the proc desc *) val set_start_node : t -> Node.t -> unit -(** indicate that we have performed preanalysis on the CFG assoociated with [t] *) - 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 diff --git a/infer/src/IR/Pvar.ml b/infer/src/IR/Pvar.ml index 8630f8854..e8da4f543 100644 --- a/infer/src/IR/Pvar.ml +++ b/infer/src/IR/Pvar.ml @@ -9,6 +9,7 @@ *) (** The Smallfoot Intermediate Language *) + open! IStd module L = Logging module F = Format diff --git a/infer/src/IR/Pvar.mli b/infer/src/IR/Pvar.mli index 3993f7406..612108925 100644 --- a/infer/src/IR/Pvar.mli +++ b/infer/src/IR/Pvar.mli @@ -9,6 +9,7 @@ *) (** Program variables. *) + open! IStd module F = Format @@ -19,149 +20,114 @@ type translation_unit = TUFile of SourceFile.t | TUExtern [@@deriving compare] 2) callee program variables, used to handle recursion ([x | callee] is distinguished from [x]) 3) global variables 4) seed variables, used to store the initial value of formal parameters - *) - +*) type t [@@deriving compare] -(** Equality for pvar's *) - val equal : t -> t -> bool - -(** Dump a program variable. *) +(** Equality for pvar's *) val d : t -> unit - -(** Dump a list of program variables. *) +(** Dump a program variable. *) val d_list : t list -> unit - -(** Get the name component of a program variable. *) +(** Dump a list of program variables. *) val get_name : t -> Mangled.t - -(** [get_ret_pvar proc_name] retuns the return pvar associated with the procedure name *) +(** Get the name component of a program variable. *) val get_ret_pvar : Typ.Procname.t -> t - -(** Get a simplified version of the name component of a program variable. *) +(** [get_ret_pvar proc_name] retuns the return pvar associated with the procedure name *) val get_simplified_name : t -> string - -(** Check if the pvar is an abduced return var or param passed by ref *) +(** Get a simplified version of the name component of a program variable. *) val is_abduced : t -> bool - -(** Check if the pvar is a callee var *) +(** Check if the pvar is an abduced return var or param passed by ref *) val is_callee : t -> bool - -(** Check if the pvar is a global var or a static local var *) +(** Check if the pvar is a callee var *) val is_global : t -> bool - -(** Check if the pvar is a static variable declared inside a function *) +(** Check if the pvar is a global var or a static local var *) val is_static_local : t -> bool - -(** Check if the pvar is a (non-static) local var *) +(** Check if the pvar is a static variable declared inside a function *) val is_local : t -> bool - -(** Check if the pvar is a seed var *) +(** Check if the pvar is a (non-static) local var *) val is_seed : t -> bool - -(** Check if the pvar is a return var *) +(** Check if the pvar is a seed var *) val is_return : t -> bool - -(** Check if a pvar is the special "this" var *) +(** Check if the pvar is a return var *) val is_this : t -> bool - -(** Check if a pvar is the special "self" var *) +(** Check if a pvar is the special "this" var *) val is_self : t -> bool - -(** return true if [pvar] is a temporary variable generated by the frontend *) +(** Check if a pvar is the special "self" var *) 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 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 - -(** create an abduced variable for a parameter passed by reference *) +(** [mk name proc_name suffix] creates a program var with the given function name and suffix *) val mk_abduced_ref_param : Typ.Procname.t -> t -> Location.t -> t - (** create an abduced variable for a parameter passed by reference *) val mk_abduced_ref_param_val : Typ.Procname.t -> Ident.t -> Location.t -> t - -(** create an abduced return variable for a call to [proc_name] at [loc] *) +(** create an abduced variable for a parameter passed by reference *) 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 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 : ?is_constexpr:bool -> ?is_pod:bool -> ?is_static_local:bool -> Mangled.t -> translation_unit -> t - -(** create a fresh temporary variable local to procedure [pname]. for use in the frontends only! *) +(** create a global variable with the given name *) val mk_tmp : string -> Typ.Procname.t -> t - -(** Pretty print a program variable. *) +(** create a fresh temporary variable local to procedure [pname]. for use in the frontends only! *) val pp : Pp.env -> F.formatter -> t -> unit - -(** Pretty print a list of program variables. *) +(** Pretty print a program variable. *) val pp_list : Pp.env -> F.formatter -> t list -> unit - -(** Pretty print a pvar which denotes a value, not an address *) +(** Pretty print a list of program variables. *) 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 -(** Turn an ordinary program variable into a callee program variable *) - val to_callee : Typ.Procname.t -> t -> t - -(** Turn a pvar into a seed pvar (which stores the initial value of a stack var) *) +(** Turn an ordinary program variable into a callee program variable *) val to_seed : t -> t - -(** Convert a pvar to string. *) +(** Turn a pvar into a seed pvar (which stores the initial value of a stack var) *) val to_string : t -> string - -(** Get the translation unit corresponding to a global. Raises Invalid_arg if not a global. *) +(** Convert a pvar to string. *) 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 [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 [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 +(** Get the procname of the initializer function for the given global variable *) diff --git a/infer/src/IR/QualifiedCppName.ml b/infer/src/IR/QualifiedCppName.ml index a01790dc6..6c299f24a 100644 --- a/infer/src/IR/QualifiedCppName.ml +++ b/infer/src/IR/QualifiedCppName.ml @@ -6,6 +6,7 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. *) + open! IStd (* internally it uses reversed list to store qualified name, for example: ["get", "shared_ptr", "std"]*) diff --git a/infer/src/IR/QualifiedCppName.mli b/infer/src/IR/QualifiedCppName.mli index 0c10e357d..2f3dd18c3 100644 --- a/infer/src/IR/QualifiedCppName.mli +++ b/infer/src/IR/QualifiedCppName.mli @@ -11,58 +11,47 @@ open! IStd type t [@@deriving compare] -(** empty qualified name *) - val empty : t +(** empty qualified name *) val equal : t -> t -> bool -(** attempts to parse the argument into a list::of::possibly::templated::qualifiers *) - val of_qual_string : string -> t - -(** returns qualified name as a string with "::" as a separator between qualifiers *) +(** attempts to parse the argument into a list::of::possibly::templated::qualifiers *) val to_qual_string : t -> string - -(** append qualifier to the end (innermost scope) of the qualified name *) +(** returns qualified name as a string with "::" as a separator between qualifiers *) val append_qualifier : t -> qual:string -> t - -(** returns last (innermost scope) qualifier and qualified name without last qualifier *) +(** append qualifier to the end (innermost scope) of the qualified name *) 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: input: 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 template args *) -val append_template_args_to_last : t -> args:string -> t - -(** returns list of qualifers *) - val to_list : t -> string list - -(** returns reversed list of qualifiers, ie innermost scope is the first element *) +(** returns list of qualifers *) val to_rev_list : t -> string list - -(** given list of qualifiers in normal order produce qualified name ["std", "move"] *) +(** returns reversed list of qualifiers, ie innermost scope is the first element *) val of_list : string list -> t - -(** given reversed list of qualifiers, produce qualified name (ie. ["move", "std"] for std::move )*) +(** given list of qualifiers in normal order produce qualified name ["std", "move"] *) 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 -(* 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: 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 does not match: ["folly","someFunction", "BAD"] - same as previous example *) - module Match : sig type quals_matcher diff --git a/infer/src/IR/Sil.ml b/infer/src/IR/Sil.ml index f0def4eeb..5c47ae08a 100644 --- a/infer/src/IR/Sil.ml +++ b/infer/src/IR/Sil.ml @@ -9,6 +9,7 @@ *) (** The Smallfoot Intermediate Language *) + open! IStd module Hashtbl = Caml.Hashtbl module L = Logging @@ -18,40 +19,37 @@ module F = Format (** Kind of prune instruction *) type if_kind = - | Ik_bexp - (* boolean expressions, and exp ? exp : exp *) + | Ik_bexp (** boolean expressions, and exp ? exp : exp *) | Ik_dowhile | Ik_for | Ik_if - | Ik_land_lor - (* obtained from translation of && or || *) + | Ik_land_lor (** obtained from translation of && or || *) | Ik_while | Ik_switch [@@deriving compare] (** An instruction. *) 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: [x] must be used in a subsequent instruction, otherwise the entire `Load` instruction may be eliminated by copy-propagation. *) | Load of Ident.t * Exp.t * Typ.t * Location.t - (** Store the value of an expression into the heap. - [*lexp1:typ = exp2] where - [lexp1] is an expression denoting a heap address - [typ] is the root type of [lexp1] - [exp2] is the expression whose value is store. *) + (** 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 - (** prune the state based on [exp=1], the boolean indicates whether true branch *) + (** Store the value of an expression into the heap. + [*lexp1:typ = exp2] where + [lexp1] is an expression denoting a heap address + [typ] is the root type of [lexp1] + [exp2] is the expression whose value is store. *) | Prune of Exp.t * Location.t * bool * if_kind - (** [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]. *) + (** 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 - (** nullify stack variable *) - | Nullify of Pvar.t * Location.t + (** [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]. *) + | Nullify of Pvar.t * Location.t (** nullify stack variable *) | Abstract of Location.t (** apply abstraction *) | Remove_temps of Ident.t list * Location.t (** remove temporaries *) | 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 = | Aeq of Exp.t * Exp.t (** equality *) | Aneq of Exp.t * Exp.t (** disequality *) - | Apred of PredSymb.t * (** predicate symbol applied to exps *) Exp.t list - | Anpred of PredSymb.t * (** negated predicate symbol applied to exps *) Exp.t list + | Apred of PredSymb.t * Exp.t list (** predicate symbol applied to exps *) + | Anpred of PredSymb.t * Exp.t list (** negated predicate symbol applied to exps *) [@@deriving compare] let equal_atom = [%compare.equal : atom] @@ -126,14 +124,14 @@ let equal_inst = [%compare.equal : inst] type 'inst strexp0 = | Eexp of Exp.t * 'inst (** Base case: expression with instrumentation *) | Estruct of (Typ.Fieldname.t * 'inst strexp0) list * 'inst (** C structure *) - (** Array of given length - There are two conditions imposed / used in the array case. - First, if some index and value pair appears inside an array - in a strexp, then the index is less than the length of the array. - For instance, x |->[10 | e1: v1] implies that e1 <= 9. - Second, if two indices appear in an array, they should be different. - For instance, x |->[10 | e1: v1, e2: v2] implies that e1 != e2. *) | Earray of Exp.t * (Exp.t * 'inst strexp0) list * 'inst + (** Array of given length + There are two conditions imposed / used in the array case. + First, if some index and value pair appears inside an array + in a strexp, then the index is less than the length of the array. + For instance, x |->[10 | e1: v1] implies that e1 <= 9. + Second, if two indices appear in an array, they should be different. + For instance, x |->[10 | e1: v1, e2: v2] implies that e1 != e2. *) [@@deriving compare] type strexp = inst strexp0 @@ -261,8 +259,8 @@ let color_pre_wrapper pe f x = else Latex.pp_color ) f color ; if Pp.equal_color color Pp.Red then - (Pp.{(** All subexpressiona red *) - pe with cmap_norm= colormap_red; color= Red}, true) + (* All subexpressions red *) + (Pp.{pe with cmap_norm= colormap_red; color= Red}, true) else (Pp.{pe with color}, true) ) else (pe, false) else (pe, false) @@ -295,7 +293,7 @@ let pp_exp_printenv pe0 f e0 = let e = match pe.Pp.obj_sub with | 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 -> e0 in @@ -424,7 +422,7 @@ let pp_instr pe0 f instr = (** 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)) -(* 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 "") (** Dump an instruction. *) @@ -480,8 +478,6 @@ let rec pp_star_seq pp f = function | x :: 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 of (doubly -)linked lists and Epara. Provides unique numbering for predicates and an iterator. *) @@ -612,7 +608,6 @@ end = struct done end -(********* END OF MODULE Predicates **********) let pp_texp_simple 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' = match (e, se) with | 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 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) (** {2 Functions for traversing SIL data types} *) + let rec strexp_expmap (f: Exp.t * inst option -> Exp.t * inst option) = let fe e = fst (f (e, None)) in 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 (** {2 Function for computing lexps in sigma} *) + let hpred_get_lexp acc = function | Hpointsto (e, _, _) -> e :: acc @@ -1235,8 +1232,7 @@ let rec exp_fav_add fav e = -> exp_fav_add fav e1 ; exp_fav_add fav e2 | Lvar _ -> () - | Lfield (* do nothing since we only count non-program variables *) - (e, _, _) + | Lfield (e, _, _) (* do nothing since we only count non-program variables *) -> exp_fav_add fav e | Lindex (e1, 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 (** {2 Functions for Substitution} *) + 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 = @@ -1527,8 +1524,8 @@ let rec exp_sub_ids (f: subst_fun) exp = | `Exp f_exp -> ( match f_exp id with | Exp.Var id' when Ident.equal id id' - -> exp - (* it will preserve physical equality when needed *) | exp' + -> exp (* it will preserve physical equality when needed *) + | exp' -> exp' ) | _ -> exp ) diff --git a/infer/src/IR/Sil.mli b/infer/src/IR/Sil.mli index 5c61b211b..330598a5d 100644 --- a/infer/src/IR/Sil.mli +++ b/infer/src/IR/Sil.mli @@ -14,48 +14,42 @@ module F = Format (** {2 Programs and Types} *) -(** Convert expression lists to expression sets. *) - val elist_to_eset : Exp.t list -> Exp.Set.t +(** Convert expression lists to expression sets. *) (** Kind of prune instruction *) - type if_kind = - | Ik_bexp - (* boolean expressions, and exp ? exp : exp *) + | Ik_bexp (** boolean expressions, and exp ? exp : exp *) | Ik_dowhile | Ik_for | Ik_if - | Ik_land_lor - (* obtained from translation of && or || *) + | Ik_land_lor (** obtained from translation of && or || *) | Ik_while | Ik_switch [@@deriving compare] (** An instruction. *) - 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: [x] must be used in a subsequent instruction, otherwise the entire `Load` instruction may be eliminated by copy-propagation. *) | 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. [*lexp1:typ = exp2] where [lexp1] is an expression denoting a heap address [typ] is the root type of [lexp1] [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 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 [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 stack variable *) - | Nullify of Pvar.t * Location.t + | Nullify of Pvar.t * Location.t (** nullify stack variable *) | Abstract of Location.t (** apply abstraction *) | Remove_temps of Ident.t list * Location.t (** remove temporaries *) | 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 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. the [exp_map] param gives a mapping of names used in the procedure of [instr1] to identifiers 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 -(** Check if an instruction is auxiliary, or if it comes from source instructions. *) - val instr_is_auxiliary : instr -> bool +(** Check if an instruction is auxiliary, or if it comes from source instructions. *) (** Offset for an lvalue. *) - type offset = Off_fld of Typ.Fieldname.t * Typ.t | Off_index of Exp.t (** {2 Components of Propositions} *) (** an atom is a pure atomic formula *) - type atom = | Aeq of Exp.t * Exp.t (** equality *) | Aneq of Exp.t * Exp.t (** disequality *) - | Apred of PredSymb.t * (** predicate symbol applied to exps *) Exp.t list - | Anpred of PredSymb.t * (** negated predicate symbol applied to exps *) Exp.t list + | Apred of PredSymb.t * Exp.t list (** predicate symbol applied to exps *) + | Anpred of PredSymb.t * Exp.t list (** negated predicate symbol applied to exps *) [@@deriving compare] val equal_atom : atom -> atom -> bool @@ -95,7 +85,6 @@ val equal_atom : atom -> atom -> bool val atom_has_local_addr : atom -> bool (** kind of lseg or dllseg predicates *) - type lseg_kind = | Lseg_NE (** nonempty (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 (** The boolean is true when the pointer was dereferenced without testing for zero. *) - type zero_flag = bool option (** True when the value was obtained by doing case analysis on null in a procedure call. *) - type null_case_flag = bool (** instrumentation of heap values *) - type inst = | Iabstraction | Iactual_precondition @@ -138,83 +124,70 @@ val inst_alloc : inst val inst_formal : inst -(** for formal parameters and heap values at the beginning of the function *) - val inst_initial : inst - -(** for initial values *) +(** for formal parameters and heap values at the beginning of the function *) val inst_lookup : inst +(** for initial values *) val inst_none : inst val inst_nullify : inst -(** the boolean indicates whether the pointer is known nonzero *) - 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_update : Location.t -> PredSymb.path_pos -> inst -(** Get the null case flag of the inst. *) - val inst_get_null_case_flag : inst -> bool option - -(** Set the null case flag of the inst. *) +(** Get the null case flag of the inst. *) val inst_set_null_case_flag : inst -> inst - -(** update the location of the instrumentation *) +(** Set the null case flag of the inst. *) val inst_new_loc : Location.t -> inst -> inst - -(** Update [inst_old] to [inst_new] preserving the zero flag *) +(** update the location of the instrumentation *) val update_inst : inst -> inst -> inst +(** Update [inst_old] to [inst_new] preserving the zero flag *) exception JoinFail -(** join of instrumentations, can raise JoinFail *) - val inst_partial_join : inst -> inst -> inst - -(** meet of instrumentations *) +(** join of instrumentations, can raise JoinFail *) 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. *) - type 'inst strexp0 = | Eexp of Exp.t * 'inst (** Base case: expression with instrumentation *) | Estruct of (Typ.Fieldname.t * 'inst strexp0) list * 'inst (** C structure *) - (** Array of given length - There are two conditions imposed / used in the array case. - First, if some index and value pair appears inside an array - in a strexp, then the index is less than the length of the array. - For instance, x |->[10 | e1: v1] implies that e1 <= 9. - Second, if two indices appear in an array, they should be different. - For instance, x |->[10 | e1: v1, e2: v2] implies that e1 != e2. *) | Earray of Exp.t * (Exp.t * 'inst strexp0) list * 'inst + (** Array of given length + There are two conditions imposed / used in the array case. + First, if some index and value pair appears inside an array + in a strexp, then the index is less than the length of the array. + For instance, x |->[10 | e1: v1] implies that e1 <= 9. + Second, if two indices appear in an array, they should be different. + For instance, x |->[10 | e1: v1, e2: v2] implies that e1 != e2. *) [@@deriving compare] type strexp = inst strexp0 +val compare_strexp : ?inst:bool -> strexp -> strexp -> int (** Comparison function for strexp. The inst:: parameter specifies whether instumentations should also 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. The inst:: parameter specifies whether instumentations should also be considered (false by default). *) -val equal_strexp : ?inst:bool -> strexp -> strexp -> bool - (** an atomic heap predicate *) - type 'inst hpred0 = | Hpointsto of Exp.t * 'inst strexp0 * Exp.t (** represents [exp|->strexp:typexp] where [typexp] @@ -256,299 +229,230 @@ type hpara = inst hpara0 type hpara_dll = inst hpara_dll0 +val compare_hpred : ?inst:bool -> hpred -> hpred -> int (** Comparison function for hpred. The inst:: parameter specifies whether instumentations should also 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. The inst:: parameter specifies whether instumentations should also be considered (false by default). *) -val equal_hpred : ?inst:bool -> hpred -> hpred -> bool - (** Sets of heap predicates *) - module HpredSet : Caml.Set.S with type elt = hpred (** {2 Compaction} *) type sharing_env -(** Create a sharing env to store canonical representations *) - val create_sharing_env : unit -> sharing_env - -(** Return a canonical representation of the exp *) +(** Create a sharing env to store canonical representations *) val exp_compact : sharing_env -> Exp.t -> Exp.t - -(** Return a compact representation of the exp *) +(** Return a canonical representation of the exp *) val hpred_compact : sharing_env -> hpred -> hpred - -(** {2 Comparision And Inspection Functions} *) +(** Return a compact representation of the exp *) val has_objc_ref_counter : Tenv.t -> hpred -> bool - -(** Returns the zero value of a type, for int, float and ptr types, None othwewise *) +(** {2 Comparision And Inspection Functions} *) 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, fail otherwise *) +(** Returns the zero value of a type, for int, float and ptr types, None othwewise *) val zero_value_of_numerical_type : Typ.t -> Exp.t - -(** Make a static local name in objc *) +(** Returns the zero value of a type, for int, float and ptr types, fail otherwise *) val mk_static_local_name : string -> string -> string - -(** Check if a pvar is a local static in objc *) +(** Make a static local name in objc *) val is_static_local_name : string -> Pvar.t -> bool - -(* A block pvar used to explain retain cycles *) +(** Check if a pvar is a local static in objc *) val block_pvar : Pvar.t - -(** Check if a pvar is a local pointing to a block in objc *) +(** A block pvar used to explain retain cycles *) val is_block_pvar : Pvar.t -> bool - -(** Return the lhs expression of a hpred *) +(** Check if a pvar is a local pointing to a block in objc *) val hpred_get_lhs : hpred -> Exp.t +(** Return the lhs expression of a hpred *) (** {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 - -(** Close color annotation if changed *) +(** Begin change color if using diff printing, return updated printenv and change status *) val color_post_wrapper : bool -> Pp.env -> F.formatter -> unit - -(** Pretty print an expression. *) +(** Close color annotation if changed *) val pp_exp_printenv : Pp.env -> F.formatter -> Exp.t -> unit - -(** Pretty print an expression with type. *) +(** Pretty print an expression. *) val pp_exp_typ : Pp.env -> F.formatter -> Exp.t * Typ.t -> unit - -(** dump an expression. *) +(** Pretty print an expression with type. *) val d_exp : Exp.t -> unit - -(** Pretty print a type. *) +(** dump an expression. *) val pp_texp : Pp.env -> F.formatter -> Exp.t -> unit - -(** Pretty print a type with all the details. *) +(** Pretty print a type. *) val pp_texp_full : Pp.env -> F.formatter -> Exp.t -> unit - -(** Dump a type expression with all the details. *) +(** Pretty print a type with all the details. *) val d_texp_full : Exp.t -> unit - -(** Pretty print a list of expressions. *) +(** Dump a type expression with all the details. *) val pp_exp_list : Pp.env -> F.formatter -> Exp.t list -> unit - -(** Dump a list of expressions. *) +(** Pretty print a list of expressions. *) val d_exp_list : Exp.t list -> unit - -(** Pretty print an offset *) +(** Dump a list of expressions. *) val pp_offset : Pp.env -> F.formatter -> offset -> unit - -(** Convert an offset to a string *) +(** Pretty print an offset *) val offset_to_string : offset -> string - -(** Dump an offset *) +(** Convert an offset to a string *) val d_offset : offset -> unit - -(** Pretty print a list of offsets *) +(** Dump an offset *) val pp_offset_list : Pp.env -> F.formatter -> offset list -> unit - -(** Dump a list of offsets *) +(** Pretty print a list of offsets *) val d_offset_list : offset list -> unit - -(** Get the location of the instruction *) +(** Dump a list of offsets *) val instr_get_loc : instr -> Location.t - -(** get the expressions occurring in the instruction *) +(** Get the location of the instruction *) val instr_get_exps : instr -> Exp.t list - -(** Pretty print an instruction. *) +(** get the expressions occurring in the instruction *) val pp_instr : Pp.env -> F.formatter -> instr -> unit - -(** Dump an instruction. *) +(** Pretty print an instruction. *) val d_instr : instr -> unit - -(** Pretty print a list of instructions. *) +(** Dump an instruction. *) val pp_instr_list : Pp.env -> F.formatter -> instr list -> unit - -(** Dump a list of instructions. *) +(** Pretty print a list of instructions. *) val d_instr_list : instr list -> unit - -(** Pretty print an atom. *) +(** Dump a list of instructions. *) val pp_atom : Pp.env -> F.formatter -> atom -> unit - -(** Dump an atom. *) +(** Pretty print an atom. *) val d_atom : atom -> unit - -(** return a string representing the inst *) +(** Dump an atom. *) val inst_to_string : inst -> string - -(** Pretty print a strexp. *) +(** return a string representing the inst *) val pp_sexp : Pp.env -> F.formatter -> strexp -> unit - -(** Dump a strexp. *) +(** Pretty print a strexp. *) val d_sexp : strexp -> unit - -(** Pretty print a strexp list. *) +(** Dump a strexp. *) val pp_sexp_list : Pp.env -> F.formatter -> strexp list -> unit - -(** Dump a strexp. *) +(** Pretty print a strexp list. *) val d_sexp_list : strexp list -> unit - -(** Pretty print a hpred. *) +(** Dump a strexp. *) val pp_hpred : Pp.env -> F.formatter -> hpred -> unit - -(** Dump a hpred. *) +(** Pretty print a hpred. *) val d_hpred : hpred -> unit - -(** Pretty print a hpara. *) +(** Dump a hpred. *) val pp_hpara : Pp.env -> F.formatter -> hpara -> unit - -(** Pretty print a list of hparas. *) +(** Pretty print a hpara. *) val pp_hpara_list : Pp.env -> F.formatter -> hpara list -> unit - -(** Pretty print a hpara_dll. *) +(** Pretty print a list of hparas. *) val pp_hpara_dll : Pp.env -> F.formatter -> hpara_dll -> unit - -(** Pretty print a list of hpara_dlls. *) +(** Pretty print a hpara_dll. *) val pp_hpara_dll_list : Pp.env -> F.formatter -> hpara_dll list -> unit +(** Pretty print a list of hpara_dlls. *) (** Module Predicates records the occurrences of predicates as parameters of (doubly -)linked lists and Epara. Provides unique numbering for predicates and an iterator. *) - module Predicates : sig (** predicate environment *) - type env - (** create an empty predicate environment *) - val empty_env : unit -> env - - (** return true if the environment is empty *) + (** create an empty predicate environment *) val is_empty : env -> bool - - (** return the id of the hpara *) + (** return true if the environment is empty *) val get_hpara_id : env -> hpara -> int - - (** return the id of the hpara_dll *) + (** return the id of the hpara *) val get_hpara_dll_id : env -> hpara_dll -> int + (** return the id of the hpara_dll *) + val iter : env -> (int -> hpara -> unit) -> (int -> hpara_dll -> unit) -> unit (** [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. *) - val iter : env -> (int -> hpara -> unit) -> (int -> hpara_dll -> unit) -> unit - - (** Process one hpred, updating the predicate environment *) - val process_hpred : env -> hpred -> unit + (** Process one hpred, updating the predicate environment *) end -(** Pretty print a hpred with optional predicate env *) - 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} *) +val array_clean_new_index : bool -> Exp.t -> Exp.t (** This function should be used before adding a new index to Earray. The [exp] is the newly created index. This function "cleans" [exp] according to whether it is the footprint or current part of the prop. 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 - -(** Change exps in hpred by [f]. *) - -(** WARNING: the result might not be normalized. *) +(** Change exps in strexp using [f]. + WARNING: the result might not be normalized. *) val hpred_expmap : (Exp.t * inst option -> Exp.t * inst option) -> hpred -> hpred - -(** Change instrumentations in hpred using [f]. *) +(** Change exps in hpred by [f]. + WARNING: the result might not be normalized. *) val hpred_instmap : (inst -> inst) -> hpred -> hpred - -(** Change exps in hpred list by [f]. *) - -(** WARNING: the result might not be normalized. *) +(** Change instrumentations in hpred using [f]. *) val hpred_list_expmap : (Exp.t * inst option -> Exp.t * inst option) -> hpred list -> hpred list - -(** Change exps in atom by [f]. *) - -(** WARNING: the result might not be normalized. *) +(** Change exps in hpred list by [f]. + WARNING: the result might not be normalized. *) val atom_expmap : (Exp.t -> Exp.t) -> atom -> atom - -(** Change exps in atom list by [f]. *) - -(** WARNING: the result might not be normalized. *) +(** Change exps in atom by [f]. + WARNING: the result might not be normalized. *) val atom_list_expmap : (Exp.t -> Exp.t) -> atom list -> atom list - -(** {2 Function for computing lexps in sigma} *) +(** Change exps in atom list by [f]. + WARNING: the result might not be normalized. *) val hpred_list_get_lexps : (Exp.t -> bool) -> hpred list -> Exp.t list -(** {2 Functions for computing program variables} *) +(** {2 Function for computing lexps in sigma} *) val exp_fpv : Exp.t -> Pvar.t list +(** {2 Functions for computing program variables} *) + val strexp_fpv : strexp -> Pvar.t list val atom_fpv : atom -> Pvar.t list @@ -561,75 +465,58 @@ val hpara_fpv : hpara -> Pvar.t list (** Type of free variables. These include primed, normal and footprint variables. We remember the order in which variables are added. *) - type fav +val fav_duplicates : bool ref (** flag to indicate whether fav's are stored in duplicate form. 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 - -(** Create a new [fav]. *) +(** Pretty print a fav. *) val fav_new : unit -> fav - -(** Emptyness check. *) +(** Create a new [fav]. *) val fav_is_empty : fav -> bool - -(** Check whether a predicate holds for all elements. *) +(** Emptyness check. *) val fav_for_all : fav -> (Ident.t -> bool) -> bool - -(** Check whether a predicate holds for some elements. *) +(** Check whether a predicate holds for all elements. *) val fav_exists : fav -> (Ident.t -> bool) -> bool - -(** Membership test fot [fav] *) +(** Check whether a predicate holds for some elements. *) val fav_mem : fav -> Ident.t -> bool - -(** Convert a list to a fav. *) +(** Membership test fot [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 that identifiers were added to [fav]. *) -val fav_to_list : fav -> Ident.t list - -(** Copy a [fav]. *) - val fav_copy : fav -> fav - -(** Turn a xxx_fav_add function into a xxx_fav function *) +(** Copy a [fav]. *) val fav_imperative_to_functional : (fav -> 'a -> unit) -> 'a -> fav - -(** [fav_filter_ident fav f] only keeps [id] if [f id] is true. *) +(** Turn a xxx_fav_add function into a xxx_fav function *) val fav_filter_ident : fav -> (Ident.t -> bool) -> unit - -(** Like [fav_filter_ident] but return a copy. *) +(** [fav_filter_ident fav f] only keeps [id] if [f id] is true. *) 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] 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 - -(** [exp_fav_add fav exp] extends [fav] with the free variables of [exp] *) +(** add identifier list to fav *) 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 @@ -647,23 +534,20 @@ val hpred_fav_add : fav -> hpred -> unit val hpred_fav : hpred -> fav -(** Variables in hpara, excluding bound vars in the body *) - val hpara_shallow_av : hpara -> fav - -(** Variables in hpara_dll, excluding bound vars in the body *) +(** Variables in hpara, excluding bound vars in the body *) 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} *) +val exp_av_add : fav -> Exp.t -> unit (** Non-program variables include all of primed, normal and footprint variables. Thus, the functions essentially compute all the identifiers occuring in a parameter. Some variables can appear more than once in the result. *) -val exp_av_add : fav -> Exp.t -> unit - val strexp_av_add : fav -> strexp -> 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)] -(** Equality for substitutions. *) - 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. For all (id1, e1), (id2, e2) in the input list, 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 -(** 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 - -(** Convert a subst to a list of pairs. *) +(** like exp_subst_of_list, but allow duplicate ids and only keep the first occurrence *) val sub_to_list : exp_subst -> (Ident.t * Exp.t) list - -(** The empty substitution. *) +(** Convert a subst to a list of pairs. *) val sub_empty : subst +(** The empty substitution. *) 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; *) +val sub_join : exp_subst -> exp_subst -> exp_subst (** Compute the common id-exp part of two inputs [subst1] and [subst2]. The first component of the output is this common part. The second and third components are the remainder of [subst1] 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]. The first component of the output is this common part. The second and third components are the remainder of [subst1] 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 that satisfies [filter]. 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 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 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 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 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 - -(** Return the list of expressions in the range of the substitution. *) +(** Return the list of identifiers in the domain of the substitution. *) val sub_range : exp_subst -> Exp.t list - -(** [sub_range_map f sub] applies [f] to the expressions in the range of [sub]. *) +(** Return the list of expressions in the range of the substitution. *) 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 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 - -(** Extend substitution and return [None] if not possible. *) +(** Checks whether [id] belongs to the domain of [subst]. *) 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 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 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 atom_sub : subst -> atom -> atom -(** apply [subst] to all id's in [instr], including LHS id's *) - val instr_sub : subst -> instr -> instr +(** apply [subst] to all id's in [instr], including LHS id's *) 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 +(** 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.} *) +val exp_replace_exp : (Exp.t * Exp.t) list -> Exp.t -> Exp.t (** The first parameter should define a partial function. No parts of hpara are replaced by these functions. *) -val exp_replace_exp : (Exp.t * Exp.t) list -> Exp.t -> Exp.t - val strexp_replace_exp : (Exp.t * Exp.t) list -> strexp -> strexp 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} *) -(** Compute the offset list of an expression *) - val exp_get_offsets : Exp.t -> offset list - -(** Add the offset list to an expression *) +(** Compute the offset list of an expression *) 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 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], [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\]] 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], [blink], [flink], and [elist]. If [para = lambda (x, y, z, xs). exists zs. b], then the result of the instantiation is [b\[cell / x, blink / y, flink / z, elist / xs, _zs'/ 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 diff --git a/infer/src/IR/Subtype.ml b/infer/src/IR/Subtype.ml index 4bd791b99..0ad625525 100644 --- a/infer/src/IR/Subtype.ml +++ b/infer/src/IR/Subtype.ml @@ -9,6 +9,7 @@ *) (** The Smallfoot Intermediate Language: Subtypes *) + open! IStd module L = Logging module F = Format diff --git a/infer/src/IR/Subtype.mli b/infer/src/IR/Subtype.mli index 546b59eba..1884af786 100644 --- a/infer/src/IR/Subtype.mli +++ b/infer/src/IR/Subtype.mli @@ -9,6 +9,7 @@ *) (** The Smallfoot Intermediate Language: Subtypes *) + open! IStd module L = Logging module F = Format @@ -21,46 +22,40 @@ val sub_type : (Typ.Name.t -> Typ.Name.t) -> t -> t val exact : t -(** denotes the current type only *) - val subtypes : t - -(** denotes the current type and any subtypes *) +(** denotes the current type only *) val subtypes_cast : t +(** denotes the current type and any subtypes *) val subtypes_instof : 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 to [st1] and [st2]. [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 [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 that [c1] is a subtype of [c2]. Note that [not (is_known_subtype tenv c1 c2) == true] does not imply 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 that [c1] is not a subtype of [c2]. Note that [not (is_known_not_subtype tenv c1 c2) == true] does not imply that [is_known_subtype tenv c1 c2 == true] *) -val is_known_not_subtype : Tenv.t -> Typ.Name.t -> Typ.Name.t -> bool - val subtypes_to_string : t -> string val is_cast : t -> bool val is_instof : t -> bool -(** equality ignoring flags in the subtype *) - val equal_modulo_flag : t -> t -> bool +(** equality ignoring flags in the subtype *) diff --git a/infer/src/IR/Tenv.mli b/infer/src/IR/Tenv.mli index a680a18de..1ca422445 100644 --- a/infer/src/IR/Tenv.mli +++ b/infer/src/IR/Tenv.mli @@ -11,53 +11,41 @@ open! IStd (** Module for Type Environments. *) -type t - (** Type for type environment. *) - -(** Add a (name,typename) pair to the global type environment. *) +type t val add : t -> Typ.Name.t -> Typ.Struct.t -> unit - -(** Create a new type environment. *) +(** Add a (name,typename) pair to the global type environment. *) val create : unit -> t - -(** Fold a function over the elements of the type environment. *) +(** Create a new type environment. *) val fold : (Typ.Name.t -> Typ.Struct.t -> 'a -> 'a) -> t -> 'a -> 'a - -(** iterate over a type environment *) +(** Fold a function over the elements of the type environment. *) val iter : (Typ.Name.t -> Typ.Struct.t -> unit) -> t -> unit - -(** Load a type environment from a file *) +(** iterate over a type environment *) val load_from_file : DB.filename -> t option - -(** Look up a name in the global type environment. *) +(** Load a type environment from a file *) val lookup : t -> Typ.Name.t -> Typ.Struct.t option - -(** Construct a struct_typ, normalizing field types *) +(** Look up a name in the global type environment. *) val mk_struct : 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 -> Typ.Struct.t - -(** Check if typename is found in t *) +(** Construct a struct_typ, normalizing field types *) val mem : t -> Typ.Name.t -> bool - -(** print a type environment *) +(** Check if typename is found in t *) val pp : Format.formatter -> t -> unit - -(** Save a type environment into a file *) +(** print a type environment *) val store_to_file : DB.filename -> t -> unit - -(** Get method that is being overriden by java_pname (if any) **) +(** Save a type environment into a file *) val get_overriden_method : t -> Typ.Procname.java -> Typ.Procname.t option +(** Get method that is being overriden by java_pname (if any) **) diff --git a/infer/src/IR/Typ.ml b/infer/src/IR/Typ.ml index 46ac1ed3d..46cbca570 100644 --- a/infer/src/IR/Typ.ml +++ b/infer/src/IR/Typ.ml @@ -9,6 +9,7 @@ *) (** The Smallfoot Intermediate Language: Types *) + open! IStd module Hashtbl = Caml.Hashtbl module L = Logging @@ -124,10 +125,8 @@ module T = struct | Tptr of t * ptr_kind (** pointer type *) | Tstruct of name (** structured value type name *) | TVar of string (** type variable (ie. C++ template variables) *) - | Tarray of - t - * IntLit.t option - * (** array type with statically fixed length and stride *) IntLit.t option + | Tarray of t * IntLit.t option * IntLit.t option + (** array type with statically fixed length and stride *) [@@deriving compare] and name = @@ -487,9 +486,8 @@ module Procname = struct { method_name: string ; parameters: java_type list ; class_name: Name.t - ; return_type: java_type option - ; (* option because constructors have no return type *) - kind: method_kind } + ; return_type: java_type option (* option because constructors have no return type *) + ; kind: method_kind } [@@deriving compare] (** Type of c procedure names. *) @@ -501,7 +499,7 @@ module Procname = struct [@@deriving compare] 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? *) | ObjCClassMethod | ObjCInstanceMethod @@ -1011,8 +1009,8 @@ module Procname = struct | _ -> to_concrete_filename pname + (** given two template arguments, try to generate mapping from generic ones to concrete ones. *) let get_template_args_mapping generic_procname concrete_procname = - (** given two template arguments, try to generate mapping from generic ones to concrete ones. *) let mapping_for_template_args (generic_name, generic_args) (concrete_name, concrete_args) = match (generic_args, concrete_args) with | Template generic_typs, Template concrete_typs diff --git a/infer/src/IR/Typ.mli b/infer/src/IR/Typ.mli index 2f49c5922..66c8f47a4 100644 --- a/infer/src/IR/Typ.mli +++ b/infer/src/IR/Typ.mli @@ -9,11 +9,11 @@ *) (** The Smallfoot Intermediate Language: Types *) + open! IStd module F = Format (** Kinds of integers *) - type ikind = | IChar (** [char] *) | ISChar (** [signed char] *) @@ -31,21 +31,17 @@ type ikind = | IU128 (** [__uint128_t] *) [@@deriving compare] -(** Check wheter the integer kind is a char *) - val ikind_is_char : ikind -> bool - -(** Check wheter the integer kind is unsigned *) +(** Check whether the integer kind is a char *) 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: the int64 is interpreted as unsigned according to the kind *) -val int_of_int64_kind : int64 -> ikind -> IntLit.t - (** Kinds of floating-point numbers *) - type fkind = | FFloat (** [float] *) | FDouble (** [double] *) @@ -53,7 +49,6 @@ type fkind = [@@deriving compare] (** kind of pointer *) - type ptr_kind = | Pk_pointer (** C/C++, Java, Objc standard/__strong pointer *) | Pk_reference (** C++ reference *) @@ -77,7 +72,6 @@ val is_restrict : type_quals -> bool val is_volatile : type_quals -> bool (** types for sil (structured) expressions *) - type t = {desc: desc; quals: type_quals} [@@deriving compare] and desc = @@ -88,10 +82,8 @@ and desc = | Tptr of t * ptr_kind (** pointer type *) | Tstruct of name (** structured value type name *) | TVar of string (** type variable (ie. C++ template variables) *) - | Tarray of - t - * IntLit.t option - * (** array type with statically fixed stride and length *) IntLit.t option + | Tarray of t * IntLit.t option * IntLit.t option + (** array type with statically fixed stride and length *) [@@deriving compare] and name = @@ -108,44 +100,35 @@ and name = 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 +(** 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 *) - type type_subst_t [@@deriving compare] module Name : sig (** Named types. *) - type t = name [@@deriving compare] - (** Equality for typenames *) - val equal : t -> t -> bool - - (** convert the typename to a string *) + (** Equality for typenames *) val to_string : t -> string + (** convert the typename to a string *) val pp : Format.formatter -> t -> unit - (** [is_class name] holds if [name] names CPP/Objc/Java class *) - val is_class : t -> bool - - (** [is_class name1 name2] holds if [name1] and [name2] name same kind of type *) + (** [is_class name] holds if [name] names CPP/Objc/Java class *) val is_same_type : t -> t -> bool - - (** name of the typename without qualifier *) + (** [is_class name1 name2] holds if [name1] and [name2] name same kind of type *) val name : t -> string - - (** qualified name of the type, may return nonsense for Java classes *) + (** name of the typename without qualifier *) val qual_name : t -> QualifiedCppName.t + (** qualified name of the type, may return nonsense for Java classes *) val unqualified_name : t -> QualifiedCppName.t @@ -158,17 +141,14 @@ module Name : sig end module Java : sig - (** Create a typename from a Java classname in the form "package.class" *) - val from_string : string -> t - - (** Create a typename from a package name and a class name *) + (** Create a typename from a Java classname in the form "package.class" *) val from_package_class : string -> string -> t - - (** [is_class name] holds if [name] names a Java class *) + (** Create a typename from a package name and a class name *) val is_class : t -> bool + (** [is_class name] holds if [name] names a Java class *) val java_lang_object : t @@ -178,35 +158,30 @@ module Name : sig end module Cpp : sig - (** Create a typename from a C++ classname *) - val from_qual_name : template_spec_info -> QualifiedCppName.t -> t - - (** [is_class name] holds if [name] names a C++ class *) + (** Create a typename from a C++ classname *) val is_class : t -> bool + (** [is_class name] holds if [name] names a C++ class *) end module Objc : sig - (** Create a typename from a Objc classname *) - val from_string : string -> t + (** Create a typename from a Objc classname *) val 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 + (** [is_class name] holds if [name] names a Objc class *) end module Set : Caml.Set.S with type elt = t end -(** Equality for types. *) - val equal : t -> t -> bool +(** Equality for types. *) 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 -(** Pretty print a type with all the details. *) - val pp_full : Pp.env -> F.formatter -> t -> unit - -(** Pretty print a type. *) +(** Pretty print a type with all the details. *) val pp : Pp.env -> F.formatter -> t -> unit +(** Pretty print a type. *) val to_string : t -> string -(** Dump a type with all the details. *) - val d_full : t -> unit - -(** Dump a list of types. *) +(** Dump a type with all the details. *) val d_list : t list -> unit - -(** The name of a type *) +(** Dump a list of types. *) val name : t -> Name.t option - -(** turn a *T into a T. fails if [t] is not a pointer type *) +(** The name of a type *) 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 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_cpp_class : t -> bool @@ -271,9 +239,8 @@ val is_pointer_to_cpp_class : t -> bool val has_block_prefix : string -> bool -(** Check if type is a type for a block in objc *) - val is_block_type : t -> bool +(** Check if type is a type for a block in objc *) val unsome : string -> t option -> t @@ -283,23 +250,18 @@ module Procname : sig (** Module for Procedure Names. *) (** Type of java procedure names. *) - type java (** Type of c procedure names. *) - type c (** Type of Objective C and C++ procedure names. *) - type objc_cpp (** Type of Objective C block names. *) - type block (** Type of procedure names. *) - type t = | Java of java | C of c @@ -308,21 +270,18 @@ module Procname : sig | ObjC_Cpp of objc_cpp [@@deriving compare] - (** Equality for proc names. *) - val equal : t -> t -> bool + (** Equality for proc names. *) type java_type = string option * string type method_kind = | Non_Static - (* in Java, procedures called with invokevirtual, invokespecial, and invokeinterface *) - | Static - - (* in Java, procedures called with invokestatic *) + (** in Java, procedures called with invokevirtual, invokespecial, and invokeinterface *) + | Static (** in Java, procedures called with invokestatic *) 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? *) | ObjCClassMethod | ObjCInstanceMethod @@ -340,258 +299,200 @@ module Procname : sig 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 - - (** Empty block name. *) + (** Create a C procedure name from plain and mangled name. *) val empty_block : t - - (** Convert a string to a proc name. *) + (** Empty block name. *) val from_string_c_fun : string -> t - - (** Return the language of the procedure. *) + (** Convert a string to a proc name. *) val get_language : t -> Config.language - - (** Return the method/function of a procname. *) + (** Return the language of the procedure. *) val get_method : t -> string - - (** Hash function for procname. *) + (** Return the method/function of a procname. *) val hash_pname : t -> int - - (** Check if a class string is an anoynmous inner class name. *) + (** Hash function for procname. *) val is_anonymous_inner_class_name : Name.t -> bool - - (** Check if this is an Objective-C/C++ method name. *) + (** Check if a class string is an anoynmous inner class name. *) val is_c_method : t -> bool - - (** Check if this is a constructor method in Objective-C. *) + (** Check if this is an Objective-C/C++ method name. *) val is_objc_constructor : string -> bool - - (** Check if this is a constructor. *) + (** Check if this is a constructor method in Objective-C. *) val is_constructor : t -> bool - - (** Check if this is a constexpr function. *) + (** Check if this is a constructor. *) val is_constexpr : t -> bool - - (** Check if this is a Java procedure name. *) + (** Check if this is a constexpr function. *) val is_java : t -> bool - - (** Check if this is a dealloc method in Objective-C. *) + (** Check if this is a Java procedure name. *) val is_objc_dealloc : string -> bool - - (** Check if this is a dealloc method. *) + (** Check if this is a dealloc method in Objective-C. *) 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 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 - - (** Replace the method of a java procname. *) + (** Replace the parameters of a java procname. *) val java_replace_return_type : java -> java_type -> java - - (** Create an objc block name. *) + (** Replace the method of a java procname. *) val mangled_objc_block : string -> t - - (** Create an objc procedure name from a class_name and method_name. *) + (** Create an objc block name. *) val objc_cpp : Name.t -> string -> objc_cpp_method_kind -> template_spec_info -> is_generic_model:bool -> objc_cpp + (** Create an objc procedure name from a class_name and method_name. *) 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 + (** Get the class name of a Objective-C/C++ procedure name. *) 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 - - (** Return the class name of a java procedure name. *) + (** Create ObjC method type from a bool is_instance. *) val java_get_class_name : java -> string - - (** Return the class name as a typename of a java procedure name. *) + (** Return the class name of a java procedure name. *) val java_get_class_type_name : java -> Name.t - - (** Return the simple class name of a java procedure name. *) + (** Return the class name as a typename of a java procedure name. *) val java_get_simple_class_name : java -> string - - (** Return the package name of a java procedure name. *) + (** Return the simple class name of a java procedure name. *) val java_get_package : java -> string option - - (** Return the method name of a java procedure name. *) + (** Return the package name of a java procedure name. *) val java_get_method : java -> string - - (** Return the return type of a java procedure name. *) + (** Return the method name of a java procedure name. *) val java_get_return_type : java -> string - - (** Return the parameters of a java procedure name. *) + (** Return the return type of a java procedure name. *) val java_get_parameters : java -> java_type list - - (** Return the parameters of a java procname as strings. *) + (** Return the parameters of a java procedure name. *) val java_get_parameters_as_strings : java -> string list + (** Return the parameters of a java procname as strings. *) + val java_is_access_method : t -> bool (** Check if the procedure name is an acess method (e.g. access$100 used to 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 - - (** Check if the procedure belongs to an anonymous inner class. *) + (** Check if the procedure name is of an auto-generated method containing '$'. *) val java_is_anonymous_inner_class : t -> bool - - (** Check if the procedure name is an anonymous inner class constructor. *) + (** Check if the procedure belongs to an anonymous inner class. *) val java_is_anonymous_inner_class_constructor : t -> bool - - (** Check if the method name is "close". *) + (** Check if the procedure name is an anonymous inner class constructor. *) val java_is_close : t -> bool - - (** Check if the java procedure is static. *) + (** Check if the method name is "close". *) 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. 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 - - (** Check if the proc name comes from generated code *) + (** Check if the proc name comes from a lambda expression *) 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. This is used in private constructors, where a proxy constructor is generated 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 - - (** Convert a java type to a string. *) + (** Replace the method name of an existing java procname. *) val java_type_to_string : java_type -> string - - (** Check if this is a class initializer. *) + (** Convert a java type to a string. *) val is_class_initializer : t -> bool - - (** Check if this is a special Infer undefined procedure. *) + (** Check if this is a class initializer. *) val is_infer_undefined : t -> bool + (** Check if this is a special Infer undefined procedure. *) + val get_global_name_of_initializer : t -> string option (** Return the name of the global for which this procedure is the initializer if this is an initializer, None otherwise. *) - val get_global_name_of_initializer : t -> string option - - (** Pretty print a proc name. *) - val pp : Format.formatter -> t -> unit - - (** Pretty print a set of proc names. *) + (** Pretty print a proc name. *) val pp_set : Format.formatter -> Set.t -> unit + (** Pretty print a set of proc names. *) + val replace_class : t -> Name.t -> t (** Replace the class name component of a procedure 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 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 - - (** Convert a proc name into a easy string for the user to see in an IDE. *) + (** Convert a proc name to a string for the user to see. *) val to_simplified_string : ?withclass:bool -> t -> string - - (** Convert a proc name into a unique identifier. *) + (** Convert a proc name into a easy string for the user to see in an IDE. *) val to_unique_id : t -> string - - (** Convert a proc name to a filename. *) + (** Convert a proc name into a unique identifier. *) val to_filename : t -> string - - (** get qualifiers of C/objc/C++ method/function *) + (** Convert a proc name to a filename. *) val get_qualifiers : t -> QualifiedCppName.t - - (** get qualifiers of a class owning objc/C++ method *) + (** get qualifiers of C/objc/C++ method/function *) 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 such substitution doesn't exist NOTE: this function doesn't check if such substitution is correct in terms of return type/function parameters. NOTE: this function doesn't deal with nested template classes, it only extracts mapping for function and/or direct parent (class that defines the method) if it exists. *) - - val get_template_args_mapping : t -> t -> type_subst_t option end -(** Return the return type of [pname_java]. *) - val java_proc_return_typ : Procname.java -> t +(** Return the return type of [pname_java]. *) module Fieldname : sig (** Names for fields of class/struct/union *) - type t [@@deriving compare] - (** Equality for field names. *) - val equal : t -> t -> bool + (** Equality for field names. *) (** Set for fieldnames *) @@ -606,58 +507,46 @@ module Fieldname : sig end module Java : sig - (** Create a java field name from string *) - val from_string : string -> t + (** Create a java field name from string *) end - (** Convert a field name to a string. *) - val to_string : t -> string + (** Convert a field name to a string. *) val to_full_string : t -> string 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 - - (** Convert a fieldname to a flat string without path. *) + (** Convert a fieldname to a simplified string with at most one-level path. *) val to_flat_string : t -> string - - (** Pretty print a field name. *) + (** Convert a fieldname to a flat string without path. *) val pp : Format.formatter -> t -> unit - - (** Pretty print a field name in latex. *) + (** Pretty print a field name. *) val pp_latex : Latex.style -> Format.formatter -> t -> unit - - (** The class part of the fieldname *) + (** Pretty print a field name in latex. *) val java_get_class : t -> string - - (** The last component of the fieldname *) + (** The class part of the fieldname *) val java_get_field : t -> string - - (** Check if the field is the synthetic this$n of a nested class, used to access the n-th outher instance. *) + (** The last component of the fieldname *) val java_is_outer_instance : t -> bool - - (** get qualified classname of a field if it's coming from clang frontend. returns None otherwise *) + (** Check if the field is the synthetic this$n of a nested class, used to access the n-th outher instance. *) val clang_get_qual_class : t -> QualifiedCppName.t option - - (** hidded fieldname constant *) + (** get qualified classname of a field if it's coming from clang frontend. returns None otherwise *) val hidden : t - (** hidded fieldname constant *) val is_hidden : t -> bool + (** hidded fieldname constant *) end module Struct : sig @@ -666,7 +555,6 @@ module Struct : sig type fields = field list (** Type for a structured value. *) - type t = private { fields: fields (** non-static fields *) ; statics: fields (** static fields *) @@ -676,33 +564,27 @@ module Struct : sig type lookup = Name.t -> t option - (** Pretty print a struct type. *) - val pp : Pp.env -> Name.t -> F.formatter -> t -> unit - - (** Construct a struct_typ, normalizing field types *) + (** Pretty print a struct type. *) val internal_mk_struct : ?default:t -> ?fields:fields -> ?statics:fields -> ?methods:Procname.t list -> ?supers:Name.t list -> ?annots:Annot.Item.t -> unit -> t - - (** the element typ of the final extensible array in the given typ, if any *) + (** Construct a struct_typ, normalizing field types *) 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 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 : lookup:lookup -> Fieldname.t -> typ -> (typ * Annot.Item.t) option - - (** Field used for objective-c reference counting *) + (** Return the type of the field [fn] and its annotation, None if [typ] has no field named [fn] *) 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 end diff --git a/infer/src/IR/Unop.ml b/infer/src/IR/Unop.ml index c5b5641d4..138296ce0 100644 --- a/infer/src/IR/Unop.ml +++ b/infer/src/IR/Unop.ml @@ -9,6 +9,7 @@ *) (** The Smallfoot Intermediate Language: Unary Operators *) + open! IStd module L = Logging module F = Format diff --git a/infer/src/IR/Unop.mli b/infer/src/IR/Unop.mli index 30d228fbb..dbdfa907d 100644 --- a/infer/src/IR/Unop.mli +++ b/infer/src/IR/Unop.mli @@ -9,12 +9,12 @@ *) (** The Smallfoot Intermediate Language: Unary Operators *) + open! IStd module L = Logging module F = Format (** Unary operations *) - type t = | Neg (** Unary minus *) | BNot (** Bitwise complement (~) *) @@ -23,6 +23,5 @@ type t = val equal : t -> t -> bool -(** String representation of a unary operator. *) - val str : t -> string +(** String representation of a unary operator. *) diff --git a/infer/src/Makefile b/infer/src/Makefile index 5a694edc0..bc5941747 100644 --- a/infer/src/Makefile +++ b/infer/src/Makefile @@ -24,7 +24,7 @@ ATDGEN_SUFFIXES = _t.ml _t.mli _j.ml _j.mli 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 # Notice that use-ocamlfind is used here to avoid a linker bug in ocamlbuild when using -tag thread diff --git a/infer/src/backend/PropUtil.ml b/infer/src/backend/PropUtil.ml index 19fe2f7f3..950ba9e4f 100644 --- a/infer/src/backend/PropUtil.ml +++ b/infer/src/backend/PropUtil.ml @@ -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 local_static e = match e with - | Exp.Lvar (* is a local static if it's a global and it has a static local name *) - pvar + | Exp.Lvar 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] | _ -> [] diff --git a/infer/src/backend/PropUtil.mli b/infer/src/backend/PropUtil.mli index 5106cfbee..64091937f 100644 --- a/infer/src/backend/PropUtil.mli +++ b/infer/src/backend/PropUtil.mli @@ -9,20 +9,16 @@ open! IStd -(** remove the return variable from the prop *) - val remove_ret : Tenv.t -> Procdesc.t -> Prop.normal Prop.t -> Prop.normal Prop.t - -(** remove locals and return variable from the prop *) +(** remove the return variable from the prop *) val remove_locals_ret : Tenv.t -> Procdesc.t -> Prop.normal Prop.t -> Prop.normal Prop.t - -(** 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. *) +(** remove locals and return variable from the prop *) val remove_locals_formals : Tenv.t -> Procdesc.t -> Prop.normal Prop.t -> Pvar.t list * Prop.normal Prop.t - -(** remove seed vars from a 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_seed_vars : Tenv.t -> 'a Prop.t -> Prop.normal Prop.t +(** remove seed vars from a prop *) diff --git a/infer/src/base/Multilinks.ml b/infer/src/base/Multilinks.ml index df532544c..362109a74 100644 --- a/infer/src/base/Multilinks.ml +++ b/infer/src/base/Multilinks.ml @@ -6,6 +6,7 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. *) + open! IStd open! PVariant module F = Format diff --git a/infer/src/base/Multilinks.mli b/infer/src/base/Multilinks.mli index b91fa1c6e..d0dab4200 100644 --- a/infer/src/base/Multilinks.mli +++ b/infer/src/base/Multilinks.mli @@ -12,35 +12,27 @@ module F = Format module L = Logging (** In-memory representation of multilink files. *) - type t -(** Add a link. *) - val add : t -> string -> unit - -(** Create a new multilink. *) +(** Add a link. *) val create : unit -> t +(** Create a new multilink. *) +val multilink_file_name : string (** Name of the multilink file. 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 +(** Read a multilink file from disk. *) +val resolve : DB.filename -> DB.filename (** Resolve a filename following multilinks. 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 - -(** Write a multilink file in the given directory *) +(** Reset the cache of multilink files *) val write : t -> dir:string -> unit +(** Write a multilink file in the given directory *) diff --git a/infer/src/clang/ClangCommand.ml b/infer/src/clang/ClangCommand.ml index c6c6043b6..bfe30a5cf 100644 --- a/infer/src/clang/ClangCommand.ml +++ b/infer/src/clang/ClangCommand.ml @@ -6,6 +6,7 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. *) + open! IStd module L = Logging @@ -73,8 +74,8 @@ let clang_cc1_cmd_sanitizer cmd = let mllvm_flags_blacklist = ["-profile-guided-section-prefix"] in let replace_option_arg option arg = if String.equal option "-arch" && String.equal arg "armv7k" then "armv7" - else if (* replace armv7k arch with armv7 *) - String.is_suffix arg ~suffix:"dep.tmp" then ( + (* replace armv7k arch with armv7 *) + 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 *) Unix.mkdir_p (Filename.dirname arg) ; arg ) diff --git a/infer/src/clang/ClangCommand.mli b/infer/src/clang/ClangCommand.mli index 65c3cefb2..97300f187 100644 --- a/infer/src/clang/ClangCommand.mli +++ b/infer/src/clang/ClangCommand.mli @@ -11,34 +11,28 @@ open! IStd 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 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 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 -### ...". *) -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 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 - -(** The value passed to an option in the arguments of a command. Must be called on normalized commands. *) +(** Whether the command has this flag set in its arguments. Must be called on normalized commands. *) val value_of_option : t -> string -> string option - -(** Whether the command is suitable for attaching the AST exporter. 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 can_attach_ast_exporter : t -> bool - -(** Add the arguments needed to attach the facebook-clang-plugins plugin. Must be called on normalized commands. *) +(** Whether the command is suitable for attaching the AST exporter. Must be called on normalized commands. *) 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 @@ -48,6 +42,5 @@ val append_args : string list -> t -> t val get_orig_argv : t -> string array -(** update the executable to be run *) - val with_exec : string -> t -> t +(** update the executable to be run *) diff --git a/infer/src/integration/ClangQuotes.ml b/infer/src/integration/ClangQuotes.ml index 41fac518f..4bfcfdd26 100644 --- a/infer/src/integration/ClangQuotes.ml +++ b/infer/src/integration/ClangQuotes.ml @@ -6,7 +6,9 @@ * 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. *) -(* 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 module L = Logging diff --git a/infer/src/integration/ClangQuotes.mli b/infer/src/integration/ClangQuotes.mli index 54a204942..14dc22c8d 100644 --- a/infer/src/integration/ClangQuotes.mli +++ b/infer/src/integration/ClangQuotes.mli @@ -7,12 +7,11 @@ * 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 *) - type style = | EscapedDoubleQuotes (** the arguments should be enclosed in "double quotes" and are already escaped *)