chh updated this revision to Diff 355699.
chh edited the summary of this revision.
chh added a comment.

Move almost all changes to MatchFinder into ClangTidy.cpp.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D98710/new/

https://reviews.llvm.org/D98710

Files:
  clang-tools-extra/clang-tidy/ClangTidy.cpp
  clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
  clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
  clang-tools-extra/clang-tidy/ClangTidyOptions.h
  clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
  clang-tools-extra/test/clang-tidy/checkers/Inputs/skip-headers/my_header1.h
  clang-tools-extra/test/clang-tidy/checkers/Inputs/skip-headers/my_header2.h
  
clang-tools-extra/test/clang-tidy/checkers/bugprone-forward-declaration-namespace.cpp
  clang-tools-extra/test/clang-tidy/checkers/bugprone-reserved-identifier.cpp
  clang-tools-extra/test/clang-tidy/checkers/bugprone-suspicious-include.cpp
  
clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-interfaces-global-init.cpp
  clang-tools-extra/test/clang-tidy/checkers/google-namespaces.cpp
  clang-tools-extra/test/clang-tidy/checkers/google-objc-function-naming.m
  clang-tools-extra/test/clang-tidy/checkers/llvm-include-order.cpp
  
clang-tools-extra/test/clang-tidy/checkers/llvm-prefer-register-over-unsigned.cpp
  
clang-tools-extra/test/clang-tidy/checkers/llvmlibc-implementation-in-namespace.cpp
  
clang-tools-extra/test/clang-tidy/checkers/llvmlibc-restrict-system-libc-headers.cpp
  clang-tools-extra/test/clang-tidy/checkers/misc-no-recursion.cpp
  
clang-tools-extra/test/clang-tidy/checkers/modernize-deprecated-headers-cxx03.cpp
  
clang-tools-extra/test/clang-tidy/checkers/modernize-deprecated-headers-cxx11.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize-pass-by-value-header.cpp
  
clang-tools-extra/test/clang-tidy/checkers/portability-restrict-system-includes-allow.cpp
  
clang-tools-extra/test/clang-tidy/checkers/portability-restrict-system-includes-disallow.cpp
  
clang-tools-extra/test/clang-tidy/checkers/readability-simplify-bool-expr-chained-conditional-assignment.cpp
  
clang-tools-extra/test/clang-tidy/checkers/readability-simplify-bool-expr-chained-conditional-return.cpp
  
clang-tools-extra/test/clang-tidy/checkers/readability-simplify-bool-expr-members.cpp
  clang-tools-extra/test/clang-tidy/checkers/readability-simplify-bool-expr.cpp
  clang-tools-extra/test/clang-tidy/checkers/skip-headers.cpp
  clang/include/clang/ASTMatchers/ASTMatchFinder.h
  clang/lib/ASTMatchers/ASTMatchFinder.cpp

Index: clang/lib/ASTMatchers/ASTMatchFinder.cpp
===================================================================
--- clang/lib/ASTMatchers/ASTMatchFinder.cpp
+++ clang/lib/ASTMatchers/ASTMatchFinder.cpp
@@ -1306,6 +1306,10 @@
                    MatchFinder::ParsingDoneTestCallback *ParsingDone)
       : Finder(Finder), ParsingDone(ParsingDone) {}
 
