Index: clang-tidy/ClangTidyDiagnosticConsumer.cpp =================================================================== --- clang-tidy/ClangTidyDiagnosticConsumer.cpp +++ clang-tidy/ClangTidyDiagnosticConsumer.cpp @@ -19,6 +19,9 @@ #include "ClangTidyDiagnosticConsumer.h" #include "llvm/ADT/SmallString.h" +#include +#include + namespace clang { namespace tidy { @@ -116,11 +119,24 @@ } } +struct LessClangTidyError { + bool operator()(const ClangTidyError *LHS, const ClangTidyError *RHS) const { + const ClangTidyMessage &M1 = LHS->Message; + const ClangTidyMessage &M2 = RHS->Message; + + return std::tie(M1.FilePath, M1.FileOffset, M1.Message) < + std::tie(M2.FilePath, M2.FileOffset, M2.Message); + } +}; + // 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; +}