chh updated this revision to Diff 360339. chh edited the summary of this revision. chh added a comment.
Add bugprone-forward-declaration-namespace-header.cpp test to show that MatchFinder-based checks can also depend on header Decls. 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/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/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/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/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-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/Frontend/MultiplexConsumer.h
Index: clang/include/clang/Frontend/MultiplexConsumer.h =================================================================== --- clang/include/clang/Frontend/MultiplexConsumer.h +++ clang/include/clang/Frontend/MultiplexConsumer.h @@ -77,8 +77,9 @@ void InitializeSema(Sema &S) override; void ForgetSema() override; -private: +protected: std::vector<std::unique_ptr<ASTConsumer>> Consumers; // Owns these. +private: std::unique_ptr<MultiplexASTMutationListener> MutationListener; std::unique_ptr<MultiplexASTDeserializationListener> DeserializationListener; }; 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.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(chh): 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: 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=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,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='*' --skip-headers=0 -- -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=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-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-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-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,173 @@ +// Same output with skip-headers=0, skip-headers=1, or skip-headers +// RUN: %check_clang_tidy -check-suffixes=ALL %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 +// +// Additional warnings on a.h +// RUN: %check_clang_tidy -check-suffixes=ALL,A %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 %s bugprone-forward-declaration-namespace %t -- --skip-headers \ +// RUN: --header-filter=.* -- -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 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 +} + +#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 +} + +// 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; +} + +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 nd { +class OUTSIDER_1; +void f(OUTSIDER_1 *); +} + +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 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 na { +template<typename T> +class T_C { + int x; +}; +} + +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 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 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 ne { +class D; +} +} + +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. +// +// Bug? Without --header-filter=.*, +// the "is never referenced" warnings are suppressed +// but not the "no definiton found" warnings. +// +// 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-ALL: 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-ALL: 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-ALL: warning: no definition found for 'T_A', but a definition with the same name 'T_A' found in another namespace '(global)' +// CHECK-NOTES-ALL: 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,4 @@ -// 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 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/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/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; +}; +} 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 na { +// This is a declaration in a wrong namespace. +class T_A; +} 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 @@ -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/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,15 +305,83 @@ 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; +}; + +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; +} + 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, + ASTConsumer *FinderASTConsumerPtr, + std::shared_ptr<DeclFilter> Filter, std::vector<std::unique_ptr<ClangTidyCheck>> Checks) : MultiplexConsumer(std::move(Consumers)), Profiling(std::move(Profiling)), Finder(std::move(Finder)), - Checks(std::move(Checks)) {} + Checks(std::move(Checks)), FinderASTConsumerPtr(FinderASTConsumerPtr), + Filter(Filter) {} + ~ClangTidyASTConsumer() override; + bool HandleTopLevelDecl(DeclGroupRef DG) override; + void HandleTranslationUnit(ASTContext &Context) override; private: // Destructor order matters! Profiling must be destructed last. @@ -321,6 +389,16 @@ std::unique_ptr<ClangTidyProfiling> Profiling; std::unique_ptr<ast_matchers::MatchFinder> Finder; std::vector<std::unique_ptr<ClangTidyCheck>> Checks; + /// Remembered Finder's ASTConsumer, which is also pushed into + /// and managed by MultiplexConsumer. + ASTConsumer *FinderASTConsumerPtr; + + // When --skip-headers, Filter is not null and handleTopLevelDecl + // will collect Decls into TopLevelDecls. + /// Check if a Decl should be skipped. + std::shared_ptr<DeclFilter> Filter; + /// All (filtered) top level decls. + std::vector<Decl *> TopLevelDecls; }; } // namespace @@ -384,6 +462,62 @@ } #endif // CLANG_TIDY_ENABLE_STATIC_ANALYZER +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); +} + +ClangTidyASTConsumer::~ClangTidyASTConsumer() {} + +bool ClangTidyASTConsumer::HandleTopLevelDecl(DeclGroupRef DG) { + if (!MultiplexConsumer::HandleTopLevelDecl(DG)) + return false; + if (Filter.get() != nullptr) { + 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; +} + +void ClangTidyASTConsumer::HandleTranslationUnit(ASTContext &Context) { + // If skip-headers is not on, there is no Filter and no skip TopLevelDecls. + // If there is no MatchFinder-based checks, FinderASTConsumerPtr is nullptr + // and there is no need to change TopLevelDecls. + // Only setTraversalScope without restoreing, assuming that this does not + // affect the static analyzer checks. + if (Filter.get() != nullptr && nullptr != FinderASTConsumerPtr) + Context.setTraversalScope(TopLevelDecls); + // If any static analyzer check does not work with filtered TopLevelDecls, + // the following loop should be changed to set/restore TraversalScope + // only when (Consumer.get() == FinderASTConsumerPtr). + for (auto &Consumer : Consumers) + Consumer->HandleTranslationUnit(Context); +} + std::unique_ptr<clang::ASTConsumer> ClangTidyASTConsumerFactory::CreateASTConsumer( clang::CompilerInstance &Compiler, StringRef File) { @@ -416,6 +550,10 @@ 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))); @@ -436,8 +574,12 @@ } std::vector<std::unique_ptr<ASTConsumer>> Consumers; - if (!Checks.empty()) - Consumers.push_back(Finder->newASTConsumer()); + ASTConsumer *FinderASTConsumerPtr = nullptr; + if (!Checks.empty()) { + std::unique_ptr<ASTConsumer> FinderASTConsumer(Finder->newASTConsumer()); + FinderASTConsumerPtr = FinderASTConsumer.get(); + Consumers.push_back(std::move(FinderASTConsumer)); + } #if CLANG_TIDY_ENABLE_STATIC_ANALYZER AnalyzerOptionsRef AnalyzerOptions = Compiler.getAnalyzerOpts(); @@ -458,7 +600,7 @@ #endif // CLANG_TIDY_ENABLE_STATIC_ANALYZER return std::make_unique<ClangTidyASTConsumer>( std::move(Consumers), std::move(Profiling), std::move(Finder), - std::move(Checks)); + FinderASTConsumerPtr, std::move(SharedDeclFilter), std::move(Checks)); } std::vector<std::string> ClangTidyASTConsumerFactory::getCheckNames() {
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits