Index: clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp =================================================================== --- clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp +++ clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp @@ -757,9 +757,12 @@ std::vector ClangTidyDiagnosticConsumer::take() { finalizeLastError(); - std::sort(Errors.begin(), Errors.end(), LessClangTidyError()); - Errors.erase(std::unique(Errors.begin(), Errors.end(), EqualClangTidyError()), - Errors.end()); + if (!*Context.getOptions().DuplicateReports) { + std::sort(Errors.begin(), Errors.end(), LessClangTidyError()); + Errors.erase(std::unique(Errors.begin(), Errors.end(), + EqualClangTidyError()), Errors.end()); + } + if (RemoveIncompatibleErrors) removeIncompatibleErrors(); return std::move(Errors); Index: clang-tools-extra/clang-tidy/ClangTidyOptions.h =================================================================== --- clang-tools-extra/clang-tidy/ClangTidyOptions.h +++ clang-tools-extra/clang-tidy/ClangTidyOptions.h @@ -66,6 +66,10 @@ /// \brief WarningsAsErrors filter. llvm::Optional WarningsAsErrors; + /// \brief Indicates whether warnings emitted by alias checkers should be + /// reported multiple times. + llvm::Optional DuplicateReports; + /// \brief Output warnings from headers matching this filter. Warnings from /// main files will always be displayed. llvm::Optional HeaderFilterRegex; Index: clang-tools-extra/clang-tidy/ClangTidyOptions.cpp =================================================================== --- clang-tools-extra/clang-tidy/ClangTidyOptions.cpp +++ clang-tools-extra/clang-tidy/ClangTidyOptions.cpp @@ -105,6 +105,7 @@ ClangTidyOptions Options; Options.Checks = ""; Options.WarningsAsErrors = ""; + Options.DuplicateReports = false; Options.HeaderFilterRegex = ""; Options.SystemHeaders = false; Options.FormatStyle = "none"; @@ -145,6 +146,7 @@ mergeCommaSeparatedLists(Result.Checks, Other.Checks); mergeCommaSeparatedLists(Result.WarningsAsErrors, Other.WarningsAsErrors); overrideValue(Result.HeaderFilterRegex, Other.HeaderFilterRegex); + overrideValue(Result.DuplicateReports, Other.DuplicateReports); overrideValue(Result.SystemHeaders, Other.SystemHeaders); overrideValue(Result.FormatStyle, Other.FormatStyle); overrideValue(Result.User, Other.User); Index: clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp =================================================================== --- clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp +++ clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp @@ -78,6 +78,15 @@ cl::init(""), cl::cat(ClangTidyCategory)); +static cl::opt DuplicateReports("duplicate-reports", cl::desc(R"( +Some checkers are aliases of others, so the same +issue may be reported by different checkers at +the same location. These duplicates are uniqued +unless this flag is provided. +)"), + cl::init(false), + cl::cat(ClangTidyCategory)); + static cl::opt HeaderFilter("header-filter", cl::desc(R"( Regular expression matching the names of the headers to output diagnostics from. Diagnostics @@ -266,6 +275,7 @@ ClangTidyOptions DefaultOptions; DefaultOptions.Checks = DefaultChecks; DefaultOptions.WarningsAsErrors = ""; + DefaultOptions.DuplicateReports = DuplicateReports; DefaultOptions.HeaderFilterRegex = HeaderFilter; DefaultOptions.SystemHeaders = SystemHeaders; DefaultOptions.FormatStyle = FormatStyle; @@ -279,6 +289,8 @@ OverrideOptions.Checks = Checks; if (WarningsAsErrors.getNumOccurrences() > 0) OverrideOptions.WarningsAsErrors = WarningsAsErrors; + if (DuplicateReports.getNumOccurrences() > 0) + OverrideOptions.DuplicateReports = DuplicateReports; if (HeaderFilter.getNumOccurrences() > 0) OverrideOptions.HeaderFilterRegex = HeaderFilter; if (SystemHeaders.getNumOccurrences() > 0) Index: clang-tools-extra/test/clang-tidy/duplicate-reports-with.cpp =================================================================== --- /dev/null +++ clang-tools-extra/test/clang-tidy/duplicate-reports-with.cpp @@ -0,0 +1,19 @@ +// RUN: %check_clang_tidy %s cert-err09-cpp,cert-err61-cpp %t -duplicate-reports -- + +void alwaysThrows() { + int ex = 42; + // At this location both cert-err09-cpp and cert-err61-cpp report the + // message. The order of the reports is unknown, that's why the checker name + // is not included in the expected warning. + + // CHECK-MESSAGES: warning: throw expression should throw anonymous temporary values instead + // CHECK-MESSAGES: warning: throw expression should throw anonymous temporary values instead + throw ex; +} + +void doTheJob() { + try { + alwaysThrows(); + } catch (int&) { + } +} Index: clang-tools-extra/test/clang-tidy/duplicate-reports-without.cpp =================================================================== --- /dev/null +++ clang-tools-extra/test/clang-tidy/duplicate-reports-without.cpp @@ -0,0 +1,17 @@ +// RUN: %check_clang_tidy %s cert-err09-cpp,cert-err61-cpp %t + +void alwaysThrows() { + int ex = 42; + // It is unknown which checker alias is reporting the warning, that is why + // the checker name is not included in the message. + + // CHECK-MESSAGES: warning: throw expression should throw anonymous temporary values instead + throw ex; +} + +void doTheJob() { + try { + alwaysThrows(); + } catch (int&) { + } +}