summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang-tools-extra/clang-tidy/ClangTidy.cpp9
-rw-r--r--clang-tools-extra/clang-tidy/ClangTidy.h8
-rw-r--r--clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp30
-rw-r--r--clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h13
-rw-r--r--clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp31
-rw-r--r--clang-tools-extra/test/clang-tidy/file-filter.cpp13
-rw-r--r--clang-tools-extra/test/clang-tidy/nolint.cpp3
-rw-r--r--clang-tools-extra/test/clang-tidy/redundant-smartptr-get.cpp2
8 files changed, 83 insertions, 26 deletions
diff --git a/clang-tools-extra/clang-tidy/ClangTidy.cpp b/clang-tools-extra/clang-tidy/ClangTidy.cpp
index 0445710eaa2..e44dab3faef 100644
--- a/clang-tools-extra/clang-tidy/ClangTidy.cpp
+++ b/clang-tools-extra/clang-tidy/ClangTidy.cpp
@@ -298,10 +298,10 @@ std::vector<std::string> getCheckNames(const ClangTidyOptions &Options) {
return Factory.getCheckNames();
}
-void runClangTidy(const ClangTidyOptions &Options,
- const tooling::CompilationDatabase &Compilations,
- ArrayRef<std::string> Ranges,
- SmallVectorImpl<ClangTidyError> *Errors) {
+ClangTidyStats runClangTidy(const ClangTidyOptions &Options,
+ const tooling::CompilationDatabase &Compilations,
+ ArrayRef<std::string> Ranges,
+ SmallVectorImpl<ClangTidyError> *Errors) {
// FIXME: Ranges are currently full files. Support selecting specific
// (line-)ranges.
ClangTool Tool(Compilations, Ranges);
@@ -333,6 +333,7 @@ void runClangTidy(const ClangTidyOptions &Options,
};
Tool.run(new ActionFactory(new ClangTidyASTConsumerFactory(Context, Options)));
+ return Context.getStats();
}
void handleErrors(SmallVectorImpl<ClangTidyError> &Errors, bool Fix) {
diff --git a/clang-tools-extra/clang-tidy/ClangTidy.h b/clang-tools-extra/clang-tidy/ClangTidy.h
index 8d71eeb37ad..1bc3e29592d 100644
--- a/clang-tools-extra/clang-tidy/ClangTidy.h
+++ b/clang-tools-extra/clang-tidy/ClangTidy.h
@@ -121,10 +121,10 @@ private:
std::vector<std::string> getCheckNames(const ClangTidyOptions &Options);
/// \brief Run a set of clang-tidy checks on a set of files.
-void runClangTidy(const ClangTidyOptions &Options,
- const tooling::CompilationDatabase &Compilations,
- ArrayRef<std::string> Ranges,
- SmallVectorImpl<ClangTidyError> *Errors);
+ClangTidyStats runClangTidy(const ClangTidyOptions &Options,
+ const tooling::CompilationDatabase &Compilations,
+ ArrayRef<std::string> Ranges,
+ SmallVectorImpl<ClangTidyError> *Errors);
// FIXME: This interface will need to be significantly extended to be useful.
// FIXME: Implement confidence levels for displaying/fixing errors.
diff --git a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
index fdf1f0c2e6c..ad30898e489 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
+++ b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
@@ -41,8 +41,6 @@ protected:
ArrayRef<CharSourceRange> Ranges,
const SourceManager *SM,
DiagOrStoredDiag Info) override {
- if (Level == DiagnosticsEngine::Ignored)
- return;
ClangTidyMessage TidyMessage = Loc.isValid()
? ClangTidyMessage(Message, *SM, Loc)
: ClangTidyMessage(Message);
@@ -111,8 +109,7 @@ ClangTidyMessage::ClangTidyMessage(StringRef Message,
FileOffset = Sources.getFileOffset(Loc);
}
-ClangTidyError::ClangTidyError(StringRef CheckName)
- : CheckName(CheckName) {}
+ClangTidyError::ClangTidyError(StringRef CheckName) : CheckName(CheckName) {}
ChecksFilter::ChecksFilter(const ClangTidyOptions &Options)
: EnableChecks(Options.EnableChecksRegex),
@@ -139,8 +136,10 @@ DiagnosticBuilder ClangTidyContext::diag(
++P;
StringRef RestOfLine(CharacterData, P - CharacterData + 1);
// FIXME: Handle /\bNOLINT\b(\([^)]*\))?/ as cpplint.py does.
- if (RestOfLine.find("NOLINT") != StringRef::npos)
+ if (RestOfLine.find("NOLINT") != StringRef::npos) {
Level = DiagnosticIDs::Ignored;
+ ++Stats.ErrorsIgnoredNOLINT;
+ }
}
unsigned ID = DiagEngine->getDiagnosticIDs()->getCustomDiagID(
Level, (Description + " [" + CheckName + "]").str());
@@ -181,8 +180,18 @@ ClangTidyDiagnosticConsumer::ClangTidyDiagnosticConsumer(ClangTidyContext &Ctx)
}
void ClangTidyDiagnosticConsumer::finalizeLastError() {
- if (!LastErrorRelatesToUserCode && !Errors.empty())
- Errors.pop_back();
+ if (!Errors.empty()) {
+ ClangTidyError &Error = Errors.back();
+ if (!Context.getChecksFilter().isCheckEnabled(Error.CheckName)) {
+ ++Context.Stats.ErrorsIgnoredCheckFilter;
+ Errors.pop_back();
+ } else if (!LastErrorRelatesToUserCode) {
+ ++Context.Stats.ErrorsIgnoredNonUserCode;
+ Errors.pop_back();
+ } else {
+ ++Context.Stats.ErrorsDisplayed;
+ }
+ }
LastErrorRelatesToUserCode = false;
}
@@ -259,10 +268,9 @@ struct LessClangTidyError {
void ClangTidyDiagnosticConsumer::finish() {
finalizeLastError();
std::set<const ClangTidyError*, LessClangTidyError> UniqueErrors;
- for (const ClangTidyError &Error : Errors) {
- if (Context.getChecksFilter().isCheckEnabled(Error.CheckName))
- UniqueErrors.insert(&Error);
- }
+ for (const ClangTidyError &Error : Errors)
+ UniqueErrors.insert(&Error);
+
for (const ClangTidyError *Error : UniqueErrors)
Context.storeError(*Error);
Errors.clear();
diff --git a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
index d944836c1b1..c030a67013a 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
+++ b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
@@ -68,6 +68,17 @@ private:
llvm::Regex DisableChecks;
};
+struct ClangTidyStats {
+ ClangTidyStats()
+ : ErrorsDisplayed(0), ErrorsIgnoredCheckFilter(0), ErrorsIgnoredNOLINT(0),
+ ErrorsIgnoredNonUserCode(0) {}
+
+ unsigned ErrorsDisplayed;
+ unsigned ErrorsIgnoredCheckFilter;
+ unsigned ErrorsIgnoredNOLINT;
+ unsigned ErrorsIgnoredNonUserCode;
+};
+
/// \brief Every \c ClangTidyCheck reports errors through a \c DiagnosticEngine
/// provided by this context.
///
@@ -108,6 +119,7 @@ public:
ChecksFilter &getChecksFilter() { return Filter; }
const ClangTidyOptions &getOptions() const { return Options; }
+ const ClangTidyStats &getStats() const { return Stats; }
private:
friend class ClangTidyDiagnosticConsumer; // Calls storeError().
@@ -119,6 +131,7 @@ private:
DiagnosticsEngine *DiagEngine;
ClangTidyOptions Options;
ChecksFilter Filter;
+ ClangTidyStats Stats;
llvm::DenseMap<unsigned, std::string> CheckNamesByDiagnosticID;
};
diff --git a/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp b/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
index 17d1c786079..624e6c05f9b 100644
--- a/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
+++ b/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
@@ -59,6 +59,31 @@ static cl::opt<bool> AnalyzeTemporaryDtors(
cl::init(false),
cl::cat(ClangTidyCategory));
+static void printStats(const clang::tidy::ClangTidyStats &Stats) {
+ unsigned ErrorsIgnored = Stats.ErrorsIgnoredNOLINT +
+ Stats.ErrorsIgnoredCheckFilter +
+ Stats.ErrorsIgnoredNonUserCode;
+ if (ErrorsIgnored) {
+ llvm::errs() << "Suppressed " << ErrorsIgnored << " warnings (";
+ StringRef Separator = "";
+ if (Stats.ErrorsIgnoredNonUserCode) {
+ llvm::errs() << Stats.ErrorsIgnoredNonUserCode << " in non-user code";
+ Separator = ", ";
+ }
+ if (Stats.ErrorsIgnoredNOLINT) {
+ llvm::errs() << Separator << Stats.ErrorsIgnoredNOLINT << " NOLINT";
+ Separator = ", ";
+ }
+ if (Stats.ErrorsIgnoredCheckFilter)
+ llvm::errs() << Separator << Stats.ErrorsIgnoredCheckFilter
+ << " with check filters";
+ llvm::errs() << ").\n";
+ if (Stats.ErrorsIgnoredNonUserCode)
+ llvm::errs() << "Use -header-filter='.*' to display errors from all "
+ "non-system headers.\n";
+ }
+}
+
int main(int argc, const char **argv) {
CommonOptionsParser OptionsParser(argc, argv, ClangTidyCategory);
@@ -78,10 +103,12 @@ int main(int argc, const char **argv) {
}
SmallVector<clang::tidy::ClangTidyError, 16> Errors;
- clang::tidy::runClangTidy(Options, OptionsParser.getCompilations(),
- OptionsParser.getSourcePathList(), &Errors);
+ clang::tidy::ClangTidyStats Stats =
+ clang::tidy::runClangTidy(Options, OptionsParser.getCompilations(),
+ OptionsParser.getSourcePathList(), &Errors);
clang::tidy::handleErrors(Errors, Fix);
+ printStats(Stats);
return 0;
}
diff --git a/clang-tools-extra/test/clang-tidy/file-filter.cpp b/clang-tools-extra/test/clang-tidy/file-filter.cpp
index f9e029b2692..fa740f34d35 100644
--- a/clang-tools-extra/test/clang-tidy/file-filter.cpp
+++ b/clang-tools-extra/test/clang-tidy/file-filter.cpp
@@ -1,6 +1,6 @@
-// RUN: clang-tidy -checks=google-explicit-constructor -disable-checks='' -header-filter='' %s -- -I %S/Inputs/file-filter | FileCheck %s
-// RUN: clang-tidy -checks=google-explicit-constructor -disable-checks='' -header-filter='.*' %s -- -I %S/Inputs/file-filter | FileCheck --check-prefix=CHECK2 %s
-// RUN: clang-tidy -checks=google-explicit-constructor -disable-checks='' -header-filter='header2\.h' %s -- -I %S/Inputs/file-filter | FileCheck --check-prefix=CHECK3 %s
+// RUN: clang-tidy -checks=google-explicit-constructor -disable-checks='' -header-filter='' %s -- -I %S/Inputs/file-filter 2>&1 | FileCheck %s
+// RUN: clang-tidy -checks=google-explicit-constructor -disable-checks='' -header-filter='.*' %s -- -I %S/Inputs/file-filter 2>&1 | FileCheck --check-prefix=CHECK2 %s
+// RUN: clang-tidy -checks=google-explicit-constructor -disable-checks='' -header-filter='header2\.h' %s -- -I %S/Inputs/file-filter 2>&1 | FileCheck --check-prefix=CHECK3 %s
#include "header1.h"
// CHECK-NOT: warning:
@@ -20,3 +20,10 @@ class A { A(int); };
// CHECK-NOT: warning:
// CHECK2-NOT: warning:
// CHECK3-NOT: warning:
+
+// CHECK: Suppressed 2 warnings (2 in non-user code)
+// CHECK: Use -header-filter='.*' to display errors from all non-system headers.
+// CHECK2-NOT: Suppressed {{.*}} warnings
+// CHECK2-NOT: Use -header-filter='.*' {{.*}}
+// CHECK3: Suppressed 1 warnings (1 in non-user code)
+// CHECK3: Use -header-filter='.*' {{.*}}
diff --git a/clang-tools-extra/test/clang-tidy/nolint.cpp b/clang-tools-extra/test/clang-tidy/nolint.cpp
index f192930c2b7..d4a5c4cd623 100644
--- a/clang-tools-extra/test/clang-tidy/nolint.cpp
+++ b/clang-tools-extra/test/clang-tidy/nolint.cpp
@@ -1,4 +1,4 @@
-// RUN: clang-tidy -checks=google-explicit-constructor -disable-checks='' %s -- | FileCheck %s
+// RUN: clang-tidy -checks=google-explicit-constructor -disable-checks='' %s -- 2>&1 | FileCheck %s
class A { A(int i); };
// CHECK: :[[@LINE-1]]:11: warning: Single-argument constructors must be explicit [google-explicit-constructor]
@@ -8,3 +8,4 @@ class B { B(int i); }; // NOLINT
class C { C(int i); }; // NOLINT(we-dont-care-about-categories-yet)
// CHECK-NOT: :[[@LINE-1]]:11: warning: Single-argument constructors must be explicit [google-explicit-constructor]
+// CHECK: Suppressed 2 warnings (2 NOLINT)
diff --git a/clang-tools-extra/test/clang-tidy/redundant-smartptr-get.cpp b/clang-tools-extra/test/clang-tidy/redundant-smartptr-get.cpp
index 091e9d4dc68..22decca04af 100644
--- a/clang-tools-extra/test/clang-tidy/redundant-smartptr-get.cpp
+++ b/clang-tools-extra/test/clang-tidy/redundant-smartptr-get.cpp
@@ -78,7 +78,7 @@ void Positive() {
// CHECK: nullptr != sp->get();
}
-// CHECK-NOT: warning
+// CHECK-NOT: warning:
void Negative() {
struct NegPtr {
OpenPOWER on IntegriCloud