Implement super mesage sends for @objc property and subscript getters/setters.

Fixes <rdar://problem/15933008>.


Swift SVN r13100
This commit is contained in:
Doug Gregor
2014-01-29 07:45:53 +00:00
parent a2b88a798e
commit f1be1ed572
9 changed files with 83 additions and 20 deletions

View File

@@ -102,10 +102,19 @@ class alignas(8) Expr {
friend class MemberRefExpr; friend class MemberRefExpr;
unsigned : NumExprBits; unsigned : NumExprBits;
unsigned IsDirectPropertyAccess : 1; unsigned IsDirectPropertyAccess : 1;
unsigned IsSuper : 1;
}; };
enum { NumMemberRefExprBits = NumExprBits + 1 }; enum { NumMemberRefExprBits = NumExprBits + 2 };
static_assert(NumMemberRefExprBits <= 32, "fits in an unsigned"); static_assert(NumMemberRefExprBits <= 32, "fits in an unsigned");
class SubscriptExprBitfields {
friend class SubscriptExpr;
unsigned : NumExprBits;
unsigned IsSuper : 1;
};
enum { NumSubscriptExprBits = NumExprBits + 1 };
static_assert(NumSubscriptExprBits <= 32, "fits in an unsigned");
class MagicIdentifierLiteralExprBitfields { class MagicIdentifierLiteralExprBitfields {
friend class MagicIdentifierLiteralExpr; friend class MagicIdentifierLiteralExpr;
unsigned : NumLiteralExprBits; unsigned : NumLiteralExprBits;
@@ -146,6 +155,7 @@ protected:
IntegerLiteralExprBitfields IntegerLiteralExprBits; IntegerLiteralExprBitfields IntegerLiteralExprBits;
StringLiteralExprBitfields StringLiteralExprBits; StringLiteralExprBitfields StringLiteralExprBits;
MemberRefExprBitfields MemberRefExprBits; MemberRefExprBitfields MemberRefExprBits;
SubscriptExprBitfields SubscriptExprBits;
MagicIdentifierLiteralExprBitfields MagicIdentifierLiteralExprBits; MagicIdentifierLiteralExprBitfields MagicIdentifierLiteralExprBits;
AbstractClosureExprBitfields AbstractClosureExprBits; AbstractClosureExprBitfields AbstractClosureExprBits;
ClosureExprBitfields ClosureExprBits; ClosureExprBitfields ClosureExprBits;
@@ -783,11 +793,20 @@ public:
void setBase(Expr *E) { Base = E; } void setBase(Expr *E) { Base = E; }
/// Return true if this member access is /// Return true if this member access is direct, meaning that it
/// does not call the getter or setter.
bool isDirectPropertyAccess() const { bool isDirectPropertyAccess() const {
return MemberRefExprBits.IsDirectPropertyAccess; return MemberRefExprBits.IsDirectPropertyAccess;
} }
/// Determine whether this member reference refers to the
/// superclass's property.
bool isSuper() const { return MemberRefExprBits.IsSuper; }
/// Set whether this member reference refers to the superclass's
/// property.
void setIsSuper(bool isSuper) { MemberRefExprBits.IsSuper = isSuper; }
SourceLoc getLoc() const { return NameLoc; } SourceLoc getLoc() const { return NameLoc; }
SourceRange getSourceRange() const { SourceRange getSourceRange() const {
if (Base->isImplicit()) if (Base->isImplicit())
@@ -1252,7 +1271,9 @@ public:
SubscriptExpr(Expr *base, Expr *index, SubscriptExpr(Expr *base, Expr *index,
ConcreteDeclRef decl = ConcreteDeclRef()) ConcreteDeclRef decl = ConcreteDeclRef())
: Expr(ExprKind::Subscript, /*Implicit=*/false, Type()), : Expr(ExprKind::Subscript, /*Implicit=*/false, Type()),
TheDecl(decl), Base(base), Index(index) { } TheDecl(decl), Base(base), Index(index) {
SubscriptExprBits.IsSuper = false;
}
/// getBase - Retrieve the base of the subscript expression, i.e., the /// getBase - Retrieve the base of the subscript expression, i.e., the
/// value being indexed. /// value being indexed.
@@ -1264,6 +1285,14 @@ public:
Expr *getIndex() const { return Index; } Expr *getIndex() const { return Index; }
void setIndex(Expr *E) { Index = E; } void setIndex(Expr *E) { Index = E; }
/// Determine whether this member reference refers to the
/// superclass's property.
bool isSuper() const { return SubscriptExprBits.IsSuper; }
/// Set whether this member reference refers to the superclass's
/// property.
void setIsSuper(bool isSuper) { SubscriptExprBits.IsSuper = isSuper; }
/// Determine whether subscript operation has a known underlying /// Determine whether subscript operation has a known underlying
/// subscript declaration or not. /// subscript declaration or not.
bool hasDecl() const { return static_cast<bool>(TheDecl); } bool hasDecl() const { return static_cast<bool>(TheDecl); }

View File

@@ -1090,6 +1090,8 @@ public:
if (E->isDirectPropertyAccess()) if (E->isDirectPropertyAccess())
OS << " direct_property_access"; OS << " direct_property_access";
if (E->isSuper())
OS << " super";
OS << '\n'; OS << '\n';
printRec(E->getBase()); printRec(E->getBase());
@@ -1162,6 +1164,8 @@ public:
} }
void visitSubscriptExpr(SubscriptExpr *E) { void visitSubscriptExpr(SubscriptExpr *E) {
printCommon(E, "subscript_expr"); printCommon(E, "subscript_expr");
if (E->isSuper())
OS << " super";
OS << '\n'; OS << '\n';
printRec(E->getBase()); printRec(E->getBase());
OS << '\n'; OS << '\n';

View File

@@ -197,6 +197,7 @@ MemberRefExpr::MemberRefExpr(Expr *base, SourceLoc dotLoc,
Member(member), DotLoc(dotLoc), NameLoc(nameLoc) { Member(member), DotLoc(dotLoc), NameLoc(nameLoc) {
MemberRefExprBits.IsDirectPropertyAccess = UsesDirectPropertyAccess; MemberRefExprBits.IsDirectPropertyAccess = UsesDirectPropertyAccess;
MemberRefExprBits.IsSuper = false;
} }
ExistentialMemberRefExpr::ExistentialMemberRefExpr(Expr *Base, SourceLoc DotLoc, ExistentialMemberRefExpr::ExistentialMemberRefExpr(Expr *Base, SourceLoc DotLoc,

View File

@@ -2410,6 +2410,7 @@ static Callee getBaseAccessorFunctionRef(SILGenFunction &gen,
SILLocation loc, SILLocation loc,
SILDeclRef constant, SILDeclRef constant,
RValueSource &selfValue, RValueSource &selfValue,
bool isSuper,
CanAnyFunctionType substAccessorType) { CanAnyFunctionType substAccessorType) {
ValueDecl *decl = constant.getDecl(); ValueDecl *decl = constant.getDecl();
@@ -2420,6 +2421,10 @@ static Callee getBaseAccessorFunctionRef(SILGenFunction &gen,
// getters and setters. // getters and setters.
if (gen.SGM.requiresObjCDispatch(decl)) { if (gen.SGM.requiresObjCDispatch(decl)) {
auto self = selfValue.forceAndPeekRValue(gen).peekScalarValue(); auto self = selfValue.forceAndPeekRValue(gen).peekScalarValue();
if (isSuper)
return Callee::forSuperMethod(gen, self, constant, substAccessorType, loc);
return Callee::forClassMethod(gen, self, constant, substAccessorType, loc); return Callee::forClassMethod(gen, self, constant, substAccessorType, loc);
} }
@@ -2431,7 +2436,8 @@ emitSpecializedAccessorFunctionRef(SILGenFunction &gen,
SILLocation loc, SILLocation loc,
SILDeclRef constant, SILDeclRef constant,
ArrayRef<Substitution> substitutions, ArrayRef<Substitution> substitutions,
RValueSource &selfValue) RValueSource &selfValue,
bool isSuper)
{ {
// If the accessor is a local constant, use it. // If the accessor is a local constant, use it.
// FIXME: Can local properties ever be generic? // FIXME: Can local properties ever be generic?
@@ -2457,7 +2463,7 @@ emitSpecializedAccessorFunctionRef(SILGenFunction &gen,
// the Self type is generic. // the Self type is generic.
// FIXME: Dynamic dispatch for archetype/existential methods. // FIXME: Dynamic dispatch for archetype/existential methods.
Callee callee = getBaseAccessorFunctionRef(gen, loc, constant, selfValue, Callee callee = getBaseAccessorFunctionRef(gen, loc, constant, selfValue,
substAccessorType); isSuper, substAccessorType);
// If there are substitutions, specialize the generic accessor. // If there are substitutions, specialize the generic accessor.
// FIXME: Generic subscript operator could add another layer of // FIXME: Generic subscript operator could add another layer of
@@ -2501,6 +2507,7 @@ ManagedValue SILGenFunction::
emitGetAccessor(SILLocation loc, AbstractStorageDecl *decl, emitGetAccessor(SILLocation loc, AbstractStorageDecl *decl,
ArrayRef<Substitution> substitutions, ArrayRef<Substitution> substitutions,
RValueSource &&selfValue, RValueSource &&selfValue,
bool isSuper,
RValueSource &&subscripts, RValueSource &&subscripts,
SGFContext c) { SGFContext c) {
@@ -2509,7 +2516,8 @@ emitGetAccessor(SILLocation loc, AbstractStorageDecl *decl,
decl->usesObjCGetterAndSetter()); decl->usesObjCGetterAndSetter());
Callee getter = emitSpecializedAccessorFunctionRef(*this, loc, get, Callee getter = emitSpecializedAccessorFunctionRef(*this, loc, get,
substitutions, selfValue); substitutions, selfValue,
isSuper);
CanAnyFunctionType accessType = getter.getSubstFormalType(); CanAnyFunctionType accessType = getter.getSubstFormalType();
CallEmission emission(*this, std::move(getter)); CallEmission emission(*this, std::move(getter));
@@ -2533,6 +2541,7 @@ emitGetAccessor(SILLocation loc, AbstractStorageDecl *decl,
void SILGenFunction::emitSetAccessor(SILLocation loc, AbstractStorageDecl *decl, void SILGenFunction::emitSetAccessor(SILLocation loc, AbstractStorageDecl *decl,
ArrayRef<Substitution> substitutions, ArrayRef<Substitution> substitutions,
RValueSource &&selfValue, RValueSource &&selfValue,
bool isSuper,
RValueSource &&subscripts, RValueSource &&subscripts,
RValueSource &&setValue) { RValueSource &&setValue) {
SILDeclRef set(decl, SILDeclRef::Kind::Setter, SILDeclRef set(decl, SILDeclRef::Kind::Setter,
@@ -2540,7 +2549,8 @@ void SILGenFunction::emitSetAccessor(SILLocation loc, AbstractStorageDecl *decl,
decl->usesObjCGetterAndSetter()); decl->usesObjCGetterAndSetter());
Callee setter = emitSpecializedAccessorFunctionRef(*this, loc, set, Callee setter = emitSpecializedAccessorFunctionRef(*this, loc, set,
substitutions, selfValue); substitutions, selfValue,
isSuper);
CanAnyFunctionType accessType = setter.getSubstFormalType(); CanAnyFunctionType accessType = setter.getSubstFormalType();
CallEmission emission(*this, std::move(setter)); CallEmission emission(*this, std::move(setter));

View File

@@ -459,7 +459,7 @@ emitRValueForDecl(SILLocation loc, ConcreteDeclRef declRef, Type ncRefType,
// Global properties have no base or subscript. // Global properties have no base or subscript.
return emitGetAccessor(loc, var, return emitGetAccessor(loc, var,
ArrayRef<Substitution>(), RValueSource(), ArrayRef<Substitution>(), RValueSource(),
RValueSource(), C); /*isSuper=*/false, RValueSource(), C);
} }
// If the referenced decl isn't a VarDecl, it should be a constant of some // If the referenced decl isn't a VarDecl, it should be a constant of some
@@ -533,6 +533,7 @@ static AbstractionPattern getOrigFormalRValueType(Type formalStorageType) {
/// is designed to work with RValue ManagedValue bases that are either +0 or +1. /// is designed to work with RValue ManagedValue bases that are either +0 or +1.
ManagedValue SILGenFunction:: ManagedValue SILGenFunction::
emitRValueForPropertyLoad(SILLocation loc, ManagedValue base, emitRValueForPropertyLoad(SILLocation loc, ManagedValue base,
bool isSuper,
VarDecl *FieldDecl, VarDecl *FieldDecl,
ArrayRef<Substitution> substitutions, ArrayRef<Substitution> substitutions,
bool isDirectPropertyAccess, bool isDirectPropertyAccess,
@@ -548,7 +549,7 @@ emitRValueForPropertyLoad(SILLocation loc, ManagedValue base,
RValueSource baseRV = prepareAccessorBaseArg(loc, base, RValueSource baseRV = prepareAccessorBaseArg(loc, base,
FieldDecl->getGetter()); FieldDecl->getGetter());
return emitGetAccessor(loc, FieldDecl, substitutions, return emitGetAccessor(loc, FieldDecl, substitutions,
std::move(baseRV), RValueSource(), C); std::move(baseRV), isSuper, RValueSource(), C);
} }
assert(FieldDecl->hasStorage() && assert(FieldDecl->hasStorage() &&
@@ -1272,7 +1273,8 @@ RValue RValueEmitter::visitMemberRefExpr(MemberRefExpr *E, SGFContext C) {
// works with +0 bases correctly, we ask for them to come back. // works with +0 bases correctly, we ask for them to come back.
ManagedValue base = SGF.emitRValueAsSingleValue(E->getBase(), ManagedValue base = SGF.emitRValueAsSingleValue(E->getBase(),
SGFContext::AllowPlusZero); SGFContext::AllowPlusZero);
ManagedValue res = SGF.emitRValueForPropertyLoad(E, base, FieldDecl, ManagedValue res = SGF.emitRValueForPropertyLoad(E, base, E->isSuper(),
FieldDecl,
E->getMember().getSubstitutions(), E->getMember().getSubstitutions(),
E->isDirectPropertyAccess(), E->isDirectPropertyAccess(),
E->getType(), C); E->getType(), C);
@@ -1330,7 +1332,8 @@ RValue RValueEmitter::visitSubscriptExpr(SubscriptExpr *E, SGFContext C) {
ManagedValue MV = ManagedValue MV =
SGF.emitGetAccessor(E, decl, E->getDecl().getSubstitutions(), SGF.emitGetAccessor(E, decl, E->getDecl().getSubstitutions(),
std::move(baseRV), std::move(subscriptRV), C); std::move(baseRV), E->isSuper(),
std::move(subscriptRV), C);
return RValue(SGF, E, MV); return RValue(SGF, E, MV);
} }

View File

@@ -582,7 +582,7 @@ public:
/// Produce a singular RValue for a load from the specified property. /// Produce a singular RValue for a load from the specified property.
ManagedValue emitRValueForPropertyLoad(SILLocation loc, ManagedValue base, ManagedValue emitRValueForPropertyLoad(SILLocation loc, ManagedValue base,
VarDecl *property, bool isSuper, VarDecl *property,
ArrayRef<Substitution> substitutions, ArrayRef<Substitution> substitutions,
bool isDirectPropertyAccess, bool isDirectPropertyAccess,
Type propTy, SGFContext C); Type propTy, SGFContext C);
@@ -601,11 +601,13 @@ public:
ManagedValue emitGetAccessor(SILLocation loc, AbstractStorageDecl *decl, ManagedValue emitGetAccessor(SILLocation loc, AbstractStorageDecl *decl,
ArrayRef<Substitution> substitutions, ArrayRef<Substitution> substitutions,
RValueSource &&optionalSelfValue, RValueSource &&optionalSelfValue,
bool isSuper,
RValueSource &&optionalSubscripts, RValueSource &&optionalSubscripts,
SGFContext C); SGFContext C);
void emitSetAccessor(SILLocation loc, AbstractStorageDecl *decl, void emitSetAccessor(SILLocation loc, AbstractStorageDecl *decl,
ArrayRef<Substitution> substitutions, ArrayRef<Substitution> substitutions,
RValueSource &&optionalSelfValue, RValueSource &&optionalSelfValue,
bool isSuper,
RValueSource &&optionalSubscripts, RValueSource &&optionalSubscripts,
RValueSource &&value); RValueSource &&value);

View File

@@ -341,6 +341,7 @@ namespace {
class GetterSetterComponent : public LogicalPathComponent { class GetterSetterComponent : public LogicalPathComponent {
// The VarDecl or SubscriptDecl being get/set. // The VarDecl or SubscriptDecl being get/set.
AbstractStorageDecl *decl; AbstractStorageDecl *decl;
bool IsSuper;
std::vector<Substitution> substitutions; std::vector<Substitution> substitutions;
Expr *subscriptIndexExpr; Expr *subscriptIndexExpr;
mutable RValue origSubscripts; mutable RValue origSubscripts;
@@ -373,11 +374,13 @@ namespace {
public: public:
GetterSetterComponent(AbstractStorageDecl *decl, GetterSetterComponent(AbstractStorageDecl *decl,
bool isSuper,
ArrayRef<Substitution> substitutions, ArrayRef<Substitution> substitutions,
LValueTypeData typeData, LValueTypeData typeData,
Expr *subscriptIndexExpr = nullptr) Expr *subscriptIndexExpr = nullptr)
: LogicalPathComponent(typeData), : LogicalPathComponent(typeData),
decl(decl), decl(decl),
IsSuper(isSuper),
substitutions(substitutions.begin(), substitutions.end()), substitutions(substitutions.begin(), substitutions.end()),
subscriptIndexExpr(subscriptIndexExpr) subscriptIndexExpr(subscriptIndexExpr)
{ {
@@ -388,6 +391,7 @@ namespace {
SILLocation loc) SILLocation loc)
: LogicalPathComponent(copied.getTypeData()), : LogicalPathComponent(copied.getTypeData()),
decl(copied.decl), decl(copied.decl),
IsSuper(copied.IsSuper),
substitutions(copied.substitutions), substitutions(copied.substitutions),
subscriptIndexExpr(copied.subscriptIndexExpr), subscriptIndexExpr(copied.subscriptIndexExpr),
origSubscripts(copied.origSubscripts.copy(gen, loc)) origSubscripts(copied.origSubscripts.copy(gen, loc))
@@ -400,7 +404,7 @@ namespace {
auto args = prepareAccessorArgs(gen, loc, base, decl->getSetter()); auto args = prepareAccessorArgs(gen, loc, base, decl->getSetter());
return gen.emitSetAccessor(loc, decl, substitutions, return gen.emitSetAccessor(loc, decl, substitutions,
std::move(args.base), std::move(args.base), IsSuper,
std::move(args.subscripts), std::move(args.subscripts),
std::move(rvalue)); std::move(rvalue));
} }
@@ -410,7 +414,7 @@ namespace {
auto args = prepareAccessorArgs(gen, loc, base, decl->getGetter()); auto args = prepareAccessorArgs(gen, loc, base, decl->getGetter());
return gen.emitGetAccessor(loc, decl, substitutions, return gen.emitGetAccessor(loc, decl, substitutions,
std::move(args.base), std::move(args.base), IsSuper,
std::move(args.subscripts), c); std::move(args.subscripts), c);
} }
@@ -523,7 +527,8 @@ static LValue emitLValueForNonMemberVarDecl(SILGenFunction &gen,
substitutions = gen.buildForwardingSubstitutions(genericParams); substitutions = gen.buildForwardingSubstitutions(genericParams);
} }
lv.add<GetterSetterComponent>(var, substitutions, typeData); lv.add<GetterSetterComponent>(var, /*isSuper=*/false, substitutions,
typeData);
} }
} }
return std::move(lv); return std::move(lv);
@@ -553,8 +558,8 @@ LValue SILGenLValue::visitMemberRefExpr(MemberRefExpr *e) {
// Use the property accessors if the variable has accessors and this isn't a // Use the property accessors if the variable has accessors and this isn't a
// direct access to underlying storage. // direct access to underlying storage.
if (var->hasAccessorFunctions() && !e->isDirectPropertyAccess()) { if (var->hasAccessorFunctions() && !e->isDirectPropertyAccess()) {
lv.add<GetterSetterComponent>(var, e->getMember().getSubstitutions(), lv.add<GetterSetterComponent>(var, e->isSuper(),
typeData); e->getMember().getSubstitutions(), typeData);
return std::move(lv); return std::move(lv);
} }
@@ -597,7 +602,8 @@ LValue SILGenLValue::visitSubscriptExpr(SubscriptExpr *e) {
auto typeData = getMemberTypeData(gen, decl->getElementType(), e); auto typeData = getMemberTypeData(gen, decl->getElementType(), e);
LValue lv = visitRec(e->getBase()); LValue lv = visitRec(e->getBase());
lv.add<GetterSetterComponent>(decl, e->getDecl().getSubstitutions(), lv.add<GetterSetterComponent>(decl, e->isSuper(),
e->getDecl().getSubstitutions(),
typeData, e->getIndex()); typeData, e->getIndex());
return std::move(lv); return std::move(lv);
} }

View File

@@ -382,7 +382,7 @@ static SILBasicBlock *emitDispatchAndDestructure(SILGenFunction &gen,
for (auto &elt : np->getElements()) { for (auto &elt : np->getElements()) {
ManagedValue MV = ManagedValue::forUnmanaged(v); ManagedValue MV = ManagedValue::forUnmanaged(v);
auto Val = gen.emitRValueForPropertyLoad(loc, MV, elt.getProperty(), auto Val = gen.emitRValueForPropertyLoad(loc, MV, false, elt.getProperty(),
// FIXME: No generic substitions. // FIXME: No generic substitions.
{}, false, {}, false,
elt.getSubPattern()->getType(), elt.getSubPattern()->getType(),

View File

@@ -401,6 +401,8 @@ namespace {
auto &tc = cs.getTypeChecker(); auto &tc = cs.getTypeChecker();
auto &context = tc.Context; auto &context = tc.Context;
bool isSuper = isa<SuperRefExpr>(base->getSemanticsProvidingExpr());
Type baseTy = base->getType()->getRValueType(); Type baseTy = base->getType()->getRValueType();
// Explicit member accesses are permitted to implicitly look // Explicit member accesses are permitted to implicitly look
@@ -547,6 +549,7 @@ namespace {
= new (context) MemberRefExpr(base, dotLoc, memberRef, = new (context) MemberRefExpr(base, dotLoc, memberRef,
memberLoc, Implicit, memberLoc, Implicit,
IsDirectPropertyAccess); IsDirectPropertyAccess);
result->setIsSuper(isSuper);
// Skip the synthesized 'self' input type of the opened type. // Skip the synthesized 'self' input type of the opened type.
result->setType(simplifyType(openedType)); result->setType(simplifyType(openedType));
@@ -752,6 +755,9 @@ namespace {
auto &tc = cs.getTypeChecker(); auto &tc = cs.getTypeChecker();
auto baseTy = base->getType()->getRValueType(); auto baseTy = base->getType()->getRValueType();
// Check whether the base is 'super'.
bool isSuper = isa<SuperRefExpr>(base->getSemanticsProvidingExpr());
// Handle accesses that implicitly look through UncheckedOptional<T>. // Handle accesses that implicitly look through UncheckedOptional<T>.
if (auto objTy = cs.lookThroughUncheckedOptionalType(baseTy)) { if (auto objTy = cs.lookThroughUncheckedOptionalType(baseTy)) {
base = coerceUncheckedOptionalToValue(base, objTy, locator); base = coerceUncheckedOptionalToValue(base, objTy, locator);
@@ -844,6 +850,7 @@ namespace {
subscript, subscript,
substitutions)); substitutions));
subscriptExpr->setType(resultTy); subscriptExpr->setType(resultTy);
subscriptExpr->setIsSuper(isSuper);
return subscriptExpr; return subscriptExpr;
} }
@@ -876,6 +883,7 @@ namespace {
auto *subscriptExpr auto *subscriptExpr
= new (tc.Context) SubscriptExpr(base, index, subscript); = new (tc.Context) SubscriptExpr(base, index, subscript);
subscriptExpr->setType(resultTy); subscriptExpr->setType(resultTy);
subscriptExpr->setIsSuper(isSuper);
return subscriptExpr; return subscriptExpr;
} }