| //===--- Expr.h - Swift Language Expression ASTs ----------------*- C++ -*-===// |
| // |
| // This source file is part of the Swift.org open source project |
| // |
| // Copyright (c) 2014 - 2018 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/DeclContext.h" |
| #include "swift/AST/DeclNameLoc.h" |
| #include "swift/AST/FunctionRefKind.h" |
| #include "swift/AST/ProtocolConformanceRef.h" |
| #include "swift/AST/TrailingCallArguments.h" |
| #include "swift/AST/TypeAlignments.h" |
| #include "swift/AST/Availability.h" |
| #include "swift/Basic/Debug.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 IdentTypeRepr; |
| class Type; |
| class TypeRepr; |
| class ValueDecl; |
| class Decl; |
| class DeclRefExpr; |
| class OpenedArchetypeType; |
| class ParamDecl; |
| 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; |
| class CallExpr; |
| class KeyPathExpr; |
| class CaptureListExpr; |
| |
| struct TrailingClosure { |
| Identifier Label; |
| SourceLoc LabelLoc; |
| Expr *ClosureExpr; |
| |
| TrailingClosure(Expr *closure) |
| : TrailingClosure(Identifier(), SourceLoc(), closure) {} |
| |
| TrailingClosure(Identifier label, SourceLoc labelLoc, Expr *closure) |
| : Label(label), LabelLoc(labelLoc), ClosureExpr(closure) {} |
| }; |
| |
| 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, |
| |
| Last_CheckedCastKind = BridgingCoercion, |
| }; |
| |
| /// What are the high-level semantics of this access? |
| enum class AccessSemantics : uint8_t { |
| /// On a storage reference, this is a direct access to the underlying |
| /// physical storage, bypassing any observers. The declaration must be |
| /// a variable with storage. |
| /// |
| /// On a function reference, this is a non-polymorphic access to a |
| /// particular implementation. |
| DirectToStorage, |
| |
| /// On a storage reference, this is a direct access to the concrete |
| /// implementation of this storage, bypassing any possibility of override. |
| DirectToImplementation, |
| |
| /// 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)+1, |
| /// The subclass of Expr that this is. |
| Kind : bitmax(NumExprKindBits,8), |
| /// 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 DictionaryExpr, |
| /// 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(LookupExpr, Expr, 1, |
| IsSuper : 1 |
| ); |
| SWIFT_INLINE_BITFIELD_EMPTY(DynamicLookupExpr, LookupExpr); |
| |
| SWIFT_INLINE_BITFIELD(ParenExpr, IdentityExpr, 1, |
| /// Whether we're wrapping a trailing closure expression. |
| HasTrailingClosure : 1 |
| ); |
| |
| SWIFT_INLINE_BITFIELD(NumberLiteralExpr, LiteralExpr, 1+1, |
| IsNegative : 1, |
| IsExplicitConversion : 1 |
| ); |
| |
| SWIFT_INLINE_BITFIELD(StringLiteralExpr, LiteralExpr, 3+1+1, |
| Encoding : 3, |
| IsSingleUnicodeScalar : 1, |
| IsSingleExtendedGraphemeCluster : 1 |
| ); |
| |
| SWIFT_INLINE_BITFIELD_FULL(InterpolatedStringLiteralExpr, LiteralExpr, 32+20, |
| : NumPadBits, |
| InterpolationCount : 20, |
| LiteralCapacity : 32 |
| ); |
| |
| 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, LookupExpr, 2, |
| Semantics : 2 // an AccessSemantics |
| ); |
| |
| SWIFT_INLINE_BITFIELD_FULL(TupleElementExpr, Expr, 32, |
| : NumPadBits, |
| FieldNo : 32 |
| ); |
| |
| SWIFT_INLINE_BITFIELD_FULL(TupleExpr, Expr, 1+1+32, |
| /// 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, LookupExpr, 2+1+1+16, |
| Semantics : 2, // an AccessSemantics |
| /// 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, DynamicLookupExpr, 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, 2, |
| FunctionRefKind : 2 |
| ); |
| |
| 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(AutoClosureExpr, AbstractClosureExpr, 2, |
| /// If the autoclosure was built for a curry thunk, the thunk kind is |
| /// stored here. |
| Kind : 2 |
| ); |
| |
| 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(DestructureTupleExpr, ImplicitConversionExpr, 16, |
| /// The number of elements in the tuple type being destructured. |
| NumElements : 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+1, |
| ThrowsIsSet : 1, |
| Throws : 1, |
| ImplicitlyAsync : 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 |
| ); |
| |
| SWIFT_INLINE_BITFIELD(OpaqueValueExpr, Expr, 1, |
| IsPlaceholder : 1 |
| ); |
| |
| } Bits; |
| |
| private: |
| /// Ty - This is the type of the expression. |
| Type Ty; |
| |
| protected: |
| Expr(ExprKind Kind, bool Implicit, Type Ty = Type()) : Ty(Ty) { |
| Bits.OpaqueBits = 0; |
| Bits.Expr.Kind = unsigned(Kind); |
| Bits.Expr.Implicit = Implicit; |
| } |
| |
| public: |
| /// Return the kind of this expression. |
| ExprKind getKind() const { return ExprKind(Bits.Expr.Kind); } |
| |
| /// 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); |
| |
| /// Return the source range of the expression. |
| SourceRange getSourceRange() const; |
| |
| /// getStartLoc - Return the location of the start of the expression. |
| SourceLoc getStartLoc() const; |
| |
| /// 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(Expr *)> getType = [](Expr *E) -> Type { |
| return E->getType(); |
| }, |
| llvm::function_ref<Decl *(Expr *)> getDecl = [](Expr *E) -> Decl * { |
| return nullptr; |
| }) 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(Expr *)> getType = [](Expr *E) -> Type { |
| return E->getType(); |
| }, |
| llvm::function_ref<bool(Expr *)> isTypeReference = |
| [](Expr *E) { return E->isTypeReference(); }) 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); |
| |
| /// Retrieves the declaration that is being referenced by this |
| /// expression, if any. |
| ConcreteDeclRef getReferencedDecl(bool stopAtParenExpr = false) 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; |
| |
| /// Returns true if this is a reference to the implicit self of function. |
| bool isSelfExprOf(const AbstractFunctionDecl *AFD, |
| bool sameBase = false) const; |
| |
| /// Given that this is a packed argument expression of the sort that |
| /// would be produced from packSingleArgument, return the index of the |
| /// unlabeled trailing closure, if there is one. |
| Optional<unsigned> getUnlabeledTrailingClosureIndexOfPackedArgument() 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(); |
| |
| SWIFT_DEBUG_DUMP; |
| void dump(raw_ostream &OS, unsigned Indent = 0) const; |
| void dump(raw_ostream &OS, llvm::function_ref<Type(Expr *)> getType, |
| llvm::function_ref<Type(TypeRepr *)> getTypeOfTypeRepr, |
| llvm::function_ref<Type(KeyPathExpr *E, unsigned index)> |
| getTypeOfKeyPathComponent, |
| 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; |
| } |
| }; |
| |
| /// ErrorExpr - Represents a semantically erroneous subexpression in the AST, |
| /// typically this will have an ErrorType. |
| class ErrorExpr : public Expr { |
| SourceRange Range; |
| Expr *OriginalExpr; |
| public: |
| ErrorExpr(SourceRange Range, Type Ty = Type(), Expr *OriginalExpr = nullptr) |
| : Expr(ExprKind::Error, /*Implicit=*/true, Ty), Range(Range), |
| OriginalExpr(OriginalExpr) {} |
| |
| SourceRange getSourceRange() const { return Range; } |
| Expr *getOriginalExpr() const { return OriginalExpr; } |
| |
| 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 { |
| Expr *Base; |
| SourceLoc Loc; |
| |
| public: |
| CodeCompletionExpr(Expr *Base, SourceLoc Loc) |
| : Expr(ExprKind::CodeCompletion, /*Implicit=*/true, Type()), |
| Base(Base), Loc(Loc) {} |
| |
| CodeCompletionExpr(SourceLoc Loc) |
| : CodeCompletionExpr(/*Base=*/nullptr, Loc) {} |
| |
| Expr *getBase() const { return Base; } |
| void setBase(Expr *E) { Base = E; } |
| |
| SourceLoc getLoc() const { return Loc; } |
| SourceLoc getStartLoc() const { return Base ? Base->getStartLoc() : Loc; } |
| SourceLoc getEndLoc() const { return Loc; } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::CodeCompletion; |
| } |
| }; |
| |
| /// LiteralExpr - Common base class between the literals. |
| class LiteralExpr : public Expr { |
| // Set by Sema: |
| ConcreteDeclRef Initializer; |
| |
| public: |
| LiteralExpr(ExprKind Kind, bool Implicit) : Expr(Kind, Implicit) {} |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() >= ExprKind::First_LiteralExpr && |
| E->getKind() <= ExprKind::Last_LiteralExpr; |
| } |
| |
| /// Retrieve the initializer that will be used to construct the |
| /// literal from the result of the initializer. |
| /// |
| /// Only 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 literal. |
| void setInitializer(ConcreteDeclRef initializer) { |
| Initializer = initializer; |
| } |
| }; |
| |
| /// BuiltinLiteralExpr - Common base class between all literals |
| /// that provides BuiltinInitializer |
| class BuiltinLiteralExpr : public LiteralExpr { |
| // Set by Seam: |
| ConcreteDeclRef BuiltinInitializer; |
| |
| public: |
| BuiltinLiteralExpr(ExprKind Kind, bool Implicit) |
| : LiteralExpr(Kind, Implicit) {} |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() >= ExprKind::First_BuiltinLiteralExpr && |
| E->getKind() <= ExprKind::Last_BuiltinLiteralExpr; |
| } |
| |
| /// Retrieve the builtin initializer that will be used to construct the |
| /// literal. |
| /// |
| /// Any type-checked 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 |
| /// literal. |
| void setBuiltinInitializer(ConcreteDeclRef builtinInitializer) { |
| BuiltinInitializer = builtinInitializer; |
| } |
| }; |
| |
| /// 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; |
| } |
| }; |
| |
| /// Abstract base class for numeric literals, potentially with a sign. |
| class NumberLiteralExpr : public BuiltinLiteralExpr { |
| /// 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) |
| : BuiltinLiteralExpr(Kind, Implicit), Val(Val), DigitsLoc(DigitsLoc) { |
| Bits.NumberLiteralExpr.IsNegative = false; |
| Bits.NumberLiteralExpr.IsExplicitConversion = false; |
| } |
| |
| bool isNegative() const { return Bits.NumberLiteralExpr.IsNegative; } |
| void setNegative(SourceLoc Loc) { |
| MinusLoc = Loc; |
| Bits.NumberLiteralExpr.IsNegative = true; |
| } |
| |
| bool isExplicitConversion() const { |
| return Bits.NumberLiteralExpr.IsExplicitConversion; |
| } |
| void setExplicitConversion(bool isExplicitConversion = true) { |
| Bits.NumberLiteralExpr.IsExplicitConversion = isExplicitConversion; |
| } |
| |
| 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; |
| } |
| }; |
| |
| /// Integer literal with a '+' or '-' sign, like '+4' or '- 2'. |
| /// |
| /// After semantic analysis assigns types, this is guaranteed to have |
| /// a BuiltinIntegerType or be a normal type and implicitly be |
| /// AnyBuiltinIntegerType. |
| class IntegerLiteralExpr : public NumberLiteralExpr { |
| public: |
| IntegerLiteralExpr(StringRef Val, SourceLoc DigitsLoc, bool Implicit = false) |
| : NumberLiteralExpr(ExprKind::IntegerLiteral, |
| Val, DigitsLoc, Implicit) |
| {} |
| |
| /// Returns a new integer literal expression with the given value. |
| /// \p C The AST context. |
| /// \p value The integer value. |
| /// \return An implicit integer literal expression which evaluates to the value. |
| static IntegerLiteralExpr * |
| createFromUnsigned(ASTContext &C, unsigned value); |
| |
| /// Returns the value of the literal, appropriately constructed in the |
| /// target type. |
| APInt getValue() const; |
| |
| /// Returns the raw value of the literal without any truncation. |
| APInt getRawValue() const; |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::IntegerLiteral; |
| } |
| }; |
| |
| /// FloatLiteralExpr - Floating point literal, like '4.0'. After semantic |
| /// analysis assigns types, BuiltinTy is guaranteed to only have a |
| /// BuiltinFloatingPointType. |
| class FloatLiteralExpr : public NumberLiteralExpr { |
| /// This is the type of the builtin literal. |
| Type BuiltinTy; |
| |
| 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; |
| } |
| |
| Type getBuiltinType() const { return BuiltinTy; } |
| void setBuiltinType(Type ty) { BuiltinTy = ty; } |
| }; |
| |
| /// A Boolean literal ('true' or 'false') |
| /// |
| class BooleanLiteralExpr : public BuiltinLiteralExpr { |
| SourceLoc Loc; |
| |
| public: |
| BooleanLiteralExpr(bool Value, SourceLoc Loc, bool Implicit = false) |
| : BuiltinLiteralExpr(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 BuiltinLiteralExpr { |
| StringRef Val; |
| SourceRange Range; |
| |
| public: |
| /// The encoding that should be used for the string literal. |
| enum Encoding : unsigned { |
| /// A UTF-8 string. |
| UTF8, |
| |
| /// 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; |
| } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::StringLiteral; |
| } |
| }; |
| |
| /// Runs a series of statements which use or modify \c SubExpr |
| /// before it is given to the rest of the expression. |
| /// |
| /// \c Body should begin with a \c VarDecl; this defines the variable |
| /// \c TapExpr will initialize at the beginning and read a result |
| /// from at the end. \c TapExpr creates a separate scope, then |
| /// assigns the result of \c SubExpr to the variable and runs \c Body |
| /// in it, returning the value of the variable after the \c Body runs. |
| /// |
| /// (The design here could be a bit cleaner, particularly where the VarDecl |
| /// is concerned.) |
| class TapExpr : public Expr { |
| Expr *SubExpr; |
| BraceStmt *Body; |
| |
| public: |
| TapExpr(Expr *SubExpr, BraceStmt *Body); |
| |
| Expr * getSubExpr() const { return SubExpr; } |
| void setSubExpr(Expr * se) { SubExpr = se; } |
| |
| /// The variable which will be accessed and possibly modified by |
| /// the \c Body. This is the first \c ASTNode in the \c Body. |
| VarDecl * getVar() const; |
| |
| BraceStmt * getBody() const { return Body; } |
| void setBody(BraceStmt * b) { Body = b; } |
| |
| SourceLoc getLoc() const { return SubExpr ? SubExpr->getLoc() : SourceLoc(); } |
| |
| SourceLoc getStartLoc() const { |
| return SubExpr ? SubExpr->getStartLoc() : SourceLoc(); |
| } |
| |
| SourceLoc getEndLoc() const; |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::Tap; |
| } |
| }; |
| |
| /// 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; |
| /// Points at the ending quote. |
| /// Needed for the upcoming \c ASTScope subsystem because lookups can be |
| /// targeted to inside an \c InterpolatedStringLiteralExpr. It would be nicer |
| /// to use \c EndLoc for this value, but then \c Lexer::getLocForEndOfToken() |
| /// would not work for \c stringLiteral->getEndLoc(). |
| SourceLoc TrailingQuoteLoc; |
| TapExpr *AppendingExpr; |
| |
| // Set by Sema: |
| OpaqueValueExpr *interpolationExpr = nullptr; |
| ConcreteDeclRef builderInit; |
| Expr *interpolationCountExpr = nullptr; |
| Expr *literalCapacityExpr = nullptr; |
| |
| public: |
| InterpolatedStringLiteralExpr(SourceLoc Loc, |
| SourceLoc TrailingQuoteLoc, |
| unsigned LiteralCapacity, |
| unsigned InterpolationCount, |
| TapExpr *AppendingExpr) |
| : LiteralExpr(ExprKind::InterpolatedStringLiteral, /*Implicit=*/false), |
| Loc(Loc), |
| TrailingQuoteLoc(TrailingQuoteLoc), |
| AppendingExpr(AppendingExpr) { |
| Bits.InterpolatedStringLiteralExpr.InterpolationCount = InterpolationCount; |
| Bits.InterpolatedStringLiteralExpr.LiteralCapacity = LiteralCapacity; |
| } |
| |
| // Sets the constructor for the interpolation type. |
| void setBuilderInit(ConcreteDeclRef decl) { builderInit = decl; } |
| ConcreteDeclRef getBuilderInit() const { return builderInit; } |
| |
| /// Sets the OpaqueValueExpr that is passed into AppendingExpr as the SubExpr |
| /// that the tap operates on. |
| void setInterpolationExpr(OpaqueValueExpr *expr) { interpolationExpr = expr; } |
| OpaqueValueExpr *getInterpolationExpr() const { return interpolationExpr; } |
| |
| /// Store a builtin integer literal expr wrapping getInterpolationCount(). |
| /// This is an arg to builderInit. |
| void setInterpolationCountExpr(Expr *expr) { interpolationCountExpr = expr; } |
| Expr *getInterpolationCountExpr() const { return interpolationCountExpr; } |
| |
| /// Store a builtin integer literal expr wrapping getLiteralCapacity(). |
| /// This is an arg to builderInit. |
| void setLiteralCapacityExpr(Expr *expr) { literalCapacityExpr = expr; } |
| Expr *getLiteralCapacityExpr() const { return literalCapacityExpr; } |
| |
| /// Retrieve the value of the literalCapacity parameter to the |
| /// initializer. |
| unsigned getLiteralCapacity() const { |
| return Bits.InterpolatedStringLiteralExpr.LiteralCapacity; |
| } |
| |
| /// Retrieve the value of the interpolationCount parameter to the |
| /// initializer. |
| unsigned getInterpolationCount() const { |
| return Bits.InterpolatedStringLiteralExpr.InterpolationCount; |
| } |
| |
| /// A block containing expressions which call |
| /// \c StringInterpolationProtocol methods to append segments to the |
| /// string interpolation. The first node in \c Body should be an uninitialized |
| /// \c VarDecl; the other statements should append to it. |
| TapExpr * getAppendingExpr() const { return AppendingExpr; } |
| void setAppendingExpr(TapExpr * AE) { AppendingExpr = AE; } |
| |
| 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; |
| } |
| |
| /// Could also be computed by relexing. |
| SourceLoc getTrailingQuoteLoc() const { |
| return TrailingQuoteLoc; |
| } |
| |
| /// Call the \c callback with information about each segment in turn. |
| void forEachSegment(ASTContext &Ctx, |
| llvm::function_ref<void(bool, CallExpr *)> callback); |
| |
| 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 BuiltinLiteralExpr { |
| public: |
| enum Kind : unsigned { |
| #define MAGIC_IDENTIFIER(NAME, STRING, SYNTAX_KIND) NAME, |
| #include "swift/AST/MagicIdentifierKinds.def" |
| }; |
| |
| static StringRef getKindString(MagicIdentifierLiteralExpr::Kind value) { |
| switch (value) { |
| #define MAGIC_IDENTIFIER(NAME, STRING, SYNTAX_KIND) case NAME: return STRING; |
| #include "swift/AST/MagicIdentifierKinds.def" |
| } |
| |
| llvm_unreachable("Unhandled MagicIdentifierLiteralExpr in getKindString."); |
| } |
| |
| private: |
| SourceLoc Loc; |
| |
| public: |
| MagicIdentifierLiteralExpr(Kind kind, SourceLoc loc, bool implicit = false) |
| : BuiltinLiteralExpr(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 isString() const { |
| switch (getKind()) { |
| #define MAGIC_STRING_IDENTIFIER(NAME, STRING, SYNTAX_KIND) \ |
| case NAME: \ |
| return true; |
| #define MAGIC_IDENTIFIER(NAME, STRING, SYNTAX_KIND) \ |
| case NAME: \ |
| return false; |
| #include "swift/AST/MagicIdentifierKinds.def" |
| } |
| 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); |
| } |
| |
| 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; |
| 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(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, |
| ArrayRef<TrailingClosure> trailingClosures, |
| 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; |
| } |
| |
| /// Return the index of the unlabeled trailing closure argument. |
| Optional<unsigned> getUnlabeledTrailingClosureIndex() const { |
| return getArg()->getUnlabeledTrailingClosureIndexOfPackedArgument(); |
| } |
| |
| 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 { |
| /// 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; } |
| void setSelf(VarDecl *self) { Self = 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. |
| /// |
| /// The type of this expression is always \c MetatypeType. |
| class TypeExpr : public Expr { |
| TypeRepr *Repr; |
| public: |
| /// Create a \c TypeExpr from a parsed \c TypeRepr. |
| TypeExpr(TypeRepr *Ty); |
| |
| /// Retrieves the corresponding instance type of the type referenced by this |
| /// expression. |
| /// |
| /// If this node has no type, the resulting instance type is also the |
| /// null \c Type(). If the type of this node is not a \c MetatypeType, the |
| /// resulting instance type is \c ErrorType. |
| Type getInstanceType() const; |
| |
| public: |
| /// Create an implicit \c TypeExpr. |
| /// |
| /// The given type is required to be non-null and must be not be |
| /// a \c MetatypeType as this function will wrap the given type in one. |
| /// |
| /// FIXME: This behavior is bizarre. |
| static TypeExpr *createImplicit(Type Ty, ASTContext &C); |
| |
| /// Create an implicit \c TypeExpr that has artificial |
| /// location information attached. |
| /// |
| /// The given type is required to be non-null and must be not be |
| /// a \c MetatypeType as this function will wrap the given type in one. |
| /// |
| /// FIXME: This behavior is bizarre. |
| /// |
| /// Due to limitations in the modeling of certain AST elements, implicit |
| /// \c TypeExpr nodes are often the only source of location information the |
| /// expression checker has when it comes time to diagnose an error. |
| static TypeExpr *createImplicitHack(SourceLoc Loc, Type Ty, ASTContext &C); |
| |
| /// Create an implicit \c TypeExpr for a given \c TypeDecl at the specified location. |
| /// |
| /// The given type is required to be non-null and must be not be |
| /// a \c MetatypeType as this function will wrap the given type in one. |
| /// |
| /// FIXME: This behavior is bizarre. |
| /// |
| /// Unlike the non-implicit case, the given location is not required to be |
| /// valid. |
| static TypeExpr *createImplicitForDecl(DeclNameLoc Loc, TypeDecl *D, |
| DeclContext *DC, Type ty); |
| |
| public: |
| /// Create a \c TypeExpr for a given \c TypeDecl at the specified location. |
| /// |
| /// The given location must be valid. If it is not, you must use |
| /// \c TypeExpr::createImplicitForDecl instead. |
| static TypeExpr *createForDecl(DeclNameLoc Loc, TypeDecl *D, DeclContext *DC); |
| |
| /// Create a TypeExpr for a member TypeDecl of the given parent TypeDecl. |
| static TypeExpr *createForMemberDecl(DeclNameLoc ParentNameLoc, |
| TypeDecl *Parent, |
| DeclNameLoc NameLoc, |
| TypeDecl *Decl); |
| |
| /// Create a TypeExpr for a member TypeDecl of the given parent IdentTypeRepr. |
| static TypeExpr *createForMemberDecl(IdentTypeRepr *ParentTR, |
| DeclNameLoc 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); |
| |
| TypeRepr *getTypeRepr() const { return Repr; } |
| // 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; |
| // 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 { |
| DeclNameRef Name; |
| DeclNameLoc Loc; |
| |
| public: |
| UnresolvedDeclRefExpr(DeclNameRef 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); |
| } |
| |
| static UnresolvedDeclRefExpr *createImplicit( |
| ASTContext &C, DeclName name, |
| DeclRefKind refKind = DeclRefKind::Ordinary) { |
| return new (C) UnresolvedDeclRefExpr(DeclNameRef(name), refKind, |
| DeclNameLoc()); |
| } |
| |
| static UnresolvedDeclRefExpr *createImplicit( |
| ASTContext &C, DeclBaseName baseName, ArrayRef<Identifier> argLabels) { |
| return UnresolvedDeclRefExpr::createImplicit(C, |
| DeclName(C, baseName, argLabels)); |
| } |
| |
| static UnresolvedDeclRefExpr *createImplicit( |
| ASTContext &C, DeclBaseName baseName, ParameterList *paramList) { |
| return UnresolvedDeclRefExpr::createImplicit(C, |
| DeclName(C, baseName, paramList)); |
| } |
| |
| bool hasName() const { return static_cast<bool>(Name); } |
| DeclNameRef 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; |
| } |
| }; |
| |
| /// LookupExpr - This abstract class represents 'a.b', 'a[]', etc where we |
| /// are referring to a member of a type, such as a property, variable, etc. |
| class LookupExpr : public Expr { |
| Expr *Base; |
| ConcreteDeclRef Member; |
| |
| protected: |
| explicit LookupExpr(ExprKind Kind, Expr *base, ConcreteDeclRef member, |
| bool Implicit) |
| : Expr(Kind, Implicit), Base(base), Member(member) { |
| Bits.LookupExpr.IsSuper = false; |
| assert(Base); |
| } |
| |
| public: |
| /// Retrieve the base of the expression. |
| Expr *getBase() const { return Base; } |
| |
| /// Replace the base of the expression. |
| void setBase(Expr *E) { Base = E; } |
| |
| /// Retrieve the member to which this access refers. |
| ConcreteDeclRef getMember() const { return Member; } |
| |
| /// Determine whether the operation has a known underlying declaration or not. |
| bool hasDecl() const { return static_cast<bool>(Member); } |
| |
| /// Retrieve the declaration that this /// operation refers to. |
| /// Only valid when \c hasDecl() is true. |
| ConcreteDeclRef getDecl() const { |
| assert(hasDecl() && "No subscript declaration known!"); |
| return getMember(); |
| } |
| |
| /// Determine whether this reference refers to the superclass's property. |
| bool isSuper() const { return Bits.LookupExpr.IsSuper; } |
| |
| /// Set whether this reference refers to the superclass's property. |
| void setIsSuper(bool isSuper) { Bits.LookupExpr.IsSuper = isSuper; } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() >= ExprKind::First_LookupExpr && |
| E->getKind() <= ExprKind::Last_LookupExpr; |
| } |
| }; |
| |
| /// MemberRefExpr - This represents 'a.b' where we are referring to a member |
| /// of a type, such as a property or variable. |
| /// |
| /// Note that methods found via 'dot' syntax are expressed as DotSyntaxCallExpr |
| /// nodes, because 'a.f' is actually an application of 'a' (the implicit object |
| /// argument) to the function 'f'. |
| class MemberRefExpr : public LookupExpr { |
| SourceLoc DotLoc; |
| DeclNameLoc NameLoc; |
| |
| public: |
| MemberRefExpr(Expr *base, SourceLoc dotLoc, ConcreteDeclRef member, |
| DeclNameLoc loc, bool Implicit, |
| AccessSemantics semantics = AccessSemantics::Ordinary); |
| SourceLoc getDotLoc() const { return DotLoc; } |
| DeclNameLoc getNameLoc() const { return NameLoc; } |
| |
| /// Return true if this member access is direct, meaning that it |
| /// does not call the getter or setter. |
| AccessSemantics getAccessSemantics() const { |
| return (AccessSemantics) Bits.MemberRefExpr.Semantics; |
| } |
| |
| SourceLoc getLoc() const { return NameLoc.getBaseNameLoc(); } |
| SourceLoc getStartLoc() const { |
| SourceLoc BaseStartLoc = getBase()->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 LookupExpr { |
| protected: |
| explicit DynamicLookupExpr(ExprKind kind, ConcreteDeclRef member, Expr *base) |
| : LookupExpr(kind, base, member, /*Implicit=*/false) { } |
| |
| public: |
| 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 = getBase()->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(Expr *)> getType = [](Expr *E) -> Type { |
| return E->getType(); |
| }); |
| |
| /// 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; |
| } |
| |
| /// Return the index of the unlabeled trailing closure argument. |
| Optional<unsigned> getUnlabeledTrailingClosureIndex() const { |
| return Index->getUnlabeledTrailingClosureIndexOfPackedArgument(); |
| } |
| |
| SourceLoc getLoc() const { return Index->getStartLoc(); } |
| |
| SourceLoc getStartLoc() const { return getBase()->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 { |
| SourceLoc DotLoc; |
| DeclNameLoc NameLoc; |
| DeclNameRef Name; |
| |
| public: |
| UnresolvedMemberExpr(SourceLoc dotLoc, DeclNameLoc nameLoc, DeclNameRef name, |
| bool implicit) |
| : Expr(ExprKind::UnresolvedMember, implicit), DotLoc(dotLoc), |
| NameLoc(nameLoc), Name(name) { |
| // FIXME: Really, we should be setting this to `FunctionRefKind::Compound` |
| // if `NameLoc` is compound, but this would be a source break for cases like |
| // ``` |
| // struct S { |
| // static func makeS(_: Int) -> S! { S() } |
| // } |
| // |
| // let s: S = .makeS(_:)(0) |
| // ``` |
| // Instead, we should store compound-ness as a separate bit from applied/ |
| // unapplied. |
| Bits.UnresolvedMemberExpr.FunctionRefKind = |
| static_cast<unsigned>(FunctionRefKind::Unapplied); |
| } |
| |
| DeclNameRef getName() const { return Name; } |
| DeclNameLoc getNameLoc() const { return NameLoc; } |
| SourceLoc getDotLoc() const { return DotLoc; } |
| |
| SourceLoc getLoc() const { return NameLoc.getBaseNameLoc(); } |
| |
| SourceLoc getStartLoc() const { return DotLoc; } |
| SourceLoc getEndLoc() const { return NameLoc.getSourceRange().End; } |
| |
| /// Retrieve the kind of function reference. |
| FunctionRefKind getFunctionRefKind() const { |
| return static_cast<FunctionRefKind>( |
| Bits.UnresolvedMemberExpr.FunctionRefKind); |
| } |
| |
| /// Set the kind of function reference. |
| void setFunctionRefKind(FunctionRefKind refKind) { |
| Bits.UnresolvedMemberExpr.FunctionRefKind = static_cast<unsigned>(refKind); |
| } |
| |
| 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 final : 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 final : 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; |
| } |
| |
| /// Whether this expression has a trailing closure as its argument. |
| bool hasTrailingClosure() const { return Bits.ParenExpr.HasTrailingClosure; } |
| |
| Optional<unsigned> |
| getUnlabeledTrailingClosureIndexOfPackedArgument() const { |
| return hasTrailingClosure() ? Optional<unsigned>(0) : None; |
| } |
| |
| static bool classof(const Expr *E) { return E->getKind() == ExprKind::Paren; } |
| }; |
| |
| /// Represents the result of a chain of accesses or calls hanging off of an |
| /// \c UnresolvedMemberExpr at the root. This is only used during type checking |
| /// to give the result type of such a chain representation in the AST. This |
| /// expression type is always implicit. |
| class UnresolvedMemberChainResultExpr : public IdentityExpr { |
| /// The base of this chain of member accesses. |
| UnresolvedMemberExpr *ChainBase; |
| public: |
| UnresolvedMemberChainResultExpr(Expr *subExpr, UnresolvedMemberExpr *base, |
| Type ty = Type()) |
| : IdentityExpr(ExprKind::UnresolvedMemberChainResult, subExpr, ty, |
| /*isImplicit=*/true), |
| ChainBase(base) { |
| assert(base); |
| } |
| |
| UnresolvedMemberExpr *getChainBase() const { return ChainBase; } |
| |
| SWIFT_FORWARD_SOURCE_LOCS_TO(getSubExpr()) |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::UnresolvedMemberChainResult; |
| } |
| }; |
| |
| /// AwaitExpr - An 'await' surrounding an expression, marking that the |
| /// expression contains code which is a coroutine that may block. |
| /// |
| /// getSemanticsProvidingExpr() looks through this because it doesn't |
| /// provide the value and only very specific clients care where the |
| /// 'await' was written. |
| class AwaitExpr final : public IdentityExpr { |
| SourceLoc AwaitLoc; |
| public: |
| AwaitExpr(SourceLoc awaitLoc, Expr *sub, Type type = Type(), |
| bool implicit = false) |
| : IdentityExpr(ExprKind::Await, sub, type, implicit), AwaitLoc(awaitLoc) { |
| } |
| |
| SourceLoc getLoc() const { return AwaitLoc; } |
| |
| SourceLoc getAwaitLoc() const { return AwaitLoc; } |
| SourceLoc getStartLoc() const { return AwaitLoc; } |
| SourceLoc getEndLoc() const { return getSubExpr()->getEndLoc(); } |
| |
| static bool classof(const Expr *e) { |
| return e->getKind() == ExprKind::Await; |
| } |
| }; |
| |
| |
| /// 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; |
| |
| Optional<unsigned> FirstTrailingArgumentAt; |
| |
| 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, SourceLoc RParenLoc, |
| ArrayRef<Expr *> SubExprs, |
| ArrayRef<Identifier> ElementNames, |
| ArrayRef<SourceLoc> ElementNameLocs, |
| Optional<unsigned> FirstTrailingArgumentAt, 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()); |
| |
| static TupleExpr *create(ASTContext &ctx, |
| SourceLoc LParenLoc, |
| SourceLoc RParenLoc, |
| ArrayRef<Expr *> SubExprs, |
| ArrayRef<Identifier> ElementNames, |
| ArrayRef<SourceLoc> ElementNameLocs, |
| Optional<unsigned> FirstTrailingArgumentAt, |
| 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; |
| |
| bool hasAnyTrailingClosures() const { |
| return (bool) FirstTrailingArgumentAt; |
| } |
| |
| /// Whether this expression has a trailing closure as its argument. |
| bool hasTrailingClosure() const { |
| return FirstTrailingArgumentAt |
| ? *FirstTrailingArgumentAt == getNumElements() - 1 |
| : false; |
| } |
| |
| bool hasMultipleTrailingClosures() const { |
| return FirstTrailingArgumentAt ? !hasTrailingClosure() : false; |
| } |
| |
| Optional<unsigned> |
| getUnlabeledTrailingClosureIndexOfPackedArgument() const { |
| return FirstTrailingArgumentAt; |
| } |
| |
| /// 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() }; |
| } |
| |
| MutableArrayRef<Expr*> getTrailingElements() { |
| return getElements().take_back(getNumTrailingElements()); |
| } |
| |
| ArrayRef<Expr*> getTrailingElements() const { |
| return getElements().take_back(getNumTrailingElements()); |
| } |
| |
| unsigned getNumElements() const { return Bits.TupleExpr.NumElements; } |
| |
| unsigned getNumTrailingElements() const { |
| return FirstTrailingArgumentAt |
| ? getNumElements() - *FirstTrailingArgumentAt |
| : 0; |
| } |
| |
| 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; } |
| }; |
| |
| /// 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; |
| ConcreteDeclRef Initializer; |
| |
| /// 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(), static_cast<size_t>(Bits.CollectionExpr.NumCommas)}; |
| } |
| ArrayRef<SourceLoc> getCommaLocs() const { |
| return {getTrailingSourceLocs(), static_cast<size_t>(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); |
| } |
| |
| static bool classof(const Expr *e) { |
| return e->getKind() >= ExprKind::First_CollectionExpr && |
| e->getKind() <= ExprKind::Last_CollectionExpr; |
| } |
| |
| /// Retrieve the initializer that will be used to construct the 'array' |
| /// literal from the result of the initializer. |
| ConcreteDeclRef getInitializer() const { return Initializer; } |
| |
| /// Set the initializer that will be used to construct the 'array' literal. |
| void setInitializer(ConcreteDeclRef initializer) { |
| Initializer = initializer; |
| } |
| }; |
| |
| /// 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; |
| } |
| |
| Type getElementType(); |
| }; |
| |
| /// 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; |
| } |
| |
| Type getElementType(); |
| }; |
| |
| /// 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 LookupExpr, |
| public TrailingCallArguments<SubscriptExpr> { |
| friend TrailingCallArguments; |
| |
| 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(Expr *)> getType = [](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, |
| ArrayRef<TrailingClosure> trailingClosures, |
| ConcreteDeclRef decl = ConcreteDeclRef(), |
| bool implicit = false, |
| AccessSemantics semantics |
| = AccessSemantics::Ordinary); |
| |
| /// 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 was written with a trailing closure. |
| bool hasTrailingClosure() const { |
| return Bits.SubscriptExpr.HasTrailingClosure; |
| } |
| |
| /// Return the index of the unlabeled trailing closure argument. |
| Optional<unsigned> getUnlabeledTrailingClosureIndex() const { |
| return getIndex()->getUnlabeledTrailingClosureIndexOfPackedArgument(); |
| } |
| |
| /// Determine whether this subscript reference should bypass the |
| /// ordinary accessors. |
| AccessSemantics getAccessSemantics() const { |
| return (AccessSemantics) Bits.SubscriptExpr.Semantics; |
| } |
| |
| SourceLoc getLoc() const { return Index->getStartLoc(); } |
| SourceLoc getStartLoc() const { return getBase()->getStartLoc(); } |
| SourceLoc getEndLoc() const { |
| auto end = Index->getEndLoc(); |
| return end.isValid() ? end : getBase()->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; |
| DeclNameRef Name; |
| ArrayRef<ValueDecl *> OuterAlternatives; |
| |
| public: |
| UnresolvedDotExpr( |
| Expr *subexpr, SourceLoc dotloc, DeclNameRef 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); |
| } |
| |
| static UnresolvedDotExpr *createImplicit( |
| ASTContext &C, Expr *base, DeclName name) { |
| return new (C) UnresolvedDotExpr(base, SourceLoc(), |
| DeclNameRef(name), DeclNameLoc(), |
| /*implicit=*/true); |
| } |
| |
| static UnresolvedDotExpr *createImplicit( |
| ASTContext &C, Expr *base, |
| DeclBaseName baseName, ArrayRef<Identifier> argLabels) { |
| return UnresolvedDotExpr::createImplicit(C, base, |
| DeclName(C, baseName, argLabels)); |
| } |
| |
| static UnresolvedDotExpr *createImplicit( |
| ASTContext &C, Expr *base, |
| DeclBaseName baseName, ParameterList *paramList) { |
| return UnresolvedDotExpr::createImplicit(C, base, |
| DeclName(C, baseName, paramList)); |
| } |
| |
| SourceLoc getLoc() const { |
| if (NameLoc.isValid()) |
| return NameLoc.getBaseNameLoc(); |
| else if (DotLoc.isValid()) |
| return DotLoc; |
| else |
| return SubExpr->getEndLoc(); |
| } |
| |
| SourceLoc getStartLoc() const { |
| auto SubLoc = SubExpr->getStartLoc(); |
| if (SubLoc.isValid()) |
| return SubLoc; |
| else if (DotLoc.isValid()) |
| return DotLoc; |
| else |
| return NameLoc.getSourceRange().Start; |
| } |
| SourceLoc getEndLoc() const { |
| if (NameLoc.isValid()) |
| return NameLoc.getSourceRange().End; |
| else if (DotLoc.isValid()) |
| return DotLoc; |
| else |
| return SubExpr->getEndLoc(); |
| } |
| |
| SourceLoc getDotLoc() const { return DotLoc; } |
| Expr *getBase() const { return SubExpr; } |
| void setBase(Expr *e) { SubExpr = e; } |
| |
| DeclNameRef 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; |
| } |
| }; |
| |
| /// 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; |
| } |
| }; |
| |
| /// 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; |
| } |
| }; |
| |
| /// 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; |
| } |
| }; |
| |
| /// 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; |
| Expr *OriginalExpr; |
| |
| public: |
| MakeTemporarilyEscapableExpr(SourceLoc NameLoc, |
| SourceLoc LParenLoc, |
| Expr *NonescapingClosureValue, |
| Expr *SubExpr, |
| SourceLoc RParenLoc, |
| OpaqueValueExpr *OpaqueValueForEscapingClosure, |
| Expr *OriginalExpr, |
| bool implicit = false) |
| : Expr(ExprKind::MakeTemporarilyEscapable, implicit, Type()), |
| NonescapingClosureValue(NonescapingClosureValue), |
| EscapingClosureValue(OpaqueValueForEscapingClosure), |
| SubExpr(SubExpr), |
| NameLoc(NameLoc), LParenLoc(LParenLoc), RParenLoc(RParenLoc), |
| OriginalExpr(OriginalExpr) |
| {} |
| |
| 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; |
| } |
| |
| /// Retrieve the original 'withoutActuallyEscaping(closure) { ... }' |
| // expression. |
| Expr *getOriginalExpr() const { |
| return OriginalExpr; |
| } |
| |
| static bool classof(const Expr *E) { |
| return E->getKind() == ExprKind::MakeTemporarilyEscapable; |
| } |
| }; |
| |
| /// 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 val ue 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. |
| OpenedArchetypeType *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) |
|