chh updated this revision to Diff 367117.
chh retitled this revision from "[clang-tidy] New feature --skip-headers, part 
1, LocFilter" to "[clang-tidy] New feature --skip-headers, part 1, 
LocationFilter".
chh edited the summary of this revision.
chh added a comment.

Factor out LocationFilter; improve more test cases.


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

https://reviews.llvm.org/D98709

Files:
  clang-tools-extra/clang-tidy/ClangTidy.cpp
  clang-tools-extra/clang-tidy/ClangTidyCheck.h
  clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
  clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
  clang-tools-extra/clang-tidy/ClangTidyModule.cpp
  clang-tools-extra/clang-tidy/ClangTidyModule.h
  clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
  clang-tools-extra/clang-tidy/ClangTidyOptions.h
  clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
  clang-tools-extra/clang-tidy/bugprone/ForwardDeclarationNamespaceCheck.cpp
  clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
  clang-tools-extra/clang-tidy/misc/UnusedUsingDeclsCheck.cpp
  clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
  clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
  
clang-tools-extra/test/clang-tidy/checkers/Inputs/bugprone-forward-declaration-namespace/a.h
  
clang-tools-extra/test/clang-tidy/checkers/Inputs/bugprone-forward-declaration-namespace/b.h
  
clang-tools-extra/test/clang-tidy/checkers/Inputs/modernize-pass-by-value/header.h
  clang-tools-extra/test/clang-tidy/checkers/Inputs/skip-headers/a.h
  clang-tools-extra/test/clang-tidy/checkers/Inputs/skip-headers/b.h
  clang-tools-extra/test/clang-tidy/checkers/Inputs/skip-headers/c.h
  clang-tools-extra/test/clang-tidy/checkers/Inputs/skip-headers/c1.h
  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/Inputs/unused-using-decls.h
  clang-tools-extra/test/clang-tidy/checkers/abseil-no-internal-dependencies.cpp
  
clang-tools-extra/test/clang-tidy/checkers/abseil-upgrade-duration-conversions.cpp
  
clang-tools-extra/test/clang-tidy/checkers/bugprone-forward-declaration-namespace-header.cpp
  
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/cppcoreguidelines-macro-usage-command-line-macros.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/google-upgrade-googletest-case.cpp
  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/misc-unused-using-decls.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-1.cpp
  clang-tools-extra/test/clang-tidy/checkers/skip-headers-2.cpp
  clang-tools-extra/test/clang-tidy/checkers/skip-headers-3.cpp
  clang-tools-extra/test/clang-tidy/checkers/skip-headers-4.cpp
  clang-tools-extra/test/clang-tidy/infrastructure/file-filter-symlinks.cpp
  clang-tools-extra/test/clang-tidy/infrastructure/file-filter.cpp
  clang-tools-extra/test/clang-tidy/infrastructure/line-filter.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
@@ -1202,6 +1202,8 @@
   if (!DeclNode) {
     return true;
   }
+  if (Options.Filter && Options.Filter->skipLocation(DeclNode->getLocation()))
+    return true;
 
   bool ScopedTraversal =
       TraversingASTNodeNotSpelledInSource || DeclNode->isImplicit();
@@ -1232,6 +1234,13 @@
   if (!StmtNode) {
     return true;
   }
+  // When a function call is in the main file or wanted header files,
+  // the call site maybe in the Decl that is not to be skipped.
+  // But the statements of the called function or parameter default expressions
+  // should be skipped. So here we need to call skipLocation here.
+  if (Options.Filter && Options.Filter->skipLocation(StmtNode->getBeginLoc()))
+    return true;
+
   bool ScopedTraversal = TraversingASTNodeNotSpelledInSource ||
                          TraversingASTChildrenNotSpelledInSource;
 
@@ -1454,5 +1463,7 @@
   return llvm::None;
 }
 
+MatchFinder::MatchFinderOptions::LocFilter::~LocFilter() = default;
+
 } // end namespace ast_matchers
 } // end namespace clang
Index: clang/include/clang/ASTMatchers/ASTMatchFinder.h
===================================================================
--- clang/include/clang/ASTMatchers/ASTMatchFinder.h
+++ clang/include/clang/ASTMatchers/ASTMatchFinder.h
@@ -133,11 +133,18 @@
       /// Per bucket timing information.
       llvm::StringMap<llvm::TimeRecord> &Records;
     };
+    struct LocFilter {
+      virtual bool skipLocation(SourceLocation) const = 0;
+      virtual ~LocFilter();
+    };
 
     /// Enables per-check timers.
     ///
     /// It prints a report after match.
     llvm::Optional<Profiling> CheckProfiling;
+
+    /// Check if MatchASTVisitor should skip node at a location.
+    std::unique_ptr<LocFilter> Filter;
   };
 
   MatchFinder(MatchFinderOptions Options = MatchFinderOptions());
Index: clang-tools-extra/test/clang-tidy/infrastructure/line-filter.cpp
===================================================================
--- clang-tools-extra/test/clang-tidy/infrastructure/line-filter.cpp
+++ clang-tools-extra/test/clang-tidy/infrastructure/line-filter.cpp
@@ -1,4 +1,4 @@
-// RUN: clang-tidy -checks='-*,google-explicit-constructor' -line-filter='[{"name":"line-filter.cpp","lines":[[18,18],[22,22]]},{"name":"header1.h","lines":[[1,2]]},{"name":"header2.h"},{"name":"header3.h"}]' -header-filter='header[12]\.h$' %s -- -I %S/Inputs/line-filter 2>&1 | FileCheck %s
+// RUN: clang-tidy --skip-headers=0 -checks='-*,google-explicit-constructor' -line-filter='[{"name":"line-filter.cpp","lines":[[18,18],[22,22]]},{"name":"header1.h","lines":[[1,2]]},{"name":"header2.h"},{"name":"header3.h"}]' -header-filter='header[12]\.h$' %s -- -I %S/Inputs/line-filter 2>&1 | FileCheck %s
 
 #include "header1.h"
 // CHECK-NOT: header1.h:{{.*}} warning
Index: clang-tools-extra/test/clang-tidy/infrastructure/file-filter.cpp
===================================================================
--- clang-tools-extra/test/clang-tidy/infrastructure/file-filter.cpp
+++ clang-tools-extra/test/clang-tidy/infrastructure/file-filter.cpp
@@ -1,14 +1,14 @@
-// RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='' %s -- -I %S/Inputs/file-filter -isystem %S/Inputs/file-filter/system 2>&1 | FileCheck %s
-// RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='' -quiet %s -- -I %S/Inputs/file-filter -isystem %S/Inputs/file-filter/system 2>&1 | FileCheck --check-prefix=CHECK-QUIET %s
-// RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='.*' %s -- -I %S/Inputs/file-filter -isystem %S/Inputs/file-filter/system 2>&1 | FileCheck --check-prefix=CHECK2 %s
-// RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='.*' -quiet %s -- -I %S/Inputs/file-filter -isystem %S/Inputs/file-filter/system 2>&1 | FileCheck --check-prefix=CHECK2-QUIET %s
-// RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='header2\.h' %s -- -I %S/Inputs/file-filter -isystem %S/Inputs/file-filter/system 2>&1 | FileCheck --check-prefix=CHECK3 %s
-// RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='header2\.h' -quiet %s -- -I %S/Inputs/file-filter -isystem %S/Inputs/file-filter/system 2>&1 | FileCheck --check-prefix=CHECK3-QUIET %s
+// RUN: clang-tidy --skip-headers=0 -checks='-*,google-explicit-constructor' -header-filter='' %s -- -I %S/Inputs/file-filter -isystem %S/Inputs/file-filter/system 2>&1 | FileCheck %s
+// RUN: clang-tidy --skip-headers=0 -checks='-*,google-explicit-constructor' -header-filter='' -quiet %s -- -I %S/Inputs/file-filter -isystem %S/Inputs/file-filter/system 2>&1 | FileCheck --check-prefix=CHECK-QUIET %s
+// RUN: clang-tidy --skip-headers=0 -checks='-*,google-explicit-constructor' -header-filter='.*' %s -- -I %S/Inputs/file-filter -isystem %S/Inputs/file-filter/system 2>&1 | FileCheck --check-prefix=CHECK2 %s
+// RUN: clang-tidy --skip-headers=0 -checks='-*,google-explicit-constructor' -header-filter='.*' -quiet %s -- -I %S/Inputs/file-filter -isystem %S/Inputs/file-filter/system 2>&1 | FileCheck --check-prefix=CHECK2-QUIET %s
+// RUN: clang-tidy --skip-headers=0 -checks='-*,google-explicit-constructor' -header-filter='header2\.h' %s -- -I %S/Inputs/file-filter -isystem %S/Inputs/file-filter/system 2>&1 | FileCheck --check-prefix=CHECK3 %s
+// RUN: clang-tidy --skip-headers=0 -checks='-*,google-explicit-constructor' -header-filter='header2\.h' -quiet %s -- -I %S/Inputs/file-filter -isystem %S/Inputs/file-filter/system 2>&1 | FileCheck --check-prefix=CHECK3-QUIET %s
 // FIXME: "-I %S/Inputs/file-filter/system/.." must be redundant.
 //       On Win32, file-filter/system\system-header1.h precedes
 //       file-filter\header*.h due to code order between '/' and '\\'.
-// RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='.*' -system-headers %s -- -I %S/Inputs/file-filter/system/.. -isystem %S/Inputs/file-filter/system 2>&1 | FileCheck --check-prefix=CHECK4 %s
-// RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='.*' -system-headers -quiet %s -- -I %S/Inputs/file-filter/system/.. -isystem %S/Inputs/file-filter/system 2>&1 | FileCheck --check-prefix=CHECK4-QUIET %s
+// RUN: clang-tidy --skip-headers=0 -checks='-*,google-explicit-constructor' -header-filter='.*' -system-headers %s -- -I %S/Inputs/file-filter/system/.. -isystem %S/Inputs/file-filter/system 2>&1 | FileCheck --check-prefix=CHECK4 %s
+// RUN: clang-tidy --skip-headers=0 -checks='-*,google-explicit-constructor' -header-filter='.*' -system-headers -quiet %s -- -I %S/Inputs/file-filter/system/.. -isystem %S/Inputs/file-filter/system 2>&1 | FileCheck --check-prefix=CHECK4-QUIET %s
 
 #include "header1.h"
 // CHECK-NOT: warning:
Index: clang-tools-extra/test/clang-tidy/infrastructure/file-filter-symlinks.cpp
===================================================================
--- clang-tools-extra/test/clang-tidy/infrastructure/file-filter-symlinks.cpp
+++ clang-tools-extra/test/clang-tidy/infrastructure/file-filter-symlinks.cpp
@@ -5,12 +5,12 @@
 // RUN: echo 'class A { A(int); };' > %t/dir1/header.h
 // RUN: ln -s %t/dir1/header.h %t/dir1/header_alias.h
 //
-// RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='dir1/dir2/\.\./header_alias\.h' %s -- -I %t 2>&1 | FileCheck --check-prefix=CHECK_HEADER_ALIAS %s
-// RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='dir1/dir2/\.\./header_alias\.h' -quiet %s -- -I %t 2>&1 | FileCheck --check-prefix=CHECK_HEADER_ALIAS %s
-// RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='header_alias\.h' %s -- -I %t 2>&1 | FileCheck --check-prefix=CHECK_HEADER_ALIAS %s
-// RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='header_alias\.h' -quiet %s -- -I %t 2>&1 | FileCheck --check-prefix=CHECK_HEADER_ALIAS %s
-// RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='header\.h' %s -- -I %t 2>&1 | FileCheck --check-prefix=CHECK_HEADER %s
-// RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='header\.h' -quiet %s -- -I %t 2>&1 | FileCheck --check-prefix=CHECK_HEADER %s
+// RUN: clang-tidy --skip-headers=0 -checks='-*,google-explicit-constructor' -header-filter='dir1/dir2/\.\./header_alias\.h' %s -- -I %t 2>&1 | FileCheck --check-prefix=CHECK_HEADER_ALIAS %s
+// RUN: clang-tidy --skip-headers=0 -checks='-*,google-explicit-constructor' -header-filter='dir1/dir2/\.\./header_alias\.h' -quiet %s -- -I %t 2>&1 | FileCheck --check-prefix=CHECK_HEADER_ALIAS %s
+// RUN: clang-tidy --skip-headers=0 -checks='-*,google-explicit-constructor' -header-filter='header_alias\.h' %s -- -I %t 2>&1 | FileCheck --check-prefix=CHECK_HEADER_ALIAS %s
+// RUN: clang-tidy --skip-headers=0 -checks='-*,google-explicit-constructor' -header-filter='header_alias\.h' -quiet %s -- -I %t 2>&1 | FileCheck --check-prefix=CHECK_HEADER_ALIAS %s
+// RUN: clang-tidy --skip-headers=0 -checks='-*,google-explicit-constructor' -header-filter='header\.h' %s -- -I %t 2>&1 | FileCheck --check-prefix=CHECK_HEADER %s
+// RUN: clang-tidy --skip-headers=0 -checks='-*,google-explicit-constructor' -header-filter='header\.h' -quiet %s -- -I %t 2>&1 | FileCheck --check-prefix=CHECK_HEADER %s
 
 // Check that `-header-filter` operates on the same file paths as paths in
 // diagnostics printed by ClangTidy.
Index: clang-tools-extra/test/clang-tidy/checkers/skip-headers-4.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/skip-headers-4.cpp
@@ -0,0 +1,40 @@
+// When the statement of a template function call does not have a
+// "valid" source location and its default argument value cast expression
+// is in an included header file, the warning on the expression should
+// be suppressed by --skip-headers.
+//
+// RUN: clang-tidy %s --skip-headers=0 \
+// RUN: -checks='-*,modernize-use-nullptr' -- \
+// RUN: | FileCheck %s -check-prefixes MAIN,NOWARNC
+//
+// RUN: clang-tidy %s --skip-headers --show-all-warnings \
+// RUN: -checks='-*,modernize-use-nullptr' -- \
+// RUN: | FileCheck %s -check-prefixes MAIN,NOWARNC
+//
+// RUN: clang-tidy %s --skip-headers=0 \
+// RUN: -checks='-*,modernize-use-nullptr' -header-filter=c.h -- \
+// RUN: | FileCheck %s -check-prefixes MAIN,WARNC
+//
+// RUN: clang-tidy %s --skip-headers --show-all-warnings \
+// RUN: -checks='-*,modernize-use-nullptr' -header-filter=c.h -- \
+// RUN: | FileCheck %s -check-prefixes MAIN,WARNC
+
+#include "Inputs/skip-headers/c.h"
+// WARNC: c.h:5:34: warning: use nullptr [modernize-use-nullptr]
+// NOWARNC-NOT: c.h:5:34: warning: use nullptr [modernize-use-nullptr]
+// NOWARNC-NOT: c.h:
+
+template <class T>
+class D {
+public:
+  template <class R>
+  explicit D(const R r, int *x = 0) : p(x) {}
+  // MAIN: :[[@LINE-1]]:34: warning: use nullptr [modernize-use-nullptr]
+private:
+  int *p;
+};
+
+C<int> x = C<int>(2);
+D<int> y = D<int>(4);
+
+// MAIN-NOT: warning:
Index: clang-tools-extra/test/clang-tidy/checkers/skip-headers-3.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/skip-headers-3.cpp
@@ -0,0 +1,30 @@
+// Test --skip-headers, which should skip statements and expressions
+// in a called function of header files even if the calling function
+// is in the main file.
+//
+// RUN: clang-tidy %s --skip-headers=0 --show-all-warnings \
+// RUN: -checks='-*,cert-dcl16-c' \
+// RUN: | FileCheck %s -check-prefixes WARNC,MAIN
+//
+// RUN: clang-tidy %s --skip-headers --show-all-warnings \
+// RUN: -checks='-*,cert-dcl16-c' --header-filter=c1.h \
+// RUN: | FileCheck %s -check-prefixes MAIN,WARNC
+//
+// RUN: clang-tidy %s --skip-headers --show-all-warnings \
+// RUN: -checks='-*,cert-dcl16-c' \
+// RUN: | FileCheck %s -check-prefixes MAIN,NOWARNC
+
+#include "Inputs/skip-headers/c1.h"
+// WARNC: c1.h:5:27: warning: integer literal has suffix 'll', which is not uppercase [cert-dcl16-c]
+// WARNC: c1.h:6:20: warning: integer literal has suffix 'll', which is not uppercase [cert-dcl16-c]
+// NOWARNC-NOT: c1.h:5:27: warning: integer literal has suffix 'll', which is not uppercase [cert-dcl16-c]
+// NOWARNC-NOT: c1.h:6:20: warning: integer literal has suffix 'll', which is not uppercase [cert-dcl16-c]
+
+void foo(int x = 3ll, C1 *p = nullptr) {
+  // MAIN: skip-headers-3.cpp:[[@LINE-1]]:18: warning: integer literal has suffix 'll', which is not uppercase [cert-dcl16-c]
+  C1::foo1();
+  p->foo2();
+  p->foo3(x);
+}
+
+// MAIN-NOT: warning: integer literal has suffix 'll', which is not uppercase [cert-dcl16-c]
Index: clang-tools-extra/test/clang-tidy/checkers/skip-headers-2.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/skip-headers-2.cpp
@@ -0,0 +1,39 @@
+// Test --skip-headers, --show-all-warnings, and --header-filter
+// with nested Decls. Users should be able to select exactly
+// which .h file to check for warnings.
+// Here a.h includes/uses b.h. Maintainers of a.h wants to check/see
+// warnings in a.h but not b.h. So they use --header-filer=a.h --skip-headers.
+//
+// RUN: clang-tidy %s --skip-headers=0 --show-all-warnings \
+// RUN: -checks='-*,readability-convert-member-functions-to-static' -- \
+// RUN: | FileCheck %s -check-prefixes WARNA,WARNB,WARNMAIN
+//
+// RUN: clang-tidy %s --skip-headers=1 --show-all-warnings \
+// RUN: -checks='-*,readability-convert-member-functions-to-static' -- \
+// RUN: | FileCheck %s -check-prefixes WARNMAIN,NOWARNA,NOWARNB
+//
+// RUN: clang-tidy %s --skip-headers=1 --show-all-warnings --header-filter=a.h \
+// RUN: -checks='-*,readability-convert-member-functions-to-static' -- \
+// RUN: | FileCheck %s -check-prefixes WARNMAIN,WARNA,NOWARNB
+//
+// RUN: clang-tidy %s --skip-headers=1 --show-all-warnings --header-filter=.* \
+// RUN: -checks='-*,readability-convert-member-functions-to-static' -- \
+// RUN: | FileCheck %s -check-prefixes WARNMAIN,WARNA,WARNB
+//
+// Current limitation of --skip-haders: b.h is skipped if a.h is skipped.
+// RUN: clang-tidy %s --skip-headers=1 --show-all-warnings --header-filter=b.h \
+// RUN: -checks='-*,readability-convert-member-functions-to-static' -- \
+// RUN: | FileCheck %s -check-prefixes WARNMAIN,NOWARNA,NOWARNB
+
+#include "Inputs/skip-headers/a.h"
+
+// WARNA: warning: method 'fooA' can be made static
+// NOWARNA-NOT: warning: method 'fooA' can be made static
+
+// WARNB: warning: method 'fooB' can be made static
+// NOWARNB-NOT: warning: method 'fooB' can be made static
+
+class C {
+  void foo(int x) { x = 3; };
+  // WARNMAIN: warning: method 'foo' can be made static
+};
Index: clang-tools-extra/test/clang-tidy/checkers/skip-headers-1.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/skip-headers-1.cpp
@@ -0,0 +1,60 @@
+// Test --skip-headers, --show-all-warnings, and --header-filter.
+//
+// Default shows no warning in .h files, with hint to use --header-filter
+// RUN: clang-tidy %s -checks='*' --skip-headers=0 -- \
+// RUN: 2>&1 | FileCheck %s -check-prefixes COUNTER,NOHEADER,MAIN,HINT
+//
+// --skip-headers skips all included files warnings; without hint
+// RUN: clang-tidy %s -checks='*' --skip-headers -- \
+// RUN: 2>&1 | FileCheck %s -check-prefixes COUNTER,NOHEADER,MAIN,NOHINT
+//
+// --show-all-warnings reports all warnings, even without --header-filters
+// RUN: clang-tidy %s -checks='*' --show-all-warnings --skip-headers=0 -- \
+// RUN: 2>&1 | FileCheck %s -check-prefixes COUNTER,HEADER,MAIN,NOHINT
+//
+// --header-filter='.*' is like --show-all-warnings
+// RUN: clang-tidy %s -checks='*' --header-filter='.*' --skip-headers=0 -- \
+// RUN: 2>&1 | FileCheck %s -check-prefixes COUNTER,HEADER,MAIN,NOHINT
+//
+// With --show-all-warnings and --skip-headers,
+// 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 COUNTER,NOHEADER,MAIN,NOHINT
+//
+// --header-filter='header1.h' shows only warnings in header1.h
+// RUN: clang-tidy %s -checks='*' --header-filter='header1.h' --skip-headers=0 -- \
+// RUN: 2>&1 | FileCheck %s -check-prefixes COUNTER,H1,MAIN,HINT
+//
+// RUN: clang-tidy %s -checks='*' --header-filter='header1.h' --skip-headers -- \
+// RUN: 2>&1 | FileCheck %s -check-prefixes COUNTER,H1,MAIN,NOHINT
+//
+// --header-filter='header2.h' shows only warnings in header2.h
+// RUN: clang-tidy %s -checks='*' --header-filter='header2.h' --skip-headers=0 -- \
+// RUN: 2>&1 | FileCheck %s -check-prefixes COUNTER,H2,MAIN,HINT
+//
+// RUN: clang-tidy %s -checks='*' --header-filter='header2.h' --skip-headers -- \
+// RUN: 2>&1 | FileCheck %s -check-prefixes COUNTER,H2,MAIN,NOHINT
+
+// All options have warning count reported:
+// COUNTER: {{[0-9]+}} warnings generated.
+
+// Not all PPCallback checks have supported skip-header yet.
+// So, some headers still have warnings.
+#include "Inputs/skip-headers/my_header1.h"
+// H1: my_header1.h:1:1: warning: header is missing header guard
+// HEADER: my_header1.h:1:1: warning: header is missing header guard
+// H2-NOT: my_header1.h
+// NOHEADER-NOT: my_header1.h FIXME
+
+// H2: my_header2.h:1:1: warning: header is missing header guard
+// HEADER: my_header2.h:1:1: warning: header is missing header guard
+// H1-NOT: my_header2.h
+// NOHEADER-NOT: my_header2.h FIXME
+
+int xyz = 135;
+// MAIN: skip-headers-1.cpp:{{[0-9]+}}:{{[0-9]+}}: warning:
+
+// HINT: Use -header-filter={{.*}} to display errors{{.*}}
+// NOHINT-NOT: Use -header-filter= FIXME
+// Not all PPCallback checks have supported skip-header yet.
+// So there are still "hint" at the end of these tests.
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=0
+// 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=0
+// 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 -- --skip-headers=0 \
+// 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 -- --skip-headers=0 \
+// 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,5 +1,9 @@
 // RUN: %check_clang_tidy %s portability-restrict-system-includes %t \
