[clang] f917356 - Revert "[clang][cli] Port ObjCMTAction to new option parsing system"

Mehdi Amini via cfe-commits cfe-commits at lists.llvm.org
Wed Nov 11 12:01:15 PST 2020


Author: Mehdi Amini
Date: 2020-11-11T20:01:03Z
New Revision: f917356f9ce026f9be9972b8c75cd3ba00e43497

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

LOG: Revert "[clang][cli] Port ObjCMTAction to new option parsing system"

This reverts commit 09248a5d25bb1c9f357247fa3da8fbe4470e9c67.

Some builds are broken. I suspect a `static constexpr` in a class missing a
definition out of class (required pre-c++17).

Added: 
    

Modified: 
    clang/include/clang/Driver/Options.td
    clang/lib/Frontend/CompilerInvocation.cpp
    llvm/include/llvm/Option/OptParser.td
    llvm/unittests/Option/OptionMarshallingTest.cpp
    llvm/unittests/Option/Opts.td
    llvm/utils/TableGen/OptParserEmitter.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 05a218ca09f0..6df4a0222484 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -340,53 +340,36 @@ def ccc_objcmt_migrate : Separate<["-"], "ccc-objcmt-migrate">,
   InternalDriverOpt,
   HelpText<"Apply modifications and produces temporary files to migrate to "
    "modern ObjC syntax">;
-
 def objcmt_migrate_literals : Flag<["-"], "objcmt-migrate-literals">, Flags<[CC1Option]>,
-  HelpText<"Enable migration to modern ObjC literals">,
-  MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_Literals">;
+  HelpText<"Enable migration to modern ObjC literals">;
 def objcmt_migrate_subscripting : Flag<["-"], "objcmt-migrate-subscripting">, Flags<[CC1Option]>,
-  HelpText<"Enable migration to modern ObjC subscripting">,
-  MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_Subscripting">;
+  HelpText<"Enable migration to modern ObjC subscripting">;
 def objcmt_migrate_property : Flag<["-"], "objcmt-migrate-property">, Flags<[CC1Option]>,
-  HelpText<"Enable migration to modern ObjC property">,
-  MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_Property">;
+  HelpText<"Enable migration to modern ObjC property">;
 def objcmt_migrate_all : Flag<["-"], "objcmt-migrate-all">, Flags<[CC1Option]>,
-  HelpText<"Enable migration to modern ObjC">,
-  MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_MigrateDecls">;
+  HelpText<"Enable migration to modern ObjC">;
 def objcmt_migrate_readonly_property : Flag<["-"], "objcmt-migrate-readonly-property">, Flags<[CC1Option]>,
-  HelpText<"Enable migration to modern ObjC readonly property">,
-  MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_ReadonlyProperty">;
+  HelpText<"Enable migration to modern ObjC readonly property">;
 def objcmt_migrate_readwrite_property : Flag<["-"], "objcmt-migrate-readwrite-property">, Flags<[CC1Option]>,
-  HelpText<"Enable migration to modern ObjC readwrite property">,
-  MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_ReadwriteProperty">;
+  HelpText<"Enable migration to modern ObjC readwrite property">;
 def objcmt_migrate_property_dot_syntax : Flag<["-"], "objcmt-migrate-property-dot-syntax">, Flags<[CC1Option]>,
-  HelpText<"Enable migration of setter/getter messages to property-dot syntax">,
-  MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_PropertyDotSyntax">;
+  HelpText<"Enable migration of setter/getter messages to property-dot syntax">;
 def objcmt_migrate_annotation : Flag<["-"], "objcmt-migrate-annotation">, Flags<[CC1Option]>,
-  HelpText<"Enable migration to property and method annotations">,
-  MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_Annotation">;
+  HelpText<"Enable migration to property and method annotations">;
 def objcmt_migrate_instancetype : Flag<["-"], "objcmt-migrate-instancetype">, Flags<[CC1Option]>,
-  HelpText<"Enable migration to infer instancetype for method result type">,
-  MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_Instancetype">;
+  HelpText<"Enable migration to infer instancetype for method result type">;
 def objcmt_migrate_nsmacros : Flag<["-"], "objcmt-migrate-ns-macros">, Flags<[CC1Option]>,
-  HelpText<"Enable migration to NS_ENUM/NS_OPTIONS macros">,
-  MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_NsMacros">;
+  HelpText<"Enable migration to NS_ENUM/NS_OPTIONS macros">;
 def objcmt_migrate_protocol_conformance : Flag<["-"], "objcmt-migrate-protocol-conformance">, Flags<[CC1Option]>,
-  HelpText<"Enable migration to add protocol conformance on classes">,
-  MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_ProtocolConformance">;
+  HelpText<"Enable migration to add protocol conformance on classes">;
 def objcmt_atomic_property : Flag<["-"], "objcmt-atomic-property">, Flags<[CC1Option]>,
-  HelpText<"Make migration to 'atomic' properties">,
-  MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_AtomicProperty">;
+  HelpText<"Make migration to 'atomic' properties">;
 def objcmt_returns_innerpointer_property : Flag<["-"], "objcmt-returns-innerpointer-property">, Flags<[CC1Option]>,
