[clang] [clang-tools-extra] [flang] [lld] [llvm] [flang][clang] Add Visibility specific help text for options (PR #81869)

David Spickett via cfe-commits cfe-commits at lists.llvm.org
Tue Feb 27 02:15:51 PST 2024


https://github.com/DavidSpickett updated https://github.com/llvm/llvm-project/pull/81869

>From 72bbd9d38cb6e292d92391fcf04154cfbc336192 Mon Sep 17 00:00:00 2001
From: David Spickett <david.spickett at linaro.org>
Date: Thu, 15 Feb 2024 09:52:22 +0000
Subject: [PATCH 1/4] [flang][clang] Add Visibility specific help text for
 options

And use it to print the correct default OpenMP version for flang.

This change adds an optional HelpTextForVisibility to options.
This allows you to change the help text (shown in documentation
and --help) for one specific visibility.

It could be generalised to a list, but we only need to pick out
flang right now so I've kept it simple but not so simple that it's
"if flang else".

For example the OpenMP option will show one default value for
Clang and another for Flang. Clang will use the existing HelpText
string.

I have not applied this to group descriptions just because
I don't know of one that needs changing. It could easily be
enabled for those too if needed. There are minor changes to them
just to get it all to compile.

This approach of storing many help strings per option in the 1
driver library seemed perferrable to making a whole new library
for Flang (even if that would mostly be including stuff from Clang).
---
 clang/include/clang/Driver/Options.td         |  5 ++-
 clang/lib/Frontend/CompilerInvocation.cpp     | 16 ++++----
 .../utils/TableGen/ClangOptionDocEmitter.cpp  | 21 +++++++++-
 flang/test/Driver/driver-help-hidden.f90      |  2 +-
 flang/test/Driver/driver-help.f90             |  2 +-
 lld/MachO/DriverUtils.cpp                     | 20 ++++++---
 lld/MinGW/Driver.cpp                          | 20 ++++++---
 lld/wasm/Driver.cpp                           | 20 ++++++---
 llvm/include/llvm/Option/OptParser.td         | 10 +++++
 llvm/include/llvm/Option/OptTable.h           | 41 +++++++++++++------
 llvm/lib/Option/OptTable.cpp                  | 14 ++++---
 .../Option/OptionMarshallingTest.cpp          |  6 +--
 llvm/utils/TableGen/OptParserEmitter.cpp      | 16 ++++++++
 13 files changed, 143 insertions(+), 50 deletions(-)

diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 3a028fadb25b18..765d5fbc1e692d 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -3385,7 +3385,10 @@ def fno_openmp : Flag<["-"], "fno-openmp">, Group<f_Group>,
 def fopenmp_version_EQ : Joined<["-"], "fopenmp-version=">, Group<f_Group>,
   Flags<[NoArgumentUnused]>,
   Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>,
-  HelpText<"Set OpenMP version (e.g. 45 for OpenMP 4.5, 51 for OpenMP 5.1). Default value is 51 for Clang">;
+  HelpText<"Set OpenMP version (e.g. 45 for OpenMP 4.5, 51 for OpenMP 5.1). Default value is 51 for Clang">,
+  HelpForVisibility<HelpTextForVisibility<FlangOption,
+    "Set OpenMP version (e.g. 45 for OpenMP 4.5, 51 for OpenMP 5.1). Default value is 11 for Flang"
+  >>;
 defm openmp_extensions: BoolFOption<"openmp-extensions",
   LangOpts<"OpenMPExtensions">, DefaultTrue,
   PosFlag<SetTrue, [NoArgumentUnused], [ClangOption, CC1Option],
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index 8d7b75b56d6129..790b0fb51cbfbd 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -522,10 +522,10 @@ static T extractMaskValue(T KeyPath) {
 
 #define PARSE_OPTION_WITH_MARSHALLING(                                         \
     ARGS, DIAGS, PREFIX_TYPE, SPELLING, ID, KIND, GROUP, ALIAS, ALIASARGS,     \
-    FLAGS, VISIBILITY, PARAM, HELPTEXT, METAVAR, VALUES, SHOULD_PARSE,         \
-    ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE,         \
-    NORMALIZER, DENORMALIZER, MERGER, EXTRACTOR, TABLE_INDEX)                  \
-  if ((VISIBILITY)&options::CC1Option) {                                       \
+    FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTFORVISIBILITY, METAVAR,        \
+    VALUES, SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, IMPLIED_CHECK,  \
+    IMPLIED_VALUE, NORMALIZER, DENORMALIZER, MERGER, EXTRACTOR, TABLE_INDEX)   \
+  if ((VISIBILITY) & options::CC1Option) {                                     \
     KEYPATH = MERGER(KEYPATH, DEFAULT_VALUE);                                  \
     if (IMPLIED_CHECK)                                                         \
       KEYPATH = MERGER(KEYPATH, IMPLIED_VALUE);                                \
@@ -539,10 +539,10 @@ 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, \
-    VISIBILITY, PARAM, HELPTEXT, METAVAR, VALUES, SHOULD_PARSE, ALWAYS_EMIT,   \
-    KEYPATH, DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER,          \
-    DENORMALIZER, MERGER, EXTRACTOR, TABLE_INDEX)                              \
-  if ((VISIBILITY)&options::CC1Option) {                                       \
+    VISIBILITY, PARAM, HELPTEXT, HELPTEXTFORVISIBILITY, METAVAR, VALUES,       \
+    SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, IMPLIED_CHECK,          \
+    IMPLIED_VALUE, NORMALIZER, DENORMALIZER, MERGER, EXTRACTOR, TABLE_INDEX)   \
+  if ((VISIBILITY) & options::CC1Option) {                                     \
     [&](const auto &Extracted) {                                               \
       if (ALWAYS_EMIT ||                                                       \
           (Extracted !=                                                        \
diff --git a/clang/utils/TableGen/ClangOptionDocEmitter.cpp b/clang/utils/TableGen/ClangOptionDocEmitter.cpp
index 3fe98909940749..1ad3fcc3d76b82 100644
--- a/clang/utils/TableGen/ClangOptionDocEmitter.cpp
+++ b/clang/utils/TableGen/ClangOptionDocEmitter.cpp
@@ -359,8 +359,25 @@ void emitOption(const DocumentedOption &Option, const Record *DocInfo,
 
   // Emit the description, if we have one.
   const Record *R = Option.Option;
-  std::string Description =
-      getRSTStringWithTextFallback(R, "DocBrief", "HelpText");
+  std::string Description;
+
+  // Prefer a program specific help string.
+  if (!isa<UnsetInit>(R->getValueInit("HelpTextForVisibility"))) {
+    const Record *VisibilityHelp = R->getValueAsDef("HelpTextForVisibility");
+    std::string VisibilityStr =
+        VisibilityHelp->getValue("Visibility")->getValue()->getAsString();
+
+    for (StringRef Mask : DocInfo->getValueAsListOfStrings("VisibilityMask")) {
+      if (VisibilityStr == Mask) {
+        Description = escapeRST(VisibilityHelp->getValueAsString("Text"));
+        break;
+      }
+    }
+  }
+
+  // If there's not a program specific string, use the default one.
+  if (Description.empty())
+    Description = getRSTStringWithTextFallback(R, "DocBrief", "HelpText");
 
   if (!isa<UnsetInit>(R->getValueInit("Values"))) {
     if (!Description.empty() && Description.back() != '.')
diff --git a/flang/test/Driver/driver-help-hidden.f90 b/flang/test/Driver/driver-help-hidden.f90
index 44dbac44772b29..94f2f4d1f522ec 100644
--- a/flang/test/Driver/driver-help-hidden.f90
+++ b/flang/test/Driver/driver-help-hidden.f90
@@ -83,7 +83,7 @@
 ! CHECK-NEXT: -fopenmp-targets=<value>
 ! CHECK-NEXT:                         Specify comma-separated list of triples OpenMP offloading targets to be supported
 ! CHECK-NEXT: -fopenmp-version=<value>
-! CHECK-NEXT:                         Set OpenMP version (e.g. 45 for OpenMP 4.5, 51 for OpenMP 5.1). Default value is 51 for Clang
+! CHECK-NEXT:                         Set OpenMP version (e.g. 45 for OpenMP 4.5, 51 for OpenMP 5.1). Default value is 11 for Flang
 ! CHECK-NEXT: -fopenmp                Parse OpenMP pragmas and generate parallel code.
 ! CHECK-NEXT: -foptimization-record-file=<file>
 ! CHECK-NEXT:                         Specify the output name of the file containing the optimization remarks. Implies -fsave-optimization-record. On Darwin platforms, this cannot be used with multiple -arch <arch> options.
diff --git a/flang/test/Driver/driver-help.f90 b/flang/test/Driver/driver-help.f90
index b4280a454e3128..31bc67e1742482 100644
--- a/flang/test/Driver/driver-help.f90
+++ b/flang/test/Driver/driver-help.f90
@@ -69,7 +69,7 @@
 ! HELP-NEXT: -fopenmp-targets=<value>
 ! HELP-NEXT:                         Specify comma-separated list of triples OpenMP offloading targets to be supported
 ! HELP-NEXT: -fopenmp-version=<value>
-! HELP-NEXT:                         Set OpenMP version (e.g. 45 for OpenMP 4.5, 51 for OpenMP 5.1). Default value is 51 for Clang
+! HELP-NEXT:                         Set OpenMP version (e.g. 45 for OpenMP 4.5, 51 for OpenMP 5.1). Default value is 11 for Flang
 ! HELP-NEXT: -fopenmp                Parse OpenMP pragmas and generate parallel code.
 ! HELP-NEXT: -foptimization-record-file=<file>
 ! HELP-NEXT:                         Specify the output name of the file containing the optimization remarks. Implies -fsave-optimization-record. On Darwin platforms, this cannot be used with multiple -arch <arch> options.
diff --git a/lld/MachO/DriverUtils.cpp b/lld/MachO/DriverUtils.cpp
index d6f18ecb85b8a8..ea86b8074b146b 100644
--- a/lld/MachO/DriverUtils.cpp
+++ b/lld/MachO/DriverUtils.cpp
@@ -45,11 +45,21 @@ using namespace lld::macho;
 // Create table mapping all options defined in Options.td
 static constexpr OptTable::Info optInfo[] = {
 #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,                                        \
+               VISIBILITY, PARAM, HELPTEXT, HELPTEXTFORVISIBILITY, METAVAR,    \
+               VALUES)                                                         \
+  {PREFIX,                                                                     \
+   NAME,                                                                       \
+   HELPTEXT,                                                                   \
+   HELPTEXTFORVISIBILITY,                                                      \
+   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 efd643f9a32203..3a1eb082d9df2b 100644
--- a/lld/MinGW/Driver.cpp
+++ b/lld/MinGW/Driver.cpp
@@ -69,11 +69,21 @@ enum {
 // Create table mapping all options defined in Options.td
 static constexpr opt::OptTable::Info infoTable[] = {
 #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,                                        \
+               VISIBILITY, PARAM, HELPTEXT, HELPTEXTFORVISIBILITY, METAVAR,    \
+               VALUES)                                                         \
+  {PREFIX,                                                                     \
+   NAME,                                                                       \
+   HELPTEXT,                                                                   \
+   HELPTEXTFORVISIBILITY,                                                      \
+   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 635f19f78b15e6..79dda5a41a4001 100644
--- a/lld/wasm/Driver.cpp
+++ b/lld/wasm/Driver.cpp
@@ -132,11 +132,21 @@ 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(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,                                        \
+               VISIBILITY, PARAM, HELPTEXT, HELPTEXTFORVISIBILITY, METAVAR,    \
+               VALUES)                                                         \
+  {PREFIX,                                                                     \
+   NAME,                                                                       \
+   HELPTEXT,                                                                   \
+   HELPTEXTFORVISIBILITY,                                                      \
+   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 7bbee1da643b8c..67757ad91b8a5d 100644
--- a/llvm/include/llvm/Option/OptParser.td
+++ b/llvm/include/llvm/Option/OptParser.td
@@ -93,6 +93,11 @@ class OptionGroup<string name> {
 
 // Define the option class.
 
+class HelpTextForVisibility<OptionVisibility visibility, string text> {
+  OptionVisibility Visibility = visibility;
+  string Text = text;
+}
+
 class Option<list<string> prefixes, string name, OptionKind kind> {
   string EnumName = ?; // Uses the def name if undefined.
   list<string> Prefixes = prefixes;
@@ -101,6 +106,7 @@ class Option<list<string> prefixes, string name, OptionKind kind> {
   // Used by MultiArg option kind.
   int NumArgs = 0;
   string HelpText = ?;
+  HelpTextForVisibility HelpTextForVisibility = ?;
   string MetaVarName = ?;
   string Values = ?;
   code ValuesCode = ?;
@@ -155,6 +161,10 @@ class Visibility<list<OptionVisibility> visibility> {
 }
 class Group<OptionGroup group> { OptionGroup Group = group; }
 class HelpText<string text> { string HelpText = text; }
+class HelpForVisibility<HelpTextForVisibility text> {
+  HelpTextForVisibility HelpTextForVisibility = text;
+}
+
 class MetaVarName<string name> { string MetaVarName = name; }
 class Values<string value> { string Values = value; }
 class ValuesCode<code valuecode> { code ValuesCode = valuecode; }
diff --git a/llvm/include/llvm/Option/OptTable.h b/llvm/include/llvm/Option/OptTable.h
index bb3b665a16319f..457a46a269c83a 100644
--- a/llvm/include/llvm/Option/OptTable.h
+++ b/llvm/include/llvm/Option/OptTable.h
@@ -58,6 +58,7 @@ class OptTable {
     ArrayRef<StringLiteral> Prefixes;
     StringLiteral PrefixedName;
     const char *HelpText;
+    std::pair<unsigned int, const char *> HelpForVisibility;
     const char *MetaVar;
     unsigned ID;
     unsigned char Kind;
@@ -145,7 +146,18 @@ class OptTable {
 
   /// Get the help text to use to describe this option.
   const char *getOptionHelpText(OptSpecifier id) const {
-    return getInfo(id).HelpText;
+    return getOptionHelpText(id, Visibility(0));
+  }
+
+  // Get the help text to use to describe this option.
+  // If it has Visibility specific help text and that visibility is in the
+  // visibility mask, use that text instead of the generic text.
+  const char *getOptionHelpText(OptSpecifier id,
+                                Visibility VisibilityMask) const {
+    auto Info = getInfo(id);
+    if (VisibilityMask & Info.HelpForVisibility.first)
+      return Info.HelpForVisibility.second;
+    return Info.HelpText;
   }
 
   /// Get the meta-variable name to use when describing
@@ -323,7 +335,8 @@ class OptTable {
 private:
   void internalPrintHelp(raw_ostream &OS, const char *Usage, const char *Title,
                          bool ShowHidden, bool ShowAllAliases,
-                         std::function<bool(const Info &)> ExcludeOption) const;
+                         std::function<bool(const Info &)> ExcludeOption,
+                         Visibility VisibilityMask) const;
 };
 
 /// Specialization of OptTable
@@ -358,30 +371,32 @@ class PrecomputedOptTable : public OptTable {
 
 #define LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(                                       \
     ID_PREFIX, PREFIX, PREFIXED_NAME, ID, KIND, GROUP, ALIAS, ALIASARGS,       \
-    FLAGS, VISIBILITY, PARAM, HELPTEXT, METAVAR, VALUES)                       \
+    FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTFORVISIBILITY, METAVAR,        \
+    VALUES)                                                                    \
   ID_PREFIX##ID
 
 #define LLVM_MAKE_OPT_ID(PREFIX, PREFIXED_NAME, ID, KIND, GROUP, ALIAS,        \
                          ALIASARGS, FLAGS, VISIBILITY, PARAM, HELPTEXT,        \
-                         METAVAR, VALUES)                                      \
-  LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(OPT_, PREFIX, PREFIXED_NAME, ID, KIND,       \
-                                  GROUP, ALIAS, ALIASARGS, FLAGS, VISIBILITY,  \
-                                  PARAM, HELPTEXT, METAVAR, VALUE)
+                         HELPTEXTFORVISIBILITY, METAVAR, VALUES)               \
+  LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(                                             \
+      OPT_, PREFIX, PREFIXED_NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS,   \
+      VISIBILITY, PARAM, HELPTEXT, HELPTEXTFORVISIBILITY, METAVAR, VALUE)
 
 #define LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(                                \
     ID_PREFIX, PREFIX, PREFIXED_NAME, ID, KIND, GROUP, ALIAS, ALIASARGS,       \
-    FLAGS, VISIBILITY, PARAM, HELPTEXT, METAVAR, VALUES)                       \
+    FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTFORVISIBILITY, METAVAR,        \
+    VALUES)                                                                    \
   llvm::opt::OptTable::Info {                                                  \
-    PREFIX, PREFIXED_NAME, HELPTEXT, METAVAR, ID_PREFIX##ID,                   \
-        llvm::opt::Option::KIND##Class, PARAM, FLAGS, VISIBILITY,              \
-        ID_PREFIX##GROUP, ID_PREFIX##ALIAS, ALIASARGS, VALUES                  \
+    PREFIX, PREFIXED_NAME, HELPTEXT, HELPTEXTFORVISIBILITY, METAVAR,           \
+        ID_PREFIX##ID, 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, VISIBILITY, PARAM, HELPTEXT, \
-                                METAVAR, VALUES)                               \
+                                HELPTEXTFORVISIBILITY, METAVAR, VALUES)        \
   LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(                                      \
       OPT_, PREFIX, PREFIXED_NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS,   \
-      VISIBILITY, PARAM, HELPTEXT, METAVAR, VALUES)
+      VISIBILITY, PARAM, HELPTEXT, HELPTEXTFORVISIBILITY, METAVAR, VALUES)
 
 #endif // LLVM_OPTION_OPTTABLE_H
diff --git a/llvm/lib/Option/OptTable.cpp b/llvm/lib/Option/OptTable.cpp
index cf69f6173b6d41..b8b6b90c253f23 100644
--- a/llvm/lib/Option/OptTable.cpp
+++ b/llvm/lib/Option/OptTable.cpp
@@ -710,7 +710,8 @@ void OptTable::printHelp(raw_ostream &OS, const char *Usage, const char *Title,
       OS, Usage, Title, ShowHidden, ShowAllAliases,
       [VisibilityMask](const Info &CandidateInfo) -> bool {
         return (CandidateInfo.Visibility & VisibilityMask) == 0;
-      });
+      },
+      VisibilityMask);
 }
 
 void OptTable::printHelp(raw_ostream &OS, const char *Usage, const char *Title,
@@ -726,13 +727,14 @@ void OptTable::printHelp(raw_ostream &OS, const char *Usage, const char *Title,
         if (CandidateInfo.Flags & FlagsToExclude)
           return true;
         return false;
-      });
+      },
+      Visibility(0));
 }
 
 void OptTable::internalPrintHelp(
     raw_ostream &OS, const char *Usage, const char *Title, bool ShowHidden,
-    bool ShowAllAliases,
-    std::function<bool(const Info &)> ExcludeOption) const {
+    bool ShowAllAliases, std::function<bool(const Info &)> ExcludeOption,
+    Visibility VisibilityMask) const {
   OS << "OVERVIEW: " << Title << "\n\n";
   OS << "USAGE: " << Usage << "\n\n";
 
@@ -754,11 +756,11 @@ void OptTable::internalPrintHelp(
 
     // If an alias doesn't have a help text, show a help text for the aliased
     // option instead.
-    const char *HelpText = getOptionHelpText(Id);
+    const char *HelpText = getOptionHelpText(Id, VisibilityMask);
     if (!HelpText && ShowAllAliases) {
       const Option Alias = getOption(Id).getAlias();
       if (Alias.isValid())
-        HelpText = getOptionHelpText(Alias.getID());
+        HelpText = getOptionHelpText(Alias.getID(), VisibilityMask);
     }
 
     if (HelpText && (strlen(HelpText) != 0)) {
diff --git a/llvm/unittests/Option/OptionMarshallingTest.cpp b/llvm/unittests/Option/OptionMarshallingTest.cpp
index 339d825c2016bf..97fbc118d1fc17 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,      \
-    VISIBILITY, PARAM, HELPTEXT, METAVAR, VALUES, SHOULD_PARSE, ALWAYS_EMIT,   \
-    KEYPATH, DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER,          \
-    DENORMALIZER, MERGER, EXTRACTOR, TABLE_INDEX)                              \
+    VISIBILITY, PARAM, HELPTEXT, HELPTEXTFORVISIBILITY, 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/utils/TableGen/OptParserEmitter.cpp b/llvm/utils/TableGen/OptParserEmitter.cpp
index c25f6c59cab383..6da8f1d182c187 100644
--- a/llvm/utils/TableGen/OptParserEmitter.cpp
+++ b/llvm/utils/TableGen/OptParserEmitter.cpp
@@ -312,6 +312,9 @@ static void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) {
     } else
       OS << ", nullptr";
 
+    // Not using Visibility specific text for group help.
+    OS << ", std::make_pair(0, nullptr)";
+
     // The option meta-variable name (unused).
     OS << ", nullptr";
 
@@ -410,6 +413,19 @@ static void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) {
     } else
       OS << ", nullptr";
 
+    // Help text specific to a certain visibility.
+    if (isa<UnsetInit>(R.getValueInit("HelpTextForVisibility")))
+      OS << ", std::make_pair(0, nullptr)";
+    else {
+      const Record *VisibilityHelp = R.getValueAsDef("HelpTextForVisibility");
+      const RecordVal *Visibility = VisibilityHelp->getValue("Visibility");
+      Init *VisibilityInit = Visibility->getValue();
+      std::string VisibilityStr = VisibilityInit->getAsString();
+      StringRef Text = VisibilityHelp->getValueAsString("Text");
+      OS << ", std::make_pair(options::" << VisibilityStr << ", \"" << Text
+         << "\")";
+    }
+
     // The option meta-variable name.
     OS << ", ";
     if (!isa<UnsetInit>(R.getValueInit("MetaVarName")))

>From 6006643ccf44faecc46446d08e6e23046e2952c7 Mon Sep 17 00:00:00 2001
From: David Spickett <david.spickett at linaro.org>
Date: Thu, 15 Feb 2024 16:29:29 +0000
Subject: [PATCH 2/4] Fix clangd compile

---
 clang-tools-extra/clangd/CompileCommands.cpp | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/clang-tools-extra/clangd/CompileCommands.cpp b/clang-tools-extra/clangd/CompileCommands.cpp
index 5b8128fca62668..1c9ad7ae456a62 100644
--- a/clang-tools-extra/clangd/CompileCommands.cpp
+++ b/clang-tools-extra/clangd/CompileCommands.cpp
@@ -466,7 +466,8 @@ 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, VISIBILITY, PARAM, HELP, METAVAR, VALUES)                \
+               FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTFORVISIBILITY,      \
+               METAVAR, VALUES)                                                \
   Prefixes[DriverID::OPT_##ID] = PREFIX;
 #include "clang/Driver/Options.inc"
 #undef OPTION
@@ -478,7 +479,8 @@ llvm::ArrayRef<ArgStripper::Rule> ArgStripper::rulesFor(llvm::StringRef Arg) {
       const void *AliasArgs;
     } AliasTable[] = {
 #define OPTION(PREFIX, PREFIXED_NAME, ID, KIND, GROUP, ALIAS, ALIASARGS,       \
-               FLAGS, VISIBILITY, PARAM, HELP, METAVAR, VALUES)                \
+               FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTFORVISIBILITY,      \
+               METAVAR, VALUES)                                                \
   {DriverID::OPT_##ID, DriverID::OPT_##ALIAS, ALIASARGS},
 #include "clang/Driver/Options.inc"
 #undef OPTION

>From f53898a048de8b03732aec88584e76a6dd098327 Mon Sep 17 00:00:00 2001
From: David Spickett <david.spickett at linaro.org>
Date: Wed, 21 Feb 2024 10:40:11 +0000
Subject: [PATCH 3/4] List of help texts instead

---
 clang-tools-extra/clangd/CompileCommands.cpp  |  4 +-
 clang/include/clang/Driver/Options.td         | 14 +++++--
 clang/lib/Frontend/CompilerInvocation.cpp     |  4 +-
 .../utils/TableGen/ClangOptionDocEmitter.cpp  |  8 +++-
 flang/test/Driver/driver-help.f90             |  2 +-
 lld/MachO/DriverUtils.cpp                     |  4 +-
 lld/MinGW/Driver.cpp                          |  4 +-
 lld/wasm/Driver.cpp                           |  4 +-
 llvm/include/llvm/Option/OptParser.td         |  6 +--
 llvm/include/llvm/Option/OptTable.h           | 27 ++++++++-----
 .../Option/OptionMarshallingTest.cpp          |  2 +-
 llvm/utils/TableGen/OptParserEmitter.cpp      | 40 ++++++++++++++-----
 12 files changed, 78 insertions(+), 41 deletions(-)

diff --git a/clang-tools-extra/clangd/CompileCommands.cpp b/clang-tools-extra/clangd/CompileCommands.cpp
index 1c9ad7ae456a62..cf9fab129b3ac0 100644
--- a/clang-tools-extra/clangd/CompileCommands.cpp
+++ b/clang-tools-extra/clangd/CompileCommands.cpp
@@ -466,7 +466,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, VISIBILITY, PARAM, HELPTEXT, HELPTEXTFORVISIBILITY,      \
+               FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTFORVISIBILITIES,    \
                METAVAR, VALUES)                                                \
   Prefixes[DriverID::OPT_##ID] = PREFIX;
 #include "clang/Driver/Options.inc"
@@ -479,7 +479,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, VISIBILITY, PARAM, HELPTEXT, HELPTEXTFORVISIBILITY,      \
+               FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTFORVISIBILITIES,    \
                METAVAR, VALUES)                                                \
   {DriverID::OPT_##ID, DriverID::OPT_##ALIAS, ALIASARGS},
 #include "clang/Driver/Options.inc"
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 765d5fbc1e692d..921aabdfc9026d 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -3382,13 +3382,19 @@ def fopenmp : Flag<["-"], "fopenmp">, Group<f_Group>,
   HelpText<"Parse OpenMP pragmas and generate parallel code.">;
 def fno_openmp : Flag<["-"], "fno-openmp">, Group<f_Group>,
   Flags<[NoArgumentUnused]>;
+class OpenMPVersionHelp<string program, string default> {
+  string str = !strconcat(
+    "Set OpenMP version (e.g. 45 for OpenMP 4.5, 51 for OpenMP 5.1). Default value is ",
+    default, " for ", program);
+}
 def fopenmp_version_EQ : Joined<["-"], "fopenmp-version=">, Group<f_Group>,
   Flags<[NoArgumentUnused]>,
   Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>,
-  HelpText<"Set OpenMP version (e.g. 45 for OpenMP 4.5, 51 for OpenMP 5.1). Default value is 51 for Clang">,
-  HelpForVisibility<HelpTextForVisibility<FlangOption,
-    "Set OpenMP version (e.g. 45 for OpenMP 4.5, 51 for OpenMP 5.1). Default value is 11 for Flang"
-  >>;
+  HelpText<OpenMPVersionHelp<"Clang", "51">.str>,
+  HelpTextForVisibilities<[
+    HelpTextForVisibility<FlangOption, OpenMPVersionHelp<"Flang", "11">.str>,
+    HelpTextForVisibility<FC1Option,   OpenMPVersionHelp<"Flang", "11">.str>,
+  ]>;
 defm openmp_extensions: BoolFOption<"openmp-extensions",
   LangOpts<"OpenMPExtensions">, DefaultTrue,
   PosFlag<SetTrue, [NoArgumentUnused], [ClangOption, CC1Option],
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index 790b0fb51cbfbd..b471b8438f3a72 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -522,7 +522,7 @@ static T extractMaskValue(T KeyPath) {
 
 #define PARSE_OPTION_WITH_MARSHALLING(                                         \
     ARGS, DIAGS, PREFIX_TYPE, SPELLING, ID, KIND, GROUP, ALIAS, ALIASARGS,     \
-    FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTFORVISIBILITY, METAVAR,        \
+    FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTFORVISIBILITIES, METAVAR,      \
     VALUES, SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, IMPLIED_CHECK,  \
     IMPLIED_VALUE, NORMALIZER, DENORMALIZER, MERGER, EXTRACTOR, TABLE_INDEX)   \
   if ((VISIBILITY) & options::CC1Option) {                                     \
@@ -539,7 +539,7 @@ 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, \
-    VISIBILITY, PARAM, HELPTEXT, HELPTEXTFORVISIBILITY, METAVAR, VALUES,       \
+    VISIBILITY, PARAM, HELPTEXT, HELPTEXTFORVISIBILITIES, METAVAR, VALUES,     \
     SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, IMPLIED_CHECK,          \
     IMPLIED_VALUE, NORMALIZER, DENORMALIZER, MERGER, EXTRACTOR, TABLE_INDEX)   \
   if ((VISIBILITY) & options::CC1Option) {                                     \
diff --git a/clang/utils/TableGen/ClangOptionDocEmitter.cpp b/clang/utils/TableGen/ClangOptionDocEmitter.cpp
index 1ad3fcc3d76b82..75bc628a96bc39 100644
--- a/clang/utils/TableGen/ClangOptionDocEmitter.cpp
+++ b/clang/utils/TableGen/ClangOptionDocEmitter.cpp
@@ -362,8 +362,9 @@ void emitOption(const DocumentedOption &Option, const Record *DocInfo,
   std::string Description;
 
   // Prefer a program specific help string.
-  if (!isa<UnsetInit>(R->getValueInit("HelpTextForVisibility"))) {
-    const Record *VisibilityHelp = R->getValueAsDef("HelpTextForVisibility");
+  std::vector<Record *> VisibilitiesHelp =
+      R->getValueAsListOfDefs("HelpTextForVisibilities");
+  for (Record *VisibilityHelp : VisibilitiesHelp) {
     std::string VisibilityStr =
         VisibilityHelp->getValue("Visibility")->getValue()->getAsString();
 
@@ -373,6 +374,9 @@ void emitOption(const DocumentedOption &Option, const Record *DocInfo,
         break;
       }
     }
+
+    if (!Description.empty())
+      break;
   }
 
   // If there's not a program specific string, use the default one.
diff --git a/flang/test/Driver/driver-help.f90 b/flang/test/Driver/driver-help.f90
index 31bc67e1742482..71ba5e79daa538 100644
--- a/flang/test/Driver/driver-help.f90
+++ b/flang/test/Driver/driver-help.f90
@@ -223,7 +223,7 @@
 ! HELP-FC1-NEXT:                         Generate code only for an OpenMP target device.
 ! HELP-FC1-NEXT: -fopenmp-target-debug   Enable debugging in the OpenMP offloading device RTL
 ! HELP-FC1-NEXT: -fopenmp-version=<value>
-! HELP-FC1-NEXT:                         Set OpenMP version (e.g. 45 for OpenMP 4.5, 51 for OpenMP 5.1). Default value is 51 for Clang
+! HELP-FC1-NEXT:                         Set OpenMP version (e.g. 45 for OpenMP 4.5, 51 for OpenMP 5.1). Default value is 11 for Flang
 ! HELP-FC1-NEXT: -fopenmp                Parse OpenMP pragmas and generate parallel code.
 ! HELP-FC1-NEXT: -fpass-plugin=<dsopath> Load pass plugin from a dynamic shared object file (only with new pass manager).
 ! HELP-FC1-NEXT: -fppc-native-vector-element-order
diff --git a/lld/MachO/DriverUtils.cpp b/lld/MachO/DriverUtils.cpp
index ea86b8074b146b..c0812f11f95a0f 100644
--- a/lld/MachO/DriverUtils.cpp
+++ b/lld/MachO/DriverUtils.cpp
@@ -45,12 +45,12 @@ using namespace lld::macho;
 // Create table mapping all options defined in Options.td
 static constexpr OptTable::Info optInfo[] = {
 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS,         \
-               VISIBILITY, PARAM, HELPTEXT, HELPTEXTFORVISIBILITY, METAVAR,    \
+               VISIBILITY, PARAM, HELPTEXT, HELPTEXTFORVISIBILITIES, METAVAR,  \
                VALUES)                                                         \
   {PREFIX,                                                                     \
    NAME,                                                                       \
    HELPTEXT,                                                                   \
-   HELPTEXTFORVISIBILITY,                                                      \
+   HELPTEXTFORVISIBILITIES,                                                    \
    METAVAR,                                                                    \
    OPT_##ID,                                                                   \
    opt::Option::KIND##Class,                                                   \
diff --git a/lld/MinGW/Driver.cpp b/lld/MinGW/Driver.cpp
index 3a1eb082d9df2b..9aa3228e8ad98c 100644
--- a/lld/MinGW/Driver.cpp
+++ b/lld/MinGW/Driver.cpp
@@ -69,12 +69,12 @@ enum {
 // Create table mapping all options defined in Options.td
 static constexpr opt::OptTable::Info infoTable[] = {
 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS,         \
-               VISIBILITY, PARAM, HELPTEXT, HELPTEXTFORVISIBILITY, METAVAR,    \
+               VISIBILITY, PARAM, HELPTEXT, HELPTEXTFORVISIBILITIES, METAVAR,  \
                VALUES)                                                         \
   {PREFIX,                                                                     \
    NAME,                                                                       \
    HELPTEXT,                                                                   \
-   HELPTEXTFORVISIBILITY,                                                      \
+   HELPTEXTFORVISIBILITIES,                                                    \
    METAVAR,                                                                    \
    OPT_##ID,                                                                   \
    opt::Option::KIND##Class,                                                   \
diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp
index 79dda5a41a4001..f9b99e2a268c86 100644
--- a/lld/wasm/Driver.cpp
+++ b/lld/wasm/Driver.cpp
@@ -132,12 +132,12 @@ 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(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS,         \
-               VISIBILITY, PARAM, HELPTEXT, HELPTEXTFORVISIBILITY, METAVAR,    \
+               VISIBILITY, PARAM, HELPTEXT, HELPTEXTFORVISIBILITIES, METAVAR,  \
                VALUES)                                                         \
   {PREFIX,                                                                     \
    NAME,                                                                       \
    HELPTEXT,                                                                   \
-   HELPTEXTFORVISIBILITY,                                                      \
+   HELPTEXTFORVISIBILITIES,                                                    \
    METAVAR,                                                                    \
    OPT_##ID,                                                                   \
    opt::Option::KIND##Class,                                                   \
diff --git a/llvm/include/llvm/Option/OptParser.td b/llvm/include/llvm/Option/OptParser.td
index 67757ad91b8a5d..2d25631414adfb 100644
--- a/llvm/include/llvm/Option/OptParser.td
+++ b/llvm/include/llvm/Option/OptParser.td
@@ -106,7 +106,7 @@ class Option<list<string> prefixes, string name, OptionKind kind> {
   // Used by MultiArg option kind.
   int NumArgs = 0;
   string HelpText = ?;
-  HelpTextForVisibility HelpTextForVisibility = ?;
+  list<HelpTextForVisibility> HelpTextForVisibilities = [];
   string MetaVarName = ?;
   string Values = ?;
   code ValuesCode = ?;
@@ -161,8 +161,8 @@ class Visibility<list<OptionVisibility> visibility> {
 }
 class Group<OptionGroup group> { OptionGroup Group = group; }
 class HelpText<string text> { string HelpText = text; }
-class HelpForVisibility<HelpTextForVisibility text> {
-  HelpTextForVisibility HelpTextForVisibility = text;
+class HelpTextForVisibilities<list<HelpTextForVisibility> texts> {
+  list<HelpTextForVisibility> HelpTextForVisibilities = texts;
 }
 
 class MetaVarName<string name> { string MetaVarName = name; }
diff --git a/llvm/include/llvm/Option/OptTable.h b/llvm/include/llvm/Option/OptTable.h
index 457a46a269c83a..dd8b136b205a85 100644
--- a/llvm/include/llvm/Option/OptTable.h
+++ b/llvm/include/llvm/Option/OptTable.h
@@ -58,7 +58,11 @@ class OptTable {
     ArrayRef<StringLiteral> Prefixes;
     StringLiteral PrefixedName;
     const char *HelpText;
-    std::pair<unsigned int, const char *> HelpForVisibility;
+    // This cannot be std::vector because OptTable is used in constexpr
+    // contexts. Increase the size of this array if you need more help text
+    // variants.
+    std::array<std::pair<unsigned int, const char *>, 2>
+        HelpTextForVisibilities;
     const char *MetaVar;
     unsigned ID;
     unsigned char Kind;
@@ -150,13 +154,14 @@ class OptTable {
   }
 
   // Get the help text to use to describe this option.
-  // If it has Visibility specific help text and that visibility is in the
+  // If it has visibility specific help text and that visibility is in the
   // visibility mask, use that text instead of the generic text.
   const char *getOptionHelpText(OptSpecifier id,
                                 Visibility VisibilityMask) const {
     auto Info = getInfo(id);
-    if (VisibilityMask & Info.HelpForVisibility.first)
-      return Info.HelpForVisibility.second;
+    for (auto [Visibility, Text] : Info.HelpTextForVisibilities)
+      if (VisibilityMask & Visibility)
+        return Text;
     return Info.HelpText;
   }
 
@@ -371,32 +376,32 @@ class PrecomputedOptTable : public OptTable {
 
 #define LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(                                       \
     ID_PREFIX, PREFIX, PREFIXED_NAME, ID, KIND, GROUP, ALIAS, ALIASARGS,       \
-    FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTFORVISIBILITY, METAVAR,        \
+    FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTFORVISIBILITIES, METAVAR,      \
     VALUES)                                                                    \
   ID_PREFIX##ID
 
 #define LLVM_MAKE_OPT_ID(PREFIX, PREFIXED_NAME, ID, KIND, GROUP, ALIAS,        \
                          ALIASARGS, FLAGS, VISIBILITY, PARAM, HELPTEXT,        \
-                         HELPTEXTFORVISIBILITY, METAVAR, VALUES)               \
+                         HELPTEXTFORVISIBILITIES, METAVAR, VALUES)             \
   LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(                                             \
       OPT_, PREFIX, PREFIXED_NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS,   \
-      VISIBILITY, PARAM, HELPTEXT, HELPTEXTFORVISIBILITY, METAVAR, VALUE)
+      VISIBILITY, PARAM, HELPTEXT, HELPTEXTFORVISIBILITIES, METAVAR, VALUE)
 
 #define LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(                                \
     ID_PREFIX, PREFIX, PREFIXED_NAME, ID, KIND, GROUP, ALIAS, ALIASARGS,       \
-    FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTFORVISIBILITY, METAVAR,        \
+    FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTFORVISIBILITIES, METAVAR,      \
     VALUES)                                                                    \
   llvm::opt::OptTable::Info {                                                  \
-    PREFIX, PREFIXED_NAME, HELPTEXT, HELPTEXTFORVISIBILITY, METAVAR,           \
+    PREFIX, PREFIXED_NAME, HELPTEXT, HELPTEXTFORVISIBILITIES, METAVAR,         \
         ID_PREFIX##ID, 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, VISIBILITY, PARAM, HELPTEXT, \
-                                HELPTEXTFORVISIBILITY, METAVAR, VALUES)        \
+                                HELPTEXTFORVISIBILITIES, METAVAR, VALUES)      \
   LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(                                      \
       OPT_, PREFIX, PREFIXED_NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS,   \
-      VISIBILITY, PARAM, HELPTEXT, HELPTEXTFORVISIBILITY, METAVAR, VALUES)
+      VISIBILITY, PARAM, HELPTEXT, HELPTEXTFORVISIBILITIES, METAVAR, VALUES)
 
 #endif // LLVM_OPTION_OPTTABLE_H
diff --git a/llvm/unittests/Option/OptionMarshallingTest.cpp b/llvm/unittests/Option/OptionMarshallingTest.cpp
index 97fbc118d1fc17..e3985e0b847369 100644
--- a/llvm/unittests/Option/OptionMarshallingTest.cpp
+++ b/llvm/unittests/Option/OptionMarshallingTest.cpp
@@ -19,7 +19,7 @@ struct OptionWithMarshallingInfo {
 static const OptionWithMarshallingInfo MarshallingTable[] = {
 #define OPTION_WITH_MARSHALLING(                                               \
     PREFIX_TYPE, PREFIXED_NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS,      \
-    VISIBILITY, PARAM, HELPTEXT, HELPTEXTFORVISIBILITY, METAVAR, VALUES,       \
+    VISIBILITY, PARAM, HELPTEXT, HELPTEXTFORVISIBILITIES, 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},
diff --git a/llvm/utils/TableGen/OptParserEmitter.cpp b/llvm/utils/TableGen/OptParserEmitter.cpp
index 6da8f1d182c187..366450b0e8eaf4 100644
--- a/llvm/utils/TableGen/OptParserEmitter.cpp
+++ b/llvm/utils/TableGen/OptParserEmitter.cpp
@@ -313,7 +313,8 @@ static void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) {
       OS << ", nullptr";
 
     // Not using Visibility specific text for group help.
-    OS << ", std::make_pair(0, nullptr)";
+    OS << ", (std::array<std::pair<unsigned, const char*>, 2>{{"
+       << "std::make_pair(0, nullptr), std::make_pair(0, nullptr)}})";
 
     // The option meta-variable name (unused).
     OS << ", nullptr";
@@ -413,18 +414,39 @@ static void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) {
     } else
       OS << ", nullptr";
 
-    // Help text specific to a certain visibility.
-    if (isa<UnsetInit>(R.getValueInit("HelpTextForVisibility")))
-      OS << ", std::make_pair(0, nullptr)";
-    else {
-      const Record *VisibilityHelp = R.getValueAsDef("HelpTextForVisibility");
-      const RecordVal *Visibility = VisibilityHelp->getValue("Visibility");
+    const unsigned MaxVisibilityHelp = 2;
+    OS << ", (std::array<std::pair<unsigned, const char*>, "
+       << MaxVisibilityHelp << ">{{";
+    unsigned NumVisibilityHelpEmitted = 0;
+
+    std::vector<Record *> VisibilitiesHelp =
+        R.getValueAsListOfDefs("HelpTextForVisibilities");
+    assert(VisibilitiesHelp.size() <= MaxVisibilityHelp &&
+           "Too many help text variants to store in "
+           "OptTable::HelpTextForVisibilities");
+
+    for (std::vector<Record *>::const_iterator VisibilityHelp =
+             VisibilitiesHelp.begin();
+         VisibilityHelp != VisibilitiesHelp.end();
+         ++VisibilityHelp, ++NumVisibilityHelpEmitted) {
+      const RecordVal *Visibility = (*VisibilityHelp)->getValue("Visibility");
       Init *VisibilityInit = Visibility->getValue();
       std::string VisibilityStr = VisibilityInit->getAsString();
-      StringRef Text = VisibilityHelp->getValueAsString("Text");
-      OS << ", std::make_pair(options::" << VisibilityStr << ", \"" << Text
+      StringRef Text = (*VisibilityHelp)->getValueAsString("Text");
+      OS << "std::make_pair(options::" << VisibilityStr << ", \"" << Text
          << "\")";
+
+      if (std::next(VisibilityHelp) != VisibilitiesHelp.end())
+        OS << ", ";
+    }
+    // Init any unused elements.
+    for (; NumVisibilityHelpEmitted < MaxVisibilityHelp;
+         ++NumVisibilityHelpEmitted) {
+      OS << "std::make_pair(0, nullptr)";
+      if ((NumVisibilityHelpEmitted + 1) != MaxVisibilityHelp)
+        OS << ", ";
     }
+    OS << "}})";
 
     // The option meta-variable name.
     OS << ", ";

>From b80b164f1a07eda6851f7ab7646d6868363afa65 Mon Sep 17 00:00:00 2001
From: David Spickett <david.spickett at linaro.org>
Date: Tue, 27 Feb 2024 10:15:32 +0000
Subject: [PATCH 4/4] Explain usage

---
 llvm/include/llvm/Option/OptTable.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/llvm/include/llvm/Option/OptTable.h b/llvm/include/llvm/Option/OptTable.h
index dd8b136b205a85..69484504e9ac12 100644
--- a/llvm/include/llvm/Option/OptTable.h
+++ b/llvm/include/llvm/Option/OptTable.h
@@ -58,6 +58,8 @@ class OptTable {
     ArrayRef<StringLiteral> Prefixes;
     StringLiteral PrefixedName;
     const char *HelpText;
+    // Help text for specific visibilities. If there is no entry here for
+    // the visibility of the program, HelpText is used instead.
     // This cannot be std::vector because OptTable is used in constexpr
     // contexts. Increase the size of this array if you need more help text
     // variants.



More information about the cfe-commits mailing list