-// RUN:     -- -config="{CheckOptions: [{key: portability-restrict-system-includes.Includes, value: '-*,stddef.h'}]}" \
+// RUN:     -- -config="{CheckOptions: [{key: portability-restrict-system-includes.Includes, value: '-*,stddef.h'}]}" --skip-headers=0 \
+// 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,5 +1,9 @@
 // RUN: %check_clang_tidy %s portability-restrict-system-includes %t \
-// RUN:     -- -config="{CheckOptions: [{key: portability-restrict-system-includes.Includes, value: '*,-stddef.h'}]}" \
+// RUN:     -- -config="{CheckOptions: [{key: portability-restrict-system-includes.Includes, value: '*,-stddef.h'}]}" --skip-headers=0 \
+// 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,82 @@
+// Reuse some tests from modernize-pass-by-value.cpp,
+// to show that header file warnings can be skipped by skip-headers,
+// but fix to header files is already suppressed by -header-filter.
+//
+// (1) -fix --skip-headers=0, suppress warning and fix in .h file
+//          showmain,noheader fixmain, nofixheader
+// (2) -fix --skip-headers=1, skip warning and fix in .h file
+//          showmain,skipheader fixmain, nofixheader
+// (3) -fix --skip-headers=0 -header-filter=.* , show and fix warnings in .h file
+//          showmain,showheader fixmain, fixheader
+// (4) -fix --skip-headers=1 -header-filter=.* , show and fix warnings in .h file
+//          showmain,showheader fixmain, fixheader
+//
+// (1)
 // 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: FileCheck -input-file=%T/pass-by-value-header.h %s -check-prefix=CHECK-FIXES
-// FIXME: Make the test work in all language modes.
+// RUN: cp %S/modernize-pass-by-value-header.cpp %T/pass-by-value-header.cpp
+// RUN: clang-tidy %T/pass-by-value-header.cpp -checks='-*,modernize-pass-by-value' \
+// RUN: --skip-headers=0 -fix -- -std=c++11 2>&1 \
+// RUN: | FileCheck %s -check-prefixes=SHOWMAIN,NOHEADER
+// RUN: FileCheck -input-file=%T/pass-by-value-header.h %s -check-prefix=NOFIXHEADER
+// RUN: FileCheck -input-file=%T/pass-by-value-header.cpp %s -check-prefix=FIXMAIN
+//
+// (2)
+// RUN: cp %S/Inputs/modernize-pass-by-value/header.h %T/pass-by-value-header.h
+// RUN: cp %S/modernize-pass-by-value-header.cpp %T/pass-by-value-header.cpp
+// RUN: clang-tidy %T/pass-by-value-header.cpp -checks='-*,modernize-pass-by-value' \
+// RUN: --skip-headers -fix -- -std=c++11 2>&1 \
+// RUN: | FileCheck %s -check-prefixes=SHOWMAIN,SKIPHEADER
+// RUN: FileCheck -input-file=%T/pass-by-value-header.h %s -check-prefix=NOFIXHEADER
+// RUN: FileCheck -input-file=%T/pass-by-value-header.cpp %s -check-prefix=FIXMAIN
+//
+// (3)
+// RUN: cp %S/Inputs/modernize-pass-by-value/header.h %T/pass-by-value-header.h
+// RUN: cp %S/modernize-pass-by-value-header.cpp %T/pass-by-value-header.cpp
+// RUN: clang-tidy %T/pass-by-value-header.cpp -checks='-*,modernize-pass-by-value' \
+// RUN: --header-filter=.* --skip-headers=0 -fix -- -std=c++11 2>&1 \
+// RUN: | FileCheck %s -check-prefixes=SHOWMAIN,SHOWHEADER
+// RUN: FileCheck -input-file=%T/pass-by-value-header.h %s -check-prefix=FIXHEADER
+// RUN: FileCheck -input-file=%T/pass-by-value-header.cpp %s -check-prefix=FIXMAIN
+//
+// (4)
+// RUN: cp %S/Inputs/modernize-pass-by-value/header.h %T/pass-by-value-header.h
+// RUN: cp %S/modernize-pass-by-value-header.cpp %T/pass-by-value-header.cpp
+// RUN: clang-tidy %T/pass-by-value-header.cpp -checks='-*,modernize-pass-by-value' \
+// RUN: --header-filter=.* --skip-headers -fix -- -std=c++11 2>&1 \
+// RUN: | FileCheck %s -check-prefixes=SHOWMAIN,SHOWHEADER
+// RUN: FileCheck -input-file=%T/pass-by-value-header.h %s -check-prefix=FIXHEADER
+// RUN: FileCheck -input-file=%T/pass-by-value-header.cpp %s -check-prefix=FIXMAIN
 
 #include "pass-by-value-header.h"
