[clang-tools-extra] [llvm] Port clang-tidy to Opts.td and multicall (PR #201743)
David Zbarsky via cfe-commits
cfe-commits at lists.llvm.org
Fri Jun 5 08:06:13 PDT 2026
https://github.com/dzbarsky updated https://github.com/llvm/llvm-project/pull/201743
>From 06b1358960b03044e84b2f3133124846d1b67d03 Mon Sep 17 00:00:00 2001
From: David Zbarsky <dzbarsky at gmail.com>
Date: Thu, 4 Jun 2026 23:38:43 -0400
Subject: [PATCH] Port clang-tidy to Opts.td and multicall
---
.../clang-tidy/tool/CMakeLists.txt | 8 +
.../clang-tidy/tool/ClangTidyMain.cpp | 622 +++++++++---------
.../clang-tidy/tool/ClangTidyMain.h | 2 +-
.../clang-tidy/tool/ClangTidyToolMain.cpp | 3 +-
clang-tools-extra/clang-tidy/tool/Opts.td | 245 +++++++
clang-tools-extra/docs/clang-tidy/index.rst | 331 +++++-----
.../infrastructure/invalid-command-line.cpp | 3 +-
.../clang-tools-extra/clang-tidy/BUILD.bazel | 22 +-
.../llvm-project-overlay/llvm/driver.bzl | 1 +
9 files changed, 738 insertions(+), 499 deletions(-)
create mode 100644 clang-tools-extra/clang-tidy/tool/Opts.td
diff --git a/clang-tools-extra/clang-tidy/tool/CMakeLists.txt b/clang-tools-extra/clang-tidy/tool/CMakeLists.txt
index 0d4501d1eac06..da007f49c934a 100644
--- a/clang-tools-extra/clang-tidy/tool/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/tool/CMakeLists.txt
@@ -3,10 +3,15 @@ set(LLVM_LINK_COMPONENTS
AllTargetsDescs
AllTargetsInfos
FrontendOpenMP
+ Option
TargetParser
support
)
+set(LLVM_TARGET_DEFINITIONS Opts.td)
+tablegen(LLVM Opts.inc -gen-opt-parser-defs)
+add_public_tablegen_target(ClangTidyOptsTableGen)
+
# Needed by LLVM's CMake checks because this file defines multiple targets.
set(LLVM_OPTIONAL_SOURCES ClangTidyMain.cpp ClangTidyToolMain.cpp)
@@ -20,6 +25,7 @@ add_clang_library(clangTidyMain STATIC
DEPENDS
omp_gen
ClangDriverOptions
+ ClangTidyOptsTableGen
)
clang_target_link_libraries(clangTidyMain
@@ -42,6 +48,8 @@ add_clang_tool(clang-tidy
DEPENDS
clang-resource-headers
${support_plugins}
+
+ GENERATE_DRIVER
)
clang_target_link_libraries(clang-tidy
PRIVATE
diff --git a/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp b/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
index 949a88f0fd50d..89ae0f497abeb 100644
--- a/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
+++ b/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
@@ -18,13 +18,22 @@
#include "../ClangTidy.h"
#include "../ClangTidyForceLinker.h" // IWYU pragma: keep
#include "../GlobList.h"
+#include "clang/Basic/Version.h"
#include "clang/Tooling/CommonOptionsParser.h"
+#include "clang/Tooling/CompilationDatabase.h"
+#include "clang/Tooling/Tooling.h"
#include "llvm/ADT/StringSet.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Option/Arg.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Option/Option.h"
+#include "llvm/Support/Allocator.h"
#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/InitLLVM.h"
+#define DONT_GET_PLUGIN_LOADER_OPTION
#include "llvm/Support/PluginLoader.h" // IWYU pragma: keep
#include "llvm/Support/Process.h"
#include "llvm/Support/Signals.h"
+#include "llvm/Support/StringSaver.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/WithColor.h"
#include "llvm/TargetParser/Host.h"
@@ -33,17 +42,62 @@
using namespace clang::tooling;
using namespace llvm;
-static cl::desc desc(StringRef Description) { return {Description.ltrim()}; }
-
-static cl::OptionCategory ClangTidyCategory("clang-tidy options");
-
-static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage);
-static cl::extrahelp ClangTidyParameterFileHelp(R"(
+namespace {
+using namespace llvm::opt;
+
+enum ID {
+ OPT_INVALID = 0,
+#define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__),
+#include "Opts.inc"
+#undef OPTION
+};
+
+#define OPTTABLE_STR_TABLE_CODE
+#include "Opts.inc"
+#undef OPTTABLE_STR_TABLE_CODE
+
+#define OPTTABLE_PREFIXES_TABLE_CODE
+#include "Opts.inc"
+#undef OPTTABLE_PREFIXES_TABLE_CODE
+
+static constexpr opt::OptTable::Info InfoTable[] = {
+#define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
+#include "Opts.inc"
+#undef OPTION
+};
+
+class ClangTidyOptTable : public opt::GenericOptTable {
+public:
+ ClangTidyOptTable()
+ : opt::GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) {}
+};
+
+static constexpr llvm::StringLiteral CommonHelp = R"(
+-p <build-path> is used to read a compile command database.
+
+ For example, it can be a CMake build directory in which a file named
+ compile_commands.json exists (use -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
+ CMake option to get this output). When no build path is specified,
+ a search for compile_commands.json will be attempted through all
+ parent paths of the first input file. See:
+ https://clang.llvm.org/docs/HowToSetupToolingForLLVM.html for an
+ example of setting up Clang Tooling on a source tree.
+
+<source0> ... specify the paths of source files. These paths are
+ looked up in the compile command database. If the path of a file is
+ absolute, it needs to point into CMake's source tree. If the path is
+ relative, the current working directory needs to be in the CMake
+ source tree and the file must be in a subdirectory of the current
+ working directory. "./" prefixes in the relative files will be
+ automatically removed, but the rest of a relative path must be a
+ suffix of a path in the compile command database.
+)";
+static constexpr llvm::StringLiteral ClangTidyParameterFileHelp = R"(
Parameters files:
A large number of options or source files can be passed as parameter files
by use '@parameter-file' in the command line.
-)");
-static cl::extrahelp ClangTidyHelp(R"(
+)";
+static constexpr llvm::StringLiteral ClangTidyHelp = R"(
Configuration files:
clang-tidy attempts to read configuration for each source file from a
.clang-tidy file located in the closest parent directory of the source
@@ -102,270 +156,221 @@ Configuration files:
some-check.SomeOption: 'some value'
...
-)");
+)";
const char DefaultChecks[] = // Enable these checks by default:
"clang-diagnostic-*"; // * compiler diagnostics
-static cl::opt<std::string> Checks("checks", desc(R"(
-Comma-separated list of globs with optional '-'
-prefix. Globs are processed in order of
-appearance in the list. Globs without '-'
-prefix add checks with matching names to the
-set, globs with the '-' prefix remove checks
-with matching names from the set of enabled
-checks. This option's value is appended to the
-value of the 'Checks' option in .clang-tidy
-file, if any.
-)"),
- cl::init(""), cl::cat(ClangTidyCategory));
-
-static cl::opt<std::string> WarningsAsErrors("warnings-as-errors", desc(R"(
-Upgrades warnings to errors. Same format as
-'-checks'.
-This option's value is appended to the value of
-the 'WarningsAsErrors' option in .clang-tidy
-file, if any.
-)"),
- cl::init(""),
- cl::cat(ClangTidyCategory));
-
-static cl::opt<std::string> HeaderFilter("header-filter", desc(R"(
-Regular expression matching the names of the
-headers to output diagnostics from. The default
-value is '.*', i.e. diagnostics from all non-system
-headers are displayed by default. Diagnostics
-from the main file of each translation unit are
-always displayed.
-Can be used together with -line-filter.
-This option overrides the 'HeaderFilterRegex'
-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
-in .clang-tidy file, if any.
-)"),
- cl::init(false), cl::cat(ClangTidyCategory));
-
-static cl::opt<std::string> LineFilter("line-filter", desc(R"(
-List of files and line ranges to output diagnostics from.
-The range is inclusive on both ends. Can be used together
-with -header-filter. The format of the list is a JSON
-array of objects. For example:
-
- [
- {"name":"file1.cpp","lines":[[1,3],[5,7]]},
- {"name":"file2.h"}
- ]
-
-This will output diagnostics from 'file1.cpp' only for
-the line ranges [1,3] and [5,7], as well as all from the
-entire 'file2.h'.
-)"),
- cl::init(""),
- cl::cat(ClangTidyCategory));
-
-static cl::opt<bool> Fix("fix", desc(R"(
-Apply suggested fixes. Without -fix-errors
-clang-tidy will bail out if any compilation
-errors were found.
-)"),
- cl::init(false), cl::cat(ClangTidyCategory));
-
-static cl::opt<bool> FixErrors("fix-errors", desc(R"(
-Apply suggested fixes even if compilation
-errors were found. If compiler errors have
-attached fix-its, clang-tidy will apply them as
-well.
-)"),
- cl::init(false), cl::cat(ClangTidyCategory));
-
-static cl::opt<bool> FixNotes("fix-notes", desc(R"(
-If a warning has no fix, but a single fix can
-be found through an associated diagnostic note,
-apply the fix.
-Specifying this flag will implicitly enable the
-'--fix' flag.
-)"),
- cl::init(false), cl::cat(ClangTidyCategory));
-
-static cl::opt<std::string> FormatStyle("format-style", desc(R"(
-Style for formatting code around applied fixes:
- - 'none' (default) turns off formatting
- - 'file' (literally 'file', not a placeholder)
- uses .clang-format file in the closest parent
- directory
- - '{ <json> }' specifies options inline, e.g.
- -format-style='{BasedOnStyle: llvm, IndentWidth: 8}'
- - 'llvm', 'google', 'webkit', 'mozilla'
-See clang-format documentation for the up-to-date
-information about formatting styles and options.
-This option overrides the 'FormatStyle` option in
-.clang-tidy file, if any.
-)"),
- cl::init("none"),
- cl::cat(ClangTidyCategory));
-
-static cl::opt<bool> ListChecks("list-checks", desc(R"(
-List all enabled checks and exit. Use with
--checks=* to list all available checks.
-)"),
- cl::init(false), cl::cat(ClangTidyCategory));
-
-static cl::opt<bool> ExplainConfig("explain-config", desc(R"(
-For each enabled check explains, where it is
-enabled, i.e. in clang-tidy binary, command
-line or a specific configuration file.
-)"),
- cl::init(false), cl::cat(ClangTidyCategory));
-
-static cl::opt<std::string> Config("config", desc(R"(
-Specifies a configuration in YAML/JSON format:
- -config="{Checks: '*',
- CheckOptions: {x: y}}"
-When the value is empty, clang-tidy will
-attempt to find a file named .clang-tidy for
-each source file in its parent directories.
-)"),
- cl::init(""), cl::cat(ClangTidyCategory));
-
-static cl::opt<std::string> ConfigFile("config-file", desc(R"(
-Specify the path of .clang-tidy or custom config file:
- e.g. --config-file=/some/path/myTidyConfigFile
-This option internally works exactly the same way as
- --config option after reading specified config file.
-Use either --config-file or --config, not both.
-)"),
- cl::init(""),
- cl::cat(ClangTidyCategory));
-
-static cl::opt<bool> DumpConfig("dump-config", desc(R"(
-Dumps configuration in the YAML format to
-stdout. This option can be used along with a
-file name (and '--' if the file is outside of a
-project with configured compilation database).
-The configuration used for this file will be
-printed.
-Use along with -checks=* to include
-configuration of all checks.
-)"),
- cl::init(false), cl::cat(ClangTidyCategory));
-
-static cl::opt<bool> EnableCheckProfile("enable-check-profile", desc(R"(
-Enable per-check timing profiles, and print a
-report to stderr.
-)"),
- cl::init(false),
- cl::cat(ClangTidyCategory));
-
-static cl::opt<std::string> StoreCheckProfile("store-check-profile", desc(R"(
-By default reports are printed in tabulated
-format to stderr. When this option is passed,
-these per-TU profiles are instead stored as JSON.
-)"),
- cl::value_desc("prefix"),
- cl::cat(ClangTidyCategory));
-
-/// This option allows enabling the experimental alpha checkers from the static
-/// analyzer. This option is set to false and not visible in help, because it is
-/// highly not recommended for users.
-static cl::opt<bool>
- AllowEnablingAnalyzerAlphaCheckers("allow-enabling-analyzer-alpha-checkers",
- cl::init(false), cl::Hidden,
- cl::cat(ClangTidyCategory));
-
-static cl::opt<bool> EnableModuleHeadersParsing("enable-module-headers-parsing",
- desc(R"(
-Enables preprocessor-level module header parsing
-for C++20 and above, empowering specific checks
-to detect macro definitions within modules. This
-feature may cause performance and parsing issues
-and is therefore considered experimental.
-)"),
- cl::init(false),
- cl::cat(ClangTidyCategory));
-
-static cl::opt<std::string> ExportFixes("export-fixes", desc(R"(
-YAML file to store suggested fixes in. The
-stored fixes can be applied to the input source
-code with clang-apply-replacements.
-)"),
- cl::value_desc("filename"),
- cl::cat(ClangTidyCategory));
-
-static cl::opt<bool> Quiet("quiet", desc(R"(
-Run clang-tidy in quiet mode. This suppresses
-printing statistics about ignored warnings and
-warnings treated as errors if the respective
-options are specified.
-)"),
- cl::init(false), cl::cat(ClangTidyCategory));
-
-static cl::opt<std::string> VfsOverlay("vfsoverlay", desc(R"(
-Overlay the virtual filesystem described by file
-over the real file system.
-)"),
- cl::value_desc("filename"),
- cl::cat(ClangTidyCategory));
-
-static cl::opt<bool> UseColor("use-color", desc(R"(
-Use colors in diagnostics. If not set, colors
-will be used if the terminal connected to
-standard output supports colors.
-This option overrides the 'UseColor' option in
-.clang-tidy file, if any.
-)"),
- cl::init(false), cl::cat(ClangTidyCategory));
-
-static cl::opt<bool> VerifyConfig("verify-config", desc(R"(
-Check the config files to ensure each check and
-option is recognized without running any checks.
-)"),
- cl::init(false), cl::cat(ClangTidyCategory));
-
-static cl::opt<bool> AllowNoChecks("allow-no-checks", desc(R"(
-Allow empty enabled checks. This suppresses
-the "no checks enabled" error when disabling
-all of the checks.
-)"),
- cl::init(false), cl::cat(ClangTidyCategory));
-
-static cl::opt<bool> ExperimentalCustomChecks("experimental-custom-checks",
- desc(R"(
-Enable experimental clang-query based
-custom checks.
-see https://clang.llvm.org/extra/clang-tidy/QueryBasedCustomChecks.html.
-)"),
- cl::init(false),
- cl::cat(ClangTidyCategory));
-
-static cl::list<std::string> RemovedArgs("removed-arg", desc(R"(
-List of arguments to remove from the command
-line sent to the compiler. Please note that
-removing arguments might change the semantic
-of the analyzed code, possibly leading to
-compiler errors, false positives or
-false negatives. This option is applied
-before --extra-arg and --extra-arg-before)"),
- cl::cat(ClangTidyCategory));
+static std::string Checks;
+static bool ChecksSpecified;
+static std::string WarningsAsErrors;
+static bool WarningsAsErrorsSpecified;
+static std::string HeaderFilter;
+static bool HeaderFilterSpecified;
+static std::string ExcludeHeaderFilter;
+static bool ExcludeHeaderFilterSpecified;
+static bool SystemHeaders;
+static bool SystemHeadersSpecified;
+static std::string LineFilter;
+static bool Fix;
+static bool FixErrors;
+static bool FixNotes;
+static std::string FormatStyle;
+static bool FormatStyleSpecified;
+static bool ListChecks;
+static bool ExplainConfig;
+static std::string Config;
+static bool ConfigSpecified;
+static std::string ConfigFile;
+static bool ConfigFileSpecified;
+static bool DumpConfig;
+static bool EnableCheckProfile;
+static std::string StoreCheckProfile;
+static bool AllowEnablingAnalyzerAlphaCheckers;
+static bool EnableModuleHeadersParsing;
+static std::string ExportFixes;
+static bool Quiet;
+static std::string VfsOverlay;
+static bool UseColor;
+static bool UseColorSpecified;
+static bool VerifyConfig;
+static bool AllowNoChecks;
+static bool ExperimentalCustomChecks;
+static std::vector<std::string> RemovedArgs;
+static bool RemovedArgsSpecified;
+
+static void printHelp(bool ShowHidden = false) {
+ ClangTidyOptTable Tbl;
+ Tbl.printHelp(outs(),
+ "clang-tidy [options] <source0> [... <sourceN>] "
+ "[-- <compiler arguments>]",
+ "clang-tidy", ShowHidden);
+ outs() << CommonHelp << ClangTidyParameterFileHelp << ClangTidyHelp;
+}
+
+static bool parseBoolArg(const opt::Arg *A, unsigned ValueID, bool &Value) {
+ if (!A->getOption().matches(ValueID)) {
+ Value = true;
+ return true;
+ }
+ std::optional<bool> Parsed = StringSwitch<std::optional<bool>>(A->getValue())
+ .CaseLower("true", true)
+ .Case("1", true)
+ .CaseLower("false", false)
+ .Case("0", false)
+ .Default(std::nullopt);
+ if (Parsed) {
+ Value = *Parsed;
+ return true;
+ }
+ errs() << "clang-tidy: invalid value '" << A->getValue() << "' for option '"
+ << A->getSpelling() << "'\n";
+ return false;
+}
+
+static bool parseBoolArg(const opt::InputArgList &Args, unsigned FlagID,
+ unsigned ValueID, bool &Value,
+ bool *Specified = nullptr) {
+ const opt::Arg *A = Args.getLastArg(FlagID, ValueID);
+ if (Specified)
+ *Specified = A != nullptr;
+ Value = false;
+ return !A || parseBoolArg(A, ValueID, Value);
+}
+
+static bool parseCommandLine(int argc, char **argv, BumpPtrAllocator &Allocator,
+ StringSaver &Saver, ClangTidyOptTable &Tbl,
+ opt::InputArgList &Args,
+ std::unique_ptr<CompilationDatabase> &Compilations,
+ std::vector<std::string> &SourcePaths) {
+ SmallVector<const char *> ExpandedArgs(argv, argv + argc);
+ cl::TokenizerCallback Tokenizer =
+ Triple(sys::getProcessTriple()).isOSWindows()
+ ? cl::TokenizeWindowsCommandLine
+ : cl::TokenizeGNUCommandLine;
+ cl::ExpansionContext ECtx(Allocator, Tokenizer);
+ if (Error Err = ECtx.expandResponseFiles(ExpandedArgs)) {
+ WithColor::error() << toString(std::move(Err)) << "\n";
+ return false;
+ }
+
+ int ToolArgc = static_cast<int>(ExpandedArgs.size());
+ std::string FixedDatabaseError;
+ Compilations = FixedCompilationDatabase::loadFromCommandLine(
+ ToolArgc, ExpandedArgs.data(), FixedDatabaseError);
+
+ SmallVector<char *> ToolArgv;
+ ToolArgv.reserve(ToolArgc);
+ for (const char *Arg : ArrayRef(ExpandedArgs).take_front(ToolArgc))
+ ToolArgv.push_back(const_cast<char *>(Arg));
+
+ bool HasError = false;
+ Args = Tbl.parseArgs(ToolArgc, ToolArgv.data(), OPT_UNKNOWN, Saver,
+ [&](StringRef Message) {
+ errs() << "clang-tidy: " << Message << '\n';
+ HasError = true;
+ });
+ if (HasError) {
+ if (!FixedDatabaseError.empty())
+ errs() << FixedDatabaseError;
+ return false;
+ }
+
+ Checks = Args.getLastArgValue(OPT_checks_EQ);
+ ChecksSpecified = Args.hasArg(OPT_checks_EQ);
+ WarningsAsErrors = Args.getLastArgValue(OPT_warnings_as_errors_EQ);
+ WarningsAsErrorsSpecified = Args.hasArg(OPT_warnings_as_errors_EQ);
+ HeaderFilter = Args.getLastArgValue(OPT_header_filter_EQ, ".*");
+ HeaderFilterSpecified = Args.hasArg(OPT_header_filter_EQ);
+ ExcludeHeaderFilter = Args.getLastArgValue(OPT_exclude_header_filter_EQ);
+ ExcludeHeaderFilterSpecified = Args.hasArg(OPT_exclude_header_filter_EQ);
+ LineFilter = Args.getLastArgValue(OPT_line_filter_EQ);
+ FormatStyle = Args.getLastArgValue(OPT_format_style_EQ, "none");
+ FormatStyleSpecified = Args.hasArg(OPT_format_style_EQ);
+ Config = Args.getLastArgValue(OPT_config_EQ);
+ ConfigSpecified = Args.hasArg(OPT_config_EQ);
+ ConfigFile = Args.getLastArgValue(OPT_config_file_EQ);
+ ConfigFileSpecified = Args.hasArg(OPT_config_file_EQ);
+ StoreCheckProfile = Args.getLastArgValue(OPT_store_check_profile_EQ);
+ ExportFixes = Args.getLastArgValue(OPT_export_fixes_EQ);
+ VfsOverlay = Args.getLastArgValue(OPT_vfsoverlay_EQ);
+ RemovedArgs = Args.getAllArgValues(OPT_removed_arg_EQ);
+ RemovedArgsSpecified = Args.hasArg(OPT_removed_arg_EQ);
+ SourcePaths = Args.getAllArgValues(OPT_INPUT);
+
+ if (!parseBoolArg(Args, OPT_system_headers, OPT_system_headers_EQ,
+ SystemHeaders, &SystemHeadersSpecified) ||
+ !parseBoolArg(Args, OPT_fix, OPT_fix_EQ, Fix) ||
+ !parseBoolArg(Args, OPT_fix_errors, OPT_fix_errors_EQ, FixErrors) ||
+ !parseBoolArg(Args, OPT_fix_notes, OPT_fix_notes_EQ, FixNotes) ||
+ !parseBoolArg(Args, OPT_list_checks, OPT_list_checks_EQ, ListChecks) ||
+ !parseBoolArg(Args, OPT_explain_config, OPT_explain_config_EQ,
+ ExplainConfig) ||
+ !parseBoolArg(Args, OPT_dump_config, OPT_dump_config_EQ, DumpConfig) ||
+ !parseBoolArg(Args, OPT_enable_check_profile, OPT_enable_check_profile_EQ,
+ EnableCheckProfile) ||
+ !parseBoolArg(Args, OPT_allow_enabling_analyzer_alpha_checkers,
+ OPT_allow_enabling_analyzer_alpha_checkers_EQ,
+ AllowEnablingAnalyzerAlphaCheckers) ||
+ !parseBoolArg(Args, OPT_enable_module_headers_parsing,
+ OPT_enable_module_headers_parsing_EQ,
+ EnableModuleHeadersParsing) ||
+ !parseBoolArg(Args, OPT_quiet, OPT_quiet_EQ, Quiet) ||
+ !parseBoolArg(Args, OPT_use_color, OPT_use_color_EQ, UseColor,
+ &UseColorSpecified) ||
+ !parseBoolArg(Args, OPT_verify_config, OPT_verify_config_EQ,
+ VerifyConfig) ||
+ !parseBoolArg(Args, OPT_allow_no_checks, OPT_allow_no_checks_EQ,
+ AllowNoChecks) ||
+ !parseBoolArg(Args, OPT_experimental_custom_checks,
+ OPT_experimental_custom_checks_EQ,
+ ExperimentalCustomChecks))
+ return false;
+
+ for (StringRef Plugin : Args.getAllArgValues(OPT_load_EQ)) {
+ PluginLoader Loader;
+ Loader = Plugin.str();
+ }
+
+ if (SourcePaths.empty()) {
+ if (!Compilations)
+ Compilations = std::make_unique<FixedCompilationDatabase>(
+ ".", std::vector<std::string>());
+ return true;
+ }
+
+ if (!Compilations) {
+ std::string ErrorMessage;
+ StringRef BuildPath = Args.getLastArgValue(OPT_p);
+ if (!BuildPath.empty())
+ Compilations =
+ CompilationDatabase::autoDetectFromDirectory(BuildPath, ErrorMessage);
+ else
+ Compilations = CompilationDatabase::autoDetectFromSource(
+ SourcePaths.front(), ErrorMessage);
+ if (!Compilations) {
+ errs() << "Error while trying to load a compilation database:\n"
+ << ErrorMessage << "Running without flags.\n";
+ Compilations = std::make_unique<FixedCompilationDatabase>(
+ ".", std::vector<std::string>());
+ }
+ }
+
+ auto AdjustingCompilations =
+ std::make_unique<ArgumentsAdjustingCompilations>(std::move(Compilations));
+ ArgumentsAdjuster Adjuster =
+ getInsertArgumentAdjuster(Args.getAllArgValues(OPT_extra_arg_before_EQ),
+ ArgumentInsertPosition::BEGIN);
+ Adjuster = combineAdjusters(
+ std::move(Adjuster),
+ getInsertArgumentAdjuster(Args.getAllArgValues(OPT_extra_arg_EQ),
+ ArgumentInsertPosition::END));
+ AdjustingCompilations->appendArgumentsAdjuster(std::move(Adjuster));
+ Compilations = std::move(AdjustingCompilations);
+ return true;
+}
+
+} // namespace
namespace clang::tidy {
@@ -402,7 +407,7 @@ createOptionsProvider(llvm::IntrusiveRefCntPtr<vfs::FileSystem> FS) {
ClangTidyGlobalOptions GlobalOptions;
if (const std::error_code Err = parseLineFilter(LineFilter, GlobalOptions)) {
llvm::errs() << "Invalid LineFilter: " << Err.message() << "\n\nUsage:\n";
- llvm::cl::PrintHelpMessage(/*Hidden=*/false, /*Categorized=*/true);
+ printHelp();
return nullptr;
}
@@ -419,21 +424,21 @@ createOptionsProvider(llvm::IntrusiveRefCntPtr<vfs::FileSystem> FS) {
DefaultOptions.User = llvm::sys::Process::GetEnv("USERNAME");
ClangTidyOptions OverrideOptions;
- if (Checks.getNumOccurrences() > 0)
+ if (ChecksSpecified)
OverrideOptions.Checks = Checks;
- if (WarningsAsErrors.getNumOccurrences() > 0)
+ if (WarningsAsErrorsSpecified)
OverrideOptions.WarningsAsErrors = WarningsAsErrors;
- if (HeaderFilter.getNumOccurrences() > 0)
+ if (HeaderFilterSpecified)
OverrideOptions.HeaderFilterRegex = HeaderFilter;
- if (ExcludeHeaderFilter.getNumOccurrences() > 0)
+ if (ExcludeHeaderFilterSpecified)
OverrideOptions.ExcludeHeaderFilterRegex = ExcludeHeaderFilter;
- if (SystemHeaders.getNumOccurrences() > 0)
+ if (SystemHeadersSpecified)
OverrideOptions.SystemHeaders = SystemHeaders;
- if (FormatStyle.getNumOccurrences() > 0)
+ if (FormatStyleSpecified)
OverrideOptions.FormatStyle = FormatStyle;
- if (UseColor.getNumOccurrences() > 0)
+ if (UseColorSpecified)
OverrideOptions.UseColor = UseColor;
- if (RemovedArgs.getNumOccurrences() > 0)
+ if (RemovedArgsSpecified)
OverrideOptions.RemovedArgs = RemovedArgs;
auto LoadConfig =
@@ -451,8 +456,8 @@ createOptionsProvider(llvm::IntrusiveRefCntPtr<vfs::FileSystem> FS) {
return nullptr;
};
- if (ConfigFile.getNumOccurrences() > 0) {
- if (Config.getNumOccurrences() > 0) {
+ if (ConfigFileSpecified) {
+ if (ConfigSpecified) {
llvm::errs() << "Error: --config-file and --config are "
"mutually exclusive. Specify only one.\n";
return nullptr;
@@ -469,7 +474,7 @@ createOptionsProvider(llvm::IntrusiveRefCntPtr<vfs::FileSystem> FS) {
return LoadConfig((*Text)->getBuffer(), ConfigFile);
}
- if (Config.getNumOccurrences() > 0)
+ if (ConfigSpecified)
return LoadConfig(Config, "<command-line-config>");
return std::make_unique<FileOptionsProvider>(
@@ -511,7 +516,8 @@ static StringRef closest(StringRef Value, const StringSet<> &Allowed) {
return Closest;
}
-static constexpr StringLiteral VerifyConfigWarningEnd = " [-verify-config]\n";
+static constexpr llvm::StringLiteral VerifyConfigWarningEnd =
+ " [-verify-config]\n";
static bool verifyChecks(const StringSet<> &AllChecks, StringRef CheckGlob,
StringRef Source) {
@@ -604,34 +610,25 @@ static llvm::IntrusiveRefCntPtr<vfs::OverlayFileSystem> createBaseFS() {
return BaseFS;
}
-int clangTidyMain(int argc, const char **argv) {
- const llvm::InitLLVM X(argc, argv);
- SmallVector<const char *> Args{argv, argv + argc};
-
- // expand parameters file to argc and argv.
- llvm::BumpPtrAllocator Alloc;
- llvm::cl::TokenizerCallback Tokenizer =
- llvm::Triple(llvm::sys::getProcessTriple()).isOSWindows()
- ? llvm::cl::TokenizeWindowsCommandLine
- : llvm::cl::TokenizeGNUCommandLine;
- llvm::cl::ExpansionContext ECtx(Alloc, Tokenizer);
- if (llvm::Error Err = ECtx.expandResponseFiles(Args)) {
- llvm::WithColor::error() << llvm::toString(std::move(Err)) << "\n";
+int clangTidyMain(int argc, char **argv) {
+ BumpPtrAllocator Alloc;
+ StringSaver Saver(Alloc);
+ ClangTidyOptTable Tbl;
+ opt::InputArgList Args;
+ std::unique_ptr<CompilationDatabase> Compilations;
+ std::vector<std::string> PathList;
+ if (!parseCommandLine(argc, argv, Alloc, Saver, Tbl, Args, Compilations,
+ PathList))
return 1;
+
+ if (Args.hasArg(OPT_help, OPT_help_hidden)) {
+ printHelp(Args.hasArg(OPT_help_hidden));
+ return 0;
}
- argc = static_cast<int>(Args.size());
- argv = Args.data();
-
- // Enable help for -load option, if plugins are enabled.
- if (cl::Option *LoadOpt = cl::getRegisteredOptions().lookup("load"))
- LoadOpt->addCategory(ClangTidyCategory);
-
- llvm::Expected<CommonOptionsParser> OptionsParser =
- CommonOptionsParser::create(argc, argv, ClangTidyCategory,
- cl::ZeroOrMore);
- if (!OptionsParser) {
- llvm::WithColor::error() << llvm::toString(OptionsParser.takeError());
- return 1;
+
+ if (Args.hasArg(OPT_version)) {
+ outs() << clang::getClangToolFullVersion("clang-tidy") << '\n';
+ return 0;
}
const llvm::IntrusiveRefCntPtr<vfs::OverlayFileSystem> BaseFS =
@@ -647,7 +644,6 @@ int clangTidyMain(int argc, const char **argv) {
const SmallString<256> ProfilePrefix = makeAbsolute(StoreCheckProfile);
StringRef FileName("dummy");
- auto PathList = OptionsParser->getSourcePathList();
if (!PathList.empty())
FileName = PathList.front();
@@ -720,13 +716,13 @@ int clangTidyMain(int argc, const char **argv) {
if (EnabledChecks.empty() && !AllowNoChecks) {
llvm::errs() << "Error: no checks enabled.\n";
- llvm::cl::PrintHelpMessage(/*Hidden=*/false, /*Categorized=*/true);
+ printHelp();
return 1;
}
if (PathList.empty()) {
llvm::errs() << "Error: no input files specified.\n";
- llvm::cl::PrintHelpMessage(/*Hidden=*/false, /*Categorized=*/true);
+ printHelp();
return 1;
}
@@ -738,8 +734,8 @@ int clangTidyMain(int argc, const char **argv) {
std::move(OwningOptionsProvider), AllowEnablingAnalyzerAlphaCheckers,
EnableModuleHeadersParsing, ExperimentalCustomChecks);
std::vector<ClangTidyError> Errors =
- runClangTidy(Context, OptionsParser->getCompilations(), PathList, BaseFS,
- FixNotes, EnableCheckProfile, ProfilePrefix, Quiet);
+ runClangTidy(Context, *Compilations, PathList, BaseFS, FixNotes,
+ EnableCheckProfile, ProfilePrefix, Quiet);
const bool FoundErrors = llvm::any_of(Errors, [](const ClangTidyError &E) {
return E.DiagLevel == ClangTidyError::Error;
});
diff --git a/clang-tools-extra/clang-tidy/tool/ClangTidyMain.h b/clang-tools-extra/clang-tidy/tool/ClangTidyMain.h
index 44b7a379e5277..1ea728ed29571 100644
--- a/clang-tools-extra/clang-tidy/tool/ClangTidyMain.h
+++ b/clang-tools-extra/clang-tidy/tool/ClangTidyMain.h
@@ -19,7 +19,7 @@
namespace clang::tidy {
-int clangTidyMain(int argc, const char **argv);
+int clangTidyMain(int argc, char **argv);
} // namespace clang::tidy
diff --git a/clang-tools-extra/clang-tidy/tool/ClangTidyToolMain.cpp b/clang-tools-extra/clang-tidy/tool/ClangTidyToolMain.cpp
index a2ba638ea15e8..086bfb6af32c5 100644
--- a/clang-tools-extra/clang-tidy/tool/ClangTidyToolMain.cpp
+++ b/clang-tools-extra/clang-tidy/tool/ClangTidyToolMain.cpp
@@ -15,7 +15,8 @@
//===----------------------------------------------------------------------===//
#include "ClangTidyMain.h"
+#include "llvm/Support/LLVMDriver.h"
-int main(int argc, const char **argv) {
+int clang_tidy_main(int argc, char **argv, const llvm::ToolContext &) {
return clang::tidy::clangTidyMain(argc, argv);
}
diff --git a/clang-tools-extra/clang-tidy/tool/Opts.td b/clang-tools-extra/clang-tidy/tool/Opts.td
new file mode 100644
index 0000000000000..6610d5fe5cd97
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/tool/Opts.td
@@ -0,0 +1,245 @@
+include "llvm/Option/OptParser.td"
+
+def clang_tidy_group : OptionGroup<"clang-tidy">,
+ HelpText<"clang-tidy options">;
+def generic_group : OptionGroup<"generic">, HelpText<"Generic Options">;
+
+class F<string name, string help>
+ : Flag<["--", "-"], name>, HelpText<help>, Group<clang_tidy_group>;
+
+multiclass B<string name, string help> {
+ def NAME : F<name, help>;
+ def NAME #_EQ : Joined<["--", "-"], name #"=">,
+ MetaVarName<"<true|false>">,
+ Group<clang_tidy_group>, Flags<[HelpHidden]>;
+}
+
+multiclass BH<string name> {
+ def NAME : Flag<["--", "-"], name>, Group<clang_tidy_group>,
+ Flags<[HelpHidden]>;
+ def NAME #_EQ : Joined<["--", "-"], name #"=">,
+ MetaVarName<"<true|false>">,
+ Group<clang_tidy_group>, Flags<[HelpHidden]>;
+}
+
+multiclass Eq<string name, string metavar, string help> {
+ def NAME #_EQ : Joined<["--", "-"], name #"=">,
+ HelpText<help>, MetaVarName<metavar>,
+ Group<clang_tidy_group>;
+ def : Separate<["--", "-"], name>, Alias<!cast<Joined>(NAME #_EQ)>;
+}
+
+class GF<string name, string help>
+ : Flag<["--", "-"], name>, HelpText<help>, Group<generic_group>;
+
+def help : GF<"help", "Display available options (--help-hidden for more)">;
+def help_hidden : GF<"help-hidden",
+ "Display all available options, including hidden options">,
+ Flags<[HelpHidden]>;
+def help_list
+ : GF<"help-list",
+ "Display list of available options (--help-list-hidden for more)">,
+ Alias<help>;
+def help_list_hidden
+ : GF<"help-list-hidden", "Display list of all available options">,
+ Alias<help_hidden>, Flags<[HelpHidden]>;
+def version : GF<"version", "Display the version of this program">;
+def h : GF<"h", "Alias for --help">, Alias<help>, Flags<[HelpHidden]>;
+
+defm checks : Eq<"checks", "<string>",
+ "Comma-separated list of globs with optional '-'\n"
+ "prefix. Globs are processed in order of\n"
+ "appearance in the list. Globs without '-'\n"
+ "prefix add checks with matching names to the\n"
+ "set, globs with the '-' prefix remove checks\n"
+ "with matching names from the set of enabled\n"
+ "checks. This option's value is appended to the\n"
+ "value of the 'Checks' option in .clang-tidy\n"
+ "file, if any.">;
+defm warnings_as_errors
+ : Eq<"warnings-as-errors", "<string>",
+ "Upgrades warnings to errors. Same format as\n"
+ "'-checks'.\n"
+ "This option's value is appended to the value of\n"
+ "the 'WarningsAsErrors' option in .clang-tidy\n"
+ "file, if any.">;
+defm header_filter
+ : Eq<"header-filter", "<string>",
+ "Regular expression matching the names of the\n"
+ "headers to output diagnostics from. The default\n"
+ "value is '.*', i.e. diagnostics from all non-system\n"
+ "headers are displayed by default. Diagnostics\n"
+ "from the main file of each translation unit are\n"
+ "always displayed.\n"
+ "Can be used together with -line-filter.\n"
+ "This option overrides the 'HeaderFilterRegex'\n"
+ "option in .clang-tidy file, if any.">;
+defm exclude_header_filter
+ : Eq<"exclude-header-filter", "<string>",
+ "Regular expression matching the names of the\n"
+ "headers to exclude diagnostics from. Diagnostics\n"
+ "from the main file of each translation unit are\n"
+ "always displayed.\n"
+ "Must be used together with --header-filter.\n"
+ "Can be used together with -line-filter.\n"
+ "This option overrides the 'ExcludeHeaderFilterRegex'\n"
+ "option in .clang-tidy file, if any.">;
+defm system_headers
+ : B<"system-headers",
+ "Display the errors from system headers.\n"
+ "This option overrides the 'SystemHeaders' option\n"
+ "in .clang-tidy file, if any.">;
+defm line_filter
+ : Eq<"line-filter", "<string>",
+ "List of files and line ranges to output diagnostics from.\n"
+ "The range is inclusive on both ends. Can be used together\n"
+ "with -header-filter. The format of the list is a JSON\n"
+ "array of objects. For example:\n"
+ " [\n"
+ " {\"name\":\"file1.cpp\",\"lines\":[[1,3],[5,7]]},\n"
+ " {\"name\":\"file2.h\"}\n"
+ " ]\n"
+ "This will output diagnostics from 'file1.cpp' only for\n"
+ "the line ranges [1,3] and [5,7], as well as all from the\n"
+ "entire 'file2.h'.">;
+defm fix
+ : B<"fix", "Apply suggested fixes. Without -fix-errors\n"
+ "clang-tidy will bail out if any compilation\n"
+ "errors were found.">;
+defm fix_errors
+ : B<"fix-errors",
+ "Apply suggested fixes even if compilation\n"
+ "errors were found. If compiler errors have\n"
+ "attached fix-its, clang-tidy will apply them as\n"
+ "well.">;
+defm fix_notes
+ : B<"fix-notes",
+ "If a warning has no fix, but a single fix can\n"
+ "be found through an associated diagnostic note,\n"
+ "apply the fix.\n"
+ "Specifying this flag will implicitly enable the\n"
+ "'--fix' flag.">;
+defm format_style
+ : Eq<"format-style", "<string>",
+ "Style for formatting code around applied fixes:\n"
+ " - 'none' (default) turns off formatting\n"
+ " - 'file' (literally 'file', not a placeholder)\n"
+ " uses .clang-format file in the closest parent\n"
+ " directory\n"
+ " - '{ <json> }' specifies options inline, e.g.\n"
+ " -format-style='{BasedOnStyle: llvm, IndentWidth: 8}'\n"
+ " - 'llvm', 'google', 'webkit', 'mozilla'\n"
+ "See clang-format documentation for the up-to-date\n"
+ "information about formatting styles and options.\n"
+ "This option overrides the 'FormatStyle` option in\n"
+ ".clang-tidy file, if any.">;
+defm list_checks
+ : B<"list-checks",
+ "List all enabled checks and exit. Use with\n"
+ "-checks=* to list all available checks.">;
+defm explain_config
+ : B<"explain-config",
+ "For each enabled check explains, where it is\n"
+ "enabled, i.e. in clang-tidy binary, command\n"
+ "line or a specific configuration file.">;
+defm config
+ : Eq<"config", "<string>",
+ "Specifies a configuration in YAML/JSON format:\n"
+ " -config=\"{Checks: '*',\n"
+ " CheckOptions: {x: y}}\"\n"
+ "When the value is empty, clang-tidy will\n"
+ "attempt to find a file named .clang-tidy for\n"
+ "each source file in its parent directories.">;
+defm config_file
+ : Eq<"config-file", "<filename>",
+ "Specify the path of .clang-tidy or custom config file:\n"
+ " e.g. --config-file=/some/path/myTidyConfigFile\n"
+ "This option internally works exactly the same way as\n"
+ " --config option after reading specified config file.\n"
+ "Use either --config-file or --config, not both.">;
+defm dump_config
+ : B<"dump-config",
+ "Dumps configuration in the YAML format to\n"
+ "stdout. This option can be used along with a\n"
+ "file name (and '--' if the file is outside of a\n"
+ "project with configured compilation database).\n"
+ "The configuration used for this file will be\n"
+ "printed.\n"
+ "Use along with -checks=* to include\n"
+ "configuration of all checks.">;
+defm enable_check_profile
+ : B<"enable-check-profile",
+ "Enable per-check timing profiles, and print a\n"
+ "report to stderr.">;
+defm store_check_profile
+ : Eq<"store-check-profile", "<prefix>",
+ "By default reports are printed in tabulated\n"
+ "format to stderr. When this option is passed,\n"
+ "these per-TU profiles are instead stored as JSON.">;
+defm allow_enabling_analyzer_alpha_checkers
+ : BH<"allow-enabling-analyzer-alpha-checkers">;
+defm enable_module_headers_parsing
+ : B<"enable-module-headers-parsing",
+ "Enables preprocessor-level module header parsing\n"
+ "for C++20 and above, empowering specific checks\n"
+ "to detect macro definitions within modules. This\n"
+ "feature may cause performance and parsing issues\n"
+ "and is therefore considered experimental.">;
+defm export_fixes
+ : Eq<"export-fixes", "<filename>",
+ "YAML file to store suggested fixes in. The\n"
+ "stored fixes can be applied to the input source\n"
+ "code with clang-apply-replacements.">;
+defm quiet
+ : B<"quiet",
+ "Run clang-tidy in quiet mode. This suppresses\n"
+ "printing statistics about ignored warnings and\n"
+ "warnings treated as errors if the respective\n"
+ "options are specified.">;
+defm vfsoverlay
+ : Eq<"vfsoverlay", "<filename>",
+ "Overlay the virtual filesystem described by file\n"
+ "over the real file system.">;
+defm use_color
+ : B<"use-color",
+ "Use colors in diagnostics. If not set, colors\n"
+ "will be used if the terminal connected to\n"
+ "standard output supports colors.\n"
+ "This option overrides the 'UseColor' option in\n"
+ ".clang-tidy file, if any.">;
+defm verify_config
+ : B<"verify-config",
+ "Check the config files to ensure each check and\n"
+ "option is recognized without running any checks.">;
+defm allow_no_checks
+ : B<"allow-no-checks",
+ "Allow empty enabled checks. This suppresses\n"
+ "the \"no checks enabled\" error when disabling\n"
+ "all of the checks.">;
+defm experimental_custom_checks
+ : B<"experimental-custom-checks",
+ "Enable experimental clang-query based\n"
+ "custom checks.\n"
+ "see https://clang.llvm.org/extra/clang-tidy/"
+ "QueryBasedCustomChecks.html.">;
+defm removed_arg
+ : Eq<"removed-arg", "<arg>",
+ "List of arguments to remove from the command\n"
+ "line sent to the compiler. Please note that\n"
+ "removing arguments might change the semantic\n"
+ "of the analyzed code, possibly leading to\n"
+ "compiler errors, false positives or\n"
+ "false negatives. This option is applied\n"
+ "before --extra-arg and --extra-arg-before">;
+
+defm extra_arg
+ : Eq<"extra-arg", "<arg>",
+ "Additional argument to append to the compiler command line">;
+defm extra_arg_before
+ : Eq<"extra-arg-before", "<arg>",
+ "Additional argument to prepend to the compiler command line">;
+def p : Separate<["-", "--"], "p">, HelpText<"Build path">,
+ MetaVarName<"<build-path>">, Group<clang_tidy_group>;
+def p_EQ : Joined<["-", "--"], "p=">, Alias<p>, Flags<[HelpHidden]>;
+defm load
+ : Eq<"load", "<pluginfilename>", "Load the specified plugin">;
diff --git a/clang-tools-extra/docs/clang-tidy/index.rst b/clang-tools-extra/docs/clang-tidy/index.rst
index 908dee6c18a7f..8b61e6fcd56ad 100644
--- a/clang-tools-extra/docs/clang-tidy/index.rst
+++ b/clang-tools-extra/docs/clang-tidy/index.rst
@@ -80,6 +80,7 @@ Name prefix Description
``darwin-`` Checks related to Darwin coding conventions.
``fuchsia-`` Checks related to Fuchsia coding conventions.
``google-`` Checks related to Google coding conventions.
+``hicpp-`` Checks related to High Integrity C++ Coding Standard.
``linuxkernel-`` Checks related to the Linux Kernel coding conventions.
``llvm-`` Checks related to the LLVM coding conventions.
``llvmlibc-`` Checks related to the LLVM-libc coding standards.
@@ -126,156 +127,161 @@ An overview of all the command-line options:
.. code-block:: console
$ clang-tidy --help
- USAGE: clang-tidy [options] <source0> [... <sourceN>]
+ OVERVIEW: clang-tidy
- OPTIONS:
+ USAGE: clang-tidy [options] <source0> [... <sourceN>] [-- <compiler arguments>]
Generic Options:
-
- --help - Display available options (--help-hidden for more)
- --help-list - Display list of available options (--help-list-hidden for more)
- --version - Display the version of this program
+ --help-list Display list of available options (--help-list-hidden for more)
+ --help Display available options (--help-hidden for more)
+ --version Display the version of this program
clang-tidy options:
-
- --allow-no-checks - Allow empty enabled checks. This suppresses
- the "no checks enabled" error when disabling
- all of the checks.
- --checks=<string> - Comma-separated list of globs with optional '-'
- prefix. Globs are processed in order of
- appearance in the list. Globs without '-'
- prefix add checks with matching names to the
- set, globs with the '-' prefix remove checks
- with matching names from the set of enabled
- checks. This option's value is appended to the
- value of the 'Checks' option in .clang-tidy
- file, if any.
- --config=<string> - Specifies a configuration in YAML/JSON format:
- -config="{Checks: '*',
- CheckOptions: {x: y}}"
- When the value is empty, clang-tidy will
- attempt to find a file named .clang-tidy for
- each source file in its parent directories.
- --config-file=<string> - Specify the path of .clang-tidy or custom config file:
- e.g. --config-file=/some/path/myTidyConfigFile
- This option internally works exactly the same way as
- --config option after reading specified config file.
- Use either --config-file or --config, not both.
- --dump-config - Dumps configuration in the YAML format to
- stdout. This option can be used along with a
- file name (and '--' if the file is outside of a
- project with configured compilation database).
- The configuration used for this file will be
- printed.
- Use along with -checks=* to include
- configuration of all checks.
- --enable-check-profile - Enable per-check timing profiles, and print a
- report to stderr.
- --enable-module-headers-parsing - Enables preprocessor-level module header parsing
- for C++20 and above, empowering specific checks
- to detect macro definitions within modules. This
- feature may cause performance and parsing issues
- and is therefore considered experimental.
- --exclude-header-filter=<string> - 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.
- --experimental-custom-checks - Enable experimental clang-query based
- custom checks.
- see https://clang.llvm.org/extra/clang-tidy/QueryBasedCustomChecks.html.
- --explain-config - For each enabled check explains, where it is
- enabled, i.e. in clang-tidy binary, command
- line or a specific configuration file.
- --export-fixes=<filename> - YAML file to store suggested fixes in. The
- stored fixes can be applied to the input source
- code with clang-apply-replacements.
- --extra-arg=<string> - Additional argument to append to the compiler command line
- --extra-arg-before=<string> - Additional argument to prepend to the compiler command line
- --fix - Apply suggested fixes. Without -fix-errors
- clang-tidy will bail out if any compilation
- errors were found.
- --fix-errors - Apply suggested fixes even if compilation
- errors were found. If compiler errors have
- attached fix-its, clang-tidy will apply them as
- well.
- --fix-notes - If a warning has no fix, but a single fix can
- be found through an associated diagnostic note,
- apply the fix.
- Specifying this flag will implicitly enable the
- '--fix' flag.
- --format-style=<string> - Style for formatting code around applied fixes:
- - 'none' (default) turns off formatting
- - 'file' (literally 'file', not a placeholder)
- uses .clang-format file in the closest parent
- directory
- - '{ <json> }' specifies options inline, e.g.
- -format-style='{BasedOnStyle: llvm, IndentWidth: 8}'
- - 'llvm', 'google', 'webkit', 'mozilla'
- See clang-format documentation for the up-to-date
- information about formatting styles and options.
- This option overrides the 'FormatStyle` option in
- .clang-tidy file, if any.
- --header-filter=<string> - Regular expression matching the names of the
- headers to output diagnostics from. The default
- value is '.*', i.e. diagnostics from all non-system
- headers are displayed by default. Diagnostics
- from the main file of each translation unit are
- always displayed.
- Can be used together with -line-filter.
- This option overrides the 'HeaderFilterRegex'
- option in .clang-tidy file, if any.
- --line-filter=<string> - List of files and line ranges to output diagnostics from.
- The range is inclusive on both ends. Can be used together
- with -header-filter. The format of the list is a JSON
- array of objects. For example:
-
- [
- {"name":"file1.cpp","lines":[[1,3],[5,7]]},
- {"name":"file2.h"}
- ]
-
- This will output diagnostics from 'file1.cpp' only for
- the line ranges [1,3] and [5,7], as well as all from the
- entire 'file2.h'.
- --list-checks - List all enabled checks and exit. Use with
- -checks=* to list all available checks.
- --load=<pluginfilename> - Load the specified plugin
- -p <string> - Build path
- --quiet - Run clang-tidy in quiet mode. This suppresses
- printing statistics about ignored warnings and
- warnings treated as errors if the respective
- options are specified.
- --removed-arg=<string> - List of arguments to remove from the command
- line sent to the compiler. Please note that
- removing arguments might change the semantic
- of the analyzed code, possibly leading to
- compiler errors, false positives or
- false negatives. This option is applied
- before --extra-arg and --extra-arg-before
- --store-check-profile=<prefix> - By default reports are printed in tabulated
- format to stderr. When this option is passed,
- these per-TU profiles are instead stored as JSON.
- --system-headers - Display the errors from system headers.
- This option overrides the 'SystemHeaders' option
- in .clang-tidy file, if any.
- --use-color - Use colors in diagnostics. If not set, colors
- will be used if the terminal connected to
- standard output supports colors.
- This option overrides the 'UseColor' option in
- .clang-tidy file, if any.
- --verify-config - Check the config files to ensure each check and
- option is recognized without running any checks.
- --vfsoverlay=<filename> - Overlay the virtual filesystem described by file
- over the real file system.
- --warnings-as-errors=<string> - Upgrades warnings to errors. Same format as
- '-checks'.
- This option's value is appended to the value of
- the 'WarningsAsErrors' option in .clang-tidy
- file, if any.
+ --allow-no-checks Allow empty enabled checks. This suppresses
+ the "no checks enabled" error when disabling
+ all of the checks.
+ --checks=<string> Comma-separated list of globs with optional '-'
+ prefix. Globs are processed in order of
+ appearance in the list. Globs without '-'
+ prefix add checks with matching names to the
+ set, globs with the '-' prefix remove checks
+ with matching names from the set of enabled
+ checks. This option's value is appended to the
+ value of the 'Checks' option in .clang-tidy
+ file, if any.
+ --config-file=<filename>
+ Specify the path of .clang-tidy or custom config file:
+ e.g. --config-file=/some/path/myTidyConfigFile
+ This option internally works exactly the same way as
+ --config option after reading specified config file.
+ Use either --config-file or --config, not both.
+ --config=<string> Specifies a configuration in YAML/JSON format:
+ -config="{Checks: '*',
+ CheckOptions: {x: y}}"
+ When the value is empty, clang-tidy will
+ attempt to find a file named .clang-tidy for
+ each source file in its parent directories.
+ --dump-config Dumps configuration in the YAML format to
+ stdout. This option can be used along with a
+ file name (and '--' if the file is outside of a
+ project with configured compilation database).
+ The configuration used for this file will be
+ printed.
+ Use along with -checks=* to include
+ configuration of all checks.
+ --enable-check-profile Enable per-check timing profiles, and print a
+ report to stderr.
+ --enable-module-headers-parsing
+ Enables preprocessor-level module header parsing
+ for C++20 and above, empowering specific checks
+ to detect macro definitions within modules. This
+ feature may cause performance and parsing issues
+ and is therefore considered experimental.
+ --exclude-header-filter=<string>
+ 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.
+ --experimental-custom-checks
+ Enable experimental clang-query based
+ custom checks.
+ see https://clang.llvm.org/extra/clang-tidy/QueryBasedCustomChecks.html.
+ --explain-config For each enabled check explains, where it is
+ enabled, i.e. in clang-tidy binary, command
+ line or a specific configuration file.
+ --export-fixes=<filename>
+ YAML file to store suggested fixes in. The
+ stored fixes can be applied to the input source
+ code with clang-apply-replacements.
+ --extra-arg-before=<arg>
+ Additional argument to prepend to the compiler command line
+ --extra-arg=<arg> Additional argument to append to the compiler command line
+ --fix-errors Apply suggested fixes even if compilation
+ errors were found. If compiler errors have
+ attached fix-its, clang-tidy will apply them as
+ well.
+ --fix-notes If a warning has no fix, but a single fix can
+ be found through an associated diagnostic note,
+ apply the fix.
+ Specifying this flag will implicitly enable the
+ '--fix' flag.
+ --fix Apply suggested fixes. Without -fix-errors
+ clang-tidy will bail out if any compilation
+ errors were found.
+ --format-style=<string> Style for formatting code around applied fixes:
+ - 'none' (default) turns off formatting
+ - 'file' (literally 'file', not a placeholder)
+ uses .clang-format file in the closest parent
+ directory
+ - '{ <json> }' specifies options inline, e.g.
+ -format-style='{BasedOnStyle: llvm, IndentWidth: 8}'
+ - 'llvm', 'google', 'webkit', 'mozilla'
+ See clang-format documentation for the up-to-date
+ information about formatting styles and options.
+ This option overrides the 'FormatStyle` option in
+ .clang-tidy file, if any.
+ --header-filter=<string>
+ Regular expression matching the names of the
+ headers to output diagnostics from. The default
+ value is '.*', i.e. diagnostics from all non-system
+ headers are displayed by default. Diagnostics
+ from the main file of each translation unit are
+ always displayed.
+ Can be used together with -line-filter.
+ This option overrides the 'HeaderFilterRegex'
+ option in .clang-tidy file, if any.
+ --line-filter=<string> List of files and line ranges to output diagnostics from.
+ The range is inclusive on both ends. Can be used together
+ with -header-filter. The format of the list is a JSON
+ array of objects. For example:
+ [
+ {"name":"file1.cpp","lines":[[1,3],[5,7]]},
+ {"name":"file2.h"}
+ ]
+ This will output diagnostics from 'file1.cpp' only for
+ the line ranges [1,3] and [5,7], as well as all from the
+ entire 'file2.h'.
+ --list-checks List all enabled checks and exit. Use with
+ -checks=* to list all available checks.
+ --load=<pluginfilename> Load the specified plugin
+ -p <build-path> Build path
+ --quiet Run clang-tidy in quiet mode. This suppresses
+ printing statistics about ignored warnings and
+ warnings treated as errors if the respective
+ options are specified.
+ --removed-arg=<arg> List of arguments to remove from the command
+ line sent to the compiler. Please note that
+ removing arguments might change the semantic
+ of the analyzed code, possibly leading to
+ compiler errors, false positives or
+ false negatives. This option is applied
+ before --extra-arg and --extra-arg-before
+ --store-check-profile=<prefix>
+ By default reports are printed in tabulated
+ format to stderr. When this option is passed,
+ these per-TU profiles are instead stored as JSON.
+ --system-headers Display the errors from system headers.
+ This option overrides the 'SystemHeaders' option
+ in .clang-tidy file, if any.
+ --use-color Use colors in diagnostics. If not set, colors
+ will be used if the terminal connected to
+ standard output supports colors.
+ This option overrides the 'UseColor' option in
+ .clang-tidy file, if any.
+ --verify-config Check the config files to ensure each check and
+ option is recognized without running any checks.
+ --vfsoverlay=<filename> Overlay the virtual filesystem described by file
+ over the real file system.
+ --warnings-as-errors=<string>
+ Upgrades warnings to errors. Same format as
+ '-checks'.
+ This option's value is appended to the value of
+ the 'WarningsAsErrors' option in .clang-tidy
+ file, if any.
-p <build-path> is used to read a compile command database.
@@ -283,7 +289,7 @@ An overview of all the command-line options:
compile_commands.json exists (use -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
CMake option to get this output). When no build path is specified,
a search for compile_commands.json will be attempted through all
- parent paths of the first input file . See:
+ parent paths of the first input file. See:
https://clang.llvm.org/docs/HowToSetupToolingForLLVM.html for an
example of setting up Clang Tooling on a source tree.
@@ -358,39 +364,6 @@ An overview of all the command-line options:
some-check.SomeOption: 'some value'
...
-Running Clang-Tidy on CUDA Files
---------------------------------
-
-:program:`clang-tidy` supports analyzing CUDA source files. To ensure correct
-header resolution, it is important to specify the CUDA toolkit path using
-``--cuda-path``. For more details on how Clang handles CUDA, see
-`Compiling CUDA with Clang <https://llvm.org/docs/CompileCudaWithLLVM.html>`_.
-
-If you are using a GCC + NVCC build setup, the compiler command database will
-contain NVCC-specific flags that :program:`clang-tidy` does not understand.
-
-In this case, you should use the ``RemovedArgs`` configuration option (or
-``--removed-arg`` command-line option) to remove these flags, and
-``ExtraArgs`` (or ``--extra-arg``) to provide the ``--cuda-path``.
-
-For example, to remove the NVCC-specific ``-gencode`` flag and provide the
-CUDA path:
-
-.. code-block:: console
-
- $ clang-tidy source.cu --removed-arg="-gencode" --removed-arg="arch=.." --extra-arg="--cuda-path=/path/to/cuda"
-
-By default, :program:`clang-tidy` will analyze both host and device code.
-To restrict the analysis to a specific side and specifically choose device
-compilation flags, use the ``--extra-arg`` flag to pass the arguments.
-
-For example, to perform device analysis only, use
-the ``--cuda-device-only`` flag:
-
-.. code-block:: console
-
- $ clang-tidy source.cu --extra-arg="--cuda-device-only" --extra-arg="--cuda-path=/path/to/cuda"
-
Clang-Tidy Automation
=====================
diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/invalid-command-line.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/invalid-command-line.cpp
index 80540411e53e3..a389fec9070a6 100644
--- a/clang-tools-extra/test/clang-tidy/infrastructure/invalid-command-line.cpp
+++ b/clang-tools-extra/test/clang-tidy/infrastructure/invalid-command-line.cpp
@@ -1,4 +1,3 @@
// RUN: not clang-tidy --invalid-arg 2>&1 | FileCheck %s
-// CHECK: error: clang-tidy{{(\.exe)?}}: Unknown command line argument '--invalid-arg'. Try: '{{.*}}clang-tidy{{(\.exe)?}} --help'
-// CHECK-NEXT: clang-tidy{{(\.exe)?}}: Did you mean '--removed-arg'?
+// CHECK: clang-tidy: unknown argument '--invalid-arg'
diff --git a/utils/bazel/llvm-project-overlay/clang-tools-extra/clang-tidy/BUILD.bazel b/utils/bazel/llvm-project-overlay/clang-tools-extra/clang-tidy/BUILD.bazel
index a4e30d615a39a..aa72d0e1fd3d4 100644
--- a/utils/bazel/llvm-project-overlay/clang-tools-extra/clang-tidy/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/clang-tools-extra/clang-tidy/BUILD.bazel
@@ -6,6 +6,8 @@ load("@bazel_skylib//rules:common_settings.bzl", "bool_flag")
load("@bazel_skylib//rules:expand_template.bzl", "expand_template")
load("@bazel_skylib//rules:native_binary.bzl", "native_binary")
load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library")
+load("//llvm:driver.bzl", "llvm_driver_cc_binary")
+load("//mlir:tblgen.bzl", "gentbl_cc_library")
load("defs.bzl", "clang_tidy_library")
package(
@@ -385,22 +387,36 @@ CHECKS = [
"//conditions:default": [],
})
+gentbl_cc_library(
+ name = "ClangTidyOptsTableGen",
+ strip_include_prefix = "tool",
+ tbl_outs = {"tool/Opts.inc": ["-gen-opt-parser-defs"]},
+ tblgen = "//llvm:llvm-tblgen",
+ td_file = "tool/Opts.td",
+ deps = ["//llvm:OptParserTdFiles"],
+)
+
cc_library(
name = "tool",
- srcs = ["tool/ClangTidyMain.cpp"],
+ srcs = [
+ "tool/ClangTidyMain.cpp",
+ "tool/ClangTidyToolMain.cpp",
+ ],
hdrs = ["tool/ClangTidyMain.h"],
deps = CHECKS + [
+ ":ClangTidyOptsTableGen",
":lib",
":utils",
+ "//clang:basic",
"//clang:tooling",
+ "//llvm:Option",
"//llvm:Support",
"//llvm:TargetParser",
],
)
-cc_binary(
+llvm_driver_cc_binary(
name = "clang-tidy",
- srcs = ["tool/ClangTidyToolMain.cpp"],
stamp = 0,
deps = [":tool"],
)
diff --git a/utils/bazel/llvm-project-overlay/llvm/driver.bzl b/utils/bazel/llvm-project-overlay/llvm/driver.bzl
index 43c7b5c241f02..d6033d3cecd9d 100644
--- a/utils/bazel/llvm-project-overlay/llvm/driver.bzl
+++ b/utils/bazel/llvm-project-overlay/llvm/driver.bzl
@@ -10,6 +10,7 @@ load("@rules_cc//cc:defs.bzl", "CcInfo", "cc_binary")
# Mapping from every tool to the cc_library that implements the tool's entrypoint.
_TOOLS = {
+ "clang-tidy": "//clang-tools-extra/clang-tidy:tool",
"clang-scan-deps": "//clang:clang-scan-deps-lib",
"clang": "//clang:clang-driver",
"dsymutil": "//llvm:dsymutil-lib",
More information about the cfe-commits
mailing list