[ocamlformat] Upgrade ocamlformat version

Reviewed By: jvillard

Differential Revision: D18162727

fbshipit-source-id: ffb9f7541
master
Josh Berdine 5 years ago committed by Facebook Github Bot
parent 9e5307b339
commit 8d20e4d64d

@ -221,7 +221,7 @@ DUNE_ML:=$(shell find * -name 'dune*.in' | grep -v workspace)
fmt_dune: fmt_dune:
parallel $(OCAMLFORMAT_EXE) -i ::: $(DUNE_ML) parallel $(OCAMLFORMAT_EXE) -i ::: $(DUNE_ML)
SRC_ML:=$(shell find * \( -name _build -or -name facebook-clang-plugins -or -path facebook/dependencies -or -path sledge/llvm \) -not -prune -or -type f -and -name '*'.ml -or -name '*'.mli 2>/dev/null) SRC_ML:=$(shell find * \( -name _build -or -name facebook-clang-plugins -or -path facebook/dependencies -or -path sledge/llvm -or -path sledge/.llvm_build \) -not -prune -or -type f -and -name '*'.ml -or -name '*'.mli 2>/dev/null)
.PHONY: fmt_all .PHONY: fmt_all
fmt_all: fmt_all:

@ -1,4 +1,5 @@
profile = ocamlformat profile = ocamlformat
break-before-in = fit-or-vertical
let-binding-spacing = sparse let-binding-spacing = sparse
margin = 100 margin = 100
version = 0.9 version = 0.12-20-gfce0d2e

@ -7,8 +7,8 @@
*) *)
(** The Smallfoot Intermediate Language: Annotations *) (** The Smallfoot Intermediate Language: Annotations *)
open! IStd
open! IStd
module F = Format module F = Format
type parameter = {name: string option; value: string} [@@deriving compare] type parameter = {name: string option; value: string} [@@deriving compare]
@ -81,9 +81,7 @@ module Method = struct
type t = {return: Item.t; params: Item.t list} type t = {return: Item.t; params: Item.t list}
(** Pretty print a method annotation. *) (** Pretty print a method annotation. *)
let pp s fmt {return; params} = let pp s fmt {return; params} = F.fprintf fmt "%a %s(%a)" Item.pp return s (Pp.seq Item.pp) params
F.fprintf fmt "%a %s(%a)" Item.pp return s (Pp.seq Item.pp) params
(** Empty method annotation. *) (** Empty method annotation. *)
let empty = {return= []; params= []} let empty = {return= []; params= []}

@ -7,8 +7,8 @@
*) *)
(** The Smallfoot Intermediate Language: Annotations *) (** The Smallfoot Intermediate Language: Annotations *)
open! IStd
open! IStd
module F = Format module F = Format
type parameter = {name: string option; value: string} type parameter = {name: string option; value: string}

@ -57,8 +57,7 @@ let should_try_to_update pname_blob akind =
|> SqliteUtils.check_result_code db ~log:"replace bind pname" ; |> SqliteUtils.check_result_code db ~log:"replace bind pname" ;
Sqlite3.bind find_stmt 2 (* :akind *) (Sqlite3.Data.INT (int64_of_attributes_kind akind)) Sqlite3.bind find_stmt 2 (* :akind *) (Sqlite3.Data.INT (int64_of_attributes_kind akind))
|> SqliteUtils.check_result_code db ~log:"replace bind attribute kind" ; |> SqliteUtils.check_result_code db ~log:"replace bind attribute kind" ;
SqliteUtils.result_single_column_option ~finalize:false ~log:"Attributes.replace" db SqliteUtils.result_single_column_option ~finalize:false ~log:"Attributes.replace" db find_stmt
find_stmt
|> (* there is no entry with a strictly larger "definedness" for that proc name *) |> (* there is no entry with a strictly larger "definedness" for that proc name *)
Option.is_none ) Option.is_none )

@ -7,6 +7,7 @@
*) *)
(** The Smallfoot Intermediate Language: Binary Operators *) (** The Smallfoot Intermediate Language: Binary Operators *)
open! IStd open! IStd
type ikind_option_for_binop = Typ.ikind option type ikind_option_for_binop = Typ.ikind option

@ -7,6 +7,7 @@
*) *)
(** The Smallfoot Intermediate Language: Binary Operators *) (** The Smallfoot Intermediate Language: Binary Operators *)
open! IStd open! IStd
(** Binary operations *) (** Binary operations *)

@ -68,7 +68,7 @@ let rec pp fmt = function
F.fprintf fmt "*%a" pp de F.fprintf fmt "*%a" pp de
| Dfcall (fun_dexp, args, _, {cf_virtual= isvirtual}) -> | Dfcall (fun_dexp, args, _, {cf_virtual= isvirtual}) ->
let pp_args fmt des = let pp_args fmt des =
if eradicate_java () then ( if des <> [] then F.pp_print_string fmt "..." ) if eradicate_java () then (if des <> [] then F.pp_print_string fmt "...")
else Pp.comma_seq pp fmt des else Pp.comma_seq pp fmt des
in in
let pp_fun fmt = function let pp_fun fmt = function
@ -148,8 +148,7 @@ let pp_vpath pe fmt vpath =
let rec has_tmp_var = function let rec has_tmp_var = function
| Dpvar pvar | Dpvaraddr pvar -> | Dpvar pvar | Dpvaraddr pvar ->
Pvar.is_frontend_tmp pvar || Pvar.is_clang_tmp pvar Pvar.is_frontend_tmp pvar || Pvar.is_clang_tmp pvar
| Dderef dexp | Ddot (dexp, _) | Darrow (dexp, _) | Dunop (_, dexp) | Dsizeof (_, Some dexp, _) | Dderef dexp | Ddot (dexp, _) | Darrow (dexp, _) | Dunop (_, dexp) | Dsizeof (_, Some dexp, _) ->
->
has_tmp_var dexp has_tmp_var dexp
| Darray (dexp1, dexp2) | Dbinop (_, dexp1, dexp2) -> | Darray (dexp1, dexp2) | Dbinop (_, dexp1, dexp2) ->
has_tmp_var dexp1 || has_tmp_var dexp2 has_tmp_var dexp1 || has_tmp_var dexp2

@ -29,11 +29,7 @@ let pp_loc_trace fmt l = PrettyPrintable.pp_collection ~pp_item:pp_loc_trace_ele
let contains_exception loc_trace_elem = let contains_exception loc_trace_elem =
let pred nt = let pred nt =
match nt with match nt with Exception _ -> true | Condition _ | Procedure_start _ | Procedure_end _ -> false
| Exception _ ->
true
| Condition _ | Procedure_start _ | Procedure_end _ ->
false
in in
List.exists ~f:pred loc_trace_elem.lt_node_tags List.exists ~f:pred loc_trace_elem.lt_node_tags

@ -47,14 +47,14 @@ and t =
val equal : t -> t -> bool val equal : t -> t -> bool
(** Equality for expressions. *) (** Equality for expressions. *)
(** Set of expressions. *)
module Set : Caml.Set.S with type elt = t module Set : Caml.Set.S with type elt = t
(** Set of expressions. *)
(** Map with expression keys. *)
module Map : Caml.Map.S with type key = t module Map : Caml.Map.S with type key = t
(** Map with expression keys. *)
(** Hashtable with expression keys. *)
module Hash : Caml.Hashtbl.S with type key = t module Hash : Caml.Hashtbl.S with type key = t
(** Hashtable with expression keys. *)
val is_null_literal : t -> bool val is_null_literal : t -> bool

@ -27,8 +27,8 @@ type t =
let pp fmt = function let pp fmt = function
| Assign (access_expr, exp, loc) -> | Assign (access_expr, exp, loc) ->
F.fprintf fmt "%a := %a [%a]" HilExp.AccessExpression.pp access_expr HilExp.pp exp F.fprintf fmt "%a := %a [%a]" HilExp.AccessExpression.pp access_expr HilExp.pp exp Location.pp
Location.pp loc loc
| Assume (exp, _, _, loc) -> | Assume (exp, _, _, loc) ->
F.fprintf fmt "assume %a [%a]" HilExp.pp exp Location.pp loc F.fprintf fmt "assume %a [%a]" HilExp.pp exp Location.pp loc
| Call (ret, call, actuals, _, loc) -> | Call (ret, call, actuals, _, loc) ->
@ -60,8 +60,8 @@ let of_sil ~include_array_indexes ~f_resolve_id (instr : Sil.instr) =
match instr with match instr with
| Load {id= lhs_id; e= rhs_exp; typ= rhs_typ; loc} -> | Load {id= lhs_id; e= rhs_exp; typ= rhs_typ; loc} ->
analyze_id_assignment ~add_deref:true (Var.of_id lhs_id) rhs_exp rhs_typ loc analyze_id_assignment ~add_deref:true (Var.of_id lhs_id) rhs_exp rhs_typ loc
| Store {e1= Lvar lhs_pvar; typ= lhs_typ; e2= rhs_exp; loc} | Store {e1= Lvar lhs_pvar; typ= lhs_typ; e2= rhs_exp; loc} when Pvar.is_ssa_frontend_tmp lhs_pvar
when Pvar.is_ssa_frontend_tmp lhs_pvar -> ->
(* do not need to add deref here as it is added implicitly in of_pvar by forgetting the & *) (* do not need to add deref here as it is added implicitly in of_pvar by forgetting the & *)
analyze_id_assignment (Var.of_pvar lhs_pvar) rhs_exp lhs_typ loc analyze_id_assignment (Var.of_pvar lhs_pvar) rhs_exp lhs_typ loc
| Call | Call

@ -217,9 +217,7 @@ let update_name_generator ids =
(** Generate a normal identifier whose name encodes a path given as a string. *) (** Generate a normal identifier whose name encodes a path given as a string. *)
let create_path pathstring = let create_path pathstring = create_normal (string_to_name ("%path%" ^ pathstring)) path_ident_stamp
create_normal (string_to_name ("%path%" ^ pathstring)) path_ident_stamp
(** {2 Pretty Printing} *) (** {2 Pretty Printing} *)

@ -28,14 +28,14 @@ type kind [@@deriving compare]
val equal_kind : kind -> kind -> bool val equal_kind : kind -> kind -> bool
(** Equality for kind. *) (** Equality for kind. *)
(** Set for identifiers. *)
module Set : Caml.Set.S with type elt = t module Set : Caml.Set.S with type elt = t
(** Set for identifiers. *)
(** Hash table with ident as key. *)
module Hash : Caml.Hashtbl.S with type key = t module Hash : Caml.Hashtbl.S with type key = t
(** Hash table with ident as key. *)
(** Map with ident as key. *)
module Map : Caml.Map.S with type key = t module Map : Caml.Map.S with type key = t
(** Map with ident as key. *)
module HashQueue : Hash_queue.S with type Key.t = t module HashQueue : Hash_queue.S with type Key.t = t

@ -328,8 +328,8 @@ let desc_unsafe_guarded_by_access accessed_fld guarded_by_str loc =
Format.asprintf Format.asprintf
"The field %a is annotated with %a, but the lock %a is not held during the access to the \ "The field %a is annotated with %a, but the lock %a is not held during the access to the \
field %s. Since the current method is non-private, it can be called from outside the \ field %s. Since the current method is non-private, it can be called from outside the \
current class without synchronization. Consider wrapping the access in a %s block or \ current class without synchronization. Consider wrapping the access in a %s block or making \
making the method private." the method private."
MF.pp_monospaced accessed_fld_str MF.pp_monospaced annot_str MF.pp_monospaced guarded_by_str MF.pp_monospaced accessed_fld_str MF.pp_monospaced annot_str MF.pp_monospaced guarded_by_str
line_info syncronized_str line_info syncronized_str
in in
@ -469,8 +469,7 @@ let desc_allocation_mismatch alloc dealloc =
let using (primitive_pname, called_pname, loc) = let using (primitive_pname, called_pname, loc) =
let by_call = let by_call =
if Typ.Procname.equal primitive_pname called_pname then "" if Typ.Procname.equal primitive_pname called_pname then ""
else else " by call to " ^ MF.monospaced_to_string (Typ.Procname.to_simplified_string called_pname)
" by call to " ^ MF.monospaced_to_string (Typ.Procname.to_simplified_string called_pname)
in in
"using " "using "
^ MF.monospaced_to_string (Typ.Procname.to_simplified_string primitive_pname) ^ MF.monospaced_to_string (Typ.Procname.to_simplified_string primitive_pname)
@ -658,8 +657,7 @@ let desc_retain_cycle cycle_str loc cycle_dotty =
Logging.d_strln "Proposition with retain cycle:" ; Logging.d_strln "Proposition with retain cycle:" ;
let tags = Tags.create () in let tags = Tags.create () in
let desc = let desc =
Format.sprintf "Retain cycle %s involving the following objects:%s" (at_line tags loc) Format.sprintf "Retain cycle %s involving the following objects:%s" (at_line tags loc) cycle_str
cycle_str
in in
{descriptions= [desc]; tags= !tags; dotty= cycle_dotty} {descriptions= [desc]; tags= !tags; dotty= cycle_dotty}

@ -42,8 +42,8 @@ val is_self : t -> bool
val rename : f:(string -> string) -> t -> t val rename : f:(string -> string) -> t -> t
(** Maps over both the plain and the mangled components. *) (** Maps over both the plain and the mangled components. *)
(** Set of Mangled. *)
module Set : Caml.Set.S with type elt = t module Set : Caml.Set.S with type elt = t
(** Set of Mangled. *)
(** Map with Mangled as key *)
module Map : Caml.Map.S with type key = t module Map : Caml.Map.S with type key = t
(** Map with Mangled as key *)

@ -167,11 +167,7 @@ module Core_foundation_model = struct
type core_lib = Core_foundation | Core_graphics type core_lib = Core_foundation | Core_graphics
let core_lib_to_type_list lib = let core_lib_to_type_list lib =
match lib with match lib with Core_foundation -> core_foundation_types | Core_graphics -> core_graphics_types
| Core_foundation ->
core_foundation_types
| Core_graphics ->
core_graphics_types
let rec is_core_lib lib typ = let rec is_core_lib lib typ =

@ -17,9 +17,7 @@ module NodeKey = struct
let to_string = Caml.Digest.to_hex let to_string = Caml.Digest.to_hex
let compute node ~simple_key ~succs ~preds = let compute node ~simple_key ~succs ~preds =
let v = let v = (simple_key node, List.rev_map ~f:simple_key succs, List.rev_map ~f:simple_key preds) in
(simple_key node, List.rev_map ~f:simple_key succs, List.rev_map ~f:simple_key preds)
in
Utils.better_hash v Utils.better_hash v
@ -351,11 +349,7 @@ module Node = struct
let pp_instrs ~highlight pe0 f node = let pp_instrs ~highlight pe0 f node =
let pe = let pe =
match highlight with match highlight with None -> pe0 | Some instr -> Pp.extend_colormap pe0 (Obj.repr instr) Red
| None ->
pe0
| Some instr ->
Pp.extend_colormap pe0 (Obj.repr instr) Red
in in
Instrs.pp pe f (get_instrs node) Instrs.pp pe f (get_instrs node)
@ -428,17 +422,17 @@ end
(* =============== END of module Node =============== *) (* =============== END of module Node =============== *)
(** Map over nodes *)
module NodeMap = Caml.Map.Make (Node) module NodeMap = Caml.Map.Make (Node)
(** Map over nodes *)
(** Hash table with nodes as keys. *)
module NodeHash = Hashtbl.Make (Node) module NodeHash = Hashtbl.Make (Node)
(** Hash table with nodes as keys. *)
(** Set of nodes. *)
module NodeSet = Node.NodeSet module NodeSet = Node.NodeSet
(** Set of nodes. *)
(** Map with node id keys. *)
module IdMap = Node.IdMap module IdMap = Node.IdMap
(** Map with node id keys. *)
(** procedure description *) (** procedure description *)
type t = type t =
@ -594,9 +588,7 @@ let set_exit_node pdesc node = pdesc.exit_node <- node
let set_start_node pdesc node = pdesc.start_node <- node let set_start_node pdesc node = pdesc.start_node <- node
(** Append the locals to the list of local variables *) (** Append the locals to the list of local variables *)
let append_locals pdesc new_locals = let append_locals pdesc new_locals = pdesc.attributes.locals <- pdesc.attributes.locals @ new_locals
pdesc.attributes.locals <- pdesc.attributes.locals @ new_locals
let set_succs_exn_only (node : Node.t) exn = node.exn <- exn let set_succs_exn_only (node : Node.t) exn = node.exn <- exn

@ -178,17 +178,17 @@ module Node : sig
val compute_key : t -> NodeKey.t val compute_key : t -> NodeKey.t
end end
(** Map with node id keys. *)
module IdMap : PrettyPrintable.PPMap with type key = Node.id module IdMap : PrettyPrintable.PPMap with type key = Node.id
(** Map with node id keys. *)
(** Hash table with nodes as keys. *)
module NodeHash : Caml.Hashtbl.S with type key = Node.t module NodeHash : Caml.Hashtbl.S with type key = Node.t
(** Hash table with nodes as keys. *)
(** Map over nodes. *)
module NodeMap : Caml.Map.S with type key = Node.t module NodeMap : Caml.Map.S with type key = Node.t
(** Map over nodes. *)
(** Set of nodes. *)
module NodeSet : Caml.Set.S with type elt = Node.t module NodeSet : Caml.Set.S with type elt = Node.t
(** Set of nodes. *)
(** procedure descriptions *) (** procedure descriptions *)
@ -316,8 +316,8 @@ val has_modify_in_block_attr : t -> Pvar.t -> bool
val is_connected : t -> (unit, [`Join | `Other]) Result.t val is_connected : t -> (unit, [`Join | `Other]) Result.t
(** checks whether a cfg for the given procdesc is connected or not *) (** checks whether a cfg for the given procdesc is connected or not *)
module SQLite : SqliteUtils.Data with type t = t option
(** per-procedure CFGs are stored in the SQLite "procedures" table as NULL if the procedure has no (** per-procedure CFGs are stored in the SQLite "procedures" table as NULL if the procedure has no
CFG *) CFG *)
module SQLite : SqliteUtils.Data with type t = t option
val load : Typ.Procname.t -> t option val load : Typ.Procname.t -> t option

@ -106,7 +106,7 @@ type ( 'context
type ('context, 'f_in, 'f_out, 'captured_types, 'emptyness) path_extra = type ('context, 'f_in, 'f_out, 'captured_types, 'emptyness) path_extra =
| PathEmpty : ('context, 'f, 'f, unit, empty) path_extra | PathEmpty : ('context, 'f, 'f, unit, empty) path_extra
| PathNonEmpty : | PathNonEmpty :
{ on_objc_cpp: 'context -> 'f_in -> objc_cpp -> ('f_out * 'captured_types capt) option } {on_objc_cpp: 'context -> 'f_in -> objc_cpp -> ('f_out * 'captured_types capt) option}
-> ('context, 'f_in, 'f_out, 'captured_types, non_empty) path_extra -> ('context, 'f_in, 'f_out, 'captured_types, non_empty) path_extra
type ('context, 'f_in, 'f_out, 'captured_types, 'markers_in, 'markers_out, 'emptyness) path_matcher = type ('context, 'f_in, 'f_out, 'captured_types, 'markers_in, 'markers_out, 'emptyness) path_matcher =
@ -272,14 +272,8 @@ let templ_cons :
let templ_end : let templ_end :
('context, 'f_in, 'f_out, 'captured_types, 'markers_in, 'markers_out, _) templ_matcher ('context, 'f_in, 'f_out, 'captured_types, 'markers_in, 'markers_out, _) templ_matcher
-> ( 'context -> ('context, 'f_in, 'f_out, 'captured_types, 'markers_in, 'markers_out, non_empty) path_matcher
, 'f_in =
, 'f_out
, 'captured_types
, 'markers_in
, 'markers_out
, non_empty )
path_matcher =
let match_empty_templ_args (f, captured_types, template_args) = let match_empty_templ_args (f, captured_types, template_args) =
match template_args with [] -> Some (f, captured_types) | _ -> None match template_args with [] -> Some (f, captured_types) | _ -> None
in in
@ -544,8 +538,7 @@ module Call = struct
| Exp.Var v -> | Exp.Var v ->
v v
| e -> | e ->
Logging.(die InternalError) Logging.(die InternalError) "Expected Lvar, got %a:%a" Exp.pp e (Typ.pp Pp.text) (typ arg)
"Expected Lvar, got %a:%a" Exp.pp e (Typ.pp Pp.text) (typ arg)
end end
type ('context, 'f_in, 'f_out, 'captured_types) proc_matcher = type ('context, 'f_in, 'f_out, 'captured_types) proc_matcher =
@ -767,16 +760,15 @@ module Call = struct
(** Matches third captured type *) (** Matches third captured type *)
let match_typ3 : let match_typ3 :
'marker -> ('context, _ * (_ * ('marker mtyp * _)), _ * (_ * ('marker * _))) one_arg_matcher 'marker -> ('context, _ * (_ * ('marker mtyp * _)), _ * (_ * ('marker * _))) one_arg_matcher =
=
let pos3 (_, (_, (x, _))) = x in let pos3 (_, (_, (x, _))) = x in
fun marker -> mk_match_typ_nth pos3 pos3 marker fun marker -> mk_match_typ_nth pos3 pos3 marker
(** Matches the type matched by the given path_matcher *) (** Matches the type matched by the given path_matcher *)
let match_typ : let match_typ :
('context, _, _, unit, unit, unit, non_empty) path_matcher ('context, _, _, unit, unit, unit, non_empty) path_matcher -> ('context, _, _) one_arg_matcher
-> ('context, _, _) one_arg_matcher = =
fun m -> fun m ->
let ({on_templated_name} : (_, _, _, unit, unit, unit, non_empty) path_matcher) = m in let ({on_templated_name} : (_, _, _, unit, unit, unit, non_empty) path_matcher) = m in
let rec match_typ context typ = let rec match_typ context typ =

@ -9,7 +9,8 @@ open! IStd
(** To be used in 'list_constraint *) (** To be used in 'list_constraint *)
type accept_more type accept_more
and end_of_list
and end_of_list
(* Markers are a fool-proofing mechanism to avoid mistaking captured types. (* Markers are a fool-proofing mechanism to avoid mistaking captured types.
Template argument types can be captured with [capt_typ] to be referenced later Template argument types can be captured with [capt_typ] to be referenced later
@ -226,7 +227,8 @@ module Call : sig
include include
Common Common
with type ('context, 'f) dispatcher = 'context -> Typ.Procname.t -> FuncArg.t list -> 'f option with type ('context, 'f) dispatcher =
'context -> Typ.Procname.t -> FuncArg.t list -> 'f option
val merge_dispatchers : val merge_dispatchers :
('context, 'f) dispatcher -> ('context, 'f) dispatcher -> ('context, 'f) dispatcher ('context, 'f) dispatcher -> ('context, 'f) dispatcher -> ('context, 'f) dispatcher

@ -38,8 +38,7 @@ type t = {pv_hash: int; pv_name: Mangled.t; pv_kind: pvar_kind} [@@deriving comp
let get_name_of_local_with_procname var = let get_name_of_local_with_procname var =
match var.pv_kind with match var.pv_kind with
| Local_var pname -> | Local_var pname ->
Mangled.from_string Mangled.from_string (F.asprintf "%s_%a" (Mangled.to_string var.pv_name) Typ.Procname.pp pname)
(F.asprintf "%s_%a" (Mangled.to_string var.pv_name) Typ.Procname.pp pname)
| _ -> | _ ->
var.pv_name var.pv_name
@ -124,9 +123,7 @@ let materialized_cpp_temporary = "SIL_materialize_temp__"
let is_frontend_tmp pvar = let is_frontend_tmp pvar =
(* Check whether the program variable is a temporary one generated by Sawja, javac, or some other (* Check whether the program variable is a temporary one generated by Sawja, javac, or some other
bytecode/name generation pass. valid java identifiers cannot contain `$` *) bytecode/name generation pass. valid java identifiers cannot contain `$` *)
let is_bytecode_tmp name = let is_bytecode_tmp name = String.contains name '$' || String.is_prefix ~prefix:"CatchVar" name in
String.contains name '$' || String.is_prefix ~prefix:"CatchVar" name
in
(* Check whether the program variable is generated by [mk_tmp] *) (* Check whether the program variable is generated by [mk_tmp] *)
let is_sil_tmp name = String.is_prefix ~prefix:tmp_prefix name in let is_sil_tmp name = String.is_prefix ~prefix:tmp_prefix name in
let name = to_string pvar in let name = to_string pvar in

@ -218,12 +218,7 @@ let compare_hpara_dll = compare_hpara_dll0 (fun _ _ -> 0)
let equal_hpara_dll = [%compare.equal: hpara_dll] let equal_hpara_dll = [%compare.equal: hpara_dll]
(** {2 Comparision and Inspection Functions} *) (** {2 Comparision and Inspection Functions} *)
let is_objc_object = function let is_objc_object = function Hpointsto (_, _, Sizeof {typ}) -> Typ.is_objc_class typ | _ -> false
| Hpointsto (_, _, Sizeof {typ}) ->
Typ.is_objc_class typ
| _ ->
false
(** Check if a pvar is a local static in objc *) (** Check if a pvar is a local static in objc *)
let is_static_local_name pname pvar = let is_static_local_name pname pvar =
@ -301,8 +296,7 @@ let pp_texp pe f = function
| Exp.Sizeof {typ; nbytes; dynamic_length; subtype} -> | Exp.Sizeof {typ; nbytes; dynamic_length; subtype} ->
let pp_len f l = Option.iter ~f:(F.fprintf f "[%a]" (pp_exp_printenv pe)) l in let pp_len f l = Option.iter ~f:(F.fprintf f "[%a]" (pp_exp_printenv pe)) l in
let pp_size f size = Option.iter ~f:(Int.pp f) size in let pp_size f size = Option.iter ~f:(Int.pp f) size in
F.fprintf f "%a%a%a%a" (Typ.pp pe) typ pp_size nbytes pp_len dynamic_length Subtype.pp F.fprintf f "%a%a%a%a" (Typ.pp pe) typ pp_size nbytes pp_len dynamic_length Subtype.pp subtype
subtype
| e -> | e ->
pp_exp_printenv pe f e pp_exp_printenv pe f e
@ -827,9 +821,7 @@ let rec pp_sexp_env pe0 envo f se =
| Eexp (e, inst) -> | Eexp (e, inst) ->
F.fprintf f "%a%a" (pp_exp_printenv pe) e (pp_inst_if_trace pe) inst F.fprintf f "%a%a" (pp_exp_printenv pe) e (pp_inst_if_trace pe) inst
| Estruct (fel, inst) -> | Estruct (fel, inst) ->
let pp_diff f (n, se) = let pp_diff f (n, se) = F.fprintf f "%a:%a" Typ.Fieldname.pp n (pp_sexp_env pe envo) se in
F.fprintf f "%a:%a" Typ.Fieldname.pp n (pp_sexp_env pe envo) se
in
F.fprintf f "{%a}%a" (pp_seq_diff pp_diff pe) fel (pp_inst_if_trace pe) inst F.fprintf f "{%a}%a" (pp_seq_diff pp_diff pe) fel (pp_inst_if_trace pe) inst
| Earray (len, nel, inst) -> | Earray (len, nel, inst) ->
let pp_diff f (i, se) = let pp_diff f (i, se) =
@ -1268,8 +1260,7 @@ let rec exp_sub_ids (f : subst_fun) exp =
let apply_sub subst : subst_fun = let apply_sub subst : subst_fun =
fun id -> fun id -> match List.Assoc.find subst ~equal:Ident.equal id with Some x -> x | None -> Exp.Var id
match List.Assoc.find subst ~equal:Ident.equal id with Some x -> x | None -> Exp.Var id
let exp_sub (subst : subst) e = exp_sub_ids (apply_sub subst) e let exp_sub (subst : subst) e = exp_sub_ids (apply_sub subst) e
@ -1305,8 +1296,7 @@ let instr_sub_ids ~sub_id_binders f instr =
if phys_equal actual' actual then actual_pair else (actual', typ) ) if phys_equal actual' actual then actual_pair else (actual', typ) )
actuals actuals
in in
if if phys_equal ret_id' ret_id_typ && phys_equal fun_exp' fun_exp && phys_equal actuals' actuals
phys_equal ret_id' ret_id_typ && phys_equal fun_exp' fun_exp && phys_equal actuals' actuals
then instr then instr
else Call (ret_id', fun_exp', actuals', call_flags, loc) else Call (ret_id', fun_exp', actuals', call_flags, loc)
| Prune (exp, loc, true_branch, if_kind) -> | Prune (exp, loc, true_branch, if_kind) ->
@ -1464,14 +1454,8 @@ let hpred_compact sh hpred =
let exp_get_offsets exp = let exp_get_offsets exp =
let rec f offlist_past e = let rec f offlist_past e =
match (e : Exp.t) with match (e : Exp.t) with
| Var _ | Var _ | Const _ | UnOp _ | BinOp _ | Exn _ | Closure _ | Lvar _ | Sizeof {dynamic_length= None}
| Const _ ->
| UnOp _
| BinOp _
| Exn _
| Closure _
| Lvar _
| Sizeof {dynamic_length= None} ->
offlist_past offlist_past
| Sizeof {dynamic_length= Some l} -> | Sizeof {dynamic_length= Some l} ->
f offlist_past l f offlist_past l

@ -7,8 +7,8 @@
*) *)
(** The Smallfoot Intermediate Language *) (** The Smallfoot Intermediate Language *)
open! IStd
open! IStd
module F = Format module F = Format
(** {2 Programs and Types} *) (** {2 Programs and Types} *)
@ -239,8 +239,8 @@ val equal_hpred : ?inst:bool -> hpred -> hpred -> bool
The inst:: parameter specifies whether instumentations should also The inst:: parameter specifies whether instumentations should also
be considered (false by default). *) be considered (false by default). *)
(** Sets of heap predicates *)
module HpredSet : Caml.Set.S with type elt = hpred module HpredSet : Caml.Set.S with type elt = hpred
(** Sets of heap predicates *)
(** {2 Compaction} *) (** {2 Compaction} *)