-// CHECK-MESSAGES: :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)) {}
+// FIXHEADER: #include <utility>
+// FIXHEADER: struct A
+// FIXHEADER: A(ThreadId tid) : threadid(std::move(tid)) {}
+// NOFIXHEADER-NOT: #include <utility>
+// NOFIXHEADER: struct A
+// NOFIXHEADER: A(const ThreadId &tid) : threadid(tid) {}
+// NOFIXHEADER-NOT: A(ThreadId tid) : threadid(std::move(tid)) {}
+
+// Test that both declaration and definition are updated.
+struct D {
+  D(const Movable &M);
+  // FIXMAIN: D(Movable M);
+  Movable M;
+};
+D::D(const Movable &M) : M(M) {}
+// SHOWMAIN: :[[@LINE-1]]:6: warning: pass by value and use std::move
+// FIXMAIN: D::D(Movable M) : M(std::move(M)) {}
+
+// bug? header file warnings shown after main file warnings
+// SHOWHEADER:     :8:5: warning: pass by value and use std::move [modernize-pass-by-value]
+// NOHEADER-NOT:   :8:5: warning: pass by value and use std::move [modernize-pass-by-value]
+// SKIPHEADER-NOT: :8:5: warning: pass by value and use std::move [modernize-pass-by-value]
+
+// no more warning or error
+// SHOWMAIN-NOT:   {{warning|error}}:
+// SHOWHEADER-NOT: {{warning|error}}:
+// NOHEADER-NOT:   {{warning|error}}:
+// SKIPHEADER-NOT: {{warning|error}}:
+//
+// NOHEADER: Suppressed {{.*}} warnings
+// SKIPHEADER-NOT: Suppressed {{.*}} warnings
+// SHOWHEADER-NOT: Suppressed {{.*}} warnings
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=0 -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=0 -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-unused-using-decls.cpp
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/misc-unused-using-decls.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/misc-unused-using-decls.cpp
@@ -1,4 +1,13 @@
-// RUN: %check_clang_tidy %s misc-unused-using-decls %t -- --fix-notes -- -fno-delayed-template-parsing -isystem %S/Inputs/
+// Setup header directory
+// RUN: rm -rf %theaders
+// RUN: mkdir %theaders
+// RUN: cp -R %S/Inputs/unused-using-decls.h %theaders
+
+// RUN: %check_clang_tidy %s misc-unused-using-decls %t -- --skip-headers=0 \
+// RUN:   --fix-notes -- -fno-delayed-template-parsing -I%theaders
+//
+// RUN: %check_clang_tidy %s misc-unused-using-decls %t -- --skip-headers \
+// RUN:   --fix-notes -- -fno-delayed-template-parsing -I%theaders
 
 // ----- Definitions -----
 template <typename T> class vector {};
@@ -66,7 +75,24 @@
 
 }  // namespace n
 
+namespace Q1 {
+class QC1;
+}
+using Q1::QC1;
+// Do not give warning about unused QC1!  It is used in .h file.
+// CHECK-MESSAGES-NOT: warning: using decl 'QC1' is unused
+
 #include "unused-using-decls.h"
