[clang] a16104e - [Option] Add "Visibility" field and clone the OptTable APIs to use it

Justin Bogner via cfe-commits cfe-commits at lists.llvm.org
Mon Aug 14 13:27:28 PDT 2023


Author: Justin Bogner
Date: 2023-08-14T13:24:54-07:00
New Revision: a16104e6da6f36f3d72dbf53d10ba56495a0d65a

URL: https://github.com/llvm/llvm-project/commit/a16104e6da6f36f3d72dbf53d10ba56495a0d65a
DIFF: https://github.com/llvm/llvm-project/commit/a16104e6da6f36f3d72dbf53d10ba56495a0d65a.diff

LOG: [Option] Add "Visibility" field and clone the OptTable APIs to use it

This splits OptTable's "Flags" field into "Flags" and "Visibility",
updates the places where we instantiate Option tables, and adds
variants of the OptTable APIs that use Visibility mask instead of
Include/Exclude flags.

We need to do this to clean up a bunch of complexity in the clang
driver's option handling - there's a whole slew of flags like
CoreOption, NoDriverOption, and FlangOnlyOption there today to try to
handle all of the permutations of flags that the various drivers need,
but it really doesn't scale well, as can be seen by things like the
somewhat recently introduced CLDXCOption.

Instead, we'll provide an additive model for visibility that's
separate from the other flags. For things like "HelpHidden", which is
used as a "subtractive" modifier for option visibility, we leave that
in "Flags" and handle it as a special case.

Note that we don't actually update the users of the Include/Exclude
APIs here or change the flags that exist in clang at all - that will
come in a follow up that refactors clang's Options.td to use the
increased flexibility this change allows.

Differential Revision: https://reviews.llvm.org/D157149

Added: 
    

Modified: 
    clang-tools-extra/clangd/CompileCommands.cpp
    clang/lib/Frontend/CompilerInvocation.cpp
    lld/MachO/DriverUtils.cpp
    lld/MinGW/Driver.cpp
    lld/wasm/Driver.cpp
    llvm/include/llvm/Option/OptParser.td
    llvm/include/llvm/Option/OptTable.h
    llvm/include/llvm/Option/Option.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-debuginfod/llvm-debuginfod.cpp
    llvm/tools/llvm-dwarfutil/llvm-dwarfutil.cpp
    llvm/tools/llvm-dwp/llvm-dwp.cpp
    llvm/tools/llvm-lipo/llvm-lipo.cpp
    llvm/tools/llvm-mt/llvm-mt.cpp
    llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
    llvm/tools/llvm-rc/llvm-rc.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/OptionMarshallingTest.cpp
    llvm/unittests/Option/OptionParsingTest.cpp
    llvm/unittests/Option/Opts.td
    llvm/utils/TableGen/OptParserEmitter.cpp

Removed: 
    


