| //===--- Expr.h - Swift Language Expression ASTs ----------------*- C++ -*-===// |
| // |
| // This source file is part of the Swift.org open source project |
| // |
| // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors |
| // Licensed under Apache License v2.0 with Runtime Library Exception |
| // |
| // See https://swift.org/LICENSE.txt for license information |
| // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file defines the Expr class and subclasses. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef SWIFT_AST_EXPR_H |
| #define SWIFT_AST_EXPR_H |
| |
| #include "swift/AST/CaptureInfo.h" |
| #include "swift/AST/ConcreteDeclRef.h" |
| #include "swift/AST/DeclNameLoc.h" |
| #include "swift/AST/FunctionRefKind.h" |
| #include "swift/AST/ProtocolConformanceRef.h" |
| #include "swift/AST/TypeAlignments.h" |
| #include "swift/AST/TypeLoc.h" |
| #include "swift/AST/TypeRepr.h" |
| #include "swift/AST/Availability.h" |
| #include "swift/Basic/InlineBitfield.h" |
| #include "llvm/Support/TrailingObjects.h" |
| #include <utility> |
| |
| namespace llvm { |
| struct fltSemantics; |
| } |
| |
| namespace swift { |
| enum class AccessKind : unsigned char; |
| class ArchetypeType; |
| class ASTContext; |
| class AvailabilitySpec; |
| class Type; |
| class ValueDecl; |
| class Decl; |
| class DeclRefExpr; |
| class Pattern; |
| class SubscriptDecl; |
| class Stmt; |
| class BraceStmt; |
| class ASTWalker; |
| class Initializer; |
| class VarDecl; |
| class OpaqueValueExpr; |
| class FuncDecl; |
| class ConstructorDecl; |
| class TypeDecl; |
| class PatternBindingDecl; |
| class ParameterList; |
| class EnumElementDecl; |
| |
| enum class ExprKind : uint8_t { |
| #define EXPR(Id, Parent) Id, |
| #define LAST_EXPR(Id) Last_Expr = Id, |
| #define EXPR_RANGE(Id, FirstId, LastId) \ |
| First_##Id##Expr = FirstId, Last_##Id##Expr = LastId, |
| #include "swift/AST/ExprNodes.def" |
| }; |
| enum : unsigned { NumExprKindBits = |
| countBitsUsed(static_cast<unsigned>(ExprKind::Last_Expr)) }; |
| |
| /// Discriminates certain kinds of checked cast that have specialized diagnostic |
| /// and/or code generation peephole behavior. |
| /// |
| /// This enumeration should not have any semantic effect on the behavior of a |
| /// well-typed program, since the runtime can perform all casts that are |
| /// statically accepted. |
| enum class CheckedCastKind : unsigned { |
| /// The kind has not been determined yet. |
| Unresolved, |
| |
| /// Valid resolved kinds start here. |
| First_Resolved, |
| |
| /// The requested cast is an implicit conversion, so this is a coercion. |
| Coercion = First_Resolved, |
| /// A checked cast with no known specific behavior. |
| ValueCast, |
| // A downcast from an array type to another array type. |
| ArrayDowncast, |
| // A downcast from a dictionary type to another dictionary type. |
| DictionaryDowncast, |
| // A downcast from a set type to another set type. |
| SetDowncast, |
| /// A bridging conversion that always succeeds. |
| BridgingCoercion, |
| /// A bridging conversion that may fail, because there are multiple Swift |
| /// value types that bridge to the same Cocoa object type. |
| /// |
| /// This kind is only used for Swift 3 compatibility diagnostics and is |
| /// treated the same as 'BridgingCoercion' otherwise. In Swift 4 or later, |
| /// any conversions with this kind show up as ValueCasts. |
| Swift3BridgingDowncast, |
| |
| Last_CheckedCastKind = Swift3BridgingDowncast, |
| }; |
| |
| enum class AccessSemantics : uint8_t { |
| /// On a property or subscript reference, this is a direct access to |
| /// the underlying storage. On a function reference, this is a |
| /// non-polymorphic access to a particular implementation. |
| DirectToStorage, |
| |
| /// On a property or subscript reference, this is a direct, |
| /// non-polymorphic access to the getter/setter accessors. |
| DirectToAccessor, |
| |
| /// On a property or subscript reference, this is an access to a property |
| /// behavior that may be an initialization. Reads always go through the |
| /// 'get' accessor on the property. Writes may go through the 'init' or |
| /// 'set' logic of the behavior based on its initialization state. |
| BehaviorInitialization, |
| |
| /// This is an ordinary access to a declaration, using whatever |
| /// polymorphism is expected. |
| Ordinary, |
| }; |
| |
| /// Expr - Base class for all expressions in swift. |
| class alignas(8) Expr { |
| Expr(const Expr&) = delete; |
| void operator=(const Expr&) = delete; |
| |
| protected: |
| union { uint64_t OpaqueBits; |
| |
| SWIFT_INLINE_BITFIELD_BASE(Expr, bitmax(NumExprKindBits,8)+2+1, |
| /// The subclass of Expr that this is. |
| Kind : bitmax(NumExprKindBits,8), |
| /// How this l-value is used, if it's an l-value. |
| LValueAccessKind : 2, |
| /// Whether the Expr represents something directly written in source or |
| /// it was implicitly generated by the type-checker. |
| Implicit : 1 |
| ); |
| |
| SWIFT_INLINE_BITFIELD_FULL(CollectionExpr, Expr, 64-NumExprBits, |
| /// True if the type of this collection expr was inferred by the collection |
| /// fallback type, like [Any]. |
| IsTypeDefaulted : 1, |
| /// Number of comma source locations. |
| NumCommas : 32 - 1 - NumExprBits, |
| /// Number of entries in the collection. If this is a DictionaryLiteral, |
| /// each entry is a Tuple with the key and value pair. |
| NumSubExprs : 32 |
| ); |
| |
| SWIFT_INLINE_BITFIELD_EMPTY(LiteralExpr, Expr); |
| SWIFT_INLINE_BITFIELD_EMPTY(IdentityExpr, Expr); |
| |
| SWIFT_INLINE_BITFIELD(ParenExpr, IdentityExpr, 1, |
| /// \brief Whether we're wrapping a trailing closure expression. |
| HasTrailingClosure : 1 |
| ); |
| |
| SWIFT_INLINE_BITFIELD(NumberLiteralExpr, LiteralExpr, 1, |
| IsNegative : 1 |
| ); |
| |
| SWIFT_INLINE_BITFIELD(StringLiteralExpr, LiteralExpr, 3+1+1, |
| Encoding : 3, |
| IsSingleUnicodeScalar : 1, |
| IsSingleExtendedGraphemeCluster : 1 |
| ); |
| |
| SWIFT_INLINE_BITFIELD(DeclRefExpr, Expr, 2+2, |
| Semantics : 2, // an AccessSemantics |
| FunctionRefKind : 2 |
| ); |
| |
| SWIFT_INLINE_BITFIELD(UnresolvedDeclRefExpr, Expr, 2+2, |
| DeclRefKind : 2, |
| FunctionRefKind : 2 |
| ); |
| |
| SWIFT_INLINE_BITFIELD(MemberRefExpr, Expr, 2+1, |
| Semantics : 2, // an AccessSemantics |
| IsSuper : 1 |
| ); |
| |
| SWIFT_INLINE_BITFIELD_FULL(TupleElementExpr, Expr, 32, |
| : NumPadBits, |
| FieldNo : 32 |
| ); |
| |
| SWIFT_INLINE_BITFIELD_FULL(TupleExpr, Expr, 1+1+1+32, |
| /// Whether this tuple has a trailing closure. |
| HasTrailingClosure : 1, |
| |
| /// Whether this tuple has any labels. |
| HasElementNames : 1, |
| |
| /// Whether this tuple has label locations. |
| HasElementNameLocations : 1, |
| |
| : NumPadBits, |
| NumElements : 32 |
| ); |
| |
| SWIFT_INLINE_BITFIELD(UnresolvedDotExpr, Expr, 2, |
| FunctionRefKind : 2 |
| ); |
| |
| SWIFT_INLINE_BITFIELD_FULL(SubscriptExpr, Expr, 2+1+16+1+1, |
| Semantics : 2, // an AccessSemantics |
| IsSuper : 1, |
| /// Whether the SubscriptExpr also has source locations for the argument |
| /// label. |
| HasArgLabelLocs : 1, |
| /// Whether the last argument is a trailing closure. |
| HasTrailingClosure : 1, |
| : NumPadBits, |
| /// # of argument labels stored after the SubscriptExpr. |
| NumArgLabels : 16 |
| ); |
| |
| SWIFT_INLINE_BITFIELD_FULL(DynamicSubscriptExpr, Expr, 1+1+16, |
| /// Whether the DynamicSubscriptExpr also has source locations for the |
| /// argument label. |
| HasArgLabelLocs : 1, |
| /// Whether the last argument is a trailing closure. |
| HasTrailingClosure : 1, |
| : NumPadBits, |
| /// # of argument labels stored after the DynamicSubscriptExpr. |
| NumArgLabels : 16 |
| ); |
| |
| SWIFT_INLINE_BITFIELD_FULL(UnresolvedMemberExpr, Expr, 1+1+1+16, |
| /// Whether the UnresolvedMemberExpr has arguments. |
| HasArguments : 1, |
| /// Whether the UnresolvedMemberExpr also has source locations for the |
| /// argument label. |
| HasArgLabelLocs : 1, |
| /// Whether the last argument is a trailing closure. |
| HasTrailingClosure : 1, |
| : NumPadBits, |
| /// # of argument labels stored after the UnresolvedMemberExpr. |
| NumArgLabels : 16 |
| ); |
| |
| SWIFT_INLINE_BITFIELD(OverloadSetRefExpr, Expr, 2, |
| FunctionRefKind : 2 |
| ); |
| |
| SWIFT_INLINE_BITFIELD(BooleanLiteralExpr, LiteralExpr, 1, |
| Value : 1 |
| ); |
| |
| SWIFT_INLINE_BITFIELD(MagicIdentifierLiteralExpr, LiteralExpr, 3+1, |
| Kind : 3, |
| StringEncoding : 1 |
| ); |
| |
| SWIFT_INLINE_BITFIELD_FULL(ObjectLiteralExpr, LiteralExpr, 3+1+1+16, |
| LitKind : 3, |
| /// Whether the ObjectLiteralExpr also has source locations for the argument |
| /// label. |
| HasArgLabelLocs : 1, |
| /// Whether the last argument is a trailing closure. |
| HasTrailingClosure : 1, |
| : NumPadBits, |
| /// # of argument labels stored after the ObjectLiteralExpr. |
| NumArgLabels : 16 |
| ); |
| |
| SWIFT_INLINE_BITFIELD(AbstractClosureExpr, Expr, (16-NumExprBits)+16, |
| : 16 - NumExprBits, // Align and leave room for subclasses |
| Discriminator : 16 |
| ); |
| |
| SWIFT_INLINE_BITFIELD(ClosureExpr, AbstractClosureExpr, 1, |
| /// True if closure parameters were synthesized from anonymous closure |
| /// variables. |
| HasAnonymousClosureVars : 1 |
| ); |
| |
| SWIFT_INLINE_BITFIELD_FULL(BindOptionalExpr, Expr, 16, |
| : NumPadBits, |
| Depth : 16 |
| ); |
| |
| SWIFT_INLINE_BITFIELD_EMPTY(ImplicitConversionExpr, Expr); |
| |
| SWIFT_INLINE_BITFIELD_FULL(TupleShuffleExpr, ImplicitConversionExpr, 2+16+16+16, |
| TypeImpact : 2, |
| : NumPadBits, |
| NumCallerDefaultArgs : 16, |
| /// This contains an entry for each element in the Expr type. Each element |
| /// specifies which index from the SubExpr that the destination element gets. |
| /// If the element value is DefaultInitialize, then the destination value |
| /// gets the default initializer for that tuple element value. |
| NumElementMappings : 16, |
| /// The arguments that are packed into the variadic element. |
| NumVariadicArgs : 16 |
| ); |
| |
| SWIFT_INLINE_BITFIELD(ForceValueExpr, Expr, 1, |
| ForcedIUO : 1 |
| ); |
| |
| SWIFT_INLINE_BITFIELD(InOutToPointerExpr, ImplicitConversionExpr, 1, |
| IsNonAccessing : 1 |
| ); |
| |
| SWIFT_INLINE_BITFIELD(ArrayToPointerExpr, ImplicitConversionExpr, 1, |
| IsNonAccessing : 1 |
| ); |
| |
| SWIFT_INLINE_BITFIELD_FULL(ErasureExpr, ImplicitConversionExpr, 32, |
| : NumPadBits, |
| NumConformances : 32 |
| ); |
| |
| SWIFT_INLINE_BITFIELD_FULL(UnresolvedSpecializeExpr, Expr, 32, |
| : NumPadBits, |
| NumUnresolvedParams : 32 |
| ); |
| |
| SWIFT_INLINE_BITFIELD_FULL(CaptureListExpr, Expr, 32, |
| : NumPadBits, |
| NumCaptures : 32 |
| ); |
| |
| SWIFT_INLINE_BITFIELD(ApplyExpr, Expr, 1+1, |
| ThrowsIsSet : 1, |
| Throws : 1 |
| ); |
| |
| SWIFT_INLINE_BITFIELD_FULL(CallExpr, ApplyExpr, 1+1+16, |
| /// Whether the CallExpr also has source locations for the argument label. |
| HasArgLabelLocs : 1, |
| /// Whether the last argument is a trailing closure. |
| HasTrailingClosure : 1, |
| : NumPadBits, |
| /// # of argument labels stored after the CallExpr. |
| NumArgLabels : 16 |
| ); |
| |
| enum { NumCheckedCastKindBits = 4 }; |
| SWIFT_INLINE_BITFIELD(CheckedCastExpr, Expr, NumCheckedCastKindBits, |
| CastKind : NumCheckedCastKindBits |
| ); |
| static_assert(unsigned(CheckedCastKind::Last_CheckedCastKind) |
| < (1 << NumCheckedCastKindBits), |
| "unable to fit a CheckedCastKind in the given number of bits"); |
| |
| SWIFT_INLINE_BITFIELD_EMPTY(CollectionUpcastConversionExpr, Expr); |
| |
| SWIFT_INLINE_BITFIELD(ObjCSelectorExpr, Expr, 2, |
| /// The selector kind. |
| SelectorKind : 2 |
| ); |
| |
| SWIFT_INLINE_BITFIELD(KeyPathExpr, Expr, 1, |
| /// Whether this is an ObjC stringified keypath. |
| IsObjC : 1 |
| ); |
| |
| SWIFT_INLINE_BITFIELD_FULL(SequenceExpr, Expr, 32, |
| : NumPadBits, |
| NumElements : 32 |
| ); |
| |
| } Bits; |
| |
| private: |
| /// Ty - This is the type of the expression. |
| Type Ty; |
| |
| void setLValueAccessKind(AccessKind accessKind) { |
| Bits.Expr.LValueAccessKind = unsigned(accessKind) + 1; |
| } |
| |
| protected: |
| Expr(ExprKind Kind, bool Implicit, Type Ty = Type()) : Ty(Ty) { |
| Bits.OpaqueBits = 0; |
| Bits.Expr.Kind = unsigned(Kind); |
| Bits.Expr.Implicit = Implicit; |
| Bits.Expr.LValueAccessKind = 0; |
| } |
| |
| public: |
| /// Return the kind of this expression. |
| ExprKind getKind() const { return ExprKind(Bits.Expr.Kind); } |
| |
| /// \brief Retrieve the name of the given expression kind. |
| /// |
| /// This name should only be used for debugging dumps and other |
| /// developer aids, and should never be part of a diagnostic or exposed |
| /// to the user of the compiler in any way. |
| static StringRef getKindName(ExprKind K); |
| |
| /// getType - Return the type of this expression. |
| Type getType() const { return Ty; } |
| |
| /// setType - Sets the type of this expression. |
| void setType(Type T); |
| |
| /// \brief Return the source range of the expression. |
| SourceRange getSourceRange() const; |
| |
| /// getStartLoc - Return the location of the start of the expression. |
| SourceLoc getStartLoc() const; |
| |
| /// \brief Retrieve the location of the last token of the expression. |
| SourceLoc getEndLoc() const; |
| |
| /// getLoc - Return the caret location of this expression. |
| SourceLoc getLoc() const; |
| |
| #define SWIFT_FORWARD_SOURCE_LOCS_TO(SUBEXPR) \ |
| SourceLoc getStartLoc() const { return (SUBEXPR)->getStartLoc(); } \ |
| SourceLoc getEndLoc() const { return (SUBEXPR)->getEndLoc(); } \ |
| SourceLoc getLoc() const { return (SUBEXPR)->getLoc(); } \ |
| SourceRange getSourceRange() const { return (SUBEXPR)->getSourceRange(); } |
| |
| SourceLoc TrailingSemiLoc; |
| |
| /// getSemanticsProvidingExpr - Find the smallest subexpression |
| /// which obeys the property that evaluating it is exactly |
| /// equivalent to evaluating this expression. |
| /// |
| /// Looks through parentheses. Would not look through something |
| /// like '(foo(), x:bar(), baz()).x'. |
| Expr *getSemanticsProvidingExpr(); |
| |
| const Expr *getSemanticsProvidingExpr() const { |
| return const_cast<Expr *>(this)->getSemanticsProvidingExpr(); |
| } |
| |
| /// getValueProvidingExpr - Find the smallest subexpression which is |
| /// responsible for generating the value of this expression. |
| /// Evaluating the result is not necessarily equivalent to |
| /// evaluating this expression because of potential missing |
| /// side-effects (which may influence the returned value). |
| Expr *getValueProvidingExpr(); |
| |
| const Expr *getValueProvidingExpr() const { |
| return const_cast<Expr *>(this)->getValueProvidingExpr(); |
| } |
| |
| /// If this is a reference to an operator written as a member of a type (or |
| /// extension thereof), return the underlying operator reference. |
| DeclRefExpr *getMemberOperatorRef(); |
| |
| /// This recursively walks the AST rooted at this expression. |
| Expr *walk(ASTWalker &walker); |
| Expr *walk(ASTWalker &&walker) { return walk(walker); } |
| |
| /// Enumerate each immediate child expression of this node, invoking the |
| /// specific functor on it. This ignores statements and other non-expression |
| /// children. |
| void forEachImmediateChildExpr(llvm::function_ref<Expr *(Expr *)> callback); |
| |
| /// Enumerate each expr node within this expression subtree, invoking the |
| /// specific functor on it. This ignores statements and other non-expression |
| /// children, and if there is a closure within the expression, this does not |
| /// walk into the body of it (unless it is single-expression). |
| void forEachChildExpr(llvm::function_ref<Expr *(Expr *)> callback); |
| |
| /// Determine whether this expression refers to a type by name. |
| /// |
| /// This distinguishes static references to types, like Int, from metatype |
| /// values, "someTy: Any.Type". |
| bool isTypeReference(llvm::function_ref<Type(const Expr *)> getType = |
| [](const Expr *E) -> Type { |
| return E->getType(); |
| }) const; |
| |
| /// Determine whether this expression refers to a statically-derived metatype. |
| /// |
| /// This implies `isTypeReference`, but also requires that the referenced type |
| /// is not an archetype or dependent type. |
| bool isStaticallyDerivedMetatype( |
| llvm::function_ref<Type(const Expr *)> getType = |
| [](const Expr *E) -> Type { return E->getType(); }) const; |
| |
| /// isImplicit - Determines whether this expression was implicitly-generated, |
| /// rather than explicitly written in the AST. |
| bool isImplicit() const { |
| return Bits.Expr.Implicit; |
| } |
| void setImplicit(bool Implicit = true) { |
| Bits.Expr.Implicit = Implicit; |
| } |
| |
| /// getLValueAccessKind - Determines how this l-value expression is used. |
| AccessKind getLValueAccessKind() const { |
| assert(hasLValueAccessKind()); |
| return AccessKind(Bits.Expr.LValueAccessKind - 1); |
| } |
| bool hasLValueAccessKind() const { |
| return Bits.Expr.LValueAccessKind != 0; |
| } |
| void clearLValueAccessKind() { |
| Bits.Expr.LValueAccessKind = 0; |
| } |
| |
| /// Set that this l-value expression is used in the given way. |
| /// |
| /// This information is also correctly propagated to any l-value |
| /// sub-expressions from which this l-value is derived. |
| /// |
| /// \param allowOverwrite - true if it's okay if an expression already |
| /// has an access kind |
| void propagateLValueAccessKind(AccessKind accessKind, |
| llvm::function_ref<Type(Expr *)> getType |
| = [](Expr *E) -> Type { |
| return E->getType(); |
| }, |
| bool allowOverwrite = false); |
| |
| /// Retrieves the declaration that is being referenced by this |
| /// expression, if any. |
| ConcreteDeclRef getReferencedDecl() const; |
| |
| /// Determine whether this expression is 'super', possibly converted to |
| /// a base class. |
| bool isSuperExpr() const; |
| |
| /// Returns whether the semantically meaningful content of this expression is |
| /// an inout expression. |
| /// |
| /// FIXME(Remove InOutType): This should eventually sub-in for |
| /// 'E->getType()->is<InOutType>()' in all cases. |
| bool isSemanticallyInOutExpr() const { |
| return getSemanticsProvidingExpr()->getKind() == ExprKind::InOut; |
| } |
| |
| /// Returns false if this expression needs to be wrapped in parens when |
| /// used inside of a any postfix expression, true otherwise. |
| /// |
| /// \param appendingPostfixOperator if the expression being |
| /// appended is a postfix operator like '!' or '?'. |
| bool canAppendPostfixExpression(bool appendingPostfixOperator = false) const; |
| |
| /// Returns true if this is an infix operator of some sort, including |
| /// a builtin operator. |
| bool isInfixOperator() const; |
| |
| /// Produce a mapping from each subexpression to its parent |
| /// expression, with the provided expression serving as the root of |
| /// the parent map. |
| llvm::DenseMap<Expr *, Expr *> getParentMap(); |
| |
| /// Produce a mapping from each subexpression to its depth in the root |
| /// expression. The root expression has depth 0, its children have depth |
| /// 1, etc. |
| llvm::DenseMap<Expr *, unsigned> getDepthMap(); |
| |
| /// Produce a mapping from each expression to its index according to a |
| /// preorder traversal of the expressions. The parent has index 0, its first |
| /// child has index 1, its second child has index 2 if the first child is a |
| /// leaf node, etc. |
| llvm::DenseMap<Expr *, unsigned> getPreorderIndexMap(); |
| |
| LLVM_ATTRIBUTE_DEPRECATED( |
| void dump() const LLVM_ATTRIBUTE_USED, |
| "only for use within the debugger"); |
| LLVM_ATTRIBUTE_DEPRECATED( |
| void dump(llvm::function_ref<Type(const Expr *)> getType, |
| llvm::function_ref<Type(const TypeLoc &)> getTypeOfTypeLoc) |
| const LLVM_ATTRIBUTE_USED, |
| "only for use within the debugger"); |
| LLVM_ATTRIBUTE_DEPRECATED( |
| void dump(raw_ostream &OS, llvm::function_ref<Type(const Expr *)> getType, |
| llvm::function_ref<Type(const TypeLoc &)> getTypeOfTypeLoc) |
| const LLVM_ATTRIBUTE_USED, |
| "only for use within the debugger"); |
| |
| void dump(raw_ostream &OS) const; |
| void print(raw_ostream &OS, unsigned Indent = 0) const; |
| void print(raw_ostream &OS, llvm::function_ref<Type(const Expr *)> getType, |
| llvm::function_ref<Type(const TypeLoc &)> getTypeOfTypeLoc, |
| unsigned Indent = 0) const; |
| void print(ASTPrinter &Printer, const PrintOptions &Opts) const; |
| |
| // Only allow allocation of Exprs using the allocator in ASTContext |
| // or by doing a placement new. |
| void *operator new(size_t Bytes, ASTContext &C, |
| unsigned Alignment = alignof(Expr)); |
| |
| // Make placement new and vanilla new/delete illegal for Exprs. |
| void *operator new(size_t Bytes) throw() = delete; |
| void operator delete(void *Data) throw() = delete; |
| |
| void *operator new(size_t Bytes, void *Mem) { |
| assert(Mem); |
| return Mem; |
| } |
| }; |
| |
| /// Helper class to capture trailing call argument labels and related |
| /// information, for expression nodes that involve argument labels, trailing |
| /// closures, etc. |
| template<typename Derived> |
| class TrailingCallArguments |
| : private llvm::TrailingObjects<Derived, Identifier, SourceLoc> { |
| // We need to friend TrailingObjects twice here to work around an MSVC bug. |
| // If we have two functions of the same name with the parameter |
| // typename TrailingObjectsIdentifier::template OverloadToken<T> where T is |
| // different for each function, then MSVC reports a "member function already |
| // defined or declared" error, which is incorrect. |
| using TrailingObjectsIdentifier = llvm::TrailingObjects<Derived, Identifier>; |
| friend TrailingObjectsIdentifier; |
| |
| using TrailingObjects = llvm::TrailingObjects<Derived, Identifier, SourceLoc>; |
| friend TrailingObjects; |
| |
| Derived &asDerived() { |
| return *static_cast<Derived *>(this); |
| } |
| |
| const Derived &asDerived() const { |
| return *static_cast<const Derived *>(this); |
| } |
| |
| size_t numTrailingObjects( |
| typename TrailingObjectsIdentifier::template OverloadToken<Identifier>) |
| const { |
| return asDerived().getNumArguments(); |
| } |
| |
| size_t numTrailingObjects( |
| typename TrailingObjectsIdentifier::template OverloadToken<SourceLoc>) |
| const { |
| return asDerived().hasArgumentLabelLocs() ? asDerived().getNumArguments() |
| : 0; |
| } |
| |
| /// Retrieve the buffer containing the argument labels. |
| MutableArrayRef<Identifier> getArgumentLabelsBuffer() { |
| return { this->template getTrailingObjects<Identifier>(), |
| asDerived().getNumArguments() }; |
| } |
| |
| /// Retrieve the buffer containing the argument label locations. |
| MutableArrayRef<SourceLoc> getArgumentLabelLocsBuffer() { |
| if (!asDerived().hasArgumentLabelLocs()) |
| return { }; |
| |
| return { this->template getTrailingObjects<SourceLoc>(), |
| asDerived().getNumArguments() }; |
| } |
| |
| protected: |
| /// Determine the total size to allocate. |
| static size_t totalSizeToAlloc(ArrayRef<Identifier> argLabels, |
| ArrayRef<SourceLoc> argLabelLocs, |
| bool hasTrailingClosure) { |
| return TrailingObjects::template totalSizeToAlloc<Identifier, SourceLoc>( |
| argLabels.size(), argLabelLocs.size()); |
| } |
| |
| /// Initialize the actual call arguments. |
| void initializeCallArguments(ArrayRef<Identifier> argLabels, |
| ArrayRef<SourceLoc> argLabelLocs, |
| bool hasTrailingClosure) { |
| if (!argLabels.empty()) { |
| std::uninitialized_copy(argLabels.begin(), argLabels.end(), |
| this->template getTrailingObjects<Identifier>()); |
| } |
| |
| if (!argLabelLocs.empty()) |
| std::uninitialized_copy(argLabelLocs.begin(), argLabelLocs.end(), |
| this->template getTrailingObjects<SourceLoc>()); |
| } |
| |
| public: |
| /// Retrieve the argument labels provided at the call site. |
| ArrayRef<Identifier> getArgumentLabels() const { |
| return { this->template getTrailingObjects<Identifier>(), |
| asDerived().getNumArguments() }; |
| } |
| |
| /// Retrieve the buffer containing the argument label locations. |
| ArrayRef<SourceLoc> getArgumentLabelLocs() const { |
| if (!asDerived().hasArgumentLabelLocs()) |
| return { }; |
| |
| return { this->template getTrailingObjects<SourceLoc>(), |
| asDerived().getNumArguments() }; |
| } |
| |
| /// Retrieve the location of the ith argument label. |
| SourceLoc getArgumentLabelLoc(unsigned i) const { |
| auto locs = getArgumentLabelLocs(); |
| return i < locs.size() ? locs[i] : SourceLoc(); |
| } |
| }; |
| |
| /// ErrorExpr - Represents a semantically erroneous subexpression in the AST, |
| /// typically this will have an ErrorType. |
| class ErrorExpr : public Expr { |
| SourceRange Range; |
| public: |
| ErrorExpr(SourceRange Range, Type Ty = Type()) |
| : Expr(ExprKind::Error, /*Implicit=*/true, Ty), Range(Range) {} |
| |
| SourceRange getSourceRange() const { return Range; } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::Error; |
| } |
| }; |
| |
| /// CodeCompletionExpr - Represents the code completion token in the AST, this |
| /// can help us preserve the context of the code completion position. |
| class CodeCompletionExpr : public Expr { |
| SourceRange Range; |
| bool Activated; |
| |
| public: |
| CodeCompletionExpr(SourceRange Range, Type Ty = Type()) : |
| Expr(ExprKind::CodeCompletion, /*Implicit=*/true, Ty), |
| Range(Range) { |
| Activated = false; |
| } |
| |
| SourceRange getSourceRange() const { return Range; } |
| |
| bool isActivated() const { return Activated; } |
| void setActivated() { Activated = true; } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::CodeCompletion; |
| } |
| }; |
| |
| /// LiteralExpr - Common base class between the literals. |
| class LiteralExpr : public Expr { |
| public: |
| LiteralExpr(ExprKind Kind, bool Implicit) : Expr(Kind, Implicit) {} |
| |
| // Make an exact copy of this one AST node. |
| LiteralExpr * |
| shallowClone(ASTContext &Ctx, |
| llvm::function_ref<void(Expr *, Type)> setType, |
| llvm::function_ref<Type(const Expr *)> getType) const; |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() >= ExprKind::First_LiteralExpr && |
| E->getKind() <= ExprKind::Last_LiteralExpr; |
| } |
| }; |
| |
| /// \brief The 'nil' literal. |
| /// |
| class NilLiteralExpr : public LiteralExpr { |
| SourceLoc Loc; |
| public: |
| NilLiteralExpr(SourceLoc Loc, bool Implicit = false) |
| : LiteralExpr(ExprKind::NilLiteral, Implicit), Loc(Loc) { |
| } |
| |
| SourceRange getSourceRange() const { |
| return Loc; |
| } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::NilLiteral; |
| } |
| }; |
| |
| /// \brief Abstract base class for numeric literals, potentially with a sign. |
| class NumberLiteralExpr : public LiteralExpr { |
| /// The value of the literal as an ASTContext-owned string. Underscores must |
| /// be stripped. |
| StringRef Val; // Use StringRef instead of APInt or APFloat, which leak. |
| |
| protected: |
| SourceLoc MinusLoc; |
| SourceLoc DigitsLoc; |
| |
| public: |
| NumberLiteralExpr(ExprKind Kind, |
| StringRef Val, SourceLoc DigitsLoc, bool Implicit) |
| : LiteralExpr(Kind, Implicit), Val(Val), DigitsLoc(DigitsLoc) |
| { |
| Bits.NumberLiteralExpr.IsNegative = false; |
| } |
| |
| bool isNegative() const { return Bits.NumberLiteralExpr.IsNegative; } |
| void setNegative(SourceLoc Loc) { |
| MinusLoc = Loc; |
| Bits.NumberLiteralExpr.IsNegative = true; |
| } |
| |
| StringRef getDigitsText() const { return Val; } |
| |
| SourceRange getSourceRange() const { |
| if (isNegative()) |
| return { MinusLoc, DigitsLoc }; |
| else |
| return DigitsLoc; |
| } |
| |
| SourceLoc getMinusLoc() const { |
| return MinusLoc; |
| } |
| |
| SourceLoc getDigitsLoc() const { |
| return DigitsLoc; |
| } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() >= ExprKind::First_NumberLiteralExpr |
| && E->getKind() <= ExprKind::Last_NumberLiteralExpr; |
| } |
| }; |
| |
| |
| /// \brief Integer literal with a '+' or '-' sign, like '+4' or '- 2'. |
| /// |
| /// After semantic analysis assigns types, this is guaranteed to only have |
| /// a BuiltinIntegerType. |
| class IntegerLiteralExpr : public NumberLiteralExpr { |
| public: |
| IntegerLiteralExpr(StringRef Val, SourceLoc DigitsLoc, bool Implicit = false) |
| : NumberLiteralExpr(ExprKind::IntegerLiteral, |
| Val, DigitsLoc, Implicit) |
| {} |
| |
| APInt getValue() const; |
| static APInt getValue(StringRef Text, unsigned BitWidth, bool Negative); |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::IntegerLiteral; |
| } |
| }; |
| |
| /// FloatLiteralExpr - Floating point literal, like '4.0'. After semantic |
| /// analysis assigns types, this is guaranteed to only have a |
| /// BuiltinFloatingPointType. |
| class FloatLiteralExpr : public NumberLiteralExpr { |
| public: |
| FloatLiteralExpr(StringRef Val, SourceLoc Loc, bool Implicit = false) |
| : NumberLiteralExpr(ExprKind::FloatLiteral, Val, Loc, Implicit) |
| {} |
| |
| APFloat getValue() const; |
| static APFloat getValue(StringRef Text, const llvm::fltSemantics &Semantics, |
| bool Negative); |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::FloatLiteral; |
| } |
| }; |
| |
| /// \brief A Boolean literal ('true' or 'false') |
| /// |
| class BooleanLiteralExpr : public LiteralExpr { |
| SourceLoc Loc; |
| |
| public: |
| BooleanLiteralExpr(bool Value, SourceLoc Loc, bool Implicit = false) |
| : LiteralExpr(ExprKind::BooleanLiteral, Implicit), Loc(Loc) { |
| Bits.BooleanLiteralExpr.Value = Value; |
| } |
| |
| /// Retrieve the Boolean value of this literal. |
| bool getValue() const { return Bits.BooleanLiteralExpr.Value; } |
| |
| SourceRange getSourceRange() const { |
| return Loc; |
| } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::BooleanLiteral; |
| } |
| }; |
| |
| /// StringLiteralExpr - String literal, like '"foo"'. |
| class StringLiteralExpr : public LiteralExpr { |
| StringRef Val; |
| SourceRange Range; |
| ConcreteDeclRef BuiltinInitializer; |
| ConcreteDeclRef Initializer; |
| |
| public: |
| /// The encoding that should be used for the string literal. |
| enum Encoding : unsigned { |
| /// A UTF-8 string. |
| UTF8, |
| |
| /// A UTF-16 string. |
| UTF16, |
| |
| /// A UTF-8 constant string. |
| UTF8ConstString, |
| |
| /// A UTF-16 constant string. |
| UTF16ConstString, |
| |
| /// A single UnicodeScalar, passed as an integer. |
| OneUnicodeScalar |
| }; |
| |
| StringLiteralExpr(StringRef Val, SourceRange Range, bool Implicit = false); |
| |
| StringRef getValue() const { return Val; } |
| SourceRange getSourceRange() const { return Range; } |
| |
| /// Determine the encoding that should be used for this string literal. |
| Encoding getEncoding() const { |
| return static_cast<Encoding>(Bits.StringLiteralExpr.Encoding); |
| } |
| |
| /// Set the encoding that should be used for this string literal. |
| void setEncoding(Encoding encoding) { |
| Bits.StringLiteralExpr.Encoding = static_cast<unsigned>(encoding); |
| } |
| |
| bool isSingleUnicodeScalar() const { |
| return Bits.StringLiteralExpr.IsSingleUnicodeScalar; |
| } |
| |
| bool isSingleExtendedGraphemeCluster() const { |
| return Bits.StringLiteralExpr.IsSingleExtendedGraphemeCluster; |
| } |
| |
| /// Retrieve the builtin initializer that will be used to construct the string |
| /// literal. |
| /// |
| /// Any type-checked string literal will have a builtin initializer, which is |
| /// called first to form a concrete Swift type. |
| ConcreteDeclRef getBuiltinInitializer() const { return BuiltinInitializer; } |
| |
| /// Set the builtin initializer that will be used to construct the string |
| /// literal. |
| void setBuiltinInitializer(ConcreteDeclRef builtinInitializer) { |
| BuiltinInitializer = builtinInitializer; |
| } |
| |
| /// Retrieve the initializer that will be used to construct the string |
| /// literal from the result of the initializer. |
| /// |
| /// Only string literals that have no builtin literal conformance will have |
| /// this initializer, which will be called on the result of the builtin |
| /// initializer. |
| ConcreteDeclRef getInitializer() const { return Initializer; } |
| |
| /// Set the initializer that will be used to construct the string literal. |
| void setInitializer(ConcreteDeclRef initializer) { |
| Initializer = initializer; |
| } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::StringLiteral; |
| } |
| }; |
| |
| /// InterpolatedStringLiteral - An interpolated string literal. |
| /// |
| /// An interpolated string literal mixes expressions (which are evaluated and |
| /// converted into string form) within a string literal. |
| /// |
| /// \code |
| /// "[\(min)..\(max)]" |
| /// \endcode |
| class InterpolatedStringLiteralExpr : public LiteralExpr { |
| /// Points at the beginning quote. |
| SourceLoc Loc; |
| MutableArrayRef<Expr *> Segments; |
| Expr *SemanticExpr; |
| |
| public: |
| InterpolatedStringLiteralExpr(SourceLoc Loc, MutableArrayRef<Expr *> Segments) |
| : LiteralExpr(ExprKind::InterpolatedStringLiteral, /*Implicit=*/false), |
| Loc(Loc), Segments(Segments), SemanticExpr() { } |
| |
| MutableArrayRef<Expr *> getSegments() { return Segments; } |
| ArrayRef<Expr *> getSegments() const { return Segments; } |
| |
| /// \brief Retrieve the expression that actually evaluates the resulting |
| /// string, typically with a series of '+' operations. |
| Expr *getSemanticExpr() const { return SemanticExpr; } |
| void setSemanticExpr(Expr *SE) { SemanticExpr = SE; } |
| |
| SourceLoc getStartLoc() const { |
| return Loc; |
| } |
| SourceLoc getEndLoc() const { |
| // SourceLocs are token based, and the interpolated string is one string |
| // token, so the range should be (Start == End). |
| return Loc; |
| } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::InterpolatedStringLiteral; |
| } |
| }; |
| |
| /// MagicIdentifierLiteralExpr - A magic identifier like #file which expands |
| /// out to a literal at SILGen time. |
| class MagicIdentifierLiteralExpr : public LiteralExpr { |
| public: |
| enum Kind : unsigned { |
| File, Line, Column, Function, DSOHandle |
| }; |
| private: |
| SourceLoc Loc; |
| ConcreteDeclRef BuiltinInitializer; |
| ConcreteDeclRef Initializer; |
| |
| public: |
| MagicIdentifierLiteralExpr(Kind kind, SourceLoc loc, bool implicit = false) |
| : LiteralExpr(ExprKind::MagicIdentifierLiteral, implicit), Loc(loc) { |
| Bits.MagicIdentifierLiteralExpr.Kind = static_cast<unsigned>(kind); |
| Bits.MagicIdentifierLiteralExpr.StringEncoding |
| = static_cast<unsigned>(StringLiteralExpr::UTF8); |
| } |
| |
| Kind getKind() const { |
| return static_cast<Kind>(Bits.MagicIdentifierLiteralExpr.Kind); |
| } |
| |
| bool isFile() const { return getKind() == File; } |
| bool isFunction() const { return getKind() == Function; } |
| bool isLine() const { return getKind() == Line; } |
| bool isColumn() const { return getKind() == Column; } |
| |
| bool isString() const { |
| switch (getKind()) { |
| case File: |
| case Function: |
| return true; |
| case Line: |
| case Column: |
| case DSOHandle: |
| return false; |
| } |
| llvm_unreachable("bad Kind"); |
| } |
| |
| SourceRange getSourceRange() const { return Loc; } |
| |
| // For a magic identifier that produces a string literal, retrieve the |
| // encoding for that string literal. |
| StringLiteralExpr::Encoding getStringEncoding() const { |
| assert(isString() && "Magic identifier literal has non-string encoding"); |
| return static_cast<StringLiteralExpr::Encoding>( |
| Bits.MagicIdentifierLiteralExpr.StringEncoding); |
| } |
| |
| // For a magic identifier that produces a string literal, set the encoding |
| // for the string literal. |
| void setStringEncoding(StringLiteralExpr::Encoding encoding) { |
| assert(isString() && "Magic identifier literal has non-string encoding"); |
| Bits.MagicIdentifierLiteralExpr.StringEncoding |
| = static_cast<unsigned>(encoding); |
| } |
| |
| /// Retrieve the builtin initializer that will be used to construct the string |
| /// literal. |
| /// |
| /// Any type-checked string literal will have a builtin initializer, which is |
| /// called first to form a concrete Swift type. |
| ConcreteDeclRef getBuiltinInitializer() const { |
| assert(isString() && "Magic identifier literal is not a string"); |
| return BuiltinInitializer; |
| } |
| |
| /// Set the builtin initializer that will be used to construct the string |
| /// literal. |
| void setBuiltinInitializer(ConcreteDeclRef builtinInitializer) { |
| assert(isString() && "Magic identifier literal is not a string"); |
| BuiltinInitializer = builtinInitializer; |
| } |
| |
| /// Retrieve the initializer that will be used to construct the string |
| /// literal from the result of the initializer. |
| /// |
| /// Only string literals that have no builtin literal conformance will have |
| /// this initializer, which will be called on the result of the builtin |
| /// initializer. |
| ConcreteDeclRef getInitializer() const { |
| assert(isString() && "Magic identifier literal is not a string"); |
| return Initializer; |
| } |
| |
| /// Set the initializer that will be used to construct the string literal. |
| void setInitializer(ConcreteDeclRef initializer) { |
| assert(isString() && "Magic identifier literal is not a string"); |
| Initializer = initializer; |
| } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::MagicIdentifierLiteral; |
| } |
| }; |
| |
| // ObjectLiteralExpr - An expression of the form |
| // '#colorLiteral(red: 1, blue: 0, green: 0, alpha: 1)' with a name and a list |
| // argument. The components of the list argument are meant to be themselves |
| // constant. |
| class ObjectLiteralExpr final |
| : public LiteralExpr, |
| public TrailingCallArguments<ObjectLiteralExpr> { |
| public: |
| /// The kind of object literal. |
| enum LiteralKind : unsigned { |
| #define POUND_OBJECT_LITERAL(Name, Desc, Proto) Name, |
| #include "swift/Syntax/TokenKinds.def" |
| }; |
| |
| private: |
| Expr *Arg; |
| Expr *SemanticExpr; |
| SourceLoc PoundLoc; |
| |
| ObjectLiteralExpr(SourceLoc PoundLoc, LiteralKind LitKind, |
| Expr *Arg, |
| ArrayRef<Identifier> argLabels, |
| ArrayRef<SourceLoc> argLabelLocs, |
| bool hasTrailingClosure, |
| bool implicit); |
| |
| public: |
| /// Create a new object literal expression. |
| /// |
| /// Note: prefer to use the second entry point, which separates out |
| /// arguments/labels/etc. |
| static ObjectLiteralExpr * |
| create(ASTContext &ctx, SourceLoc poundLoc, LiteralKind kind, Expr *arg, |
| bool implicit, llvm::function_ref<Type(const Expr *)> getType); |
| |
| /// Create a new object literal expression. |
| static ObjectLiteralExpr *create(ASTContext &ctx, SourceLoc poundLoc, |
| LiteralKind kind, |
| SourceLoc lParenLoc, |
| ArrayRef<Expr *> args, |
| ArrayRef<Identifier> argLabels, |
| ArrayRef<SourceLoc> argLabelLocs, |
| SourceLoc rParenLoc, |
| Expr *trailingClosure, |
| bool implicit); |
| |
| LiteralKind getLiteralKind() const { |
| return static_cast<LiteralKind>(Bits.ObjectLiteralExpr.LitKind); |
| } |
| |
| Expr *getArg() const { return Arg; } |
| void setArg(Expr *arg) { Arg = arg; } |
| |
| unsigned getNumArguments() const { |
| return Bits.ObjectLiteralExpr.NumArgLabels; |
| } |
| bool hasArgumentLabelLocs() const { |
| return Bits.ObjectLiteralExpr.HasArgLabelLocs; |
| } |
| |
| /// Whether this call with written with a trailing closure. |
| bool hasTrailingClosure() const { |
| return Bits.ObjectLiteralExpr.HasTrailingClosure; |
| } |
| |
| Expr *getSemanticExpr() const { return SemanticExpr; } |
| void setSemanticExpr(Expr *expr) { SemanticExpr = expr; } |
| |
| SourceLoc getSourceLoc() const { return PoundLoc; } |
| SourceRange getSourceRange() const { |
| return SourceRange(PoundLoc, Arg->getEndLoc()); |
| } |
| |
| /// Return the string form of the literal name. |
| StringRef getLiteralKindRawName() const; |
| |
| StringRef getLiteralKindPlainName() const; |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::ObjectLiteral; |
| } |
| }; |
| |
| /// DiscardAssignmentExpr - A '_' in the left-hand side of an assignment, which |
| /// discards the corresponding tuple element on the right-hand side. |
| class DiscardAssignmentExpr : public Expr { |
| SourceLoc Loc; |
| |
| public: |
| DiscardAssignmentExpr(SourceLoc Loc, bool Implicit) |
| : Expr(ExprKind::DiscardAssignment, Implicit), Loc(Loc) {} |
| |
| SourceRange getSourceRange() const { return Loc; } |
| SourceLoc getLoc() const { return Loc; } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::DiscardAssignment; |
| } |
| }; |
| |
| /// DeclRefExpr - A reference to a value, "x". |
| class DeclRefExpr : public Expr { |
| /// \brief The declaration pointer. |
| ConcreteDeclRef D; |
| DeclNameLoc Loc; |
| |
| public: |
| DeclRefExpr(ConcreteDeclRef D, DeclNameLoc Loc, bool Implicit, |
| AccessSemantics semantics = AccessSemantics::Ordinary, |
| Type Ty = Type()) |
| : Expr(ExprKind::DeclRef, Implicit, Ty), D(D), Loc(Loc) { |
| Bits.DeclRefExpr.Semantics = (unsigned) semantics; |
| Bits.DeclRefExpr.FunctionRefKind = |
| static_cast<unsigned>(Loc.isCompound() ? FunctionRefKind::Compound |
| : FunctionRefKind::Unapplied); |
| } |
| |
| /// Retrieve the declaration to which this expression refers. |
| ValueDecl *getDecl() const { |
| return getDeclRef().getDecl(); |
| } |
| |
| /// Return true if this access is direct, meaning that it does not call the |
| /// getter or setter. |
| AccessSemantics getAccessSemantics() const { |
| return (AccessSemantics) Bits.DeclRefExpr.Semantics; |
| } |
| |
| /// Retrieve the concrete declaration reference. |
| ConcreteDeclRef getDeclRef() const { |
| return D; |
| } |
| |
| SourceRange getSourceRange() const { return Loc.getSourceRange(); } |
| SourceLoc getLoc() const { return Loc.getBaseNameLoc(); } |
| DeclNameLoc getNameLoc() const { return Loc; } |
| |
| /// Retrieve the kind of function reference. |
| FunctionRefKind getFunctionRefKind() const { |
| return static_cast<FunctionRefKind>(Bits.DeclRefExpr.FunctionRefKind); |
| } |
| |
| /// Set the kind of function reference. |
| void setFunctionRefKind(FunctionRefKind refKind) { |
| Bits.DeclRefExpr.FunctionRefKind = static_cast<unsigned>(refKind); |
| } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::DeclRef; |
| } |
| }; |
| |
| /// A reference to 'super'. References to members of 'super' resolve to members |
| /// of a superclass of 'self'. |
| class SuperRefExpr : public Expr { |
| VarDecl *Self; |
| SourceLoc Loc; |
| |
| public: |
| SuperRefExpr(VarDecl *Self, SourceLoc Loc, bool Implicit, |
| Type SuperTy = Type()) |
| : Expr(ExprKind::SuperRef, Implicit, SuperTy), Self(Self), Loc(Loc) {} |
| |
| VarDecl *getSelf() const { return Self; } |
| |
| SourceLoc getSuperLoc() const { return Loc; } |
| SourceRange getSourceRange() const { return Loc; } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::SuperRef; |
| } |
| }; |
| |
| /// A reference to a type in expression context, spelled out as a TypeLoc. Sema |
| /// forms this expression as a result of name binding. This always has |
| /// MetaTypetype. |
| class TypeExpr : public Expr { |
| TypeLoc Info; |
| TypeExpr(Type Ty); |
| public: |
| // Create a TypeExpr with location information. |
| TypeExpr(TypeLoc Ty); |
| |
| // The type of a TypeExpr is always a metatype type. Return the instance |
| // type, ErrorType if an error, or null if not set yet. |
| Type getInstanceType(llvm::function_ref<bool(const Expr *)> hasType = |
| [](const Expr *E) -> bool { return !!E->getType(); }, |
| llvm::function_ref<Type(const Expr *)> getType = |
| [](const Expr *E) -> Type { |
| return E->getType(); |
| }) const; |
| |
| // Create an implicit TypeExpr, which has no location information. |
| static TypeExpr *createImplicit(Type Ty, ASTContext &C) { |
| return new (C) TypeExpr(Ty); |
| } |
| |
| // Create an implicit TypeExpr, with location information even though it |
| // shouldn't have one. This is presently used to work around other location |
| // processing bugs. If you have an implicit location, use createImplicit. |
| static TypeExpr *createImplicitHack(SourceLoc Loc, Type Ty, ASTContext &C); |
| |
| |
| /// Create a TypeExpr for a TypeDecl at the specified location. |
| static TypeExpr *createForDecl(SourceLoc Loc, TypeDecl *D, |
| DeclContext *DC, |
| bool isImplicit); |
| |
| /// Create a TypeExpr for a member TypeDecl of the given parent TypeDecl. |
| static TypeExpr *createForMemberDecl(SourceLoc ParentNameLoc, |
| TypeDecl *Parent, |
| SourceLoc NameLoc, |
| TypeDecl *Decl); |
| |
| /// Create a TypeExpr for a member TypeDecl of the given parent IdentTypeRepr. |
| static TypeExpr *createForMemberDecl(IdentTypeRepr *ParentTR, |
| SourceLoc NameLoc, |
| TypeDecl *Decl); |
| |
| /// Create a TypeExpr from an IdentTypeRepr with the given arguments applied |
| /// at the specified location. |
| /// |
| /// Returns nullptr if the reference cannot be formed, which is a hack due |
| /// to limitations in how we model generic typealiases. |
| static TypeExpr *createForSpecializedDecl(IdentTypeRepr *ParentTR, |
| ArrayRef<TypeRepr*> Args, |
| SourceRange AngleLocs, |
| ASTContext &C); |
| |
| TypeLoc &getTypeLoc() { return Info; } |
| TypeLoc getTypeLoc() const { return Info; } |
| TypeRepr *getTypeRepr() const { return Info.getTypeRepr(); } |
| // NOTE: TypeExpr::getType() returns the type of the expr node, which is the |
| // metatype of what is stored as an operand type. |
| |
| SourceRange getSourceRange() const { return Info.getSourceRange(); } |
| // TODO: optimize getStartLoc() and getEndLoc() when TypeLoc allows it. |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::Type; |
| } |
| }; |
| |
| |
| |
| /// A reference to another initializer from within a constructor body, |
| /// either to a delegating initializer or to a super.init invocation. |
| /// For a reference type, this semantically references a different constructor |
| /// entry point, called the 'initializing constructor', from the 'allocating |
| /// constructor' entry point referenced by a 'new' expression. |
| class OtherConstructorDeclRefExpr : public Expr { |
| ConcreteDeclRef Ctor; |
| DeclNameLoc Loc; |
| |
| public: |
| OtherConstructorDeclRefExpr(ConcreteDeclRef Ctor, DeclNameLoc Loc, |
| bool Implicit, Type Ty = {}) |
| : Expr(ExprKind::OtherConstructorDeclRef, Implicit, Ty), |
| Ctor(Ctor), Loc(Loc) |
| {} |
| |
| ConstructorDecl *getDecl() const; |
| ConcreteDeclRef getDeclRef() const { return Ctor; } |
| |
| SourceLoc getLoc() const { return Loc.getBaseNameLoc(); } |
| DeclNameLoc getConstructorLoc() const { return Loc; } |
| SourceRange getSourceRange() const { return Loc.getSourceRange(); } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::OtherConstructorDeclRef; |
| } |
| }; |
| |
| /// OverloadSetRefExpr - A reference to an overloaded set of values with a |
| /// single name. |
| /// |
| /// This is an abstract class that covers the various different kinds of |
| /// overload sets. |
| class OverloadSetRefExpr : public Expr { |
| ArrayRef<ValueDecl*> Decls; |
| |
| protected: |
| OverloadSetRefExpr(ExprKind Kind, ArrayRef<ValueDecl*> decls, |
| FunctionRefKind functionRefKind, bool Implicit, Type Ty) |
| : Expr(Kind, Implicit, Ty), Decls(decls) { |
| Bits.OverloadSetRefExpr.FunctionRefKind = |
| static_cast<unsigned>(functionRefKind); |
| } |
| |
| public: |
| ArrayRef<ValueDecl*> getDecls() const { return Decls; } |
| |
| void setDecls(ArrayRef<ValueDecl *> domain) { |
| Decls = domain; |
| } |
| |
| /// getBaseType - Determine the type of the base object provided for the |
| /// given overload set, which is only non-null when dealing with an overloaded |
| /// member reference. |
| Type getBaseType() const; |
| |
| /// hasBaseObject - Determine whether this overloaded expression has a |
| /// concrete base object (which is not a metatype). |
| bool hasBaseObject() const; |
| |
| /// Retrieve the kind of function reference. |
| FunctionRefKind getFunctionRefKind() const { |
| return static_cast<FunctionRefKind>( |
| Bits.OverloadSetRefExpr.FunctionRefKind); |
| } |
| |
| /// Set the kind of function reference. |
| void setFunctionRefKind(FunctionRefKind refKind) { |
| Bits.OverloadSetRefExpr.FunctionRefKind = static_cast<unsigned>(refKind); |
| } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() >= ExprKind::First_OverloadSetRefExpr && |
| E->getKind() <= ExprKind::Last_OverloadSetRefExpr; |
| } |
| }; |
| |
| /// OverloadedDeclRefExpr - A reference to an overloaded name that should |
| /// eventually be resolved (by overload resolution) to a value reference. |
| class OverloadedDeclRefExpr final : public OverloadSetRefExpr { |
| DeclNameLoc Loc; |
| |
| public: |
| OverloadedDeclRefExpr(ArrayRef<ValueDecl*> Decls, DeclNameLoc Loc, |
| FunctionRefKind functionRefKind, |
| bool Implicit, Type Ty = Type()) |
| : OverloadSetRefExpr(ExprKind::OverloadedDeclRef, Decls, functionRefKind, |
| Implicit, Ty), |
| Loc(Loc) { |
| } |
| |
| DeclNameLoc getNameLoc() const { return Loc; } |
| SourceLoc getLoc() const { return Loc.getBaseNameLoc(); } |
| SourceRange getSourceRange() const { return Loc.getSourceRange(); } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::OverloadedDeclRef; |
| } |
| }; |
| |
| /// UnresolvedDeclRefExpr - This represents use of an undeclared identifier, |
| /// which may ultimately be a use of something that hasn't been defined yet, it |
| /// may be a use of something that got imported (which will be resolved during |
| /// sema), or may just be a use of an unknown identifier. |
| /// |
| class UnresolvedDeclRefExpr : public Expr { |
| DeclName Name; |
| DeclNameLoc Loc; |
| |
| public: |
| UnresolvedDeclRefExpr(DeclName name, DeclRefKind refKind, DeclNameLoc loc) |
| : Expr(ExprKind::UnresolvedDeclRef, /*Implicit=*/loc.isInvalid()), |
| Name(name), Loc(loc) { |
| Bits.UnresolvedDeclRefExpr.DeclRefKind = static_cast<unsigned>(refKind); |
| Bits.UnresolvedDeclRefExpr.FunctionRefKind = |
| static_cast<unsigned>(Loc.isCompound() ? FunctionRefKind::Compound |
| : FunctionRefKind::Unapplied); |
| } |
| |
| bool hasName() const { return static_cast<bool>(Name); } |
| DeclName getName() const { return Name; } |
| |
| DeclRefKind getRefKind() const { |
| return static_cast<DeclRefKind>(Bits.UnresolvedDeclRefExpr.DeclRefKind); |
| } |
| |
| /// Retrieve the kind of function reference. |
| FunctionRefKind getFunctionRefKind() const { |
| return static_cast<FunctionRefKind>( |
| Bits.UnresolvedDeclRefExpr.FunctionRefKind); |
| } |
| |
| /// Set the kind of function reference. |
| void setFunctionRefKind(FunctionRefKind refKind) { |
| Bits.UnresolvedDeclRefExpr.FunctionRefKind = static_cast<unsigned>(refKind); |
| } |
| |
| DeclNameLoc getNameLoc() const { return Loc; } |
| |
| SourceRange getSourceRange() const { return Loc.getSourceRange(); } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::UnresolvedDeclRef; |
| } |
| }; |
| |
| /// 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; |
| 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; } |
| |
| /// 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(); |
| if (BaseStartLoc.isInvalid() || NameLoc.isInvalid()) { |
| return NameLoc.getBaseNameLoc(); |
| } else { |
| return BaseStartLoc; |
| } |
| } |
| SourceLoc getEndLoc() const { |
| return NameLoc.getSourceRange().End; |
| } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::MemberRef; |
| } |
| }; |
| |
| /// 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 { |
| protected: |
| Expr *Base; |
| ConcreteDeclRef Member; |
| |
| explicit DynamicLookupExpr(ExprKind kind, ConcreteDeclRef member, Expr *base) |
| : Expr(kind, /*Implicit=*/false), Base(base), Member(member) { } |
| |
| 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; |
| } |
| }; |
| |
| /// A reference to a member of an object that was found via dynamic lookup. |
| /// |
| /// A member found via dynamic lookup may not actually be available at runtime. |
| /// Therefore, a reference to that member always returns an optional instance. |
| /// Users can then propagate the optional (via ?) or assert that the member is |
| /// always available (via !). For example: |
| /// |
| /// \code |
| /// class C { |
| /// func @objc foo(i : Int) -> String { ... } |
| /// }; |
| /// |
| /// var x : AnyObject = <some value> |
| /// print(x.foo!(17)) // x.foo has type ((i : Int) -> String)? |
| /// \endcode |
| class DynamicMemberRefExpr : public DynamicLookupExpr { |
| SourceLoc DotLoc; |
| DeclNameLoc NameLoc; |
| |
| public: |
| DynamicMemberRefExpr(Expr *base, SourceLoc dotLoc, |
| ConcreteDeclRef member, |
| DeclNameLoc nameLoc) |
| : DynamicLookupExpr(ExprKind::DynamicMemberRef, member, base), |
| DotLoc(dotLoc), NameLoc(nameLoc) { |
| } |
| |
| /// Retrieve the location of the member name. |
| DeclNameLoc getNameLoc() const { return NameLoc; } |
| |
| /// Retrieve the location of the '.'. |
| SourceLoc getDotLoc() const { return DotLoc; } |
| |
| SourceLoc getLoc() const { return NameLoc.getBaseNameLoc(); } |
| |
| SourceLoc getStartLoc() const { |
| SourceLoc BaseStartLoc = Base->getStartLoc(); |
| if (BaseStartLoc.isInvalid() || NameLoc.isInvalid()) { |
| return NameLoc.getBaseNameLoc(); |
| } else { |
| return BaseStartLoc; |
| } |
| } |
| SourceLoc getEndLoc() const { return NameLoc.getSourceRange().End; } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::DynamicMemberRef; |
| } |
| }; |
| |
| /// A subscript on an object with dynamic lookup type. |
| /// |
| /// A subscript found via dynamic lookup may not actually be available |
| /// at runtime. Therefore, the result of performing the subscript |
| /// operation always returns an optional instance.Users can then |
| /// propagate the optional (via ?) or assert that the member is always |
| /// available (via !). For example: |
| /// |
| /// \code |
| /// class C { |
| /// @objc subscript (i : Int) -> String { |
| /// get { |
| /// ... |
| /// } |
| /// } |
| /// }; |
| /// |
| /// var x : AnyObject = <some value> |
| /// print(x[27]! // x[27] has type String? |
| /// \endcode |
| class DynamicSubscriptExpr final |
| : public DynamicLookupExpr, |
| public TrailingCallArguments<DynamicSubscriptExpr> { |
| friend TrailingCallArguments; |
| |
| Expr *Index; |
| |
| DynamicSubscriptExpr(Expr *base, Expr *index, ArrayRef<Identifier> argLabels, |
| ArrayRef<SourceLoc> argLabelLocs, |
| bool hasTrailingClosure, ConcreteDeclRef member, |
| bool implicit); |
| |
| public: |
| /// Create a dynamic subscript. |
| /// |
| /// Note: do not create new callers to this entry point; use the entry point |
| /// that takes separate index arguments. |
| static DynamicSubscriptExpr * |
| create(ASTContext &ctx, Expr *base, Expr *index, ConcreteDeclRef decl, |
| bool implicit, |
| llvm::function_ref<Type(const Expr *)> getType = |
| [](const Expr *E) -> Type { return E->getType(); }); |
| |
| /// Create a new dynamic subscript. |
| static DynamicSubscriptExpr *create(ASTContext &ctx, Expr *base, |
| SourceLoc lSquareLoc, |
| ArrayRef<Expr *> indexArgs, |
| ArrayRef<Identifier> indexArgLabels, |
| ArrayRef<SourceLoc> indexArgLabelLocs, |
| SourceLoc rSquareLoc, |
| Expr *trailingClosure, |
| 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; } |
| void setIndex(Expr *E) { Index = E; } |
| |
| unsigned getNumArguments() const { |
| return Bits.DynamicSubscriptExpr.NumArgLabels; |
| } |
| |
| bool hasArgumentLabelLocs() const { |
| return Bits.DynamicSubscriptExpr.HasArgLabelLocs; |
| } |
| |
| /// Whether this call with written with a trailing closure. |
| bool hasTrailingClosure() const { |
| return Bits.DynamicSubscriptExpr.HasTrailingClosure; |
| } |
| |
| SourceLoc getLoc() const { return Index->getStartLoc(); } |
| |
| SourceLoc getStartLoc() const { return Base->getStartLoc(); } |
| SourceLoc getEndLoc() const { return Index->getEndLoc(); } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::DynamicSubscript; |
| } |
| }; |
| |
| /// UnresolvedMemberExpr - This represents '.foo', an unresolved reference to a |
| /// member, which is to be resolved with context sensitive type information into |
| /// bar.foo. These always have unresolved type. |
| class UnresolvedMemberExpr final |
| : public Expr, |
| public TrailingCallArguments<UnresolvedMemberExpr> { |
| SourceLoc DotLoc; |
| DeclNameLoc NameLoc; |
| DeclName Name; |
| Expr *Argument; |
| |
| UnresolvedMemberExpr(SourceLoc dotLoc, DeclNameLoc nameLoc, |
| DeclName name, Expr *argument, |
| ArrayRef<Identifier> argLabels, |
| ArrayRef<SourceLoc> argLabelLocs, |
| bool hasTrailingClosure, |
| bool implicit); |
| |
| public: |
| /// Create a new unresolved member expression with no arguments. |
| static UnresolvedMemberExpr *create(ASTContext &ctx, SourceLoc dotLoc, |
| DeclNameLoc nameLoc, DeclName name, |
| bool implicit); |
| |
| /// Create a new unresolved member expression. |
| static UnresolvedMemberExpr *create(ASTContext &ctx, SourceLoc dotLoc, |
| DeclNameLoc nameLoc, DeclName name, |
| SourceLoc lParenLoc, |
| ArrayRef<Expr *> args, |
| ArrayRef<Identifier> argLabels, |
| ArrayRef<SourceLoc> argLabelLocs, |
| SourceLoc rParenLoc, |
| Expr *trailingClosure, |
| bool implicit); |
| |
| DeclName getName() const { return Name; } |
| DeclNameLoc getNameLoc() const { return NameLoc; } |
| SourceLoc getDotLoc() const { return DotLoc; } |
| Expr *getArgument() const { return Argument; } |
| void setArgument(Expr *argument) { Argument = argument; } |
| |
| /// Whether this reference has arguments. |
| bool hasArguments() const { |
| return Bits.UnresolvedMemberExpr.HasArguments; |
| } |
| |
| unsigned getNumArguments() const { |
| return Bits.UnresolvedMemberExpr.NumArgLabels; |
| } |
| |
| bool hasArgumentLabelLocs() const { |
| return Bits.UnresolvedMemberExpr.HasArgLabelLocs; |
| } |
| |
| /// Whether this call with written with a trailing closure. |
| bool hasTrailingClosure() const { |
| return Bits.UnresolvedMemberExpr.HasTrailingClosure; |
| } |
| |
| SourceLoc getLoc() const { return NameLoc.getBaseNameLoc(); } |
| |
| SourceLoc getStartLoc() const { return DotLoc; } |
| SourceLoc getEndLoc() const { |
| return (Argument ? Argument->getEndLoc() : NameLoc.getSourceRange().End); |
| } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::UnresolvedMember; |
| } |
| }; |
| |
| /// AnyTryExpr - An abstract superclass for 'try' and 'try!'. |
| /// |
| /// These are like IdentityExpr in some ways, but they're a bit too |
| /// semantic differentiated to just always look through. |
| class AnyTryExpr : public Expr { |
| Expr *SubExpr; |
| SourceLoc TryLoc; |
| |
| public: |
| AnyTryExpr(ExprKind kind, SourceLoc tryLoc, Expr *sub, |
| Type type, bool implicit) |
| : Expr(kind, implicit, type), SubExpr(sub), TryLoc(tryLoc) {} |
| |
| SourceLoc getLoc() const { return SubExpr->getLoc(); } |
| Expr *getSubExpr() const { return SubExpr; } |
| void setSubExpr(Expr *E) { SubExpr = E; } |
| |
| SourceLoc getTryLoc() const { return TryLoc; } |
| |
| SourceLoc getStartLoc() const { return TryLoc; } |
| SourceLoc getEndLoc() const { return getSubExpr()->getEndLoc(); } |
| |
| static bool classof(const Expr *e) { |
| return e->getKind() >= ExprKind::First_AnyTryExpr |
| && e->getKind() <= ExprKind::Last_AnyTryExpr; |
| } |
| }; |
| |
| /// TryExpr - A 'try' surrounding an expression, marking that the |
| /// expression contains code which might throw. |
| /// |
| /// getSemanticsProvidingExpr() looks through this because it doesn't |
| /// provide the value and only very specific clients care where the |
| /// 'try' was written. |
| class TryExpr : public AnyTryExpr { |
| public: |
| TryExpr(SourceLoc tryLoc, Expr *sub, Type type = Type(), |
| bool implicit = false) |
| : AnyTryExpr(ExprKind::Try, tryLoc, sub, type, implicit) {} |
| |
| static bool classof(const Expr *e) { |
| return e->getKind() == ExprKind::Try; |
| } |
| }; |
| |
| /// ForceTryExpr - A 'try!' surrounding an expression, marking that |
| /// the expression contains code which might throw, but that the code |
| /// should dynamically assert if it does. |
| class ForceTryExpr : public AnyTryExpr { |
| SourceLoc ExclaimLoc; |
| |
| public: |
| ForceTryExpr(SourceLoc tryLoc, Expr *sub, SourceLoc exclaimLoc, |
| Type type = Type(), bool implicit = false) |
| : AnyTryExpr(ExprKind::ForceTry, tryLoc, sub, type, implicit), |
| ExclaimLoc(exclaimLoc) {} |
| |
| SourceLoc getExclaimLoc() const { return ExclaimLoc; } |
| |
| static bool classof(const Expr *e) { |
| return e->getKind() == ExprKind::ForceTry; |
| } |
| }; |
| |
| /// A 'try?' surrounding an expression, marking that the expression contains |
| /// code which might throw, and that the result should be injected into an |
| /// Optional. If the code does throw, \c nil is produced. |
| class OptionalTryExpr : public AnyTryExpr { |
| SourceLoc QuestionLoc; |
| |
| public: |
| OptionalTryExpr(SourceLoc tryLoc, Expr *sub, SourceLoc questionLoc, |
| Type type = Type(), bool implicit = false) |
| : AnyTryExpr(ExprKind::OptionalTry, tryLoc, sub, type, implicit), |
| QuestionLoc(questionLoc) {} |
| |
| SourceLoc getQuestionLoc() const { return QuestionLoc; } |
| |
| static bool classof(const Expr *e) { |
| return e->getKind() == ExprKind::OptionalTry; |
| } |
| }; |
| |
| /// An expression node that does not affect the evaluation of its subexpression. |
| class IdentityExpr : public Expr { |
| Expr *SubExpr; |
| |
| public: |
| IdentityExpr(ExprKind kind, |
| Expr *subExpr, Type ty = Type(), |
| bool implicit = false) |
| : Expr(kind, implicit, ty), SubExpr(subExpr) |
| {} |
| |
| SourceLoc getLoc() const { return SubExpr->getLoc(); } |
| Expr *getSubExpr() const { return SubExpr; } |
| void setSubExpr(Expr *E) { SubExpr = E; } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() >= ExprKind::First_IdentityExpr |
| && E->getKind() <= ExprKind::Last_IdentityExpr; |
| } |
| }; |
| |
| /// The '.self' pseudo-property, which has no effect except to |
| /// satisfy the syntactic requirement that type values appear only as part of |
| /// a property chain. |
| class DotSelfExpr : public IdentityExpr { |
| SourceLoc DotLoc; |
| SourceLoc SelfLoc; |
| |
| public: |
| DotSelfExpr(Expr *subExpr, SourceLoc dot, SourceLoc self, |
| Type ty = Type()) |
| : IdentityExpr(ExprKind::DotSelf, subExpr, ty), |
| DotLoc(dot), SelfLoc(self) |
| {} |
| |
| SourceLoc getDotLoc() const { return DotLoc; } |
| SourceLoc getSelfLoc() const { return SelfLoc; } |
| |
| SourceLoc getStartLoc() const { return getSubExpr()->getStartLoc(); } |
| SourceLoc getEndLoc() const { return SelfLoc; } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::DotSelf; |
| } |
| }; |
| |
| /// A parenthesized expression like '(x+x)'. Syntactically, |
| /// this is just a TupleExpr with exactly one element that has no label. |
| /// Semantically, however, it serves only as grouping parentheses and |
| /// does not form an expression of tuple type (unless the sub-expression |
| /// has tuple type, of course). |
| class ParenExpr : public IdentityExpr { |
| SourceLoc LParenLoc, RParenLoc; |
| |
| public: |
| ParenExpr(SourceLoc lploc, Expr *subExpr, SourceLoc rploc, |
| bool hasTrailingClosure, |
| Type ty = Type()) |
| : IdentityExpr(ExprKind::Paren, subExpr, ty), |
| LParenLoc(lploc), RParenLoc(rploc) { |
| Bits.ParenExpr.HasTrailingClosure = hasTrailingClosure; |
| assert(lploc.isValid() == rploc.isValid() && |
| "Mismatched source location information"); |
| } |
| |
| SourceLoc getLParenLoc() const { return LParenLoc; } |
| SourceLoc getRParenLoc() const { return RParenLoc; } |
| |
| // When the locations of the parens are invalid, ask our |
| // subexpression for its source range instead. This isn't a |
| // hot path and so we don't both optimizing for it. |
| |
| SourceLoc getStartLoc() const { |
| return (LParenLoc.isInvalid() ? getSubExpr()->getStartLoc() : LParenLoc); |
| } |
| SourceLoc getEndLoc() const { |
| // If we have a trailing closure, our end point is the end of the |
| // trailing closure. |
| if (RParenLoc.isInvalid() || Bits.ParenExpr.HasTrailingClosure) |
| return getSubExpr()->getEndLoc(); |
| return RParenLoc; |
| } |
| |
| /// \brief Whether this expression has a trailing closure as its argument. |
| bool hasTrailingClosure() const { return Bits.ParenExpr.HasTrailingClosure; } |
| |
| static bool classof(const Expr *E) { return E->getKind() == ExprKind::Paren; } |
| }; |
| |
| /// TupleExpr - Parenthesized expressions like '(a: x+x)' and '(x, y, 4)'. Also |
| /// used to represent the operands to a binary operator. Note that |
| /// expressions like '(4)' are represented with a ParenExpr. |
| class TupleExpr final : public Expr, |
| private llvm::TrailingObjects<TupleExpr, Expr *, Identifier, SourceLoc> { |
| friend TrailingObjects; |
| |
| SourceLoc LParenLoc; |
| SourceLoc RParenLoc; |
| |
| size_t numTrailingObjects(OverloadToken<Expr *>) const { |
| return getNumElements(); |
| } |
| size_t numTrailingObjects(OverloadToken<Identifier>) const { |
| return hasElementNames() ? getNumElements() : 0; |
| } |
| size_t numTrailingObjects(OverloadToken<SourceLoc>) const { |
| return hasElementNames() ? getNumElements() : 0; |
| } |
| |
| /// Retrieve the buffer containing the element names. |
| MutableArrayRef<Identifier> getElementNamesBuffer() { |
| if (!hasElementNames()) |
| return { }; |
| |
| return { getTrailingObjects<Identifier>(), getNumElements() }; |
| } |
| |
| /// Retrieve the buffer containing the element name locations. |
| MutableArrayRef<SourceLoc> getElementNameLocsBuffer() { |
| if (!hasElementNameLocs()) |
| return { }; |
| |
| return { getTrailingObjects<SourceLoc>(), getNumElements() }; |
| } |
| |
| TupleExpr(SourceLoc LParenLoc, ArrayRef<Expr *> SubExprs, |
| ArrayRef<Identifier> ElementNames, |
| ArrayRef<SourceLoc> ElementNameLocs, |
| SourceLoc RParenLoc, bool HasTrailingClosure, bool Implicit, |
| Type Ty); |
| |
| public: |
| /// Create a tuple. |
| static TupleExpr *create(ASTContext &ctx, |
| SourceLoc LParenLoc, |
| ArrayRef<Expr *> SubExprs, |
| ArrayRef<Identifier> ElementNames, |
| ArrayRef<SourceLoc> ElementNameLocs, |
| SourceLoc RParenLoc, bool HasTrailingClosure, |
| bool Implicit, Type Ty = Type()); |
| |
| /// Create an empty tuple. |
| static TupleExpr *createEmpty(ASTContext &ctx, SourceLoc LParenLoc, |
| SourceLoc RParenLoc, bool Implicit); |
| |
| /// Create an implicit tuple with no source information. |
| static TupleExpr *createImplicit(ASTContext &ctx, ArrayRef<Expr *> SubExprs, |
| ArrayRef<Identifier> ElementNames); |
| |
| SourceLoc getLParenLoc() const { return LParenLoc; } |
| SourceLoc getRParenLoc() const { return RParenLoc; } |
| |
| SourceRange getSourceRange() const; |
| |
| /// \brief Whether this expression has a trailing closure as its argument. |
| bool hasTrailingClosure() const { return Bits.TupleExpr.HasTrailingClosure; } |
| |
| /// Retrieve the elements of this tuple. |
| MutableArrayRef<Expr*> getElements() { |
| return { getTrailingObjects<Expr *>(), getNumElements() }; |
| } |
| |
| /// Retrieve the elements of this tuple. |
| ArrayRef<Expr*> getElements() const { |
| return { getTrailingObjects<Expr *>(), getNumElements() }; |
| } |
| |
| unsigned getNumElements() const { return Bits.TupleExpr.NumElements; } |
| |
| Expr *getElement(unsigned i) const { |
| return getElements()[i]; |
| } |
| void setElement(unsigned i, Expr *e) { |
| getElements()[i] = e; |
| } |
| |
| /// Whether this tuple has element names. |
| bool hasElementNames() const { |
| return Bits.TupleExpr.HasElementNames; |
| } |
| |
| /// Retrieve the element names for a tuple. |
| ArrayRef<Identifier> getElementNames() const { |
| return const_cast<TupleExpr *>(this)->getElementNamesBuffer(); |
| } |
| |
| /// Retrieve the ith element name. |
| Identifier getElementName(unsigned i) const { |
| return hasElementNames() ? getElementNames()[i] : Identifier(); |
| } |
| |
| /// Whether this tuple has element name locations. |
| bool hasElementNameLocs() const { |
| return Bits.TupleExpr.HasElementNameLocations; |
| } |
| |
| /// Retrieve the locations of the element names for a tuple. |
| ArrayRef<SourceLoc> getElementNameLocs() const { |
| return const_cast<TupleExpr *>(this)->getElementNameLocsBuffer(); |
| } |
| |
| /// Retrieve the location of the ith label, if known. |
| SourceLoc getElementNameLoc(unsigned i) const { |
| if (hasElementNameLocs()) |
| return getElementNameLocs()[i]; |
| |
| return SourceLoc(); |
| } |
| |
| static bool classof(const Expr *E) { return E->getKind() == ExprKind::Tuple; } |
| }; |
| |
| /// \brief A collection literal expression. |
| /// |
| /// The subexpression is represented as a TupleExpr or ParenExpr and |
| /// passed on to the appropriate semantics-providing conversion |
| /// operation. |
| class CollectionExpr : public Expr { |
| SourceLoc LBracketLoc; |
| SourceLoc RBracketLoc; |
| |
| Expr *SemanticExpr = nullptr; |
| |
| /// Retrieve the intrusive pointer storage from the subtype |
| Expr *const *getTrailingObjectsPointer() const; |
| Expr **getTrailingObjectsPointer() { |
| const CollectionExpr *temp = this; |
| return const_cast<Expr**>(temp->getTrailingObjectsPointer()); |
| } |
| |
| /// Retrieve the intrusive pointer storage from the subtype |
| const SourceLoc *getTrailingSourceLocs() const; |
| SourceLoc *getTrailingSourceLocs() { |
| const CollectionExpr *temp = this; |
| return const_cast<SourceLoc*>(temp->getTrailingSourceLocs()); |
| } |
| |
| protected: |
| CollectionExpr(ExprKind Kind, SourceLoc LBracketLoc, |
| ArrayRef<Expr*> Elements, ArrayRef<SourceLoc> CommaLocs, |
| SourceLoc RBracketLoc, Type Ty) |
| : Expr(Kind, /*Implicit=*/false, Ty), |
| LBracketLoc(LBracketLoc), RBracketLoc(RBracketLoc) { |
| Bits.CollectionExpr.IsTypeDefaulted = false; |
| Bits.CollectionExpr.NumSubExprs = Elements.size(); |
| Bits.CollectionExpr.NumCommas = CommaLocs.size(); |
| assert(Bits.CollectionExpr.NumCommas == CommaLocs.size() && "Truncation"); |
| std::uninitialized_copy(Elements.begin(), Elements.end(), |
| getTrailingObjectsPointer()); |
| std::uninitialized_copy(CommaLocs.begin(), CommaLocs.end(), |
| getTrailingSourceLocs()); |
| } |
| |
| public: |
| |
| /// Retrieve the elements stored in the collection. |
| ArrayRef<Expr *> getElements() const { |
| return {getTrailingObjectsPointer(), Bits.CollectionExpr.NumSubExprs}; |
| } |
| MutableArrayRef<Expr *> getElements() { |
| return {getTrailingObjectsPointer(), Bits.CollectionExpr.NumSubExprs}; |
| } |
| Expr *getElement(unsigned i) const { return getElements()[i]; } |
| void setElement(unsigned i, Expr *E) { getElements()[i] = E; } |
| unsigned getNumElements() const { return Bits.CollectionExpr.NumSubExprs; } |
| |
| /// Retrieve the comma source locations stored in the collection. Please note |
| /// that trailing commas are currently allowed, and that invalid code may have |
| /// stray or missing commas. |
| MutableArrayRef<SourceLoc> getCommaLocs() { |
| return {getTrailingSourceLocs(), Bits.CollectionExpr.NumCommas}; |
| } |
| ArrayRef<SourceLoc> getCommaLocs() const { |
| return {getTrailingSourceLocs(), Bits.CollectionExpr.NumCommas}; |
| } |
| unsigned getNumCommas() const { return Bits.CollectionExpr.NumCommas; } |
| |
| bool isTypeDefaulted() const { return Bits.CollectionExpr.IsTypeDefaulted; } |
| void setIsTypeDefaulted(bool value = true) { |
| Bits.CollectionExpr.IsTypeDefaulted = value; |
| } |
| |
| SourceLoc getLBracketLoc() const { return LBracketLoc; } |
| SourceLoc getRBracketLoc() const { return RBracketLoc; } |
| SourceRange getSourceRange() const { |
| return SourceRange(LBracketLoc, RBracketLoc); |
| } |
| |
| Expr *getSemanticExpr() const { return SemanticExpr; } |
| void setSemanticExpr(Expr *e) { SemanticExpr = e; } |
| |
| static bool classof(const Expr *e) { |
| return e->getKind() >= ExprKind::First_CollectionExpr && |
| e->getKind() <= ExprKind::Last_CollectionExpr; |
| } |
| |
| }; |
| |
| /// \brief An array literal expression [a, b, c]. |
| class ArrayExpr final : public CollectionExpr, |
| private llvm::TrailingObjects<ArrayExpr, Expr*, SourceLoc> { |
| friend TrailingObjects; |
| friend CollectionExpr; |
| |
| size_t numTrailingObjects(OverloadToken<Expr *>) const { |
| return getNumElements(); |
| } |
| size_t numTrailingObjects(OverloadToken<SourceLoc>) const { |
| return getNumCommas(); |
| } |
| |
| ArrayExpr(SourceLoc LBracketLoc, ArrayRef<Expr*> Elements, |
| ArrayRef<SourceLoc> CommaLocs, |
| SourceLoc RBracketLoc, Type Ty) |
| : CollectionExpr(ExprKind::Array, LBracketLoc, Elements, CommaLocs, |
| RBracketLoc, Ty) { } |
| public: |
| static ArrayExpr *create(ASTContext &C, SourceLoc LBracketLoc, |
| ArrayRef<Expr*> Elements, |
| ArrayRef<SourceLoc> CommaLocs, |
| SourceLoc RBracketLoc, |
| Type Ty = Type()); |
| |
| static bool classof(const Expr *e) { |
| return e->getKind() == ExprKind::Array; |
| } |
| }; |
| |
| /// \brief A dictionary literal expression [a : x, b : y, c : z]. |
| class DictionaryExpr final : public CollectionExpr, |
| private llvm::TrailingObjects<DictionaryExpr, Expr*, SourceLoc> { |
| friend TrailingObjects; |
| friend CollectionExpr; |
| |
| size_t numTrailingObjects(OverloadToken<Expr *>) const { |
| return getNumElements(); |
| } |
| size_t numTrailingObjects(OverloadToken<SourceLoc>) const { |
| return getNumCommas(); |
| } |
| |
| DictionaryExpr(SourceLoc LBracketLoc, ArrayRef<Expr*> Elements, |
| ArrayRef<SourceLoc> CommaLocs, |
| SourceLoc RBracketLoc, Type Ty) |
| : CollectionExpr(ExprKind::Dictionary, LBracketLoc, Elements, CommaLocs, |
| RBracketLoc, Ty) { } |
| public: |
| |
| static DictionaryExpr *create(ASTContext &C, SourceLoc LBracketLoc, |
| ArrayRef<Expr*> Elements, |
| ArrayRef<SourceLoc> CommaLocs, |
| SourceLoc RBracketLoc, |
| Type Ty = Type()); |
| |
| static bool classof(const Expr *e) { |
| return e->getKind() == ExprKind::Dictionary; |
| } |
| }; |
| |
| /// Subscripting expressions like a[i] that refer to an element within a |
| /// container. |
| /// |
| /// There is no built-in subscripting in the language. Rather, a fully |
| /// 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, |
| public TrailingCallArguments<SubscriptExpr> { |
| friend TrailingCallArguments; |
| |
| ConcreteDeclRef TheDecl; |
| Expr *Base; |
| Expr *Index; |
| |
| SubscriptExpr(Expr *base, Expr *index, ArrayRef<Identifier> argLabels, |
| ArrayRef<SourceLoc> argLabelLocs, bool hasTrailingClosure, |
| ConcreteDeclRef decl, bool implicit, AccessSemantics semantics); |
| |
| public: |
| /// Create a subscript. |
| /// |
| /// Note: do not create new callers to this entry point; use the entry point |
| /// that takes separate index arguments. |
| static SubscriptExpr * |
| create(ASTContext &ctx, Expr *base, Expr *index, |
| ConcreteDeclRef decl = ConcreteDeclRef(), bool implicit = false, |
| AccessSemantics semantics = AccessSemantics::Ordinary, |
| llvm::function_ref<Type(const Expr *)> getType = |
| [](const Expr *E) -> Type { return E->getType(); }); |
| |
| /// Create a new subscript. |
| static SubscriptExpr *create(ASTContext &ctx, Expr *base, |
| SourceLoc lSquareLoc, |
| ArrayRef<Expr *> indexArgs, |
| ArrayRef<Identifier> indexArgLabels, |
| ArrayRef<SourceLoc> indexArgLabelLocs, |
| SourceLoc rSquareLoc, |
| Expr *trailingClosure, |
| ConcreteDeclRef decl = ConcreteDeclRef(), |
| bool implicit = false, |
| 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; } |
| void setIndex(Expr *E) { Index = E; } |
| |
| unsigned getNumArguments() const { |
| return Bits.SubscriptExpr.NumArgLabels; |
| } |
| |
| bool hasArgumentLabelLocs() const { |
| return Bits.SubscriptExpr.HasArgLabelLocs; |
| } |
| |
| /// Whether this call with written with a trailing closure. |
| bool hasTrailingClosure() const { |
| return Bits.SubscriptExpr.HasTrailingClosure; |
| } |
| |
| /// Determine whether this subscript reference should bypass the |
| /// ordinary accessors. |
| AccessSemantics getAccessSemantics() const { |
| 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 getEndLoc() const { |
| auto end = Index->getEndLoc(); |
| return end.isValid() ? end : Base->getEndLoc(); |
| } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::Subscript; |
| } |
| }; |
| |
| /// Subscripting expression that applies a keypath to a base. |
| class KeyPathApplicationExpr : public Expr { |
| Expr *Base; |
| Expr *KeyPath; |
| SourceLoc LBracketLoc, RBracketLoc; |
| |
| public: |
| KeyPathApplicationExpr(Expr *base, SourceLoc lBracket, Expr *keyPath, |
| SourceLoc rBracket, Type ty, bool implicit) |
| : Expr(ExprKind::KeyPathApplication, implicit, ty), |
| Base(base), KeyPath(keyPath), LBracketLoc(lBracket), RBracketLoc(rBracket) |
| {} |
| |
| SourceLoc getLoc() const { return LBracketLoc; } |
| SourceLoc getStartLoc() const { return Base->getStartLoc(); } |
| SourceLoc getEndLoc() const { return RBracketLoc; } |
| |
| Expr *getBase() const { return Base; } |
| void setBase(Expr *E) { Base = E; } |
| Expr *getKeyPath() const { return KeyPath; } |
| void setKeyPath(Expr *E) { KeyPath = E; } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::KeyPathApplication; |
| } |
| }; |
| |
| /// A member access (foo.bar) on an expression with unresolved type. |
| class UnresolvedDotExpr : public Expr { |
| Expr *SubExpr; |
| SourceLoc DotLoc; |
| DeclNameLoc NameLoc; |
| DeclName Name; |
| ArrayRef<ValueDecl *> OuterAlternatives; |
| |
| public: |
| UnresolvedDotExpr( |
| Expr *subexpr, SourceLoc dotloc, DeclName name, DeclNameLoc nameloc, |
| bool Implicit, |
| ArrayRef<ValueDecl *> outerAlternatives = ArrayRef<ValueDecl *>()) |
| : Expr(ExprKind::UnresolvedDot, Implicit), SubExpr(subexpr), |
| DotLoc(dotloc), NameLoc(nameloc), Name(name), |
| OuterAlternatives(outerAlternatives) { |
| Bits.UnresolvedDotExpr.FunctionRefKind = |
| static_cast<unsigned>(NameLoc.isCompound() ? FunctionRefKind::Compound |
| : FunctionRefKind::Unapplied); |
| } |
| |
| SourceLoc getLoc() const { return NameLoc.getBaseNameLoc(); } |
| |
| SourceLoc getStartLoc() const { |
| return (DotLoc.isInvalid() ? NameLoc.getSourceRange().End |
| : SubExpr->getStartLoc()); |
| } |
| SourceLoc getEndLoc() const { |
| return NameLoc.getSourceRange().End; |
| } |
| |
| SourceLoc getDotLoc() const { return DotLoc; } |
| Expr *getBase() const { return SubExpr; } |
| void setBase(Expr *e) { SubExpr = e; } |
| |
| DeclName getName() const { return Name; } |
| DeclNameLoc getNameLoc() const { return NameLoc; } |
| |
| ArrayRef<ValueDecl *> getOuterAlternatives() const { |
| return OuterAlternatives; |
| } |
| |
| /// Retrieve the kind of function reference. |
| FunctionRefKind getFunctionRefKind() const { |
| return static_cast<FunctionRefKind>(Bits.UnresolvedDotExpr.FunctionRefKind); |
| } |
| |
| /// Set the kind of function reference. |
| void setFunctionRefKind(FunctionRefKind refKind) { |
| Bits.UnresolvedDotExpr.FunctionRefKind = static_cast<unsigned>(refKind); |
| } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::UnresolvedDot; |
| } |
| }; |
| |
| /// TupleElementExpr - Refer to an element of a tuple, |
| /// e.g. "(1,field:2).field". |
| class TupleElementExpr : public Expr { |
| Expr *SubExpr; |
| SourceLoc NameLoc; |
| SourceLoc DotLoc; |
| |
| public: |
| TupleElementExpr(Expr *SubExpr, SourceLoc DotLoc, unsigned FieldNo, |
| SourceLoc NameLoc, Type Ty) |
| : Expr(ExprKind::TupleElement, /*Implicit=*/false, Ty), SubExpr(SubExpr), |
| NameLoc(NameLoc), DotLoc(DotLoc) { |
| Bits.TupleElementExpr.FieldNo = FieldNo; |
| } |
| |
| SourceLoc getLoc() const { return NameLoc; } |
| Expr *getBase() const { return SubExpr; } |
| void setBase(Expr *e) { SubExpr = e; } |
| |
| unsigned getFieldNumber() const { return Bits.TupleElementExpr.FieldNo; } |
| SourceLoc getNameLoc() const { return NameLoc; } |
| SourceLoc getDotLoc() const { return DotLoc; } |
| |
| SourceLoc getStartLoc() const { return getBase()->getStartLoc(); } |
| SourceLoc getEndLoc() const { return getNameLoc(); } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::TupleElement; |
| } |
| }; |
| |
| /// \brief Describes a monadic bind from T? to T. |
| /// |
| /// In a ?-chain expression, this is the part that's spelled with a |
| /// postfix ?. |
| /// |
| /// A BindOptionalExpr must always appear within a |
| /// OptionalEvaluationExpr. If the operand of the BindOptionalExpr |
| /// evaluates to a missing value, the OptionalEvaluationExpr |
| /// immediately completes and produces a missing value in the result |
| /// type. |
| /// |
| /// The depth of the BindOptionalExpr indicates which |
| /// OptionalEvaluationExpr is completed, in case the BindOptionalExpr |
| /// is contained within more than one such expression. |
| class BindOptionalExpr : public Expr { |
| Expr *SubExpr; |
| SourceLoc QuestionLoc; |
| |
| public: |
| BindOptionalExpr(Expr *subExpr, SourceLoc questionLoc, |
| unsigned depth, Type ty = Type()) |
| : Expr(ExprKind::BindOptional, /*Implicit=*/ questionLoc.isInvalid(), ty), |
| SubExpr(subExpr), QuestionLoc(questionLoc) { |
| Bits.BindOptionalExpr.Depth = depth; |
| assert(Bits.BindOptionalExpr.Depth == depth && "bitfield truncation"); |
| } |
| |
| SourceRange getSourceRange() const { |
| if (QuestionLoc.isInvalid()) |
| return SubExpr->getSourceRange(); |
| return SourceRange(SubExpr->getStartLoc(), QuestionLoc); |
| } |
| SourceLoc getStartLoc() const { |
| return SubExpr->getStartLoc(); |
| } |
| SourceLoc getEndLoc() const { |
| return (QuestionLoc.isInvalid() ? SubExpr->getEndLoc() : QuestionLoc); |
| } |
| SourceLoc getLoc() const { |
| if (isImplicit()) |
| return SubExpr->getLoc(); |
| |
| return getQuestionLoc(); |
| } |
| SourceLoc getQuestionLoc() const { return QuestionLoc; } |
| |
| unsigned getDepth() const { return Bits.BindOptionalExpr.Depth; } |
| void setDepth(unsigned depth) { |
| Bits.BindOptionalExpr.Depth = depth; |
| } |
| |
| Expr *getSubExpr() const { return SubExpr; } |
| void setSubExpr(Expr *expr) { SubExpr = expr; } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::BindOptional; |
| } |
| }; |
| |
| /// \brief Describes the outer limits of an operation containing |
| /// monadic binds of T? to T. |
| /// |
| /// In a ?-chain expression, this is implicitly formed at the outer |
| /// limits of the chain. For example, in (foo?.bar?().baz).fred, |
| /// this is nested immediately within the parens. |
| /// |
| /// This expression will always have optional type. |
| class OptionalEvaluationExpr : public Expr { |
| Expr *SubExpr; |
| |
| public: |
| OptionalEvaluationExpr(Expr *subExpr, Type ty = Type()) |
| : Expr(ExprKind::OptionalEvaluation, /*Implicit=*/ true, ty), |
| SubExpr(subExpr) {} |
| |
| SWIFT_FORWARD_SOURCE_LOCS_TO(SubExpr) |
| |
| Expr *getSubExpr() const { return SubExpr; } |
| void setSubExpr(Expr *expr) { SubExpr = expr; } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::OptionalEvaluation; |
| } |
| }; |
| |
| /// \brief An expression that forces an optional to its underlying value. |
| /// |
| /// \code |
| /// func parseInt(s : String) -> Int? { ... } |
| /// |
| /// var maybeInt = parseInt("5") // returns an Int? |
| /// var forcedInt = parseInt("5")! // returns an Int; fails on empty optional |
| /// \endcode |
| /// |
| class ForceValueExpr : public Expr { |
| Expr *SubExpr; |
| SourceLoc ExclaimLoc; |
| |
| public: |
| ForceValueExpr(Expr *subExpr, SourceLoc exclaimLoc, bool forcedIUO = false) |
| : Expr(ExprKind::ForceValue, /*Implicit=*/exclaimLoc.isInvalid(), Type()), |
| SubExpr(subExpr), ExclaimLoc(exclaimLoc) { |
| Bits.ForceValueExpr.ForcedIUO = forcedIUO; |
| } |
| |
| SourceRange getSourceRange() const { |
| if (ExclaimLoc.isInvalid()) |
| return SubExpr->getSourceRange(); |
| |
| return SourceRange(SubExpr->getStartLoc(), ExclaimLoc); |
| } |
| SourceLoc getStartLoc() const { |
| return SubExpr->getStartLoc(); |
| } |
| SourceLoc getEndLoc() const { |
| return (isImplicit() ? SubExpr->getEndLoc() : getExclaimLoc()); |
| } |
| SourceLoc getLoc() const { |
| if (!isImplicit()) |
| return getExclaimLoc(); |
| |
| return SubExpr->getLoc(); |
| } |
| SourceLoc getExclaimLoc() const { return ExclaimLoc; } |
| |
| Expr *getSubExpr() const { return SubExpr; } |
| void setSubExpr(Expr *expr) { SubExpr = expr; } |
| |
| bool isForceOfImplicitlyUnwrappedOptional() const { |
| return Bits.ForceValueExpr.ForcedIUO; |
| } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::ForceValue; |
| } |
| }; |
| |
| /// \brief An expression that grants temporary escapability to a nonescaping |
| /// closure value. |
| /// |
| /// This expression is formed by the type checker when a call to the |
| /// `withoutActuallyEscaping` declaration is made. |
| class MakeTemporarilyEscapableExpr : public Expr { |
| Expr *NonescapingClosureValue; |
| OpaqueValueExpr *EscapingClosureValue; |
| Expr *SubExpr; |
| SourceLoc NameLoc, LParenLoc, RParenLoc; |
| |
| public: |
| MakeTemporarilyEscapableExpr(SourceLoc NameLoc, |
| SourceLoc LParenLoc, |
| Expr *NonescapingClosureValue, |
| Expr *SubExpr, |
| SourceLoc RParenLoc, |
| OpaqueValueExpr *OpaqueValueForEscapingClosure, |
| bool implicit = false) |
| : Expr(ExprKind::MakeTemporarilyEscapable, implicit, Type()), |
| NonescapingClosureValue(NonescapingClosureValue), |
| EscapingClosureValue(OpaqueValueForEscapingClosure), |
| SubExpr(SubExpr), |
| NameLoc(NameLoc), LParenLoc(LParenLoc), RParenLoc(RParenLoc) |
| {} |
| |
| SourceLoc getStartLoc() const { |
| return NameLoc; |
| } |
| SourceLoc getEndLoc() const { |
| return RParenLoc; |
| } |
| |
| SourceLoc getLoc() const { |
| return NameLoc; |
| } |
| |
| /// Retrieve the opaque value representing the escapable copy of the |
| /// closure. |
| OpaqueValueExpr *getOpaqueValue() const { return EscapingClosureValue; } |
| |
| /// Retrieve the nonescaping closure expression. |
| Expr *getNonescapingClosureValue() const { |
| return NonescapingClosureValue; |
| } |
| void setNonescapingClosureValue(Expr *e) { |
| NonescapingClosureValue = e; |
| } |
| |
| /// Retrieve the subexpression that has access to the escapable copy of the |
| /// closure. |
| Expr *getSubExpr() const { |
| return SubExpr; |
| } |
| void setSubExpr(Expr *e) { |
| SubExpr = e; |
| } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::MakeTemporarilyEscapable; |
| } |
| }; |
| |
| /// \brief An expression that opens up a value of protocol or protocol |
| /// composition type and gives a name to its dynamic type. |
| /// |
| /// This expression is implicitly created by the type checker when |
| /// calling a method on a protocol. In the future, this may become an |
| /// actual operation within the language. |
| class OpenExistentialExpr : public Expr { |
| Expr *ExistentialValue; |
| OpaqueValueExpr *OpaqueValue; |
| Expr *SubExpr; |
| SourceLoc ExclaimLoc; |
| |
| public: |
| OpenExistentialExpr(Expr *existentialValue, |
| OpaqueValueExpr *opaqueValue, |
| Expr *subExpr, |
| Type subExprTy) |
| : Expr(ExprKind::OpenExistential, /*Implicit=*/ true, subExprTy), |
| ExistentialValue(existentialValue), OpaqueValue(opaqueValue), |
| SubExpr(subExpr) { } |
| |
| SWIFT_FORWARD_SOURCE_LOCS_TO(SubExpr) |
| |
| /// Retrieve the expression that is being evaluated using the |
| /// archetype value. |
| /// |
| /// This subexpression (and no other) may refer to the archetype |
| /// type or the opaque value that stores the archetype's value. |
| Expr *getSubExpr() const { return SubExpr; } |
| |
| /// Set the subexpression that is being evaluated. |
| void setSubExpr(Expr *expr) { SubExpr = expr; } |
| |
| /// Retrieve the existential value that is being opened. |
| Expr *getExistentialValue() const { return ExistentialValue; } |
| |
| /// Set the existential value that is being opened. |
| void setExistentialValue(Expr *expr) { ExistentialValue = expr; } |
| |
| /// Retrieve the opaque value representing the value (of archetype |
| /// type) stored in the existential. |
| OpaqueValueExpr *getOpaqueValue() const { return OpaqueValue; } |
| |
| /// Retrieve the opened archetype, which can only be referenced |
| /// within this expression's subexpression. |
| ArchetypeType *getOpenedArchetype() const; |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::OpenExistential; |
| } |
| }; |
| |
| /// ImplicitConversionExpr - An abstract class for expressions which |
| /// implicitly convert the value of an expression in some way. |
| class ImplicitConversionExpr : public Expr { |
| Expr *SubExpr; |
| |
| protected: |
| ImplicitConversionExpr(ExprKind kind, Expr *subExpr, Type ty) |
| : Expr(kind, /*Implicit=*/true, ty), SubExpr(subExpr) {} |
| |
| public: |
| SWIFT_FORWARD_SOURCE_LOCS_TO(SubExpr) |
| |
| Expr *getSubExpr() const { return SubExpr; } |
| void setSubExpr(Expr *e) { SubExpr = e; } |
| |
| Expr *getSyntacticSubExpr() const { |
| if (auto *ICE = dyn_cast<ImplicitConversionExpr>(SubExpr)) |
| return ICE->getSyntacticSubExpr(); |
| return SubExpr; |
| } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() >= ExprKind::First_ImplicitConversionExpr && |
| E->getKind() <= ExprKind::Last_ImplicitConversionExpr; |
| } |
| }; |
| |
| /// The implicit conversion from a class metatype to AnyObject. |
| class ClassMetatypeToObjectExpr : public ImplicitConversionExpr { |
| public: |
| ClassMetatypeToObjectExpr(Expr *subExpr, Type ty) |
| : ImplicitConversionExpr(ExprKind::ClassMetatypeToObject, subExpr, ty) {} |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::ClassMetatypeToObject; |
| } |
| }; |
| |
| /// The implicit conversion from a class existential metatype to AnyObject. |
| class ExistentialMetatypeToObjectExpr : public ImplicitConversionExpr { |
| public: |
| ExistentialMetatypeToObjectExpr(Expr *subExpr, Type ty) |
| : ImplicitConversionExpr(ExprKind::ExistentialMetatypeToObject, subExpr, ty) {} |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::ExistentialMetatypeToObject; |
| } |
| }; |
| |
| /// The implicit conversion from a protocol value metatype to ObjC's Protocol |
| /// class type. |
| class ProtocolMetatypeToObjectExpr : public ImplicitConversionExpr { |
| public: |
| ProtocolMetatypeToObjectExpr(Expr *subExpr, Type ty) |
| : ImplicitConversionExpr(ExprKind::ProtocolMetatypeToObject, subExpr, ty) {} |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::ProtocolMetatypeToObject; |
| } |
| }; |
| |
| /// InjectIntoOptionalExpr - The implicit conversion from T to T?. |
| class InjectIntoOptionalExpr : public ImplicitConversionExpr { |
| public: |
| InjectIntoOptionalExpr(Expr *subExpr, Type ty) |
| : ImplicitConversionExpr(ExprKind::InjectIntoOptional, subExpr, ty) {} |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::InjectIntoOptional; |
| } |
| }; |
| |
| /// Convert the address of an inout property to a pointer. |
| class InOutToPointerExpr : public ImplicitConversionExpr { |
| public: |
| InOutToPointerExpr(Expr *subExpr, Type ty) |
| : ImplicitConversionExpr(ExprKind::InOutToPointer, subExpr, ty) { |
| Bits.InOutToPointerExpr.IsNonAccessing = false; |
| } |
| |
| /// Is this conversion "non-accessing"? That is, is it only using the |
| /// pointer for its identity, as opposed to actually accessing the memory? |
| bool isNonAccessing() const { |
| return Bits.InOutToPointerExpr.IsNonAccessing; |
| } |
| void setNonAccessing(bool nonAccessing = true) { |
| Bits.InOutToPointerExpr.IsNonAccessing = nonAccessing; |
| } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::InOutToPointer; |
| } |
| }; |
| |
| /// Convert the address of an array to a pointer. |
| class ArrayToPointerExpr : public ImplicitConversionExpr { |
| public: |
| ArrayToPointerExpr(Expr *subExpr, Type ty) |
| : ImplicitConversionExpr(ExprKind::ArrayToPointer, subExpr, ty) { |
| Bits.ArrayToPointerExpr.IsNonAccessing = false; |
| } |
| |
| /// Is this conversion "non-accessing"? That is, is it only using the |
| /// pointer for its identity, as opposed to actually accessing the memory? |
| bool isNonAccessing() const { |
| return Bits.ArrayToPointerExpr.IsNonAccessing; |
| } |
| void setNonAccessing(bool nonAccessing = true) { |
| Bits.ArrayToPointerExpr.IsNonAccessing = nonAccessing; |
| } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::ArrayToPointer; |
| } |
| }; |
| |
| /// Convert the a string to a pointer referencing its encoded representation. |
| class StringToPointerExpr : public ImplicitConversionExpr { |
| public: |
| StringToPointerExpr(Expr *subExpr, Type ty) |
| : ImplicitConversionExpr(ExprKind::StringToPointer, subExpr, ty) {} |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::StringToPointer; |
| } |
| }; |
| |
| /// Convert a pointer to a different kind of pointer. |
| class PointerToPointerExpr : public ImplicitConversionExpr { |
| public: |
| PointerToPointerExpr(Expr *subExpr, Type ty) |
| : ImplicitConversionExpr(ExprKind::PointerToPointer, subExpr, ty) {} |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::PointerToPointer; |
| } |
| }; |
| |
| /// Convert between a foreign object and its corresponding Objective-C object. |
| class ForeignObjectConversionExpr : public ImplicitConversionExpr { |
| public: |
| ForeignObjectConversionExpr(Expr *subExpr, Type ty) |
| : ImplicitConversionExpr(ExprKind::ForeignObjectConversion, subExpr, ty) {} |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::ForeignObjectConversion; |
| } |
| }; |
| |
| /// Construct an unevaluated instance of the underlying metatype. |
| class UnevaluatedInstanceExpr : public ImplicitConversionExpr { |
| public: |
| UnevaluatedInstanceExpr(Expr *subExpr, Type ty) |
| : ImplicitConversionExpr(ExprKind::UnevaluatedInstance, subExpr, ty) {} |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::UnevaluatedInstance; |
| } |
| }; |
| |
| /// TupleShuffleExpr - This represents a permutation of a tuple value to a new |
| /// tuple type. |
| /// |
| /// If hasScalarSource() is true, the subexpression should be treated |
| /// as if it were implicitly injected into a single-element tuple |
| /// type. Otherwise, the subexpression is known to have a tuple type. |
| class TupleShuffleExpr final : public ImplicitConversionExpr, |
| private llvm::TrailingObjects<TupleShuffleExpr, Expr *, int, unsigned> { |
| friend TrailingObjects; |
| |
| size_t numTrailingObjects(OverloadToken<Expr *>) const { |
| return Bits.TupleShuffleExpr.NumCallerDefaultArgs; |
| } |
| size_t numTrailingObjects(OverloadToken<int>) const { |
| return Bits.TupleShuffleExpr.NumElementMappings; |
| } |
| size_t numTrailingObjects(OverloadToken<unsigned>) const { |
| return Bits.TupleShuffleExpr.NumVariadicArgs; |
| } |
| |
| public: |
| enum : int { |
| /// The element mapping value indicating that a field of the destination |
| /// tuple should be default-initialized. |
| DefaultInitialize = -1, |
| /// The element mapping is part of the variadic field. |
| Variadic = -2, |
| /// The element mapping value indicating that the field of the |
| /// destination tuple should be default-initialized with an expression |
| /// provided by the caller. |
| /// FIXME: Yet another indication that TupleShuffleExpr uses the wrong |
| /// formulation. |
| CallerDefaultInitialize = -3 |
| }; |
| |
| enum TypeImpact { |
| /// The source value is a tuple which is destructured and modified to |
| /// create the result, which is a tuple. |
| TupleToTuple, |
| |
| /// The source value is a tuple which is destructured and modified to |
| /// create the result, which is a scalar because it has one element and |
| /// no labels. |
| TupleToScalar, |
| |
| /// The source value is an individual value (possibly one with tuple |
| /// type) which is inserted into a particular position in the result, |
| /// which is a tuple. |
| ScalarToTuple |
| |
| // (TupleShuffleExprs are never created for a scalar-to-scalar conversion.) |
| }; |
| |
| private: |
| /// If we're doing a varargs shuffle, this is the array type to build. |
| Type VarargsArrayTy; |
| |
| /// If there are any default arguments, the owning function |
| /// declaration. |
| ConcreteDeclRef DefaultArgsOwner; |
| |
| TupleShuffleExpr(Expr *subExpr, ArrayRef<int> elementMapping, |
| TypeImpact typeImpact, |
| ConcreteDeclRef defaultArgsOwner, |
| ArrayRef<unsigned> VariadicArgs, |
| Type VarargsArrayTy, |
| ArrayRef<Expr *> CallerDefaultArgs, |
| Type ty) |
| : ImplicitConversionExpr(ExprKind::TupleShuffle, subExpr, ty), |
| VarargsArrayTy(VarargsArrayTy), DefaultArgsOwner(defaultArgsOwner) { |
| Bits.TupleShuffleExpr.TypeImpact = typeImpact; |
| Bits.TupleShuffleExpr.NumCallerDefaultArgs = CallerDefaultArgs.size(); |
| Bits.TupleShuffleExpr.NumElementMappings = elementMapping.size(); |
| Bits.TupleShuffleExpr.NumVariadicArgs = VariadicArgs.size(); |
| std::uninitialized_copy(CallerDefaultArgs.begin(), CallerDefaultArgs.end(), |
| getTrailingObjects<Expr*>()); |
| std::uninitialized_copy(elementMapping.begin(), elementMapping.end(), |
| getTrailingObjects<int>()); |
| std::uninitialized_copy(VariadicArgs.begin(), VariadicArgs.end(), |
| getTrailingObjects<unsigned>()); |
| } |
| |
| public: |
| static TupleShuffleExpr *create(ASTContext &ctx, Expr *subExpr, |
| ArrayRef<int> elementMapping, |
| TypeImpact typeImpact, |
| ConcreteDeclRef defaultArgsOwner, |
| ArrayRef<unsigned> VariadicArgs, |
| Type VarargsArrayTy, |
| ArrayRef<Expr *> CallerDefaultArgs, |
| Type ty); |
| |
| ArrayRef<int> getElementMapping() const { |
| return {getTrailingObjects<int>(), |
| Bits.TupleShuffleExpr.NumElementMappings}; |
| } |
| |
| /// What is the type impact of this shuffle? |
| TypeImpact getTypeImpact() const { |
| return TypeImpact(Bits.TupleShuffleExpr.TypeImpact); |
| } |
| |
| bool isSourceScalar() const { |
| return getTypeImpact() == ScalarToTuple; |
| } |
| |
| bool isResultScalar() const { |
| return getTypeImpact() == TupleToScalar; |
| } |
| |
| Type getVarargsArrayType() const { |
| assert(!VarargsArrayTy.isNull()); |
| return VarargsArrayTy; |
| } |
| Type getVarargsArrayTypeOrNull() const { |
| return VarargsArrayTy; |
| } |
| |
| /// Retrieve the argument indices for the variadic arguments. |
| ArrayRef<unsigned> getVariadicArgs() const { |
| return {getTrailingObjects<unsigned>(), |
| Bits.TupleShuffleExpr.NumVariadicArgs}; |
| } |
| |
| /// Retrieve the owner of the default arguments. |
| ConcreteDeclRef getDefaultArgsOwner() const { return DefaultArgsOwner; } |
| |
| /// Retrieve the caller-defaulted arguments. |
| ArrayRef<Expr *> getCallerDefaultArgs() const { |
| return {getTrailingObjects<Expr*>(), |
| Bits.TupleShuffleExpr.NumCallerDefaultArgs}; |
| } |
| |
| /// Retrieve the caller-defaulted arguments. |
| MutableArrayRef<Expr *> getCallerDefaultArgs() { |
| return {getTrailingObjects<Expr*>(), |
| Bits.TupleShuffleExpr.NumCallerDefaultArgs}; |
| } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::TupleShuffle; |
| } |
| }; |
| |
| /// LoadExpr - Turn an l-value into an r-value by performing a "load" |
| /// operation. This operation may actually be a logical operation, |
| /// i.e. one implemented using a call to a potentially user-defined |
| /// function instead of a simple memory transaction. |
| class LoadExpr : public ImplicitConversionExpr { |
| public: |
| LoadExpr(Expr *subExpr, Type type) |
| : ImplicitConversionExpr(ExprKind::Load, subExpr, type) {} |
| |
| static bool classof(const Expr *E) { return E->getKind() == ExprKind::Load; } |
| }; |
| |
| /// This is a conversion from an expression of UnresolvedType to an arbitrary |
| /// other type, and from an arbitrary type to UnresolvedType. This node does |
| /// not appear in valid code, only in code involving diagnostics. |
| class UnresolvedTypeConversionExpr : public ImplicitConversionExpr { |
| public: |
| UnresolvedTypeConversionExpr(Expr *subExpr, Type type) |
| : ImplicitConversionExpr(ExprKind::UnresolvedTypeConversion, subExpr, type) {} |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::UnresolvedTypeConversion; |
| } |
| }; |
| |
| /// FunctionConversionExpr - Convert a function to another function type, |
| /// which might involve renaming the parameters or handling substitutions |
| /// of subtypes (in the return) or supertypes (in the input). |
| /// |
| /// FIXME: This should be a CapturingExpr. |
| class FunctionConversionExpr : public ImplicitConversionExpr { |
| public: |
| FunctionConversionExpr(Expr *subExpr, Type type) |
| : ImplicitConversionExpr(ExprKind::FunctionConversion, subExpr, type) {} |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::FunctionConversion; |
| } |
| }; |
| |
| /// Perform a function conversion from one function that to one that has a |
| /// covariant result type. |
| /// |
| /// This conversion is technically unsafe; however, semantic analysis will |
| /// only introduce such a conversion in cases where other language features |
| /// (i.e., Self returns) enforce static safety. Additionally, this conversion |
| /// avoids changing the ABI of the function in question. |
| class CovariantFunctionConversionExpr : public ImplicitConversionExpr { |
| public: |
| CovariantFunctionConversionExpr(Expr *subExpr, Type type) |
| : ImplicitConversionExpr(ExprKind::CovariantFunctionConversion, subExpr, |
| type) { } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::CovariantFunctionConversion; |
| } |
| }; |
| |
| /// Perform a conversion from a superclass to a subclass for a call to |
| /// a method with a covariant result type. |
| /// |
| /// This conversion is technically unsafe; however, semantic analysis will |
| /// only introduce such a conversion in cases where other language features |
| /// (i.e., Self returns) enforce static safety. |
| class CovariantReturnConversionExpr : public ImplicitConversionExpr { |
| public: |
| CovariantReturnConversionExpr(Expr *subExpr, Type type) |
| : ImplicitConversionExpr(ExprKind::CovariantReturnConversion, subExpr, |
| type) { } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::CovariantReturnConversion; |
| } |
| }; |
| |
| /// Perform a function conversion from a function returning an |
| /// Optional<T> to a function returning T. |
| /// |
| /// This is generated during expression type checking in places where |
| /// we need to force the result type of a function being called. When |
| /// we go to rewrite the call, we remove this node and force the |
| /// result of the call to the underlying function. It should never |
| /// exist outside of this final stage of expression type checking. |
| class ImplicitlyUnwrappedFunctionConversionExpr |
| : public ImplicitConversionExpr { |
| public: |
| ImplicitlyUnwrappedFunctionConversionExpr(Expr *subExpr, Type type) |
| : ImplicitConversionExpr(ExprKind::ImplicitlyUnwrappedFunctionConversion, |
| subExpr, type) {} |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::ImplicitlyUnwrappedFunctionConversion; |
| } |
| }; |
| |
| /// MetatypeConversionExpr - Convert a metatype to another metatype |
| /// using essentially a derived-to-base conversion. |
| class MetatypeConversionExpr : public ImplicitConversionExpr { |
| public: |
| MetatypeConversionExpr(Expr *subExpr, Type type) |
| : ImplicitConversionExpr(ExprKind::MetatypeConversion, subExpr, type) {} |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::MetatypeConversion; |
| } |
| }; |
| |
| /// CollectionUpcastConversionExpr - Convert a collection whose |
| /// elements have some type T to the same kind of collection whose |
| /// elements have type U, where U is a subtype of T. |
| class CollectionUpcastConversionExpr : public ImplicitConversionExpr { |
| public: |
| struct ConversionPair { |
| OpaqueValueExpr *OrigValue; |
| Expr *Conversion; |
| |
| explicit operator bool() const { return OrigValue != nullptr; } |
| }; |
| private: |
| ConversionPair KeyConversion; |
| ConversionPair ValueConversion; |
| public: |
| CollectionUpcastConversionExpr(Expr *subExpr, Type type, |
| ConversionPair keyConversion, |
| ConversionPair valueConversion) |
| : ImplicitConversionExpr( |
| ExprKind::CollectionUpcastConversion, subExpr, type), |
| KeyConversion(keyConversion), ValueConversion(valueConversion) { |
| assert((!KeyConversion || ValueConversion) |
| && "key conversion without value conversion"); |
| } |
| |
| /// Returns the expression that should be used to perform a |
| /// conversion of the collection's values; null if the conversion |
| /// is formally trivial because the key type does not change. |
| const ConversionPair &getKeyConversion() const { |
| return KeyConversion; |
| } |
| void setKeyConversion(const ConversionPair &pair) { |
| KeyConversion = pair; |
| } |
| |
| /// Returns the expression that should be used to perform a |
| /// conversion of the collection's values; null if the conversion |
| /// is formally trivial because the value type does not change. |
| const ConversionPair &getValueConversion() const { |
| return ValueConversion; |
| } |
| void setValueConversion(const ConversionPair &pair) { |
| ValueConversion = pair; |
| } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::CollectionUpcastConversion; |
| } |
| }; |
| |
| /// ErasureExpr - Perform type erasure by converting a value to existential |
| /// type. For example: |
| /// |
| /// \code |
| /// protocol Printable {} |
| /// struct Book {} |
| /// |
| /// var printable: Printable = Book() // erases type |
| /// var printableType: Printable.Type = Book.self // erases metatype |
| /// \endcode |
| /// |
| /// The type of the expression should always satisfy isAnyExistentialType(). |
| /// |
| /// The type of the sub-expression should always be either: |
| /// - a non-existential type of the appropriate kind or |
| /// - an existential type of the appropriate kind which is a subtype |
| /// of the result type. |
| /// |
| /// "Appropriate kind" means e.g. a concrete/existential metatype if the |
| /// result is an existential metatype. |
| class ErasureExpr final : public ImplicitConversionExpr, |
| private llvm::TrailingObjects<ErasureExpr, ProtocolConformanceRef> { |
| friend TrailingObjects; |
| |
| ErasureExpr(Expr *subExpr, Type type, |
| ArrayRef<ProtocolConformanceRef> conformances) |
| : ImplicitConversionExpr(ExprKind::Erasure, subExpr, type) { |
| Bits.ErasureExpr.NumConformances = conformances.size(); |
| std::uninitialized_copy(conformances.begin(), conformances.end(), |
| getTrailingObjects<ProtocolConformanceRef>()); |
| } |
| |
| public: |
| static ErasureExpr *create(ASTContext &ctx, Expr *subExpr, Type type, |
| ArrayRef<ProtocolConformanceRef> conformances); |
| |
| /// \brief Retrieve the mapping specifying how the type of the subexpression |
| /// maps to the resulting existential type. If the resulting existential |
| /// type involves several different protocols, there will be mappings for each |
| /// of those protocols, in the order in which the existential type expands |
| /// its properties. |
| /// |
| /// The entries in this array may be null, indicating that the conformance |
| /// to the corresponding protocol is trivial (because the source |
| /// type is either an archetype or an existential type that conforms to |
| /// that corresponding protocol). |
| ArrayRef<ProtocolConformanceRef> getConformances() const { |
| return {getTrailingObjects<ProtocolConformanceRef>(), |
| Bits.ErasureExpr.NumConformances }; |
| } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::Erasure; |
| } |
| }; |
| |
| /// AnyHashableErasureExpr - Perform type erasure by converting a value |
| /// to AnyHashable type. |
| /// |
| /// The type of the sub-expression should always be a type that implements |
| /// the Hashable protocol. |
| class AnyHashableErasureExpr : public ImplicitConversionExpr { |
| ProtocolConformanceRef Conformance; |
| |
| public: |
| AnyHashableErasureExpr(Expr *subExpr, Type type, |
| ProtocolConformanceRef conformance) |
| : ImplicitConversionExpr(ExprKind::AnyHashableErasure, subExpr, type), |
| Conformance(conformance) {} |
| |
| /// \brief Retrieve the mapping specifying how the type of the |
| /// subexpression conforms to the Hashable protocol. |
| ProtocolConformanceRef getConformance() const { |
| return Conformance; |
| } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::AnyHashableErasure; |
| } |
| }; |
| |
| /// ConditionalBridgeFromObjCExpr - Bridge a value from a non-native |
| /// representation. |
| class ConditionalBridgeFromObjCExpr : public ImplicitConversionExpr { |
| ConcreteDeclRef Conversion; |
| |
| public: |
| ConditionalBridgeFromObjCExpr(Expr *subExpr, Type type, |
| ConcreteDeclRef conversion) |
| : ImplicitConversionExpr(ExprKind::ConditionalBridgeFromObjC, subExpr, type), |
| Conversion(conversion) { |
| } |
| |
| /// \brief Retrieve the conversion function. |
| ConcreteDeclRef getConversion() const { |
| return Conversion; |
| } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::ConditionalBridgeFromObjC; |
| } |
| }; |
| |
| /// BridgeFromObjCExpr - Bridge a value from a non-native representation. |
| class BridgeFromObjCExpr : public ImplicitConversionExpr { |
| public: |
| BridgeFromObjCExpr(Expr *subExpr, Type type) |
| : ImplicitConversionExpr(ExprKind::BridgeFromObjC, subExpr, type) {} |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::BridgeFromObjC; |
| } |
| }; |
| |
| /// BridgeToObjCExpr - Bridge a value to a non-native representation. |
| class BridgeToObjCExpr : public ImplicitConversionExpr { |
| public: |
| BridgeToObjCExpr(Expr *subExpr, Type type) |
| : ImplicitConversionExpr(ExprKind::BridgeToObjC, subExpr, type) {} |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::BridgeToObjC; |
| } |
| }; |
| |
| /// UnresolvedSpecializeExpr - Represents an explicit specialization using |
| /// a type parameter list (e.g. "Vector<Int>") that has not been resolved. |
| class UnresolvedSpecializeExpr final : public Expr, |
| private llvm::TrailingObjects<UnresolvedSpecializeExpr, TypeLoc> { |
| friend TrailingObjects; |
| |
| Expr *SubExpr; |
| SourceLoc LAngleLoc; |
| SourceLoc RAngleLoc; |
| |
| UnresolvedSpecializeExpr(Expr *SubExpr, |
| SourceLoc LAngleLoc, |
| ArrayRef<TypeLoc> UnresolvedParams, |
| SourceLoc RAngleLoc) |
| : Expr(ExprKind::UnresolvedSpecialize, /*Implicit=*/false), |
| SubExpr(SubExpr), LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc) { |
| Bits.UnresolvedSpecializeExpr.NumUnresolvedParams = UnresolvedParams.size(); |
| std::uninitialized_copy(UnresolvedParams.begin(), UnresolvedParams.end(), |
| getTrailingObjects<TypeLoc>()); |
| } |
| |
| public: |
| static UnresolvedSpecializeExpr * |
| create(ASTContext &ctx, Expr *SubExpr, SourceLoc LAngleLoc, |
| ArrayRef<TypeLoc> UnresolvedParams, SourceLoc RAngleLoc); |
| |
| Expr *getSubExpr() const { return SubExpr; } |
| void setSubExpr(Expr *e) { SubExpr = e; } |
| |
| /// \brief Retrieve the list of type parameters. These parameters have not yet |
| /// been bound to archetypes of the entity to be specialized. |
| ArrayRef<TypeLoc> getUnresolvedParams() const { |
| return {getTrailingObjects<TypeLoc>(), |
| Bits.UnresolvedSpecializeExpr.NumUnresolvedParams}; |
| } |
| MutableArrayRef<TypeLoc> getUnresolvedParams() { |
| return {getTrailingObjects<TypeLoc>(), |
| Bits.UnresolvedSpecializeExpr.NumUnresolvedParams}; |
| } |
| |
| SourceLoc getLoc() const { return LAngleLoc; } |
| SourceLoc getLAngleLoc() const { return LAngleLoc; } |
| SourceLoc getRAngleLoc() const { return RAngleLoc; } |
| |
| SourceLoc getStartLoc() const { return SubExpr->getStartLoc(); } |
| SourceLoc getEndLoc() const { return RAngleLoc; } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::UnresolvedSpecialize; |
| } |
| }; |
| |
| /// \brief Describes an implicit conversion from a subclass to one of its |
| /// superclasses. |
| class DerivedToBaseExpr : public ImplicitConversionExpr { |
| public: |
| DerivedToBaseExpr(Expr *subExpr, Type type) |
| : ImplicitConversionExpr(ExprKind::DerivedToBase, subExpr, type) {} |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::DerivedToBase; |
| } |
| }; |
| |
| /// \brief Describes an implicit conversion from a value of archetype type to |
| /// its concrete superclass. |
| class ArchetypeToSuperExpr : public ImplicitConversionExpr { |
| public: |
| ArchetypeToSuperExpr(Expr *subExpr, Type type) |
| : ImplicitConversionExpr(ExprKind::ArchetypeToSuper, subExpr, type) {} |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::ArchetypeToSuper; |
| } |
| }; |
| |
| /// The builtin unary '&' operator, which converts the |
| /// given lvalue into an 'inout' argument value. |
| class InOutExpr : public Expr { |
| Expr *SubExpr; |
| SourceLoc OperLoc; |
| |
| public: |
| InOutExpr(SourceLoc operLoc, Expr *subExpr, Type baseType, |
| bool isImplicit = false); |
| |
| SourceLoc getStartLoc() const { return OperLoc; } |
| SourceLoc getEndLoc() const { return SubExpr->getEndLoc(); } |
| SourceLoc getLoc() const { return OperLoc; } |
| |
| Expr *getSubExpr() const { return SubExpr; } |
| void setSubExpr(Expr *e) { SubExpr = e; } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::InOut; |
| } |
| }; |
| |
| /// SequenceExpr - A list of binary operations which has not yet been |
| /// folded into a tree. The operands all have even indices, while the |
| /// subexpressions with odd indices are all (potentially overloaded) |
| /// references to binary operators. |
| class SequenceExpr final : public Expr, |
| private llvm::TrailingObjects<SequenceExpr, Expr *> { |
| friend TrailingObjects; |
| |
| SequenceExpr(ArrayRef<Expr*> elements) |
| : Expr(ExprKind::Sequence, /*Implicit=*/false) { |
| Bits.SequenceExpr.NumElements = elements.size(); |
| assert(Bits.SequenceExpr.NumElements > 0 && "zero-length sequence!"); |
| std::uninitialized_copy(elements.begin(), elements.end(), |
| getTrailingObjects<Expr*>()); |
| } |
| |
| public: |
| static SequenceExpr *create(ASTContext &ctx, ArrayRef<Expr*> elements); |
| |
| SourceLoc getStartLoc() const { |
| return getElement(0)->getStartLoc(); |
| } |
| SourceLoc getEndLoc() const { |
| return getElement(getNumElements() - 1)->getEndLoc(); |
| } |
| |
| unsigned getNumElements() const { return Bits.SequenceExpr.NumElements; } |
| |
| MutableArrayRef<Expr*> getElements() { |
| return {getTrailingObjects<Expr*>(), Bits.SequenceExpr.NumElements}; |
| } |
| |
| ArrayRef<Expr*> getElements() const { |
| return {getTrailingObjects<Expr*>(), Bits.SequenceExpr.NumElements}; |
| } |
| |
| Expr *getElement(unsigned i) const { |
| return getElements()[i]; |
| } |
| void setElement(unsigned i, Expr *e) { |
| getElements()[i] = e; |
| } |
| |
| // Implement isa/cast/dyncast/etc. |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::Sequence; |
| } |
| }; |
| |
| |
| /// \brief A base class for closure expressions. |
| class AbstractClosureExpr : public DeclContext, public Expr { |
| CaptureInfo Captures; |
| |
| /// \brief The set of parameters. |
| ParameterList *parameterList; |
| |
| public: |
| AbstractClosureExpr(ExprKind Kind, Type FnType, bool Implicit, |
| unsigned Discriminator, DeclContext *Parent) |
| : DeclContext(DeclContextKind::AbstractClosureExpr, Parent), |
| Expr(Kind, Implicit, FnType), |
| parameterList(nullptr) { |
| Bits.AbstractClosureExpr.Discriminator = Discriminator; |
| } |
| |
| CaptureInfo &getCaptureInfo() { return Captures; } |
| const CaptureInfo &getCaptureInfo() const { return Captures; } |
| |
| /// \brief Retrieve the parameters of this closure. |
| ParameterList *getParameters() { return parameterList; } |
| const ParameterList *getParameters() const { return parameterList; } |
| void setParameterList(ParameterList *P); |
| |
| // Expose this to users. |
| using DeclContext::setParent; |
| |
| /// Returns a discriminator which determines this expression's index |
| /// in the sequence of closure expressions within the current |
| /// function. |
| /// |
| /// There are separate sequences for explicit and implicit closures. |
| /// This allows explicit closures to maintain a stable numbering |
| /// across simple edits that introduce auto closures above them, |
| /// which is the best we can reasonably do. |
| /// |
| /// (Autoclosures are likely to be eliminated immediately, even in |
| /// unoptimized builds, so their names are fairly unimportant. It's |
| /// much more likely that explicit closures will survive |
| /// optimization and therefore make it into e.g. stack traces. |
| /// Having their symbol names be stable across minor code changes is |
| /// therefore pretty useful for debugging.) |
| unsigned getDiscriminator() const { |
| return Bits.AbstractClosureExpr.Discriminator; |
| } |
| void setDiscriminator(unsigned discriminator) { |
| assert(getDiscriminator() == InvalidDiscriminator); |
| assert(discriminator != InvalidDiscriminator); |
| Bits.AbstractClosureExpr.Discriminator = discriminator; |
| } |
| enum : unsigned { InvalidDiscriminator = 0xFFFF }; |
| |
| ArrayRef<ParameterList *> getParameterLists() { |
| return parameterList ? parameterList : ArrayRef<ParameterList *>(); |
| } |
| |
| ArrayRef<const ParameterList *> getParameterLists() const { |
| return parameterList ? parameterList : ArrayRef<const ParameterList *>(); |
| } |
| |
| /// \brief Retrieve the result type of this closure. |
| Type getResultType(llvm::function_ref<Type(const Expr *)> getType = |
| [](const Expr *E) -> Type { |
| return E->getType(); |
| }) const; |
| |
| /// \brief Return whether this closure is throwing when fully applied. |
| bool isBodyThrowing() const; |
| |
| /// Whether this closure consists of a single expression. |
| bool hasSingleExpressionBody() const; |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() >= ExprKind::First_AbstractClosureExpr && |
| E->getKind() <= ExprKind::Last_AbstractClosureExpr; |
| } |
| |
| static bool classof(const DeclContext *DC) { |
| return DC->getContextKind() == DeclContextKind::AbstractClosureExpr; |
| } |
| |
| using DeclContext::operator new; |
| using Expr::dump; |
| }; |
| |
| /// SerializedAbstractClosureExpr - This represents what was originally an |
| /// AbstractClosureExpr during serialization. It is preserved only to maintain |
| /// the correct AST structure and remangling after deserialization. |
| class SerializedAbstractClosureExpr : public SerializedLocalDeclContext { |
| const Type Ty; |
| llvm::PointerIntPair<Type, 1> TypeAndImplicit; |
| const unsigned Discriminator; |
| |
| public: |
| SerializedAbstractClosureExpr(Type Ty, bool Implicit, unsigned Discriminator, |
| DeclContext *Parent) |
| : SerializedLocalDeclContext(LocalDeclContextKind::AbstractClosure, |
| Parent), |
| TypeAndImplicit(llvm::PointerIntPair<Type, 1>(Ty, Implicit)), |
| Discriminator(Discriminator) {} |
| |
| Type getType() const { |
| return TypeAndImplicit.getPointer(); |
| } |
| |
| unsigned getDiscriminator() const { |
| return Discriminator; |
| } |
| |
| bool isImplicit() const { |
| return TypeAndImplicit.getInt(); |
| } |
| |
| static bool classof(const DeclContext *DC) { |
| if (auto LDC = dyn_cast<SerializedLocalDeclContext>(DC)) |
| return LDC->getLocalDeclContextKind() == |
| LocalDeclContextKind::AbstractClosure; |
| return false; |
| } |
| }; |
| |
| /// \brief An explicit unnamed function expression, which can optionally have |
| /// named arguments. |
| /// |
| /// \code |
| /// { $0 + $1 } |
| /// { a, b -> Int in a + b } |
| /// { (a : Int, b : Int) -> Int in a + b } |
| /// { [weak c] (a : Int) -> Int in a + c!.getFoo() } |
| /// \endcode |
| class ClosureExpr : public AbstractClosureExpr { |
| |
| /// The location of the "throws", if present. |
| SourceLoc ThrowsLoc; |
| |
| /// \brief The location of the '->' denoting an explicit return type, |
| /// if present. |
| SourceLoc ArrowLoc; |
| |
| /// The location of the "in", if present. |
| SourceLoc InLoc; |
| |
| /// \brief The explicitly-specified result type. |
| TypeLoc ExplicitResultType; |
| |
| /// \brief The body of the closure, along with a bit indicating whether it |
| /// was originally just a single expression. |
| llvm::PointerIntPair<BraceStmt *, 1, bool> Body; |
| |
| public: |
| ClosureExpr(ParameterList *params, SourceLoc throwsLoc, SourceLoc arrowLoc, |
| SourceLoc inLoc, TypeLoc explicitResultType, |
| unsigned discriminator, DeclContext *parent) |
| : AbstractClosureExpr(ExprKind::Closure, Type(), /*Implicit=*/false, |
| discriminator, parent), |
| ThrowsLoc(throwsLoc), ArrowLoc(arrowLoc), InLoc(inLoc), |
| ExplicitResultType(explicitResultType), |
| Body(nullptr) { |
| setParameterList(params); |
| Bits.ClosureExpr.HasAnonymousClosureVars = false; |
| } |
| |
| SourceRange getSourceRange() const; |
| SourceLoc getStartLoc() const; |
| SourceLoc getEndLoc() const; |
| SourceLoc getLoc() const; |
| |
| BraceStmt *getBody() const { return Body.getPointer(); } |
| void setBody(BraceStmt *S, bool isSingleExpression) { |
| Body.setPointer(S); |
| Body.setInt(isSingleExpression); |
| } |
| |
| /// \brief Determine whether the parameters of this closure are actually |
| /// anonymous closure variables. |
| bool hasAnonymousClosureVars() const { |
| return Bits.ClosureExpr.HasAnonymousClosureVars; |
| } |
| |
| /// \brief Set the parameters of this closure along with a flag indicating |
| /// whether these parameters are actually anonymous closure variables. |
| void setHasAnonymousClosureVars() { |
| Bits.ClosureExpr.HasAnonymousClosureVars = true; |
| } |
| |
| /// \brief Determine whether this closure expression has an |
| /// explicitly-specified result type. |
| bool hasExplicitResultType() const { return ArrowLoc.isValid(); } |
| |
| |
| /// \brief Retrieve the location of the \c '->' for closures with an |
| /// explicit result type. |
| SourceLoc getArrowLoc() const { |
| assert(hasExplicitResultType() && "No arrow location"); |
| return ArrowLoc; |
| } |
| |
| /// \brief Retrieve the location of the \c in for a closure that has it. |
| SourceLoc getInLoc() const { |
| return InLoc; |
| } |
| |
| /// \brief Retrieve the location of the 'throws' for a closure that has it. |
| SourceLoc getThrowsLoc() const { |
| return ThrowsLoc; |
| } |
| |
| /// \brief Retrieve the explicit result type location information. |
| TypeLoc &getExplicitResultTypeLoc() { |
| assert(hasExplicitResultType() && "No explicit result type"); |
| return ExplicitResultType; |
| } |
| |
| void setExplicitResultType(SourceLoc arrowLoc, TypeLoc resultType) { |
| ArrowLoc = arrowLoc; |
| ExplicitResultType = resultType; |
| } |
| |
| /// \brief Determine whether the closure has a single expression for its |
| /// body. |
| /// |
| /// This will be true for closures such as, e.g., |
| /// \code |
| /// { $0 + 1 } |
| /// \endcode |
| /// |
| /// or |
| /// |
| /// \code |
| /// { x, y in x > y } |
| /// \endcode |
| /// |
| /// ... even if the closure has been coerced to return Void by the type |
| /// checker. This function does not return true for empty closures. |
| bool hasSingleExpressionBody() const { |
| return Body.getInt(); |
| } |
| |
| /// \brief Retrieve the body for closure that has a single expression for |
| /// its body. |
| /// |
| /// Only valid when \c hasSingleExpressionBody() is true. |
| Expr *getSingleExpressionBody() const; |
| |
| /// \brief Set the body for a closure that has a single expression as its |
| /// body. |
| /// |
| /// This routine cannot change whether a closure has a single expression as |
| /// its body; it can only update that expression. |
| void setSingleExpressionBody(Expr *NewBody); |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::Closure; |
| } |
| static bool classof(const AbstractClosureExpr *E) { |
| return E->getKind() == ExprKind::Closure; |
| } |
| static bool classof(const DeclContext *C) { |
| return isa<AbstractClosureExpr>(C) && classof(cast<AbstractClosureExpr>(C)); |
| } |
| }; |
| |
| |
| /// \brief This is a closure of the contained subexpression that is formed |
| /// when a scalar expression is converted to @autoclosure function type. |
| /// For example: |
| /// \code |
| /// func f(x : @autoclosure () -> Int) |
| /// f(42) // AutoclosureExpr convert from Int to ()->Int |
| /// \endcode |
| class AutoClosureExpr : public AbstractClosureExpr { |
| BraceStmt *Body; |
| |
| public: |
| AutoClosureExpr(Expr *Body, Type ResultTy, unsigned Discriminator, |
| DeclContext *Parent) |
| : AbstractClosureExpr(ExprKind::AutoClosure, ResultTy, /*Implicit=*/true, |
| Discriminator, Parent) { |
| setBody(Body); |
| } |
| |
| SourceRange getSourceRange() const; |
| SourceLoc getStartLoc() const; |
| SourceLoc getEndLoc() const; |
| SourceLoc getLoc() const; |
| |
| BraceStmt *getBody() const { return Body; } |
| void setBody(Expr *E); |
| |
| // Expose this to users. |
| using DeclContext::setParent; |
| |
| /// Returns the body of the autoclosure as an \c Expr. |
| /// |
| /// The body of an autoclosure always consists of a single expression. |
| Expr *getSingleExpressionBody() const; |
| |
| // Implement isa/cast/dyncast/etc. |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::AutoClosure; |
| } |
| static bool classof(const AbstractClosureExpr *E) { |
| return E->getKind() == ExprKind::AutoClosure; |
| } |
| static bool classof(const DeclContext *C) { |
| return isa<AbstractClosureExpr>(C) && classof(cast<AbstractClosureExpr>(C)); |
| } |
| }; |
| |
| /// Instances of this structure represent elements of the capture list that can |
| /// optionally occur in a capture expression. |
| struct CaptureListEntry { |
| VarDecl *Var; |
| PatternBindingDecl *Init; |
| |
| CaptureListEntry(VarDecl *Var, PatternBindingDecl *Init) |
| : Var(Var), Init(Init) { |
| } |
| }; |
| |
| /// CaptureListExpr - This expression represents the capture list on an explicit |
| /// closure. Because the capture list is evaluated outside of the closure, this |
| /// CaptureList wraps the ClosureExpr. The dynamic semantics are that evaluates |
| /// the variable bindings from the capture list, then evaluates the |
| /// subexpression (the closure itself) and returns the result. |
| class CaptureListExpr final : public Expr, |
| private llvm::TrailingObjects<CaptureListExpr, CaptureListEntry> { |
| friend TrailingObjects; |
| |
| ClosureExpr *closureBody; |
| |
| CaptureListExpr(ArrayRef<CaptureListEntry> captureList, |
| ClosureExpr *closureBody) |
| : Expr(ExprKind::CaptureList, /*Implicit=*/false, Type()), |
| closureBody(closureBody) { |
| Bits.CaptureListExpr.NumCaptures = captureList.size(); |
| std::uninitialized_copy(captureList.begin(), captureList.end(), |
| getTrailingObjects<CaptureListEntry>()); |
| } |
| |
| public: |
| static CaptureListExpr *create(ASTContext &ctx, |
| ArrayRef<CaptureListEntry> captureList, |
| ClosureExpr *closureBody); |
| |
| ArrayRef<CaptureListEntry> getCaptureList() { |
| return {getTrailingObjects<CaptureListEntry>(), |
| Bits.CaptureListExpr.NumCaptures}; |
| } |
| ClosureExpr *getClosureBody() { return closureBody; } |
| const ClosureExpr *getClosureBody() const { return closureBody; } |
| |
| void setClosureBody(ClosureExpr *body) { closureBody = body; } |
| |
| /// This is a bit weird, but the capture list is lexically contained within |
| /// the closure, so the ClosureExpr has the full source range. |
| SWIFT_FORWARD_SOURCE_LOCS_TO(closureBody) |
| |
| // Implement isa/cast/dyncast/etc. |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::CaptureList; |
| } |
| }; |
| |
| /// DynamicTypeExpr - "type(of: base)" - Produces a metatype value. |
| /// |
| /// The metatype value comes from evaluating an expression then retrieving the |
| /// metatype of the result. |
| class DynamicTypeExpr : public Expr { |
| SourceLoc KeywordLoc; |
| SourceLoc LParenLoc; |
| Expr *Base; |
| SourceLoc RParenLoc; |
| |
| public: |
| explicit DynamicTypeExpr(SourceLoc KeywordLoc, SourceLoc LParenLoc, |
| Expr *Base, SourceLoc RParenLoc, Type Ty) |
| : Expr(ExprKind::DynamicType, /*Implicit=*/false, Ty), |
| KeywordLoc(KeywordLoc), LParenLoc(LParenLoc), Base(Base), |
| RParenLoc(RParenLoc) { } |
| |
| Expr *getBase() const { return Base; } |
| void setBase(Expr *base) { Base = base; } |
| |
| SourceLoc getLoc() const { return KeywordLoc; } |
| SourceRange getSourceRange() const { |
| return SourceRange(KeywordLoc, RParenLoc); |
| } |
| |
| SourceLoc getStartLoc() const { |
| return KeywordLoc; |
| } |
| SourceLoc getEndLoc() const { |
| return RParenLoc; |
| } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::DynamicType; |
| } |
| }; |
| |
| /// An expression referring to an opaque object of a fixed type. |
| /// |
| /// Opaque value expressions occur when a particular value within the AST |
| /// needs to be re-used without being re-evaluated or for a value that is |
| /// a placeholder. OpaqueValueExpr nodes are introduced by some other AST |
| /// node (say, a \c DynamicMemberRefExpr) and can only be used within the |
| /// subexpressions of that AST node. |
| class OpaqueValueExpr : public Expr { |
| SourceLoc Loc; |
| |
| public: |
| explicit OpaqueValueExpr(SourceLoc Loc, Type Ty) |
| : Expr(ExprKind::OpaqueValue, /*Implicit=*/true, Ty), Loc(Loc) { } |
| |
| SourceRange getSourceRange() const { return Loc; } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::OpaqueValue; |
| } |
| }; |
| |
| /// ApplyExpr - Superclass of various function calls, which apply an argument to |
| /// a function to get a result. |
| class ApplyExpr : public Expr { |
| /// The function being called. |
| Expr *Fn; |
| |
| /// The argument being passed to it, and whether it's a 'super' argument. |
| llvm::PointerIntPair<Expr *, 1, bool> ArgAndIsSuper; |
| |
| protected: |
| ApplyExpr(ExprKind Kind, Expr *Fn, Expr *Arg, bool Implicit, Type Ty = Type()) |
| : Expr(Kind, Implicit, Ty), Fn(Fn), ArgAndIsSuper(Arg, false) { |
| assert(classof((Expr*)this) && "ApplyExpr::classof out of date"); |
| Bits.ApplyExpr.ThrowsIsSet = false; |
| } |
| |
| public: |
| Expr *getFn() const { return Fn; } |
| void setFn(Expr *e) { Fn = e; } |
| Expr *getSemanticFn() const { return Fn->getSemanticsProvidingExpr(); } |
| |
| Expr *getArg() const { return ArgAndIsSuper.getPointer(); } |
| void setArg(Expr *e) { |
| assert((getKind() != ExprKind::Binary || isa<TupleExpr>(e)) && |
| "BinaryExprs must have a TupleExpr as the argument"); |
| ArgAndIsSuper = {e, ArgAndIsSuper.getInt()}; |
| } |
| |
| bool isSuper() const { return ArgAndIsSuper.getInt(); } |
| void setIsSuper(bool super) { |
| ArgAndIsSuper = {ArgAndIsSuper.getPointer(), super}; |
| } |
| |
| /// Has the type-checker set the 'throws' bit yet? |
| /// |
| /// In general, this should only be used for debugging purposes. |
| bool isThrowsSet() const { return Bits.ApplyExpr.ThrowsIsSet; } |
| |
| /// Does this application throw? This is only meaningful after |
| /// complete type-checking. |
| /// |
| /// If true, the function expression must have a throwing function |
| /// type. The converse is not true because of 'rethrows' functions. |
| bool throws() const { |
| assert(Bits.ApplyExpr.ThrowsIsSet); |
| return Bits.ApplyExpr.Throws; |
| } |
| void setThrows(bool throws) { |
| assert(!Bits.ApplyExpr.ThrowsIsSet); |
| Bits.ApplyExpr.ThrowsIsSet = true; |
| Bits.ApplyExpr.Throws = throws; |
| } |
| |
| ValueDecl *getCalledValue() const; |
| |
| /// Retrieve the argument labels provided at the call site. |
| /// |
| /// \param scratch Scratch space that will be used when the argument labels |
| /// aren't already stored in the AST context. |
| ArrayRef<Identifier> |
| getArgumentLabels(SmallVectorImpl<Identifier> &scratch) const; |
| |
| /// Whether this application was written using a trailing closure. |
| bool hasTrailingClosure() const; |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() >= ExprKind::First_ApplyExpr && |
| E->getKind() <= ExprKind::Last_ApplyExpr; |
| } |
| }; |
| |
| /// CallExpr - Application of an argument to a function, which occurs |
| /// syntactically through juxtaposition with a TupleExpr whose |
| /// leading '(' is unspaced. |
| class CallExpr final : public ApplyExpr, |
| public TrailingCallArguments<CallExpr> { |
| friend TrailingCallArguments; |
| |
| CallExpr(Expr *fn, Expr *arg, bool Implicit, |
| ArrayRef<Identifier> argLabels, |
| ArrayRef<SourceLoc> argLabelLocs, |
| bool hasTrailingClosure, |
| Type ty); |
| |
| public: |
| /// Create a new call expression. |
| /// |
| /// Note: prefer to use the entry points that separate out the arguments. |
| static CallExpr * |
| create(ASTContext &ctx, Expr *fn, Expr *arg, ArrayRef<Identifier> argLabels, |
| ArrayRef<SourceLoc> argLabelLocs, bool hasTrailingClosure, |
| bool implicit, Type type = Type(), |
| llvm::function_ref<Type(const Expr *)> getType = |
| [](const Expr *E) -> Type { return E->getType(); }); |
| |
| /// Create a new implicit call expression without any source-location |
| /// information. |
| /// |
| /// \param fn The function being called |
| /// \param args The call arguments, not including a trailing closure (if any). |
| /// \param argLabels The argument labels, whose size must equal args.size(), |
| /// or which must be empty. |
| static CallExpr * |
| createImplicit(ASTContext &ctx, Expr *fn, ArrayRef<Expr *> args, |
| ArrayRef<Identifier> argLabels, |
| llvm::function_ref<Type(const Expr *)> getType = |
| [](const Expr *E) -> Type { return E->getType(); }) { |
| return create(ctx, fn, SourceLoc(), args, argLabels, { }, SourceLoc(), |
| /*trailingClosure=*/nullptr, /*implicit=*/true, getType); |
| } |
| |
| /// Create a new call expression. |
| /// |
| /// \param fn The function being called |
| /// \param args The call arguments, not including a trailing closure (if any). |
| /// \param argLabels The argument labels, whose size must equal args.size(), |
| /// or which must be empty. |
| /// \param argLabelLocs The locations of the argument labels, whose size must |
| /// equal args.size() or which must be empty. |
| /// \param trailingClosure The trailing closure, if any. |
| static CallExpr * |
| create(ASTContext &ctx, Expr *fn, SourceLoc lParenLoc, ArrayRef<Expr *> args, |
| ArrayRef<Identifier> argLabels, ArrayRef<SourceLoc> argLabelLocs, |
| SourceLoc rParenLoc, Expr *trailingClosure, bool implicit, |
| llvm::function_ref<Type(const Expr *)> getType = |
| [](const Expr *E) -> Type { return E->getType(); }); |
| |
| SourceLoc getStartLoc() const { |
| SourceLoc fnLoc = getFn()->getStartLoc(); |
| return (fnLoc.isValid() ? fnLoc : getArg()->getStartLoc()); |
| } |
| SourceLoc getEndLoc() const { |
| SourceLoc argLoc = getArg()->getEndLoc(); |
| return (argLoc.isValid() ? argLoc : getFn()->getEndLoc()); |
| } |
| |
| SourceLoc getLoc() const { |
| SourceLoc FnLoc = getFn()->getLoc(); |
| return FnLoc.isValid() ? FnLoc : getArg()->getLoc(); |
| } |
| |
| unsigned getNumArguments() const { return Bits.CallExpr.NumArgLabels; } |
| bool hasArgumentLabelLocs() const { return Bits.CallExpr.HasArgLabelLocs; } |
| |
| /// Whether this call with written with a trailing closure. |
| bool hasTrailingClosure() const { return Bits.CallExpr.HasTrailingClosure; } |
| |
| using TrailingCallArguments::getArgumentLabels; |
| |
| /// Retrieve the expression that directly represents the callee. |
| /// |
| /// The "direct" callee is the expression representing the callee |
| /// after looking through top-level constructs that don't affect the |
| /// identity of the callee, e.g., extra parentheses, optional |
| /// unwrapping (?)/forcing (!), etc. |
| Expr *getDirectCallee() const; |
| |
| static bool classof(const Expr *E) { return E->getKind() == ExprKind::Call; } |
| }; |
| |
| /// PrefixUnaryExpr - Prefix unary expressions like '!y'. |
| class PrefixUnaryExpr : public ApplyExpr { |
| public: |
| PrefixUnaryExpr(Expr *Fn, Expr *Arg, Type Ty = Type()) |
| : ApplyExpr(ExprKind::PrefixUnary, Fn, Arg, /*Implicit=*/false, Ty) {} |
| |
| SourceLoc getLoc() const { return getFn()->getStartLoc(); } |
| |
| SourceLoc getStartLoc() const { |
| return getFn()->getStartLoc(); |
| } |
| SourceLoc getEndLoc() const { |
| return getArg()->getEndLoc(); |
| } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::PrefixUnary; |
| } |
| }; |
| |
| /// PostfixUnaryExpr - Prefix unary expressions like '!y'. |
| class PostfixUnaryExpr : public ApplyExpr { |
| public: |
| PostfixUnaryExpr(Expr *Fn, Expr *Arg, Type Ty = Type()) |
| : ApplyExpr(ExprKind::PostfixUnary, Fn, Arg, /*Implicit=*/false, Ty) {} |
| |
| SourceLoc getLoc() const { return getFn()->getStartLoc(); } |
| |
| SourceLoc getStartLoc() const { |
| return getArg()->getStartLoc(); |
| } |
| SourceLoc getEndLoc() const { |
| return getFn()->getEndLoc(); |
| } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::PostfixUnary; |
| } |
| }; |
| |
| /// BinaryExpr - Infix binary expressions like 'x+y'. The argument is always |
| /// an implicit tuple expression of the type expected by the function. |
| class BinaryExpr : public ApplyExpr { |
| public: |
| BinaryExpr(Expr *Fn, TupleExpr *Arg, bool Implicit, Type Ty = Type()) |
| : ApplyExpr(ExprKind::Binary, Fn, Arg, Implicit, Ty) {} |
| |
| SourceLoc getLoc() const { return getFn()->getLoc(); } |
| |
| SourceRange getSourceRange() const { return getArg()->getSourceRange(); } |
| SourceLoc getStartLoc() const { return getArg()->getStartLoc(); } |
| SourceLoc getEndLoc() const { return getArg()->getEndLoc(); } |
| |
| TupleExpr *getArg() const { return cast<TupleExpr>(ApplyExpr::getArg()); } |
| |
| static bool classof(const Expr *E) { return E->getKind() == ExprKind::Binary;} |
| }; |
| |
| /// SelfApplyExpr - Abstract application that provides the 'self' pointer for |
| /// a method curried as (this : Self) -> (params) -> result. |
| /// |
| /// The application of a curried method to 'self' semantically differs from |
| /// normal function application because the 'self' parameter can be implicitly |
| /// materialized from an rvalue. |
| class SelfApplyExpr : public ApplyExpr { |
| protected: |
| SelfApplyExpr(ExprKind K, Expr *FnExpr, Expr *BaseExpr, Type Ty) |
| : ApplyExpr(K, FnExpr, BaseExpr, FnExpr->isImplicit(), Ty) { } |
| |
| public: |
| Expr *getBase() const { return getArg(); } |
| void setBase(Expr *E) { setArg(E); } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() >= ExprKind::First_SelfApplyExpr && |
| E->getKind() <= ExprKind::Last_SelfApplyExpr; |
| } |
| }; |
| |
| /// DotSyntaxCallExpr - Refer to a method of a type, e.g. P.x. 'x' |
| /// is modeled as a DeclRefExpr or OverloadSetRefExpr on the method. |
| class DotSyntaxCallExpr : public SelfApplyExpr { |
| SourceLoc DotLoc; |
| |
| public: |
| DotSyntaxCallExpr(Expr *FnExpr, SourceLoc DotLoc, Expr *BaseExpr, |
| Type Ty = Type()) |
| : SelfApplyExpr(ExprKind::DotSyntaxCall, FnExpr, BaseExpr, Ty), |
| DotLoc(DotLoc) { |
| setImplicit(DotLoc.isInvalid()); |
| } |
| |
| SourceLoc getDotLoc() const { return DotLoc; } |
| |
| SourceLoc getLoc() const { |
| return isImplicit() ? getBase()->getStartLoc() : getFn()->getLoc(); |
| } |
| SourceLoc getStartLoc() const { |
| return getBase()->getStartLoc(); |
| } |
| SourceLoc getEndLoc() const { |
| return isImplicit() ? getBase()->getEndLoc() : getFn()->getEndLoc(); |
| } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::DotSyntaxCall; |
| } |
| }; |
| |
| /// ConstructorRefCallExpr - Refer to a constructor for a type P. The |
| /// actual reference to function which returns the constructor is modeled |
| /// as a DeclRefExpr. |
| class ConstructorRefCallExpr : public SelfApplyExpr { |
| public: |
| ConstructorRefCallExpr(Expr *FnExpr, Expr *BaseExpr, Type Ty = Type()) |
| : SelfApplyExpr(ExprKind::ConstructorRefCall, FnExpr, BaseExpr, Ty) {} |
| |
| SourceLoc getLoc() const { return getFn()->getLoc(); } |
| SourceLoc getStartLoc() const { return getBase()->getStartLoc(); } |
| SourceLoc getEndLoc() const { return getFn()->getEndLoc(); } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::ConstructorRefCall; |
| } |
| }; |
| |
| /// DotSyntaxBaseIgnoredExpr - When a.b resolves to something that does not need |
| /// the actual value of the base (e.g. when applied to a metatype, module, or |
| /// the base of a 'static' function) this expression node is created. The |
| /// semantics are that its base is evaluated and discarded, then 'b' is |
| /// evaluated and returned as the result of the expression. |
| class DotSyntaxBaseIgnoredExpr : public Expr { |
| Expr *LHS; |
| SourceLoc DotLoc; |
| Expr *RHS; |
| public: |
| DotSyntaxBaseIgnoredExpr(Expr *LHS, SourceLoc DotLoc, Expr *RHS, Type rhsTy) |
| : Expr(ExprKind::DotSyntaxBaseIgnored, /*Implicit=*/false, rhsTy), |
| LHS(LHS), DotLoc(DotLoc), RHS(RHS) { |
| } |
| |
| Expr *getLHS() const { return LHS; } |
| void setLHS(Expr *E) { LHS = E; } |
| SourceLoc getDotLoc() const { return DotLoc; } |
| Expr *getRHS() const { return RHS; } |
| void setRHS(Expr *E) { RHS = E; } |
| |
| SourceLoc getStartLoc() const { |
| return DotLoc.isValid() ? LHS->getStartLoc() : RHS->getStartLoc(); |
| } |
| SourceLoc getEndLoc() const { return RHS->getEndLoc(); } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::DotSyntaxBaseIgnored; |
| } |
| }; |
| |
| /// \brief Represents an explicit cast, 'a as T' or 'a is T', where "T" is a |
| /// type, and "a" is the expression that will be converted to the type. |
| class ExplicitCastExpr : public Expr { |
| Expr *SubExpr; |
| SourceLoc AsLoc; |
| TypeLoc CastTy; |
| |
| protected: |
| ExplicitCastExpr(ExprKind kind, Expr *sub, SourceLoc AsLoc, TypeLoc castTy, |
| Type resultTy) |
| : Expr(kind, /*Implicit=*/false), SubExpr(sub), AsLoc(AsLoc), CastTy(castTy) |
| {} |
| |
| public: |
| Expr *getSubExpr() const { return SubExpr; } |
| |
| /// Get the type syntactically spelled in the cast. For some forms of checked |
| /// cast this is different from the result type of the expression. |
| TypeLoc &getCastTypeLoc() { return CastTy; } |
| |
| /// Get the type syntactically spelled in the cast. For some forms of checked |
| /// cast this is different from the result type of the expression. |
| TypeLoc getCastTypeLoc() const { return CastTy; } |
| |
| void setSubExpr(Expr *E) { SubExpr = E; } |
| |
| SourceLoc getLoc() const { |
| if (AsLoc.isValid()) |
| return AsLoc; |
| |
| return SubExpr->getLoc(); |
| } |
| |
| SourceLoc getAsLoc() const { |
| return AsLoc; |
| } |
| |
| SourceRange getSourceRange() const { |
| SourceRange castTyRange = CastTy.getSourceRange(); |
| if (castTyRange.isInvalid()) |
| return SubExpr->getSourceRange(); |
| |
| auto startLoc = SubExpr ? SubExpr->getStartLoc() : AsLoc; |
| auto endLoc = castTyRange.End; |
| |
| return {startLoc, endLoc}; |
| } |
| |
| /// True if the node has been processed by SequenceExpr folding. |
| bool isFolded() const { return SubExpr; } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() >= ExprKind::First_ExplicitCastExpr && |
| E->getKind() <= ExprKind::Last_ExplicitCastExpr; |
| } |
| }; |
| |
| /// Return a string representation of a CheckedCastKind. |
| StringRef getCheckedCastKindName(CheckedCastKind kind); |
| |
| /// \brief Abstract base class for checked casts 'as' and 'is'. These represent |
| /// casts that can dynamically fail. |
| class CheckedCastExpr : public ExplicitCastExpr { |
| public: |
| CheckedCastExpr(ExprKind kind, |
| Expr *sub, SourceLoc asLoc, TypeLoc castTy, Type resultTy) |
| : ExplicitCastExpr(kind, sub, asLoc, castTy, resultTy) |
| { |
| Bits.CheckedCastExpr.CastKind = unsigned(CheckedCastKind::Unresolved); |
| } |
| |
| /// Return the semantic kind of cast performed. |
| CheckedCastKind getCastKind() const { |
| return CheckedCastKind(Bits.CheckedCastExpr.CastKind); |
| } |
| void setCastKind(CheckedCastKind kind) { |
| Bits.CheckedCastExpr.CastKind = unsigned(kind); |
| } |
| |
| /// True if the cast has been type-checked and its kind has been set. |
| bool isResolved() const { |
| return getCastKind() >= CheckedCastKind::First_Resolved; |
| } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() >= ExprKind::First_CheckedCastExpr |
| && E->getKind() <= ExprKind::Last_CheckedCastExpr; |
| } |
| }; |
| |
| /// Represents an explicit forced checked cast, which converts |
| /// from a value of some type to some specified subtype and fails dynamically |
| /// if the value does not have that type. |
| /// Spelled 'a as! T' and produces a value of type 'T'. |
| class ForcedCheckedCastExpr : public CheckedCastExpr { |
| SourceLoc ExclaimLoc; |
| |
| public: |
| ForcedCheckedCastExpr(Expr *sub, SourceLoc asLoc, SourceLoc exclaimLoc, |
| TypeLoc type) |
| : CheckedCastExpr(ExprKind::ForcedCheckedCast, |
| sub, asLoc, type, type.getType()), |
| ExclaimLoc(exclaimLoc) |
| { |
| } |
| |
| ForcedCheckedCastExpr(SourceLoc asLoc, SourceLoc exclaimLoc, TypeLoc type) |
| : ForcedCheckedCastExpr(nullptr, asLoc, exclaimLoc, type) |
| { |
| } |
| |
| /// Retrieve the location of the '!' that follows 'as'. |
| SourceLoc getExclaimLoc() const { return ExclaimLoc; } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::ForcedCheckedCast; |
| } |
| }; |
| |
| /// \brief Represents an explicit conditional checked cast, which converts |
| /// from a type to some subtype and produces an Optional value, which will be |
| /// .Some(x) if the cast succeeds, or .None if the cast fails. |
| /// Spelled 'a as? T' and produces a value of type 'T?'. |
| class ConditionalCheckedCastExpr : public CheckedCastExpr { |
| SourceLoc QuestionLoc; |
| |
| public: |
| ConditionalCheckedCastExpr(Expr *sub, SourceLoc asLoc, SourceLoc questionLoc, |
| TypeLoc type) |
| : CheckedCastExpr(ExprKind::ConditionalCheckedCast, |
| sub, asLoc, type, type.getType()), |
| QuestionLoc(questionLoc) |
| { } |
| |
| ConditionalCheckedCastExpr(SourceLoc asLoc, SourceLoc questionLoc, |
| TypeLoc type) |
| : ConditionalCheckedCastExpr(nullptr, asLoc, questionLoc, type) |
| {} |
| |
| /// Retrieve the location of the '?' that follows 'as'. |
| SourceLoc getQuestionLoc() const { return QuestionLoc; } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::ConditionalCheckedCast; |
| } |
| }; |
| |
| /// \brief Represents a runtime type check query, 'a is T', where 'T' is a type |
| /// and 'a' is a value of some related type. Evaluates to a Bool true if 'a' is |
| /// of the type and 'a as T' would succeed, false otherwise. |
| /// |
| /// FIXME: We should support type queries with a runtime metatype value too. |
| class IsExpr : public CheckedCastExpr { |
| public: |
| IsExpr(Expr *sub, SourceLoc isLoc, TypeLoc type) |
| : CheckedCastExpr(ExprKind::Is, |
| sub, isLoc, type, Type()) |
| {} |
| |
| IsExpr(SourceLoc isLoc, TypeLoc type) |
| : IsExpr(nullptr, isLoc, type) |
| {} |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::Is; |
| } |
| }; |
| |
| /// \brief Represents an explicit coercion from a value to a specific type. |
| /// |
| /// Spelled 'a as T' and produces a value of type 'T'. |
| class CoerceExpr : public ExplicitCastExpr { |
| public: |
| CoerceExpr(Expr *sub, SourceLoc asLoc, TypeLoc type) |
| : ExplicitCastExpr(ExprKind::Coerce, sub, asLoc, type, type.getType()) |
| { } |
| |
| CoerceExpr(SourceLoc asLoc, TypeLoc type) |
| : CoerceExpr(nullptr, asLoc, type) |
| { } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::Coerce; |
| } |
| }; |
| |
| /// \brief Represents two expressions joined by the arrow operator '->', which |
| /// may be preceded by the 'throws' keyword. Currently this only exists to be |
| /// transformed into a FunctionTypeRepr by simplifyTypeExpr() in Sema. |
| class ArrowExpr : public Expr { |
| SourceLoc ThrowsLoc; |
| SourceLoc ArrowLoc; |
| Expr *Args; |
| Expr *Result; |
| public: |
| ArrowExpr(Expr *Args, SourceLoc ThrowsLoc, SourceLoc ArrowLoc, Expr *Result) |
| : Expr(ExprKind::Arrow, /*implicit=*/false, Type()), |
| ThrowsLoc(ThrowsLoc), ArrowLoc(ArrowLoc), Args(Args), Result(Result) |
| { } |
| |
| ArrowExpr(SourceLoc ThrowsLoc, SourceLoc ArrowLoc) |
| : Expr(ExprKind::Arrow, /*implicit=*/false, Type()), |
| ThrowsLoc(ThrowsLoc), ArrowLoc(ArrowLoc), Args(nullptr), Result(nullptr) |
| { } |
| |
| Expr *getArgsExpr() const { return Args; } |
| void setArgsExpr(Expr *E) { Args = E; } |
| Expr *getResultExpr() const { return Result; } |
| void setResultExpr(Expr *E) { Result = E; } |
| SourceLoc getThrowsLoc() const { return ThrowsLoc; } |
| SourceLoc getArrowLoc() const { return ArrowLoc; } |
| bool isFolded() const { return Args != nullptr && Result != nullptr; } |
| |
| SourceLoc getSourceLoc() const { return ArrowLoc; } |
| SourceLoc getStartLoc() const { |
| return isFolded() ? Args->getStartLoc() : |
| ThrowsLoc.isValid() ? ThrowsLoc : ArrowLoc; |
| } |
| SourceLoc getEndLoc() const { |
| return isFolded() ? Result->getEndLoc() : ArrowLoc; |
| } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::Arrow; |
| } |
| }; |
| |
| /// \brief Represents the rebinding of 'self' in a constructor that calls out |
| /// to another constructor. The result of the subexpression is assigned to |
| /// 'self', and the expression returns void. |
| /// |
| /// When a super.init or delegating initializer is invoked, 'self' is |
| /// reassigned to the result of the initializer (after being downcast in the |
| /// case of super.init). |
| /// |
| /// This is needed for reference types with ObjC interop, where |
| /// reassigning 'self' is a supported feature, and for value type delegating |
| /// constructors, where the delegatee constructor is responsible for |
| /// initializing 'self' in-place before the delegator's logic executes. |
| class RebindSelfInConstructorExpr : public Expr { |
| Expr *SubExpr; |
| VarDecl *Self; |
| public: |
| RebindSelfInConstructorExpr(Expr *SubExpr, VarDecl *Self); |
| |
| SWIFT_FORWARD_SOURCE_LOCS_TO(SubExpr) |
| |
| VarDecl *getSelf() const { return Self; } |
| Expr *getSubExpr() const { return SubExpr; } |
| void setSubExpr(Expr *Sub) { SubExpr = Sub; } |
| |
| OtherConstructorDeclRefExpr *getCalledConstructor(bool &isChainToSuper) const; |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::RebindSelfInConstructor; |
| } |
| }; |
| |
| /// \brief The conditional expression 'x ? y : z'. |
| class IfExpr : public Expr { |
| Expr *CondExpr, *ThenExpr, *ElseExpr; |
| SourceLoc QuestionLoc, ColonLoc; |
| public: |
| IfExpr(Expr *CondExpr, |
| SourceLoc QuestionLoc, Expr *ThenExpr, |
| SourceLoc ColonLoc, Expr *ElseExpr, |
| Type Ty = Type()) |
| : Expr(ExprKind::If, /*Implicit=*/false, Ty), |
| CondExpr(CondExpr), ThenExpr(ThenExpr), ElseExpr(ElseExpr), |
| QuestionLoc(QuestionLoc), ColonLoc(ColonLoc) |
| {} |
| |
| IfExpr(SourceLoc QuestionLoc, Expr *ThenExpr, SourceLoc ColonLoc) |
| : IfExpr(nullptr, QuestionLoc, ThenExpr, ColonLoc, nullptr) |
| {} |
| |
| SourceLoc getLoc() const { return QuestionLoc; } |
| SourceLoc getStartLoc() const { |
| return (isFolded() ? CondExpr->getStartLoc() : QuestionLoc); |
| } |
| SourceLoc getEndLoc() const { |
| return (isFolded() ? ElseExpr->getEndLoc() : ColonLoc); |
| } |
| SourceLoc getQuestionLoc() const { return QuestionLoc; } |
| SourceLoc getColonLoc() const { return ColonLoc; } |
| |
| Expr *getCondExpr() const { return CondExpr; } |
| void setCondExpr(Expr *E) { CondExpr = E; } |
| |
| Expr *getThenExpr() const { return ThenExpr; } |
| void setThenExpr(Expr *E) { ThenExpr = E; } |
| |
| Expr *getElseExpr() const { return ElseExpr; } |
| void setElseExpr(Expr *E) { ElseExpr = E; } |
| |
| /// True if the node has been processed by binary expression folding. |
| bool isFolded() const { return CondExpr && ElseExpr; } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::If; |
| } |
| }; |
| |
| /// EnumIsCaseExpr - A boolean expression that is true if an enum value is of |
| /// a particular case. |
| class EnumIsCaseExpr : public Expr { |
| Expr *SubExpr; |
| EnumElementDecl *Element; |
| |
| public: |
| EnumIsCaseExpr(Expr *SubExpr, EnumElementDecl *Element) |
| : Expr(ExprKind::EnumIsCase, /*implicit*/ true), |
| SubExpr(SubExpr), Element(Element) |
| {} |
| |
| Expr *getSubExpr() const { return SubExpr; } |
| void setSubExpr(Expr *e) { SubExpr = e; } |
| |
| EnumElementDecl *getEnumElement() const { return Element; } |
| void setEnumElement(EnumElementDecl *elt) { Element = elt; } |
| |
| SourceLoc getLoc() const { return SubExpr->getLoc(); } |
| SourceLoc getStartLoc() const { return SubExpr->getStartLoc(); } |
| SourceLoc getEndLoc() const { return SubExpr->getEndLoc(); } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::EnumIsCase; |
| } |
| }; |
| |
| /// AssignExpr - A value assignment, like "x = y". |
| class AssignExpr : public Expr { |
| Expr *Dest; |
| Expr *Src; |
| SourceLoc EqualLoc; |
| |
| public: |
| AssignExpr(Expr *Dest, SourceLoc EqualLoc, Expr *Src, bool Implicit) |
| : Expr(ExprKind::Assign, Implicit), |
| Dest(Dest), Src(Src), EqualLoc(EqualLoc) {} |
| |
| AssignExpr(SourceLoc EqualLoc) |
| : AssignExpr(nullptr, EqualLoc, nullptr, /*Implicit=*/false) |
| {} |
| |
| Expr *getDest() const { return Dest; } |
| void setDest(Expr *e) { Dest = e; } |
| Expr *getSrc() const { return Src; } |
| void setSrc(Expr *e) { Src = e; } |
| |
| SourceLoc getEqualLoc() const { return EqualLoc; } |
| |
| SourceLoc getLoc() const { |
| SourceLoc loc = EqualLoc; |
| if (loc.isValid()) { |
| return loc; |
| } |
| return getStartLoc(); |
| } |
| SourceLoc getStartLoc() const { |
| if (!isFolded()) return EqualLoc; |
| return ( Dest->getStartLoc().isValid() |
| ? Dest->getStartLoc() |
| : Src->getStartLoc()); |
| } |
| SourceLoc getEndLoc() const { |
| if (!isFolded()) return EqualLoc; |
| return (Src->getEndLoc().isValid() ? Src->getEndLoc() : Dest->getEndLoc()); |
| } |
| |
| /// True if the node has been processed by binary expression folding. |
| bool isFolded() const { return Dest && Src; } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::Assign; |
| } |
| }; |
| |
| /// \brief A pattern production that has been parsed but hasn't been resolved |
| /// into a complete pattern. Name binding converts these into standalone pattern |
| /// nodes or raises an error if a pattern production appears in an invalid |
| /// position. |
| class UnresolvedPatternExpr : public Expr { |
| Pattern *subPattern; |
| |
| public: |
| explicit UnresolvedPatternExpr(Pattern *subPattern) |
| : Expr(ExprKind::UnresolvedPattern, /*Implicit=*/false), |
| subPattern(subPattern) { } |
| |
| const Pattern *getSubPattern() const { return subPattern; } |
| Pattern *getSubPattern() { return subPattern; } |
| void setSubPattern(Pattern *p) { subPattern = p; } |
| |
| SourceRange getSourceRange() const; |
| SourceLoc getStartLoc() const; |
| SourceLoc getEndLoc() const; |
| SourceLoc getLoc() const; |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::UnresolvedPattern; |
| } |
| }; |
| |
| |
| /// An editor placeholder (<#such as this#>) that occurred in an expression |
| /// context. If the placeholder is a typed one (see \c EditorPlaceholderData) |
| /// its type string will be typechecked and will be associated with this expr. |
| class EditorPlaceholderExpr : public Expr { |
| Identifier Placeholder; |
| SourceLoc Loc; |
| TypeLoc PlaceholderTy; |
| TypeRepr *ExpansionTyR; |
| Expr *SemanticExpr; |
| |
| public: |
| EditorPlaceholderExpr(Identifier Placeholder, SourceLoc Loc, |
| TypeLoc PlaceholderTy, |
| TypeRepr *ExpansionTyR) |
| : Expr(ExprKind::EditorPlaceholder, /*Implicit=*/false), |
| Placeholder(Placeholder), Loc(Loc), |
| PlaceholderTy(PlaceholderTy), |
| ExpansionTyR(ExpansionTyR), |
| SemanticExpr(nullptr) { |
| } |
| |
| Identifier getPlaceholder() const { return Placeholder; } |
| SourceRange getSourceRange() const { return Loc; } |
| TypeLoc &getTypeLoc() { return PlaceholderTy; } |
| TypeLoc getTypeLoc() const { return PlaceholderTy; } |
| |
| /// The TypeRepr to be considered for placeholder expansion. |
| TypeRepr *getTypeForExpansion() const { return ExpansionTyR; } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::EditorPlaceholder; |
| } |
| |
| Expr *getSemanticExpr() const { return SemanticExpr; } |
| void setSemanticExpr(Expr *SE) { SemanticExpr = SE; } |
| }; |
| |
| /// Produces the Objective-C selector of the referenced method. |
| /// |
| /// \code |
| /// #selector(UIView.insertSubview(_:aboveSubview:)) |
| /// \endcode |
| class ObjCSelectorExpr : public Expr { |
| SourceLoc KeywordLoc; |
| SourceLoc LParenLoc; |
| SourceLoc ModifierLoc; |
| Expr *SubExpr; |
| SourceLoc RParenLoc; |
| AbstractFunctionDecl *ResolvedMethod = nullptr; |
| |
| public: |
| /// The kind of #selector expression this is. |
| enum ObjCSelectorKind { |
| Method, Getter, Setter |
| }; |
| |
| ObjCSelectorExpr(ObjCSelectorKind kind, SourceLoc keywordLoc, |
| SourceLoc lParenLoc, SourceLoc modifierLoc, Expr *subExpr, |
| SourceLoc rParenLoc) |
| : Expr(ExprKind::ObjCSelector, /*Implicit=*/false), |
| KeywordLoc(keywordLoc), LParenLoc(lParenLoc), |
| ModifierLoc(modifierLoc), SubExpr(subExpr), RParenLoc(rParenLoc) { |
| Bits.ObjCSelectorExpr.SelectorKind = static_cast<unsigned>(kind); |
| } |
| |
| Expr *getSubExpr() const { return SubExpr; } |
| void setSubExpr(Expr *expr) { SubExpr = expr; } |
| |
| /// Whether this selector references a property getter or setter. |
| bool isPropertySelector() const { |
| switch (getSelectorKind()) { |
| case ObjCSelectorKind::Method: |
| return false; |
| |
| case ObjCSelectorKind::Getter: |
| case ObjCSelectorKind::Setter: |
| return true; |
| } |
| |
| llvm_unreachable("Unhandled ObjcSelectorKind in switch."); |
| } |
| |
| /// Whether this selector references a method. |
| bool isMethodSelector() const { |
| switch (getSelectorKind()) { |
| case ObjCSelectorKind::Method: |
| return true; |
| |
| case ObjCSelectorKind::Getter: |
| case ObjCSelectorKind::Setter: |
| return false; |
| } |
| } |
| |
| /// Retrieve the Objective-C method to which this expression refers. |
| AbstractFunctionDecl *getMethod() const { return ResolvedMethod; } |
| |
| /// Set the Objective-C method to which this expression refers. |
| void setMethod(AbstractFunctionDecl *method) { ResolvedMethod = method; } |
| |
| SourceLoc getLoc() const { return KeywordLoc; } |
| SourceRange getSourceRange() const { |
| return SourceRange(KeywordLoc, RParenLoc); |
| } |
| |
| /// The location at which the getter: or setter: starts. Requires the selector |
| /// to be a getter or setter. |
| SourceLoc getModifierLoc() const { |
| assert(isPropertySelector() && "Modifiers only set on property selectors"); |
| return ModifierLoc; |
| } |
| |
| /// Retrieve the kind of the selector (method, getter, setter) |
| ObjCSelectorKind getSelectorKind() const { |
| return static_cast<ObjCSelectorKind>(Bits.ObjCSelectorExpr.SelectorKind); |
| } |
| |
| /// Override the selector kind. |
| /// |
| /// Used by the type checker to recover from ill-formed #selector |
| /// expressions. |
| void overrideObjCSelectorKind(ObjCSelectorKind newKind, |
| SourceLoc modifierLoc) { |
| Bits.ObjCSelectorExpr.SelectorKind = static_cast<unsigned>(newKind); |
| ModifierLoc = modifierLoc; |
| } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::ObjCSelector; |
| } |
| }; |
| |
| /// Produces a keypath string for the given referenced property. |
| /// |
| /// \code |
| /// #keyPath(Person.friends.firstName) |
| /// \endcode |
| class KeyPathExpr : public Expr { |
| SourceLoc StartLoc; |
| SourceLoc LParenLoc; |
| SourceLoc EndLoc; |
| Expr *ObjCStringLiteralExpr = nullptr; |
| |
| // The parsed root of a Swift keypath (the section before an unusual dot, like |
| // Foo.Bar in \Foo.Bar.?.baz). |
| Expr *ParsedRoot = nullptr; |
| // The parsed path of a Swift keypath (the section after an unusual dot, like |
| // ?.baz in \Foo.Bar.?.baz). |
| Expr *ParsedPath = nullptr; |
| |
| // The processed/resolved type, like Foo.Bar in \Foo.Bar.?.baz. |
| TypeRepr *RootType = nullptr; |
| |
| public: |
| /// A single stored component, which will be one of: |
| /// - an unresolved DeclName, which has to be type-checked |
| /// - a resolved ValueDecl, referring to |
| /// - a subscript index expression, which may or may not be resolved |
| /// - an optional chaining, forcing, or wrapping component |
| class Component { |
| public: |
| enum class Kind: unsigned { |
| Invalid, |
| UnresolvedProperty, |
| UnresolvedSubscript, |
| Property, |
| Subscript, |
| OptionalForce, |
| OptionalChain, |
| OptionalWrap |
| }; |
| |
| private: |
| union DeclNameOrRef { |
| DeclName UnresolvedName; |
| ConcreteDeclRef ResolvedDecl; |
| |
| DeclNameOrRef() : UnresolvedName{} {} |
| DeclNameOrRef(DeclName un) : UnresolvedName(un) {} |
| DeclNameOrRef(ConcreteDeclRef rd) : ResolvedDecl(rd) {} |
| } Decl; |
| |
| |
| llvm::PointerIntPair<Expr *, 3, Kind> SubscriptIndexExprAndKind; |
| ArrayRef<Identifier> SubscriptLabels; |
| ArrayRef<ProtocolConformanceRef> SubscriptHashableConformances; |
| Type ComponentType; |
| SourceLoc Loc; |
| |
| explicit Component(ASTContext *ctxForCopyingLabels, |
| DeclNameOrRef decl, |
| Expr *indexExpr, |
| ArrayRef<Identifier> subscriptLabels, |
| ArrayRef<ProtocolConformanceRef> indexHashables, |
| Kind kind, |
| Type type, |
| SourceLoc loc); |
| |
| public: |
| Component() |
| : Component(nullptr, {}, nullptr, {}, {}, Kind::Invalid, |
| Type(), SourceLoc()) |
| {} |
| |
| /// Create an unresolved component for a property. |
| static Component forUnresolvedProperty(DeclName UnresolvedName, |
| SourceLoc Loc) { |
| return Component(nullptr, |
| UnresolvedName, nullptr, {}, {}, |
| Kind::UnresolvedProperty, |
| Type(), |
| Loc); |
| } |
| |
| /// Create an unresolved component for a subscript. |
| static Component forUnresolvedSubscript(ASTContext &ctx, |
| SourceLoc lSquareLoc, |
| ArrayRef<Expr *> indexArgs, |
| ArrayRef<Identifier> indexArgLabels, |
| ArrayRef<SourceLoc> indexArgLabelLocs, |
| SourceLoc rSquareLoc, |
| Expr *trailingClosure); |
| |
| /// Create an unresolved component for a subscript. |
| /// |
| /// You shouldn't add new uses of this overload; use the one that takes a |
| /// list of index arguments. |
| static Component forUnresolvedSubscriptWithPrebuiltIndexExpr( |
| ASTContext &context, |
| Expr *index, |
| ArrayRef<Identifier> subscriptLabels, |
| SourceLoc loc) { |
| |
| return Component(&context, |
| {}, index, subscriptLabels, {}, |
| Kind::UnresolvedSubscript, |
| Type(), loc); |
| } |
| |
| /// Create an unresolved optional force `!` component. |
| static Component forUnresolvedOptionalForce(SourceLoc BangLoc) { |
| return Component(nullptr, {}, nullptr, {}, {}, |
| Kind::OptionalForce, |
| Type(), |
| BangLoc); |
| } |
| |
| /// Create an unresolved optional chain `?` component. |
| static Component forUnresolvedOptionalChain(SourceLoc QuestionLoc) { |
| return Component(nullptr, {}, nullptr, {}, {}, |
| Kind::OptionalChain, |
| Type(), |
| QuestionLoc); |
| } |
| |
| /// Create a component for a property. |
| static Component forProperty(ConcreteDeclRef property, |
| Type propertyType, |
| SourceLoc loc) { |
| return Component(nullptr, property, nullptr, {}, {}, |
| Kind::Property, |
| propertyType, |
| loc); |
| } |
| |
| /// Create a component for a subscript. |
| static Component forSubscript(ASTContext &ctx, |
| ConcreteDeclRef subscript, |
| SourceLoc lSquareLoc, |
| ArrayRef<Expr *> indexArgs, |
| ArrayRef<Identifier> indexArgLabels, |
| ArrayRef<SourceLoc> indexArgLabelLocs, |
| SourceLoc rSquareLoc, |
| Expr *trailingClosure, |
| Type elementType, |
| ArrayRef<ProtocolConformanceRef> indexHashables); |
| |
| /// Create a component for a subscript. |
| /// |
| /// You shouldn't add new uses of this overload; use the one that takes a |
| /// list of index arguments. |
| static Component forSubscriptWithPrebuiltIndexExpr( |
| ConcreteDeclRef subscript, Expr *index, ArrayRef<Identifier> labels, |
| Type elementType, SourceLoc loc, |
| ArrayRef<ProtocolConformanceRef> indexHashables); |
| |
| /// Create an optional-forcing `!` component. |
| static Component forOptionalForce(Type forcedType, SourceLoc bangLoc) { |
| return Component(nullptr, {}, nullptr, {}, {}, |
| Kind::OptionalForce, forcedType, |
| bangLoc); |
| } |
| |
| /// Create an optional-chaining `?` component. |
| static Component forOptionalChain(Type unwrappedType, |
| SourceLoc questionLoc) { |
| return Component(nullptr, {}, nullptr, {}, {}, |
| Kind::OptionalChain, unwrappedType, |
| questionLoc); |
| } |
| |
| /// Create an optional-wrapping component. This doesn't have a surface |
| /// syntax but may appear when the non-optional result of an optional chain |
| /// is implicitly wrapped. |
| static Component forOptionalWrap(Type wrappedType) { |
| return Component(nullptr, {}, nullptr, {}, {}, |
| Kind::OptionalWrap, wrappedType, |
| SourceLoc()); |
| } |
| |
| SourceLoc getLoc() const { |
| return Loc; |
| } |
| |
| Kind getKind() const { |
| return SubscriptIndexExprAndKind.getInt(); |
| } |
| |
| bool isValid() const { |
| return getKind() != Kind::Invalid; |
| } |
| |
| bool isResolved() const { |
| if (!getComponentType()) |
| return false; |
| |
| switch (getKind()) { |
| case Kind::Subscript: |
| case Kind::OptionalChain: |
| case Kind::OptionalWrap: |
| case Kind::OptionalForce: |
| case Kind::Property: |
| return true; |
| |
| case Kind::UnresolvedSubscript: |
| case Kind::UnresolvedProperty: |
| case Kind::Invalid: |
| return false; |
| } |
| } |
| |
| Expr *getIndexExpr() const { |
| switch (getKind()) { |
| case Kind::Subscript: |
| case Kind::UnresolvedSubscript: |
| return SubscriptIndexExprAndKind.getPointer(); |
| |
| case Kind::Invalid: |
| case Kind::OptionalChain: |
| case Kind::OptionalWrap: |
| case Kind::OptionalForce: |
| case Kind::UnresolvedProperty: |
| case Kind::Property: |
| return nullptr; |
| } |
| } |
| |
| ArrayRef<Identifier> getSubscriptLabels() const { |
| switch (getKind()) { |
| case Kind::Subscript: |
| case Kind::UnresolvedSubscript: |
| return SubscriptLabels; |
| |
| case Kind::Invalid: |
| case Kind::OptionalChain: |
| case Kind::OptionalWrap: |
| case Kind::OptionalForce: |
| case Kind::UnresolvedProperty: |
| case Kind::Property: |
| llvm_unreachable("no subscript labels for this kind"); |
| } |
| } |
| |
| ArrayRef<ProtocolConformanceRef> |
| getSubscriptIndexHashableConformances() const { |
| switch (getKind()) { |
| case Kind::Subscript: |
| return SubscriptHashableConformances; |
| |
| case Kind::UnresolvedSubscript: |
| case Kind::Invalid: |
| case Kind::OptionalChain: |
| case Kind::OptionalWrap: |
| case Kind::OptionalForce: |
| case Kind::UnresolvedProperty: |
| case Kind::Property: |
| return {}; |
| } |
| } |
| |
| void setSubscriptIndexHashableConformances( |
| ArrayRef<ProtocolConformanceRef> hashables); |
| |
| DeclName getUnresolvedDeclName() const { |
| switch (getKind()) { |
| case Kind::UnresolvedProperty: |
| return Decl.UnresolvedName; |
| |
| case Kind::Invalid: |
| case Kind::Subscript: |
| case Kind::UnresolvedSubscript: |
| case Kind::OptionalChain: |
| case Kind::OptionalWrap: |
| case Kind::OptionalForce: |
| case Kind::Property: |
| llvm_unreachable("no unresolved name for this kind"); |
| } |
| } |
| |
| ConcreteDeclRef getDeclRef() const { |
| switch (getKind()) { |
| case Kind::Property: |
| case Kind::Subscript: |
| return Decl.ResolvedDecl; |
| |
| case Kind::Invalid: |
| case Kind::UnresolvedProperty: |
| case Kind::UnresolvedSubscript: |
| case Kind::OptionalChain: |
| case Kind::OptionalWrap: |
| case Kind::OptionalForce: |
| llvm_unreachable("no decl ref for this kind"); |
| } |
| } |
| |
| Type getComponentType() const { |
| return ComponentType; |
| } |
| |
| void setComponentType(Type t) { |
| ComponentType = t; |
| } |
| }; |
| |
| private: |
| llvm::MutableArrayRef<Component> Components; |
| |
| public: |
| /// Create a new #keyPath expression. |
| KeyPathExpr(ASTContext &C, |
| SourceLoc keywordLoc, SourceLoc lParenLoc, |
| ArrayRef<Component> components, |
| SourceLoc rParenLoc, |
| bool isImplicit = false); |
| |
| KeyPathExpr(SourceLoc backslashLoc, Expr *parsedRoot, Expr *parsedPath, |
| bool isImplicit = false) |
| : Expr(ExprKind::KeyPath, isImplicit), StartLoc(backslashLoc), |
| EndLoc(parsedPath ? parsedPath->getEndLoc() : parsedRoot->getEndLoc()), |
| ParsedRoot(parsedRoot), ParsedPath(parsedPath) { |
| assert((parsedRoot || parsedPath) && |
| "keypath must have either root or path"); |
| Bits.KeyPathExpr.IsObjC = false; |
| } |
| |
| SourceLoc getLoc() const { return StartLoc; } |
| SourceRange getSourceRange() const { return SourceRange(StartLoc, EndLoc); } |
| |
| /// Get the components array. |
| ArrayRef<Component> getComponents() const { |
| return Components; |
| } |
| MutableArrayRef<Component> getMutableComponents() { |
| return Components; |
| } |
| |
| /// Resolve the components of an un-type-checked expr. This copies over the |
| /// components from the argument array. |
| void resolveComponents(ASTContext &C, |
| ArrayRef<Component> resolvedComponents); |
| |
| /// Retrieve the string literal expression, which will be \c NULL prior to |
| /// type checking and a string literal after type checking for an |
| /// @objc key path. |
| Expr *getObjCStringLiteralExpr() const { |
| return ObjCStringLiteralExpr; |
| } |
| |
| /// Set the semantic expression. |
| void setObjCStringLiteralExpr(Expr *expr) { |
| ObjCStringLiteralExpr = expr; |
| } |
| |
| Expr *getParsedRoot() const { |
| assert(!isObjC() && "cannot get parsed root of ObjC keypath"); |
| return ParsedRoot; |
| } |
| void setParsedRoot(Expr *root) { |
| assert(!isObjC() && "cannot get parsed root of ObjC keypath"); |
| ParsedRoot = root; |
| } |
| |
| Expr *getParsedPath() const { |
| assert(!isObjC() && "cannot get parsed path of ObjC keypath"); |
| return ParsedPath; |
| } |
| void setParsedPath(Expr *path) { |
| assert(!isObjC() && "cannot set parsed path of ObjC keypath"); |
| ParsedPath = path; |
| } |
| |
| TypeRepr *getRootType() const { |
| assert(!isObjC() && "cannot get root type of ObjC keypath"); |
| return RootType; |
| } |
| void setRootType(TypeRepr *rootType) { |
| assert(!isObjC() && "cannot set root type of ObjC keypath"); |
| RootType = rootType; |
| } |
| |
| /// True if this is an ObjC key path expression. |
| bool isObjC() const { return Bits.KeyPathExpr.IsObjC; } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::KeyPath; |
| } |
| }; |
| |
| /// Represents the unusual behavior of a . in a \ keypath expression, such as |
| /// \.[0] and \Foo.?. |
| class KeyPathDotExpr : public Expr { |
| SourceLoc DotLoc; |
| |
| public: |
| KeyPathDotExpr(SourceLoc dotLoc) |
| : Expr(ExprKind::KeyPathDot, /*isImplicit=*/true), DotLoc(dotLoc) {} |
| |
| SourceLoc getLoc() const { return DotLoc; } |
| SourceRange getSourceRange() const { return SourceRange(DotLoc, DotLoc); } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::KeyPathDot; |
| } |
| }; |
| |
| inline bool Expr::isInfixOperator() const { |
| return isa<BinaryExpr>(this) || isa<IfExpr>(this) || |
| isa<AssignExpr>(this) || isa<ExplicitCastExpr>(this); |
| } |
| |
| inline Expr *const *CollectionExpr::getTrailingObjectsPointer() const { |
| if (auto ty = dyn_cast<ArrayExpr>(this)) |
| return ty->getTrailingObjects<Expr*>(); |
| if (auto ty = dyn_cast<DictionaryExpr>(this)) |
| return ty->getTrailingObjects<Expr*>(); |
| llvm_unreachable("Unhandled CollectionExpr!"); |
| } |
| |
| inline const SourceLoc *CollectionExpr::getTrailingSourceLocs() const { |
| if (auto ty = dyn_cast<ArrayExpr>(this)) |
| return ty->getTrailingObjects<SourceLoc>(); |
| if (auto ty = dyn_cast<DictionaryExpr>(this)) |
| return ty->getTrailingObjects<SourceLoc>(); |
| llvm_unreachable("Unhandled CollectionExpr!"); |
| } |
| |
| #undef SWIFT_FORWARD_SOURCE_LOCS_TO |
| |
| } // end namespace swift |
| |
| #endif |