[ocamlformat] Upgrade to ocamlformat 0.4

Reviewed By: jvillard

Differential Revision: D7079161

fbshipit-source-id: 17b2f0c
master
Josh Berdine 7 years ago committed by Facebook Github Bot
parent 4b56e32a29
commit 3534838b73

@ -1,3 +1,3 @@
margin 100
sparse true
version 0.3
version 0.4

@ -284,7 +284,7 @@ let log_issue err_kind err_log loc (node_id, node_key) session ltr ?linters_def_
"@\n%a@\n@?"
(Exceptions.pp_err ~node_key loc err_kind error.name error.description error.ml_loc)
() ;
if err_kind <> Exceptions.Kerror then
if err_kind <> Exceptions.Kerror then (
let warn_str =
let pp fmt =
Format.fprintf fmt "%s %a" error.name.IssueType.unique_id Localise.pp_error_desc
@ -301,6 +301,6 @@ let log_issue err_kind err_log loc (node_id, node_key) session ltr ?linters_def_
| Exceptions.Kinfo | Exceptions.Kadvice | Exceptions.Klike ->
L.d_info
in
d warn_str ; L.d_ln ()
d warn_str ; L.d_ln () )
in
if should_print_now then print_now ()

@ -161,8 +161,8 @@ td.rowname { text-align:right; font-weight:bold; color:#444444; padding-right:2e
let node_text =
let pp fmt =
Format.fprintf fmt
"<span class='%s'>%s<span class='expansion'>node%d preds:%a succs:%a exn:%a %s%s</span></span>"
style_class display_name id (Pp.seq Format.pp_print_int) preds
"<span class='%s'>%s<span class='expansion'>node%d preds:%a succs:%a exn:%a \
%s%s</span></span>" style_class display_name id (Pp.seq Format.pp_print_int) preds
(Pp.seq Format.pp_print_int) succs (Pp.seq Format.pp_print_int) exn description
(if not isvisited then "\nNOT VISITED" else "")
in

@ -261,8 +261,8 @@ let deref_str_nil_argument_in_variadic_method pn total_args arg_number =
in
let problem_str =
Printf.sprintf
"could be %s which results in a call to %s with %d arguments instead of %d (%s indicates that the last argument of this variadic %s has been reached)"
nil_null
"could be %s which results in a call to %s with %d arguments instead of %d (%s indicates \
that the last argument of this variadic %s has been reached)" nil_null
(Typ.Procname.to_simplified_string pn)
arg_number (total_args - 1) nil_null function_method
in
@ -389,9 +389,11 @@ let desc_unsafe_guarded_by_access accessed_fld guarded_by_str loc =
in
let msg =
Format.asprintf
"The field %a is annotated with %a, but the lock %a is not held during the access to the field %s. Since the current method is non-private, it can be called from outside the current class without synchronization. Consider wrapping the access in a %s block or making the method private."
MF.pp_monospaced accessed_fld_str MF.pp_monospaced annot_str MF.pp_monospaced guarded_by_str
line_info syncronized_str
"The field %a is annotated with %a, but the lock %a is not held during the access to the \
field %s. Since the current method is non-private, it can be called from outside the \
current class without synchronization. Consider wrapping the access in a %s block or \
making the method private." MF.pp_monospaced accessed_fld_str MF.pp_monospaced annot_str
MF.pp_monospaced guarded_by_str line_info syncronized_str
in
{no_desc with descriptions= [msg]}
@ -403,10 +405,12 @@ let desc_fragment_retains_view fragment_typ fieldname fld_typ pname : error_desc
(format_typ fragment_typ) (format_field fieldname) (format_typ fld_typ) (format_method pname)
in
let consequences =
"If this Fragment is placed on the back stack, a reference to this (probably dead) View will be retained."
"If this Fragment is placed on the back stack, a reference to this (probably dead) View will \
be retained."
in
let advice =
"In general, it is a good idea to initialize View's in onCreateView, then nullify them in onDestroyView."
"In general, it is a good idea to initialize View's in onCreateView, then nullify them in \
onDestroyView."
in
{no_desc with descriptions= [problem; consequences; advice]}

@ -786,8 +786,8 @@ let specialize_with_block_args callee_pdesc pname_with_block_args block_args =
source_file
| None ->
Logging.die InternalError
"specialize_with_block_args ahould only be called with defined procedures, but we cannot find the captured file of procname %a"
Typ.Procname.pp pname
"specialize_with_block_args ahould only be called with defined procedures, but we \
cannot find the captured file of procname %a" Typ.Procname.pp pname
in
let resolved_attributes =
{ callee_attributes with

@ -96,11 +96,11 @@ let load_global () : t option =
let store_to_filename tenv tenv_filename =
Serialization.write_to_file tenv_serializer tenv_filename ~data:tenv ;
if Config.debug_mode then
if Config.debug_mode then (
let debug_filename = DB.filename_to_string (DB.filename_add_suffix tenv_filename ".debug") in
let out_channel = Out_channel.create debug_filename in
let fmt = Format.formatter_of_out_channel out_channel in
Format.fprintf fmt "%a" pp tenv ; Out_channel.close out_channel
Format.fprintf fmt "%a" pp tenv ; Out_channel.close out_channel )
let store source_file tenv = tenv_filename_of_source_file source_file |> store_to_filename tenv

@ -1248,8 +1248,15 @@ module Struct = struct
if Config.debug_mode then
(* change false to true to print the details of struct *)
F.fprintf f
"%a @\n\tfields: {%a@\n\t}@\n\tsupers: {%a@\n\t}@\n\tmethods: {%a@\n\t}@\n\tannots: {%a@\n\t}"
Name.pp name
"%a @\n\
\tfields: {%a@\n\
\t}@\n\
\tsupers: {%a@\n\
\t}@\n\
\tmethods: {%a@\n\
\t}@\n\
\tannots: {%a@\n\
\t}" Name.pp name
(Pp.seq (pp_field pe))
fields
(Pp.seq (fun f n -> F.fprintf f "@\n\t\t%a" Name.pp n))

@ -78,7 +78,7 @@ struct
let instr_ids = match CFG.instr_ids node with [] -> [(Sil.skip_instr, None)] | l -> l in
if debug then NodePrinter.start_session (CFG.underlying_node node) ;
let astate_post, inv_map_post = List.fold ~f:compute_post ~init:(pre, inv_map) instr_ids in
( if debug then
if debug then (
let instrs = List.map ~f:fst instr_ids in
L.d_strln
(Format.asprintf "PRE: %a@.INSTRS: %aPOST: %a@." Domain.pp pre
@ -90,7 +90,7 @@ struct
in
(inv_map'', Scheduler.schedule_succs work_queue node)
in
if InvariantMap.mem node_id inv_map then
if InvariantMap.mem node_id inv_map then (
let old_state = InvariantMap.find node_id inv_map in
let widened_pre =
if CFG.is_loop_head pdesc node then
@ -102,9 +102,10 @@ struct
let visit_count' = old_state.visit_count + 1 in
if visit_count' > Config.max_widens then
L.(die InternalError)
"Exceeded max widening threshold %d while analyzing %a. Please check your widening operator or increase the threshold"
Config.max_widens Typ.Procname.pp (Procdesc.get_proc_name pdesc) ;
update_inv_map widened_pre visit_count'
"Exceeded max widening threshold %d while analyzing %a. Please check your widening \
operator or increase the threshold" Config.max_widens Typ.Procname.pp
(Procdesc.get_proc_name pdesc) ;
update_inv_map widened_pre visit_count' )
else
(* first time visiting this node *)
let visit_count = 1 in

@ -30,13 +30,13 @@ struct
type extras = TransferFunctions.extras
let pp_pre_post pre post hil_instr node =
if Config.write_html then
if Config.write_html then (
let underyling_node = CFG.underlying_node node in
NodePrinter.start_session underyling_node ;
L.d_strln
(Format.asprintf "PRE: %a@.INSTR: %a@.POST: %a@." TransferFunctions.Domain.pp pre
HilInstr.pp hil_instr TransferFunctions.Domain.pp post) ;
NodePrinter.finish_session underyling_node
NodePrinter.finish_session underyling_node )
let is_java_unlock pname actuals =

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

@ -226,7 +226,7 @@ module IssuesJson = struct
if key.in_footprint && error_filter source_file key.err_desc key.err_name
&& should_report_source_file
&& should_report key.err_kind key.err_name key.err_desc err_data.err_class
then
then (
let kind = Exceptions.err_kind_string key.err_kind in
let bug_type = key.err_name.IssueType.unique_id in
let file = SourceFile.to_string source_file in
@ -278,7 +278,7 @@ module IssuesJson = struct
; access= err_data.access }
in
if not !is_first_item then pp "," else is_first_item := false ;
pp "%s@?" (Jsonbug_j.string_of_jsonbug bug)
pp "%s@?" (Jsonbug_j.string_of_jsonbug bug) )
(** Write bug report in JSON format *)

@ -191,7 +191,7 @@ let get_retain_cycles hpred tenv prop_ =
let exn_retain_cycle tenv hpred cycle =
let retain_cycle = desc_retain_cycle tenv cycle in
let cycle_dotty = Format.asprintf "%a" RetainCyclesType.pp_dotty cycle in
( if Config.debug_mode then
if Config.debug_mode then (
let rc_dotty_dir = Filename.concat Config.results_dir Config.retain_cycle_dotty_dir in
Utils.create_dir rc_dotty_dir ;
let rc_dotty_file = Filename.temp_file ~in_dir:rc_dotty_dir "rc" ".dot" in

@ -1039,7 +1039,7 @@ let check_junk ?original_prop pname tenv prop =
List.rev sigma_done
| hpred :: sigma_todo' ->
let entries = Sil.hpred_entries hpred in
if should_remove_hpred entries then
if should_remove_hpred entries then (
let part = if fp_part then "footprint" else "normal" in
L.d_strln (".... Prop with garbage in " ^ part ^ " part ....") ;
L.d_increase_indent 1 ;
@ -1159,7 +1159,7 @@ let check_junk ?original_prop pname tenv prop =
leaks_reported := alloc_attribute :: !leaks_reported )
in
if not ignore_leak then report_leak () ;
remove_junk_recursive sigma_done sigma_todo'
remove_junk_recursive sigma_done sigma_todo' )
else remove_junk_recursive (hpred :: sigma_done) sigma_todo'
in
remove_junk_recursive [] sigma

@ -249,7 +249,7 @@ module CheckJoinPre : InfoLossCheckerSig = struct
List.length es >= 1
| Exp.Var _ ->
if Int.equal Config.join_cond 0 then List.exists ~f:(Exp.equal Exp.zero) es
else if Dangling.check side e then
else if Dangling.check side e then (
let r = List.exists ~f:(fun e' -> not (Dangling.check side_op e')) es in
if r then (
L.d_str ".... Dangling Check (dang e:" ;
@ -258,7 +258,7 @@ module CheckJoinPre : InfoLossCheckerSig = struct
Sil.d_exp_list es ;
L.d_strln ") ...." ;
L.d_ln () ) ;
r
r )
else
let r = List.exists ~f:(Dangling.check side_op) es in
if r then (

@ -112,11 +112,11 @@ let print_stack_info = ref false
let strip_special_chars b =
let b = Bytes.of_string b in
let replace st c c' =
if Bytes.contains st c then
if Bytes.contains st c then (
let idx = String.index_exn (Bytes.to_string st) c in
try Bytes.set st idx c' ; st with Invalid_argument _ ->
L.internal_error "@\n@\nstrip_special_chars: Invalid argument!@\n@." ;
assert false
assert false )
else st
in
let s0 = replace b '(' 'B' in

@ -1150,11 +1150,11 @@ let explain_dereference_as_caller_expression proc_name tenv ?(use_buckets= false
if Pvar.is_global pv then
let dexp = exp_lv_dexp tenv node (Exp.Lvar pv) in
create_dereference_desc proc_name tenv ~use_buckets dexp deref_str actual_pre loc
else if Pvar.is_callee pv then
else if Pvar.is_callee pv then (
let position = find_formal_param_number pv_name in
if verbose then L.d_strln ("parameter number: " ^ string_of_int position) ;
explain_nth_function_parameter proc_name tenv use_buckets deref_str actual_pre position
pvar_off
pvar_off )
else if Attribute.has_dangling_uninit tenv spec_pre exp then
Localise.desc_uninitialized_dangling_pointer_deref deref_str (Pvar.to_string pv) loc
else Localise.no_desc

@ -153,14 +153,14 @@ and isel_match isel1 sub vars isel2 =
| (idx1, se1') :: isel1', (idx2, se2') :: isel2' ->
let idx2 = Sil.exp_sub (`Exp sub) idx2 in
let sanity_check = not (List.exists ~f:(fun id -> Sil.ident_in_exp id idx2) vars) in
if not sanity_check then
if not sanity_check then (
let pe = Pp.text in
L.internal_error "@[.... Sanity Check Failure while Matching Index-Strexps ....@\n" ;
L.internal_error "@[<4> IDX1: %a, STREXP1: %a@\n" (Sil.pp_exp_printenv pe) idx1
(Sil.pp_sexp pe) se1' ;
L.internal_error "@[<4> IDX2: %a, STREXP2: %a@\n@." (Sil.pp_exp_printenv pe) idx2
(Sil.pp_sexp pe) se2' ;
assert false
assert false )
else if Exp.equal idx1 idx2 then
match strexp_match se1' sub vars se2' with
| None ->

@ -102,10 +102,10 @@ let should_link ~target ~target_results_dir ~stats infer_out_src infer_out_dst =
let was_copied () =
let captured_src = Filename.concat infer_out_src Config.captured_dir_name in
let captured_dst = Filename.concat infer_out_dst Config.captured_dir_name in
if Sys.file_exists captured_src = `Yes && Sys.is_directory captured_src = `Yes then
if Sys.file_exists captured_src = `Yes && Sys.is_directory captured_src = `Yes then (
let captured_files = Array.to_list (Sys.readdir captured_src) in
num_captured_files := List.length captured_files ;
List.for_all ~f:(fun file -> check_file (Filename.concat captured_dst file)) captured_files
List.for_all ~f:(fun file -> check_file (Filename.concat captured_dst file)) captured_files )
else true
in
let was_modified () = String.Set.mem !modified_targets target in

@ -205,10 +205,10 @@ end = struct
let nodes_found stats = stats.max_length > 0 in
function
| Pstart (node, stats) ->
if stats_is_dummy stats then
if stats_is_dummy stats then (
let found = f node in
stats.max_length <- (if found then 1 else 0) ;
stats.linear_num <- 1.0
stats.linear_num <- 1.0 )
| Pnode (node, _, _, path, stats, _) ->
if stats_is_dummy stats then (
compute_stats do_calls f path ;
@ -227,7 +227,7 @@ end = struct
stats.max_length <- max stats1.max_length stats2.max_length ;
stats.linear_num <- stats1.linear_num +. stats2.linear_num )
| Pcall (path1, _, ExecCompleted path2, stats) ->
if stats_is_dummy stats then
if stats_is_dummy stats then (
let stats2 =
match do_calls with
| true ->
@ -244,12 +244,12 @@ end = struct
compute_stats do_calls f' path1 ; get_stats path1
in
stats.max_length <- stats1.max_length + stats2.max_length ;
stats.linear_num <- stats1.linear_num
stats.linear_num <- stats1.linear_num )
| Pcall (path, _, ExecSkipped _, stats) ->
if stats_is_dummy stats then
if stats_is_dummy stats then (
let stats1 = compute_stats do_calls f path ; get_stats path in
stats.max_length <- stats1.max_length ;
stats.linear_num <- stats1.linear_num
stats.linear_num <- stats1.linear_num )
end
(* End of module Invariant *)
@ -441,10 +441,10 @@ end = struct
F.fprintf fmt "(%a: %s)" (doit (n - 1)) path reason
in
let print_delayed () =
if not (PathMap.is_empty !delayed) then
if not (PathMap.is_empty !delayed) then (
let f path num = F.fprintf fmt "P%d = %a@\n" num (doit 1) path in
F.fprintf fmt "where@\n" ;
PathMap.iter f !delayed
PathMap.iter f !delayed )
in
add_delayed path ; doit 0 fmt path ; print_delayed ()

@ -358,7 +358,7 @@ let node_finish_session node =
(** Write html file for the procedure.
The boolean indicates whether to print whole seconds only *)
let write_proc_html pdesc =
if Config.write_html then
if Config.write_html then (
let pname = Procdesc.get_proc_name pdesc in
let source = (Procdesc.get_loc pdesc).file in
let nodes = List.sort ~cmp:Procdesc.Node.compare (Procdesc.get_nodes pdesc) in
@ -386,7 +386,7 @@ let write_proc_html pdesc =
()
| Some summary ->
Specs.pp_summary_html source Black fmt summary ;
Io_infer.Html.close (fd, fmt)
Io_infer.Html.close (fd, fmt) )
(** Creare a hash table mapping line numbers to the set of errors occurring on that line *)

@ -465,8 +465,9 @@ let rec create_strexp_of_type ~path tenv struct_init_mode (typ: Typ.t) len inst
-> (
if List.exists ~f:(fun (n, _) -> Typ.Name.equal n name) path then
L.die InternalError
"Ill-founded recursion in [create_strexp_of_type]: a sub-element of struct %a is also of type struct %a: %a:%a"
Typ.Name.pp name Typ.Name.pp name pp_path (List.rev path) Typ.Name.pp name ;
"Ill-founded recursion in [create_strexp_of_type]: a sub-element of struct %a is also \
of type struct %a: %a:%a" Typ.Name.pp name Typ.Name.pp name pp_path (List.rev path)
Typ.Name.pp name ;
match (struct_init_mode, Tenv.lookup tenv name) with
| Fld_init, Some {fields} ->
(* pass len as an accumulator, so that it is passed to create_strexp_of_type for the last
@ -2284,7 +2285,6 @@ let from_pi pi = set prop_emp ~pi
let from_sigma sigma = set prop_emp ~sigma
(** {2 Prop iterators} *)
(** Iterator state over sigma. *)

@ -876,7 +876,7 @@ let get_smt_key a p =
let check_atom tenv prop a0 =
let a = Prop.atom_normalize_prop tenv prop a0 in
let prop_no_fp = Prop.set prop ~pi_fp:[] ~sigma_fp:[] in
( if Config.smt_output then
if Config.smt_output then (
let key = get_smt_key a prop_no_fp in
let key_filename =
let source = (State.get_loc ()).file in

@ -181,7 +181,7 @@ let rec create_struct_values pname tenv orig_prop footprint_part kind max_stamp
| Tint _, _ | Tfloat _, _ | Tvoid, _ | Tfun _, _ | Tptr _, _ | TVar _, _ ->
fail t off __POS__
in
( if Config.trace_rearrange then
if Config.trace_rearrange then (
let _, se, _ = res in
L.d_strln "exiting create_struct_values, returning" ;
Sil.d_sexp se ;
@ -327,7 +327,7 @@ and array_case_analysis_index pname tenv orig_prop footprint_part kind max_stamp
let array_default = Sil.Earray (array_len, array_cont, inst_arr) in
let typ_default = Typ.mk_array ~default:typ_array typ_cont ?length:typ_array_len in
[([], array_default, typ_default)]
else if !Config.footprint then
else if !Config.footprint then (
let atoms, elem_se, elem_typ =
create_struct_values pname tenv orig_prop footprint_part kind max_stamp typ_cont off inst
in
@ -337,7 +337,7 @@ and array_case_analysis_index pname tenv orig_prop footprint_part kind max_stamp
in
let array_new = Sil.Earray (array_len, cont_new, inst_arr) in
let typ_new = Typ.mk_array ~default:typ_array elem_typ ?length:typ_array_len in
[(atoms, array_new, typ_new)]
[(atoms, array_new, typ_new)] )
else
let res_new =
if array_is_full then []

@ -68,8 +68,9 @@ let log_issue_deprecated ?(store_summary= false) err_kind proc_name ?loc ?node_i
Specs.store_summary summary
| None ->
L.(die InternalError)
"Trying to report error on procedure %a, but cannot because no summary exists for this procedure. Did you mean to log the error on the caller of %a instead?"
Typ.Procname.pp proc_name Typ.Procname.pp proc_name
"Trying to report error on procedure %a, but cannot because no summary exists for this \
procedure. Did you mean to log the error on the caller of %a instead?" Typ.Procname.pp
proc_name Typ.Procname.pp proc_name
let log_error = log_issue_from_summary Exceptions.Kerror

@ -791,7 +791,7 @@ let handle_objc_instance_method_call_or_skip pdesc tenv actual_pars path callee_
| _ ->
prop
in
if is_receiver_null then
if is_receiver_null then (
(* objective-c instance method with a null receiver just return objc_null(res). *)
let path = Paths.Path.add_description path path_description in
L.d_strln
@ -801,7 +801,7 @@ let handle_objc_instance_method_call_or_skip pdesc tenv actual_pars path callee_
we want to add the attribute OBJC_NULL to it so that we
can keep track of how this object became null,
so that in a NPE we can separate it into a different error type *)
[(add_objc_null_attribute_or_nullify_result pre, path)]
[(add_objc_null_attribute_or_nullify_result pre, path)] )
else
match force_objc_init_return_nil pdesc callee_pname tenv ret_id pre path receiver with
| [] ->

@ -419,7 +419,7 @@ let check_path_errors_in_post tenv caller_pname post post_path =
let check_attr atom =
match atom with
| Sil.Apred (Adiv0 path_pos, [e]) ->
if Prover.check_zero tenv e then
if Prover.check_zero tenv e then (
let desc =
Errdesc.explain_divide_by_zero tenv e (State.get_node ()) (State.get_loc ())
in
@ -431,7 +431,7 @@ let check_path_errors_in_post tenv caller_pname post post_path =
in
State.set_path new_path path_pos_opt ;
let exn = Exceptions.Divide_by_zero (desc, __POS__) in
Reporting.log_warning_deprecated caller_pname exn
Reporting.log_warning_deprecated caller_pname exn )
| _ ->
()
in
@ -964,7 +964,7 @@ let mk_actual_precondition tenv prop actual_params formal_params =
| f :: fpars', a :: apars' ->
(f, a) :: comb fpars' apars'
| [], _ ->
( if apars <> [] then
if apars <> [] then (
let str =
"more actual pars than formal pars in fun call ("
^ string_of_int (List.length actual_params) ^ " vs "
@ -1234,9 +1234,9 @@ let exe_call_postprocess tenv ret_id trace_call callee_pname callee_attrs loc re
let call_desc kind_opt = Localise.desc_precondition_not_met kind_opt callee_pname loc in
let res_with_path_idents =
if !Config.footprint then
if List.is_empty valid_res_cons_pre_missing then
(* no valid results where actual pre and missing are consistent *)
match deref_errors with
if List.is_empty valid_res_cons_pre_missing then (
match (* no valid results where actual pre and missing are consistent *)
deref_errors with
| error :: _
-> (
(* dereference error detected *)
@ -1304,7 +1304,7 @@ let exe_call_postprocess tenv ret_id trace_call callee_pname callee_attrs loc re
else call_desc None
in
trace_call CR_not_met ;
raise (Exceptions.Precondition_not_met (desc, __POS__))
raise (Exceptions.Precondition_not_met (desc, __POS__)) )
else
(* combine the valid results, and store diverging states *)
let process_valid_res vr =

@ -74,8 +74,10 @@ $(b,infer) $(b,capture) $(i,[options]) $(b,--) $(b,ndk-build) $(i,...)
$(b,infer) $(b,capture) $(i,[--no-xcpretty]) $(i,[options]) $(b,--) $(b,xcodebuild) $(i,...)|}
~description:
[ `P
"Capture the build command or compilation database specified on the command line: infer intercepts calls to the compiler to read source files, translate them into infer's intermediate representation, and store the result of the translation in the results directory."
]
"Capture the build command or compilation database specified on the command line: infer \
intercepts calls to the compiler to read source files, translate them into infer's \
intermediate representation, and store the result of the translation in the results \
directory." ]
~see_also:InferCommand.([Analyze; Compile; Run])
@ -85,20 +87,26 @@ let compile =
~synopsis:"$(b,infer) $(b,compile) $(b,--) $(i,[compile command])"
~description:
[ `P
"Intercepts compilation commands similarly to $(b,infer-capture), but simply execute these compilation commands and do not perform any translation of the source files. This can be useful to configure build systems or for debugging purposes."
]
"Intercepts compilation commands similarly to $(b,infer-capture), but simply execute \
these compilation commands and do not perform any translation of the source files. \
This can be useful to configure build systems or for debugging purposes." ]
~examples:
[ `P
"$(b,cmake)(1) hardcodes the absolute paths to the compiler inside the Makefiles it generates, which defeats the later capture of compilation commands by infer. Thus, to capture a CMake project, one should configure the project from within the infer build environment, for instance:"
"$(b,cmake)(1) hardcodes the absolute paths to the compiler inside the Makefiles it \
generates, which defeats the later capture of compilation commands by infer. Thus, to \
capture a CMake project, one should configure the project from within the infer build \
environment, for instance:"
; `Pre {| mkdir build && cd build
infer compile -- cmake ..
infer capture -- make|}
; `P
"The same solution can be used for projects whose \"./configure\" script hardcodes the paths to the compilers, for instance:"
"The same solution can be used for projects whose \"./configure\" script hardcodes the \
paths to the compilers, for instance:"
; `Pre {| infer compile -- ./configure
infer capture -- make|}
; `P
"Another solution for CMake projects is to use CMake's compilation databases, for instance:"
"Another solution for CMake projects is to use CMake's compilation databases, for \
instance:"
; `Pre
{| mkdir build && cd build
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=1 ..
@ -121,8 +129,8 @@ let explore =
~synopsis:{|$(b,infer) $(b,explore) $(i,[options])|}
~description:
[ `P
"Show the list of bugs on the console and explore symbolic program traces emitted by infer to explain a report. Can also generate an HTML report from a JSON report."
]
"Show the list of bugs on the console and explore symbolic program traces emitted by \
infer to explain a report. Can also generate an HTML report from a JSON report." ]
~see_also:InferCommand.([Report; Run])
@ -141,45 +149,64 @@ $(b,infer) $(i,[options]) $(b,--) $(b,compile command)
$(b,infer) $(i,[options])|}
~description:
[ `P
"Infer is a static analyzer. Given a collection of source files written in Java or in languages of the C family, and a command to build them, infer produces a list of potential issues."
"Infer is a static analyzer. Given a collection of source files written in Java or in \
languages of the C family, and a command to build them, infer produces a list of \
potential issues."
; `P
"Infer consists of a collection of tools referenced in the $(i,SEE ALSO) section of this manual. See their respective manuals for more information."
"Infer consists of a collection of tools referenced in the $(i,SEE ALSO) section of \
this manual. See their respective manuals for more information."
; `P
"When run without a subcommand, and if a compilation command is specified via the $(b,--) option or one of the $(b,--clang-compilation-database[-escaped]) options, then $(b,infer) behaves as $(b,infer-run)(1). Otherwise, $(b,infer) behaves as $(b,infer-analyze)(1)."
]
"When run without a subcommand, and if a compilation command is specified via the \
$(b,--) option or one of the $(b,--clang-compilation-database[-escaped]) options, then \
$(b,infer) behaves as $(b,infer-run)(1). Otherwise, $(b,infer) behaves as \
$(b,infer-analyze)(1)." ]
~options:
(`Prepend
[ `P "Every infer command accepts the arguments from all the other infer commands."
; `P
(Printf.sprintf
"Options are read from the $(b,%s) file, then from the $(b,%s) environment variable, then from the command line. Options in $(b,%s) take precedence over options in $(b,%s), and options passed on the command line take precedence over options in $(b,%s). See the $(i,%s) and $(i,%s) sections of this manual for more information."
inferconfig_file CLOpt.args_env_var CLOpt.args_env_var inferconfig_file
CLOpt.args_env_var Cmdliner.Manpage.s_environment Cmdliner.Manpage.s_files)
"Options are read from the $(b,%s) file, then from the $(b,%s) environment \
variable, then from the command line. Options in $(b,%s) take precedence over \
options in $(b,%s), and options passed on the command line take precedence over \
options in $(b,%s). See the $(i,%s) and $(i,%s) sections of this manual for more \
information." inferconfig_file CLOpt.args_env_var CLOpt.args_env_var
inferconfig_file CLOpt.args_env_var Cmdliner.Manpage.s_environment
Cmdliner.Manpage.s_files)
; `P
"Options can be specified inside an argument file $(i,file) by passing $(b,@)$(i,file) as argument. The format is one option per line, and enclosing single ' and double \" quotes are ignored."
"Options can be specified inside an argument file $(i,file) by passing \
$(b,@)$(i,file) as argument. The format is one option per line, and enclosing single \
' and double \" quotes are ignored."
; `P
"Options without a default value (e.g., $(b,--linter)) and options with list-like values (e.g., $(b,--Xbuck)) all have a corresponding $(b,--option-reset) flag that resets their values to nothing or the empty list, respectively. For instance, $(b,--Xbuck-reset) will cancel any previous $(b,--Xbuck) option passed to infer."
"Options without a default value (e.g., $(b,--linter)) and options with list-like \
values (e.g., $(b,--Xbuck)) all have a corresponding $(b,--option-reset) flag that \
resets their values to nothing or the empty list, respectively. For instance, \
$(b,--Xbuck-reset) will cancel any previous $(b,--Xbuck) option passed to infer."
; `P
"See the manuals of individual infer commands for details about their supported options. The following is a list of all the supported options (see also $(b,--help-full) for options reserved for internal use)."
])
"See the manuals of individual infer commands for details about their supported \
options. The following is a list of all the supported options (see also \
$(b,--help-full) for options reserved for internal use)." ])
~environment:
[ `P
(Printf.sprintf
"Extra arguments may be passed to all infer commands using the $(b,%s) environment variable (see the $(i,%s) section). $(b,%s) is expected to contain a string of %c-separated options. For instance, calling `%s=--debug^--print-logs infer` is equivalent to calling `infer --debug --print-logs`."
CLOpt.args_env_var Cmdliner.Manpage.s_options CLOpt.args_env_var CLOpt.env_var_sep
CLOpt.args_env_var)
"Extra arguments may be passed to all infer commands using the $(b,%s) environment \
variable (see the $(i,%s) section). $(b,%s) is expected to contain a string of \
%c-separated options. For instance, calling `%s=--debug^--print-logs infer` is \
equivalent to calling `infer --debug --print-logs`." CLOpt.args_env_var
Cmdliner.Manpage.s_options CLOpt.args_env_var CLOpt.env_var_sep CLOpt.args_env_var)
; `P
(Printf.sprintf "$(b,%s): Tells infer where to find the %s file. (See the %s section)"
inferconfig_env_var inferconfig_file Cmdliner.Manpage.s_files)
; `P
(Printf.sprintf
"If $(b,%s) is set to \"1\", then infer commands will exit with an error code in some cases when otherwise a simple warning would be emitted on stderr, for instance if a deprecated form of an option is used."
CLOpt.strict_mode_env_var) ]
"If $(b,%s) is set to \"1\", then infer commands will exit with an error code in \
some cases when otherwise a simple warning would be emitted on stderr, for instance \
if a deprecated form of an option is used." CLOpt.strict_mode_env_var) ]
~files:
[ `P
(Printf.sprintf
"$(b,%s) can be used to store infer options. Its format is that of a JSON record, where fields are infer long-form options, without their leading \"--\", and values depend on the type of the option:"
inferconfig_file)
"$(b,%s) can be used to store infer options. Its format is that of a JSON record, \
where fields are infer long-form options, without their leading \"--\", and values \
depend on the type of the option:" inferconfig_file)
; `Noblank
; `P "- for switches options, the value is a JSON boolean (true or false, without quotes)"
; `Noblank
@ -189,14 +216,14 @@ $(b,infer) $(i,[options])|}
; `Noblank
; `P
(Printf.sprintf
"- path options have string values, and are interpreted relative to the location of the %s file"
inferconfig_file)
"- path options have string values, and are interpreted relative to the location of \
the %s file" inferconfig_file)
; `Noblank
; `P "- cumulative options are JSON arrays of the appropriate type"
; `P
(Printf.sprintf
"Infer will look for an $(b,%s) file in the current directory, then its parent, etc., stopping at the first $(b,%s) file found."
inferconfig_file inferconfig_file)
"Infer will look for an $(b,%s) file in the current directory, then its parent, \
etc., stopping at the first $(b,%s) file found." inferconfig_file inferconfig_file)
; `P "Example:"
; `Pre
{| {
@ -211,10 +238,11 @@ let report =
~synopsis:"$(b,infer) $(b,report) $(i,[options]) [$(i,file.specs)...]"
~description:
[ `P
"Read, convert, and print .specs files in the results directory. Each spec is printed to standard output unless option -q is used."
"Read, convert, and print .specs files in the results directory. Each spec is printed \
to standard output unless option -q is used."
; `P
"If no specs file are passed on the command line, process all the .specs in the results directory."
]
"If no specs file are passed on the command line, process all the .specs in the results \
directory." ]
~see_also:InferCommand.([ReportDiff; Run])
@ -222,10 +250,13 @@ let reportdiff =
mk_command_doc ~title:"Infer Report Difference"
~short_description:"compute the differences between two infer reports"
~synopsis:
"$(b,infer) $(b,reportdiff) $(b,--report-current) $(i,file) $(b,--report-previous) $(i,file) $(i,[options])"
"$(b,infer) $(b,reportdiff) $(b,--report-current) $(i,file) $(b,--report-previous) \
$(i,file) $(i,[options])"
~description:
[ `P
"Given two infer reports $(i,previous) and $(i,current), compute the following three reports and store them inside the \"differential/\" subdirectory of the results directory:"
"Given two infer reports $(i,previous) and $(i,current), compute the following three \
reports and store them inside the \"differential/\" subdirectory of the results \
directory:"
; `Noblank
; `P
"- $(b,introduced.json) contains the issues found in $(i,current) but not $(i,previous);"
@ -233,7 +264,8 @@ let reportdiff =
; `P "- $(b,fixed.json) contains the issues found in $(i,previous) but not $(i,current);"
; `Noblank
; `P
"- $(b,preexisting.json) contains the issues found in both $(i,previous) and $(i,current)."
"- $(b,preexisting.json) contains the issues found in both $(i,previous) and \
$(i,current)."
; `P "All three files follow the same format as normal infer reports." ]
~see_also:InferCommand.([Report])
@ -244,8 +276,8 @@ let events =
~synopsis:{|$(b,infer) $(b,events)|}
~description:
[ `P
"Emit to stdout one JSON object per line, each describing a logged event happened during the execution of Infer"
]
"Emit to stdout one JSON object per line, each describing a logged event happened \
during the execution of Infer" ]
~see_also:InferCommand.([Report; Run])
@ -257,7 +289,8 @@ let run =
$(b,infer) $(i,[options]) $(b,--) $(i,compile command)|}
~description:
[ `P
"Calling \"$(b,infer) $(b,run) $(i,[options])\" is equivalent to performing the following sequence of commands:"
"Calling \"$(b,infer) $(b,run) $(i,[options])\" is equivalent to performing the \
following sequence of commands:"
; `Pre {|$(b,infer) $(b,capture) $(i,[options])
$(b,infer) $(b,analyze) $(i,[options])|} ]
~see_also:InferCommand.([Analyze; Capture; Report])

@ -477,7 +477,7 @@ let mk_string_list ?(default= []) ?(f= fun s -> s) ?(deprecated= []) ~long ?shor
let normalize_path_in_args_being_parsed ?(f= Fn.id) ~is_anon_arg str =
if Filename.is_relative str then
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
position in [!args_to_parse], as is the case e.g. when calling
@ -485,7 +485,7 @@ let normalize_path_in_args_being_parsed ?(f= Fn.id) ~is_anon_arg str =
let root = Unix.getcwd () in
let abs_path = Utils.filename_to_absolute ~root str in
!args_to_parse.((!arg_being_parsed + if is_anon_arg then 0 else 1)) <- f abs_path ;
abs_path
abs_path )
else str
@ -922,7 +922,7 @@ let parse ?config_file ~usage action initial_command =
in
let to_export =
let argv_to_export = decode_env_to_argv !args_to_export in
if argv_to_export <> [] then
if argv_to_export <> [] then (
(* We have to be careful not to add too much data to the environment because the size of the
environment contributes to the length of the command to be run. If the environment + CLI is
too big, running any command will fail with a cryptic "exit code 127" error. Use an argfile
@ -930,7 +930,7 @@ let parse ?config_file ~usage action initial_command =
let file = Filename.temp_file "args_" "" in
Out_channel.with_file file ~f:(fun oc -> Out_channel.output_lines oc argv_to_export) ;
if not !keep_args_file then Utils.unlink_file_on_exit file ;
"@" ^ file
"@" ^ file )
else ""
in
Unix.putenv ~key:args_env_var ~data:to_export ;

@ -614,12 +614,12 @@ and ( analysis_blacklist_files_containing_options
( mk_filtering_options ~suffix:"blacklist-files-containing"
~deprecated_suffix:["blacklist_files_containing"]
~help:
"blacklist files containing the specified string for the given analyzer (see $(b,--analyzer) for valid values)"
~meta:"string"
"blacklist files containing the specified string for the given analyzer (see \
$(b,--analyzer) for valid values)" ~meta:"string"
, mk_filtering_options ~suffix:"blacklist-path-regex" ~deprecated_suffix:["blacklist"]
~help:
"blacklist the analysis of files whose relative path matches the specified OCaml-style regex (to whitelist: $(b,--<analyzer>-whitelist-path-regex))"
~meta:"path_regex"
"blacklist the analysis of files whose relative path matches the specified OCaml-style \
regex (to whitelist: $(b,--<analyzer>-whitelist-path-regex))" ~meta:"path_regex"
, mk_filtering_options ~suffix:"whitelist-path-regex" ~deprecated_suffix:["whitelist"] ~help:""
~meta:"path_regex"
, mk_filtering_options ~suffix:"suppress-errors" ~deprecated_suffix:["suppress_errors"]
@ -660,8 +660,9 @@ and analyzer =
if equal_analyzer x y then Some s else None )
in
CLOpt.warnf
"WARNING: The analyzer '%s' is deprecated, use the '%s' subcommand instead:@\n@\n infer %s ..."
analyzer_str analyzer_str analyzer_str ;
"WARNING: The analyzer '%s' is deprecated, use the '%s' subcommand instead:@\n\
@\n \
infer %s ..." analyzer_str analyzer_str analyzer_str ;
x
| _ as x ->
x)
@ -698,7 +699,10 @@ and ( annotation_reachability
in
let annotation_reachability =
mk_checker ~default:true ~long:"annotation-reachability"
"the annotation reachability checker. Given a pair of source and sink annotation, e.g. @PerformanceCritical and @Expensive, this checker will warn whenever some method annotated with @PerformanceCritical calls, directly or indirectly, another method annotated with @Expensive"
"the annotation reachability checker. Given a pair of source and sink annotation, e.g. \
@PerformanceCritical and @Expensive, this checker will warn whenever some method annotated \
with @PerformanceCritical calls, directly or indirectly, another method annotated with \
@Expensive"
and biabduction =
mk_checker ~long:"biabduction" ~default:true
"the separation logic based bi-abduction analysis using the checkers framework"
@ -716,7 +720,8 @@ and ( annotation_reachability
"detects when Android fragments are not explicitly nullified before becoming unreabable"
and immutable_cast =
mk_checker ~long:"immutable-cast" ~default:true
"the detection of object cast from immutable type to mutable type. For instance, it will detect cast from ImmutableList to List, ImmutableMap to Map, and ImmutableSet to Set."
"the detection of object cast from immutable type to mutable type. For instance, it will \
detect cast from ImmutableList to List, ImmutableMap to Map, and ImmutableSet to Set."
and linters = mk_checker ~long:"linters" ~default:true "syntactic linters"
and litho = mk_checker ~long:"litho" "Experimental checkers supporting the Litho framework"
and liveness =
@ -724,7 +729,9 @@ and ( annotation_reachability
and ownership = mk_checker ~long:"ownership" ~default:false "the detection of C++ lifetime bugs"
and printf_args =
mk_checker ~long:"printf-args" ~default:true
"the detection of mismatch between the Java printf format strings and the argument types For, example, this checker will warn about the type error in `printf(\"Hello %d\", \"world\")`"
"the detection of mismatch between the Java printf format strings and the argument types \
For, example, this checker will warn about the type error in `printf(\"Hello %d\", \
\"world\")`"
and quandary = mk_checker ~long:"quandary" ~default:true "the quandary taint analysis"
and racerd =
mk_checker ~long:"racerd" ~deprecated:["-threadsafety"] ~default:true
@ -804,7 +811,8 @@ Example format: for custom annotations com.my.annotation.{Source1,Source2,Sink1}
and append_buck_flavors =
CLOpt.mk_string_list ~long:"append-buck-flavors"
~in_help:InferCommand.([(Capture, manual_buck_flavors)])
"Additional Buck flavors to append to targets discovered by the $(b,--buck-compilation-database) option."
"Additional Buck flavors to append to targets discovered by the \
$(b,--buck-compilation-database) option."
and array_level =
@ -840,8 +848,8 @@ and buck_build_args =
and buck_compilation_database_depth =
CLOpt.mk_int_opt ~long:"buck-compilation-database-depth"
~in_help:InferCommand.([(Capture, manual_buck_compilation_db)])
"Depth of dependencies used by the $(b,--buck-compilation-database deps) option. By default, all recursive dependencies are captured."
~meta:"int"
"Depth of dependencies used by the $(b,--buck-compilation-database deps) option. By default, \
all recursive dependencies are captured." ~meta:"int"
and buck_compilation_database =
@ -866,7 +874,8 @@ and changed_files_index =
CLOpt.mk_path_opt ~long:"changed-files-index"
~in_help:InferCommand.([(Analyze, manual_generic); (Diff, manual_generic)])
~meta:"file"
"Specify the file containing the list of source files from which reactive analysis should start. Source files should be specified relative to project root or be absolute"
"Specify the file containing the list of source files from which reactive analysis should \
start. Source files should be specified relative to project root or be absolute"
and check_version =
@ -892,12 +901,16 @@ and clang_frontend_action =
and clang_include_to_override_regex =
CLOpt.mk_string_opt ~long:"clang-include-to-override-regex"
~deprecated:["-clang-include-to-override"] ~meta:"dir_OCaml_regex"
"Use this option in the uncommon case where the normal compilation process overrides the location of internal compiler headers. This option should specify regular expression with the path to those headers so that infer can use its own clang internal headers instead."
"Use this option in the uncommon case where the normal compilation process overrides the \
location of internal compiler headers. This option should specify regular expression with \
the path to those headers so that infer can use its own clang internal headers instead."
and clang_ignore_regex =
CLOpt.mk_string_opt ~long:"clang-ignore-regex" ~meta:"dir_OCaml_regex"
"The files in this regex will be ignored in the compilation process and an empty file will be passed to clang instead. This is to be used with the buck flavour infer-capture-all to work around missing generated files."
"The files in this regex will be ignored in the compilation process and an empty file will be \
passed to clang instead. This is to be used with the buck flavour infer-capture-all to work \
around missing generated files."
and classpath = CLOpt.mk_string_opt ~long:"classpath" "Specify the Java classpath"
@ -917,13 +930,15 @@ and compilation_database_escaped =
CLOpt.mk_path_list ~long:"compilation-database-escaped"
~deprecated:["-clang-compilation-db-files-escaped"]
~in_help:InferCommand.([(Capture, manual_clang)])
"File that contain compilation commands where all entries are escaped for the shell, eg coming from Xcode (can be specified multiple times)"
"File that contain compilation commands where all entries are escaped for the shell, eg \
coming from Xcode (can be specified multiple times)"
and compute_analytics =
CLOpt.mk_bool ~long:"compute-analytics" ~default:false
~in_help:InferCommand.([(Capture, manual_clang); (Run, manual_clang)])
"Emit analytics as info-level issues, like component kit line count and component kit file cyclomatic complexity"
"Emit analytics as info-level issues, like component kit line count and component kit file \
cyclomatic complexity"
(** Continue the capture for reactive mode:
@ -931,26 +946,31 @@ and compute_analytics =
and continue =
CLOpt.mk_bool ~deprecated:["continue"] ~long:"continue"
~in_help:InferCommand.([(Analyze, manual_generic)])
"Continue the capture for the reactive analysis, increasing the changed files/procedures. (If a procedure was changed beforehand, keep the changed marking.)"
"Continue the capture for the reactive analysis, increasing the changed files/procedures. (If \
a procedure was changed beforehand, keep the changed marking.)"
and current_to_previous_script =
CLOpt.mk_string_opt ~long:"current-to-previous-script"
~in_help:InferCommand.([(Diff, manual_generic)])
~meta:"shell"
"Specify a script to checkout a previous version of the project to compare against, assuming we are on the current version already."
"Specify a script to checkout a previous version of the project to compare against, assuming \
we are on the current version already."
and cxx_infer_headers =
CLOpt.mk_bool ~long:"cxx-infer-headers" ~default:true
~in_help:InferCommand.([(Capture, manual_clang)])
"Include C++ header models during compilation. Infer swaps some C++ headers for its own in order to get a better model of, eg, the standard library. This can sometimes cause compilation failures."
"Include C++ header models during compilation. Infer swaps some C++ headers for its own in \
order to get a better model of, eg, the standard library. This can sometimes cause \
compilation failures."
and cxx_scope_guards =
CLOpt.mk_json ~long:"cxx-scope-guards"
~in_help:InferCommand.([(Analyze, manual_clang)])
"Specify scope guard classes that can be read only by destructors without being reported as dead stores."
"Specify scope guard classes that can be read only by destructors without being reported as \
dead stores."
and cxx =
@ -1040,7 +1060,9 @@ and ( bo_debug
let debug =
CLOpt.mk_bool_group ~deprecated:["debug"; "-stats"] ~long:"debug" ~short:'g'
~in_help:all_generic_manuals
"Debug mode (also sets $(b,--debug-level 2), $(b,--developer-mode), $(b,--no-filtering), $(b,--print-buckets), $(b,--print-types), $(b,--reports-include-ml-loc), $(b,--no-only-cheap-debug), $(b,--trace-error), $(b,--write-dotty), $(b,--write-html))"
"Debug mode (also sets $(b,--debug-level 2), $(b,--developer-mode), $(b,--no-filtering), \
$(b,--print-buckets), $(b,--print-types), $(b,--reports-include-ml-loc), \
$(b,--no-only-cheap-debug), $(b,--trace-error), $(b,--write-dotty), $(b,--write-html))"
~f:(fun debug ->
if debug then set_debug_level 2 else set_debug_level 0 ;
CommandLineOption.keep_args_file := debug ;
@ -1061,8 +1083,10 @@ and ( bo_debug
- 2: very verbose debugging enabled|}
and debug_exceptions =
CLOpt.mk_bool_group ~long:"debug-exceptions"
"Generate lightweight debugging information: just print the internal exceptions during analysis (also sets $(b,--developer-mode), $(b,--no-filtering), $(b,--print-buckets), $(b,--reports-include-ml-loc))"
[developer_mode; print_buckets; reports_include_ml_loc] [filtering; keep_going]
"Generate lightweight debugging information: just print the internal exceptions during \
analysis (also sets $(b,--developer-mode), $(b,--no-filtering), $(b,--print-buckets), \
$(b,--reports-include-ml-loc))" [developer_mode; print_buckets; reports_include_ml_loc]
[filtering; keep_going]
and default_linters =
CLOpt.mk_bool ~long:"default-linters"
~in_help:InferCommand.([(Capture, manual_clang_linters)])
@ -1070,8 +1094,8 @@ and ( bo_debug
and frontend_tests =
CLOpt.mk_bool_group ~long:"frontend-tests"
~in_help:InferCommand.([(Capture, manual_clang)])
"Save filename.ext.test.dot with the cfg in dotty format for frontend tests (also sets $(b,--print-types))"
[print_types] []
"Save filename.ext.test.dot with the cfg in dotty format for frontend tests (also sets \
$(b,--print-types))" [print_types] []
and models_mode =
CLOpt.mk_bool_group ~long:"models-mode" "Mode for analyzing the models" [] [keep_going]
and print_logs =
@ -1087,7 +1111,9 @@ and ( bo_debug
let linters_developer_mode =
CLOpt.mk_bool_group ~long:"linters-developer-mode"
~in_help:InferCommand.([(Capture, manual_clang_linters)])
"Debug mode for developing new linters. (Sets the analyzer to $(b,linters); also sets $(b,--debug), $(b,--debug-level-linters 2), $(b,--developer-mode), and unsets $(b,--allowed-failures) and $(b,--default-linters)."
"Debug mode for developing new linters. (Sets the analyzer to $(b,linters); also sets \
$(b,--debug), $(b,--debug-level-linters 2), $(b,--developer-mode), and unsets \
$(b,--allowed-failures) and $(b,--default-linters)."
~f:(fun debug ->
debug_level_linters := if debug then 2 else 0 ;
debug )
@ -1120,18 +1146,22 @@ and ( bo_debug
and dependencies =
CLOpt.mk_bool ~deprecated:["dependencies"] ~long:"dependencies"
~in_help:InferCommand.([(Capture, manual_java)])
"Translate all the dependencies during the capture. The classes in the given jar file will be translated. No sources needed."
"Translate all the dependencies during the capture. The classes in the given jar file will be \
translated. No sources needed."
and differential_filter_files =
CLOpt.mk_string_opt ~long:"differential-filter-files"
~in_help:InferCommand.([(Report, manual_generic)])
"Specify the file containing the list of source files for which a differential report is desired. Source files should be specified relative to project root or be absolute"
"Specify the file containing the list of source files for which a differential report is \
desired. Source files should be specified relative to project root or be absolute"
and differential_filter_set =
CLOpt.mk_symbol_seq ~long:"differential-filter-set" ~eq:PVariant.( = )
"Specify which set of the differential results is filtered with the modified files provided through the $(b,--differential-modified-files) argument. By default it is applied to all sets ($(b,introduced), $(b,fixed), and $(b,preexisting))"
"Specify which set of the differential results is filtered with the modified files provided \
through the $(b,--differential-modified-files) argument. By default it is applied to all \
sets ($(b,introduced), $(b,fixed), and $(b,preexisting))"
~symbols:[("introduced", `Introduced); ("fixed", `Fixed); ("preexisting", `Preexisting)]
~default:[`Introduced; `Fixed; `Preexisting]
@ -1157,10 +1187,19 @@ and () =
mk false ~default:disabled_issues_ids ~long:"disable-issue-type"
~deprecated:["disable_checks"; "-disable-checks"]
(Printf.sprintf
"Do not show reports coming from this type of issue. Each checker can report a range of issue types. This option provides fine-grained filtering over which types of issue should be reported once the checkers have run. In particular, note that disabling issue types does not make the corresponding checker not run.\n By default, the following issue types are disabled: %s.\n\n See also $(b,--report-issue-type).\n"
"Do not show reports coming from this type of issue. Each checker can report a range of \
issue types. This option provides fine-grained filtering over which types of issue should \
be reported once the checkers have run. In particular, note that disabling issue types \
does not make the corresponding checker not run.\n \
By default, the following issue types are disabled: %s.\n\
\n \
See also $(b,--report-issue-type).\n\
"
(String.concat ~sep:", " disabled_issues_ids)) ;
mk true ~long:"enable-issue-type" ~deprecated:["enable_checks"; "-enable-checks"]
"Show reports coming from this type of issue. By default, all issue types are enabled except the ones listed in $(b,--disable-issue-type). Note that enabling issue types does not make the corresponding checker run; see individual checker options to turn them on or off."
"Show reports coming from this type of issue. By default, all issue types are enabled except \
the ones listed in $(b,--disable-issue-type). Note that enabling issue types does not make \
the corresponding checker run; see individual checker options to turn them on or off."
and dotty_cfg_libs =
@ -1228,13 +1267,23 @@ and filter_paths =
and filter_report =
CLOpt.mk_string_list ~long:"filter-report"
~in_help:InferCommand.([(Report, manual_generic); (Run, manual_generic)])
"Specify a filter for issues to report. If multiple filters are specified, they are applied in the order in which they are specified. Each filter is applied to each issue detected, and only issues which are accepted by all filters are reported. Each filter is of the form: `<issue_type_regex>:<filename_regex>:<reason_string>`. The first two components are OCaml Str regular expressions, with an optional `!` character prefix. If a regex has a `!` prefix, the polarity is inverted, and the filter becomes a \"blacklist\" instead of a \"whitelist\". Each filter is interpreted as an implication: an issue matches if it does not match the `issue_type_regex` or if it does match the `filename_regex`. The filenames that are tested by the regex are relative to the `--project-root` directory. The `<reason_string>` is a non-empty string used to explain why the issue was filtered."
"Specify a filter for issues to report. If multiple filters are specified, they are applied \
in the order in which they are specified. Each filter is applied to each issue detected, and \
only issues which are accepted by all filters are reported. Each filter is of the form: \
`<issue_type_regex>:<filename_regex>:<reason_string>`. The first two components are OCaml \
Str regular expressions, with an optional `!` character prefix. If a regex has a `!` prefix, \
the polarity is inverted, and the filter becomes a \"blacklist\" instead of a \"whitelist\". \
Each filter is interpreted as an implication: an issue matches if it does not match the \
`issue_type_regex` or if it does match the `filename_regex`. The filenames that are tested \
by the regex are relative to the `--project-root` directory. The `<reason_string>` is a \
non-empty string used to explain why the issue was filtered."
and flavors =
CLOpt.mk_bool ~deprecated:["-use-flavors"] ~long:"flavors"
~in_help:InferCommand.([(Capture, manual_buck_flavors)])
"Buck integration using Buck flavors (clang only), eg $(i,`infer --flavors -- buck build //foo:bar#infer`)"
"Buck integration using Buck flavors (clang only), eg $(i,`infer --flavors -- buck build \
//foo:bar#infer`)"
and force_delete_results_dir =
@ -1245,7 +1294,8 @@ and force_delete_results_dir =
; (Compile, manual_generic)
; (Diff, manual_generic)
; (Run, manual_generic) ])
"Do not refuse to delete the results directory if it doesn't look like an infer results directory."
"Do not refuse to delete the results directory if it doesn't look like an infer results \
directory."
and force_integration =
@ -1262,7 +1312,8 @@ and from_json_report =
CLOpt.mk_path_opt ~long:"from-json-report"
~in_help:InferCommand.([(Report, manual_generic)])
~meta:"report.json"
"Load analysis results from a report file (default is to load the results from the specs files generated by the analysis)."
"Load analysis results from a report file (default is to load the results from the specs \
files generated by the analysis)."
and frontend_stats =
@ -1274,7 +1325,8 @@ and gen_previous_build_command_script =
CLOpt.mk_string_opt ~long:"gen-previous-build-command-script"
~in_help:InferCommand.([(Diff, manual_generic)])
~meta:"shell"
"Specify a script that outputs the build command to capture in the previous version of the project. The script should output the command on stdout. For example \"echo make\"."
"Specify a script that outputs the build command to capture in the previous version of the \
project. The script should output the command on stdout. For example \"echo make\"."
and generated_classes =
@ -1305,7 +1357,8 @@ and help_format =
~symbols:[("auto", `Auto); ("groff", `Groff); ("pager", `Pager); ("plain", `Plain)]
~eq:PVariant.( = ) ~default:`Auto
~in_help:(List.map InferCommand.all_commands ~f:(fun command -> (command, manual_generic)))
"Show this help in the specified format. $(b,auto) sets the format to $(b,plain) if the environment variable $(b,TERM) is \"dumb\" or undefined, and to $(b,pager) otherwise."
"Show this help in the specified format. $(b,auto) sets the format to $(b,plain) if the \
environment variable $(b,TERM) is \"dumb\" or undefined, and to $(b,pager) otherwise."
and html =
@ -1316,7 +1369,8 @@ and html =
and icfg_dotty_outfile =
CLOpt.mk_path_opt ~long:"icfg-dotty-outfile" ~meta:"path"
"If set, specifies path where .dot file should be written, it overrides the path for all other options that would generate icfg file otherwise"
"If set, specifies path where .dot file should be written, it overrides the path for all \
other options that would generate icfg file otherwise"
and ignore_trivial_traces =
@ -1338,7 +1392,8 @@ and iphoneos_target_sdk_version =
and iphoneos_target_sdk_version_path_regex =
CLOpt.mk_string_list ~long:"iphoneos-target-sdk-version-path-regex"
~in_help:InferCommand.([(Capture, manual_clang_linters)])
"To pass a specific target SDK version to use for iphoneos in a particular path, with the format path:version (can be specified multiple times)"
"To pass a specific target SDK version to use for iphoneos in a particular path, with the \
format path:version (can be specified multiple times)"
and issues_fields =
@ -1367,7 +1422,8 @@ and issues_txt =
and iterations =
CLOpt.mk_int ~deprecated:["iterations"] ~long:"iterations" ~default:1 ~meta:"int"
"Specify the maximum number of operations for each function, expressed as a multiple of symbolic operations and a multiple of seconds of elapsed time"
"Specify the maximum number of operations for each function, expressed as a multiple of \
symbolic operations and a multiple of seconds of elapsed time"
and java_jar_compiler =
@ -1404,7 +1460,8 @@ and log_file =
and linter =
CLOpt.mk_string_opt ~long:"linter"
~in_help:InferCommand.([(Capture, manual_clang_linters)])
"From the linters available, only run this one linter. (Useful together with $(b,--linters-developer-mode))"
"From the linters available, only run this one linter. (Useful together with \
$(b,--linters-developer-mode))"
and linters_def_file =
@ -1421,7 +1478,8 @@ and linters_def_folder =
in
let () =
CLOpt.mk_set linters_def_folder [] ~long:"reset-linters-def-folder"
"Reset the list of folders containing linters definitions to be empty (see $(b,linters-def-folder))."
"Reset the list of folders containing linters definitions to be empty (see \
$(b,linters-def-folder))."
in
linters_def_folder
@ -1429,7 +1487,9 @@ and linters_def_folder =
and linters_doc_url =
CLOpt.mk_string_list ~long:"linters-doc-url"
~in_help:InferCommand.([(Capture, manual_clang_linters)])
"Specify custom documentation URL for some linter that overrides the default one. Useful if your project has specific ways of fixing a lint error that is not true in general or public info. Format: linter_name:doc_url."
"Specify custom documentation URL for some linter that overrides the default one. Useful if \
your project has specific ways of fixing a lint error that is not true in general or public \
info. Format: linter_name:doc_url."
and linters_ignore_clang_failures =
@ -1449,7 +1509,8 @@ and load_average =
CLOpt.mk_float_opt ~long:"load-average" ~short:'l'
~in_help:InferCommand.([(Capture, manual_generic)])
~meta:"float"
"Do not start new parallel jobs if the load average is greater than that specified (Buck and make only)"
"Do not start new parallel jobs if the load average is greater than that specified (Buck and \
make only)"
and margin =
@ -1460,7 +1521,8 @@ and margin =
and max_nesting =
CLOpt.mk_int_opt ~long:"max-nesting"
~in_help:InferCommand.([(Explore, manual_generic)])
"Level of nested procedure calls to show. Trace elements beyond the maximum nesting level are skipped. If omitted, all levels are shown."
"Level of nested procedure calls to show. Trace elements beyond the maximum nesting level are \
skipped. If omitted, all levels are shown."
and merge =
@ -1507,15 +1569,16 @@ and only_show =
and passthroughs =
CLOpt.mk_bool ~long:"passthroughs" ~default:false
"In error traces, show intermediate steps that propagate data. When false, error traces are shorter and show only direct flow via souces/sinks"
"In error traces, show intermediate steps that propagate data. When false, error traces are \
shorter and show only direct flow via souces/sinks"
and patterns_modeled_expensive =
let long = "modeled-expensive" in
( long
, CLOpt.mk_json ~deprecated:["modeled_expensive"] ~long
"Matcher or list of matchers for methods that should be considered expensive by the performance critical checker."
)
"Matcher or list of matchers for methods that should be considered expensive by the \
performance critical checker." )
and patterns_never_returning_null =
@ -1529,8 +1592,8 @@ and patterns_skip_implementation =
let long = "skip-implementation" in
( long
, CLOpt.mk_json ~long
"Matcher or list of matchers for names of files where we only want to translate the method declaration, skipping the body of the methods (Java only)."
)
"Matcher or list of matchers for names of files where we only want to translate the method \
declaration, skipping the body of the methods (Java only)." )
and patterns_skip_translation =
@ -1560,7 +1623,10 @@ and previous_to_current_script =
CLOpt.mk_string_opt ~long:"previous-to-current-script"
~in_help:InferCommand.([(Diff, manual_generic)])
~meta:"shell"
"Specify a script to checkout the current version of the project. The project is supposed to already be at that current version when running $(b,infer diff); the script is used after having analyzed the current and previous versions of the project, to restore the project to the current version."
"Specify a script to checkout the current version of the project. The project is supposed to \
already be at that current version when running $(b,infer diff); the script is used after \
having analyzed the current and previous versions of the project, to restore the project to \
the current version."
and print_active_checkers =
@ -1587,7 +1653,9 @@ and print_using_diff =
and procedures_per_process =
CLOpt.mk_int ~long:"procedures-per-process" ~default:1000 ~meta:"int"
"Specify the number of procedures to analyze per process when using $(b,--per-procedure-parallelism). If 0 is specified, each file is divided into $(b,--jobs) groups of procedures."
"Specify the number of procedures to analyze per process when using \
$(b,--per-procedure-parallelism). If 0 is specified, each file is divided into $(b,--jobs) \
groups of procedures."
and procs_csv =
@ -1652,7 +1720,8 @@ and racerd_use_path_stability =
and reactive =
CLOpt.mk_bool ~deprecated:["reactive"] ~long:"reactive" ~short:'r'
~in_help:InferCommand.([(Analyze, manual_generic)])
"Reactive mode: the analysis starts from the files captured since the $(i,infer) command started"
"Reactive mode: the analysis starts from the files captured since the $(i,infer) command \
started"
and reactive_capture =
@ -1687,7 +1756,9 @@ and report_hook =
~in_help:InferCommand.([(Analyze, manual_generic); (Run, manual_generic)])
~default:(lib_dir ^/ "python" ^/ "report.py")
~meta:"script"
"Specify a script to be executed after the analysis results are written. This script will be passed, $(b,--issues-json), $(b,--issues-txt), $(b,--issues-xml), $(b,--project-root), and $(b,--results-dir)."
"Specify a script to be executed after the analysis results are written. This script will be \
passed, $(b,--issues-json), $(b,--issues-txt), $(b,--issues-xml), $(b,--project-root), and \
$(b,--results-dir)."
and report_previous =
@ -1732,7 +1803,8 @@ and select =
and siof_safe_methods =
CLOpt.mk_string_list ~long:"siof-safe-methods"
~in_help:InferCommand.([(Analyze, manual_siof)])
"Methods that are SIOF-safe; \"foo::bar\" will match \"foo::bar()\", \"foo<int>::bar()\", etc. (can be specified multiple times)"
"Methods that are SIOF-safe; \"foo::bar\" will match \"foo::bar()\", \"foo<int>::bar()\", \
etc. (can be specified multiple times)"
and skip_analysis_in_path =
@ -1823,14 +1895,18 @@ and stacktrace =
CLOpt.mk_path_opt ~deprecated:["st"] ~long:"stacktrace"
~in_help:InferCommand.([(Analyze, manual_crashcontext)])
~meta:"file"
"File path containing a json-encoded Java crash stacktrace. Used to guide the analysis (only with '-a crashcontext'). See tests/codetoanalyze/java/crashcontext/*.json for examples of the expected format."
"File path containing a json-encoded Java crash stacktrace. Used to guide the analysis (only \
with '-a crashcontext'). See tests/codetoanalyze/java/crashcontext/*.json for examples of \
the expected format."
and stacktraces_dir =
CLOpt.mk_path_opt ~long:"stacktraces-dir"
~in_help:InferCommand.([(Analyze, manual_crashcontext)])
~meta:"dir"
"Directory path containing multiple json-encoded Java crash stacktraces. Used to guide the analysis (only with '-a crashcontext'). See tests/codetoanalyze/java/crashcontext/*.json for examples of the expected format."
"Directory path containing multiple json-encoded Java crash stacktraces. Used to guide the \
analysis (only with '-a crashcontext'). See tests/codetoanalyze/java/crashcontext/*.json \
for examples of the expected format."
and stats_report =
@ -1879,7 +1955,8 @@ and trace_rearrange =
and tracing =
CLOpt.mk_bool ~deprecated:["tracing"] ~long:"tracing"
"Report error traces for runtime exceptions (Java only): generate preconditions for runtimeexceptions in Java and report errors for public methods which throw runtime exceptions"
"Report error traces for runtime exceptions (Java only): generate preconditions for \
runtimeexceptions in Java and report errors for public methods which throw runtime exceptions"
and tv_commit =
@ -1947,7 +2024,8 @@ and xcode_developer_dir =
and xcpretty =
CLOpt.mk_bool ~long:"xcpretty" ~default:false
~in_help:InferCommand.([(Capture, manual_clang)])
"Infer will use xcpretty together with xcodebuild to analyze an iOS app. xcpretty just needs to be in the path, infer command is still just $(i,`infer -- <xcodebuild command>`)."
"Infer will use xcpretty together with xcodebuild to analyze an iOS app. xcpretty just needs \
to be in the path, infer command is still just $(i,`infer -- <xcodebuild command>`)."
(* The "rest" args must appear after "--" on the command line, and hence after other args, so they
@ -1961,7 +2039,7 @@ let javac_classes_out =
needed but the tests break without this for now. See discussion in D4397716. *)
~default:CLOpt.init_work_dir
~f:(fun classes_out ->
( if !buck then
if !buck then (
let classes_out_infer = resolve classes_out ^/ buck_results_dir_name in
(* extend env var args to pass args to children that do not receive the rest args *)
CLOpt.extend_env_args ["--results-dir"; classes_out_infer] ;
@ -1973,7 +2051,7 @@ let javac_classes_out =
and _ =
CLOpt.mk_string_opt ~parse_mode:CLOpt.Javac ~deprecated:["classpath"; "cp"] ~long:""
~f:(fun classpath ->
( if !buck then
if !buck then (
let paths = String.split classpath ~on:':' in
let files = List.filter paths ~f:(fun path -> Sys.is_file path = `Yes) in
CLOpt.extend_env_args (List.concat_map files ~f:(fun file -> ["--specs-library"; file])) ;
@ -2167,8 +2245,8 @@ let process_iphoneos_target_sdk_version_path_regex args =
{path= Str.regexp path; version}
| None ->
L.(die UserError)
"Incorrect format for the option iphoneos-target-sdk_version-path-regex. The correct format is path:version but got %s"
arg
"Incorrect format for the option iphoneos-target-sdk_version-path-regex. The correct \
format is path:version but got %s" arg
in
List.map ~f:process_iphoneos_target_sdk_version_path_regex args
@ -2182,8 +2260,8 @@ let process_linters_doc_url args =
{linter; doc_url}
| None ->
L.(die UserError)
"Incorrect format for the option linters-doc-url. The correct format is linter:doc_url but got %s"
arg
"Incorrect format for the option linters-doc-url. The correct format is linter:doc_url \
but got %s" arg
in
List.map ~f:linters_doc_url args
@ -2664,7 +2742,10 @@ let clang_frontend_action_string =
let dynamic_dispatch =
CLOpt.mk_bool ~long:"dynamic-dispatch" ~default:biabduction
"Specify treatment of dynamic dispatch in Java code: false 'none' treats dynamic dispatch as a call to unknown code and true triggers lazy dynamic dispatch. The latter mode follows the JVM semantics and creates procedure descriptions during symbolic execution using the type information found in the abstract state"
"Specify treatment of dynamic dispatch in Java code: false 'none' treats dynamic dispatch as \
a call to unknown code and true triggers lazy dynamic dispatch. The latter mode follows the \
JVM semantics and creates procedure descriptions during symbolic execution using the type \
information found in the abstract state"
~in_help:InferCommand.([(Analyze, manual_java)])

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

@ -15,14 +15,14 @@ open! IStd
(** apply a map function for escape sequences *)
let escape_map map_fun s =
let needs_escape = String.exists ~f:(fun c -> Option.is_some (map_fun c)) s in
if needs_escape then
if needs_escape then (
let len = String.length s in
let buf = Buffer.create len in
for i = 0 to len - 1 do
let c = String.unsafe_get s i in
match map_fun c with None -> Buffer.add_char buf c | Some s' -> Buffer.add_string buf s'
done ;
Buffer.contents buf
Buffer.contents buf )
else (* not escaping anything, so don't waste memory on a copy of the string *)
s

@ -313,7 +313,9 @@ let setup_log_file () =
reset_formatters () ;
if CLOpt.is_originator && preexisting_logfile then
phase
"============================================================@\n= New infer execution begins@\n============================================================"
"============================================================@\n\
= New infer execution begins@\n\
============================================================"
(** type of printable elements *)

@ -21,4 +21,3 @@ val start_child : f:('a -> unit) -> pool:t -> 'a -> unit
val wait_all : t -> unit
(** Wait until all the currently executing processes terminate *)

@ -6,5 +6,6 @@
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*)
val in_child : bool ref
(** Keep track of whether the current execution is in a child process *)

@ -43,8 +43,9 @@ let remove_results_dir () =
if not Config.force_delete_results_dir then
Result.iter_error (is_results_dir ~check_correct_version:false ()) ~f:(fun err ->
L.(die UserError)
"ERROR: '%s' exists but does not seem to be an infer results directory: %s@\nERROR: Please delete '%s' and try again@."
Config.results_dir err Config.results_dir ) ;
"ERROR: '%s' exists but does not seem to be an infer results directory: %s@\n\
ERROR: Please delete '%s' and try again@." Config.results_dir err Config.results_dir
) ;
Utils.rmtree Config.results_dir ) ;
RunState.reset ()

@ -45,8 +45,10 @@ let load_and_validate () =
(fun err_msg ->
Error
(Printf.sprintf
"Incompatible results directory '%s':\n%s\nWas '%s' created using an older version of infer?"
Config.results_dir err_msg Config.results_dir) )
"Incompatible results directory '%s':\n\
%s\n\
Was '%s' created using an older version of infer?" Config.results_dir err_msg
Config.results_dir) )
msg
in
if Sys.file_exists state_file_path <> `Yes then error "save state not found"

@ -47,13 +47,15 @@ let create_serializer (key: Key.t) : 'a serializer =
let read_data ((key': Key.t), (version': int), (value: 'a)) source_msg =
if key <> key' then (
L.user_error
"Wrong key in when loading data from %s -- are you running infer with results coming from a previous version of infer?@\n"
source_msg ;
"Wrong key in when loading data from %s -- are you running infer with results coming from \
a previous version of infer?@\n\
" source_msg ;
None )
else if version <> version' then (
L.user_error
"Wrong version in when loading data from %s -- are you running infer with results coming from a previous version of infer?@\n"
source_msg ;
"Wrong version in when loading data from %s -- are you running infer with results coming \
from a previous version of infer?@\n\
" source_msg ;
None )
else Some value
in

@ -9,8 +9,8 @@
open! IStd
exception Error of string
(** The functions in this module tend to raise more often than their counterparts in [Sqlite3]. In particular, they may raise if the [Sqlite3.Rc.t] result of certain operations is unexpected. *)
exception Error of string
val check_sqlite_error : ?fatal:bool -> Sqlite3.db -> log:string -> Sqlite3.Rc.t -> unit
(** Assert that the result is either [Sqlite3.Rc.OK]. If [row_is_ok] then [Sqlite3.Rc.ROW] is also accepted. If the result is not valid, then if [fatal] is set raise [Error], otherwise log the error and proceed. *)

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

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

@ -113,9 +113,7 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
let new_sym_num = BoUtils.counter_gen 0 in
let add_formal (mem, inst_num) (pvar, typ) =
let loc = Loc.of_pvar pvar in
let mem =
declare_symbolic_val pname tenv node location loc typ ~inst_num ~new_sym_num mem
in
let mem = declare_symbolic_val pname tenv node location loc typ ~inst_num ~new_sym_num mem in
(mem, inst_num + 1)
in
List.fold ~f:add_formal ~init:(mem, inst_num) formals |> fst
@ -187,8 +185,7 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
Sem.get_subst_map tenv pdesc params caller_mem callee_entry_mem ~callee_ret_alias
in
instantiate_ret ret callee_pname callee_exit_mem subst_map caller_mem ret_alias location
|> instantiate_param tenv pdesc params callee_entry_mem callee_exit_mem subst_map
location
|> instantiate_param tenv pdesc params callee_entry_mem callee_exit_mem subst_map location
| None ->
caller_mem
@ -427,9 +424,7 @@ module Report = struct
()
| Sil.Prune (cond, location, true_branch, _) ->
let i = match cond with Exp.Const Const.Cint i -> i | _ -> IntLit.zero in
let desc =
Errdesc.explain_condition_always_true_false tenv i cond node location
in
let desc = Errdesc.explain_condition_always_true_false tenv i cond node location in
let exn =
Exceptions.Condition_always_true_false (desc, not true_branch, __POS__)
in

@ -219,8 +219,7 @@ module Val = struct
let traces_caller =
List.fold symbols
~f:(fun traces symbol ->
try TraceSet.join (Itv.SubstMap.find symbol trace_map) traces with Not_found -> traces
)
try TraceSet.join (Itv.SubstMap.find symbol trace_map) traces with Not_found -> traces )
~init:TraceSet.empty
in
let traces = TraceSet.instantiate ~traces_caller ~traces_callee:x.traces location in
@ -719,8 +718,7 @@ module MemReach = struct
| LatestPrune.V (x, _, prunes), Exp.UnOp (Unop.LNot, Exp.Var r, _) -> (
match find_simple_alias r m with
| Some Loc.Var Var.ProgramVar y when Pvar.equal x y ->
List.fold_left prunes ~init:m ~f:(fun acc (l, v) ->
update_mem (PowLoc.singleton l) v acc )
List.fold_left prunes ~init:m ~f:(fun acc (l, v) -> update_mem (PowLoc.singleton l) v acc)
| _ ->
m )
| _ ->
@ -867,6 +865,5 @@ module Summary = struct
let pp : F.formatter -> t -> unit =
fun fmt (entry_mem, exit_mem, condition_set) ->
F.fprintf fmt "%a@,%a@,%a@," Mem.pp entry_mem Mem.pp exit_mem PO.ConditionSet.pp
condition_set
F.fprintf fmt "%a@,%a@,%a@," Mem.pp entry_mem Mem.pp exit_mem PO.ConditionSet.pp condition_set
end

@ -164,8 +164,7 @@ module ArrayAccessCondition = struct
let filter1 : t -> bool =
fun c ->
ItvPure.is_top c.idx || ItvPure.is_top c.size
|| Itv.Bound.eq (ItvPure.lb c.idx) Itv.Bound.MInf
ItvPure.is_top c.idx || ItvPure.is_top c.size || Itv.Bound.eq (ItvPure.lb c.idx) Itv.Bound.MInf
|| Itv.Bound.eq (ItvPure.lb c.size) Itv.Bound.MInf
|| ItvPure.is_nat c.idx && ItvPure.is_nat c.size
@ -212,8 +211,8 @@ module ArrayAccessCondition = struct
else if Itv.Bound.is_symbolic (ItvPure.lb c.idx)
&& Itv.Bound.le (ItvPure.lb c'.size) (ItvPure.lb c.idx)
then Some IssueType.buffer_overrun_s2 (* other symbolic bounds are probably too noisy *)
else if Config.bo_debug <= 3 && (ItvPure.is_symbolic c.idx || ItvPure.is_symbolic c.size)
then None
else if Config.bo_debug <= 3 && (ItvPure.is_symbolic c.idx || ItvPure.is_symbolic c.size) then
None
else if filter1 c then Some IssueType.buffer_overrun_l5
else if filter2 c then Some IssueType.buffer_overrun_l4
else Some IssueType.buffer_overrun_l3

@ -488,8 +488,7 @@ module Make (CFG : ProcCfg.S) = struct
if itv1 <> bot && itv1 <> top then
if Itv.eq itv2 bot then
(lb itv1, Bottom, TraceSet.empty) :: (ub itv1, Bottom, TraceSet.empty) :: l
else
(lb itv1, NonBottom (lb itv2), traces) :: (ub itv1, NonBottom (ub itv2), traces) :: l
else (lb itv1, NonBottom (lb itv2), traces) :: (ub itv1, NonBottom (ub itv2), traces) :: l
else l
in
let add_pair_val v1 v2 pairs =

@ -114,8 +114,8 @@ module Make (CFG : ProcCfg.S) = struct
: decl_sym_val:decl_sym_val -> Typ.Procname.t -> Tenv.t -> CFG.node -> Location.t
-> depth:int -> Loc.t -> Typ.t -> ?offset:Itv.t -> ?size:Itv.t -> inst_num:int
-> new_sym_num:counter -> new_alloc_num:counter -> Dom.Mem.astate -> Dom.Mem.astate =
fun ~decl_sym_val pname tenv node location ~depth loc typ ?offset ?size ~inst_num
~new_sym_num ~new_alloc_num mem ->
fun ~decl_sym_val pname tenv node location ~depth loc typ ?offset ?size ~inst_num ~new_sym_num
~new_alloc_num mem ->
let option_value opt_x default_f = match opt_x with Some x -> x | None -> default_f () in
let itv_make_sym () = Itv.make_sym pname new_sym_num in
let offset = option_value offset itv_make_sym in

@ -267,8 +267,7 @@ module Bound = struct
let eval_int x i1 i2 = match x with Plus -> i1 + i2 | Minus -> i1 - i2
let pp ~need_plus : F.formatter -> t -> unit =
fun fmt ->
function Plus -> if need_plus then F.fprintf fmt "+" | Minus -> F.fprintf fmt "-"
fun fmt -> function Plus -> if need_plus then F.fprintf fmt "+" | Minus -> F.fprintf fmt "-"
end
type min_max = Min | Max [@@deriving compare]
@ -298,8 +297,7 @@ module Bound = struct
let equal = [%compare.equal : t]
let pp : F.formatter -> t -> unit =
fun fmt ->
function
fun fmt -> function
| MInf ->
F.fprintf fmt "-oo"
| PInf ->
@ -332,8 +330,7 @@ module Bound = struct
let eq_symbol : Symbol.t -> t -> bool =
fun s ->
function
fun s -> function
| Linear (0, se) -> (
match SymLinear.get_one_symbol_opt se with None -> false | Some s' -> Symbol.equal s s' )
| _ ->
@ -377,8 +374,7 @@ module Bound = struct
let use_symbol : Symbol.t -> t -> bool =
fun s ->
function
fun s -> function
| PInf | MInf ->
false
| Linear (_, se) ->
@ -1291,9 +1287,11 @@ let lift1 : (ItvPure.t -> ItvPure.t) -> t -> t =
let lift1_opt : (ItvPure.t -> ItvPure.t option) -> t -> t =
fun f ->
function
| Bottom -> Bottom | NonBottom x -> match f x with None -> Bottom | Some v -> NonBottom v
fun f -> function
| Bottom ->
Bottom
| NonBottom x ->
match f x with None -> Bottom | Some v -> NonBottom v
let lift2 : (ItvPure.t -> ItvPure.t -> ItvPure.t) -> t -> t -> t =

@ -177,7 +177,10 @@ let checker {Callbacks.proc_desc; tenv; get_proc_desc; summary} : Specs.summary
( match loaded_stacktraces with
| None ->
L.(die UserError)
"Missing command line option. Either '--stacktrace stack.json' or '--stacktrace-dir ./dir' must be used when running '-a crashcontext'. This options expects a JSON formated stack trace or a directory containing multiple such traces, respectively. See tests/codetoanalyze/java/crashcontext/*.json for examples of the expected format."
"Missing command line option. Either '--stacktrace stack.json' or '--stacktrace-dir \
./dir' must be used when running '-a crashcontext'. This options expects a JSON formated \
stack trace or a directory containing multiple such traces, respectively. See \
tests/codetoanalyze/java/crashcontext/*.json for examples of the expected format."
| Some stacktraces ->
let extras = {get_proc_desc; stacktraces} in
ignore (Analyzer.exec_pdesc (ProcData.make proc_desc tenv extras) ~initial:Domain.empty) ) ;

@ -130,13 +130,15 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
if is_direct_dereference then
(* direct dereference without intermediate variable *)
F.asprintf
"The return value of %s is annotated with %a and is dereferenced without being checked for null at %a"
"The return value of %s is annotated with %a and is dereferenced without being \
checked for null at %a"
(MF.monospaced_to_string simplified_pname)
MF.pp_monospaced annotation Location.pp loc
else
(* dereference with intermediate variable *)
F.asprintf
"Variable %a is indirectly annotated with %a (source %a) and is dereferenced without being checked for null at %a"
"Variable %a is indirectly annotated with %a (source %a) and is dereferenced without \
being checked for null at %a"
(MF.wrap_monospaced AccessPath.pp)
ap MF.pp_monospaced annotation (MF.wrap_monospaced CallSite.pp) call_site Location.pp
loc

@ -57,7 +57,8 @@ module Make (Spec : Spec) : S = struct
(* failsafe for accidental non-finite height domains *)
if num_iters >= iters_befor_timeout then
L.(die InternalError)
"Stopping analysis after 1000 iterations without convergence. Make sure your domain is finite height."
"Stopping analysis after 1000 iterations without convergence. Make sure your domain is \
finite height."
else widen ~prev ~next ~num_iters
end

@ -440,6 +440,7 @@ module PathSet (Config : Config) = struct
let mem access_path tree =
match get_node access_path tree with None -> false | Some (is_mem, _) -> is_mem
(* print as a set of paths rather than a map of paths to bools *)
let pp fmt tree =
let collect_path acc access_path (is_mem, _) = if is_mem then access_path :: acc else acc in

@ -34,7 +34,8 @@ let check_immutable_cast tenv curr_pname curr_pdesc typ_expected typ_found_opt l
if in_casts name_expected name_given then
let description =
Format.asprintf
"Method %s returns %a but the return type is %a. Make sure that users of this method do not try to modify the collection."
"Method %s returns %a but the return type is %a. Make sure that users of this \
method do not try to modify the collection."
(Typ.Procname.to_simplified_string curr_pname)
Typ.Name.pp name_given Typ.Name.pp name_expected
in

@ -7,13 +7,13 @@
* of patent rights can be found in the PATENTS file in the same directory.
*)
exception ALParserInvariantViolationException of string
(** Raised when the parser encounters a violation of a certain invariant *)
exception ALParserInvariantViolationException of string
type exc_info
exception ALFileException of exc_info
(** Raised when any exception from the lexer/parser of AL is caught, to include source-location info *)
exception ALFileException of exc_info
val create_exc_info : string -> Lexing.lexbuf -> exc_info

@ -118,7 +118,7 @@ let run_clang clang_command read =
let run_plugin_and_frontend source_path frontend clang_cmd =
let clang_plugin_cmd = ClangCommand.with_plugin_args clang_cmd in
( if debug_mode then
if debug_mode then (
(* -cc1 clang commands always set -o explicitly *)
let basename = source_path ^ ".ast" in
(* Emit the clang command with the extra args piped to infer-as-clang *)

@ -119,8 +119,13 @@ let exec_action_item ~prog ~args = function
(* An error in the output of `clang -### ...`. Outputs the error and fail. This is because
`clang -###` pretty much never fails, but warns of failures on stderr instead. *)
L.(die UserError)
"Failed to execute compilation command:@\n'%s' %a@\n@\nError message:@\n%s@\n@\n*** Infer needs a working compilation command to run."
prog Pp.cli_args args error
"Failed to execute compilation command:@\n\
'%s' %a@\n\
@\n\
Error message:@\n\
%s@\n\
@\n\
*** Infer needs a working compilation command to run." prog Pp.cli_args args error
| ClangWarning warning ->
L.external_warning "%s@\n" warning
| Command clang_cmd ->
@ -156,6 +161,9 @@ let exe ~prog ~args =
will fail with the appropriate error message from clang instead of silently analyzing 0
files. *)
L.(debug Capture Quiet)
"WARNING: `clang -### <args>` returned an empty set of commands to run and no error. Will run the original command directly:@\n %s@\n"
"WARNING: `clang -### <args>` returned an empty set of commands to run and no error. Will \
run the original command directly:@\n \
%s@\n\
"
(String.concat ~sep:" " @@ prog :: args) ;
Process.create_process_and_wait ~prog ~args )

@ -185,7 +185,8 @@ let component_factory_function_advice context an =
; description= "Break out composite components"
; suggestion=
Some
"Prefer subclassing CKCompositeComponent to static helper functions that return a CKComponent subclass."
"Prefer subclassing CKCompositeComponent to static helper functions that return \
a CKComponent subclass."
; doc_url= None
; loc= CFrontend_checkers.location_from_dinfo context decl_info }
else None
@ -298,7 +299,8 @@ let component_with_multiple_factory_methods_advice context an =
; description= "Avoid Overrides"
; suggestion=
Some
"Instead, always expose all parameters in a single designated initializer and document which are optional."
"Instead, always expose all parameters in a single designated initializer and \
document which are optional."
; doc_url= None
; loc= CFrontend_checkers.location_from_decl context meth_decl } )
(List.drop factory_methods 1)

