diff --git a/infer/src/IR/Errlog.mli b/infer/src/IR/Errlog.mli index f77193c37..199786ddf 100644 --- a/infer/src/IR/Errlog.mli +++ b/infer/src/IR/Errlog.mli @@ -45,17 +45,15 @@ type err_key = private {severity: Exceptions.severity; err_name: IssueType.t; err_desc: Localise.error_desc} [@@deriving compare] -(* Merges two error keys, setting the result's severity to the maximum - of that of the two arguments and giving the user the opportunity - to pass a function to merge the IssueTypes and descriptions - of the two. *) - val merge_err_key : err_key -> err_key -> merge_issues:(IssueType.t -> IssueType.t -> IssueType.t) -> merge_descriptions:(string list -> string list -> string) -> err_key +(** Merges two error keys, setting the result's severity to the maximum of that of the two arguments + and giving the user the opportunity to pass a function to merge the IssueTypes and descriptions + of the two. *) (** Data associated to a specific error *) type err_data = private @@ -71,12 +69,12 @@ type err_data = private ; doc_url: string option (** url to documentation of the issue type *) ; access: string option ; extras: Jsonbug_t.extra option } - -(* Merges two err_datas, throwing out most information and setting the trace of the - result to the concatenation of the traces of the two arguments with a - separator in between. Used specifically for QuandaryBO. *) +[@@deriving compare] val merge_err_data : err_data -> err_data -> err_data +(** Merges two err_datas, throwing out most information and setting the trace of the result to the + concatenation of the traces of the two arguments with a separator in between. Used specifically + for QuandaryBO. *) (** Type of the error log *) type t diff --git a/infer/src/backend/Issue.ml b/infer/src/backend/Issue.ml index a8bd57181..943763647 100644 --- a/infer/src/backend/Issue.ml +++ b/infer/src/backend/Issue.ml @@ -8,6 +8,13 @@ open! IStd module L = Logging +type t = + { proc_name: Typ.Procname.t + ; proc_location: Location.t + ; err_key: Errlog.err_key + ; err_data: Errlog.err_data } +[@@deriving compare] + (** Wrapper of an issue that compares all parts except the procname *) type err_data_ = Errlog.err_data @@ -21,7 +28,7 @@ type proc_name_ = Typ.Procname.t (* ignore proc name *) let compare_proc_name_ _ _ = 0 -type t = +type t_ignore_duplicates = t = {proc_name: proc_name_; proc_location: Location.t; err_key: Errlog.err_key; err_data: err_data_} [@@deriving compare] @@ -30,7 +37,10 @@ type t = identical warning on the same line. Accomplish this by sorting without regard to procname, then de-duplicating. *) let sort_filter_issues issues = - let issues' = List.dedup_and_sort ~compare issues in + let issues' = + let compare = if Config.filtering then compare_t_ignore_duplicates else compare in + List.dedup_and_sort ~compare issues + in ( if Config.developer_mode then let num_pruned_issues = List.length issues - List.length issues' in if num_pruned_issues > 0 then diff --git a/infer/src/backend/Issue.mli b/infer/src/backend/Issue.mli index b4ce44a4a..ee1f7ddb3 100644 --- a/infer/src/backend/Issue.mli +++ b/infer/src/backend/Issue.mli @@ -7,11 +7,10 @@ open! IStd -type err_data_ = Errlog.err_data - -type proc_name_ = Typ.Procname.t - type t = - {proc_name: proc_name_; proc_location: Location.t; err_key: Errlog.err_key; err_data: err_data_} + { proc_name: Typ.Procname.t + ; proc_location: Location.t + ; err_key: Errlog.err_key + ; err_data: Errlog.err_data } val sort_filter_issues : t list -> t list diff --git a/infer/tests/codetoanalyze/cpp/errors/issues.exp b/infer/tests/codetoanalyze/cpp/errors/issues.exp index 9bd91a73b..c4b8ed0c1 100644 --- a/infer/tests/codetoanalyze/cpp/errors/issues.exp +++ b/infer/tests/codetoanalyze/cpp/errors/issues.exp @@ -1,4 +1,5 @@ INFER_MODEL/cpp/include/infer_model/unique_ptr.h, std::operator!=<65d659492edc5cb5>, 1, Abduction_case_not_implemented, no_bucket, ERROR, [start of procedure std::operator!=<65d659492edc5cb5>()] +INFER_MODEL/cpp/include/infer_model/unique_ptr.h, std::operator!=, 1, Abduction_case_not_implemented, no_bucket, ERROR, [start of procedure std::operator!=()] INFER_MODEL/cpp/include/infer_model/unique_ptr.h, std::unique_ptr>::__infer_inner_destructor_~unique_ptr, 0, Missing_fld, no_bucket, ERROR, [start of procedure __infer_inner_destructor_~unique_ptr,start of procedure Pointer,return from a call to unique_ptr_with_deleter::Pointer::Pointer,start of procedure Pointer,return from a call to unique_ptr_with_deleter::Pointer::Pointer] INFER_MODEL/cpp/include/infer_model/unique_ptr.h, std::unique_ptr>::__infer_inner_destructor_~unique_ptr, 0, Missing_fld, no_bucket, ERROR, [start of procedure __infer_inner_destructor_~unique_ptr,start of procedure Pointer,return from a call to unique_ptr_with_deleter::Pointer::Pointer,start of procedure Pointer,return from a call to unique_ptr_with_deleter::Pointer::Pointer] codetoanalyze/cpp/errors/biabduction/process_splitting_assert.cpp, fail, 2, NULL_DEREFERENCE, B5, ERROR, [start of procedure fail(),Taking true branch] @@ -11,7 +12,9 @@ codetoanalyze/cpp/errors/c_tests/c_bugs.cpp, resource_leak_is_reported, 0, RESOU codetoanalyze/cpp/errors/include_header/header.h, header::A::div0, 0, DIVIDE_BY_ZERO, no_bucket, ERROR, [start of procedure div0] codetoanalyze/cpp/errors/include_header/header.h, header::div0_fun, 0, DIVIDE_BY_ZERO, no_bucket, ERROR, [start of procedure header::div0_fun()] codetoanalyze/cpp/errors/include_header/header2.h, header2::B::div0, 0, DIVIDE_BY_ZERO, no_bucket, ERROR, [start of procedure div0] +codetoanalyze/cpp/errors/include_header/header2.h, header2::B::div0, 0, DIVIDE_BY_ZERO, no_bucket, ERROR, [start of procedure div0] codetoanalyze/cpp/errors/include_header/header2.h, header2::div0_templ, 1, DIVIDE_BY_ZERO, no_bucket, ERROR, [start of procedure header2::div0_templ()] +codetoanalyze/cpp/errors/include_header/header2.h, header2::div0_templ, 1, DIVIDE_BY_ZERO, no_bucket, ERROR, [start of procedure header2::div0_templ()] codetoanalyze/cpp/errors/memory_leaks/array_leak.cpp, leak, 6, MEMORY_LEAK, CPP, ERROR, [start of procedure leak(),return from a call to leak] codetoanalyze/cpp/errors/memory_leaks/object_leak.cpp, object_leak, 0, MEMORY_LEAK, CPP, ERROR, [start of procedure object_leak(),start of procedure Rectangle,return from a call to Rectangle::Rectangle,return from a call to object_leak] codetoanalyze/cpp/errors/memory_leaks/raii_malloc.cpp, memory_leak, 0, MEMORY_LEAK, no_bucket, ERROR, [start of procedure memory_leak(),return from a call to memory_leak] diff --git a/infer/tests/codetoanalyze/cpp/liveness/issues.exp b/infer/tests/codetoanalyze/cpp/liveness/issues.exp index 1b739d2da..cedf52c68 100644 --- a/infer/tests/codetoanalyze/cpp/liveness/issues.exp +++ b/infer/tests/codetoanalyze/cpp/liveness/issues.exp @@ -25,5 +25,6 @@ codetoanalyze/cpp/liveness/dead_stores.cpp, dead_stores::unused_tmp_bad, 0, DEAD codetoanalyze/cpp/liveness/dead_stores.cpp, dead_stores::use_then_dead_bad, 3, DEAD_STORE, no_bucket, ERROR, [Write of unused value] codetoanalyze/cpp/liveness/dead_stores_constexpr.cpp, capture_const_bad, 1, DEAD_STORE, no_bucket, ERROR, [Write of unused value] codetoanalyze/cpp/liveness/non_type_template_param.cpp, X<3>::isZeroBad, 1, DEAD_STORE, no_bucket, ERROR, [Write of unused value] +codetoanalyze/cpp/liveness/non_type_template_param.cpp, X<7>::isZeroBad, 1, DEAD_STORE, no_bucket, ERROR, [Write of unused value] codetoanalyze/cpp/liveness/non_type_template_param.cpp, instanciateTemplateBad, 3, DEAD_STORE, no_bucket, ERROR, [Write of unused value] codetoanalyze/cpp/liveness/non_type_template_param.cpp, instanciateTemplateConstOk_FP, 1, DEAD_STORE, no_bucket, ERROR, [Write of unused value] diff --git a/infer/tests/codetoanalyze/objcpp/errors/issues.exp b/infer/tests/codetoanalyze/objcpp/errors/issues.exp index b5017ae1f..5746babac 100644 --- a/infer/tests/codetoanalyze/objcpp/errors/issues.exp +++ b/infer/tests/codetoanalyze/objcpp/errors/issues.exp @@ -1,4 +1,5 @@ codetoanalyze/objcpp/errors/BlockLfield.mm, A::mOk, 1, PRECONDITION_NOT_FOUND, no_bucket, ERROR, [start of procedure mOk] codetoanalyze/objcpp/errors/BlockLfield.mm, CFunWithBlockOk, 2, PRECONDITION_NOT_MET, no_bucket, WARNING, [start of procedure CFunWithBlockOk()] +codetoanalyze/objcpp/errors/BlockLfield.mm, CFunWithBlockOk_objc_blockA::mOk_1, 2, PRECONDITION_NOT_MET, no_bucket, WARNING, [start of procedure CFunWithBlockOk()] codetoanalyze/objcpp/errors/c_functions.mm, main, 4, NULL_DEREFERENCE, B5, ERROR, [start of procedure main(),start of procedure autoUpdating,return from a call to A::autoUpdating,start of procedure autoUpdating2,Skipping dispatch_once2(): method has no implementation,return from a call to A::autoUpdating2,Executing synthesized getter block,start of procedure block,return from a call to objc_blockobjc_blockA::autoUpdating_1_2,Message block with receiver nil returns nil.] codetoanalyze/objcpp/errors/retain_cycles/RetainCycleWithStruct.mm, Animation::tracer, 2, RETAIN_CYCLE, no_bucket, ERROR, [start of procedure tracer,start of procedure _State,return from a call to _State::_State,start of procedure initWithAnimation:,Taking true branch,return from a call to Tracer::initWithAnimation:]