llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang-tools-extra @llvm/pr-subscribers-clang-tidy Author: David Zbarsky (dzbarsky) <details> <summary>Changes</summary> --- Patch is 69.16 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/201743.diff 9 Files Affected: - (modified) clang-tools-extra/clang-tidy/tool/CMakeLists.txt (+8) - (modified) clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp (+309-313) - (modified) clang-tools-extra/clang-tidy/tool/ClangTidyMain.h (+1-1) - (modified) clang-tools-extra/clang-tidy/tool/ClangTidyToolMain.cpp (+2-1) - (added) clang-tools-extra/clang-tidy/tool/Opts.td (+245) - (modified) clang-tools-extra/docs/clang-tidy/index.rst (+152-179) - (modified) clang-tools-extra/test/clang-tidy/infrastructure/invalid-command-line.cpp (+1-2) - (modified) utils/bazel/llvm-project-overlay/clang-tools-extra/clang-tidy/BUILD.bazel (+19-3) - (modified) utils/bazel/llvm-project-overlay/llvm/driver.bzl (+1) ``````````diff 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); + ExcludeHeaderFilter... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/201743 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
