Skip to content

Add option to exclude headers from clang-tidy analysis #91400

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 17 additions & 11 deletions clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,18 @@ ClangTidyDiagnosticConsumer::ClangTidyDiagnosticConsumer(
: Context(Ctx), ExternalDiagEngine(ExternalDiagEngine),
RemoveIncompatibleErrors(RemoveIncompatibleErrors),
GetFixesFromNotes(GetFixesFromNotes),
EnableNolintBlocks(EnableNolintBlocks) {}
EnableNolintBlocks(EnableNolintBlocks) {

if (Context.getOptions().HeaderFilterRegex &&
!Context.getOptions().HeaderFilterRegex->empty())
HeaderFilter =
std::make_unique<llvm::Regex>(*Context.getOptions().HeaderFilterRegex);

if (Context.getOptions().ExcludeHeaderFilterRegex &&
!Context.getOptions().ExcludeHeaderFilterRegex->empty())
ExcludeHeaderFilter = std::make_unique<llvm::Regex>(
*Context.getOptions().ExcludeHeaderFilterRegex);
}

void ClangTidyDiagnosticConsumer::finalizeLastError() {
if (!Errors.empty()) {
Expand Down Expand Up @@ -562,22 +573,17 @@ void ClangTidyDiagnosticConsumer::checkFilters(SourceLocation Location,
}

StringRef FileName(File->getName());
LastErrorRelatesToUserCode = LastErrorRelatesToUserCode ||
Sources.isInMainFile(Location) ||
getHeaderFilter()->match(FileName);
LastErrorRelatesToUserCode =
LastErrorRelatesToUserCode || Sources.isInMainFile(Location) ||
(HeaderFilter &&
(HeaderFilter->match(FileName) &&
!(ExcludeHeaderFilter && ExcludeHeaderFilter->match(FileName))));

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
Expand Down
1 change: 1 addition & 0 deletions clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,7 @@ class ClangTidyDiagnosticConsumer : public DiagnosticConsumer {
bool EnableNolintBlocks;
std::vector<ClangTidyError> Errors;
std::unique_ptr<llvm::Regex> HeaderFilter;
std::unique_ptr<llvm::Regex> ExcludeHeaderFilter;
bool LastErrorRelatesToUserCode = false;
bool LastErrorPassesLineFilter = false;
bool LastErrorWasIgnored = false;
Expand Down
6 changes: 5 additions & 1 deletion clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,8 @@ template <> struct MappingTraits<ClangTidyOptions> {
IO.mapOptional("ImplementationFileExtensions",
Options.ImplementationFileExtensions);
IO.mapOptional("HeaderFilterRegex", Options.HeaderFilterRegex);
IO.mapOptional("ExcludeHeaderFilterRegex",
Options.ExcludeHeaderFilterRegex);
IO.mapOptional("FormatStyle", Options.FormatStyle);
IO.mapOptional("User", Options.User);
IO.mapOptional("CheckOptions", Options.CheckOptions);
Expand All @@ -191,7 +193,8 @@ ClangTidyOptions ClangTidyOptions::getDefaults() {
Options.WarningsAsErrors = "";
Options.HeaderFileExtensions = {"", "h", "hh", "hpp", "hxx"};
Options.ImplementationFileExtensions = {"c", "cc", "cpp", "cxx"};
Options.HeaderFilterRegex = "";
Options.HeaderFilterRegex = std::nullopt;
Options.ExcludeHeaderFilterRegex = std::nullopt;
Options.SystemHeaders = false;
Options.FormatStyle = "none";
Options.User = std::nullopt;
Expand Down Expand Up @@ -231,6 +234,7 @@ ClangTidyOptions &ClangTidyOptions::mergeWith(const ClangTidyOptions &Other,
overrideValue(ImplementationFileExtensions,
Other.ImplementationFileExtensions);
overrideValue(HeaderFilterRegex, Other.HeaderFilterRegex);
overrideValue(ExcludeHeaderFilterRegex, Other.ExcludeHeaderFilterRegex);
overrideValue(SystemHeaders, Other.SystemHeaders);
overrideValue(FormatStyle, Other.FormatStyle);
overrideValue(User, Other.User);
Expand Down
4 changes: 4 additions & 0 deletions clang-tools-extra/clang-tidy/ClangTidyOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ struct ClangTidyOptions {
/// main files will always be displayed.
std::optional<std::string> HeaderFilterRegex;

/// \brief Exclude warnings from headers matching this filter, even if they
/// match \c HeaderFilterRegex.
std::optional<std::string> ExcludeHeaderFilterRegex;

/// Output warnings from system headers matching \c HeaderFilterRegex.
std::optional<bool> SystemHeaders;

Expand Down
18 changes: 18 additions & 0 deletions clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ Configuration files:
Checks - Same as '--checks'. Additionally, the list of
globs can be specified as a list instead of a
string.
ExcludeHeaderFilterRegex - Same as '--exclude-header-filter'.
ExtraArgs - Same as '--extra-args'.
ExtraArgsBefore - Same as '--extra-args-before'.
FormatStyle - Same as '--format-style'.
Expand Down Expand Up @@ -132,6 +133,20 @@ option in .clang-tidy file, if any.
cl::init(""),
cl::cat(ClangTidyCategory));

static cl::opt<std::string> ExcludeHeaderFilter("exclude-header-filter",
desc(R"(
Regular expression matching the names of the
headers to exclude diagnostics from. Diagnostics
from the main file of each translation unit are
always displayed.
Must be used together with --header-filter.
Can be used together with -line-filter.
This option overrides the 'ExcludeHeaderFilterRegex'
option in .clang-tidy file, if any.
)"),
cl::init(""),
cl::cat(ClangTidyCategory));

static cl::opt<bool> SystemHeaders("system-headers", desc(R"(
Display the errors from system headers.
This option overrides the 'SystemHeaders' option
Expand Down Expand Up @@ -353,6 +368,7 @@ static std::unique_ptr<ClangTidyOptionsProvider> createOptionsProvider(
DefaultOptions.Checks = DefaultChecks;
DefaultOptions.WarningsAsErrors = "";
DefaultOptions.HeaderFilterRegex = HeaderFilter;
DefaultOptions.ExcludeHeaderFilterRegex = ExcludeHeaderFilter;
DefaultOptions.SystemHeaders = SystemHeaders;
DefaultOptions.FormatStyle = FormatStyle;
DefaultOptions.User = llvm::sys::Process::GetEnv("USER");
Expand All @@ -367,6 +383,8 @@ static std::unique_ptr<ClangTidyOptionsProvider> createOptionsProvider(
OverrideOptions.WarningsAsErrors = WarningsAsErrors;
if (HeaderFilter.getNumOccurrences() > 0)
OverrideOptions.HeaderFilterRegex = HeaderFilter;
if (ExcludeHeaderFilter.getNumOccurrences() > 0)
OverrideOptions.ExcludeHeaderFilterRegex = ExcludeHeaderFilter;
if (SystemHeaders.getNumOccurrences() > 0)
OverrideOptions.SystemHeaders = SystemHeaders;
if (FormatStyle.getNumOccurrences() > 0)
Expand Down
13 changes: 13 additions & 0 deletions clang-tools-extra/clang-tidy/tool/run-clang-tidy.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,11 +106,14 @@ def get_tidy_invocation(
use_color,
plugins,
warnings_as_errors,
exclude_header_filter,
):
"""Gets a command line for clang-tidy."""
start = [clang_tidy_binary]
if allow_enabling_alpha_checkers:
start.append("-allow-enabling-analyzer-alpha-checkers")
if exclude_header_filter is not None:
start.append("--exclude-header-filter=" + exclude_header_filter)
if header_filter is not None:
start.append("-header-filter=" + header_filter)
if line_filter is not None:
Expand Down Expand Up @@ -228,6 +231,7 @@ def run_tidy(args, clang_tidy_binary, tmpdir, build_path, queue, lock, failed_fi
args.use_color,
args.plugins,
args.warnings_as_errors,
args.exclude_header_filter,
)

proc = subprocess.Popen(
Expand Down Expand Up @@ -292,6 +296,14 @@ def main():
"-config option after reading specified config file. "
"Use either -config-file or -config, not both.",
)
parser.add_argument(
"-exclude-header-filter",
default=None,
help="Regular expression matching the names of the "
"headers to exclude diagnostics from. Diagnostics from "
"the main file of each translation unit are always "
"displayed.",
)
parser.add_argument(
"-header-filter",
default=None,
Expand Down Expand Up @@ -450,6 +462,7 @@ def main():
args.use_color,
args.plugins,
args.warnings_as_errors,
args.exclude_header_filter,
)
invocation.append("-list-checks")
invocation.append("-")
Expand Down
3 changes: 3 additions & 0 deletions clang-tools-extra/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,9 @@ Improvements to clang-tidy
- Fixed `--verify-config` option not properly parsing checks when using the
literal operator in the `.clang-tidy` config.

- Added argument `--exclude-header-filter` and config option `ExcludeHeaderFilterRegex`
to exclude headers from analysis via a RegEx.

New checks
^^^^^^^^^^

Expand Down
Loading
Loading