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