+// FIXME: here we should have a warning on unused using decl 'QC2'
+
+namespace Q3 {
+class QC3;
+}
+using Q3::QC3; // QC3 should be removed
+// CHECK-MESSAGES: warning: using decl 'QC3' is unused
+// CHECK-MESSAGES: note: remove the using
+// CHECK-FIXES: {{^}}// QC3 should be removed
+
 namespace ns {
 template <typename T>
 class AA {
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=0
+// 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,5 +1,9 @@
 // RUN: %check_clang_tidy %s llvmlibc-restrict-system-libc-headers %t \
-// RUN:   -- -- -isystem %S/Inputs/llvmlibc/system \
+// RUN:   -- --skip-headers=0 -- -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>
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=0
+// 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=0
+// 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=0 -- -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-upgrade-googletest-case.cpp
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/google-upgrade-googletest-case.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/google-upgrade-googletest-case.cpp
@@ -1,5 +1,7 @@
-// RUN: %check_clang_tidy %s google-upgrade-googletest-case %t -- -- -I%S/Inputs
-// RUN: %check_clang_tidy -check-suffix=NOSUITE %s google-upgrade-googletest-case %t -- -- -DNOSUITE -I%S/Inputs/gtest/nosuite
+// RUN: %check_clang_tidy %s google-upgrade-googletest-case %t -- --skip-headers=0 -- -I%S/Inputs
+// RUN: %check_clang_tidy -check-suffix=NOSUITE %s google-upgrade-googletest-case %t -- --skip-headers=0 -- -DNOSUITE -I%S/Inputs/gtest/nosuite
+// RUN: %check_clang_tidy %s google-upgrade-googletest-case %t -- --skip-headers -- -I%S/Inputs
+// RUN: %check_clang_tidy -check-suffix=NOSUITE %s google-upgrade-googletest-case %t -- --skip-headers -- -DNOSUITE -I%S/Inputs/gtest/nosuite
 
 #include "gtest/gtest.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=0 -- -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 --skip-headers=0 -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 --skip-headers=0 -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 --skip-headers=0 --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-macro-usage-command-line-macros.cpp
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-macro-usage-command-line-macros.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-macro-usage-command-line-macros.cpp
@@ -1,6 +1,11 @@
-// RUN: %check_clang_tidy -check-suffixes=NORMAL %s cppcoreguidelines-macro-usage %t -- -- -D_ZZZ_IM_A_MACRO
-// RUN: %check_clang_tidy -check-suffixes=NORMAL %s cppcoreguidelines-macro-usage %t -- -config='{CheckOptions: [{key: cppcoreguidelines-macro-usage.IgnoreCommandLineMacros, value: true}]}' -- -D_ZZZ_IM_A_MACRO
-// RUN: %check_clang_tidy -check-suffixes=NORMAL,CL %s cppcoreguidelines-macro-usage %t -- -config='{CheckOptions: [{key: cppcoreguidelines-macro-usage.IgnoreCommandLineMacros, value: false}]}' -- -D_ZZZ_IM_A_MACRO
+// RUN: %check_clang_tidy -check-suffixes=NORMAL %s cppcoreguidelines-macro-usage %t -- --skip-headers=0 -- -D_ZZZ_IM_A_MACRO
+// RUN: %check_clang_tidy -check-suffixes=NORMAL %s cppcoreguidelines-macro-usage %t -- --skip-headers=0 -config='{CheckOptions: [{key: cppcoreguidelines-macro-usage.IgnoreCommandLineMacros, value: true}]}' -- -D_ZZZ_IM_A_MACRO
+// RUN: %check_clang_tidy -check-suffixes=NORMAL,CL %s cppcoreguidelines-macro-usage %t -- --skip-headers=0 -config='{CheckOptions: [{key: cppcoreguidelines-macro-usage.IgnoreCommandLineMacros, value: false}]}' -- -D_ZZZ_IM_A_MACRO
+//
+// Should work with --skip-header too.
+// RUN: %check_clang_tidy -check-suffixes=NORMAL %s cppcoreguidelines-macro-usage %t -- --skip-headers -- -D_ZZZ_IM_A_MACRO
+// RUN: %check_clang_tidy -check-suffixes=NORMAL %s cppcoreguidelines-macro-usage %t -- --skip-headers -config='{CheckOptions: [{key: cppcoreguidelines-macro-usage.IgnoreCommandLineMacros, value: true}]}' -- -D_ZZZ_IM_A_MACRO
+// RUN: %check_clang_tidy -check-suffixes=NORMAL,CL %s cppcoreguidelines-macro-usage %t -- --skip-headers -config='{CheckOptions: [{key: cppcoreguidelines-macro-usage.IgnoreCommandLineMacros, value: false}]}' -- -D_ZZZ_IM_A_MACRO
 
 // CHECK-MESSAGES-CL: warning: macro '_ZZZ_IM_A_MACRO' used to declare a constant; consider using a 'constexpr' constant
 
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=0
+// 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=0 -- -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,4 +1,7 @@
-// RUN: %check_clang_tidy %s bugprone-reserved-identifier %t -- -- \
+// RUN: %check_clang_tidy %s bugprone-reserved-identifier %t -- --skip-headers=0 -- \
+// 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
 
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=0
+// 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/bugprone-forward-declaration-namespace-header.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/bugprone-forward-declaration-namespace-header.cpp
@@ -0,0 +1,174 @@
+// Same output with skip-headers=0, skip-headers=1, or skip-headers
+//
+// With --skip-headers=0 and no --header-filter, there should be no warning
+// shown for a.h or b.h. But there seems to be a bug and we are seeing the A1 warnings.
+// RUN: %check_clang_tidy -check-suffixes=ALL,A1 %s bugprone-forward-declaration-namespace %t -- --skip-headers=0 \
+// RUN:   -- -I%S/Inputs/bugprone-forward-declaration-namespace
+// RUN: %check_clang_tidy -check-suffixes=ALL %s bugprone-forward-declaration-namespace %t -- --skip-headers=1 \
+// RUN:   -- -I%S/Inputs/bugprone-forward-declaration-namespace
+// RUN: %check_clang_tidy -check-suffixes=ALL %s bugprone-forward-declaration-namespace %t -- --skip-headers \
+// RUN:   -- -I%S/Inputs/bugprone-forward-declaration-namespace
+//
+// Same output with header-filter=b.h because there is no warning on b.h
+// RUN: %check_clang_tidy -check-suffixes=ALL %s bugprone-forward-declaration-namespace %t -- --skip-headers \
+// RUN:   --header-filter=b.h -- -I%S/Inputs/bugprone-forward-declaration-namespace
+//
+// With --header-filter, we should see all warnings from a.h.
+// RUN: %check_clang_tidy -check-suffixes=ALL,A,A1 %s bugprone-forward-declaration-namespace %t -- --skip-headers=0 \
+// RUN:   --header-filter=.* -- -I%S/Inputs/bugprone-forward-declaration-namespace
+// RUN: %check_clang_tidy -check-suffixes=ALL,A,A1 %s bugprone-forward-declaration-namespace %t -- --skip-headers \
+// RUN:   --header-filter=.* -- -I%S/Inputs/bugprone-forward-declaration-namespace
+// RUN: %check_clang_tidy -check-suffixes=ALL,A,A1 %s bugprone-forward-declaration-namespace %t -- --skip-headers=0 \
+// RUN:   --header-filter=a.h -- -I%S/Inputs/bugprone-forward-declaration-namespace
+// RUN: %check_clang_tidy -check-suffixes=ALL,A,A1 %s bugprone-forward-declaration-namespace %t -- --skip-headers \
+// RUN:   --header-filter=a.h -- -I%S/Inputs/bugprone-forward-declaration-namespace
+
+#include "a.h"
+
+class T_A;
+
+class T_A {
+  int x;
+};
+
+class NESTED;
+// CHECK-NOTES-ALL: :[[@LINE-1]]:7: warning: no definition found for 'NESTED', but a definition with the same name 'NESTED' found in another namespace '(anonymous namespace)::nq::(anonymous)'
+// CHECK-NOTES-ALL: note: a definition of 'NESTED' is found here
+
+namespace {
+namespace nq {
+namespace {
+class NESTED {};
+} // namespace
+} // namespace nq
+} // namespace
+
+namespace na {
+class T_B;
+// CHECK-NOTES-ALL: :[[@LINE-1]]:7: warning: declaration 'T_B' is never referenced, but a declaration with the same name found in another namespace 'nb'
+// CHECK-NOTES-ALL: note: a declaration of 'T_B' is found here
+// CHECK-NOTES-ALL: :[[@LINE-3]]:7: warning: no definition found for 'T_B', but a definition with the same name 'T_B' found in another namespace 'nb'
+// CHECK-NOTES-ALL: note: a definition of 'T_B' is found here
+} // namespace na
+
+#include "b.h"
+
+namespace na {
+class T_B;
+// CHECK-NOTES-ALL: :[[@LINE-1]]:7: warning: declaration 'T_B' is never referenced, but a declaration with the same name found in another namespace 'nb'
+// CHECK-NOTES-ALL: note: a declaration of 'T_B' is found here
+// CHECK-NOTES-ALL: :[[@LINE-3]]:7: warning: no definition found for 'T_B', but a definition with the same name 'T_B' found in another namespace 'nb'
+// CHECK-NOTES-ALL: note: a definition of 'T_B' is found here
+} // namespace na
+
+// A simple forward declaration. Although it is never used, but no declaration
+// with the same name is found in other namespace.
+class OUTSIDER;
+
+namespace na {
+// This class is referenced declaration, we don't generate warning.
+class OUTSIDER_1;
+} // namespace na
+
+void f(na::OUTSIDER_1);
+
+namespace nc {
+// This class is referenced as friend in OOP.
+class OUTSIDER_1;
+
+class OOP {
+  friend struct OUTSIDER_1;
+};
+} // namespace nc
+
+namespace nd {
+class OUTSIDER_1;
+void f(OUTSIDER_1 *);
+} // namespace nd
+
+namespace nb {
+class OUTSIDER_1;
+// CHECK-NOTES-ALL: :[[@LINE-1]]:7: warning: declaration 'OUTSIDER_1' is never referenced, but a declaration with the same name found in another namespace 'na'
+// CHECK-NOTES-ALL: note: a declaration of 'OUTSIDER_1' is found here
+} // namespace nb
+
+namespace na {
+template <typename T>
+class T_C;
+}
+
+namespace nb {
+// FIXME: this is an error, but we don't consider template class declaration
+// now.
+template <typename T>
+class T_C;
+} // namespace nb
+
+namespace na {
+template <typename T>
+class T_C {
+  int x;
+};
+} // namespace na
+
+namespace na {
+
+template <typename T>
+class T_TEMP {
+  template <typename _Tp1>
+  struct rebind { typedef T_TEMP<_Tp1> other; };
+};
+
+// We ignore class template specialization.
+template class T_TEMP<char>;
+} // namespace na
+
+namespace nb {
+
+template <typename T>
+class T_TEMP_1 {
+  template <typename _Tp1>
+  struct rebind { typedef T_TEMP_1<_Tp1> other; };
+};
+
+// We ignore class template specialization.
+extern template class T_TEMP_1<char>;
+} // namespace nb
+
+namespace nd {
+class D;
+// CHECK-NOTES-ALL: :[[@LINE-1]]:7: warning: declaration 'D' is never referenced, but a declaration with the same name found in another namespace 'nd::ne'
+// CHECK-NOTES-ALL: note: a declaration of 'D' is found here
+} // namespace nd
+
+namespace nd {
+namespace ne {
+class D;
+}
+} // namespace nd
+
+int f(nd::ne::D &d);
+
+// This should be ignored by the check.
+template <typename... Args>
+class Observer {
+  class Impl;
+};
+
+template <typename... Args>
+class Observer<Args...>::Impl {
+};
+
+// Work around limit of FileCheck, the expected warnings in a.h files are listed here.
+//
+// Warnings on namespace { class T_A; }
+// CHECK-NOTES-A: warning: declaration 'T_A' is never referenced, but a declaration with the same name found in another namespace 'na' [bugprone-forward-declaration-namespace]
+// CHECK-NOTES-A: note: a declaration of 'T_A' is found here
+// CHECK-NOTES-A1: warning: no definition found for 'T_A', but a definition with the same name 'T_A' found in another namespace '(global)' [bugprone-forward-declaration-namespace]
+// CHECK-NOTES-A1: note: a definition of 'T_A' is found here
+//
+// Warnings on namespace na { class T_A; }
+// CHECK-NOTES-A: warning: declaration 'T_A' is never referenced, but a declaration with the same name found in another namespace '(anonymous)'
+// CHECK-NOTES-A: note: a declaration of 'T_A' is found here
+// CHECK-NOTES-A1: warning: no definition found for 'T_A', but a definition with the same name 'T_A' found in another namespace '(global)'
+// CHECK-NOTES-A1: note: a definition of 'T_A' is found here
Index: clang-tools-extra/test/clang-tidy/checkers/abseil-upgrade-duration-conversions.cpp
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/abseil-upgrade-duration-conversions.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/abseil-upgrade-duration-conversions.cpp
@@ -1,4 +1,5 @@
-// RUN: %check_clang_tidy -std=c++11-or-later %s abseil-upgrade-duration-conversions %t -- -- -I%S/Inputs
+// RUN: %check_clang_tidy -std=c++11-or-later %s abseil-upgrade-duration-conversions %t -- --skip-headers=0 -- -I%S/Inputs
+// RUN: %check_clang_tidy -std=c++11-or-later %s abseil-upgrade-duration-conversions %t -- --skip-headers -- -I%S/Inputs
 
 using int64_t = long long;
 
Index: clang-tools-extra/test/clang-tidy/checkers/abseil-no-internal-dependencies.cpp
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/abseil-no-internal-dependencies.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/abseil-no-internal-dependencies.cpp
@@ -1,5 +1,5 @@
-// RUN: %check_clang_tidy %s abseil-no-internal-dependencies %t,  -- -- -I %S/Inputs
-// RUN: clang-tidy -checks='-*, abseil-no-internal-dependencies' -header-filter='.*' %s -- -I %S/Inputs 2>&1 | FileCheck %s
+// RUN: %check_clang_tidy %s abseil-no-internal-dependencies %t,  -- --skip-headers=0 -- -I %S/Inputs
+// RUN: clang-tidy --skip-headers=0 -checks='-*, abseil-no-internal-dependencies' -header-filter='.*' %s -- -I %S/Inputs 2>&1 | FileCheck %s
 
 #include "absl/strings/internal-file.h"
 #include "absl/flags/internal-file.h"
Index: clang-tools-extra/test/clang-tidy/checkers/Inputs/unused-using-decls.h
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/Inputs/unused-using-decls.h
+++ clang-tools-extra/test/clang-tidy/checkers/Inputs/unused-using-decls.h
@@ -9,3 +9,11 @@
     S();
   }
 };