@ -109,9 +109,7 @@ let is_captured source =
|> Option.is_some ) |> Option.is_some )
let is_non_empty_statement = let is_non_empty_statement = ResultsDatabase.register_statement "SELECT 1 FROM source_files LIMIT 1"
ResultsDatabase.register_statement "SELECT 1 FROM source_files LIMIT 1"
let is_empty () = let is_empty () =
ResultsDatabase.with_registered_statement is_non_empty_statement ~f:(fun db stmt -> ResultsDatabase.with_registered_statement is_non_empty_statement ~f:(fun db stmt ->
@ -134,8 +132,8 @@ let is_freshly_captured source =
SourceFile.SQLite.serialize source SourceFile.SQLite.serialize source
|> Sqlite3.bind load_stmt 1 |> Sqlite3.bind load_stmt 1
|> SqliteUtils.check_result_code db ~log:"load bind source file" ; |> SqliteUtils.check_result_code db ~log:"load bind source file" ;
SqliteUtils.result_single_column_option ~finalize:false SqliteUtils.result_single_column_option ~finalize:false ~log:"SourceFiles.is_freshly_captured"
~log:"SourceFiles.is_freshly_captured" db load_stmt db load_stmt
|> Option.value_map ~default:false ~f:deserialize_freshly_captured ) |> Option.value_map ~default:false ~f:deserialize_freshly_captured )

@ -261,9 +261,7 @@ let with_block_args_instrs resolved_pdesc substitutions =
in in
let call_instr = let call_instr =
let id_exps = List.map ~f:(fun (id, _, typ) -> (id, typ)) id_exp_typs in let id_exps = List.map ~f:(fun (id, _, typ) -> (id, typ)) id_exp_typs in
let converted_args = let converted_args = List.map ~f:(fun (exp, typ) -> (convert_exp exp, typ)) origin_args in
List.map ~f:(fun (exp, typ) -> (convert_exp exp, typ)) origin_args
in
Sil.Call Sil.Call
( return_ids ( return_ids
, Exp.Const (Const.Cfun block_name) , Exp.Const (Const.Cfun block_name)
@ -341,8 +339,8 @@ let with_block_args callee_pdesc pname_with_block_args block_args =
source_file source_file
| None -> | None ->
Logging.die InternalError Logging.die InternalError
"specialize_with_block_args ahould only be called with defined procedures, but we \ "specialize_with_block_args ahould only be called with defined procedures, but we cannot \
cannot find the captured file of procname %a" find the captured file of procname %a"
Typ.Procname.pp pname Typ.Procname.pp pname
in in
let resolved_attributes = let resolved_attributes =

@ -9,8 +9,8 @@ module L = Logging
(** Module for Type Environments. *) (** Module for Type Environments. *)
(** Hash tables on type names. *)
module TypenameHash = Caml.Hashtbl.Make (Typ.Name) module TypenameHash = Caml.Hashtbl.Make (Typ.Name)
(** Hash tables on type names. *)
module TypenameHashNormalizer = MaximumSharing.ForHashtbl (TypenameHash) module TypenameHashNormalizer = MaximumSharing.ForHashtbl (TypenameHash)

@ -129,10 +129,7 @@ let range_of_ikind =
let ikind_is_char = function IChar | ISChar | IUChar -> true | _ -> false let ikind_is_char = function IChar | ISChar | IUChar -> true | _ -> false
(** Kinds of floating-point numbers *) (** Kinds of floating-point numbers *)
type fkind = type fkind = FFloat (** [float] *) | FDouble (** [double] *) | FLongDouble (** [long double] *)
| FFloat (** [float] *)
| FDouble (** [double] *)
| FLongDouble (** [long double] *)
[@@deriving compare] [@@deriving compare]
let equal_fkind = [%compare.equal: fkind] let equal_fkind = [%compare.equal: fkind]
@ -1423,8 +1420,7 @@ module Procname = struct
end end
module Fieldname = struct module Fieldname = struct
type t = Clang of {class_name: Name.t; field_name: string} | Java of string type t = Clang of {class_name: Name.t; field_name: string} | Java of string [@@deriving compare]
[@@deriving compare]
let equal = [%compare.equal: t] let equal = [%compare.equal: t]

@ -55,10 +55,7 @@ val ikind_is_unsigned : ikind -> bool
(** Check whether the integer kind is unsigned *) (** Check whether the integer kind is unsigned *)
(** Kinds of floating-point numbers *) (** Kinds of floating-point numbers *)
type fkind = type fkind = FFloat (** [float] *) | FDouble (** [double] *) | FLongDouble (** [long double] *)
| FFloat (** [float] *)
| FDouble (** [double] *)
| FLongDouble (** [long double] *)
[@@deriving compare] [@@deriving compare]
(** kind of pointer *) (** kind of pointer *)
@ -448,8 +445,7 @@ being the name of the struct, [None] means the parameter is of some other type.
; template_args: template_spec_info } ; template_args: template_spec_info }
[@@deriving compare] [@@deriving compare]
val make : val make : Name.t -> string -> kind -> template_spec_info -> Parameter.clang_parameter list -> t
Name.t -> string -> kind -> template_spec_info -> Parameter.clang_parameter list -> t
(** Create an objc procedure name from a class_name and method_name. *) (** Create an objc procedure name from a class_name and method_name. *)
val get_class_name : t -> string val get_class_name : t -> string
@ -540,14 +536,14 @@ being the name of the struct, [None] means the parameter is of some other type.
val is_objc_method : t -> bool val is_objc_method : t -> bool
(** Hash tables with proc names as keys. *)
module Hash : Caml.Hashtbl.S with type key = t module Hash : Caml.Hashtbl.S with type key = t
(** Hash tables with proc names as keys. *)
(** Maps from proc names. *)
module Map : PrettyPrintable.PPMap with type key = t module Map : PrettyPrintable.PPMap with type key = t
(** Maps from proc names. *)
(** Sets of proc names. *)
module Set : PrettyPrintable.PPSet with type elt = t module Set : PrettyPrintable.PPSet with type elt = t
(** Sets of proc names. *)
module SQLite : sig module SQLite : sig
val serialize : t -> Sqlite3.Data.t val serialize : t -> Sqlite3.Data.t
@ -643,11 +639,11 @@ module Fieldname : sig
val equal : t -> t -> bool val equal : t -> t -> bool
(** Equality for field names. *) (** Equality for field names. *)
(** Set for fieldnames *)
module Set : Caml.Set.S with type elt = t module Set : Caml.Set.S with type elt = t
(** Set for fieldnames *)
(** Map for fieldnames *)
module Map : Caml.Map.S with type key = t module Map : Caml.Map.S with type key = t
(** Map for fieldnames *)
module Clang : sig module Clang : sig
val from_class_name : Name.t -> string -> t val from_class_name : Name.t -> string -> t