################################################################################
diff  --git a/clang-tools-extra/clangd/CompileCommands.cpp b/clang-tools-extra/clangd/CompileCommands.cpp
index 00f4c4ca9fef0a..3fce1b8bcb490c 100644
--- a/clang-tools-extra/clangd/CompileCommands.cpp
+++ b/clang-tools-extra/clangd/CompileCommands.cpp
@@ -494,7 +494,7 @@ llvm::ArrayRef<ArgStripper::Rule> ArgStripper::rulesFor(llvm::StringRef Arg) {
   static constexpr llvm::ArrayRef<llvm::StringLiteral> NAME(                   \
       NAME##_init, std::size(NAME##_init) - 1);
 #define OPTION(PREFIX, PREFIXED_NAME, ID, KIND, GROUP, ALIAS, ALIASARGS,       \
-               FLAGS, PARAM, HELP, METAVAR, VALUES)                            \
+               FLAGS, VISIBILITY, PARAM, HELP, METAVAR, VALUES)                \
   Prefixes[DriverID::OPT_##ID] = PREFIX;
 #include "clang/Driver/Options.inc"
 #undef OPTION
@@ -506,7 +506,7 @@ llvm::ArrayRef<ArgStripper::Rule> ArgStripper::rulesFor(llvm::StringRef Arg) {
       const void *AliasArgs;
     } AliasTable[] = {
 #define OPTION(PREFIX, PREFIXED_NAME, ID, KIND, GROUP, ALIAS, ALIASARGS,       \
-               FLAGS, PARAM, HELP, METAVAR, VALUES)                            \
+               FLAGS, VISIBILITY, PARAM, HELP, METAVAR, VALUES)                \
   {DriverID::OPT_##ID, DriverID::OPT_##ALIAS, ALIASARGS},
 #include "clang/Driver/Options.inc"
 #undef OPTION

diff  --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index 87190093767b05..0d7a497cbd42af 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -423,9 +423,9 @@ static T extractMaskValue(T KeyPath) {
 
 #define PARSE_OPTION_WITH_MARSHALLING(                                         \
     ARGS, DIAGS, PREFIX_TYPE, SPELLING, ID, KIND, GROUP, ALIAS, ALIASARGS,     \
-    FLAGS, PARAM, HELPTEXT, METAVAR, VALUES, SHOULD_PARSE, ALWAYS_EMIT,        \
-    KEYPATH, DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER,          \
-    DENORMALIZER, MERGER, EXTRACTOR, TABLE_INDEX)                              \
+    FLAGS, VISIBILITY, PARAM, HELPTEXT, METAVAR, VALUES, SHOULD_PARSE,         \
+    ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE,         \
+    NORMALIZER, DENORMALIZER, MERGER, EXTRACTOR, TABLE_INDEX)                  \
   if ((FLAGS)&options::CC1Option) {                                            \
     KEYPATH = MERGER(KEYPATH, DEFAULT_VALUE);                                  \
     if (IMPLIED_CHECK)                                                         \
@@ -440,9 +440,9 @@ static T extractMaskValue(T KeyPath) {
 // with lifetime extension of the reference.
 #define GENERATE_OPTION_WITH_MARSHALLING(                                      \
     CONSUMER, PREFIX_TYPE, SPELLING, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, \
-    PARAM, HELPTEXT, METAVAR, VALUES, SHOULD_PARSE, ALWAYS_EMIT, KEYPATH,      \
-    DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, DENORMALIZER,     \
-    MERGER, EXTRACTOR, TABLE_INDEX)                                            \
+    VISIBILKITY, PARAM, HELPTEXT, METAVAR, VALUES, SHOULD_PARSE, ALWAYS_EMIT,  \
+    KEYPATH, DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER,          \
+    DENORMALIZER, MERGER, EXTRACTOR, TABLE_INDEX)                              \
   if ((FLAGS)&options::CC1Option) {                                            \
     [&](const auto &Extracted) {                                               \
       if (ALWAYS_EMIT ||                                                       \

diff  --git a/lld/MachO/DriverUtils.cpp b/lld/MachO/DriverUtils.cpp
index b0be96f3592c4a..17499451382a55 100644
--- a/lld/MachO/DriverUtils.cpp
+++ b/lld/MachO/DriverUtils.cpp
@@ -44,9 +44,13 @@ using namespace lld::macho;
 
 // Create table mapping all options defined in Options.td
 static constexpr OptTable::Info optInfo[] = {
-#define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12)      \
-  {X1, X2, X10,         X11,         OPT_##ID, Option::KIND##Class,            \
-   X9, X8, OPT_##GROUP, OPT_##ALIAS, X7,       X12},
+#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS,         \
+               VISIBILITY, PARAM, HELPTEXT, METAVAR, VALUES)                   \
+  {PREFIX,      NAME,        HELPTEXT,                                         \
+   METAVAR,     OPT_##ID,    opt::Option::KIND##Class,                         \
+   PARAM,       FLAGS,       VISIBILITY,                                       \
+   OPT_##GROUP, OPT_##ALIAS, ALIASARGS,                                        \
+   VALUES},
 #include "Options.inc"
 #undef OPTION
 };

diff  --git a/lld/MinGW/Driver.cpp b/lld/MinGW/Driver.cpp
index 67c45051a703a8..ecd5cdf94244cd 100644
--- a/lld/MinGW/Driver.cpp
+++ b/lld/MinGW/Driver.cpp
@@ -71,9 +71,13 @@ enum {
 
 // Create table mapping all options defined in Options.td
 static constexpr opt::OptTable::Info infoTable[] = {
-#define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12)      \
-  {X1, X2, X10,         X11,         OPT_##ID, opt::Option::KIND##Class,       \
-   X9, X8, OPT_##GROUP, OPT_##ALIAS, X7,       X12},
+#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS,         \
+               VISIBILITY, PARAM, HELPTEXT, METAVAR, VALUES)                   \
+  {PREFIX,      NAME,        HELPTEXT,                                         \
+   METAVAR,     OPT_##ID,    opt::Option::KIND##Class,                         \
+   PARAM,       FLAGS,       VISIBILITY,                                       \
+   OPT_##GROUP, OPT_##ALIAS, ALIASARGS,                                        \
+   VALUES},
 #include "Options.inc"
 #undef OPTION
 };

diff  --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp
index c98d3522a5a227..266ca252c1306c 100644
--- a/lld/wasm/Driver.cpp
+++ b/lld/wasm/Driver.cpp
@@ -111,9 +111,13 @@ bool link(ArrayRef<const char *> args, llvm::raw_ostream &stdoutOS,
 
 // Create table mapping all options defined in Options.td
 static constexpr opt::OptTable::Info optInfo[] = {
-#define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12)      \
-  {X1, X2, X10,         X11,         OPT_##ID, opt::Option::KIND##Class,       \
-   X9, X8, OPT_##GROUP, OPT_##ALIAS, X7,       X12},
+#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS,         \
+               VISIBILITY, PARAM, HELPTEXT, METAVAR, VALUES)                   \
+  {PREFIX,      NAME,        HELPTEXT,                                         \
+   METAVAR,     OPT_##ID,    opt::Option::KIND##Class,                         \
+   PARAM,       FLAGS,       VISIBILITY,                                       \
+   OPT_##GROUP, OPT_##ALIAS, ALIASARGS,                                        \
+   VALUES},
 #include "Options.inc"
 #undef OPTION
 };

diff  --git a/llvm/include/llvm/Option/OptParser.td b/llvm/include/llvm/Option/OptParser.td
index 94b945defac110..8f3da090920396 100644
--- a/llvm/include/llvm/Option/OptParser.td
+++ b/llvm/include/llvm/Option/OptParser.td
@@ -73,6 +73,13 @@ def RenderJoined : OptionFlag;
 // (only sensible on joined options).
 def RenderSeparate : OptionFlag;
 
+// Define Visibility categories
+
+class OptionVisibility {}
+
+// Explicit specifier for default visibility
+def Default : OptionVisibility;
+
 // Define the option group class.
 
 class OptionGroup<string name> {
@@ -81,6 +88,7 @@ class OptionGroup<string name> {
   string HelpText = ?;
   OptionGroup Group = ?;
   list<OptionFlag> Flags = [];
+  list<OptionVisibility> Vis = [];
 }
 
 // Define the option class.
@@ -97,6 +105,7 @@ class Option<list<string> prefixes, string name, OptionKind kind> {
   string Values = ?;
   code ValuesCode = ?;
   list<OptionFlag> Flags = [];
+  list<OptionVisibility> Vis = [Default];
   OptionGroup Group = ?;
   Option Alias = ?;
   list<string> AliasArgs = [];
@@ -141,6 +150,7 @@ class Alias<Option alias> { Option Alias = alias; }
 class AliasArgs<list<string> aliasargs> { list<string> AliasArgs = aliasargs; }
 class EnumName<string name> { string EnumName = name; }
 class Flags<list<OptionFlag> flags> { list<OptionFlag> Flags = flags; }
+class Vis<list<OptionVisibility> vis> { list<OptionVisibility> Vis = vis; }
 class Group<OptionGroup group> { OptionGroup Group = group; }
 class HelpText<string text> { string HelpText = text; }
 class MetaVarName<string name> { string MetaVarName = name; }

diff  --git a/llvm/include/llvm/Option/OptTable.h b/llvm/include/llvm/Option/OptTable.h
index 092f41e0ff5a55..262ce103056664 100644
--- a/llvm/include/llvm/Option/OptTable.h
+++ b/llvm/include/llvm/Option/OptTable.h
@@ -30,6 +30,18 @@ class ArgList;
 class InputArgList;
 class Option;
 
+/// Helper for overload resolution while transitioning from
+/// FlagsToInclude/FlagsToExclude APIs to VisibilityMask APIs.
+class Visibility {
+  unsigned Mask = ~0U;
+
+public:
+  explicit Visibility(unsigned Mask) : Mask(Mask) {}
+  Visibility() = default;
+
+  operator unsigned() const { return Mask; }
+};
+
 /// Provide access to the Option info table.
 ///
 /// The OptTable class provides a layer of indirection which allows Option
@@ -51,6 +63,7 @@ class OptTable {
     unsigned char Kind;
     unsigned char Param;
     unsigned int Flags;
+    unsigned int Visibility;
     unsigned short GroupID;
     unsigned short AliasID;
     const char *AliasArgs;
@@ -180,10 +193,8 @@ class OptTable {
   /// string includes prefix dashes "-" as well as values "=l".
   /// \param [out] NearestString - The nearest option string found in the
   /// OptTable.
-  /// \param [in] FlagsToInclude - Only find options with any of these flags.
-  /// Zero is the default, which includes all flags.
-  /// \param [in] FlagsToExclude - Don't find options with this flag. Zero
-  /// is the default, and means exclude nothing.
+  /// \param [in] VisibilityMask - Only include options with any of these
+  ///                              visibility flags set.
   /// \param [in] MinimumLength - Don't find options shorter than this length.
   /// For example, a minimum length of 3 prevents "-x" from being considered
   /// near to "-S".
@@ -192,13 +203,29 @@ class OptTable {
   ///
   /// \return The edit distance of the nearest string found.
   unsigned findNearest(StringRef Option, std::string &NearestString,
-                       unsigned FlagsToInclude = 0, unsigned FlagsToExclude = 0,
+                       Visibility VisibilityMask = Visibility(),
                        unsigned MinimumLength = 4,
                        unsigned MaximumDistance = UINT_MAX) const;
 
+  unsigned findNearest(StringRef Option, std::string &NearestString,
+                       unsigned FlagsToInclude, unsigned FlagsToExclude = 0,
+                       unsigned MinimumLength = 4,
+                       unsigned MaximumDistance = UINT_MAX) const;
+
+private:
+  unsigned
+  internalFindNearest(StringRef Option, std::string &NearestString,
+                      unsigned MinimumLength, unsigned MaximumDistance,
+                      std::function<bool(const Info &)> ExcludeOption) const;
+
+public:
+  bool findExact(StringRef Option, std::string &ExactString,
+                 Visibility VisibilityMask = Visibility()) const {
+    return findNearest(Option, ExactString, VisibilityMask, 4, 0) == 0;
+  }
+
   bool findExact(StringRef Option, std::string &ExactString,
-                 unsigned FlagsToInclude = 0,
-                 unsigned FlagsToExclude = 0) const {
+                 unsigned FlagsToInclude, unsigned FlagsToExclude = 0) const {
     return findNearest(Option, ExactString, FlagsToInclude, FlagsToExclude, 4,
                        0) == 0;
   }
@@ -209,18 +236,26 @@ class OptTable {
   /// \param [in,out] Index - The current parsing position in the argument
   /// string list; on return this will be the index of the next argument
   /// string to parse.
-  /// \param [in] FlagsToInclude - Only parse options with any of these flags.
-  /// Zero is the default which includes all flags.
-  /// \param [in] FlagsToExclude - Don't parse options with this flag.  Zero
-  /// is the default and means exclude nothing.
+  /// \param [in] VisibilityMask - Only include options with any of these
+  /// visibility flags set.
   ///
   /// \return The parsed argument, or 0 if the argument is missing values
   /// (in which case Index still points at the conceptual next argument string
   /// to parse).
+  std::unique_ptr<Arg>
+  ParseOneArg(const ArgList &Args, unsigned &Index,
+              Visibility VisibilityMask = Visibility()) const;
+
   std::unique_ptr<Arg> ParseOneArg(const ArgList &Args, unsigned &Index,
-                                   unsigned FlagsToInclude = 0,
-                                   unsigned FlagsToExclude = 0) const;
+                                   unsigned FlagsToInclude,
+                                   unsigned FlagsToExclude) const;
+
+private:
+  std::unique_ptr<Arg>
+  internalParseOneArg(const ArgList &Args, unsigned &Index,
+                      std::function<bool(const Option &)> ExcludeOption) const;
 
+public:
   /// Parse an list of arguments into an InputArgList.
   ///
   /// The resulting InputArgList will reference the strings in [\p ArgBegin,
@@ -233,16 +268,25 @@ class OptTable {
   /// \param MissingArgIndex - On error, the index of the option which could
   /// not be parsed.
   /// \param MissingArgCount - On error, the number of missing options.
-  /// \param FlagsToInclude - Only parse options with any of these flags.
-  /// Zero is the default which includes all flags.
-  /// \param FlagsToExclude - Don't parse options with this flag.  Zero
-  /// is the default and means exclude nothing.
+  /// \param VisibilityMask - Only include options with any of these
+  /// visibility flags set.
   /// \return An InputArgList; on error this will contain all the options
   /// which could be parsed.
   InputArgList ParseArgs(ArrayRef<const char *> Args, unsigned &MissingArgIndex,
-                         unsigned &MissingArgCount, unsigned FlagsToInclude = 0,
+                         unsigned &MissingArgCount,
+                         Visibility VisibilityMask = Visibility()) const;
+
+  InputArgList ParseArgs(ArrayRef<const char *> Args, unsigned &MissingArgIndex,
+                         unsigned &MissingArgCount, unsigned FlagsToInclude,
                          unsigned FlagsToExclude = 0) const;
 
+private:
+  InputArgList
+  internalParseArgs(ArrayRef<const char *> Args, unsigned &MissingArgIndex,
+                    unsigned &MissingArgCount,
+                    std::function<bool(const Option &)> ExcludeOption) const;
+
+public:
   /// A convenience helper which handles optional initial options populated from
   /// an environment variable, expands response files recursively and parses
   /// options.
@@ -253,26 +297,32 @@ class OptTable {
   /// could be parsed.
   InputArgList parseArgs(int Argc, char *const *Argv, OptSpecifier Unknown,
                          StringSaver &Saver,
-                         function_ref<void(StringRef)> ErrorFn) const;
+                         std::function<void(StringRef)> ErrorFn) const;
 
   /// Render the help text for an option table.
   ///
   /// \param OS - The stream to write the help text to.
   /// \param Usage - USAGE: Usage
   /// \param Title - OVERVIEW: Title
-  /// \param FlagsToInclude - If non-zero, only include options with any
-  ///                         of these flags set.
-  /// \param FlagsToExclude - Exclude options with any of these flags set.
+  /// \param VisibilityMask - Only in                 Visibility VisibilityMask,clude options with any of these
+  ///                         visibility flags set.
+  /// \param ShowHidden     - If true, display options marked as HelpHidden
   /// \param ShowAllAliases - If true, display all options including aliases
   ///                         that don't have help texts. By default, we display
   ///                         only options that are not hidden and have help
   ///                         texts.
+  void printHelp(raw_ostream &OS, const char *Usage, const char *Title,
+                 bool ShowHidden = false, bool ShowAllAliases = false,
+                 Visibility VisibilityMask = Visibility()) const;
+
   void printHelp(raw_ostream &OS, const char *Usage, const char *Title,
                  unsigned FlagsToInclude, unsigned FlagsToExclude,
                  bool ShowAllAliases) const;
 
-  void printHelp(raw_ostream &OS, const char *Usage, const char *Title,
-                 bool ShowHidden = false, bool ShowAllAliases = false) const;
+private:
+  void internalPrintHelp(raw_ostream &OS, const char *Usage, const char *Title,
+                         bool ShowHidden, bool ShowAllAliases,
+                         std::function<bool(const Info &)> ExcludeOption) const;
 };
 
 /// Specialization of OptTable
@@ -305,31 +355,32 @@ class PrecomputedOptTable : public OptTable {
 
 } // end namespace llvm
 
-#define LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(ID_PREFIX, PREFIX, PREFIXED_NAME, ID,  \
-                                        KIND, GROUP, ALIAS, ALIASARGS, FLAGS,  \
-                                        PARAM, HELPTEXT, METAVAR, VALUES)      \
+#define LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(                                       \
+    ID_PREFIX, PREFIX, PREFIXED_NAME, ID, KIND, GROUP, ALIAS, ALIASARGS,       \
+    FLAGS, VISIBILITY, PARAM, HELPTEXT, METAVAR, VALUES)                       \
   ID_PREFIX##ID
 
 #define LLVM_MAKE_OPT_ID(PREFIX, PREFIXED_NAME, ID, KIND, GROUP, ALIAS,        \
-                         ALIASARGS, FLAGS, PARAM, HELPTEXT, METAVAR, VALUES)   \
+                         ALIASARGS, FLAGS, VISIBILITY, PARAM, HELPTEXT,        \
+                         METAVAR, VALUES)                                      \
   LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(OPT_, PREFIX, PREFIXED_NAME, ID, KIND,       \
-                                  GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,       \
-                                  HELPTEXT, METAVAR, VALUE)
+                                  GROUP, ALIAS, ALIASARGS, FLAGS, VISIBILITY,  \
+                                  PARAM, HELPTEXT, METAVAR, VALUE)
 
 #define LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(                                \
     ID_PREFIX, PREFIX, PREFIXED_NAME, ID, KIND, GROUP, ALIAS, ALIASARGS,       \
-    FLAGS, PARAM, HELPTEXT, METAVAR, VALUES)                                   \
+    FLAGS, VISIBILITY, PARAM, HELPTEXT, METAVAR, VALUES)                       \
   llvm::opt::OptTable::Info {                                                  \
     PREFIX, PREFIXED_NAME, HELPTEXT, METAVAR, ID_PREFIX##ID,                   \
-        llvm::opt::Option::KIND##Class, PARAM, FLAGS, ID_PREFIX##GROUP,        \
-        ID_PREFIX##ALIAS, ALIASARGS, VALUES                                    \
+        llvm::opt::Option::KIND##Class, PARAM, FLAGS, VISIBILITY,              \
+        ID_PREFIX##GROUP, ID_PREFIX##ALIAS, ALIASARGS, VALUES                  \
   }
 
 #define LLVM_CONSTRUCT_OPT_INFO(PREFIX, PREFIXED_NAME, ID, KIND, GROUP, ALIAS, \
-                                ALIASARGS, FLAGS, PARAM, HELPTEXT, METAVAR,    \
-                                VALUES)                                        \
-  LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(OPT_, PREFIX, PREFIXED_NAME, ID,      \
-                                         KIND, GROUP, ALIAS, ALIASARGS, FLAGS, \
-                                         PARAM, HELPTEXT, METAVAR, VALUES)
+                                ALIASARGS, FLAGS, VISIBILITY, PARAM, HELPTEXT, \
+                                METAVAR, VALUES)                               \
+  LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(                                      \
+      OPT_, PREFIX, PREFIXED_NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS,   \
+      VISIBILITY, PARAM, HELPTEXT, METAVAR, VALUES)
 
 #endif // LLVM_OPTION_OPTTABLE_H

diff  --git a/llvm/include/llvm/Option/Option.h b/llvm/include/llvm/Option/Option.h
index 2c90745cd3bcd5..90134f02ff6df4 100644
--- a/llvm/include/llvm/Option/Option.h
+++ b/llvm/include/llvm/Option/Option.h
@@ -37,6 +37,10 @@ enum DriverFlag {
   RenderSeparate   = (1 << 3)
 };
 
+enum DriverVisibility {
+  Default = (1 << 0),
+};
+
 /// Option - Abstract representation for a single form of driver
 /// argument.
 ///
@@ -183,6 +187,11 @@ class Option {
     return Info->Flags & Val;
   }
 
+  /// Test if this option has the visibility flag \a Val.
+  bool hasVisibilityFlag(unsigned Val) const {
+    return Info->Visibility & Val;
+  }
+
   /// getUnaliasedOption - Return the final option this option
   /// aliases (itself, if the option has no alias).
   const Option getUnaliasedOption() const {

diff  --git a/llvm/lib/ExecutionEngine/JITLink/COFFDirectiveParser.cpp b/llvm/lib/ExecutionEngine/JITLink/COFFDirectiveParser.cpp
index 957c879cf7559f..f23f3ed9406bdc 100644
--- a/llvm/lib/ExecutionEngine/JITLink/COFFDirectiveParser.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/COFFDirectiveParser.cpp
@@ -36,6 +36,7 @@ static constexpr const ArrayRef<StringLiteral>
     PrefixTable(PrefixTable_init, std::size(PrefixTable_init) - 1);
 
 // Create table mapping all options defined in COFFOptions.td
+using namespace llvm::opt;
 static constexpr opt::OptTable::Info infoTable[] = {
 #define OPTION(...)                                                            \
   LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(COFF_OPT_, __VA_ARGS__),

diff  --git a/llvm/lib/Option/OptTable.cpp b/llvm/lib/Option/OptTable.cpp
index 3d7bef8af0dbc7..baa537adf3cb12 100644
--- a/llvm/lib/Option/OptTable.cpp
+++ b/llvm/lib/Option/OptTable.cpp
@@ -225,10 +225,36 @@ OptTable::findByPrefix(StringRef Cur, unsigned int DisableFlags) const {
   return Ret;
 }
 
+unsigned OptTable::findNearest(StringRef Option, std::string &NearestString,
+                               Visibility VisibilityMask,
+                               unsigned MinimumLength,
+                               unsigned MaximumDistance) const {
+  return internalFindNearest(
+      Option, NearestString, MinimumLength, MaximumDistance,
+      [VisibilityMask](const Info &CandidateInfo) {
+        return (CandidateInfo.Visibility & VisibilityMask) == 0;
+      });
+}
+
 unsigned OptTable::findNearest(StringRef Option, std::string &NearestString,
                                unsigned FlagsToInclude, unsigned FlagsToExclude,
                                unsigned MinimumLength,
                                unsigned MaximumDistance) const {
+  return internalFindNearest(
+      Option, NearestString, MinimumLength, MaximumDistance,
+      [FlagsToInclude, FlagsToExclude](const Info &CandidateInfo) {
+        if (FlagsToInclude && !(CandidateInfo.Flags & FlagsToInclude))
+          return true;
+        if (CandidateInfo.Flags & FlagsToExclude)
+          return true;
+        return false;
+      });
+}
+
+unsigned OptTable::internalFindNearest(
+    StringRef Option, std::string &NearestString, unsigned MinimumLength,
+    unsigned MaximumDistance,
+    std::function<bool(const Info &)> ExcludeOption) const {
   assert(!Option.empty());
 
   // Consider each [option prefix + option name] pair as a candidate, finding
@@ -248,12 +274,8 @@ unsigned OptTable::findNearest(StringRef Option, std::string &NearestString,
     if (CandidateName.size() < MinimumLength)
       continue;
 
-    // * If FlagsToInclude were specified, ignore options that don't include
-    //   those flags.
-    if (FlagsToInclude && !(CandidateInfo.Flags & FlagsToInclude))
-      continue;
-    // * Ignore options that contain the FlagsToExclude.
-    if (CandidateInfo.Flags & FlagsToExclude)
+    // Ignore options that are excluded via masks
+    if (ExcludeOption(CandidateInfo))
       continue;
 
     // * Ignore positional argument option candidates (which do not
@@ -315,8 +337,8 @@ unsigned OptTable::findNearest(StringRef Option, std::string &NearestString,
 
 // Parse a single argument, return the new argument, and update Index. If
 // GroupedShortOptions is true, -a matches "-abc" and the argument in Args will
-// be updated to "-bc". This overload does not support
-// FlagsToInclude/FlagsToExclude or case insensitive options.
+// be updated to "-bc". This overload does not support VisibilityMask or case
+// insensitive options.
 std::unique_ptr<Arg> OptTable::parseOneArgGrouped(InputArgList &Args,
                                                   unsigned &Index) const {
   // Anything that doesn't start with PrefixesUnion is an input, as is '-'
@@ -380,9 +402,29 @@ std::unique_ptr<Arg> OptTable::parseOneArgGrouped(InputArgList &Args,
   return std::make_unique<Arg>(getOption(UnknownOptionID), Str, Index++, CStr);
 }
 
+std::unique_ptr<Arg> OptTable::ParseOneArg(const ArgList &Args, unsigned &Index,
+                                           Visibility VisibilityMask) const {
+  return internalParseOneArg(Args, Index, [VisibilityMask](const Option &Opt) {
+    return !Opt.hasVisibilityFlag(VisibilityMask);
+  });
+}
+
 std::unique_ptr<Arg> OptTable::ParseOneArg(const ArgList &Args, unsigned &Index,
                                            unsigned FlagsToInclude,
                                            unsigned FlagsToExclude) const {
+  return internalParseOneArg(
+      Args, Index, [FlagsToInclude, FlagsToExclude](const Option &Opt) {
+        if (FlagsToInclude && !Opt.hasFlag(FlagsToInclude))
+          return true;
+        if (Opt.hasFlag(FlagsToExclude))
+          return true;
+        return false;
+      });
+}
+
+std::unique_ptr<Arg> OptTable::internalParseOneArg(
+    const ArgList &Args, unsigned &Index,
+    std::function<bool(const Option &)> ExcludeOption) const {
   unsigned Prev = Index;
   StringRef Str = Args.getArgString(Index);
 
@@ -418,9 +460,7 @@ std::unique_ptr<Arg> OptTable::ParseOneArg(const ArgList &Args, unsigned &Index,
 
     Option Opt(Start, this);
 
-    if (FlagsToInclude && !Opt.hasFlag(FlagsToInclude))
-      continue;
-    if (Opt.hasFlag(FlagsToExclude))
+    if (ExcludeOption(Opt))
       continue;
 
     // See if this option matches.
@@ -444,11 +484,37 @@ std::unique_ptr<Arg> OptTable::ParseOneArg(const ArgList &Args, unsigned &Index,
                                Str.data());
 }
 
-InputArgList OptTable::ParseArgs(ArrayRef<const char *> ArgArr,
+InputArgList OptTable::ParseArgs(ArrayRef<const char *> Args,
+                                 unsigned &MissingArgIndex,
+                                 unsigned &MissingArgCount,
+                                 Visibility VisibilityMask) const {
+  return internalParseArgs(
+      Args, MissingArgIndex, MissingArgCount,
+      [VisibilityMask](const Option &Opt) {
+        return !Opt.hasVisibilityFlag(VisibilityMask);
+      });
+}
+
+InputArgList OptTable::ParseArgs(ArrayRef<const char *> Args,
                                  unsigned &MissingArgIndex,
                                  unsigned &MissingArgCount,
                                  unsigned FlagsToInclude,
                                  unsigned FlagsToExclude) const {
+  return internalParseArgs(
+      Args, MissingArgIndex, MissingArgCount,
+      [FlagsToInclude, FlagsToExclude](const Option &Opt) {
+        if (FlagsToInclude && !Opt.hasFlag(FlagsToInclude))
+          return true;
+        if (Opt.hasFlag(FlagsToExclude))
+          return true;
+        return false;
+      });
+}
+
+InputArgList OptTable::internalParseArgs(
+    ArrayRef<const char *> ArgArr, unsigned &MissingArgIndex,
+    unsigned &MissingArgCount,
+    std::function<bool(const Option &)> ExcludeOption) const {
   InputArgList Args(ArgArr.begin(), ArgArr.end());
 
   // FIXME: Handle '@' args (or at least error on them).
@@ -481,7 +547,7 @@ InputArgList OptTable::ParseArgs(ArrayRef<const char *> ArgArr,
     unsigned Prev = Index;
     std::unique_ptr<Arg> A = GroupedShortOptions
                  ? parseOneArgGrouped(Args, Index)
-                 : ParseOneArg(Args, Index, FlagsToInclude, FlagsToExclude);
+                 : internalParseOneArg(Args, Index, ExcludeOption);
     assert((Index > Prev || GroupedShortOptions) &&
            "Parser failed to consume argument.");
 
@@ -502,7 +568,7 @@ InputArgList OptTable::ParseArgs(ArrayRef<const char *> ArgArr,
 
 InputArgList OptTable::parseArgs(int Argc, char *const *Argv,
                                  OptSpecifier Unknown, StringSaver &Saver,
-                                 function_ref<void(StringRef)> ErrorFn) const {
+                                 std::function<void(StringRef)> ErrorFn) const {
   SmallVector<const char *, 0> NewArgv;
   // The environment variable specifies initial options which can be overridden
   // by commnad line options.
@@ -626,14 +692,35 @@ static const char *getOptionHelpGroup(const OptTable &Opts, OptSpecifier Id) {
 }
 
 void OptTable::printHelp(raw_ostream &OS, const char *Usage, const char *Title,
-                         bool ShowHidden, bool ShowAllAliases) const {
-  printHelp(OS, Usage, Title, /*Include*/ 0, /*Exclude*/
-            (ShowHidden ? 0 : HelpHidden), ShowAllAliases);
+                         bool ShowHidden, bool ShowAllAliases,
+                         Visibility VisibilityMask) const {
+  return internalPrintHelp(
+      OS, Usage, Title, ShowHidden, ShowAllAliases,
+      [VisibilityMask](const Info &CandidateInfo) -> bool {
+        return (CandidateInfo.Visibility & VisibilityMask) == 0;
+      });
 }
 
 void OptTable::printHelp(raw_ostream &OS, const char *Usage, const char *Title,
                          unsigned FlagsToInclude, unsigned FlagsToExclude,
                          bool ShowAllAliases) const {
+  bool ShowHidden = !(FlagsToExclude & HelpHidden);
+  FlagsToExclude &= ~HelpHidden;
+  return internalPrintHelp(
+      OS, Usage, Title, ShowHidden, ShowAllAliases,
+      [FlagsToInclude, FlagsToExclude](const Info &CandidateInfo) {
+        if (FlagsToInclude && !(CandidateInfo.Flags & FlagsToInclude))
+          return true;
+        if (CandidateInfo.Flags & FlagsToExclude)
+          return true;
+        return false;
+      });
+}
+
+void OptTable::internalPrintHelp(
+    raw_ostream &OS, const char *Usage, const char *Title, bool ShowHidden,
+    bool ShowAllAliases,
+    std::function<bool(const Info &)> ExcludeOption) const {
   OS << "OVERVIEW: " << Title << "\n\n";
   OS << "USAGE: " << Usage << "\n\n";
 
@@ -646,10 +733,11 @@ void OptTable::printHelp(raw_ostream &OS, const char *Usage, const char *Title,
     if (getOptionKind(Id) == Option::GroupClass)
       continue;
 
-    unsigned Flags = getInfo(Id).Flags;
-    if (FlagsToInclude && !(Flags & FlagsToInclude))
+    const Info &CandidateInfo = getInfo(Id);
+    if (!ShowHidden && (CandidateInfo.Flags & opt::HelpHidden))
       continue;
-    if (Flags & FlagsToExclude)
+
+    if (ExcludeOption(CandidateInfo))
       continue;
 
     // If an alias doesn't have a help text, show a help text for the aliased

diff  --git a/llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp b/llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp
index df05f507ef0c70..781bc9a058e1fd 100644
--- a/llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp
+++ b/llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp
@@ -45,6 +45,7 @@ enum {
 #include "Options.inc"
 #undef PREFIX
 
+using namespace llvm::opt;
 static constexpr opt::OptTable::Info InfoTable[] = {
 #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
 #include "Options.inc"

diff  --git a/llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp b/llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp
index d158795d7bb803..158bbbdfc9b897 100644
--- a/llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp
+++ b/llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp
@@ -51,6 +51,7 @@ enum {
 #include "Options.inc"
 #undef PREFIX
 
+using namespace llvm::opt;
 static constexpr opt::OptTable::Info InfoTable[] = {
 #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
 #include "Options.inc"

diff  --git a/llvm/tools/dsymutil/dsymutil.cpp b/llvm/tools/dsymutil/dsymutil.cpp
index 6f1e06cf2f6591..20d11bceb05eed 100644
--- a/llvm/tools/dsymutil/dsymutil.cpp
+++ b/llvm/tools/dsymutil/dsymutil.cpp
@@ -71,6 +71,7 @@ enum ID {
 #include "Options.inc"
 #undef PREFIX
 
+using namespace llvm::opt;
 static constexpr opt::OptTable::Info InfoTable[] = {
 #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
 #include "Options.inc"

diff  --git a/llvm/tools/llvm-cvtres/llvm-cvtres.cpp b/llvm/tools/llvm-cvtres/llvm-cvtres.cpp
index 0bc1bcb84822ef..0c10769a9488ea 100644
--- a/llvm/tools/llvm-cvtres/llvm-cvtres.cpp
+++ b/llvm/tools/llvm-cvtres/llvm-cvtres.cpp
@@ -49,6 +49,7 @@ enum ID {
 #include "Opts.inc"
 #undef PREFIX
 
+using namespace llvm::opt;
 static constexpr opt::OptTable::Info InfoTable[] = {
 #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
 #include "Opts.inc"

diff  --git a/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp b/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp
index 17476293de2744..734064371f2e81 100644
--- a/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp
+++ b/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp
@@ -39,6 +39,7 @@ enum ID {
 #include "Opts.inc"
 #undef PREFIX
 
+using namespace llvm::opt;
 static constexpr opt::OptTable::Info InfoTable[] = {
 #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
 #include "Opts.inc"

diff  --git a/llvm/tools/llvm-debuginfod/llvm-debuginfod.cpp b/llvm/tools/llvm-debuginfod/llvm-debuginfod.cpp
index cc1f38c4e2b42f..1869f2eb4bc6d4 100644
--- a/llvm/tools/llvm-debuginfod/llvm-debuginfod.cpp
+++ b/llvm/tools/llvm-debuginfod/llvm-debuginfod.cpp
@@ -43,6 +43,7 @@ enum ID {
 #include "Opts.inc"
 #undef PREFIX
 
+using namespace llvm::opt;
 static constexpr opt::OptTable::Info InfoTable[] = {
 #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
 #include "Opts.inc"

diff  --git a/llvm/tools/llvm-dwarfutil/llvm-dwarfutil.cpp b/llvm/tools/llvm-dwarfutil/llvm-dwarfutil.cpp
index 08ff4c53c436aa..e09060abb62673 100644
--- a/llvm/tools/llvm-dwarfutil/llvm-dwarfutil.cpp
+++ b/llvm/tools/llvm-dwarfutil/llvm-dwarfutil.cpp
@@ -45,6 +45,7 @@ enum ID {
 #include "Options.inc"
 #undef PREFIX
 
+using namespace llvm::opt;
 static constexpr opt::OptTable::Info InfoTable[] = {
 #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
 #include "Options.inc"

diff  --git a/llvm/tools/llvm-dwp/llvm-dwp.cpp b/llvm/tools/llvm-dwp/llvm-dwp.cpp
index af5621e24b65d3..f976298dcadc2f 100644
--- a/llvm/tools/llvm-dwp/llvm-dwp.cpp
+++ b/llvm/tools/llvm-dwp/llvm-dwp.cpp
@@ -55,6 +55,7 @@ enum ID {
 #include "Opts.inc"
 #undef PREFIX
 
+using namespace llvm::opt;
 static constexpr opt::OptTable::Info InfoTable[] = {
 #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
 #include "Opts.inc"

diff  --git a/llvm/tools/llvm-lipo/llvm-lipo.cpp b/llvm/tools/llvm-lipo/llvm-lipo.cpp
index 82b8b3dbb03d13..b1f202877b15e8 100644
--- a/llvm/tools/llvm-lipo/llvm-lipo.cpp
+++ b/llvm/tools/llvm-lipo/llvm-lipo.cpp
@@ -80,6 +80,7 @@ namespace lipo {
 #include "LipoOpts.inc"
 #undef PREFIX
 
+using namespace llvm::opt;
 static constexpr opt::OptTable::Info LipoInfoTable[] = {
 #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(LIPO_, __VA_ARGS__),
 #include "LipoOpts.inc"

diff  --git a/llvm/tools/llvm-mt/llvm-mt.cpp b/llvm/tools/llvm-mt/llvm-mt.cpp
index f3283a4a5a7c2e..246e092898b3bd 100644
--- a/llvm/tools/llvm-mt/llvm-mt.cpp
+++ b/llvm/tools/llvm-mt/llvm-mt.cpp
@@ -47,6 +47,7 @@ enum ID {
 #include "Opts.inc"
 #undef PREFIX
 
+using namespace llvm::opt;
 static constexpr opt::OptTable::Info InfoTable[] = {
 #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
 #include "Opts.inc"

diff  --git a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
index 02b7790ecb3e78..d33adb0b6a3e47 100644
--- a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
+++ b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
@@ -26,6 +26,7 @@
 
 using namespace llvm;
 using namespace llvm::objcopy;
+using namespace llvm::opt;
 
 namespace {
 enum ObjcopyID {

diff  --git a/llvm/tools/llvm-rc/llvm-rc.cpp b/llvm/tools/llvm-rc/llvm-rc.cpp
index 5745901ea4a87a..ec1cdae27cf62b 100644
--- a/llvm/tools/llvm-rc/llvm-rc.cpp
+++ b/llvm/tools/llvm-rc/llvm-rc.cpp
@@ -44,6 +44,7 @@
 
 using namespace llvm;
 using namespace llvm::rc;
+using namespace llvm::opt;
 
 namespace {
 

diff  --git a/llvm/tools/llvm-strings/llvm-strings.cpp b/llvm/tools/llvm-strings/llvm-strings.cpp
index 9a727205e834a0..8642be3127fed5 100644
--- a/llvm/tools/llvm-strings/llvm-strings.cpp
+++ b/llvm/tools/llvm-strings/llvm-strings.cpp
@@ -45,6 +45,7 @@ enum ID {
 #include "Opts.inc"
 #undef PREFIX
 
+using namespace llvm::opt;
 static constexpr opt::OptTable::Info InfoTable[] = {
 #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
 #include "Opts.inc"

diff  --git a/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp b/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp
index 478ebc1851cd13..f43aad6c4cf7c8 100644
--- a/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp
+++ b/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp
@@ -62,6 +62,7 @@ enum ID {
 #include "Opts.inc"
 #undef PREFIX
 
+using namespace llvm::opt;
 static constexpr opt::OptTable::Info InfoTable[] = {
 #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
 #include "Opts.inc"

diff  --git a/llvm/tools/llvm-tli-checker/llvm-tli-checker.cpp b/llvm/tools/llvm-tli-checker/llvm-tli-checker.cpp
index 2adce18c85fc0b..a091e37ff4026d 100644
--- a/llvm/tools/llvm-tli-checker/llvm-tli-checker.cpp
+++ b/llvm/tools/llvm-tli-checker/llvm-tli-checker.cpp
@@ -40,6 +40,7 @@ enum ID {
 #include "Opts.inc"
 #undef PREFIX
 
+using namespace llvm::opt;
 static constexpr opt::OptTable::Info InfoTable[] = {
 #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
 #include "Opts.inc"

diff  --git a/llvm/unittests/Option/OptionMarshallingTest.cpp b/llvm/unittests/Option/OptionMarshallingTest.cpp
index d9320950845392..339d825c2016bf 100644
--- a/llvm/unittests/Option/OptionMarshallingTest.cpp
+++ b/llvm/unittests/Option/OptionMarshallingTest.cpp
@@ -19,9 +19,9 @@ struct OptionWithMarshallingInfo {
 static const OptionWithMarshallingInfo MarshallingTable[] = {
 #define OPTION_WITH_MARSHALLING(                                               \
     PREFIX_TYPE, PREFIXED_NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS,      \
-    PARAM, HELPTEXT, METAVAR, VALUES, SHOULD_PARSE, ALWAYS_EMIT, KEYPATH,      \
-    DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, DENORMALIZER,     \
-    MERGER, EXTRACTOR, TABLE_INDEX)                                            \
+    VISIBILITY, PARAM, HELPTEXT, METAVAR, VALUES, SHOULD_PARSE, ALWAYS_EMIT,   \
+    KEYPATH, DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER,          \
+    DENORMALIZER, MERGER, EXTRACTOR, TABLE_INDEX)                              \
   {PREFIXED_NAME, #KEYPATH, #IMPLIED_CHECK, #IMPLIED_VALUE},
 #include "Opts.inc"
 #undef OPTION_WITH_MARSHALLING

diff  --git a/llvm/unittests/Option/OptionParsingTest.cpp b/llvm/unittests/Option/OptionParsingTest.cpp
index e6ca41005c522c..d9a2a9ed2e9645 100644
--- a/llvm/unittests/Option/OptionParsingTest.cpp
+++ b/llvm/unittests/Option/OptionParsingTest.cpp
@@ -44,6 +44,10 @@ enum OptionFlags {
   OptFlag3 = (1 << 6)
 };
 
+enum OptionVisibility {
+  SubtoolVis = (1 << 2),
+};
+
 static constexpr OptTable::Info InfoTable[] = {
 #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
 #include "Opts.inc"
@@ -163,6 +167,43 @@ TYPED_TEST(OptTableTest, ParseWithFlagExclusions) {
   EXPECT_EQ("bar", AL.getLastArgValue(OPT_C));
 }
 
+TYPED_TEST(OptTableTest, ParseWithVisibility) {
+  TypeParam T;
+  unsigned MAI, MAC;
+
+  const char *STArgs[] = {"-A", "-Q", "-R"};
+
+  // With no visibility specified, we find all of the arguments.
+  InputArgList AL = T.ParseArgs(STArgs, MAI, MAC);
+  EXPECT_TRUE(AL.hasArg(OPT_A));
+  EXPECT_TRUE(AL.hasArg(OPT_Q));
+  EXPECT_TRUE(AL.hasArg(OPT_R));
+
+  // Default visibility omits SubtoolVis.
+  AL = T.ParseArgs(STArgs, MAI, MAC, Visibility(Default));
+  EXPECT_TRUE(AL.hasArg(OPT_A));
+  EXPECT_FALSE(AL.hasArg(OPT_Q));
+  EXPECT_TRUE(AL.hasArg(OPT_R));
+
+  // ~SubtoolVis still finds arguments that are visible in Default.
+  AL = T.ParseArgs(STArgs, MAI, MAC, Visibility(~SubtoolVis));
+  EXPECT_TRUE(AL.hasArg(OPT_A));
+  EXPECT_FALSE(AL.hasArg(OPT_Q));
+  EXPECT_TRUE(AL.hasArg(OPT_R));
+
+  // Only SubtoolVis.
+  AL = T.ParseArgs(STArgs, MAI, MAC, Visibility(SubtoolVis));
+  EXPECT_FALSE(AL.hasArg(OPT_A));
+  EXPECT_TRUE(AL.hasArg(OPT_Q));
+  EXPECT_TRUE(AL.hasArg(OPT_R));
+
+  // Both Default and SubtoolVis are found.
+  AL = T.ParseArgs(STArgs, MAI, MAC, Visibility(Default | SubtoolVis));
+  EXPECT_TRUE(AL.hasArg(OPT_A));
+  EXPECT_TRUE(AL.hasArg(OPT_Q));
+  EXPECT_TRUE(AL.hasArg(OPT_R));
+}
+
 TYPED_TEST(OptTableTest, ParseAliasInGroup) {
   TypeParam T;
   unsigned MAI, MAC;
@@ -345,6 +386,12 @@ TYPED_TEST(OptTableTest, FindNearest) {
                               /*FlagsToInclude=*/0,
                               /*FlagsToExclude=*/OptFlag2));
   EXPECT_EQ(Nearest, "-doopf1");
+
+  // Spelling should respect visibility.
+  EXPECT_EQ(1U, T.findNearest("-xyzzy", Nearest, Visibility(Default)));
+  EXPECT_EQ(Nearest, "-xyzzy2");
+  EXPECT_EQ(1U, T.findNearest("-xyzzy", Nearest, Visibility(SubtoolVis)));
+  EXPECT_EQ(Nearest, "-xyzzy1");
 }
 
 TYPED_TEST(DISABLED_OptTableTest, FindNearestFIXME) {

diff  --git a/llvm/unittests/Option/Opts.td b/llvm/unittests/Option/Opts.td
index cdfc614e4621c2..b973c1aae1b9f3 100644
--- a/llvm/unittests/Option/Opts.td
+++ b/llvm/unittests/Option/Opts.td
@@ -4,6 +4,8 @@ def OptFlag1 : OptionFlag;
 def OptFlag2 : OptionFlag;
 def OptFlag3 : OptionFlag;
 
+def SubtoolVis : OptionVisibility;
+
 def A : Flag<["-"], "A">, HelpText<"The A option">, Flags<[OptFlag1]>;
 def AB : Flag<["-"], "AB">;
 def B : Joined<["-"], "B">, HelpText<"The B option">, MetaVarName<"B">, Flags<[OptFlag2]>;
@@ -35,6 +37,8 @@ def Blarn : Flag<["--", "-"], "blarn">, HelpText<"The blarn option">, Flags<[Opt
 def Cramb : Joined<["/"], "cramb:">, HelpText<"The cramb option">, MetaVarName<"CRAMB">, Flags<[OptFlag1]>;
 def Doopf1 : Flag<["-"], "doopf1">, HelpText<"The doopf1 option">, Flags<[OptFlag1]>;
 def Doopf2 : Flag<["-"], "doopf2">, HelpText<"The doopf2 option">, Flags<[OptFlag2]>;
+def Xyzzy1 : Flag<["-"], "xyzzy1">, HelpText<"The xyzzy1 option">, Vis<[SubtoolVis]>;
+def Xyzzy2 : Flag<["-"], "xyzzy2">, HelpText<"The xyzzy2 option">, Vis<[Default]>;
 def Ermgh : Joined<["--"], "ermgh">, HelpText<"The ermgh option">, MetaVarName<"ERMGH">, Flags<[OptFlag1]>;
 def Fjormp : Flag<["--"], "fjormp">, HelpText<"The fjormp option">, Flags<[OptFlag1]>;
 
@@ -43,6 +47,9 @@ def Glorrmp_eq : Flag<["--"], "glorrmp=">;
 def Blurmpq : Flag<["--"], "blurmp">;
 def Blurmpq_eq : Flag<["--"], "blurmp=">;
 
+def Q : Flag<["-"], "Q">, Vis<[SubtoolVis]>;
+def R : Flag<["-"], "R">, Vis<[Default, SubtoolVis]>;
+
 class XOpts<string base> : KeyPathAndMacro<"X->", base> {}
 
 def marshalled_flag_d : Flag<["-"], "marshalled-flag-d">,

diff  --git a/llvm/utils/TableGen/OptParserEmitter.cpp b/llvm/utils/TableGen/OptParserEmitter.cpp
index ff9736781ce20a..1ac0ae10d03a46 100644
--- a/llvm/utils/TableGen/OptParserEmitter.cpp
+++ b/llvm/utils/TableGen/OptParserEmitter.cpp
@@ -302,7 +302,7 @@ static void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) {
       OS << "INVALID";
 
     // The other option arguments (unused for groups).
-    OS << ", INVALID, nullptr, 0, 0";
+    OS << ", INVALID, nullptr, 0, 0, 0";
 
     // The option help text.
     if (!isa<UnsetInit>(R.getValueInit("HelpText"))) {
@@ -340,8 +340,10 @@ static void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) {
     // The containing option group (if any).
     OS << ", ";
     const ListInit *GroupFlags = nullptr;
+    const ListInit *GroupVis = nullptr;
     if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group"))) {
       GroupFlags = DI->getDef()->getValueAsListInit("Flags");
+      GroupVis = DI->getDef()->getValueAsListInit("Vis");
       OS << getOptionName(*DI->getDef());
     } else
       OS << "INVALID";
@@ -368,7 +370,7 @@ static void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) {
       OS << "\"";
     }
 
-    // The option flags.
+    // "Flags" for the option, such as HelpHidden and Render*
     OS << ", ";
     int NumFlags = 0;
     const ListInit *LI = R.getValueAsListInit("Flags");
@@ -382,6 +384,21 @@ static void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) {
     if (NumFlags == 0)
       OS << '0';
 
+    // Option visibility, for sharing options between drivers.
+    OS << ", ";
+    int NumVisFlags = 0;
+    LI = R.getValueAsListInit("Vis");
+    for (Init *I : *LI)
+      OS << (NumVisFlags++ ? " | " : "")
+         << cast<DefInit>(I)->getDef()->getName();
+    if (GroupVis) {
+      for (Init *I : *GroupVis)
+        OS << (NumVisFlags++ ? " | " : "")
+           << cast<DefInit>(I)->getDef()->getName();
+    }
+    if (NumVisFlags == 0)
+      OS << '0';
+
     // The option parameter field.
     OS << ", " << R.getValueAsInt("NumArgs");
 


        


More information about the cfe-commits mailing list