[ocamlformat] upgrade to ocamlformat 0.7

Reviewed By: mbouaziz

Differential Revision: D9496601

fbshipit-source-id: 83c6fd241
master
Josh Berdine 6 years ago committed by Facebook Github Bot
parent 060924adff
commit 40ab73037e

@ -1,3 +1,3 @@
margin 100
sparse true
version 0.5
break-cases = nested
margin = 100
version = 0.7

@ -1 +1 @@
19b52cea4dd5ffff8094aaa671ae019a969863f8
b3ed72b3997cb7712e54f90d47128d6dd8e18f53

@ -638,7 +638,7 @@ endif
# This is a magical version number that doesn't reinstall the world when added on top of what we
# have in opam.lock. To upgrade this version number, manually try to install several utop versions
# until you find one that doesn't recompile the world. TODO(t20828442): get rid of magic
OPAM_DEV_DEPS = ocamlformat.$$(grep version .ocamlformat | cut -d ' ' -f 2) ocp-indent merlin utop.2.2.0 webbrowser
OPAM_DEV_DEPS = ocamlformat.$$(grep version .ocamlformat | cut -d ' ' -f 3) ocp-indent merlin utop.2.2.0 webbrowser
ifneq ($(EMACS),no)
OPAM_DEV_DEPS += tuareg

@ -75,8 +75,7 @@ let rec get_typ t tenv : Typ.t option =
match t with
| Base (_, typ) ->
Some typ
| FieldOffset (ae, fld)
-> (
| FieldOffset (ae, fld) -> (
let base_typ_opt = get_typ ae tenv in
match base_typ_opt with
| Some base_typ ->
@ -88,9 +87,9 @@ let rec get_typ t tenv : Typ.t option =
| AddressOf ae ->
let base_typ_opt = get_typ ae tenv in
Option.map base_typ_opt ~f:(fun base_typ -> Typ.mk (Tptr (base_typ, Pk_pointer)))
| Dereference ae ->
| Dereference ae -> (
let base_typ_opt = get_typ ae tenv in
match base_typ_opt with Some {Typ.desc= Tptr (typ, _)} -> Some typ | _ -> None
match base_typ_opt with Some {Typ.desc= Tptr (typ, _)} -> Some typ | _ -> None )
let rec pp fmt = function
@ -110,7 +109,7 @@ let rec pp fmt = function
F.fprintf fmt "*(%a)" pp ae
let equal = [%compare.equal : t]
let equal = [%compare.equal: t]
let base_of_id id typ = (Var.of_id id, typ)
@ -144,8 +143,8 @@ let rec normalize t =
(* Adapted from AccessPath.of_exp. *)
let of_exp ~include_array_indexes ~add_deref exp0 typ0 ~(f_resolve_id: Var.t -> t option) =
let rec of_exp_ exp typ (add_accesses: t -> t) acc : t list =
let of_exp ~include_array_indexes ~add_deref exp0 typ0 ~(f_resolve_id : Var.t -> t option) =
let rec of_exp_ exp typ (add_accesses : t -> t) acc : t list =
match exp with
| Exp.Var id -> (
match f_resolve_id (Var.of_id id) with
@ -200,14 +199,12 @@ let of_exp ~include_array_indexes ~add_deref exp0 typ0 ~(f_resolve_id: Var.t ->
IList.map_changed ~f:normalize ~equal (of_exp_ exp0 typ0 Fn.id [])
let of_lhs_exp ~include_array_indexes ~add_deref lhs_exp typ ~(f_resolve_id: Var.t -> t option) =
let of_lhs_exp ~include_array_indexes ~add_deref lhs_exp typ ~(f_resolve_id : Var.t -> t option) =
match lhs_exp with
| Exp.Lfield _ when not add_deref
-> (
| Exp.Lfield _ when not add_deref -> (
let res = of_exp ~include_array_indexes ~add_deref:true lhs_exp typ ~f_resolve_id in
match res with [lhs_ae] -> Some (AddressOf lhs_ae) | _ -> None )
| Exp.Lindex _ when not add_deref
-> (
| Exp.Lindex _ when not add_deref -> (
let res =
let typ' =
match typ.Typ.desc with
@ -220,6 +217,6 @@ let of_lhs_exp ~include_array_indexes ~add_deref lhs_exp typ ~(f_resolve_id: Var
of_exp ~include_array_indexes ~add_deref:true lhs_exp typ' ~f_resolve_id
in
match res with [lhs_ae] -> Some (AddressOf lhs_ae) | _ -> None )
| _ ->
| _ -> (
let res = of_exp ~include_array_indexes ~add_deref lhs_exp typ ~f_resolve_id in
match res with [lhs_ae] -> Some lhs_ae | _ -> None
match res with [lhs_ae] -> Some lhs_ae | _ -> None )

@ -39,8 +39,12 @@ val pp : Format.formatter -> t -> unit
val equal : t -> t -> bool
val of_lhs_exp :
include_array_indexes:bool -> add_deref:bool -> Exp.t -> Typ.t
-> f_resolve_id:(Var.t -> t option) -> t option
include_array_indexes:bool
-> add_deref:bool
-> Exp.t
-> Typ.t
-> f_resolve_id:(Var.t -> t option)
-> t option
(** convert [lhs_exp] to an access expression, resolving identifiers using [f_resolve_id] *)
val normalize : t -> t

@ -17,13 +17,13 @@ module Raw = struct
consistent, and the variable names should already be enough to distinguish the bases. *)
type base = Var.t * typ_ [@@deriving compare]
let equal_base = [%compare.equal : base]
let equal_base = [%compare.equal: base]
type access = ArrayAccess of Typ.t * t list | FieldAccess of Typ.Fieldname.t
and t = (base * access list) [@@deriving compare]
and t = base * access list [@@deriving compare]
let equal_access = [%compare.equal : access]
let equal_access = [%compare.equal: access]
let equal_access_list l1 l2 = Int.equal (List.compare compare_access l1 l2) 0
@ -50,7 +50,7 @@ module Raw = struct
F.fprintf fmt "%a.%a" pp_base base pp_access_list accesses
let equal = [%compare.equal : t]
let equal = [%compare.equal: t]
let truncate ((base, accesses) as t) =
match List.rev accesses with
@ -96,12 +96,12 @@ module Raw = struct
(Some base_typ, None)
| [last_access] ->
(Some base_typ, Some last_access)
| curr_access :: rest ->
| curr_access :: rest -> (
match get_access_type tenv base_typ curr_access with
| Some access_typ ->
last_access_info_impl tenv access_typ rest
| None ->
(None, None)
(None, None) )
in
last_access_info_impl tenv base_typ accesses
@ -134,7 +134,7 @@ module Raw = struct
let of_id id typ = (base_of_id id typ, [])
let of_exp ~include_array_indexes exp0 typ0 ~(f_resolve_id: Var.t -> t option) =
let of_exp ~include_array_indexes exp0 typ0 ~(f_resolve_id : Var.t -> t option) =
(* [typ] is the type of the last element of the access path (e.g., typeof(g) for x.f.g) *)
let rec of_exp_ exp typ accesses acc =
match exp with
@ -177,7 +177,7 @@ module Raw = struct
of_exp_ exp0 typ0 [] []
let of_lhs_exp ~include_array_indexes lhs_exp typ ~(f_resolve_id: Var.t -> t option) =
let of_lhs_exp ~include_array_indexes lhs_exp typ ~(f_resolve_id : Var.t -> t option) =
match of_exp ~include_array_indexes lhs_exp typ ~f_resolve_id with
| [lhs_ap] ->
Some lhs_ap
@ -208,7 +208,7 @@ module Abs = struct
type t = Abstracted of Raw.t | Exact of Raw.t [@@deriving compare]
let equal = [%compare.equal : t]
let equal = [%compare.equal: t]
let extract = function Exact ap | Abstracted ap -> ap
@ -296,8 +296,7 @@ let inner_class_normalize p =
(base, accesses) ) )
(* this$n.f ... -> this.f . ... *)
(* happens in ctrs only *)
| Some ((Var.ProgramVar pvar, typ), all_accesses)
when is_synthetic_this pvar ->
| Some ((Var.ProgramVar pvar, typ), all_accesses) when is_synthetic_this pvar ->
let varname = Mangled.from_string "this" in
mk_pvar_as varname pvar
|> Option.map ~f:(fun new_pvar -> (base_of_pvar new_pvar typ, all_accesses))

@ -8,6 +8,7 @@
(** The Smallfoot Intermediate Language: Annotations *)
open! IStd
module F = Format
type parameters = string list [@@deriving compare]
@ -33,6 +34,7 @@ let pp fmt annotation =
module Item = struct
(* Don't use nonrec due to https://github.com/janestreet/ppx_compare/issues/2 *)
(* type nonrec t = list (t, bool) [@@deriving compare]; *)
(** Annotation for one item: a list of annotations with visibility. *)
type t_ = (t * bool) list [@@deriving compare]
@ -67,7 +69,7 @@ module Method = struct
(** Annotation for a method: return value and list of parameters. *)
type t = Item.t * Item.t list [@@deriving compare]
let equal = [%compare.equal : t]
let equal = [%compare.equal: t]
(** Pretty print a method annotation. *)
let pp s fmt (ia, ial) = F.fprintf fmt "%a %s(%a)" Item.pp ia s (Pp.seq Item.pp) ial

@ -8,6 +8,7 @@
(** The Smallfoot Intermediate Language: Annotations *)
open! IStd
module F = Format
type parameters = string list

@ -10,7 +10,7 @@ module F = Format
type attributes_kind = ProcUndefined | ProcObjCAccessor | ProcDefined [@@deriving compare]
let equal_attributes_kind = [%compare.equal : attributes_kind]
let equal_attributes_kind = [%compare.equal: attributes_kind]
let attributes_kind_to_int64 =
[(ProcUndefined, Int64.zero); (ProcObjCAccessor, Int64.one); (ProcDefined, Int64.of_int 2)]
@ -23,10 +23,10 @@ let int64_of_attributes_kind a =
let deserialize_attributes_kind =
let int64_to_attributes_kind = List.Assoc.inverse attributes_kind_to_int64 in
function[@warning "-8"]
| Sqlite3.Data.INT n -> List.Assoc.find_exn ~equal:Int64.equal int64_to_attributes_kind n
| Sqlite3.Data.INT n -> List.Assoc.find_exn ~equal:Int64.equal int64_to_attributes_kind n
let proc_kind_of_attr (proc_attributes: ProcAttributes.t) =
let proc_kind_of_attr (proc_attributes : ProcAttributes.t) =
if proc_attributes.is_defined then ProcDefined
else if Option.is_some proc_attributes.objc_accessor then ProcObjCAccessor
else ProcUndefined
@ -124,7 +124,7 @@ let find ~defined pname_blob =
let load pname = Typ.Procname.SQLite.serialize pname |> find ~defined:false
let store (attr: ProcAttributes.t) =
let store (attr : ProcAttributes.t) =
let pkind = proc_kind_of_attr attr in
let key = Typ.Procname.SQLite.serialize attr.proc_name in
if should_try_to_update key pkind then

@ -34,7 +34,7 @@ type t =
| LOr (** logical or. Does not always evaluate both operands. *)
[@@deriving compare]
let equal = [%compare.equal : t]
let equal = [%compare.equal: t]
(** This function returns true if the operation is injective
wrt. each argument: op(e,-) and op(-, e) is injective for all e.

@ -10,7 +10,7 @@ module F = Format
type t = {pname: Typ.Procname.t; loc: Location.t} [@@deriving compare]
let equal = [%compare.equal : t]
let equal = [%compare.equal: t]
let pname t = t.pname

@ -20,7 +20,8 @@ let iter_over_sorted_procs cfg ~f =
Typ.Procname.compare (Procdesc.get_proc_name pdesc1) (Procdesc.get_proc_name pdesc2)
in
Typ.Procname.Hash.fold (fun _ pdesc acc -> pdesc :: acc) cfg []
|> List.sort ~compare:compare_proc_desc_by_proc_name |> List.iter ~f
|> List.sort ~compare:compare_proc_desc_by_proc_name
|> List.iter ~f
let get_all_proc_names cfg =
@ -30,7 +31,7 @@ let get_all_proc_names cfg =
(** Create a new procdesc *)
let create_proc_desc cfg (proc_attributes: ProcAttributes.t) =
let create_proc_desc cfg (proc_attributes : ProcAttributes.t) =
let pdesc = Procdesc.from_proc_attributes proc_attributes in
Typ.Procname.Hash.add cfg proc_attributes.proc_name pdesc ;
pdesc
@ -38,13 +39,14 @@ let create_proc_desc cfg (proc_attributes: ProcAttributes.t) =
(** Iterate over all the nodes in the cfg *)
let iter_all_nodes ~sorted cfg ~f =
let do_proc_desc _ (pdesc: Procdesc.t) =
let do_proc_desc _ (pdesc : Procdesc.t) =
List.iter ~f:(fun node -> f pdesc node) (Procdesc.get_nodes pdesc)
in
if not sorted then Typ.Procname.Hash.iter do_proc_desc cfg
else
iter_over_sorted_procs cfg ~f:(fun pdesc ->
Procdesc.get_nodes pdesc |> List.sort ~compare:Procdesc.Node.compare
Procdesc.get_nodes pdesc
|> List.sort ~compare:Procdesc.Node.compare
|> List.iter ~f:(fun node -> f pdesc node) )
@ -58,7 +60,8 @@ end)
let load source =
ResultsDatabase.with_registered_statement load_statement ~f:(fun db load_stmt ->
SourceFile.SQLite.serialize source |> Sqlite3.bind load_stmt 1
SourceFile.SQLite.serialize source
|> Sqlite3.bind load_stmt 1
|> SqliteUtils.check_result_code db ~log:"load bind source file" ;
SqliteUtils.result_single_column_option ~finalize:false ~log:"Cfg.load" db load_stmt
|> Option.map ~f:SQLite.deserialize )
@ -98,7 +101,8 @@ let inline_synthetic_method ((ret_id, _) as ret) etl pdesc loc_call : Sil.instr
| Sil.Store (Exp.Lfield (_, fn, ft), bt, _, _), [(* setter for fields *) (e1, _); (e2, _)] ->
let instr' = Sil.Store (Exp.Lfield (e1, fn, ft), bt, e2, loc_call) in
found instr instr'
| Sil.Store (Exp.Lfield (Exp.Lvar pvar, fn, ft), bt, _, _), [(e1, _)] when Pvar.is_global pvar ->
| Sil.Store (Exp.Lfield (Exp.Lvar pvar, fn, ft), bt, _, _), [(e1, _)] when Pvar.is_global pvar
->
(* setter for static fields *)
let instr' = Sil.Store (Exp.Lfield (Exp.Lvar pvar, fn, ft), bt, e1, loc_call) in
found instr instr'
@ -129,7 +133,7 @@ let proc_inline_synthetic_methods cfg pdesc : unit =
let instr_inline_synthetic_method instr =
match instr with
| Sil.Call (ret_id_typ, Exp.Const (Const.Cfun (Typ.Procname.Java java_pn as pn)), etl, loc, _)
-> (
-> (
match Typ.Procname.Hash.find cfg pn with
| pd ->
let is_access = Typ.Procname.Java.is_access_method java_pn in

@ -10,7 +10,7 @@ open! IStd
type t = CPP_INSTANCE | OBJC_INSTANCE | CPP_CLASS | OBJC_CLASS | BLOCK | C_FUNCTION
[@@deriving compare]
let equal = [%compare.equal : t]
let equal = [%compare.equal: t]
let to_string = function
| CPP_INSTANCE ->

@ -19,7 +19,7 @@ type t =
| Cclass of Ident.name (** class constant *)
[@@deriving compare]
let equal = [%compare.equal : t]
let equal = [%compare.equal: t]
let kind_equal c1 c2 =
let const_kind_number = function

@ -50,7 +50,7 @@ let rec pp fmt = function
match builtin_functions_to_string pn with
| Some str ->
F.pp_print_string fmt str
| None ->
| None -> (
let procname_str = Typ.Procname.to_simplified_string pn in
match pn with
| Typ.Procname.ObjC_Cpp {kind= ObjCInstanceMethod}
@ -61,7 +61,7 @@ let rec pp fmt = function
| None ->
F.pp_print_string fmt procname_str )
| _ ->
F.pp_print_string fmt procname_str )
F.pp_print_string fmt procname_str ) )
| Dconst c ->
(Const.pp Pp.text) fmt c
| Dderef de ->
@ -148,7 +148,8 @@ let pp_vpath pe fmt vpath =
let rec has_tmp_var = function
| Dpvar pvar | Dpvaraddr pvar ->
Pvar.is_frontend_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
| Darray (dexp1, dexp2) | Dbinop (_, dexp1, dexp2) ->
has_tmp_var dexp1 || has_tmp_var dexp2

@ -109,7 +109,7 @@ module ErrLogHash = struct
let equal key1 key2 =
[%compare.equal : Exceptions.severity * bool * IssueType.t]
[%compare.equal: Exceptions.severity * bool * IssueType.t]
(key1.severity, key1.in_footprint, key1.err_name)
(key2.severity, key2.in_footprint, key2.err_name)
&& Localise.error_desc_equal key1.err_desc key2.err_desc
@ -130,20 +130,20 @@ let empty () = ErrLogHash.create 13
type iter_fun = err_key -> err_data -> unit
(** Apply f to nodes and error names *)
let iter (f: iter_fun) (err_log: t) =
let iter (f : iter_fun) (err_log : t) =
ErrLogHash.iter
(fun err_key set -> ErrDataSet.iter (fun err_data -> f err_key err_data) set)
err_log
let fold (f: err_key -> err_data -> 'a -> 'a) t acc =
let fold (f : err_key -> err_data -> 'a -> 'a) t acc =
ErrLogHash.fold
(fun err_key set acc -> ErrDataSet.fold (fun err_data acc -> f err_key err_data acc) set acc)
t acc
(** Return the number of elements in the error log which satisfy [filter] *)
let size filter (err_log: t) =
let size filter (err_log : t) =
let count = ref 0 in
ErrLogHash.iter
(fun key err_datas ->
@ -154,7 +154,7 @@ let size filter (err_log: t) =
(** Print errors from error log *)
let pp_errors fmt (errlog: t) =
let pp_errors fmt (errlog : t) =
let f key _ =
if Exceptions.equal_severity key.severity Exceptions.Error then
F.fprintf fmt "%a@ " IssueType.pp key.err_name
@ -163,7 +163,7 @@ let pp_errors fmt (errlog: t) =
(** Print warnings from error log *)
let pp_warnings fmt (errlog: t) =
let pp_warnings fmt (errlog : t) =
let f key _ =
if Exceptions.equal_severity key.severity Exceptions.Warning then
F.fprintf fmt "%a %a@ " IssueType.pp key.err_name Localise.pp_error_desc key.err_desc
@ -172,7 +172,7 @@ let pp_warnings fmt (errlog: t) =
(** Print an error log in html format *)
let pp_html source path_to_root fmt (errlog: t) =
let pp_html source path_to_root fmt (errlog : t) =
let pp_eds fmt err_datas =
let pp_nodeid_session_loc fmt err_data =
Io_infer.Html.pp_session_link source path_to_root fmt
@ -198,7 +198,7 @@ let pp_html source path_to_root fmt (errlog: t) =
(** Add an error description to the error log unless there is
one already at the same node + session; return true if added *)
let add_issue tbl err_key (err_datas: ErrDataSet.t) : bool =
let add_issue tbl err_key (err_datas : ErrDataSet.t) : bool =
try
let current_eds = ErrLogHash.find tbl err_key in
if ErrDataSet.subset err_datas current_eds then false
@ -221,7 +221,7 @@ let log_issue procname ~clang_method_kind severity err_log ~loc ~node ~session ~
let severity = Option.value error.severity ~default:severity in
let hide_java_loc_zero =
(* hide java errors at location zero unless in -developer_mode *)
not Config.developer_mode && Language.curr_language_is Java && Int.equal loc.Location.line 0
(not Config.developer_mode) && Language.curr_language_is Java && Int.equal loc.Location.line 0
in
let hide_memory_error =
match Localise.error_desc_get_bucket error.description with
@ -242,26 +242,26 @@ let log_issue procname ~clang_method_kind severity err_log ~loc ~node ~session ~
|| (Config.developer_mode && exn_developer)
in
( if exn_developer then
let issue =
let lang = Typ.Procname.get_language procname in
let clang_method_kind =
match lang with
| Language.Clang ->
Option.map ~f:ClangMethodKind.to_string clang_method_kind
| _ ->
None
in
EventLogger.AnalysisIssue
{ bug_type= error.name.IssueType.unique_id
; bug_kind= Exceptions.severity_string severity
; clang_method_kind
; exception_triggered_location= error.ocaml_pos
; lang= Language.to_explicit_string lang
; procedure_name= Typ.Procname.to_string procname
; source_location= loc }
let issue =
let lang = Typ.Procname.get_language procname in
let clang_method_kind =
match lang with
| Language.Clang ->
Option.map ~f:ClangMethodKind.to_string clang_method_kind
| _ ->
None
in
EventLogger.log issue ) ;
if should_report && not hide_java_loc_zero && not hide_memory_error then
EventLogger.AnalysisIssue
{ bug_type= error.name.IssueType.unique_id
; bug_kind= Exceptions.severity_string severity
; clang_method_kind
; exception_triggered_location= error.ocaml_pos
; lang= Language.to_explicit_string lang
; procedure_name= Typ.Procname.to_string procname
; source_location= loc }
in
EventLogger.log issue ) ;
if should_report && (not hide_java_loc_zero) && not hide_memory_error then
let added =
let node_id, node_key =
match node with

@ -75,7 +75,7 @@ val iter : iter_fun -> t -> unit
val fold : (err_key -> err_data -> 'a -> 'a) -> t -> 'a -> 'a
val pp_loc_trace_elem : Format.formatter -> loc_trace_elem -> unit [@@warning "-32"]
val pp_loc_trace_elem : Format.formatter -> loc_trace_elem -> unit [@@warning "-32"]
val pp_loc_trace : Format.formatter -> loc_trace -> unit
@ -95,6 +95,17 @@ val update : t -> t -> unit
(** Update an old error log with a new one *)
val log_issue :
Typ.Procname.t -> clang_method_kind:ClangMethodKind.t option -> Exceptions.severity -> t
-> loc:Location.t -> node:node -> session:int -> ltr:loc_trace -> linters_def_file:string option
-> doc_url:string option -> access:string option -> extras:Jsonbug_t.extra option -> exn -> unit
Typ.Procname.t
-> clang_method_kind:ClangMethodKind.t option
-> Exceptions.severity
-> t
-> loc:Location.t
-> node:node
-> session:int
-> ltr:loc_trace
-> linters_def_file:string option
-> doc_url:string option
-> access:string option
-> extras:Jsonbug_t.extra option
-> exn
-> unit

@ -17,7 +17,7 @@ type visibility =
| Exn_system (** never add to error log *)
[@@deriving compare]
let equal_visibility = [%compare.equal : visibility]
let equal_visibility = [%compare.equal: visibility]
let string_of_visibility vis =
match vis with Exn_user -> "user" | Exn_developer -> "developer" | Exn_system -> "system"
@ -26,12 +26,12 @@ let string_of_visibility vis =
(** class of error/warning *)
type err_class = Checker | Prover | Nocat | Linters [@@deriving compare]
let equal_err_class = [%compare.equal : err_class]
let equal_err_class = [%compare.equal: err_class]
(** severity of the report *)
type severity = Advice | Error | Info | Like | Warning [@@deriving compare]
let equal_severity = [%compare.equal : severity]
let equal_severity = [%compare.equal: severity]
exception Abduction_case_not_implemented of L.ocaml_pos

@ -152,8 +152,14 @@ val print_exception_html : string -> exn -> unit
(** print a description of the exception to the html output *)
val pp_err :
Location.t -> severity -> IssueType.t -> Localise.error_desc -> Logging.ocaml_pos option
-> Format.formatter -> unit -> unit
Location.t
-> severity
-> IssueType.t
-> Localise.error_desc
-> Logging.ocaml_pos option
-> Format.formatter
-> unit
-> unit
(** pretty print an error *)
type t =

@ -47,7 +47,7 @@ and t =
| Sizeof of sizeof_data
[@@deriving compare]
let equal = [%compare.equal : t]
let equal = [%compare.equal: t]
let hash = Hashtbl.hash
@ -268,18 +268,17 @@ let is_objc_block_closure = function
let rec gen_free_vars =
let open Sequence.Generator in
function
| Var id ->
yield id
| Cast (_, e) | Exn e | Lfield (e, _, _) | Sizeof {dynamic_length= Some e} | UnOp (_, e, _) ->
gen_free_vars e
| Closure {captured_vars} ->
ISequence.gen_sequence_list captured_vars ~f:(fun (e, _, _) -> gen_free_vars e)
| Const (Cint _ | Cfun _ | Cstr _ | Cfloat _ | Cclass _)
| Lvar _
| Sizeof {dynamic_length= None} ->
return ()
| BinOp (_, e1, e2) | Lindex (e1, e2) ->
gen_free_vars e1 >>= fun () -> gen_free_vars e2
| Var id ->
yield id
| Cast (_, e) | Exn e | Lfield (e, _, _) | Sizeof {dynamic_length= Some e} | UnOp (_, e, _) ->
gen_free_vars e
| Closure {captured_vars} ->
ISequence.gen_sequence_list captured_vars ~f:(fun (e, _, _) -> gen_free_vars e)
| Const (Cint _ | Cfun _ | Cstr _ | Cfloat _ | Cclass _) | Lvar _ | Sizeof {dynamic_length= None}
->
return ()
| BinOp (_, e1, e2) | Lindex (e1, e2) ->
gen_free_vars e1 >>= fun () -> gen_free_vars e2
let free_vars e = Sequence.Generator.run (gen_free_vars e)
@ -289,16 +288,16 @@ let ident_mem e id = free_vars e |> Sequence.exists ~f:(Ident.equal id)
let rec gen_program_vars =
let open Sequence.Generator in
function
| Lvar name ->
yield name
| Const _ | Var _ | Sizeof {dynamic_length= None} ->
return ()
| Cast (_, e) | Exn e | Lfield (e, _, _) | Sizeof {dynamic_length= Some e} | UnOp (_, e, _) ->
gen_program_vars e
| BinOp (_, e1, e2) | Lindex (e1, e2) ->
gen_program_vars e1 >>= fun () -> gen_program_vars e2
| Closure {captured_vars} ->
ISequence.gen_sequence_list captured_vars ~f:(fun (e, _, _) -> gen_program_vars e)
| Lvar name ->
yield name
| Const _ | Var _ | Sizeof {dynamic_length= None} ->
return ()
| Cast (_, e) | Exn e | Lfield (e, _, _) | Sizeof {dynamic_length= Some e} | UnOp (_, e, _) ->
gen_program_vars e
| BinOp (_, e1, e2) | Lindex (e1, e2) ->
gen_program_vars e1 >>= fun () -> gen_program_vars e2
| Closure {captured_vars} ->
ISequence.gen_sequence_list captured_vars ~f:(fun (e, _, _) -> gen_program_vars e)
let program_vars e = Sequence.Generator.run (gen_program_vars e)

@ -32,14 +32,14 @@ let mk_procedure_name_filter ~filter =
match filter with
| None ->
(None, None)
| Some filter_string ->
| Some filter_string -> (
match String.lsplit2 ~on:':' filter_string with
| Some (source_file_filter, proc_name_filter) ->
(Some (Str.regexp source_file_filter), Some (Str.regexp proc_name_filter))
| None ->
(* if only one filter is supplied assume it's for procedure names and the source files are
a wildcard *)
(None, Some (Str.regexp filter_string))
(None, Some (Str.regexp filter_string)) )
in
let source_file_filter =
filter_of_regexp_opt ~to_string:SourceFile.to_string source_file_regexp

@ -57,11 +57,9 @@ let rec get_typ tenv = function
| BinaryOperator ((Lt | Gt | Le | Ge | Eq | Ne | LAnd | LOr), _, _) ->
Some (Typ.mk (Typ.Tint Typ.IBool))
| BinaryOperator (_, e1, e2) -> (
match
(* TODO: doing this properly will require taking account of language-specific coercion
(* TODO: doing this properly will require taking account of language-specific coercion
semantics. Only return a type when the operands have the same type for now *)
(get_typ tenv e1, get_typ tenv e2)
with
match (get_typ tenv e1, get_typ tenv e2) with
| Some typ1, Some typ2 when Typ.equal typ1 typ2 ->
Some typ1
| _ ->
@ -112,7 +110,7 @@ let get_access_exprs exp0 =
produce the same result as evaluating the SIL expression and replacing the temporary variables
using [f_resolve_id] *)
let of_sil ~include_array_indexes ~f_resolve_id ~add_deref exp typ =
let rec of_sil_ (exp: Exp.t) typ =
let rec of_sil_ (exp : Exp.t) typ =
match exp with
| Var id ->
let ae =
@ -168,7 +166,8 @@ let of_sil ~include_array_indexes ~f_resolve_id ~add_deref exp typ =
(Exp.Lfield
( Var (Ident.create_normal (Ident.string_to_name (Exp.to_string root_exp)) 0)
, fld
, root_exp_typ )) typ )
, root_exp_typ ))
typ )
| Lindex (Const (Cstr s), index_exp) ->
(* indexed string literal (e.g., "foo"[1]). represent this by introducing a dummy variable
for the string literal. if you actually need to see the value of the string literal in the
@ -186,15 +185,16 @@ let of_sil ~include_array_indexes ~f_resolve_id ~add_deref exp typ =
of_sil_
(Exp.Lindex
( Var (Ident.create_normal (Ident.string_to_name (Exp.to_string root_exp)) 0)
, index_exp )) typ )
| Lvar _ ->
, index_exp ))
typ )
| Lvar _ -> (
match
AccessExpression.of_lhs_exp ~include_array_indexes ~add_deref exp typ ~f_resolve_id
with
| Some access_expr ->
AccessExpression access_expr
| None ->
L.(die InternalError) "Couldn't convert var expression %a to access path" Exp.pp exp
L.(die InternalError) "Couldn't convert var expression %a to access path" Exp.pp exp )
in
of_sil_ exp typ

@ -28,8 +28,12 @@ val get_typ : Tenv.t -> t -> Typ.t option
(** Get the type of the expression. Warning: not fully implemented *)
val of_sil :
include_array_indexes:bool -> f_resolve_id:(Var.t -> AccessExpression.t option) -> add_deref:bool
-> Exp.t -> Typ.t -> t
include_array_indexes:bool
-> f_resolve_id:(Var.t -> AccessExpression.t option)
-> add_deref:bool
-> Exp.t
-> Typ.t
-> t
(** Convert SIL expression to HIL expression *)
val get_access_exprs : t -> AccessExpression.t list

