diff --git a/infer/documentation/issues/NONEXHAUSTIVE_PATTERN_MATCH.md b/infer/documentation/issues/NONEXHAUSTIVE_PATTERN_MATCH.md deleted file mode 100644 index 4dfad9f8e..000000000 --- a/infer/documentation/issues/NONEXHAUSTIVE_PATTERN_MATCH.md +++ /dev/null @@ -1,10 +0,0 @@ -## Nonexhaustive pattern match in Erlang - -Reports an error when a function clause is missing. - -For example, if we call `tail([])` and the full definition of `tail` is -```erlang -tail([_|Xs]) -> Xs. -``` - -The error is also reported if the failing pattern match is in a `case` expression. diff --git a/infer/documentation/issues/NO_MATCHING_CASE_CLAUSE.md b/infer/documentation/issues/NO_MATCHING_CASE_CLAUSE.md new file mode 100644 index 000000000..397b65d33 --- /dev/null +++ b/infer/documentation/issues/NO_MATCHING_CASE_CLAUSE.md @@ -0,0 +1,13 @@ +## No matching case clause in Erlang + +Reports an error when none of the clauses of a `case` match the expression. Corresponds to the `{case_clause,V}` error in the Erlang runtime. + +For example, if we call `tail([])` and the full definition of `tail` is +```erlang +tail(X) -> + case X of + [_|T] -> T + end. +``` + +This error is reported if either the pattern(s) or the guard(s) prevent matching any of the clauses. diff --git a/infer/documentation/issues/NO_MATCHING_FUNCTION_CLAUSE.md b/infer/documentation/issues/NO_MATCHING_FUNCTION_CLAUSE.md new file mode 100644 index 000000000..006de5e24 --- /dev/null +++ b/infer/documentation/issues/NO_MATCHING_FUNCTION_CLAUSE.md @@ -0,0 +1,10 @@ +## No matching function clause in Erlang + +Reports an error when none of the clauses of a function match the arguments of a call. Corresponds to the `function_clause` error in the Erlang runtime. + +For example, if we call `tail([])` and the full definition of `tail` is +```erlang +tail([_|Xs]) -> Xs. +``` + +This error is reported if either the pattern(s) or the guard(s) prevent matching any of the clauses. diff --git a/infer/documentation/issues/NO_MATCH_OF_RHS.md b/infer/documentation/issues/NO_MATCH_OF_RHS.md new file mode 100644 index 000000000..8c9f5bd3d --- /dev/null +++ b/infer/documentation/issues/NO_MATCH_OF_RHS.md @@ -0,0 +1,5 @@ +## No match of right hand side value in Erlang + +Reports an error when the right hand side value of a `match` expression does not match the pattern on the left hand side. Corresponds to the `{badmatch,V}` error in the Erlang runtime. + +For example, `[H|T] = []` gives the error because the left hand side pattern requires at least one element in the list on the right hand side. diff --git a/infer/documentation/issues/NO_TRUE_BRANCH_IN_IF.md b/infer/documentation/issues/NO_TRUE_BRANCH_IN_IF.md new file mode 100644 index 000000000..2e5191c08 --- /dev/null +++ b/infer/documentation/issues/NO_TRUE_BRANCH_IN_IF.md @@ -0,0 +1,12 @@ +## No true branch when evaluating an if expression in Erlang + +Reports an error when none of the branches of an `if` expression evaluate to true. Corresponds to the `if_clause` error in the Erlang runtime. + +For example, if we call `sign(0)` and the full definition of `sign` is +```erlang +sign(X) -> + if + X > 0 -> positive; + X < 0 -> negative + end. +``` diff --git a/infer/man/man1/infer-full.txt b/infer/man/man1/infer-full.txt index c4b4c017b..a7fdfbfe6 100644 --- a/infer/man/man1/infer-full.txt +++ b/infer/man/man1/infer-full.txt @@ -550,7 +550,10 @@ OPTIONS NIL_BLOCK_CALL (enabled by default), NIL_INSERTION_INTO_COLLECTION (enabled by default), NIL_MESSAGING_TO_NON_POD (enabled by default), - NONEXHAUSTIVE_PATTERN_MATCH (enabled by default), + NO_MATCHING_CASE_CLAUSE (enabled by default), + NO_MATCHING_FUNCTION_CLAUSE (enabled by default), + NO_MATCH_OF_RHS (enabled by default), + NO_TRUE_BRANCH_IN_IF (enabled by default), NULLPTR_DEREFERENCE (enabled by default), NULL_DEREFERENCE (enabled by default), OPTIONAL_EMPTY_ACCESS (enabled by default), diff --git a/infer/man/man1/infer-report.txt b/infer/man/man1/infer-report.txt index f8464a969..e21f91df6 100644 --- a/infer/man/man1/infer-report.txt +++ b/infer/man/man1/infer-report.txt @@ -221,7 +221,10 @@ OPTIONS NIL_BLOCK_CALL (enabled by default), NIL_INSERTION_INTO_COLLECTION (enabled by default), NIL_MESSAGING_TO_NON_POD (enabled by default), - NONEXHAUSTIVE_PATTERN_MATCH (enabled by default), + NO_MATCHING_CASE_CLAUSE (enabled by default), + NO_MATCHING_FUNCTION_CLAUSE (enabled by default), + NO_MATCH_OF_RHS (enabled by default), + NO_TRUE_BRANCH_IN_IF (enabled by default), NULLPTR_DEREFERENCE (enabled by default), NULL_DEREFERENCE (enabled by default), OPTIONAL_EMPTY_ACCESS (enabled by default), diff --git a/infer/man/man1/infer.txt b/infer/man/man1/infer.txt index af963bab2..8b11d3e3e 100644 --- a/infer/man/man1/infer.txt +++ b/infer/man/man1/infer.txt @@ -550,7 +550,10 @@ OPTIONS NIL_BLOCK_CALL (enabled by default), NIL_INSERTION_INTO_COLLECTION (enabled by default), NIL_MESSAGING_TO_NON_POD (enabled by default), - NONEXHAUSTIVE_PATTERN_MATCH (enabled by default), + NO_MATCHING_CASE_CLAUSE (enabled by default), + NO_MATCHING_FUNCTION_CLAUSE (enabled by default), + NO_MATCH_OF_RHS (enabled by default), + NO_TRUE_BRANCH_IN_IF (enabled by default), NULLPTR_DEREFERENCE (enabled by default), NULL_DEREFERENCE (enabled by default), OPTIONAL_EMPTY_ACCESS (enabled by default), diff --git a/infer/src/IR/BuiltinDecl.ml b/infer/src/IR/BuiltinDecl.ml index 8fe2c0b8e..dcb5f6d9b 100644 --- a/infer/src/IR/BuiltinDecl.ml +++ b/infer/src/IR/BuiltinDecl.ml @@ -76,12 +76,18 @@ let __delete_array = create_procname "__delete_array" let __delete_locked_attribute = create_procname "__delete_locked_attribute" +let __erlang_error_badmatch = create_procname "__erlang_error_badmatch" + +let __erlang_error_case_clause = create_procname "__erlang_error_case_clause" + +let __erlang_error_function_clause = create_procname "__erlang_error_function_clause" + +let __erlang_error_if_clause = create_procname "__erlang_error_if_clause" + let __erlang_make_cons = create_procname "__erlang_make_cons" let __erlang_make_nil = create_procname "__erlang_make_nil" -let __erlang_pattern_fail = create_procname "__erlang_pattern_fail" - let __exit = create_procname "_exit" let __objc_bridge_transfer = create_procname "__objc_bridge_transfer" diff --git a/infer/src/IR/BuiltinDecl.mli b/infer/src/IR/BuiltinDecl.mli index 496dab5fd..3232e0978 100644 --- a/infer/src/IR/BuiltinDecl.mli +++ b/infer/src/IR/BuiltinDecl.mli @@ -13,13 +13,18 @@ include BUILTINS.S with type t = Procname.t val is_declared : Procname.t -> bool +val __erlang_error_badmatch : Procname.t + +val __erlang_error_case_clause : Procname.t + +val __erlang_error_function_clause : Procname.t + +val __erlang_error_if_clause : Procname.t + val __erlang_make_cons : Procname.t val __erlang_make_nil : Procname.t -val __erlang_pattern_fail : Procname.t -(** all patterns in a function failed to match *) - val __infer_initializer_list : Procname.t val __infer_skip_function : Procname.t diff --git a/infer/src/base/IssueType.ml b/infer/src/base/IssueType.ml index a015cd63c..0511b9144 100644 --- a/infer/src/base/IssueType.ml +++ b/infer/src/base/IssueType.ml @@ -804,9 +804,24 @@ let nil_messaging_to_non_pod = ~user_documentation:[%blob "../../documentation/issues/NIL_MESSAGING_TO_NON_POD.md"] -let nonexhaustive_pattern_match = - register ~id:"NONEXHAUSTIVE_PATTERN_MATCH" Error Pulse - ~user_documentation:[%blob "../../documentation/issues/NONEXHAUSTIVE_PATTERN_MATCH.md"] +let no_match_of_rhs = + register ~id:"NO_MATCH_OF_RHS" Error Pulse + ~user_documentation:[%blob "../../documentation/issues/NO_MATCH_OF_RHS.md"] + + +let no_matching_case_clause = + register ~id:"NO_MATCHING_CASE_CLAUSE" Error Pulse + ~user_documentation:[%blob "../../documentation/issues/NO_MATCHING_CASE_CLAUSE.md"] + + +let no_matching_function_clause = + register ~id:"NO_MATCHING_FUNCTION_CLAUSE" Error Pulse + ~user_documentation:[%blob "../../documentation/issues/NO_MATCHING_FUNCTION_CLAUSE.md"] + + +let no_true_branch_in_if = + register ~id:"NO_TRUE_BRANCH_IN_IF" Error Pulse + ~user_documentation:[%blob "../../documentation/issues/NO_TRUE_BRANCH_IN_IF.md"] let null_dereference = diff --git a/infer/src/base/IssueType.mli b/infer/src/base/IssueType.mli index cbd92d179..dc72d262d 100644 --- a/infer/src/base/IssueType.mli +++ b/infer/src/base/IssueType.mli @@ -282,7 +282,13 @@ val nil_insertion_into_collection : t val nil_messaging_to_non_pod : t -val nonexhaustive_pattern_match : t +val no_match_of_rhs : t + +val no_matching_case_clause : t + +val no_matching_function_clause : t + +val no_true_branch_in_if : t val null_dereference : t diff --git a/infer/src/erlang/ErlangTranslator.ml b/infer/src/erlang/ErlangTranslator.ml index f3822c962..4ce9c43a6 100644 --- a/infer/src/erlang/ErlangTranslator.ml +++ b/infer/src/erlang/ErlangTranslator.ml @@ -158,11 +158,11 @@ module Node = struct make env kind [prune] - let make_pattern_fail env = + let make_fail env fail_function = let any = typ_of_name Any in let crash_instruction = let ret_var = Ident.create_fresh Ident.knormal (* not used: nothing returned *) in - let pattern_fail_fun = Exp.Const (Cfun BuiltinDecl.__erlang_pattern_fail) in + let pattern_fail_fun = Exp.Const (Cfun fail_function) in Sil.Call ((ret_var, any), pattern_fail_fun, [], env.location, CallFlags.default) in make_throw env crash_instruction @@ -446,7 +446,7 @@ and translate_expression env {Ast.line; simple_expression} = let id = Ident.create_fresh Ident.knormal in let expr_block = translate_expression {env with result= Present (Exp.Var id)} expression in let blocks = Block.any env (List.map ~f:(translate_case_clause env [id]) cases) in - let crash_node = Node.make_pattern_fail env in + let crash_node = Node.make_fail env BuiltinDecl.__erlang_error_case_clause in blocks.exit_failure |~~> [crash_node] ; let blocks = {blocks with exit_failure= crash_node} in Block.all env [expr_block; blocks] @@ -463,7 +463,7 @@ and translate_expression env {Ast.line; simple_expression} = Block.all env [head_block; tail_block; Block.make_instruction env [call_instruction]] | If clauses -> let blocks = Block.any env (List.map ~f:(translate_case_clause env []) clauses) in - let crash_node = Node.make_pattern_fail env in + let crash_node = Node.make_fail env BuiltinDecl.__erlang_error_if_clause in blocks.exit_failure |~~> [crash_node] ; let blocks = {blocks with exit_failure= crash_node} in blocks @@ -484,7 +484,7 @@ and translate_expression env {Ast.line; simple_expression} = | Match {pattern; body} -> let body_block = translate_expression {env with result= Present (Exp.Var ret_var)} body in let pattern_block = translate_pattern env ret_var pattern in - let crash_node = Node.make_pattern_fail env in + let crash_node = Node.make_fail env BuiltinDecl.__erlang_error_badmatch in pattern_block.exit_failure |~~> [crash_node] ; let pattern_block = {pattern_block with exit_failure= crash_node} in Block.all env [body_block; pattern_block] @@ -604,8 +604,8 @@ let translate_one_function env cfg function_ clauses = loads_node |~~> [start] in let () = - (* If all patterns fail, call BuiltinDecl.__erlang_pattern_fail *) - let crash_node = Node.make_pattern_fail env in + (* If all patterns fail, call special method *) + let crash_node = Node.make_fail env BuiltinDecl.__erlang_error_function_clause in exit_failure |~~> [crash_node] ; crash_node |~~> [Procdesc.get_exit_node procdesc] in diff --git a/infer/src/pulse/PulseDiagnostic.ml b/infer/src/pulse/PulseDiagnostic.ml index 7b1da9820..391f5abf4 100644 --- a/infer/src/pulse/PulseDiagnostic.ml +++ b/infer/src/pulse/PulseDiagnostic.ml @@ -22,7 +22,11 @@ type access_to_invalid_address = ; must_be_valid_reason: Invalidation.must_be_valid_reason option } [@@deriving compare, equal] -type nonexhaustive_pattern_match = {calling_context: calling_context; location: Location.t} +type erlang_error = + | Badmatch of {calling_context: calling_context; location: Location.t} + | Case_clause of {calling_context: calling_context; location: Location.t} + | Function_clause of {calling_context: calling_context; location: Location.t} + | If_clause of {calling_context: calling_context; location: Location.t} [@@deriving compare, equal] type read_uninitialized_value = {calling_context: calling_context; trace: Trace.t} @@ -30,14 +34,14 @@ type read_uninitialized_value = {calling_context: calling_context; trace: Trace. let yojson_of_access_to_invalid_address = [%yojson_of: _] -let yojson_of_nonexhaustive_pattern_match = [%yojson_of: _] +let yojson_of_erlang_error = [%yojson_of: _] let yojson_of_read_uninitialized_value = [%yojson_of: _] type t = | AccessToInvalidAddress of access_to_invalid_address | MemoryLeak of {procname: Procname.t; allocation_trace: Trace.t; location: Location.t} - | NonexhaustivePatternMatch of nonexhaustive_pattern_match + | ErlangError of erlang_error | ReadUninitializedValue of read_uninitialized_value | StackVariableAddressEscape of {variable: Var.t; history: ValueHistory.t; location: Location.t} [@@deriving equal] @@ -50,7 +54,10 @@ let get_location = function | ReadUninitializedValue {calling_context= (_, location) :: _} -> (* report at the call site that triggers the bug *) location | MemoryLeak {location} - | NonexhaustivePatternMatch {location} + | ErlangError (Badmatch {location}) + | ErlangError (Case_clause {location}) + | ErlangError (Function_clause {location}) + | ErlangError (If_clause {location}) | StackVariableAddressEscape {location} -> location @@ -174,8 +181,14 @@ let get_message diagnostic = "%s memory leak. Memory dynamically allocated at line %d %a is not freed after the last \ access at %a" pulse_start_msg allocation_line pp_allocation_trace allocation_trace Location.pp location - | NonexhaustivePatternMatch {calling_context= _; location} -> - F.asprintf "%s nonexhaustive pattern match at %a" pulse_start_msg Location.pp location + | ErlangError (Badmatch {calling_context= _; location}) -> + F.asprintf "%s no match of RHS at %a" pulse_start_msg Location.pp location + | ErlangError (Case_clause {calling_context= _; location}) -> + F.asprintf "%s no matching case clause at %a" pulse_start_msg Location.pp location + | ErlangError (Function_clause {calling_context= _; location}) -> + F.asprintf "%s no matching function clause at %a" pulse_start_msg Location.pp location + | ErlangError (If_clause {calling_context= _; location}) -> + F.asprintf "%s no true branch in if expression at %a" pulse_start_msg Location.pp location | ReadUninitializedValue {calling_context; trace} -> let root_var = PulseTrace.find_map trace ~f:(function VariableDeclared (pvar, _) -> Some pvar | _ -> None) @@ -309,9 +322,18 @@ let get_trace = function ~pp_immediate:(fun fmt -> F.fprintf fmt "allocated by `%a` here" Procname.pp procname) allocation_trace @@ [Errlog.make_trace_element 0 location "memory becomes unreachable here" []] - | NonexhaustivePatternMatch {calling_context; location} -> + | ErlangError (Badmatch {calling_context; location}) -> get_trace_calling_context calling_context - @@ [Errlog.make_trace_element 0 location "no pattern match here" []] + @@ [Errlog.make_trace_element 0 location "no match of RHS here" []] + | ErlangError (Case_clause {calling_context; location}) -> + get_trace_calling_context calling_context + @@ [Errlog.make_trace_element 0 location "no matching case clause here" []] + | ErlangError (Function_clause {calling_context; location}) -> + get_trace_calling_context calling_context + @@ [Errlog.make_trace_element 0 location "no matching function clause here" []] + | ErlangError (If_clause {calling_context; location}) -> + get_trace_calling_context calling_context + @@ [Errlog.make_trace_element 0 location "no true branch in if expression here" []] | ReadUninitializedValue {calling_context; trace} -> get_trace_calling_context calling_context @@ Trace.add_to_errlog ~nesting:0 @@ -333,8 +355,14 @@ let get_issue_type = function Invalidation.issue_type_of_cause invalidation must_be_valid_reason | MemoryLeak _ -> IssueType.pulse_memory_leak - | NonexhaustivePatternMatch _ -> - IssueType.nonexhaustive_pattern_match + | ErlangError (Badmatch _) -> + IssueType.no_match_of_rhs + | ErlangError (Case_clause _) -> + IssueType.no_matching_case_clause + | ErlangError (Function_clause _) -> + IssueType.no_matching_function_clause + | ErlangError (If_clause _) -> + IssueType.no_true_branch_in_if | ReadUninitializedValue _ -> IssueType.uninitialized_value_pulse | StackVariableAddressEscape _ -> diff --git a/infer/src/pulse/PulseDiagnostic.mli b/infer/src/pulse/PulseDiagnostic.mli index 717ee1559..8cee8c6f6 100644 --- a/infer/src/pulse/PulseDiagnostic.mli +++ b/infer/src/pulse/PulseDiagnostic.mli @@ -28,7 +28,11 @@ type access_to_invalid_address = ; must_be_valid_reason: Invalidation.must_be_valid_reason option } [@@deriving compare, equal, yojson_of] -type nonexhaustive_pattern_match = {calling_context: calling_context; location: Location.t} +type erlang_error = + | Badmatch of {calling_context: calling_context; location: Location.t} + | Case_clause of {calling_context: calling_context; location: Location.t} + | Function_clause of {calling_context: calling_context; location: Location.t} + | If_clause of {calling_context: calling_context; location: Location.t} [@@deriving compare, equal, yojson_of] type read_uninitialized_value = @@ -44,7 +48,7 @@ type read_uninitialized_value = type t = | AccessToInvalidAddress of access_to_invalid_address | MemoryLeak of {procname: Procname.t; allocation_trace: Trace.t; location: Location.t} - | NonexhaustivePatternMatch of nonexhaustive_pattern_match + | ErlangError of erlang_error | ReadUninitializedValue of read_uninitialized_value | StackVariableAddressEscape of {variable: Var.t; history: ValueHistory.t; location: Location.t} [@@deriving equal] diff --git a/infer/src/pulse/PulseLatentIssue.ml b/infer/src/pulse/PulseLatentIssue.ml index 8749ae50a..ed4beb91f 100644 --- a/infer/src/pulse/PulseLatentIssue.ml +++ b/infer/src/pulse/PulseLatentIssue.ml @@ -12,15 +12,15 @@ module Arithmetic = PulseArithmetic type t = | AccessToInvalidAddress of Diagnostic.access_to_invalid_address - | NonexhaustivePatternMatch of Diagnostic.nonexhaustive_pattern_match + | ErlangError of Diagnostic.erlang_error | ReadUninitializedValue of Diagnostic.read_uninitialized_value [@@deriving compare, equal, yojson_of] let to_diagnostic = function | AccessToInvalidAddress access_to_invalid_address -> Diagnostic.AccessToInvalidAddress access_to_invalid_address - | NonexhaustivePatternMatch nonexhaustive_pattern_match -> - Diagnostic.NonexhaustivePatternMatch nonexhaustive_pattern_match + | ErlangError erlang_error -> + Diagnostic.ErlangError erlang_error | ReadUninitializedValue read_uninitialized_value -> Diagnostic.ReadUninitializedValue read_uninitialized_value @@ -28,9 +28,14 @@ let to_diagnostic = function let add_call call_and_loc = function | AccessToInvalidAddress access -> AccessToInvalidAddress {access with calling_context= call_and_loc :: access.calling_context} - | NonexhaustivePatternMatch nonmatch -> - NonexhaustivePatternMatch - {nonmatch with calling_context= call_and_loc :: nonmatch.calling_context} + | ErlangError (Badmatch {calling_context; location}) -> + ErlangError (Badmatch {calling_context= call_and_loc :: calling_context; location}) + | ErlangError (Case_clause {calling_context; location}) -> + ErlangError (Case_clause {calling_context= call_and_loc :: calling_context; location}) + | ErlangError (Function_clause {calling_context; location}) -> + ErlangError (Function_clause {calling_context= call_and_loc :: calling_context; location}) + | ErlangError (If_clause {calling_context; location}) -> + ErlangError (If_clause {calling_context= call_and_loc :: calling_context; location}) | ReadUninitializedValue read -> ReadUninitializedValue {read with calling_context= call_and_loc :: read.calling_context} @@ -53,7 +58,7 @@ let should_report (astate : AbductiveDomain.summary) (diagnostic : Diagnostic.t) `ReportNow | AccessToInvalidAddress latent -> if is_manifest astate then `ReportNow else `DelayReport (AccessToInvalidAddress latent) - | NonexhaustivePatternMatch latent -> - if is_manifest astate then `ReportNow else `DelayReport (NonexhaustivePatternMatch latent) + | ErlangError latent -> + if is_manifest astate then `ReportNow else `DelayReport (ErlangError latent) | ReadUninitializedValue latent -> if is_manifest astate then `ReportNow else `DelayReport (ReadUninitializedValue latent) diff --git a/infer/src/pulse/PulseLatentIssue.mli b/infer/src/pulse/PulseLatentIssue.mli index 8532b25e8..778f0e4f2 100644 --- a/infer/src/pulse/PulseLatentIssue.mli +++ b/infer/src/pulse/PulseLatentIssue.mli @@ -15,7 +15,7 @@ module AbductiveDomain = PulseAbductiveDomain type t = | AccessToInvalidAddress of Diagnostic.access_to_invalid_address - | NonexhaustivePatternMatch of Diagnostic.nonexhaustive_pattern_match + | ErlangError of Diagnostic.erlang_error | ReadUninitializedValue of Diagnostic.read_uninitialized_value [@@deriving compare, equal, yojson_of] diff --git a/infer/src/pulse/PulseModels.ml b/infer/src/pulse/PulseModels.ml index 181b10504..e5341254e 100644 --- a/infer/src/pulse/PulseModels.ml +++ b/infer/src/pulse/PulseModels.ml @@ -1507,11 +1507,32 @@ module Android = struct end module Erlang = struct - let pattern_fail : model = + let error_badmatch : model = + fun {location} astate -> + [ Error + (ReportableError {astate; diagnostic= ErlangError (Badmatch {calling_context= []; location})}) + ] + + + let error_case_clause : model = + fun {location} astate -> + [ Error + (ReportableError + {astate; diagnostic= ErlangError (Case_clause {calling_context= []; location})}) ] + + + let error_function_clause : model = + fun {location} astate -> + [ Error + (ReportableError + {astate; diagnostic= ErlangError (Function_clause {calling_context= []; location})}) ] + + + let error_if_clause : model = fun {location} astate -> [ Error (ReportableError - {astate; diagnostic= NonexhaustivePatternMatch {calling_context= []; location}}) ] + {astate; diagnostic= ErlangError (If_clause {calling_context= []; location})}) ] let make_nil : model = @@ -1627,7 +1648,11 @@ module ProcNameDispatcher = struct ; +BuiltinDecl.(match_builtin __erlang_make_cons) <>$ capt_arg_payload $+ capt_arg_payload $--> Erlang.make_cons ; +BuiltinDecl.(match_builtin __erlang_make_nil) <>--> Erlang.make_nil - ; +BuiltinDecl.(match_builtin __erlang_pattern_fail) <>--> Erlang.pattern_fail + ; +BuiltinDecl.(match_builtin __erlang_error_badmatch) <>--> Erlang.error_badmatch + ; +BuiltinDecl.(match_builtin __erlang_error_case_clause) <>--> Erlang.error_case_clause + ; +BuiltinDecl.(match_builtin __erlang_error_function_clause) + <>--> Erlang.error_function_clause + ; +BuiltinDecl.(match_builtin __erlang_error_if_clause) <>--> Erlang.error_if_clause ; +BuiltinDecl.(match_builtin __infer_initializer_list) <>$ capt_arg_payload $+...$--> Misc.id_first_arg ~desc:"infer_init_list" diff --git a/infer/src/pulse/PulseReport.ml b/infer/src/pulse/PulseReport.ml index e4340914e..7392569ce 100644 --- a/infer/src/pulse/PulseReport.ml +++ b/infer/src/pulse/PulseReport.ml @@ -47,10 +47,7 @@ let is_nullsafe_error tenv diagnostic jn = being equal to the value being dereferenced *) let is_constant_deref_without_invalidation (diagnostic : Diagnostic.t) = match diagnostic with - | MemoryLeak _ - | NonexhaustivePatternMatch _ - | ReadUninitializedValue _ - | StackVariableAddressEscape _ -> + | MemoryLeak _ | ErlangError _ | ReadUninitializedValue _ | StackVariableAddressEscape _ -> false | AccessToInvalidAddress {invalidation; access_trace} -> ( match invalidation with diff --git a/infer/tests/codetoanalyze/erlang/features/issues.exp b/infer/tests/codetoanalyze/erlang/features/issues.exp index fad3f86c9..875fc551d 100644 --- a/infer/tests/codetoanalyze/erlang/features/issues.exp +++ b/infer/tests/codetoanalyze/erlang/features/issues.exp @@ -1,15 +1,15 @@ -codetoanalyze/erlang/features/src/arithmetic.erl, test_add1_Bad/0, -9, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [calling context starts here,in call to `warn/1`,no pattern match here] -codetoanalyze/erlang/features/src/arithmetic.erl, test_add2_Bad/0, -24, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [calling context starts here,in call to `warn/1`,no pattern match here] -codetoanalyze/erlang/features/src/arithmetic.erl, test_idiv1_Bad/0, -114, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [calling context starts here,in call to `warn/1`,no pattern match here] -codetoanalyze/erlang/features/src/arithmetic.erl, test_mul1_Bad/0, -69, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [calling context starts here,in call to `warn/1`,no pattern match here] -codetoanalyze/erlang/features/src/arithmetic.erl, test_mul2_Bad/0, -84, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [calling context starts here,in call to `warn/1`,no pattern match here] -codetoanalyze/erlang/features/src/arithmetic.erl, test_mul3_Bad/0, -99, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [calling context starts here,in call to `warn/1`,no pattern match here] -codetoanalyze/erlang/features/src/arithmetic.erl, test_multiple_Bad/0, -158, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [calling context starts here,in call to `warn/1`,no pattern match here] -codetoanalyze/erlang/features/src/arithmetic.erl, test_rem_Bad/0, -145, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [calling context starts here,in call to `warn/1`,no pattern match here] -codetoanalyze/erlang/features/src/arithmetic.erl, test_sub1_Bad/0, -39, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [calling context starts here,in call to `warn/1`,no pattern match here] -codetoanalyze/erlang/features/src/arithmetic.erl, test_sub2_Bad/0, -54, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [calling context starts here,in call to `warn/1`,no pattern match here] -codetoanalyze/erlang/features/src/arithmetic.erl, test_uminus1_Bad/0, -170, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [calling context starts here,in call to `warn/1`,no pattern match here] -codetoanalyze/erlang/features/src/arithmetic.erl, test_uminus2_Bad/0, -183, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [calling context starts here,in call to `warn/1`,no pattern match here] -codetoanalyze/erlang/features/src/arithmetic.erl, warn/1, 0, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [*** LATENT ***,no pattern match here] -codetoanalyze/erlang/features/src/block.erl, test_block_Bad/0, -15, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [calling context starts here,in call to `warn/1`,no pattern match here] -codetoanalyze/erlang/features/src/block.erl, warn/1, 0, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [*** LATENT ***,no pattern match here] +codetoanalyze/erlang/features/src/arithmetic.erl, test_add1_Bad/0, -9, NO_MATCHING_FUNCTION_CLAUSE, no_bucket, ERROR, [calling context starts here,in call to `warn/1`,no matching function clause here] +codetoanalyze/erlang/features/src/arithmetic.erl, test_add2_Bad/0, -24, NO_MATCHING_FUNCTION_CLAUSE, no_bucket, ERROR, [calling context starts here,in call to `warn/1`,no matching function clause here] +codetoanalyze/erlang/features/src/arithmetic.erl, test_idiv1_Bad/0, -114, NO_MATCHING_FUNCTION_CLAUSE, no_bucket, ERROR, [calling context starts here,in call to `warn/1`,no matching function clause here] +codetoanalyze/erlang/features/src/arithmetic.erl, test_mul1_Bad/0, -69, NO_MATCHING_FUNCTION_CLAUSE, no_bucket, ERROR, [calling context starts here,in call to `warn/1`,no matching function clause here] +codetoanalyze/erlang/features/src/arithmetic.erl, test_mul2_Bad/0, -84, NO_MATCHING_FUNCTION_CLAUSE, no_bucket, ERROR, [calling context starts here,in call to `warn/1`,no matching function clause here] +codetoanalyze/erlang/features/src/arithmetic.erl, test_mul3_Bad/0, -99, NO_MATCHING_FUNCTION_CLAUSE, no_bucket, ERROR, [calling context starts here,in call to `warn/1`,no matching function clause here] +codetoanalyze/erlang/features/src/arithmetic.erl, test_multiple_Bad/0, -158, NO_MATCHING_FUNCTION_CLAUSE, no_bucket, ERROR, [calling context starts here,in call to `warn/1`,no matching function clause here] +codetoanalyze/erlang/features/src/arithmetic.erl, test_rem_Bad/0, -145, NO_MATCHING_FUNCTION_CLAUSE, no_bucket, ERROR, [calling context starts here,in call to `warn/1`,no matching function clause here] +codetoanalyze/erlang/features/src/arithmetic.erl, test_sub1_Bad/0, -39, NO_MATCHING_FUNCTION_CLAUSE, no_bucket, ERROR, [calling context starts here,in call to `warn/1`,no matching function clause here] +codetoanalyze/erlang/features/src/arithmetic.erl, test_sub2_Bad/0, -54, NO_MATCHING_FUNCTION_CLAUSE, no_bucket, ERROR, [calling context starts here,in call to `warn/1`,no matching function clause here] +codetoanalyze/erlang/features/src/arithmetic.erl, test_uminus1_Bad/0, -170, NO_MATCHING_FUNCTION_CLAUSE, no_bucket, ERROR, [calling context starts here,in call to `warn/1`,no matching function clause here] +codetoanalyze/erlang/features/src/arithmetic.erl, test_uminus2_Bad/0, -183, NO_MATCHING_FUNCTION_CLAUSE, no_bucket, ERROR, [calling context starts here,in call to `warn/1`,no matching function clause here] +codetoanalyze/erlang/features/src/arithmetic.erl, warn/1, 0, NO_MATCHING_FUNCTION_CLAUSE, no_bucket, ERROR, [*** LATENT ***,no matching function clause here] +codetoanalyze/erlang/features/src/block.erl, test_block_Bad/0, -15, NO_MATCHING_FUNCTION_CLAUSE, no_bucket, ERROR, [calling context starts here,in call to `warn/1`,no matching function clause here] +codetoanalyze/erlang/features/src/block.erl, warn/1, 0, NO_MATCHING_FUNCTION_CLAUSE, no_bucket, ERROR, [*** LATENT ***,no matching function clause here] diff --git a/infer/tests/codetoanalyze/erlang/nonmatch/issues.exp b/infer/tests/codetoanalyze/erlang/nonmatch/issues.exp index 260371b9e..f8460bf6f 100644 --- a/infer/tests/codetoanalyze/erlang/nonmatch/issues.exp +++ b/infer/tests/codetoanalyze/erlang/nonmatch/issues.exp @@ -1,30 +1,30 @@ -codetoanalyze/erlang/nonmatch/src/case_expression.erl, case_simple/1, 1, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [*** LATENT ***,no pattern match here] -codetoanalyze/erlang/nonmatch/src/case_expression.erl, case_test_simple3_Bad/0, -14, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [calling context starts here,in call to `case_simple/1`,no pattern match here] -codetoanalyze/erlang/nonmatch/src/case_expression.erl, case_test_tail3_Bad/0, -15, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [calling context starts here,in call to `tail_with_case/1`,no pattern match here] -codetoanalyze/erlang/nonmatch/src/case_expression.erl, tail_with_case/1, 1, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [*** LATENT ***,no pattern match here] -codetoanalyze/erlang/nonmatch/src/case_guards.erl, accepts_positive/1, 1, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [*** LATENT ***,no pattern match here] -codetoanalyze/erlang/nonmatch/src/case_guards.erl, accepts_positive2/1, 1, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [*** LATENT ***,no pattern match here] -codetoanalyze/erlang/nonmatch/src/case_guards.erl, test_accepts_positive2_Bad/0, -16, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [calling context starts here,in call to `accepts_positive2/1`,no pattern match here] -codetoanalyze/erlang/nonmatch/src/case_guards.erl, test_accepts_positive_Bad/0, -15, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [calling context starts here,in call to `accepts_positive/1`,no pattern match here] -codetoanalyze/erlang/nonmatch/src/function.erl, assert_empty/1, 0, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [*** LATENT ***,no pattern match here] -codetoanalyze/erlang/nonmatch/src/function.erl, assert_second_is_nil/1, 0, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [*** LATENT ***,no pattern match here] -codetoanalyze/erlang/nonmatch/src/function.erl, list_match_test_empty2_Bad/0, -12, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [calling context starts here,in call to `assert_empty/1`,no pattern match here] -codetoanalyze/erlang/nonmatch/src/function.erl, list_match_test_empty3_Bad/0, -14, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [calling context starts here,in call to `assert_empty/1`,no pattern match here] -codetoanalyze/erlang/nonmatch/src/function.erl, list_match_test_secondnil3_Bad/0, -20, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [calling context starts here,in call to `assert_second_is_nil/1`,no pattern match here] -codetoanalyze/erlang/nonmatch/src/function.erl, list_match_test_tail3_Bad/0, -8, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [calling context starts here,in call to `tail/1`,no pattern match here] -codetoanalyze/erlang/nonmatch/src/function.erl, tail/1, 0, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [*** LATENT ***,no pattern match here] -codetoanalyze/erlang/nonmatch/src/function_guards.erl, accepts_positive/1, 0, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [*** LATENT ***,no pattern match here] -codetoanalyze/erlang/nonmatch/src/function_guards.erl, accepts_positive2/1, 0, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [*** LATENT ***,no pattern match here] -codetoanalyze/erlang/nonmatch/src/function_guards.erl, fp_accepts_all_tricky3/1, 0, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [*** LATENT ***,no pattern match here] -codetoanalyze/erlang/nonmatch/src/function_guards.erl, possible_exception/1, 0, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [*** LATENT ***,no pattern match here] -codetoanalyze/erlang/nonmatch/src/function_guards.erl, test_accepts_positive2_Bad/0, -23, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [calling context starts here,in call to `accepts_positive2/1`,no pattern match here] -codetoanalyze/erlang/nonmatch/src/function_guards.erl, test_accepts_positive_Bad/0, -19, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [calling context starts here,in call to `accepts_positive/1`,no pattern match here] -codetoanalyze/erlang/nonmatch/src/function_guards.erl, test_possible_exception_Bad/0, -37, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [calling context starts here,in call to `possible_exception/1`,no pattern match here] -codetoanalyze/erlang/nonmatch/src/if_expression.erl, accepts_positive/1, 1, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [*** LATENT ***,no pattern match here] -codetoanalyze/erlang/nonmatch/src/if_expression.erl, test_accepts_positive_Bad/0, -13, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [calling context starts here,in call to `accepts_positive/1`,no pattern match here] +codetoanalyze/erlang/nonmatch/src/case_expression.erl, case_simple/1, 1, NO_MATCHING_CASE_CLAUSE, no_bucket, ERROR, [*** LATENT ***,no matching case clause here] +codetoanalyze/erlang/nonmatch/src/case_expression.erl, case_test_simple3_Bad/0, -14, NO_MATCHING_CASE_CLAUSE, no_bucket, ERROR, [calling context starts here,in call to `case_simple/1`,no matching case clause here] +codetoanalyze/erlang/nonmatch/src/case_expression.erl, case_test_tail3_Bad/0, -15, NO_MATCHING_CASE_CLAUSE, no_bucket, ERROR, [calling context starts here,in call to `tail_with_case/1`,no matching case clause here] +codetoanalyze/erlang/nonmatch/src/case_expression.erl, tail_with_case/1, 1, NO_MATCHING_CASE_CLAUSE, no_bucket, ERROR, [*** LATENT ***,no matching case clause here] +codetoanalyze/erlang/nonmatch/src/case_guards.erl, accepts_positive/1, 1, NO_MATCHING_CASE_CLAUSE, no_bucket, ERROR, [*** LATENT ***,no matching case clause here] +codetoanalyze/erlang/nonmatch/src/case_guards.erl, accepts_positive2/1, 1, NO_MATCHING_CASE_CLAUSE, no_bucket, ERROR, [*** LATENT ***,no matching case clause here] +codetoanalyze/erlang/nonmatch/src/case_guards.erl, test_accepts_positive2_Bad/0, -16, NO_MATCHING_CASE_CLAUSE, no_bucket, ERROR, [calling context starts here,in call to `accepts_positive2/1`,no matching case clause here] +codetoanalyze/erlang/nonmatch/src/case_guards.erl, test_accepts_positive_Bad/0, -15, NO_MATCHING_CASE_CLAUSE, no_bucket, ERROR, [calling context starts here,in call to `accepts_positive/1`,no matching case clause here] +codetoanalyze/erlang/nonmatch/src/function.erl, assert_empty/1, 0, NO_MATCHING_FUNCTION_CLAUSE, no_bucket, ERROR, [*** LATENT ***,no matching function clause here] +codetoanalyze/erlang/nonmatch/src/function.erl, assert_second_is_nil/1, 0, NO_MATCHING_FUNCTION_CLAUSE, no_bucket, ERROR, [*** LATENT ***,no matching function clause here] +codetoanalyze/erlang/nonmatch/src/function.erl, list_match_test_empty2_Bad/0, -12, NO_MATCHING_FUNCTION_CLAUSE, no_bucket, ERROR, [calling context starts here,in call to `assert_empty/1`,no matching function clause here] +codetoanalyze/erlang/nonmatch/src/function.erl, list_match_test_empty3_Bad/0, -14, NO_MATCHING_FUNCTION_CLAUSE, no_bucket, ERROR, [calling context starts here,in call to `assert_empty/1`,no matching function clause here] +codetoanalyze/erlang/nonmatch/src/function.erl, list_match_test_secondnil3_Bad/0, -20, NO_MATCHING_FUNCTION_CLAUSE, no_bucket, ERROR, [calling context starts here,in call to `assert_second_is_nil/1`,no matching function clause here] +codetoanalyze/erlang/nonmatch/src/function.erl, list_match_test_tail3_Bad/0, -8, NO_MATCHING_FUNCTION_CLAUSE, no_bucket, ERROR, [calling context starts here,in call to `tail/1`,no matching function clause here] +codetoanalyze/erlang/nonmatch/src/function.erl, tail/1, 0, NO_MATCHING_FUNCTION_CLAUSE, no_bucket, ERROR, [*** LATENT ***,no matching function clause here] +codetoanalyze/erlang/nonmatch/src/function_guards.erl, accepts_positive/1, 0, NO_MATCHING_FUNCTION_CLAUSE, no_bucket, ERROR, [*** LATENT ***,no matching function clause here] +codetoanalyze/erlang/nonmatch/src/function_guards.erl, accepts_positive2/1, 0, NO_MATCHING_FUNCTION_CLAUSE, no_bucket, ERROR, [*** LATENT ***,no matching function clause here] +codetoanalyze/erlang/nonmatch/src/function_guards.erl, fp_accepts_all_tricky3/1, 0, NO_MATCHING_FUNCTION_CLAUSE, no_bucket, ERROR, [*** LATENT ***,no matching function clause here] +codetoanalyze/erlang/nonmatch/src/function_guards.erl, possible_exception/1, 0, NO_MATCHING_FUNCTION_CLAUSE, no_bucket, ERROR, [*** LATENT ***,no matching function clause here] +codetoanalyze/erlang/nonmatch/src/function_guards.erl, test_accepts_positive2_Bad/0, -23, NO_MATCHING_FUNCTION_CLAUSE, no_bucket, ERROR, [calling context starts here,in call to `accepts_positive2/1`,no matching function clause here] +codetoanalyze/erlang/nonmatch/src/function_guards.erl, test_accepts_positive_Bad/0, -19, NO_MATCHING_FUNCTION_CLAUSE, no_bucket, ERROR, [calling context starts here,in call to `accepts_positive/1`,no matching function clause here] +codetoanalyze/erlang/nonmatch/src/function_guards.erl, test_possible_exception_Bad/0, -37, NO_MATCHING_FUNCTION_CLAUSE, no_bucket, ERROR, [calling context starts here,in call to `possible_exception/1`,no matching function clause here] +codetoanalyze/erlang/nonmatch/src/if_expression.erl, accepts_positive/1, 1, NO_TRUE_BRANCH_IN_IF, no_bucket, ERROR, [*** LATENT ***,no true branch in if expression here] +codetoanalyze/erlang/nonmatch/src/if_expression.erl, test_accepts_positive_Bad/0, -13, NO_TRUE_BRANCH_IN_IF, no_bucket, ERROR, [calling context starts here,in call to `accepts_positive/1`,no true branch in if expression here] codetoanalyze/erlang/nonmatch/src/match.erl, match_test_b_Bad/0, 1, CONSTANT_ADDRESS_DEREFERENCE, no_bucket, WARNING, [in call to `two/0`,is the constant 2,assigned,returned,return from call to `two/0`,invalid access occurs here] -codetoanalyze/erlang/nonmatch/src/match.erl, match_test_b_Bad/0, 1, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [no pattern match here] -codetoanalyze/erlang/nonmatch/src/match.erl, match_test_e_Bad/0, -15, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [calling context starts here,in call to `tail/1`,no pattern match here] -codetoanalyze/erlang/nonmatch/src/match.erl, match_test_g_Bad/0, 7, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [calling context starts here,in call to `only_accepts_one/1`,no pattern match here] -codetoanalyze/erlang/nonmatch/src/match.erl, only_accepts_one/1, 0, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [*** LATENT ***,no pattern match here] -codetoanalyze/erlang/nonmatch/src/match.erl, tail/1, 0, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [*** LATENT ***,no pattern match here] +codetoanalyze/erlang/nonmatch/src/match.erl, match_test_b_Bad/0, 1, NO_MATCH_OF_RHS, no_bucket, ERROR, [no match of RHS here] +codetoanalyze/erlang/nonmatch/src/match.erl, match_test_e_Bad/0, -15, NO_MATCHING_FUNCTION_CLAUSE, no_bucket, ERROR, [calling context starts here,in call to `tail/1`,no matching function clause here] +codetoanalyze/erlang/nonmatch/src/match.erl, match_test_g_Bad/0, 7, NO_MATCHING_FUNCTION_CLAUSE, no_bucket, ERROR, [calling context starts here,in call to `only_accepts_one/1`,no matching function clause here] +codetoanalyze/erlang/nonmatch/src/match.erl, only_accepts_one/1, 0, NO_MATCHING_FUNCTION_CLAUSE, no_bucket, ERROR, [*** LATENT ***,no matching function clause here] +codetoanalyze/erlang/nonmatch/src/match.erl, tail/1, 0, NO_MATCHING_FUNCTION_CLAUSE, no_bucket, ERROR, [*** LATENT ***,no matching function clause here] diff --git a/infer/tests/codetoanalyze/erlang/topl/issues.exp b/infer/tests/codetoanalyze/erlang/topl/issues.exp index a28383f58..c13365d56 100644 --- a/infer/tests/codetoanalyze/erlang/topl/issues.exp +++ b/infer/tests/codetoanalyze/erlang/topl/issues.exp @@ -1,7 +1,7 @@ -codetoanalyze/erlang/topl/src/topl_taint.erl, fp_test_f_Bad/0, 1, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [no pattern match here] -codetoanalyze/erlang/topl/src/topl_taint.erl, fp_test_g_Ok/0, 1, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [no pattern match here] +codetoanalyze/erlang/topl/src/topl_taint.erl, fp_test_f_Bad/0, 1, NO_MATCHING_CASE_CLAUSE, no_bucket, ERROR, [no matching case clause here] +codetoanalyze/erlang/topl/src/topl_taint.erl, fp_test_g_Ok/0, 1, NO_MATCHING_CASE_CLAUSE, no_bucket, ERROR, [no matching case clause here] codetoanalyze/erlang/topl/src/topl_taint.erl, test_a_Bad/0, 0, TOPL_ERROR, no_bucket, ERROR, [call to source/0,call to sink/1] codetoanalyze/erlang/topl/src/topl_taint.erl, test_c_Bad/0, 0, TOPL_ERROR, no_bucket, ERROR, [call to source/0,call to sink/1] codetoanalyze/erlang/topl/src/topl_taint.erl, test_d_Bad/0, 0, TOPL_ERROR, no_bucket, ERROR, [call to source/0,call to call_sink_indirectly/1,call to call_sink/1,call to sink/1] codetoanalyze/erlang/topl/src/topl_taint.erl, test_h_Bad/0, 0, TOPL_ERROR, no_bucket, ERROR, [call to dirty_if_argument_nil/1,call to source/0,call to sink/1] -codetoanalyze/erlang/topl/src/topl_taint.erl, test_j_Bad/0, 1, NONEXHAUSTIVE_PATTERN_MATCH, no_bucket, ERROR, [no pattern match here] +codetoanalyze/erlang/topl/src/topl_taint.erl, test_j_Bad/0, 1, NO_MATCHING_CASE_CLAUSE, no_bucket, ERROR, [no matching case clause here]