dang created this revision.
dang added a reviewer: Bigcheese.
Herald added subscribers: llvm-commits, cfe-commits, jfb, dexonsmith.
Herald added projects: clang, LLVM.
dang marked an inline comment as done.
dang added inline comments.


================
Comment at: clang/include/clang/Driver/Options.td:328-331
+  HelpText<"Enable migration to modern ObjC literals">,
+  MarshallingInfoFlag<"FrontendOpts.ObjCMTAction", "0", "unsigned">, 
Normalizer<"normalizeFlagToValue<unsigned>">,
+  ValueMerger<"MERGE_VALUE_MASK">, ValueExtractor<"EXTRACT_VALUE_MASK">,
+  NormalizerCookie<"FrontendOptions::ObjCMT_Literals">;
----------------
If this kind of combination of normalizer, value merger and extractor happen 
again, I will make a mixin that helps set this up. Or do you reckon it is worth 
doing it now for readability.


Merge existing marhsalling info kinds and add some primitives to
express flag options that contribute to a bitfield.

Depends on D82574 <https://reviews.llvm.org/D82574>


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D82860

Files:
  clang/include/clang/Driver/Options.td
  clang/lib/Frontend/CompilerInvocation.cpp
  llvm/include/llvm/Option/OptParser.td
  llvm/utils/TableGen/OptParserEmitter.cpp

Index: llvm/utils/TableGen/OptParserEmitter.cpp
===================================================================
--- llvm/utils/TableGen/OptParserEmitter.cpp
+++ llvm/utils/TableGen/OptParserEmitter.cpp
@@ -59,70 +59,21 @@
   OS << "[" << PrefixLength << "]";
 }
 
-class MarshallingKindInfo {
+class MarshallingInfo {
 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");
-    return Ret;
-  }
-
-private:
-  MarshallingFlagInfo(const Record &R)
-      : MarshallingKindInfo(R, "OPTION_WITH_MARSHALLING_FLAG") {}
-};
-
-class MarshallingStringInfo final : public MarshallingKindInfo {
-public:
   StringRef NormalizerRetTy;
   StringRef Normalizer;
+  StringRef NormalizerCookie;
   StringRef Denormalizer;
+  StringRef ValueMerger;
+  StringRef ValueExtractor;
   int TableIndex = -1;
   std::vector<StringRef> Values;
   std::vector<StringRef> NormalizedValues;
@@ -143,17 +94,31 @@
   static constexpr const char *ValueTablesDecl =
       "static const SimpleEnumValueTable SimpleEnumValueTables[] = ";
 
-  void emitSpecific(raw_ostream &OS) const override {
+  void emit(raw_ostream &OS) const {
+    write_cstring(OS, StringRef(getOptionSpelling(R)));
+    OS << ", ";
+    OS << ShouldAlwaysEmit;
+    OS << ", ";
+    OS << KeyPath;
+    OS << ", ";
+    emitScopedNormalizedValue(OS, DefaultValue);
+    OS << ", ";
     emitScopedNormalizedValue(OS, NormalizerRetTy);
     OS << ", ";
     OS << Normalizer;
     OS << ", ";
     OS << Denormalizer;
     OS << ", ";
+    OS << NormalizerCookie;
+    OS << ", ";
+    OS << ValueMerger;
+    OS << ", ";
+    OS << ValueExtractor;
+    OS << ", ";
     OS << TableIndex;
   }
 
-  Optional<StringRef> emitValueTable(raw_ostream &OS) const override {
+  Optional<StringRef> emitValueTable(raw_ostream &OS) const {
     if (TableIndex == -1)
       return {};
     OS << "static const SimpleEnumValue " << ValueTableName << "[] = {\n";
@@ -169,23 +134,33 @@
     return StringRef(ValueTableName);
   }
 
-  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");
+  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.NormalizerCookie = R.getValueAsString("NormalizerCookie");
+    Ret.ValueMerger = R.getValueAsString("ValueMerger");
+    Ret.ValueExtractor = R.getValueAsString("ValueExtractor");
 
     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 (;;) {
@@ -193,13 +168,13 @@
         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");
     }
@@ -208,36 +183,19 @@
   }
 
 private:
-  MarshallingStringInfo(const Record &R)
-      : MarshallingKindInfo(R, "OPTION_WITH_MARSHALLING_STRING") {}
+  void emitScopedNormalizedValue(raw_ostream &OS,
+                                 StringRef NormalizedValue) const {
+    if (!NormalizedValuesScope.empty())
+      OS << NormalizedValuesScope << "::";
+    OS << NormalizedValue;
+  }
+
+  MarshallingInfo(const Record &R) : R(R){};
 
   static size_t NextTableIndex;
 };
 
-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;
-}
+size_t MarshallingInfo::NextTableIndex = 0;
 
 /// OptParserEmitter - This tablegen backend takes an input .td file
 /// describing a list of options and emits a data structure for parsing and
