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

Reply via email to