Hi djasper,

Add clang-tidy -header-filter option to specify from which headers we
want diagnostics to be printed. By default we don't print diagnostics from
headers. We always print diagnostics from the main file of each translation
unit.

http://reviews.llvm.org/D3590

Files:
  clang-tidy/ClangTidyDiagnosticConsumer.cpp
  clang-tidy/ClangTidyDiagnosticConsumer.h
  clang-tidy/ClangTidyOptions.h
  clang-tidy/tool/ClangTidyMain.cpp
  test/clang-tidy/Inputs/
  test/clang-tidy/Inputs/file-filter/
  test/clang-tidy/Inputs/file-filter/header1.h
  test/clang-tidy/Inputs/file-filter/header2.h
  test/clang-tidy/file-filter.cpp
Index: clang-tidy/ClangTidyDiagnosticConsumer.cpp
===================================================================
--- clang-tidy/ClangTidyDiagnosticConsumer.cpp
+++ clang-tidy/ClangTidyDiagnosticConsumer.cpp
@@ -124,7 +124,7 @@
 
 ClangTidyContext::ClangTidyContext(SmallVectorImpl<ClangTidyError> *Errors,
                                    const ClangTidyOptions &Options)
-    : Errors(Errors), DiagEngine(nullptr), Filter(Options) {}
+    : Errors(Errors), DiagEngine(nullptr), Options(Options), Filter(Options) {}
 
 DiagnosticBuilder ClangTidyContext::diag(
     StringRef CheckName, SourceLocation Loc, StringRef Description,
@@ -171,7 +171,8 @@
 }
 
 ClangTidyDiagnosticConsumer::ClangTidyDiagnosticConsumer(ClangTidyContext &Ctx)