-  HelpText<"Enable migration to annotate property with NS_RETURNS_INNER_POINTER">,
-  MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_ReturnsInnerPointerProperty">;
+  HelpText<"Enable migration to annotate property with NS_RETURNS_INNER_POINTER">;
 def objcmt_ns_nonatomic_iosonly: Flag<["-"], "objcmt-ns-nonatomic-iosonly">, Flags<[CC1Option]>,
-  HelpText<"Enable migration to use NS_NONATOMIC_IOSONLY macro for setting property's 'atomic' attribute">,
-  MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_NsAtomicIOSOnlyProperty">;
+  HelpText<"Enable migration to use NS_NONATOMIC_IOSONLY macro for setting property's 'atomic' attribute">;
 def objcmt_migrate_designated_init : Flag<["-"], "objcmt-migrate-designated-init">, Flags<[CC1Option]>,
-  HelpText<"Enable migration to infer NS_DESIGNATED_INITIALIZER for initializer methods">,
-  MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_DesignatedInitializer">;
-
+  HelpText<"Enable migration to infer NS_DESIGNATED_INITIALIZER for initializer methods">;
 def objcmt_whitelist_dir_path: Joined<["-"], "objcmt-whitelist-dir-path=">, Flags<[CC1Option]>,
   HelpText<"Only modify files with a filename contained in the provided directory path">;
 // The misspelt "white-list" [sic] alias is due for removal.

diff  --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index 0a776bfe4518..d3516f5bf1a4 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -125,24 +125,6 @@ CompilerInvocationBase::~CompilerInvocationBase() = default;
 #include "clang/Driver/Options.inc"
 #undef SIMPLE_ENUM_VALUE_TABLE
 