@ -45,11 +45,11 @@ type translation =
SSA temporary variable to the access path it represents. Evaluating the HIL instruction should
produce the same result as evaluating the SIL instruction and replacing the temporary variables
using [f_resolve_id]. *)
let of_sil ~include_array_indexes ~f_resolve_id (instr: Sil.instr) =
let exp_of_sil ?(add_deref= false) =
let of_sil ~include_array_indexes ~f_resolve_id (instr : Sil.instr) =
let exp_of_sil ?(add_deref = false) =
HilExp.of_sil ~include_array_indexes ~f_resolve_id ~add_deref
in
let analyze_id_assignment ?(add_deref= false) lhs_id rhs_exp rhs_typ loc =
let analyze_id_assignment ?(add_deref = false) lhs_id rhs_exp rhs_typ loc =
let rhs_hil_exp = exp_of_sil ~add_deref rhs_exp rhs_typ in
match rhs_hil_exp with
| AccessExpression rhs_access_expr ->
@ -77,23 +77,21 @@ let of_sil ~include_array_indexes ~f_resolve_id (instr: Sil.instr) =
| AccessExpression access_expr ->
access_expr
| BinaryOperator (_, exp0, exp1) -> (
match
(* pointer arithmetic. somewhere in one of the expressions, there should be at least
(* pointer arithmetic. somewhere in one of the expressions, there should be at least
one pointer type represented as an access path. just use that access path and forget
about the arithmetic. if you need to model this more precisely, you should be using
SIL instead *)
HilExp.get_access_exprs exp0
with
match HilExp.get_access_exprs exp0 with
| ap :: _ ->
ap
| [] ->
| [] -> (
match HilExp.get_access_exprs exp1 with
| ap :: _ ->
ap
| [] ->
L.(die InternalError)
"Invalid pointer arithmetic expression %a used as LHS at %a" Exp.pp lhs_exp
Location.pp_file_pos loc )
Location.pp_file_pos loc ) )
| Constant (Const.Cint i) ->
(* this can happen in intentionally crashing code like *0xdeadbeef = 0 used for
debugging. doesn't really matter what we do here, so just create a dummy var *)

@ -30,7 +30,9 @@ type translation =
| Ignore (** no-op *)
val of_sil :
include_array_indexes:bool -> f_resolve_id:(Var.t -> AccessExpression.t option) -> Sil.instr
include_array_indexes:bool
-> f_resolve_id:(Var.t -> AccessExpression.t option)
-> Sil.instr
-> translation
(** convert an SIL instruction into an HIL instruction. The [f_resolve_id] function should map an
SSA temporary variable to the access path it represents. Evaluating the HIL instruction should

@ -42,7 +42,7 @@ type name = Name.t [@@deriving compare]
let name_spec = Name.Spec
let equal_name = [%compare.equal : name]
let equal_name = [%compare.equal: name]
type kind =
| KNone
@ -59,7 +59,7 @@ let knormal = KNormal
let kprimed = KPrimed
let equal_kind = [%compare.equal : kind]
let equal_kind = [%compare.equal: kind]
(* timestamp for a path identifier *)
let path_ident_stamp = -3
@ -89,7 +89,7 @@ module Hash = Hashtbl.Make (struct
let equal = equal
let hash (id: t) = Hashtbl.hash id
let hash (id : t) = Hashtbl.hash id
end)
let idlist_to_idset ids = List.fold ~f:(fun set id -> Set.add id set) ~init:Set.empty ids
@ -139,9 +139,7 @@ module NameGenerator = struct
let stamp = NameHash.find !name_map name in
NameHash.replace !name_map name (stamp + 1) ;
stamp + 1
with Caml.Not_found ->
NameHash.add !name_map name 0 ;
0
with Caml.Not_found -> NameHash.add !name_map name 0 ; 0
in
{kind; name; stamp}
@ -199,15 +197,15 @@ let get_name id = id.name
let has_kind id kind = equal_kind id.kind kind
let is_primed (id: t) = has_kind id KPrimed
let is_primed (id : t) = has_kind id KPrimed
let is_normal (id: t) = has_kind id KNormal || has_kind id KNone
let is_normal (id : t) = has_kind id KNormal || has_kind id KNone
let is_footprint (id: t) = has_kind id KFootprint
let is_footprint (id : t) = has_kind id KFootprint
let is_none (id: t) = has_kind id KNone
let is_none (id : t) = has_kind id KNone
let is_path (id: t) = has_kind id KNormal && Int.equal id.stamp path_ident_stamp
let is_path (id : t) = has_kind id KNormal && Int.equal id.stamp path_ident_stamp
(** Update the name generator so that the given id's are not generated again *)
let update_name_generator ids =
@ -259,4 +257,4 @@ let hashqueue_of_sequence ?init s =
q
let set_of_sequence ?(init= Set.empty) s = Sequence.fold s ~init ~f:(fun ids id -> Set.add id ids)
let set_of_sequence ?(init = Set.empty) s = Sequence.fold s ~init ~f:(fun ids id -> Set.add id ids)

@ -45,8 +45,8 @@ type reversed
type not_reversed
type 'rev t =
| NotReversed: Sil.instr Array.t -> not_reversed t
| Reversed: Sil.instr RevArray.t -> reversed t
| NotReversed : Sil.instr Array.t -> not_reversed t
| Reversed : Sil.instr RevArray.t -> reversed t
type not_reversed_t = not_reversed t
@ -70,7 +70,9 @@ let filter_map (NotReversed instrs) ~f = NotReversed (Array.filter_map instrs ~f
let map_changed =
let aux_changed arr ~f i =
for i = i to Array.length arr - 1 do Array.unsafe_get arr i |> f |> Array.unsafe_set arr i done ;
for i = i to Array.length arr - 1 do
Array.unsafe_get arr i |> f |> Array.unsafe_set arr i
done ;
arr
in
let rec aux_unchanged ~equal arr ~f i =
@ -93,7 +95,7 @@ let reverse_order (NotReversed instrs) = Reversed (RevArray.of_rev_array instrs)
(* Functions on both reversed and non-reversed arrays *)
let is_empty (type r) (t: r t) =
let is_empty (type r) (t : r t) =
match t with
| NotReversed instrs ->
Array.is_empty instrs
@ -101,7 +103,7 @@ let is_empty (type r) (t: r t) =
RevArray.is_empty rev_instrs
let fold (type r) (t: r t) ~init ~f =
let fold (type r) (t : r t) ~init ~f =
match t with
| NotReversed instrs ->
Array.fold instrs ~init ~f
@ -115,7 +117,7 @@ let exists t ~f = Container.exists ~iter t ~f
let for_all t ~f = Container.for_all ~iter t ~f
let count (type r) (t: r t) =
let count (type r) (t : r t) =
match t with
| NotReversed instrs ->
Array.length instrs
@ -125,7 +127,7 @@ let count (type r) (t: r t) =
let nth_exists t index = index < count t
let nth_exn (type r) (t: r t) index =
let nth_exn (type r) (t : r t) index =
match t with
| NotReversed instrs ->
instrs.(index)
@ -133,7 +135,7 @@ let nth_exn (type r) (t: r t) index =
RevArray.get rev_instrs index
let last (type r) (t: r t) =
let last (type r) (t : r t) =
match t with
| NotReversed instrs ->
if is_empty t then None else Some (Array.last instrs)

@ -28,7 +28,9 @@ val of_rev_list : Sil.instr list -> not_reversed_t
val filter_map : not_reversed_t -> f:(Sil.instr -> Sil.instr option) -> not_reversed_t
val map_changed :
equal:(Sil.instr -> Sil.instr -> bool) -> not_reversed_t -> f:(Sil.instr -> Sil.instr)
equal:(Sil.instr -> Sil.instr -> bool)
-> not_reversed_t
-> f:(Sil.instr -> Sil.instr)
-> not_reversed_t
val reverse_order : not_reversed_t -> reversed t

@ -38,7 +38,7 @@ let compare (unsigned1, i1, _) (unsigned2, i2, _) =
let compare_value (unsigned1, i1, _) (unsigned2, i2, _) =
[%compare : int * Int64.t] (area unsigned1 i1, i1) (area unsigned2 i2, i2)
[%compare: int * Int64.t] (area unsigned1 i1, i1) (area unsigned2 i2, i2)
let eq i1 i2 = Int.equal (compare_value i1 i2) 0
@ -81,9 +81,9 @@ let iszero (_, i, _) = Int64.equal i 0L
let isnull (_, i, ptr) = Int64.equal i 0L && ptr
let isminusone (unsigned, i, _) = not unsigned && Int64.equal i (-1L)
let isminusone (unsigned, i, _) = (not unsigned) && Int64.equal i (-1L)
let isnegative (unsigned, i, _) = not unsigned && i < 0L
let isnegative (unsigned, i, _) = (not unsigned) && i < 0L
let neg (unsigned, i, ptr) = (unsigned, Int64.neg i, ptr)

@ -35,7 +35,7 @@ val of_int64 : int64 -> t
val geq : t -> t -> bool
val gt : t -> t -> bool [@@warning "-32"]
val gt : t -> t -> bool [@@warning "-32"]
val isminusone : t -> bool

@ -128,7 +128,7 @@ td.rowname { text-align:right; font-weight:bold; color:#444444; padding-right:2e
(** Print end color *)
let pp_end_color fmt () = F.pp_print_string fmt "</span>"
let pp_link ?(name= None) ?(pos= None) ~path fmt text =
let pp_link ?(name = None) ?(pos = None) ~path fmt text =
let link_str =
let escaped_path = List.map ~f:Escape.escape_url path in
DB.filename_to_string (DB.Results_dir.path_to_filename DB.Results_dir.Rel escaped_path)
@ -165,7 +165,7 @@ td.rowname { text-align:right; font-weight:bold; color:#444444; padding-right:2e
(** Print an html link to the given line number of the current source file *)
let pp_line_link ?(with_name= false) ?(text= None) source path_to_root fmt linenum =
let pp_line_link ?(with_name = false) ?(text = None) source path_to_root fmt linenum =
let fname = DB.source_file_encoding source in
let linenum_str = string_of_int linenum in
let name = "LINE" ^ linenum_str in
@ -178,7 +178,7 @@ td.rowname { text-align:right; font-weight:bold; color:#444444; padding-right:2e
(** Print an html link given node id and session *)
let pp_session_link ?(with_name= false) ?proc_name source path_to_root fmt
let pp_session_link ?(with_name = false) ?proc_name source path_to_root fmt
(node_id, session, linenum) =
let node_name = "node" ^ string_of_int node_id in
let text, pos =

@ -28,8 +28,13 @@ module Html : sig
(** Open an Html file to append data *)
val pp_line_link :
?with_name:bool -> ?text:string option -> SourceFile.t -> DB.Results_dir.path
-> Format.formatter -> int -> unit
?with_name:bool
-> ?text:string option
-> SourceFile.t
-> DB.Results_dir.path
-> Format.formatter
-> int
-> unit
(** Print an html link to the given line number of the current source file *)
val pp_hline : Format.formatter -> unit -> unit
@ -39,8 +44,17 @@ module Html : sig
(** Print end color *)
val pp_node_link :
DB.Results_dir.path -> Typ.Procname.t -> description:string -> preds:int list -> succs:int list
-> exn:int list -> isvisited:bool -> isproof:bool -> Format.formatter -> int -> unit
DB.Results_dir.path
-> Typ.Procname.t
-> description:string
-> preds:int list
-> succs:int list
-> exn:int list
-> isvisited:bool
-> isproof:bool
-> Format.formatter
-> int
-> unit
(** Print an html link to the given node.
Usage: [pp_node_link path_to_root ... fmt id].
[path_to_root] is the path to the dir for the procedure in the spec db.
@ -50,8 +64,13 @@ module Html : sig
(** Print an html link to the given proc *)
val pp_session_link :
?with_name:bool -> ?proc_name:Typ.Procname.t -> SourceFile.t -> string list -> Format.formatter
-> int * int * int -> unit
?with_name:bool
-> ?proc_name:Typ.Procname.t
-> SourceFile.t
-> string list
-> Format.formatter
-> int * int * int
-> unit
(** Print an html link given node id and session *)
val pp_start_color : Format.formatter -> Pp.color -> unit

@ -122,7 +122,7 @@ let error_desc_hash desc = Hashtbl.hash (desc_get_comparable desc)
(** equality for error_desc *)
let error_desc_equal desc1 desc2 =
[%compare.equal : string list] (desc_get_comparable desc1) (desc_get_comparable desc2)
[%compare.equal: string list] (desc_get_comparable desc1) (desc_get_comparable desc2)
let line_tag_ tags tag loc =
@ -260,7 +260,8 @@ let deref_str_undef (proc_name, loc) =
; value_post= None
; problem_str=
"could be assigned by a call to skip function " ^ proc_name_str
^ at_line_tag tags Tags.call_line loc ^ " and is dereferenced or freed" }
^ at_line_tag tags Tags.call_line loc
^ " and is dereferenced or freed" }
(** dereference strings for a freed pointer dereference *)
@ -447,12 +448,14 @@ let dereference_string proc_name deref_str value_str access_opt loc =
"is annotated with " ^ annotation_name ^ " and is dereferenced without a null check"
else
"is indirectly marked " ^ annotation_name ^ " (source: "
^ MF.monospaced_to_string nullable_src ^ ") and is dereferenced without a null check"
^ MF.monospaced_to_string nullable_src
^ ") and is dereferenced without a null check"
| None, Some weak_var_str ->
if String.equal weak_var_str value_str then
"is a weak pointer captured in the block and is dereferenced without a null check"
else
"is equal to the variable " ^ MF.monospaced_to_string weak_var_str
"is equal to the variable "
^ MF.monospaced_to_string weak_var_str
^ ", a weak pointer captured in the block, and is dereferenced without a null check"
| None, None ->
deref_str.problem_str
@ -460,10 +463,10 @@ let dereference_string proc_name deref_str value_str access_opt loc =
[problem_str ^ " " ^ at_line tags loc]
in
let access_desc = access_desc access_opt in
{no_desc with descriptions= value_desc :: access_desc @ problem_desc; tags= !tags}
{no_desc with descriptions= (value_desc :: access_desc) @ problem_desc; tags= !tags}
let parameter_field_not_null_checked_desc (desc: error_desc) exp =
let parameter_field_not_null_checked_desc (desc : error_desc) exp =
let parameter_not_nullable_desc var =
let var_s = Pvar.to_string var in
let param_not_null_desc =
@ -502,7 +505,7 @@ let parameter_field_not_null_checked_desc (desc: error_desc) exp =
desc
let has_tag (desc: error_desc) tag =
let has_tag (desc : error_desc) tag =
List.exists ~f:(fun (tag', _) -> String.equal tag tag') desc.tags
@ -518,8 +521,10 @@ let desc_allocation_mismatch alloc dealloc =
else
" by call to " ^ MF.monospaced_to_string (Typ.Procname.to_simplified_string called_pname)
in
"using " ^ MF.monospaced_to_string (Typ.Procname.to_simplified_string primitive_pname)
^ by_call ^ " " ^ at_line (Tags.create ()) (* ignore the tag *) loc
"using "
^ MF.monospaced_to_string (Typ.Procname.to_simplified_string primitive_pname)
^ by_call ^ " "
^ at_line (Tags.create ()) (* ignore the tag *) loc
in
let description =
Format.sprintf "%s %s is deallocated %s" mem_dyn_allocated (using alloc) (using dealloc)
@ -631,7 +636,8 @@ let desc_leak hpred_type_opt value_str_opt resource_opt resource_action_opt loc
| None ->
("", "", "")
| Some s ->
Tags.update tags Tags.value s ; (MF.monospaced_to_string s, " to ", " on ")
Tags.update tags Tags.value s ;
(MF.monospaced_to_string s, " to ", " on ")
in
let typ_str =
match hpred_type_opt with
@ -672,7 +678,7 @@ let desc_leak hpred_type_opt value_str_opt resource_opt resource_action_opt loc
match bucket_opt with Some bucket when Config.show_buckets -> bucket | _ -> ""
in
{ no_desc with
descriptions= bucket_str :: xxx_allocated_to @ by_call_to @ is_not_rxxx_after; tags= !tags }
descriptions= (bucket_str :: xxx_allocated_to) @ by_call_to @ is_not_rxxx_after; tags= !tags }
let desc_buffer_overrun desc = verbatim_desc desc
@ -724,8 +730,8 @@ let desc_registered_observer_being_deallocated pvar loc =
let obj_str = MF.monospaced_to_string (Pvar.to_string pvar) in
{ no_desc with
descriptions=
[ registered_observer_being_deallocated_str obj_str ^ at_line tags loc
^ ". Being still registered as observer of the notification "
[ registered_observer_being_deallocated_str obj_str
^ at_line tags loc ^ ". Being still registered as observer of the notification "
^ "center, the deallocated object " ^ obj_str ^ " may be notified in the future." ]
; tags= !tags }

@ -35,7 +35,7 @@ module BucketLevel : sig
val b3 : string
val b4 : string [@@warning "-32"]
val b4 : string [@@warning "-32"]
val b5 : string
(** lowest likelihood *)
@ -113,7 +113,8 @@ val is_parameter_not_null_checked_desc : error_desc -> bool
val is_field_not_null_checked_desc : error_desc -> bool
val desc_allocation_mismatch :
Typ.Procname.t * Typ.Procname.t * Location.t -> Typ.Procname.t * Typ.Procname.t * Location.t
Typ.Procname.t * Typ.Procname.t * Location.t
-> Typ.Procname.t * Typ.Procname.t * Location.t
-> error_desc
val desc_class_cast_exception :
@ -136,8 +137,13 @@ val is_empty_vector_access_desc : error_desc -> bool
val desc_frontend_warning : string -> string option -> Location.t -> error_desc
val desc_leak :
Exp.t option -> string option -> PredSymb.resource option -> PredSymb.res_action option
-> Location.t -> string option -> error_desc
Exp.t option
-> string option
-> PredSymb.resource option
-> PredSymb.res_action option
-> Location.t
-> string option
-> error_desc
val desc_buffer_overrun : string -> error_desc

@ -13,19 +13,21 @@ module F = Format
type t = {plain: string; mangled: string option} [@@deriving compare]
let equal = [%compare.equal : t]
let equal = [%compare.equal: t]
(** Convert a string to a mangled name *)
let from_string (s: string) = {plain= s; mangled= None}
let from_string (s : string) = {plain= s; mangled= None}
(** Create a mangled name from a plain and mangled string *)
let mangled (plain: string) (mangled: string) = {plain; mangled= Some (plain ^ "{" ^ mangled ^ "}")}
let mangled (plain : string) (mangled : string) =
{plain; mangled= Some (plain ^ "{" ^ mangled ^ "}")}
(** Convert a mangled name to a string *)
let to_string (pn: t) = pn.plain
let to_string (pn : t) = pn.plain
(** Convert a full mangled name to a string *)
let to_string_full (pn: t) =
let to_string_full (pn : t) =
match pn.mangled with Some mangled -> pn.plain ^ "{" ^ mangled ^ "}" | None -> pn.plain

@ -20,7 +20,7 @@ let pp_func_attribute fmt = function FA_sentinel (i, j) -> F.fprintf fmt "sentin
(** Visibility modifiers. *)
type access = Default | Public | Private | Protected [@@deriving compare]
let equal_access = [%compare.equal : access]
let equal_access = [%compare.equal: access]
let string_of_access = function
| Default ->
@ -55,7 +55,7 @@ type resource = Rmemory of mem_kind | Rfile | Rignore | Rlock [@@deriving compar
(** kind of resource action *)
type res_act_kind = Racquire | Rrelease [@@deriving compare]
let equal_res_act_kind = [%compare.equal : res_act_kind]
let equal_res_act_kind = [%compare.equal: res_act_kind]
(** kind of dangling pointers *)
type dangling_kind =
@ -69,7 +69,7 @@ type dangling_kind =
(** position in a path: proc name, node id *)
type path_pos = Typ.Procname.t * int [@@deriving compare]
let equal_path_pos = [%compare.equal : path_pos]
let equal_path_pos = [%compare.equal: path_pos]
(** acquire/release action on a resource *)
type res_action =
@ -81,7 +81,7 @@ type res_action =
(* ignore other values beside resources: arbitrary merging into one *)
let compare_res_action {ra_kind= k1; ra_res= r1} {ra_kind= k2; ra_res= r2} =
[%compare : res_act_kind * resource] (k1, r1) (k2, r2)
[%compare: res_act_kind * resource] (k1, r1) (k2, r2)
(* type aliases for components of t values that compare should ignore *)
@ -123,7 +123,7 @@ type t =
| Awont_leak (** value do not participate in memory leak analysis *)
[@@deriving compare]
let equal = [%compare.equal : t]
let equal = [%compare.equal: t]
(** name of the allocation function for the given memory kind *)
let mem_alloc_pname = function
@ -162,7 +162,7 @@ type category =
| ACwontleak
[@@deriving compare]
let equal_category = [%compare.equal : category]
let equal_category = [%compare.equal: category]
let to_category att =
match att with
@ -221,8 +221,11 @@ let to_string pe = function
let str_vpath =
if Config.trace_error then F.asprintf "%a" (DecompiledExp.pp_vpath pe) ra.ra_vpath else ""
in
name ^ Binop.str pe Lt ^ Typ.Procname.to_string ra.ra_pname ^ ":"
^ string_of_int ra.ra_loc.Location.line ^ Binop.str pe Gt ^ str_vpath
name ^ Binop.str pe Lt
^ Typ.Procname.to_string ra.ra_pname
^ ":"
^ string_of_int ra.ra_loc.Location.line
^ Binop.str pe Gt ^ str_vpath
| Aautorelease ->
"AUTORELEASE"
| Adangling dk ->
@ -260,4 +263,4 @@ let to_string pe = function
let pp pe fmt a = F.pp_print_string fmt (to_string pe a)
(** dump an attribute *)
let d_attribute (a: t) = L.add_print_with_pe pp a
let d_attribute (a : t) = L.add_print_with_pe pp a

@ -39,7 +39,7 @@ type var_attribute = Modify_in_block [@@deriving compare]
let string_of_var_attribute = function Modify_in_block -> "<Modify_in_block>"
let var_attribute_equal = [%compare.equal : var_attribute]
let var_attribute_equal = [%compare.equal: var_attribute]
type var_data = {name: Mangled.t; typ: Typ.t; attributes: var_attribute list} [@@deriving compare]
@ -151,24 +151,24 @@ let pp f
SourceFile.pp translation_unit ;
if not (PredSymb.equal_access default.access access) then
F.fprintf f "; access= %a@," (Pp.to_string ~f:PredSymb.string_of_access) access ;
if not ([%compare.equal : (Mangled.t * Typ.t) list] default.captured captured) then
if not ([%compare.equal: (Mangled.t * Typ.t) list] default.captured captured) then
F.fprintf f "; captured= [@[%a@]]@," pp_parameters captured ;
pp_bool_default ~default:default.did_preanalysis "did_preanalysis" did_preanalysis f () ;
if not ([%compare.equal : string list] default.exceptions exceptions) then
if not ([%compare.equal: string list] default.exceptions exceptions) then
F.fprintf f "; exceptions= [@[%a@]]@,"
(Pp.semicolon_seq ~print_env:Pp.text_break F.pp_print_string)
exceptions ;
(* always print formals *)
F.fprintf f "; formals= [@[%a@]]@," pp_parameters formals ;
if not ([%compare.equal : int list] default.const_formals const_formals) then
if not ([%compare.equal: int list] default.const_formals const_formals) then
F.fprintf f "; const_formals= [@[%a@]]@,"
(Pp.semicolon_seq ~print_env:Pp.text_break F.pp_print_int)
const_formals ;
if not ([%compare.equal : int list] default.by_vals by_vals) then
if not ([%compare.equal: int list] default.by_vals by_vals) then
F.fprintf f "; by_vals= [@[%a@]]@,"
(Pp.semicolon_seq ~print_env:Pp.text_break F.pp_print_int)
by_vals ;
if not ([%compare.equal : PredSymb.func_attribute list] default.func_attributes func_attributes)
if not ([%compare.equal: PredSymb.func_attribute list] default.func_attributes func_attributes)
then
F.fprintf f "; func_attributes= [@[%a@]]@,"
(Pp.semicolon_seq ~print_env:Pp.text_break PredSymb.pp_func_attribute)
@ -191,7 +191,7 @@ let pp f
(Pp.to_string ~f:ClangMethodKind.to_string)
clang_method_kind ;
if not (Location.equal default.loc loc) then F.fprintf f "; loc= %a@," Location.pp loc ;
if not ([%compare.equal : var_data list] default.locals locals) then
if not ([%compare.equal: var_data list] default.locals locals) then
F.fprintf f "; locals= [@[%a@]]@,"
(Pp.semicolon_seq ~print_env:Pp.text_break pp_var_data)
locals ;
@ -199,7 +199,7 @@ let pp f
has_added_return_param f () ;
if not (Annot.Method.equal default.method_annotation method_annotation) then
F.fprintf f "; method_annotation= %a@," (Annot.Method.pp "") method_annotation ;
if not ([%compare.equal : objc_accessor_type option] default.objc_accessor objc_accessor) then
if not ([%compare.equal: objc_accessor_type option] default.objc_accessor objc_accessor) then
F.fprintf f "; objc_accessor= %a@," (Pp.option pp_objc_accessor_type) objc_accessor ;
if
(* HACK: this hardcodes the default instead of comparing to [default.proc_flags], and tests

@ -32,7 +32,7 @@ end
module Node = struct
type id = int [@@deriving compare]
let equal_id = [%compare.equal : id]
let equal_id = [%compare.equal: id]
type stmt_nodekind =
| AssertionFailure
@ -84,7 +84,7 @@ module Node = struct
| Skip_node of string
[@@deriving compare]
let equal_nodekind = [%compare.equal : nodekind]
let equal_nodekind = [%compare.equal: nodekind]
(** a node *)
type t =
@ -120,7 +120,7 @@ module Node = struct
let hash node = Hashtbl.hash node.id
let equal = [%compare.equal : t]
let equal = [%compare.equal: t]
(** Get the unique id of the node *)
let get_id node = node.id
@ -160,7 +160,8 @@ module Node = struct
let get_siblings node =
get_preds node
|> ISequence.gen_sequence_list ~f:(fun parent ->
get_succs parent |> Sequence.of_list |> Sequence.filter ~f:(fun n -> not (equal node n))
get_succs parent |> Sequence.of_list
|> Sequence.filter ~f:(fun n -> not (equal node n))
|> Sequence.Generator.of_sequence )
|> Sequence.Generator.run
@ -182,8 +183,7 @@ module Node = struct
let find_in_node_or_preds =
let rec find ~f visited nodes =
match nodes with
| node :: nodes when not (NodeSet.mem node visited)
-> (
| node :: nodes when not (NodeSet.mem node visited) -> (
let instrs = get_instrs node in
match Instrs.find_map ~f:(f node) instrs with
| Some res ->
@ -325,7 +325,7 @@ module Node = struct
(** Dump extended instructions for the node *)
let d_instrs ~(sub_instrs: bool) (curr_instr: Sil.instr option) (node: t) =
let d_instrs ~(sub_instrs : bool) (curr_instr : Sil.instr option) (node : t) =
L.add_print_with_pe ~color:Pp.Green (pp_instrs ~sub_instrs ~instro:curr_instr) node
@ -374,7 +374,8 @@ module Node = struct
in
Some instr_key
in
get_instrs node |> IContainer.rev_filter_map_to_list ~fold:Instrs.fold ~f:add_instr
get_instrs node
|> IContainer.rev_filter_map_to_list ~fold:Instrs.fold ~f:add_instr
|> Utils.better_hash
@ -420,7 +421,7 @@ let compute_distance_to_exit_node pdesc =
let exit_node = pdesc.exit_node in
let rec mark_distance dist nodes =
let next_nodes = ref [] in
let do_node (node: Node.t) =
let do_node (node : Node.t) =
match node.dist_exit with
| Some _ ->
()
@ -530,13 +531,13 @@ let append_locals pdesc 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
(** Set the successor nodes and exception nodes, and build predecessor links *)
let set_succs_exn_base (node: Node.t) succs exn =
let set_succs_exn_base (node : Node.t) succs exn =
node.succs <- succs ;
node.exn <- exn ;
List.iter ~f:(fun (n: Node.t) -> n.preds <- node :: n.preds) succs
List.iter ~f:(fun (n : Node.t) -> n.preds <- node :: n.preds) succs
(** Create a new cfg node *)
@ -563,7 +564,7 @@ let create_node pdesc loc kind instrs = create_node_internal pdesc loc kind (Ins
(** Set the successor and exception nodes.
If this is a join node right before the exit node, add an extra node in the middle,
otherwise nullify and abstract instructions cannot be added after a conditional. *)
let node_set_succs_exn pdesc (node: Node.t) succs exn =
let node_set_succs_exn pdesc (node : Node.t) succs exn =
match (node.kind, succs) with
| Join_node, [({Node.kind= Exit_node _} as exit_node)] ->
let kind = Node.Stmt_node BetweenJoinAndExit in
@ -599,7 +600,7 @@ let get_loop_heads pdesc =
lh
let is_loop_head pdesc (node: Node.t) =
let is_loop_head pdesc (node : Node.t) =
let lh = match pdesc.loop_heads with Some lh -> lh | None -> get_loop_heads pdesc in
NodeSet.mem node lh
@ -611,7 +612,7 @@ let pp_var_attributes fmt attrs =
if List.is_empty attrs then () else F.fprintf fmt "(%a)" (Pp.seq ~sep:"," pp_attribute) attrs
let pp_local fmt (var_data: ProcAttributes.var_data) =
let pp_local fmt (var_data : ProcAttributes.var_data) =
Format.fprintf fmt " %a:%a%a" Mangled.pp var_data.name (Typ.pp_full Pp.text) var_data.typ
pp_var_attributes var_data.attributes
@ -665,7 +666,7 @@ let is_specialized pdesc =
let is_captured_var procdesc pvar =
let procname = get_proc_name procdesc in
let pvar_name = Pvar.get_name pvar in
let pvar_local_matches (var_data: ProcAttributes.var_data) =
let pvar_local_matches (var_data : ProcAttributes.var_data) =
Mangled.equal var_data.name pvar_name
in
let pvar_matches (name, _) = Mangled.equal name pvar_name in
@ -689,7 +690,7 @@ let is_captured_var procdesc pvar =
let has_modify_in_block_attr procdesc pvar =
let pvar_name = Pvar.get_name pvar in
let pvar_local_matches (var_data: ProcAttributes.var_data) =
let pvar_local_matches (var_data : ProcAttributes.var_data) =
Mangled.equal var_data.name pvar_name
&& List.exists var_data.attributes ~f:(fun attr ->
ProcAttributes.var_attribute_equal attr ProcAttributes.Modify_in_block )
@ -769,7 +770,8 @@ let specialize_types_proc callee_pdesc resolved_pdesc substitutions =
in
subst_map := Ident.Map.add id specialized_typname !subst_map ;
Some (Sil.Load (id, convert_exp origin_exp, mk_ptr_typ specialized_typname, loc))
| Sil.Load (id, (Exp.Var origin_id as origin_exp), ({Typ.desc= Tstruct _} as origin_typ), loc) ->
| Sil.Load (id, (Exp.Var origin_id as origin_exp), ({Typ.desc= Tstruct _} as origin_typ), loc)
->
let updated_typ : Typ.t =
try Typ.mk ~default:origin_typ (Tstruct (Ident.Map.find origin_id !subst_map))
with Caml.Not_found -> origin_typ
@ -822,7 +824,7 @@ exception UnmatchedParameters
(name, typ) where name is a parameter. The resulting proc desc is isomorphic but
all the type of the parameters are replaced in the instructions according to the list.
The virtual calls are also replaced to match the parameter types *)
let specialize_types ?(has_clang_model= false) callee_pdesc resolved_pname args =
let specialize_types ?(has_clang_model = false) callee_pdesc resolved_pname args =
let callee_attributes = get_attributes callee_pdesc in
let resolved_params, substitutions =
try
@ -918,7 +920,7 @@ let specialize_with_block_args_instrs resolved_pdesc substitutions =
in
let closure = Exp.Closure {name= block_name; captured_vars= id_exp_typs} in
let instr = Sil.Store (assignee_exp, origin_typ, closure, loc) in
(remove_temps_instr :: instr :: load_instrs @ instrs, id_map)
((remove_temps_instr :: instr :: load_instrs) @ instrs, id_map)
| Sil.Store (assignee_exp, origin_typ, origin_exp, loc) ->
let set_instr =
Sil.Store (convert_exp assignee_exp, origin_typ, convert_exp origin_exp, loc)
@ -942,7 +944,7 @@ let specialize_with_block_args_instrs resolved_pdesc substitutions =
, loc
, call_flags )
in
let instrs = remove_temps_instr :: call_instr :: load_instrs @ instrs in
let instrs = (remove_temps_instr :: call_instr :: load_instrs) @ instrs in
(instrs, id_map)
with Caml.Not_found ->
convert_generic_call return_ids (Exp.Var id) origin_args loc call_flags )
@ -972,10 +974,10 @@ let specialize_with_block_args callee_pdesc pname_with_block_args block_args =
(* Substitution from a block parameter to the block name and the new formals
that correspond to the captured variables *)
let substitutions : (Typ.Procname.t * (Mangled.t * Typ.t) list) Mangled.Map.t =
List.fold2_exn callee_attributes.formals block_args ~init:Mangled.Map.empty ~f:
(fun subts (param_name, _) block_arg_opt ->
List.fold2_exn callee_attributes.formals block_args ~init:Mangled.Map.empty
~f:(fun subts (param_name, _) block_arg_opt ->
match block_arg_opt with
| Some (cl: Exp.closure) ->
| Some (cl : Exp.closure) ->
let formals_from_captured =
List.map
~f:(fun (_, var, typ) ->
@ -1044,8 +1046,7 @@ let is_connected proc_desc =
in
let rec is_consecutive_join_nodes n visited =
match Node.get_kind n with
| Node.Join_node
-> (
| Node.Join_node -> (
if NodeSet.mem n visited then false
else
let succs = Node.get_succs n in
@ -1064,7 +1065,7 @@ let is_connected proc_desc =
| Node.Start_node _ ->
if List.is_empty succs || not (List.is_empty preds) then Error `Other else Ok ()
| Node.Exit_node _ ->
if not (List.is_empty succs) || List.is_empty preds then Error `Other else Ok ()
if (not (List.is_empty succs)) || List.is_empty preds then Error `Other else Ok ()
| Node.Stmt_node _ | Node.Prune_node _ | Node.Skip_node _ ->
if List.is_empty succs || List.is_empty preds then Error `Other else Ok ()
| Node.Join_node ->
@ -1075,7 +1076,7 @@ let is_connected proc_desc =
introduce a sequence of join nodes *)
if
(List.is_empty preds && not (is_consecutive_join_nodes n NodeSet.empty))
|| (not (List.is_empty preds) && List.is_empty succs)
|| ((not (List.is_empty preds)) && List.is_empty succs)
then Error `Join
else Ok ()
in

@ -78,23 +78,27 @@ type ( 'f_in
, 'markers_out
, 'list_constraint ) template_arg =
{ eat_template_arg:
'f_in * 'captured_types_in capt * Typ.template_arg list
'f_in * 'captured_types_in capt * Typ.template_arg list
-> ('f_out * 'captured_types_out capt * Typ.template_arg list) option
; add_marker: 'markers_in -> 'markers_out }
type ('context, 'f_in, 'f_out, 'captured_types, 'markers_in, 'markers_out, 'list_constraint) templ_matcher
=
{ on_objc_cpp:
'context -> 'f_in -> objc_cpp
'context
-> 'f_in
-> objc_cpp
-> ('f_out * 'captured_types capt * Typ.template_arg list) option
; on_templated_name:
'context -> 'f_in -> templated_name
'context
-> 'f_in
-> templated_name
-> ('f_out * 'captured_types capt * Typ.template_arg list) option
; get_markers: 'markers_in -> 'markers_out }
type ('context, 'f_in, 'f_out, 'captured_types, 'emptyness) 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 }
-> ('context, 'f_in, 'f_out, 'captured_types, non_empty) path_extra
@ -120,10 +124,10 @@ let empty : ('context, 'f, 'f, unit, 'markers, 'markers, empty) path_matcher =
{on_templated_name; path_extra= PathEmpty; get_markers}
let name_cons
: ('context, 'f_in, 'f_out, 'captured_types, 'markers_in, 'markers_out, _) path_matcher
-> string
-> ('context, 'f_in, 'f_out, 'captured_types, 'markers_in, 'markers_out) name_matcher =
let name_cons :
('context, 'f_in, 'f_out, 'captured_types, 'markers_in, 'markers_out, _) path_matcher
-> string
-> ('context, 'f_in, 'f_out, 'captured_types, 'markers_in, 'markers_out) name_matcher =
fun m name ->
let {on_templated_name; get_markers} = m in
let fuzzy_name_regexp =
@ -136,7 +140,7 @@ let name_cons
| _ ->
None
in
let on_objc_cpp context f (objc_cpp: Typ.Procname.ObjC_Cpp.t) =
let on_objc_cpp context f (objc_cpp : Typ.Procname.ObjC_Cpp.t) =
if String.equal name objc_cpp.method_name then
on_templated_name context f (templated_name_of_class_name objc_cpp.class_name)
else None
@ -144,10 +148,10 @@ let name_cons
{on_objc_cpp; on_qual_name; get_markers}
let name_cons_f
: ('context, 'f_in, 'f_out, 'captured_types, 'markers_in, 'markers_out, _) path_matcher
-> ('context -> string -> bool)
-> ('context, 'f_in, 'f_out, 'captured_types, 'markers_in, 'markers_out) name_matcher =
let name_cons_f :
('context, 'f_in, 'f_out, 'captured_types, 'markers_in, 'markers_out, _) path_matcher
-> ('context -> string -> bool)
-> ('context, 'f_in, 'f_out, 'captured_types, 'markers_in, 'markers_out) name_matcher =
fun m f_name ->
let {on_templated_name; get_markers} = m in
let on_qual_name context f qual_name =
@ -157,7 +161,7 @@ let name_cons_f
| _ ->
None
in
let on_objc_cpp context f (objc_cpp: Typ.Procname.ObjC_Cpp.t) =
let on_objc_cpp context f (objc_cpp : Typ.Procname.ObjC_Cpp.t) =
if f_name context objc_cpp.method_name then
on_templated_name context f (templated_name_of_class_name objc_cpp.class_name)
else None
@ -165,32 +169,26 @@ let name_cons_f
{on_objc_cpp; on_qual_name; get_markers}
let all_names_cons
: ('context, 'f_in, 'f_out, 'captured_types, 'markers_in, 'markers_out, non_empty) path_matcher
-> ( 'context
, 'f_in
, 'f_out
, 'captured_tpes
, 'markers_in
, 'markers_out
, non_empty )
path_matcher =
let all_names_cons :
('context, 'f_in, 'f_out, 'captured_types, 'markers_in, 'markers_out, non_empty) path_matcher
-> ('context, 'f_in, 'f_out, 'captured_tpes, 'markers_in, 'markers_out, non_empty) path_matcher
=
fun m ->
let {on_templated_name; get_markers; path_extra= PathNonEmpty {on_objc_cpp}} = m in
let rec on_templated_name_rec context f templated_name =
match on_templated_name context f templated_name with
| Some _ as some ->
some
| None ->
| None -> (
let qual_name, _template_args = templated_name in
match QualifiedCppName.extract_last qual_name with
| None ->
None
| Some (_last, rest) ->
on_templated_name_rec context f (rest, [])
on_templated_name_rec context f (rest, []) )
in
let on_templated_name = on_templated_name_rec in
let on_objc_cpp context f (objc_cpp: Typ.Procname.ObjC_Cpp.t) =
let on_objc_cpp context f (objc_cpp : Typ.Procname.ObjC_Cpp.t) =
match on_objc_cpp context f objc_cpp with
| Some _ as some ->
some
@ -200,16 +198,16 @@ let all_names_cons
{on_templated_name; get_markers; path_extra= PathNonEmpty {on_objc_cpp}}
let templ_begin
: ('context, 'f_in, 'f_out, 'captured_types, 'markers_in, 'markers_out) name_matcher
-> ( 'context
, 'f_in
, 'f_out
, 'captured_types
, 'markers_in
, 'markers_out
, accept_more )
templ_matcher =
let templ_begin :
('context, 'f_in, 'f_out, 'captured_types, 'markers_in, 'markers_out) name_matcher
-> ( 'context
, 'f_in
, 'f_out
, 'captured_types
, 'markers_in
, 'markers_out
, accept_more )
templ_matcher =
fun m ->
let {on_objc_cpp; on_qual_name; get_markers} = m in
let on_templated_name context f (qual_name, template_args) =
@ -219,7 +217,7 @@ let templ_begin
| Some (f, captured_types) ->
Some (f, captured_types, template_args)
in
let on_objc_cpp context f (objc_cpp: Typ.Procname.ObjC_Cpp.t) =
let on_objc_cpp context f (objc_cpp : Typ.Procname.ObjC_Cpp.t) =
match on_objc_cpp context f objc_cpp with
| None ->
None
@ -230,31 +228,25 @@ let templ_begin
{on_objc_cpp; on_templated_name; get_markers}
let templ_cons
: ( 'context
, 'f_in
, 'f_interm
, 'captured_types_in
, 'markers_interm
, 'markers_out
, accept_more )
templ_matcher
-> ( 'f_interm
, 'f_out
, 'captured_types_in
, 'captured_types_out
, 'markers_in
, 'markers_interm
, 'lc )
template_arg
-> ( 'context
, 'f_in
, 'f_out
, 'captured_types_out
, 'markers_in
, 'markers_out
, 'lc )
templ_matcher =
let templ_cons :
( 'context
, 'f_in
, 'f_interm
, 'captured_types_in
, 'markers_interm
, 'markers_out
, accept_more )
templ_matcher
-> ( 'f_interm
, 'f_out
, 'captured_types_in
, 'captured_types_out
, 'markers_in
, 'markers_interm
, 'lc )
template_arg
-> ('context, 'f_in, 'f_out, 'captured_types_out, 'markers_in, 'markers_out, 'lc) templ_matcher
=
fun m template_arg ->
let {on_objc_cpp; on_templated_name; get_markers} = m in
let {eat_template_arg; add_marker} = template_arg in
@ -268,16 +260,16 @@ let templ_cons
{on_objc_cpp; on_templated_name; get_markers}
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
, non_empty )
path_matcher =
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
, non_empty )
path_matcher =
let match_empty_templ_args (f, captured_types, template_args) =
match template_args with [] -> Some (f, captured_types) | _ -> None
in
@ -306,7 +298,7 @@ module type Common = sig
(** Eats a type *)
val capt_typ :
'marker
'marker
-> ( 'marker mtyp -> 'f
, 'f
, 'captured_types
@ -347,14 +339,14 @@ module type Common = sig
(** Starts a path with a matching name that satisfies the given function *)
val ( &+ ) :
( 'context
, 'f_in
, 'f_interm
, 'captured_types_in
, 'markers_interm
, 'markers_out
, accept_more )
templ_matcher
( 'context
, 'f_in
, 'f_interm
, 'captured_types_in
, 'markers_interm
, 'markers_out
, accept_more )
templ_matcher
-> ( 'f_interm
, 'f_out
, 'captured_types_in
@ -367,7 +359,7 @@ module type Common = sig
(** Separate template arguments *)
val ( < ) :
('context, 'f_in, 'f_interm, 'captured_types_in, 'markers_interm, 'markers_out) name_matcher
('context, 'f_in, 'f_interm, 'captured_types_in, 'markers_interm, 'markers_out) name_matcher
-> ( 'f_interm
, 'f_out
, 'captured_types_in
@ -380,29 +372,33 @@ module type Common = sig
(** Starts template arguments after a name *)
val ( >:: ) :
('context, 'f_in, 'f_out, 'captured_types, 'markers_in, 'markers_out, _) templ_matcher
-> string -> ('context, 'f_in, 'f_out, 'captured_types, 'markers_in, 'markers_out) name_matcher
('context, 'f_in, 'f_out, 'captured_types, 'markers_in, 'markers_out, _) templ_matcher
-> string
-> ('context, 'f_in, 'f_out, 'captured_types, 'markers_in, 'markers_out) name_matcher
(** Ends template arguments and starts a name *)
val ( &+...>:: ) :
( 'context
, 'f_in
, 'f_out
, 'captured_types
, 'markers_in
, 'markers_out
, accept_more )
templ_matcher -> string
( 'context
, 'f_in
, 'f_out
, 'captured_types
, 'markers_in
, 'markers_out
, accept_more )
templ_matcher
-> string
-> ('context, 'f_in, 'f_out, 'captured_types, 'markers_in, 'markers_out) name_matcher
(** Ends template arguments with eats-ALL and starts a name *)
val ( &:: ) :
('context, 'f_in, 'f_out, 'captured_types, 'markers_in, 'markers_out) name_matcher -> string
('context, 'f_in, 'f_out, 'captured_types, 'markers_in, 'markers_out) name_matcher
-> string
-> ('context, 'f_in, 'f_out, 'captured_types, 'markers_in, 'markers_out) name_matcher
(** Separates names (accepts ALL template arguments on the left one) *)
val ( <>:: ) :
('context, 'f_in, 'f_out, 'captured_types, 'markers_in, 'markers_out) name_matcher -> string
('context, 'f_in, 'f_out, 'captured_types, 'markers_in, 'markers_out) name_matcher
-> string
-> ('context, 'f_in, 'f_out, 'captured_types, 'markers_in, 'markers_out) name_matcher
(** Separates names (accepts NO template arguments on the left one) *)
end
@ -413,15 +409,15 @@ module Common = struct
let add_no_marker capture_markers = capture_markers
(** Eats all template args *)
let any_template_args
: ('f, 'f, 'captured_types, 'captured_types, 'markers, 'markers, end_of_list) template_arg =
let any_template_args :
('f, 'f, 'captured_types, 'captured_types, 'markers, 'markers, end_of_list) template_arg =
let eat_template_arg (f, captured_types, _) = Some (f, captured_types, []) in
{eat_template_arg; add_marker= add_no_marker}
(** Eats a type *)
let any_typ
: ('f, 'f, 'captured_types, 'captured_types, 'markers, 'markers, accept_more) template_arg =
let any_typ :
('f, 'f, 'captured_types, 'captured_types, 'markers, 'markers, accept_more) template_arg =
let eat_template_arg (f, captured_types, template_args) =
match template_args with Typ.TType _ :: rest -> Some (f, captured_types, rest) | _ -> None
in
@ -429,16 +425,16 @@ module Common = struct
(** Captures a type than can be back-referenced *)
let capt_typ
: 'marker
-> ( 'marker mtyp -> 'f
, 'f
, 'captured_types
, 'marker mtyp * 'captured_types
, 'markers
, 'marker * 'markers
, accept_more )
template_arg =
let capt_typ :
'marker
-> ( 'marker mtyp -> 'f
, 'f
, 'captured_types
, 'marker mtyp * 'captured_types
, 'markers
, 'marker * 'markers
, accept_more )
template_arg =
fun marker ->
let eat_template_arg (f, captured_types, template_args) =
match template_args with
@ -453,15 +449,15 @@ module Common = struct
(** Captures an int *)
let capt_int
: ( Int64.t -> 'f
, 'f
, 'captured_types
, 'captured_types
, 'markers
, 'markers
, accept_more )
template_arg =
let capt_int :
( Int64.t -> 'f
, 'f
, 'captured_types
, 'captured_types
, 'markers
, 'markers
, accept_more )
template_arg =
let eat_template_arg (f, captured_types, template_args) =
match template_args with Typ.TInt i :: rest -> Some (f i, captured_types, rest) | _ -> None
in
@ -469,15 +465,15 @@ module Common = struct
(** Captures all template args *)
let capt_all
: ( Typ.template_arg list -> 'f
, 'f
, 'captured_types
, 'captured_types
, 'markers
, 'markers
, end_of_list )
template_arg =
let capt_all :
( Typ.template_arg list -> 'f
, 'f
, 'captured_types
, 'captured_types
, 'markers
, 'markers
, end_of_list )
template_arg =
let eat_template_arg (f, captured_types, template_args) =
Some (f template_args, captured_types, [])
in
@ -580,8 +576,11 @@ module Call = struct
let pre_map_opt opt ~f = match opt with None -> DoesNotMatch | Some x -> Matches (f x)
type ('context, 'f_in, 'f_out, 'captured_types) func_args_end =
on_args:('context, 'f_in, 'f_out, 'captured_types) on_args -> 'context -> FuncArg.t list
-> 'f_in * 'captured_types -> ('context, 'f_out) pre_result
on_args:('context, 'f_in, 'f_out, 'captured_types) on_args
-> 'context
-> FuncArg.t list
-> 'f_in * 'captured_types
-> ('context, 'f_out) pre_result
type ('context, 'f_in, 'f_out) all_args_matcher =
{ on_objc_cpp: 'context -> 'f_in -> objc_cpp -> FuncArg.t list -> ('context, 'f_out) pre_result
@ -590,19 +589,19 @@ module Call = struct
type ('context, 'f) dispatcher = 'context -> Typ.Procname.t -> FuncArg.t list -> 'f option
let args_begin
: ('context, 'f_in, 'f_out, 'captured_types, unit, 'markers, non_empty) path_matcher
-> ('context, 'f_in, 'f_out, 'f_out, 'captured_types, 'markers) args_matcher =
let args_begin :
('context, 'f_in, 'f_out, 'captured_types, unit, 'markers, non_empty) path_matcher
-> ('context, 'f_in, 'f_out, 'f_out, 'captured_types, 'markers) args_matcher =
let on_args _context _capt f_args = Some f_args in
fun m ->
let {on_templated_name; path_extra= PathNonEmpty {on_objc_cpp}; get_markers} = m in
let markers = get_markers () in
let get_captures (f, captured_types) = (f, captured_types ()) in
let on_c context f (c: c) =
let on_c context f (c : c) =
let template_args = template_args_of_template_spec_info c.template_args in
on_templated_name context f (c.name, template_args) |> Option.map ~f:get_captures
in
let on_java context f (java: java) =
let on_java context f (java : java) =
on_templated_name context f (templated_name_of_java java) |> Option.map ~f:get_captures
in
let on_objc_cpp context f objc_cpp =
@ -612,10 +611,10 @@ module Call = struct
{on_proc; on_args; markers}
let args_cons
: ('context, 'f_in, 'f_proc_out, 'f_interm, 'captured_types, 'markers) args_matcher
-> ('context, 'f_interm, 'f_out, 'captured_types, 'markers) func_arg
-> ('context, 'f_in, 'f_proc_out, 'f_out, 'captured_types, 'markers) args_matcher =
let args_cons :
('context, 'f_in, 'f_proc_out, 'f_interm, 'captured_types, 'markers) args_matcher
-> ('context, 'f_interm, 'f_out, 'captured_types, 'markers) func_arg
-> ('context, 'f_in, 'f_proc_out, 'f_out, 'captured_types, 'markers) args_matcher =
fun m func_arg ->
let {on_proc; on_args; markers} = m in
let {marker_static_checker; eat_func_arg} = func_arg in
@ -626,10 +625,10 @@ module Call = struct
{on_proc; on_args; markers}
let args_end
: ('context, 'f_in, 'f_proc_out, 'f_out, 'captured_types, 'markers) args_matcher
-> ('context, 'f_proc_out, 'f_out, 'captured_types) func_args_end
-> ('context, 'f_in, 'f_out) all_args_matcher =
let args_end :
('context, 'f_in, 'f_proc_out, 'f_out, 'captured_types, 'markers) args_matcher
-> ('context, 'f_proc_out, 'f_out, 'captured_types) func_args_end
-> ('context, 'f_in, 'f_out) all_args_matcher =
fun m func_args_end ->
let {on_proc= {on_c; on_java; on_objc_cpp}; on_args} = m in
let on_c context f c args =
@ -644,10 +643,10 @@ module Call = struct
{on_c; on_java; on_objc_cpp}
let make_matcher
: ('context, 'f_in, 'f_out) all_args_matcher -> 'f_in -> ('context, 'f_out) matcher =
let make_matcher :
('context, 'f_in, 'f_out) all_args_matcher -> 'f_in -> ('context, 'f_out) matcher =
fun m f ->
let {on_c; on_java; on_objc_cpp} : (_, _, _) all_args_matcher = m in
let ({on_c; on_java; on_objc_cpp} : (_, _, _) all_args_matcher) = m in
let on_objc_cpp context objc_cpp args =
match on_objc_cpp context f objc_cpp args with
| DoesNotMatch ->
@ -682,14 +681,14 @@ module Call = struct
let make_dispatcher : ('context, 'f) matcher list -> ('context, 'f) dispatcher =
fun matchers ->
let on_objc_cpp context objc_cpp args =
List.find_map matchers ~f:(fun (matcher: _ matcher) ->
List.find_map matchers ~f:(fun (matcher : _ matcher) ->
matcher.on_objc_cpp context objc_cpp args )
in
let on_c context c args =
List.find_map matchers ~f:(fun (matcher: _ matcher) -> matcher.on_c context c args)
List.find_map matchers ~f:(fun (matcher : _ matcher) -> matcher.on_c context c args)
in
let on_java context java args =
List.find_map matchers ~f:(fun (matcher: _ matcher) -> matcher.on_java context java args)
List.find_map matchers ~f:(fun (matcher : _ matcher) -> matcher.on_java context java args)
in
fun context procname args ->
match procname with
@ -713,9 +712,11 @@ module Call = struct
{match_arg; marker_static_checker= no_marker_checker}
let mk_match_typ_nth
: ('markers -> 'marker) -> ('captured_types -> 'marker mtyp) -> 'marker
-> ('context, 'captured_types, 'markers) one_arg_matcher =
let mk_match_typ_nth :
('markers -> 'marker)
-> ('captured_types -> 'marker mtyp)
-> 'marker
-> ('context, 'captured_types, 'markers) one_arg_matcher =
fun get_m get_c marker ->
let marker_static_checker markers = Polymorphic_compare.( = ) marker (get_m markers) in
let match_arg _context capt arg = Typ.equal (FuncArg.typ arg) (get_c capt) in
@ -729,25 +730,26 @@ module Call = struct
(** Matches second captured type *)
let match_typ2 : 'marker -> ('context, _ * ('marker mtyp * _), _ * ('marker * _)) one_arg_matcher =
let match_typ2 : 'marker -> ('context, _ * ('marker mtyp * _), _ * ('marker * _)) one_arg_matcher
=
let pos2 (_, (x, _)) = x in
fun marker -> mk_match_typ_nth pos2 pos2 marker
(** Matches third captured type *)
let match_typ3
: 'marker
-> ('context, _ * (_ * ('marker mtyp * _)), _ * (_ * ('marker * _))) one_arg_matcher =
let match_typ3 :
'marker -> ('context, _ * (_ * ('marker mtyp * _)), _ * (_ * ('marker * _))) one_arg_matcher
=
let pos3 (_, (_, (x, _))) = x in
fun marker -> mk_match_typ_nth pos3 pos3 marker
(** Matches the type matched by the given path_matcher *)
let match_typ
: ('context, _, _, unit, unit, unit, non_empty) path_matcher
-> ('context, _, _) one_arg_matcher =
let match_typ :
('context, _, _, unit, unit, unit, non_empty) path_matcher
-> ('context, _, _) one_arg_matcher =
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 =
match typ with
| {Typ.desc= Tstruct name} ->
@ -762,6 +764,7 @@ module Call = struct
(* Function argument capture *)
(** Do not capture this argument *)
let no_capture : (_, _, 'f, 'f) arg_capture =
let get_captured_value _arg = () in
@ -802,10 +805,10 @@ module Call = struct
{on_empty; wrapper}
let make_arg
: ('arg_in, 'arg_out, 'f_in, 'f_out) arg_preparer
-> ('context, 'arg_in, 'arg_out, 'f_in, 'f_out, _, _) one_arg
-> ('context, 'f_in, 'f_out, _, _) func_arg =
let make_arg :
('arg_in, 'arg_out, 'f_in, 'f_out) arg_preparer
-> ('context, 'arg_in, 'arg_out, 'f_in, 'f_out, _, _) one_arg
-> ('context, 'f_in, 'f_out, _, _) func_arg =
fun arg_preparer one_arg ->
let {on_empty; wrapper} = arg_preparer in
let {one_arg_matcher; capture} = one_arg in
@ -856,6 +859,7 @@ module Call = struct
(* Function args end *)
(** Matches if there is no function arguments left *)
let no_args_left : ('context, _, _, _) func_args_end =
let match_empty_args = function Some (f, []) -> Matches f | _ -> DoesNotMatch in
@ -868,10 +872,10 @@ module Call = struct
(** If [func_args_end1] does not match, use [func_args_end2] *)
let alternative_args_end
: ('context, 'f_in, 'f_out, 'captured_types) func_args_end
-> ('context, 'f_in, 'f_out, 'captured_types) func_args_end
-> ('context, 'f_in, 'f_out, 'captured_types) func_args_end =
let alternative_args_end :
('context, 'f_in, 'f_out, 'captured_types) func_args_end
-> ('context, 'f_in, 'f_out, 'captured_types) func_args_end
-> ('context, 'f_in, 'f_out, 'captured_types) func_args_end =
fun func_args_end1 func_args_end2 ~on_args context args f_capt ->
match func_args_end1 ~on_args context args f_capt with
| DoesNotMatch ->
@ -952,19 +956,23 @@ module type NameCommon = sig
include Common
val ( >--> ) :
('context, 'f_in, 'f_out, 'captured_types, unit, 'markers, _) templ_matcher -> 'f_in
('context, 'f_in, 'f_out, 'captured_types, unit, 'markers, _) templ_matcher
-> 'f_in
-> ('context, 'f_out) matcher
val ( <>--> ) :
('context, 'f_in, 'f_out, 'captured_types, unit, 'markers) name_matcher -> 'f_in
('context, 'f_in, 'f_out, 'captured_types, unit, 'markers) name_matcher
-> 'f_in
-> ('context, 'f_out) matcher
val ( &--> ) :
('context, 'f_in, 'f_out, 'captured_types, unit, 'markers) name_matcher -> 'f_in
('context, 'f_in, 'f_out, 'captured_types, unit, 'markers) name_matcher
-> 'f_in
-> ('context, 'f_out) matcher
val ( &::.*--> ) :
('context, 'f_in, 'f_out, 'captured_types, unit, 'markers) name_matcher -> 'f_in
('context, 'f_in, 'f_out, 'captured_types, unit, 'markers) name_matcher
-> 'f_in
-> ('context, 'f_out) matcher
(** After a name, accepts ALL template arguments, accepts ALL path tails (names, templates),
accepts ALL function arguments, binds the function *)
@ -977,12 +985,13 @@ module NameCommon = struct
{ on_templated_name: 'context -> templated_name -> 'f option
; on_objc_cpp: 'context -> objc_cpp -> 'f option }
let make_matcher
: ('context, 'f_in, 'f_out, _, _, _, non_empty) path_matcher -> 'f_in
-> ('context, 'f_out) matcher =
let make_matcher :
('context, 'f_in, 'f_out, _, _, _, non_empty) path_matcher
-> 'f_in
-> ('context, 'f_out) matcher =
fun m f ->
let {on_templated_name; path_extra= PathNonEmpty {on_objc_cpp}}
: ('context, 'f_in, 'f_out, _, _, _, non_empty) path_matcher =
let ({on_templated_name; path_extra= PathNonEmpty {on_objc_cpp}}
: ('context, 'f_in, 'f_out, _, _, _, non_empty) path_matcher) =
m
in
let on_templated_name context templated_name =
@ -1011,17 +1020,17 @@ module ProcName = struct
let make_dispatcher : ('context, 'f) matcher list -> ('context, 'f) dispatcher =
fun matchers ->
let on_objc_cpp context objc_cpp =
List.find_map matchers ~f:(fun (matcher: _ matcher) -> matcher.on_objc_cpp context objc_cpp)
List.find_map matchers ~f:(fun (matcher : _ matcher) -> matcher.on_objc_cpp context objc_cpp)
in
let on_templated_name context templated_name =
List.find_map matchers ~f:(fun (matcher: _ matcher) ->
List.find_map matchers ~f:(fun (matcher : _ matcher) ->
matcher.on_templated_name context templated_name )
in
let on_java context (java: Typ.Procname.Java.t) =
let on_java context (java : Typ.Procname.Java.t) =
let templated_name = templated_name_of_java java in
on_templated_name context templated_name
in
let on_c context (c: c) =
let on_c context (c : c) =
let template_args = template_args_of_template_spec_info c.template_args in
let templated_name = (c.name, template_args) in
on_templated_name context templated_name
@ -1046,6 +1055,6 @@ module TypName = struct
let make_dispatcher : ('context, 'f) matcher list -> ('context, 'f) dispatcher =
fun matchers context typname ->
let templated_name = templated_name_of_class_name typname in
List.find_map matchers ~f:(fun (matcher: _ matcher) ->
List.find_map matchers ~f:(fun (matcher : _ matcher) ->
matcher.on_templated_name context templated_name )
end

@ -67,7 +67,7 @@ module type Common = sig
(** Eats a type *)
val capt_typ :
'marker
'marker
-> ( 'marker mtyp -> 'f
, 'f
, 'captured_types
@ -108,14 +108,14 @@ module type Common = sig
(** Starts a path with a matching name that satisfies the given function *)
val ( &+ ) :
( 'context
, 'f_in
, 'f_interm
, 'captured_types_in
, 'markers_interm
, 'markers_out
, accept_more )
templ_matcher
( 'context
, 'f_in
, 'f_interm
, 'captured_types_in
, 'markers_interm
, 'markers_out
, accept_more )
templ_matcher
-> ( 'f_interm
, 'f_out
, 'captured_types_in
@ -128,7 +128,7 @@ module type Common = sig
(** Separate template arguments *)
val ( < ) :
('context, 'f_in, 'f_interm, 'captured_types_in, 'markers_interm, 'markers_out) name_matcher
('context, 'f_in, 'f_interm, 'captured_types_in, 'markers_interm, 'markers_out) name_matcher
-> ( 'f_interm
, 'f_out
, 'captured_types_in
@ -141,29 +141,33 @@ module type Common = sig
(** Starts template arguments after a name *)
val ( >:: ) :
('context, 'f_in, 'f_out, 'captured_types, 'markers_in, 'markers_out, _) templ_matcher
-> string -> ('context, 'f_in, 'f_out, 'captured_types, 'markers_in, 'markers_out) name_matcher
('context, 'f_in, 'f_out, 'captured_types, 'markers_in, 'markers_out, _) templ_matcher
-> string
-> ('context, 'f_in, 'f_out, 'captured_types, 'markers_in, 'markers_out) name_matcher
(** Ends template arguments and starts a name *)
val ( &+...>:: ) :
( 'context
, 'f_in
, 'f_out
, 'captured_types
, 'markers_in
, 'markers_out
, accept_more )
templ_matcher -> string
( 'context
, 'f_in
, 'f_out
, 'captured_types
, 'markers_in
, 'markers_out
, accept_more )
templ_matcher
-> string
-> ('context, 'f_in, 'f_out, 'captured_types, 'markers_in, 'markers_out) name_matcher
(** Ends template arguments with eats-ALL and starts a name *)
val ( &:: ) :
('context, 'f_in, 'f_out, 'captured_types, 'markers_in, 'markers_out) name_matcher -> string
('context, 'f_in, 'f_out, 'captured_types, 'markers_in, 'markers_out) name_matcher
-> string
-> ('context, 'f_in, 'f_out, 'captured_types, 'markers_in, 'markers_out) name_matcher
(** Separates names (accepts ALL template arguments on the left one) *)
val ( <>:: ) :
('context, 'f_in, 'f_out, 'captured_types, 'markers_in, 'markers_out) name_matcher -> string
('context, 'f_in, 'f_out, 'captured_types, 'markers_in, 'markers_out) name_matcher
-> string
-> ('context, 'f_in, 'f_out, 'captured_types, 'markers_in, 'markers_out) name_matcher
(** Separates names (accepts NO template arguments on the left one) *)
end
@ -172,19 +176,23 @@ module type NameCommon = sig
include Common
val ( >--> ) :
('context, 'f_in, 'f_out, 'captured_types, unit, 'markers, _) templ_matcher -> 'f_in
('context, 'f_in, 'f_out, 'captured_types, unit, 'markers, _) templ_matcher
-> 'f_in
-> ('context, 'f_out) matcher
val ( <>--> ) :
('context, 'f_in, 'f_out, 'captured_types, unit, 'markers) name_matcher -> 'f_in
('context, 'f_in, 'f_out, 'captured_types, unit, 'markers) name_matcher
-> 'f_in
-> ('context, 'f_out) matcher
val ( &--> ) :
('context, 'f_in, 'f_out, 'captured_types, unit, 'markers) name_matcher -> 'f_in
('context, 'f_in, 'f_out, 'captured_types, unit, 'markers) name_matcher
-> 'f_in
-> ('context, 'f_out) matcher
val ( &::.*--> ) :
('context, 'f_in, 'f_out, 'captured_types, unit, 'markers) name_matcher -> 'f_in
('context, 'f_in, 'f_out, 'captured_types, unit, 'markers) name_matcher
-> 'f_in
-> ('context, 'f_out) matcher
(** After a name, accepts ALL template arguments, accepts ALL path tails (names, templates),
accepts ALL function arguments, binds the function *)
@ -192,7 +200,8 @@ end
(* ocaml ignores the warning suppression at toplevel, hence the [include struct ... end] trick *)
include sig
include
sig
[@@@warning "-60"]
module ProcName :
@ -207,9 +216,9 @@ module Call : sig
type t = Exp.t * Typ.t
end
include Common
with type ('context, 'f) dispatcher =
'context -> Typ.Procname.t -> FuncArg.t list -> 'f option
include
Common
with type ('context, 'f) dispatcher = 'context -> Typ.Procname.t -> FuncArg.t list -> 'f option
type ('context, 'f_in, 'f_proc_out, 'f_out, 'captured_types, 'markers) args_matcher
@ -227,12 +236,12 @@ module Call : sig
(** Captures one arg expression *)
val capt_arg_of_typ :
('context, unit, _, unit, unit, unit) name_matcher
('context, unit, _, unit, unit, unit) name_matcher
-> ('context, FuncArg.t, 'wrapped_arg, 'wrapped_arg -> 'f, 'f, _, _) one_arg
(** Captures one arg of the given type *)
val capt_exp_of_typ :
('context, unit, _, unit, unit, unit) name_matcher
('context, unit, _, unit, unit, unit) name_matcher
-> ('context, Exp.t, 'wrapped_arg, 'wrapped_arg -> 'f, 'f, _, _) one_arg
(** Captures one arg expression of the given type *)
@ -247,88 +256,98 @@ module Call : sig
(** Matches second captured type *)
val typ3 :
'marker
'marker
-> ('context, unit, _, 'f, 'f, _ * (_ * ('marker mtyp * _)), _ * (_ * ('marker * _))) one_arg
(** Matches third captured type *)
val ( $+ ) :
('context, 'f_in, 'f_proc_out, 'f_interm, 'captured_types, 'markers) args_matcher
('context, 'f_in, 'f_proc_out, 'f_interm, 'captured_types, 'markers) args_matcher
-> ('context, 'arg, 'arg, 'f_interm, 'f_out, 'captured_types, 'markers) one_arg
-> ('context, 'f_in, 'f_proc_out, 'f_out, 'captured_types, 'markers) args_matcher
(** Separate function arguments *)
val ( $+? ) :
('context, 'f_in, 'f_proc_out, 'f_interm, 'captured_types, 'markers) args_matcher
('context, 'f_in, 'f_proc_out, 'f_interm, 'captured_types, 'markers) args_matcher
-> ('context, 'arg, 'arg option, 'f_interm, 'f_out, 'captured_types, 'markers) one_arg
-> ('context, 'f_in, 'f_proc_out, 'f_out, 'captured_types, 'markers) args_matcher
(** Add an optional argument *)
val ( >$ ) :
('context, 'f_in, 'f_proc_out, 'ct, unit, 'cm, _) templ_matcher
('context, 'f_in, 'f_proc_out, 'ct, unit, 'cm, _) templ_matcher
-> ('context, 'arg, 'arg, 'f_proc_out, 'f_out, 'ct, 'cm) one_arg
-> ('context, 'f_in, 'f_proc_out, 'f_out, 'ct, 'cm) args_matcher
(** Ends template arguments and starts function arguments *)
val ( $--> ) :
('context, 'f_in, _, 'f_out, 'captured_types, 'markers) args_matcher -> 'f_in
('context, 'f_in, _, 'f_out, 'captured_types, 'markers) args_matcher
-> 'f_in
-> ('context, 'f_out) matcher
(** Ends function arguments, binds the function *)
val ( $ ) :
('context, 'f_in, 'f_proc_out, 'captured_types, unit, 'markers) name_matcher
('context, 'f_in, 'f_proc_out, 'captured_types, unit, 'markers) name_matcher
-> ('context, 'arg, 'arg, 'f_proc_out, 'f_out, 'captured_types, 'markers) one_arg
-> ('context, 'f_in, 'f_proc_out, 'f_out, 'captured_types, 'markers) args_matcher
(** Ends a name with accept-ALL template arguments and starts function arguments *)
val ( <>$ ) :
('context, 'f_in, 'f_proc_out, 'captured_types, unit, 'markers) name_matcher
('context, 'f_in, 'f_proc_out, 'captured_types, unit, 'markers) name_matcher
-> ('context, 'arg, 'arg, 'f_proc_out, 'f_out, 'captured_types, 'markers) one_arg
-> ('context, 'f_in, 'f_proc_out, 'f_out, 'captured_types, 'markers) args_matcher
(** Ends a name with accept-NO template arguments and starts function arguments *)
val ( >--> ) :
('context, 'f_in, 'f_out, 'captured_types, unit, 'markers, _) templ_matcher -> 'f_in
('context, 'f_in, 'f_out, 'captured_types, unit, 'markers, _) templ_matcher
-> 'f_in
-> ('context, 'f_out) matcher
(** Ends template arguments, accepts ALL function arguments, binds the function *)
val ( $+...$--> ) :
('context, 'f_in, _, 'f_out, 'captured_types, 'markers) args_matcher -> 'f_in
('context, 'f_in, _, 'f_out, 'captured_types, 'markers) args_matcher
-> 'f_in
-> ('context, 'f_out) matcher
(** Ends function arguments with eats-ALL and binds the function *)
val ( >$$--> ) :
('context, 'f_in, 'f_out, 'captured_types, unit, 'markers, _) templ_matcher -> 'f_in
('context, 'f_in, 'f_out, 'captured_types, unit, 'markers, _) templ_matcher
-> 'f_in
-> ('context, 'f_out) matcher
(** Ends template arguments, accepts NO function arguments, binds the function *)
val ( $$--> ) :
('context, 'f_in, 'f_out, 'captured_types, unit, 'markers) name_matcher -> 'f_in
('context, 'f_in, 'f_out, 'captured_types, unit, 'markers) name_matcher
-> 'f_in
-> ('context, 'f_out) matcher
(** After a name, accepts ALL template arguments, accepts NO function arguments, binds the function *)
val ( <>$$--> ) :
('context, 'f_in, 'f_out, 'captured_types, unit, 'markers) name_matcher -> 'f_in
('context, 'f_in, 'f_out, 'captured_types, unit, 'markers) name_matcher
-> 'f_in
-> ('context, 'f_out) matcher
(** After a name, accepts NO template arguments, accepts NO function arguments, binds the function *)
val ( &--> ) :
('context, 'f_in, 'f_out, 'captured_types, unit, 'markers) name_matcher -> 'f_in
('context, 'f_in, 'f_out, 'captured_types, unit, 'markers) name_matcher
-> 'f_in
-> ('context, 'f_out) matcher
(** After a name, accepts ALL template arguments, accepts ALL function arguments, binds the function *)
val ( <>--> ) :
('context, 'f_in, 'f_out, 'captured_types, unit, 'markers) name_matcher -> 'f_in
('context, 'f_in, 'f_out, 'captured_types, unit, 'markers) name_matcher
-> 'f_in
-> ('context, 'f_out) matcher
(** After a name, accepts NO template arguments, accepts ALL function arguments, binds the function *)
val ( &::.*--> ) :
('context, 'f_in, 'f_out, 'captured_types, unit, 'markers) name_matcher -> 'f_in
('context, 'f_in, 'f_out, 'captured_types, unit, 'markers) name_matcher
-> 'f_in
-> ('context, 'f_out) matcher
(** After a name, accepts ALL template arguments, accepts ALL path tails (names, templates),
accepts ALL function arguments, binds the function *)
val ( $!--> ) :
('context, 'f_in, 'f_proc_out, 'f_out, 'captured_types, 'markers) args_matcher -> 'f_in
('context, 'f_in, 'f_proc_out, 'f_out, 'captured_types, 'markers) args_matcher
-> 'f_in
-> ('context, 'f_out) matcher
(** Ends function arguments, accepts NO more function arguments.
If the args do not match, raise an internal error.

@ -51,7 +51,7 @@ let compare_modulo_this x y =
else compare_pvar_kind x.pv_kind y.pv_kind
let equal = [%compare.equal : t]
let equal = [%compare.equal: t]
let get_declaring_function pv =
match pv.pv_kind with
@ -97,7 +97,7 @@ let pp pe f pv =
(** Dump a program variable. *)
let d (pvar: t) = L.add_print_with_pe pp pvar
let d (pvar : t) = L.add_print_with_pe pp pvar
let get_name pv = pv.pv_name
@ -198,10 +198,10 @@ let to_callee pname pvar =
assert false
let name_hash (name: Mangled.t) = Hashtbl.hash name
let name_hash (name : Mangled.t) = Hashtbl.hash name
(** [mk name proc_name] creates a program var with the given function name *)
let mk (name: Mangled.t) (proc_name: Typ.Procname.t) : t =
let mk (name : Mangled.t) (proc_name : Typ.Procname.t) : t =
{pv_hash= name_hash name; pv_name= name; pv_kind= Local_var proc_name}
@ -209,13 +209,13 @@ let get_ret_pvar pname = mk Ident.name_return pname
(** [mk_callee name proc_name] creates a program var
for a callee function with the given function name *)
let mk_callee (name: Mangled.t) (proc_name: Typ.Procname.t) : t =
let mk_callee (name : Mangled.t) (proc_name : Typ.Procname.t) : t =
{pv_hash= name_hash name; pv_name= name; pv_kind= Callee_var proc_name}
(** create a global variable with the given name *)
let mk_global ?(is_constexpr= false) ?(is_pod= true) ?(is_static_local= false)
?(is_static_global= false) ?translation_unit (name: Mangled.t) : t =
let mk_global ?(is_constexpr = false) ?(is_pod = true) ?(is_static_local = false)
?(is_static_global = false) ?translation_unit (name : Mangled.t) : t =
{ pv_hash= name_hash name
; pv_name= name
; pv_kind= Global_var (translation_unit, is_constexpr, is_pod, is_static_local, is_static_global)
@ -230,12 +230,12 @@ let mk_tmp name pname =
(** create an abduced return variable for a call to [proc_name] at [loc] *)
let mk_abduced_ret (proc_name: Typ.Procname.t) (loc: Location.t) : t =
let mk_abduced_ret (proc_name : Typ.Procname.t) (loc : Location.t) : t =
let name = Mangled.from_string ("$RET_" ^ Typ.Procname.to_unique_id proc_name) in
{pv_hash= name_hash name; pv_name= name; pv_kind= Abduced_retvar (proc_name, loc)}
let mk_abduced_ref_param (proc_name: Typ.Procname.t) (index: int) (loc: Location.t) : t =
let mk_abduced_ref_param (proc_name : Typ.Procname.t) (index : int) (loc : Location.t) : t =
let name = Mangled.from_string ("$REF_PARAM_VAL_" ^ Typ.Procname.to_unique_id proc_name) in
{pv_hash= name_hash name; pv_name= name; pv_kind= Abduced_ref_param (proc_name, index, loc)}

@ -93,8 +93,13 @@ val mk_callee : Mangled.t -> Typ.Procname.t -> t
for a callee function with the given function name *)
val mk_global :
?is_constexpr:bool -> ?is_pod:bool -> ?is_static_local:bool -> ?is_static_global:bool
-> ?translation_unit:SourceFile.t -> Mangled.t -> t
?is_constexpr:bool
-> ?is_pod:bool
-> ?is_static_local:bool
-> ?is_static_global:bool
-> ?translation_unit:SourceFile.t
-> Mangled.t
-> t
(** create a global variable with the given name *)
val mk_tmp : string -> Typ.Procname.t -> t

@ -75,7 +75,7 @@ module Match = struct
let matching_separator = "#"
let regexp_string_of_qualifiers ?(prefix= false) quals =
let regexp_string_of_qualifiers ?(prefix = false) quals =
Str.quote (to_separated_string ~sep:matching_separator quals) ^ if prefix then "" else "$"
@ -94,7 +94,7 @@ module Match = struct
let colon_splits = String.split qual_name ~on:':' in
List.iter colon_splits ~f:(fun s ->
(* Filter out the '<' in operator< and operator<= *)
if not (String.is_prefix s ~prefix:"operator<") && String.contains s '<' then
if (not (String.is_prefix s ~prefix:"operator<")) && String.contains s '<' then
raise (ParseError ("Unexpected template in fuzzy qualified name %s." ^ qual_name)) ) ;
of_qual_string qual_name

@ -52,7 +52,7 @@ type instr =
| Remove_temps of Ident.t list * Location.t (** remove temporaries *)
[@@deriving compare]
let equal_instr = [%compare.equal : instr]
let equal_instr = [%compare.equal: instr]
let skip_instr = Remove_temps ([], Location.dummy)
@ -77,7 +77,7 @@ type atom =
| Anpred of PredSymb.t * Exp.t list (** negated predicate symbol applied to exps *)
[@@deriving compare]
let equal_atom = [%compare.equal : atom]
let equal_atom = [%compare.equal: atom]
let atom_has_local_addr a =
match a with
@ -93,7 +93,7 @@ type lseg_kind =
| Lseg_PE (** possibly empty (possibly circular) listseg *)
[@@deriving compare]
let equal_lseg_kind = [%compare.equal : lseg_kind]
let equal_lseg_kind = [%compare.equal: lseg_kind]
(** The boolean is true when the pointer was dereferenced without testing for zero. *)
type zero_flag = bool option [@@deriving compare]
@ -117,7 +117,7 @@ type inst =
| Ireturn_from_call of int
[@@deriving compare]
let equal_inst = [%compare.equal : inst]
let equal_inst = [%compare.equal: inst]
(** structured expressions represent a value of structured type, such as an array or a struct. *)
type 'inst strexp0 =
@ -135,11 +135,11 @@ type 'inst strexp0 =
type strexp = inst strexp0
let compare_strexp ?(inst= false) se1 se2 =
let compare_strexp ?(inst = false) se1 se2 =
compare_strexp0 (match inst with true -> compare_inst | false -> fun _ _ -> 0) se1 se2
let equal_strexp ?(inst= false) se1 se2 = Int.equal (compare_strexp ~inst se1 se2) 0
let equal_strexp ?(inst = false) se1 se2 = Int.equal (compare_strexp ~inst se1 se2) 0
(** an atomic heap predicate *)
type 'inst hpred0 =
@ -180,23 +180,23 @@ and 'inst hpara_dll0 =
type hpred = inst hpred0
(** Comparison between heap predicates. Reverse natural order, and order first by anchor exp. *)
let compare_hpred ?(inst= false) hpred1 hpred2 =
let compare_hpred ?(inst = false) hpred1 hpred2 =
compare_hpred0 (match inst with true -> compare_inst | false -> fun _ _ -> 0) hpred1 hpred2
let equal_hpred ?(inst= false) hpred1 hpred2 = Int.equal (compare_hpred ~inst hpred1 hpred2) 0
let equal_hpred ?(inst = false) hpred1 hpred2 = Int.equal (compare_hpred ~inst hpred1 hpred2) 0
type hpara = inst hpara0
let compare_hpara = compare_hpara0 (fun _ _ -> 0)
let equal_hpara = [%compare.equal : hpara]
let equal_hpara = [%compare.equal: hpara]
type hpara_dll = inst hpara_dll0
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} *)
let is_objc_object = function
@ -273,13 +273,13 @@ let pp_exp_printenv pe0 f e0 =
(** dump an expression. *)
let d_exp (e: Exp.t) = L.add_print_with_pe pp_exp_printenv e
let d_exp (e : Exp.t) = L.add_print_with_pe pp_exp_printenv e
(** Pretty print a list of expressions. *)
let pp_exp_list pe f expl = Pp.seq (pp_exp_printenv pe) f expl
(** dump a list of expressions. *)
let d_exp_list (el: Exp.t list) = L.add_print_with_pe pp_exp_list el
let d_exp_list (el : Exp.t list) = L.add_print_with_pe pp_exp_list el
let pp_texp pe f = function
| Exp.Sizeof {typ; nbytes; dynamic_length; subtype} ->
@ -303,7 +303,7 @@ let pp_texp_full pe f = function
(** Dump a type expression with all the details. *)
let d_texp_full (te: Exp.t) = L.add_print_with_pe pp_texp_full te
let d_texp_full (te : Exp.t) = L.add_print_with_pe pp_texp_full te
(** Pretty print an offset *)
let pp_offset pe f = function
@ -327,7 +327,7 @@ let rec pp_offset_list pe f = function
(** Dump a list of offsets *)
let d_offset_list (offl: offset list) = L.add_print_with_pe pp_offset_list offl
let d_offset_list (offl : offset list) = L.add_print_with_pe pp_offset_list offl
let pp_exp_typ pe f (e, t) = F.fprintf f "%a:%a" (pp_exp_printenv pe) e (Typ.pp pe) t
@ -423,7 +423,7 @@ let add_with_block_parameters_flag instr =
let is_block_pvar pvar = Typ.has_block_prefix (Mangled.to_string (Pvar.get_name pvar))
(** Dump an instruction. *)
let d_instr (i: instr) = L.add_print_with_pe ~color:Pp.Green pp_instr i
let d_instr (i : instr) = L.add_print_with_pe ~color:Pp.Green pp_instr i
let pp_atom pe0 f a =
let pe, changed = color_pre_wrapper pe0 f a in
@ -442,7 +442,7 @@ let pp_atom pe0 f a =
(** dump an atom *)
let d_atom (a: atom) = L.add_print_with_pe pp_atom a
let d_atom (a : atom) = L.add_print_with_pe pp_atom a
let pp_lseg_kind f = function Lseg_NE -> F.pp_print_string f "ne" | Lseg_PE -> ()
@ -566,21 +566,21 @@ end = struct
This can in turn extend the todo list for the nested predicates,
which are then visited as well.
Can be applied only once, as it destroys the todo list *)
let iter (env: env) f f_dll =
let iter (env : env) f f_dll =
while env.todo <> [] || env.todo_dll <> [] do
match env.todo with
| hpara :: todo' ->
env.todo <- todo' ;
let n, emitted = HparaHash.find env.hash hpara in
if not emitted then f n hpara
| [] ->
| [] -> (
match env.todo_dll with
| hpara_dll :: todo_dll' ->
env.todo_dll <- todo_dll' ;
let n, emitted = HparaDllHash.find env.hash_dll hpara_dll in
if not emitted then f_dll n hpara_dll
| [] ->
()
() )
done
end
@ -874,57 +874,57 @@ let pp_hpara_dll pe f = pp_hpara_dll_env pe None f
let pp_hpred pe f = pp_hpred_env pe None f
(** dump a strexp. *)
let d_sexp (se: strexp) = L.add_print_with_pe pp_sexp se
let d_sexp (se : strexp) = L.add_print_with_pe pp_sexp se
(** dump a hpred. *)
let d_hpred (hpred: hpred) = L.add_print_with_pe pp_hpred hpred
let d_hpred (hpred : hpred) = L.add_print_with_pe pp_hpred hpred
(** {2 Functions for traversing SIL data types} *)
let rec strexp_expmap (f: Exp.t * inst option -> Exp.t * inst option) =
let rec strexp_expmap (f : Exp.t * inst option -> Exp.t * inst option) =
let fe e = fst (f (e, None)) in
let fei (e, inst) =
match f (e, Some inst) with e', None -> (e', inst) | e', Some inst' -> (e', inst')
in
function
| Eexp (e, inst) ->
let e', inst' = fei (e, inst) in
Eexp (e', inst')
| Estruct (fld_se_list, inst) ->
let f_fld_se (fld, se) = (fld, strexp_expmap f se) in
Estruct (List.map ~f:f_fld_se fld_se_list, inst)
| Earray (len, idx_se_list, inst) ->
let len' = fe len in
let f_idx_se (idx, se) =
let idx' = fe idx in
(idx', strexp_expmap f se)
in
Earray (len', List.map ~f:f_idx_se idx_se_list, inst)
let hpred_expmap (f: Exp.t * inst option -> Exp.t * inst option) =
| Eexp (e, inst) ->
let e', inst' = fei (e, inst) in
Eexp (e', inst')
| Estruct (fld_se_list, inst) ->
let f_fld_se (fld, se) = (fld, strexp_expmap f se) in
Estruct (List.map ~f:f_fld_se fld_se_list, inst)
| Earray (len, idx_se_list, inst) ->
let len' = fe len in
let f_idx_se (idx, se) =
let idx' = fe idx in
(idx', strexp_expmap f se)
in
Earray (len', List.map ~f:f_idx_se idx_se_list, inst)
let hpred_expmap (f : Exp.t * inst option -> Exp.t * inst option) =
let fe e = fst (f (e, None)) in
function
| Hpointsto (e, se, te) ->
let e' = fe e in
let se' = strexp_expmap f se in
let te' = fe te in
Hpointsto (e', se', te')
| Hlseg (k, hpara, root, next, shared) ->
let root' = fe root in
let next' = fe next in
let shared' = List.map ~f:fe shared in
Hlseg (k, hpara, root', next', shared')
| Hdllseg (k, hpara, iF, oB, oF, iB, shared) ->
let iF' = fe iF in
let oB' = fe oB in
let oF' = fe oF in
let iB' = fe iB in
let shared' = List.map ~f:fe shared in
Hdllseg (k, hpara, iF', oB', oF', iB', shared')
let rec strexp_instmap (f: inst -> inst) strexp =
| Hpointsto (e, se, te) ->
let e' = fe e in
let se' = strexp_expmap f se in
let te' = fe te in
Hpointsto (e', se', te')
| Hlseg (k, hpara, root, next, shared) ->
let root' = fe root in
let next' = fe next in
let shared' = List.map ~f:fe shared in
Hlseg (k, hpara, root', next', shared')
| Hdllseg (k, hpara, iF, oB, oF, iB, shared) ->
let iF' = fe iF in
let oB' = fe oB in
let oF' = fe oF in
let iB' = fe iB in
let shared' = List.map ~f:fe shared in
Hdllseg (k, hpara, iF', oB', oF', iB', shared')
let rec strexp_instmap (f : inst -> inst) strexp =
match strexp with
| Eexp (e, inst) ->
Eexp (e, f inst)
@ -936,15 +936,15 @@ let rec strexp_instmap (f: inst -> inst) strexp =
Earray (len, List.map ~f:f_idx_se idx_se_list, f inst)
let rec hpara_instmap (f: inst -> inst) hpara =
let rec hpara_instmap (f : inst -> inst) hpara =
{hpara with body= List.map ~f:(hpred_instmap f) hpara.body}
and hpara_dll_instmap (f: inst -> inst) hpara_dll =
and hpara_dll_instmap (f : inst -> inst) hpara_dll =
{hpara_dll with body_dll= List.map ~f:(hpred_instmap f) hpara_dll.body_dll}
and hpred_instmap (fn: inst -> inst) (hpred: hpred) : hpred =
and hpred_instmap (fn : inst -> inst) (hpred : hpred) : hpred =
match hpred with
| Hpointsto (e, se, te) ->
let se' = strexp_instmap fn se in
@ -955,11 +955,11 @@ and hpred_instmap (fn: inst -> inst) (hpred: hpred) : hpred =
Hdllseg (k, hpara_dll_instmap fn hpar_dll, e, f, g, h, el)
let hpred_list_expmap (f: Exp.t * inst option -> Exp.t * inst option) (hlist: hpred list) =
let hpred_list_expmap (f : Exp.t * inst option -> Exp.t * inst option) (hlist : hpred list) =
List.map ~f:(hpred_expmap f) hlist
let atom_expmap (f: Exp.t -> Exp.t) = function
let atom_expmap (f : Exp.t -> Exp.t) = function
| Aeq (e1, e2) ->
Aeq (f e1, f e2)
| Aneq (e1, e2) ->
@ -981,7 +981,7 @@ let hpred_get_lexp acc = function
e1 :: e2 :: acc
let hpred_list_get_lexps (filter: Exp.t -> bool) (hlist: hpred list) : Exp.t list =
let hpred_list_get_lexps (filter : Exp.t -> bool) (hlist : hpred list) : Exp.t list =
let lexps = List.fold ~f:hpred_get_lexp ~init:[] hlist in
List.filter ~f:filter lexps
@ -993,10 +993,10 @@ let hpred_entries hpred = hpred_get_lexp [] hpred
let atom_gen_free_vars =
let open Sequence.Generator in
function
| Aeq (e1, e2) | Aneq (e1, e2) ->
Exp.gen_free_vars e1 >>= fun () -> Exp.gen_free_vars e2
| Apred (_, es) | Anpred (_, es) ->
ISequence.gen_sequence_list es ~f:Exp.gen_free_vars
| Aeq (e1, e2) | Aneq (e1, e2) ->
Exp.gen_free_vars e1 >>= fun () -> Exp.gen_free_vars e2
| Apred (_, es) | Anpred (_, es) ->
ISequence.gen_sequence_list es ~f:Exp.gen_free_vars
let atom_free_vars a = Sequence.Generator.run (atom_gen_free_vars a)
@ -1004,35 +1004,35 @@ let atom_free_vars a = Sequence.Generator.run (atom_gen_free_vars a)
let rec strexp_gen_free_vars =
let open Sequence.Generator in
function
| Eexp (e, _) ->
Exp.gen_free_vars e
| Estruct (fld_se_list, _) ->
ISequence.gen_sequence_list fld_se_list ~f:(fun (_, se) -> strexp_gen_free_vars se)
| Earray (len, idx_se_list, _) ->
Exp.gen_free_vars len
>>= fun () ->
ISequence.gen_sequence_list idx_se_list ~f:(fun (e, se) ->
Exp.gen_free_vars e >>= fun () -> strexp_gen_free_vars se )
| Eexp (e, _) ->
Exp.gen_free_vars e
| Estruct (fld_se_list, _) ->
ISequence.gen_sequence_list fld_se_list ~f:(fun (_, se) -> strexp_gen_free_vars se)
| Earray (len, idx_se_list, _) ->
Exp.gen_free_vars len
>>= fun () ->
ISequence.gen_sequence_list idx_se_list ~f:(fun (e, se) ->
Exp.gen_free_vars e >>= fun () -> strexp_gen_free_vars se )
let hpred_gen_free_vars =
let open Sequence.Generator in
function
| Hpointsto (base, sexp, te) ->
Exp.gen_free_vars base
>>= fun () -> strexp_gen_free_vars sexp >>= fun () -> Exp.gen_free_vars te
| Hlseg (_, _, e1, e2, elist) ->
Exp.gen_free_vars e1
>>= fun () ->
Exp.gen_free_vars e2 >>= fun () -> ISequence.gen_sequence_list elist ~f:Exp.gen_free_vars
| Hdllseg (_, _, e1, e2, e3, e4, elist) ->
Exp.gen_free_vars e1
>>= fun () ->
Exp.gen_free_vars e2
>>= fun () ->
Exp.gen_free_vars e3
>>= fun () ->
Exp.gen_free_vars e4 >>= fun () -> ISequence.gen_sequence_list elist ~f:Exp.gen_free_vars
| Hpointsto (base, sexp, te) ->
Exp.gen_free_vars base
>>= fun () -> strexp_gen_free_vars sexp >>= fun () -> Exp.gen_free_vars te
| Hlseg (_, _, e1, e2, elist) ->
Exp.gen_free_vars e1
>>= fun () ->
Exp.gen_free_vars e2 >>= fun () -> ISequence.gen_sequence_list elist ~f:Exp.gen_free_vars
| Hdllseg (_, _, e1, e2, e3, e4, elist) ->
Exp.gen_free_vars e1
>>= fun () ->
Exp.gen_free_vars e2
>>= fun () ->
Exp.gen_free_vars e3
>>= fun () ->
Exp.gen_free_vars e4 >>= fun () -> ISequence.gen_sequence_list elist ~f:Exp.gen_free_vars
let hpred_free_vars h = Sequence.Generator.run (hpred_gen_free_vars h)
@ -1102,7 +1102,7 @@ type subst = [`Exp of exp_subst | `Typ of Typ.type_subst_t] [@@deriving compare]
type subst_fun = [`Exp of Ident.t -> Exp.t | `Typ of (Typ.t -> Typ.t) * (Typ.Name.t -> Typ.Name.t)]
let equal_exp_subst = [%compare.equal : exp_subst]
let equal_exp_subst = [%compare.equal: exp_subst]
let sub_no_duplicated_ids sub = not (List.contains_dup ~compare:compare_ident_exp_ids sub)
@ -1168,11 +1168,11 @@ let sub_symmetric_difference sub1_in sub2_in =
(** [sub_find filter sub] returns the expression associated to the first identifier
that satisfies [filter]. Raise [Not_found] if there isn't one. *)
let sub_find filter (sub: exp_subst) = snd (List.find_exn ~f:(fun (i, _) -> filter i) sub)
let sub_find filter (sub : exp_subst) = snd (List.find_exn ~f:(fun (i, _) -> filter i) sub)
(** [sub_filter filter sub] restricts the domain of [sub] to the
identifiers satisfying [filter]. *)
let sub_filter filter (sub: exp_subst) = List.filter ~f:(fun (i, _) -> filter i) sub
let sub_filter filter (sub : exp_subst) = List.filter ~f:(fun (i, _) -> filter i) sub
(** [sub_filter_pair filter sub] restricts the domain of [sub] to the
identifiers satisfying [filter(id, sub(id))]. *)
@ -1180,11 +1180,13 @@ let sub_filter_pair = List.filter
(** [sub_range_partition filter sub] partitions [sub] according to
whether range expressions satisfy [filter]. *)
let sub_range_partition filter (sub: exp_subst) = List.partition_tf ~f:(fun (_, e) -> filter e) sub
let sub_range_partition filter (sub : exp_subst) =
List.partition_tf ~f:(fun (_, e) -> filter e) sub
(** [sub_domain_partition filter sub] partitions [sub] according to
whether domain identifiers satisfy [filter]. *)
let sub_domain_partition filter (sub: exp_subst) =
let sub_domain_partition filter (sub : exp_subst) =
List.partition_tf ~f:(fun (i, _) -> filter i) sub
@ -1217,7 +1219,7 @@ let exp_subst_gen_free_vars sub =
let exp_subst_free_vars sub = Sequence.Generator.run (exp_subst_gen_free_vars sub)
let rec exp_sub_ids (f: subst_fun) exp =
let rec exp_sub_ids (f : subst_fun) exp =
let f_typ x = match f with `Exp _ -> x | `Typ (f, _) -> f x in
let f_tname x = match f with `Exp _ -> x | `Typ (_, f) -> f x in
match (exp : Exp.t) with
@ -1238,8 +1240,7 @@ let rec exp_sub_ids (f: subst_fun) exp =
if phys_equal e' e then exp else Exp.Exn e'
| Closure c ->
let captured_vars =
IList.map_changed
~equal:[%compare.equal : Exp.t * Pvar.t * Typ.t]
IList.map_changed ~equal:[%compare.equal: Exp.t * Pvar.t * Typ.t]
~f:(fun ((e, pvar, typ) as captured) ->
let e' = exp_sub_ids f e in
let typ' = f_typ typ in
@ -1301,7 +1302,7 @@ let apply_sub subst : subst_fun =
`Typ (Typ.sub_type typ_subst, Typ.sub_tname typ_subst)
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
(** apply [f] to id's in [instr]. if [sub_id_binders] is false, [f] is only applied to bound id's *)
let instr_sub_ids ~sub_id_binders f instr =
@ -1333,8 +1334,7 @@ let instr_sub_ids ~sub_id_binders f instr =
in
let fun_exp' = exp_sub_ids f fun_exp in
let actuals' =
IList.map_changed
~equal:[%compare.equal : Exp.t * Typ.t]
IList.map_changed ~equal:[%compare.equal: Exp.t * Typ.t]
~f:(fun ((actual, typ) as actual_pair) ->
let actual' = exp_sub_ids f actual in
let typ' = sub_typ typ in
@ -1357,7 +1357,7 @@ let instr_sub_ids ~sub_id_binders f instr =
(** apply [subst] to all id's in [instr], including binder id's *)
let instr_sub (subst: subst) instr = instr_sub_ids ~sub_id_binders:true (apply_sub subst) instr
let instr_sub (subst : subst) instr = instr_sub_ids ~sub_id_binders:true (apply_sub subst) instr
let atom_sub subst = atom_expmap (exp_sub subst)
@ -1375,7 +1375,7 @@ let rec exp_replace_exp epairs e =
match List.find ~f:(fun (e1, _) -> Exp.equal e e1) epairs with
| Some (_, e2) ->
e2
| None ->
| None -> (
(* If e is a compound expression, we need to check for its subexpressions as well *)
match e with
| Exp.UnOp (op, e0, ty) ->
@ -1396,7 +1396,7 @@ let rec exp_replace_exp epairs e =
let index' = exp_replace_exp epairs index in
if phys_equal base base' && phys_equal index index' then e else Exp.Lindex (base', index')
| _ ->
e
e )
let atom_replace_exp epairs atom = atom_expmap (fun e -> exp_replace_exp epairs e) atom
@ -1568,7 +1568,7 @@ let hpara_instantiate para e1 e2 elist =
in
let subst =
`Exp
(exp_subst_of_list ((para.root, e1) :: (para.next, e2) :: subst_for_svars @ subst_for_evars))
(exp_subst_of_list (((para.root, e1) :: (para.next, e2) :: subst_for_svars) @ subst_for_evars))
in
(ids_evars, List.map ~f:(hpred_sub subst) para.body)
@ -1578,7 +1578,7 @@ let hpara_instantiate para e1 e2 elist =
then the result of the instantiation is
[b\[cell / x, blink / y, flink / z, elist / xs, zs'_/ zs\]]
for some fresh [_zs'].*)
let hpara_dll_instantiate (para: hpara_dll) cell blink flink elist =
let hpara_dll_instantiate (para : hpara_dll) cell blink flink elist =
let subst_for_svars =
let g id e = (id, e) in
try List.map2_exn ~f:g para.svars_dll elist with Invalid_argument _ -> assert false
@ -1594,7 +1594,7 @@ let hpara_dll_instantiate (para: hpara_dll) cell blink flink elist =
let subst =
`Exp
(exp_subst_of_list
( (para.cell, cell) :: (para.blink, blink) :: (para.flink, flink) :: subst_for_svars
( ((para.cell, cell) :: (para.blink, blink) :: (para.flink, flink) :: subst_for_svars)
@ subst_for_evars ))
in
(ids_evars, List.map ~f:(hpred_sub subst) para.body_dll)

@ -8,6 +8,7 @@
(** The Smallfoot Intermediate Language *)
open! IStd
module F = Format
(** {2 Programs and Types} *)

@ -23,7 +23,8 @@ let select_existing_statement =
let get_existing_data source_file =
ResultsDatabase.with_registered_statement select_existing_statement ~f:(fun db stmt ->
SourceFile.SQLite.serialize source_file |> Sqlite3.bind stmt 1
SourceFile.SQLite.serialize source_file
|> Sqlite3.bind stmt 1
(* :source *)
|> SqliteUtils.check_result_code db ~log:"get_existing_data bind source file" ;
SqliteUtils.result_option ~finalize:false db ~log:"looking for pre-existing cfgs" stmt
@ -53,7 +54,8 @@ let add source_file cfg tenv =
sure that all attributes were written to disk (but not necessarily flushed) *)
Cfg.save_attributes source_file cfg ;
ResultsDatabase.with_registered_statement store_statement ~f:(fun db store_stmt ->
SourceFile.SQLite.serialize source_file |> Sqlite3.bind store_stmt 1
SourceFile.SQLite.serialize source_file
|> Sqlite3.bind store_stmt 1
(* :source *)
|> SqliteUtils.check_result_code db ~log:"store bind source file" ;
Cfg.SQLite.serialize cfg |> Sqlite3.bind store_stmt 2
@ -77,8 +79,8 @@ let get_all ~filter () =
it inside the function *)
Sqlite3.prepare db "SELECT source_file FROM source_files"
|> IContainer.rev_filter_map_to_list
~fold:(SqliteUtils.result_fold_single_column_rows db ~log:"getting all source files") ~f:
(fun column ->
~fold:(SqliteUtils.result_fold_single_column_rows db ~log:"getting all source files")
~f:(fun column ->
let source_file = SourceFile.SQLite.deserialize column in
Option.some_if (filter source_file) source_file )
@ -90,7 +92,8 @@ let load_proc_names_statement =
let proc_names_of_source source =
ResultsDatabase.with_registered_statement load_proc_names_statement ~f:(fun db load_stmt ->
SourceFile.SQLite.serialize source |> Sqlite3.bind load_stmt 1
SourceFile.SQLite.serialize source
|> Sqlite3.bind load_stmt 1
|> SqliteUtils.check_result_code db ~log:"load bind source file" ;
SqliteUtils.result_single_column_option ~finalize:false db
~log:"SourceFiles.proc_names_of_source" load_stmt
@ -103,7 +106,8 @@ let exists_source_statement =
let is_captured source =
ResultsDatabase.with_registered_statement exists_source_statement ~f:(fun db exists_stmt ->
SourceFile.SQLite.serialize source |> Sqlite3.bind exists_stmt 1
SourceFile.SQLite.serialize source
|> Sqlite3.bind exists_stmt 1
(* :k *)
|> SqliteUtils.check_result_code db ~log:"load captured source file" ;
SqliteUtils.result_single_column_option ~finalize:false ~log:"SourceFiles.is_captured" db
@ -133,7 +137,8 @@ let deserialize_freshly_captured = function[@warning "-8"]
let is_freshly_captured source =
ResultsDatabase.with_registered_statement is_freshly_captured_statement ~f:(fun db load_stmt ->
SourceFile.SQLite.serialize source |> Sqlite3.bind load_stmt 1
SourceFile.SQLite.serialize source
|> Sqlite3.bind load_stmt 1
|> SqliteUtils.check_result_code db ~log:"load bind source file" ;
SqliteUtils.result_single_column_option ~finalize:false
~log:"SourceFiles.is_freshly_captured" db load_stmt

@ -29,5 +29,11 @@ val mark_all_stale : unit -> unit
(** mark all source files as stale; do be called at the start of a new capture phase *)
val pp_all :
filter:Filtering.source_files_filter -> cfgs:bool -> type_environment:bool
-> procedure_names:bool -> freshly_captured:bool -> Format.formatter -> unit -> unit
filter:Filtering.source_files_filter
-> cfgs:bool
-> type_environment:bool
-> procedure_names:bool
-> freshly_captured:bool
-> Format.formatter
-> unit
-> unit

@ -19,18 +19,18 @@ let list_to_string list =
type t' = Exact (** denotes the current type only *) | Subtypes of Typ.Name.t list
[@@deriving compare]
let equal_modulo_flag (st1, _) (st2, _) = [%compare.equal : t'] st1 st2
let equal_modulo_flag (st1, _) (st2, _) = [%compare.equal: t'] st1 st2
(** denotes the current type and a list of types that are not their subtypes *)
type kind = CAST | INSTOF | NORMAL [@@deriving compare]
let equal_kind = [%compare.equal : kind]
let equal_kind = [%compare.equal: kind]
type t = t' * kind [@@deriving compare]
type result = No | Unknown | Yes [@@deriving compare]
let equal_result = [%compare.equal : result]
let equal_result = [%compare.equal: result]
let sub_type tname_subst st_pair =
let st, kind = st_pair in
@ -44,7 +44,7 @@ let sub_type tname_subst st_pair =
let max_result res1 res2 = if compare_result res1 res2 <= 0 then res2 else res1
let is_interface tenv (class_name: Typ.Name.t) =
let is_interface tenv (class_name : Typ.Name.t) =
match (class_name, Tenv.lookup tenv class_name) with
| JavaClass _, Some {fields= []; methods= []} ->
true
@ -98,7 +98,7 @@ let check_subtype =
let is_subt = check_subclass_tenv tenv c1 c2 in
subtMap := SubtypesMap.add (c1, c2) is_subt !subtMap ;
is_subt
: result )
: result )
let is_known_subtype tenv c1 c2 : bool = equal_result (check_subtype tenv c1 c2) Yes
@ -227,7 +227,7 @@ let rec add_not_subtype tenv c1 l1 l2 =
if should_add then c :: rest' else rest'
let get_subtypes tenv (c1, ((st1, flag1): t)) (c2, ((st2, flag2): t)) =
let get_subtypes tenv (c1, ((st1, flag1) : t)) (c2, ((st2, flag2) : t)) =
let is_sub = is_known_subtype tenv c1 c2 in
let pos_st, neg_st =
match (st1, st2) with

@ -44,7 +44,7 @@ val is_known_subtype : Tenv.t -> Typ.Name.t -> Typ.Name.t -> bool
val is_cast : t -> bool
val is_instof : t -> bool [@@warning "-32"]
val is_instof : t -> bool [@@warning "-32"]
val equal_modulo_flag : t -> t -> bool
(** equality ignoring flags in the subtype *)

@ -22,7 +22,7 @@ end)
(** Type for type environment. *)
type t = Typ.Struct.t TypenameHash.t
let pp fmt (tenv: t) =
let pp fmt (tenv : t) =
TypenameHash.iter
(fun name typ ->
Format.fprintf fmt "@[<6>NAME: %s@]@," (Typ.Name.to_string name) ;
@ -44,7 +44,7 @@ let mk_struct tenv ?default ?fields ?statics ?methods ?supers ?annots name =
(** Look up a name in the global type environment. *)
let lookup tenv name : Typ.Struct.t option =
try Some (TypenameHash.find tenv name) with Caml.Not_found ->
try Some (TypenameHash.find tenv name) with Caml.Not_found -> (
(* ToDo: remove the following additional lookups once C/C++ interop is resolved *)
match (name : Typ.Name.t) with
| CStruct m -> (
@ -52,7 +52,7 @@ let lookup tenv name : Typ.Struct.t option =
| CppClass (m, NoTemplate) -> (
try Some (TypenameHash.find tenv (CStruct m)) with Caml.Not_found -> None )
| _ ->
None
None )
let compare_fields (name1, _, _) (name2, _, _) = Typ.Fieldname.compare name1 name2
@ -131,7 +131,8 @@ let load_global () : t option =
let load source =
ResultsDatabase.with_registered_statement load_statement ~f:(fun db load_stmt ->
SourceFile.SQLite.serialize source |> Sqlite3.bind load_stmt 1
SourceFile.SQLite.serialize source
|> Sqlite3.bind load_stmt 1
|> SqliteUtils.check_result_code db ~log:"load bind source file" ;
SqliteUtils.result_single_column_option ~finalize:false ~log:"Tenv.load" db load_stmt
|> Option.bind ~f:(fun x ->

@ -30,15 +30,21 @@ val lookup : t -> Typ.Name.t -> Typ.Struct.t option
(** Look up a name in the global type environment. *)
val mk_struct :
t -> ?default:Typ.Struct.t -> ?fields:Typ.Struct.fields -> ?statics:Typ.Struct.fields
-> ?methods:Typ.Procname.t list -> ?supers:Typ.Name.t list -> ?annots:Annot.Item.t -> Typ.Name.t
t
-> ?default:Typ.Struct.t
-> ?fields:Typ.Struct.fields
-> ?statics:Typ.Struct.fields
-> ?methods:Typ.Procname.t list
-> ?supers:Typ.Name.t list
-> ?annots:Annot.Item.t
-> Typ.Name.t
-> Typ.Struct.t
(** Construct a struct_typ, normalizing field types *)
val add_field : t -> Typ.Name.t -> Typ.Struct.field -> unit
(** Add a field to a given struct in the global type environment. *)
val pp : Format.formatter -> t -> unit [@@warning "-32"]
val pp : Format.formatter -> t -> unit [@@warning "-32"]
(** print a type environment *)
val language_is : t -> Language.t -> bool

@ -96,7 +96,7 @@ type ptr_kind =
| Pk_objc_autoreleasing (** Obj-C __autoreleasing pointer *)
[@@deriving compare]
let equal_ptr_kind = [%compare.equal : ptr_kind]
let equal_ptr_kind = [%compare.equal: ptr_kind]
let ptr_kind_string = function
| Pk_reference ->
@ -146,21 +146,21 @@ module T = struct
| Template of {mangled: string option; args: template_arg list}
[@@deriving compare]
let equal_desc = [%compare.equal : desc]
let equal_desc = [%compare.equal: desc]
let equal_quals = [%compare.equal : type_quals]
let equal_quals = [%compare.equal: type_quals]
let equal_template_arg = [%compare.equal : template_arg]
let equal_template_arg = [%compare.equal: template_arg]
let equal = [%compare.equal : t]
let equal = [%compare.equal: t]
end
include T
let mk_type_quals ?default ?is_const ?is_restrict ?is_volatile () =
let default_ = {is_const= false; is_restrict= false; is_volatile= false} in
let mk_aux ?(default= default_) ?(is_const= default.is_const) ?(is_restrict= default.is_restrict)
?(is_volatile= default.is_volatile) () =
let mk_aux ?(default = default_) ?(is_const = default.is_const)
?(is_restrict = default.is_restrict) ?(is_volatile = default.is_volatile) () =
{is_const; is_restrict; is_volatile}
in
mk_aux ?default ?is_const ?is_restrict ?is_volatile ()
@ -174,7 +174,7 @@ let is_volatile {is_volatile} = is_volatile
let mk ?default ?quals desc : t =
let default_ = {desc; quals= mk_type_quals ()} in
let mk_aux ?(default= default_) ?(quals= default.quals) desc = {desc; quals} in
let mk_aux ?(default = default_) ?(quals = default.quals) desc = {desc; quals} in
mk_aux ?default ?quals desc
@ -317,7 +317,7 @@ and sub_tname subst tname =
module Name = struct
type t = name [@@deriving compare]
let equal = [%compare.equal : t]
let equal = [%compare.equal: t]
let qual_name = function
| CStruct name | CUnion name | ObjcClass name | ObjcProtocol name ->
@ -490,10 +490,10 @@ module Name = struct
end
(** dump a type with all the details. *)
let d_full (t: t) = L.add_print_with_pe pp_full t
let d_full (t : t) = L.add_print_with_pe pp_full t
(** dump a list of types. *)
let d_list (tl: t list) =
let d_list (tl : t list) =
let pp pe = Pp.seq (pp pe) in
L.add_print_with_pe pp tl
@ -547,7 +547,7 @@ module Procname = struct
(** Level of verbosity of some to_string functions. *)
type detail_level = Verbose | Non_verbose | Simple [@@deriving compare]
let equal_detail_level = [%compare.equal : detail_level]
let equal_detail_level = [%compare.equal: detail_level]
let is_verbose v = match v with Verbose -> true | _ -> false
@ -625,7 +625,7 @@ module Procname = struct
let get_parameters j = j.parameters
(** Prints a string of a java procname with the given level of verbosity *)
let to_string ?(withclass= false) j verbosity =
let to_string ?(withclass = false) j verbosity =
match verbosity with
| Verbose | Non_verbose ->
(* if verbose, then package.class.method(params): rtype,
@ -830,7 +830,8 @@ module Procname = struct
| CPPMethod {mangled} | CPPDestructor {mangled} ->
"(" ^ Option.value ~default:"" mangled ^ ")"
| CPPConstructor {mangled; is_constexpr} ->
"{" ^ Option.value ~default:"" mangled ^ (if is_constexpr then "|constexpr" else "")
"{" ^ Option.value ~default:"" mangled
^ (if is_constexpr then "|constexpr" else "")
^ "}"
| ObjCClassMethod ->
"class"
@ -849,7 +850,8 @@ module Procname = struct
| Verbose ->
let m_str = kind_to_verbose_string osig.kind in
Name.name osig.class_name ^ "_" ^ osig.method_name
^ Parameter.parameters_to_string osig.parameters ^ m_str
^ Parameter.parameters_to_string osig.parameters
^ m_str
let get_parameters osig = osig.parameters
@ -885,12 +887,12 @@ module Procname = struct
plain ^ "()"
| Non_verbose ->
plain
| Verbose ->
| Verbose -> (
match mangled with
| None ->
plain ^ Parameter.parameters_to_string parameters
| Some s ->
plain ^ Parameter.parameters_to_string parameters ^ "{" ^ s ^ "}"
plain ^ Parameter.parameters_to_string parameters ^ "{" ^ s ^ "}" )
let get_parameters c = c.parameters
@ -931,7 +933,7 @@ module Procname = struct
| WithBlockParameters of t * Block.block_name list
[@@deriving compare]
let equal = [%compare.equal : t]
let equal = [%compare.equal: t]
let hash = Hashtbl.hash
@ -967,7 +969,7 @@ module Procname = struct
(** Replace the class name component of a procedure name.
In case of Java, replace package and class name. *)
let rec replace_class t (new_class: Name.t) =
let rec replace_class t (new_class : Name.t) =
match t with
| Java j ->
Java {j with class_name= new_class}
@ -983,7 +985,7 @@ module Procname = struct
match t with ObjC_Cpp osig -> Name.is_objc_protocol osig.class_name | _ -> false
let rec objc_cpp_replace_method_name t (new_method_name: string) =
let rec objc_cpp_replace_method_name t (new_method_name : string) =
match t with
| ObjC_Cpp osig ->
ObjC_Cpp {osig with method_name= new_method_name}
@ -1102,7 +1104,7 @@ module Procname = struct
(** Convenient representation of a procname for external tools (e.g. eclipse plugin) *)
let rec to_simplified_string ?(withclass= false) p =
let rec to_simplified_string ?(withclass = false) p =
match p with
| Java j ->
Java.to_string ~withclass j Simple
@ -1258,7 +1260,9 @@ module Procname = struct
:: Option.to_list mangled
|> String.concat ~sep:"#"
| ObjC_Cpp objc_cpp ->
get_qual_name_str pname ^ Parameter.parameters_to_string objc_cpp.parameters ^ "#"
get_qual_name_str pname
^ Parameter.parameters_to_string objc_cpp.parameters
^ "#"
^ ObjC_Cpp.kind_to_verbose_string objc_cpp.kind
| _ ->
to_unique_id pname
@ -1304,7 +1308,7 @@ module Fieldname = struct
type t = Clang of {class_name: Name.t; field_name: string} | Java of string
[@@deriving compare]
let equal = [%compare.equal : t]
let equal = [%compare.equal: t]
module T = struct
type nonrec t = t
@ -1444,15 +1448,15 @@ module Struct = struct
let internal_mk_struct ?default ?fields ?statics ?methods ?supers ?annots () =
let default_ = {fields= []; statics= []; methods= []; supers= []; annots= Annot.Item.empty} in
let mk_struct_ ?(default= default_) ?(fields= default.fields) ?(statics= default.statics)
?(methods= default.methods) ?(supers= default.supers) ?(annots= default.annots) () =
let mk_struct_ ?(default = default_) ?(fields = default.fields) ?(statics = default.statics)
?(methods = default.methods) ?(supers = default.supers) ?(annots = default.annots) () =
{fields; statics; methods; supers; annots}
in
mk_struct_ ?default ?fields ?statics ?methods ?supers ?annots ()
(** the element typ of the final extensible array in the given typ, if any *)
let rec get_extensible_array_element_typ ~lookup (typ: T.t) =
let rec get_extensible_array_element_typ ~lookup (typ : T.t) =
match typ.desc with
| Tarray {elt} ->
Some elt
@ -1471,7 +1475,7 @@ module Struct = struct
(** If a struct type with field f, return the type of f. If not, return the default *)
let fld_typ ~lookup ~default fn (typ: T.t) =
let fld_typ ~lookup ~default fn (typ : T.t) =
match typ.desc with
| Tstruct name -> (
match lookup name with
@ -1484,7 +1488,7 @@ module Struct = struct
default
let get_field_type_and_annotation ~lookup fn (typ: T.t) =
let get_field_type_and_annotation ~lookup fn (typ : T.t) =
match typ.desc with
| Tstruct name | Tptr ({desc= Tstruct name}, _) -> (
match lookup name with

@ -56,7 +56,11 @@ val equal_ptr_kind : ptr_kind -> ptr_kind -> bool
type type_quals [@@deriving compare]
val mk_type_quals :
?default:type_quals -> ?is_const:bool -> ?is_restrict:bool -> ?is_volatile:bool -> unit
?default:type_quals
-> ?is_const:bool
-> ?is_restrict:bool
-> ?is_volatile:bool
-> unit
-> type_quals
val is_const : type_quals -> bool
@ -643,8 +647,14 @@ module Struct : sig
(** Pretty print a struct type. *)
val internal_mk_struct :
?default:t -> ?fields:fields -> ?statics:fields -> ?methods:Procname.t list
-> ?supers:Name.t list -> ?annots:Annot.Item.t -> unit -> t
?default:t
-> ?fields:fields
-> ?statics:fields
-> ?methods:Procname.t list
-> ?supers:Name.t list
-> ?annots:Annot.Item.t
-> unit
-> t
(** Construct a struct_typ, normalizing field types *)
val get_extensible_array_element_typ : lookup:lookup -> typ -> typ option

@ -17,7 +17,7 @@ type t =
| LNot (** Logical Not (!) *)
[@@deriving compare]
let equal = [%compare.equal : t]
let equal = [%compare.equal: t]
(** String representation of unary operator. *)
let to_string = function Neg -> "-" | BNot -> "~" | LNot -> "!"

@ -12,7 +12,7 @@ module F = Format
type t = LogicalVar of Ident.t | ProgramVar of Pvar.t [@@deriving compare]
let equal = [%compare.equal : t]
let equal = [%compare.equal: t]
let compare_modulo_this x y =
match (x, y) with

@ -1,7 +1,9 @@
(* -*- tuareg -*- *)
(* NOTE: prepend dune.common to this file! *)
;; Format.sprintf
{|
;;
Format.sprintf
{|
(library
(name InferIR)
(public_name InferIR)
@ -16,7 +18,7 @@
(mld_files index)
)
|}
(String.concat " " common_cflags)
(String.concat " " common_optflags)
(String.concat " " ("InferBase" :: common_libraries))
|> Jbuild_plugin.V1.send
(String.concat " " common_cflags)
(String.concat " " common_optflags)
(String.concat " " ("InferBase" :: common_libraries))
|> Jbuild_plugin.V1.send

@ -297,7 +297,7 @@ module BooleanOr = struct
let is_empty astate = not astate
let ( <= ) ~lhs ~rhs = not lhs || rhs
let ( <= ) ~lhs ~rhs = (not lhs) || rhs
let join = ( || )

@ -59,7 +59,8 @@ module BottomLifted (Domain : S) : sig
end
(** Create a domain with Top element from a pre-domain *)
include sig
include
sig
(* ocaml ignores the warning suppression at toplevel, hence the [include struct ... end] trick *)
[@@@warning "-60"]
@ -124,7 +125,8 @@ end
(** Boolean domain ordered by p || ~q. Useful when you want a boolean that's true only when it's
true in both conditional branches. *)
include sig
include
sig
(* ocaml ignores the warning suppression at toplevel, hence the [include struct ... end] trick *)
[@@@warning "-60"]
@ -146,10 +148,10 @@ end
module CountDomain (MaxCount : MaxCount) : sig
include WithBottom with type astate = private int
val top : astate [@@warning "-32"]
val top : astate [@@warning "-32"]
(** maximum value *)
val is_top : astate -> bool [@@warning "-32"]
val is_top : astate -> bool [@@warning "-32"]
(** return true if this is the maximum value *)
val increment : astate -> astate

@ -19,12 +19,17 @@ module type S = sig
type invariant_map = TransferFunctions.Domain.astate state InvariantMap.t
val compute_post :
?debug:bool -> TransferFunctions.extras ProcData.t -> initial:TransferFunctions.Domain.astate
?debug:bool
-> TransferFunctions.extras ProcData.t
-> initial:TransferFunctions.Domain.astate
-> TransferFunctions.Domain.astate option
val exec_cfg :
TransferFunctions.CFG.t -> TransferFunctions.extras ProcData.t
-> initial:TransferFunctions.Domain.astate -> debug:bool -> invariant_map
TransferFunctions.CFG.t
-> TransferFunctions.extras ProcData.t
-> initial:TransferFunctions.Domain.astate
-> debug:bool
-> invariant_map
val exec_pdesc :
TransferFunctions.extras ProcData.t -> initial:TransferFunctions.Domain.astate -> invariant_map
@ -139,14 +144,14 @@ struct
match extract_post_ pred with
| None ->
joined_post_opt
| Some post as some_post ->
| Some post as some_post -> (
match joined_post_opt with
| None ->
some_post
| Some joined_post ->
let res = Domain.join joined_post post in
if debug then debug_absint_operation (`Join (joined_post, post, res)) node ;
Some res )
Some res ) )
in
match Scheduler.pop work_queue with
| Some (_, [], work_queue') ->
@ -179,7 +184,7 @@ struct
(* compute and return the postcondition of [pdesc] *)
let compute_post ?(debug= Config.write_html) ({ProcData.pdesc} as proc_data) ~initial =
let compute_post ?(debug = Config.write_html) ({ProcData.pdesc} as proc_data) ~initial =
let cfg = CFG.from_pdesc pdesc in
let inv_map = exec_cfg cfg proc_data ~initial ~debug in
extract_post (Node.id (CFG.exit_node cfg)) inv_map

@ -19,14 +19,19 @@ module type S = sig
type invariant_map = TransferFunctions.Domain.astate state InvariantMap.t
val compute_post :
?debug:bool -> TransferFunctions.extras ProcData.t -> initial:TransferFunctions.Domain.astate
?debug:bool
-> TransferFunctions.extras ProcData.t
-> initial:TransferFunctions.Domain.astate
-> TransferFunctions.Domain.astate option
(** compute and return the postcondition for the given procedure starting from [initial]. If
[debug] is true, print html debugging output. *)
val exec_cfg :
TransferFunctions.CFG.t -> TransferFunctions.extras ProcData.t
-> initial:TransferFunctions.Domain.astate -> debug:bool -> invariant_map
TransferFunctions.CFG.t
-> TransferFunctions.extras ProcData.t
-> initial:TransferFunctions.Domain.astate
-> debug:bool
-> invariant_map
(** compute and return invariant map for the given CFG/procedure starting from [initial]. if
[debug] is true, print html debugging output. *)

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

@ -42,7 +42,7 @@ struct
let is_java_unlock pname actuals =
(* would check is_java, but we want to include builtins too *)
not (Typ.Procname.is_c_method pname)
(not (Typ.Procname.is_c_method pname))
&& match RacerDConfig.Models.get_lock pname actuals with Unlock -> true | _ -> false

@ -42,7 +42,7 @@ module MakeAbstractInterpreterWithConfig
module type of AbstractInterpreter.Make (CFG) (Make (MakeTransferFunctions) (HilConfig))
val compute_post :
Interpreter.TransferFunctions.extras ProcData.t
Interpreter.TransferFunctions.extras ProcData.t
-> initial:MakeTransferFunctions(CFG).Domain.astate
-> MakeTransferFunctions(CFG).Domain.astate option
(** compute and return the postcondition for the given procedure starting from [initial]. If

@ -63,7 +63,7 @@ let get_this_type proc_attributes =
match proc_attributes.ProcAttributes.formals with (_, t) :: _ -> Some t | _ -> None
let type_get_direct_supertypes tenv (typ: Typ.t) =
let type_get_direct_supertypes tenv (typ : Typ.t) =
match typ.desc with
| Tptr ({desc= Tstruct name}, _) | Tstruct name -> (
match Tenv.lookup tenv name with Some {supers} -> supers | None -> [] )
@ -75,7 +75,7 @@ let type_get_class_name {Typ.desc} =
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
| Tptr ({desc= Tstruct name}, _) | Tstruct name -> (
match Tenv.lookup tenv name with Some {annots} -> Some annots | None -> None )
@ -93,7 +93,7 @@ let rec get_type_name {Typ.desc} =
"_"
let get_field_type_name tenv (typ: Typ.t) (fieldname: Typ.Fieldname.t) : string option =
let get_field_type_name tenv (typ : Typ.t) (fieldname : Typ.Fieldname.t) : string option =
match typ.desc with
| Tstruct name | Tptr ({desc= Tstruct name}, _) -> (
match Tenv.lookup tenv name with
@ -109,7 +109,7 @@ let get_field_type_name tenv (typ: Typ.t) (fieldname: Typ.Fieldname.t) : string
None
let java_get_const_type_name (const: Const.t) : string =
let java_get_const_type_name (const : Const.t) : string =
match const with
| Const.Cstr _ ->
"java.lang.String"
@ -121,7 +121,7 @@ let java_get_const_type_name (const: Const.t) : string =
"_"
let get_vararg_type_names tenv (call_node: Procdesc.Node.t) (ivar: Pvar.t) : string list =
let get_vararg_type_names tenv (call_node : Procdesc.Node.t) (ivar : Pvar.t) : string list =
(* Is this the node creating ivar? *)
let initializes_array instrs =
instrs
@ -224,7 +224,7 @@ let initializer_classes =
let initializer_methods = ["onActivityCreated"; "onAttach"; "onCreate"; "onCreateView"; "setUp"]
(** Check if the type has in its supertypes from the initializer_classes list. *)
let type_has_initializer (tenv: Tenv.t) (t: Typ.t) : bool =
let type_has_initializer (tenv : Tenv.t) (t : Typ.t) : bool =
let is_initializer_class typename _ =
List.mem ~equal:Typ.Name.equal initializer_classes typename
in
@ -236,7 +236,7 @@ let type_has_initializer (tenv: Tenv.t) (t: Typ.t) : bool =
(** Check if the method is one of the known initializer methods. *)
let method_is_initializer (tenv: Tenv.t) (proc_attributes: ProcAttributes.t) : bool =
let method_is_initializer (tenv : Tenv.t) (proc_attributes : ProcAttributes.t) : bool =
match get_this_type proc_attributes with
| Some this_type ->
if type_has_initializer tenv this_type then
@ -289,11 +289,10 @@ let proc_calls resolve_attributes pdesc filter : (Typ.Procname.t * ProcAttribute
Instrs.iter ~f:(do_instruction node) instrs
in
let nodes = Procdesc.get_nodes pdesc in
List.iter ~f:do_node nodes ;
List.rev !res
List.iter ~f:do_node nodes ; List.rev !res
let override_find ?(check_current_type= true) f tenv proc_name =
let override_find ?(check_current_type = true) f tenv proc_name =
let method_name = Typ.Procname.get_method proc_name in
let is_override pname =
(* Note: very coarse! TODO: match parameter names/types to get an exact match *)
@ -325,7 +324,7 @@ let override_find ?(check_current_type= true) f tenv proc_name =
None
let override_exists ?(check_current_type= true) f tenv proc_name =
let override_exists ?(check_current_type = true) f tenv proc_name =
override_find ~check_current_type f tenv proc_name |> Option.is_some

@ -50,12 +50,17 @@ val java_get_vararg_values : Procdesc.Node.t -> Pvar.t -> Idenv.t -> Exp.t list
(** Get the values of a vararg parameter given the pvar used to assign the elements. *)
val proc_calls :
(Typ.Procname.t -> ProcAttributes.t option) -> Procdesc.t
-> (Typ.Procname.t -> ProcAttributes.t -> bool) -> (Typ.Procname.t * ProcAttributes.t) list
(Typ.Procname.t -> ProcAttributes.t option)
-> Procdesc.t
-> (Typ.Procname.t -> ProcAttributes.t -> bool)
-> (Typ.Procname.t * ProcAttributes.t) list
(** Return the callees that satisfy [filter]. *)
val override_find :
?check_current_type:bool -> (Typ.Procname.t -> bool) -> Tenv.t -> Typ.Procname.t
?check_current_type:bool
-> (Typ.Procname.t -> bool)
-> Tenv.t
-> Typ.Procname.t
-> Typ.Procname.t option
(** Return a method which overrides [procname] and satisfies [f] (including [procname] itself when [check_current_type] is true, which it is by default). *)

@ -74,9 +74,8 @@ end
module InstrNode : sig
type instr_index = int
include Node
with type t = Procdesc.Node.t * instr_index
and type id = Procdesc.Node.id * instr_index
include
Node with type t = Procdesc.Node.t * instr_index and type id = Procdesc.Node.id * instr_index
end = struct
type instr_index = int [@@deriving compare]
@ -297,10 +296,8 @@ module Backward (Base : S with type instrs_dir = Instrs.not_reversed) = struct
end
module OneInstrPerNode (Base : S with module Node = DefaultNode) : sig
include S
with type t = Base.t
and module Node = InstrNode
and type instrs_dir = Instrs.not_reversed
include
S with type t = Base.t and module Node = InstrNode and type instrs_dir = Instrs.not_reversed
val last_of_underlying_node : Procdesc.Node.t -> Node.t
end = struct
@ -383,7 +380,7 @@ module MakeOcamlGraph (Base : S) = struct
let compare n1 n2 = Base.Node.compare_id (Base.Node.id n1) (Base.Node.id n2)
let equal = [%compare.equal : t]
let equal = [%compare.equal: t]
let hash = Base.Node.hash
end

@ -83,9 +83,8 @@ module DefaultNode : Node with type t = Procdesc.Node.t and type id = Procdesc.N
module InstrNode : sig
type instr_index
include Node
with type t = Procdesc.Node.t * instr_index
and type id = Procdesc.Node.id * instr_index
include
Node with type t = Procdesc.Node.t * instr_index and type id = Procdesc.Node.id * instr_index
end
(** Forward CFG with no exceptional control-flow *)
@ -107,10 +106,8 @@ module Backward (Base : S with type instrs_dir = Instrs.not_reversed) :
S with type t = Base.t and module Node = Base.Node and type instrs_dir = Instrs.reversed
module OneInstrPerNode (Base : S with module Node = DefaultNode) : sig
include S
with type t = Base.t
and module Node = InstrNode
and type instrs_dir = Instrs.not_reversed
include
S with type t = Base.t and module Node = InstrNode and type instrs_dir = Instrs.not_reversed
val last_of_underlying_node : Procdesc.Node.t -> Node.t
end

@ -85,6 +85,7 @@ module ReversePostorder (CFG : ProcCfg.S) = struct
(* TODO: could do this slightly more efficiently by keeping a list of priority zero nodes for
quick popping, and do a linear search only when this list is empty *)
(** remove and return the node with the highest priority (note that smaller integers have higher
priority), the ids of its visited predecessors, and new schedule *)
let pop t =

@ -28,11 +28,11 @@ end
module Make (P : Payload) : S with type t = P.t = struct
type t = P.t
let update_summary p (summary: Summary.t) =
let update_summary p (summary : Summary.t) =
{summary with payloads= P.update_payloads p summary.payloads}
let of_summary (summary: Summary.t) = P.of_payloads summary.payloads
let of_summary (summary : Summary.t) = P.of_payloads summary.payloads
let read caller_pdesc callee_pname =
Ondemand.analyze_proc_name ~caller_pdesc callee_pname |> Option.bind ~f:of_summary

@ -10,7 +10,7 @@ open Core
type t = Analyze | Capture | Compile | Diff | Events | Explore | Report | ReportDiff | Run
[@@deriving compare]
let equal = [%compare.equal : t]
let equal = [%compare.equal: t]
let command_to_string =
[ (Analyze, "analyze")

@ -3,8 +3,9 @@
let cflags = common_cflags @ ["-w"; "-27-32-34-35-39"]
;; Format.sprintf
{|
;;
Format.sprintf
{|
(library
(name InferGenerated)
(public_name InferGenerated)
@ -19,6 +20,6 @@ let cflags = common_cflags @ ["-w"; "-27-32-34-35-39"]
(mld_files index)
)
|}
(String.concat " " cflags)
(String.concat " " common_optflags)
|> Jbuild_plugin.V1.send
(String.concat " " cflags)
(String.concat " " common_optflags)
|> Jbuild_plugin.V1.send

@ -13,7 +13,7 @@ module LocListSet = struct
type t = Location.t list [@@deriving compare]
end)
let mem s xs = not (List.is_empty xs) && mem (List.sort ~compare:Location.compare xs) s
let mem s xs = (not (List.is_empty xs)) && mem (List.sort ~compare:Location.compare xs) s
let add s xs = if List.is_empty xs then s else add (List.sort ~compare:Location.compare xs) s
end
@ -23,7 +23,7 @@ let is_duplicate_report end_locs reported_ends =
let sort_by_decreasing_preference_to_report issues =
let compare (x: Jsonbug_t.jsonbug) (y: Jsonbug_t.jsonbug) =
let compare (x : Jsonbug_t.jsonbug) (y : Jsonbug_t.jsonbug) =
let n = Int.compare (List.length x.bug_trace) (List.length y.bug_trace) in
if n <> 0 then n
else
@ -34,15 +34,15 @@ let sort_by_decreasing_preference_to_report issues =
let sort_by_location issues =
let compare (x: Jsonbug_t.jsonbug) (y: Jsonbug_t.jsonbug) =
[%compare : string * int * int] (x.file, x.line, x.column) (y.file, y.line, y.column)
let compare (x : Jsonbug_t.jsonbug) (y : Jsonbug_t.jsonbug) =
[%compare: string * int * int] (x.file, x.line, x.column) (y.file, y.line, y.column)
in
List.sort ~compare issues
let dedup (issues: Jsonbug_t.jsonbug list) =
List.fold (sort_by_decreasing_preference_to_report issues) ~init:(LocListSet.empty, []) ~f:
(fun (reported_ends, nondup_issues) (issue: Jsonbug_t.jsonbug) ->
let dedup (issues : Jsonbug_t.jsonbug list) =
List.fold (sort_by_decreasing_preference_to_report issues) ~init:(LocListSet.empty, [])
~f:(fun (reported_ends, nondup_issues) (issue : Jsonbug_t.jsonbug) ->
match issue.access with
| Some encoded ->
let _, _, end_locs = IssueAuxData.decode encoded in
@ -72,7 +72,7 @@ end = struct
let count report =
let count_aux t (e: Jsonbug_t.extra) =
let count_aux t (e : Jsonbug_t.extra) =
match e with
| {cost_polynomial= Some cp} when String.equal cp zero_token_str ->
{t with zero= t.zero + 1}
@ -133,7 +133,7 @@ type t =
; costs_summary: Yojson.Basic.json }
(** Set operations should keep duplicated issues with identical hashes *)
let of_reports ~(current_report: Jsonbug_t.report) ~(previous_report: Jsonbug_t.report) : t =
let of_reports ~(current_report : Jsonbug_t.report) ~(previous_report : Jsonbug_t.report) : t =
let to_map report =
List.fold_left
~f:(fun map issue -> Map.add_multi map ~key:issue.Jsonbug_t.hash ~data:issue)

@ -13,7 +13,7 @@ module FileRenamings = struct
type t = renaming list [@@deriving compare]
let equal = [%compare.equal : t]
let equal = [%compare.equal: t]
let empty = []
@ -26,8 +26,7 @@ module FileRenamings = struct
let renaming_of_assoc assoc : renaming =
try
match assoc with
| `Assoc l
-> (
| `Assoc l -> (
let current_opt = List.Assoc.find ~equal:String.equal l "current" in
let previous_opt = List.Assoc.find ~equal:String.equal l "previous" in
match (current_opt, previous_opt) with
@ -59,7 +58,7 @@ module FileRenamings = struct
let from_json_file file : t = from_json (In_channel.read_all file)
let find_previous (t: t) current =
let find_previous (t : t) current =
let r = List.find ~f:(fun r -> String.equal current r.current) t in
Option.map ~f:(fun r -> r.previous) r
@ -83,7 +82,7 @@ end
(** Returns a triple [(l1', dups, l2')] where [dups] is the set of elements of that are in the
intersection of [l1] and [l2] according to [cmd] and additionally satisfy [pred], and [lN'] is
[lN] minus [dups]. [dups] contains only one witness for each removed issue, taken from [l1]. *)
let relative_complements ~compare ?(pred= fun _ -> true) l1 l2 =
let relative_complements ~compare ?(pred = fun _ -> true) l1 l2 =
let rec aux ((out_l1, dups, out_l2) as out) in_l1 in_l2 =
let is_last_seen_dup v =
match dups with ld :: _ -> Int.equal (compare ld v) 0 | [] -> false
@ -115,7 +114,7 @@ let relative_complements ~compare ?(pred= fun _ -> true) l1 l2 =
type issue_file_with_renaming = Jsonbug_t.jsonbug * string option
let skip_duplicated_types_on_filenames renamings (diff: Differential.t) : Differential.t =
let skip_duplicated_types_on_filenames renamings (diff : Differential.t) : Differential.t =
let compare_issue_file_with_renaming (issue1, previous_file1) (issue2, previous_file2) =
let f1, f2 =
( Option.value previous_file1 ~default:issue1.Jsonbug_t.file
@ -123,8 +122,9 @@ let skip_duplicated_types_on_filenames renamings (diff: Differential.t) : Differ
in
String.compare f1 f2
in
let compare ((issue1, _) as issue_with_previous_file1) ((issue2, _) as issue_with_previous_file2) =
[%compare : Caml.Digest.t * string * issue_file_with_renaming]
let compare ((issue1, _) as issue_with_previous_file1) ((issue2, _) as issue_with_previous_file2)
=
[%compare: Caml.Digest.t * string * issue_file_with_renaming]
(issue1.Jsonbug_t.node_key, issue1.Jsonbug_t.bug_type, issue_with_previous_file1)
(issue2.Jsonbug_t.node_key, issue2.Jsonbug_t.bug_type, issue_with_previous_file2)
in
@ -153,13 +153,13 @@ type file_extension = string [@@deriving compare]
type weak_hash = string * string * string * Caml.Digest.t [@@deriving compare]
(* Strip issues whose paths are not among those we're interested in *)
let interesting_paths_filter (interesting_paths: SourceFile.t list option) =
let interesting_paths_filter (interesting_paths : SourceFile.t list option) =
match interesting_paths with
| Some (paths: SourceFile.t list) ->
| Some (paths : SourceFile.t list) ->
let interesting_paths_set =
paths
|> List.filter_map ~f:(fun p ->
if not (SourceFile.is_invalid p) && SourceFile.is_under_project_root p then
if (not (SourceFile.is_invalid p)) && SourceFile.is_under_project_root p then
Some (SourceFile.to_string p)
else None )
|> String.Set.of_list
@ -172,8 +172,8 @@ let interesting_paths_filter (interesting_paths: SourceFile.t list option) =
Fn.id
let do_filter (diff: Differential.t) (renamings: FileRenamings.t) ~(skip_duplicated_types: bool)
~(interesting_paths: SourceFile.t list option) : Differential.t =
let do_filter (diff : Differential.t) (renamings : FileRenamings.t) ~(skip_duplicated_types : bool)
~(interesting_paths : SourceFile.t list option) : Differential.t =
let paths_filter = interesting_paths_filter interesting_paths in
let apply_paths_filter_if_needed label issues =
if List.exists ~f:(PolyVariantEqual.( = ) label) Config.differential_filter_set then

@ -30,12 +30,18 @@ module FileRenamings : sig
end
val do_filter :
Differential.t -> FileRenamings.t -> skip_duplicated_types:bool
-> interesting_paths:SourceFile.t list option -> Differential.t
Differential.t
-> FileRenamings.t
-> skip_duplicated_types:bool
-> interesting_paths:SourceFile.t list option
-> Differential.t
module VISIBLE_FOR_TESTING_DO_NOT_USE_DIRECTLY : sig
val relative_complements :
compare:('a -> 'a -> int) -> ?pred:('a -> bool) -> 'a list -> 'a list
compare:('a -> 'a -> int)
-> ?pred:('a -> bool)
-> 'a list
-> 'a list
-> 'a list * 'a list * 'a list
val skip_duplicated_types_on_filenames : FileRenamings.t -> Differential.t -> Differential.t

@ -8,6 +8,7 @@
(** Main module for the analysis after the capture phase *)
open! IStd
module L = Logging
let clear_caches () =
@ -84,7 +85,7 @@ let main ~changed_files =
let n_source_files = List.length source_files_to_analyze in
L.progress "Found %d%s source file%s to analyze in %s@." n_source_files
( if Config.reactive_mode || Option.is_some changed_files then
" (out of " ^ string_of_int (List.length all_source_files) ^ ")"
" (out of " ^ string_of_int (List.length all_source_files) ^ ")"
else "" )
(if Int.equal n_source_files 1 then "" else "s")
Config.results_dir ;

@ -43,14 +43,14 @@ let error_desc_to_plain_string error_desc =
let error_desc_to_dotty_string error_desc = Localise.error_desc_get_dotty error_desc
let compute_key (bug_type: string) (proc_name: Typ.Procname.t) (filename: string) =
let compute_key (bug_type : string) (proc_name : Typ.Procname.t) (filename : string) =
let base_filename = Filename.basename filename
and simple_procedure_name = Typ.Procname.get_method proc_name in
String.concat ~sep:"|" [base_filename; simple_procedure_name; bug_type]
let compute_hash (severity: string) (bug_type: string) (proc_name: Typ.Procname.t)
(filename: string) (qualifier: string) =
let compute_hash (severity : string) (bug_type : string) (proc_name : Typ.Procname.t)
(filename : string) (qualifier : string) =
let base_filename = Filename.basename filename in
let hashable_procedure_name = Typ.Procname.hashable_name proc_name in
let location_independent_qualifier =
@ -161,8 +161,8 @@ module ProcsCsv = struct
pp "%s@\n" sv.vproof_trace
end
let should_report (issue_kind: Exceptions.severity) issue_type error_desc eclass =
if not Config.filtering || Exceptions.equal_err_class eclass Exceptions.Linters then true
let should_report (issue_kind : Exceptions.severity) issue_type error_desc eclass =
if (not Config.filtering) || Exceptions.equal_err_class eclass Exceptions.Linters then true
else
let issue_kind_is_blacklisted =
match issue_kind with Info -> true | Advice | Error | Like | Warning -> false
@ -187,12 +187,13 @@ let should_report (issue_kind: Exceptions.severity) issue_type error_desc eclass
(* 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. *)
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 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 =
(* 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)))
|| Bool.equal filename_polarity (Str.string_match filename_re filename 0)
in
Option.some_if (not accepted) reason
@ -216,9 +217,7 @@ module MakeJsonListPrinter (P : sig
type elt
val to_string : elt -> string option
end) :
Printer with type elt = P.elt =
struct
end) : Printer with type elt = P.elt = struct
include P
let is_first_item = ref true
@ -249,7 +248,7 @@ type json_issue_printer_typ =
module JsonIssuePrinter = MakeJsonListPrinter (struct
type elt = json_issue_printer_typ
let to_string ({error_filter; proc_name; proc_loc_opt; err_key; err_data}: elt) =
let to_string ({error_filter; proc_name; proc_loc_opt; err_key; err_data} : elt) =
let source_file, procedure_start_line =
match proc_loc_opt with
| Some proc_loc ->
@ -262,10 +261,11 @@ module JsonIssuePrinter = MakeJsonListPrinter (struct
"Invalid source file for %a %a@.Trace: %a@." IssueType.pp err_key.err_name
Localise.pp_error_desc err_key.err_desc Errlog.pp_loc_trace err_data.loc_trace ;
let should_report_source_file =
not (SourceFile.is_infer_model source_file) || Config.debug_mode || Config.debug_exceptions
(not (SourceFile.is_infer_model source_file)) || Config.debug_mode || Config.debug_exceptions
in
if
err_key.in_footprint && error_filter source_file err_key.err_name
err_key.in_footprint
&& error_filter source_file err_key.err_name
&& should_report_source_file
&& should_report err_key.severity err_key.err_name err_key.err_desc err_data.err_class
then
@ -364,7 +364,7 @@ module JsonCostsPrinter = MakeJsonListPrinter (struct
end)
let pp_custom_of_report fmt report fields =
let pp_custom_of_issue fmt (issue: Jsonbug_t.jsonbug) =
let pp_custom_of_issue fmt (issue : Jsonbug_t.jsonbug) =
let open Jsonbug_t in
let comma_separator index = if index > 0 then ", " else "" in
let pp_trace fmt trace comma =
@ -383,7 +383,8 @@ let pp_custom_of_report fmt report fields =
| `Issue_field_bucket ->
let bucket =
match
String.lsplit2 issue.qualifier ~on:']' |> Option.map ~f:fst
String.lsplit2 issue.qualifier ~on:']'
|> Option.map ~f:fst
|> Option.bind ~f:(String.chop_prefix ~prefix:"[")
with
| Some bucket ->
@ -428,13 +429,13 @@ let pp_custom_of_report fmt report fields =
let tests_jsonbug_compare bug1 bug2 =
let open Jsonbug_t in
[%compare : string * string * int * string * Caml.Digest.t]
[%compare: string * string * int * string * Caml.Digest.t]
(bug1.file, bug1.procedure, bug1.line - bug1.procedure_start_line, bug1.bug_type, bug1.hash)
(bug2.file, bug2.procedure, bug2.line - bug2.procedure_start_line, bug2.bug_type, bug2.hash)
module IssuesTxt = struct
let pp_issue fmt error_filter proc_loc_opt (key: Errlog.err_key) (err_data: Errlog.err_data) =
let pp_issue fmt error_filter proc_loc_opt (key : Errlog.err_key) (err_data : Errlog.err_data) =
let source_file =
match proc_loc_opt with
| Some proc_loc ->
@ -443,8 +444,9 @@ module IssuesTxt = struct
err_data.loc.Location.file
in
if
key.in_footprint && error_filter source_file key.err_name
&& (not Config.filtering || String.is_empty (censored_reason key.err_name source_file))
key.in_footprint
&& error_filter source_file key.err_name
&& ((not Config.filtering) || String.is_empty (censored_reason key.err_name source_file))
then Exceptions.pp_err err_data.loc key.severity key.err_name key.err_desc None fmt ()
@ -503,7 +505,9 @@ module Stats = struct
let res = ref [] in
let indent_string n =
let s = ref "" in
for _ = 1 to n do s := " " ^ !s done ;
for _ = 1 to n do
s := " " ^ !s
done ;
!s
in
let num = ref 0 in
@ -525,13 +529,12 @@ module Stats = struct
in
res := line :: "" :: !res
in
List.iter ~f:loc_to_string ltr ;
List.rev !res
List.iter ~f:loc_to_string ltr ; List.rev !res
let process_err_log error_filter linereader err_log stats =
let found_errors = ref false in
let process_row (key: Errlog.err_key) (err_data: Errlog.err_data) =
let process_row (key : Errlog.err_key) (err_data : Errlog.err_data) =
let type_str = key.err_name.IssueType.unique_id in
if key.in_footprint && error_filter key.err_name then
match key.severity with
@ -604,7 +607,7 @@ module Stats = struct
end
module StatsLogs = struct
let process _ (summary: Summary.t) _ _ =
let process _ (summary : Summary.t) _ _ =
let num_preposts =
match summary.payloads.biabduction with Some {preposts} -> List.length preposts | None -> 0
in
@ -681,7 +684,7 @@ module Issue = struct
type err_data_ = Errlog.err_data
(* no derived compare for err_data; just compare the locations *)
let compare_err_data_ (err_data1: Errlog.err_data) (err_data2: Errlog.err_data) =
let compare_err_data_ (err_data1 : Errlog.err_data) (err_data2 : Errlog.err_data) =
Location.compare err_data1.loc err_data2.loc
@ -701,15 +704,16 @@ module Issue = struct
let sort_filter_issues issues =
let issues' = List.dedup_and_sort ~compare issues in
( if Config.developer_mode then
let num_pruned_issues = List.length issues - List.length issues' in
if num_pruned_issues > 0 then
L.user_warning "Note: pruned %d duplicate issues@\n" num_pruned_issues ) ;
let num_pruned_issues = List.length issues - List.length issues' in
if num_pruned_issues > 0 then
L.user_warning "Note: pruned %d duplicate issues@\n" num_pruned_issues ) ;
issues'
end
let error_filter filters proc_name file error_name =
(Config.write_html || not (IssueType.(equal skip_function) error_name))
&& filters.Inferconfig.path_filter file && filters.Inferconfig.error_filter error_name
&& filters.Inferconfig.path_filter file
&& filters.Inferconfig.error_filter error_name
&& filters.Inferconfig.proc_filter proc_name
@ -751,7 +755,7 @@ let get_outfile outfile =
L.(die InternalError) "An outfile is require for this format."
let pp_issue_in_format (format_kind, (outfile_opt: Utils.outfile option)) error_filter
let pp_issue_in_format (format_kind, (outfile_opt : Utils.outfile option)) error_filter
{Issue.proc_name; proc_location; err_key; err_data} =
match format_kind with
| Json ->
@ -769,7 +773,7 @@ let pp_issue_in_format (format_kind, (outfile_opt: Utils.outfile option)) error_
IssuesTxt.pp_issue outf.fmt error_filter (Some proc_location) err_key err_data
let pp_issues_in_format (format_kind, (outfile_opt: Utils.outfile option)) =
let pp_issues_in_format (format_kind, (outfile_opt : Utils.outfile option)) =
match format_kind with
| Json ->
let outf = get_outfile outfile_opt in
@ -785,7 +789,7 @@ let pp_issues_in_format (format_kind, (outfile_opt: Utils.outfile option)) =
IssuesTxt.pp_issues_of_error_log outf.fmt
let pp_procs_in_format (format_kind, (outfile_opt: Utils.outfile option)) =
let pp_procs_in_format (format_kind, (outfile_opt : Utils.outfile option)) =
match format_kind with
| Csv ->
let outf = get_outfile outfile_opt in
@ -841,7 +845,7 @@ let pp_summary summary =
summary
let pp_costs_in_format (format_kind, (outfile_opt: Utils.outfile option)) =
let pp_costs_in_format (format_kind, (outfile_opt : Utils.outfile option)) =
match format_kind with
| Json ->
let outf = get_outfile outfile_opt in
@ -883,7 +887,7 @@ let pp_json_report_by_report_kind formats_by_report_kind fname =
match Utils.read_file fname with
| Ok report_lines ->
let pp_json_issues format_list report =
let pp_json_issue (format_kind, (outfile_opt: Utils.outfile option)) =
let pp_json_issue (format_kind, (outfile_opt : Utils.outfile option)) =
match format_kind with
| Tests ->
let outf = get_outfile outfile_opt in
@ -916,7 +920,8 @@ let pp_json_report_by_report_kind formats_by_report_kind fname =
L.(die UserError) "Error reading '%s': %s" fname error
let pp_lint_issues_by_report_kind formats_by_report_kind error_filter linereader procname error_log =
let pp_lint_issues_by_report_kind formats_by_report_kind error_filter linereader procname error_log
=
let pp_summary_by_report_kind (report_kind, format_list) =
match (report_kind, format_list) with
| Issues, _ :: _ ->
@ -955,7 +960,7 @@ let spec_files_from_cmdline () =
files may be generated between init and report time. *)
List.iter
~f:(fun arg ->
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") )
Config.anon_args ;
if Config.test_filtering then ( Inferconfig.test () ; L.exit 0 ) ;
@ -1002,7 +1007,7 @@ let init_stats_format_list () =
let init_files format_list_by_kind =
let init_files_of_report_kind (report_kind, format_list) =
let init_files_of_format (format_kind, (outfile_opt: Utils.outfile option)) =
let init_files_of_format (format_kind, (outfile_opt : Utils.outfile option)) =
match (format_kind, report_kind) with
| Csv, Issues ->
L.(die InternalError) "Printing issues in a CSV format is not implemented"
@ -1032,9 +1037,9 @@ let init_files format_list_by_kind =
List.iter ~f:init_files_of_report_kind format_list_by_kind
let finalize_and_close_files format_list_by_kind (stats: Stats.t) =
let finalize_and_close_files format_list_by_kind (stats : Stats.t) =
let close_files_of_report_kind (report_kind, format_list) =
let close_files_of_format (format_kind, (outfile_opt: Utils.outfile option)) =
let close_files_of_format (format_kind, (outfile_opt : Utils.outfile option)) =
( match (format_kind, report_kind) with
| Logs, (Issues | Procs | Summary) ->
L.(die InternalError) "Logging these reports is not implemented"

@ -12,40 +12,39 @@ let compilation_db = lazy (CompilationDatabase.from_json_files !Config.clang_com
(** Given proc_attributes try to produce proc_attributes' where proc_attributes'.is_defined = true
It may trigger capture of extra files to do so and when it does, it waits for
frontend to finish before returning *)
let try_capture (attributes: ProcAttributes.t) : ProcAttributes.t option =
let lazy cdb = compilation_db in
let try_capture (attributes : ProcAttributes.t) : ProcAttributes.t option =
let (lazy cdb) = compilation_db in
( if Option.is_none (Attributes.load_defined attributes.proc_name) then
let decl_file = attributes.loc.file in
let definition_file_opt = SourceFile.of_header decl_file in
let try_compile definition_file =
(* Use the cfg as a proxy to find out whether definition_file was already captured. If it
let decl_file = attributes.loc.file in
let definition_file_opt = SourceFile.of_header decl_file in
let try_compile definition_file =
(* Use the cfg as a proxy to find out whether definition_file was already captured. If it
was, there is no point in trying to capture it again. Treat existance of the cfg as a
barrier - if it exists it means that all attributes files have been created - write logic
is defined in Cfg.store *)
if not (SourceFiles.is_captured decl_file) then (
L.(debug Capture Verbose) "Started capture of %a...@\n" SourceFile.pp definition_file ;
Timeout.suspend_existing_timeout ~keep_symop_total:true ;
protect
~f:(fun () -> CaptureCompilationDatabase.capture_file_in_database cdb definition_file)
~finally:Timeout.resume_previous_timeout ;
if Config.debug_mode && Option.is_none (Attributes.load_defined attributes.proc_name)
then
(* peek at the results to know if capture succeeded, but only in debug mode *)
L.(debug Capture Verbose)
"Captured file %a to get procedure %a but it wasn't found there@\n" SourceFile.pp
definition_file Typ.Procname.pp attributes.proc_name )
else
if not (SourceFiles.is_captured decl_file) then (
L.(debug Capture Verbose) "Started capture of %a...@\n" SourceFile.pp definition_file ;
Timeout.suspend_existing_timeout ~keep_symop_total:true ;
protect
~f:(fun () -> CaptureCompilationDatabase.capture_file_in_database cdb definition_file)
~finally:Timeout.resume_previous_timeout ;
if Config.debug_mode && Option.is_none (Attributes.load_defined attributes.proc_name) then
(* peek at the results to know if capture succeeded, but only in debug mode *)
L.(debug Capture Verbose)
"Wanted to capture file %a to get procedure %a but file was already captured@\n"
SourceFile.pp definition_file Typ.Procname.pp attributes.proc_name
in
match definition_file_opt with
| None ->
L.(debug Capture Medium)
"Couldn't find source file for %a (declared in %a)@\n" Typ.Procname.pp
attributes.proc_name SourceFile.pp decl_file
| Some file ->
try_compile file ) ;
"Captured file %a to get procedure %a but it wasn't found there@\n" SourceFile.pp
definition_file Typ.Procname.pp attributes.proc_name )
else
L.(debug Capture Verbose)
"Wanted to capture file %a to get procedure %a but file was already captured@\n"
SourceFile.pp definition_file Typ.Procname.pp attributes.proc_name
in
match definition_file_opt with
| None ->
L.(debug Capture Medium)
"Couldn't find source file for %a (declared in %a)@\n" Typ.Procname.pp
attributes.proc_name SourceFile.pp decl_file
| Some file ->
try_compile file ) ;
(* It's important to call load_defined_attributes again in all cases to make sure we try
reading from disk again no matter which condition happened. If previous call to
load_defined_attributes is None, it may mean couple of things:

@ -266,7 +266,7 @@ let compute_mem_stats () =
(stats, mem)
let compute_time_stats ?rtime_counter (initial_times: Unix.process_times) =
let compute_time_stats ?rtime_counter (initial_times : Unix.process_times) =
let exit_times = Unix.times () in
let rtime_span = Mtime_clock.elapsed () in
let rtime =

@ -10,8 +10,8 @@ module F = Format
let get_all ~filter () =
let db = ResultsDatabase.get_database () in
let stmt = Sqlite3.prepare db "SELECT source_file, proc_name FROM procedures" in
SqliteUtils.result_fold_rows db ~log:"reading all procedure names" stmt ~init:[] ~f:
(fun rev_results stmt ->
SqliteUtils.result_fold_rows db ~log:"reading all procedure names" stmt ~init:[]
~f:(fun rev_results stmt ->
let source_file = Sqlite3.column stmt 0 |> SourceFile.SQLite.deserialize in
let proc_name = Sqlite3.column stmt 1 |> Typ.Procname.SQLite.deserialize in
if filter source_file proc_name then proc_name :: rev_results else rev_results )
@ -20,7 +20,7 @@ let get_all ~filter () =
let pp_all ~filter ~proc_name:proc_name_cond ~attr_kind ~source_file:source_file_cond
~proc_attributes fmt () =
let db = ResultsDatabase.get_database () in
let pp_if ?(new_line= false) condition title pp fmt x =
let pp_if ?(new_line = false) condition title pp fmt x =
if condition then (
if new_line then F.fprintf fmt "@[<v2>" else F.fprintf fmt "@[<h>" ;
F.fprintf fmt "%s:@ %a@]@;" title pp x )
@ -31,7 +31,7 @@ let pp_all ~filter ~proc_name:proc_name_cond ~attr_kind ~source_file:source_file
pp_if ?new_line condition title pp fmt (Sqlite3.column stmt column |> deserialize)
in
let pp_row stmt fmt source_file proc_name =
let[@warning "-8"] Sqlite3.Data.TEXT proc_name_hum = Sqlite3.column stmt 1 in
let[@warning "-8"] (Sqlite3.Data.TEXT proc_name_hum) = Sqlite3.column stmt 1 in
Format.fprintf fmt "@[<v2>%s@,%a%a%a%a@]@\n" proc_name_hum
(pp_if source_file_cond "source_file" SourceFile.pp)
source_file
@ -47,8 +47,8 @@ let pp_all ~filter ~proc_name:proc_name_cond ~attr_kind ~source_file:source_file
(* we could also register this statement but it's typically used only once per run so just prepare
it inside the function *)
Sqlite3.prepare db "SELECT * FROM procedures"
|> Container.iter ~fold:(SqliteUtils.result_fold_rows db ~log:"print all procedures") ~f:
(fun stmt ->
|> Container.iter ~fold:(SqliteUtils.result_fold_rows db ~log:"print all procedures")
~f:(fun stmt ->
let proc_name = Sqlite3.column stmt 0 |> Typ.Procname.SQLite.deserialize in
let source_file = Sqlite3.column stmt 3 |> SourceFile.SQLite.deserialize in
if filter source_file proc_name then pp_row stmt fmt source_file proc_name )

@ -10,5 +10,11 @@ open! IStd
val get_all : filter:Filtering.procedures_filter -> unit -> Typ.Procname.t list
val pp_all :
filter:Filtering.procedures_filter -> proc_name:bool -> attr_kind:bool -> source_file:bool
-> proc_attributes:bool -> Format.formatter -> unit -> unit
filter:Filtering.procedures_filter
-> proc_name:bool
-> attr_kind:bool
-> source_file:bool
-> proc_attributes:bool
-> Format.formatter
-> unit
-> unit

@ -14,8 +14,11 @@ let aggregated_stats_by_target_filename = "aggregated_stats_by_target.json"
let json_files_to_ignore_regex =
Str.regexp
( ".*\\(" ^ Str.quote aggregated_stats_filename ^ "\\|"
^ Str.quote aggregated_stats_by_target_filename ^ "\\)$" )
( ".*\\("
^ Str.quote aggregated_stats_filename
^ "\\|"
^ Str.quote aggregated_stats_by_target_filename
^ "\\)$" )
let dir_exists dir = Sys.is_directory dir = `Yes
@ -24,7 +27,8 @@ let find_json_files_in_dir dir =
let is_valid_json_file path =
let s = Unix.lstat path in
let json_regex = Str.regexp_case_fold ".*\\.json$" in
not (Str.string_match json_files_to_ignore_regex path 0) && Str.string_match json_regex path 0
(not (Str.string_match json_files_to_ignore_regex path 0))
&& Str.string_match json_regex path 0
&& Polymorphic_compare.( = ) s.st_kind Unix.S_REG
in
match dir_exists dir with
@ -63,7 +67,8 @@ let load_data_from_infer_deps file =
Error (error "malformed input")
in
let parse_lines lines = List.map lines ~f:extract_target_and_path |> Result.all in
Utils.read_file file |> Result.map_error ~f:(fun msg -> error "%s" msg)
Utils.read_file file
|> Result.map_error ~f:(fun msg -> error "%s" msg)
|> Result.bind ~f:parse_lines

@ -36,7 +36,7 @@ module Stats = struct
let nb_visited_re {nodes_visited_re} = IntSet.cardinal nodes_visited_re
let update ?(add_symops= 0) ?failure_kind stats =
let update ?(add_symops = 0) ?failure_kind stats =
let symops = stats.symops + add_symops in
let failure_kind = match failure_kind with None -> stats.failure_kind | some -> some in
{stats with symops; failure_kind}
@ -139,7 +139,7 @@ let pp_html source color fmt summary =
(** Add the summary to the table for the given function *)
let add (proc_name: Typ.Procname.t) (summary: t) : unit =
let add (proc_name : Typ.Procname.t) (summary : t) : unit =
Typ.Procname.Hash.replace cache proc_name summary
@ -228,7 +228,7 @@ let proc_resolve_attributes proc_name =
(** Save summary for the procedure into the spec database *)
let store (summ: t) =
let store (summ : t) =
let final_summary = {summ with status= Status.Analyzed} in
let proc_name = get_proc_name final_summary in
(* Make sure the summary in memory is identical to the saved one *)

@ -10,7 +10,7 @@ module L = Logging
type 'a doer = 'a -> unit
let run_sequentially ~(f: 'a doer) (tasks: 'a list) : unit =
let run_sequentially ~(f : 'a doer) (tasks : 'a list) : unit =
let task_bar = TaskBar.create ~jobs:1 in
(ProcessPoolState.update_status :=
fun t status ->

@ -32,11 +32,11 @@ let procedure_callbacks = ref []
let cluster_callbacks = ref []
let register_procedure_callback ?(dynamic_dispatch= false) language (callback: proc_callback_t) =
let register_procedure_callback ?(dynamic_dispatch = false) language (callback : proc_callback_t) =
procedure_callbacks := {dynamic_dispatch; language; callback} :: !procedure_callbacks
let register_cluster_callback language (callback: cluster_callback_t) =
let register_cluster_callback language (callback : cluster_callback_t) =
cluster_callbacks := {language; callback} :: !cluster_callbacks
@ -88,7 +88,7 @@ let iterate_cluster_callbacks all_procs exe_env source_file =
!cluster_callbacks
let dump_duplicate_procs (exe_env: Exe_env.t) source_file procs =
let dump_duplicate_procs (exe_env : Exe_env.t) source_file procs =
let duplicate_procs =
List.filter_map procs ~f:(fun pname ->
match Exe_env.get_proc_desc exe_env pname with
@ -96,7 +96,7 @@ let dump_duplicate_procs (exe_env: Exe_env.t) source_file procs =
match Attributes.load pname with
| Some {translation_unit; loc}
when (* defined in another file *)
not (SourceFile.equal source_file translation_unit)
(not (SourceFile.equal source_file translation_unit))
&& (* really defined in the current file and not in an include *)
SourceFile.equal source_file loc.file ->
Some (pname, translation_unit)
@ -122,7 +122,7 @@ let create_perf_stats_report source_file =
(** Invoke all procedure and cluster callbacks on a given environment. *)
let analyze_file (exe_env: Exe_env.t) source_file =
let analyze_file (exe_env : Exe_env.t) source_file =
let saved_language = !Language.curr_language in
let analyze_ondemand summary proc_desc = iterate_procedure_callbacks exe_env summary proc_desc in
(* Invoke procedure callbacks using on-demand analysis schedulling *)

@ -24,9 +24,7 @@ type proc_callback_args =
type proc_callback_t = proc_callback_args -> Summary.t
type cluster_callback_args =
{ procedures: (Tenv.t * Procdesc.t) list
; source_file: SourceFile.t
; exe_env: Exe_env.t }
{procedures: (Tenv.t * Procdesc.t) list; source_file: SourceFile.t; exe_env: Exe_env.t}
type cluster_callback_t = cluster_callback_args -> unit

@ -74,7 +74,8 @@ let collect_all_summaries root_summaries_dir stacktrace_file stacktraces_dir =
(fun summaries path ->
(* check if the file is a JSON file under the crashcontext dir *)
if
Sys.is_directory path <> `Yes && Filename.check_suffix path "json"
Sys.is_directory path <> `Yes
&& Filename.check_suffix path "json"
&& String.is_suffix ~suffix:"crashcontext" (Filename.dirname path)
then path :: summaries
else summaries )
@ -86,14 +87,15 @@ let collect_all_summaries root_summaries_dir stacktrace_file stacktraces_dir =
None
| Some file ->
let crashcontext_dir = Config.results_dir ^/ "crashcontext" in
Utils.create_dir crashcontext_dir ; Some (file, crashcontext_dir ^/ "crashcontext.json")
Utils.create_dir crashcontext_dir ;
Some (file, crashcontext_dir ^/ "crashcontext.json")
in
let trace_file_regexp = Str.regexp "\\(.*\\)\\.json" in
let pairs_for_stactrace_dir =
match stacktraces_dir with
| None ->
[]
| Some s ->
| Some s -> (
let dir = DB.filename_from_string s in
let trace_file_matcher path =
let path_str = DB.filename_to_string path in
@ -110,7 +112,7 @@ let collect_all_summaries root_summaries_dir stacktrace_file stacktraces_dir =
DB.fold_paths_matching statement below, so we don't need to
call Str.string_match again. *)
| Caml.Not_found
-> assert false
-> assert false )
in
let input_output_file_pairs =
match pair_for_stacktrace_file with

@ -45,7 +45,7 @@ type link =
{kind: kind_of_links; src: coordinate; src_fld: string; trg: coordinate; trg_fld: string}
[@@deriving compare]
let equal_link = [%compare.equal : link]
let equal_link = [%compare.equal: link]
(* type of the visualized boxes/nodes in the graph*)
type dotty_node =
@ -247,7 +247,7 @@ let reset_proposition_counter () = proposition_counter := 0
let reset_dotty_spec_counter () = spec_counter := 0
let color_to_str (c: Pp.color) =
let color_to_str (c : Pp.color) =
match c with
| Black ->
"black"
@ -261,8 +261,8 @@ let color_to_str (c: Pp.color) =
"red"
let make_dangling_boxes pe allocated_nodes (sigma_lambda: (Sil.hpred * int) list) =
let exp_color hpred (exp: Exp.t) =
let make_dangling_boxes pe allocated_nodes (sigma_lambda : (Sil.hpred * int) list) =
let exp_color hpred (exp : Exp.t) =
if Pp.equal_color (pe.Pp.cmap_norm (Obj.repr hpred)) Pp.Red then Pp.Red
else pe.Pp.cmap_norm (Obj.repr exp)
in
@ -271,7 +271,8 @@ let make_dangling_boxes pe allocated_nodes (sigma_lambda: (Sil.hpred * int) list
incr dotty_state_count ;
let coo = mk_coordinate n lambda in
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
[Dotdangling (coo, e, e_color_str)]
| Sil.Hlseg (_, _, _, e2, _) when not (Exp.equal e2 Exp.zero) ->
@ -370,7 +371,7 @@ let rec dotty_mk_node pe sigma =
| [] ->
[]
| (hpred, lambda) :: sigma' ->
let exp_color (exp: Exp.t) =
let exp_color (exp : Exp.t) =
if Pp.equal_color (pe.Pp.cmap_norm (Obj.repr hpred)) Pp.Red then Pp.Red
else pe.Pp.cmap_norm (Obj.repr exp)
in
@ -474,8 +475,7 @@ let node_in_cycle cycle node =
let rec compute_target_struct_fields dotnodes list_fld p f lambda cycle =
let find_target_one_fld (fn, se) =
match se with
| Sil.Eexp (e, _)
-> (
| Sil.Eexp (e, _) -> (
if is_nil e p then
let n' = make_nil_node lambda in
if !print_full_prop then [(LinkStructToExp, Typ.Fieldname.to_string fn, n', "")] else []
@ -520,8 +520,7 @@ let rec compute_target_struct_fields dotnodes list_fld p f lambda cycle =
let rec compute_target_array_elements dotnodes list_elements p f lambda =
let find_target_one_element (idx, se) =
match se with
| Sil.Eexp (e, _)
-> (
| Sil.Eexp (e, _) -> (
if is_nil e p then
let n' = make_nil_node lambda in
[(LinkArrayToExp, Exp.to_string idx, n', "")]
@ -598,15 +597,14 @@ let rec dotty_mk_set_links dotnodes sigma p f cycle =
let lnk =
mk_link LinkToArray (mk_coordinate n lambda) "" (mk_coordinate (n + 1) lambda) trg_label
in
lnk :: links_from_elements @ dotty_mk_set_links dotnodes sigma' p f cycle
(lnk :: links_from_elements) @ dotty_mk_set_links dotnodes sigma' p f cycle
in
match sigma with
| [] ->
[]
| (Sil.Hpointsto (e, Sil.Earray (_, lie, _), _), lambda) :: sigma' ->
make_links_for_arrays e lie lambda sigma'
| (Sil.Hpointsto (e, Sil.Estruct (lfld, _), _), lambda) :: sigma'
-> (
| (Sil.Hpointsto (e, Sil.Estruct (lfld, _), _), lambda) :: sigma' -> (
let src = look_up dotnodes e lambda in
match src with
| [] ->
@ -639,8 +637,7 @@ let rec dotty_mk_set_links dotnodes sigma p f cycle =
in
lnk_from_address_struct @ links_from_fields
@ 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
match src with
| [] ->
@ -658,8 +655,7 @@ let rec dotty_mk_set_links dotnodes sigma p f cycle =
let ll = List.concat_map ~f:ff nl in
ll @ dotty_mk_set_links dotnodes sigma' p f cycle
else dotty_mk_set_links dotnodes sigma' p f cycle )
| (Sil.Hlseg (_, _, e1, e2, _), lambda) :: sigma'
-> (
| (Sil.Hlseg (_, _, e1, e2, _), lambda) :: sigma' -> (
let src = look_up dotnodes e1 lambda in
match src with
| [] ->
@ -670,7 +666,7 @@ let rec dotty_mk_set_links dotnodes sigma p f cycle =
mk_link LinkToSSL (mk_coordinate (n + 1) lambda) "" (mk_coordinate m lambda) lab
in
lnk :: dotty_mk_set_links dotnodes sigma' p f cycle )
| (Sil.Hdllseg (_, _, e1, e2, e3, _, _), lambda) :: sigma' ->
| (Sil.Hdllseg (_, _, e1, e2, e3, _, _), lambda) :: sigma' -> (
let src = look_up dotnodes e1 lambda in
match src with
| [] ->
@ -693,7 +689,7 @@ let rec dotty_mk_set_links dotnodes sigma p f cycle =
| m :: _ ->
[mk_link LinkToDLL (mk_coordinate n lambda) "" (mk_coordinate m lambda) ""]
in
target_Blink @ target_Flink @ dotty_mk_set_links dotnodes sigma' p f cycle
target_Blink @ target_Flink @ dotty_mk_set_links dotnodes sigma' p f cycle )
let print_kind f kind =
@ -709,7 +705,7 @@ let print_kind f kind =
F.fprintf f "@\n POST%iL0 [label=\"POST %i \", style=filled, color= yellow]@\n"
!dotty_state_count !post_counter ;
print_stack_info := true
| Lambda_pred (no, lev, array) ->
| Lambda_pred (no, lev, array) -> (
match array with
| false ->
F.fprintf f "%s @\n state%iL%i [label=\"INTERNAL STRUCTURE %i \", %s]@\n"
@ -723,7 +719,7 @@ let print_kind f kind =
"style=filled, color= lightblue" ;
(* F.fprintf f "state%iL%i -> struct%iL%i:%s [color=\"lightblue \" arrowhead=none] @\n"
!dotty_state_count !lambda_counter no lev lab;*)
incr dotty_state_count
incr dotty_state_count )
(* print a link between two nodes in the graph *)
@ -764,7 +760,7 @@ let dotty_pp_link f link =
(* given the list of nodes and links get rid of spec nodes that are not pointed to by anybody*)
let filter_useless_spec_dollar_box (nodes: dotty_node list) (links: link list) =
let filter_useless_spec_dollar_box (nodes : dotty_node list) (links : link list) =
let tmp_nodes = ref nodes in
let tmp_links = ref links in
let remove_links_from ln =
@ -825,8 +821,7 @@ let filter_useless_spec_dollar_box (nodes: dotty_node list) (links: link list) =
let rec print_struct f pe e te l coo c =
let print_type =
match te with
| Exp.Sizeof {typ}
-> (
| Exp.Sizeof {typ} -> (
let str_t = Typ.to_string typ in
match Str.split_delim (Str.regexp_string Config.anonymous_block_prefix) str_t with
| [_; _] ->
@ -887,7 +882,8 @@ and print_sll f pe nesting k e1 coo =
F.fprintf f "state%iL%i [label=\" \"] @\n" (n + 1) lambda ;
F.fprintf f "state%iL%i -> state%iL%i [label=\" \"] }" n' lambda (n + 1) lambda ;
incr lambda_counter ;
pp_dotty f (Lambda_pred (n + 1, lambda, false))
pp_dotty f
(Lambda_pred (n + 1, lambda, false))
(Prop.normalize (Tenv.create ()) (Prop.from_sigma nesting))
None
@ -914,7 +910,8 @@ and print_dll f pe nesting k e1 e4 coo =
F.fprintf f "state%iL%i -> state%iL%i [label=\" \"]@\n" (n + 1) lambda n' lambda ;
F.fprintf f "state%iL%i -> state%iL%i [label=\" \"]}@\n" n' lambda (n + 1) lambda ;
incr lambda_counter ;
pp_dotty f (Lambda_pred (n', lambda, false))
pp_dotty f
(Lambda_pred (n', lambda, false))
(Prop.normalize (Tenv.create ()) (Prop.from_sigma nesting))
None
@ -997,7 +994,7 @@ and display_pure_info f pe prop =
(** Pretty print a proposition in dotty format. *)
and pp_dotty f kind (prop_: Prop.normal Prop.t) cycle =
and pp_dotty f kind (prop_ : Prop.normal Prop.t) cycle =
incr proposition_counter ;
let pe, prop =
match kind with
@ -1068,7 +1065,7 @@ let pp_dotty_one_spec f pre posts =
(********** Print control flow graph (in dot form) for fundec to channel. You have to compute an
interprocedural cfg first. *)
let pp_cfgnodename pname fmt (n: Procdesc.Node.t) =
let pp_cfgnodename pname fmt (n : Procdesc.Node.t) =
F.fprintf fmt "\"%s_%d\""
(Escape.escape_dotty (Typ.Procname.to_filename pname))
(Procdesc.Node.get_id n :> int)
@ -1092,7 +1089,7 @@ let pp_var_list fmt etl =
let pp_local_list fmt etl = List.iter ~f:(Procdesc.pp_local fmt) etl
let pp_cfgnodelabel pdesc fmt (n: Procdesc.Node.t) =
let pp_cfgnodelabel pdesc fmt (n : Procdesc.Node.t) =
let pp_label fmt n =
match Procdesc.Node.get_kind n with
| Procdesc.Node.Start_node pname ->
@ -1129,7 +1126,7 @@ let pp_cfgnodelabel pdesc fmt (n: Procdesc.Node.t) =
F.fprintf fmt "%d: %a \\n %a" (Procdesc.Node.get_id n :> int) pp_label n pp_instrs instrs
let pp_cfgnodeshape fmt (n: Procdesc.Node.t) =
let pp_cfgnodeshape fmt (n : Procdesc.Node.t) =
match Procdesc.Node.get_kind n with
| Procdesc.Node.Start_node _ | Procdesc.Node.Exit_node _ ->
F.pp_print_string fmt "color=yellow style=filled"
@ -1143,7 +1140,7 @@ let pp_cfgnodeshape fmt (n: Procdesc.Node.t) =
()
let pp_cfgnode pdesc fmt (n: Procdesc.Node.t) =
let pp_cfgnode pdesc fmt (n : Procdesc.Node.t) =
let pname = Procdesc.get_proc_name pdesc in
F.fprintf fmt "%a [label=\"%a\" %a]@\n\t@\n" (pp_cfgnodename pname) n (pp_cfgnodelabel pdesc) n
pp_cfgnodeshape n ;
@ -1207,7 +1204,7 @@ let print_icfg_dotty source cfg =
(********** END of Printing dotty files ***********)
(** Dotty printing for specs *)
let pp_speclist_dotty f (splist: Prop.normal BiabductionSummary.spec list) =
let pp_speclist_dotty f (splist : Prop.normal BiabductionSummary.spec list) =
let pp_simple_saved = !Config.pp_simple in
Config.pp_simple := true ;
reset_proposition_counter () ;
@ -1225,7 +1222,7 @@ let pp_speclist_dotty f (splist: Prop.normal BiabductionSummary.spec list) =
Config.pp_simple := pp_simple_saved
let pp_speclist_to_file (filename: DB.filename) spec_list =
let pp_speclist_to_file (filename : DB.filename) spec_list =
let pp_simple_saved = !Config.pp_simple in
Config.pp_simple := true ;
let outc = Out_channel.create (DB.filename_to_string (DB.filename_add_suffix filename ".dot")) in
@ -1235,5 +1232,5 @@ let pp_speclist_to_file (filename: DB.filename) spec_list =
Config.pp_simple := pp_simple_saved
let pp_speclist_dotty_file (filename: DB.filename) spec_list =
let pp_speclist_dotty_file (filename : DB.filename) spec_list =
try pp_speclist_to_file filename spec_list with exn when SymOp.exn_not_failure exn -> ()

@ -73,8 +73,8 @@ let verbose = Config.trace_error
(** Find the function call instruction used to initialize normal variable [id],
and return the function name and arguments *)
let find_normal_variable_funcall (node: Procdesc.Node.t) (id: Ident.t)
: (Exp.t * Exp.t list * Location.t * CallFlags.t) option =
let find_normal_variable_funcall (node : Procdesc.Node.t) (id : Ident.t) :
(Exp.t * Exp.t list * Location.t * CallFlags.t) option =
let find_declaration _ = function
| Sil.Call ((id0, _), fun_exp, args, loc, call_flags) when Ident.equal id id0 ->
Some (fun_exp, List.map ~f:fst args, loc, call_flags)
@ -93,7 +93,8 @@ let find_normal_variable_funcall (node: Procdesc.Node.t) (id: Ident.t)
(** Find a program variable assignment in the current node or predecessors. *)
let find_program_variable_assignment node pvar : (Procdesc.Node.t * Ident.t) option =
let find_instr node = function
| Sil.Store (Exp.Lvar pvar_, _, Exp.Var id, _) when Pvar.equal pvar pvar_ && Ident.is_normal id ->
| Sil.Store (Exp.Lvar pvar_, _, Exp.Var id, _) when Pvar.equal pvar pvar_ && Ident.is_normal id
->
Some (node, id)
| _ ->
None
@ -155,7 +156,7 @@ let rec find_boolean_assignment node pvar true_branch : Procdesc.Node.t option =
(** Find the Load instruction used to declare normal variable [id],
and return the expression dereferenced to initialize [id] *)
let rec find_normal_variable_load_ tenv (seen: Exp.Set.t) node id : DExp.t option =
let rec find_normal_variable_load_ tenv (seen : Exp.Set.t) node id : DExp.t option =
let find_declaration node = function
| Sil.Load (id0, e, _, _) when Ident.equal id id0 ->
if verbose then (
@ -206,7 +207,7 @@ let rec find_normal_variable_load_ tenv (seen: Exp.Set.t) node id : DExp.t optio
(** describe lvalue [e] as a dexp *)
and exp_lv_dexp_ tenv (seen_: Exp.Set.t) node e : DExp.t option =
and exp_lv_dexp_ tenv (seen_ : Exp.Set.t) node e : DExp.t option =
if Exp.Set.mem e seen_ then (
L.d_str "exp_lv_dexp: cycle detected" ;
Sil.d_exp e ;
@ -218,8 +219,7 @@ and exp_lv_dexp_ tenv (seen_: Exp.Set.t) node e : DExp.t option =
| Exp.Const c ->
if verbose then ( L.d_str "exp_lv_dexp: constant " ; Sil.d_exp e ; L.d_ln () ) ;
Some (DExp.Dderef (DExp.Dconst c))
| Exp.BinOp (Binop.PlusPI, e1, e2)
-> (
| Exp.BinOp (Binop.PlusPI, e1, e2) -> (
if verbose then (
L.d_str "exp_lv_dexp: (e1 +PI e2) " ;
Sil.d_exp e ;
@ -229,8 +229,7 @@ and exp_lv_dexp_ tenv (seen_: Exp.Set.t) node e : DExp.t option =
Some (DExp.Dbinop (Binop.PlusPI, de1, de2))
| _ ->
None )
| Exp.Var id when Ident.is_normal id
-> (
| Exp.Var id when Ident.is_normal id -> (
if verbose then (
L.d_str "exp_lv_dexp: normal var " ;
Sil.d_exp e ;
@ -253,7 +252,7 @@ and exp_lv_dexp_ tenv (seen_: Exp.Set.t) node e : DExp.t option =
Some (DExp.Dfcall (DExp.Dconst (Cfun pname), [], loc, call_flags))
| None ->
None )
| Some (node', id) ->
| Some (node', id) -> (
match find_normal_variable_funcall node' id with
| Some (fun_exp, eargs, loc, call_flags) ->
let fun_dexpo = exp_rv_dexp_ tenv seen node' fun_exp in
@ -264,10 +263,9 @@ and exp_lv_dexp_ tenv (seen_: Exp.Set.t) node e : DExp.t option =
let args = List.map ~f:unNone blame_args in
Some (DExp.Dfcall (unNone fun_dexpo, args, loc, call_flags))
| None ->
exp_rv_dexp_ tenv seen node' (Exp.Var id)
exp_rv_dexp_ tenv seen node' (Exp.Var id) )
else Some (DExp.Dpvar pvar)
| Exp.Lfield (Exp.Var id, f, _) when Ident.is_normal id
-> (
| Exp.Lfield (Exp.Var id, f, _) when Ident.is_normal id -> (
if verbose then (
L.d_str "exp_lv_dexp: Lfield with var " ;
Sil.d_exp (Exp.Var id) ;
@ -278,8 +276,7 @@ and exp_lv_dexp_ tenv (seen_: Exp.Set.t) node e : DExp.t option =
None
| Some de ->
Some (DExp.Darrow (de, f)) )
| Exp.Lfield (e1, f, _)
-> (
| Exp.Lfield (e1, f, _) -> (
if verbose then (
L.d_str "exp_lv_dexp: Lfield " ;
Sil.d_exp e1 ;
@ -290,8 +287,7 @@ and exp_lv_dexp_ tenv (seen_: Exp.Set.t) node e : DExp.t option =
None
| Some de ->
Some (DExp.Ddot (de, f)) )
| Exp.Lindex (e1, e2)
-> (
| Exp.Lindex (e1, e2) -> (
if verbose then (
L.d_str "exp_lv_dexp: Lindex " ; Sil.d_exp e1 ; L.d_str " " ; Sil.d_exp e2 ; L.d_ln () ) ;
match (exp_lv_dexp_ tenv seen node e1, exp_rv_dexp_ tenv seen node e2) with
@ -311,7 +307,7 @@ and exp_lv_dexp_ tenv (seen_: Exp.Set.t) node e : DExp.t option =
(** describe rvalue [e] as a dexp *)
and exp_rv_dexp_ tenv (seen_: Exp.Set.t) node e : DExp.t option =
and exp_rv_dexp_ tenv (seen_ : Exp.Set.t) node e : DExp.t option =
if Exp.Set.mem e seen_ then (
L.d_str "exp_rv_dexp: cycle detected" ;
Sil.d_exp e ;
@ -337,8 +333,7 @@ and exp_rv_dexp_ tenv (seen_: Exp.Set.t) node e : DExp.t option =
Sil.d_exp e ;
L.d_ln () ) ;
find_normal_variable_load_ tenv seen node id
| Exp.Lfield (e1, f, _)
-> (
| Exp.Lfield (e1, f, _) -> (
if verbose then (
L.d_str "exp_rv_dexp: Lfield " ;
Sil.d_exp e1 ;
@ -349,8 +344,7 @@ and exp_rv_dexp_ tenv (seen_: Exp.Set.t) node e : DExp.t option =
None
| Some de ->
Some (DExp.Ddot (de, f)) )
| Exp.Lindex (e1, e2)
-> (
| Exp.Lindex (e1, e2) -> (
if verbose then (
L.d_str "exp_rv_dexp: Lindex " ; Sil.d_exp e1 ; L.d_str " " ; Sil.d_exp e2 ; L.d_ln () ) ;
match (exp_rv_dexp_ tenv seen node e1, exp_rv_dexp_ tenv seen node e2) with
@ -358,16 +352,14 @@ and exp_rv_dexp_ tenv (seen_: Exp.Set.t) node e : DExp.t option =
None
| Some de1, Some 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 () ) ;
match (exp_rv_dexp_ tenv seen node e1, exp_rv_dexp_ tenv seen node e2) with
| None, _ | _, None ->
None
| Some de1, Some 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 () ) ;
match exp_rv_dexp_ tenv seen node e1 with
| None ->
@ -496,7 +488,8 @@ let explain_leak tenv hpred prop alloc_att_opt bucket =
let is_file = match resource_opt with Some PredSymb.Rfile -> true | _ -> false in
let check_pvar pvar =
(* check that pvar is local or global and has the same type as the leaked hpred *)
(Pvar.is_local pvar || Pvar.is_global pvar) && not (Pvar.is_frontend_tmp pvar)
(Pvar.is_local pvar || Pvar.is_global pvar)
&& (not (Pvar.is_frontend_tmp pvar))
&&
match (hpred_typ_opt, find_typ_without_ptr prop pvar) with
| Some (Exp.Sizeof {typ= t1}), Some (Exp.Sizeof {typ= {Typ.desc= Tptr (t2, _)}}) ->
@ -515,8 +508,7 @@ let explain_leak tenv hpred prop alloc_att_opt bucket =
L.d_str "explain_leak: no current instruction" ;
L.d_ln () ) ;
value_str_from_pvars_vpath [] vpath
| Some (Sil.Nullify (pvar, _)) when check_pvar pvar
-> (
| Some (Sil.Nullify (pvar, _)) when check_pvar pvar -> (
if verbose then (
L.d_str "explain_leak: current instruction is Nullify for pvar " ;
Pvar.d pvar ;
@ -547,8 +539,7 @@ let explain_leak tenv hpred prop alloc_att_opt bucket =
List.rev_filter ~f:(fun pvar -> not (Pvar.is_frontend_tmp pvar)) rev_nullify_pvars
in
value_str_from_pvars_vpath nullify_pvars_notmp vpath
| Some (Sil.Store (lexp, _, _, _)) when is_none vpath
-> (
| Some (Sil.Store (lexp, _, _, _)) when is_none vpath -> (
if verbose then (
L.d_str "explain_leak: current instruction Set for " ;
Sil.d_exp lexp ;
@ -588,8 +579,7 @@ let vpath_find tenv prop exp_ : DExp.t option * Typ.t option =
let rec find sigma_acc sigma_todo exp =
let do_fse res sigma_acc' sigma_todo' lexp texp (f, se) =
match se with
| Sil.Eexp (e, _) when Exp.equal exp e
-> (
| Sil.Eexp (e, _) when Exp.equal exp e -> (
let sigma' = List.rev_append sigma_acc' sigma_todo' in
match lexp with
| Exp.Lvar pv ->
@ -622,8 +612,7 @@ let vpath_find tenv prop exp_ : DExp.t option * Typ.t option =
in
let do_sexp sigma_acc' sigma_todo' lexp sexp texp =
match sexp with
| Sil.Eexp (e, _) when Exp.equal exp e
-> (
| Sil.Eexp (e, _) when Exp.equal exp e -> (
let sigma' = List.rev_append sigma_acc' sigma_todo' in
match lexp with
| Exp.Lvar pv when not (Pvar.is_frontend_tmp pv) ->
@ -659,41 +648,41 @@ let vpath_find tenv prop exp_ : DExp.t option * Typ.t option =
List.exists ~f:filter (Sil.sub_to_list prop.Prop.sub)
in
function
| Sil.Hpointsto (Exp.Lvar pv, sexp, texp)
when Pvar.is_local pv || Pvar.is_global pv || Pvar.is_seed pv ->
do_sexp sigma_acc' sigma_todo' (Exp.Lvar pv) sexp texp
| Sil.Hpointsto (Exp.Var id, sexp, texp)
when Ident.is_normal id || (Ident.is_footprint id && substituted_from_normal id) ->
do_sexp sigma_acc' sigma_todo' (Exp.Var id) sexp texp
| _ ->
(None, None)
| Sil.Hpointsto (Exp.Lvar pv, sexp, texp)
when Pvar.is_local pv || Pvar.is_global pv || Pvar.is_seed pv ->
do_sexp sigma_acc' sigma_todo' (Exp.Lvar pv) sexp texp
| Sil.Hpointsto (Exp.Var id, sexp, texp)
when Ident.is_normal id || (Ident.is_footprint id && substituted_from_normal id) ->
do_sexp sigma_acc' sigma_todo' (Exp.Var id) sexp texp
| _ ->
(None, None)
in
match sigma_todo with
| [] ->
(None, None)
| hpred :: sigma_todo' ->
| hpred :: sigma_todo' -> (
match do_hpred sigma_acc sigma_todo' hpred with
| Some de, typo ->
(Some de, typo)
| None, _ ->
find (hpred :: sigma_acc) sigma_todo' exp
find (hpred :: sigma_acc) sigma_todo' exp )
in
let res = find [] prop.Prop.sigma exp_ in
( if verbose then
match res with
| None, _ ->
L.d_str "vpath_find: cannot find " ;
Sil.d_exp exp_ ;
L.d_ln ()
| Some de, typo ->
L.d_str "vpath_find: found " ;
L.d_str (DExp.to_string de) ;
L.d_str " : " ;
match typo with None -> L.d_str " No type" | Some typ -> Typ.d_full typ ; L.d_ln () ) ;
match res with
| None, _ ->
L.d_str "vpath_find: cannot find " ;
Sil.d_exp exp_ ;
L.d_ln ()
| Some de, typo -> (
L.d_str "vpath_find: found " ;
L.d_str (DExp.to_string de) ;
L.d_str " : " ;
match typo with None -> L.d_str " No type" | Some typ -> Typ.d_full typ ; L.d_ln () ) ) ;
res
let access_opt ?(is_nullable= false) inst =
let access_opt ?(is_nullable = false) inst =
match inst with
| Sil.Iupdate (_, ncf, n, _) ->
Some (Localise.Last_assigned (n, ncf))
@ -724,7 +713,7 @@ let explain_dexp_access prop dexp is_nullable =
L.d_ln () ) ;
None
in
let find_ptsto (e: Exp.t) : Sil.strexp option =
let find_ptsto (e : Exp.t) : Sil.strexp option =
let res = ref None in
let do_hpred = function
| Sil.Hpointsto (e', se, _) when Exp.equal e e' ->
@ -813,8 +802,7 @@ let explain_dexp_access prop dexp is_nullable =
| DExp.Dbinop (Binop.PlusPI, DExp.Dpvar _, DExp.Dconst _) as de ->
if verbose then L.d_strln ("lookup: case )pvar + constant) " ^ DExp.to_string de) ;
None
| DExp.Dfcall (DExp.Dconst c, _, loc, _)
-> (
| DExp.Dfcall (DExp.Dconst c, _, loc, _) -> (
if verbose then L.d_strln "lookup: found Dfcall " ;
match c with
| Const.Cfun _ ->
@ -873,8 +861,8 @@ let explain_dereference_access outermost_array is_nullable de_opt_ prop =
(** Create a description of a dereference operation *)
let create_dereference_desc proc_name tenv ?(use_buckets= false) ?(outermost_array= false)
?(is_nullable= false) ?(is_premature_nil= false) de_opt deref_str prop loc =
let create_dereference_desc proc_name tenv ?(use_buckets = false) ?(outermost_array = false)
?(is_nullable = false) ?(is_premature_nil = false) de_opt deref_str prop loc =
let value_str, access_opt = explain_dereference_access outermost_array is_nullable de_opt prop in
let access_opt' =
match access_opt with
@ -967,9 +955,9 @@ let rec find_outermost_dereference tenv node e =
if outermost_array is true, the outermost array access is removed
if outermost_dereference is true, stop at the outermost dereference
(skipping e.g. outermost field access) *)
let explain_access_ proc_name tenv ?(use_buckets= false) ?(outermost_array= false)
?(outermost_dereference= false) ?(is_nullable= false) ?(is_premature_nil= false) deref_str prop
loc =
let explain_access_ proc_name tenv ?(use_buckets = false) ?(outermost_array = false)
?(outermost_dereference = false) ?(is_nullable = false) ?(is_premature_nil = false) deref_str
prop loc =
let find_exp_dereferenced () =
match State.get_instr () with
| Some (Sil.Store (e, _, _, _)) ->
@ -1018,8 +1006,8 @@ let explain_access_ proc_name tenv ?(use_buckets= false) ?(outermost_array= fals
(** Produce a description of which expression is dereferenced in the current instruction, if any.
The subexpression to focus on is obtained by removing field and index accesses. *)
let explain_dereference proc_name tenv ?(use_buckets= false) ?(is_nullable= false)
?(is_premature_nil= false) deref_str prop loc =
let explain_dereference proc_name tenv ?(use_buckets = false) ?(is_nullable = false)
?(is_premature_nil = false) deref_str prop loc =
explain_access_ proc_name tenv ~use_buckets ~outermost_array:false ~outermost_dereference:true
~is_nullable ~is_premature_nil deref_str prop loc
@ -1073,7 +1061,7 @@ let explain_nth_function_parameter proc_name tenv use_buckets deref_str prop n p
let find_with_exp prop exp =
let res = ref None in
let found_in_pvar pv =
if not (Pvar.is_abduced pv) && not (Pvar.is_this pv) then res := Some (pv, Fpvar)
if (not (Pvar.is_abduced pv)) && not (Pvar.is_this pv) then res := Some (pv, Fpvar)
in
let found_in_struct pv fld_lst =
(* found_in_pvar has priority *)
@ -1106,7 +1094,7 @@ let find_with_exp prop exp =
(** return a description explaining value [exp] in [prop] in terms of a source expression
using the formal parameters of the call *)
let explain_dereference_as_caller_expression proc_name tenv ?(use_buckets= false) deref_str
let explain_dereference_as_caller_expression proc_name tenv ?(use_buckets = false) deref_str
actual_pre spec_pre exp node loc formal_params =
let find_formal_param_number name =
let rec find n = function

@ -44,7 +44,13 @@ val explain_array_access :
(** Produce a description of the array access performed in the current instruction, if any. *)
val explain_class_cast_exception :
Tenv.t -> Typ.Procname.t option -> Exp.t -> Exp.t -> Exp.t -> Procdesc.Node.t -> Location.t
Tenv.t
-> Typ.Procname.t option
-> Exp.t
-> Exp.t
-> Exp.t
-> Procdesc.Node.t
-> Location.t
-> Localise.error_desc
(** explain a class cast exception *)
@ -55,13 +61,29 @@ val explain_deallocate_constant_string : string -> PredSymb.res_action -> Locali
(** Explain a deallocate constant string error *)
val explain_dereference :
Typ.Procname.t -> Tenv.t -> ?use_buckets:bool -> ?is_nullable:bool -> ?is_premature_nil:bool
-> Localise.deref_str -> 'a Prop.t -> Location.t -> Localise.error_desc
Typ.Procname.t
-> Tenv.t
-> ?use_buckets:bool
-> ?is_nullable:bool
-> ?is_premature_nil:bool
-> Localise.deref_str
-> 'a Prop.t
-> Location.t
-> Localise.error_desc
(** Produce a description of which expression is dereferenced in the current instruction, if any. *)
val explain_dereference_as_caller_expression :
Typ.Procname.t -> Tenv.t -> ?use_buckets:bool -> Localise.deref_str -> 'a Prop.t -> 'b Prop.t
-> Exp.t -> Procdesc.Node.t -> Location.t -> Pvar.t list -> Localise.error_desc
Typ.Procname.t
-> Tenv.t
-> ?use_buckets:bool
-> Localise.deref_str
-> 'a Prop.t
-> 'b Prop.t
-> Exp.t
-> Procdesc.Node.t
-> Location.t
-> Pvar.t list
-> Localise.error_desc
(** return a description explaining value [exp] in [prop] in terms of a source expression
using the formal parameters of the call *)
@ -87,7 +109,11 @@ val explain_unary_minus_applied_to_unsigned_expression :
(** explain unary minus applied to unsigned expression *)
val explain_leak :
Tenv.t -> Sil.hpred -> 'a Prop.t -> PredSymb.t option -> string option
Tenv.t
-> Sil.hpred
-> 'a Prop.t
-> PredSymb.t option
-> string option
-> Exceptions.visibility * Localise.error_desc
(** Produce a description of a leak by looking at the current state.
If the current instruction is a variable nullify, blame the variable.

@ -84,7 +84,7 @@ let get_tenv exe_env proc_name =
match proc_name with
| Typ.Procname.Java _ ->
Lazy.force java_global_tenv
| _ ->
| _ -> (
match get_file_data exe_env proc_name with
| Some file_data -> (
match file_data_to_tenv file_data with
@ -99,7 +99,7 @@ let get_tenv exe_env proc_name =
let loc = State.get_loc () in
L.(die InternalError)
"get_tenv: file_data not found for %a in file '%a' at %a" Typ.Procname.pp proc_name
SourceFile.pp loc.Location.file Location.pp loc
SourceFile.pp loc.Location.file Location.pp loc )
(** return the cfg associated to the procedure *)

@ -45,7 +45,7 @@ let is_matching patterns source_file =
(** Check if a proc name is matching the name given as string. *)
let match_method language proc_name method_name =
not (BuiltinDecl.is_declared proc_name)
(not (BuiltinDecl.is_declared proc_name))
&& Language.equal (Typ.Procname.get_language proc_name) language
&& String.equal (Typ.Procname.get_method proc_name) method_name
@ -73,14 +73,14 @@ module FileContainsStringMatcher = struct
let source_map = ref SourceFile.Map.empty in
let regexp = Str.regexp (String.concat ~sep:"\\|" s_patterns) in
fun source_file ->
try SourceFile.Map.find source_file !source_map with Caml.Not_found ->
try SourceFile.Map.find source_file !source_map with Caml.Not_found -> (
try
let file_in = In_channel.create (SourceFile.to_abs_path source_file) in
let pattern_found = file_contains regexp file_in in
In_channel.close file_in ;
source_map := SourceFile.Map.add source_file pattern_found !source_map ;
pattern_found
with Sys_error _ -> false
with Sys_error _ -> false )
end
type method_pattern = {class_name: string; method_name: string option}
@ -220,7 +220,7 @@ let patterns_of_json_with_key (json_key, json) =
error
in
(* Translate a JSON entry into a matching pattern *)
let create_pattern (assoc: (string * Yojson.Basic.json) list) =
let create_pattern (assoc : (string * Yojson.Basic.json) list) =
let create_method_pattern assoc =
let loop mp = function
| key, `String s when String.equal key "class" ->
@ -308,9 +308,10 @@ let filters_from_inferconfig inferconfig : filters =
FileContainsStringMatcher.create_matcher inferconfig.blacklist_files_containing
in
function
| source_file ->
whitelist_filter source_file && not (blacklist_filter source_file)
&& not (blacklist_files_containing_filter source_file)
| source_file ->
whitelist_filter source_file
&& (not (blacklist_filter source_file))
&& not (blacklist_files_containing_filter source_file)
in
let error_filter = function
| error_name ->

@ -89,7 +89,7 @@ let should_link ~target ~target_results_dir ~stats infer_out_src infer_out_dst =
~f:(fun file ->
let file_path = Filename.concat captured_file file in
Sys.file_exists file_path = `Yes
&& (not check_timestamp_of_symlinks || symlink_up_to_date file_path) )
&& ((not check_timestamp_of_symlinks) || symlink_up_to_date file_path) )
contents
else true
in

@ -20,7 +20,7 @@ let callbacks_ref = ref None
let cached_results = lazy (Typ.Procname.Hash.create 128)
let set_callbacks (callbacks: callbacks) = callbacks_ref := Some callbacks
let set_callbacks (callbacks : callbacks) = callbacks_ref := Some callbacks
let unset_callbacks () = callbacks_ref := None
@ -60,7 +60,8 @@ let should_be_analyzed proc_name proc_attributes =
| None ->
false
in
should_create_summary proc_name proc_attributes && not (is_active proc_name)
should_create_summary proc_name proc_attributes
&& (not (is_active proc_name))
&& (* avoid infinite loops *)
not (already_analyzed proc_name)
@ -148,7 +149,7 @@ let run_proc_analysis analyze_proc ~caller_pdesc callee_pdesc =
log_elapsed_time () ;
summary
in
let log_error_and_continue exn (summary: Summary.t) kind =
let log_error_and_continue exn (summary : Summary.t) kind =
let loc = State.get_loc () in
Reporting.log_error summary ~loc exn ;
let stats = Summary.Stats.update summary.stats ~failure_kind:kind in
@ -172,7 +173,7 @@ let run_proc_analysis analyze_proc ~caller_pdesc callee_pdesc =
in
let final_summary = postprocess summary in
restore_global_state old_state ; final_summary
with exn ->
with exn -> (
IExn.reraise_if exn ~f:(fun () -> restore_global_state old_state ; not Config.keep_going) ;
L.internal_error "@\nERROR RUNNING BACKEND: %a %s@\n@\nBACK TRACE@\n%s@?" Typ.Procname.pp
callee_pname (Exn.to_string exn) (Printexc.get_backtrace ()) ;
@ -183,7 +184,7 @@ let run_proc_analysis analyze_proc ~caller_pdesc callee_pdesc =
log_error_and_continue exn initial_summary kind
| _ ->
(* this happens with assert false or some other unrecognized exception *)
log_error_and_continue exn initial_summary (FKcrash (Exn.to_string exn))
log_error_and_continue exn initial_summary (FKcrash (Exn.to_string exn)) )
let analyze_proc ?caller_pdesc callee_pdesc =

@ -144,8 +144,7 @@ let add_nullify_instrs pdesc tenv liveness_inv_map =
(fun var (pvars_acc, ids_acc) ->
match Var.to_exp var with
(* we nullify all address taken variables at the end of the procedure *)
| Exp.Lvar pvar
when not (AddressTaken.Domain.mem pvar address_taken_vars) ->
| Exp.Lvar pvar when not (AddressTaken.Domain.mem pvar address_taken_vars) ->
(pvar :: pvars_acc, ids_acc)
| Exp.Var id ->
(pvars_acc, id :: ids_acc)

@ -36,19 +36,18 @@ module LineReader = struct
in
lines := line :: !lines
done ;
assert false
(* execution never reaches here *)
assert false (* execution never reaches here *)
with End_of_file ->
In_channel.close cin ;
Array.of_list (List.rev !lines)
let file_data (hash: t) fname =
try Some (Hashtbl.find hash fname) with Caml.Not_found ->
let file_data (hash : t) fname =
try Some (Hashtbl.find hash fname) with Caml.Not_found -> (
try
let lines_arr = read_file (SourceFile.to_abs_path fname) in
Hashtbl.add hash fname lines_arr ; Some lines_arr
with exn when SymOp.exn_not_failure exn -> None
with exn when SymOp.exn_not_failure exn -> None )
let from_file_linenum_original hash fname linenum =
@ -114,8 +113,14 @@ let pp_node_link path_to_root ?proof_cover ~description fmt node =
when starting and finishing the processing of a node *)
module NodesHtml : sig
val start_node :
int -> Location.t -> Typ.Procname.t -> Procdesc.Node.t list -> Procdesc.Node.t list
-> Procdesc.Node.t list -> SourceFile.t -> bool
int
-> Location.t
-> Typ.Procname.t
-> Procdesc.Node.t list
-> Procdesc.Node.t list
-> Procdesc.Node.t list
-> SourceFile.t
-> bool
val finish_node : Typ.Procname.t -> int -> SourceFile.t -> unit
end = struct
@ -175,7 +180,7 @@ let force_delayed_prints () =
(** Start a session, and create a new html fine for the node if it does not exist yet *)
let start_session ~pp_name node (loc: Location.t) proc_name session source =
let start_session ~pp_name node (loc : Location.t) proc_name session source =
let node_id = Procdesc.Node.get_id node in
if
NodesHtml.start_node
@ -189,7 +194,8 @@ let start_session ~pp_name node (loc: Location.t) proc_name session source =
node Io_infer.Html.pp_end_color () ;
F.fprintf !curr_html_formatter "%a%a %t" Io_infer.Html.pp_hline ()
(Io_infer.Html.pp_session_link source ~with_name:true [".."] ~proc_name)
((node_id :> int), session, loc.Location.line) pp_name ;
((node_id :> int), session, loc.Location.line)
pp_name ;
F.fprintf !curr_html_formatter "<LISTING>%a" Io_infer.Html.pp_start_color Pp.Black
@ -241,7 +247,7 @@ let write_proc_html pdesc =
(** Creare a hash table mapping line numbers to the set of errors occurring on that line *)
let create_table_err_per_line err_log =
let err_per_line = Hashtbl.create 17 in
let add_err (key: Errlog.err_key) (err_data: Errlog.err_data) =
let add_err (key : Errlog.err_key) (err_data : Errlog.err_data) =
let err_str =
F.asprintf "%s %a" key.err_name.IssueType.unique_id Localise.pp_error_desc key.err_desc
in
@ -268,7 +274,8 @@ let write_html_proc source proof_cover table_nodes_at_linenum global_err_log pro
in
let proc_loc = Procdesc.get_loc proc_desc in
let process_proc =
Procdesc.is_defined proc_desc && SourceFile.equal proc_loc.Location.file source
Procdesc.is_defined proc_desc
&& SourceFile.equal proc_loc.Location.file source
&&
match Attributes.find_file_capturing_procedure proc_name with
| None ->

@ -9,19 +9,25 @@ open! IStd
module L = Logging
type log_t =
?ltr:Errlog.loc_trace -> ?linters_def_file:string -> ?doc_url:string -> ?access:string
-> ?extras:Jsonbug_t.extra -> exn -> unit
?ltr:Errlog.loc_trace
-> ?linters_def_file:string
-> ?doc_url:string
-> ?access:string
-> ?extras:Jsonbug_t.extra
-> exn
-> unit
let log_issue_from_errlog procname ~clang_method_kind severity err_log ~loc ~node ~ltr
~linters_def_file ~doc_url ~access ~extras exn =
let issue_type = (Exceptions.recognize_exception exn).name in
if not Config.filtering (* no-filtering takes priority *) || issue_type.IssueType.enabled then
if (not Config.filtering) (* no-filtering takes priority *) || issue_type.IssueType.enabled then
let session = (State.get_session () :> int) in
Errlog.log_issue procname ~clang_method_kind severity err_log ~loc ~node ~session ~ltr
~linters_def_file ~doc_url ~access ~extras exn
let log_frontend_issue procname severity errlog ~loc ~node_key ~ltr ~linters_def_file ~doc_url exn =
let log_frontend_issue procname severity errlog ~loc ~node_key ~ltr ~linters_def_file ~doc_url exn
=
let node = Errlog.FrontendNode {node_key} in
log_issue_from_errlog procname ~clang_method_kind:None severity errlog ~loc ~node ~ltr
~linters_def_file ~doc_url ~access:None ~extras:None exn
@ -87,7 +93,7 @@ let log_issue_external procname severity ~loc ~ltr ?access issue_type error_mess
~linters_def_file:None ~doc_url:None ~access ~extras:None exn
let is_suppressed ?(field_name= None) tenv proc_desc kind =
let is_suppressed ?(field_name = None) tenv proc_desc kind =
let lookup = Tenv.lookup tenv in
let proc_attributes = Procdesc.get_attributes proc_desc in
(* Errors can be suppressed with annotations. An error of kind CHECKER_ERROR_NAME can be
@ -95,7 +101,7 @@ let is_suppressed ?(field_name= None) tenv proc_desc kind =
- @android.annotation.SuppressLint("checker-error-name")
- @some.PrefixErrorName
where the kind matching is case - insensitive and ignores '-' and '_' characters. *)
let annotation_matches (a: Annot.t) =
let annotation_matches (a : Annot.t) =
let normalize str = Str.global_replace (Str.regexp "[_-]") "" (String.lowercase str) in
let drop_prefix str = Str.replace_first (Str.regexp "^[A-Za-z]+_") "" str in
let normalized_equal s1 s2 = String.equal (normalize s1) (normalize s2) in

@ -10,8 +10,13 @@ open! IStd
(** Type of functions to report issues to the error_log in a spec. *)
type log_t =
?ltr:Errlog.loc_trace -> ?linters_def_file:string -> ?doc_url:string -> ?access:string
-> ?extras:Jsonbug_t.extra -> exn -> unit
?ltr:Errlog.loc_trace
-> ?linters_def_file:string
-> ?doc_url:string
-> ?access:string
-> ?extras:Jsonbug_t.extra
-> exn
-> unit
val log_issue_deprecated :
Exceptions.severity -> Typ.Procname.t -> ?node:Procdesc.Node.t -> ?loc:Location.t -> log_t
@ -20,9 +25,16 @@ val log_issue_deprecated :
Use log_error/warning instead *)
val log_frontend_issue :
Typ.Procname.t -> Exceptions.severity -> Errlog.t -> loc:Location.t
-> node_key:Procdesc.NodeKey.t -> ltr:Errlog.loc_trace -> linters_def_file:string option
-> doc_url:string option -> exn -> unit
Typ.Procname.t
-> Exceptions.severity
-> Errlog.t
-> loc:Location.t
-> node_key:Procdesc.NodeKey.t
-> ltr:Errlog.loc_trace
-> linters_def_file:string option
-> doc_url:string option
-> exn
-> unit
(** Report a frontend issue of a given kind in the given error log. *)
val log_error : Summary.t -> loc:Location.t -> log_t
@ -32,8 +44,14 @@ val log_warning : Summary.t -> loc:Location.t -> log_t
(** Add an warning to the given summary. *)
val log_issue_external :
Typ.Procname.t -> Exceptions.severity -> loc:Location.t -> ltr:Errlog.loc_trace -> ?access:string
-> IssueType.t -> string -> unit
Typ.Procname.t
-> Exceptions.severity
-> loc:Location.t
-> ltr:Errlog.loc_trace
-> ?access:string
-> IssueType.t
-> string
-> unit
(** Log an issue to the error log in [IssueLog] associated with the given procname. *)
val is_suppressed :

@ -238,7 +238,8 @@ $(b,infer) $(i,[options])|}
"cxx": false,
"infer-blacklist-files-containing": ["@generated","@Generated"]
}|}
] ~see_also:InferCommand.all_commands "infer"
]
~see_also:InferCommand.all_commands "infer"
let report =

@ -64,7 +64,7 @@ let to_arg_speclist = List.map ~f:to_arg_spec_triple
(* NOTE: All variants must be also added to `all_parse_modes` below *)
type parse_mode = InferCommand | Javac | NoParse [@@deriving compare]
let equal_parse_mode = [%compare.equal : parse_mode]
let equal_parse_mode = [%compare.equal: parse_mode]
let all_parse_modes = [InferCommand; Javac; NoParse]
@ -218,7 +218,8 @@ let add parse_mode sections desc =
in
(* in the help of `infer` itself, show in which specific commands the option is used *)
let commands =
List.map ~f:fst sections |> List.sort ~compare:InferCommand.compare
List.map ~f:fst sections
|> List.sort ~compare:InferCommand.compare
|> List.remove_consecutive_duplicates ~equal:InferCommand.equal
|> List.map ~f:(fun cmd ->
let exe = InferCommand.to_exe_name cmd in
@ -264,7 +265,7 @@ let deprecate_desc parse_mode ~long ~short ~deprecated doc desc =
; decode_json= deprecated_decode_json }
let mk ?(deprecated= []) ?(parse_mode= InferCommand) ?(in_help= []) ~long ?short:short0 ~default
let mk ?(deprecated = []) ?(parse_mode = InferCommand) ?(in_help = []) ~long ?short:short0 ~default
~meta doc ~default_to_string ~decode_json ~mk_setter ~mk_spec =
let variable = ref default in
let closure = mk_setter variable in
@ -316,8 +317,14 @@ let curr_command = ref None
(* end parsing state *)
type 'a t =
?deprecated:string list -> long:Arg.key -> ?short:char -> ?parse_mode:parse_mode
-> ?in_help:(InferCommand.t * string) list -> ?meta:string -> Arg.doc -> 'a
?deprecated:string list
-> long:Arg.key
-> ?short:char
-> ?parse_mode:parse_mode
-> ?in_help:(InferCommand.t * string) list
-> ?meta:string
-> Arg.doc
-> 'a
let string_json_decoder ~long ~inferconfig_dir:_ json = [dashdash long; YBU.to_string json]
@ -333,7 +340,7 @@ let list_json_decoder json_decoder ~inferconfig_dir json =
List.concat (YBU.convert_each (json_decoder ~inferconfig_dir) json)
let mk_set var value ?(deprecated= []) ~long ?short ?parse_mode ?in_help ?(meta= "") doc =
let mk_set var value ?(deprecated = []) ~long ?short ?parse_mode ?in_help ?(meta = "") doc =
let setter () = var := value in
ignore
(mk ~deprecated ~long ?short ~default:() ?parse_mode ?in_help ~meta doc
@ -356,8 +363,8 @@ let reset_doc_opt ~long = Printf.sprintf "Cancel the effect of $(b,%s)." (dashda
let reset_doc_list ~long = Printf.sprintf "Set $(b,%s) to the empty list." (dashdash long)
let mk_option ?(default= None) ?(default_to_string= fun _ -> "") ~f ?(mk_reset= true)
?(deprecated= []) ~long ?short ?parse_mode ?in_help ?(meta= "string") doc =
let mk_option ?(default = None) ?(default_to_string = fun _ -> "") ~f ?(mk_reset = true)
?(deprecated = []) ~long ?short ?parse_mode ?in_help ?(meta = "string") doc =
let mk () =
mk ~deprecated ~long ?short ~default ?parse_mode ?in_help ~meta doc ~default_to_string
~decode_json:(string_json_decoder ~long)
@ -370,8 +377,8 @@ let mk_option ?(default= None) ?(default_to_string= fun _ -> "") ~f ?(mk_reset=
else mk ()
let mk_bool ?(deprecated_no= []) ?(default= false) ?(f= fun b -> b) ?(deprecated= []) ~long ?short
?parse_mode ?in_help ?(meta= "") doc0 =
let mk_bool ?(deprecated_no = []) ?(default = false) ?(f = fun b -> b) ?(deprecated = []) ~long
?short ?parse_mode ?in_help ?(meta = "") doc0 =
let nolong =
let len = String.length long in
if len > 3 && String.sub long ~pos:0 ~len:3 = "no-" then String.sub long ~pos:3 ~len:(len - 3)
@ -413,7 +420,7 @@ let mk_bool ?(deprecated_no= []) ?(default= false) ?(f= fun b -> b) ?(deprecated
var
let mk_bool_group ?(deprecated_no= []) ?(default= false) ?f:(f0 = Fn.id) ?(deprecated= []) ~long
let mk_bool_group ?(deprecated_no = []) ?(default = false) ?f:(f0 = Fn.id) ?(deprecated = []) ~long
?short ?parse_mode ?in_help ?meta doc children no_children =
let f b =
List.iter ~f:(fun child -> child := b) children ;
@ -423,8 +430,8 @@ let mk_bool_group ?(deprecated_no= []) ?(default= false) ?f:(f0 = Fn.id) ?(depre
mk_bool ~deprecated ~deprecated_no ~default ~long ?short ~f ?parse_mode ?in_help ?meta doc
let mk_int ~default ?(f= Fn.id) ?(deprecated= []) ~long ?short ?parse_mode ?in_help ?(meta= "int")
doc =
let mk_int ~default ?(f = Fn.id) ?(deprecated = []) ~long ?short ?parse_mode ?in_help
?(meta = "int") doc =
mk ~deprecated ~long ?short ~default ?parse_mode ?in_help ~meta doc
~default_to_string:string_of_int
~mk_setter:(fun var str -> var := f (int_of_string str))
@ -432,21 +439,22 @@ let mk_int ~default ?(f= Fn.id) ?(deprecated= []) ~long ?short ?parse_mode ?in_h
~mk_spec:(fun set -> String set)
let mk_int_opt ?default ?f:(f0 = Fn.id) ?(deprecated= []) ~long ?short ?parse_mode ?in_help
?(meta= "int") doc =
let mk_int_opt ?default ?f:(f0 = Fn.id) ?(deprecated = []) ~long ?short ?parse_mode ?in_help
?(meta = "int") doc =
let default_to_string = function Some f -> string_of_int f | None -> "" in
let f s = Some (f0 (int_of_string s)) in
mk_option ~deprecated ~long ?short ~default ~default_to_string ~f ?parse_mode ?in_help ~meta doc
let mk_float_opt ?default ?(deprecated= []) ~long ?short ?parse_mode ?in_help ?(meta= "float") doc =
let mk_float_opt ?default ?(deprecated = []) ~long ?short ?parse_mode ?in_help ?(meta = "float")
doc =
let default_to_string = function Some f -> string_of_float f | None -> "" in
let f s = Some (float_of_string s) in
mk_option ~deprecated ~long ?short ~default ~default_to_string ~f ?parse_mode ?in_help ~meta doc
let mk_string ~default ?(f= fun s -> s) ?(deprecated= []) ~long ?short ?parse_mode ?in_help
?(meta= "string") doc =
let mk_string ~default ?(f = fun s -> s) ?(deprecated = []) ~long ?short ?parse_mode ?in_help
?(meta = "string") doc =
mk ~deprecated ~long ?short ~default ?parse_mode ?in_help ~meta doc
~default_to_string:(fun s -> s)
~mk_setter:(fun var str -> var := f str)
@ -454,16 +462,16 @@ let mk_string ~default ?(f= fun s -> s) ?(deprecated= []) ~long ?short ?parse_mo
~mk_spec:(fun set -> String set)
let mk_string_opt ?default ?(f= fun s -> s) ?mk_reset ?(deprecated= []) ~long ?short ?parse_mode
?in_help ?(meta= "string") doc =
let mk_string_opt ?default ?(f = fun s -> s) ?mk_reset ?(deprecated = []) ~long ?short ?parse_mode
?in_help ?(meta = "string") doc =
let default_to_string = function Some s -> s | None -> "" in
let f s = Some (f s) in
mk_option ~deprecated ~long ?short ~default ~default_to_string ~f ?mk_reset ?parse_mode ?in_help
~meta doc
let mk_string_list ?(default= []) ?(f= fun s -> s) ?(deprecated= []) ~long ?short ?parse_mode
?in_help ?(meta= "string") doc =
let mk_string_list ?(default = []) ?(f = fun s -> s) ?(deprecated = []) ~long ?short ?parse_mode
?in_help ?(meta = "string") doc =
let mk () =
mk ~deprecated ~long ?short ~default ?parse_mode ?in_help ~meta:("+" ^ meta) doc
~default_to_string:(String.concat ~sep:",")
@ -475,7 +483,7 @@ let mk_string_list ?(default= []) ?(f= fun s -> s) ?(deprecated= []) ~long ?shor
mk_with_reset [] ~reset_doc ~long ?parse_mode mk
let normalize_path_in_args_being_parsed ?(f= Fn.id) ~is_anon_arg str =
let normalize_path_in_args_being_parsed ?(f = Fn.id) ~is_anon_arg str =
if Filename.is_relative str then (
(* Replace relative paths with absolute ones on the fly in the args being parsed. This assumes
that [!arg_being_parsed] points at either [str] (if [is_anon_arg]) or at the option name
@ -498,8 +506,8 @@ let mk_path_helper ~setter ~default_to_string ~default ~deprecated ~long ~short
~mk_spec:(fun set -> String set)
let mk_path ~default ?(f= Fn.id) ?(deprecated= []) ~long ?short ?parse_mode ?in_help
?(meta= "path") =
let mk_path ~default ?(f = Fn.id) ?(deprecated = []) ~long ?short ?parse_mode ?in_help
?(meta = "path") =
mk_path_helper
~setter:(fun var x -> var := f x)
~decode_json:(path_json_decoder ~long)
@ -507,7 +515,8 @@ let mk_path ~default ?(f= Fn.id) ?(deprecated= []) ~long ?short ?parse_mode ?in_
~default ~deprecated ~long ~short ~parse_mode ~in_help ~meta
let mk_path_opt ?default ?(deprecated= []) ~long ?short ?parse_mode ?in_help ?(meta= "path") doc =
let mk_path_opt ?default ?(deprecated = []) ~long ?short ?parse_mode ?in_help ?(meta = "path") doc
=
let mk () =
mk_path_helper
~setter:(fun var x -> var := Some x)
@ -519,8 +528,8 @@ let mk_path_opt ?default ?(deprecated= []) ~long ?short ?parse_mode ?in_help ?(m
mk_with_reset None ~reset_doc ~long ?parse_mode mk
let mk_path_list ?(default= []) ?(deprecated= []) ~long ?short ?parse_mode ?in_help ?(meta= "path")
doc =
let mk_path_list ?(default = []) ?(deprecated = []) ~long ?short ?parse_mode ?in_help
?(meta = "path") doc =
let mk () =
mk_path_helper
~setter:(fun var x -> var := x :: !var)
@ -537,8 +546,8 @@ let mk_symbols_meta symbols =
Printf.sprintf "{ %s }" (String.concat ~sep:" | " strings)
let mk_symbol ~default ~symbols ~eq ?(f= Fn.id) ?(deprecated= []) ~long ?short ?parse_mode ?in_help
?meta doc =
let mk_symbol ~default ~symbols ~eq ?(f = Fn.id) ?(deprecated = []) ~long ?short ?parse_mode
?in_help ?meta doc =
let strings = List.map ~f:fst symbols in
let sym_to_str = List.map ~f:(fun (x, y) -> (y, x)) symbols in
let of_string str = List.Assoc.find_exn ~equal:String.equal symbols str in
@ -551,8 +560,8 @@ let mk_symbol ~default ~symbols ~eq ?(f= Fn.id) ?(deprecated= []) ~long ?short ?
~mk_spec:(fun set -> Symbol (strings, set))
let mk_symbol_opt ~symbols ?(f= Fn.id) ?(mk_reset= true) ?(deprecated= []) ~long ?short ?parse_mode
?in_help ?meta doc =
let mk_symbol_opt ~symbols ?(f = Fn.id) ?(mk_reset = true) ?(deprecated = []) ~long ?short
?parse_mode ?in_help ?meta doc =
let strings = List.map ~f:fst symbols in
let of_string str = List.Assoc.find_exn ~equal:String.equal symbols str in
let meta = Option.value meta ~default:(mk_symbols_meta symbols) in
@ -569,7 +578,7 @@ let mk_symbol_opt ~symbols ?(f= Fn.id) ?(mk_reset= true) ?(deprecated= []) ~long
else mk ()
let mk_symbol_seq ?(default= []) ~symbols ~eq ?(deprecated= []) ~long ?short ?parse_mode ?in_help
let mk_symbol_seq ?(default = []) ~symbols ~eq ?(deprecated = []) ~long ?short ?parse_mode ?in_help
?meta doc =
let sym_to_str = List.map ~f:(fun (x, y) -> (y, x)) symbols in
let of_string str = List.Assoc.find_exn ~equal:String.equal symbols str in
@ -583,7 +592,7 @@ let mk_symbol_seq ?(default= []) ~symbols ~eq ?(deprecated= []) ~long ?short ?pa
~mk_spec:(fun set -> String set)
let mk_json ?(deprecated= []) ~long ?short ?parse_mode ?in_help ?(meta= "json") doc =
let mk_json ?(deprecated = []) ~long ?short ?parse_mode ?in_help ?(meta = "json") doc =
mk ~deprecated ~long ?short ?parse_mode ?in_help ~meta doc ~default:(`List [])
~default_to_string:Yojson.Basic.to_string
~mk_setter:(fun var json -> var := Yojson.Basic.from_string json)
@ -603,7 +612,7 @@ let normalize_desc_list speclist =
else s
in
let remove_weird_chars =
String.filter ~f:(function 'a'..'z' | '0'..'9' | '-' -> true | _ -> false)
String.filter ~f:(function 'a' .. 'z' | '0' .. '9' | '-' -> true | _ -> false)
in
remove_weird_chars @@ String.lowercase @@ remove_no k
in
@ -677,8 +686,8 @@ let set_curr_speclist_for_parse_mode ~usage parse_mode =
List.Assoc.find_exn ~equal:equal_parse_mode parse_mode_desc_lists parse_mode
in
curr_speclist :=
normalize_desc_list !full_desc_list |> List.map ~f:xdesc |> add_or_suppress_help
|> to_arg_speclist ;
normalize_desc_list !full_desc_list
|> List.map ~f:xdesc |> add_or_suppress_help |> to_arg_speclist ;
assert (check_no_duplicates !curr_speclist) ;
curr_usage
@ -694,7 +703,7 @@ let string_of_command command =
s
let mk_rest_actions ?(parse_mode= InferCommand) ?(in_help= []) doc ~usage decode_action =
let mk_rest_actions ?(parse_mode = InferCommand) ?(in_help = []) doc ~usage decode_action =
let rest = ref [] in
let spec =
String
@ -814,7 +823,7 @@ let encode_argv_to_env argv =
String.concat ~sep:(String.make 1 env_var_sep)
(List.filter
~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"
env_var_sep arg ;
@ -973,12 +982,12 @@ let show_manual ?internal_section format default_doc command_opt =
match command_opt with
| None ->
default_doc
| Some command ->
| Some command -> (
match List.Assoc.find_exn ~equal:InferCommand.equal !subcommands command with
| Some command_doc, _, _ ->
command_doc
| None, _, _ ->
L.(die InternalError) "No manual for internal command %s" (string_of_command command)
L.(die InternalError) "No manual for internal command %s" (string_of_command command) )
in
let pp_meta f meta =
match meta with "" -> () | meta -> F.fprintf f " $(i,%s)" (Cmdliner.Manpage.escape meta)
@ -1007,12 +1016,11 @@ let show_manual ?internal_section format default_doc command_opt =
match command_doc.manual_options with
| `Replace blocks ->
`S Cmdliner.Manpage.s_options :: blocks
| `Prepend blocks ->
| `Prepend blocks -> (
let hidden =
match internal_section with
| Some section ->
`S section
:: `P "Use at your own risk."
`S section :: `P "Use at your own risk."
:: List.concat_map ~f:block_of_desc (normalize_desc_list !hidden_descs_list)
| None ->
[]
@ -1026,11 +1034,13 @@ let show_manual ?internal_section format default_doc command_opt =
(fun section descs result ->
`S section
:: (if String.equal section Cmdliner.Manpage.s_options then blocks else [])
@ List.concat_map ~f:block_of_desc (normalize_desc_list descs) @ result )
@ List.concat_map ~f:block_of_desc (normalize_desc_list descs)
@ result )
!sections hidden
| None ->
`S Cmdliner.Manpage.s_options :: blocks
@ List.concat_map ~f:block_of_desc (normalize_desc_list !visible_descs_list) @ hidden
(`S Cmdliner.Manpage.s_options :: blocks)
@ List.concat_map ~f:block_of_desc (normalize_desc_list !visible_descs_list)
@ hidden )
in
let blocks =
[ `Blocks command_doc.manual_before_options

@ -41,8 +41,14 @@ val init_work_dir : string
- a documentation string
*)
type 'a t =
?deprecated:string list -> long:string -> ?short:char -> ?parse_mode:parse_mode
-> ?in_help:(InferCommand.t * string) list -> ?meta:string -> string -> 'a
?deprecated:string list
-> long:string
-> ?short:char
-> ?parse_mode:parse_mode
-> ?in_help:(InferCommand.t * string) list
-> ?meta:string
-> string
-> 'a
val mk_set : 'a ref -> 'a -> unit t
(** [mk_set variable value] defines a command line option which sets [variable] to [value]. *)
@ -55,7 +61,9 @@ val mk_bool : ?deprecated_no:string list -> ?default:bool -> ?f:(bool -> bool) -
either "Activates:" or "Deactivates:", so should be phrased accordingly. *)
val mk_bool_group :
?deprecated_no:string list -> ?default:bool -> ?f:(bool -> bool)
?deprecated_no:string list
-> ?default:bool
-> ?f:(bool -> bool)
-> (bool ref list -> bool ref list -> bool ref) t
(** [mk_bool_group children not_children] behaves as [mk_bool] with the addition that all the
[children] are also set and the [no_children] are unset. A child can be unset by including
@ -114,8 +122,12 @@ val mk_anon : unit -> string list ref
order they appeared on the command line. *)
val mk_rest_actions :
?parse_mode:parse_mode -> ?in_help:(InferCommand.t * string) list -> string -> usage:string
-> (string -> parse_mode) -> string list ref
?parse_mode:parse_mode
-> ?in_help:(InferCommand.t * string) list
-> string
-> usage:string
-> (string -> parse_mode)
-> string list ref
(** [mk_rest_actions doc ~usage command_to_parse_mode] defines a [string list ref] of the command
line arguments following ["--"], in the reverse order they appeared on the command line. [usage]
is the usage message in case of parse errors or if --help is passed. For example, calling
@ -127,13 +139,23 @@ val mk_rest_actions :
type command_doc
val mk_command_doc :
title:string -> section:int -> version:string -> date:string -> short_description:string
-> synopsis:Cmdliner.Manpage.block list -> description:Cmdliner.Manpage.block list
title:string
-> section:int
-> version:string
-> date:string
-> short_description:string
-> synopsis:Cmdliner.Manpage.block list
-> description:Cmdliner.Manpage.block list
-> ?options:[`Prepend of Cmdliner.Manpage.block list | `Replace of Cmdliner.Manpage.block list]
-> ?exit_status:Cmdliner.Manpage.block list -> ?environment:Cmdliner.Manpage.block list
-> ?files:Cmdliner.Manpage.block list -> ?notes:Cmdliner.Manpage.block list
-> ?bugs:Cmdliner.Manpage.block list -> ?examples:Cmdliner.Manpage.block list
-> see_also:Cmdliner.Manpage.block list -> string -> command_doc
-> ?exit_status:Cmdliner.Manpage.block list
-> ?environment:Cmdliner.Manpage.block list
-> ?files:Cmdliner.Manpage.block list
-> ?notes:Cmdliner.Manpage.block list
-> ?bugs:Cmdliner.Manpage.block list
-> ?examples:Cmdliner.Manpage.block list
-> see_also:Cmdliner.Manpage.block list
-> string
-> command_doc
(** [mk_command_doc ~title ~section ~version ~short_description ~synopsis ~description ~see_also
command_exe] records information about a command that is used to create its man page. A lot of
the concepts are taken from man-pages(7).
@ -152,9 +174,14 @@ val mk_command_doc :
*)
val mk_subcommand :
InferCommand.t -> ?on_unknown_arg:[`Add | `Skip | `Reject] -> name:string
-> ?deprecated_long:string -> ?parse_mode:parse_mode -> ?in_help:(InferCommand.t * string) list
-> command_doc option -> unit
InferCommand.t
-> ?on_unknown_arg:[`Add | `Skip | `Reject]
-> name:string
-> ?deprecated_long:string
-> ?parse_mode:parse_mode
-> ?in_help:(InferCommand.t * string) list
-> command_doc option
-> unit
(** [mk_subcommand command ~long command_doc] defines the subcommand [command]. A subcommand is
activated by passing [name], and by passing [--deprecated_long] if specified. A man page is
automatically generated for [command] based on the information in [command_doc], if available
@ -174,7 +201,10 @@ val extend_env_args : string list -> unit
(** [extend_env_args args] appends [args] to those passed via [args_env_var] *)
val parse :
?config_file:string -> usage:Arg.usage_msg -> parse_mode -> InferCommand.t option
?config_file:string
-> usage:Arg.usage_msg
-> parse_mode
-> InferCommand.t option
-> InferCommand.t option * (int -> 'a)
(** [parse ~usage parse_mode command] parses command line arguments as specified by preceding calls
to the [mk_*] functions, and returns:
@ -198,7 +228,10 @@ val is_env_var_set : string -> bool
(** [is_env_var_set var] is true if $[var]=1 *)
val show_manual :
?internal_section:string -> Cmdliner.Manpage.format -> command_doc -> InferCommand.t option
?internal_section:string
-> Cmdliner.Manpage.format
-> command_doc
-> InferCommand.t option
-> unit
(** Display the manual of [command] to the user, or [command_doc] if [command] is None. [format] is
used as for [Cmdliner.Manpage.print]. If [internal_section] is specified, add a section titled

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

Loading…
Cancel
Save