@ -172,8 +172,10 @@ let unary_operation_instruction translation_unit_context uoi e typ loc =
| `Real | `Imag | `Extension | `Coawait ->
let uok = Clang_ast_j.string_of_unary_operator_kind uoi.Clang_ast_t.uoi_kind in
L.(debug Capture Medium)
"@\nWARNING: Missing translation for Unary Operator Kind %s. The construct has been ignored...@\n"
uok ;
"@\n\
WARNING: Missing translation for Unary Operator Kind %s. The construct has been \
ignored...@\n\
" uok ;
(e, [])

@ -562,13 +562,14 @@ let get_superclass_curr_class_objc_from_decl (decl: Clang_ast_t.decl) =
otdi.otdi_super
| _ ->
Logging.die InternalError
"Expected that ObjCImplementationDecl always has a pointer to it's interface, but wasn't the case with %s"
ni.Clang_ast_t.ni_name )
"Expected that ObjCImplementationDecl always has a pointer to it's interface, but \
wasn't the case with %s" ni.Clang_ast_t.ni_name )
| ObjCCategoryDecl (_, _, _, _, ocdi) ->
ocdi.odi_class_interface
| ObjCCategoryImplDecl (_, _, _, _, ocidi) ->
ocidi.ocidi_class_interface
| decl ->
Logging.die InternalError
"Expected to be called only with ObjCInterfaceDecl, ObjCImplementationDecl, ObjCCategoryDecl or ObjCCategoryImplDecl, but got %s"
"Expected to be called only with ObjCInterfaceDecl, ObjCImplementationDecl, \
ObjCCategoryDecl or ObjCCategoryImplDecl, but got %s"
(Clang_ast_proj.get_decl_kind_string decl)