-    : Context(Ctx), LastErrorRelatesToUserCode(false) {
+    : Context(Ctx), HeaderFilter(Ctx.getOptions().HeaderFilterRegex),
+      LastErrorRelatesToUserCode(false) {
   IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
   Diags.reset(new DiagnosticsEngine(
       IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs), &*DiagOpts, this,
@@ -217,12 +218,27 @@
       Sources);
 
   // Let argument parsing-related warnings through.
-  if (!Info.getLocation().isValid() ||
-      !Diags->getSourceManager().isInSystemHeader(Info.getLocation())) {
+  if (relatesToUserCode(Info.getLocation())) {
     LastErrorRelatesToUserCode = true;
   }
 }
 
+bool ClangTidyDiagnosticConsumer::relatesToUserCode(SourceLocation Location) {
+  // Invalid location may mean a diagnostic in a command line, don't skip these.
+  if (!Location.isValid())
+    return true;
+
+  const SourceManager &Sources = Diags->getSourceManager();
+  if (Sources.isInSystemHeader(Location))
+    return false;
+
+  FileID FID = Sources.getDecomposedExpansionLoc(Location).first;
+  if (FID == Sources.getMainFileID())
+    return true;
+
+  return HeaderFilter.match(Sources.getFileEntryForID(FID)->getName());
+}
+
 struct LessClangTidyError {
   bool operator()(const ClangTidyError *LHS, const ClangTidyError *RHS) const {
     const ClangTidyMessage &M1 = LHS->Message;
Index: clang-tidy/ClangTidyDiagnosticConsumer.h
===================================================================
--- clang-tidy/ClangTidyDiagnosticConsumer.h
+++ clang-tidy/ClangTidyDiagnosticConsumer.h
@@ -10,6 +10,7 @@
 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANG_TIDY_DIAGNOSTIC_CONSUMER_H
 #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANG_TIDY_DIAGNOSTIC_CONSUMER_H
 
+#include "ClangTidyOptions.h"
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Tooling/Refactoring.h"
@@ -28,8 +29,6 @@
 
 namespace tidy {
 
-struct ClangTidyOptions;
-
 /// \brief A message from a clang-tidy check.
 ///
 /// Note that this is independent of a \c SourceManager.
@@ -108,6 +107,7 @@
   StringRef getCheckName(unsigned DiagnosticID) const;
 
   ChecksFilter &getChecksFilter() { return Filter; }
+  const ClangTidyOptions &getOptions() const { return Options; }
 
 private:
   friend class ClangTidyDiagnosticConsumer; // Calls storeError().
@@ -117,6 +117,7 @@
 
   SmallVectorImpl<ClangTidyError> *Errors;
   DiagnosticsEngine *DiagEngine;
+  ClangTidyOptions Options;
   ChecksFilter Filter;
 
   llvm::DenseMap<unsigned, std::string> CheckNamesByDiagnosticID;
@@ -142,8 +143,10 @@
 
 private:
   void finalizeLastError();
+  bool relatesToUserCode(SourceLocation Location);
 
   ClangTidyContext &Context;
+  llvm::Regex HeaderFilter;
   std::unique_ptr<DiagnosticsEngine> Diags;
   SmallVector<ClangTidyError, 8> Errors;
   bool LastErrorRelatesToUserCode;
Index: clang-tidy/ClangTidyOptions.h
===================================================================
--- clang-tidy/ClangTidyOptions.h
+++ clang-tidy/ClangTidyOptions.h
@@ -10,14 +10,19 @@
 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANG_TIDY_OPTIONS_H
 #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANG_TIDY_OPTIONS_H
 
+#include <string>
+
 namespace clang {
 namespace tidy {
 
 /// \brief Contains options for clang-tidy.
 struct ClangTidyOptions {
   ClangTidyOptions() : EnableChecksRegex(".*"), AnalyzeTemporaryDtors(false) {}
   std::string EnableChecksRegex;
   std::string DisableChecksRegex;
+  // Output warnings from headers matching this filter. Warnings from main files
+  // will always be displayed.
+  std::string HeaderFilterRegex;
   bool AnalyzeTemporaryDtors;
 };
 
Index: clang-tidy/tool/ClangTidyMain.cpp
===================================================================
--- clang-tidy/tool/ClangTidyMain.cpp
+++ clang-tidy/tool/ClangTidyMain.cpp
@@ -39,6 +39,12 @@
              "|llvm-namespace-comment" // Not complete.
              "|google-.*)"),           // Doesn't apply to LLVM.
     cl::cat(ClangTidyCategory));
+static cl::opt<std::string> HeaderFilter(
+    "header-filter",
+    cl::desc("Regular expression matching the names of the headers to output\n"
+             "diagnostics from. Diagnostics from the main files of\n"
+             "translation units are always displayed."),
+    cl::init(""), cl::cat(ClangTidyCategory));
 static cl::opt<bool> Fix("fix", cl::desc("Fix detected errors if possible."),
                          cl::init(false), cl::cat(ClangTidyCategory));
 
@@ -59,6 +65,7 @@
   clang::tidy::ClangTidyOptions Options;
   Options.EnableChecksRegex = Checks;
   Options.DisableChecksRegex = DisableChecks;
+  Options.HeaderFilterRegex = HeaderFilter;
   Options.AnalyzeTemporaryDtors = AnalyzeTemporaryDtors;
 
   // FIXME: Allow using --list-checks without positional arguments.
Index: test/clang-tidy/Inputs/file-filter/header1.h
===================================================================
--- /dev/null
+++ test/clang-tidy/Inputs/file-filter/header1.h
@@ -0,0 +1 @@
+class A1 { A1(int); };
Index: test/clang-tidy/Inputs/file-filter/header2.h
===================================================================
--- /dev/null
+++ test/clang-tidy/Inputs/file-filter/header2.h
@@ -0,0 +1 @@
+class A2 { A2(int); };
Index: test/clang-tidy/file-filter.cpp
===================================================================
--- /dev/null
+++ test/clang-tidy/file-filter.cpp
@@ -0,0 +1,22 @@
+// 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
+
+#include "header1.h"
+// CHECK-NOT: warning:
+// CHECK2: header1.h:1:12: warning: Single-argument constructors must be explicit [google-explicit-constructor]
+// CHECK3-NOT: warning:
+
+#include "header2.h"
+// CHECK-NOT: warning:
+// CHECK2: header2.h:1:12: warning: Single-argument constructors {{.*}}
+// CHECK3: header2.h:1:12: warning: Single-argument constructors {{.*}}
+
+class A { A(int); };
+// CHECK: :[[@LINE-1]]:11: warning: Single-argument constructors {{.*}}
+// CHECK2: :[[@LINE-2]]:11: warning: Single-argument constructors {{.*}}
+// CHECK3: :[[@LINE-3]]:11: warning: Single-argument constructors {{.*}}
+
+// CHECK-NOT: warning:
+// CHECK2-NOT: warning:
+// CHECK3-NOT: warning:
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to