Skip to content

[AST] NFC: Create abstract class for MemberRefExpr/SubscriptExpr #16741

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
138 changes: 64 additions & 74 deletions include/swift/AST/Expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,10 @@ class alignas(8) Expr {

SWIFT_INLINE_BITFIELD_EMPTY(LiteralExpr, Expr);
SWIFT_INLINE_BITFIELD_EMPTY(IdentityExpr, Expr);
SWIFT_INLINE_BITFIELD(LookupExpr, Expr, 1,
IsSuper : 1
);
SWIFT_INLINE_BITFIELD_EMPTY(DynamicLookupExpr, LookupExpr);

SWIFT_INLINE_BITFIELD(ParenExpr, IdentityExpr, 1,
/// \brief Whether we're wrapping a trailing closure expression.
Expand All @@ -182,9 +186,8 @@ class alignas(8) Expr {
FunctionRefKind : 2
);

SWIFT_INLINE_BITFIELD(MemberRefExpr, Expr, 2+1,
Semantics : 2, // an AccessSemantics
IsSuper : 1
SWIFT_INLINE_BITFIELD(MemberRefExpr, LookupExpr, 2,
Semantics : 2 // an AccessSemantics
);

SWIFT_INLINE_BITFIELD_FULL(TupleElementExpr, Expr, 32,
Expand All @@ -210,9 +213,8 @@ class alignas(8) Expr {
FunctionRefKind : 2
);

SWIFT_INLINE_BITFIELD_FULL(SubscriptExpr, Expr, 2+1+16+1+1,
SWIFT_INLINE_BITFIELD_FULL(SubscriptExpr, LookupExpr, 2+1+1+16,
Semantics : 2, // an AccessSemantics
IsSuper : 1,
/// Whether the SubscriptExpr also has source locations for the argument
/// label.
HasArgLabelLocs : 1,
Expand All @@ -223,7 +225,7 @@ class alignas(8) Expr {
NumArgLabels : 16
);

SWIFT_INLINE_BITFIELD_FULL(DynamicSubscriptExpr, Expr, 1+1+16,
SWIFT_INLINE_BITFIELD_FULL(DynamicSubscriptExpr, DynamicLookupExpr, 1+1+16,
/// Whether the DynamicSubscriptExpr also has source locations for the
/// argument label.
HasArgLabelLocs : 1,
Expand Down Expand Up @@ -1489,47 +1491,79 @@ class UnresolvedDeclRefExpr : public Expr {
return E->getKind() == ExprKind::UnresolvedDeclRef;
}
};

/// LookupExpr - This abstract class represents 'a.b', 'a[]', etc where we
/// are referring to a member of a type, such as a property, variable, etc.
class LookupExpr : public Expr {
Expr *Base;
ConcreteDeclRef Member;

protected:
explicit LookupExpr(ExprKind Kind, Expr *base, ConcreteDeclRef member,
bool Implicit)
: Expr(Kind, Implicit), Base(base), Member(member) {
Bits.LookupExpr.IsSuper = false;
assert(Base);
}

public:
/// Retrieve the base of the expression.
Expr *getBase() const { return Base; }

/// Replace the base of the expression.
void setBase(Expr *E) { Base = E; }

/// Retrieve the member to which this access refers.
ConcreteDeclRef getMember() const { return Member; }

/// Determine whether the operation has a known underlying declaration or not.
bool hasDecl() const { return static_cast<bool>(Member); }

/// Retrieve the declaration that this /// operation refers to.
/// Only valid when \c hasDecl() is true.
ConcreteDeclRef getDecl() const {
assert(hasDecl() && "No subscript declaration known!");
return getMember();
}

/// Determine whether this reference refers to the superclass's property.
bool isSuper() const { return Bits.LookupExpr.IsSuper; }

/// Set whether this reference refers to the superclass's property.
void setIsSuper(bool isSuper) { Bits.LookupExpr.IsSuper = isSuper; }

static bool classof(const Expr *E) {
return E->getKind() >= ExprKind::First_LookupExpr &&
E->getKind() <= ExprKind::Last_LookupExpr;
}
};

/// MemberRefExpr - This represents 'a.b' where we are referring to a member
/// of a type, such as a property or variable.
///
/// Note that methods found via 'dot' syntax are expressed as DotSyntaxCallExpr
/// nodes, because 'a.f' is actually an application of 'a' (the implicit object
/// argument) to the function 'f'.
class MemberRefExpr : public Expr {
Expr *Base;
ConcreteDeclRef Member;
class MemberRefExpr : public LookupExpr {
SourceLoc DotLoc;
DeclNameLoc NameLoc;

public:
MemberRefExpr(Expr *base, SourceLoc dotLoc, ConcreteDeclRef member,
DeclNameLoc loc, bool Implicit,
AccessSemantics semantics = AccessSemantics::Ordinary);
Expr *getBase() const { return Base; }
ConcreteDeclRef getMember() const { return Member; }
DeclNameLoc getNameLoc() const { return NameLoc; }
SourceLoc getDotLoc() const { return DotLoc; }

void setBase(Expr *E) { Base = E; }
DeclNameLoc getNameLoc() const { return NameLoc; }

/// Return true if this member access is direct, meaning that it
/// does not call the getter or setter.
AccessSemantics getAccessSemantics() const {
return (AccessSemantics) Bits.MemberRefExpr.Semantics;
}

/// Determine whether this member reference refers to the
/// superclass's property.
bool isSuper() const { return Bits.MemberRefExpr.IsSuper; }

/// Set whether this member reference refers to the superclass's
/// property.
void setIsSuper(bool isSuper) { Bits.MemberRefExpr.IsSuper = isSuper; }

SourceLoc getLoc() const { return NameLoc.getBaseNameLoc(); }
SourceLoc getStartLoc() const {
SourceLoc BaseStartLoc = Base->getStartLoc();
SourceLoc BaseStartLoc = getBase()->getStartLoc();
if (BaseStartLoc.isInvalid() || NameLoc.isInvalid()) {
return NameLoc.getBaseNameLoc();
} else {
Expand All @@ -1548,24 +1582,12 @@ class MemberRefExpr : public Expr {
/// Common base for expressions that involve dynamic lookup, which
/// determines at runtime whether a particular method, property, or
/// subscript is available.
class DynamicLookupExpr : public Expr {
class DynamicLookupExpr : public LookupExpr {
protected:
Expr *Base;
ConcreteDeclRef Member;

explicit DynamicLookupExpr(ExprKind kind, ConcreteDeclRef member, Expr *base)
: Expr(kind, /*Implicit=*/false), Base(base), Member(member) { }
: LookupExpr(kind, base, member, /*Implicit=*/false) { }

public:
/// Retrieve the member to which this access refers.
ConcreteDeclRef getMember() const { return Member; }

/// Retrieve the base of the expression.
Expr *getBase() const { return Base; }

/// Replace the base of the expression.
void setBase(Expr *base) { Base = base; }

static bool classof(const Expr *E) {
return E->getKind() >= ExprKind::First_DynamicLookupExpr &&
E->getKind() <= ExprKind::Last_DynamicLookupExpr;
Expand Down Expand Up @@ -1608,7 +1630,7 @@ class DynamicMemberRefExpr : public DynamicLookupExpr {
SourceLoc getLoc() const { return NameLoc.getBaseNameLoc(); }

SourceLoc getStartLoc() const {
SourceLoc BaseStartLoc = Base->getStartLoc();
SourceLoc BaseStartLoc = getBase()->getStartLoc();
if (BaseStartLoc.isInvalid() || NameLoc.isInvalid()) {
return NameLoc.getBaseNameLoc();
} else {
Expand Down Expand Up @@ -1676,12 +1698,6 @@ class DynamicSubscriptExpr final
ConcreteDeclRef decl,
bool implicit);

/// Retrieve the base of the expression.
Expr *getBase() const { return Base; }

/// Replace the base of the expression.
void setBase(Expr *base) { Base = base; }

/// getIndex - Retrieve the index of the subscript expression, i.e., the
/// "offset" into the base value.
Expr *getIndex() const { return Index; }
Expand All @@ -1702,7 +1718,7 @@ class DynamicSubscriptExpr final

SourceLoc getLoc() const { return Index->getStartLoc(); }

SourceLoc getStartLoc() const { return Base->getStartLoc(); }
SourceLoc getStartLoc() const { return getBase()->getStartLoc(); }
SourceLoc getEndLoc() const { return Index->getEndLoc(); }

static bool classof(const Expr *E) {
Expand Down Expand Up @@ -2230,12 +2246,10 @@ class DictionaryExpr final : public CollectionExpr,
/// type-checked and well-formed subscript expression refers to a subscript
/// declaration, which provides a getter and (optionally) a setter that will
/// be used to perform reads/writes.
class SubscriptExpr final : public Expr,
class SubscriptExpr final : public LookupExpr,
public TrailingCallArguments<SubscriptExpr> {
friend TrailingCallArguments;

ConcreteDeclRef TheDecl;
Expr *Base;
Expr *Index;

SubscriptExpr(Expr *base, Expr *index, ArrayRef<Identifier> argLabels,
Expand Down Expand Up @@ -2267,11 +2281,6 @@ class SubscriptExpr final : public Expr,
AccessSemantics semantics
= AccessSemantics::Ordinary);

/// getBase - Retrieve the base of the subscript expression, i.e., the
/// value being indexed.
Expr *getBase() const { return Base; }
void setBase(Expr *E) { Base = E; }

/// getIndex - Retrieve the index of the subscript expression, i.e., the
/// "offset" into the base value.
Expr *getIndex() const { return Index; }
Expand All @@ -2296,30 +2305,11 @@ class SubscriptExpr final : public Expr,
return (AccessSemantics) Bits.SubscriptExpr.Semantics;
}

/// Determine whether this member reference refers to the
/// superclass's property.
bool isSuper() const { return Bits.SubscriptExpr.IsSuper; }

/// Set whether this member reference refers to the superclass's
/// property.
void setIsSuper(bool isSuper) { Bits.SubscriptExpr.IsSuper = isSuper; }

/// Determine whether subscript operation has a known underlying
/// subscript declaration or not.
bool hasDecl() const { return static_cast<bool>(TheDecl); }

/// Retrieve the subscript declaration that this subscripting
/// operation refers to. Only valid when \c hasDecl() is true.
ConcreteDeclRef getDecl() const {
assert(hasDecl() && "No subscript declaration known!");
return TheDecl;
}

SourceLoc getLoc() const { return Index->getStartLoc(); }
SourceLoc getStartLoc() const { return Base->getStartLoc(); }
SourceLoc getStartLoc() const { return getBase()->getStartLoc(); }
SourceLoc getEndLoc() const {
auto end = Index->getEndLoc();
return end.isValid() ? end : Base->getEndLoc();
return end.isValid() ? end : getBase()->getEndLoc();
}

static bool classof(const Expr *E) {
Expand Down
14 changes: 8 additions & 6 deletions include/swift/AST/ExprNodes.def
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,14 @@ ABSTRACT_EXPR(OverloadSetRef, Expr)
UNCHECKED_EXPR(OverloadedDeclRef, OverloadSetRefExpr)
EXPR_RANGE(OverloadSetRef, OverloadedDeclRef, OverloadedDeclRef)
UNCHECKED_EXPR(UnresolvedDeclRef, Expr)
EXPR(MemberRef, Expr)
ABSTRACT_EXPR(DynamicLookup, Expr)
EXPR(DynamicMemberRef, DynamicLookupExpr)
EXPR(DynamicSubscript, DynamicLookupExpr)
EXPR_RANGE(DynamicLookup, DynamicMemberRef, DynamicSubscript)
ABSTRACT_EXPR(Lookup, Expr)
EXPR(MemberRef, LookupExpr)
EXPR(Subscript, LookupExpr)
ABSTRACT_EXPR(DynamicLookup, LookupExpr)
EXPR(DynamicMemberRef, DynamicLookupExpr)
EXPR(DynamicSubscript, DynamicLookupExpr)
EXPR_RANGE(DynamicLookup, DynamicMemberRef, DynamicSubscript)
EXPR_RANGE(Lookup, MemberRef, DynamicSubscript)
UNCHECKED_EXPR(UnresolvedSpecialize, Expr)
UNCHECKED_EXPR(UnresolvedMember, Expr)
UNCHECKED_EXPR(UnresolvedDot, Expr)
Expand All @@ -111,7 +114,6 @@ ABSTRACT_EXPR(Collection, Expr)
EXPR(Array, CollectionExpr)
EXPR(Dictionary, CollectionExpr)
EXPR_RANGE(Collection, Array, Dictionary)
EXPR(Subscript, Expr)
EXPR(KeyPathApplication, Expr)
EXPR(TupleElement, Expr)
EXPR(CaptureList, Expr)
Expand Down
11 changes: 4 additions & 7 deletions lib/AST/Expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1342,12 +1342,10 @@ ConstructorDecl *OtherConstructorDeclRefExpr::getDecl() const {
MemberRefExpr::MemberRefExpr(Expr *base, SourceLoc dotLoc,
ConcreteDeclRef member, DeclNameLoc nameLoc,
bool Implicit, AccessSemantics semantics)
: Expr(ExprKind::MemberRef, Implicit), Base(base),
Member(member), DotLoc(dotLoc), NameLoc(nameLoc) {
: LookupExpr(ExprKind::MemberRef, base, member, Implicit),
DotLoc(dotLoc), NameLoc(nameLoc) {

Bits.MemberRefExpr.Semantics = (unsigned) semantics;
Bits.MemberRefExpr.IsSuper = false;
assert(Member);
}

Type OverloadSetRefExpr::getBaseType() const {
Expand Down Expand Up @@ -1588,10 +1586,9 @@ SubscriptExpr::SubscriptExpr(Expr *base, Expr *index,
bool hasTrailingClosure,
ConcreteDeclRef decl,
bool implicit, AccessSemantics semantics)
: Expr(ExprKind::Subscript, implicit, Type()),
TheDecl(decl), Base(base), Index(index) {
: LookupExpr(ExprKind::Subscript, base, decl, implicit),
Index(index) {
Bits.SubscriptExpr.Semantics = (unsigned) semantics;
Bits.SubscriptExpr.IsSuper = false;
Bits.SubscriptExpr.NumArgLabels = argLabels.size();
Bits.SubscriptExpr.HasArgLabelLocs = !argLabelLocs.empty();
Bits.SubscriptExpr.HasTrailingClosure = hasTrailingClosure;
Expand Down
22 changes: 2 additions & 20 deletions lib/SILGen/SILGenExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4567,30 +4567,12 @@ static bool mayLieAboutNonOptionalReturn(SILModule &M, Expr *expr) {
return mayLieAboutNonOptionalReturn(M, load->getSubExpr());
}

// A reference to a member property.
if (auto member = dyn_cast<MemberRefExpr>(expr)) {
// A reference to a potentially dynamic member/subscript property.
if (auto member = dyn_cast<LookupExpr>(expr)) {
return isVerbatimNullableTypeInC(M, member->getType()) &&
mayLieAboutNonOptionalReturn(M, member->getMember().getDecl());
}

// A reference to a subscript.
if (auto subscript = dyn_cast<SubscriptExpr>(expr)) {
return isVerbatimNullableTypeInC(M, subscript->getType()) &&
mayLieAboutNonOptionalReturn(M, subscript->getDecl().getDecl());
}

// A reference to a member property found via dynamic lookup.
if (auto member = dyn_cast<DynamicMemberRefExpr>(expr)) {
return isVerbatimNullableTypeInC(M, member->getType()) &&
mayLieAboutNonOptionalReturn(M, member->getMember().getDecl());
}

// A reference to a subscript found via dynamic lookup.
if (auto subscript = dyn_cast<DynamicSubscriptExpr>(expr)) {
return isVerbatimNullableTypeInC(M, subscript->getType()) &&
mayLieAboutNonOptionalReturn(M, subscript->getMember().getDecl());
}

return false;
}

Expand Down
10 changes: 2 additions & 8 deletions lib/Sema/CSApply.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -759,14 +759,8 @@ namespace {
return ctorRef->getArg();
} else if (auto apply = dyn_cast<ApplyExpr>(expr)) {
return apply->getFn();
} else if (auto memberRef = dyn_cast<MemberRefExpr>(expr)) {
return memberRef->getBase();
} else if (auto dynMemberRef = dyn_cast<DynamicMemberRefExpr>(expr)) {
return dynMemberRef->getBase();
} else if (auto subscriptRef = dyn_cast<SubscriptExpr>(expr)) {
return subscriptRef->getBase();
} else if (auto dynSubscriptRef = dyn_cast<DynamicSubscriptExpr>(expr)) {
return dynSubscriptRef->getBase();
} else if (auto lookupRef = dyn_cast<LookupExpr>(expr)) {
return lookupRef->getBase();
} else if (auto load = dyn_cast<LoadExpr>(expr)) {
return load->getSubExpr();
} else if (auto inout = dyn_cast<InOutExpr>(expr)) {
Expand Down