@ -52,8 +52,8 @@ let decl_ref_or_selector_name an =
"The reference " ^ Ctl_parser_types.ast_node_name decl_an
| _ ->
L.(die ExternalError)
"decl_ref_or_selector_name must be called with a DeclRefExpr or an ObjCMessageExpr, but got %s"
(tag_name_of_node an)
"decl_ref_or_selector_name must be called with a DeclRefExpr or an ObjCMessageExpr, but \
got %s" (tag_name_of_node an)
let iphoneos_target_sdk_version context _ =

@ -25,7 +25,9 @@ let filter_parsed_linters_developer parsed_linters =
match Config.linter with
| None ->
L.(die UserError)
"In linters developer mode you should debug only one linter at a time. This is important for debugging the rule. Pass the flag --linter <name> to specify the linter you want to debug."
"In linters developer mode you should debug only one linter at a time. This is \
important for debugging the rule. Pass the flag --linter <name> to specify the linter \
you want to debug."
| Some lint ->
List.filter ~f:(fun (rule: linter) -> String.equal rule.issue_desc.id lint) parsed_linters
else parsed_linters

@ -275,8 +275,8 @@ let get_superclass_curr_class_objc context =
CAst_utils.get_superclass_curr_class_objc_from_decl decl
| None ->
Logging.die InternalError
"Expected that the current class ptr in the context is a valid pointer to class decl, but didn't find declaration, ptr is %d "
ptr )
"Expected that the current class ptr in the context is a valid pointer to class decl, \
but didn't find declaration, ptr is %d " ptr )
| CContext.ContextNoCls ->
Logging.die InternalError
"This should only be called in the context of a class, but got CContext.ContextNoCls"
@ -625,13 +625,13 @@ let create_local_procdesc ?(set_objc_accessor_attr= false) trans_unit_ctx cfg te
in
Cfg.create_proc_desc cfg proc_attributes
in
if defined then
if defined then (
let start_kind = Procdesc.Node.Start_node proc_name in
let start_node = Procdesc.create_node procdesc loc_start start_kind [] in
let exit_kind = Procdesc.Node.Exit_node proc_name in
let exit_node = Procdesc.create_node procdesc loc_exit exit_kind [] in
Procdesc.set_start_node procdesc start_node ;
Procdesc.set_exit_node procdesc exit_node
Procdesc.set_exit_node procdesc exit_node )
in
if should_create_procdesc cfg proc_name defined set_objc_accessor_attr then (
create_new_procdesc () ; true )

