serge-sans-paille updated this revision to Diff 485931.
serge-sans-paille added a comment.

(rebased on main. Note that this patch is applied on top of 
https://reviews.llvm.org/D140699)


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D140800/new/

https://reviews.llvm.org/D140800

Files:
  clang/lib/Driver/DriverOptions.cpp
  clang/lib/Driver/ToolChains/Gnu.cpp
  clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
  lld/COFF/Driver.h
  lld/COFF/DriverUtils.cpp
  lld/ELF/Driver.h
  lld/ELF/DriverUtils.cpp
  lld/MachO/Driver.h
  lld/MachO/DriverUtils.cpp
  lld/MinGW/Driver.cpp
  lld/wasm/Driver.cpp
  lldb/tools/driver/Driver.cpp
  lldb/tools/lldb-server/lldb-gdbserver.cpp
  lldb/tools/lldb-vscode/lldb-vscode.cpp
  llvm/include/llvm/Option/OptTable.h
  llvm/lib/ExecutionEngine/JITLink/COFFDirectiveParser.cpp
  llvm/lib/Option/OptTable.cpp
  llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp
  llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp
  llvm/tools/dsymutil/dsymutil.cpp
  llvm/tools/llvm-cvtres/llvm-cvtres.cpp
  llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp
  llvm/tools/llvm-dwarfutil/llvm-dwarfutil.cpp
  llvm/tools/llvm-ifs/llvm-ifs.cpp
  llvm/tools/llvm-lipo/llvm-lipo.cpp
  llvm/tools/llvm-ml/llvm-ml.cpp
  llvm/tools/llvm-mt/llvm-mt.cpp
  llvm/tools/llvm-nm/llvm-nm.cpp
  llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
  llvm/tools/llvm-objdump/llvm-objdump.cpp
  llvm/tools/llvm-rc/llvm-rc.cpp
  llvm/tools/llvm-readobj/llvm-readobj.cpp
  llvm/tools/llvm-size/llvm-size.cpp
  llvm/tools/llvm-strings/llvm-strings.cpp
  llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp
  llvm/tools/llvm-tli-checker/llvm-tli-checker.cpp
  llvm/unittests/Option/OptionParsingTest.cpp
  llvm/utils/TableGen/OptParserEmitter.cpp

Index: llvm/utils/TableGen/OptParserEmitter.cpp
===================================================================
--- llvm/utils/TableGen/OptParserEmitter.cpp
+++ llvm/utils/TableGen/OptParserEmitter.cpp
@@ -237,8 +237,14 @@
       CurPrefix = NewPrefix;
   }
 
-  // Dump prefixes.
+  DenseSet<StringRef> PrefixesUnionSet;
+  for (const auto &Prefix : Prefixes)
+    PrefixesUnionSet.insert(Prefix.first.begin(), Prefix.first.end());
+  SmallVector<StringRef> PrefixesUnion(PrefixesUnionSet.begin(),
+                                       PrefixesUnionSet.end());
+  array_pod_sort(PrefixesUnion.begin(), PrefixesUnion.end());
 
+  // Dump prefixes.
   OS << "/////////\n";
   OS << "// Prefixes\n\n";
   OS << "#ifdef PREFIX\n";
@@ -259,6 +265,20 @@
   OS << "#undef COMMA\n";
   OS << "#endif // PREFIX\n\n";
 
+  // Dump prefix unions.
+  OS << "/////////\n";
+  OS << "// Prefix Union\n\n";
+  OS << "#ifdef PREFIX_UNION\n";
+  OS << "#define COMMA ,\n";
+  OS << "PREFIX_UNION({\n";
+  for (const auto &Prefix : PrefixesUnion) {
+    OS << "llvm::StringLiteral(\"" << Prefix << "\") COMMA ";
+  }
+  OS << "llvm::StringLiteral(\"\")})\n";
+  OS << "#undef COMMA\n";
+  OS << "#endif // PREFIX_UNION\n\n";
+
+  // Dump groups.
   OS << "/////////\n";
   OS << "// ValuesCode\n\n";
   OS << "#ifdef OPTTABLE_VALUES_CODE\n";
Index: llvm/unittests/Option/OptionParsingTest.cpp
===================================================================
--- llvm/unittests/Option/OptionParsingTest.cpp
+++ llvm/unittests/Option/OptionParsingTest.cpp
@@ -32,6 +32,14 @@
 #include "Opts.inc"
 #undef PREFIX
 
+static constexpr const StringLiteral PrefixTable_init[] =
+#define PREFIX_UNION(VALUES) VALUES
+#include "Opts.inc"
+#undef PREFIX_UNION
+    ;
+static constexpr const ArrayRef<StringLiteral>
+    PrefixTable(PrefixTable_init, std::size(PrefixTable_init) - 1);
+
 enum OptionFlags {
   OptFlag1 = (1 << 4),
   OptFlag2 = (1 << 5),
@@ -48,10 +56,16 @@
 };
 
 namespace {
-class TestOptTable : public OptTable {
+class TestOptTable : public GenericOptTable {
 public:
   TestOptTable(bool IgnoreCase = false)
-    : OptTable(InfoTable, IgnoreCase) {}
+      : GenericOptTable(InfoTable, IgnoreCase) {}
+};
+
+class TestPrecomputedOptTable : public PrecomputedOptTable {
+public:
+  TestPrecomputedOptTable(bool IgnoreCase = false)
+      : PrecomputedOptTable(InfoTable, PrefixTable, IgnoreCase) {}
 };
 }
 
@@ -67,8 +81,20 @@
   "-Gchuu", "2"
   };
 
