[clang-tools-extra] r204321 - Post-filter clang-tidy diagnostic messages.

Alexander Kornienko alexfh at google.com
Thu Mar 20 02:38:22 PDT 2014


Author: alexfh
Date: Thu Mar 20 04:38:22 2014
New Revision: 204321

URL: http://llvm.org/viewvc/llvm-project?rev=204321&view=rev
Log:
Post-filter clang-tidy diagnostic messages.

Summary:
This patch implements filtering of clang-tidy diagnostic messages by
the check name, so that "clang-tidy -checks=^llvm-" won't output any clang
warnings, for example. This is also helpful to run specific static-analyzer
checks: static analyzer always needs core checks to be enabled, but the user may
be interested only in the checks he asked for.

This patch also exposes warning option names for built-in diagnostics. We need
to have a namespace for these names to avoid collisions and to allow convenient
filtering, so I prefix them with "-W". I'm not sure it's the best thing to do,
and maybe "W" or "clang-diagnostic-" or something like this would be better.

Reviewers: klimek

Reviewed By: klimek

CC: cfe-commits

Differential Revision: http://llvm-reviews.chandlerc.com/D3121

Modified:
    clang-tools-extra/trunk/clang-tidy/ClangTidy.cpp
    clang-tools-extra/trunk/clang-tidy/ClangTidy.h
    clang-tools-extra/trunk/clang-tidy/ClangTidyDiagnosticConsumer.cpp
    clang-tools-extra/trunk/clang-tidy/ClangTidyDiagnosticConsumer.h
    clang-tools-extra/trunk/clang-tidy/ClangTidyModule.cpp
    clang-tools-extra/trunk/test/clang-tidy/diagnostic.cpp
    clang-tools-extra/trunk/unittests/clang-tidy/ClangTidyTest.h

Modified: clang-tools-extra/trunk/clang-tidy/ClangTidy.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/ClangTidy.cpp?rev=204321&r1=204320&r2=204321&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/ClangTidy.cpp (original)
+++ clang-tools-extra/trunk/clang-tidy/ClangTidy.cpp Thu Mar 20 04:38:22 2014
@@ -93,10 +93,8 @@ private:
 } // namespace
 
 ClangTidyASTConsumerFactory::ClangTidyASTConsumerFactory(
-    StringRef EnableChecksRegex, StringRef DisableChecksRegex,
     ClangTidyContext &Context)