@ -450,7 +450,10 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
{empty_res_trans with exps= [(Exp.Sizeof sizeof_data, sizeof_typ)]}
| k ->
L.(debug Capture Medium)
"@\nWARNING: Missing translation of Uniry_Expression_Or_Trait of kind: %s . Expression ignored, returned -1... @\n"
"@\n\
WARNING: Missing translation of Uniry_Expression_Or_Trait of kind: %s . Expression \
ignored, returned -1... @\n\
"
(Clang_ast_j.string_of_unary_expr_or_type_trait_kind k) ;
{empty_res_trans with exps= [(Exp.minus_one, typ)]}
@ -1007,7 +1010,8 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
let res_trans_callee = instruction trans_state_callee fun_exp_stmt in
let sil_fe, _ =
extract_exp_from_list res_trans_callee.exps
"WARNING: The translation of fun_exp did not return an expression.Returning -1. NEED TO BE FIXED"
"WARNING: The translation of fun_exp did not return an expression.Returning -1. NEED TO \
BE FIXED"
in
let callee_pname_opt =
match sil_fe with Exp.Const Const.Cfun pn -> Some pn | _ -> None
@ -1042,8 +1046,10 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
else
(* FIXME(t21762295) this is reachable *)
CFrontend_config.incorrect_assumption __POS__ si.Clang_ast_t.si_source_range
"In call to %a: stmt_list and res_trans_par.exps must have same size but they don't:@\nstmt_list(%d)=[%a]@\nres_trans_par.exps(%d)=[%a]@\n"
Typ.Procname.pp procname (List.length params) (Pp.seq Exp.pp)
"In call to %a: stmt_list and res_trans_par.exps must have same size but they don't:@\n\
stmt_list(%d)=[%a]@\n\
res_trans_par.exps(%d)=[%a]@\n\
" Typ.Procname.pp procname (List.length params) (Pp.seq Exp.pp)
(List.map ~f:fst params) (List.length params_stmt)
(Pp.seq (Pp.to_string ~f:Clang_ast_j.string_of_stmt))
params_stmt
@ -2413,7 +2419,9 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
let trans_state_pri = PriorityNode.try_claim_priority_node trans_state stmt_info in
let stmt =
extract_stmt_from_singleton stmt_list
"WARNING: We expect only one element in stmt list defining the operand in UnaryOperator. NEED FIXING@\n"
"WARNING: We expect only one element in stmt list defining the operand in UnaryOperator. \
NEED FIXING@\n\
"
in
let trans_state' = {trans_state_pri with succ_nodes= []} in
let res_trans_stmt = instruction trans_state' stmt in
@ -2524,7 +2532,10 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
{empty_res_trans with root_nodes= [ret_node]; leaf_nodes= []}
| _ ->
L.(debug Capture Verbose)
"@\nWARNING: Missing translation of Return Expression. Return Statement ignored. Need fixing!@\n" ;
"@\n\
WARNING: Missing translation of Return Expression. Return Statement ignored. Need \
fixing!@\n\
" ;
{empty_res_trans with root_nodes= succ_nodes}
in
(* We expect a return with only one expression *)

