Skip to content

Commit 6333fa5

Browse files
carlosgalvezpCarlos Gálvez
and
Carlos Gálvez
authored
[clang-tidy] Fix broken HeaderFilterRegex when read from config file (#133582)
PR #91400 broke the usage of HeaderFilterRegex via config file, because it is now created at a different point in the execution and leads to a different value. The result of that is that using HeaderFilterRegex only in the config file does NOT work, in other words clang-tidy stops triggering warnings on header files, thereby losing a lot of coverage. This patch reverts the logic so that the header filter is created upon calling the getHeaderFilter() function. Additionally, this patch adds 2 unit tests to prevent regressions in the future: - One of them, "simple", tests the most basic use case with a single top-level .clang-tidy file. - The second one, "inheritance", demonstrates that the subfolder only gets warnings from headers within it, and not from parent headers. Fixes #118009 Fixes #121969 Fixes #133453 Co-authored-by: Carlos Gálvez <[email protected]>
1 parent e1aaee7 commit 6333fa5

File tree

13 files changed

+49
-19
lines changed

13 files changed

+49
-19
lines changed

clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp

+19-17
Original file line numberDiff line numberDiff line change
@@ -311,18 +311,7 @@ ClangTidyDiagnosticConsumer::ClangTidyDiagnosticConsumer(
311311
: Context(Ctx), ExternalDiagEngine(ExternalDiagEngine),
312312
RemoveIncompatibleErrors(RemoveIncompatibleErrors),
313313
GetFixesFromNotes(GetFixesFromNotes),
314-
EnableNolintBlocks(EnableNolintBlocks) {
315-
316-
if (Context.getOptions().HeaderFilterRegex &&
317-
!Context.getOptions().HeaderFilterRegex->empty())
318-
HeaderFilter =
319-
std::make_unique<llvm::Regex>(*Context.getOptions().HeaderFilterRegex);
320-
321-
if (Context.getOptions().ExcludeHeaderFilterRegex &&
322-
!Context.getOptions().ExcludeHeaderFilterRegex->empty())
323-
ExcludeHeaderFilter = std::make_unique<llvm::Regex>(
324-
*Context.getOptions().ExcludeHeaderFilterRegex);
325-
}
314+
EnableNolintBlocks(EnableNolintBlocks) {}
326315

327316
void ClangTidyDiagnosticConsumer::finalizeLastError() {
328317
if (!Errors.empty()) {
@@ -571,17 +560,30 @@ void ClangTidyDiagnosticConsumer::checkFilters(SourceLocation Location,
571560
}
572561

573562
StringRef FileName(File->getName());
574-
LastErrorRelatesToUserCode =
575-
LastErrorRelatesToUserCode || Sources.isInMainFile(Location) ||
576-
(HeaderFilter &&
577-
(HeaderFilter->match(FileName) &&
578-
!(ExcludeHeaderFilter && ExcludeHeaderFilter->match(FileName))));
563+
LastErrorRelatesToUserCode = LastErrorRelatesToUserCode ||
564+
Sources.isInMainFile(Location) ||
565+
(getHeaderFilter()->match(FileName) &&
566+
!getExcludeHeaderFilter()->match(FileName));
579567

580568
unsigned LineNumber = Sources.getExpansionLineNumber(Location);
581569
LastErrorPassesLineFilter =
582570
LastErrorPassesLineFilter || passesLineFilter(FileName, LineNumber);
583571
}
584572

573+
llvm::Regex *ClangTidyDiagnosticConsumer::getHeaderFilter() {
574+
if (!HeaderFilter)
575+
HeaderFilter =
576+
std::make_unique<llvm::Regex>(*Context.getOptions().HeaderFilterRegex);
577+
return HeaderFilter.get();
578+
}
579+
580+
llvm::Regex *ClangTidyDiagnosticConsumer::getExcludeHeaderFilter() {
581+
if (!ExcludeHeaderFilter)
582+
ExcludeHeaderFilter = std::make_unique<llvm::Regex>(
583+
*Context.getOptions().ExcludeHeaderFilterRegex);
584+
return ExcludeHeaderFilter.get();
585+
}
586+
585587
void ClangTidyDiagnosticConsumer::removeIncompatibleErrors() {
586588
// Each error is modelled as the set of intervals in which it applies
587589
// replacements. To detect overlapping replacements, we use a sweep line

clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h

+4
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,10 @@ class ClangTidyDiagnosticConsumer : public DiagnosticConsumer {
302302
/// context.
303303
llvm::Regex *getHeaderFilter();
304304

305+
/// Returns the \c ExcludeHeaderFilter constructed for the options set in the
306+
/// context.
307+
llvm::Regex *getExcludeHeaderFilter();
308+
305309
/// Updates \c LastErrorRelatesToUserCode and LastErrorPassesLineFilter
306310
/// according to the diagnostic \p Location.
307311
void checkFilters(SourceLocation Location, const SourceManager &Sources);

clang-tools-extra/clang-tidy/ClangTidyOptions.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -194,8 +194,8 @@ ClangTidyOptions ClangTidyOptions::getDefaults() {
194194
Options.WarningsAsErrors = "";
195195
Options.HeaderFileExtensions = {"", "h", "hh", "hpp", "hxx"};
196196
Options.ImplementationFileExtensions = {"c", "cc", "cpp", "cxx"};
197-
Options.HeaderFilterRegex = std::nullopt;
198-
Options.ExcludeHeaderFilterRegex = std::nullopt;
197+
Options.HeaderFilterRegex = "";
198+
Options.ExcludeHeaderFilterRegex = "";
199199
Options.SystemHeaders = false;
200200
Options.FormatStyle = "none";
201201
Options.User = std::nullopt;

clang-tools-extra/docs/ReleaseNotes.rst

+3
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,9 @@ Improvements to clang-tidy
9494
- Improved :program:`clang-tidy-diff.py` script. Add the `-warnings-as-errors`
9595
argument to treat warnings as errors.
9696

97+
- Fixed bug in :program:`clang-tidy` by which `HeaderFilterRegex` did not take
98+
effect when passed via the `.clang-tidy` file.
99+
97100
New checks
98101
^^^^^^^^^^
99102

Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
HeaderFilterRegex: '.*'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// RUN: clang-tidy -checks=-*,google-explicit-constructor %s 2>&1 | FileCheck %s
2+
#include "foo.h"
3+
// CHECK: foo.h:1:12: warning: single-argument constructors must be marked explicit
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
struct X { X(int); };
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
InheritParentConfig: true
2+
HeaderFilterRegex: 'subfolder/.*'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// shell is required for the "dirname" command
2+
// REQUIRES: shell
3+
// RUN: clang-tidy -checks=-*,google-explicit-constructor %s -- -I "$(dirname %S)" 2>&1 | FileCheck %s
4+
#include "foo.h"
5+
// CHECK-NOT: foo.h:1:12: warning: single-argument constructors must be marked explicit
6+
7+
#include "bar.h"
8+
// CHECK: bar.h:1:13: warning: single-argument constructors must be marked explicit
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
struct XX { XX(int); };
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
HeaderFilterRegex: '.*'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// RUN: clang-tidy -checks=-*,google-explicit-constructor %s 2>&1 | FileCheck %s
2+
#include "foo.h"
3+
// CHECK: foo.h:1:12: warning: single-argument constructors must be marked explicit
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
struct X { X(int); };

0 commit comments

Comments
 (0)