Skip to content

Commit

Permalink
Reland [clang][cli] Port ObjCMTAction to new option parsing system
Browse files Browse the repository at this point in the history
Merge existing marhsalling info kinds and add some primitives to
express flag options that contribute to a bitfield.

Depends on D82574

Original patch by Daniel Grumberg.

Reviewed By: Bigcheese

Differential Revision: https://reviews.llvm.org/D82860
  • Loading branch information
jansvoboda11 committed Nov 13, 2020
1 parent c30ab6c commit d2d59d2
Show file tree
Hide file tree
Showing 6 changed files with 207 additions and 239 deletions.
47 changes: 32 additions & 15 deletions clang/include/clang/Driver/Options.td
Expand Up @@ -340,36 +340,53 @@ 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">;
HelpText<"Enable migration to modern ObjC literals">,
MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "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">,
MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_Subscripting">;
def objcmt_migrate_property : Flag<["-"], "objcmt-migrate-property">, Flags<[CC1Option]>,
HelpText<"Enable migration to modern ObjC property">;
HelpText<"Enable migration to modern ObjC property">,
MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_Property">;
def objcmt_migrate_all : Flag<["-"], "objcmt-migrate-all">, Flags<[CC1Option]>,
HelpText<"Enable migration to modern ObjC">;
HelpText<"Enable migration to modern ObjC">,
MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_MigrateDecls">;
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">,
MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_ReadonlyProperty">;
def objcmt_migrate_readwrite_property : Flag<["-"], "objcmt-migrate-readwrite-property">, Flags<[CC1Option]>,
HelpText<"Enable migration to modern ObjC readwrite property">;
HelpText<"Enable migration to modern ObjC readwrite property">,
MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_ReadwriteProperty">;
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 of setter/getter messages to property-dot syntax">,
MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_PropertyDotSyntax">;
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">,
MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_Annotation">;
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">,
MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "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">,
MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "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">,
MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_ProtocolConformance">;
def objcmt_atomic_property : Flag<["-"], "objcmt-atomic-property">, Flags<[CC1Option]>,
HelpText<"Make migration to 'atomic' properties">;
HelpText<"Make migration to 'atomic' properties">,
MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_AtomicProperty">;
def objcmt_returns_innerpointer_property : Flag<["-"], "objcmt-returns-innerpointer-property">, Flags<[CC1Option]>,
HelpText<"Enable migration to annotate property with NS_RETURNS_INNER_POINTER">;
HelpText<"Enable migration to annotate property with NS_RETURNS_INNER_POINTER">,
MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_ReturnsInnerPointerProperty">;
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">,
MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "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">,
MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_DesignatedInitializer">;

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.
Expand Down
129 changes: 62 additions & 67 deletions clang/lib/Frontend/CompilerInvocation.cpp
Expand Up @@ -125,6 +125,24 @@ 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,
Expand All @@ -146,22 +164,26 @@ static llvm::Optional<unsigned> normalizeSimpleEnum(OptSpecifier Opt,
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,
Expand All @@ -173,6 +195,24 @@ 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)
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -2010,37 +2050,6 @@ 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));

Expand Down Expand Up @@ -3722,26 +3731,18 @@ static void ParseTargetArgs(TargetOptions &Opts, ArgList &Args,

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) || (DEFAULT_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, MERGER, EXTRACTOR, TABLE_INDEX) \
{ \
this->KEYPATH = MERGER(this->KEYPATH, DEFAULT_VALUE); \
if (auto MaybeValue = NORMALIZER(OPT_##ID, TABLE_INDEX, Args, Diags)) \
this->KEYPATH = static_cast<TYPE>(*MaybeValue); \
else \
this->KEYPATH = DEFAULT_VALUE; \
this->KEYPATH = MERGER(this->KEYPATH, static_cast<TYPE>(*MaybeValue)); \
}

#include "clang/Driver/Options.inc"
#undef OPTION_WITH_MARSHALLING_STRING
#undef OPTION_WITH_MARSHALLING_FLAG
#undef OPTION_WITH_MARSHALLING
return true;
}

Expand Down Expand Up @@ -3996,29 +3997,23 @@ std::string CompilerInvocation::getModuleHash() const {

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 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) \
TYPE, NORMALIZER, DENORMALIZER, MERGER, EXTRACTOR, TABLE_INDEX) \
if (((FLAGS) & options::CC1Option) && \
(ALWAYS_EMIT || this->KEYPATH != DEFAULT_VALUE)) { \
(ALWAYS_EMIT || EXTRACTOR(this->KEYPATH) != (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, EXTRACTOR(this->KEYPATH)); \
} \
}

#include "clang/Driver/Options.inc"
#undef OPTION_WITH_MARSHALLING_STRING
#undef OPTION_WITH_MARSHALLING_FLAG
#undef OPTION_WITH_MARSHALLING
}

IntrusiveRefCntPtr<llvm::vfs::FileSystem>
Expand Down
32 changes: 21 additions & 11 deletions llvm/include/llvm/Option/OptParser.td
Expand Up @@ -97,17 +97,15 @@ 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 = ?;
}

Expand Down Expand Up @@ -144,29 +142,39 @@ class ValuesCode<code valuecode> { code ValuesCode = valuecode; }

// Helpers for defining marshalling information.

class DefaultAnyOf<list<Option> defaults> {
code DefaultValue = !foldl("false", defaults, accumulator, option,
!strconcat(accumulator, " || ", !cast<string>(option.KeyPath)));
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 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<[]>>
class MarshallingInfoFlag<code keypath, DefaultAnyOf defaults = DefaultAnyOf<[]>, code ty="unsigned">
: MarshallingInfo<keypath, defaults.DefaultValue> {
string MarshallingKind = "flag";
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#">)";
}

// Mixins for additional marshalling attributes.

class IsNegative { bit IsPositive = 0; }
class IsNegative {
// todo: create & apply a normalizer for negative flags
}
class AlwaysEmit { bit ShouldAlwaysEmit = 1; }
class Normalizer<code normalizer> { code Normalizer = normalizer; }
class Denormalizer<code denormalizer> { code Denormalizer = denormalizer; }
Expand All @@ -177,6 +185,8 @@ class AutoNormalizeEnum {
code Normalizer = "normalizeSimpleEnum";
code Denormalizer = "denormalizeSimpleEnum";
}
class ValueMerger<code merger> { code ValueMerger = merger; }
class ValueExtractor<code extractor> { code ValueExtractor = extractor; }

// Predefined options.

Expand Down

0 comments on commit d2d59d2

Please sign in to comment.