@ -230,7 +230,7 @@ module PriorityNode = struct
let compute_results_to_parent trans_state loc nd_name stmt_info res_states_children =
let res_state = collect_res_trans trans_state.context.procdesc res_states_children in
let create_node = own_priority_node trans_state.priority stmt_info && res_state.instrs <> [] in
if create_node then
if create_node then (
(* We need to create a node *)
let node_kind = Procdesc.Node.Stmt_node nd_name in
let node = Nodes.create_node node_kind res_state.instrs loc trans_state.context in
@ -240,7 +240,7 @@ module PriorityNode = struct
res_state.leaf_nodes ;
(* Invariant: if root_nodes is empty then the params have not created a node.*)
let root_nodes = if res_state.root_nodes <> [] then res_state.root_nodes else [node] in
{res_state with root_nodes; leaf_nodes= [node]; instrs= []; exps= []}
{res_state with root_nodes; leaf_nodes= [node]; instrs= []; exps= []} )
else
(* The node is created by the parent. We just pass back nodes/leafs params *)
{res_state with exps= []}

@ -357,7 +357,9 @@ type abs_ctype =
let display_equality_warning () =
L.(debug Linters Medium)
"[WARNING:] Type Comparison failed... This might indicate that the types are different or the specified type is internally represented in a different way and therefore not recognized.@\n"
"[WARNING:] Type Comparison failed... This might indicate that the types are different or the \
specified type is internally represented in a different way and therefore not recognized.@\n\
"
let rec abs_ctype_to_string t =
@ -483,7 +485,11 @@ and check_type_ptr type_ptr abs_ctype =
comparison function for Clang_ast_t.c_type *)
and c_type_equal c_type abs_ctype =
L.(debug Linters Medium)
"@\nComparing c_type/abs_ctype for equality... Type compared: @\nc_type = `%s` @\nabs_ctype =`%s`@\n"
"@\n\
Comparing c_type/abs_ctype for equality... Type compared: @\n\
c_type = `%s` @\n\
abs_ctype =`%s`@\n\
"
(Clang_ast_j.string_of_c_type c_type)
(abs_ctype_to_string abs_ctype) ;
let open Clang_ast_t in