@ -62,8 +62,8 @@ module Partition = struct
(* [fold_right] is expected to always provide a non-empty sequence. (* [fold_right] is expected to always provide a non-empty sequence.
Hence the result of [fold_right ~f:prepend_node] will always start with a Node. *) Hence the result of [fold_right ~f:prepend_node] will always start with a Node. *)
Logging.(die InternalError) Logging.(die InternalError)
"WeakTopologicalOrder.Partition.expand: the expansion function fold_right should \ "WeakTopologicalOrder.Partition.expand: the expansion function fold_right should not \
not return ~init directly" return ~init directly"
| Node {node= head; next= rest} -> | Node {node= head; next= rest} ->
Component {head; rest; next} ) Component {head; rest; next} )
@ -111,12 +111,12 @@ module type Make = functor (CFG : PreProcCfg) -> S with module CFG = CFG
module Bourdoncle_SCC (CFG : PreProcCfg) = struct module Bourdoncle_SCC (CFG : PreProcCfg) = struct
module CFG = CFG module CFG = CFG
module Dfn = CFG.Node.IdMap
(** (**
[dfn] contains a DFS pre-order indexing. A node is not in the map if it has never been visited. [dfn] contains a DFS pre-order indexing. A node is not in the map if it has never been visited.
A node's dfn is +oo if it has been fully visited (head of cross-edges) or we want to hide it A node's dfn is +oo if it has been fully visited (head of cross-edges) or we want to hide it
for building a subcomponent partition (head of highest back-edges). for building a subcomponent partition (head of highest back-edges).
*) *)
module Dfn = CFG.Node.IdMap
(* (*
Unlike Bourdoncle's paper version or OCamlGraph implementation, this implementation handles Unlike Bourdoncle's paper version or OCamlGraph implementation, this implementation handles

@ -78,8 +78,8 @@ end
module type Make = functor (CFG : PreProcCfg) -> S with module CFG = CFG module type Make = functor (CFG : PreProcCfg) -> S with module CFG = CFG
module Bourdoncle_SCC : Make
(** (**
Implementation of Bourdoncle's "Hierarchical decomposition of a directed graph into strongly Implementation of Bourdoncle's "Hierarchical decomposition of a directed graph into strongly
connected components and subcomponents". See [Bou] Figure 4, page 10. connected components and subcomponents". See [Bou] Figure 4, page 10.
*) *)
module Bourdoncle_SCC : Make

@ -532,8 +532,7 @@ module InvertedMap (Key : PrettyPrintable.PrintableOrderedType) (ValueDomain : S
inter prev next ~f:(fun prev next -> ValueDomain.widen ~prev ~next ~num_iters) inter prev next ~f:(fun prev next -> ValueDomain.widen ~prev ~next ~num_iters)
end end
module SafeInvertedMap (Key : PrettyPrintable.PrintableOrderedType) (ValueDomain : WithTop) = module SafeInvertedMap (Key : PrettyPrintable.PrintableOrderedType) (ValueDomain : WithTop) = struct
struct
module M = InvertedMap (Key) (ValueDomain) module M = InvertedMap (Key) (ValueDomain)
type key = M.key type key = M.key

@ -17,9 +17,9 @@ end
open! Types open! Types
exception Stop_analysis
(** This exception can be raised by abstract interpreters to stop the analysis early without (** This exception can be raised by abstract interpreters to stop the analysis early without
triggering further errors. Clients who raise this exception should catch it eventually. *) triggering further errors. Clients who raise this exception should catch it eventually. *)
exception Stop_analysis
(** Abstract domains and domain combinators *) (** Abstract domains and domain combinators *)
@ -38,13 +38,12 @@ module type S = sig
val widen : prev:t -> next:t -> num_iters:int -> t val widen : prev:t -> next:t -> num_iters:int -> t
end end
include include (* ocaml ignores the warning suppression at toplevel, hence the [include struct ... end] trick *)
(* ocaml ignores the warning suppression at toplevel, hence the [include struct ... end] trick *)
sig sig
[@@@warning "-60"] [@@@warning "-60"]
(** a trivial domain *)
module Empty : S with type t = unit module Empty : S with type t = unit
(** a trivial domain *)
end end
(** A domain with an explicit bottom value *) (** A domain with an explicit bottom value *)
@ -95,8 +94,7 @@ module Flat (V : PrettyPrintable.PrintableEquatableType) : sig
val get : t -> V.t option val get : t -> V.t option
end end
include include sig
sig
[@@@warning "-60"] [@@@warning "-60"]
(** Stacked abstract domain: tagged union of [Below] and [Above] domains where all elements of [Below] are strictly smaller than elements of [Above] *) (** Stacked abstract domain: tagged union of [Below] and [Above] domains where all elements of [Below] are strictly smaller than elements of [Above] *)
@ -165,8 +163,7 @@ module type FiniteSetS = sig
include WithBottom with type t := t include WithBottom with type t := t
end end
include include sig
sig
[@@@warning "-60"] [@@@warning "-60"]
(** Lift a PPSet to a powerset domain ordered by subset. The elements of the set should be drawn from (** Lift a PPSet to a powerset domain ordered by subset. The elements of the set should be drawn from
@ -195,18 +192,14 @@ module type MapS = sig
include WithBottom with type t := t include WithBottom with type t := t
end end
include include sig
sig
[@@@warning "-60"] [@@@warning "-60"]
(** Map domain ordered by union over the set of bindings, so the bottom element is the empty map. (** Map domain ordered by union over the set of bindings, so the bottom element is the empty map.
Every element implicitly maps to bottom unless it is explicitly bound to something else. Every element implicitly maps to bottom unless it is explicitly bound to something else.
Uses PPMap as the underlying map *) Uses PPMap as the underlying map *)
module MapOfPPMap (PPMap : PrettyPrintable.PPMap) (ValueDomain : S) : module MapOfPPMap (PPMap : PrettyPrintable.PPMap) (ValueDomain : S) :
MapS MapS with type key = PPMap.key and type value = ValueDomain.t and type t = ValueDomain.t PPMap.t
with type key = PPMap.key
and type value = ValueDomain.t
and type t = ValueDomain.t PPMap.t
end end
(** Map domain ordered by union over the set of bindings, so the bottom element is the empty map. (** Map domain ordered by union over the set of bindings, so the bottom element is the empty map.
@ -233,8 +226,7 @@ module SafeInvertedMap (Key : PrettyPrintable.PrintableOrderedType) (ValueDomain
(* ocaml ignores the warning suppression at toplevel, hence the [include struct ... end] trick *) (* ocaml ignores the warning suppression at toplevel, hence the [include struct ... end] trick *)
include include sig
sig
[@@@warning "-60"] [@@@warning "-60"]
module FiniteMultiMap module FiniteMultiMap
@ -250,13 +242,13 @@ include
end end
end end
module BooleanAnd : S with type t = bool
(** Boolean domain ordered by p || ~q. Useful when you want a boolean that's true only when it's (** Boolean domain ordered by p || ~q. Useful when you want a boolean that's true only when it's
true in both conditional branches. *) true in both conditional branches. *)
module BooleanAnd : S with type t = bool
module BooleanOr : WithBottom with type t = bool
(** Boolean domain ordered by ~p || q. Useful when you want a boolean that's true only when it's (** Boolean domain ordered by ~p || q. Useful when you want a boolean that's true only when it's
true in one conditional branch. *) true in one conditional branch. *)
module BooleanOr : WithBottom with type t = bool
module type MaxCount = sig module type MaxCount = sig
val max : int val max : int
@ -268,8 +260,8 @@ end
module CountDomain (MaxCount : MaxCount) : sig module CountDomain (MaxCount : MaxCount) : sig
include WithBottom with type t = private int include WithBottom with type t = private int
(** top is maximum value *)
include WithTop with type t := t include WithTop with type t := t
(** top is maximum value *)
val increment : t -> t val increment : t -> t
(** bump the count by one if it is less than the max *) (** bump the count by one if it is less than the max *)
@ -284,11 +276,11 @@ end
(** Domain keeping a non-negative count with a bounded maximum value. (** Domain keeping a non-negative count with a bounded maximum value.
[join] is minimum and [top] is zero. *) [join] is minimum and [top] is zero. *)
module DownwardIntDomain (MaxCount : MaxCount) : sig module DownwardIntDomain (MaxCount : MaxCount) : sig
(** top is zero *)
include WithTop with type t = private int include WithTop with type t = private int
(** top is zero *)
(** bottom is the provided maximum *)
include WithBottom with type t := t include WithBottom with type t := t
(** bottom is the provided maximum *)
val increment : t -> t val increment : t -> t
(** bump the count by one if this won't cross the maximum *) (** bump the count by one if this won't cross the maximum *)

@ -204,8 +204,7 @@ module AbstractInterpreterCommon (TransferFunctions : TransferFunctions.SIL) = s
let prev = old_state.State.pre in let prev = old_state.State.pre in
let next = astate_pre in let next = astate_pre in
let res = Domain.widen ~prev ~next ~num_iters in let res = Domain.widen ~prev ~next ~num_iters in
if Config.write_html then if Config.write_html then debug_absint_operation (`Widen (num_iters, (prev, next, res))) ;
debug_absint_operation (`Widen (num_iters, (prev, next, res))) ;
res ) res )
else astate_pre else astate_pre
in in
@ -453,8 +452,8 @@ module MakeUsingWTO (TransferFunctions : TransferFunctions.SIL) = struct
let compute_post ?(do_narrowing = false) = make_compute_post ~exec_cfg_internal ~do_narrowing let compute_post ?(do_narrowing = false) = make_compute_post ~exec_cfg_internal ~do_narrowing
end end
module type Make = functor (TransferFunctions : TransferFunctions.SIL) -> S module type Make = functor (TransferFunctions : TransferFunctions.SIL) ->
with module TransferFunctions = TransferFunctions S with module TransferFunctions = TransferFunctions
module MakeRPO (T : TransferFunctions.SIL) = module MakeRPO (T : TransferFunctions.SIL) =
MakeWithScheduler (Scheduler.ReversePostorder (T.CFG)) (T) MakeWithScheduler (Scheduler.ReversePostorder (T.CFG)) (T)

@ -58,11 +58,11 @@ module type S = sig
(** extract the state for a node id from the given invariant map *) (** extract the state for a node id from the given invariant map *)
end end
module type Make = functor (TransferFunctions : TransferFunctions.SIL) -> S module type Make = functor (TransferFunctions : TransferFunctions.SIL) ->
with module TransferFunctions = TransferFunctions S with module TransferFunctions = TransferFunctions
(** create an intraprocedural abstract interpreter from transfer functions using the reverse post-order scheduler *)
module MakeRPO : Make module MakeRPO : Make
(** create an intraprocedural abstract interpreter from transfer functions using the reverse post-order scheduler *)
(** create an intraprocedural abstract interpreter from transfer functions using Bourdoncle's strongly connected component weak topological order *)
module MakeWTO : Make module MakeWTO : Make
(** create an intraprocedural abstract interpreter from transfer functions using Bourdoncle's strongly connected component weak topological order *)

@ -118,9 +118,7 @@ let type_get_direct_supertypes tenv (typ : Typ.t) =
[] []
let type_get_class_name {Typ.desc} = let type_get_class_name {Typ.desc} = match desc with Typ.Tptr (typ, _) -> Typ.name typ | _ -> None
match desc with Typ.Tptr (typ, _) -> Typ.name typ | _ -> None
let type_get_annotation tenv (typ : Typ.t) : Annot.Item.t option = let type_get_annotation tenv (typ : Typ.t) : Annot.Item.t option =
match typ.desc with match typ.desc with

@ -216,9 +216,7 @@ module Exceptional = struct
in in
fold_exceptional_succs pdesc n ~f:add_exn_pred ~init:exn_preds_acc fold_exceptional_succs pdesc n ~f:add_exn_pred ~init:exn_preds_acc
in in
let exceptional_preds = let exceptional_preds = Procdesc.fold_nodes pdesc ~f:add_exn_preds ~init:Procdesc.IdMap.empty in
Procdesc.fold_nodes pdesc ~f:add_exn_preds ~init:Procdesc.IdMap.empty
in
(pdesc, exceptional_preds) (pdesc, exceptional_preds)
@ -291,8 +289,7 @@ end
(** Wrapper that reverses the direction of the CFG *) (** Wrapper that reverses the direction of the CFG *)
module Backward (Base : S with type instrs_dir = Instrs.not_reversed) = struct module Backward (Base : S with type instrs_dir = Instrs.not_reversed) = struct
include ( include (
Base : Base : S with type t = Base.t and type instrs_dir := Base.instrs_dir and module Node = Base.Node )
S with type t = Base.t and type instrs_dir := Base.instrs_dir and module Node = Base.Node )
type instrs_dir = Instrs.reversed type instrs_dir = Instrs.reversed
@ -341,8 +338,7 @@ end = struct
let instrs (node, index) = let instrs (node, index) =
let instrs = Base.instrs node in let instrs = Base.instrs node in
if Instrs.is_empty instrs then Instrs.empty if Instrs.is_empty instrs then Instrs.empty else Instrs.nth_exn instrs index |> Instrs.singleton
else Instrs.nth_exn instrs index |> Instrs.singleton
let first_of_node node = (node, 0) let first_of_node node = (node, 0)

@ -91,10 +91,7 @@ end
(** Forward CFG with no exceptional control-flow *) (** Forward CFG with no exceptional control-flow *)
module Normal : module Normal :
S S with type t = Procdesc.t and module Node = DefaultNode and type instrs_dir = Instrs.not_reversed
with type t = Procdesc.t
and module Node = DefaultNode
and type instrs_dir = Instrs.not_reversed
(** Forward CFG with exceptional control-flow *) (** Forward CFG with exceptional control-flow *)
module Exceptional : module Exceptional :

@ -20,8 +20,7 @@ module type S = sig
val of_summary : Summary.t -> t option val of_summary : Summary.t -> t option
val read_full : val read_full : caller_summary:Summary.t -> callee_pname:Typ.Procname.t -> (Procdesc.t * t) option
caller_summary:Summary.t -> callee_pname:Typ.Procname.t -> (Procdesc.t * t) option
val read : caller_summary:Summary.t -> callee_pname:Typ.Procname.t -> t option val read : caller_summary:Summary.t -> callee_pname:Typ.Procname.t -> t option
@ -44,8 +43,7 @@ module Make (P : Payload) : S with type t = P.t = struct
let get_payload analysis_result = let get_payload analysis_result =
let open Option.Monad_infix in let open Option.Monad_infix in
analysis_result analysis_result
>>= fun summary -> >>= fun summary -> of_summary summary >>| fun payload -> (Summary.get_proc_desc summary, payload)
of_summary summary >>| fun payload -> (Summary.get_proc_desc summary, payload)
let read_full ~caller_summary ~callee_pname = let read_full ~caller_summary ~callee_pname =

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

@ -13,8 +13,8 @@ open! IStd
module type S = sig module type S = sig
module CFG : ProcCfg.S module CFG : ProcCfg.S
(** abstract domain whose state we propagate *)
module Domain : AbstractDomain.S module Domain : AbstractDomain.S
(** abstract domain whose state we propagate *)
(** read-only extra state (results of previous analyses, globals, etc.) *) (** read-only extra state (results of previous analyses, globals, etc.) *)
type extras type extras

@ -21,8 +21,7 @@ let rec parse_import_file import_file channel =
; global_paths= curr_file_paths ; global_paths= curr_file_paths
; checkers= _ } -> ; checkers= _ } ->
already_imported_files := import_file :: !already_imported_files ; already_imported_files := import_file :: !already_imported_files ;
collect_all_macros_and_paths ~from_file:import_file imports curr_file_macros collect_all_macros_and_paths ~from_file:import_file imports curr_file_macros curr_file_paths
curr_file_paths
| None -> | None ->
L.(debug Linters Medium) "No macros or paths found.@\n" ; L.(debug Linters Medium) "No macros or paths found.@\n" ;
([], []) ([], [])

@ -22,9 +22,9 @@ let filter_parsed_linters_developer parsed_linters =
match Config.linter with match Config.linter with
| None -> | None ->
L.(die UserError) L.(die UserError)
"In linters developer mode you should debug only one linter at a time. This is \ "In linters developer mode you should debug only one linter at a time. This is important \
important for debugging the rule. Pass the flag --linter <name> to specify the linter \ for debugging the rule. Pass the flag --linter <name> to specify the linter you want to \
you want to debug." debug."
| Some lint -> | Some lint ->
List.filter List.filter
~f:(fun (rule : linter) -> ~f:(fun (rule : linter) ->
@ -40,9 +40,7 @@ let filter_parsed_linters_by_path parsed_linters source_file =
~f:(fun path -> ALVar.compare_str_with_alexp (SourceFile.to_rel_path source_file) path) ~f:(fun path -> ALVar.compare_str_with_alexp (SourceFile.to_rel_path source_file) path)
paths paths
in in
let whitelist_ok = let whitelist_ok = List.is_empty linter.whitelist_paths || should_lint linter.whitelist_paths in
List.is_empty linter.whitelist_paths || should_lint linter.whitelist_paths
in
let blacklist_ok = let blacklist_ok =
List.is_empty linter.blacklist_paths || not (should_lint linter.blacklist_paths) List.is_empty linter.blacklist_paths || not (should_lint linter.blacklist_paths)
in in
@ -343,8 +341,7 @@ let expand_formula phi map_ error_msg_ =
expand f1_sub map' error_msg' expand f1_sub map' error_msg'
| Unequal_lengths -> | Unequal_lengths ->
L.(die ExternalError) L.(die ExternalError)
"Formula identifier '%s' is not called with the right number of parameters" name "Formula identifier '%s' is not called with the right number of parameters" name )
)
with Caml.Not_found -> acc with Caml.Not_found -> acc
(* in this case it should be a predicate *) ) (* in this case it should be a predicate *) )
| Not f1 -> | Not f1 ->
@ -491,8 +488,8 @@ let log_frontend_issue method_decl_opt (node : Ctl_parser_types.ast_node)
~ltr:trace ~node_key ~ltr:trace ~node_key
let fill_issue_desc_info_and_log context ~witness ~current_node (issue_desc : CIssue.issue_desc) let fill_issue_desc_info_and_log context ~witness ~current_node (issue_desc : CIssue.issue_desc) loc
loc = =
let process_message message = let process_message message =
remove_new_lines_and_whitespace (expand_message_string context message current_node) remove_new_lines_and_whitespace (expand_message_string context message current_node)
in in
@ -502,8 +499,8 @@ let fill_issue_desc_info_and_log context ~witness ~current_node (issue_desc : CI
try log_frontend_issue context.CLintersContext.current_method witness issue_desc' try log_frontend_issue context.CLintersContext.current_method witness issue_desc'
with CFrontend_errors.IncorrectAssumption e -> with CFrontend_errors.IncorrectAssumption e ->
let trans_unit_ctx = context.CLintersContext.translation_unit_context in let trans_unit_ctx = context.CLintersContext.translation_unit_context in
ClangLogging.log_caught_exception trans_unit_ctx "IncorrectAssumption" e.position ClangLogging.log_caught_exception trans_unit_ctx "IncorrectAssumption" e.position e.source_range
e.source_range e.ast_node e.ast_node
(* Calls the set of hard coded checkers (if any) *) (* Calls the set of hard coded checkers (if any) *)

@ -95,8 +95,7 @@ let receiver_method_call an =
Ctl_parser_types.ast_node_name (Ctl_parser_types.Decl decl) Ctl_parser_types.ast_node_name (Ctl_parser_types.Decl decl)
| _ -> | _ ->
L.(die ExternalError) L.(die ExternalError)
"receiver_method_call must be called with ObjCMessageExpr, but got %s" "receiver_method_call must be called with ObjCMessageExpr, but got %s" (tag_name_of_node an)
(tag_name_of_node an)
let ivar_name an = let ivar_name an =

@ -7,13 +7,13 @@
open! IStd open! IStd
(** Raised when the parser encounters a violation of a certain invariant *)
exception ALParserInvariantViolationException of string exception ALParserInvariantViolationException of string
(** Raised when the parser encounters a violation of a certain invariant *)
type exc_info type exc_info
(** Raised when any exception from the lexer/parser of AL is caught, to include source-location info *)
exception ALFileException of exc_info exception ALFileException of exc_info
(** Raised when any exception from the lexer/parser of AL is caught, to include source-location info *)
val create_exc_info : string -> Lexing.lexbuf -> exc_info val create_exc_info : string -> Lexing.lexbuf -> exc_info

@ -60,9 +60,7 @@ let rec is_component_or_controller_descendant_impl decl =
CKComponentController. CKComponentController.
Does not recurse into hierarchy. *) Does not recurse into hierarchy. *)
and contains_ck_impl decl_list = and contains_ck_impl decl_list = List.exists ~f:is_component_or_controller_descendant_impl decl_list
List.exists ~f:is_component_or_controller_descendant_impl decl_list
(** An easy way to fix the component kit best practice (** An easy way to fix the component kit best practice
http://componentkit.org/docs/avoid-local-variables.html http://componentkit.org/docs/avoid-local-variables.html
@ -165,8 +163,8 @@ let mutable_local_vars_advice context an =
else None else None
with CFrontend_errors.IncorrectAssumption e -> with CFrontend_errors.IncorrectAssumption e ->
let trans_unit_ctx = context.CLintersContext.translation_unit_context in let trans_unit_ctx = context.CLintersContext.translation_unit_context in
ClangLogging.log_caught_exception trans_unit_ctx "IncorrectAssumption" e.position ClangLogging.log_caught_exception trans_unit_ctx "IncorrectAssumption" e.position e.source_range
e.source_range e.ast_node ; e.ast_node ;
None None
@ -257,9 +255,7 @@ let component_with_unconventional_superclass_advice context an =
in in
match an with match an with
| Ctl_parser_types.Decl (Clang_ast_t.ObjCImplementationDecl (_, _, _, _, impl_decl_info)) -> | Ctl_parser_types.Decl (Clang_ast_t.ObjCImplementationDecl (_, _, _, _, impl_decl_info)) ->
let if_decl_opt = let if_decl_opt = CAst_utils.get_decl_opt_with_decl_ref impl_decl_info.oidi_class_interface in
CAst_utils.get_decl_opt_with_decl_ref impl_decl_info.oidi_class_interface
in
if Option.is_some if_decl_opt && is_ck_context context an then if Option.is_some if_decl_opt && is_ck_context context an then
check_interface (Option.value_exn if_decl_opt) check_interface (Option.value_exn if_decl_opt)
else None else None
@ -315,9 +311,7 @@ let component_with_multiple_factory_methods_advice context an =
in in
match an with match an with
| Ctl_parser_types.Decl (Clang_ast_t.ObjCImplementationDecl (_, _, _, _, impl_decl_info)) -> ( | Ctl_parser_types.Decl (Clang_ast_t.ObjCImplementationDecl (_, _, _, _, impl_decl_info)) -> (
let if_decl_opt = let if_decl_opt = CAst_utils.get_decl_opt_with_decl_ref impl_decl_info.oidi_class_interface in
CAst_utils.get_decl_opt_with_decl_ref impl_decl_info.oidi_class_interface
in
match if_decl_opt with Some d when is_ck_context context an -> check_interface d | _ -> [] ) match if_decl_opt with Some d when is_ck_context context an -> check_interface d | _ -> [] )
| _ -> | _ ->
[] []

@ -446,11 +446,7 @@ let objc_message_receiver context an =
(* an |= call_method(m) where the name must be exactly m *) (* an |= call_method(m) where the name must be exactly m *)
let call_method an m = let call_method an m =
match get_selector an with match get_selector an with Some selector -> ALVar.compare_str_with_alexp selector m | _ -> false
| Some selector ->
ALVar.compare_str_with_alexp selector m
| _ ->
false
let call_class_method an mname = let call_class_method an mname =
@ -1427,9 +1423,7 @@ let rec get_decl_attributes_for_callexpr_param an =
L.debug Linters Verbose "#####POINTER LOOP UP: '%i'@\n" si.si_pointer ; L.debug Linters Verbose "#####POINTER LOOP UP: '%i'@\n" si.si_pointer ;
match CAst_utils.get_decl_opt_with_decl_ref drti.drti_decl_ref with match CAst_utils.get_decl_opt_with_decl_ref drti.drti_decl_ref with
| Some (FunctionDecl (_, _, _, fdi)) -> | Some (FunctionDecl (_, _, _, fdi)) ->
List.fold fdi.fdi_parameters List.fold fdi.fdi_parameters ~f:(fun acc p -> List.append (get_attr_param p) acc) ~init:[]
~f:(fun acc p -> List.append (get_attr_param p) acc)
~init:[]
| Some (ParmVarDecl _ as d) -> | Some (ParmVarDecl _ as d) ->
get_attr_param d get_attr_param d
| _ -> | _ ->
@ -1590,9 +1584,7 @@ let source_file_matches src_file path_re =
~default:false src_file ~default:false src_file
let is_in_source_file an path_re = let is_in_source_file an path_re = source_file_matches (Ctl_parser_types.get_source_file an) path_re
source_file_matches (Ctl_parser_types.get_source_file an) path_re
let is_referencing_decl_from_source_file an path_re = let is_referencing_decl_from_source_file an path_re =
source_file_matches (Ctl_parser_types.get_referenced_decl_source_file an) path_re source_file_matches (Ctl_parser_types.get_referenced_decl_source_file an) path_re

@ -434,8 +434,7 @@ val get_available_attr_ios_sdk : Ctl_parser_types.ast_node -> string option
val get_selector : Ctl_parser_types.ast_node -> string option val get_selector : Ctl_parser_types.ast_node -> string option
val within_responds_to_selector_block : val within_responds_to_selector_block : CLintersContext.context -> Ctl_parser_types.ast_node -> bool
CLintersContext.context -> Ctl_parser_types.ast_node -> bool
val objc_method_call_within_responds_to_selector_block : val objc_method_call_within_responds_to_selector_block :
CLintersContext.context -> Ctl_parser_types.ast_node -> bool CLintersContext.context -> Ctl_parser_types.ast_node -> bool

@ -201,9 +201,8 @@ let get_successor_stmts_of_decl decl =
Option.to_list block_decl_info.Clang_ast_t.bdi_body Option.to_list block_decl_info.Clang_ast_t.bdi_body
| VarDecl (_, _, _, var_decl_info) -> | VarDecl (_, _, _, var_decl_info) ->
Option.to_list var_decl_info.vdi_init_expr Option.to_list var_decl_info.vdi_init_expr
| ObjCIvarDecl (_, _, _, fldi, _) | ObjCIvarDecl (_, _, _, fldi, _) | FieldDecl (_, _, _, fldi) | ObjCAtDefsFieldDecl (_, _, _, fldi)
| FieldDecl (_, _, _, fldi) ->
| ObjCAtDefsFieldDecl (_, _, _, fldi) ->
Option.to_list fldi.fldi_init_expr Option.to_list fldi.fldi_init_expr
| _ -> | _ ->
[] []
@ -232,13 +231,13 @@ let rec is_node_successor_of ~is_successor:succ_node node =
| Stmt _ -> | Stmt _ ->
let node_succ_stmts = get_successor_stmts node in let node_succ_stmts = get_successor_stmts node in
List.exists node_succ_stmts ~f:(fun (s : Clang_ast_t.stmt) -> List.exists node_succ_stmts ~f:(fun (s : Clang_ast_t.stmt) ->
ast_node_equal (Stmt s) succ_node ast_node_equal (Stmt s) succ_node || is_node_successor_of ~is_successor:succ_node (Stmt s)
|| is_node_successor_of ~is_successor:succ_node (Stmt s) ) )
| Decl _ -> | Decl _ ->
let node_succ_decls = get_successor_decls node in let node_succ_decls = get_successor_decls node in
List.exists node_succ_decls ~f:(fun (d : Clang_ast_t.decl) -> List.exists node_succ_decls ~f:(fun (d : Clang_ast_t.decl) ->
ast_node_equal (Decl d) succ_node ast_node_equal (Decl d) succ_node || is_node_successor_of ~is_successor:succ_node (Decl d)
|| is_node_successor_of ~is_successor:succ_node (Decl d) ) )
let get_direct_successor_nodes an = let get_direct_successor_nodes an =

@ -105,8 +105,7 @@ let reset () = copy initial ~into:global_stats
let pp f stats = let pp f stats =
let pp_hit_percent hit miss f = let pp_hit_percent hit miss f =
let total = hit + miss in let total = hit + miss in
if Int.equal total 0 then F.pp_print_string f "N/A%%" if Int.equal total 0 then F.pp_print_string f "N/A%%" else F.fprintf f "%d%%" (hit * 100 / total)
else F.fprintf f "%d%%" (hit * 100 / total)
in in
let pp_int_field stats f field = let pp_int_field stats f field =
F.fprintf f "%s= %d@;" (Field.name field) (Field.get field stats) F.fprintf f "%s= %d@;" (Field.name field) (Field.get field stats)
@ -120,8 +119,7 @@ let pp f stats =
Fields.iter ~summary_file_try_load:(pp_int_field stats f) Fields.iter ~summary_file_try_load:(pp_int_field stats f)
~summary_read_from_disk:(pp_int_field stats f) ~summary_read_from_disk:(pp_int_field stats f)
~summary_cache_hits:(pp_cache_hits stats stats.summary_cache_misses f) ~summary_cache_hits:(pp_cache_hits stats stats.summary_cache_misses f)
~summary_cache_misses:(pp_int_field stats f) ~summary_cache_misses:(pp_int_field stats f) ~summary_has_model_queries:(pp_int_field stats f)
~summary_has_model_queries:(pp_int_field stats f)
~ondemand_procs_analyzed:(pp_int_field stats f) ~ondemand_procs_analyzed:(pp_int_field stats f)
~ondemand_local_cache_hits:(pp_cache_hits stats stats.ondemand_local_cache_misses f) ~ondemand_local_cache_hits:(pp_cache_hits stats stats.ondemand_local_cache_misses f)
~ondemand_local_cache_misses:(pp_int_field stats f) ~ondemand_local_cache_misses:(pp_int_field stats f)

@ -8,8 +8,7 @@ open! IStd
module F = Format module F = Format
module type NodeSig = sig module type NodeSig = sig
type t = private type t = private {id: int; pname: Typ.Procname.t; mutable successors: int list; mutable flag: bool}
{id: int; pname: Typ.Procname.t; mutable successors: int list; mutable flag: bool}
val make : int -> Typ.Procname.t -> int list -> t val make : int -> Typ.Procname.t -> int list -> t
@ -144,7 +143,7 @@ let to_dotty g filename =
let remove_unflagged_and_unflag_all {id_map; node_map} = let remove_unflagged_and_unflag_all {id_map; node_map} =
NodeMap.filter_map_inplace NodeMap.filter_map_inplace
(fun _id (n : Node.t) -> (fun _id (n : Node.t) ->
if n.flag then ( Node.unset_flag n ; Some n ) else ( IdMap.remove id_map n.pname ; None ) ) if n.flag then (Node.unset_flag n ; Some n) else (IdMap.remove id_map n.pname ; None) )
node_map node_map

@ -8,8 +8,7 @@ open! IStd
module F = Format module F = Format
module type NodeSig = sig module type NodeSig = sig
type t = private type t = private {id: int; pname: Typ.Procname.t; mutable successors: int list; mutable flag: bool}
{id: int; pname: Typ.Procname.t; mutable successors: int list; mutable flag: bool}
val make : int -> Typ.Procname.t -> int list -> t val make : int -> Typ.Procname.t -> int list -> t

@ -208,8 +208,8 @@ end
let issue_of_cost kind CostIssues.{complexity_increase_issue; zero_issue; infinite_issue} ~delta let issue_of_cost kind CostIssues.{complexity_increase_issue; zero_issue; infinite_issue} ~delta
~prev_item ~prev_item
~curr_item:( {CostItem.cost_item= cost_info; degree_with_term= curr_degree_with_term} as ~curr_item:
curr_item ) = ({CostItem.cost_item= cost_info; degree_with_term= curr_degree_with_term} as curr_item) =
let file = cost_info.Jsonbug_t.loc.file in let file = cost_info.Jsonbug_t.loc.file in
let method_name = cost_info.Jsonbug_t.procedure_name in let method_name = cost_info.Jsonbug_t.procedure_name in
let is_on_ui_thread = cost_info.Jsonbug_t.is_on_ui_thread in let is_on_ui_thread = cost_info.Jsonbug_t.is_on_ui_thread in
@ -413,8 +413,7 @@ let of_reports ~(current_report : Jsonbug_t.report) ~(previous_report : Jsonbug_
let to_files {introduced; fixed; preexisting; costs_summary} destdir = let to_files {introduced; fixed; preexisting; costs_summary} destdir =
Out_channel.write_all (destdir ^/ "introduced.json") Out_channel.write_all (destdir ^/ "introduced.json") ~data:(Jsonbug_j.string_of_report introduced) ;
~data:(Jsonbug_j.string_of_report introduced) ;
Out_channel.write_all (destdir ^/ "fixed.json") ~data:(Jsonbug_j.string_of_report fixed) ; Out_channel.write_all (destdir ^/ "fixed.json") ~data:(Jsonbug_j.string_of_report fixed) ;
Out_channel.write_all (destdir ^/ "preexisting.json") Out_channel.write_all (destdir ^/ "preexisting.json")
~data:(Jsonbug_j.string_of_report preexisting) ; ~data:(Jsonbug_j.string_of_report preexisting) ;

@ -48,9 +48,8 @@ module FileRenamings = struct
with Yojson.Json_error err -> with Yojson.Json_error err ->
L.(die UserError) L.(die UserError)
"Error parsing file renamings: %s@\n\ "Error parsing file renamings: %s@\n\
Expected JSON object of the following form: '%s', but instead got: '%s'" Expected JSON object of the following form: '%s', but instead got: '%s'" err
err "{\"current\": \"aaa.java\", \"previous\": \"BBB.java\"}" "{\"current\": \"aaa.java\", \"previous\": \"BBB.java\"}" (Yojson.Basic.to_string assoc)
(Yojson.Basic.to_string assoc)
in in
match j with match j with
| `List json_renamings -> | `List json_renamings ->

@ -72,8 +72,7 @@ let _read_file_perf_data fname =
match split_class_method_name itm.Perf_profiler_t.function_name with match split_class_method_name itm.Perf_profiler_t.function_name with
| Some (classname, methodname) -> | Some (classname, methodname) ->
let procname = JProcname.make_void_signature_procname ~classname ~methodname in let procname = JProcname.make_void_signature_procname ~classname ~methodname in
global_perf_profiler_data := global_perf_profiler_data := PerfProfilerDataMap.add procname itm !global_perf_profiler_data
PerfProfilerDataMap.add procname itm !global_perf_profiler_data
| _ -> | _ ->
() ()
in in

@ -7,8 +7,8 @@
*) *)
(** Main module for the analysis after the capture phase *) (** Main module for the analysis after the capture phase *)
open! IStd
open! IStd
module F = Format module F = Format
module L = Logging module L = Logging
@ -36,8 +36,8 @@ let analyze_target : SchedulerTypes.target Tasks.doer =
let analyze_proc_name exe_env proc_name = let analyze_proc_name exe_env proc_name =
decr procs_left ; decr procs_left ;
if Int.( <= ) !procs_left 0 then ( if Int.( <= ) !procs_left 0 then (
L.log_task "Analysing block of %d procs, starting with %a@." L.log_task "Analysing block of %d procs, starting with %a@." per_procedure_logging_granularity
per_procedure_logging_granularity Typ.Procname.pp proc_name ; Typ.Procname.pp proc_name ;
procs_left := per_procedure_logging_granularity ) ; procs_left := per_procedure_logging_granularity ) ;
Ondemand.analyze_proc_name_toplevel exe_env proc_name Ondemand.analyze_proc_name_toplevel exe_env proc_name
in in
@ -116,9 +116,7 @@ let get_source_files_to_analyze ~changed_files =
let analyze source_files_to_analyze = let analyze source_files_to_analyze =
if Int.equal Config.jobs 1 then ( if Int.equal Config.jobs 1 then (
let target_files = let target_files = List.rev_map source_files_to_analyze ~f:(fun sf -> SchedulerTypes.File sf) in
List.rev_map source_files_to_analyze ~f:(fun sf -> SchedulerTypes.File sf)
in
Tasks.run_sequentially ~f:analyze_target target_files ; Tasks.run_sequentially ~f:analyze_target target_files ;
BackendStats.get () ) BackendStats.get () )
else ( else (
@ -167,8 +165,8 @@ let invalidate_changed_procedures changed_files =
0 0
in in
L.progress L.progress
"Incremental analysis: %d nodes in reverse analysis call graph, %d of which were \ "Incremental analysis: %d nodes in reverse analysis call graph, %d of which were invalidated \
invalidated @." @."
total_nodes invalidated_nodes ; total_nodes invalidated_nodes ;
ScubaLogging.log_count ~label:"incremental_analysis.total_nodes" ~value:total_nodes ; ScubaLogging.log_count ~label:"incremental_analysis.total_nodes" ~value:total_nodes ;
ScubaLogging.log_count ~label:"incremental_analysis.invalidated_nodes" ~value:invalidated_nodes ; ScubaLogging.log_count ~label:"incremental_analysis.invalidated_nodes" ~value:invalidated_nodes ;

@ -156,16 +156,14 @@ let should_report (issue_kind : Exceptions.severity) issue_type error_desc eclas
in in
List.mem ~equal:IssueType.equal null_deref_issue_types issue_type List.mem ~equal:IssueType.equal null_deref_issue_types issue_type
in in
if issue_type_is_null_deref then Localise.error_desc_is_reportable_bucket error_desc if issue_type_is_null_deref then Localise.error_desc_is_reportable_bucket error_desc else true
else true
(* The reason an issue should be censored (that is, not reported). The empty (* The reason an issue should be censored (that is, not reported). The empty
string (that is "no reason") means that the issue should be reported. *) string (that is "no reason") means that the issue should be reported. *)
let censored_reason (issue_type : IssueType.t) source_file = let censored_reason (issue_type : IssueType.t) source_file =
let filename = SourceFile.to_rel_path source_file in let filename = SourceFile.to_rel_path source_file in
let rejected_by ((issue_type_polarity, issue_type_re), (filename_polarity, filename_re), reason) let rejected_by ((issue_type_polarity, issue_type_re), (filename_polarity, filename_re), reason) =
=
let accepted = let accepted =
(* matches issue_type_re implies matches filename_re *) (* matches issue_type_re implies matches filename_re *)
(not (Bool.equal issue_type_polarity (Str.string_match issue_type_re issue_type.unique_id 0))) (not (Bool.equal issue_type_polarity (Str.string_match issue_type_re issue_type.unique_id 0)))
@ -332,9 +330,8 @@ module JsonCostsPrinter = MakeJsonListPrinter (struct
(CostDomain.BasicCost.pp_degree ~only_bigO:false) (CostDomain.BasicCost.pp_degree ~only_bigO:false)
degree_with_term degree_with_term
; big_o= ; big_o=
Format.asprintf "%a" Format.asprintf "%a" (CostDomain.BasicCost.pp_degree ~only_bigO:true) degree_with_term
(CostDomain.BasicCost.pp_degree ~only_bigO:true) }
degree_with_term }
in in
let cost_info cost = let cost_info cost =
{ Jsonbug_t.polynomial_version= CostDomain.BasicCost.version { Jsonbug_t.polynomial_version= CostDomain.BasicCost.version
@ -407,8 +404,7 @@ let pp_custom_of_report fmt report fields =
| `Issue_field_hash -> | `Issue_field_hash ->
Format.fprintf fmt "%s%s" (comma_separator index) (Caml.Digest.to_hex issue.hash) Format.fprintf fmt "%s%s" (comma_separator index) (Caml.Digest.to_hex issue.hash)
| `Issue_field_line_offset -> | `Issue_field_line_offset ->
Format.fprintf fmt "%s%d" (comma_separator index) Format.fprintf fmt "%s%d" (comma_separator index) (issue.line - issue.procedure_start_line)
(issue.line - issue.procedure_start_line)
| `Issue_field_qualifier_contains_potential_exception_note -> | `Issue_field_qualifier_contains_potential_exception_note ->
Format.pp_print_bool fmt Format.pp_print_bool fmt
(String.is_substring issue.qualifier ~substring:potential_exception_message) (String.is_substring issue.qualifier ~substring:potential_exception_message)
@ -506,9 +502,7 @@ module Stats = struct
let loc = lt.Errlog.lt_loc in let loc = lt.Errlog.lt_loc in
let level = lt.Errlog.lt_level in let level = lt.Errlog.lt_level in
let description = lt.Errlog.lt_description in let description = lt.Errlog.lt_description in
let code = let code = match Printer.LineReader.from_loc linereader loc with Some s -> s | None -> "" in
match Printer.LineReader.from_loc linereader loc with Some s -> s | None -> ""
in
let line = let line =
let pp fmt = let pp fmt =
if description <> "" then if description <> "" then
@ -611,8 +605,7 @@ module StatsLogs = struct
{ analysis_nodes_visited= Summary.Stats.nb_visited summary.stats { analysis_nodes_visited= Summary.Stats.nb_visited summary.stats
; analysis_status= Summary.Stats.failure_kind summary.stats ; analysis_status= Summary.Stats.failure_kind summary.stats
; analysis_total_nodes= Summary.get_proc_desc summary |> Procdesc.get_nodes_num ; analysis_total_nodes= Summary.get_proc_desc summary |> Procdesc.get_nodes_num
; clang_method_kind= ; clang_method_kind= (match lang with Language.Clang -> Some clang_method_kind | _ -> None)
(match lang with Language.Clang -> Some clang_method_kind | _ -> None)
; lang= Language.to_explicit_string lang ; lang= Language.to_explicit_string lang
; method_location= Summary.get_loc summary ; method_location= Summary.get_loc summary
; method_name= Typ.Procname.to_string proc_name ; method_name= Typ.Procname.to_string proc_name
@ -798,11 +791,7 @@ module SummaryStats = struct
module StringMap = PrettyPrintable.MakePPMap (String) module StringMap = PrettyPrintable.MakePPMap (String)
type ('i, 'k) result = type ('i, 'k) result =
| R : | R : {typ: 't typ; get: 'i -> 't; aggrs: ('t, 'k) MetricAggregator.t list} -> ('i, 'k) result
{ typ: 't typ
; get: 'i -> 't
; aggrs: ('t, 'k) MetricAggregator.t list }
-> ('i, 'k) result
let init metrics aggregators = let init metrics aggregators =
List.fold metrics ~init:StringMap.empty ~f:(fun acc (name, M {typ; get}) -> List.fold metrics ~init:StringMap.empty ~f:(fun acc (name, M {typ; get}) ->

@ -7,8 +7,7 @@
open! IStd open! IStd
include include sig
sig
(* ignore dead modules added by @@deriving fields *) (* ignore dead modules added by @@deriving fields *)
[@@@warning "-60"] [@@@warning "-60"]

@ -41,7 +41,7 @@ let spec_files_from_cmdline () =
if (not (Filename.check_suffix arg Config.specs_files_suffix)) && arg <> "." then if (not (Filename.check_suffix arg Config.specs_files_suffix)) && arg <> "." then
print_usage_exit ("file " ^ arg ^ ": arguments must be .specs files") ) print_usage_exit ("file " ^ arg ^ ": arguments must be .specs files") )
Config.anon_args ; Config.anon_args ;
if Config.test_filtering then ( Inferconfig.test () ; L.exit 0 ) ; if Config.test_filtering then (Inferconfig.test () ; L.exit 0) ;
if List.is_empty Config.anon_args then load_specfiles () else List.rev Config.anon_args ) if List.is_empty Config.anon_args then load_specfiles () else List.rev Config.anon_args )
else load_specfiles () else load_specfiles ()

@ -86,8 +86,7 @@ let collect_all_stats_files () =
let buck_out_parent = Filename.concat p Filename.parent_dir_name in let buck_out_parent = Filename.concat p Filename.parent_dir_name in
let targets_files = let targets_files =
List.map List.map
~f:(fun (t, p) -> ~f:(fun (t, p) -> (t, find_stats_files_in_dir (concatenate_paths buck_out_parent p)))
(t, find_stats_files_in_dir (concatenate_paths buck_out_parent p)) )
r r
in in
Ok (Buck_out targets_files) Ok (Buck_out targets_files)

@ -64,8 +64,7 @@ let iterate_procedure_callbacks exe_env summary =
let is_specialized = Procdesc.is_specialized proc_desc in let is_specialized = Procdesc.is_specialized proc_desc in
List.fold ~init:summary List.fold ~init:summary
~f:(fun summary {name; dynamic_dispatch; language; callback} -> ~f:(fun summary {name; dynamic_dispatch; language; callback} ->
if Language.equal language procedure_language && (dynamic_dispatch || not is_specialized) if Language.equal language procedure_language && (dynamic_dispatch || not is_specialized) then (
then (
PerfEvent.( PerfEvent.(
log (fun logger -> log (fun logger ->
log_begin_event logger ~name ~categories:["backend"] log_begin_event logger ~name ~categories:["backend"]

@ -41,8 +41,7 @@ type coordinate = {id: int; lambda: int} [@@deriving compare]
(* define a link between two nodes. src_fld/trg_fld define the label of the src/trg field. It is*) (* define a link between two nodes. src_fld/trg_fld define the label of the src/trg field. It is*)
(* useful for having nodes from within a struct and/or to inside a struct *) (* useful for having nodes from within a struct and/or to inside a struct *)
type link = type link = {kind: kind_of_links; src: coordinate; src_fld: string; trg: coordinate; trg_fld: string}
{kind: kind_of_links; src: coordinate; src_fld: string; trg: coordinate; trg_fld: string}
[@@deriving compare] [@@deriving compare]
let equal_link = [%compare.equal: link] let equal_link = [%compare.equal: link]
@ -272,8 +271,7 @@ let make_dangling_boxes pe allocated_nodes (sigma_lambda : (Sil.hpred * int) lis
incr dotty_state_count ; incr dotty_state_count ;
let coo = mk_coordinate n lambda in let coo = mk_coordinate n lambda in
match hpred with match hpred with
| Sil.Hpointsto (_, Sil.Eexp (e, _), _) when (not (Exp.equal e Exp.zero)) && !print_full_prop | Sil.Hpointsto (_, Sil.Eexp (e, _), _) when (not (Exp.equal e Exp.zero)) && !print_full_prop ->
->
let e_color_str = color_to_str (exp_color hpred e) in let e_color_str = color_to_str (exp_color hpred e) in
[Dotdangling (coo, e, e_color_str)] [Dotdangling (coo, e, e_color_str)]
| Sil.Hlseg (_, _, _, e2, _) when not (Exp.equal e2 Exp.zero) -> | Sil.Hlseg (_, _, _, e2, _) when not (Exp.equal e2 Exp.zero) ->
@ -324,8 +322,7 @@ let make_dangling_boxes pe allocated_nodes (sigma_lambda : (Sil.hpred * int) lis
| [] -> | [] ->
[] []
| d :: candidates -> | d :: candidates ->
if is_allocated d then subtract_allocated candidates if is_allocated d then subtract_allocated candidates else d :: subtract_allocated candidates
else d :: subtract_allocated candidates
in in
let candidate_dangling = List.concat_map ~f:get_rhs_predicate sigma_lambda in let candidate_dangling = List.concat_map ~f:get_rhs_predicate sigma_lambda in
let candidate_dangling = filter_duplicate candidate_dangling [] in let candidate_dangling = filter_duplicate candidate_dangling [] in
@ -365,8 +362,7 @@ let rec dotty_mk_node pe sigma =
let e1_color_str = color_to_str (exp_color e1) in let e1_color_str = color_to_str (exp_color e1) in
incr dotty_state_count ; incr dotty_state_count ;
(* increment once more n+1 is the box for e4 *) (* increment once more n+1 is the box for e4 *)
[ Dotdllseg [Dotdllseg (mk_coordinate n lambda, e1, e2, e3, e4, k, hpara_dll.Sil.body_dll, e1_color_str)]
(mk_coordinate n lambda, e1, e2, e3, e4, k, hpara_dll.Sil.body_dll, e1_color_str) ]
in in
match sigma with match sigma with
| [] -> | [] ->
@ -589,8 +585,8 @@ let rec dotty_mk_set_links dotnodes sigma p f cycle =
~f:(fun (k, lab_src, m, lab_trg) -> ~f:(fun (k, lab_src, m, lab_trg) ->
mk_link k mk_link k
(mk_coordinate (n + 1) lambda) (mk_coordinate (n + 1) lambda)
(strip_special_chars lab_src) (mk_coordinate m lambda) (strip_special_chars lab_src) (mk_coordinate m lambda) (strip_special_chars lab_trg)
(strip_special_chars lab_trg) ) )
target_list target_list
in in
let links_from_elements = List.concat_map ~f:ff (n :: nl) in let links_from_elements = List.concat_map ~f:ff (n :: nl) in
@ -636,8 +632,8 @@ let rec dotty_mk_set_links dotnodes sigma p f cycle =
trg_label ] trg_label ]
else [] else []
in in
lnk_from_address_struct @ links_from_fields lnk_from_address_struct @ links_from_fields @ dotty_mk_set_links dotnodes sigma' p f cycle
@ dotty_mk_set_links dotnodes sigma' p f cycle ) )
| (Sil.Hpointsto (e, Sil.Eexp (e', _), _), lambda) :: sigma' -> ( | (Sil.Hpointsto (e, Sil.Eexp (e', _), _), lambda) :: sigma' -> (
let src = look_up dotnodes e lambda in let src = look_up dotnodes e lambda in
match src with match src with
@ -745,8 +741,8 @@ let dotty_pp_link f link =
F.fprintf f "struct%iL%i:%s%iL%i -> state%iL%i[label=\"\"]@\n" n1 lambda1 src_fld n1 lambda1 F.fprintf f "struct%iL%i:%s%iL%i -> state%iL%i[label=\"\"]@\n" n1 lambda1 src_fld n1 lambda1
n2 lambda2 n2 lambda2
| _, LinkRetainCycle -> | _, LinkRetainCycle ->
F.fprintf f "struct%iL%i:%s%iL%i -> struct%iL%i:%s%iL%i[label=\"\", color= red]@\n" n1 F.fprintf f "struct%iL%i:%s%iL%i -> struct%iL%i:%s%iL%i[label=\"\", color= red]@\n" n1 lambda1
lambda1 src_fld n1 lambda1 n2 lambda2 trg_fld n2 lambda2 src_fld n1 lambda1 n2 lambda2 trg_fld n2 lambda2
| _, LinkStructToStruct when !print_full_prop -> | _, LinkStructToStruct when !print_full_prop ->
F.fprintf f "struct%iL%i:%s%iL%i -> struct%iL%i:%s%iL%i[label=\"\"]@\n" n1 lambda1 src_fld n1 F.fprintf f "struct%iL%i:%s%iL%i -> struct%iL%i:%s%iL%i[label=\"\"]@\n" n1 lambda1 src_fld n1
lambda1 n2 lambda2 trg_fld n2 lambda2 lambda1 n2 lambda2 trg_fld n2 lambda2
@ -844,8 +840,7 @@ let rec print_struct f pe e te l coo c =
else else
F.fprintf f F.fprintf f
" node [%s]; @\n struct%iL%i [label=\"{<%s%iL%i> OBJECT: %s } | %a\" ] fontcolor=%s@\n" " node [%s]; @\n struct%iL%i [label=\"{<%s%iL%i> OBJECT: %s } | %a\" ] fontcolor=%s@\n"
"shape=record" n lambda e_no_special_char n lambda print_type (struct_to_dotty_str pe coo) l "shape=record" n lambda e_no_special_char n lambda print_type (struct_to_dotty_str pe coo) l c ;
c ;
F.fprintf f "}@\n" F.fprintf f "}@\n"
@ -868,9 +863,8 @@ and print_sll f pe nesting k e1 coo =
incr dotty_state_count ; incr dotty_state_count ;
( match k with ( match k with
| Sil.Lseg_NE -> | Sil.Lseg_NE ->
F.fprintf f F.fprintf f "subgraph cluster_%iL%i { %s node [style=filled,color=white]; label=\"list NE\";"
"subgraph cluster_%iL%i { %s node [style=filled,color=white]; label=\"list NE\";" n' n' lambda "style=filled; color=lightgrey;"
lambda "style=filled; color=lightgrey;"
| Sil.Lseg_PE -> | Sil.Lseg_PE ->
F.fprintf f F.fprintf f
"subgraph cluster_%iL%i { %s node [style=filled,color=white]; label=\"list PE\";" n' "subgraph cluster_%iL%i { %s node [style=filled,color=white]; label=\"list PE\";" n'
@ -935,9 +929,7 @@ and dotty_pp_state f pe cycle dotnode =
| Dotpointsto (coo, e1, c) when !print_full_prop -> | Dotpointsto (coo, e1, c) when !print_full_prop ->
dotty_exp coo e1 c false dotty_exp coo e1 c false
| Dotstruct (coo, e1, l, c, te) -> | Dotstruct (coo, e1, l, c, te) ->
let l' = let l' = if !print_full_prop then l else List.filter ~f:(fun edge -> in_cycle cycle edge) l in
if !print_full_prop then l else List.filter ~f:(fun edge -> in_cycle cycle edge) l
in
print_struct f pe e1 te l' coo c print_struct f pe e1 te l' coo c
| Dotarray (coo, e1, e2, l, _, c) when !print_full_prop -> | Dotarray (coo, e1, e2, l, _, c) when !print_full_prop ->
print_array f pe e1 e2 l coo c print_array f pe e1 e2 l coo c
@ -1149,8 +1141,7 @@ let pp_cfgnode pdesc fmt (n : Procdesc.Node.t) =
(* don't print exception edges to the exit node *) (* don't print exception edges to the exit node *)
() ()
| _ -> | _ ->
F.fprintf fmt "@\n\t %a -> %a %s;" (pp_cfgnodename pname) n1 (pp_cfgnodename pname) n2 F.fprintf fmt "@\n\t %a -> %a %s;" (pp_cfgnodename pname) n1 (pp_cfgnodename pname) n2 color
color
in in
List.iter ~f:(fun n' -> print_edge n n' false) (Procdesc.Node.get_succs n) ; List.iter ~f:(fun n' -> print_edge n n' false) (Procdesc.Node.get_succs n) ;
List.iter ~f:(fun n' -> print_edge n n' true) (Procdesc.Node.get_exn n) List.iter ~f:(fun n' -> print_edge n n' true) (Procdesc.Node.get_exn n)

@ -213,7 +213,7 @@ and exp_lv_dexp_ tenv (seen_ : Exp.Set.t) node e : DExp.t option =
let seen = Exp.Set.add e seen_ in let seen = Exp.Set.add e seen_ in
match Prop.exp_normalize_noabs tenv Sil.sub_empty e with match Prop.exp_normalize_noabs tenv Sil.sub_empty e with
| Exp.Const c -> | Exp.Const c ->
if verbose then ( L.d_str "exp_lv_dexp: constant " ; Sil.d_exp e ; L.d_ln () ) ; if verbose then (L.d_str "exp_lv_dexp: constant " ; Sil.d_exp e ; L.d_ln ()) ;
Some (DExp.Dderef (DExp.Dconst c)) Some (DExp.Dderef (DExp.Dconst c))
| Exp.BinOp (Binop.PlusPI, e1, e2) -> ( | Exp.BinOp (Binop.PlusPI, e1, e2) -> (
if verbose then ( if verbose then (
@ -311,7 +311,7 @@ and exp_rv_dexp_ tenv (seen_ : Exp.Set.t) node e : DExp.t option =
let seen = Exp.Set.add e seen_ in let seen = Exp.Set.add e seen_ in
match e with match e with
| Exp.Const c -> | Exp.Const c ->
if verbose then ( L.d_str "exp_rv_dexp: constant " ; Sil.d_exp e ; L.d_ln () ) ; if verbose then (L.d_str "exp_rv_dexp: constant " ; Sil.d_exp e ; L.d_ln ()) ;
Some (DExp.Dconst c) Some (DExp.Dconst c)
| Exp.Lvar pv -> | Exp.Lvar pv ->
if verbose then ( if verbose then (
@ -346,24 +346,24 @@ and exp_rv_dexp_ tenv (seen_ : Exp.Set.t) node e : DExp.t option =
| Some de1, Some de2 -> | Some de1, Some de2 ->
Some (DExp.Darray (de1, de2)) ) Some (DExp.Darray (de1, de2)) )
| Exp.BinOp (op, e1, e2) -> ( | Exp.BinOp (op, e1, e2) -> (
if verbose then ( L.d_str "exp_rv_dexp: BinOp " ; Sil.d_exp e ; L.d_ln () ) ; if verbose then (L.d_str "exp_rv_dexp: BinOp " ; Sil.d_exp e ; L.d_ln ()) ;
match (exp_rv_dexp_ tenv seen node e1, exp_rv_dexp_ tenv seen node e2) with match (exp_rv_dexp_ tenv seen node e1, exp_rv_dexp_ tenv seen node e2) with
| None, _ | _, None -> | None, _ | _, None ->
None None
| Some de1, Some de2 -> | Some de1, Some de2 ->
Some (DExp.Dbinop (op, de1, de2)) ) Some (DExp.Dbinop (op, de1, de2)) )
| Exp.UnOp (op, e1, _) -> ( | Exp.UnOp (op, e1, _) -> (
if verbose then ( L.d_str "exp_rv_dexp: UnOp " ; Sil.d_exp e ; L.d_ln () ) ; if verbose then (L.d_str "exp_rv_dexp: UnOp " ; Sil.d_exp e ; L.d_ln ()) ;
match exp_rv_dexp_ tenv seen node e1 with match exp_rv_dexp_ tenv seen node e1 with
| None -> | None ->
None None
| Some de1 -> | Some de1 ->
Some (DExp.Dunop (op, de1)) ) Some (DExp.Dunop (op, de1)) )
| Exp.Cast (_, e1) -> | Exp.Cast (_, e1) ->
if verbose then ( L.d_str "exp_rv_dexp: Cast " ; Sil.d_exp e ; L.d_ln () ) ; if verbose then (L.d_str "exp_rv_dexp: Cast " ; Sil.d_exp e ; L.d_ln ()) ;
exp_rv_dexp_ tenv seen node e1 exp_rv_dexp_ tenv seen node e1
| Exp.Sizeof {typ; dynamic_length; subtype} -> | Exp.Sizeof {typ; dynamic_length; subtype} ->
if verbose then ( L.d_str "exp_rv_dexp: type " ; Sil.d_exp e ; L.d_ln () ) ; if verbose then (L.d_str "exp_rv_dexp: type " ; Sil.d_exp e ; L.d_ln ()) ;
Some Some
(DExp.Dsizeof (typ, Option.bind dynamic_length ~f:(exp_rv_dexp_ tenv seen node), subtype)) (DExp.Dsizeof (typ, Option.bind dynamic_length ~f:(exp_rv_dexp_ tenv seen node), subtype))
| _ -> | _ ->
@ -564,7 +564,7 @@ let explain_leak tenv hpred prop alloc_att_opt bucket =
(** find the dexp, if any, where the given value is stored (** find the dexp, if any, where the given value is stored
also return the type of the value if found *) also return the type of the value if found *)
let vpath_find tenv prop exp_ : DExp.t option * Typ.t option = let vpath_find tenv prop exp_ : DExp.t option * Typ.t option =
if verbose then ( L.d_str "in vpath_find exp:" ; Sil.d_exp exp_ ; L.d_ln () ) ; if verbose then (L.d_str "in vpath_find exp:" ; Sil.d_exp exp_ ; L.d_ln ()) ;
let rec find sigma_acc sigma_todo exp = let rec find sigma_acc sigma_todo exp =
let do_fse res sigma_acc' sigma_todo' lexp texp (f, se) = let do_fse res sigma_acc' sigma_todo' lexp texp (f, se) =
match se with match se with

@ -87,8 +87,7 @@ val explain_dereference_as_caller_expression :
(** return a description explaining value [exp] in [prop] in terms of a source expression (** return a description explaining value [exp] in [prop] in terms of a source expression
using the formal parameters of the call *) using the formal parameters of the call *)
val explain_divide_by_zero : val explain_divide_by_zero : Tenv.t -> Exp.t -> Procdesc.Node.t -> Location.t -> Localise.error_desc
Tenv.t -> Exp.t -> Procdesc.Node.t -> Location.t -> Localise.error_desc
(** explain a division by zero *) (** explain a division by zero *)
val explain_condition_always_true_false : val explain_condition_always_true_false :

@ -70,8 +70,8 @@ let file_data_to_tenv file_data =
let file_data_to_integer_type_widths file_data = let file_data_to_integer_type_widths file_data =
if is_none file_data.integer_type_widths then if is_none file_data.integer_type_widths then
file_data.integer_type_widths file_data.integer_type_widths <-
<- Option.first_some (Typ.IntegerWidths.load file_data.source) (Some Typ.IntegerWidths.java) ; Option.first_some (Typ.IntegerWidths.load file_data.source) (Some Typ.IntegerWidths.java) ;
file_data.integer_type_widths file_data.integer_type_widths

@ -19,8 +19,7 @@ let merge_global_tenvs infer_deps_file =
let global_tenv_path = let global_tenv_path =
infer_out_src ^/ Config.global_tenv_filename |> DB.filename_from_string infer_out_src ^/ Config.global_tenv_filename |> DB.filename_from_string
in in
Tenv.read global_tenv_path Tenv.read global_tenv_path |> Option.iter ~f:(fun tenv -> Tenv.merge ~src:tenv ~dst:global_tenv)
|> Option.iter ~f:(fun tenv -> Tenv.merge ~src:tenv ~dst:global_tenv)
in in
Utils.iter_infer_deps ~project_root:Config.project_root ~f:merge infer_deps_file ; Utils.iter_infer_deps ~project_root:Config.project_root ~f:merge infer_deps_file ;
Tenv.store_global global_tenv ; Tenv.store_global global_tenv ;

@ -191,8 +191,7 @@ let run_proc_analysis ~caller_pdesc callee_pdesc =
let stats = Summary.Stats.update summary.stats ~failure_kind:kind in let stats = Summary.Stats.update summary.stats ~failure_kind:kind in
let payloads = let payloads =
let biabduction = let biabduction =
Some Some BiabductionSummary.{preposts= []; phase= summary.payloads.biabduction |> opt_get_phase}
BiabductionSummary.{preposts= []; phase= summary.payloads.biabduction |> opt_get_phase}
in in
{summary.payloads with biabduction} {summary.payloads with biabduction}
in in
@ -275,8 +274,8 @@ let dump_duplicate_procs source_file procs =
~append:true ~perm:0o666 ~f:(fun outc -> ~append:true ~perm:0o666 ~f:(fun outc ->
let fmt = F.formatter_of_out_channel outc in let fmt = F.formatter_of_out_channel outc in
List.iter duplicate_procs ~f:(fun (pname, source_captured) -> List.iter duplicate_procs ~f:(fun (pname, source_captured) ->
F.fprintf fmt "DUPLICATE_SYMBOLS source:%a source_captured:%a pname:%a@\n" F.fprintf fmt "DUPLICATE_SYMBOLS source:%a source_captured:%a pname:%a@\n" SourceFile.pp
SourceFile.pp source_file SourceFile.pp source_captured Typ.Procname.pp pname ) ; source_file SourceFile.pp source_captured Typ.Procname.pp pname ) ;
F.pp_print_flush fmt () ) F.pp_print_flush fmt () )
in in
if not (List.is_empty duplicate_procs) then output_to_file duplicate_procs if not (List.is_empty duplicate_procs) then output_to_file duplicate_procs

@ -51,8 +51,8 @@ module VarDomain = Liveness.Domain
each pvar in to_nullify afer we finish the analysis. Nullify instructions speed up the analysis each pvar in to_nullify afer we finish the analysis. Nullify instructions speed up the analysis
by enabling it to GC state that will no longer be read. *) by enabling it to GC state that will no longer be read. *)
module NullifyTransferFunctions = struct module NullifyTransferFunctions = struct
(** (reaching non-nullified vars) * (vars to nullify) *)
module Domain = AbstractDomain.Pair (VarDomain) (VarDomain) module Domain = AbstractDomain.Pair (VarDomain) (VarDomain)
(** (reaching non-nullified vars) * (vars to nullify) *)
module CFG = ProcCfg.Exceptional module CFG = ProcCfg.Exceptional

@ -43,8 +43,7 @@ let mk_command_doc ~see_also:see_also_commands ?environment:environment_opt ?fil
Cmdliner.Manpage.s_files section ) ] Cmdliner.Manpage.s_files section ) ]
in in
CLOpt.mk_command_doc ~section ~version:Version.versionString CLOpt.mk_command_doc ~section ~version:Version.versionString
~date:Version.man_pages_last_modify_date ~synopsis:[`Pre synopsis] ~environment ~files ~date:Version.man_pages_last_modify_date ~synopsis:[`Pre synopsis] ~environment ~files ~see_also
~see_also
let analyze = let analyze =
@ -86,8 +85,8 @@ let compile =
~description: ~description:
[ `P [ `P
"Intercepts compilation commands similarly to $(b,infer-capture), but simply execute \ "Intercepts compilation commands similarly to $(b,infer-capture), but simply execute \
these compilation commands and do not perform any translation of the source files. \ these compilation commands and do not perform any translation of the source files. This \
This can be useful to configure build systems or for debugging purposes." ] can be useful to configure build systems or for debugging purposes." ]
~examples: ~examples:
[ `P [ `P
"$(b,cmake)(1) hardcodes the absolute paths to the compiler inside the Makefiles it \ "$(b,cmake)(1) hardcodes the absolute paths to the compiler inside the Makefiles it \
@ -151,8 +150,8 @@ $(b,infer) $(i,[options])|}
languages of the C family, and a command to build them, infer produces a list of \ languages of the C family, and a command to build them, infer produces a list of \
potential issues." potential issues."
; `P ; `P
"Infer consists of a collection of tools referenced in the $(i,SEE ALSO) section of \ "Infer consists of a collection of tools referenced in the $(i,SEE ALSO) section of this \
this manual. See their respective manuals for more information." manual. See their respective manuals for more information."
; `P ; `P
"When run without a subcommand, and if a compilation command is specified via the \ "When run without a subcommand, and if a compilation command is specified via the \
$(b,--) option or one of the $(b,--clang-compilation-database[-escaped]) options, then \ $(b,--) option or one of the $(b,--clang-compilation-database[-escaped]) options, then \
@ -171,9 +170,9 @@ $(b,infer) $(i,[options])|}
inferconfig_file CLOpt.args_env_var CLOpt.args_env_var inferconfig_file inferconfig_file CLOpt.args_env_var CLOpt.args_env_var inferconfig_file
CLOpt.args_env_var Cmdliner.Manpage.s_environment Cmdliner.Manpage.s_files) CLOpt.args_env_var Cmdliner.Manpage.s_environment Cmdliner.Manpage.s_files)
; `P ; `P
"Options can be specified inside an argument file $(i,file) by passing \ "Options can be specified inside an argument file $(i,file) by passing $(b,@)$(i,file) \
$(b,@)$(i,file) as argument. The format is one option per line, and enclosing single \ as argument. The format is one option per line, and enclosing single ' and double \" \
' and double \" quotes are ignored." quotes are ignored."
; `P ; `P
"Options without a default value (e.g., $(b,--linter)) and options with list-like \ "Options without a default value (e.g., $(b,--linter)) and options with list-like \
values (e.g., $(b,--Xbuck)) all have a corresponding $(b,--option-reset) flag that \ values (e.g., $(b,--Xbuck)) all have a corresponding $(b,--option-reset) flag that \
@ -197,9 +196,9 @@ $(b,infer) $(i,[options])|}
inferconfig_env_var inferconfig_file Cmdliner.Manpage.s_files) inferconfig_env_var inferconfig_file Cmdliner.Manpage.s_files)
; `P ; `P
(Printf.sprintf (Printf.sprintf
"If $(b,%s) is set to \"1\", then infer commands will exit with an error code in \ "If $(b,%s) is set to \"1\", then infer commands will exit with an error code in some \
some cases when otherwise a simple warning would be emitted on stderr, for instance \ cases when otherwise a simple warning would be emitted on stderr, for instance if a \
if a deprecated form of an option is used." deprecated form of an option is used."
CLOpt.strict_mode_env_var) ] CLOpt.strict_mode_env_var) ]
~files: ~files:
[ `P [ `P
@ -224,8 +223,8 @@ $(b,infer) $(i,[options])|}
; `P "- cumulative options are JSON arrays of the appropriate type" ; `P "- cumulative options are JSON arrays of the appropriate type"
; `P ; `P
(Printf.sprintf (Printf.sprintf
"Infer will look for an $(b,%s) file in the current directory, then its parent, \ "Infer will look for an $(b,%s) file in the current directory, then its parent, etc., \
etc., stopping at the first $(b,%s) file found." stopping at the first $(b,%s) file found."
inferconfig_file inferconfig_file) inferconfig_file inferconfig_file)
; `P "Example:" ; `P "Example:"
; `Pre ; `Pre
@ -242,8 +241,8 @@ let report =
~synopsis:"$(b,infer) $(b,report) $(i,[options]) [$(i,file.specs)...]" ~synopsis:"$(b,infer) $(b,report) $(i,[options]) [$(i,file.specs)...]"
~description: ~description:
[ `P [ `P
"Read, convert, and print .specs files in the results directory. Each spec is printed \ "Read, convert, and print .specs files in the results directory. Each spec is printed to \
to standard output unless option -q is used." standard output unless option -q is used."
; `P ; `P
"If no specs file are passed on the command line, process all the .specs in the results \ "If no specs file are passed on the command line, process all the .specs in the results \
directory." ] directory." ]
@ -254,16 +253,15 @@ let reportdiff =
mk_command_doc ~title:"Infer Report Difference" mk_command_doc ~title:"Infer Report Difference"
~short_description:"compute the differences between two infer reports" ~short_description:"compute the differences between two infer reports"
~synopsis: ~synopsis:
"$(b,infer) $(b,reportdiff) $(b,--report-current) $(i,file) $(b,--report-previous) \ "$(b,infer) $(b,reportdiff) $(b,--report-current) $(i,file) $(b,--report-previous) $(i,file) \
$(i,file) $(i,[options])" $(i,[options])"
~description: ~description:
[ `P [ `P
"Given two infer reports $(i,previous) and $(i,current), compute the following three \ "Given two infer reports $(i,previous) and $(i,current), compute the following three \
reports and store them inside the \"differential/\" subdirectory of the results \ reports and store them inside the \"differential/\" subdirectory of the results \
directory:" directory:"
; `Noblank ; `Noblank
; `P ; `P "- $(b,introduced.json) contains the issues found in $(i,current) but not $(i,previous);"
"- $(b,introduced.json) contains the issues found in $(i,current) but not $(i,previous);"
; `Noblank ; `Noblank
; `P "- $(b,fixed.json) contains the issues found in $(i,previous) but not $(i,current);" ; `P "- $(b,fixed.json) contains the issues found in $(i,previous) but not $(i,current);"
; `Noblank ; `Noblank
@ -280,8 +278,8 @@ let events =
~synopsis:{|$(b,infer) $(b,events)|} ~synopsis:{|$(b,infer) $(b,events)|}
~description: ~description:
[ `P [ `P
"Emit to stdout one JSON object per line, each describing a logged event happened \ "Emit to stdout one JSON object per line, each describing a logged event happened during \
during the execution of Infer" ] the execution of Infer" ]
~see_also:InferCommand.[Report; Run] ~see_also:InferCommand.[Report; Run]

@ -99,8 +99,7 @@ type desc =
; default_string: string ; default_string: string
; spec: spec ; spec: spec
; decode_json: inferconfig_dir:string -> Yojson.Basic.t -> string list ; decode_json: inferconfig_dir:string -> Yojson.Basic.t -> string list
(** how to go from an option in the json config file to a list of command-line options *) (** how to go from an option in the json config file to a list of command-line options *) }
}
let dashdash ?short long = let dashdash ?short long =
match (long, short) with match (long, short) with
@ -190,9 +189,7 @@ let add parse_mode sections desc =
let desc_list = List.Assoc.find_exn ~equal:equal_parse_mode parse_mode_desc_lists parse_mode in let desc_list = List.Assoc.find_exn ~equal:equal_parse_mode parse_mode_desc_lists parse_mode in
desc_list := desc :: !desc_list ; desc_list := desc :: !desc_list ;
let add_to_section (command, section) = let add_to_section (command, section) =
let sections = let sections = List.Assoc.find_exn ~equal:InferCommand.equal help_sections_desc_lists command in
List.Assoc.find_exn ~equal:InferCommand.equal help_sections_desc_lists command
in
let prev_contents = try SectionMap.find section !sections with Caml.Not_found -> [] in let prev_contents = try SectionMap.find section !sections with Caml.Not_found -> [] in
sections := SectionMap.add section (desc :: prev_contents) !sections sections := SectionMap.add section (desc :: prev_contents) !sections
in in
@ -526,8 +523,8 @@ let map_to_str map =
String.concat list ~sep:"," String.concat list ~sep:","
let mk_string_map ?(default = String.Map.empty) ?(default_to_string = map_to_str) let mk_string_map ?(default = String.Map.empty) ?(default_to_string = map_to_str) ?(deprecated = [])
?(deprecated = []) ~long ?short ?parse_mode ?in_help ?(meta = "key=value") doc = ~long ?short ?parse_mode ?in_help ?(meta = "key=value") doc =
let flag = mk_flag ~deprecated ?short ~long in let flag = mk_flag ~deprecated ?short ~long in
let split_str str = let split_str str =
match String.lsplit2 str ~on:'=' with match String.lsplit2 str ~on:'=' with
@ -568,8 +565,8 @@ let normalize_path_in_args_being_parsed ?(f = Fn.id) ~is_anon_arg str =
else str else str
let mk_path_helper ~setter ~default_to_string ~default ~deprecated ~long ~short ~parse_mode let mk_path_helper ~setter ~default_to_string ~default ~deprecated ~long ~short ~parse_mode ~in_help
~in_help ~meta ~decode_json doc = ~meta ~decode_json doc =
mk ~deprecated ~long ?short ~default ?parse_mode ?in_help ~meta doc ~decode_json mk ~deprecated ~long ?short ~default ?parse_mode ?in_help ~meta doc ~decode_json
~default_to_string ~default_to_string
~mk_setter:(fun var str -> ~mk_setter:(fun var str ->
@ -707,8 +704,8 @@ let normalize_desc_list speclist =
sort speclist sort speclist
let mk_command_doc ~title ~section ~version ~date ~short_description ~synopsis ~description let mk_command_doc ~title ~section ~version ~date ~short_description ~synopsis ~description ?options
?options ?exit_status ?environment ?files ?notes ?bugs ?examples ~see_also command_str = ?exit_status ?environment ?files ?notes ?bugs ?examples ~see_also command_str =
let add_if section blocks = let add_if section blocks =
match blocks with None -> `Blocks [] | Some bs -> `Blocks (`S section :: bs) match blocks with None -> `Blocks [] | Some bs -> `Blocks (`S section :: bs)
in in
@ -840,8 +837,7 @@ let anon_fun arg =
(* stop parsing the current args and go look in that argfile *) (* stop parsing the current args and go look in that argfile *)
raise (SubArguments (args_from_argfile arg)) raise (SubArguments (args_from_argfile arg))
else if else if
!anon_arg_action.parse_subcommands !anon_arg_action.parse_subcommands && List.Assoc.mem !subcommand_actions ~equal:String.equal arg
&& List.Assoc.mem !subcommand_actions ~equal:String.equal arg
then then
let command_switch = List.Assoc.find_exn !subcommand_actions ~equal:String.equal arg in let command_switch = List.Assoc.find_exn !subcommand_actions ~equal:String.equal arg in
match (!curr_command, is_originator) with match (!curr_command, is_originator) with
@ -906,8 +902,8 @@ let encode_argv_to_env argv =
~f:(fun arg -> ~f:(fun arg ->
(not (String.contains arg env_var_sep)) (not (String.contains arg env_var_sep))
|| ||
( warnf "WARNING: Ignoring unsupported option containing '%c' character: %s@\n" ( warnf "WARNING: Ignoring unsupported option containing '%c' character: %s@\n" env_var_sep
env_var_sep arg ; arg ;
false ) ) false ) )
argv) argv)

@ -124,8 +124,7 @@ val mk_symbol :
(** [mk_symbol long symbols] defines a command line flag [--long <symbol>] where [(<symbol>,_)] is (** [mk_symbol long symbols] defines a command line flag [--long <symbol>] where [(<symbol>,_)] is
an element of [symbols]. *) an element of [symbols]. *)
val mk_symbol_opt : val mk_symbol_opt : symbols:(string * 'a) list -> ?f:('a -> 'a) -> ?mk_reset:bool -> 'a option ref t
symbols:(string * 'a) list -> ?f:('a -> 'a) -> ?mk_reset:bool -> 'a option ref t
(** [mk_symbol_opt] is similar to [mk_symbol] but defaults to [None]. If [mk_reset] is false then do not create an additional --[long]-reset option to reset the value of the option to [None]. *) (** [mk_symbol_opt] is similar to [mk_symbol] but defaults to [None]. If [mk_reset] is false then do not create an additional --[long]-reset option to reset the value of the option to [None]. *)
val mk_symbol_seq : val mk_symbol_seq :

@ -140,8 +140,7 @@ let build_system_of_exe_name name =
If this is an alias for another build system that infer supports, you can use@\n\ If this is an alias for another build system that infer supports, you can use@\n\
`--force-integration <command>` where <command> is one of the following supported build \ `--force-integration <command>` where <command> is one of the following supported build \
systems:@\n\ systems:@\n\
@[<v2> %a@]" @[<v2> %a@]" name
name
(Pp.seq ~print_env:Pp.text_break ~sep:"" F.pp_print_string) (Pp.seq ~print_env:Pp.text_break ~sep:"" F.pp_print_string)
( List.map ~f:fst build_system_exe_assoc ( List.map ~f:fst build_system_exe_assoc
|> List.map ~f:string_of_build_system |> List.map ~f:string_of_build_system
@ -663,9 +662,7 @@ and { annotation_reachability
; uninit } = ; uninit } =
let mk_checker ?(default = false) ?(deprecated = []) ~long doc = let mk_checker ?(default = false) ?(deprecated = []) ~long doc =
let var = let var =
CLOpt.mk_bool ~long CLOpt.mk_bool ~long ~in_help:InferCommand.[(Analyze, manual_generic)] ~default ~deprecated doc
~in_help:InferCommand.[(Analyze, manual_generic)]
~default ~deprecated doc
in in
all_checkers := (var, long, doc, default) :: !all_checkers ; all_checkers := (var, long, doc, default) :: !all_checkers ;
var var
@ -819,8 +816,8 @@ and annotation_reachability_cxx =
} }
|} |}
^ "\n\ ^ "\n\
This will cause us to create a new ISOLATED_REACHING_CONNECT issue for every function \ This will cause us to create a new ISOLATED_REACHING_CONNECT issue for every function whose \
whose source path starts with \"isolated/\" that may reach the function named \"connect\", \ source path starts with \"isolated/\" that may reach the function named \"connect\", \
ignoring paths that go through a symbol matching the OCaml regexp \".*::Trusted::.*\"." ) ignoring paths that go through a symbol matching the OCaml regexp \".*::Trusted::.*\"." )
@ -888,8 +885,8 @@ and buck_blacklist =
~long:"buck-blacklist" ~long:"buck-blacklist"
~in_help:InferCommand.[(Run, manual_buck_flavors); (Capture, manual_buck_flavors)] ~in_help:InferCommand.[(Run, manual_buck_flavors); (Capture, manual_buck_flavors)]
~meta:"regex" ~meta:"regex"
"Skip capture of files matched by the specified regular expression (only the \"flavors \ "Skip capture of files matched by the specified regular expression (only the \"flavors (C++)\" \
(C++)\" Buck integration is supported, not Java)." Buck integration is supported, not Java)."
and buck_build_args = and buck_build_args =
@ -935,8 +932,7 @@ and buck_out =
and buck_targets_blacklist = and buck_targets_blacklist =
CLOpt.mk_string_list ~long:"buck-targets-blacklist" CLOpt.mk_string_list ~long:"buck-targets-blacklist"
~in_help: ~in_help:InferCommand.[(Run, manual_buck_compilation_db); (Capture, manual_buck_compilation_db)]
InferCommand.[(Run, manual_buck_compilation_db); (Capture, manual_buck_compilation_db)]
~meta:"regex" "Skip capture of buck targets matched by the specified regular expression." ~meta:"regex" "Skip capture of buck targets matched by the specified regular expression."
@ -968,8 +964,8 @@ and censor_report =
filter is of the form: `<issue_type_regex>:<filename_regex>:<reason_string>`. The first two \ filter is of the form: `<issue_type_regex>:<filename_regex>:<reason_string>`. The first two \
components are OCaml Str regular expressions, with an optional `!` character prefix. If a \ components are OCaml Str regular expressions, with an optional `!` character prefix. If a \
regex has a `!` prefix, the polarity is inverted, and the filter becomes a \"blacklist\" \ regex has a `!` prefix, the polarity is inverted, and the filter becomes a \"blacklist\" \
instead of a \"whitelist\". Each filter is interpreted as an implication: an issue matches \ instead of a \"whitelist\". Each filter is interpreted as an implication: an issue matches if \
if it does not match the `issue_type_regex` or if it does match the `filename_regex`. The \ it does not match the `issue_type_regex` or if it does match the `filename_regex`. The \
filenames that are tested by the regex are relative to the `--project-root` directory. The \ filenames that are tested by the regex are relative to the `--project-root` directory. The \
`<reason_string>` is a non-empty string used to explain why the issue was filtered." `<reason_string>` is a non-empty string used to explain why the issue was filtered."
@ -1029,8 +1025,8 @@ and clang_ignore_regex =
and clang_idirafter_to_override_regex = and clang_idirafter_to_override_regex =
CLOpt.mk_string_opt ~long:"clang-idirafter-to-override-regex" ~meta:"dir_OCaml_regex" CLOpt.mk_string_opt ~long:"clang-idirafter-to-override-regex" ~meta:"dir_OCaml_regex"
"Use this option in the uncommon case where the normal compilation process overrides the \ "Use this option in the uncommon case where the normal compilation process overrides the \
location of internal compiler headers. This option should specify regular expression with \ location of internal compiler headers. This option should specify regular expression with the \
the path to those headers so that infer can use its own clang internal headers instead. \ path to those headers so that infer can use its own clang internal headers instead. \
Concretely, this will replace $(b,-idirafter <path matching the regex>) with $(b,-idirafter \ Concretely, this will replace $(b,-idirafter <path matching the regex>) with $(b,-idirafter \
/path/to/infer/facebook-clang-plugins/clang/install/lib/clang/<version>/include)." /path/to/infer/facebook-clang-plugins/clang/install/lib/clang/<version>/include)."
@ -1040,8 +1036,8 @@ and clang_isystem_to_override_regex =
~deprecated:["-clang-include-to-override-regex"; "-clang-include-to-override"] ~deprecated:["-clang-include-to-override-regex"; "-clang-include-to-override"]
~meta:"dir_OCaml_regex" ~meta:"dir_OCaml_regex"
"Use this option in the uncommon case where the normal compilation process overrides the \ "Use this option in the uncommon case where the normal compilation process overrides the \
location of internal compiler headers. This option should specify regular expression with \ location of internal compiler headers. This option should specify regular expression with the \
the path to those headers so that infer can use its own clang internal headers instead. \ path to those headers so that infer can use its own clang internal headers instead. \
Concretely, this will replace $(b,-isystem <path matching the regex>) with $(b,-isystem \ Concretely, this will replace $(b,-isystem <path matching the regex>) with $(b,-isystem \
/path/to/infer/facebook-clang-plugins/clang/install/lib/clang/<version>/include)." /path/to/infer/facebook-clang-plugins/clang/install/lib/clang/<version>/include)."
@ -1069,8 +1065,8 @@ and compilation_database_escaped =
CLOpt.mk_path_list ~long:"compilation-database-escaped" CLOpt.mk_path_list ~long:"compilation-database-escaped"
~deprecated:["-clang-compilation-db-files-escaped"] ~deprecated:["-clang-compilation-db-files-escaped"]
~in_help:InferCommand.[(Capture, manual_clang)] ~in_help:InferCommand.[(Capture, manual_clang)]
"File that contain compilation commands where all entries are escaped for the shell, eg \ "File that contain compilation commands where all entries are escaped for the shell, eg coming \
coming from Xcode (can be specified multiple times)" from Xcode (can be specified multiple times)"
and compute_analytics = and compute_analytics =
@ -1195,8 +1191,7 @@ and ( biabduction_models_mode
and print_buckets = and print_buckets =
CLOpt.mk_bool ~long:"print-buckets" CLOpt.mk_bool ~long:"print-buckets"
"Show the internal bucket of Infer reports in their textual description" "Show the internal bucket of Infer reports in their textual description"
and print_types = and print_types = CLOpt.mk_bool ~long:"print-types" ~default:false "Print types in symbolic heaps"
CLOpt.mk_bool ~long:"print-types" ~default:false "Print types in symbolic heaps"
and keep_going = and keep_going =
CLOpt.mk_bool ~deprecated_no:["-no-failures-allowed"] ~long:"keep-going" CLOpt.mk_bool ~deprecated_no:["-no-failures-allowed"] ~long:"keep-going"
~in_help:InferCommand.[(Analyze, manual_generic)] ~in_help:InferCommand.[(Analyze, manual_generic)]
@ -1327,8 +1322,8 @@ and differential_filter_files =
and differential_filter_set = and differential_filter_set =
CLOpt.mk_symbol_seq ~long:"differential-filter-set" ~eq:PolyVariantEqual.( = ) CLOpt.mk_symbol_seq ~long:"differential-filter-set" ~eq:PolyVariantEqual.( = )
"Specify which set of the differential results is filtered with the modified files provided \ "Specify which set of the differential results is filtered with the modified files provided \
through the $(b,--differential-modified-files) argument. By default it is applied to all \ through the $(b,--differential-modified-files) argument. By default it is applied to all sets \
sets ($(b,introduced), $(b,fixed), and $(b,preexisting))" ($(b,introduced), $(b,fixed), and $(b,preexisting))"
~symbols:[("introduced", `Introduced); ("fixed", `Fixed); ("preexisting", `Preexisting)] ~symbols:[("introduced", `Introduced); ("fixed", `Fixed); ("preexisting", `Preexisting)]
~default:[`Introduced; `Fixed; `Preexisting] ~default:[`Introduced; `Fixed; `Preexisting]
@ -1400,16 +1395,14 @@ and eradicate_return_over_annotated =
CLOpt.mk_bool ~long:"eradicate-return-over-annotated" "Return over-annotated warning" CLOpt.mk_bool ~long:"eradicate-return-over-annotated" "Return over-annotated warning"
and eradicate_verbose = and eradicate_verbose = CLOpt.mk_bool ~long:"eradicate-verbose" "Print initial and final typestates"
CLOpt.mk_bool ~long:"eradicate-verbose" "Print initial and final typestates"
and external_java_packages = and external_java_packages =
CLOpt.mk_string_list ~long:"external-java-packages" CLOpt.mk_string_list ~long:"external-java-packages"
~in_help:InferCommand.[(Analyze, manual_java)] ~in_help:InferCommand.[(Analyze, manual_java)]
~meta:"prefix" ~meta:"prefix"
"Specify a list of Java package prefixes for external Java packages. If set, the analysis \ "Specify a list of Java package prefixes for external Java packages. If set, the analysis will \
will not report non-actionable warnings on those packages." not report non-actionable warnings on those packages."
and fail_on_bug = and fail_on_bug =
@ -1464,8 +1457,8 @@ and from_json_report =
CLOpt.mk_path_opt ~long:"from-json-report" CLOpt.mk_path_opt ~long:"from-json-report"
~in_help:InferCommand.[(Report, manual_generic)] ~in_help:InferCommand.[(Report, manual_generic)]
~meta:"report.json" ~meta:"report.json"
"Load analysis results from a report file (default is to load the results from the specs \ "Load analysis results from a report file (default is to load the results from the specs files \
files generated by the analysis)." generated by the analysis)."
and frontend_stats = and frontend_stats =
@ -1540,8 +1533,8 @@ and hoisting_report_only_expensive =
and icfg_dotty_outfile = and icfg_dotty_outfile =
CLOpt.mk_path_opt ~long:"icfg-dotty-outfile" ~meta:"path" CLOpt.mk_path_opt ~long:"icfg-dotty-outfile" ~meta:"path"
"If set, specifies path where .dot file should be written, it overrides the path for all \ "If set, specifies path where .dot file should be written, it overrides the path for all other \
other options that would generate icfg file otherwise" options that would generate icfg file otherwise"
and iphoneos_target_sdk_version = and iphoneos_target_sdk_version =
@ -1623,9 +1616,9 @@ and liveness_dangerous_classes =
CLOpt.mk_json ~long:"liveness-dangerous-classes" CLOpt.mk_json ~long:"liveness-dangerous-classes"
~in_help:InferCommand.[(Analyze, manual_clang)] ~in_help:InferCommand.[(Analyze, manual_clang)]
"Specify classes where the destructor should be ignored when computing liveness. In other \ "Specify classes where the destructor should be ignored when computing liveness. In other \
words, assignement to variables of these types (or common wrappers around these types such \ words, assignement to variables of these types (or common wrappers around these types such as \
as $(i,unique_ptr<type>)) will count as dead stores when the variables are not read \ $(i,unique_ptr<type>)) will count as dead stores when the variables are not read explicitly \
explicitly by the program." by the program."
and log_events = and log_events =
@ -1695,8 +1688,7 @@ and linters_ignore_clang_failures =
and linters_validate_syntax_only = and linters_validate_syntax_only =
CLOpt.mk_bool ~long:"linters-validate-syntax-only" CLOpt.mk_bool ~long:"linters-validate-syntax-only"
~in_help:InferCommand.[(Capture, manual_clang_linters)] ~in_help:InferCommand.[(Capture, manual_clang_linters)]
~default:false ~default:false "Validate syntax of AL files, then emit possible errors in JSON format to stdout"
"Validate syntax of AL files, then emit possible errors in JSON format to stdout"
and load_average = and load_average =
@ -1760,8 +1752,8 @@ and nullable_annotation =
and nullsafe_third_party_signatures = and nullsafe_third_party_signatures =
CLOpt.mk_string_opt ~long:"nullsafe-third-party-signatures" CLOpt.mk_string_opt ~long:"nullsafe-third-party-signatures"
"Path to a folder with annotated signatures of third-party methods to be taken into account \ "Path to a folder with annotated signatures of third-party methods to be taken into account by \
by nullsafe. Path is either relative to .inferconfig folder or absolute" nullsafe. Path is either relative to .inferconfig folder or absolute"
and nullsafe_strict_containers = and nullsafe_strict_containers =
@ -1869,8 +1861,8 @@ and procedures_attributes =
and procedures_definedness = and procedures_definedness =
CLOpt.mk_bool ~long:"procedures-definedness" ~default:true CLOpt.mk_bool ~long:"procedures-definedness" ~default:true
~in_help:InferCommand.[(Explore, manual_explore_procedures)] ~in_help:InferCommand.[(Explore, manual_explore_procedures)]
"Include procedures definedness in the output of $(b,--procedures), i.e. whether the \ "Include procedures definedness in the output of $(b,--procedures), i.e. whether the procedure \
procedure definition was found, or only the procedure declaration, or the procedure is an \ definition was found, or only the procedure declaration, or the procedure is an \
auto-generated Objective-C accessor" auto-generated Objective-C accessor"
@ -1878,8 +1870,8 @@ and procedures_filter =
CLOpt.mk_string_opt ~long:"procedures-filter" ~meta:"filter" CLOpt.mk_string_opt ~long:"procedures-filter" ~meta:"filter"
~in_help:InferCommand.[(Explore, manual_explore_procedures)] ~in_help:InferCommand.[(Explore, manual_explore_procedures)]
"With $(b,--procedures), only print functions and methods (procedures) matching the specified \ "With $(b,--procedures), only print functions and methods (procedures) matching the specified \
$(i,filter). A procedure filter is of the form $(i,path_pattern:procedure_name). Patterns \ $(i,filter). A procedure filter is of the form $(i,path_pattern:procedure_name). Patterns are \
are interpreted as OCaml Str regular expressions. For instance, to keep only methods named \ interpreted as OCaml Str regular expressions. For instance, to keep only methods named \
\"foo\", one can use the filter \".*:foo\", or \"foo\" for short." \"foo\", one can use the filter \".*:foo\", or \"foo\" for short."
@ -2097,8 +2089,7 @@ and rest =
~in_help:InferCommand.[(Capture, manual_generic); (Run, manual_generic)] ~in_help:InferCommand.[(Capture, manual_generic); (Run, manual_generic)]
"Stop argument processing, use remaining arguments as a build command" ~usage:exe_usage "Stop argument processing, use remaining arguments as a build command" ~usage:exe_usage
(fun build_exe -> (fun build_exe ->
match Filename.basename build_exe with "java" | "javac" -> CLOpt.Javac | _ -> CLOpt.NoParse match Filename.basename build_exe with "java" | "javac" -> CLOpt.Javac | _ -> CLOpt.NoParse )
)
and results_dir = and results_dir =
@ -2136,8 +2127,8 @@ and scuba_normals =
and siof_safe_methods = and siof_safe_methods =
CLOpt.mk_string_list ~long:"siof-safe-methods" CLOpt.mk_string_list ~long:"siof-safe-methods"
~in_help:InferCommand.[(Analyze, manual_siof)] ~in_help:InferCommand.[(Analyze, manual_siof)]
"Methods that are SIOF-safe; \"foo::bar\" will match \"foo::bar()\", \"foo<int>::bar()\", \ "Methods that are SIOF-safe; \"foo::bar\" will match \"foo::bar()\", \"foo<int>::bar()\", etc. \
etc. (can be specified multiple times)" (can be specified multiple times)"
and skip_analysis_in_path = and skip_analysis_in_path =
@ -2263,8 +2254,8 @@ and sqlite_cache_size =
CLOpt.mk_int ~long:"sqlite-cache-size" ~default:2000 CLOpt.mk_int ~long:"sqlite-cache-size" ~default:2000
~in_help: ~in_help:
InferCommand.[(Analyze, manual_generic); (Capture, manual_generic); (Run, manual_generic)] InferCommand.[(Analyze, manual_generic); (Capture, manual_generic); (Run, manual_generic)]
"SQLite cache size in pages (if positive) or kB (if negative), follows formal of \ "SQLite cache size in pages (if positive) or kB (if negative), follows formal of corresponding \
corresponding SQLite PRAGMA." SQLite PRAGMA."
and sqlite_page_size = and sqlite_page_size =
@ -2421,8 +2412,7 @@ and type_size =
and uninit_interproc = and uninit_interproc =
CLOpt.mk_bool ~long:"uninit-interproc" CLOpt.mk_bool ~long:"uninit-interproc" "Run uninit check in the experimental interprocedural mode"
"Run uninit check in the experimental interprocedural mode"
and unsafe_malloc = and unsafe_malloc =

@ -44,8 +44,7 @@ module Implementation = struct
let replace_attributes ~pname_str ~pname ~akind ~source_file ~attributes ~proc_desc ~callees = let replace_attributes ~pname_str ~pname ~akind ~source_file ~attributes ~proc_desc ~callees =
ResultsDatabase.with_registered_statement attribute_replace_statement ResultsDatabase.with_registered_statement attribute_replace_statement ~f:(fun db replace_stmt ->
~f:(fun db replace_stmt ->
Sqlite3.bind replace_stmt 1 (* :pname *) pname Sqlite3.bind replace_stmt 1 (* :pname *) pname
|> SqliteUtils.check_result_code db ~log:"replace bind pname" ; |> SqliteUtils.check_result_code db ~log:"replace bind pname" ;
Sqlite3.bind replace_stmt 2 (* :proc_name_hum *) (Sqlite3.Data.TEXT pname_str) Sqlite3.bind replace_stmt 2 (* :proc_name_hum *) (Sqlite3.Data.TEXT pname_str)
@ -146,13 +145,11 @@ module Implementation = struct
let db_file = infer_out_src ^/ ResultsDatabase.database_filename in let db_file = infer_out_src ^/ ResultsDatabase.database_filename in
let main_db = ResultsDatabase.get_database () in let main_db = ResultsDatabase.get_database () in
Sqlite3.exec main_db (Printf.sprintf "ATTACH '%s' AS attached" db_file) Sqlite3.exec main_db (Printf.sprintf "ATTACH '%s' AS attached" db_file)
|> SqliteUtils.check_result_code main_db |> SqliteUtils.check_result_code main_db ~log:(Printf.sprintf "attaching database '%s'" db_file) ;
~log:(Printf.sprintf "attaching database '%s'" db_file) ;
merge_procedures_table ~db_file ; merge_procedures_table ~db_file ;
merge_source_files_table ~db_file ; merge_source_files_table ~db_file ;
Sqlite3.exec main_db "DETACH attached" Sqlite3.exec main_db "DETACH attached"
|> SqliteUtils.check_result_code main_db |> SqliteUtils.check_result_code main_db ~log:(Printf.sprintf "detaching database '%s'" db_file)
~log:(Printf.sprintf "detaching database '%s'" db_file)
let merge infer_deps_file = let merge infer_deps_file =

@ -16,8 +16,8 @@ exception InferInternalError of string
exception InferUserError of string exception InferUserError of string
(** This can be used to avoid scattering exit invocations all over the codebase *)
exception InferExit of int exception InferExit of int
(** This can be used to avoid scattering exit invocations all over the codebase *)
(** kind of error for [die], with similar semantics as [Logging.{external,internal,user}_error] *) (** kind of error for [die], with similar semantics as [Logging.{external,internal,user}_error] *)
type error = ExternalError | InternalError | UserError type error = ExternalError | InternalError | UserError

@ -145,8 +145,7 @@ let checkers_allocates_memory =
let checkers_annotation_reachability_error = let checkers_annotation_reachability_error =
register_from_string "CHECKERS_ANNOTATION_REACHABILITY_ERROR" register_from_string "CHECKERS_ANNOTATION_REACHABILITY_ERROR" ~hum:"Annotation Reachability Error"
~hum:"Annotation Reachability Error"
let checkers_calls_expensive_method = let checkers_calls_expensive_method =

@ -17,9 +17,7 @@ let add_float ({floats} as t) ~key ~data = {t with floats= String.Map.set floats
let add_string ({strings} as t) ~key ~data = {t with strings= String.Map.set strings ~key ~data} let add_string ({strings} as t) ~key ~data = {t with strings= String.Map.set strings ~key ~data}
let add_string_opt t ~key ~data = let add_string_opt t ~key ~data = match data with Some data -> add_string t ~key ~data | None -> t
match data with Some data -> add_string t ~key ~data | None -> t
let yojson_of_integers integers = let yojson_of_integers integers =
let f ~key ~data acc = (key, `Int data) :: acc in let f ~key ~data acc = (key, `Int data) :: acc in

@ -134,7 +134,7 @@ let register_formatter =
let formatters = mk_formatters () in let formatters = mk_formatters () in
let formatters_ref = ref formatters in let formatters_ref = ref formatters in
logging_formatters := ((formatters_ref, mk_formatters), formatters) :: !logging_formatters ; logging_formatters := ((formatters_ref, mk_formatters), formatters) :: !logging_formatters ;
formatters_ref) formatters_ref )
let flush_formatters {file; console_file} = let flush_formatters {file; console_file} =
@ -209,9 +209,7 @@ let phase fmt = log ~to_console:false phase_file_fmts fmt
let progress fmt = log ~to_console:(not Config.quiet) progress_file_fmts fmt let progress fmt = log ~to_console:(not Config.quiet) progress_file_fmts fmt
let log_task fmt = let log_task fmt =
let to_console = let to_console = match Config.progress_bar with `Plain -> true | `Quiet | `MultiLine -> false in
match Config.progress_bar with `Plain -> true | `Quiet | `MultiLine -> false
in
log ~to_console progress_file_fmts fmt log ~to_console progress_file_fmts fmt
@ -277,9 +275,7 @@ let internal_error fmt = log ~to_console:true internal_error_file_fmts fmt
type ocaml_pos = string * int * int * int type ocaml_pos = string * int * int * int
(** Convert a ml location to a string *) (** Convert a ml location to a string *)
let ocaml_pos_to_string (file, lnum, cnum, enum) = let ocaml_pos_to_string (file, lnum, cnum, enum) = Printf.sprintf "%s:%d:%d-%d:" file lnum cnum enum
Printf.sprintf "%s:%d:%d-%d:" file lnum cnum enum
(** Pretty print a location of ml source *) (** Pretty print a location of ml source *)
let pp_ocaml_pos fmt ocaml_pos = F.pp_print_string fmt (ocaml_pos_to_string ocaml_pos) let pp_ocaml_pos fmt ocaml_pos = F.pp_print_string fmt (ocaml_pos_to_string ocaml_pos)

@ -61,8 +61,8 @@ val debug : debug_kind -> debug_level -> ('a, F.formatter, unit) format -> 'a
val debug_dev : ('a, Format.formatter, unit) format -> 'a val debug_dev : ('a, Format.formatter, unit) format -> 'a
[@@deprecated [@@deprecated
"Only use to debug during development. If you want more permanent logging, use \ "Only use to debug during development. If you want more permanent logging, use [Logging.debug] \
[Logging.debug] instead."] instead."]
[@@warning "-32"] [@@warning "-32"]
(** For debugging during development. *) (** For debugging during development. *)

@ -245,7 +245,7 @@ let logger =
else else
(* assume the trace file is here and is ready to accept list elements *) (* assume the trace file is here and is ready to accept list elements *)
JsonFragment.(pp_state := InList :: !pp_state) ) ; JsonFragment.(pp_state := InList :: !pp_state) ) ;
logger) logger )
(* export logging functions that output a list element at a time and flushes so that multiple (* export logging functions that output a list element at a time and flushes so that multiple

@ -270,8 +270,7 @@ let process_updates pool buffer =
(* try to schedule more work if there are idle workers *) (* try to schedule more work if there are idle workers *)
if not (pool.tasks.is_empty ()) then if not (pool.tasks.is_empty ()) then
Array.iteri pool.children_states ~f:(fun slot state -> Array.iteri pool.children_states ~f:(fun slot state ->
match state with Idle -> send_work_to_child pool slot | Initializing | Processing _ -> () match state with Idle -> send_work_to_child pool slot | Initializing | Processing _ -> () )
)
type 'a final_worker_message = Finished of int * 'a option | FinalCrash of int type 'a final_worker_message = Finished of int * 'a option | FinalCrash of int

@ -58,8 +58,7 @@ let remove_results_dir () =
Result.iter_error (is_results_dir ~check_correct_version:false ()) ~f:(fun err -> Result.iter_error (is_results_dir ~check_correct_version:false ()) ~f:(fun err ->
L.(die UserError) L.(die UserError)
"ERROR: '%s' exists but does not seem to be an infer results directory: %s@\n\ "ERROR: '%s' exists but does not seem to be an infer results directory: %s@\n\
ERROR: Please delete '%s' and try again@." ERROR: Please delete '%s' and try again@." Config.results_dir err Config.results_dir ) ;
Config.results_dir err Config.results_dir ) ;
Utils.rmtree Config.results_dir ) ; Utils.rmtree Config.results_dir ) ;
RunState.reset () RunState.reset ()
@ -81,8 +80,8 @@ let create_results_dir () =
L.progress "Deleting results dir because --force-delete-results-dir was passed@." ; L.progress "Deleting results dir because --force-delete-results-dir was passed@." ;
remove_results_dir () ) remove_results_dir () )
else else
L.die UserError "ERROR: %s@\nPlease remove '%s' and try again" error L.die UserError "ERROR: %s@\nPlease remove '%s' and try again" error Config.results_dir
Config.results_dir ) ; ) ;
Unix.mkdir_p Config.results_dir ; Unix.mkdir_p Config.results_dir ;
Unix.mkdir_p (Config.results_dir ^/ Config.events_dir_name) ; Unix.mkdir_p (Config.results_dir ^/ Config.events_dir_name) ;
List.iter ~f:Unix.mkdir_p results_dir_dir_markers ; List.iter ~f:Unix.mkdir_p results_dir_dir_markers ;

@ -47,8 +47,7 @@ let load_and_validate () =
"'%s' already exists but it is not an empty directory and it does not look like an \ "'%s' already exists but it is not an empty directory and it does not look like an \
infer results directory:\n\ infer results directory:\n\
\ %s\n\ \ %s\n\
Was it created using an older version of infer?" Was it created using an older version of infer?" Config.results_dir err_msg) )
Config.results_dir err_msg) )
msg msg
in in
if Sys.file_exists state_file_path <> `Yes then if Sys.file_exists state_file_path <> `Yes then

@ -100,9 +100,7 @@ let line_count source_file =
count_newlines abs_path count_newlines abs_path
let to_rel_path fname = let to_rel_path fname = match fname with RelativeProjectRoot path -> path | _ -> to_abs_path fname
match fname with RelativeProjectRoot path -> path | _ -> to_abs_path fname
let invalid ml_source_file = Invalid {ml_source_file} let invalid ml_source_file = Invalid {ml_source_file}

@ -9,11 +9,11 @@ open! IStd
type t [@@deriving compare] type t [@@deriving compare]
(** Maps from source_file *)
module Map : Caml.Map.S with type key = t module Map : Caml.Map.S with type key = t
(** Maps from source_file *)
(** Set of source files *)
module Set : Caml.Set.S with type elt = t module Set : Caml.Set.S with type elt = t
(** Set of source files *)
module Hash : Caml.Hashtbl.S with type key = t module Hash : Caml.Hashtbl.S with type key = t

@ -25,8 +25,7 @@ let exec db ~log ~stmt =
PerfEvent.log_begin_event logger ~name:"sql exec" ~arguments:[("stmt", `String log)] () ) ; PerfEvent.log_begin_event logger ~name:"sql exec" ~arguments:[("stmt", `String log)] () ) ;
let rc = Sqlite3.exec db stmt in let rc = Sqlite3.exec db stmt in
PerfEvent.(log (fun logger -> log_end_event logger ())) ; PerfEvent.(log (fun logger -> log_end_event logger ())) ;
try check_result_code db ~log rc try check_result_code db ~log rc with Error err -> error "exec: %s (%s)" err (Sqlite3.errmsg db)
with Error err -> error "exec: %s (%s)" err (Sqlite3.errmsg db)
let finalize db ~log stmt = let finalize db ~log stmt =
@ -48,8 +47,7 @@ let result_fold_rows ?finalize:(do_finalize = true) db ~log stmt ~init ~f =
| err -> | err ->
L.die InternalError "%s: %s (%s)" log (Sqlite3.Rc.to_string err) (Sqlite3.errmsg db) L.die InternalError "%s: %s (%s)" log (Sqlite3.Rc.to_string err) (Sqlite3.errmsg db)
in in
if do_finalize then if do_finalize then protect ~finally:(fun () -> finalize db ~log stmt) ~f:(fun () -> aux init stmt)
protect ~finally:(fun () -> finalize db ~log stmt) ~f:(fun () -> aux init stmt)
else aux init stmt else aux init stmt
@ -64,8 +62,7 @@ let zero_or_one_row ~log = function
| [x] -> | [x] ->
Some x Some x
| _ :: _ :: _ as l -> | _ :: _ :: _ as l ->
L.die InternalError "%s: zero or one result expected, got %d rows instead" log L.die InternalError "%s: zero or one result expected, got %d rows instead" log (List.length l)
(List.length l)
let result_option ?finalize db ~log ~read_row stmt = let result_option ?finalize db ~log ~read_row stmt =
@ -79,8 +76,7 @@ let result_single_column_option ?finalize db ~log stmt =
let result_unit ?finalize db ~log stmt = let result_unit ?finalize db ~log stmt =
if if not (Container.is_empty stmt ~iter:(Container.iter ~fold:(result_fold_rows ?finalize db ~log)))
not (Container.is_empty stmt ~iter:(Container.iter ~fold:(result_fold_rows ?finalize db ~log)))
then L.die InternalError "%s: the SQLite query should not return any rows" log then L.die InternalError "%s: the SQLite query should not return any rows" log

@ -7,9 +7,9 @@
open! IStd open! IStd
exception Error of string
(** The functions in this module tend to raise more often than their counterparts in [Sqlite3]. In (** The functions in this module tend to raise more often than their counterparts in [Sqlite3]. In
particular, they may raise if the [Sqlite3.Rc.t] result of certain operations is unexpected. *) particular, they may raise if the [Sqlite3.Rc.t] result of certain operations is unexpected. *)
exception Error of string
val check_result_code : Sqlite3.db -> log:string -> Sqlite3.Rc.t -> unit val check_result_code : Sqlite3.db -> log:string -> Sqlite3.Rc.t -> unit
(** Assert that the result is either [Sqlite3.Rc.OK] or [Sqlite3.Rc.ROW]. If the result is not (** Assert that the result is either [Sqlite3.Rc.OK] or [Sqlite3.Rc.ROW]. If the result is not

@ -17,8 +17,8 @@ type failure_kind =
| FKrecursion_timeout of int (** max recursion level exceeded *) | FKrecursion_timeout of int (** max recursion level exceeded *)
| FKcrash of string (** uncaught exception or failed assertion *) | FKcrash of string (** uncaught exception or failed assertion *)
(** failure that prevented analysis from finishing *)
exception Analysis_failure_exe of failure_kind exception Analysis_failure_exe of failure_kind
(** failure that prevented analysis from finishing *)
let exn_not_failure = function Analysis_failure_exe _ -> false | _ -> true let exn_not_failure = function Analysis_failure_exe _ -> false | _ -> true

@ -59,8 +59,8 @@ type failure_kind =
| FKrecursion_timeout of int (** max recursion level exceeded *) | FKrecursion_timeout of int (** max recursion level exceeded *)
| FKcrash of string (** uncaught exception or failed assertion *) | FKcrash of string (** uncaught exception or failed assertion *)
(** Timeout exception *)
exception Analysis_failure_exe of failure_kind exception Analysis_failure_exe of failure_kind
(** Timeout exception *)
val exn_not_failure : exn -> bool val exn_not_failure : exn -> bool
(** check that the exception is not a timeout exception *) (** check that the exception is not a timeout exception *)

@ -70,8 +70,7 @@ let draw_top_bar fmt ~term_width ~total ~finished ~elapsed =
++ ( "%s" ++ ( "%s"
, max (String.length elapsed_string) 9 , max (String.length elapsed_string) 9
(* leave some room for elapsed_string to avoid flicker. 9 characters is "XXhXXmXXs" so it (* leave some room for elapsed_string to avoid flicker. 9 characters is "XXhXXmXXs" so it
gives some reasonable margin. *) gives some reasonable margin. *) )
)
in in
let top_bar_size = min term_width top_bar_size_default in let top_bar_size = min term_width top_bar_size_default in
let progress_bar_size = top_bar_size - size_around_progress_bar in let progress_bar_size = top_bar_size - size_around_progress_bar in

@ -212,9 +212,7 @@ let with_file_lock ~file_lock:{file; oc; fd} ~f =
let with_intermediate_temp_file_out file ~f = let with_intermediate_temp_file_out file ~f =
let temp_filename, temp_oc = let temp_filename, temp_oc = Filename.open_temp_file ~in_dir:(Filename.dirname file) "infer" "" in
Filename.open_temp_file ~in_dir:(Filename.dirname file) "infer" ""
in
let f () = f temp_oc in let f () = f temp_oc in
let finally () = let finally () =
Out_channel.close temp_oc ; Out_channel.close temp_oc ;

@ -50,7 +50,7 @@ let zip_libraries =
&& (not Config.biabduction_models_mode) && (not Config.biabduction_models_mode)
&& Sys.file_exists Config.biabduction_models_jar = `Yes && Sys.file_exists Config.biabduction_models_jar = `Yes
then mk_zip_lib Config.biabduction_models_jar :: zip_libs then mk_zip_lib Config.biabduction_models_jar :: zip_libs
else zip_libs) else zip_libs )
(** Search path in the list of zip libraries and use a cache directory to save already deserialized (** Search path in the list of zip libraries and use a cache directory to save already deserialized

@ -457,8 +457,8 @@ let blur_array_indices tenv (p : Prop.normal Prop.t) (root : StrexpMatch.path)
(** Given [p] containing an array at [root], only keep [indices] in it *) (** Given [p] containing an array at [root], only keep [indices] in it *)
let keep_only_indices tenv (p : Prop.normal Prop.t) (path : StrexpMatch.path) let keep_only_indices tenv (p : Prop.normal Prop.t) (path : StrexpMatch.path) (indices : Exp.t list)
(indices : Exp.t list) : Prop.normal Prop.t * bool = : Prop.normal Prop.t * bool =
let prune_sigma footprint_part sigma = let prune_sigma footprint_part sigma =
try try
let matched = StrexpMatch.find_path sigma path in let matched = StrexpMatch.find_path sigma path in
@ -509,16 +509,16 @@ let strexp_do_abstract tenv footprint_part p ((path, se_in, _) : StrexpMatch.str
if Config.trace_absarray && not footprint_part then L.d_strln "strexp_do_abstract (nonfootprint)" ; if Config.trace_absarray && not footprint_part then L.d_strln "strexp_do_abstract (nonfootprint)" ;
let prune_and_blur d_keys keep blur path keep_keys blur_keys = let prune_and_blur d_keys keep blur path keep_keys blur_keys =
let p2, changed2 = let p2, changed2 =
if Config.trace_absarray then ( L.d_str "keep " ; d_keys keep_keys ; L.d_ln () ) ; if Config.trace_absarray then (L.d_str "keep " ; d_keys keep_keys ; L.d_ln ()) ;
keep p path keep_keys keep p path keep_keys
in in
let p3, changed3 = let p3, changed3 =
if List.is_empty blur_keys then (p2, false) if List.is_empty blur_keys then (p2, false)
else ( else (
if Config.trace_absarray then ( L.d_str "blur " ; d_keys blur_keys ; L.d_ln () ) ; if Config.trace_absarray then (L.d_str "blur " ; d_keys blur_keys ; L.d_ln ()) ;
blur p2 path blur_keys ) blur p2 path blur_keys )
in in
if Config.trace_absarray then ( L.d_strln "Returns" ; Prop.d_prop p3 ; L.d_ln () ; L.d_ln () ) ; if Config.trace_absarray then (L.d_strln "Returns" ; Prop.d_prop p3 ; L.d_ln () ; L.d_ln ()) ;
(p3, changed2 || changed3) (p3, changed2 || changed3)
in in
let prune_and_blur_indices = let prune_and_blur_indices =
@ -549,7 +549,7 @@ let strexp_do_abstract tenv footprint_part p ((path, se_in, _) : StrexpMatch.str
let keep_ksel = List.filter ~f:should_keep ksel in let keep_ksel = List.filter ~f:should_keep ksel in
let keep_keys = List.map ~f:fst keep_ksel in let keep_keys = List.map ~f:fst keep_ksel in
let keep_keys' = if List.is_empty keep_keys then default_keys else keep_keys in let keep_keys' = if List.is_empty keep_keys then default_keys else keep_keys in
if Config.trace_absarray then ( L.d_str "keep " ; d_keys keep_keys' ; L.d_ln () ) ; if Config.trace_absarray then (L.d_str "keep " ; d_keys keep_keys' ; L.d_ln ()) ;
abstract keep_keys' [] abstract keep_keys' []
in in
let do_array_reexecution esel = let do_array_reexecution esel =

@ -41,8 +41,8 @@ module Jprop : sig
(** Extract the toplevel jprop of a prop *) (** Extract the toplevel jprop of a prop *)
end end
(** set of visited nodes: node id and list of lines of all the instructions *)
module Visitedset : Caml.Set.S with type elt = Procdesc.Node.id * int list module Visitedset : Caml.Set.S with type elt = Procdesc.Node.id * int list
(** set of visited nodes: node id and list of lines of all the instructions *)
(** A spec consists of: (** A spec consists of:
pre: a joined prop pre: a joined prop

@ -121,13 +121,10 @@ let check_access access_opt de_opt =
Instrs.exists ~f:filter (Procdesc.Node.get_instrs node) Instrs.exists ~f:filter (Procdesc.Node.get_instrs node)
in in
let do_node node = let do_node node =
Int.equal (Procdesc.Node.get_loc node).Location.line line_number Int.equal (Procdesc.Node.get_loc node).Location.line line_number && has_call_or_sets_null node
&& has_call_or_sets_null node
in in
let path, pos_opt = State.get_path () in let path, pos_opt = State.get_path () in
match match IContainer.rev_filter_to_list path ~fold:Paths.Path.fold_all_nodes_nocalls ~f:do_node with
IContainer.rev_filter_to_list path ~fold:Paths.Path.fold_all_nodes_nocalls ~f:do_node
with
| [] -> | [] ->
None None
| local_access_nodes -> | local_access_nodes ->

@ -20,8 +20,7 @@ let execute___builtin_va_arg {Builtin.summary; tenv; prop_; path; args; loc; exe
match args with match args with
| [(lexp3, typ3)] -> | [(lexp3, typ3)] ->
let instr' = Sil.Store {e1= lexp3; root_typ= typ3; typ= typ3; e2= Exp.zero; loc} in let instr' = Sil.Store {e1= lexp3; root_typ= typ3; typ= typ3; e2= Exp.zero; loc} in
SymExec.instrs ~mask_errors:true exe_env tenv summary (Instrs.singleton instr') SymExec.instrs ~mask_errors:true exe_env tenv summary (Instrs.singleton instr') [(prop_, path)]
[(prop_, path)]
| _ -> | _ ->
raise (Exceptions.Wrong_argument_number __POS__) raise (Exceptions.Wrong_argument_number __POS__)
@ -86,8 +85,7 @@ let add_array_to_prop tenv pdesc prop_ lexp typ =
(* Add an array in prop if it is not allocated.*) (* Add an array in prop if it is not allocated.*)
let execute___require_allocated_array {Builtin.tenv; summary; prop_; path; args} : Builtin.ret_typ let execute___require_allocated_array {Builtin.tenv; summary; prop_; path; args} : Builtin.ret_typ =
=
let pdesc = Summary.get_proc_desc summary in let pdesc = Summary.get_proc_desc summary in
match args with match args with
| [(lexp, typ)] -> ( | [(lexp, typ)] -> (
@ -173,8 +171,7 @@ let create_type tenv n_lexp typ prop =
| Typ.Tptr (typ', _) -> | Typ.Tptr (typ', _) ->
let sexp = Sil.Estruct ([], Sil.inst_none) in let sexp = Sil.Estruct ([], Sil.inst_none) in
let texp = let texp =
Exp.Sizeof Exp.Sizeof {typ= typ'; nbytes= None; dynamic_length= None; subtype= Subtype.subtypes}
{typ= typ'; nbytes= None; dynamic_length= None; subtype= Subtype.subtypes}
in in
let hpred = Prop.mk_ptsto tenv n_lexp sexp texp in let hpred = Prop.mk_ptsto tenv n_lexp sexp texp in
Some hpred Some hpred
@ -215,8 +212,7 @@ let create_type tenv n_lexp typ prop =
else null_case @ non_null_case else null_case @ non_null_case
let execute___get_type_of {Builtin.summary; tenv; prop_; path; ret_id_typ; args} : Builtin.ret_typ let execute___get_type_of {Builtin.summary; tenv; prop_; path; ret_id_typ; args} : Builtin.ret_typ =
=
match args with match args with
| [(lexp, typ)] -> | [(lexp, typ)] ->
let pname = Summary.get_proc_name summary in let pname = Summary.get_proc_name summary in
@ -364,8 +360,7 @@ let set_resource_attribute tenv prop path n_lexp loc ra_res =
(** Set the attibute of the value as file *) (** Set the attibute of the value as file *)
let execute___set_file_attribute {Builtin.tenv; summary; prop_; path; args; loc} : Builtin.ret_typ let execute___set_file_attribute {Builtin.tenv; summary; prop_; path; args; loc} : Builtin.ret_typ =
=
match args with match args with
| [(lexp, _)] -> | [(lexp, _)] ->
let pname = Summary.get_proc_name summary in let pname = Summary.get_proc_name summary in
@ -421,8 +416,7 @@ let execute___set_attr attr {Builtin.tenv; summary; prop_; path; args} : Builtin
(** Delete the locked attibute of the value*) (** Delete the locked attibute of the value*)
let execute___delete_locked_attribute {Builtin.tenv; prop_; summary; path; args} : Builtin.ret_typ let execute___delete_locked_attribute {Builtin.tenv; prop_; summary; path; args} : Builtin.ret_typ =
=
match args with match args with
| [(lexp, _)] -> | [(lexp, _)] ->
delete_attr tenv (Summary.get_proc_desc summary) prop_ path lexp PredSymb.Alocked delete_attr tenv (Summary.get_proc_desc summary) prop_ path lexp PredSymb.Alocked
@ -497,8 +491,8 @@ let execute_free_nonzero_ mk ?(mark_as_freed = true) pdesc tenv instr prop lexp
raise (Exceptions.Array_of_pointsto __POS__) ) raise (Exceptions.Array_of_pointsto __POS__) )
let execute_free mk ?(mark_as_freed = true) {Builtin.summary; instr; tenv; prop_; path; args; loc} let execute_free mk ?(mark_as_freed = true) {Builtin.summary; instr; tenv; prop_; path; args; loc} :
: Builtin.ret_typ = Builtin.ret_typ =
match args with match args with
| [(lexp, typ)] -> | [(lexp, typ)] ->
let pname = Summary.get_proc_name summary in let pname = Summary.get_proc_name summary in
@ -607,8 +601,8 @@ let execute_alloc mk can_return_null {Builtin.summary; tenv; prop_; path; ret_id
else [(prop_alloc, path)] else [(prop_alloc, path)]
let execute___cxx_typeid ({Builtin.summary; tenv; prop_; args; loc; exe_env} as r) : let execute___cxx_typeid ({Builtin.summary; tenv; prop_; args; loc; exe_env} as r) : Builtin.ret_typ
Builtin.ret_typ = =
match args with match args with
| type_info_exp :: rest -> ( | type_info_exp :: rest -> (
let res = execute_alloc PredSymb.Mnew false {r with args= [type_info_exp]} in let res = execute_alloc PredSymb.Mnew false {r with args= [type_info_exp]} in
@ -718,8 +712,8 @@ let execute_return_first_argument {Builtin.tenv; summary; prop_; path; ret_id_ty
raise (Exceptions.Wrong_argument_number __POS__) raise (Exceptions.Wrong_argument_number __POS__)
let execute___split_get_nth {Builtin.tenv; summary; prop_; path; ret_id_typ; args} : let execute___split_get_nth {Builtin.tenv; summary; prop_; path; ret_id_typ; args} : Builtin.ret_typ
Builtin.ret_typ = =
match args with match args with
| [(lexp1, _); (lexp2, _); (lexp3, _)] -> ( | [(lexp1, _); (lexp2, _); (lexp3, _)] -> (
let pname = Summary.get_proc_name summary in let pname = Summary.get_proc_name summary in
@ -779,8 +773,8 @@ let execute___infer_fail {Builtin.summary; tenv; prop_; path; args; loc; exe_env
(* translate builtin assertion failure *) (* translate builtin assertion failure *)
let execute___assert_fail {Builtin.summary; tenv; prop_; path; args; loc; exe_env} : let execute___assert_fail {Builtin.summary; tenv; prop_; path; args; loc; exe_env} : Builtin.ret_typ
Builtin.ret_typ = =
let error_str = let error_str =
match List.length args with match List.length args with
| 4 -> | 4 ->
@ -812,8 +806,7 @@ let execute_objc_alloc_no_fail symb_state typ alloc_fun_opt
[] []
in in
let alloc_instr = let alloc_instr =
Sil.Call Sil.Call (ret_id_typ, alloc_fun, [(sizeof_typ, ptr_typ)] @ alloc_fun_exp, loc, CallFlags.default)
(ret_id_typ, alloc_fun, [(sizeof_typ, ptr_typ)] @ alloc_fun_exp, loc, CallFlags.default)
in in
SymExec.instrs exe_env tenv summary (Instrs.singleton alloc_instr) symb_state SymExec.instrs exe_env tenv summary (Instrs.singleton alloc_instr) symb_state
@ -904,9 +897,7 @@ let __method_set_ignore_attribute =
let __new = Builtin.register BuiltinDecl.__new (execute_alloc PredSymb.Mnew false) let __new = Builtin.register BuiltinDecl.__new (execute_alloc PredSymb.Mnew false)
let __new_array = let __new_array = Builtin.register BuiltinDecl.__new_array (execute_alloc PredSymb.Mnew_array false)
Builtin.register BuiltinDecl.__new_array (execute_alloc PredSymb.Mnew_array false)
(* like __objc_alloc, but does not return nil *) (* like __objc_alloc, but does not return nil *)
let __objc_alloc_no_fail = let __objc_alloc_no_fail =

@ -7,8 +7,8 @@
open! IStd open! IStd
(** Models for the builtin functions supported *)
include BUILTINS.S with type t = Builtin.registered include BUILTINS.S with type t = Builtin.registered
(** Models for the builtin functions supported *)
val init : unit -> unit val init : unit -> unit
(** Clients of Builtin module should call this before Builtin module is used. (** Clients of Builtin module should call this before Builtin module is used.

@ -32,7 +32,7 @@ let equal_sigma sigma1 sigma2 =
L.d_strln "failure reason 1" ; raise Sil.JoinFail L.d_strln "failure reason 1" ; raise Sil.JoinFail
| hpred1 :: sigma1_rest', hpred2 :: sigma2_rest' -> | hpred1 :: sigma1_rest', hpred2 :: sigma2_rest' ->
if Sil.equal_hpred hpred1 hpred2 then f sigma1_rest' sigma2_rest' if Sil.equal_hpred hpred1 hpred2 then f sigma1_rest' sigma2_rest'
else ( L.d_strln "failure reason 2" ; raise Sil.JoinFail ) else (L.d_strln "failure reason 2" ; raise Sil.JoinFail)
in in
let sigma1_sorted = List.sort ~compare:Sil.compare_hpred sigma1 in let sigma1_sorted = List.sort ~compare:Sil.compare_hpred sigma1 in
let sigma2_sorted = List.sort ~compare:Sil.compare_hpred sigma2 in let sigma2_sorted = List.sort ~compare:Sil.compare_hpred sigma2 in
@ -119,7 +119,7 @@ end = struct
let new_c = lookup_const' const_tbl new_r in let new_c = lookup_const' const_tbl new_r in
let old_c = lookup_const' const_tbl old_r in let old_c = lookup_const' const_tbl old_r in
let res_c = Exp.Set.union new_c old_c in let res_c = Exp.Set.union new_c old_c in
if Exp.Set.cardinal res_c > 1 then ( L.d_strln "failure reason 3" ; raise Sil.JoinFail ) ; if Exp.Set.cardinal res_c > 1 then (L.d_strln "failure reason 3" ; raise Sil.JoinFail) ;
Hashtbl.replace tbl old_r new_r ; Hashtbl.replace tbl old_r new_r ;
Hashtbl.replace const_tbl new_r res_c Hashtbl.replace const_tbl new_r res_c
@ -127,7 +127,7 @@ end = struct
let replace_const' tbl const_tbl e c = let replace_const' tbl const_tbl e c =
let r = find' tbl e in let r = find' tbl e in
let set = Exp.Set.add c (lookup_const' const_tbl r) in let set = Exp.Set.add c (lookup_const' const_tbl r) in
if Exp.Set.cardinal set > 1 then ( L.d_strln "failure reason 4" ; raise Sil.JoinFail ) ; if Exp.Set.cardinal set > 1 then (L.d_strln "failure reason 4" ; raise Sil.JoinFail) ;
Hashtbl.replace const_tbl r set Hashtbl.replace const_tbl r set
@ -148,12 +148,12 @@ end = struct
L.d_strln "failure reason 5" ; raise Sil.JoinFail ) L.d_strln "failure reason 5" ; raise Sil.JoinFail )
| Exp.Var id, Exp.Const _ | Exp.Var id, Exp.Lvar _ -> | Exp.Var id, Exp.Const _ | Exp.Var id, Exp.Lvar _ ->
if can_rename id then replace_const' tbl const_tbl e e' if can_rename id then replace_const' tbl const_tbl e e'
else ( L.d_strln "failure reason 6" ; raise Sil.JoinFail ) else (L.d_strln "failure reason 6" ; raise Sil.JoinFail)
| Exp.Const _, Exp.Var id' | Exp.Lvar _, Exp.Var id' -> | Exp.Const _, Exp.Var id' | Exp.Lvar _, Exp.Var id' ->
if can_rename id' then replace_const' tbl const_tbl e' e if can_rename id' then replace_const' tbl const_tbl e' e
else ( L.d_strln "failure reason 7" ; raise Sil.JoinFail ) else (L.d_strln "failure reason 7" ; raise Sil.JoinFail)
| _ -> | _ ->
if not (Exp.equal e e') then ( L.d_strln "failure reason 8" ; raise Sil.JoinFail ) else () if not (Exp.equal e e') then (L.d_strln "failure reason 8" ; raise Sil.JoinFail) else ()
let check side es = let check side es =
@ -588,15 +588,15 @@ end = struct
let res = ref [] in let res = ref [] in
let f v = let f v =
match (v, side) with match (v, side) with
| (Exp.BinOp (Binop.PlusA _, e1', Exp.Const (Const.Cint i)), e2, e'), Lhs | (Exp.BinOp (Binop.PlusA _, e1', Exp.Const (Const.Cint i)), e2, e'), Lhs when Exp.equal e e1'
when Exp.equal e e1' -> ->
let c' = Exp.int (IntLit.neg i) in let c' = Exp.int (IntLit.neg i) in
let v' = let v' =
(e1', Exp.BinOp (Binop.PlusA None, e2, c'), Exp.BinOp (Binop.PlusA None, e', c')) (e1', Exp.BinOp (Binop.PlusA None, e2, c'), Exp.BinOp (Binop.PlusA None, e', c'))
in in
res := v' :: !res res := v' :: !res
| (e1, Exp.BinOp (Binop.PlusA _, e2', Exp.Const (Const.Cint i)), e'), Rhs | (e1, Exp.BinOp (Binop.PlusA _, e2', Exp.Const (Const.Cint i)), e'), Rhs when Exp.equal e e2'
when Exp.equal e e2' -> ->
let c' = Exp.int (IntLit.neg i) in let c' = Exp.int (IntLit.neg i) in
let v' = let v' =
(Exp.BinOp (Binop.PlusA None, e1, c'), e2', Exp.BinOp (Binop.PlusA None, e', c')) (Exp.BinOp (Binop.PlusA None, e1, c'), e2', Exp.BinOp (Binop.PlusA None, e', c'))
@ -750,7 +750,7 @@ end = struct
let get_other_atoms tenv side atom_in = let get_other_atoms tenv side atom_in =
let build_other_atoms construct side e = let build_other_atoms construct side e =
if Config.trace_join then ( L.d_str "build_other_atoms: " ; Sil.d_exp e ; L.d_ln () ) ; if Config.trace_join then (L.d_str "build_other_atoms: " ; Sil.d_exp e ; L.d_ln ()) ;
let others1 = get_others_direct_or_induced side e in let others1 = get_others_direct_or_induced side e in
let others2 = match others1 with None -> get_others_deep side e | Some _ -> others1 in let others2 = match others1 with None -> get_others_deep side e | Some _ -> others1 in
match others2 with match others2 with
@ -831,8 +831,7 @@ end = struct
if if
(not (Exp.free_vars e1 |> Sequence.exists ~f:can_rename)) (not (Exp.free_vars e1 |> Sequence.exists ~f:can_rename))
&& not (Exp.free_vars e2 |> Sequence.exists ~f:can_rename) && not (Exp.free_vars e2 |> Sequence.exists ~f:can_rename)
then then if Exp.equal e1 e2 then e1 else (L.d_strln "failure reason 13" ; raise Sil.JoinFail)
if Exp.equal e1 e2 then e1 else ( L.d_strln "failure reason 13" ; raise Sil.JoinFail )
else else
match default_op with match default_op with
| ExtDefault e -> | ExtDefault e ->
@ -920,7 +919,7 @@ let ident_partial_join (id1 : Ident.t) (id2 : Ident.t) =
match (Ident.is_normal id1, Ident.is_normal id2) with match (Ident.is_normal id1, Ident.is_normal id2) with
| true, true -> | true, true ->
if Ident.equal id1 id2 then Exp.Var id1 if Ident.equal id1 id2 then Exp.Var id1
else ( L.d_strln "failure reason 14" ; raise Sil.JoinFail ) else (L.d_strln "failure reason 14" ; raise Sil.JoinFail)
| true, _ | _, true -> | true, _ | _, true ->
Rename.extend (Exp.Var id1) (Exp.Var id2) Rename.ExtFresh Rename.extend (Exp.Var id1) (Exp.Var id2) Rename.ExtFresh
| _ -> | _ ->
@ -936,7 +935,7 @@ let ident_partial_meet (id1 : Ident.t) (id2 : Ident.t) =
match (Ident.is_normal id1, Ident.is_normal id2) with match (Ident.is_normal id1, Ident.is_normal id2) with
| true, true -> | true, true ->
if Ident.equal id1 id2 then Exp.Var id1 if Ident.equal id1 id2 then Exp.Var id1
else ( L.d_strln "failure reason 16" ; raise Sil.JoinFail ) else (L.d_strln "failure reason 16" ; raise Sil.JoinFail)
| true, _ -> | true, _ ->
let e1, e2 = (Exp.Var id1, Exp.Var id2) in let e1, e2 = (Exp.Var id1, Exp.Var id2) in
Rename.extend e1 e2 (Rename.ExtDefault e1) Rename.extend e1 e2 (Rename.ExtDefault e1)
@ -949,7 +948,7 @@ let ident_partial_meet (id1 : Ident.t) (id2 : Ident.t) =
else if Ident.is_footprint id1 && Ident.equal id1 id2 then else if Ident.is_footprint id1 && Ident.equal id1 id2 then
let e = Exp.Var id1 in let e = Exp.Var id1 in
Rename.extend e e (Rename.ExtDefault e) Rename.extend e e (Rename.ExtDefault e)
else ( L.d_strln "failure reason 17" ; raise Sil.JoinFail ) else (L.d_strln "failure reason 17" ; raise Sil.JoinFail)
(** {2 Join and Meet for Exps} *) (** {2 Join and Meet for Exps} *)
@ -965,7 +964,7 @@ let const_partial_join c1 c2 =
L.d_strln "failure reason 18" ; raise Sil.JoinFail ) L.d_strln "failure reason 18" ; raise Sil.JoinFail )
else if !BiabductionConfig.abs_val >= 2 then else if !BiabductionConfig.abs_val >= 2 then
FreshVarExp.get_fresh_exp (Exp.Const c1) (Exp.Const c2) FreshVarExp.get_fresh_exp (Exp.Const c1) (Exp.Const c2)
else ( L.d_strln "failure reason 19" ; raise Sil.JoinFail ) else (L.d_strln "failure reason 19" ; raise Sil.JoinFail)
let rec exp_partial_join (e1 : Exp.t) (e2 : Exp.t) : Exp.t = let rec exp_partial_join (e1 : Exp.t) (e2 : Exp.t) : Exp.t =
@ -974,12 +973,12 @@ let rec exp_partial_join (e1 : Exp.t) (e2 : Exp.t) : Exp.t =
| Exp.Var id1, Exp.Var id2 -> | Exp.Var id1, Exp.Var id2 ->
ident_partial_join id1 id2 ident_partial_join id1 id2
| Exp.Var id, Exp.Const _ | Exp.Const _, Exp.Var id -> | Exp.Var id, Exp.Const _ | Exp.Const _, Exp.Var id ->
if Ident.is_normal id then ( L.d_strln "failure reason 20" ; raise Sil.JoinFail ) if Ident.is_normal id then (L.d_strln "failure reason 20" ; raise Sil.JoinFail)
else Rename.extend e1 e2 Rename.ExtFresh else Rename.extend e1 e2 Rename.ExtFresh
| Exp.Const c1, Exp.Const c2 -> | Exp.Const c1, Exp.Const c2 ->
const_partial_join c1 c2 const_partial_join c1 c2
| Exp.Var id, Exp.Lvar _ | Exp.Lvar _, Exp.Var id -> | Exp.Var id, Exp.Lvar _ | Exp.Lvar _, Exp.Var id ->
if Ident.is_normal id then ( L.d_strln "failure reason 21" ; raise Sil.JoinFail ) if Ident.is_normal id then (L.d_strln "failure reason 21" ; raise Sil.JoinFail)
else Rename.extend e1 e2 Rename.ExtFresh else Rename.extend e1 e2 Rename.ExtFresh
| Exp.BinOp (Binop.PlusA _, Exp.Var id1, Exp.Const _), Exp.Var id2 | Exp.BinOp (Binop.PlusA _, Exp.Var id1, Exp.Const _), Exp.Var id2
| Exp.Var id1, Exp.BinOp (Binop.PlusA _, Exp.Var id2, Exp.Const _) | Exp.Var id1, Exp.BinOp (Binop.PlusA _, Exp.Var id2, Exp.Const _)
@ -996,12 +995,12 @@ let rec exp_partial_join (e1 : Exp.t) (e2 : Exp.t) : Exp.t =
let e_res = Rename.extend (Exp.int c1') (Exp.Var id2) Rename.ExtFresh in let e_res = Rename.extend (Exp.int c1') (Exp.Var id2) Rename.ExtFresh in
Exp.BinOp (Binop.PlusA None, e_res, Exp.int c2) Exp.BinOp (Binop.PlusA None, e_res, Exp.int c2)
| Exp.Cast (t1, e1), Exp.Cast (t2, e2) -> | Exp.Cast (t1, e1), Exp.Cast (t2, e2) ->
if not (Typ.equal t1 t2) then ( L.d_strln "failure reason 22" ; raise Sil.JoinFail ) if not (Typ.equal t1 t2) then (L.d_strln "failure reason 22" ; raise Sil.JoinFail)
else else
let e1'' = exp_partial_join e1 e2 in let e1'' = exp_partial_join e1 e2 in
Exp.Cast (t1, e1'') Exp.Cast (t1, e1'')
| Exp.UnOp (unop1, e1, topt1), Exp.UnOp (unop2, e2, _) -> | Exp.UnOp (unop1, e1, topt1), Exp.UnOp (unop2, e2, _) ->
if not (Unop.equal unop1 unop2) then ( L.d_strln "failure reason 23" ; raise Sil.JoinFail ) if not (Unop.equal unop1 unop2) then (L.d_strln "failure reason 23" ; raise Sil.JoinFail)
else Exp.UnOp (unop1, exp_partial_join e1 e2, topt1) (* should be topt1 = topt2 *) else Exp.UnOp (unop1, exp_partial_join e1 e2, topt1) (* should be topt1 = topt2 *)
| Exp.BinOp (Binop.PlusPI, e1, e1'), Exp.BinOp (Binop.PlusPI, e2, e2') -> | Exp.BinOp (Binop.PlusPI, e1, e1'), Exp.BinOp (Binop.PlusPI, e2, e2') ->
let e1'' = exp_partial_join e1 e2 in let e1'' = exp_partial_join e1 e2 in
@ -1014,16 +1013,16 @@ let rec exp_partial_join (e1 : Exp.t) (e2 : Exp.t) : Exp.t =
in in
Exp.BinOp (Binop.PlusPI, e1'', e2'') Exp.BinOp (Binop.PlusPI, e1'', e2'')
| Exp.BinOp (binop1, e1, e1'), Exp.BinOp (binop2, e2, e2') -> | Exp.BinOp (binop1, e1, e1'), Exp.BinOp (binop2, e2, e2') ->
if not (Binop.equal binop1 binop2) then ( L.d_strln "failure reason 24" ; raise Sil.JoinFail ) if not (Binop.equal binop1 binop2) then (L.d_strln "failure reason 24" ; raise Sil.JoinFail)
else else
let e1'' = exp_partial_join e1 e2 in let e1'' = exp_partial_join e1 e2 in
let e2'' = exp_partial_join e1' e2' in let e2'' = exp_partial_join e1' e2' in
Exp.BinOp (binop1, e1'', e2'') Exp.BinOp (binop1, e1'', e2'')
| Exp.Lvar pvar1, Exp.Lvar pvar2 -> | Exp.Lvar pvar1, Exp.Lvar pvar2 ->
if not (Pvar.equal pvar1 pvar2) then ( L.d_strln "failure reason 25" ; raise Sil.JoinFail ) if not (Pvar.equal pvar1 pvar2) then (L.d_strln "failure reason 25" ; raise Sil.JoinFail)
else e1 else e1
| Exp.Lfield (e1, f1, t1), Exp.Lfield (e2, f2, _) -> | Exp.Lfield (e1, f1, t1), Exp.Lfield (e2, f2, _) ->
if not (Typ.Fieldname.equal f1 f2) then ( L.d_strln "failure reason 26" ; raise Sil.JoinFail ) if not (Typ.Fieldname.equal f1 f2) then (L.d_strln "failure reason 26" ; raise Sil.JoinFail)
else Exp.Lfield (exp_partial_join e1 e2, f1, t1) (* should be t1 = t2 *) else Exp.Lfield (exp_partial_join e1 e2, f1, t1) (* should be t1 = t2 *)
| Exp.Lindex (e1, e1'), Exp.Lindex (e2, e2') -> | Exp.Lindex (e1, e1'), Exp.Lindex (e2, e2') ->
let e1'' = exp_partial_join e1 e2 in let e1'' = exp_partial_join e1 e2 in
@ -1073,8 +1072,7 @@ and typ_partial_join (t1 : Typ.t) (t2 : Typ.t) =
match (t1.desc, t2.desc) with match (t1.desc, t2.desc) with
| Typ.Tptr (t1, pk1), Typ.Tptr (t2, pk2) | Typ.Tptr (t1, pk1), Typ.Tptr (t2, pk2)
when Typ.equal_ptr_kind pk1 pk2 && Typ.equal_quals t1.quals t2.quals -> when Typ.equal_ptr_kind pk1 pk2 && Typ.equal_quals t1.quals t2.quals ->
Typ.mk ~default:t1 (Tptr (typ_partial_join t1 t2, pk1)) Typ.mk ~default:t1 (Tptr (typ_partial_join t1 t2, pk1)) (* quals are the same for t1 and t2 *)
(* quals are the same for t1 and t2 *)
| ( Typ.Tarray {elt= typ1; length= len1; stride= stride1} | ( Typ.Tarray {elt= typ1; length= len1; stride= stride1}
, Typ.Tarray {elt= typ2; length= len2; stride= stride2} ) , Typ.Tarray {elt= typ2; length= len2; stride= stride2} )
when Typ.equal_quals typ1.quals typ2.quals -> when Typ.equal_quals typ1.quals typ2.quals ->
@ -1100,37 +1098,37 @@ let rec exp_partial_meet (e1 : Exp.t) (e2 : Exp.t) : Exp.t =
ident_partial_meet id1 id2 ident_partial_meet id1 id2
| Exp.Var id, Exp.Const _ -> | Exp.Var id, Exp.Const _ ->
if not (Ident.is_normal id) then Rename.extend e1 e2 (Rename.ExtDefault e2) if not (Ident.is_normal id) then Rename.extend e1 e2 (Rename.ExtDefault e2)
else ( L.d_strln "failure reason 27" ; raise Sil.JoinFail ) else (L.d_strln "failure reason 27" ; raise Sil.JoinFail)
| Exp.Const _, Exp.Var id -> | Exp.Const _, Exp.Var id ->
if not (Ident.is_normal id) then Rename.extend e1 e2 (Rename.ExtDefault e1) if not (Ident.is_normal id) then Rename.extend e1 e2 (Rename.ExtDefault e1)
else ( L.d_strln "failure reason 28" ; raise Sil.JoinFail ) else (L.d_strln "failure reason 28" ; raise Sil.JoinFail)
| Exp.Const c1, Exp.Const c2 -> | Exp.Const c1, Exp.Const c2 ->
if Const.equal c1 c2 then e1 else ( L.d_strln "failure reason 29" ; raise Sil.JoinFail ) if Const.equal c1 c2 then e1 else (L.d_strln "failure reason 29" ; raise Sil.JoinFail)
| Exp.Cast (t1, e1), Exp.Cast (t2, e2) -> | Exp.Cast (t1, e1), Exp.Cast (t2, e2) ->
if not (Typ.equal t1 t2) then ( L.d_strln "failure reason 30" ; raise Sil.JoinFail ) if not (Typ.equal t1 t2) then (L.d_strln "failure reason 30" ; raise Sil.JoinFail)
else else
let e1'' = exp_partial_meet e1 e2 in let e1'' = exp_partial_meet e1 e2 in
Exp.Cast (t1, e1'') Exp.Cast (t1, e1'')
| Exp.UnOp (unop1, e1, topt1), Exp.UnOp (unop2, e2, _) -> | Exp.UnOp (unop1, e1, topt1), Exp.UnOp (unop2, e2, _) ->
if not (Unop.equal unop1 unop2) then ( L.d_strln "failure reason 31" ; raise Sil.JoinFail ) if not (Unop.equal unop1 unop2) then (L.d_strln "failure reason 31" ; raise Sil.JoinFail)
else Exp.UnOp (unop1, exp_partial_meet e1 e2, topt1) (* should be topt1 = topt2 *) else Exp.UnOp (unop1, exp_partial_meet e1 e2, topt1) (* should be topt1 = topt2 *)
| Exp.BinOp (binop1, e1, e1'), Exp.BinOp (binop2, e2, e2') -> | Exp.BinOp (binop1, e1, e1'), Exp.BinOp (binop2, e2, e2') ->
if not (Binop.equal binop1 binop2) then ( L.d_strln "failure reason 32" ; raise Sil.JoinFail ) if not (Binop.equal binop1 binop2) then (L.d_strln "failure reason 32" ; raise Sil.JoinFail)
else else
let e1'' = exp_partial_meet e1 e2 in let e1'' = exp_partial_meet e1 e2 in
let e2'' = exp_partial_meet e1' e2' in let e2'' = exp_partial_meet e1' e2' in
Exp.BinOp (binop1, e1'', e2'') Exp.BinOp (binop1, e1'', e2'')
| Exp.Var id, Exp.Lvar _ -> | Exp.Var id, Exp.Lvar _ ->
if not (Ident.is_normal id) then Rename.extend e1 e2 (Rename.ExtDefault e2) if not (Ident.is_normal id) then Rename.extend e1 e2 (Rename.ExtDefault e2)
else ( L.d_strln "failure reason 33" ; raise Sil.JoinFail ) else (L.d_strln "failure reason 33" ; raise Sil.JoinFail)
| Exp.Lvar _, Exp.Var id -> | Exp.Lvar _, Exp.Var id ->
if not (Ident.is_normal id) then Rename.extend e1 e2 (Rename.ExtDefault e1) if not (Ident.is_normal id) then Rename.extend e1 e2 (Rename.ExtDefault e1)
else ( L.d_strln "failure reason 34" ; raise Sil.JoinFail ) else (L.d_strln "failure reason 34" ; raise Sil.JoinFail)
| Exp.Lvar pvar1, Exp.Lvar pvar2 -> | Exp.Lvar pvar1, Exp.Lvar pvar2 ->
if not (Pvar.equal pvar1 pvar2) then ( L.d_strln "failure reason 35" ; raise Sil.JoinFail ) if not (Pvar.equal pvar1 pvar2) then (L.d_strln "failure reason 35" ; raise Sil.JoinFail)
else e1 else e1
| Exp.Lfield (e1, f1, t1), Exp.Lfield (e2, f2, _) -> | Exp.Lfield (e1, f1, t1), Exp.Lfield (e2, f2, _) ->
if not (Typ.Fieldname.equal f1 f2) then ( L.d_strln "failure reason 36" ; raise Sil.JoinFail ) if not (Typ.Fieldname.equal f1 f2) then (L.d_strln "failure reason 36" ; raise Sil.JoinFail)
else Exp.Lfield (exp_partial_meet e1 e2, f1, t1) (* should be t1 = t2 *) else Exp.Lfield (exp_partial_meet e1 e2, f1, t1) (* should be t1 = t2 *)
| Exp.Lindex (e1, e1'), Exp.Lindex (e2, e2') -> | Exp.Lindex (e1, e1'), Exp.Lindex (e2, e2') ->
let e1'' = exp_partial_meet e1 e2 in let e1'' = exp_partial_meet e1 e2 in
@ -1286,25 +1284,25 @@ let kind_meet k1 k2 =
let hpara_partial_join tenv (hpara1 : Sil.hpara) (hpara2 : Sil.hpara) : Sil.hpara = let hpara_partial_join tenv (hpara1 : Sil.hpara) (hpara2 : Sil.hpara) : Sil.hpara =
if Match.hpara_match_with_impl tenv true hpara2 hpara1 then hpara1 if Match.hpara_match_with_impl tenv true hpara2 hpara1 then hpara1
else if Match.hpara_match_with_impl tenv true hpara1 hpara2 then hpara2 else if Match.hpara_match_with_impl tenv true hpara1 hpara2 then hpara2
else ( L.d_strln "failure reason 53" ; raise Sil.JoinFail ) else (L.d_strln "failure reason 53" ; raise Sil.JoinFail)
let hpara_partial_meet tenv (hpara1 : Sil.hpara) (hpara2 : Sil.hpara) : Sil.hpara = let hpara_partial_meet tenv (hpara1 : Sil.hpara) (hpara2 : Sil.hpara) : Sil.hpara =
if Match.hpara_match_with_impl tenv true hpara2 hpara1 then hpara2 if Match.hpara_match_with_impl tenv true hpara2 hpara1 then hpara2
else if Match.hpara_match_with_impl tenv true hpara1 hpara2 then hpara1 else if Match.hpara_match_with_impl tenv true hpara1 hpara2 then hpara1
else ( L.d_strln "failure reason 54" ; raise Sil.JoinFail ) else (L.d_strln "failure reason 54" ; raise Sil.JoinFail)
let hpara_dll_partial_join tenv (hpara1 : Sil.hpara_dll) (hpara2 : Sil.hpara_dll) : Sil.hpara_dll = let hpara_dll_partial_join tenv (hpara1 : Sil.hpara_dll) (hpara2 : Sil.hpara_dll) : Sil.hpara_dll =
if Match.hpara_dll_match_with_impl tenv true hpara2 hpara1 then hpara1 if Match.hpara_dll_match_with_impl tenv true hpara2 hpara1 then hpara1
else if Match.hpara_dll_match_with_impl tenv true hpara1 hpara2 then hpara2 else if Match.hpara_dll_match_with_impl tenv true hpara1 hpara2 then hpara2
else ( L.d_strln "failure reason 55" ; raise Sil.JoinFail ) else (L.d_strln "failure reason 55" ; raise Sil.JoinFail)
let hpara_dll_partial_meet tenv (hpara1 : Sil.hpara_dll) (hpara2 : Sil.hpara_dll) : Sil.hpara_dll = let hpara_dll_partial_meet tenv (hpara1 : Sil.hpara_dll) (hpara2 : Sil.hpara_dll) : Sil.hpara_dll =
if Match.hpara_dll_match_with_impl tenv true hpara2 hpara1 then hpara2 if Match.hpara_dll_match_with_impl tenv true hpara2 hpara1 then hpara2
else if Match.hpara_dll_match_with_impl tenv true hpara1 hpara2 then hpara1 else if Match.hpara_dll_match_with_impl tenv true hpara1 hpara2 then hpara1
else ( L.d_strln "failure reason 56" ; raise Sil.JoinFail ) else (L.d_strln "failure reason 56" ; raise Sil.JoinFail)
(** {2 Join and Meet for hpred} *) (** {2 Join and Meet for hpred} *)
@ -1329,7 +1327,7 @@ let hpred_partial_join tenv mode (todo : Exp.t * Exp.t * Exp.t) (hpred1 : Sil.hp
let iF', iB' = let iF', iB' =
if fwd1 && fwd2 then (e, exp_partial_join iB1 iB2) if fwd1 && fwd2 then (e, exp_partial_join iB1 iB2)
else if (not fwd1) && not fwd2 then (exp_partial_join iF1 iF2, e) else if (not fwd1) && not fwd2 then (exp_partial_join iF1 iF2, e)
else ( L.d_strln "failure reason 57" ; raise Sil.JoinFail ) else (L.d_strln "failure reason 57" ; raise Sil.JoinFail)
in in
let oF' = exp_partial_join oF1 oF2 in let oF' = exp_partial_join oF1 oF2 in
let oB' = exp_partial_join oB1 oB2 in let oB' = exp_partial_join oB1 oB2 in
@ -1339,8 +1337,8 @@ let hpred_partial_join tenv mode (todo : Exp.t * Exp.t * Exp.t) (hpred1 : Sil.hp
assert false assert false
let hpred_partial_meet tenv (todo : Exp.t * Exp.t * Exp.t) (hpred1 : Sil.hpred) let hpred_partial_meet tenv (todo : Exp.t * Exp.t * Exp.t) (hpred1 : Sil.hpred) (hpred2 : Sil.hpred)
(hpred2 : Sil.hpred) : Sil.hpred = : Sil.hpred =
let e1, e2, e = todo in let e1, e2, e = todo in
match (hpred1, hpred2) with match (hpred1, hpred2) with
| Sil.Hpointsto (_, se1, te1), Sil.Hpointsto (_, se2, te2) when Exp.equal te1 te2 -> | Sil.Hpointsto (_, se1, te1), Sil.Hpointsto (_, se2, te2) when Exp.equal te1 te2 ->
@ -1360,7 +1358,7 @@ let hpred_partial_meet tenv (todo : Exp.t * Exp.t * Exp.t) (hpred1 : Sil.hpred)
let iF', iB' = let iF', iB' =
if fwd1 && fwd2 then (e, exp_partial_meet iB1 iB2) if fwd1 && fwd2 then (e, exp_partial_meet iB1 iB2)
else if (not fwd1) && not fwd2 then (exp_partial_meet iF1 iF2, e) else if (not fwd1) && not fwd2 then (exp_partial_meet iF1 iF2, e)
else ( L.d_strln "failure reason 59" ; raise Sil.JoinFail ) else (L.d_strln "failure reason 59" ; raise Sil.JoinFail)
in in
let oF' = exp_partial_meet oF1 oF2 in let oF' = exp_partial_meet oF1 oF2 in
let oB' = exp_partial_meet oB1 oB2 in let oB' = exp_partial_meet oB1 oB2 in
@ -1487,7 +1485,7 @@ let rec sigma_partial_join' tenv mode (sigma_acc : Prop.sigma) (sigma1_in : Prop
'side' describes that target is Lhs or Rhs. 'side' describes that target is Lhs or Rhs.
'todo' describes the start point. *) 'todo' describes the start point. *)
let cut_sigma side todo (target : Prop.sigma) (other : Prop.sigma) = let cut_sigma side todo (target : Prop.sigma) (other : Prop.sigma) =
let list_is_empty l = if l <> [] then ( L.d_strln "failure reason 61" ; raise Sil.JoinFail ) in let list_is_empty l = if l <> [] then (L.d_strln "failure reason 61" ; raise Sil.JoinFail) in
let x = Todo.take () in let x = Todo.take () in
Todo.push todo ; Todo.push todo ;
let res = let res =
@ -1550,13 +1548,13 @@ let rec sigma_partial_join' tenv mode (sigma_acc : Prop.sigma) (sigma1_in : Prop
if (not Config.nelseg) || Sil.equal_lseg_kind k Sil.Lseg_PE then if (not Config.nelseg) || Sil.equal_lseg_kind k Sil.Lseg_PE then
let sigma_acc' = join_list_and_non Lhs e lseg e1 e2 :: sigma_acc in let sigma_acc' = join_list_and_non Lhs e lseg e1 e2 :: sigma_acc in
sigma_partial_join' tenv mode sigma_acc' sigma1 sigma2 sigma_partial_join' tenv mode sigma_acc' sigma1 sigma2
else ( L.d_strln "failure reason 62" ; raise Sil.JoinFail ) else (L.d_strln "failure reason 62" ; raise Sil.JoinFail)
| None, Some (Sil.Hlseg (k, _, _, _, _) as lseg) | None, Some (Sil.Hlseg (k, _, _, _, _) as lseg)
| None, Some (Sil.Hdllseg (k, _, _, _, _, _, _) as lseg) -> | None, Some (Sil.Hdllseg (k, _, _, _, _, _, _) as lseg) ->
if (not Config.nelseg) || Sil.equal_lseg_kind k Sil.Lseg_PE then if (not Config.nelseg) || Sil.equal_lseg_kind k Sil.Lseg_PE then
let sigma_acc' = join_list_and_non Rhs e lseg e2 e1 :: sigma_acc in let sigma_acc' = join_list_and_non Rhs e lseg e2 e1 :: sigma_acc in
sigma_partial_join' tenv mode sigma_acc' sigma1 sigma2 sigma_partial_join' tenv mode sigma_acc' sigma1 sigma2
else ( L.d_strln "failure reason 63" ; raise Sil.JoinFail ) else (L.d_strln "failure reason 63" ; raise Sil.JoinFail)
| None, _ | _, None -> | None, _ | _, None ->
L.d_strln "failure reason 64" ; raise Sil.JoinFail L.d_strln "failure reason 64" ; raise Sil.JoinFail
| Some hpred1, Some hpred2 when same_pred hpred1 hpred2 -> | Some hpred1, Some hpred2 when same_pred hpred1 hpred2 ->
@ -1619,7 +1617,7 @@ let sigma_partial_join tenv mode (sigma1 : Prop.sigma) (sigma2 : Prop.sigma) :
SymOp.try_finally SymOp.try_finally
~f:(fun () -> ~f:(fun () ->
if Rename.check lost_little then (s1, s2, s3) if Rename.check lost_little then (s1, s2, s3)
else ( L.d_strln "failed Rename.check" ; raise Sil.JoinFail ) ) else (L.d_strln "failed Rename.check" ; raise Sil.JoinFail) )
~finally:CheckJoin.final ~finally:CheckJoin.final
@ -1726,9 +1724,7 @@ let pi_partial_join tenv mode (ep1 : Prop.exposed Prop.t) (ep2 : Prop.exposed Pr
| None -> | None ->
None None
| Some (n, e) -> | Some (n, e) ->
let bound = let bound = if IntLit.leq IntLit.minus_one n then IntLit.minus_one else widening_bottom in
if IntLit.leq IntLit.minus_one n then IntLit.minus_one else widening_bottom
in
let a' = Prop.mk_inequality tenv (Exp.BinOp (Binop.Lt, Exp.int bound, e)) in let a' = Prop.mk_inequality tenv (Exp.BinOp (Binop.Lt, Exp.int bound, e)) in
Some a' ) Some a' )
in in
@ -1803,12 +1799,12 @@ let pi_partial_join tenv mode (ep1 : Prop.exposed Prop.t) (ep2 : Prop.exposed Pr
let p2 = Prop.normalize tenv ep2 in let p2 = Prop.normalize tenv ep2 in
List.fold ~f:(handle_atom_with_widening Lhs p2 pi2) ~init:[] pi1 List.fold ~f:(handle_atom_with_widening Lhs p2 pi2) ~init:[] pi1
in in
if Config.trace_join then ( L.d_str "atom_list1: " ; Prop.d_pi atom_list1 ; L.d_ln () ) ; if Config.trace_join then (L.d_str "atom_list1: " ; Prop.d_pi atom_list1 ; L.d_ln ()) ;
let atom_list2 = let atom_list2 =
let p1 = Prop.normalize tenv ep1 in let p1 = Prop.normalize tenv ep1 in
List.fold ~f:(handle_atom_with_widening Rhs p1 pi1) ~init:[] pi2 List.fold ~f:(handle_atom_with_widening Rhs p1 pi1) ~init:[] pi2
in in
if Config.trace_join then ( L.d_str "atom_list2: " ; Prop.d_pi atom_list2 ; L.d_ln () ) ; if Config.trace_join then (L.d_str "atom_list2: " ; Prop.d_pi atom_list2 ; L.d_ln ()) ;
let atom_list_combined = IList.inter ~cmp:Sil.compare_atom atom_list1 atom_list2 in let atom_list_combined = IList.inter ~cmp:Sil.compare_atom atom_list1 atom_list2 in
if Config.trace_join then ( if Config.trace_join then (
L.d_str "atom_list_combined: " ; Prop.d_pi atom_list_combined ; L.d_ln () ) ; L.d_str "atom_list_combined: " ; Prop.d_pi atom_list_combined ; L.d_ln () ) ;
@ -1824,7 +1820,7 @@ let pi_partial_meet tenv (p : Prop.normal Prop.t) (ep1 : 'a Prop.t) (ep2 : 'b Pr
let handle_atom sub dom atom = let handle_atom sub dom atom =
if Sil.atom_free_vars atom |> Sequence.for_all ~f:(fun id -> Ident.Set.mem id dom) then if Sil.atom_free_vars atom |> Sequence.for_all ~f:(fun id -> Ident.Set.mem id dom) then
Sil.atom_sub sub atom Sil.atom_sub sub atom
else ( L.d_str "handle_atom failed on " ; Sil.d_atom atom ; L.d_ln () ; raise Sil.JoinFail ) else (L.d_str "handle_atom failed on " ; Sil.d_atom atom ; L.d_ln () ; raise Sil.JoinFail)
in in
let f1 p' atom = Prop.prop_atom_and tenv p' (handle_atom sub1 dom1 atom) in let f1 p' atom = Prop.prop_atom_and tenv p' (handle_atom sub1 dom1 atom) in
let f2 p' atom = Prop.prop_atom_and tenv p' (handle_atom sub2 dom2 atom) in let f2 p' atom = Prop.prop_atom_and tenv p' (handle_atom sub2 dom2 atom) in
@ -1857,7 +1853,7 @@ let eprop_partial_meet tenv (ep1 : 'a Prop.t) (ep2 : 'b Prop.t) : 'c Prop.t =
let f e = Exp.free_vars e |> Sequence.for_all ~f:Ident.is_normal in let f e = Exp.free_vars e |> Sequence.for_all ~f:Ident.is_normal in
Sil.equal_subst sub1 sub2 && List.for_all ~f range1 Sil.equal_subst sub1 sub2 && List.for_all ~f range1
in in
if not (sub_check ()) then ( L.d_strln "sub_check() failed" ; raise Sil.JoinFail ) if not (sub_check ()) then (L.d_strln "sub_check() failed" ; raise Sil.JoinFail)
else else
let todos = List.map ~f:(fun x -> (x, x, x)) es in let todos = List.map ~f:(fun x -> (x, x, x)) es in
List.iter ~f:Todo.push todos ; List.iter ~f:Todo.push todos ;
@ -1918,8 +1914,7 @@ let eprop_partial_join' tenv mode (ep1 : Prop.exposed Prop.t) (ep2 : Prop.expose
(sub_common_normal, eqs1, eqs2) (sub_common_normal, eqs1, eqs2)
in in
if not (simple_check && expensive_check es1 es2) then ( if not (simple_check && expensive_check es1 es2) then (
if not simple_check then L.d_strln "simple_check failed" if not simple_check then L.d_strln "simple_check failed" else L.d_strln "expensive_check failed" ;
else L.d_strln "expensive_check failed" ;
raise Sil.JoinFail ) ; raise Sil.JoinFail ) ;
let todos = List.map ~f:(fun x -> (x, x, x)) es1 in let todos = List.map ~f:(fun x -> (x, x, x)) es1 in
List.iter ~f:Todo.push todos ; List.iter ~f:Todo.push todos ;
@ -1959,10 +1954,8 @@ let footprint_partial_join' tenv (p1 : Prop.normal Prop.t) (p2 : Prop.normal Pro
in in
let sigma_fp = let sigma_fp =
let sigma_fp0 = efp.Prop.sigma in let sigma_fp0 = efp.Prop.sigma in
let f a = let f a = Sil.hpred_free_vars a |> Sequence.exists ~f:(fun a -> not (Ident.is_footprint a)) in
Sil.hpred_free_vars a |> Sequence.exists ~f:(fun a -> not (Ident.is_footprint a)) if List.exists ~f sigma_fp0 then (L.d_strln "failure reason 66" ; raise Sil.JoinFail) ;
in
if List.exists ~f sigma_fp0 then ( L.d_strln "failure reason 66" ; raise Sil.JoinFail ) ;
sigma_fp0 sigma_fp0
in in
let ep1' = Prop.set p1 ~pi_fp ~sigma_fp in let ep1' = Prop.set p1 ~pi_fp ~sigma_fp in

@ -356,9 +356,7 @@ let rec iter_match_with_impl tenv iter condition sub vars hpat hpats =
prop_match_with_impl_sub tenv p condition sub_new vars_leftover hpat_next hpats_rest prop_match_with_impl_sub tenv p condition sub_new vars_leftover hpat_next hpats_rest
in in
let do_para_lseg _ = let do_para_lseg _ =
let para2_exist_vars, para2_inst = let para2_exist_vars, para2_inst = Sil.hpara_instantiate para2 e_start2 e_end2 es_shared2 in
Sil.hpara_instantiate para2 e_start2 e_end2 es_shared2
in
(* let allow_impl hpred = {hpred=hpred; flag=hpat.flag} in *) (* let allow_impl hpred = {hpred=hpred; flag=hpat.flag} in *)
let allow_impl hpred = {hpred; flag= true} in let allow_impl hpred = {hpred; flag= true} in
let para2_hpat, para2_hpats = let para2_hpat, para2_hpats =

@ -168,7 +168,7 @@ end = struct
| Pstart (_, stats) -> | Pstart (_, stats) ->
if not (stats_is_dummy stats) then set_dummy_stats stats if not (stats_is_dummy stats) then set_dummy_stats stats
| Pnode (_, _, _, path, stats, _) | Pcall (path, _, ExecSkipped _, stats) -> | Pnode (_, _, _, path, stats, _) | Pcall (path, _, ExecSkipped _, stats) ->
if not (stats_is_dummy stats) then ( reset_stats path ; set_dummy_stats stats ) if not (stats_is_dummy stats) then (reset_stats path ; set_dummy_stats stats)
| Pjoin (path1, path2, stats) -> | Pjoin (path1, path2, stats) ->
if not (stats_is_dummy stats) then ( if not (stats_is_dummy stats) then (
reset_stats path1 ; reset_stats path2 ; set_dummy_stats stats ) reset_stats path1 ; reset_stats path2 ; set_dummy_stats stats )

@ -229,9 +229,7 @@ let get_pure_extended p =
(** Print existential quantification *) (** Print existential quantification *)
let pp_evars f evars = let pp_evars f evars = if evars <> [] then F.fprintf f "exists [%a]. " (Pp.comma_seq Ident.pp) evars
if evars <> [] then F.fprintf f "exists [%a]. " (Pp.comma_seq Ident.pp) evars
(** Print an hpara in simple mode *) (** Print an hpara in simple mode *)
let pp_hpara_simple pe_ env n f pred = let pp_hpara_simple pe_ env n f pred =
@ -357,8 +355,7 @@ let gen_free_vars {sigma; sigma_fp; sub; pi; pi_fp} =
>>= fun () -> >>= fun () ->
sigma_gen_free_vars sigma_fp sigma_gen_free_vars sigma_fp
>>= fun () -> >>= fun () ->
Sil.subst_gen_free_vars sub Sil.subst_gen_free_vars sub >>= fun () -> pi_gen_free_vars pi >>= fun () -> pi_gen_free_vars pi_fp
>>= fun () -> pi_gen_free_vars pi >>= fun () -> pi_gen_free_vars pi_fp
let free_vars prop = Sequence.Generator.run (gen_free_vars prop) let free_vars prop = Sequence.Generator.run (gen_free_vars prop)
@ -440,8 +437,7 @@ let rec create_strexp_of_type ~path tenv struct_init_mode (typ : Typ.t) len inst
let init_value () = let init_value () =
let create_fresh_var () = let create_fresh_var () =
let fresh_id = let fresh_id =
Ident.create_fresh Ident.create_fresh (if !BiabductionConfig.footprint then Ident.kfootprint else Ident.kprimed)
(if !BiabductionConfig.footprint then Ident.kfootprint else Ident.kprimed)
in in
Exp.Var fresh_id Exp.Var fresh_id
in in
@ -455,8 +451,8 @@ let rec create_strexp_of_type ~path tenv struct_init_mode (typ : Typ.t) len inst
| Tstruct name, _ -> ( | Tstruct name, _ -> (
if List.exists ~f:(fun (n, _) -> Typ.Name.equal n name) path then if List.exists ~f:(fun (n, _) -> Typ.Name.equal n name) path then
L.die InternalError L.die InternalError
"Ill-founded recursion in [create_strexp_of_type]: a sub-element of struct %a is also \ "Ill-founded recursion in [create_strexp_of_type]: a sub-element of struct %a is also of \
of type struct %a: %a:%a" type struct %a: %a:%a"
Typ.Name.pp name Typ.Name.pp name pp_path (List.rev path) Typ.Name.pp name ; Typ.Name.pp name Typ.Name.pp name pp_path (List.rev path) Typ.Name.pp name ;
match (struct_init_mode, Tenv.lookup tenv name) with match (struct_init_mode, Tenv.lookup tenv name) with
| Fld_init, Some {fields} -> | Fld_init, Some {fields} ->
@ -1481,10 +1477,7 @@ module Normalize = struct
, Sizeof {typ= {desc= Tarray {elt}} as arr} ) , Sizeof {typ= {desc= Tarray {elt}} as arr} )
when Typ.equal typ elt -> when Typ.equal typ elt ->
let sizeof_data = let sizeof_data =
{ Exp.typ= arr {Exp.typ= arr; nbytes= None; dynamic_length= Some (Exp.BinOp (omult, x, len)); subtype}
; nbytes= None
; dynamic_length= Some (Exp.BinOp (omult, x, len))
; subtype }
in in
let hpred' = mk_ptsto_exp tenv Fld_init (root, Sizeof sizeof_data, None) inst in let hpred' = mk_ptsto_exp tenv Fld_init (root, Sizeof sizeof_data, None) inst in
replace_hpred (replace_array_contents hpred' esel) replace_hpred (replace_array_contents hpred' esel)
@ -1495,10 +1488,7 @@ module Normalize = struct
, Sizeof {typ= {desc= Tarray {elt}} as arr} ) , Sizeof {typ= {desc= Tarray {elt}} as arr} )
when Typ.equal typ elt -> when Typ.equal typ elt ->
let sizeof_data = let sizeof_data =
{ Exp.typ= arr {Exp.typ= arr; nbytes= None; dynamic_length= Some (Exp.BinOp (omult, x, len)); subtype}
; nbytes= None
; dynamic_length= Some (Exp.BinOp (omult, x, len))
; subtype }
in in
let hpred' = mk_ptsto_exp tenv Fld_init (root, Sizeof sizeof_data, None) inst in let hpred' = mk_ptsto_exp tenv Fld_init (root, Sizeof sizeof_data, None) inst in
replace_hpred (replace_array_contents hpred' esel) replace_hpred (replace_array_contents hpred' esel)
@ -1553,9 +1543,7 @@ module Normalize = struct
in in
List.fold ~f:get_disequality_info ~init:[] nonineq_list List.fold ~f:get_disequality_info ~init:[] nonineq_list
in in
let is_neq e n = let is_neq e n = List.exists ~f:(fun (e', n') -> Exp.equal e e' && IntLit.eq n n') diseq_list in
List.exists ~f:(fun (e', n') -> Exp.equal e e' && IntLit.eq n n') diseq_list
in
let le_list_tightened = let le_list_tightened =
let get_le_inequality_info acc a = let get_le_inequality_info acc a =
match atom_exp_le_const a with Some (e, n) -> (e, n) :: acc | _ -> acc match atom_exp_le_const a with Some (e, n) -> (e, n) :: acc | _ -> acc

@ -193,8 +193,7 @@ val mk_ptsto_exp : Tenv.t -> struct_init_mode -> Exp.t * Exp.t * Exp.t option ->
(** Construct a points-to predicate for an expression using either the provided expression [name] as (** Construct a points-to predicate for an expression using either the provided expression [name] as
base for fresh identifiers. *) base for fresh identifiers. *)
val mk_ptsto_lvar : val mk_ptsto_lvar : Tenv.t -> struct_init_mode -> Sil.inst -> Pvar.t * Exp.t * Exp.t option -> hpred
Tenv.t -> struct_init_mode -> Sil.inst -> Pvar.t * Exp.t * Exp.t option -> hpred
(** Construct a points-to predicate for a single program variable. (** Construct a points-to predicate for a single program variable.
If [expand_structs] is true, initialize the fields of structs with fresh variables. *) If [expand_structs] is true, initialize the fields of structs with fresh variables. *)

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

Loading…
Cancel
Save