+
+QC1 *foo();
+
+namespace Q2 {
+class QC2 {};
+} // namespace Q2
+using Q2::QC2;
+// not used QC2 should have warning only when .h file is selected with --header-filter
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/test/clang-tidy/checkers/Inputs/skip-headers/c1.h
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/Inputs/skip-headers/c1.h
@@ -0,0 +1,10 @@
+#ifndef C1_H_
+#define C1_H_
+
+struct C1 {
+  static int foo1(int n = 1ll);
+  int foo2(int n = 2ll);
+  int foo3(int n);
+};
+
+#endif // C1_H_
Index: clang-tools-extra/test/clang-tidy/checkers/Inputs/skip-headers/c.h
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/Inputs/skip-headers/c.h
@@ -0,0 +1,9 @@
+template <class T>
+class C {
+public:
+  template <class R>
+  explicit C(const R r, int *x = 0) : p(x) {}
+
+private:
+  int *p;
+};
Index: clang-tools-extra/test/clang-tidy/checkers/Inputs/skip-headers/b.h
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/Inputs/skip-headers/b.h
@@ -0,0 +1,4 @@
+class B {
+  // expect a warning on fooB
+  void fooB(int x) { x = 2; };
+};
Index: clang-tools-extra/test/clang-tidy/checkers/Inputs/skip-headers/a.h
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/Inputs/skip-headers/a.h
@@ -0,0 +1,4 @@
+class A {
+#include "b.h"
+  void fooA(int x) { x = 1; };
+};
Index: clang-tools-extra/test/clang-tidy/checkers/Inputs/modernize-pass-by-value/header.h
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/Inputs/modernize-pass-by-value/header.h
+++ clang-tools-extra/test/clang-tidy/checkers/Inputs/modernize-pass-by-value/header.h
@@ -8,3 +8,10 @@
   A(const ThreadId &tid) : threadid(tid) {}
   ThreadId threadid;
 };
+
+struct Movable {
+  int a, b, c;
+  Movable() = default;
+  Movable(const Movable &) {}
+  Movable(Movable &&) {}
+};
Index: clang-tools-extra/test/clang-tidy/checkers/Inputs/bugprone-forward-declaration-namespace/b.h
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/Inputs/bugprone-forward-declaration-namespace/b.h
@@ -0,0 +1,9 @@
+namespace nb {
+class T_B;
+}
+
+namespace nb {
+class T_B {
+  int x;
+};
+} // namespace nb
Index: clang-tools-extra/test/clang-tidy/checkers/Inputs/bugprone-forward-declaration-namespace/a.h
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/Inputs/bugprone-forward-declaration-namespace/a.h
@@ -0,0 +1,9 @@
+namespace {
+// This is a declaration in a wrong namespace.
+class T_A;
+} // namespace
+
+namespace na {
+// This is a declaration in a wrong namespace.
+class T_A;
+} // namespace na
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/modernize/UseNullptrCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
+++ clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
@@ -217,6 +217,12 @@
       return true;
     }
 
+    // When Stmt S does not have a "valid" location,
+    // skipLocation won't skip it.
+    // So we need to check here if C should be skipped.
+    if (Check.skipLocation(C->getBeginLoc()))
+      return true;
+
     auto* CastSubExpr = C->getSubExpr()->IgnoreParens();
     // Ignore cast expressions which cast nullptr literal.
     if (isa<CXXNullPtrLiteralExpr>(CastSubExpr)) {
Index: clang-tools-extra/clang-tidy/misc/UnusedUsingDeclsCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/misc/UnusedUsingDeclsCheck.cpp
+++ clang-tools-extra/clang-tidy/misc/UnusedUsingDeclsCheck.cpp
@@ -179,7 +179,8 @@
 
 void UnusedUsingDeclsCheck::onEndOfTranslationUnit() {
   for (const auto &Context : Contexts) {
-    if (!Context.IsUsed) {
+    if (!Context.IsUsed &&
+        !skipLocation(Context.FoundUsingDecl->getLocation())) {
       diag(Context.FoundUsingDecl->getLocation(), "using decl %0 is unused")
           << Context.FoundUsingDecl;
       // Emit a fix and a fix description of the check;
Index: clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
===================================================================
--- clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
+++ clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
@@ -55,7 +55,7 @@
     CheckFactories.registerCheck<UnusedParametersCheck>(
         "misc-unused-parameters");
     CheckFactories.registerCheck<UnusedUsingDeclsCheck>(
-        "misc-unused-using-decls");
+        "misc-unused-using-decls", true);
   }
 };
 
Index: clang-tools-extra/clang-tidy/bugprone/ForwardDeclarationNamespaceCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/bugprone/ForwardDeclarationNamespaceCheck.cpp
+++ clang-tools-extra/clang-tidy/bugprone/ForwardDeclarationNamespaceCheck.cpp
@@ -130,6 +130,9 @@
           CurDecl->getLocation().isInvalid()) {
         continue;
       }
+      if (skipLocation(CurDecl->getLocation())) {
+        continue; // Skip if --skip-headers and CurDecl's file is skipped.
+      }
       // Compare with all other declarations with the same name.
       for (const auto *Decl : Declarations) {
         if (Decl == CurDecl) {
Index: clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
===================================================================
--- clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
+++ clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
@@ -99,7 +99,7 @@
     CheckFactories.registerCheck<FoldInitTypeCheck>(
         "bugprone-fold-init-type");
     CheckFactories.registerCheck<ForwardDeclarationNamespaceCheck>(
-        "bugprone-forward-declaration-namespace");
+        "bugprone-forward-declaration-namespace", true);
     CheckFactories.registerCheck<ForwardingReferenceOverloadCheck>(
         "bugprone-forwarding-reference-overload");
     CheckFactories.registerCheck<ImplicitWideningOfMultiplicationResultCheck>(
Index: clang-tools-extra/clang-tidy/ClangTidyOptions.h
===================================================================
--- clang-tools-extra/clang-tidy/ClangTidyOptions.h
+++ clang-tools-extra/clang-tidy/ClangTidyOptions.h
@@ -79,6 +79,15 @@
   /// Output warnings from system headers matching \c HeaderFilterRegex.
   llvm::Optional<bool> SystemHeaders;
 
+  /// Show all warnings, including warnings from all header files.
+  /// This overrides HeaderFilterRegex and SystemHeaders.
+  /// This is an option intended for testing/debugging clang-tidy.
+  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;
+
   /// Format code around applied fixes with clang-format using this
   /// style.
   ///
Index: clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
===================================================================
--- clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
+++ clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
@@ -89,6 +89,9 @@
     IO.mapOptional("Checks", Options.Checks);
     IO.mapOptional("WarningsAsErrors", Options.WarningsAsErrors);
     IO.mapOptional("HeaderFilterRegex", Options.HeaderFilterRegex);
+    // SystemHeaders not mapped?
+    // ShowAllWarnings is hidden debug only option.
+    IO.mapOptional("SkipHeaders", Options.SkipHeaders);
     IO.mapOptional("AnalyzeTemporaryDtors", Ignored); // legacy compatibility
     IO.mapOptional("FormatStyle", Options.FormatStyle);
     IO.mapOptional("User", Options.User);
@@ -111,6 +114,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 +152,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/ClangTidyModule.h
===================================================================
--- clang-tools-extra/clang-tidy/ClangTidyModule.h
+++ clang-tools-extra/clang-tidy/ClangTidyModule.h
@@ -33,7 +33,8 @@
   /// Registers check \p Factory with name \p Name.
   ///
   /// For all checks that have default constructors, use \c registerCheck.
-  void registerCheckFactory(llvm::StringRef Name, CheckFactory Factory);
+  void registerCheckFactory(llvm::StringRef Name, CheckFactory Factory,
+                            bool IsAllFileCheck = false);
 
   /// Registers the \c CheckType with the name \p Name.
   ///
@@ -53,27 +54,37 @@
   /// class MyModule : public ClangTidyModule {
   ///   void addCheckFactories(ClangTidyCheckFactories &Factories) override {
   ///     Factories.registerCheck<MyTidyCheck>("myproject-my-check");
+  ///     // or Factories.registerCheck<MyTidyCheck>("my-check", true);
+  ///     // for a check that needs to match all Decls in header files.
   ///   }
   /// };
   /// \endcode
-  template <typename CheckType> void registerCheck(llvm::StringRef CheckName) {
-    registerCheckFactory(CheckName,
-                         [](llvm::StringRef Name, ClangTidyContext *Context) {
-                           return std::make_unique<CheckType>(Name, Context);
-                         });
+  template <typename CheckType>
+  void registerCheck(llvm::StringRef CheckName, bool IsAllFileCheck = false) {
+    registerCheckFactory(
+        CheckName,
+        [](llvm::StringRef Name, ClangTidyContext *Context) {
+          return std::make_unique<CheckType>(Name, Context);
+        },
+        IsAllFileCheck);
   }
 
   /// Create instances of checks that are enabled.
   std::vector<std::unique_ptr<ClangTidyCheck>>
   createChecks(ClangTidyContext *Context);
 
+  /// Create instances of all-file checks that are enabled.
+  std::vector<std::unique_ptr<ClangTidyCheck>>
+  createAllFileChecks(ClangTidyContext *Context);
+
   typedef llvm::StringMap<CheckFactory> FactoryMap;
   FactoryMap::const_iterator begin() const { return Factories.begin(); }
   FactoryMap::const_iterator end() const { return Factories.end(); }
   bool empty() const { return Factories.empty(); }
 
 private:
-  FactoryMap Factories;
+  FactoryMap Factories; // has both normal checks and all-file checks
+  llvm::StringMap<bool> IsAllFileChecks; // check name -> is all-file check
 };
 
 /// A clang-tidy module groups a number of \c ClangTidyChecks and gives
Index: clang-tools-extra/clang-tidy/ClangTidyModule.cpp
===================================================================
--- clang-tools-extra/clang-tidy/ClangTidyModule.cpp
+++ clang-tools-extra/clang-tidy/ClangTidyModule.cpp
@@ -17,20 +17,34 @@
 namespace tidy {
 
 void ClangTidyCheckFactories::registerCheckFactory(StringRef Name,
-                                                   CheckFactory Factory) {
+                                                   CheckFactory Factory,
+                                                   bool IsAllFileCheck) {
   Factories.insert_or_assign(Name, std::move(Factory));
+  IsAllFileChecks.insert_or_assign(Name, IsAllFileCheck);
 }
 
 std::vector<std::unique_ptr<ClangTidyCheck>>
 ClangTidyCheckFactories::createChecks(ClangTidyContext *Context) {
   std::vector<std::unique_ptr<ClangTidyCheck>> Checks;
   for (const auto &Factory : Factories) {
-    if (Context->isCheckEnabled(Factory.getKey()))
+    if (Context->isCheckEnabled(Factory.getKey()) &&
+        !IsAllFileChecks[Factory.getKey()])
       Checks.emplace_back(Factory.getValue()(Factory.getKey(), Context));
   }
   return Checks;
 }
 
+std::vector<std::unique_ptr<ClangTidyCheck>>
+ClangTidyCheckFactories::createAllFileChecks(ClangTidyContext *Context) {
+  std::vector<std::unique_ptr<ClangTidyCheck>> AllFileChecks;
+  for (const auto &Factory : Factories) {
+    if (Context->isCheckEnabled(Factory.getKey()) &&
+        IsAllFileChecks[Factory.getKey()])
+      AllFileChecks.emplace_back(Factory.getValue()(Factory.getKey(), Context));
+  }
+  return AllFileChecks;
+}
+
 ClangTidyOptions ClangTidyModule::getModuleOptions() {
   return ClangTidyOptions();
 }
Index: clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
===================================================================
--- clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
+++ clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
@@ -11,7 +11,9 @@
 
 #include "ClangTidyOptions.h"
 #include "ClangTidyProfiling.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/SourceManager.h"
 #include "clang/Tooling/Core/Diagnostic.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/Support/Regex.h"
@@ -20,10 +22,6 @@
 
 class ASTContext;
 class CompilerInstance;
-class SourceManager;
-namespace ast_matchers {
-class MatchFinder;
-}
 namespace tooling {
 class CompilationDatabase;
 }
@@ -104,6 +102,11 @@
   configurationDiag(StringRef Message,
                     DiagnosticIDs::Level Level = DiagnosticIDs::Warning);
 
+  /// Returns the \c SourceManager of the used \c DiagnosticsEngine.
+  SourceManager &getSourceManager() const {
+    return DiagEngine->getSourceManager();
+  }
+
   /// Sets the \c SourceManager of the used \c DiagnosticsEngine.
   ///
   /// This is called from the \c ClangTidyCheck base class.
@@ -212,6 +215,11 @@
   bool AllowEnablingAnalyzerAlphaCheckers;
 };
 
+typedef ast_matchers::MatchFinder::MatchFinderOptions::LocFilter
+    ClangTidyLocationFilter;
+
+class ClangTidyLocationFilterImpl;
+
 /// Check whether a given diagnostic should be suppressed due to the presence
 /// of a "NOLINT" suppression comment.
 /// This is exposed so that other tools that present clang-tidy diagnostics
@@ -244,6 +252,7 @@
                               DiagnosticsEngine *ExternalDiagEngine = nullptr,
                               bool RemoveIncompatibleErrors = true,
                               bool GetFixesFromNotes = false);
+  ~ClangTidyDiagnosticConsumer();
 
   // FIXME: The concept of converting between FixItHints and Replacements is
   // more generic and should be pulled out into a more useful Diagnostics
@@ -254,15 +263,21 @@
   // Retrieve the diagnostics that were captured.
   std::vector<ClangTidyError> take();
 
+  /// Returns true if the Location should have warnings suppressed.
+  static bool skipLocation(SourceLocation Location) {
+    return LocationFilter && LocationFilter->skipLocation(Location);
+  }
+
+  static ClangTidyLocationFilter *newLocationFilter(ClangTidyContext *Context);
+
+  static ClangTidyLocationFilterImpl *
+  newLocationFilterImpl(ClangTidyContext *Context);
+
 private:
   void finalizeLastError();
   void removeIncompatibleErrors();
   void removeDuplicatedDiagnosticsOfAliasCheckers();
 
-  /// Returns the \c HeaderFilter constructed for the options set in the
-  /// context.
-  llvm::Regex *getHeaderFilter();
-
   /// Updates \c LastErrorRelatesToUserCode and LastErrorPassesLineFilter
   /// according to the diagnostic \p Location.
   void checkFilters(SourceLocation Location, const SourceManager &Sources);
@@ -275,10 +290,12 @@
   bool RemoveIncompatibleErrors;
   bool GetFixesFromNotes;
   std::vector<ClangTidyError> Errors;
-  std::unique_ptr<llvm::Regex> HeaderFilter;
+  std::unique_ptr<ClangTidyLocationFilterImpl> LocationFilterImpl;
   bool LastErrorRelatesToUserCode;
   bool LastErrorPassesLineFilter;
   bool LastErrorWasIgnored;
+
+  static std::unique_ptr<ClangTidyLocationFilter> LocationFilter;
 };
 
 } // end namespace tidy
