llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang-format

Author: David Zbarsky (dzbarsky)

<details>
<summary>Changes</summary>



---

Patch is 30.37 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/201730.diff


5 Files Affected:

- (modified) clang/tools/clang-format/CMakeLists.txt (+12-1) 
- (modified) clang/tools/clang-format/ClangFormat.cpp (+226-206) 
- (added) clang/tools/clang-format/Opts.td (+154) 
- (modified) utils/bazel/llvm-project-overlay/clang/BUILD.bazel (+19-3) 
- (modified) utils/bazel/llvm-project-overlay/llvm/driver.bzl (+1) 


``````````diff
diff --git a/clang/tools/clang-format/CMakeLists.txt 
b/clang/tools/clang-format/CMakeLists.txt
index 1c61a3c8fb803..5a1e53d3aa99b 100644
--- a/clang/tools/clang-format/CMakeLists.txt
+++ b/clang/tools/clang-format/CMakeLists.txt
@@ -1,7 +1,18 @@
-set(LLVM_LINK_COMPONENTS support)
+set(LLVM_LINK_COMPONENTS
+  Option
+  Support
+  )
+
+set(LLVM_TARGET_DEFINITIONS Opts.td)
+tablegen(LLVM Opts.inc -gen-opt-parser-defs)
+add_public_tablegen_target(ClangFormatOptsTableGen)
 
 add_clang_tool(clang-format
   ClangFormat.cpp
+
+  DEPENDS
+  ClangFormatOptsTableGen
+  GENERATE_DRIVER
   )
 
 set(CLANG_FORMAT_LIB_DEPS
diff --git a/clang/tools/clang-format/ClangFormat.cpp 
b/clang/tools/clang-format/ClangFormat.cpp
index 37d0eb83414f4..f4bf01fbc4e39 100644
--- a/clang/tools/clang-format/ClangFormat.cpp
+++ b/clang/tools/clang-format/ClangFormat.cpp
@@ -21,198 +21,80 @@
 #include "clang/Format/Format.h"
 #include "clang/Rewrite/Core/Rewriter.h"
 #include "llvm/ADT/StringSwitch.h"
-#include "llvm/Support/CommandLine.h"
+#include "llvm/Option/Arg.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Option/Option.h"
+#include "llvm/Support/Allocator.h"
 #include "llvm/Support/FileSystem.h"
-#include "llvm/Support/InitLLVM.h"
-#include "llvm/Support/Process.h"
+#include "llvm/Support/LLVMDriver.h"
+#include "llvm/Support/StringSaver.h"
 #include <fstream>
+#include <optional>
+#include <string>
+#include <vector>
 
 using namespace llvm;
 using clang::tooling::Replacements;
 
-static cl::opt<bool> Help("h", cl::desc("Alias for -help"), cl::Hidden);
-
-// Mark all our options with this category, everything else (except for 
-version
-// and -help) will be hidden.
-static cl::OptionCategory ClangFormatCategory("Clang-format options");
-
-static cl::list<unsigned>
-    Offsets("offset",
-            cl::desc("Format a range starting at this byte offset.\n"
-                     "Multiple ranges can be formatted by specifying\n"
-                     "several -offset and -length pairs.\n"
-                     "Can only be used with one input file."),
-            cl::cat(ClangFormatCategory));
-static cl::list<unsigned>
-    Lengths("length",
-            cl::desc("Format a range of this length (in bytes).\n"
-                     "Multiple ranges can be formatted by specifying\n"
-                     "several -offset and -length pairs.\n"
-                     "When only a single -offset is specified without\n"
-                     "-length, clang-format will format up to the end\n"
-                     "of the file.\n"
-                     "Can only be used with one input file."),
-            cl::cat(ClangFormatCategory));
-static cl::list<std::string>
-    LineRanges("lines",
-               cl::desc("<start line>:<end line> - format a range of\n"
-                        "lines (both 1-based).\n"
-                        "Multiple ranges can be formatted by specifying\n"
-                        "several -lines arguments.\n"
-                        "Can't be used with -offset and -length.\n"
-                        "Can only be used with one input file."),
-               cl::cat(ClangFormatCategory));
-static cl::opt<std::string>
-    Style("style", cl::desc(clang::format::StyleOptionHelpDescription),
-          cl::init(clang::format::DefaultFormatStyle),
-          cl::cat(ClangFormatCategory));
-static cl::opt<std::string>
-    FallbackStyle("fallback-style",
-                  cl::desc("The name of the predefined style used as a\n"
-                           "fallback in case clang-format is invoked with\n"
-                           "-style=file, but can not find the .clang-format\n"
-                           "file to use. Defaults to 'LLVM'.\n"
-                           "Use -fallback-style=none to skip formatting."),
-                  cl::init(clang::format::DefaultFallbackStyle),
-                  cl::cat(ClangFormatCategory));
-
-static cl::opt<std::string> AssumeFileName(
-    "assume-filename",
-    cl::desc("Set filename used to determine the language and to find\n"
-             ".clang-format file.\n"
-             "Only used when reading from stdin.\n"
-             "If this is not passed, the .clang-format file is searched\n"
-             "relative to the current working directory when reading stdin.\n"
-             "Unrecognized filenames are treated as C++.\n"
-             "supported:\n"
-             "  CSharp: .cs\n"
-             "  Java: .java\n"
-             "  JavaScript: .js .mjs .cjs .ts\n"
-             "  JSON: .json .ipynb\n"
-             "  Objective-C: .m .mm\n"
-             "  Proto: .proto .protodevel\n"
-             "  TableGen: .td\n"
-             "  TextProto: .txtpb .textpb .pb.txt .textproto .asciipb\n"
-             "  Verilog: .sv .svh .v .vh"),
-    cl::init("<stdin>"), cl::cat(ClangFormatCategory));
-
-static cl::opt<bool> Inplace("i",
-                             cl::desc("Inplace edit <file>s, if specified."),
-                             cl::cat(ClangFormatCategory));
-
-static cl::opt<bool> OutputXML("output-replacements-xml",
-                               cl::desc("Output replacements as XML."),
-                               cl::cat(ClangFormatCategory));
-static cl::opt<bool>
-    DumpConfig("dump-config",
-               cl::desc("Dump configuration options to stdout and exit.\n"
-                        "Can be used with -style option."),
-               cl::cat(ClangFormatCategory));
-static cl::opt<unsigned>
-    Cursor("cursor",
-           cl::desc("The position of the cursor when invoking\n"
-                    "clang-format from an editor integration"),
-           cl::init(0), cl::cat(ClangFormatCategory));
-
-static cl::opt<bool>
-    SortIncludes("sort-includes",
-                 cl::desc("If set, overrides the include sorting behavior\n"
-                          "determined by the SortIncludes style flag"),
-                 cl::cat(ClangFormatCategory));
-
-static cl::opt<std::string> QualifierAlignment(
-    "qualifier-alignment",
-    cl::desc("If set, overrides the qualifier alignment style\n"
-             "determined by the QualifierAlignment style flag"),
-    cl::init(""), cl::cat(ClangFormatCategory));
-
-static cl::opt<std::string> Files(
-    "files",
-    cl::desc("A file containing a list of files to process, one per line."),
-    cl::value_desc("filename"), cl::init(""), cl::cat(ClangFormatCategory));
-
-static cl::opt<bool>
-    Verbose("verbose", cl::desc("If set, shows the list of processed files"),
-            cl::cat(ClangFormatCategory));
-
-// Use --dry-run to match other LLVM tools when you mean do it but don't
-// actually do it
-static cl::opt<bool>
-    DryRun("dry-run",
-           cl::desc("If set, do not actually make the formatting changes"),
-           cl::cat(ClangFormatCategory));
-
-// Use -n as a common command as an alias for --dry-run. (git and make use -n)
-static cl::alias DryRunShort("n", cl::desc("Alias for --dry-run"),
-                             cl::cat(ClangFormatCategory), 
cl::aliasopt(DryRun),
-                             cl::NotHidden);
-
-// Emulate being able to turn on/off the warning.
-static cl::opt<bool>
-    WarnFormat("Wclang-format-violations",
-               cl::desc("Warnings about individual formatting changes needed. "
-                        "Used only with --dry-run or -n"),
-               cl::init(true), cl::cat(ClangFormatCategory), cl::Hidden);
-
-static cl::opt<bool>
-    NoWarnFormat("Wno-clang-format-violations",
-                 cl::desc("Do not warn about individual formatting changes "
-                          "needed. Used only with --dry-run or -n"),
-                 cl::init(false), cl::cat(ClangFormatCategory), cl::Hidden);
-
-static cl::opt<unsigned> ErrorLimit(
-    "ferror-limit",
-    cl::desc("Set the maximum number of clang-format errors to emit\n"
-             "before stopping (0 = no limit).\n"
-             "Used only with --dry-run or -n"),
-    cl::init(0), cl::cat(ClangFormatCategory));
-
-static cl::opt<bool>
-    WarningsAsErrors("Werror",
-                     cl::desc("If set, changes formatting warnings to errors"),
-                     cl::cat(ClangFormatCategory));
-
 namespace {
-enum class WNoError { Unknown };
-}
+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
+
+using namespace llvm::opt;
+static constexpr opt::OptTable::Info InfoTable[] = {
+#define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
+#include "Opts.inc"
+#undef OPTION
+};
 
-static cl::bits<WNoError> WNoErrorList(
-    "Wno-error",
-    cl::desc("If set, don't error out on the specified warning type."),
-    cl::values(
-        clEnumValN(WNoError::Unknown, "unknown",
-                   "If set, unknown format options are only warned about.\n"
-                   "This can be used to enable formatting, even if the\n"
-                   "configuration contains unknown (newer) options.\n"
-                   "Use with caution, as this might lead to dramatically\n"
-                   "differing format depending on an option being\n"
-                   "supported or not.")),
-    cl::cat(ClangFormatCategory));
-
-static cl::opt<bool>
-    ShowColors("fcolor-diagnostics",
-               cl::desc("If set, and on a color-capable terminal controls "
-                        "whether or not to print diagnostics in color"),
-               cl::init(true), cl::cat(ClangFormatCategory), cl::Hidden);
-
-static cl::opt<bool>
-    NoShowColors("fno-color-diagnostics",
-                 cl::desc("If set, and on a color-capable terminal controls "
-                          "whether or not to print diagnostics in color"),
-                 cl::init(false), cl::cat(ClangFormatCategory), cl::Hidden);
-
-static cl::list<std::string> FileNames(cl::Positional,
-                                       cl::desc("[@<file>] [<file> ...]"),
-                                       cl::cat(ClangFormatCategory));
-
-static cl::opt<bool> FailOnIncompleteFormat(
-    "fail-on-incomplete-format",
-    cl::desc("If set, fail with exit code 1 on incomplete format."),
-    cl::init(false), cl::cat(ClangFormatCategory));
-
-static cl::opt<bool> ListIgnored("list-ignored",
-                                 cl::desc("List ignored files."),
-                                 cl::cat(ClangFormatCategory), cl::Hidden);
+class ClangFormatOptTable : public opt::GenericOptTable {
+public:
+  ClangFormatOptTable()
+      : opt::GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) {
+    setDashDashParsing(true);
+  }
+};
+
+static std::vector<unsigned> Offsets;
+static std::vector<unsigned> Lengths;
+static std::vector<std::string> LineRanges;
+static std::string Style;
+static std::string FallbackStyle;
+static std::string AssumeFileName;
+static bool Inplace;
+static bool OutputXML;
+static bool DumpConfig;
+static unsigned Cursor;
+static bool CursorSpecified;
+static bool SortIncludes;
+static bool SortIncludesSpecified;
+static std::string QualifierAlignment;
+static std::string Files;
+static bool Verbose;
+static bool DryRun;
+static bool WarnFormat;
+static bool NoWarnFormat;
+static unsigned ErrorLimit;
+static bool WarningsAsErrors;
+static bool WNoErrorUnknown;
+static bool ShowColors;
+static bool NoShowColors;
+static std::vector<std::string> FileNames;
+static bool FailOnIncompleteFormat;
+static bool ListIgnored;
+} // namespace
 
 namespace clang {
 namespace format {
@@ -370,7 +252,6 @@ static bool emitReplacementWarnings(const Replacements 
&Replaces,
 static void outputXML(const Replacements &Replaces,
                       const Replacements &FormatChanges,
                       const FormattingAttemptStatus &Status,
-                      const cl::opt<unsigned> &Cursor,
                       unsigned CursorPosition) {
   outs() << "<?xml version='1.0'?>\n<replacements "
             "xml:space='preserve' incomplete_format='"
@@ -378,7 +259,7 @@ static void outputXML(const Replacements &Replaces,
   if (!Status.FormatComplete)
     outs() << " line='" << Status.Line << "'";
   outs() << ">\n";
-  if (Cursor.getNumOccurrences() != 0) {
+  if (CursorSpecified) {
     outs() << "<cursor>" << 
FormatChanges.getShiftedCodePosition(CursorPosition)
            << "</cursor>\n";
   }
@@ -444,7 +325,7 @@ static bool format(StringRef FileName, bool 
ErrorOnIncompleteFormat = false) {
 
   Expected<FormatStyle> FormatStyle =
       getStyle(Style, AssumedFileName, FallbackStyle, Code->getBuffer(),
-               nullptr, WNoErrorList.isSet(WNoError::Unknown));
+               nullptr, WNoErrorUnknown);
   if (!FormatStyle) {
     llvm::errs() << toString(FormatStyle.takeError()) << "\n";
     return true;
@@ -471,7 +352,7 @@ static bool format(StringRef FileName, bool 
ErrorOnIncompleteFormat = false) {
     FormatStyle->QualifierOrder = {Qualifiers.begin(), Qualifiers.end()};
   }
 
-  if (SortIncludes.getNumOccurrences() != 0) {
+  if (SortIncludesSpecified) {
     FormatStyle->SortIncludes = {};
     if (SortIncludes)
       FormatStyle->SortIncludes.Enabled = true;
@@ -507,7 +388,7 @@ static bool format(StringRef FileName, bool 
ErrorOnIncompleteFormat = false) {
            emitReplacementWarnings(Replaces, AssumedFileName, std::move(Code));
   }
   if (OutputXML) {
-    outputXML(Replaces, FormatChanges, Status, Cursor, CursorPosition);
+    outputXML(Replaces, FormatChanges, Status, CursorPosition);
   } else {
     auto InMemoryFileSystem =
         makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
@@ -526,7 +407,7 @@ static bool format(StringRef FileName, bool 
ErrorOnIncompleteFormat = false) {
       if (Rewrite.overwriteChangedFiles())
         return true;
     } else {
-      if (Cursor.getNumOccurrences() != 0) {
+      if (CursorSpecified) {
         outs() << "{ \"Cursor\": "
                << FormatChanges.getShiftedCodePosition(CursorPosition)
                << ", \"IncompleteFormat\": "
@@ -548,6 +429,138 @@ static void PrintVersion(raw_ostream &OS) {
   OS << clang::getClangToolFullVersion("clang-format") << '\n';
 }
 
+static bool parseUnsignedArgs(const opt::InputArgList &Args, OptSpecifier ID,
+                              std::vector<unsigned> &Values) {
+  for (const opt::Arg *A : Args.filtered(ID)) {
+    unsigned Value;
+    if (!StringRef(A->getValue()).getAsInteger(0, Value)) {
+      Values.push_back(Value);
+      continue;
+    }
+    errs() << "clang-format: invalid value '" << A->getValue()
+           << "' for option '" << A->getSpelling() << "'\n";
+    return false;
+  }
+  return true;
+}
+
+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-format: invalid value '" << A->getValue() << "' for option 
'"
+         << A->getSpelling() << "'\n";
+  return false;
+}
+
+static bool parseBoolArg(const opt::InputArgList &Args, unsigned FlagID,
+                         unsigned ValueID, bool Default, bool &Value,
+                         bool *Specified = nullptr) {
+  const opt::Arg *A = Args.getLastArg(FlagID, ValueID);
+  if (Specified)
+    *Specified = A != nullptr;
+  if (!A) {
+    Value = Default;
+    return true;
+  }
+  return parseBoolArg(A, ValueID, Value);
+}
+
+static bool parseArgs(int argc, char **argv, StringSaver &Saver,
+                      ClangFormatOptTable &Tbl, opt::InputArgList &Args) {
+  bool HasError = false;
+  Args = Tbl.parseArgs(argc, argv, OPT_UNKNOWN, Saver, [&](StringRef Msg) {
+    errs() << "clang-format: " << Msg << '\n';
+    HasError = true;
+  });
+  if (HasError)
+    return false;
+
+  Offsets.clear();
+  Lengths.clear();
+  LineRanges = Args.getAllArgValues(OPT_lines_EQ);
+  Style = Args.getLastArgValue(OPT_style_EQ, 
clang::format::DefaultFormatStyle);
+  FallbackStyle = Args.getLastArgValue(OPT_fallback_style_EQ,
+                                       clang::format::DefaultFallbackStyle);
+  AssumeFileName = Args.getLastArgValue(OPT_assume_filename_EQ, "<stdin>");
+  Cursor = 0;
+  CursorSpecified = Args.hasArg(OPT_cursor_EQ);
+  QualifierAlignment = Args.getLastArgValue(OPT_qualifier_alignment_EQ);
+  Files = Args.getLastArgValue(OPT_files_EQ);
+  ErrorLimit = 0;
+  WNoErrorUnknown = false;
+  FileNames = Args.getAllArgValues(OPT_INPUT);
+
+  if (!parseBoolArg(Args, OPT_i, OPT_i_EQ, false, Inplace) ||
+      !parseBoolArg(Args, OPT_output_replacements_xml,
+                    OPT_output_replacements_xml_EQ, false, OutputXML) ||
+      !parseBoolArg(Args, OPT_dump_config, OPT_dump_config_EQ, false,
+                    DumpConfig) ||
+      !parseBoolArg(Args, OPT_sort_includes, OPT_sort_includes_EQ, false,
+                    SortIncludes, &SortIncludesSpecified) ||
+      !parseBoolArg(Args, OPT_verbose, OPT_verbose_EQ, false, Verbose) ||
+      !parseBoolArg(Args, OPT_dry_run, OPT_dry_run_EQ, false, DryRun) ||
+      !parseBoolArg(Args, OPT_Wclang_format_violations,
+                    OPT_Wclang_format_violations_EQ, true, WarnFormat) ||
+      !parseBoolArg(Args, OPT_Wno_clang_format_violations,
+                    OPT_Wno_clang_format_violations_EQ, false, NoWarnFormat) ||
+      !parseBoolArg(Args, OPT_Werror, OPT_Werror_EQ, false, WarningsAsErrors) 
||
+      !parseBoolArg(Args, OPT_fcolor_diagnostics, OPT_fcolor_diagnostics_EQ,
+                    true, ShowColors) ||
+      !parseBoolArg(Args, OPT_fno_color_diagnostics,
+                    OPT_fno_color_diagnostics_EQ, false, NoShowColors) ||
+      !parseBoolArg(Args, OPT_fail_on_incomplete_format,
+                    OPT_fail_on_incomplete_format_EQ, false,
+                    FailOnIncompleteFormat) ||
+      !parseBoolArg(Args, OPT_list_ignored, OPT_list_ignored_EQ, false,
+                    ListIgnored)) {
+    return false;
+  }
+
+  if (!parseUnsignedArgs(Args, OPT_offset_EQ, Offsets) ||
+      !parseUnsignedArgs(Args, OPT_length_EQ, Lengths)) {
+    return false;
+  }
+
+  if (const opt::Arg *A = Args.getLastArg(OPT_cursor_EQ)) {
+    if (StringRef(A->getValue()).getAsInteger(0, Cursor)) {
+      errs() << "clang-format: invalid value '" << A->getValue()
+             << "' for option '" << A->getSpelling() << "'\n";
+      return false;
+    }
+  }
+
+  if (const opt::Arg *A = Args.getLastArg(OPT_ferror_limit_EQ)) {
+    if (StringRef(A->getValue()).getAsInteger(0, ErrorLimit)) {
+      errs() << "clang-format: invalid value '" << A->getValue()
+             << "' for option '" << A->getSpelling() << "'\n";
+      return false;
+    }
+  }
+
+  for (StringRef Warning : Args.getAllArgValues(OPT_Wno_error_EQ)) {
+    if (Warning == "unknown") {
+      WNoErrorUnknown = true;
+      continue;
+    }
+    errs() << "clang-format: invalid value '" << Warning
+           << "' for option '-Wno-error'\n";
+    return false;
+  }
+  return true;
+}
+
 // Dump the configuration.
 static int dumpConfig() {
   std::unique_ptr<llvm::MemoryBuffer> Code;
@@ -664,24 +677,31 @@ static bool isIgnored(StringRef FilePath) {
   return false;
 }
 
-int main(int argc, const char **argv) {
-  InitLLVM X(argc, argv);
-
-  cl::HideUnrelatedOptions(ClangFormatCategory);
+int clang_format_main(int argc, char **argv, const llvm::ToolContext &) {
+  BumpPtrAllocator Alloc;
+  StringSaver Saver(Alloc);
+  ClangFormatOptTable Tbl;
+  opt::InputArgList Args;
+  if (!parseArgs(argc, argv, Saver, Tbl, Args))
+    return 1;
 
-  cl::SetVersionPrinter(PrintVersion);
-  cl::ParseCommandLineOptions(
-      argc, argv,
-      "A tool to format C/C++/Java/JavaScript/JSON/Objective-C/Protobuf/C# "
-      "code.\n\n"
-      "If no arguments are specified, it formats the code from standard 
input\n"
-      "and writes the result to the standard output.\n"
-      "If <file>s are given, it reformats the files. If -i is specifi...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/201730
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to