blob: c9804f29831e304b3b630c427455ab344a67c560 [file] [log] [blame]
//===--- Expr.h - Swift Language Expression ASTs ----------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file defines the Expr class and subclasses.
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_AST_EXPR_H
#define SWIFT_AST_EXPR_H
#include "swift/AST/CaptureInfo.h"
#include "swift/AST/ConcreteDeclRef.h"
#include "swift/AST/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 OpenedArchetypeType;
class Pattern;
class SubscriptDecl;
class Stmt;
class BraceStmt;
class ASTWalker;
class Initializer;
class VarDecl;
class OpaqueValueExpr;
class FuncDecl;
class ConstructorDecl;
class TypeDecl;
class PatternBindingDecl;
class ParameterList;
class EnumElementDecl;
class CallExpr;
enum class ExprKind : uint8_t {
#define EXPR(Id, Parent) Id,
#define LAST_EXPR(Id) Last_Expr = Id,
#define EXPR_RANGE(Id, FirstId, LastId) \
First_##Id##Expr = FirstId, Last_##Id##Expr = LastId,
#include "swift/AST/ExprNodes.def"
};
enum : unsigned { NumExprKindBits =
countBitsUsed(static_cast<unsigned>(ExprKind::Last_Expr)) };
/// Discriminates certain kinds of checked cast that have specialized diagnostic
/// and/or code generation peephole behavior.
///
/// This enumeration should not have any semantic effect on the behavior of a
/// well-typed program, since the runtime can perform all casts that are
/// statically accepted.
enum class CheckedCastKind : unsigned {
/// The kind has not been determined yet.
Unresolved,
/// Valid resolved kinds start here.
First_Resolved,
/// The requested cast is an implicit conversion, so this is a coercion.
Coercion = First_Resolved,
/// A checked cast with no known specific behavior.
ValueCast,
// A downcast from an array type to another array type.
ArrayDowncast,
// A downcast from a dictionary type to another dictionary type.
DictionaryDowncast,
// A downcast from a set type to another set type.
SetDowncast,
/// A bridging conversion that always succeeds.
BridgingCoercion,
Last_CheckedCastKind = BridgingCoercion,
};
/// What are the high-level semantics of this access?
enum class AccessSemantics : uint8_t {
/// On a storage reference, this is a direct access to the underlying
/// physical storage, bypassing any observers. The declaration must be
/// a variable with storage.
///
/// On a function reference, this is a non-polymorphic access to a
/// particular implementation.
DirectToStorage,
/// On a storage reference, this is a direct access to the concrete
/// implementation of this storage, bypassing any possibility of override.
DirectToImplementation,
/// This is an ordinary access to a declaration, using whatever
/// polymorphism is expected.
Ordinary,
};
/// Expr - Base class for all expressions in swift.
class alignas(8) Expr {
Expr(const Expr&) = delete;
void operator=(const Expr&) = delete;
protected:
union { uint64_t OpaqueBits;
SWIFT_INLINE_BITFIELD_BASE(Expr, bitmax(NumExprKindBits,8)+1,
/// The subclass of Expr that this is.
Kind : bitmax(NumExprKindBits,8),
/// Whether the Expr represents something directly written in source or
/// it was implicitly generated by the type-checker.
Implicit : 1
);
SWIFT_INLINE_BITFIELD_FULL(CollectionExpr, Expr, 64-NumExprBits,
/// True if the type of this collection expr was inferred by the collection
/// fallback type, like [Any].
IsTypeDefaulted : 1,
/// Number of comma source locations.
NumCommas : 32 - 1 - NumExprBits,
/// Number of entries in the collection. If this is a DictionaryExpr,
/// each entry is a Tuple with the key and value pair.
NumSubExprs : 32
);
SWIFT_INLINE_BITFIELD_EMPTY(LiteralExpr, Expr);
SWIFT_INLINE_BITFIELD_EMPTY(IdentityExpr, Expr);
SWIFT_INLINE_BITFIELD(LookupExpr, Expr, 1,
IsSuper : 1
);
SWIFT_INLINE_BITFIELD_EMPTY(DynamicLookupExpr, LookupExpr);
SWIFT_INLINE_BITFIELD(ParenExpr, IdentityExpr, 1,
/// Whether we're wrapping a trailing closure expression.
HasTrailingClosure : 1
);
SWIFT_INLINE_BITFIELD(NumberLiteralExpr, LiteralExpr, 1+1,
IsNegative : 1,
IsExplicitConversion : 1
);
SWIFT_INLINE_BITFIELD(StringLiteralExpr, LiteralExpr, 3+1+1,
Encoding : 3,
IsSingleUnicodeScalar : 1,
IsSingleExtendedGraphemeCluster : 1
);
SWIFT_INLINE_BITFIELD_FULL(InterpolatedStringLiteralExpr, LiteralExpr, 32+20,
: NumPadBits,
InterpolationCount : 20,
LiteralCapacity : 32
);
SWIFT_INLINE_BITFIELD(DeclRefExpr, Expr, 2+2,
Semantics : 2, // an AccessSemantics
FunctionRefKind : 2
);
SWIFT_INLINE_BITFIELD(UnresolvedDeclRefExpr, Expr, 2+2,
DeclRefKind : 2,
FunctionRefKind : 2
);
SWIFT_INLINE_BITFIELD(MemberRefExpr, LookupExpr, 2,
Semantics : 2 // an AccessSemantics
);
SWIFT_INLINE_BITFIELD_FULL(TupleElementExpr, Expr, 32,
: NumPadBits,
FieldNo : 32
);
SWIFT_INLINE_BITFIELD_FULL(TupleExpr, Expr, 1+1+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, LookupExpr, 2+1+1+16,
Semantics : 2, // an AccessSemantics
/// Whether the SubscriptExpr also has source locations for the argument
/// label.
HasArgLabelLocs : 1,
/// Whether the last argument is a trailing closure.
HasTrailingClosure : 1,
: NumPadBits,
/// # of argument labels stored after the SubscriptExpr.
NumArgLabels : 16
);
SWIFT_INLINE_BITFIELD_FULL(DynamicSubscriptExpr, DynamicLookupExpr, 1+1+16,
/// Whether the DynamicSubscriptExpr also has source locations for the
/// argument label.
HasArgLabelLocs : 1,
/// Whether the last argument is a trailing closure.
HasTrailingClosure : 1,
: NumPadBits,
/// # of argument labels stored after the DynamicSubscriptExpr.
NumArgLabels : 16
);
SWIFT_INLINE_BITFIELD_FULL(UnresolvedMemberExpr, Expr, 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(DestructureTupleExpr, ImplicitConversionExpr, 16,
/// The number of elements in the tuple type being destructured.
NumElements : 16
);
SWIFT_INLINE_BITFIELD_FULL(ArgumentShuffleExpr, 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;
protected:
Expr(ExprKind Kind, bool Implicit, Type Ty = Type()) : Ty(Ty) {
Bits.OpaqueBits = 0;
Bits.Expr.Kind = unsigned(Kind);
Bits.Expr.Implicit = Implicit;
}
public:
/// Return the kind of this expression.
ExprKind getKind() const { return ExprKind(Bits.Expr.Kind); }
/// Retrieve the name of the given expression kind.
///
/// This name should only be used for debugging dumps and other
/// developer aids, and should never be part of a diagnostic or exposed
/// to the user of the compiler in any way.
static StringRef getKindName(ExprKind K);
/// getType - Return the type of this expression.
Type getType() const { return Ty; }
/// setType - Sets the type of this expression.
void setType(Type T);
/// Return the source range of the expression.
SourceRange getSourceRange() const;
/// getStartLoc - Return the location of the start of the expression.
SourceLoc getStartLoc() const;
/// Retrieve the location of the last token of the expression.
SourceLoc getEndLoc() const;
/// getLoc - Return the caret location of this expression.
SourceLoc getLoc() const;
#define SWIFT_FORWARD_SOURCE_LOCS_TO(SUBEXPR) \
SourceLoc getStartLoc() const { return (SUBEXPR)->getStartLoc(); } \
SourceLoc getEndLoc() const { return (SUBEXPR)->getEndLoc(); } \
SourceLoc getLoc() const { return (SUBEXPR)->getLoc(); } \
SourceRange getSourceRange() const { return (SUBEXPR)->getSourceRange(); }
SourceLoc TrailingSemiLoc;
/// getSemanticsProvidingExpr - Find the smallest subexpression
/// which obeys the property that evaluating it is exactly
/// equivalent to evaluating this expression.
///
/// Looks through parentheses. Would not look through something
/// like '(foo(), x:bar(), baz()).x'.
Expr *getSemanticsProvidingExpr();
const Expr *getSemanticsProvidingExpr() const {
return const_cast<Expr *>(this)->getSemanticsProvidingExpr();
}
/// getValueProvidingExpr - Find the smallest subexpression which is
/// responsible for generating the value of this expression.
/// Evaluating the result is not necessarily equivalent to
/// evaluating this expression because of potential missing
/// side-effects (which may influence the returned value).
Expr *getValueProvidingExpr();
const Expr *getValueProvidingExpr() const {
return const_cast<Expr *>(this)->getValueProvidingExpr();
}
/// If this is a reference to an operator written as a member of a type (or
/// extension thereof), return the underlying operator reference.
DeclRefExpr *getMemberOperatorRef();
/// This recursively walks the AST rooted at this expression.
Expr *walk(ASTWalker &walker);
Expr *walk(ASTWalker &&walker) { return walk(walker); }
/// Enumerate each immediate child expression of this node, invoking the
/// specific functor on it. This ignores statements and other non-expression
/// children.
void forEachImmediateChildExpr(llvm::function_ref<Expr *(Expr *)> callback);
/// Enumerate each expr node within this expression subtree, invoking the
/// specific functor on it. This ignores statements and other non-expression
/// children, and if there is a closure within the expression, this does not
/// walk into the body of it (unless it is single-expression).
void forEachChildExpr(llvm::function_ref<Expr *(Expr *)> callback);
/// Determine whether this expression refers to a type by name.
///
/// This distinguishes static references to types, like Int, from metatype
/// values, "someTy: Any.Type".
bool isTypeReference(llvm::function_ref<Type(const Expr *)> getType =
[](const Expr *E) -> Type { return E->getType(); },
llvm::function_ref<Decl *(const Expr *)> getDecl =
[](const Expr *E) -> Decl * {
return nullptr;
}) const;
/// Determine whether this expression refers to a statically-derived metatype.
///
/// This implies `isTypeReference`, but also requires that the referenced type
/// is not an archetype or dependent type.
bool isStaticallyDerivedMetatype(
llvm::function_ref<Type(const Expr *)> getType =
[](const Expr *E) -> Type { return E->getType(); },
llvm::function_ref<bool(const Expr *)> isTypeReference =
[](const Expr *E) { return E->isTypeReference(); }) const;
/// isImplicit - Determines whether this expression was implicitly-generated,
/// rather than explicitly written in the AST.
bool isImplicit() const {
return Bits.Expr.Implicit;
}
void setImplicit(bool Implicit = true) {
Bits.Expr.Implicit = Implicit;
}
/// 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;
/// Returns true if this is a reference to the implicit self of function.
bool isSelfExprOf(const AbstractFunctionDecl *AFD,
bool sameBase = false) 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 and parent,
/// in the root expression. The root expression has depth 0, its children have
/// depth 1, etc.
llvm::DenseMap<Expr *, std::pair<unsigned, Expr *>> 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, unsigned Indent = 0) const;
void dump(raw_ostream &OS, llvm::function_ref<Type(const Expr *)> getType,
llvm::function_ref<Type(const TypeLoc &)> getTypeOfTypeLoc,
unsigned Indent = 0) const;
void print(ASTPrinter &Printer, const PrintOptions &Opts) const;
// Only allow allocation of Exprs using the allocator in ASTContext
// or by doing a placement new.
void *operator new(size_t Bytes, ASTContext &C,
unsigned Alignment = alignof(Expr));
// Make placement new and vanilla new/delete illegal for Exprs.
void *operator new(size_t Bytes) throw() = delete;
void operator delete(void *Data) throw() = delete;
void *operator new(size_t Bytes, void *Mem) {
assert(Mem);
return Mem;
}
};
/// Helper class to capture trailing call argument labels and related
/// information, for expression nodes that involve argument labels, trailing
/// closures, etc.
template<typename Derived>
class TrailingCallArguments
: private llvm::TrailingObjects<Derived, Identifier, SourceLoc> {
// We need to friend TrailingObjects twice here to work around an MSVC bug.
// If we have two functions of the same name with the parameter
// typename TrailingObjectsIdentifier::template OverloadToken<T> where T is
// different for each function, then MSVC reports a "member function already
// defined or declared" error, which is incorrect.
using TrailingObjectsIdentifier = llvm::TrailingObjects<Derived, Identifier>;
friend TrailingObjectsIdentifier;
using TrailingObjects = llvm::TrailingObjects<Derived, Identifier, SourceLoc>;
friend TrailingObjects;
Derived &asDerived() {
return *static_cast<Derived *>(this);
}
const Derived &asDerived() const {
return *static_cast<const Derived *>(this);
}
size_t numTrailingObjects(
typename TrailingObjectsIdentifier::template OverloadToken<Identifier>)
const {
return asDerived().getNumArguments();
}
size_t numTrailingObjects(
typename TrailingObjectsIdentifier::template OverloadToken<SourceLoc>)
const {
return asDerived().hasArgumentLabelLocs() ? asDerived().getNumArguments()
: 0;
}
/// Retrieve the buffer containing the argument labels.
MutableArrayRef<Identifier> getArgumentLabelsBuffer() {
return { this->template getTrailingObjects<Identifier>(),
asDerived().getNumArguments() };
}
/// Retrieve the buffer containing the argument label locations.
MutableArrayRef<SourceLoc> getArgumentLabelLocsBuffer() {
if (!asDerived().hasArgumentLabelLocs())
return { };
return { this->template getTrailingObjects<SourceLoc>(),
asDerived().getNumArguments() };
}
protected:
/// Determine the total size to allocate.
static size_t totalSizeToAlloc(ArrayRef<Identifier> argLabels,
ArrayRef<SourceLoc> argLabelLocs,
bool hasTrailingClosure) {
return TrailingObjects::template totalSizeToAlloc<Identifier, SourceLoc>(
argLabels.size(), argLabelLocs.size());
}
/// Initialize the actual call arguments.
void initializeCallArguments(ArrayRef<Identifier> argLabels,
ArrayRef<SourceLoc> argLabelLocs,
bool hasTrailingClosure) {
if (!argLabels.empty()) {
std::uninitialized_copy(argLabels.begin(), argLabels.end(),
this->template getTrailingObjects<Identifier>());
}
if (!argLabelLocs.empty())
std::uninitialized_copy(argLabelLocs.begin(), argLabelLocs.end(),
this->template getTrailingObjects<SourceLoc>());
}
public:
/// Retrieve the argument labels provided at the call site.
ArrayRef<Identifier> getArgumentLabels() const {
return { this->template getTrailingObjects<Identifier>(),
asDerived().getNumArguments() };
}
/// Retrieve the buffer containing the argument label locations.
ArrayRef<SourceLoc> getArgumentLabelLocs() const {
if (!asDerived().hasArgumentLabelLocs())
return { };
return { this->template getTrailingObjects<SourceLoc>(),
asDerived().getNumArguments() };
}
/// Retrieve the location of the ith argument label.
SourceLoc getArgumentLabelLoc(unsigned i) const {
auto locs = getArgumentLabelLocs();
return i < locs.size() ? locs[i] : SourceLoc();
}
};
/// ErrorExpr - Represents a semantically erroneous subexpression in the AST,
/// typically this will have an ErrorType.
class ErrorExpr : public Expr {
SourceRange Range;
public:
ErrorExpr(SourceRange Range, Type Ty = Type())
: Expr(ExprKind::Error, /*Implicit=*/true, Ty), Range(Range) {}
SourceRange getSourceRange() const { return Range; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::Error;
}
};
/// CodeCompletionExpr - Represents the code completion token in the AST, this
/// can help us preserve the context of the code completion position.
class CodeCompletionExpr : public Expr {
SourceRange Range;
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;
}
};
/// The 'nil' literal.
///
class NilLiteralExpr : public LiteralExpr {
SourceLoc Loc;
ConcreteDeclRef Initializer;
public:
NilLiteralExpr(SourceLoc Loc, bool Implicit = false)
: LiteralExpr(ExprKind::NilLiteral, Implicit), Loc(Loc) {
}
SourceRange getSourceRange() const {
return Loc;
}
/// Retrieve the initializer that will be used to construct the 'nil'
/// literal from the result of the initializer.
ConcreteDeclRef getInitializer() const { return Initializer; }
/// Set the initializer that will be used to construct the 'nil' literal.
void setInitializer(ConcreteDeclRef initializer) {
Initializer = initializer;
}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::NilLiteral;
}
};
/// 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.
ConcreteDeclRef BuiltinInitializer;
ConcreteDeclRef Initializer;
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;
Bits.NumberLiteralExpr.IsExplicitConversion = false;
}
bool isNegative() const { return Bits.NumberLiteralExpr.IsNegative; }
void setNegative(SourceLoc Loc) {
MinusLoc = Loc;
Bits.NumberLiteralExpr.IsNegative = true;
}
bool isExplicitConversion() const {
return Bits.NumberLiteralExpr.IsExplicitConversion;
}
void setExplicitConversion(bool isExplicitConversion = true) {
Bits.NumberLiteralExpr.IsExplicitConversion = isExplicitConversion;
}
StringRef getDigitsText() const { return Val; }
SourceRange getSourceRange() const {
if (isNegative())
return { MinusLoc, DigitsLoc };
else
return DigitsLoc;
}
SourceLoc getMinusLoc() const {
return MinusLoc;
}
SourceLoc getDigitsLoc() const {
return DigitsLoc;
}
/// Retrieve the builtin initializer that will be used to construct the
/// boolean literal.
///
/// Any type-checked boolean 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 boolean
/// literal.
void setBuiltinInitializer(ConcreteDeclRef builtinInitializer) {
BuiltinInitializer = builtinInitializer;
}
/// Retrieve the initializer that will be used to construct the boolean
/// literal from the result of the initializer.
///
/// Only boolean 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 boolean literal.
void setInitializer(ConcreteDeclRef initializer) {
Initializer = initializer;
}
static bool classof(const Expr *E) {
return E->getKind() >= ExprKind::First_NumberLiteralExpr
&& E->getKind() <= ExprKind::Last_NumberLiteralExpr;
}
};
/// Integer literal with a '+' or '-' sign, like '+4' or '- 2'.
///
/// After semantic analysis assigns types, this is guaranteed to have
/// a BuiltinIntegerType or be a normal type and implicitly be
/// AnyBuiltinIntegerType.
class IntegerLiteralExpr : public NumberLiteralExpr {
public:
IntegerLiteralExpr(StringRef Val, SourceLoc DigitsLoc, bool Implicit = false)
: NumberLiteralExpr(ExprKind::IntegerLiteral,
Val, DigitsLoc, Implicit)
{}
/// Returns a new integer literal expression with the given value.
/// \p C The AST context.
/// \p value The integer value.
/// \return An implicit integer literal expression which evaluates to the value.
static IntegerLiteralExpr *
createFromUnsigned(ASTContext &C, unsigned value);
/// Returns the value of the literal, appropriately constructed in the
/// target type.
APInt getValue() const;
/// Returns the raw value of the literal without any truncation.
APInt getRawValue() const;
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::IntegerLiteral;
}
};
/// FloatLiteralExpr - Floating point literal, like '4.0'. After semantic
/// analysis assigns types, BuiltinTy is guaranteed to only have a
/// BuiltinFloatingPointType.
class FloatLiteralExpr : public NumberLiteralExpr {
/// This is the type of the builtin literal.
Type BuiltinTy;
public:
FloatLiteralExpr(StringRef Val, SourceLoc Loc, bool Implicit = false)
: NumberLiteralExpr(ExprKind::FloatLiteral, Val, Loc, Implicit)
{}
APFloat getValue() const;
static APFloat getValue(StringRef Text, const llvm::fltSemantics &Semantics,
bool Negative);
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::FloatLiteral;
}
Type getBuiltinType() const { return BuiltinTy; }
void setBuiltinType(Type ty) { BuiltinTy = ty; }
};
/// A Boolean literal ('true' or 'false')
///
class BooleanLiteralExpr : public LiteralExpr {
SourceLoc Loc;
ConcreteDeclRef BuiltinInitializer;
ConcreteDeclRef Initializer;
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;
}
/// Retrieve the builtin initializer that will be used to construct the
/// boolean literal.
///
/// Any type-checked boolean 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 boolean
/// literal.
void setBuiltinInitializer(ConcreteDeclRef builtinInitializer) {
BuiltinInitializer = builtinInitializer;
}
/// Retrieve the initializer that will be used to construct the boolean
/// literal from the result of the initializer.
///
/// Only boolean 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 boolean literal.
void setInitializer(ConcreteDeclRef initializer) {
Initializer = initializer;
}
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 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;
}
};
/// Runs a series of statements which use or modify \c SubExpr
/// before it is given to the rest of the expression.
///
/// \c Body should begin with a \c VarDecl; this defines the variable
/// \c TapExpr will initialize at the beginning and read a result
/// from at the end. \c TapExpr creates a separate scope, then
/// assigns the result of \c SubExpr to the variable and runs \c Body
/// in it, returning the value of the variable after the \c Body runs.
///
/// (The design here could be a bit cleaner, particularly where the VarDecl
/// is concerned.)
class TapExpr : public Expr {
Expr *SubExpr;
BraceStmt *Body;
public:
TapExpr(Expr *SubExpr, BraceStmt *Body);
Expr * getSubExpr() const { return SubExpr; }
void setSubExpr(Expr * se) { SubExpr = se; }
/// The variable which will be accessed and possibly modified by
/// the \c Body. This is the first \c ASTNode in the \c Body.
VarDecl * getVar() const;
BraceStmt * getBody() const { return Body; }
void setBody(BraceStmt * b) { Body = b; }
SourceLoc getLoc() const { return SubExpr ? SubExpr->getLoc() : SourceLoc(); }
SourceRange getSourceRange() const {
return SubExpr ? SubExpr->getSourceRange() : SourceRange();
}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::Tap;
}
};
/// InterpolatedStringLiteral - An interpolated string literal.
///
/// An interpolated string literal mixes expressions (which are evaluated and
/// converted into string form) within a string literal.
///
/// \code
/// "[\(min)..\(max)]"
/// \endcode
class InterpolatedStringLiteralExpr : public LiteralExpr {
/// Points at the beginning quote.
SourceLoc Loc;
TapExpr *AppendingExpr;
Expr *SemanticExpr;
public:
InterpolatedStringLiteralExpr(SourceLoc Loc, unsigned LiteralCapacity,
unsigned InterpolationCount,
TapExpr *AppendingExpr)
: LiteralExpr(ExprKind::InterpolatedStringLiteral, /*Implicit=*/false),
Loc(Loc), AppendingExpr(AppendingExpr), SemanticExpr() {
Bits.InterpolatedStringLiteralExpr.InterpolationCount = InterpolationCount;
Bits.InterpolatedStringLiteralExpr.LiteralCapacity = LiteralCapacity;
}
/// Retrieve the value of the literalCapacity parameter to the
/// initializer.
unsigned getLiteralCapacity() const {
return Bits.InterpolatedStringLiteralExpr.LiteralCapacity;
}
/// Retrieve the value of the interpolationCount parameter to the
/// initializer.
unsigned getInterpolationCount() const {
return Bits.InterpolatedStringLiteralExpr.InterpolationCount;
}
/// A block containing expressions which call
/// \c StringInterpolationProtocol methods to append segments to the
/// string interpolation. The first node in \c Body should be an uninitialized
/// \c VarDecl; the other statements should append to it.
TapExpr * getAppendingExpr() const { return AppendingExpr; }
void setAppendingExpr(TapExpr * AE) { AppendingExpr = AE; }
/// 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;
}
/// Call the \c callback with information about each segment in turn.
void forEachSegment(ASTContext &Ctx,
llvm::function_ref<void(bool, CallExpr *)> callback);
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::InterpolatedStringLiteral;
}
};
/// MagicIdentifierLiteralExpr - A magic identifier like #file which expands
/// out to a literal at SILGen time.
class MagicIdentifierLiteralExpr : public 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
/// literal.
///
/// Any type-checked literal will have a builtin initializer, which is
/// called first to form a concrete Swift type.
ConcreteDeclRef getBuiltinInitializer() const {
return BuiltinInitializer;
}
/// Set the builtin initializer that will be used to construct the literal.
void setBuiltinInitializer(ConcreteDeclRef builtinInitializer) {
BuiltinInitializer = builtinInitializer;
}
/// Retrieve the initializer that will be used to construct the literal from
/// the result of the initializer.
///
/// Only literals that have no builtin literal conformance will have
/// this initializer, which will be called on the result of the builtin
/// initializer.
ConcreteDeclRef getInitializer() const {
return Initializer;
}
/// Set the initializer that will be used to construct the literal.
void setInitializer(ConcreteDeclRef initializer) {
Initializer = initializer;
}
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 {
/// 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;
}
};
/// LookupExpr - This abstract class represents 'a.b', 'a[]', etc where we
/// are referring to a member of a type, such as a property, variable, etc.
class LookupExpr : public Expr {
Expr *Base;
ConcreteDeclRef Member;
protected:
explicit LookupExpr(ExprKind Kind, Expr *base, ConcreteDeclRef member,
bool Implicit)
: Expr(Kind, Implicit), Base(base), Member(member) {
Bits.LookupExpr.IsSuper = false;
assert(Base);
}
public:
/// Retrieve the base of the expression.
Expr *getBase() const { return Base; }
/// Replace the base of the expression.
void setBase(Expr *E) { Base = E; }
/// Retrieve the member to which this access refers.
ConcreteDeclRef getMember() const { return Member; }
/// Determine whether the operation has a known underlying declaration or not.
bool hasDecl() const { return static_cast<bool>(Member); }
/// Retrieve the declaration that this /// operation refers to.
/// Only valid when \c hasDecl() is true.
ConcreteDeclRef getDecl() const {
assert(hasDecl() && "No subscript declaration known!");
return getMember();
}
/// Determine whether this reference refers to the superclass's property.
bool isSuper() const { return Bits.LookupExpr.IsSuper; }
/// Set whether this reference refers to the superclass's property.
void setIsSuper(bool isSuper) { Bits.LookupExpr.IsSuper = isSuper; }
static bool classof(const Expr *E) {
return E->getKind() >= ExprKind::First_LookupExpr &&
E->getKind() <= ExprKind::Last_LookupExpr;
}
};
/// MemberRefExpr - This represents 'a.b' where we are referring to a member
/// of a type, such as a property or variable.
///
/// Note that methods found via 'dot' syntax are expressed as DotSyntaxCallExpr
/// nodes, because 'a.f' is actually an application of 'a' (the implicit object
/// argument) to the function 'f'.
class MemberRefExpr : public LookupExpr {
SourceLoc DotLoc;
DeclNameLoc NameLoc;
public:
MemberRefExpr(Expr *base, SourceLoc dotLoc, ConcreteDeclRef member,
DeclNameLoc loc, bool Implicit,
AccessSemantics semantics = AccessSemantics::Ordinary);
SourceLoc getDotLoc() const { return DotLoc; }
DeclNameLoc getNameLoc() const { return NameLoc; }
/// Return true if this member access is direct, meaning that it
/// does not call the getter or setter.
AccessSemantics getAccessSemantics() const {
return (AccessSemantics) Bits.MemberRefExpr.Semantics;
}
SourceLoc getLoc() const { return NameLoc.getBaseNameLoc(); }
SourceLoc getStartLoc() const {
SourceLoc BaseStartLoc = getBase()->getStartLoc();
if (BaseStartLoc.isInvalid() || NameLoc.isInvalid()) {
return NameLoc.getBaseNameLoc();
} else {
return BaseStartLoc;
}
}
SourceLoc getEndLoc() const {
return NameLoc.getSourceRange().End;
}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::MemberRef;
}
};
/// Common base for expressions that involve dynamic lookup, which
/// determines at runtime whether a particular method, property, or
/// subscript is available.
class DynamicLookupExpr : public LookupExpr {
protected:
explicit DynamicLookupExpr(ExprKind kind, ConcreteDeclRef member, Expr *base)
: LookupExpr(kind, base, member, /*Implicit=*/false) { }
public:
static bool classof(const Expr *E) {
return E->getKind() >= ExprKind::First_DynamicLookupExpr &&
E->getKind() <= ExprKind::Last_DynamicLookupExpr;
}
};
/// A reference to a member of an object that was found via dynamic lookup.
///
/// A member found via dynamic lookup may not actually be available at runtime.
/// Therefore, a reference to that member always returns an optional instance.
/// Users can then propagate the optional (via ?) or assert that the member is
/// always available (via !). For example:
///
/// \code
/// class C {
/// func @objc foo(i : Int) -> String { ... }
/// };
///
/// var x : AnyObject = <some value>
/// print(x.foo!(17)) // x.foo has type ((i : Int) -> String)?
/// \endcode
class DynamicMemberRefExpr : public DynamicLookupExpr {
SourceLoc DotLoc;
DeclNameLoc NameLoc;
public:
DynamicMemberRefExpr(Expr *base, SourceLoc dotLoc,
ConcreteDeclRef member,
DeclNameLoc nameLoc)
: DynamicLookupExpr(ExprKind::DynamicMemberRef, member, base),
DotLoc(dotLoc), NameLoc(nameLoc) {
}
/// Retrieve the location of the member name.
DeclNameLoc getNameLoc() const { return NameLoc; }
/// Retrieve the location of the '.'.
SourceLoc getDotLoc() const { return DotLoc; }
SourceLoc getLoc() const { return NameLoc.getBaseNameLoc(); }
SourceLoc getStartLoc() const {
SourceLoc BaseStartLoc = getBase()->getStartLoc();
if (BaseStartLoc.isInvalid() || NameLoc.isInvalid()) {
return NameLoc.getBaseNameLoc();
} else {
return BaseStartLoc;
}
}
SourceLoc getEndLoc() const { return NameLoc.getSourceRange().End; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::DynamicMemberRef;
}
};
/// A subscript on an object with dynamic lookup type.
///
/// A subscript found via dynamic lookup may not actually be available
/// at runtime. Therefore, the result of performing the subscript
/// operation always returns an optional instance.Users can then
/// propagate the optional (via ?) or assert that the member is always
/// available (via !). For example:
///
/// \code
/// class C {
/// @objc subscript (i : Int) -> String {
/// get {
/// ...
/// }
/// }
/// };
///
/// var x : AnyObject = <some value>
/// print(x[27]! // x[27] has type String?
/// \endcode
class DynamicSubscriptExpr final
: public DynamicLookupExpr,
public TrailingCallArguments<DynamicSubscriptExpr> {
friend TrailingCallArguments;
Expr *Index;
DynamicSubscriptExpr(Expr *base, Expr *index, ArrayRef<Identifier> argLabels,
ArrayRef<SourceLoc> argLabelLocs,
bool hasTrailingClosure, ConcreteDeclRef member,
bool implicit);
public:
/// Create a dynamic subscript.
///
/// Note: do not create new callers to this entry point; use the entry point
/// that takes separate index arguments.
static DynamicSubscriptExpr *
create(ASTContext &ctx, Expr *base, Expr *index, ConcreteDeclRef decl,
bool implicit,
llvm::function_ref<Type(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);
/// 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 getBase()->getStartLoc(); }
SourceLoc getEndLoc() const { return Index->getEndLoc(); }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::DynamicSubscript;
}
};
/// UnresolvedMemberExpr - This represents '.foo', an unresolved reference to a
/// member, which is to be resolved with context sensitive type information into
/// bar.foo. These always have unresolved type.
class UnresolvedMemberExpr final
: public Expr,
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;
}
/// 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;
/// 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; }
};
/// A collection literal expression.
///
/// The subexpression is represented as a TupleExpr or ParenExpr and
/// passed on to the appropriate semantics-providing conversion
/// operation.
class CollectionExpr : public Expr {
SourceLoc LBracketLoc;
SourceLoc RBracketLoc;
ConcreteDeclRef Initializer;
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(), static_cast<size_t>(Bits.CollectionExpr.NumCommas)};
}
ArrayRef<SourceLoc> getCommaLocs() const {
return {getTrailingSourceLocs(), static_cast<size_t>(Bits.CollectionExpr.NumCommas)};
}
unsigned getNumCommas() const { return Bits.CollectionExpr.NumCommas; }
bool isTypeDefaulted() const { return Bits.CollectionExpr.IsTypeDefaulted; }
void setIsTypeDefaulted(bool value = true) {
Bits.CollectionExpr.IsTypeDefaulted = value;
}
SourceLoc getLBracketLoc() const { return LBracketLoc; }
SourceLoc getRBracketLoc() const { return RBracketLoc; }
SourceRange getSourceRange() const {
return SourceRange(LBracketLoc, RBracketLoc);
}
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;
}
/// Retrieve the initializer that will be used to construct the 'array'
/// literal from the result of the initializer.
ConcreteDeclRef getInitializer() const { return Initializer; }
/// Set the initializer that will be used to construct the 'array' literal.
void setInitializer(ConcreteDeclRef initializer) {
Initializer = initializer;
}
};
/// An array literal expression [a, b, c].
class ArrayExpr final : public CollectionExpr,
private llvm::TrailingObjects<ArrayExpr, Expr*, SourceLoc> {
friend TrailingObjects;
friend CollectionExpr;
size_t numTrailingObjects(OverloadToken<Expr *>) const {
return getNumElements();
}
size_t numTrailingObjects(OverloadToken<SourceLoc>) const {
return getNumCommas();
}
ArrayExpr(SourceLoc LBracketLoc, ArrayRef<Expr*> Elements,
ArrayRef<SourceLoc> CommaLocs,
SourceLoc RBracketLoc, Type Ty)
: CollectionExpr(ExprKind::Array, LBracketLoc, Elements, CommaLocs,
RBracketLoc, Ty) { }
public:
static ArrayExpr *create(ASTContext &C, SourceLoc LBracketLoc,
ArrayRef<Expr*> Elements,
ArrayRef<SourceLoc> CommaLocs,
SourceLoc RBracketLoc,
Type Ty = Type());
static bool classof(const Expr *e) {
return e->getKind() == ExprKind::Array;
}
Type getElementType();
};
/// A dictionary literal expression [a : x, b : y, c : z].
class DictionaryExpr final : public CollectionExpr,
private llvm::TrailingObjects<DictionaryExpr, Expr*, SourceLoc> {
friend TrailingObjects;
friend CollectionExpr;
size_t numTrailingObjects(OverloadToken<Expr *>) const {
return getNumElements();
}
size_t numTrailingObjects(OverloadToken<SourceLoc>) const {
return getNumCommas();
}
DictionaryExpr(SourceLoc LBracketLoc, ArrayRef<Expr*> Elements,
ArrayRef<SourceLoc> CommaLocs,
SourceLoc RBracketLoc, Type Ty)
: CollectionExpr(ExprKind::Dictionary, LBracketLoc, Elements, CommaLocs,
RBracketLoc, Ty) { }
public:
static DictionaryExpr *create(ASTContext &C, SourceLoc LBracketLoc,
ArrayRef<Expr*> Elements,
ArrayRef<SourceLoc> CommaLocs,
SourceLoc RBracketLoc,
Type Ty = Type());
static bool classof(const Expr *e) {
return e->getKind() == ExprKind::Dictionary;
}
};
/// Subscripting expressions like a[i] that refer to an element within a
/// container.
///
/// There is no built-in subscripting in the language. Rather, a fully
/// type-checked and well-formed subscript expression refers to a subscript
/// declaration, which provides a getter and (optionally) a setter that will
/// be used to perform reads/writes.
class SubscriptExpr final : public LookupExpr,
public TrailingCallArguments<SubscriptExpr> {
friend TrailingCallArguments;
Expr *Index;
SubscriptExpr(Expr *base, Expr *index, ArrayRef<Identifier> argLabels,
ArrayRef<SourceLoc> argLabelLocs, bool hasTrailingClosure,
ConcreteDeclRef decl, bool implicit, AccessSemantics semantics);
public:
/// Create a subscript.
///
/// Note: do not create new callers to this entry point; use the entry point
/// that takes separate index arguments.
static SubscriptExpr *
create(ASTContext &ctx, Expr *base, Expr *index,
ConcreteDeclRef decl = ConcreteDeclRef(), bool implicit = false,
AccessSemantics semantics = AccessSemantics::Ordinary,
llvm::function_ref<Type(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);
/// getIndex - Retrieve the index of the subscript expression, i.e., the
/// "offset" into the base value.
Expr *getIndex() const { return Index; }
void setIndex(Expr *E) { Index = E; }
unsigned getNumArguments() const {
return Bits.SubscriptExpr.NumArgLabels;
}
bool hasArgumentLabelLocs() const {
return Bits.SubscriptExpr.HasArgLabelLocs;
}
/// Whether this call was written with a trailing closure.
bool hasTrailingClosure() const {
return Bits.SubscriptExpr.HasTrailingClosure;
}
/// Determine whether this subscript reference should bypass the
/// ordinary accessors.
AccessSemantics getAccessSemantics() const {
return (AccessSemantics) Bits.SubscriptExpr.Semantics;
}
SourceLoc getLoc() const { return Index->getStartLoc(); }
SourceLoc getStartLoc() const { return getBase()->getStartLoc(); }
SourceLoc getEndLoc() const {
auto end = Index->getEndLoc();
return end.isValid() ? end : getBase()->getEndLoc();
}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::Subscript;
}
};
/// Subscripting expression that applies a keypath to a base.
class KeyPathApplicationExpr : public Expr {
Expr *Base;
Expr *KeyPath;
SourceLoc LBracketLoc, RBracketLoc;
public:
KeyPathApplicationExpr(Expr *base, SourceLoc lBracket, Expr *keyPath,
SourceLoc rBracket, Type ty, bool implicit)
: Expr(ExprKind::KeyPathApplication, implicit, ty),
Base(base), KeyPath(keyPath), LBracketLoc(lBracket), RBracketLoc(rBracket)
{}
SourceLoc getLoc() const { return LBracketLoc; }
SourceLoc getStartLoc() const { return Base->getStartLoc(); }
SourceLoc getEndLoc() const { return RBracketLoc; }
Expr *getBase() const { return Base; }
void setBase(Expr *E) { Base = E; }
Expr *getKeyPath() const { return KeyPath; }
void setKeyPath(Expr *E) { KeyPath = E; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::KeyPathApplication;
}
};
/// A member access (foo.bar) on an expression with unresolved type.
class UnresolvedDotExpr : public Expr {
Expr *SubExpr;
SourceLoc DotLoc;
DeclNameLoc NameLoc;
DeclName Name;
ArrayRef<ValueDecl *> OuterAlternatives;
public:
UnresolvedDotExpr(
Expr *subexpr, SourceLoc dotloc, DeclName name, DeclNameLoc nameloc,
bool Implicit,
ArrayRef<ValueDecl *> outerAlternatives = ArrayRef<ValueDecl *>())
: Expr(ExprKind::UnresolvedDot, Implicit), SubExpr(subexpr),
DotLoc(dotloc), NameLoc(nameloc), Name(name),
OuterAlternatives(outerAlternatives) {
Bits.UnresolvedDotExpr.FunctionRefKind =
static_cast<unsigned>(NameLoc.isCompound() ? FunctionRefKind::Compound
: FunctionRefKind::Unapplied);
}
SourceLoc getLoc() const { return NameLoc.getBaseNameLoc(); }
SourceLoc getStartLoc() const {
return (DotLoc.isInvalid() ? NameLoc.getSourceRange().End
: SubExpr->getStartLoc());
}
SourceLoc getEndLoc() const {
return NameLoc.getSourceRange().End;
}
SourceLoc getDotLoc() const { return DotLoc; }
Expr *getBase() const { return SubExpr; }
void setBase(Expr *e) { SubExpr = e; }
DeclName getName() const { return Name; }
DeclNameLoc getNameLoc() const { return NameLoc; }
ArrayRef<ValueDecl *> getOuterAlternatives() const {
return OuterAlternatives;
}
/// Retrieve the kind of function reference.
FunctionRefKind getFunctionRefKind() const {
return static_cast<FunctionRefKind>(Bits.UnresolvedDotExpr.FunctionRefKind);
}
/// Set the kind of function reference.
void setFunctionRefKind(FunctionRefKind refKind) {
Bits.UnresolvedDotExpr.FunctionRefKind = static_cast<unsigned>(refKind);
}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::UnresolvedDot;
}
};
/// TupleElementExpr - Refer to an element of a tuple,
/// e.g. "(1,field:2).field".
class TupleElementExpr : public Expr {
Expr *SubExpr;
SourceLoc NameLoc;
SourceLoc DotLoc;
public:
TupleElementExpr(Expr *SubExpr, SourceLoc DotLoc, unsigned FieldNo,
SourceLoc NameLoc, Type Ty)
: Expr(ExprKind::TupleElement, /*Implicit=*/false, Ty), SubExpr(SubExpr),
NameLoc(NameLoc), DotLoc(DotLoc) {
Bits.TupleElementExpr.FieldNo = FieldNo;
}
SourceLoc getLoc() const { return NameLoc; }
Expr *getBase() const { return SubExpr; }
void setBase(Expr *e) { SubExpr = e; }
unsigned getFieldNumber() const { return Bits.TupleElementExpr.FieldNo; }
SourceLoc getNameLoc() const { return NameLoc; }
SourceLoc getDotLoc() const { return DotLoc; }
SourceLoc getStartLoc() const { return getBase()->getStartLoc(); }
SourceLoc getEndLoc() const { return getNameLoc(); }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::TupleElement;
}
};
/// Describes a monadic bind from T? to T.
///
/// In a ?-chain expression, this is the part that's spelled with a
/// postfix ?.
///
/// A BindOptionalExpr must always appear within a
/// OptionalEvaluationExpr. If the operand of the BindOptionalExpr
/// evaluates to a missing value, the OptionalEvaluationExpr
/// immediately completes and produces a missing value in the result
/// type.
///
/// The depth of the BindOptionalExpr indicates which
/// OptionalEvaluationExpr is completed, in case the BindOptionalExpr
/// is contained within more than one such expression.
class BindOptionalExpr : public Expr {
Expr *SubExpr;
SourceLoc QuestionLoc;
public:
BindOptionalExpr(Expr *subExpr, SourceLoc questionLoc,
unsigned depth, Type ty = Type())
: Expr(ExprKind::BindOptional, /*Implicit=*/ questionLoc.isInvalid(), ty),
SubExpr(subExpr), QuestionLoc(questionLoc) {
Bits.BindOptionalExpr.Depth = depth;
assert(Bits.BindOptionalExpr.Depth == depth && "bitfield truncation");
}
SourceRange getSourceRange() const {
if (QuestionLoc.isInvalid())
return SubExpr->getSourceRange();
return SourceRange(SubExpr->getStartLoc(), QuestionLoc);
}
SourceLoc getStartLoc() const {
return SubExpr->getStartLoc();
}
SourceLoc getEndLoc() const {
return (QuestionLoc.isInvalid() ? SubExpr->getEndLoc() : QuestionLoc);
}
SourceLoc getLoc() const {
if (isImplicit())
return SubExpr->getLoc();
return getQuestionLoc();
}
SourceLoc getQuestionLoc() const { return QuestionLoc; }
unsigned getDepth() const { return Bits.BindOptionalExpr.Depth; }
void setDepth(unsigned depth) {
Bits.BindOptionalExpr.Depth = depth;
}
Expr *getSubExpr() const { return SubExpr; }
void setSubExpr(Expr *expr) { SubExpr = expr; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::BindOptional;
}
};
/// Describes the outer limits of an operation containing
/// monadic binds of T? to T.
///
/// In a ?-chain expression, this is implicitly formed at the outer
/// limits of the chain. For example, in (foo?.bar?().baz).fred,
/// this is nested immediately within the parens.
///
/// This expression will always have optional type.
class OptionalEvaluationExpr : public Expr {
Expr *SubExpr;
public:
OptionalEvaluationExpr(Expr *subExpr, Type ty = Type())
: Expr(ExprKind::OptionalEvaluation, /*Implicit=*/ true, ty),
SubExpr(subExpr) {}
SWIFT_FORWARD_SOURCE_LOCS_TO(SubExpr)
Expr *getSubExpr() const { return SubExpr; }
void setSubExpr(Expr *expr) { SubExpr = expr; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::OptionalEvaluation;
}
};
/// An expression that forces an optional to its underlying value.
///
/// \code
/// func parseInt(s : String) -> Int? { ... }
///
/// var maybeInt = parseInt("5") // returns an Int?
/// var forcedInt = parseInt("5")! // returns an Int; fails on empty optional
/// \endcode
///
class ForceValueExpr : public Expr {
Expr *SubExpr;
SourceLoc ExclaimLoc;
public:
ForceValueExpr(Expr *subExpr, SourceLoc exclaimLoc, bool forcedIUO = false)
: Expr(ExprKind::ForceValue, /*Implicit=*/exclaimLoc.isInvalid(), Type()),
SubExpr(subExpr), ExclaimLoc(exclaimLoc) {
Bits.ForceValueExpr.ForcedIUO = forcedIUO;
}
SourceRange getSourceRange() const {
if (ExclaimLoc.isInvalid())
return SubExpr->getSourceRange();
return SourceRange(SubExpr->getStartLoc(), ExclaimLoc);
}
SourceLoc getStartLoc() const {
return SubExpr->getStartLoc();
}
SourceLoc getEndLoc() const {
return (isImplicit() ? SubExpr->getEndLoc() : getExclaimLoc());
}
SourceLoc getLoc() const {
if (!isImplicit())
return getExclaimLoc();
return SubExpr->getLoc();
}
SourceLoc getExclaimLoc() const { return ExclaimLoc; }
Expr *getSubExpr() const { return SubExpr; }
void setSubExpr(Expr *expr) { SubExpr = expr; }
bool isForceOfImplicitlyUnwrappedOptional() const {
return Bits.ForceValueExpr.ForcedIUO;
}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::ForceValue;
}
};
/// An expression that grants temporary escapability to a nonescaping
/// closure value.
///
/// This expression is formed by the type checker when a call to the
/// `withoutActuallyEscaping` declaration is made.
class MakeTemporarilyEscapableExpr : public Expr {
Expr *NonescapingClosureValue;
OpaqueValueExpr *EscapingClosureValue;
Expr *SubExpr;
SourceLoc NameLoc, LParenLoc, RParenLoc;
Expr *OriginalExpr;
public:
MakeTemporarilyEscapableExpr(SourceLoc NameLoc,
SourceLoc LParenLoc,
Expr *NonescapingClosureValue,
Expr *SubExpr,
SourceLoc RParenLoc,
OpaqueValueExpr *OpaqueValueForEscapingClosure,
Expr *OriginalExpr,
bool implicit = false)
: Expr(ExprKind::MakeTemporarilyEscapable, implicit, Type()),
NonescapingClosureValue(NonescapingClosureValue),
EscapingClosureValue(OpaqueValueForEscapingClosure),
SubExpr(SubExpr),
NameLoc(NameLoc), LParenLoc(LParenLoc), RParenLoc(RParenLoc),
OriginalExpr(OriginalExpr)
{}
SourceLoc getStartLoc() const {
return NameLoc;
}
SourceLoc getEndLoc() const {
return RParenLoc;
}
SourceLoc getLoc() const {
return NameLoc;
}
/// Retrieve the opaque value representing the escapable copy of the
/// closure.
OpaqueValueExpr *getOpaqueValue() const { return EscapingClosureValue; }
/// Retrieve the nonescaping closure expression.
Expr *getNonescapingClosureValue() const {
return NonescapingClosureValue;
}
void setNonescapingClosureValue(Expr *e) {
NonescapingClosureValue = e;
}
/// Retrieve the subexpression that has access to the escapable copy of the
/// closure.
Expr *getSubExpr() const {
return SubExpr;
}
void setSubExpr(Expr *e) {
SubExpr = e;
}
/// Retrieve the original 'withoutActuallyEscaping(closure) { ... }'
// expression.
Expr *getOriginalExpr() const {
return OriginalExpr;
}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::MakeTemporarilyEscapable;
}
};
/// An expression that opens up a value of protocol or protocol
/// composition type and gives a name to its dynamic type.
///
/// This expression is implicitly created by the type checker when
/// calling a method on a protocol. In the future, this may become an
/// actual operation within the language.
class OpenExistentialExpr : public Expr {
Expr *ExistentialValue;
OpaqueValueExpr *OpaqueValue;
Expr *SubExpr;
SourceLoc ExclaimLoc;
public:
OpenExistentialExpr(Expr *existentialValue,
OpaqueValueExpr *opaqueValue,
Expr *subExpr,
Type subExprTy)
: Expr(ExprKind::OpenExistential, /*Implicit=*/ true, subExprTy),
ExistentialValue(existentialValue), OpaqueValue(opaqueValue),
SubExpr(subExpr) { }
SWIFT_FORWARD_SOURCE_LOCS_TO(SubExpr)
/// Retrieve the expression that is being evaluated using the
/// archetype value.
///
/// This subexpression (and no other) may refer to the archetype
/// type or the opaque value that stores the archetype's value.
Expr *getSubExpr() const { return SubExpr; }
/// Set the subexpression that is being evaluated.
void setSubExpr(Expr *expr) { SubExpr = expr; }
/// Retrieve the existential value that is being opened.
Expr *getExistentialValue() const { return ExistentialValue; }
/// Set the existential val ue that is being opened.
void setExistentialValue(Expr *expr) { ExistentialValue = expr; }
/// Retrieve the opaque value representing the value (of archetype
/// type) stored in the existential.
OpaqueValueExpr *getOpaqueValue() const { return OpaqueValue; }
/// Retrieve the opened archetype, which can only be referenced
/// within this expression's subexpression.
OpenedArchetypeType *getOpenedArchetype() const;
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::OpenExistential;
}
};
/// ImplicitConversionExpr - An abstract class for expressions which
/// implicitly convert the value of an expression in some way.
class ImplicitConversionExpr : public Expr {
Expr *SubExpr;
protected:
ImplicitConversionExpr(ExprKind kind, Expr *subExpr, Type ty)
: Expr(kind, /*Implicit=*/true, ty), SubExpr(subExpr) {}
public:
SWIFT_FORWARD_SOURCE_LOCS_TO(SubExpr)
Expr *getSubExpr() const { return SubExpr; }
void setSubExpr(Expr *e) { SubExpr = e; }
Expr *getSyntacticSubExpr() const {
if (auto *ICE = dyn_cast<ImplicitConversionExpr>(SubExpr))
return ICE->getSyntacticSubExpr();
return SubExpr;
}
static bool classof(const Expr *E) {
return E->getKind() >= ExprKind::First_ImplicitConversionExpr &&
E->getKind() <= ExprKind::Last_ImplicitConversionExpr;
}
};
/// The implicit conversion from a class metatype to AnyObject.
class ClassMetatypeToObjectExpr : public ImplicitConversionExpr {
public:
ClassMetatypeToObjectExpr(Expr *subExpr, Type ty)
: 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;
}
};
/// DestructureTupleExpr - Destructure a tuple value produced by a source
/// expression, binding the elements to OpaqueValueExprs, then evaluate the
/// result expression written in terms of the OpaqueValueExprs.
class DestructureTupleExpr final : public ImplicitConversionExpr,
private llvm::TrailingObjects<DestructureTupleExpr, OpaqueValueExpr *> {
friend TrailingObjects;
size_t numTrailingObjects(OverloadToken<OpaqueValueExpr *>) const {
return Bits.DestructureTupleExpr.NumElements;
}
private:
Expr *DstExpr;
DestructureTupleExpr(ArrayRef<OpaqueValueExpr *> destructuredElements,
Expr *srcExpr, Expr *dstExpr, Type ty)
: ImplicitConversionExpr(ExprKind::DestructureTuple, srcExpr, ty),
DstExpr(dstExpr) {
Bits.DestructureTupleExpr.NumElements = destructuredElements.size();
std::uninitialized_copy(destructuredElements.begin(),
destructuredElements.end(),
getTrailingObjects<OpaqueValueExpr *>());
}
public:
/// Create a tuple destructuring. The type of srcExpr must be a tuple type,
/// and the number of elements must equal the size of destructureElements.
static DestructureTupleExpr *
create(ASTContext &ctx,
ArrayRef<OpaqueValueExpr *> destructuredElements,
Expr *srcExpr, Expr *dstExpr, Type ty);
ArrayRef<OpaqueValueExpr *> getDestructuredElements() const {
return {getTrailingObjects<OpaqueValueExpr *>(),
static_cast<size_t>(Bits.DestructureTupleExpr.NumElements)};
}
Expr *getResultExpr() const {
return DstExpr;
}
void setResultExpr(Expr *dstExpr) {
DstExpr = dstExpr;
}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::DestructureTuple;
}
};
/// ArgumentShuffleExpr - This represents a "complex" argument list of an
/// ApplyExpr, with default arguments or varargs.
///
/// 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 ArgumentShuffleExpr final : public ImplicitConversionExpr,
private llvm::TrailingObjects<ArgumentShuffleExpr, Expr *, int, unsigned> {
friend TrailingObjects;
size_t numTrailingObjects(OverloadToken<Expr *>) const {
return Bits.ArgumentShuffleExpr.NumCallerDefaultArgs;
}
size_t numTrailingObjects(OverloadToken<int>) const {
return Bits.ArgumentShuffleExpr.NumElementMappings;
}
size_t numTrailingObjects(OverloadToken<unsigned>) const {
return Bits.ArgumentShuffleExpr.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 ArgumentShuffleExpr 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.
///
/// Example: (x: Int) => (x: Int, y: Int = 0).
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.
///
/// Example: () -> (_: Int = 0)
/// Another example: (Int, Int) => (_: Int...)
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.
///
/// Example: (Int) -> (_: Int, y: Int = 0)
ScalarToTuple
// (ArgumentShuffleExpr 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;
ArgumentShuffleExpr(Expr *subExpr, ArrayRef<int> elementMapping,
TypeImpact typeImpact,
ConcreteDeclRef defaultArgsOwner,
ArrayRef<unsigned> VariadicArgs,
Type VarargsArrayTy,
ArrayRef<Expr *> CallerDefaultArgs,
Type ty)
: ImplicitConversionExpr(ExprKind::ArgumentShuffle, subExpr, ty),
VarargsArrayTy(VarargsArrayTy), DefaultArgsOwner(defaultArgsOwner) {
Bits.ArgumentShuffleExpr.TypeImpact = typeImpact;
Bits.ArgumentShuffleExpr.NumCallerDefaultArgs = CallerDefaultArgs.size();
Bits.ArgumentShuffleExpr.NumElementMappings = elementMapping.size();
Bits.ArgumentShuffleExpr.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 ArgumentShuffleExpr *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>(),
static_cast<size_t>(Bits.ArgumentShuffleExpr.NumElementMappings)};
}
/// What is the type impact of this shuffle?
TypeImpact getTypeImpact() const {
return TypeImpact(Bits.ArgumentShuffleExpr.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>(),
static_cast<size_t>(Bits.ArgumentShuffleExpr.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*>(),
static_cast<size_t>(Bits.ArgumentShuffleExpr.NumCallerDefaultArgs)};
}
/// Retrieve the caller-defaulted arguments.
MutableArrayRef<Expr *> getCallerDefaultArgs() {
return {getTrailingObjects<Expr*>(),
static_cast<size_t>(Bits.ArgumentShuffleExpr.NumCallerDefaultArgs)};
}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::ArgumentShuffle;
}
};
/// 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);
/// 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) {}
/// 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) {
}
/// 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; }
/// 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;
}
};
/// 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;
}
};
/// 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;
}
};
/// The not-yet-actually-surfaced '...' varargs expansion operator,
/// which splices an array into a sequence of variadic arguments.
class VarargExpansionExpr : public Expr {
Expr *SubExpr;
public:
VarargExpansionExpr(Expr *subExpr, bool implicit, Type type = Type())
: Expr(ExprKind::VarargExpansion, implicit, type), SubExpr(subExpr) {}
SWIFT_FORWARD_SOURCE_LOCS_TO(SubExpr)
Expr *getSubExpr() const { return SubExpr; }
void setSubExpr(Expr *subExpr) { SubExpr = subExpr; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::VarargExpansion;
}
};
/// 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;
}
};
/// A base class for closure expressions.
class AbstractClosureExpr : public DeclContext, public Expr {
CaptureInfo Captures;
/// 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; }
/// 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 };
/// Retrieve the result type of this closure.
Type getResultType(llvm::function_ref<Type(const Expr *)> getType =
[](const Expr *E) -> Type {
return E->getType();
}) const;
/// 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;
}
};
/// 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;
/// The location of the '->' denoting an explicit return type,
/// if present.
SourceLoc ArrowLoc;
/// The location of the "in", if present.
SourceLoc InLoc;
/// The explicitly-specified result type.
TypeLoc ExplicitResultType;
/// 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);
}
/// Determine whether the parameters of this closure are actually
/// anonymous closure variables.
bool hasAnonymousClosureVars() const {
return Bits.ClosureExpr.HasAnonymousClosureVars;
}
/// 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;
}
/// Determine whether this closure expression has an
/// explicitly-specified result type.
bool hasExplicitResultType() const { return ArrowLoc.isValid(); }
/// Retrieve the location of the \c '->' for closures with an
/// explicit result type.
SourceLoc getArrowLoc() const {
assert(hasExplicitResultType() && "No arrow location");
return ArrowLoc;
}
/// Retrieve the location of the \c in for a closure that has it.
SourceLoc getInLoc() const {
return InLoc;
}
/// Retrieve the location of the 'throws' for a closure that has it.
SourceLoc getThrowsLoc() const {
return ThrowsLoc;
}
/// 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;
}
/// 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();
}
/// Retrieve the body for closure that has a single expression for
/// its body.
///
/// Only valid when \c hasSingleExpressionBody() is true.
Expr *getSingleExpressionBody() const;
/// 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);
/// Is this a completely empty closure?
bool hasEmptyBody() const;
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));
}
};
/// 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;
/// Returns true if \c e could be used as the call's argument. For most \c ApplyExpr
/// subclasses, this means it is a \c ParenExpr, \c TupleExpr, or
/// \c ArgumentShuffleExpr.
bool validateArg(Expr *e) const;
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");
assert(validateArg(Arg) && "Arg is not a permitted expr kind");
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(validateArg(e) && "Arg is not a permitted expr kind");
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 - Postfix 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;
}
};
/// 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);
/// 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;
}
};
/// 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;
}
};
/// 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;
}
};
/// 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 {
/// Since there is already `asLoc` location,
/// we use it to store `start` of the initializer
/// call source range to save some storage.
SourceLoc InitRangeEnd;
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)
{ }
private:
CoerceExpr(SourceRange initRange, Expr *literal, TypeLoc type)
: ExplicitCastExpr(ExprKind::Coerce, literal, initRange.Start,
type, type.getType()), InitRangeEnd(initRange.End)
{ setImplicit(); }
public:
/// Create an implicit coercion expression for literal initialization
/// preserving original source information, this way original call
/// could be recreated if needed.
static CoerceExpr *forLiteralInit(ASTContext &ctx, Expr *literal,
SourceRange range, TypeLoc literalType) {
return new (ctx) CoerceExpr(range, literal, literalType);
}
bool isLiteralInit() const { return InitRangeEnd.isValid(); }
SourceRange getSourceRange() const {
return isLiteralInit()
? SourceRange(getAsLoc(), InitRangeEnd)
: ExplicitCastExpr::getSourceRange();
}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::Coerce;
}
};
/// 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;
}
};
/// 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;
}
};
/// 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;
}
};
/// 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; }
};
/// A LazyInitializerExpr is used to embed an existing typechecked
/// expression --- like the initializer of a lazy variable --- into an
/// untypechecked AST.
class LazyInitializerExpr : public Expr {
Expr *SubExpr;
public:
LazyInitializerExpr(Expr *subExpr)
: Expr(ExprKind::LazyInitializer, /*implicit*/ true),
SubExpr(subExpr) {}
SourceRange getSourceRange() const { return SubExpr->getSourceRange(); }
SourceLoc getStartLoc() const { return SubExpr->getStartLoc(); }
SourceLoc getEndLoc() const { return SubExpr->getEndLoc(); }
SourceLoc getLoc() const { return SubExpr->getLoc(); }
Expr *getSubExpr() const { return SubExpr; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::LazyInitializer;
}
};
/// 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,
Identity,
TupleElement,
};
private:
union DeclNameOrRef {
DeclName UnresolvedName;
ConcreteDeclRef ResolvedDecl;
DeclNameOrRef() : UnresolvedName{} {}
DeclNameOrRef(DeclName un) : UnresolvedName(un) {}
DeclNameOrRef(ConcreteDeclRef rd) : ResolvedDecl(rd) {}
} Decl;
Expr *SubscriptIndexExpr;
const Identifier *SubscriptLabelsData;
const ProtocolConformanceRef *SubscriptHashableConformancesData;
union {
unsigned SubscriptSize;
unsigned TupleIndex;
};
Kind KindValue;
Type ComponentType;
SourceLoc Loc;
explicit Component(ASTContext *ctxForCopyingLabels,
DeclNameOrRef decl,
Expr *indexExpr,
ArrayRef<Identifier> subscriptLabels,
ArrayRef<ProtocolConformanceRef> indexHashables,
Kind kind,
Type type,
SourceLoc loc);
// Private constructor for tuple element kind
Component(unsigned tupleIndex, Type elementType, SourceLoc loc)
: Component(nullptr, {}, nullptr, {}, {}, Kind::TupleElement,
elementType, loc) {
TupleIndex = tupleIndex;
}
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());
}
static Component forIdentity(SourceLoc selfLoc) {
return Component(nullptr, {}, nullptr, {}, {},
Kind::Identity, Type(),
selfLoc);
}
static Component forTupleElement(unsigned fieldNumber,
Type elementType,
SourceLoc loc) {
return Component(fieldNumber, elementType, loc);
}
SourceLoc getLoc() const {
return Loc;
}
Kind getKind() const {
return KindValue;
}
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:
case Kind::Identity:
case Kind::TupleElement:
return true;
case Kind::UnresolvedSubscript:
case Kind::UnresolvedProperty:
case Kind::Invalid:
return false;
}
llvm_unreachable("unhandled kind");
}
Expr *getIndexExpr() const {
switch (getKind()) {
case Kind::Subscript:
case Kind::UnresolvedSubscript:
return SubscriptIndexExpr;
case Kind::Invalid:
case Kind::OptionalChain:
case Kind::OptionalWrap:
case Kind::OptionalForce:
case Kind::UnresolvedProperty:
case Kind::Property:
case Kind::Identity:
case Kind::TupleElement:
return nullptr;
}
llvm_unreachable("unhandled kind");
}
ArrayRef<Identifier> getSubscriptLabels() const {
switch (getKind()) {
case Kind::Subscript:
case Kind::UnresolvedSubscript:
return {SubscriptLabelsData, (size_t)SubscriptSize};
case Kind::Invalid:
case Kind::OptionalChain:
case Kind::OptionalWrap:
case Kind::OptionalForce:
case Kind::UnresolvedProperty:
case Kind::Property:
case Kind::Identity:
case Kind::TupleElement:
llvm_unreachable("no subscript labels for this kind");
}
llvm_unreachable("unhandled kind");
}
ArrayRef<ProtocolConformanceRef>
getSubscriptIndexHashableConformances() const {
switch (getKind()) {
case Kind::Subscript:
if (!SubscriptHashableConformancesData)
return {};
return {SubscriptHashableConformancesData, (size_t)SubscriptSize};
case Kind::UnresolvedSubscript:
case Kind::Invalid:
case Kind::OptionalChain:
case Kind::OptionalWrap:
case Kind::OptionalForce:
case Kind::UnresolvedProperty:
case Kind::Property:
case Kind::Identity:
case Kind::TupleElement:
return {};
}
llvm_unreachable("unhandled 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:
case Kind::Identity:
case Kind::TupleElement:
llvm_unreachable("no unresolved name for this kind");
}
llvm_unreachable("unhandled 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:
case Kind::Identity:
case Kind::TupleElement:
llvm_unreachable("no decl ref for this kind");
}
llvm_unreachable("unhandled kind");
}
unsigned getTupleIndex() const {
switch (getKind()) {
case Kind::TupleElement:
return TupleIndex;
case Kind::Invalid:
case Kind::UnresolvedProperty:
case Kind::UnresolvedSubscript:
case Kind::OptionalChain:
case Kind::OptionalWrap:
case Kind::OptionalForce:
case Kind::Identity:
case Kind::Property:
case Kind::Subscript:
llvm_unreachable("no field number for this kind");
}
llvm_unreachable("unhandled 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 bool ApplyExpr::validateArg(Expr *e) const {
if (isa<SelfApplyExpr>(this))
return true;
else if (isa<BinaryExpr>(this))
return isa<TupleExpr>(e);
else
return isa<ParenExpr>(e) || isa<TupleExpr>(e) || isa<ArgumentShuffleExpr>(e);
}
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