-    : Filter(EnableChecksRegex, DisableChecksRegex), Context(Context),
-      CheckFactories(new ClangTidyCheckFactories) {
+    : Context(Context), CheckFactories(new ClangTidyCheckFactories) {
   for (ClangTidyModuleRegistry::iterator I = ClangTidyModuleRegistry::begin(),
                                          E = ClangTidyModuleRegistry::end();
        I != E; ++I) {
@@ -104,7 +102,7 @@ ClangTidyASTConsumerFactory::ClangTidyAS
     Module->addCheckFactories(*CheckFactories);
   }
 
-  CheckFactories->createChecks(Filter, Checks);
+  CheckFactories->createChecks(Context.getChecksFilter(), Checks);
 
   for (ClangTidyCheck *Check : Checks) {
     Check->setContext(&Context);
@@ -149,7 +147,7 @@ clang::ASTConsumer *ClangTidyASTConsumer
 std::vector<std::string> ClangTidyASTConsumerFactory::getCheckNames() {
   std::vector<std::string> CheckNames;
   for (const auto &CheckFactory : *CheckFactories) {
-    if (Filter.IsCheckEnabled(CheckFactory.first))
+    if (Context.getChecksFilter().isCheckEnabled(CheckFactory.first))
       CheckNames.push_back(CheckFactory.first);
   }
 
@@ -168,7 +166,8 @@ ClangTidyASTConsumerFactory::getCheckers
   for (StringRef CheckName : StaticAnalyzerChecks) {
     std::string Checker((AnalyzerCheckNamePrefix + CheckName).str());
     AnalyzerChecksEnabled |=
-        Filter.IsCheckEnabled(Checker) && !CheckName.startswith("debug");
+        Context.getChecksFilter().isCheckEnabled(Checker) &&
+        !CheckName.startswith("debug");
   }
 
   if (AnalyzerChecksEnabled) {
@@ -183,21 +182,14 @@ ClangTidyASTConsumerFactory::getCheckers
       std::string Checker((AnalyzerCheckNamePrefix + CheckName).str());
 
       if (CheckName.startswith("core") ||
-          (!CheckName.startswith("debug") && Filter.IsCheckEnabled(Checker)))
+          (!CheckName.startswith("debug") &&
+           Context.getChecksFilter().isCheckEnabled(Checker)))
         List.push_back(std::make_pair(CheckName, true));
     }
   }
   return List;
 }
 
-ChecksFilter::ChecksFilter(StringRef EnableChecksRegex,
-                           StringRef DisableChecksRegex)
-    : EnableChecks(EnableChecksRegex), DisableChecks(DisableChecksRegex) {}
-
-bool ChecksFilter::IsCheckEnabled(StringRef Name) {
-  return EnableChecks.match(Name) && !DisableChecks.match(Name);
-}
-
 DiagnosticBuilder ClangTidyCheck::diag(SourceLocation Loc, StringRef Message,
                                        DiagnosticIDs::Level Level) {
   return Context->diag(CheckName, Loc, Message, Level);
@@ -216,9 +208,9 @@ void ClangTidyCheck::setName(StringRef N
 std::vector<std::string> getCheckNames(StringRef EnableChecksRegex,
                                        StringRef DisableChecksRegex) {
   SmallVector<ClangTidyError, 8> Errors;
-  clang::tidy::ClangTidyContext Context(&Errors);
-  ClangTidyASTConsumerFactory Factory(EnableChecksRegex, DisableChecksRegex,
-                                      Context);
+  clang::tidy::ClangTidyContext Context(&Errors, EnableChecksRegex,
+                                        DisableChecksRegex);
+  ClangTidyASTConsumerFactory Factory(Context);
   return Factory.getCheckNames();
 }
 
@@ -229,7 +221,8 @@ void runClangTidy(StringRef EnableChecks
   // FIXME: Ranges are currently full files. Support selecting specific
   // (line-)ranges.
   ClangTool Tool(Compilations, Ranges);
-  clang::tidy::ClangTidyContext Context(Errors);
+  clang::tidy::ClangTidyContext Context(Errors, EnableChecksRegex,
+                                        DisableChecksRegex);
   ClangTidyDiagnosticConsumer DiagConsumer(Context);
 
   Tool.setDiagnosticConsumer(&DiagConsumer);
@@ -256,8 +249,7 @@ void runClangTidy(StringRef EnableChecks
     ClangTidyASTConsumerFactory *ConsumerFactory;
   };
 
-  Tool.run(new ActionFactory(new ClangTidyASTConsumerFactory(
-      EnableChecksRegex, DisableChecksRegex, Context)));
+  Tool.run(new ActionFactory(new ClangTidyASTConsumerFactory(Context)));
 }
 
 static SourceLocation getLocation(SourceManager &SourceMgr, StringRef FilePath,

Modified: clang-tools-extra/trunk/clang-tidy/ClangTidy.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/ClangTidy.h?rev=204321&r1=204320&r2=204321&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/ClangTidy.h (original)
+++ clang-tools-extra/trunk/clang-tidy/ClangTidy.h Thu Mar 20 04:38:22 2014
@@ -89,24 +89,11 @@ private:
   std::string CheckName;
 };
 
-/// \brief Filters checks by name.
-class ChecksFilter {
-public:
-  ChecksFilter(StringRef EnableChecksRegex, StringRef DisableChecksRegex);
-  bool IsCheckEnabled(StringRef Name);
-
-private:
-  llvm::Regex EnableChecks;
-  llvm::Regex DisableChecks;
-};
-
 class ClangTidyCheckFactories;
 
 class ClangTidyASTConsumerFactory {
 public:
-  ClangTidyASTConsumerFactory(StringRef EnableChecksRegex,
-                              StringRef DisableChecksRegex,
-                              ClangTidyContext &Context);
+  ClangTidyASTConsumerFactory(ClangTidyContext &Context);
   ~ClangTidyASTConsumerFactory();
 
   /// \brief Returns an ASTConsumer that runs the specified clang-tidy checks.
@@ -120,7 +107,6 @@ private:
   typedef std::vector<std::pair<std::string, bool> > CheckersList;
   CheckersList getCheckersControlList();
 
-  ChecksFilter Filter;
   SmallVector<ClangTidyCheck *, 8> Checks;
   ClangTidyContext &Context;
   ast_matchers::MatchFinder Finder;

Modified: clang-tools-extra/trunk/clang-tidy/ClangTidyDiagnosticConsumer.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/ClangTidyDiagnosticConsumer.cpp?rev=204321&r1=204320&r2=204321&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/ClangTidyDiagnosticConsumer.cpp (original)
+++ clang-tools-extra/trunk/clang-tidy/ClangTidyDiagnosticConsumer.cpp Thu Mar 20 04:38:22 2014
@@ -113,6 +113,19 @@ ClangTidyMessage::ClangTidyMessage(Strin
 ClangTidyError::ClangTidyError(StringRef CheckName)
     : CheckName(CheckName) {}
 
+ChecksFilter::ChecksFilter(StringRef EnableChecksRegex,
+                           StringRef DisableChecksRegex)
+    : EnableChecks(EnableChecksRegex), DisableChecks(DisableChecksRegex) {}
+
+bool ChecksFilter::isCheckEnabled(StringRef Name) {
+  return EnableChecks.match(Name) && !DisableChecks.match(Name);
+}
+
+ClangTidyContext::ClangTidyContext(SmallVectorImpl<ClangTidyError> *Errors,
+                                   StringRef EnableChecksRegex,
+                                   StringRef DisableChecksRegex)
+    : Errors(Errors), Filter(EnableChecksRegex, DisableChecksRegex) {}
+
 DiagnosticBuilder ClangTidyContext::diag(
     StringRef CheckName, SourceLocation Loc, StringRef Description,
     DiagnosticIDs::Level Level /* = DiagnosticIDs::Warning*/) {
@@ -179,7 +192,14 @@ void ClangTidyDiagnosticConsumer::Handle
            "A diagnostic note can only be appended to a message.");
   } else {
     finalizeLastError();
-    Errors.push_back(ClangTidyError(Context.getCheckName(Info.getID())));
+    StringRef WarningOption =
+        Context.DiagEngine->getDiagnosticIDs()->getWarningOptionForDiag(
+            Info.getID());
+    std::string CheckName = !WarningOption.empty()
+                                ? ("clang-diagnostic-" + WarningOption).str()
+                                : Context.getCheckName(Info.getID()).str();
+
+    Errors.push_back(ClangTidyError(CheckName));
   }
 
   // FIXME: Provide correct LangOptions for each file.
@@ -218,7 +238,8 @@ void ClangTidyDiagnosticConsumer::finish
   finalizeLastError();
   std::set<const ClangTidyError*, LessClangTidyError> UniqueErrors;
   for (const ClangTidyError &Error : Errors) {
-    if (UniqueErrors.insert(&Error).second)
+    if (Context.getChecksFilter().isCheckEnabled(Error.CheckName) &&
+        UniqueErrors.insert(&Error).second)
       Context.storeError(Error);
   }
   Errors.clear();

Modified: clang-tools-extra/trunk/clang-tidy/ClangTidyDiagnosticConsumer.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/ClangTidyDiagnosticConsumer.h?rev=204321&r1=204320&r2=204321&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/ClangTidyDiagnosticConsumer.h (original)
+++ clang-tools-extra/trunk/clang-tidy/ClangTidyDiagnosticConsumer.h Thu Mar 20 04:38:22 2014
@@ -14,6 +14,7 @@
 #include "clang/Basic/SourceManager.h"
 #include "clang/Tooling/Refactoring.h"
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/Support/Regex.h"
 
 namespace clang {
 
@@ -55,6 +56,17 @@ struct ClangTidyError {
   SmallVector<ClangTidyMessage, 1> Notes;
 };
 
+/// \brief Filters checks by name.
+class ChecksFilter {
+public:
+  ChecksFilter(StringRef EnableChecksRegex, StringRef DisableChecksRegex);
+  bool isCheckEnabled(StringRef Name);
+
+private:
+  llvm::Regex EnableChecks;
+  llvm::Regex DisableChecks;
+};
+
 /// \brief Every \c ClangTidyCheck reports errors through a \c DiagnosticEngine
 /// provided by this context.
 ///
@@ -66,8 +78,8 @@ struct ClangTidyError {
 /// \endcode
 class ClangTidyContext {
 public:
-  ClangTidyContext(SmallVectorImpl<ClangTidyError> *Errors)
-      : Errors(Errors), DiagEngine(0) {}
+  ClangTidyContext(SmallVectorImpl<ClangTidyError> *Errors,
+                   StringRef EnableChecksRegex, StringRef DisableChecksRegex);
 
   /// \brief Report any errors detected using this method.
   ///
@@ -93,6 +105,8 @@ public:
   /// diagnostic ID.
   StringRef getCheckName(unsigned DiagnosticID) const;
 
+  ChecksFilter &getChecksFilter() { return Filter; }
+
 private:
   friend class ClangTidyDiagnosticConsumer; // Calls storeError().
 
@@ -100,7 +114,9 @@ private:
   void storeError(const ClangTidyError &Error);
 
   SmallVectorImpl<ClangTidyError> *Errors;
-  DiagnosticsEngine *DiagEngine;
+  DiagnosticsEngine *DiagEngine{nullptr};
+  ChecksFilter Filter;
+
   llvm::DenseMap<unsigned, std::string> CheckNamesByDiagnosticID;
 };
 

Modified: clang-tools-extra/trunk/clang-tidy/ClangTidyModule.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/ClangTidyModule.cpp?rev=204321&r1=204320&r2=204321&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/ClangTidyModule.cpp (original)
+++ clang-tools-extra/trunk/clang-tidy/ClangTidyModule.cpp Thu Mar 20 04:38:22 2014
@@ -29,7 +29,7 @@ void ClangTidyCheckFactories::addCheckFa
 void ClangTidyCheckFactories::createChecks(
     ChecksFilter &Filter, SmallVectorImpl<ClangTidyCheck *> &Checks) {
   for (const auto &Factory : Factories) {
-    if (Filter.IsCheckEnabled(Factory.first)) {
+    if (Filter.isCheckEnabled(Factory.first)) {
       ClangTidyCheck *Check = Factory.second->createCheck();
       Check->setName(Factory.first);
       Checks.push_back(Check);

Modified: clang-tools-extra/trunk/test/clang-tidy/diagnostic.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/diagnostic.cpp?rev=204321&r1=204320&r2=204321&view=diff
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/diagnostic.cpp (original)
+++ clang-tools-extra/trunk/test/clang-tidy/diagnostic.cpp Thu Mar 20 04:38:22 2014
@@ -1,5 +1,21 @@
-// RUN: clang-tidy %s -- -fan-unknown-option | FileCheck -check-prefix=CHECK1 %s
-// RUN: clang-tidy %s.nonexistent.cpp -- | FileCheck -check-prefix=CHECK2 %s
+// RUN: clang-tidy %s.nonexistent.cpp -- | FileCheck -check-prefix=CHECK1 %s
+// RUN: clang-tidy %s -- -fan-unknown-option | FileCheck -check-prefix=CHECK2 %s
+// RUN: clang-tidy -checks='^(google-|clang-diagnostic-literal-conversion)' %s -- -fan-unknown-option | FileCheck -check-prefix=CHECK3 %s
 
-// CHECK1: warning: unknown argument: '-fan-unknown-option'
-// CHECK2: warning: error reading '{{.*}}.nonexistent.cpp'
+// CHECK1-NOT: warning
+// CHECK2-NOT: warning
+// CHECK3-NOT: warning
+
+// CHECK1: warning: error reading '{{.*}}.nonexistent.cpp'
+// CHECK2: warning: unknown argument: '-fan-unknown-option'
+
+// CHECK2: :[[@LINE+2]]:9: warning: implicit conversion from 'double' to 'int' changes value
+// CHECK3: :[[@LINE+1]]:9: warning: implicit conversion from 'double' to 'int' changes value
+int a = 1.5;
+
+// CHECK2: :[[@LINE+2]]:11: warning: Single-argument constructors must be explicit [google-explicit-constructor]
+// CHECK3: :[[@LINE+1]]:11: warning: Single-argument constructors must be explicit [google-explicit-constructor]
+class A { A(int) {} };
+
+// CHECK2-NOT: warning:
+// CHECK3-NOT: warning:

Modified: clang-tools-extra/trunk/unittests/clang-tidy/ClangTidyTest.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clang-tidy/ClangTidyTest.h?rev=204321&r1=204320&r2=204321&view=diff
==============================================================================
--- clang-tools-extra/trunk/unittests/clang-tidy/ClangTidyTest.h (original)
+++ clang-tools-extra/trunk/unittests/clang-tidy/ClangTidyTest.h Thu Mar 20 04:38:22 2014
@@ -42,7 +42,7 @@ private:
 template <typename T> std::string runCheckOnCode(StringRef Code) {
   T Check;
   SmallVector<ClangTidyError, 16> Errors;
-  ClangTidyContext Context(&Errors);
+  ClangTidyContext Context(&Errors, ".*", "");
   ClangTidyDiagnosticConsumer DiagConsumer(Context);
   Check.setContext(&Context);
 





More information about the cfe-commits mailing list