@@ -427,7 +385,7 @@
       OS << "nullptr";
   };
 
-  std::vector<std::unique_ptr<MarshallingKindInfo>> OptsWithMarshalling;
+  std::vector<MarshallingInfo> OptsWithMarshalling;
   for (unsigned I = 0, E = Opts.size(); I != E; ++I) {
     const Record &R = *Opts[I];
 
@@ -435,32 +393,32 @@
     OS << "OPTION(";
     WriteOptRecordFields(OS, R);
     OS << ")\n";
-    if (!isa<UnsetInit>(R.getValueInit("MarshallingKind")) &&
+    if (!isa<UnsetInit>(R.getValueInit("KeyPath")) &&
         !R.getValueAsString("KeyPath").empty())
-      OptsWithMarshalling.push_back(MarshallingKindInfo::create(R));
+      OptsWithMarshalling.push_back(MarshallingInfo::create(R));
   }
   OS << "#endif // OPTION\n";
 
   for (const auto &KindInfo : OptsWithMarshalling) {
-    OS << "#ifdef " << KindInfo->MacroName << "\n";
-    OS << KindInfo->MacroName << "(";
-    WriteOptRecordFields(OS, KindInfo->R);
+    OS << "#ifdef " << KindInfo.MacroName << "\n";
+    OS << KindInfo.MacroName << "(";
+    WriteOptRecordFields(OS, KindInfo.R);
     OS << ", ";
-    KindInfo->emit(OS);
+    KindInfo.emit(OS);
     OS << ")\n";
-    OS << "#endif // " << KindInfo->MacroName << "\n";
+    OS << "#endif // " << KindInfo.MacroName << "\n";
   }
 
   OS << "\n";
   OS << "#ifdef SIMPLE_ENUM_VALUE_TABLE";
   OS << "\n";
-  OS << MarshallingStringInfo::ValueTablePreamble;
+  OS << MarshallingInfo::ValueTablePreamble;
   std::vector<StringRef> ValueTableNames;
   for (const auto &KindInfo : OptsWithMarshalling)
-    if (auto MaybeValueTableName = KindInfo->emitValueTable(OS))
+    if (auto MaybeValueTableName = KindInfo.emitValueTable(OS))
       ValueTableNames.push_back(*MaybeValueTableName);
 
-  OS << MarshallingStringInfo::ValueTablesDecl << "{";
+  OS << MarshallingInfo::ValueTablesDecl << "{";
   for (auto ValueTableName : ValueTableNames)
     OS << "{" << ValueTableName << ", sizeof(" << ValueTableName
        << ") / sizeof(SimpleEnumValue)"
Index: llvm/include/llvm/Option/OptParser.td
===================================================================
--- llvm/include/llvm/Option/OptParser.td
+++ llvm/include/llvm/Option/OptParser.td
@@ -97,17 +97,16 @@
   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 NormalizerCookie = "nullptr";
+  code ValueMerger = "MERGE_ASSIGN_VALUE";
+  code ValueExtractor = "EXTRACT_VALUE";
   list<code> NormalizedValues = ?;
 }
 
@@ -148,23 +147,27 @@
   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, code defaultvalue>
+class MarshallingInfoFlag<code keypath, code defaultvalue, code ty="bool">
   : MarshallingInfo<keypath, defaultvalue> {
-  string MarshallingKind = "flag";
+  code NormalizerRetTy = ty;
+  code Normalizer = "normalizeSimpleFlag";
 }
 
 // Mixins for additional marshalling attributes.
 
-class IsNegative { bit IsPositive = 0; }
+class IsNegative {
+  code Normalizer = "normalizeSimpleNegativeFlag";
+}
 class AlwaysEmit { bit ShouldAlwaysEmit = 1; }
 class Normalizer<code normalizer> { code Normalizer = normalizer; }
 class Denormalizer<code denormalizer> { code Denormalizer = denormalizer; }
+class NormalizerCookie<code cookie> { code NormalizerCookie = cookie; }
 class NormalizedValuesScope<code scope> { code NormalizedValuesScope = scope; }
 class NormalizedValues<list<code> definitions> { list<code> NormalizedValues = definitions; } 
 class DenormalizeString { code Denormalizer = "denormalizeString"; }
@@ -172,6 +175,8 @@
   code Normalizer = "normalizeSimpleEnum";
   code Denormalizer = "denormalizeSimpleEnum";
 }
+class ValueMerger<code merger> { code ValueMerger = merger; }
+class ValueExtractor<code extractor> { code ValueExtractor = extractor; }
 
 // Predefined options.
 
Index: clang/lib/Frontend/CompilerInvocation.cpp
===================================================================
--- clang/lib/Frontend/CompilerInvocation.cpp
+++ clang/lib/Frontend/CompilerInvocation.cpp
@@ -125,10 +125,31 @@
 #include "clang/Driver/Options.inc"
 #undef SIMPLE_ENUM_VALUE_TABLE
 
-static llvm::Optional<unsigned> normalizeSimpleEnum(OptSpecifier Opt,
-                                                    unsigned TableIndex,
-                                                    const ArgList &Args,
-                                                    DiagnosticsEngine &Diags) {
+static llvm::Optional<bool>
+normalizeSimpleFlag(OptSpecifier Opt, unsigned TableIndex, const ArgList &Args,
+                    DiagnosticsEngine &Diags, void *Cookie) {
+  return Args.hasArg(Opt);
+}
+
+static llvm::Optional<bool>
+normalizeSimpleNegativeFlag(OptSpecifier Opt, unsigned TableIndex,
+                            const ArgList &Args, DiagnosticsEngine &Diags,
+                            void *Cookie) {
+  return !Args.hasArg(Opt);
+}
+
+template <typename T>
+static llvm::Optional<T>
+normalizeFlagToValue(OptSpecifier Opt, unsigned TableIndex, const ArgList &Args,
+                     DiagnosticsEngine &Diags, T Cookie) {
+  if (Args.hasArg(Opt))
+    return Cookie;
+  return None;
+}
+
+static llvm::Optional<unsigned>
+normalizeSimpleEnum(OptSpecifier Opt, unsigned TableIndex, const ArgList &Args,
+                    DiagnosticsEngine &Diags, void *Cookie) {
   assert(TableIndex < SimpleEnumValueTablesSize);
   const SimpleEnumValueTable &Table = SimpleEnumValueTables[TableIndex];
 
@@ -146,27 +167,32 @@
   return None;
 }
 
-static const char *denormalizeSimpleEnum(CompilerInvocation::StringAllocator SA,
-                                         unsigned TableIndex, unsigned Value) {
+static void denormalizeSimpleEnum(SmallVectorImpl<const char *> &Args,
+                                  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)
-      return Table.Table[I].Name;
+  for (int I = 0, E = Table.Size; I != E; ++I) {
+    if (Value == Table.Table[I].Value) {
+      Args.push_back(Table.Table[I].Name);
+      return;
+    }
+  }
 
   llvm_unreachable("The simple enum value was not correctly defined in "
                    "the tablegen option description");
 }
 
-static const char *denormalizeString(CompilerInvocation::StringAllocator SA,
-                                     unsigned TableIndex,
-                                     const std::string &Value) {
-  return SA(Value);
+static void denormalizeString(SmallVectorImpl<const char *> &Args,
+                              CompilerInvocation::StringAllocator SA,
+                              unsigned TableIndex, const std::string &Value) {
+  Args.push_back(SA(Value));
 }
 
 static Optional<std::string> normalizeTriple(OptSpecifier Opt, int TableIndex,
                                              const ArgList &Args,
-                                             DiagnosticsEngine &Diags) {
+                                             DiagnosticsEngine &Diags,
+                                             void *Cookie) {
   auto *Arg = Args.getLastArg(Opt);
   if (!Arg)
     return None;
@@ -1968,37 +1994,6 @@
   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));
 
@@ -3614,26 +3609,25 @@
 
 bool CompilerInvocation::parseSimpleArgs(const ArgList &Args,
                                          DiagnosticsEngine &Diags) {
-#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;
+#define MERGE_ASSIGN_VALUE(KEYPATH, VALUE) (KEYPATH) = (VALUE)
+#define MERGE_VALUE_MASK(KEYPATH, VALUE) (KEYPATH) |= (VALUE)
 
-#define OPTION_WITH_MARSHALLING_STRING(                                        \
+#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, TABLE_INDEX)                               \
+    TYPE, NORMALIZER, DENORMALIZER, COOKIE, MERGER, EXTRACTOR, TABLE_INDEX)    \
   {                                                                            \
-    if (auto MaybeValue = NORMALIZER(OPT_##ID, TABLE_INDEX, Args, Diags))      \
-      this->KEYPATH = static_cast<TYPE>(*MaybeValue);                          \
+    if (auto MaybeValue =                                                      \
+            NORMALIZER(OPT_##ID, TABLE_INDEX, Args, Diags, COOKIE))            \
+      MERGER(this->KEYPATH, static_cast<TYPE>(*MaybeValue));                   \
     else                                                                       \
-      this->KEYPATH = DEFAULT_VALUE;                                           \
+      MERGER(this->KEYPATH, DEFAULT_VALUE);                                    \
   }
 
 #include "clang/Driver/Options.inc"
-#undef OPTION_WITH_MARSHALLING_STRING
-#undef OPTION_WITH_MARSHALLING_FLAG
+#undef OPTION_WITH_MARSHALLING
+#undef MERGE_VALUE_MASK
+#undef MERGE_ASSIGN_VALUE
   return true;
 }
 
@@ -3880,29 +3874,28 @@
 
 void CompilerInvocation::generateCC1CommandLine(
     SmallVectorImpl<const char *> &Args, StringAllocator SA) const {
-#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(                                        \
+#define EXTRACT_VALUE(KEYPATH, COOKIE) (KEYPATH)
+#define EXTRACT_VALUE_MASK(KEYPATH, COOKIE) ((KEYPATH) & (COOKIE))
+
+#define OPTION_WITH_MARSHALLING(                                               \
     PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,        \
     HELPTEXT, METAVAR, VALUES, SPELLING, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE,  \
-    NORMALIZER_RET_TY, NORMALIZER, DENORMALIZER, TABLE_INDEX)                  \
-  if (((FLAGS) & options::CC1Option) &&                                          \
-      (ALWAYS_EMIT || this->KEYPATH != DEFAULT_VALUE)) {                       \
+    TYPE, NORMALIZER, DENORMALIZER, COOKIE, MERGER, EXTRACTOR, TABLE_INDEX)    \
+  if (((FLAGS)&options::CC1Option) &&                                          \
+      (ALWAYS_EMIT || EXTRACTOR(this->KEYPATH, COOKIE) != DEFAULT_VALUE)) {    \
+    if (Option::KIND##Class == Option::FlagClass) {                            \
+      Args.push_back(SPELLING);                                                \
+    }                                                                          \
     if (Option::KIND##Class == Option::SeparateClass) {                        \
       Args.push_back(SPELLING);                                                \
-      Args.push_back(DENORMALIZER(SA, TABLE_INDEX, this->KEYPATH));            \
+      DENORMALIZER(Args, SA, TABLE_INDEX, this->KEYPATH);                      \
     }                                                                          \
   }
 
 #include "clang/Driver/Options.inc"
-#undef OPTION_WITH_MARSHALLING_STRING
-#undef OPTION_WITH_MARSHALLING_FLAG
+#undef OPTION_WITH_MARSHALLING
+#undef EXTRACT_VALUE_MASK
+#undef EXTRACT_VALUE
 }
 
 namespace clang {
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -323,36 +323,83 @@
   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">;
+  HelpText<"Enable migration to modern ObjC literals">,
+  MarshallingInfoFlag<"FrontendOpts.ObjCMTAction", "0", "unsigned">, Normalizer<"normalizeFlagToValue<unsigned>">,
+  ValueMerger<"MERGE_VALUE_MASK">, ValueExtractor<"EXTRACT_VALUE_MASK">,
+  NormalizerCookie<"FrontendOptions::ObjCMT_Literals">;
 def objcmt_migrate_subscripting : Flag<["-"], "objcmt-migrate-subscripting">, Flags<[CC1Option]>,
-  HelpText<"Enable migration to modern ObjC subscripting">;
+  HelpText<"Enable migration to modern ObjC subscripting">,
+  MarshallingInfoFlag<"FrontendOpts.ObjCMTAction", "0", "unsigned">, Normalizer<"normalizeFlagToValue<unsigned>">,
+  ValueMerger<"MERGE_VALUE_MASK">, ValueExtractor<"EXTRACT_VALUE_MASK">,
+  NormalizerCookie<"FrontendOptions::ObjCMT_Subscripting">;
+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">,
+  MarshallingInfoFlag<"FrontendOpts.ObjCMTAction", "0", "unsigned">, Normalizer<"normalizeFlagToValue<unsigned>">,
+  ValueMerger<"MERGE_VALUE_MASK">, ValueExtractor<"EXTRACT_VALUE_MASK">,
+  NormalizerCookie<"FrontendOptions::ObjCMT_PropertyDotSyntax">;
 def objcmt_migrate_property : Flag<["-"], "objcmt-migrate-property">, Flags<[CC1Option]>,
-  HelpText<"Enable migration to modern ObjC property">;
-def objcmt_migrate_all : Flag<["-"], "objcmt-migrate-all">, Flags<[CC1Option]>,
-  HelpText<"Enable migration to modern ObjC">;
+  HelpText<"Enable migration to modern ObjC property">,
+  MarshallingInfoFlag<"FrontendOpts.ObjCMTAction", "0", "unsigned">, Normalizer<"normalizeFlagToValue<unsigned>">,
+  ValueMerger<"MERGE_VALUE_MASK">, ValueExtractor<"EXTRACT_VALUE_MASK">,
+  NormalizerCookie<"FrontendOptions::ObjCMT_Property">;
 def objcmt_migrate_readonly_property : Flag<["-"], "objcmt-migrate-readonly-property">, Flags<[CC1Option]>,
-  HelpText<"Enable migration to modern ObjC readonly property">;
+  HelpText<"Enable migration to modern ObjC readonly property">,
+  MarshallingInfoFlag<"FrontendOpts.ObjCMTAction", "0", "unsigned">, Normalizer<"normalizeFlagToValue<unsigned>">,
+  ValueMerger<"MERGE_VALUE_MASK">, ValueExtractor<"EXTRACT_VALUE_MASK">,
+  NormalizerCookie<"FrontendOptions::ObjCMT_ReadonlyProperty">;
 def objcmt_migrate_readwrite_property : Flag<["-"], "objcmt-migrate-readwrite-property">, Flags<[CC1Option]>,
-  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">;
+  HelpText<"Enable migration to modern ObjC readwrite property">,
+  MarshallingInfoFlag<"FrontendOpts.ObjCMTAction", "0", "unsigned">, Normalizer<"normalizeFlagToValue<unsigned>">,
+  ValueMerger<"MERGE_VALUE_MASK">, ValueExtractor<"EXTRACT_VALUE_MASK">,
+  NormalizerCookie<"FrontendOptions::ObjCMT_ReadwriteProperty">;
 def objcmt_migrate_annotation : Flag<["-"], "objcmt-migrate-annotation">, Flags<[CC1Option]>,
-  HelpText<"Enable migration to property and method annotations">;
+  HelpText<"Enable migration to property and method annotations">,
+  MarshallingInfoFlag<"FrontendOpts.ObjCMTAction", "0", "unsigned">, Normalizer<"normalizeFlagToValue<unsigned>">,
+  ValueMerger<"MERGE_VALUE_MASK">, ValueExtractor<"EXTRACT_VALUE_MASK">,
+  NormalizerCookie<"FrontendOptions::ObjCMT_Annotation">;
+def objcmt_returns_innerpointer_property : Flag<["-"], "objcmt-returns-innerpointer-property">, Flags<[CC1Option]>,
+  HelpText<"Enable migration to annotate property with NS_RETURNS_INNER_POINTER">,
+  MarshallingInfoFlag<"FrontendOpts.ObjCMTAction", "0", "unsigned">, Normalizer<"normalizeFlagToValue<unsigned>">,
+  ValueMerger<"MERGE_VALUE_MASK">, ValueExtractor<"EXTRACT_VALUE_MASK">,
+  NormalizerCookie<"FrontendOptions::ObjCMT_ReturnsInnerPointerProperty">;
 def objcmt_migrate_instancetype : Flag<["-"], "objcmt-migrate-instancetype">, Flags<[CC1Option]>,
-  HelpText<"Enable migration to infer instancetype for method result type">;
+  HelpText<"Enable migration to infer instancetype for method result type">,
+  MarshallingInfoFlag<"FrontendOpts.ObjCMTAction", "0", "unsigned">, Normalizer<"normalizeFlagToValue<unsigned>">,
+  ValueMerger<"MERGE_VALUE_MASK">, ValueExtractor<"EXTRACT_VALUE_MASK">,
+  NormalizerCookie<"FrontendOptions::ObjCMT_Instancetype">;
 def objcmt_migrate_nsmacros : Flag<["-"], "objcmt-migrate-ns-macros">, Flags<[CC1Option]>,
-  HelpText<"Enable migration to NS_ENUM/NS_OPTIONS macros">;
+  HelpText<"Enable migration to NS_ENUM/NS_OPTIONS macros">,
+  MarshallingInfoFlag<"FrontendOpts.ObjCMTAction", "0", "unsigned">, Normalizer<"normalizeFlagToValue<unsigned>">,
+  ValueMerger<"MERGE_VALUE_MASK">, ValueExtractor<"EXTRACT_VALUE_MASK">,
+  NormalizerCookie<"FrontendOptions::ObjCMT_NsMacros">;
 def objcmt_migrate_protocol_conformance : Flag<["-"], "objcmt-migrate-protocol-conformance">, Flags<[CC1Option]>,
-  HelpText<"Enable migration to add protocol conformance on classes">;
+  HelpText<"Enable migration to add protocol conformance on classes">,
+  MarshallingInfoFlag<"FrontendOpts.ObjCMTAction", "0", "unsigned">, Normalizer<"normalizeFlagToValue<unsigned>">,
+  ValueMerger<"MERGE_VALUE_MASK">, ValueExtractor<"EXTRACT_VALUE_MASK">,
+  NormalizerCookie<"FrontendOptions::ObjCMT_ProtocolConformance">;
 def objcmt_atomic_property : Flag<["-"], "objcmt-atomic-property">, Flags<[CC1Option]>,
-  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">;
+  HelpText<"Make migration to 'atomic' properties">,
+  MarshallingInfoFlag<"FrontendOpts.ObjCMTAction", "0", "unsigned">, Normalizer<"normalizeFlagToValue<unsigned>">,
+  ValueMerger<"MERGE_VALUE_MASK">, ValueExtractor<"EXTRACT_VALUE_MASK">,
+  NormalizerCookie<"FrontendOptions::ObjCMT_AtomicProperty">;
 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">;
+  HelpText<"Enable migration to use NS_NONATOMIC_IOSONLY macro for setting property's 'atomic' attribute">,
+  MarshallingInfoFlag<"FrontendOpts.ObjCMTAction", "0", "unsigned">, Normalizer<"normalizeFlagToValue<unsigned>">,
+  ValueMerger<"MERGE_VALUE_MASK">, ValueExtractor<"EXTRACT_VALUE_MASK">,
+  NormalizerCookie<"FrontendOptions::ObjCMT_NsAtomicIOSOnlyProperty">;
 def objcmt_migrate_designated_init : Flag<["-"], "objcmt-migrate-designated-init">, Flags<[CC1Option]>,
-  HelpText<"Enable migration to infer NS_DESIGNATED_INITIALIZER for initializer methods">;
+  HelpText<"Enable migration to infer NS_DESIGNATED_INITIALIZER for initializer methods">,
+  MarshallingInfoFlag<"FrontendOpts.ObjCMTAction", "0", "unsigned">, Normalizer<"normalizeFlagToValue<unsigned>">,
+  ValueMerger<"MERGE_VALUE_MASK">, ValueExtractor<"EXTRACT_VALUE_MASK">,
+  NormalizerCookie<"FrontendOptions::ObjCMT_DesignatedInitializer">;
+def objcmt_migrate_all : Flag<["-"], "objcmt-migrate-all">, Flags<[CC1Option]>,
+  HelpText<"Enable migration to modern ObjC">,
+  MarshallingInfoFlag<"FrontendOpts.ObjCMTAction", "0", "unsigned">, Normalizer<"normalizeFlagToValue<unsigned>">,
+  ValueMerger<"MERGE_VALUE_MASK">, ValueExtractor<"EXTRACT_VALUE_MASK">,
+  NormalizerCookie<"FrontendOptions::ObjCMT_MigrateDecls">;
+
 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.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to