Index: clang-tidy/ClangTidyDiagnosticConsumer.cpp =================================================================== --- clang-tidy/ClangTidyDiagnosticConsumer.cpp +++ clang-tidy/ClangTidyDiagnosticConsumer.cpp @@ -19,6 +19,8 @@ #include "ClangTidyDiagnosticConsumer.h" #include "llvm/ADT/SmallString.h" +#include + namespace clang { namespace tidy { @@ -116,11 +118,31 @@ } } +struct LessClangTidyError { + bool operator()(const ClangTidyError *LHS, const ClangTidyError *RHS) const { + const ClangTidyMessage &M1 = LHS->Message; + const ClangTidyMessage &M2 = RHS->Message; + + if (M1.FileOffset != M2.FileOffset) + return M1.FileOffset < M2.FileOffset; + int Result = M1.FilePath.compare(M2.FilePath); + if (Result != 0) + return Result < 0; + Result = M1.Message.compare(M2.Message); + if (Result != 0) + return Result < 0; + return false; + } +}; + // Flushes the internal diagnostics buffer to the ClangTidyContext. void ClangTidyDiagnosticConsumer::finish() { finalizeLastError(); - for (const ClangTidyError &Error : Errors) - Context.storeError(Error); + std::set UniqueErrors; + for (const ClangTidyError &Error : Errors) { + if (UniqueErrors.insert(&Error).second) + Context.storeError(Error); + } Errors.clear(); } Index: test/clang-tidy/deduplication.cpp =================================================================== --- /dev/null +++ test/clang-tidy/deduplication.cpp @@ -0,0 +1,12 @@ +// RUN: clang-tidy -checks=google-explicit-constructor %s -- | FileCheck %s + +template +class A { A(T); }; +// CHECK: :[[@LINE-1]]:11: warning: Single-argument constructors must be explicit [google-explicit-constructor] +// CHECK-NOT: warning: + + +void f() { + A a; + A b; +}