-static llvm::Optional<bool> normalizeSimpleFlag(OptSpecifier Opt,
-                                                unsigned TableIndex,
-                                                const ArgList &Args,
-                                                DiagnosticsEngine &Diags) {
-  if (Args.hasArg(Opt))
-    return true;
-  return None;
-}
-
-template <typename T, T Value>
-static llvm::Optional<T>
-normalizeFlagToValue(OptSpecifier Opt, unsigned TableIndex, const ArgList &Args,
-                     DiagnosticsEngine &Diags) {
-  if (Args.hasArg(Opt))
-    return Value;
-  return None;
-}
-
 static llvm::Optional<unsigned> normalizeSimpleEnum(OptSpecifier Opt,
                                                     unsigned TableIndex,
                                                     const ArgList &Args,
@@ -164,26 +146,22 @@ static llvm::Optional<unsigned> normalizeSimpleEnum(OptSpecifier Opt,
   return None;
 }
 
-static void denormalizeSimpleEnum(SmallVectorImpl<const char *> &Args,
-                                  CompilerInvocation::StringAllocator SA,
-                                  unsigned TableIndex, unsigned Value) {
+static const char *denormalizeSimpleEnum(CompilerInvocation::StringAllocator SA,
+                                         unsigned TableIndex, unsigned Value) {
   assert(TableIndex < SimpleEnumValueTablesSize);
   const SimpleEnumValueTable &Table = SimpleEnumValueTables[TableIndex];
-  for (int I = 0, E = Table.Size; I != E; ++I) {
-    if (Value == Table.Table[I].Value) {
-      Args.push_back(Table.Table[I].Name);
-      return;
-    }
-  }
+  for (int I = 0, E = Table.Size; I != E; ++I)
+    if (Value == Table.Table[I].Value)
+      return Table.Table[I].Name;
 
   llvm_unreachable("The simple enum value was not correctly defined in "
                    "the tablegen option description");
 }
 
-static void denormalizeString(SmallVectorImpl<const char *> &Args,
-                              CompilerInvocation::StringAllocator SA,
-                              unsigned TableIndex, const std::string &Value) {
-  Args.push_back(SA(Value));
+static const char *denormalizeString(CompilerInvocation::StringAllocator SA,
+                                     unsigned TableIndex,
+                                     const std::string &Value) {
+  return SA(Value);
 }
 
 static Optional<std::string> normalizeTriple(OptSpecifier Opt, int TableIndex,
@@ -195,24 +173,6 @@ static Optional<std::string> normalizeTriple(OptSpecifier Opt, int TableIndex,
   return llvm::Triple::normalize(Arg->getValue());
 }
 
-template <typename T, typename U>
-static T mergeForwardValue(T KeyPath, U Value) {
-  return Value;
-}
-
-template <typename T, typename U> static T mergeMaskValue(T KeyPath, U Value) {
-  return KeyPath | Value;
-}
-
-template <typename T> static T extractForwardValue(T KeyPath) {
-  return KeyPath;
-}
-
-template <typename T, typename U, U Value>
-static T extractMaskValue(T KeyPath) {
-  return KeyPath & Value;
-}
-
 //===----------------------------------------------------------------------===//
 // Deserialization (from args)
 //===----------------------------------------------------------------------===//
@@ -2050,6 +2010,37 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
   Opts.ARCMTMigrateEmitARCErrors
     = Args.hasArg(OPT_arcmt_migrate_emit_arc_errors);
 
+  if (Args.hasArg(OPT_objcmt_migrate_literals))
+    Opts.ObjCMTAction |= FrontendOptions::ObjCMT_Literals;
+  if (Args.hasArg(OPT_objcmt_migrate_subscripting))
+    Opts.ObjCMTAction |= FrontendOptions::ObjCMT_Subscripting;
+  if (Args.hasArg(OPT_objcmt_migrate_property_dot_syntax))
+    Opts.ObjCMTAction |= FrontendOptions::ObjCMT_PropertyDotSyntax;
+  if (Args.hasArg(OPT_objcmt_migrate_property))
+    Opts.ObjCMTAction |= FrontendOptions::ObjCMT_Property;
+  if (Args.hasArg(OPT_objcmt_migrate_readonly_property))
+    Opts.ObjCMTAction |= FrontendOptions::ObjCMT_ReadonlyProperty;
+  if (Args.hasArg(OPT_objcmt_migrate_readwrite_property))
+    Opts.ObjCMTAction |= FrontendOptions::ObjCMT_ReadwriteProperty;
+  if (Args.hasArg(OPT_objcmt_migrate_annotation))
+    Opts.ObjCMTAction |= FrontendOptions::ObjCMT_Annotation;
+  if (Args.hasArg(OPT_objcmt_returns_innerpointer_property))
+    Opts.ObjCMTAction |= FrontendOptions::ObjCMT_ReturnsInnerPointerProperty;
+  if (Args.hasArg(OPT_objcmt_migrate_instancetype))
+    Opts.ObjCMTAction |= FrontendOptions::ObjCMT_Instancetype;
+  if (Args.hasArg(OPT_objcmt_migrate_nsmacros))
+    Opts.ObjCMTAction |= FrontendOptions::ObjCMT_NsMacros;
+  if (Args.hasArg(OPT_objcmt_migrate_protocol_conformance))
+    Opts.ObjCMTAction |= FrontendOptions::ObjCMT_ProtocolConformance;
+  if (Args.hasArg(OPT_objcmt_atomic_property))
+    Opts.ObjCMTAction |= FrontendOptions::ObjCMT_AtomicProperty;
+  if (Args.hasArg(OPT_objcmt_ns_nonatomic_iosonly))
+    Opts.ObjCMTAction |= FrontendOptions::ObjCMT_NsAtomicIOSOnlyProperty;
+  if (Args.hasArg(OPT_objcmt_migrate_designated_init))
+    Opts.ObjCMTAction |= FrontendOptions::ObjCMT_DesignatedInitializer;
+  if (Args.hasArg(OPT_objcmt_migrate_all))
+    Opts.ObjCMTAction |= FrontendOptions::ObjCMT_MigrateDecls;
+
   Opts.ObjCMTWhiteListPath =
       std::string(Args.getLastArgValue(OPT_objcmt_whitelist_dir_path));
 
@@ -3734,18 +3725,26 @@ static void ParseTargetArgs(TargetOptions &Opts, ArgList &Args,
 
 bool CompilerInvocation::parseSimpleArgs(const ArgList &Args,
                                          DiagnosticsEngine &Diags) {
-#define OPTION_WITH_MARSHALLING(                                               \
+#define OPTION_WITH_MARSHALLING_FLAG(PREFIX_TYPE, NAME, ID, KIND, GROUP,       \
+                                     ALIAS, ALIASARGS, FLAGS, PARAM, HELPTEXT, \
+                                     METAVAR, VALUES, SPELLING, ALWAYS_EMIT,   \
+                                     KEYPATH, DEFAULT_VALUE, IS_POSITIVE)      \
+  this->KEYPATH = (Args.hasArg(OPT_##ID) && IS_POSITIVE) || (DEFAULT_VALUE);
+
+#define OPTION_WITH_MARSHALLING_STRING(                                        \
     PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,        \
     HELPTEXT, METAVAR, VALUES, SPELLING, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE,  \
-    TYPE, NORMALIZER, DENORMALIZER, MERGER, EXTRACTOR, TABLE_INDEX)            \
+    TYPE, NORMALIZER, DENORMALIZER, TABLE_INDEX)                               \
   {                                                                            \
-    this->KEYPATH = MERGER(this->KEYPATH, DEFAULT_VALUE);                      \
     if (auto MaybeValue = NORMALIZER(OPT_##ID, TABLE_INDEX, Args, Diags))      \
-      this->KEYPATH = MERGER(this->KEYPATH, static_cast<TYPE>(*MaybeValue));   \
+      this->KEYPATH = static_cast<TYPE>(*MaybeValue);                          \
+    else                                                                       \
+      this->KEYPATH = DEFAULT_VALUE;                                           \
   }
 
 #include "clang/Driver/Options.inc"
-#undef OPTION_WITH_MARSHALLING
+#undef OPTION_WITH_MARSHALLING_STRING
+#undef OPTION_WITH_MARSHALLING_FLAG
   return true;
 }
 
@@ -4000,23 +3999,29 @@ std::string CompilerInvocation::getModuleHash() const {
 
 void CompilerInvocation::generateCC1CommandLine(
     SmallVectorImpl<const char *> &Args, StringAllocator SA) const {
-#define OPTION_WITH_MARSHALLING(                                               \
+#define OPTION_WITH_MARSHALLING_FLAG(PREFIX_TYPE, NAME, ID, KIND, GROUP,       \
+                                     ALIAS, ALIASARGS, FLAGS, PARAM, HELPTEXT, \
+                                     METAVAR, VALUES, SPELLING, ALWAYS_EMIT,   \
+                                     KEYPATH, DEFAULT_VALUE, IS_POSITIVE)      \
+  if ((FLAGS) & options::CC1Option &&                                          \
+      (ALWAYS_EMIT || this->KEYPATH != (DEFAULT_VALUE)))                       \
+    Args.push_back(SPELLING);
+
+#define OPTION_WITH_MARSHALLING_STRING(                                        \
     PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,        \
     HELPTEXT, METAVAR, VALUES, SPELLING, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE,  \
-    TYPE, NORMALIZER, DENORMALIZER, MERGER, EXTRACTOR, TABLE_INDEX)            \
+    NORMALIZER_RET_TY, NORMALIZER, DENORMALIZER, TABLE_INDEX)                  \
   if (((FLAGS) & options::CC1Option) &&                                        \
-      (ALWAYS_EMIT || EXTRACTOR(this->KEYPATH) != (DEFAULT_VALUE))) {          \
-    if (Option::KIND##Class == Option::FlagClass) {                            \
-      Args.push_back(SPELLING);                                                \
-    }                                                                          \
+      (ALWAYS_EMIT || this->KEYPATH != DEFAULT_VALUE)) {                       \
     if (Option::KIND##Class == Option::SeparateClass) {                        \
       Args.push_back(SPELLING);                                                \
-      DENORMALIZER(Args, SA, TABLE_INDEX, EXTRACTOR(this->KEYPATH));           \
+      Args.push_back(DENORMALIZER(SA, TABLE_INDEX, this->KEYPATH));            \
     }                                                                          \
   }
 
 #include "clang/Driver/Options.inc"
-#undef OPTION_WITH_MARSHALLING
+#undef OPTION_WITH_MARSHALLING_STRING
+#undef OPTION_WITH_MARSHALLING_FLAG
 }
 
 namespace clang {

diff  --git a/llvm/include/llvm/Option/OptParser.td b/llvm/include/llvm/Option/OptParser.td
index 005a9524699f..47b4788b2209 100644
--- a/llvm/include/llvm/Option/OptParser.td
+++ b/llvm/include/llvm/Option/OptParser.td
@@ -97,15 +97,17 @@ class Option<list<string> prefixes, string name, OptionKind kind> {
   OptionGroup Group = ?;
   Option Alias = ?;
   list<string> AliasArgs = [];
+  string MarshallingKind = ?;
   code KeyPath = ?;
   code DefaultValue = ?;
   bit ShouldAlwaysEmit = 0;
+  // Used by the Flag option kind.
+  bit IsPositive = 1;
+  // Used by the String option kind.
   code NormalizerRetTy = ?;
   code NormalizedValuesScope = "";
   code Normalizer = "";
   code Denormalizer = "";
-  code ValueMerger = "mergeForwardValue";
-  code ValueExtractor = "extractForwardValue";
   list<code> NormalizedValues = ?;
 }
 
@@ -142,39 +144,29 @@ class ValuesCode<code valuecode> { code ValuesCode = valuecode; }
 
 // Helpers for defining marshalling information.
 
-class DefaultAnyOf<list<Option> options, string default = "false", string separator = " || "> {
-  code DefaultValue = !foldl(default, options, accumulator, option,
-                             !strconcat(accumulator, separator, !cast<string>(option.KeyPath)));
+class DefaultAnyOf<list<Option> defaults> {
+  code DefaultValue = !foldl("false", defaults, accumulator, option,
+                             !strconcat(accumulator, " || ", !cast<string>(option.KeyPath)));
 }
 
 class MarshallingInfo<code keypath, code defaultvalue> {
   code KeyPath = keypath;
   code DefaultValue = defaultvalue;
 }
-
 class MarshallingInfoString<code keypath, code defaultvalue, code normalizerretty>
   : MarshallingInfo<keypath, defaultvalue> {
+  string MarshallingKind = "string";
   code NormalizerRetTy = normalizerretty;
 }
 
-class MarshallingInfoFlag<code keypath, DefaultAnyOf defaults = DefaultAnyOf<[]>, code ty="unsigned">
+class MarshallingInfoFlag<code keypath, DefaultAnyOf defaults = DefaultAnyOf<[]>>
   : MarshallingInfo<keypath, defaults.DefaultValue> {
-  code NormalizerRetTy = ty;
-  code Normalizer = "normalizeSimpleFlag";
-}
-
-class MarshallingInfoBitfieldFlag<code keypath, code value>
-  : MarshallingInfoFlag<keypath, DefaultAnyOf<[], "0u", " | ">, "unsigned"> {
-  code Normalizer = "(normalizeFlagToValue<unsigned, "#value#">)";
-  code ValueMerger = "mergeMaskValue";
-  code ValueExtractor = "(extractMaskValue<unsigned, decltype("#value#"), "#value#">)";
+  string MarshallingKind = "flag";
 }
 
 // Mixins for additional marshalling attributes.
 
-class IsNegative {
-  // todo: create & apply a normalizer for negative flags
-}
+class IsNegative { bit IsPositive = 0; }
 class AlwaysEmit { bit ShouldAlwaysEmit = 1; }
 class Normalizer<code normalizer> { code Normalizer = normalizer; }
 class Denormalizer<code denormalizer> { code Denormalizer = denormalizer; }
@@ -185,8 +177,6 @@ class AutoNormalizeEnum {
   code Normalizer = "normalizeSimpleEnum";
   code Denormalizer = "denormalizeSimpleEnum";
 }
-class ValueMerger<code merger> { code ValueMerger = merger; }
-class ValueExtractor<code extractor> { code ValueExtractor = extractor; }
 
 // Predefined options.
 

diff  --git a/llvm/unittests/Option/OptionMarshallingTest.cpp b/llvm/unittests/Option/OptionMarshallingTest.cpp
index e8582f1bbbd0..bf26a767bba1 100644
--- a/llvm/unittests/Option/OptionMarshallingTest.cpp
+++ b/llvm/unittests/Option/OptionMarshallingTest.cpp
@@ -15,33 +15,33 @@ struct OptionWithMarshallingInfo {
 };
 
 static const OptionWithMarshallingInfo MarshallingTable[] = {
-#define OPTION_WITH_MARSHALLING(                                               \
-    PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,        \
-    HELPTEXT, METAVAR, VALUES, SPELLING, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE,  \
-    TYPE, NORMALIZER, DENORMALIZER, MERGER, EXTRACTOR, TABLE_INDEX)            \
-  {NAME, #KEYPATH, #DEFAULT_VALUE},
+#define OPTION_WITH_MARSHALLING_FLAG(PREFIX_TYPE, NAME, ID, KIND, GROUP,       \
+                                     ALIAS, ALIASARGS, FLAGS, PARAM, HELPTEXT, \
+                                     METAVAR, VALUES, SPELLING, ALWAYS_EMIT,   \
+                                     KEYPATH, DEFAULT_VALUE, IS_POSITIVE)      \
+  { NAME, #KEYPATH, #DEFAULT_VALUE },
 #include "Opts.inc"
-#undef OPTION_WITH_MARSHALLING
+#undef OPTION_WITH_MARSHALLING_FLAG
 };
 
 TEST(OptionMarshalling, EmittedOrderSameAsDefinitionOrder) {
-  ASSERT_STREQ(MarshallingTable[0].Name, "marshalled-flag-d");
-  ASSERT_STREQ(MarshallingTable[1].Name, "marshalled-flag-c");
-  ASSERT_STREQ(MarshallingTable[2].Name, "marshalled-flag-b");
-  ASSERT_STREQ(MarshallingTable[3].Name, "marshalled-flag-a");
+  ASSERT_STREQ(MarshallingTable[0].Name, "marshalled-flag-0");
+  ASSERT_STREQ(MarshallingTable[1].Name, "marshalled-flag-1");
+  ASSERT_STREQ(MarshallingTable[2].Name, "marshalled-flag-2");
+  ASSERT_STREQ(MarshallingTable[3].Name, "marshalled-flag-3");
 }
 
 TEST(OptionMarshalling, EmittedSpecifiedKeyPath) {
-  ASSERT_STREQ(MarshallingTable[0].KeyPath, "MarshalledFlagD");
-  ASSERT_STREQ(MarshallingTable[1].KeyPath, "MarshalledFlagC");
-  ASSERT_STREQ(MarshallingTable[2].KeyPath, "MarshalledFlagB");
-  ASSERT_STREQ(MarshallingTable[3].KeyPath, "MarshalledFlagA");
+  ASSERT_STREQ(MarshallingTable[0].KeyPath, "MarshalledFlag0");
+  ASSERT_STREQ(MarshallingTable[1].KeyPath, "MarshalledFlag1");
+  ASSERT_STREQ(MarshallingTable[2].KeyPath, "MarshalledFlag2");
+  ASSERT_STREQ(MarshallingTable[3].KeyPath, "MarshalledFlag3");
 }
 
 TEST(OptionMarshalling, DefaultAnyOfConstructedDisjunctionOfKeypaths) {
   ASSERT_STREQ(MarshallingTable[0].DefaultValue, "false");
-  ASSERT_STREQ(MarshallingTable[1].DefaultValue, "false || MarshalledFlagD");
-  ASSERT_STREQ(MarshallingTable[2].DefaultValue, "false || MarshalledFlagD");
+  ASSERT_STREQ(MarshallingTable[1].DefaultValue, "false || MarshalledFlag0");
+  ASSERT_STREQ(MarshallingTable[2].DefaultValue, "false || MarshalledFlag0");
   ASSERT_STREQ(MarshallingTable[3].DefaultValue,
-            "false || MarshalledFlagC || MarshalledFlagB");
+            "false || MarshalledFlag1 || MarshalledFlag2");
 }

diff  --git a/llvm/unittests/Option/Opts.td b/llvm/unittests/Option/Opts.td
index 62cd6151ea9e..3bbf210b0b74 100644
--- a/llvm/unittests/Option/Opts.td
+++ b/llvm/unittests/Option/Opts.td
@@ -45,11 +45,11 @@ def Blurmpq_eq : Flag<["--"], "blurmp=">;
 
 def DashDash : Option<["--"], "", KIND_REMAINING_ARGS>;
 
-def marshalled_flag_d : Flag<["-"], "marshalled-flag-d">,
-  MarshallingInfoFlag<"MarshalledFlagD", DefaultAnyOf<[]>>;
-def marshalled_flag_c : Flag<["-"], "marshalled-flag-c">,
-  MarshallingInfoFlag<"MarshalledFlagC", DefaultAnyOf<[marshalled_flag_d]>>;
-def marshalled_flag_b : Flag<["-"], "marshalled-flag-b">,
-  MarshallingInfoFlag<"MarshalledFlagB", DefaultAnyOf<[marshalled_flag_d]>>;
-def marshalled_flag_a : Flag<["-"], "marshalled-flag-a">,
-  MarshallingInfoFlag<"MarshalledFlagA", DefaultAnyOf<[marshalled_flag_c, marshalled_flag_b]>>;
+def marshalled_flag_0 : Flag<["-"], "marshalled-flag-0">,
+  MarshallingInfoFlag<"MarshalledFlag0", DefaultAnyOf<[]>>;
+def marshalled_flag_1 : Flag<["-"], "marshalled-flag-1">,
+  MarshallingInfoFlag<"MarshalledFlag1", DefaultAnyOf<[marshalled_flag_0]>>;
+def marshalled_flag_2 : Flag<["-"], "marshalled-flag-2">,
+  MarshallingInfoFlag<"MarshalledFlag2", DefaultAnyOf<[marshalled_flag_0]>>;
+def marshalled_flag_3 : Flag<["-"], "marshalled-flag-3">,
+  MarshallingInfoFlag<"MarshalledFlag3", DefaultAnyOf<[marshalled_flag_1, marshalled_flag_2]>>;

diff  --git a/llvm/utils/TableGen/OptParserEmitter.cpp b/llvm/utils/TableGen/OptParserEmitter.cpp
index a3387896e541..d791bd8032c2 100644
--- a/llvm/utils/TableGen/OptParserEmitter.cpp
+++ b/llvm/utils/TableGen/OptParserEmitter.cpp
@@ -61,20 +61,74 @@ static void emitNameUsingSpelling(raw_ostream &OS, const Record &R) {
   OS << "[" << PrefixLength << "]";
 }
 
-class MarshallingInfo {
+class MarshallingKindInfo {
 public:
-  static constexpr const char *MacroName = "OPTION_WITH_MARSHALLING";
-
   const Record &R;
+  const char *MacroName;
   bool ShouldAlwaysEmit;
   StringRef KeyPath;
   StringRef DefaultValue;
   StringRef NormalizedValuesScope;
+
+  void emit(raw_ostream &OS) const {
+    write_cstring(OS, StringRef(getOptionSpelling(R)));
+    OS << ", ";
+    OS << ShouldAlwaysEmit;
+    OS << ", ";
+    OS << KeyPath;
+    OS << ", ";
+    emitScopedNormalizedValue(OS, DefaultValue);
+    OS << ", ";
+    emitSpecific(OS);
+  }
+
+  virtual Optional<StringRef> emitValueTable(raw_ostream &OS) const {
+    return None;
+  }
+
+  virtual ~MarshallingKindInfo() = default;
+
+  static std::unique_ptr<MarshallingKindInfo> create(const Record &R);
+
+protected:
+  void emitScopedNormalizedValue(raw_ostream &OS,
+                                 StringRef NormalizedValue) const {
+    if (!NormalizedValuesScope.empty())
+      OS << NormalizedValuesScope << "::";
+    OS << NormalizedValue;
+  }
+
+  virtual void emitSpecific(raw_ostream &OS) const = 0;
+  MarshallingKindInfo(const Record &R, const char *MacroName)
+      : R(R), MacroName(MacroName) {}
+};
+
+class MarshallingFlagInfo final : public MarshallingKindInfo {
+public:
+  bool IsPositive;
+
+  void emitSpecific(raw_ostream &OS) const override { OS << IsPositive; }
+
+  static std::unique_ptr<MarshallingKindInfo> create(const Record &R) {
+    std::unique_ptr<MarshallingFlagInfo> Ret(new MarshallingFlagInfo(R));
+    Ret->IsPositive = R.getValueAsBit("IsPositive");
+    // FIXME: This is a workaround for a bug in older versions of clang (< 3.9)
+    //   The constructor that is supposed to allow for Derived to Base
+    //   conversion does not work. Remove this if we drop support for such
+    //   configurations.
+    return std::unique_ptr<MarshallingKindInfo>(Ret.release());
+  }
+
+private:
+  MarshallingFlagInfo(const Record &R)
+      : MarshallingKindInfo(R, "OPTION_WITH_MARSHALLING_FLAG") {}
+};
+
+class MarshallingStringInfo final : public MarshallingKindInfo {
+public:
   StringRef NormalizerRetTy;
   StringRef Normalizer;
   StringRef Denormalizer;
-  StringRef ValueMerger;
-  StringRef ValueExtractor;
   int TableIndex = -1;
   std::vector<StringRef> Values;
   std::vector<StringRef> NormalizedValues;
@@ -95,29 +149,17 @@ struct SimpleEnumValueTable {
   static constexpr const char *ValueTablesDecl =
       "static const SimpleEnumValueTable SimpleEnumValueTables[] = ";
 
-  void emit(raw_ostream &OS) const {
-    write_cstring(OS, StringRef(getOptionSpelling(R)));
-    OS << ", ";
-    OS << ShouldAlwaysEmit;
-    OS << ", ";
-    OS << KeyPath;
-    OS << ", ";
-    emitScopedNormalizedValue(OS, DefaultValue);
-    OS << ", ";
+  void emitSpecific(raw_ostream &OS) const override {
     emitScopedNormalizedValue(OS, NormalizerRetTy);
     OS << ", ";
     OS << Normalizer;
     OS << ", ";
     OS << Denormalizer;
     OS << ", ";
-    OS << ValueMerger;
-    OS << ", ";
-    OS << ValueExtractor;
-    OS << ", ";
     OS << TableIndex;
   }
 
-  Optional<StringRef> emitValueTable(raw_ostream &OS) const {
+  Optional<StringRef> emitValueTable(raw_ostream &OS) const override {
     if (TableIndex == -1)
       return {};
     OS << "static const SimpleEnumValue " << ValueTableName << "[] = {\n";
@@ -133,32 +175,23 @@ struct SimpleEnumValueTable {
     return StringRef(ValueTableName);
   }
 
-  static MarshallingInfo create(const Record &R) {
-    assert(!isa<UnsetInit>(R.getValueInit("KeyPath")) &&
-           !isa<UnsetInit>(R.getValueInit("DefaultValue")) &&
-           !isa<UnsetInit>(R.getValueInit("NormalizerRetTy")) &&
-           !isa<UnsetInit>(R.getValueInit("ValueMerger")) &&
-           "MarshallingInfo must have a type");
-
-    MarshallingInfo Ret(R);
-    Ret.ShouldAlwaysEmit = R.getValueAsBit("ShouldAlwaysEmit");
-    Ret.KeyPath = R.getValueAsString("KeyPath");
-    Ret.DefaultValue = R.getValueAsString("DefaultValue");
-    Ret.NormalizedValuesScope = R.getValueAsString("NormalizedValuesScope");
-    Ret.NormalizerRetTy = R.getValueAsString("NormalizerRetTy");
-
-    Ret.Normalizer = R.getValueAsString("Normalizer");
-    Ret.Denormalizer = R.getValueAsString("Denormalizer");
-    Ret.ValueMerger = R.getValueAsString("ValueMerger");
-    Ret.ValueExtractor = R.getValueAsString("ValueExtractor");
+  static std::unique_ptr<MarshallingKindInfo> create(const Record &R) {
+    assert(!isa<UnsetInit>(R.getValueInit("NormalizerRetTy")) &&
+           "String options must have a type");
+
+    std::unique_ptr<MarshallingStringInfo> Ret(new MarshallingStringInfo(R));
+    Ret->NormalizerRetTy = R.getValueAsString("NormalizerRetTy");
+
+    Ret->Normalizer = R.getValueAsString("Normalizer");
+    Ret->Denormalizer = R.getValueAsString("Denormalizer");
 
     if (!isa<UnsetInit>(R.getValueInit("NormalizedValues"))) {
       assert(!isa<UnsetInit>(R.getValueInit("Values")) &&
              "Cannot provide normalized values for value-less options");
-      Ret.TableIndex = NextTableIndex++;
-      Ret.NormalizedValues = R.getValueAsListOfStrings("NormalizedValues");
-      Ret.Values.reserve(Ret.NormalizedValues.size());
-      Ret.ValueTableName = getOptionName(R) + "ValueTable";
+      Ret->TableIndex = NextTableIndex++;
+      Ret->NormalizedValues = R.getValueAsListOfStrings("NormalizedValues");
+      Ret->Values.reserve(Ret->NormalizedValues.size());
+      Ret->ValueTableName = getOptionName(R) + "ValueTable";
 
       StringRef ValuesStr = R.getValueAsString("Values");
       for (;;) {
@@ -166,34 +199,55 @@ struct SimpleEnumValueTable {
         if (Idx == StringRef::npos)
           break;
         if (Idx > 0)
-          Ret.Values.push_back(ValuesStr.slice(0, Idx));
+          Ret->Values.push_back(ValuesStr.slice(0, Idx));
         ValuesStr = ValuesStr.slice(Idx + 1, StringRef::npos);
       }
       if (!ValuesStr.empty())
-        Ret.Values.push_back(ValuesStr);
+        Ret->Values.push_back(ValuesStr);
 
-      assert(Ret.Values.size() == Ret.NormalizedValues.size() &&
+      assert(Ret->Values.size() == Ret->NormalizedValues.size() &&
              "The number of normalized values doesn't match the number of "
              "values");
     }
 
-    return Ret;
+    // FIXME: This is a workaround for a bug in older versions of clang (< 3.9)
+    //   The constructor that is supposed to allow for Derived to Base
+    //   conversion does not work. Remove this if we drop support for such
+    //   configurations.
+    return std::unique_ptr<MarshallingKindInfo>(Ret.release());
   }
 
 private:
-  void emitScopedNormalizedValue(raw_ostream &OS,
-                                 StringRef NormalizedValue) const {
-    if (!NormalizedValuesScope.empty())
-      OS << NormalizedValuesScope << "::";
-    OS << NormalizedValue;
-  }
-
-  MarshallingInfo(const Record &R) : R(R){};
+  MarshallingStringInfo(const Record &R)
+      : MarshallingKindInfo(R, "OPTION_WITH_MARSHALLING_STRING") {}
 
   static size_t NextTableIndex;
 };
 
-size_t MarshallingInfo::NextTableIndex = 0;
+size_t MarshallingStringInfo::NextTableIndex = 0;
+
+std::unique_ptr<MarshallingKindInfo>
+MarshallingKindInfo::create(const Record &R) {
+  assert(!isa<UnsetInit>(R.getValueInit("KeyPath")) &&
+         !isa<UnsetInit>(R.getValueInit("DefaultValue")) &&
+         "Must provide at least a key-path and a default value for emitting "
+         "marshalling information");
+
+  std::unique_ptr<MarshallingKindInfo> Ret = nullptr;
+  StringRef MarshallingKindStr = R.getValueAsString("MarshallingKind");
+
+  if (MarshallingKindStr == "flag")
+    Ret = MarshallingFlagInfo::create(R);
+  else if (MarshallingKindStr == "string")
+    Ret = MarshallingStringInfo::create(R);
+
+  Ret->ShouldAlwaysEmit = R.getValueAsBit("ShouldAlwaysEmit");
+  Ret->KeyPath = R.getValueAsString("KeyPath");
+  Ret->DefaultValue = R.getValueAsString("DefaultValue");
+  if (!isa<UnsetInit>(R.getValueInit("NormalizedValuesScope")))
+    Ret->NormalizedValuesScope = R.getValueAsString("NormalizedValuesScope");
+  return Ret;
+}
 
 /// OptParserEmitter - This tablegen backend takes an input .td file
 /// describing a list of options and emits a data structure for parsing and
@@ -384,7 +438,7 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) {
   };
 
   auto IsMarshallingOption = [](const Record &R) {
-    return !isa<UnsetInit>(R.getValueInit("KeyPath")) &&
+    return !isa<UnsetInit>(R.getValueInit("MarshallingKind")) &&
            !R.getValueAsString("KeyPath").empty();
   };
 
@@ -418,30 +472,30 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) {
   array_pod_sort(OptsWithMarshalling.begin(), OptsWithMarshalling.end(),
                  CmpMarshallingOpts);
 
-  std::vector<MarshallingInfo> MarshallingInfos;
+  std::vector<std::unique_ptr<MarshallingKindInfo>> MarshallingKindInfos;
   for (const auto *R : OptsWithMarshalling)
-    MarshallingInfos.push_back(MarshallingInfo::create(*R));
+    MarshallingKindInfos.push_back(MarshallingKindInfo::create(*R));
 
-  for (const auto &MI : MarshallingInfos) {
-    OS << "#ifdef " << MI.MacroName << "\n";
-    OS << MI.MacroName << "(";
-    WriteOptRecordFields(OS, MI.R);
+  for (const auto &KindInfo : MarshallingKindInfos) {
+    OS << "#ifdef " << KindInfo->MacroName << "\n";
+    OS << KindInfo->MacroName << "(";
+    WriteOptRecordFields(OS, KindInfo->R);
     OS << ", ";
-    MI.emit(OS);
+    KindInfo->emit(OS);
     OS << ")\n";
-    OS << "#endif // " << MI.MacroName << "\n";
+    OS << "#endif // " << KindInfo->MacroName << "\n";
   }
 
   OS << "\n";
   OS << "#ifdef SIMPLE_ENUM_VALUE_TABLE";
   OS << "\n";
-  OS << MarshallingInfo::ValueTablePreamble;
+  OS << MarshallingStringInfo::ValueTablePreamble;
   std::vector<StringRef> ValueTableNames;
-  for (const auto &MI : MarshallingInfos)
-    if (auto MaybeValueTableName = MI.emitValueTable(OS))
+  for (const auto &KindInfo : MarshallingKindInfos)
+    if (auto MaybeValueTableName = KindInfo->emitValueTable(OS))
       ValueTableNames.push_back(*MaybeValueTableName);
 
-  OS << MarshallingInfo::ValueTablesDecl << "{";
+  OS << MarshallingStringInfo::ValueTablesDecl << "{";
   for (auto ValueTableName : ValueTableNames)
     OS << "{" << ValueTableName << ", sizeof(" << ValueTableName
        << ") / sizeof(SimpleEnumValue)"


        


More information about the cfe-commits mailing list