Index: clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
===================================================================
--- clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
+++ clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
@@ -38,6 +38,91 @@
 using namespace clang;
 using namespace tidy;
 
+namespace clang {
+namespace tidy {
+
+class ClangTidyLocationFilterImpl : ClangTidyLocationFilter {
+public:
+  ClangTidyLocationFilterImpl(ClangTidyContext *Context);
+  ~ClangTidyLocationFilterImpl();
+  virtual bool skipLocation(SourceLocation Location) const override;
+
+private:
+  friend class ClangTidyDiagnosticConsumer;
+  /// Returns true if the Location with FileID is in a skipped system header.
+  bool isSkippedSystemHeader(SourceLocation Location, FileID FileID,
+                             const FileEntry *File,
+                             const SourceManager &Sources) const;
+
+  /// Returns true if the Location with FileID is in user code.
+  bool isUserCode(SourceLocation Location, FileID FileID, const FileEntry *File,
+                  const SourceManager &Sources) const;
+
+  ClangTidyContext *Context;
+  mutable FileID LastSkippedSystemFileID;
+  mutable FileID LastSkippedFileID;
+  mutable FileID LastAcceptedFileID;
+  std::unique_ptr<llvm::Regex> HeaderFilterRegex;
+};
+
+} // end namespace tidy
+} // end namespace clang
+
+ClangTidyLocationFilterImpl::~ClangTidyLocationFilterImpl() = default;
+
+ClangTidyLocationFilterImpl::ClangTidyLocationFilterImpl(
+    ClangTidyContext *Context)
+    : Context(Context), LastSkippedSystemFileID(FileID::getSentinel()),
+      LastSkippedFileID(FileID::getSentinel()),
+      LastAcceptedFileID(FileID::getSentinel()),
+      HeaderFilterRegex(std::make_unique<llvm::Regex>(
+          *Context->getOptions().HeaderFilterRegex)) {}
+
+bool ClangTidyLocationFilterImpl::skipLocation(SourceLocation Location) const {
+  if (!Location.isValid())
+    return false;
+  SourceManager &Sources = Context->getSourceManager();
+  FileID FID = Sources.getDecomposedExpansionLoc(Location).first;
+  // Do not skip built-in and command line yet.
+  const FileEntry *File = Sources.getFileEntryForID(FID);
+  if (!File)
+    return false;
+  return isSkippedSystemHeader(Location, FID, File, Sources) ||
+         !isUserCode(Location, FID, File, Sources);
+}
+
+bool ClangTidyLocationFilterImpl::isSkippedSystemHeader(
+    SourceLocation Location, FileID FID, const FileEntry *File,
+    const SourceManager &Sources) const {
+  if (!File)
+    return false;
+  if (FID == LastSkippedSystemFileID)
+    return true;
+  if (!*Context->getOptions().SystemHeaders &&
+      Sources.isInSystemHeader(Location)) {
+    LastSkippedSystemFileID = FID;
+    return true;
+  }
+  return false;
+}
+
+bool ClangTidyLocationFilterImpl::isUserCode(
+    SourceLocation Location, FileID FID, const FileEntry *File,
+    const SourceManager &Sources) const {
+  assert(File);
+  if (FID == LastSkippedFileID)
+    return false;
+  if (FID == LastAcceptedFileID)
+    return true;
+  bool IsUserCode = Sources.isInMainFile(Location) ||
+                    HeaderFilterRegex->match(File->getName());
+  if (IsUserCode)
+    LastAcceptedFileID = FID;
+  else
+    LastSkippedFileID = FID;
+  return IsUserCode;
+}
+
 namespace {
 class ClangTidyDiagnosticRenderer : public DiagnosticRenderer {
 public:
@@ -276,13 +361,35 @@
   return "";
 }
 
+// Global LocationFilter is non-null if --skip-header is enabled.
+std::unique_ptr<ClangTidyLocationFilter>
+    ClangTidyDiagnosticConsumer::LocationFilter;
+
 ClangTidyDiagnosticConsumer::ClangTidyDiagnosticConsumer(
     ClangTidyContext &Ctx, DiagnosticsEngine *ExternalDiagEngine,
     bool RemoveIncompatibleErrors, bool GetFixesFromNotes)
     : Context(Ctx), ExternalDiagEngine(ExternalDiagEngine),
       RemoveIncompatibleErrors(RemoveIncompatibleErrors),
-      GetFixesFromNotes(GetFixesFromNotes), LastErrorRelatesToUserCode(false),
-      LastErrorPassesLineFilter(false), LastErrorWasIgnored(false) {}
+      GetFixesFromNotes(GetFixesFromNotes),
+      LocationFilterImpl(newLocationFilterImpl(&Ctx)),
+      LastErrorRelatesToUserCode(false), LastErrorPassesLineFilter(false),
+      LastErrorWasIgnored(false) {
+  if (*Ctx.getOptions().SkipHeaders)
+    LocationFilter =
+        std::unique_ptr<ClangTidyLocationFilter>(newLocationFilter(&Ctx));
+}
+
+ClangTidyLocationFilterImpl *
+ClangTidyDiagnosticConsumer::newLocationFilterImpl(ClangTidyContext *Context) {
+  return new ClangTidyLocationFilterImpl(Context);
+}
+
+ClangTidyLocationFilter *
+ClangTidyDiagnosticConsumer::newLocationFilter(ClangTidyContext *Context) {
+  return new ClangTidyLocationFilterImpl(Context);
+}
+
+ClangTidyDiagnosticConsumer::~ClangTidyDiagnosticConsumer() = default;
 
 void ClangTidyDiagnosticConsumer::finalizeLastError() {
   if (!Errors.empty()) {
@@ -580,21 +687,19 @@
 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;
   }
 
-  if (!*Context.getOptions().SystemHeaders &&
-      Sources.isInSystemHeader(Location))
-    return;
-
   // FIXME: We start with a conservative approach here, but the actual type of
   // location needed depends on the check (in particular, where this check wants
   // to apply fixes).
   FileID FID = Sources.getDecomposedExpansionLoc(Location).first;
   const FileEntry *File = Sources.getFileEntryForID(FID);
+  if (LocationFilterImpl->isSkippedSystemHeader(Location, FID, File, Sources))
+    return;
 
   // -DMACRO definitions on the command line have locations in a virtual buffer
   // that doesn't have a FileEntry. Don't skip these as well.
@@ -605,22 +710,15 @@
   }
 
   StringRef FileName(File->getName());
-  LastErrorRelatesToUserCode = LastErrorRelatesToUserCode ||
-                               Sources.isInMainFile(Location) ||
-                               getHeaderFilter()->match(FileName);
+  LastErrorRelatesToUserCode =
+      LastErrorRelatesToUserCode ||
+      LocationFilterImpl->isUserCode(Location, FID, File, Sources);
 
   unsigned LineNumber = Sources.getExpansionLineNumber(Location);
   LastErrorPassesLineFilter =
       LastErrorPassesLineFilter || passesLineFilter(FileName, LineNumber);
 }
 