@ -257,8 +257,11 @@ let add_valid_formulae an checker lcxt cl =
add_in_set phi acc_set
| AG _ | AX _ | AF _ | AU _ | EH _ | ET _ | Implies _ ->
Logging.die InternalError
"@\n We should not have operators AG, AX, AF, AU, EH, ET.\n Failing with formula @\n %a@\n"
CTL.Debug.pp_formula phi
"@\n \
We should not have operators AG, AX, AF, AU, EH, ET.\n \
Failing with formula @\n \
%a@\n\
" CTL.Debug.pp_formula phi
| _ ->
acc_set
in
@ -329,11 +332,11 @@ let build_valuation an lcxt linter_map_context =
closure_map := ClosureHashtbl.add normalized_condition (is_state_only, cl') !closure_map ;
(is_state_only, cl')
in
if not (is_state_only && skip_evaluation_InNode_formula an normalized_condition) then
if not (is_state_only && skip_evaluation_InNode_formula an normalized_condition) then (
let sat_set = add_valid_formulae an linter.issue_desc.id lcxt cl in
(*L.progress " [Set Size: %i] @\n" (CTLFormulaSet.cardinal sat_set);*)
if CTLFormulaSet.mem normalized_condition sat_set then report_issue an lcxt linter ;
add_formula_to_valuation (node_pointer, linter.issue_desc.id) sat_set
add_formula_to_valuation (node_pointer, linter.issue_desc.id) sat_set )
in
List.iter
~f:(fun (linter: linter) ->

@ -844,13 +844,13 @@ let get_reporting_explanation_java report_kind tenv pname thread =
| _, Some threadsafe_explanation when RacerDDomain.ThreadsDomain.is_any thread ->
( IssueType.thread_safety_violation
, F.asprintf
"%s, so we assume that this method can run in parallel with other non-private methods in the class (including itself)."
threadsafe_explanation )
"%s, so we assume that this method can run in parallel with other non-private methods \
in the class (including itself)." threadsafe_explanation )
| _, Some threadsafe_explanation ->
( IssueType.thread_safety_violation
, F.asprintf
"%s. Although this access is not known to run on a background thread, it may happen in parallel with another access that does."
threadsafe_explanation )
"%s. Although this access is not known to run on a background thread, it may happen in \
parallel with another access that does." threadsafe_explanation )
| _, None ->
(* failed to explain based on @ThreadSafe annotation; have to justify using background thread *)
if RacerDDomain.ThreadsDomain.is_any thread then
@ -859,8 +859,9 @@ let get_reporting_explanation_java report_kind tenv pname thread =
else
( IssueType.thread_safety_violation
, F.asprintf
"@\n Reporting because another access to the same memory occurs on a background thread, although this access may not."
)
"@\n \
Reporting because another access to the same memory occurs on a background thread, \
although this access may not." )
(** Explain why we are reporting this access, in C++ *)
@ -995,8 +996,12 @@ let get_contaminated_race_message access wobbly_paths =
in
Option.map wobbly_path_opt ~f:(fun (wobbly_path, access_path) ->
F.asprintf
"@\n\nNote that the prefix path %a has been contaminated during the execution, so the reported race on %a might be a false positive.@\n\n"
AccessPath.pp wobbly_path AccessPath.pp access_path )
"@\n\
\n\
Note that the prefix path %a has been contaminated during the execution, so the reported \
race on %a might be a false positive.@\n\
\n\
" AccessPath.pp wobbly_path AccessPath.pp access_path )
let report_thread_safety_violation tenv pdesc ~make_description ~report_kind access thread
@ -1058,7 +1063,8 @@ let report_unannotated_interface_violation tenv pdesc access thread reported_pna
let class_name = Typ.Procname.Java.get_class_name java_pname in
let make_description _ _ _ _ =
F.asprintf
"Unprotected call to method of un-annotated interface %s. Consider annotating the class with %a, adding a lock, or using an interface that is known to be thread-safe."
"Unprotected call to method of un-annotated interface %s. Consider annotating the class \
with %a, adding a lock, or using an interface that is known to be thread-safe."
class_name MF.pp_monospaced "@ThreadSafe"
in
report_thread_safety_violation tenv pdesc ~make_description ~report_kind:UnannotatedInterface
@ -1222,12 +1228,12 @@ let report_unsafe_accesses (aggregated_access_map: reported_access list AccessLi
in
if AccessData.is_unprotected precondition
&& (not (List.is_empty writes_on_background_thread) || ThreadsDomain.is_any threads)
then
then (
let conflict = List.hd writes_on_background_thread in
report_thread_safety_violation tenv procdesc
~make_description:make_unprotected_write_description
~report_kind:(WriteWriteRace conflict) access threads wobbly_paths ;
update_reported access pname reported_acc
update_reported access pname reported_acc )
else reported_acc
| _ ->
(* Do not report unprotected writes when an access can't run in parallel with itself, or
@ -1252,12 +1258,12 @@ let report_unsafe_accesses (aggregated_access_map: reported_access list AccessLi
is_conflict other_access precondition other_threads )
accesses
in
if not (List.is_empty all_writes) then
if not (List.is_empty all_writes) then (
let conflict = List.hd_exn all_writes in
report_thread_safety_violation tenv procdesc
~make_description:(make_read_write_race_description ~read_is_sync:false conflict)
~report_kind:(ReadWriteRace conflict.access) access threads wobbly_paths ;
update_reported access pname reported_acc
update_reported access pname reported_acc )
else reported_acc
| Access.Read _ | ContainerRead _ ->
(* protected read. report unprotected writes and opposite protected writes as conflicts *)
@ -1279,13 +1285,13 @@ let report_unsafe_accesses (aggregated_access_map: reported_access list AccessLi
)
accesses
in
if not (List.is_empty conflicting_writes) then
if not (List.is_empty conflicting_writes) then (
let conflict = List.hd_exn conflicting_writes in
(* protected read with conflicting unprotected write(s). warn. *)
report_thread_safety_violation tenv procdesc
~make_description:(make_read_write_race_description ~read_is_sync:true conflict)
~report_kind:(ReadWriteRace conflict.access) access threads wobbly_paths ;
update_reported access pname reported_acc
update_reported access pname reported_acc )
else reported_acc
in
AccessListMap.fold

@ -615,16 +615,25 @@ type summary =
let pp_summary fmt {threads; locks; accesses; return_ownership; return_attributes; wobbly_paths} =
F.fprintf fmt
"@\nThreads: %a, Locks: %a @\nAccesses %a @\nOwnership: %a @\nReturn Attributes: %a @\nWobbly Paths: %a@\n"
ThreadsDomain.pp threads LocksDomain.pp locks AccessDomain.pp accesses
"@\n\
Threads: %a, Locks: %a @\n\
Accesses %a @\n\
Ownership: %a @\n\
Return Attributes: %a @\n\
Wobbly Paths: %a@\n\
" ThreadsDomain.pp threads LocksDomain.pp locks AccessDomain.pp accesses
OwnershipAbstractValue.pp return_ownership AttributeSetDomain.pp return_attributes
StabilityDomain.pp wobbly_paths
let pp fmt {threads; locks; accesses; ownership; attribute_map; wobbly_paths} =
F.fprintf fmt
"Threads: %a, Locks: %a @\nAccesses %a @\n Ownership: %a @\nAttributes: %a @\nNon-stable Paths: %a@\n"
ThreadsDomain.pp threads LocksDomain.pp locks AccessDomain.pp accesses OwnershipDomain.pp
"Threads: %a, Locks: %a @\n\
Accesses %a @\n \
Ownership: %a @\n\
Attributes: %a @\n\
Non-stable Paths: %a@\n\
" ThreadsDomain.pp threads LocksDomain.pp locks AccessDomain.pp accesses OwnershipDomain.pp
ownership AttributeMapDomain.pp attribute_map StabilityDomain.pp wobbly_paths

@ -111,13 +111,14 @@ module MkCallback (Extension : ExtensionT) : CallBackT = struct
curr_pname curr_pdesc find_canonical_duplicate annotated_signature typestate node
linereader
in
( if Config.write_html then
if Config.write_html then (
let d_typestate ts = L.d_strln (F.asprintf "%a" (TypeState.pp Extension.ext) ts) in
L.d_strln "before:" ;
d_typestate typestate ;
L.d_strln "after:" ;
List.iter ~f:d_typestate typestates_succ ) ;
NodePrinter.finish_session node ; (typestates_succ, typestates_exn)
NodePrinter.finish_session node ;
(typestates_succ, typestates_exn)
let proc_throws _ = DontKnow

@ -209,7 +209,7 @@ let check_field_assignment tenv find_canonical_duplicate curr_pdesc node instr_r
true )
&& not (field_is_mutable ())
in
( if should_report_nullable || should_report_absent then
if should_report_nullable || should_report_absent then (
let ann =
if should_report_nullable then AnnotatedSignature.Nullable else AnnotatedSignature.Present
in

@ -295,29 +295,30 @@ let annotated_list_nullable =
, "javax.lang.model.util.Elements.getAllAnnotationMirrors(javax.lang.model.element.Element):java.util.List"
)
; ( o2
, "javax.lang.model.util.Elements.hides(javax.lang.model.element.Element, javax.lang.model.element.Element):boolean"
)
, "javax.lang.model.util.Elements.hides(javax.lang.model.element.Element, \
javax.lang.model.element.Element):boolean" )
; ( o3
, "javax.lang.model.util.Elements.overrides(javax.lang.model.element.ExecutableElement, javax.lang.model.element.ExecutableElement, javax.lang.model.element.TypeElement):boolean"
, "javax.lang.model.util.Elements.overrides(javax.lang.model.element.ExecutableElement, \
javax.lang.model.element.ExecutableElement, javax.lang.model.element.TypeElement):boolean"
)
; ( o1
, "javax.lang.model.util.Types.asElement(javax.lang.model.type.TypeMirror):javax.lang.model.element.Element"
)
; ( o2
, "javax.lang.model.util.Types.isSameType(javax.lang.model.type.TypeMirror, javax.lang.model.type.TypeMirror):boolean"
)
, "javax.lang.model.util.Types.isSameType(javax.lang.model.type.TypeMirror, \
javax.lang.model.type.TypeMirror):boolean" )
; ( o2
, "javax.lang.model.util.Types.isSubtype(javax.lang.model.type.TypeMirror, javax.lang.model.type.TypeMirror):boolean"
)
, "javax.lang.model.util.Types.isSubtype(javax.lang.model.type.TypeMirror, \
javax.lang.model.type.TypeMirror):boolean" )
; ( o2
, "javax.lang.model.util.Types.isAssignable(javax.lang.model.type.TypeMirror, javax.lang.model.type.TypeMirror):boolean"
)
, "javax.lang.model.util.Types.isAssignable(javax.lang.model.type.TypeMirror, \
javax.lang.model.type.TypeMirror):boolean" )
; ( o2
, "javax.lang.model.util.Types.contains(javax.lang.model.type.TypeMirror, javax.lang.model.type.TypeMirror):boolean"
)
, "javax.lang.model.util.Types.contains(javax.lang.model.type.TypeMirror, \
javax.lang.model.type.TypeMirror):boolean" )
; ( o2
, "javax.lang.model.util.Types.isSubsignature(javax.lang.model.type.ExecutableType, javax.lang.model.type.ExecutableType):boolean"
)
, "javax.lang.model.util.Types.isSubsignature(javax.lang.model.type.ExecutableType, \
javax.lang.model.type.ExecutableType):boolean" )
; ( o1
, "javax.lang.model.util.Types.directSupertypes(javax.lang.model.type.TypeMirror):java.util.List"
)
@ -337,34 +338,35 @@ let annotated_list_nullable =
, "javax.lang.model.util.Types.getArrayType(javax.lang.model.type.TypeMirror):javax.lang.model.type.ArrayType"
)
; ( o2
, "javax.lang.model.util.Types.getWildcardType(javax.lang.model.type.TypeMirror, javax.lang.model.type.TypeMirror):javax.lang.model.type.WildcardType"
)
, "javax.lang.model.util.Types.getWildcardType(javax.lang.model.type.TypeMirror, \
javax.lang.model.type.TypeMirror):javax.lang.model.type.WildcardType" )
; ( o2
, "javax.lang.model.util.Types.getDeclaredType(javax.lang.model.element.TypeElement, javax.lang.model.type.TypeMirror[]):javax.lang.model.type.DeclaredType"
)
, "javax.lang.model.util.Types.getDeclaredType(javax.lang.model.element.TypeElement, \
javax.lang.model.type.TypeMirror[]):javax.lang.model.type.DeclaredType" )
; ( o3
, "javax.lang.model.util.Types.getDeclaredType(javax.lang.model.type.DeclaredType, javax.lang.model.element.TypeElement, javax.lang.model.type.TypeMirror[]):javax.lang.model.type.DeclaredType"
)
, "javax.lang.model.util.Types.getDeclaredType(javax.lang.model.type.DeclaredType, \
javax.lang.model.element.TypeElement, \
javax.lang.model.type.TypeMirror[]):javax.lang.model.type.DeclaredType" )
; ( o2
, "javax.lang.model.util.Types.asMemberOf(javax.lang.model.type.DeclaredType, javax.lang.model.element.Element):javax.lang.model.type.TypeMirror"
)
, "javax.lang.model.util.Types.asMemberOf(javax.lang.model.type.DeclaredType, \
javax.lang.model.element.Element):javax.lang.model.type.TypeMirror" )
; ( n3
, "javax.tools.JavaCompiler.getStandardFileManager(javax.tools.DiagnosticListener,java.util.Locale,java.nio.charset.Charset):javax.tools.StandardJavaFileManager"
)
; (ng, "javax.tools.JavaFileObject.getAccessLevel():javax.lang.model.element.Modifier")
; (ng, "javax.tools.JavaFileObject.getNestingKind():javax.lang.model.element.NestingKind")
; ( o2
, "com.sun.source.util.SourcePositions.getStartPosition(com.sun.source.tree.CompilationUnitTree, com.sun.source.tree.Tree):long"
)
, "com.sun.source.util.SourcePositions.getStartPosition(com.sun.source.tree.CompilationUnitTree, \
com.sun.source.tree.Tree):long" )
; ( o2
, "com.sun.source.util.SourcePositions.getEndPosition(com.sun.source.tree.CompilationUnitTree, com.sun.source.tree.Tree):long"
)
, "com.sun.source.util.SourcePositions.getEndPosition(com.sun.source.tree.CompilationUnitTree, \
com.sun.source.tree.Tree):long" )
; ( (n, [o; o])
, "com.sun.source.util.TreePath.getPath(com.sun.source.tree.CompilationUnitTree, com.sun.source.tree.Tree):com.sun.source.util.TreePath"
)
, "com.sun.source.util.TreePath.getPath(com.sun.source.tree.CompilationUnitTree, \
com.sun.source.tree.Tree):com.sun.source.util.TreePath" )
; ( (n, [o; o])
, "com.sun.source.util.TreePath.getPath(com.sun.source.util.TreePath, com.sun.source.tree.Tree):com.sun.source.util.TreePath"
)
, "com.sun.source.util.TreePath.getPath(com.sun.source.util.TreePath, \
com.sun.source.tree.Tree):com.sun.source.util.TreePath" )
; ( (n, [o])
, "com.sun.source.util.Trees.getTree(javax.lang.model.element.Element):com.sun.source.tree.Tree"
)
@ -375,23 +377,25 @@ let annotated_list_nullable =
, "com.sun.source.util.Trees.getTree(javax.lang.model.element.ExecutableElement):com.sun.source.tree.MethodTree"
)
; ( (n, [o; o])
, "com.sun.source.util.Trees.getTree(javax.lang.model.element.Element, javax.lang.model.element.AnnotationMirror):com.sun.source.tree.Tree"
)
, "com.sun.source.util.Trees.getTree(javax.lang.model.element.Element, \
javax.lang.model.element.AnnotationMirror):com.sun.source.tree.Tree" )
; ( (n, [o; o; o])
, "com.sun.source.util.Trees.getTree(javax.lang.model.element.Element, javax.lang.model.element.AnnotationMirror, javax.lang.model.element.AnnotationValue):com.sun.source.tree.Tree"
)
, "com.sun.source.util.Trees.getTree(javax.lang.model.element.Element, \
javax.lang.model.element.AnnotationMirror, \
javax.lang.model.element.AnnotationValue):com.sun.source.tree.Tree" )
; ( o2
, "com.sun.source.util.Trees.getPath(com.sun.source.tree.CompilationUnitTree, com.sun.source.tree.Tree):com.sun.source.util.TreePath"
)
, "com.sun.source.util.Trees.getPath(com.sun.source.tree.CompilationUnitTree, \
com.sun.source.tree.Tree):com.sun.source.util.TreePath" )
; ( (n, [o])
, "com.sun.source.util.Trees.getPath(javax.lang.model.element.Element):com.sun.source.util.TreePath"
)
; ( (n, [o; o])
, "com.sun.source.util.Trees.getPath(javax.lang.model.element.Element, javax.lang.model.element.AnnotationMirror):com.sun.source.util.TreePath"
)
, "com.sun.source.util.Trees.getPath(javax.lang.model.element.Element, \
javax.lang.model.element.AnnotationMirror):com.sun.source.util.TreePath" )
; ( (n, [o; o; o])
, "com.sun.source.util.Trees.getPath(javax.lang.model.element.Element, javax.lang.model.element.AnnotationMirror, javax.lang.model.element.AnnotationValue):com.sun.source.util.TreePath"
)
, "com.sun.source.util.Trees.getPath(javax.lang.model.element.Element, \
javax.lang.model.element.AnnotationMirror, \
javax.lang.model.element.AnnotationValue):com.sun.source.util.TreePath" )
; ( (n, [o])
, "com.sun.source.util.Trees.getElement(com.sun.source.util.TreePath):javax.lang.model.element.Element"
)
@ -404,17 +408,18 @@ let annotated_list_nullable =
; ( (n, [o])
, "com.sun.source.util.Trees.getDocComment(com.sun.source.util.TreePath):java.lang.String" )
; ( o2
, "com.sun.source.util.Trees.isAccessible(com.sun.source.tree.Scope, javax.lang.model.element.TypeElement):boolean"
)
, "com.sun.source.util.Trees.isAccessible(com.sun.source.tree.Scope, \
javax.lang.model.element.TypeElement):boolean" )
; ( o3
, "com.sun.source.util.Trees.isAccessible(com.sun.source.tree.Scope, javax.lang.model.element.Element, javax.lang.model.type.DeclaredType):boolean"
)
, "com.sun.source.util.Trees.isAccessible(com.sun.source.tree.Scope, \
javax.lang.model.element.Element, javax.lang.model.type.DeclaredType):boolean" )
; ( o1
, "com.sun.source.util.Trees.getOriginalType(javax.lang.model.type.ErrorType):javax.lang.model.type.TypeMirror"
)
; ( (o, [o; o; o; o])
, "com.sun.source.util.Trees.printMessage(javax.tools.Diagnostic.Kind, java.lang.CharSequence, com.sun.source.tree.Tree, com.sun.source.tree.CompilationUnitTree):void"
)
, "com.sun.source.util.Trees.printMessage(javax.tools.Diagnostic.Kind, \
java.lang.CharSequence, com.sun.source.tree.Tree, \
com.sun.source.tree.CompilationUnitTree):void" )
; ( o1
, "com.sun.source.util.Trees.getLub(com.sun.source.tree.CatchTree):javax.lang.model.type.TypeMirror"
)