-TEST(Option, OptionParsing) {
-  TestOptTable T;
+// Test fixture
+template <typename T> class OptTableTest : public ::testing::Test {};
+
+template <typename T> class DISABLED_OptTableTest : public ::testing::Test {};
+
+// Test both precomputed and computed OptTables with the same suite of tests.
+using OptTableTestTypes =
+    ::testing::Types<TestOptTable, TestPrecomputedOptTable>;
+
+TYPED_TEST_SUITE(OptTableTest, OptTableTestTypes, );
+TYPED_TEST_SUITE(DISABLED_OptTableTest, OptTableTestTypes, );
+
+TYPED_TEST(OptTableTest, OptionParsing) {
+  TypeParam T;
   unsigned MAI, MAC;
   InputArgList AL = T.ParseArgs(Args, MAI, MAC);
 
@@ -114,8 +140,8 @@
   EXPECT_EQ("desu", StringRef(ASL[1]));
 }
 
-TEST(Option, ParseWithFlagExclusions) {
-  TestOptTable T;
+TYPED_TEST(OptTableTest, ParseWithFlagExclusions) {
+  TypeParam T;
   unsigned MAI, MAC;
 
   // Exclude flag3 to avoid parsing as OPT_SLASH_C.
@@ -142,8 +168,8 @@
   EXPECT_EQ("bar", AL.getLastArgValue(OPT_C));
 }
 
-TEST(Option, ParseAliasInGroup) {
-  TestOptTable T;
+TYPED_TEST(OptTableTest, ParseAliasInGroup) {
+  TypeParam T;
   unsigned MAI, MAC;
 
   const char *MyArgs[] = { "-I" };
@@ -151,8 +177,8 @@
   EXPECT_TRUE(AL.hasArg(OPT_H));
 }
 
-TEST(Option, AliasArgs) {
-  TestOptTable T;
+TYPED_TEST(OptTableTest, AliasArgs) {
+  TypeParam T;
   unsigned MAI, MAC;
 
   const char *MyArgs[] = { "-J", "-Joo" };
@@ -162,8 +188,8 @@
   EXPECT_EQ("bar", AL.getAllArgValues(OPT_B)[1]);
 }
 
-TEST(Option, IgnoreCase) {
-  TestOptTable T(true);
+TYPED_TEST(OptTableTest, IgnoreCase) {
+  TypeParam T(true);
   unsigned MAI, MAC;
 
   const char *MyArgs[] = { "-a", "-joo" };
@@ -172,8 +198,8 @@
   EXPECT_TRUE(AL.hasArg(OPT_B));
 }
 
-TEST(Option, DoNotIgnoreCase) {
-  TestOptTable T;
+TYPED_TEST(OptTableTest, DoNotIgnoreCase) {
+  TypeParam T;
   unsigned MAI, MAC;
 
   const char *MyArgs[] = { "-a", "-joo" };
@@ -182,8 +208,8 @@
   EXPECT_FALSE(AL.hasArg(OPT_B));
 }
 
-TEST(Option, SlurpEmpty) {
-  TestOptTable T;
+TYPED_TEST(OptTableTest, SlurpEmpty) {
+  TypeParam T;
   unsigned MAI, MAC;
 
   const char *MyArgs[] = { "-A", "-slurp" };
@@ -193,8 +219,8 @@
   EXPECT_EQ(0U, AL.getAllArgValues(OPT_Slurp).size());
 }
 
-TEST(Option, Slurp) {
-  TestOptTable T;
+TYPED_TEST(OptTableTest, Slurp) {
+  TypeParam T;
   unsigned MAI, MAC;
 
   const char *MyArgs[] = { "-A", "-slurp", "-B", "--", "foo" };
@@ -209,8 +235,8 @@
   EXPECT_EQ("foo", AL.getAllArgValues(OPT_Slurp)[2]);
 }
 
-TEST(Option, SlurpJoinedEmpty) {
-  TestOptTable T;
+TYPED_TEST(OptTableTest, SlurpJoinedEmpty) {
+  TypeParam T;
   unsigned MAI, MAC;
 
   const char *MyArgs[] = { "-A", "-slurpjoined" };
@@ -220,8 +246,8 @@
   EXPECT_EQ(AL.getAllArgValues(OPT_SlurpJoined).size(), 0U);
 }
 
-TEST(Option, SlurpJoinedOneJoined) {
-  TestOptTable T;
+TYPED_TEST(OptTableTest, SlurpJoinedOneJoined) {
+  TypeParam T;
   unsigned MAI, MAC;
 
   const char *MyArgs[] = { "-A", "-slurpjoinedfoo" };
@@ -232,8 +258,8 @@
   EXPECT_EQ(AL.getAllArgValues(OPT_SlurpJoined)[0], "foo");
 }
 
-TEST(Option, SlurpJoinedAndSeparate) {
-  TestOptTable T;
+TYPED_TEST(OptTableTest, SlurpJoinedAndSeparate) {
+  TypeParam T;
   unsigned MAI, MAC;
 
   const char *MyArgs[] = { "-A", "-slurpjoinedfoo", "bar", "baz" };
@@ -246,8 +272,8 @@
   EXPECT_EQ("baz", AL.getAllArgValues(OPT_SlurpJoined)[2]);
 }
 
-TEST(Option, SlurpJoinedButSeparate) {
-  TestOptTable T;
+TYPED_TEST(OptTableTest, SlurpJoinedButSeparate) {
+  TypeParam T;
   unsigned MAI, MAC;
 
   const char *MyArgs[] = { "-A", "-slurpjoined", "foo", "bar", "baz" };
@@ -260,8 +286,8 @@
   EXPECT_EQ("baz", AL.getAllArgValues(OPT_SlurpJoined)[2]);
 }
 
-TEST(Option, FlagAliasToJoined) {
-  TestOptTable T;
+TYPED_TEST(OptTableTest, FlagAliasToJoined) {
+  TypeParam T;
   unsigned MAI, MAC;
 
   // Check that a flag alias provides an empty argument to a joined option.
@@ -273,8 +299,8 @@
   EXPECT_EQ("", AL.getAllArgValues(OPT_B)[0]);
 }
 
-TEST(Option, FindNearest) {
-  TestOptTable T;
+TYPED_TEST(OptTableTest, FindNearest) {
+  TypeParam T;
   std::string Nearest;
 
   // Options that are too short should not be considered
@@ -324,8 +350,8 @@
   EXPECT_EQ(Nearest, "-doopf1");
 }
 
-TEST(DISABLED_Option, FindNearestFIXME) {
-  TestOptTable T;
+TYPED_TEST(DISABLED_OptTableTest, FindNearestFIXME) {
+  TypeParam T;
   std::string Nearest;
 
   // FIXME: Options with joined values should not have those values considered
@@ -333,11 +359,10 @@
   // succeed.
   EXPECT_EQ(1U, T.findNearest("--erbghFoo", Nearest));
   EXPECT_EQ(Nearest, "--ermghFoo");
-
 }
 
-TEST(Option, ParseGroupedShortOptions) {
-  TestOptTable T;
+TYPED_TEST(OptTableTest, ParseGroupedShortOptions) {
+  TypeParam T;
   T.setGroupedShortOptions(true);
   unsigned MAI, MAC;
 
@@ -366,8 +391,8 @@
   EXPECT_TRUE(AL3.hasArg(OPT_Blorp));
 }
 
-TEST(Option, UnknownOptions) {
-  TestOptTable T;
+TYPED_TEST(OptTableTest, UnknownOptions) {
+  TypeParam T;
   unsigned MAI, MAC;
   const char *Args[] = {"-u", "--long", "0"};
   for (int I = 0; I < 2; ++I) {
@@ -380,8 +405,8 @@
   }
 }
 
-TEST(Option, FlagsWithoutValues) {
-  TestOptTable T;
+TYPED_TEST(OptTableTest, FlagsWithoutValues) {
+  TypeParam T;
   T.setGroupedShortOptions(true);
   unsigned MAI, MAC;
   const char *Args[] = {"-A=1", "-A="};
@@ -392,8 +417,8 @@
   EXPECT_EQ("-A=", Unknown[1]);
 }
 
-TEST(Option, UnknownGroupedShortOptions) {
-  TestOptTable T;
+TYPED_TEST(OptTableTest, UnknownGroupedShortOptions) {
+  TypeParam T;
   T.setGroupedShortOptions(true);
   unsigned MAI, MAC;
   const char *Args[] = {"-AuzK", "-AuzK"};
Index: llvm/tools/llvm-tli-checker/llvm-tli-checker.cpp
===================================================================
--- llvm/tools/llvm-tli-checker/llvm-tli-checker.cpp
+++ llvm/tools/llvm-tli-checker/llvm-tli-checker.cpp
@@ -54,9 +54,9 @@
 #undef OPTION
 };
 
-class TLICheckerOptTable : public opt::OptTable {
+class TLICheckerOptTable : public opt::GenericOptTable {
 public:
-  TLICheckerOptTable() : OptTable(InfoTable) {}
+  TLICheckerOptTable() : GenericOptTable(InfoTable) {}
 };
 } // end anonymous namespace
 
Index: llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp
===================================================================
--- llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp
+++ llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp
@@ -75,9 +75,9 @@
 #undef OPTION
 };
 
-class SymbolizerOptTable : public opt::OptTable {
+class SymbolizerOptTable : public opt::GenericOptTable {
 public:
-  SymbolizerOptTable() : OptTable(InfoTable) {
+  SymbolizerOptTable() : GenericOptTable(InfoTable) {
     setGroupedShortOptions(true);
   }
 };
Index: llvm/tools/llvm-strings/llvm-strings.cpp
===================================================================
--- llvm/tools/llvm-strings/llvm-strings.cpp
+++ llvm/tools/llvm-strings/llvm-strings.cpp
@@ -58,9 +58,11 @@
 #undef OPTION
 };
 
-class StringsOptTable : public opt::OptTable {
+class StringsOptTable : public opt::GenericOptTable {
 public:
-  StringsOptTable() : OptTable(InfoTable) { setGroupedShortOptions(true); }
+  StringsOptTable() : GenericOptTable(InfoTable) {
+    setGroupedShortOptions(true);
+  }
 };
 } // namespace
 
Index: llvm/tools/llvm-size/llvm-size.cpp
===================================================================
--- llvm/tools/llvm-size/llvm-size.cpp
+++ llvm/tools/llvm-size/llvm-size.cpp
@@ -66,9 +66,9 @@
 #undef OPTION
 };
 
-class SizeOptTable : public opt::OptTable {
+class SizeOptTable : public opt::GenericOptTable {
 public:
-  SizeOptTable() : OptTable(InfoTable) { setGroupedShortOptions(true); }
+  SizeOptTable() : GenericOptTable(InfoTable) { setGroupedShortOptions(true); }
 };
 
 enum OutputFormatTy { berkeley, sysv, darwin };
Index: llvm/tools/llvm-readobj/llvm-readobj.cpp
===================================================================
--- llvm/tools/llvm-readobj/llvm-readobj.cpp
+++ llvm/tools/llvm-readobj/llvm-readobj.cpp
@@ -80,9 +80,11 @@
 #undef OPTION
 };
 
-class ReadobjOptTable : public opt::OptTable {
+class ReadobjOptTable : public opt::GenericOptTable {
 public:
-  ReadobjOptTable() : OptTable(InfoTable) { setGroupedShortOptions(true); }
+  ReadobjOptTable() : opt::GenericOptTable(InfoTable) {
+    setGroupedShortOptions(true);
+  }
 };
 
 enum OutputFormatTy { bsd, sysv, posix, darwin, just_symbols };
Index: llvm/tools/llvm-rc/llvm-rc.cpp
===================================================================
--- llvm/tools/llvm-rc/llvm-rc.cpp
+++ llvm/tools/llvm-rc/llvm-rc.cpp
@@ -76,9 +76,9 @@
 };
 } // namespace rc_opt
 
-class RcOptTable : public opt::OptTable {
+class RcOptTable : public opt::GenericOptTable {
 public:
-  RcOptTable() : OptTable(rc_opt::InfoTable, /* IgnoreCase = */ true) {}
+  RcOptTable() : GenericOptTable(rc_opt::InfoTable, /* IgnoreCase = */ true) {}
 };
 
 enum Windres_ID {
@@ -110,10 +110,10 @@
 };
 } // namespace windres_opt
 
-class WindresOptTable : public opt::OptTable {
+class WindresOptTable : public opt::GenericOptTable {
 public:
   WindresOptTable()
-      : OptTable(windres_opt::InfoTable, /* IgnoreCase = */ false) {}
+      : GenericOptTable(windres_opt::InfoTable, /* IgnoreCase = */ false) {}
 };
 
 static ExitOnError ExitOnErr;
Index: llvm/tools/llvm-objdump/llvm-objdump.cpp
===================================================================
--- llvm/tools/llvm-objdump/llvm-objdump.cpp
+++ llvm/tools/llvm-objdump/llvm-objdump.cpp
@@ -97,18 +97,19 @@
 
 namespace {
 
-class CommonOptTable : public opt::OptTable {
+class CommonOptTable : public opt::GenericOptTable {
 public:
   CommonOptTable(ArrayRef<Info> OptionInfos, const char *Usage,
                  const char *Description)
-      : OptTable(OptionInfos), Usage(Usage), Description(Description) {
+      : opt::GenericOptTable(OptionInfos), Usage(Usage),
+        Description(Description) {
     setGroupedShortOptions(true);
   }
 
   void printHelp(StringRef Argv0, bool ShowHidden = false) const {
     Argv0 = sys::path::filename(Argv0);
-    opt::OptTable::printHelp(outs(), (Argv0 + Usage).str().c_str(), Description,
-                             ShowHidden, ShowHidden);
+    opt::GenericOptTable::printHelp(outs(), (Argv0 + Usage).str().c_str(),
+                                    Description, ShowHidden, ShowHidden);
     // TODO Replace this with OptTable API once it adds extrahelp support.
     outs() << "\nPass @FILE as argument to read options from FILE.\n";
   }
Index: llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
===================================================================
--- llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
+++ llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
@@ -56,9 +56,9 @@
 };
 } // namespace objcopy_opt
 
-class ObjcopyOptTable : public opt::OptTable {
+class ObjcopyOptTable : public opt::GenericOptTable {
 public:
-  ObjcopyOptTable() : OptTable(objcopy_opt::ObjcopyInfoTable) {
+  ObjcopyOptTable() : opt::GenericOptTable(objcopy_opt::ObjcopyInfoTable) {
     setGroupedShortOptions(true);
   }
 };
@@ -101,10 +101,10 @@
 };
 } // namespace install_name_tool
 
-class InstallNameToolOptTable : public opt::OptTable {
+class InstallNameToolOptTable : public opt::GenericOptTable {
 public:
   InstallNameToolOptTable()
-      : OptTable(install_name_tool::InstallNameToolInfoTable) {}
+      : GenericOptTable(install_name_tool::InstallNameToolInfoTable) {}
 };
 
 enum BitcodeStripID {
@@ -145,9 +145,10 @@
 };
 } // namespace bitcode_strip
 
-class BitcodeStripOptTable : public opt::OptTable {
+class BitcodeStripOptTable : public opt::GenericOptTable {
 public:
-  BitcodeStripOptTable() : OptTable(bitcode_strip::BitcodeStripInfoTable) {}
+  BitcodeStripOptTable()
+      : opt::GenericOptTable(bitcode_strip::BitcodeStripInfoTable) {}
 };
 
 enum StripID {
@@ -179,9 +180,9 @@
 };
 } // namespace strip
 
-class StripOptTable : public opt::OptTable {
+class StripOptTable : public opt::GenericOptTable {
 public:
-  StripOptTable() : OptTable(strip::StripInfoTable) {
+  StripOptTable() : GenericOptTable(strip::StripInfoTable) {
     setGroupedShortOptions(true);
   }
 };
Index: llvm/tools/llvm-nm/llvm-nm.cpp
===================================================================
--- llvm/tools/llvm-nm/llvm-nm.cpp
+++ llvm/tools/llvm-nm/llvm-nm.cpp
@@ -83,9 +83,11 @@
 #undef OPTION
 };
 
-class NmOptTable : public opt::OptTable {
+class NmOptTable : public opt::GenericOptTable {
 public:
-  NmOptTable() : OptTable(InfoTable) { setGroupedShortOptions(true); }
+  NmOptTable() : opt::GenericOptTable(InfoTable) {
+    setGroupedShortOptions(true);
+  }
 };
 
 enum OutputFormatTy { bsd, sysv, posix, darwin, just_symbols };
Index: llvm/tools/llvm-mt/llvm-mt.cpp
===================================================================
--- llvm/tools/llvm-mt/llvm-mt.cpp
+++ llvm/tools/llvm-mt/llvm-mt.cpp
@@ -60,9 +60,9 @@
 #undef OPTION
 };
 
-class CvtResOptTable : public opt::OptTable {
+class CvtResOptTable : public opt::GenericOptTable {
 public:
-  CvtResOptTable() : OptTable(InfoTable, true) {}
+  CvtResOptTable() : opt::GenericOptTable(InfoTable, true) {}
 };
 } // namespace
 
Index: llvm/tools/llvm-ml/llvm-ml.cpp
===================================================================
--- llvm/tools/llvm-ml/llvm-ml.cpp
+++ llvm/tools/llvm-ml/llvm-ml.cpp
@@ -79,9 +79,9 @@
 #undef OPTION
 };
 
-class MLOptTable : public opt::OptTable {
+class MLOptTable : public opt::GenericOptTable {
 public:
-  MLOptTable() : OptTable(InfoTable, /*IgnoreCase=*/false) {}
+  MLOptTable() : opt::GenericOptTable(InfoTable, /*IgnoreCase=*/false) {}
 };
 } // namespace
 
Index: llvm/tools/llvm-lipo/llvm-lipo.cpp
===================================================================
--- llvm/tools/llvm-lipo/llvm-lipo.cpp
+++ llvm/tools/llvm-lipo/llvm-lipo.cpp
@@ -93,9 +93,9 @@
 };
 } // namespace lipo
 
-class LipoOptTable : public opt::OptTable {
+class LipoOptTable : public opt::GenericOptTable {
 public:
-  LipoOptTable() : OptTable(lipo::LipoInfoTable) {}
+  LipoOptTable() : opt::GenericOptTable(lipo::LipoInfoTable) {}
 };
 
 enum class LipoAction {
Index: llvm/tools/llvm-ifs/llvm-ifs.cpp
===================================================================
--- llvm/tools/llvm-ifs/llvm-ifs.cpp
+++ llvm/tools/llvm-ifs/llvm-ifs.cpp
@@ -79,9 +79,11 @@
 #undef OPTION
 };
 
-class IFSOptTable : public opt::OptTable {
+class IFSOptTable : public opt::GenericOptTable {
 public:
-  IFSOptTable() : OptTable(InfoTable) { setGroupedShortOptions(true); }
+  IFSOptTable() : opt::GenericOptTable(InfoTable) {
+    setGroupedShortOptions(true);
+  }
 };
 
 struct DriverConfig {
Index: llvm/tools/llvm-dwarfutil/llvm-dwarfutil.cpp
===================================================================
--- llvm/tools/llvm-dwarfutil/llvm-dwarfutil.cpp
+++ llvm/tools/llvm-dwarfutil/llvm-dwarfutil.cpp
@@ -59,9 +59,9 @@
 #undef OPTION
 };
 
-class DwarfutilOptTable : public opt::OptTable {
+class DwarfutilOptTable : public opt::GenericOptTable {
 public:
-  DwarfutilOptTable() : OptTable(InfoTable) {}
+  DwarfutilOptTable() : opt::GenericOptTable(InfoTable) {}
 };
 } // namespace
 
Index: llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp
===================================================================
--- llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp
+++ llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp
@@ -51,9 +51,11 @@
 #undef OPTION
 };
 
-class CxxfiltOptTable : public opt::OptTable {
+class CxxfiltOptTable : public opt::GenericOptTable {
 public:
-  CxxfiltOptTable() : OptTable(InfoTable) { setGroupedShortOptions(true); }
+  CxxfiltOptTable() : opt::GenericOptTable(InfoTable) {
+    setGroupedShortOptions(true);
+  }
 };
 } // namespace
 
Index: llvm/tools/llvm-cvtres/llvm-cvtres.cpp
===================================================================
--- llvm/tools/llvm-cvtres/llvm-cvtres.cpp
+++ llvm/tools/llvm-cvtres/llvm-cvtres.cpp
@@ -63,9 +63,9 @@
 #undef OPTION
 };
 
-class CvtResOptTable : public opt::OptTable {
+class CvtResOptTable : public opt::GenericOptTable {
 public:
-  CvtResOptTable() : OptTable(InfoTable, true) {}
+  CvtResOptTable() : opt::GenericOptTable(InfoTable, true) {}
 };
 }
 
Index: llvm/tools/dsymutil/dsymutil.cpp
===================================================================
--- llvm/tools/dsymutil/dsymutil.cpp
+++ llvm/tools/dsymutil/dsymutil.cpp
@@ -82,9 +82,9 @@
 #undef OPTION
 };
 
-class DsymutilOptTable : public opt::OptTable {
+class DsymutilOptTable : public opt::GenericOptTable {
 public:
-  DsymutilOptTable() : OptTable(InfoTable) {}
+  DsymutilOptTable() : opt::GenericOptTable(InfoTable) {}
 };
 } // namespace
 
Index: llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp
===================================================================
--- llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp
+++ llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp
@@ -56,11 +56,10 @@
 #undef OPTION
 };
 
-class LibOptTable : public opt::OptTable {
+class LibOptTable : public opt::GenericOptTable {
 public:
-  LibOptTable() : OptTable(InfoTable, true) {}
+  LibOptTable() : opt::GenericOptTable(InfoTable, true) {}
 };
-
 }
 
 static std::string getDefaultOutputPath(const NewArchiveMember &FirstMember) {
Index: llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp
===================================================================
--- llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp
+++ llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp
@@ -52,9 +52,9 @@
 #undef OPTION
 };
 
-class DllOptTable : public llvm::opt::OptTable {
+class DllOptTable : public opt::GenericOptTable {
 public:
-  DllOptTable() : OptTable(InfoTable, false) {}
+  DllOptTable() : opt::GenericOptTable(InfoTable, false) {}
 };
 
 // Opens a file. Path has to be resolved already.
Index: llvm/lib/Option/OptTable.cpp
===================================================================
--- llvm/lib/Option/OptTable.cpp
+++ llvm/lib/Option/OptTable.cpp
@@ -9,7 +9,6 @@
 #include "llvm/Option/OptTable.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/StringSet.h"
 #include "llvm/Option/Arg.h"
 #include "llvm/Option/ArgList.h"
 #include "llvm/Option/OptSpecifier.h"
@@ -23,6 +22,7 @@
 #include <cctype>
 #include <cstring>
 #include <map>
+#include <set>
 #include <string>
 #include <utility>
 #include <vector>
@@ -125,16 +125,13 @@
     }
   }
 #endif
+}
 
-  // Build prefixes.
-  for (unsigned i = FirstSearchableIndex + 1, e = getNumOptions() + 1;
-                i != e; ++i) {
-    const auto &P = getInfo(i).Prefixes;
-    PrefixesUnion.insert(P.begin(), P.end());
-  }
+void OptTable::buildPrefixChars() {
+  assert(PrefixChars.empty() && "rebuilding a non-empty prefix char");
 
   // Build prefix chars.
-  for (const StringRef &Prefix : PrefixesUnion.keys()) {
+  for (const StringLiteral &Prefix : getPrefixesUnion()) {
     for (char C : Prefix)
       if (!is_contained(PrefixChars, C))
         PrefixChars.push_back(C);
@@ -151,10 +148,10 @@
   return Option(&getInfo(id), this);
 }
 
-static bool isInput(const StringSet<> &Prefixes, StringRef Arg) {
+static bool isInput(const ArrayRef<StringLiteral> &Prefixes, StringRef Arg) {
   if (Arg == "-")
     return true;
-  for (const StringRef &Prefix : Prefixes.keys())
+  for (const StringRef &Prefix : Prefixes)
     if (Arg.startswith(Prefix))
       return false;
   return true;
@@ -236,6 +233,9 @@
   // Consider each [option prefix + option name] pair as a candidate, finding
   // the closest match.
   unsigned BestDistance = UINT_MAX;
+  SmallString<16> Candidate;
+  SmallString<16> NormalizedName;
+
   for (const Info &CandidateInfo :
        ArrayRef<Info>(OptionInfos).drop_front(FirstSearchableIndex)) {
     StringRef CandidateName = CandidateInfo.Name;
@@ -243,7 +243,7 @@
     // We can eliminate some option prefix/name pairs as candidates right away:
     // * Ignore option candidates with empty names, such as "--", or names
     //   that do not meet the minimum length.
-    if (CandidateName.empty() || CandidateName.size() < MinimumLength)
+    if (CandidateName.size() < MinimumLength)
       continue;
 
     // * If FlagsToInclude were specified, ignore options that don't include
@@ -262,26 +262,25 @@
     // Now check if the candidate ends with a character commonly used when
     // delimiting an option from its value, such as '=' or ':'. If it does,
     // attempt to split the given option based on that delimiter.
-    StringRef LHS, RHS;
     char Last = CandidateName.back();
     bool CandidateHasDelimiter = Last == '=' || Last == ':';
-    std::string NormalizedName = std::string(Option);
+    StringRef RHS;
     if (CandidateHasDelimiter) {
-      std::tie(LHS, RHS) = Option.split(Last);
-      NormalizedName = std::string(LHS);
-      if (Option.find(Last) == LHS.size())
+      std::tie(NormalizedName, RHS) = Option.split(Last);
+      if (Option.find(Last) == NormalizedName.size())
         NormalizedName += Last;
-    }
+    } else
+      NormalizedName = Option;
 
     // Consider each possible prefix for each candidate to find the most
     // appropriate one. For example, if a user asks for "--helm", suggest
     // "--help" over "-help".
     for (auto CandidatePrefix : CandidateInfo.Prefixes) {
-      std::string Candidate = (CandidatePrefix + CandidateName).str();
-      StringRef CandidateRef = Candidate;
-      unsigned Distance =
-          CandidateRef.edit_distance(NormalizedName, /*AllowReplacements=*/true,
-                                     /*MaxEditDistance=*/BestDistance);
+      Candidate = CandidatePrefix;
+      Candidate += CandidateName;
+      unsigned Distance = StringRef(Candidate).edit_distance(
+          NormalizedName, /*AllowReplacements=*/true,
+          /*MaxEditDistance=*/BestDistance);
       if (RHS.empty() && CandidateHasDelimiter) {
         // The Candidate ends with a = or : delimiter, but the option passed in
         // didn't contain the delimiter (or doesn't have anything after it).
@@ -310,7 +309,7 @@
   // itself.
   const char *CStr = Args.getArgString(Index);
   StringRef Str(CStr);
-  if (isInput(PrefixesUnion, Str))
+  if (isInput(getPrefixesUnion(), Str))
     return std::make_unique<Arg>(getOption(InputOptionID), Str, Index++, CStr);
 
   const Info *End = OptionInfos.data() + OptionInfos.size();
@@ -375,7 +374,7 @@
 
   // Anything that doesn't start with PrefixesUnion is an input, as is '-'
   // itself.
-  if (isInput(PrefixesUnion, Str))
+  if (isInput(getPrefixesUnion(), Str))
     return std::make_unique<Arg>(getOption(InputOptionID), Str, Index++,
                                  Str.data());
 
@@ -653,3 +652,13 @@
 
   OS.flush();
 }
+
+GenericOptTable::GenericOptTable(ArrayRef<Info> OptionInfos, bool IgnoreCase)
+    : OptTable(OptionInfos, IgnoreCase) {
+
+  std::set<StringLiteral> TmpPrefixesUnion;
+  for (auto const &Info : OptionInfos.drop_front(FirstSearchableIndex))
+    TmpPrefixesUnion.insert(Info.Prefixes.begin(), Info.Prefixes.end());
+  PrefixesUnionBuffer.append(TmpPrefixesUnion.begin(), TmpPrefixesUnion.end());
+  buildPrefixChars();
+}
Index: llvm/lib/ExecutionEngine/JITLink/COFFDirectiveParser.cpp
===================================================================
--- llvm/lib/ExecutionEngine/JITLink/COFFDirectiveParser.cpp
+++ llvm/lib/ExecutionEngine/JITLink/COFFDirectiveParser.cpp
@@ -27,6 +27,14 @@
 #include "COFFOptions.inc"
 #undef PREFIX
 
+static constexpr const StringLiteral PrefixTable_init[] =
+#define PREFIX_UNION(VALUES) VALUES
+#include "COFFOptions.inc"
+#undef PREFIX_UNION
+    ;
+static constexpr const ArrayRef<StringLiteral>
+    PrefixTable(PrefixTable_init, std::size(PrefixTable_init) - 1);
+
 // Create table mapping all options defined in COFFOptions.td
 static constexpr opt::OptTable::Info infoTable[] = {
 #define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12)      \
@@ -46,9 +54,9 @@
 #undef OPTION
 };
 
-class COFFOptTable : public opt::OptTable {
+class COFFOptTable : public opt::PrecomputedOptTable {
 public:
-  COFFOptTable() : OptTable(infoTable, true) {}
+  COFFOptTable() : PrecomputedOptTable(infoTable, PrefixTable, true) {}
 };
 
 static COFFOptTable optTable;
Index: llvm/include/llvm/Option/OptTable.h
===================================================================
--- llvm/include/llvm/Option/OptTable.h
+++ llvm/include/llvm/Option/OptTable.h
@@ -12,7 +12,6 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/StringSet.h"
 #include "llvm/Option/OptSpecifier.h"
 #include "llvm/Support/StringSaver.h"
 #include <cassert>
@@ -68,14 +67,17 @@
   unsigned InputOptionID = 0;
   unsigned UnknownOptionID = 0;
 
+protected:
   /// The index of the first option which can be parsed (i.e., is not a
   /// special option like 'input' or 'unknown', and is not an option group).
   unsigned FirstSearchableIndex = 0;
 
+  /// The union of the first element of all option prefixes.
+  SmallString<8> PrefixChars;
+
   /// The union of all option prefixes. If an argument does not begin with
   /// one of these, it is an input.
-  StringSet<> PrefixesUnion;
-  SmallString<8> PrefixChars;
+  virtual ArrayRef<StringLiteral> getPrefixesUnion() const = 0;
 
 private:
   const Info &getInfo(OptSpecifier Opt) const {
@@ -88,10 +90,15 @@
                                           unsigned &Index) const;
 
 protected:
+  /// Initialize OptTable using Tablegen'ed OptionInfos. Child class must
+  /// manually call \c buildPrefixChars once they are fully constructed.
   OptTable(ArrayRef<Info> OptionInfos, bool IgnoreCase = false);
 
+  /// Build (or rebuild) the PrefixChars member.
+  void buildPrefixChars();
+
 public:
-  ~OptTable();
+  virtual ~OptTable();
 
   /// Return the total number of option classes.
   unsigned getNumOptions() const { return OptionInfos.size(); }
@@ -246,6 +253,32 @@
                  bool ShowHidden = false, bool ShowAllAliases = false) const;
 };
 
+/// Specialization of
+class GenericOptTable : public OptTable {
+  SmallVector<StringLiteral> PrefixesUnionBuffer;
+
+protected:
+  GenericOptTable(ArrayRef<Info> OptionInfos, bool IgnoreCase = false);
+  ArrayRef<StringLiteral> getPrefixesUnion() const final {
+    return PrefixesUnionBuffer;
+  }
+};
+
+class PrecomputedOptTable : public OptTable {
+  ArrayRef<StringLiteral> PrefixesUnion;
+
+protected:
+  PrecomputedOptTable(ArrayRef<Info> OptionInfos,
+                      ArrayRef<StringLiteral> PrefixesTable,
+                      bool IgnoreCase = false)
+      : OptTable(OptionInfos, IgnoreCase), PrefixesUnion(PrefixesTable) {
+    buildPrefixChars();
+  }
+  ArrayRef<StringLiteral> getPrefixesUnion() const final {
+    return PrefixesUnion;
+  }
+};
+
 } // end namespace opt
 
 } // end namespace llvm
Index: lldb/tools/lldb-vscode/lldb-vscode.cpp
===================================================================
--- lldb/tools/lldb-vscode/lldb-vscode.cpp
+++ lldb/tools/lldb-vscode/lldb-vscode.cpp
@@ -96,9 +96,9 @@
 #include "Options.inc"
 #undef OPTION
 };
-class LLDBVSCodeOptTable : public llvm::opt::OptTable {
+class LLDBVSCodeOptTable : public llvm::opt::GenericOptTable {
 public:
-  LLDBVSCodeOptTable() : OptTable(InfoTable, true) {}
+  LLDBVSCodeOptTable() : llvm::opt::GenericOptTable(InfoTable, true) {}
 };
 
 typedef void (*RequestCallback)(const llvm::json::Object &command);
Index: lldb/tools/lldb-server/lldb-gdbserver.cpp
===================================================================
--- lldb/tools/lldb-server/lldb-gdbserver.cpp
+++ lldb/tools/lldb-server/lldb-gdbserver.cpp
@@ -297,9 +297,9 @@
 #undef OPTION
 };
 
-class LLGSOptTable : public opt::OptTable {
+class LLGSOptTable : public opt::GenericOptTable {
 public:
-  LLGSOptTable() : OptTable(InfoTable) {}
+  LLGSOptTable() : opt::GenericOptTable(InfoTable) {}
 
   void PrintHelp(llvm::StringRef Name) {
     std::string Usage =
Index: lldb/tools/driver/Driver.cpp
===================================================================
--- lldb/tools/driver/Driver.cpp
+++ lldb/tools/driver/Driver.cpp
@@ -78,9 +78,9 @@
 #undef OPTION
 };
 
-class LLDBOptTable : public opt::OptTable {
+class LLDBOptTable : public opt::GenericOptTable {
 public:
-  LLDBOptTable() : OptTable(InfoTable) {}
+  LLDBOptTable() : opt::GenericOptTable(InfoTable) {}
 };
 } // namespace
 
Index: lld/wasm/Driver.cpp
===================================================================
--- lld/wasm/Driver.cpp
+++ lld/wasm/Driver.cpp
@@ -120,9 +120,9 @@
 };
 
 namespace {
-class WasmOptTable : public llvm::opt::OptTable {
+class WasmOptTable : public opt::GenericOptTable {
 public:
-  WasmOptTable() : OptTable(optInfo) {}
+  WasmOptTable() : opt::GenericOptTable(optInfo) {}
   opt::InputArgList parse(ArrayRef<const char *> argv);
 };
 } // namespace
Index: lld/MinGW/Driver.cpp
===================================================================
--- lld/MinGW/Driver.cpp
+++ lld/MinGW/Driver.cpp
@@ -79,9 +79,9 @@
 };
 
 namespace {
-class MinGWOptTable : public opt::OptTable {
+class MinGWOptTable : public opt::GenericOptTable {
 public:
-  MinGWOptTable() : OptTable(infoTable, false) {}
+  MinGWOptTable() : opt::GenericOptTable(infoTable, false) {}
   opt::InputArgList parse(ArrayRef<const char *> argv);
 };
 } // namespace
Index: lld/MachO/DriverUtils.cpp
===================================================================
--- lld/MachO/DriverUtils.cpp
+++ lld/MachO/DriverUtils.cpp
@@ -51,7 +51,7 @@
 #undef OPTION
 };
 
-MachOOptTable::MachOOptTable() : OptTable(optInfo) {}
+MachOOptTable::MachOOptTable() : GenericOptTable(optInfo) {}
 
 // Set color diagnostics according to --color-diagnostics={auto,always,never}
 // or --no-color-diagnostics flags.
Index: lld/MachO/Driver.h
===================================================================
--- lld/MachO/Driver.h
+++ lld/MachO/Driver.h
@@ -25,7 +25,7 @@
 class DylibFile;
 class InputFile;
 
-class MachOOptTable : public llvm::opt::OptTable {
+class MachOOptTable : public llvm::opt::GenericOptTable {
 public:
   MachOOptTable();
   llvm::opt::InputArgList parse(ArrayRef<const char *> argv);
Index: lld/ELF/DriverUtils.cpp
===================================================================
--- lld/ELF/DriverUtils.cpp
+++ lld/ELF/DriverUtils.cpp
@@ -50,7 +50,7 @@
 #undef OPTION
 };
 
-ELFOptTable::ELFOptTable() : OptTable(optInfo) {}
+ELFOptTable::ELFOptTable() : GenericOptTable(optInfo) {}
 
 // Set color diagnostics according to --color-diagnostics={auto,always,never}
 // or --no-color-diagnostics flags.
Index: lld/ELF/Driver.h
===================================================================
--- lld/ELF/Driver.h
+++ lld/ELF/Driver.h
@@ -16,7 +16,7 @@
 
 namespace lld::elf {
 // Parses command line options.
-class ELFOptTable : public llvm::opt::OptTable {
+class ELFOptTable : public llvm::opt::GenericOptTable {
 public:
   ELFOptTable();
   llvm::opt::InputArgList parse(ArrayRef<const char *> argv);
Index: lld/COFF/DriverUtils.cpp
===================================================================
--- lld/COFF/DriverUtils.cpp
+++ lld/COFF/DriverUtils.cpp
@@ -788,7 +788,7 @@
 #undef OPTION
 };
 
-COFFOptTable::COFFOptTable() : OptTable(infoTable, true) {}
+COFFOptTable::COFFOptTable() : GenericOptTable(infoTable, true) {}
 
 COFFOptTable optTable;
 
Index: lld/COFF/Driver.h
===================================================================
--- lld/COFF/Driver.h
+++ lld/COFF/Driver.h
@@ -36,7 +36,7 @@
 using llvm::COFF::WindowsSubsystem;
 using std::optional;
 
-class COFFOptTable : public llvm::opt::OptTable {
+class COFFOptTable : public llvm::opt::GenericOptTable {
 public:
   COFFOptTable();
 };
Index: clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
===================================================================
--- clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
+++ clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
@@ -138,9 +138,9 @@
 #undef OPTION
 };
 
-class WrapperOptTable : public opt::OptTable {
+class WrapperOptTable : public opt::GenericOptTable {
 public:
-  WrapperOptTable() : OptTable(InfoTable) {}
+  WrapperOptTable() : opt::GenericOptTable(InfoTable) {}
 };
 
 const OptTable &getOptTable() {
Index: clang/lib/Driver/ToolChains/Gnu.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Gnu.cpp
+++ clang/lib/Driver/ToolChains/Gnu.cpp
@@ -23,6 +23,7 @@
 #include "clang/Driver/Options.h"
 #include "clang/Driver/Tool.h"
 #include "clang/Driver/ToolChain.h"
+#include "llvm/ADT/StringSet.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/Option/ArgList.h"
 #include "llvm/Support/CodeGen.h"
Index: clang/lib/Driver/DriverOptions.cpp
===================================================================
--- clang/lib/Driver/DriverOptions.cpp
+++ clang/lib/Driver/DriverOptions.cpp
@@ -27,6 +27,14 @@
 #include "clang/Driver/Options.inc"
 #undef PREFIX
 
+static constexpr const llvm::StringLiteral PrefixTable_init[] =
+#define PREFIX_UNION(VALUES) VALUES
+#include "clang/Driver/Options.inc"
+#undef PREFIX_UNION
+    ;
+static constexpr const llvm::ArrayRef<llvm::StringLiteral>
+    PrefixTable(PrefixTable_init, std::size(PrefixTable_init) - 1);
+
 static constexpr OptTable::Info InfoTable[] = {
 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
                HELPTEXT, METAVAR, VALUES)                                      \
@@ -38,12 +46,10 @@
 
 namespace {
 
-class DriverOptTable : public OptTable {
+class DriverOptTable : public PrecomputedOptTable {
 public:
-  DriverOptTable()
-    : OptTable(InfoTable) {}
+  DriverOptTable() : PrecomputedOptTable(InfoTable, PrefixTable) {}
 };
-
 }
 
 const llvm::opt::OptTable &clang::driver::getDriverOptTable() {
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to