-llvm::Regex *ClangTidyDiagnosticConsumer::getHeaderFilter() {
-  if (!HeaderFilter)
-    HeaderFilter =
-        std::make_unique<llvm::Regex>(*Context.getOptions().HeaderFilterRegex);
-  return HeaderFilter.get();
-}
-
 void ClangTidyDiagnosticConsumer::removeIncompatibleErrors() {
   // Each error is modelled as the set of intervals in which it applies
   // replacements. To detect overlapping replacements, we use a sweep line
Index: clang-tools-extra/clang-tidy/ClangTidyCheck.h
===================================================================
--- clang-tools-extra/clang-tidy/ClangTidyCheck.h
+++ clang-tools-extra/clang-tidy/ClangTidyCheck.h
@@ -132,6 +132,11 @@
   /// whether it has the default value or it has been overridden.
   virtual void storeOptions(ClangTidyOptions::OptionMap &Options) {}
 
+  /// Returns true if the Location should have warnings suppressed.
+  static bool skipLocation(SourceLocation Location) {
+    return ClangTidyDiagnosticConsumer::skipLocation(Location);
+  }
+
   /// Provides access to the ``ClangTidyCheck`` options via check-local
   /// names.
   ///
Index: clang-tools-extra/clang-tidy/ClangTidy.cpp
===================================================================
--- clang-tools-extra/clang-tidy/ClangTidy.cpp
+++ clang-tools-extra/clang-tidy/ClangTidy.cpp
@@ -307,20 +307,26 @@
 
 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::vector<std::unique_ptr<ClangTidyCheck>> Checks)
+  ClangTidyASTConsumer(
+      std::vector<std::unique_ptr<ASTConsumer>> Consumers,
+      std::unique_ptr<ClangTidyProfiling> Profiling,
+      std::unique_ptr<ast_matchers::MatchFinder> Finder,
+      std::unique_ptr<ast_matchers::MatchFinder> AllFileFinder,
+      std::vector<std::unique_ptr<ClangTidyCheck>> Checks,
+      std::vector<std::unique_ptr<ClangTidyCheck>> AllFileChecks)
       : MultiplexConsumer(std::move(Consumers)),
         Profiling(std::move(Profiling)), Finder(std::move(Finder)),
-        Checks(std::move(Checks)) {}
+        AllFileFinder(std::move(AllFileFinder)), Checks(std::move(Checks)),
+        AllFileChecks(std::move(AllFileChecks)) {}
 
 private:
   // 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<ast_matchers::MatchFinder> AllFileFinder;
   std::vector<std::unique_ptr<ClangTidyCheck>> Checks;
+  std::vector<std::unique_ptr<ClangTidyCheck>> AllFileChecks;
 };
 
 } // namespace
@@ -403,22 +409,38 @@
 
   std::vector<std::unique_ptr<ClangTidyCheck>> Checks =
       CheckFactories->createChecks(&Context);
+  std::vector<std::unique_ptr<ClangTidyCheck>> AllFileChecks =
+      CheckFactories->createAllFileChecks(&Context);
 
-  llvm::erase_if(Checks, [&](std::unique_ptr<ClangTidyCheck> &Check) {
+  auto EraseFilter = [&](std::unique_ptr<ClangTidyCheck> &Check) {
     return !Check->isLanguageVersionSupported(Context.getLangOpts());
-  });
+  };
+  llvm::erase_if(Checks, EraseFilter);
+  llvm::erase_if(AllFileChecks, EraseFilter);
 
   ast_matchers::MatchFinder::MatchFinderOptions FinderOptions;
+  ast_matchers::MatchFinder::MatchFinderOptions AllFileFinderOptions;
 
   std::unique_ptr<ClangTidyProfiling> Profiling;
   if (Context.getEnableProfiling()) {
     Profiling = std::make_unique<ClangTidyProfiling>(
         Context.getProfileStorageParams());
+    // Two Finders share the same Profiling->Records.
     FinderOptions.CheckProfiling.emplace(Profiling->Records);
+    AllFileFinderOptions.CheckProfiling.emplace(Profiling->Records);
+  }
+
+  // LocationFilter is not for AllFileFinder.
+  if (*Context.getOptions().SkipHeaders) {
+    std::unique_ptr<ClangTidyLocationFilter> LocationFilter(
+        ClangTidyDiagnosticConsumer::newLocationFilter(&Context));
+    FinderOptions.Filter = std::move(LocationFilter);
   }
 
   std::unique_ptr<ast_matchers::MatchFinder> Finder(
       new ast_matchers::MatchFinder(std::move(FinderOptions)));
+  std::unique_ptr<ast_matchers::MatchFinder> AllFileFinder(
+      new ast_matchers::MatchFinder(std::move(AllFileFinderOptions)));
 
   Preprocessor *PP = &Compiler.getPreprocessor();
   Preprocessor *ModuleExpanderPP = PP;
@@ -434,10 +456,16 @@
     Check->registerMatchers(&*Finder);
     Check->registerPPCallbacks(*SM, PP, ModuleExpanderPP);
   }
+  for (auto &Check : AllFileChecks) {
+    Check->registerMatchers(&*AllFileFinder);
+    Check->registerPPCallbacks(*SM, PP, ModuleExpanderPP);
+  }
 
   std::vector<std::unique_ptr<ASTConsumer>> Consumers;
   if (!Checks.empty())
     Consumers.push_back(Finder->newASTConsumer());
+  if (!AllFileChecks.empty())
+    Consumers.push_back(AllFileFinder->newASTConsumer());
 
 #if CLANG_TIDY_ENABLE_STATIC_ANALYZER
   AnalyzerOptionsRef AnalyzerOptions = Compiler.getAnalyzerOpts();
@@ -458,7 +486,7 @@
 #endif // CLANG_TIDY_ENABLE_STATIC_ANALYZER
   return std::make_unique<ClangTidyASTConsumer>(
       std::move(Consumers), std::move(Profiling), std::move(Finder),
-      std::move(Checks));
+      std::move(AllFileFinder), std::move(Checks), std::move(AllFileChecks));
 }
 
 std::vector<std::string> ClangTidyASTConsumerFactory::getCheckNames() {
@@ -484,6 +512,10 @@
       CheckFactories->createChecks(&Context);
   for (const auto &Check : Checks)
     Check->storeOptions(Options);
+  std::vector<std::unique_ptr<ClangTidyCheck>> AllFileChecks =
+      CheckFactories->createAllFileChecks(&Context);
+  for (const auto &Check : AllFileChecks)
+    Check->storeOptions(Options);
   return Options;
 }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D98709: [clang-tid... Chih-Hung Hsieh via Phabricator via cfe-commits

Reply via email to