@ -447,8 +447,8 @@ let report_error_now tenv (st_report_error: st_report_error) err_instance loc pd
in
( IssueType.eradicate_inconsistent_subclass_parameter_annotation
, Format.asprintf
"%s parameter %a of method %a is not %a but is declared %ain the parent class method %a."
(translate_position pos) MF.pp_monospaced param_name MF.pp_monospaced
"%s parameter %a of method %a is not %a but is declared %ain the parent class method \
%a." (translate_position pos) MF.pp_monospaced param_name MF.pp_monospaced
(Typ.Procname.to_simplified_string ~withclass:true pn)
MF.pp_monospaced "@Nullable" MF.pp_monospaced "@Nullable" MF.pp_monospaced
(Typ.Procname.to_simplified_string ~withclass:true opn)

@ -258,12 +258,12 @@ let rec exceed_length ~max = function
let store_args_in_file args =
if exceed_length ~max:max_command_line_length args then
if exceed_length ~max:max_command_line_length args then (
let file = Filename.temp_file "buck_targets_" ".txt" in
let write_args outc = Out_channel.output_string outc (String.concat ~sep:"\n" args) in
let () = Utils.with_file_out file ~f:write_args in
L.(debug Capture Quiet) "Buck targets options stored in file '%s'@\n" file ;
[Printf.sprintf "@%s" file]
[Printf.sprintf "@%s" file] )
else args

@ -84,7 +84,8 @@ let run_compilation_database compilation_database should_capture_file =
L.(debug Analysis Medium) "Ran %d jobs" number_of_jobs ;
if sentinel_exists fail_sentinel then (
L.progress
"Failure detected, capture did not finish successfully. Use `--linters-ignore-clang-failures` to ignore compilation errors. Terminating@." ;
"Failure detected, capture did not finish successfully. Use \
`--linters-ignore-clang-failures` to ignore compilation errors. Terminating@." ;
L.exit 1 )

@ -27,8 +27,8 @@ let checkout revision =
match script_opt with
| None ->
L.(die UserError)
"Please specify a script to checkout the %a revision of your project using --checkout-%a <script>."
pp_revision revision pp_revision revision
"Please specify a script to checkout the %a revision of your project using --checkout-%a \
<script>." pp_revision revision pp_revision revision
| Some script ->
L.progress "Checking out %a version:@\n %s@\n" pp_revision revision script ;
let (), exit_or_signal = Utils.with_process_in script Utils.consume_in in

@ -170,7 +170,10 @@ let check_xcpretty () =
()
| Error _ ->
L.user_error
"@\nxcpretty not found in the path. Please consider installing xcpretty for a more robust integration with xcodebuild. Otherwise use the option --no-xcpretty.@\n@."
"@\n\
xcpretty not found in the path. Please consider installing xcpretty for a more robust \
integration with xcodebuild. Otherwise use the option --no-xcpretty.@\n\
@."
let capture_with_compilation_database db_files =
@ -258,7 +261,7 @@ let capture ~changed_files mode =
["--xcode-developer-dir"; d] )
@ "--"
::
( if in_buck_mode && Config.flavors then
( if in_buck_mode && Config.flavors then (
(* let children infer processes know that they are inside Buck *)
let infer_args_with_buck =
String.concat
@ -275,7 +278,7 @@ let capture ~changed_files mode =
let updated_buck_cmd = prog :: command :: Buck.store_args_in_file all_args in
Logging.(debug Capture Quiet)
"Processed buck command '%a'@\n" (Pp.seq Pp.string) updated_buck_cmd ;
updated_buck_cmd
updated_buck_cmd )
else build_cmd ) )
in
run_command ~prog:infer_py ~args
@ -439,7 +442,8 @@ let assert_supported_mode required_analyzer requested_mode_string =
"clang and xcode"
in
L.(die UserError)
"Unsupported build mode: %s@\nInfer was built with %s analyzers disabled.@ Please rebuild infer with %s enabled.@."
"Unsupported build mode: %s@\n\
Infer was built with %s analyzers disabled.@ Please rebuild infer with %s enabled.@."
requested_mode_string analyzer_string analyzer_string
@ -461,7 +465,8 @@ let assert_supported_build_system build_system =
else (
if Config.reactive_mode then
L.user_error
"WARNING: The reactive analysis mode is not compatible with the Buck integration for Java" ;
"WARNING: The reactive analysis mode is not compatible with the Buck integration \
for Java" ;
(`Java, Config.string_of_build_system build_system) )
in
assert_supported_mode analyzer build_string
@ -488,7 +493,8 @@ let mode_of_build_command build_cmd =
match (build_system : Config.build_system) with
| BAnalyze ->
CLOpt.warnf
"WARNING: `infer -- analyze` is deprecated; use the `infer analyze` subcommand instead@." ;
"WARNING: `infer -- analyze` is deprecated; use the `infer analyze` subcommand \
instead@." ;
Analyze
| BBuck when Option.is_some Config.buck_compilation_database ->
BuckCompilationDB (prog, List.append args (List.rev Config.buck_build_args))
@ -543,7 +549,7 @@ let run_prologue mode =
let run_epilogue mode =
( if CLOpt.is_originator then
if CLOpt.is_originator then (
let in_buck_mode = match mode with PythonCapture (BBuck, _) -> true | _ -> false in
if Config.developer_mode then StatsAggregator.generate_files () ;
if Config.equal_analyzer Config.analyzer Config.Crashcontext then

@ -61,7 +61,12 @@ let compile compiler build_prog build_args =
| None ->
let verbose_errlog = Utils.with_file_in verbose_out_file ~f:In_channel.input_all in
L.(die UserError)
"@\n*** Failed to execute compilation command: %s@\n*** Command: %s@\n*** Output:@\n%s%s@\n*** Infer needs a working compilation command to run.@."
"@\n\
*** Failed to execute compilation command: %s@\n\
*** Command: %s@\n\
*** Output:@\n\
%s%s@\n\
*** Infer needs a working compilation command to run.@."
(Unix.Exit_or_signal.to_string_hum (Error err))
shell_cmd log verbose_errlog )
| exception exn ->

@ -119,7 +119,8 @@ let load_from_verbose_output javac_verbose_out =
1. [wrote DirectoryFileObject[/path/to/classes_out:path/to/File.java]], leaves `path/to/File.java` in match group 2
2. [wrote RegularFileObject[path/to/File.java]], leaves `path/to/File.java` in match group 5
3. [wrote SimpleFileObject[path/to/File.java]], also leaves `path/to/File.java` in match group 5 *)
"\\[wrote \\(DirectoryFileObject\\[%s:\\(.*\\)\\|\\(\\(Regular\\|Simple\\)FileObject\\[\\(.*\\)\\)\\)\\]\\]"
"\\[wrote \
\\(DirectoryFileObject\\[%s:\\(.*\\)\\|\\(\\(Regular\\|Simple\\)FileObject\\[\\(.*\\)\\)\\)\\]\\]"
Config.javac_classes_out)
in
let source_filename_re =

@ -747,8 +747,8 @@ module Make (TaintSpecification : TaintSpec.S) = struct
(* invariant 1: sinks with no footprint sources are dead and should be forgotten *)
if Sources.Footprint.is_empty footprint_sources && not (Sinks.is_empty sinks) then
Logging.die InternalError
"Trace %a associated with %a tracks sinks even though no more sources can flow into them"
Sinks.pp sinks AccessPath.Abs.pp access_path ;
"Trace %a associated with %a tracks sinks even though no more sources can flow into \
them" Sinks.pp sinks AccessPath.Abs.pp access_path ;
(* invariant 2: we should never have sinks without sources *)
if Sources.is_empty sources && not (Sinks.is_empty sinks) then
Logging.die InternalError "We have sinks %a associated with %a, but no sources" Sinks.pp

@ -251,13 +251,13 @@ let check_copyright fname =
let lines_arr = Array.of_list lines in
match find_copyright_line lines 0 with
| None ->
if file_should_have_copyright fname then
if file_should_have_copyright fname then (
let year = 1900 + (Unix.localtime (Unix.time ())).Unix.tm_year in
let com_style = List.Assoc.find_exn com_style_of_lang ~equal:Filename.check_suffix fname in
let prefix = prefix_of_comment_style com_style in
let start = default_start_line_of_com_style com_style in
output_diff fname lines_arr start (-1) (-1) 0 false year com_style prefix ;
Pervasives.exit copyright_modified_exit_code
Pervasives.exit copyright_modified_exit_code )
| Some n ->
let line = lines_arr.(n) in
let cstart, com_style = find_comment_start_and_style lines_arr n in
@ -270,10 +270,10 @@ let check_copyright fname =
Pervasives.exit copyright_malformed_exit_code
| Some fb_year ->
let prefix = prefix_of_comment_style com_style in
if copyright_has_changed mono fb_year com_style prefix cstart cend lines_arr then
if copyright_has_changed mono fb_year com_style prefix cstart cend lines_arr then (
let len = String.length line in
output_diff fname lines_arr cstart n cend len mono fb_year com_style prefix ;
Pervasives.exit copyright_modified_exit_code )
Pervasives.exit copyright_modified_exit_code ) )
else (
F.eprintf "Copyright not recognized: %s@." fname ;
Pervasives.exit copyright_malformed_exit_code )

@ -140,8 +140,9 @@ let tests =
; read_field_to_id "read_id" "base_id" "f"
; var_assign_id "var" "read_id"
; invariant
"{ base_id$0.f* => (SOURCE -> ?),\n ret_id$0* => (SOURCE -> ?),\n &var* => (SOURCE -> ?) }"
] )
"{ base_id$0.f* => (SOURCE -> ?),\n \
ret_id$0* => (SOURCE -> ?),\n \
&var* => (SOURCE -> ?) }" ] )
; ( "source flows to var then cleared"
, [ assign_to_source "ret_id"
; var_assign_id "var" "ret_id"

Loading…
Cancel
Save