+  bool HandleTopLevelDecl(DeclGroupRef DG) override {
+    return Finder->HandleTopLevelDecl(DG);
+  }
+
 private:
   void HandleTranslationUnit(ASTContext &Context) override {
     if (ParsingDone != nullptr) {
@@ -1434,6 +1438,10 @@
   Visitor.match(Node);
 }
 
+bool MatchFinder::HandleTopLevelDecl(DeclGroupRef) {
+  return true;
+}
+
 void MatchFinder::matchAST(ASTContext &Context) {
   internal::MatchASTVisitor Visitor(&Matchers, Options);
   Visitor.set_active_ast_context(&Context);
Index: clang/include/clang/ASTMatchers/ASTMatchFinder.h
===================================================================
--- clang/include/clang/ASTMatchers/ASTMatchFinder.h
+++ clang/include/clang/ASTMatchers/ASTMatchFinder.h
@@ -141,7 +141,10 @@
   };
 
   MatchFinder(MatchFinderOptions Options = MatchFinderOptions());
-  ~MatchFinder();
+  virtual ~MatchFinder();
+
+  /// Inside a MatchASTConsumer, handles all top level Decl.
+  virtual bool HandleTopLevelDecl(DeclGroupRef DG);
 
   /// Adds a matcher to execute when running over the AST.
   ///
@@ -196,7 +199,7 @@
   /// @}
 
   /// Finds all matches in the given AST.
-  void matchAST(ASTContext &Context);
+  virtual void matchAST(ASTContext &Context);
 
   /// Registers a callback to notify the end of parsing.
   ///
Index: clang-tools-extra/test/clang-tidy/checkers/skip-headers.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/skip-headers.cpp
@@ -0,0 +1,54 @@
+// Test --skip-headers, --show-all-warnings, and --header-filter.
+// TODO: when skip-headers implementation is complete, add back
+//      -implicit-check-not="{{warning|error}}:"
+// and use no_hint instead of hint
+//
+// Default shows no warning in .h files, and give HINT to use --header-filter
+// RUN: clang-tidy %s -checks='*' -- \
+// RUN: 2>&1 | FileCheck %s -check-prefixes WARN,MAIN,HINT
+// later:    -implicit-check-not="{{warning|error}}:"
+//
+// --skip-headers skips included files; finds only warnings in the main file.
+// RUN: clang-tidy %s -checks='*' --skip-headers -- \
+// RUN: 2>&1 | FileCheck %s -check-prefixes WARN,MAIN,HINT
+// later:    no_hint -implicit-check-not="{{warning|error}}:"
+//
+// --show-all-warnings reports all warnings, even without --header-filters
+// RUN: clang-tidy %s -checks='*' --show-all-warnings -- \
+// RUN: 2>&1 | FileCheck %s -check-prefixes WARN,WARN_BOTH,MAIN,NO_HINT
+//
+// --header-filter='.*' is like --show-all-warnings
+// RUN: clang-tidy %s -checks='*' --header-filter='.*' -- \
+// RUN: 2>&1 | FileCheck %s -check-prefixes WARN,WARN_BOTH,MAIN,NO_HINT
+//
+// --header-filter='header1.h' shows only warnings in header1.h
+// RUN: clang-tidy %s -checks='*' --header-filter='header1.h' -- \
+// RUN: 2>&1 | FileCheck %s -check-prefixes WARN,WARN1,MAIN,HINT
+// later:    -implicit-check-not="{{warning|error}}:"
+//
+// The main purpose of --show-all-warnings is to debug --skip-headers.
+// When used together, no warnings should be reported from header files.
+// RUN: clang-tidy %s -checks='*' --skip-headers --show-all-warnings -- \
+// RUN: 2>&1 | FileCheck %s -check-prefixes WARN,MAIN,NO_HINT
+// later:  -implicit-check-not="{{warning|error}}:"
+//
+// use --skip-headers and --header-filter='header2.h'
+// to skip header1.h but not header2.h
+// RUN: clang-tidy %s -checks='*' --skip-headers --header-filter='header2.h' \
+// RUN: 2>&1 | FileCheck %s -check-prefixes WARN,WARN2,MAIN,HINT
+// later:  no_hint
+
+// WARN: {{[0-9]+}} warnings generated.
+#include "Inputs/skip-headers/my_header1.h"
+// WARN1: my_header1.h:1:1: warning: header is missing header guard
+// WARN1-NOT: my_header2.h
+// WARN2: my_header2.h:1:1: warning: header is missing header guard
+// WARN2-NOT: my_header1.h
+// WARN_BOTH: my_header1.h:1:1: warning: header is missing header guard
+// WARN_BOTH: my_header2.h:1:1: warning: header is missing header guard
+
+int xyz = 135;
+// MAIN-COUNT-4: skip-headers.cpp:{{[0-9]+}}:{{[0-9]+}}: warning:
+
+// HINT: Use -header-filter={{.*}} to display errors{{.*}}
+// NO_HINT-NOT: Use -header-filter=
Index: clang-tools-extra/test/clang-tidy/checkers/readability-simplify-bool-expr.cpp
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/readability-simplify-bool-expr.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/readability-simplify-bool-expr.cpp
@@ -1,4 +1,5 @@
 // RUN: %check_clang_tidy %s readability-simplify-boolean-expr %t
+// RUN: %check_clang_tidy %s readability-simplify-boolean-expr %t -- --skip-headers
 
 bool a1 = false;
 
Index: clang-tools-extra/test/clang-tidy/checkers/readability-simplify-bool-expr-members.cpp
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/readability-simplify-bool-expr-members.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/readability-simplify-bool-expr-members.cpp
@@ -1,4 +1,5 @@
 // RUN: %check_clang_tidy %s readability-simplify-boolean-expr %t
+// RUN: %check_clang_tidy %s readability-simplify-boolean-expr %t -- --skip-headers
 
 class A {
 public:
Index: clang-tools-extra/test/clang-tidy/checkers/readability-simplify-bool-expr-chained-conditional-return.cpp
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/readability-simplify-bool-expr-chained-conditional-return.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/readability-simplify-bool-expr-chained-conditional-return.cpp
@@ -1,4 +1,7 @@
-// RUN: %check_clang_tidy %s readability-simplify-boolean-expr %t -- -config="{CheckOptions: [{key: "readability-simplify-boolean-expr.ChainedConditionalReturn", value: true}]}" --
+// RUN: %check_clang_tidy %s readability-simplify-boolean-expr %t -- \
+// RUN: -config="{CheckOptions: [{key: "readability-simplify-boolean-expr.ChainedConditionalReturn", value: true}]}" --
+// RUN: %check_clang_tidy %s readability-simplify-boolean-expr %t -- --skip-headers \
+// RUN: -config="{CheckOptions: [{key: "readability-simplify-boolean-expr.ChainedConditionalReturn", value: true}]}" --
 
 bool chained_conditional_compound_return(int i) {
   if (i < 0) {
Index: clang-tools-extra/test/clang-tidy/checkers/readability-simplify-bool-expr-chained-conditional-assignment.cpp
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/readability-simplify-bool-expr-chained-conditional-assignment.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/readability-simplify-bool-expr-chained-conditional-assignment.cpp
@@ -1,4 +1,7 @@
-// RUN: %check_clang_tidy %s readability-simplify-boolean-expr %t -- -config="{CheckOptions: [{key: "readability-simplify-boolean-expr.ChainedConditionalAssignment", value: true}]}" --
+// RUN: %check_clang_tidy %s readability-simplify-boolean-expr %t -- \
+// RUN: -config="{CheckOptions: [{key: "readability-simplify-boolean-expr.ChainedConditionalAssignment", value: true}]}" --
+// RUN: %check_clang_tidy %s readability-simplify-boolean-expr %t -- --skip-headers \
+// RUN: -config="{CheckOptions: [{key: "readability-simplify-boolean-expr.ChainedConditionalAssignment", value: true}]}" --
 
 void chained_conditional_compound_assignment(int i) {
   bool b;
Index: clang-tools-extra/test/clang-tidy/checkers/portability-restrict-system-includes-disallow.cpp
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/portability-restrict-system-includes-disallow.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/portability-restrict-system-includes-disallow.cpp
@@ -1,6 +1,10 @@
 // RUN: %check_clang_tidy %s portability-restrict-system-includes %t \
 // RUN:     -- -config="{CheckOptions: [{key: portability-restrict-system-includes.Includes, value: '-*,stddef.h'}]}" \
 // RUN:     -- -isystem %S/Inputs/portability-restrict-system-includes/system
+//
+// RUN: %check_clang_tidy %s portability-restrict-system-includes %t \
+// RUN:     -- -config="{CheckOptions: [{key: portability-restrict-system-includes.Includes, value: '-*,stddef.h'}]}" --skip-headers \
+// RUN:     -- -isystem %S/Inputs/portability-restrict-system-includes/system
 
 // Test allow-list functionality: disallow all but stddef.h.
 
Index: clang-tools-extra/test/clang-tidy/checkers/portability-restrict-system-includes-allow.cpp
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/portability-restrict-system-includes-allow.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/portability-restrict-system-includes-allow.cpp
@@ -1,6 +1,10 @@
 // RUN: %check_clang_tidy %s portability-restrict-system-includes %t \
 // RUN:     -- -config="{CheckOptions: [{key: portability-restrict-system-includes.Includes, value: '*,-stddef.h'}]}" \
 // RUN:     -- -isystem %S/Inputs/portability-restrict-system-includes/system
+//
+// RUN: %check_clang_tidy %s portability-restrict-system-includes %t \
+// RUN:     -- -config="{CheckOptions: [{key: portability-restrict-system-includes.Includes, value: '*,-stddef.h'}]}" --skip-headers \
+// RUN:     -- -isystem %S/Inputs/portability-restrict-system-includes/system
 
 // Test block-list functionality: allow all but stddef.h.
 
Index: clang-tools-extra/test/clang-tidy/checkers/modernize-pass-by-value-header.cpp
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/modernize-pass-by-value-header.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/modernize-pass-by-value-header.cpp
@@ -1,9 +1,37 @@
 // RUN: cp %S/Inputs/modernize-pass-by-value/header.h %T/pass-by-value-header.h
-// RUN: clang-tidy %s -checks='-*,modernize-pass-by-value' -header-filter='.*' -fix -- -std=c++11 -I %T | FileCheck %s -check-prefix=CHECK-MESSAGES -implicit-check-not="{{warning|error}}:"
+// RUN: clang-tidy %s -checks='-*,modernize-pass-by-value' -header-filter='.*' -fix -- -std=c++11 -I %T \
+// RUN: | FileCheck %s -check-prefix=CHECK-MESSAGES -implicit-check-not="{{warning|error}}:"
 // RUN: FileCheck -input-file=%T/pass-by-value-header.h %s -check-prefix=CHECK-FIXES
+//
+// RUN: cp %S/Inputs/modernize-pass-by-value/header.h %T/pass-by-value-header.h
+// RUN: clang-tidy %s -checks='*' -- -std=c++11 -I %T \
+// RUN: 2>&1 | FileCheck %s -check-prefix=CHECK-NOHEADER -allow-empty
+//
+// RUN: cp %S/Inputs/modernize-pass-by-value/header.h %T/pass-by-value-header.h
+// RUN: clang-tidy %s -checks='-*,modernize-pass-by-value' --skip-headers -fix -- -std=c++11 -I %T \
+// RUN: | FileCheck %s -check-prefix=CHECK-SKIP -allow-empty -implicit-check-not="{{warning|error}}:"
+// RUN: FileCheck -input-file=%T/pass-by-value-header.h %s -check-prefix=CHECK-SKIP-FIXES
+//
+// RUN: cp %S/Inputs/modernize-pass-by-value/header.h %T/pass-by-value-header.h
+// RUN: clang-tidy %s -checks='*' --skip-headers -- -std=c++11 -I %T \
+// RUN: | FileCheck %s -check-prefix=CHECK-SKIP -allow-empty -implicit-check-not="{{warning|error}}:"
+//
 // FIXME: Make the test work in all language modes.
 
 #include "pass-by-value-header.h"
-// CHECK-MESSAGES: :8:5: warning: pass by value and use std::move [modernize-pass-by-value]
+// header file warnings are not shown, with --skip-headers, or without -header-filter
+// CHECK-MESSAGES:     :8:5: warning: pass by value and use std::move [modernize-pass-by-value]
+// CHECK-NOHEADER-NOT: :8:5: warning: pass by value and use std::move [modernize-pass-by-value]
+// CHECK-SKIP-NOT:     :8:5: warning: pass by value and use std::move [modernize-pass-by-value]
+//
 // CHECK-FIXES: #include <utility>
 // CHECK-FIXES: A(ThreadId tid) : threadid(std::move(tid)) {}
+// CHECK-SKIP-FIXES-NOT: #include <utility>
+//
+// header files are checked even without -header-filtler
+// CHECK-NOHEADER: Suppressed {{.*}} warnings
+// CHECK-NOHEADER: Use -header-filter={{.*}} to display errors{{.*}}
+//
+// header files are not checked with --skip-headers
+// CHECK-SKIP-NOT: Suppressed {{.*}} warnings
+// CHECK-SKIP-NOT: Use -header-filter={{.*}} to display errors{{.*}}
Index: clang-tools-extra/test/clang-tidy/checkers/modernize-deprecated-headers-cxx11.cpp
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/modernize-deprecated-headers-cxx11.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/modernize-deprecated-headers-cxx11.cpp
@@ -1,4 +1,5 @@
 // RUN: %check_clang_tidy -std=c++11-or-later %s modernize-deprecated-headers %t -- -extra-arg-before=-isystem%S/Inputs/modernize-deprecated-headers
+// RUN: %check_clang_tidy -std=c++11-or-later %s modernize-deprecated-headers %t -- --skip-headers -extra-arg-before=-isystem%S/Inputs/modernize-deprecated-headers
 
 #include <assert.h>
 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'assert.h'; consider using 'cassert' instead [modernize-deprecated-headers]
Index: clang-tools-extra/test/clang-tidy/checkers/modernize-deprecated-headers-cxx03.cpp
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/modernize-deprecated-headers-cxx03.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/modernize-deprecated-headers-cxx03.cpp
@@ -1,4 +1,5 @@
 // RUN: %check_clang_tidy -std=c++98 %s modernize-deprecated-headers %t -- -extra-arg-before=-isystem%S/Inputs/modernize-deprecated-headers
+// RUN: %check_clang_tidy -std=c++98 %s modernize-deprecated-headers %t -- --skip-headers -extra-arg-before=-isystem%S/Inputs/modernize-deprecated-headers
 
 #include <assert.h>
 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: inclusion of deprecated C++ header 'assert.h'; consider using 'cassert' instead [modernize-deprecated-headers]
Index: clang-tools-extra/test/clang-tidy/checkers/misc-no-recursion.cpp
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/misc-no-recursion.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/misc-no-recursion.cpp
@@ -1,4 +1,5 @@
 // RUN: %check_clang_tidy %s misc-no-recursion %t
+// RUN: %check_clang_tidy %s misc-no-recursion %t -- --skip-headers
 
 // We don't have the definition of this function,
 // so we can't tell anything about it..
Index: clang-tools-extra/test/clang-tidy/checkers/llvmlibc-restrict-system-libc-headers.cpp
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/llvmlibc-restrict-system-libc-headers.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/llvmlibc-restrict-system-libc-headers.cpp
@@ -1,6 +1,10 @@
 // RUN: %check_clang_tidy %s llvmlibc-restrict-system-libc-headers %t \
 // RUN:   -- -- -isystem %S/Inputs/llvmlibc/system \
 // RUN:   -resource-dir %S/Inputs/llvmlibc/resource
+//
+// RUN: %check_clang_tidy %s llvmlibc-restrict-system-libc-headers %t \
+// RUN:   -- --skip-headers -- -isystem %S/Inputs/llvmlibc/system \
+// RUN:   -resource-dir %S/Inputs/llvmlibc/resource
 
 #include <stdio.h>
 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: system include stdio.h not allowed
Index: clang-tools-extra/test/clang-tidy/checkers/llvmlibc-implementation-in-namespace.cpp
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/llvmlibc-implementation-in-namespace.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/llvmlibc-implementation-in-namespace.cpp
@@ -1,4 +1,5 @@
 // RUN: %check_clang_tidy %s llvmlibc-implementation-in-namespace %t
+// RUN: %check_clang_tidy %s llvmlibc-implementation-in-namespace %t -- --skip-headers
 
 #define MACRO_A "defining macros outside namespace is valid"
 
Index: clang-tools-extra/test/clang-tidy/checkers/llvm-prefer-register-over-unsigned.cpp
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/llvm-prefer-register-over-unsigned.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/llvm-prefer-register-over-unsigned.cpp
@@ -1,4 +1,5 @@
 // RUN: %check_clang_tidy %s llvm-prefer-register-over-unsigned %t
+// RUN: %check_clang_tidy %s llvm-prefer-register-over-unsigned %t -- --skip-headers
 
 namespace llvm {
 class Register {
Index: clang-tools-extra/test/clang-tidy/checkers/llvm-include-order.cpp
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/llvm-include-order.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/llvm-include-order.cpp
@@ -1,4 +1,5 @@
 // RUN: %check_clang_tidy %s llvm-include-order %t -- -- -isystem %S/Inputs/Headers
+// RUN: %check_clang_tidy %s llvm-include-order %t -- --skip-headers -- -isystem %S/Inputs/Headers
 
 // CHECK-MESSAGES: [[@LINE+2]]:1: warning: #includes are not sorted properly
 #include "j.h"
Index: clang-tools-extra/test/clang-tidy/checkers/google-objc-function-naming.m
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/google-objc-function-naming.m
+++ clang-tools-extra/test/clang-tidy/checkers/google-objc-function-naming.m
@@ -1,4 +1,5 @@
 // RUN: %check_clang_tidy %s google-objc-function-naming %t -- -- -isystem %S/Inputs/Headers
+// RUN: %check_clang_tidy %s google-objc-function-naming %t -- --skip-headers -- -isystem %S/Inputs/Headers
 
 #include <stdio.h>
 
Index: clang-tools-extra/test/clang-tidy/checkers/google-namespaces.cpp
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/google-namespaces.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/google-namespaces.cpp
@@ -1,6 +1,32 @@
-// RUN: clang-tidy %s -checks='-*,google-build-namespaces,google-build-using-namespace' -header-filter='.*' -- | FileCheck %s -implicit-check-not="{{warning|error}}:"
+// RUN: clang-tidy %s -checks='-*,google-build-namespaces,google-build-using-namespace' -header-filter='.*' -- \
+// RUN: 2>&1 | FileCheck %s -check-prefixes CHECK,CHECK1 -implicit-check-not="{{warning|error}}:"
+
+// RUN: clang-tidy %s -checks='-*,google-build-namespaces,google-build-using-namespace' -- \
+// RUN: 2>&1 | FileCheck %s -check-prefixes CHECK,CHECK0 -implicit-check-not="{{warning|error}}:"
+//
+// RUN: clang-tidy %s --skip-headers -checks='-*,google-build-namespaces,google-build-using-namespace' -- \
+// RUN: 2>&1 | FileCheck %s -check-prefixes CHECK,CHECK2 -implicit-check-not="{{warning|error}}:"
+//
+// -header-filter overrides --skip-header
+// RUN: clang-tidy %s --skip-headers -header-filter='.*' -checks='-*,google-build-namespaces,google-build-using-namespace' -- \
+// RUN: 2>&1 | FileCheck %s -check-prefixes CHECK,CHECK1 -implicit-check-not="{{warning|error}}:"
+//
+// --show-all-warnings is like -header-filter=.* + -system-headers
+// RUN: clang-tidy %s --show-all-warnings -checks='-*,google-build-namespaces,google-build-using-namespace' -- \
+// RUN: 2>&1 | FileCheck %s -check-prefixes CHECK,CHECK1 -implicit-check-not="{{warning|error}}:"
+
+// --skip-header skips 1 warning in the header file.
+// CHECK0: 7 warnings generated
+// CHECK1: 7 warnings generated
+// CHECK2: 6 warnings generated
+
 #include "Inputs/google-namespaces.h"
-// CHECK: warning: do not use unnamed namespaces in header files [google-build-namespaces]
+// with -header-filter, warning in .h file is shown
+// CHECK1: warning: do not use unnamed namespaces in header files [google-build-namespaces]
+// without -header-filter, warning in .h files are not shown
+// CHECK0-NOT: warning: do not use unnamed namespaces in header files [google-build-namespaces]
+// with --skip-header, no warning in .h file is detected at all
+// CHECK2-NOT: warning: do not use unnamed namespaces in header files [google-build-namespaces]
 
 using namespace spaaaace;
 // CHECK: :[[@LINE-1]]:1: warning: do not use namespace using-directives; use using-declarations instead [google-build-using-namespace]
@@ -50,3 +76,14 @@
 
 using namespace foo_literals;
 // CHECK: :[[@LINE-1]]:1: warning: do not use namespace using-directives; use using-declarations instead [google-build-using-namespace]
+
+// If -header-filter= is not used and there is some warning in .h file,
+// give a reminder to use -header-filter.
+// CHECK0: Use -header-filter={{.*}} to display errors{{.*}}
+//
+// If -header-filter= is used, no summary of this message.
+// CHECK1-NOT: Use -header-filter={{.*}} to display errors{{.*}}
+//
+// With --skip-header, no warning in .h file is detected or hidden,
+// no need to give a reminder to use -header-filter.
+// CHECK2-NOT: Use -header-filter={{.*}} to display errors{{.*}}
Index: clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-interfaces-global-init.cpp
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-interfaces-global-init.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-interfaces-global-init.cpp
@@ -1,4 +1,5 @@
 // RUN: %check_clang_tidy %s cppcoreguidelines-interfaces-global-init %t
+// RUN: %check_clang_tidy %s cppcoreguidelines-interfaces-global-init %t -- --skip-headers
 
 constexpr int makesInt() { return 3; }
 constexpr int takesInt(int i) { return i + 1; }
Index: clang-tools-extra/test/clang-tidy/checkers/bugprone-suspicious-include.cpp
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/bugprone-suspicious-include.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/bugprone-suspicious-include.cpp
@@ -1,4 +1,5 @@
 // RUN: %check_clang_tidy %s bugprone-suspicious-include %t -- -- -isystem %S/Inputs/Headers -fmodules
+// RUN: %check_clang_tidy %s bugprone-suspicious-include %t -- --skip-headers -- -isystem %S/Inputs/Headers -fmodules
 
 // clang-format off
 
Index: clang-tools-extra/test/clang-tidy/checkers/bugprone-reserved-identifier.cpp
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/bugprone-reserved-identifier.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/bugprone-reserved-identifier.cpp
@@ -1,6 +1,9 @@
 // RUN: %check_clang_tidy %s bugprone-reserved-identifier %t -- -- \
 // RUN:   -I%S/Inputs/bugprone-reserved-identifier \
 // RUN:   -isystem %S/Inputs/bugprone-reserved-identifier/system
+// RUN: %check_clang_tidy %s bugprone-reserved-identifier %t -- --skip-headers -- \
+// RUN:   -I%S/Inputs/bugprone-reserved-identifier \
+// RUN:   -isystem %S/Inputs/bugprone-reserved-identifier/system
 
 // no warnings expected without -header-filter=
 #include "user-header.h"
Index: clang-tools-extra/test/clang-tidy/checkers/bugprone-forward-declaration-namespace.cpp
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/bugprone-forward-declaration-namespace.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/bugprone-forward-declaration-namespace.cpp
@@ -1,4 +1,5 @@
 // RUN: %check_clang_tidy %s bugprone-forward-declaration-namespace %t
+// RUN: %check_clang_tidy %s bugprone-forward-declaration-namespace %t -- --skip-headers
 
 namespace {
 // This is a declaration in a wrong namespace.
Index: clang-tools-extra/test/clang-tidy/checkers/Inputs/skip-headers/my_header2.h
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/Inputs/skip-headers/my_header2.h
@@ -0,0 +1,6 @@
+// bad header guard
+#ifndef SOME_MACRO
+
+int abc = 123; // bad definition in .h file
+
+#endif
Index: clang-tools-extra/test/clang-tidy/checkers/Inputs/skip-headers/my_header1.h
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/Inputs/skip-headers/my_header1.h
@@ -0,0 +1,3 @@
+// no header guard
+
+#include "my_header2.h"
Index: clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
===================================================================
--- clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
+++ clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
@@ -95,10 +95,23 @@
                                          cl::init(""),
                                          cl::cat(ClangTidyCategory));
 
+static cl::opt<bool> ShowAllWarnings("show-all-warnings",
+                                     cl::desc("Display all warning messages."),
+                                     cl::init(false), cl::Hidden,
+                                     cl::cat(ClangTidyCategory));
+
+static cl::opt<bool> SkipHeaders("skip-headers", cl::desc(R"(
+Do not check included header files, but
+files matching the --header-filter pattern are still checked.
+System headers are still checked if --system-headers is true.
+)"),
+                                 cl::init(false), cl::cat(ClangTidyCategory));
+
 static cl::opt<bool>
     SystemHeaders("system-headers",
                   cl::desc("Display the errors from system headers."),
                   cl::init(false), cl::cat(ClangTidyCategory));
+
 static cl::opt<std::string> LineFilter("line-filter", cl::desc(R"(
 List of files with line ranges to filter the
 warnings. Can be used together with
@@ -300,6 +313,8 @@
   DefaultOptions.Checks = DefaultChecks;
   DefaultOptions.WarningsAsErrors = "";
   DefaultOptions.HeaderFilterRegex = HeaderFilter;
+  DefaultOptions.ShowAllWarnings = ShowAllWarnings;
+  DefaultOptions.SkipHeaders = SkipHeaders;
   DefaultOptions.SystemHeaders = SystemHeaders;
   DefaultOptions.FormatStyle = FormatStyle;
   DefaultOptions.User = llvm::sys::Process::GetEnv("USER");
@@ -314,6 +329,10 @@
     OverrideOptions.WarningsAsErrors = WarningsAsErrors;
   if (HeaderFilter.getNumOccurrences() > 0)
     OverrideOptions.HeaderFilterRegex = HeaderFilter;
+  if (ShowAllWarnings.getNumOccurrences() > 0)
+    OverrideOptions.ShowAllWarnings = ShowAllWarnings;
+  if (SkipHeaders.getNumOccurrences() > 0)
+    OverrideOptions.SkipHeaders = SkipHeaders;
   if (SystemHeaders.getNumOccurrences() > 0)
     OverrideOptions.SystemHeaders = SystemHeaders;
   if (FormatStyle.getNumOccurrences() > 0)
Index: clang-tools-extra/clang-tidy/ClangTidyOptions.h
===================================================================
--- clang-tools-extra/clang-tidy/ClangTidyOptions.h
+++ clang-tools-extra/clang-tidy/ClangTidyOptions.h
@@ -76,6 +76,13 @@
   /// main files will always be displayed.
   llvm::Optional<std::string> HeaderFilterRegex;
 
+  /// Show all warnings, including warnings from all header files.
+  llvm::Optional<bool> ShowAllWarnings;
+
+  /// Do not check included files, except files matching the --header-filter
+  /// and system files when --system-headers is used.
+  llvm::Optional<bool> SkipHeaders;
+
   /// Output warnings from system headers matching \c HeaderFilterRegex.
   llvm::Optional<bool> SystemHeaders;
 
Index: clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
===================================================================
--- clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
+++ clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
@@ -111,6 +111,8 @@
   Options.Checks = "";
   Options.WarningsAsErrors = "";
   Options.HeaderFilterRegex = "";
+  Options.ShowAllWarnings = false;
+  Options.SkipHeaders = false;
   Options.SystemHeaders = false;
   Options.FormatStyle = "none";
   Options.User = llvm::None;
@@ -147,6 +149,8 @@
   mergeCommaSeparatedLists(Checks, Other.Checks);
   mergeCommaSeparatedLists(WarningsAsErrors, Other.WarningsAsErrors);
   overrideValue(HeaderFilterRegex, Other.HeaderFilterRegex);
+  overrideValue(ShowAllWarnings, Other.ShowAllWarnings);
+  overrideValue(SkipHeaders, Other.SkipHeaders);
   overrideValue(SystemHeaders, Other.SystemHeaders);
   overrideValue(FormatStyle, Other.FormatStyle);
   overrideValue(User, Other.User);
Index: clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
===================================================================
--- clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
+++ clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
@@ -580,7 +580,7 @@
 void ClangTidyDiagnosticConsumer::checkFilters(SourceLocation Location,
                                                const SourceManager &Sources) {
   // Invalid location may mean a diagnostic in a command line, don't skip these.
-  if (!Location.isValid()) {
+  if (!Location.isValid() || *Context.getOptions().ShowAllWarnings) {
     LastErrorRelatesToUserCode = true;
     LastErrorPassesLineFilter = true;
     return;
Index: clang-tools-extra/clang-tidy/ClangTidy.cpp
===================================================================
--- clang-tools-extra/clang-tidy/ClangTidy.cpp
+++ clang-tools-extra/clang-tidy/ClangTidy.cpp
@@ -305,11 +305,50 @@
   unsigned WarningsAsErrors;
 };
 
+// Check if a Decl should be skipped by clang-tidy checks.
+struct DeclFilter {
+  DeclFilter(ClangTidyContext &Ctx, SourceManager &SM)
+      : Context(Ctx), Sources(SM) {
+    HeaderFilter =
+        std::make_unique<llvm::Regex>(*Ctx.getOptions().HeaderFilterRegex);
+    LastSkippedFileID = FileID::getSentinel();
+    LastAcceptedFileID = FileID::getSentinel();
+  }
+  bool skipDecl(Decl *);
+  bool skipLocation(SourceLocation);
+
+private:
+  bool skipFileID(SourceLocation, FileID);
+  ClangTidyContext &Context;
+  SourceManager &Sources;
+  std::unique_ptr<llvm::Regex> HeaderFilter;
+  FileID LastSkippedFileID;
+  FileID LastAcceptedFileID;
+};
+
+// Add extra filter option to MatchFinder.
+struct ClangTidyMatchFinder : public ast_matchers::MatchFinder {
+  ClangTidyMatchFinder(MatchFinderOptions Options,
+                       std::shared_ptr<DeclFilter> Filter)
+      : MatchFinder(Options), Filter(Filter) {}
+  virtual ~ClangTidyMatchFinder() override {}
+  bool HandleTopLevelDecl(DeclGroupRef DG) override;
+  void matchAST(ASTContext &Context) override;
+
+private:
+  bool hasFilter() { return Filter.get() != nullptr; }
+  std::vector<Decl *> &getTraversalScope() { return TopLevelDecls; }
+  /// Check if a Decl should be skipped.
+  std::shared_ptr<DeclFilter> Filter;
+  /// All (filtered) top level decls.
+  std::vector<Decl *> TopLevelDecls;
+};
+
 class ClangTidyASTConsumer : public MultiplexConsumer {
 public:
   ClangTidyASTConsumer(std::vector<std::unique_ptr<ASTConsumer>> Consumers,
                        std::unique_ptr<ClangTidyProfiling> Profiling,
-                       std::unique_ptr<ast_matchers::MatchFinder> Finder,
+                       std::unique_ptr<ClangTidyMatchFinder> Finder,
                        std::vector<std::unique_ptr<ClangTidyCheck>> Checks)
       : MultiplexConsumer(std::move(Consumers)),
         Profiling(std::move(Profiling)), Finder(std::move(Finder)),
@@ -319,7 +358,7 @@
   // Destructor order matters! Profiling must be destructed last.
   // Or at least after Finder.
   std::unique_ptr<ClangTidyProfiling> Profiling;
-  std::unique_ptr<ast_matchers::MatchFinder> Finder;
+  std::unique_ptr<ClangTidyMatchFinder> Finder;
   std::vector<std::unique_ptr<ClangTidyCheck>> Checks;
 };
 
@@ -384,6 +423,96 @@
 }
 #endif // CLANG_TIDY_ENABLE_STATIC_ANALYZER
 
+bool DeclFilter::skipFileID(SourceLocation Location, FileID FID) {
+  // do not skip the main file
+  if (Sources.isInMainFile(Location))
+    return false;
+  // skip system headers unless --system-headers is used
+  if (Sources.isInSystemHeader(Location))
+    return !*Context.getOptions().SystemHeaders;
+  const FileEntry *File = Sources.getFileEntryForID(FID);
+  // without a FileEntry, cannot verify header file path to skip
+  if (!File)
+    return false;
+  StringRef FileName(File->getName());
+  // skip, unless file name matches --header-filter
+  return !HeaderFilter->match(FileName);
+}
+
+bool DeclFilter::skipDecl(Decl *Decl) {
+  return skipLocation(Decl->getLocation());
+}
+
+bool DeclFilter::skipLocation(SourceLocation Location) {
+  // cannot get valid FileID if Location is invalid
+  if (!Location.isValid())
+    return false;
+  // Similar to ClangTidyDiagnosticConsumer::checkFilters,
+  // the decision to skip a check depends on getDecomposedExpansionLoc.
+  auto FID = Sources.getDecomposedExpansionLoc(Location).first;
+  // Quick check against last checked results.
+  if (FID == LastSkippedFileID)
+    return true;
+  if (FID == LastAcceptedFileID)
+    return false;
+  auto ShouldSkip = skipFileID(Location, FID);
+  if (ShouldSkip) {
+    LastSkippedFileID = FID;
+  } else {
+    LastAcceptedFileID = FID;
+  }
+  return ShouldSkip;
+}
+
+void ClangTidyMatchFinder::matchAST(ASTContext &Context) {
+  if (hasFilter()) {
+    auto SavedScope = Context.getTraversalScope();
+    auto &MyTopDecls = getTraversalScope();
+    Context.setTraversalScope(MyTopDecls);
+    MatchFinder::matchAST(Context);
+    Context.setTraversalScope(SavedScope);
+  } else {
+    MatchFinder::matchAST(Context);
+  }
+}
+
+template <class T>
+bool isTemplateSpecializationKind(const NamedDecl *D,
+                                  TemplateSpecializationKind Kind) {
+  if (const auto *TD = dyn_cast<T>(D))
+    return TD->getTemplateSpecializationKind() == Kind;
+  return false;
+}
+
+bool isTemplateSpecializationKind(const NamedDecl *D,
+                                  TemplateSpecializationKind Kind) {
+  return isTemplateSpecializationKind<FunctionDecl>(D, Kind) ||
+         isTemplateSpecializationKind<CXXRecordDecl>(D, Kind) ||
+         isTemplateSpecializationKind<VarDecl>(D, Kind);
+}
+
+bool isImplicitTemplateInstantiation(const NamedDecl *D) {
+  return isTemplateSpecializationKind(D, TSK_ImplicitInstantiation);
+}
+
+bool ClangTidyMatchFinder::HandleTopLevelDecl(DeclGroupRef DG) {
+  if (hasFilter()) {
+    for (Decl *D : DG) {
+      if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
+        if (isImplicitTemplateInstantiation(ND))
+          continue;
+
+      // ObjCMethodDecl are not actually top-level decls.
+      if (isa<ObjCMethodDecl>(D))
+        continue;
+
+      if (!Filter->skipDecl(D))
+        TopLevelDecls.push_back(D);
+    }
+  }
+  return true;
+}
+
 std::unique_ptr<clang::ASTConsumer>
 ClangTidyASTConsumerFactory::CreateASTConsumer(
     clang::CompilerInstance &Compiler, StringRef File) {
@@ -416,9 +545,13 @@
         Context.getProfileStorageParams());
     FinderOptions.CheckProfiling.emplace(Profiling->Records);
   }
+  std::shared_ptr<DeclFilter> SharedDeclFilter;
+  if (*Context.getOptions().SkipHeaders)
+    SharedDeclFilter =
+        std::shared_ptr<DeclFilter>(new DeclFilter(Context, *SM));
 
-  std::unique_ptr<ast_matchers::MatchFinder> Finder(
-      new ast_matchers::MatchFinder(std::move(FinderOptions)));
+  std::unique_ptr<ClangTidyMatchFinder> Finder(
+      new ClangTidyMatchFinder(std::move(FinderOptions), SharedDeclFilter));
 
   Preprocessor *PP = &Compiler.getPreprocessor();
   Preprocessor *ModuleExpanderPP = PP;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to