Files
swift-mirror/include/swift/AST/Expr.h
Joe Groff 5e682924f6 AST: Drop insignificant CheckedCastKinds.
We'd like to kill this enum off eventually, since the runtime inevitably needs to be able to handle arbitrary checked casts in opaque contexts, and SILGen and IRGen can deal with picking more optimal runtime entry points for specific casts. Only the container bridging kinds are still depended on anymore, and even those ought to eventually be handlable by the runtime in 'x as T' situations. NFC yet.

Swift SVN r23127
2014-11-06 04:05:05 +00:00

3434 lines
112 KiB
C++

//===--- Expr.h - Swift Language Expression ASTs ----------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file defines the Expr class and subclasses.
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_AST_EXPR_H
#define SWIFT_AST_EXPR_H
#include "swift/AST/CaptureInfo.h"
#include "swift/AST/ConcreteDeclRef.h"
#include "swift/AST/DeclContext.h"
#include "swift/AST/Identifier.h"
#include "swift/AST/Substitution.h"
#include "swift/AST/TypeLoc.h"
#include "swift/AST/Availability.h"
#include "swift/Basic/SourceLoc.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
namespace llvm {
struct fltSemantics;
}
namespace swift {
class ArchetypeType;
class ASTContext;
class VersionConstraintAvailabilitySpec;
class Type;
class ValueDecl;
class Decl;
class Pattern;
class SubscriptDecl;
class Stmt;
class BraceStmt;
class ASTWalker;
class Initializer;
class VarDecl;
class OpaqueValueExpr;
class ProtocolConformance;
class FuncDecl;
class ConstructorDecl;
class TypeDecl;
class PatternBindingDecl;
enum class ExprKind : uint8_t {
#define EXPR(Id, Parent) Id,
#define EXPR_RANGE(Id, FirstId, LastId) \
First_##Id##Expr = FirstId, Last_##Id##Expr = LastId,
#include "swift/AST/ExprNodes.def"
};
/// Discriminates the different kinds of checked cast supported.
///
/// This enumeration should not exist. Only the collection downcast kinds are
/// currently significant. Please don't add new kinds.
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 non-value-changing checked cast.
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 dictionary type to another dictionary type that
// requires bridging.
DictionaryDowncastBridged,
/// A downcast from an object of class or Objective-C existential
/// type to its bridged value type.
BridgeFromObjectiveC,
Last_CheckedCastKind = BridgeFromObjectiveC,
};
enum class AccessSemantics : unsigned char {
/// This is a direct access to the underlying storage of a stored
/// property or subscript.
DirectToStorage,
/// This is a direct, non-polymorphic access to the getter/setter
/// accessors of a property or subscript.
DirectToAccessor,
/// This is an ordinary access to a member.
Ordinary,
};
/// Expr - Base class for all expressions in swift.
class alignas(8) Expr {
Expr(const Expr&) = delete;
void operator=(const Expr&) = delete;
class ExprBitfields {
friend class Expr;
/// The subclass of Expr that this is.
unsigned Kind : 8;
/// Whether the Expr represents something directly written in source or
/// it was implicitly generated by the type-checker.
unsigned Implicit : 1;
};
enum { NumExprBits = 9 };
static_assert(NumExprBits <= 32, "fits in an unsigned");
class LiteralExprBitfields {
friend class LiteralExpr;
unsigned : NumExprBits;
};
enum { NumLiteralExprBits = NumExprBits + 0 };
static_assert(NumLiteralExprBits <= 32, "fits in an unsigned");
class IntegerLiteralExprBitfields {
friend class IntegerLiteralExpr;
unsigned : NumLiteralExprBits;
unsigned IsNegative : 1;
};
enum { NumIntegerLiteralExprBits = NumLiteralExprBits + 1 };
static_assert(NumIntegerLiteralExprBits <= 32, "fits in an unsigned");
class StringLiteralExprBitfields {
friend class StringLiteralExpr;
unsigned : NumLiteralExprBits;
unsigned Encoding : 2;
unsigned IsSingleUnicodeScalar : 1;
unsigned IsSingleExtendedGraphemeCluster : 1;
};
enum { NumStringLiteralExprBits = NumLiteralExprBits + 2 };
static_assert(NumStringLiteralExprBits <= 32, "fits in an unsigned");
class DeclRefExprBitfields {
friend class DeclRefExpr;
unsigned : NumExprBits;
unsigned Semantics : 2; // an AccessSemantics
};
enum { NumDeclRefExprBits = NumExprBits + 2 };
static_assert(NumDeclRefExprBits <= 32, "fits in an unsigned");
class MemberRefExprBitfields {
friend class MemberRefExpr;
unsigned : NumExprBits;
unsigned Semantics : 2; // an AccessSemantics
unsigned IsSuper : 1;
};
enum { NumMemberRefExprBits = NumExprBits + 3 };
static_assert(NumMemberRefExprBits <= 32, "fits in an unsigned");
class TupleExprBitfields {
friend class TupleExpr;
unsigned : NumExprBits;
/// Whether this tuple has a trailing closure.
unsigned HasTrailingClosure : 1;
/// Whether this tuple has any labels.
unsigned HasElementNames : 1;
/// Whether this tuple has label locations.
unsigned HasElementNameLocations : 1;
};
enum { NumTupleExprBits = NumExprBits + 3 };
static_assert(NumTupleExprBits <= 32, "fits in an unsigned");
class SubscriptExprBitfields {
friend class SubscriptExpr;
unsigned : NumExprBits;
unsigned Semantics : 2; // an AccessSemantics
unsigned IsSuper : 1;
};
enum { NumSubscriptExprBits = NumExprBits + 3 };
static_assert(NumSubscriptExprBits <= 32, "fits in an unsigned");
class BooleanLiteralExprBitfields {
friend class BooleanLiteralExpr;
unsigned : NumLiteralExprBits;
unsigned Value : 1;
};
enum { NumBooleanLiteralExprBits = NumLiteralExprBits + 1 };
static_assert(NumBooleanLiteralExprBits <= 32, "fits in an unsigned");
class MagicIdentifierLiteralExprBitfields {
friend class MagicIdentifierLiteralExpr;
unsigned : NumLiteralExprBits;
unsigned Kind : 3;
unsigned StringEncoding : 1;
};
enum { NumMagicIdentifierLiteralExprBits = NumLiteralExprBits + 4 };
static_assert(NumMagicIdentifierLiteralExprBits <= 32, "fits in an unsigned");
class AbstractClosureExprBitfields {
friend class AbstractClosureExpr;
unsigned : NumExprBits;
unsigned Discriminator : 16;
enum : unsigned {
InvalidDiscriminator = 0xFFFF
};
};
enum { NumAbstractClosureExprBits = NumExprBits + 16 };
static_assert(NumAbstractClosureExprBits <= 32, "fits in an unsigned");
class ClosureExprBitfields {
friend class ClosureExpr;
unsigned : NumAbstractClosureExprBits;
/// True if closure parameters were synthesized from anonymous closure
/// variables.
unsigned HasAnonymousClosureVars : 1;
};
enum { NumClosureExprBits = NumAbstractClosureExprBits + 1 };
static_assert(NumClosureExprBits <= 32, "fits in an unsigned");
class BindOptionalExprBitfields {
friend class BindOptionalExpr;
unsigned : NumExprBits;
unsigned Depth : 16;
};
enum { NumBindOptionalExprBits = NumExprBits + 16 };
static_assert(NumBindOptionalExprBits <= 32, "fits in an unsigned");
enum { NumCheckedCastKindBits = 4 };
class CheckedCastExprBitfields {
friend class CheckedCastExpr;
unsigned : NumExprBits;
unsigned CastKind : NumCheckedCastKindBits;
};
enum { NumCheckedCastExprBits = NumExprBits + 4 };
static_assert(NumCheckedCastExprBits <= 32, "fits in an unsigned");
static_assert(unsigned(CheckedCastKind::Last_CheckedCastKind)
< (1 << NumCheckedCastKindBits),
"unable to fit a CheckedCastKind in the given number of bits");
class CollectionUpcastConversionExprBitfields {
friend class CollectionUpcastConversionExpr;
unsigned : NumExprBits;
unsigned BridgesToObjC : 1;
};
enum { NumCollectionUpcastConversionExprBits = NumExprBits + 1 };
static_assert(NumCollectionUpcastConversionExprBits <= 32, "fits in an unsigned");
protected:
union {
ExprBitfields ExprBits;
LiteralExprBitfields LiteralExprBits;
IntegerLiteralExprBitfields IntegerLiteralExprBits;
StringLiteralExprBitfields StringLiteralExprBits;
DeclRefExprBitfields DeclRefExprBits;
TupleExprBitfields TupleExprBits;
MemberRefExprBitfields MemberRefExprBits;
SubscriptExprBitfields SubscriptExprBits;
BooleanLiteralExprBitfields BooleanLiteralExprBits;
MagicIdentifierLiteralExprBitfields MagicIdentifierLiteralExprBits;
AbstractClosureExprBitfields AbstractClosureExprBits;
ClosureExprBitfields ClosureExprBits;
BindOptionalExprBitfields BindOptionalExprBits;
CheckedCastExprBitfields CheckedCastExprBits;
CollectionUpcastConversionExprBitfields CollectionUpcastConversionExprBits;
};
private:
/// Ty - This is the type of the expression.
Type Ty;
protected:
Expr(ExprKind Kind, bool Implicit, Type Ty = Type()) : Ty(Ty) {
ExprBits.Kind = unsigned(Kind);
ExprBits.Implicit = Implicit;
}
public:
/// Return the kind of this expression.
ExprKind getKind() const { return ExprKind(ExprBits.Kind); }
/// \brief Retrieve the name of the given expression kind.
///
/// This name should only be used for debugging dumps and other
/// developer aids, and should never be part of a diagnostic or exposed
/// to the user of the compiler in any way.
static StringRef getKindName(ExprKind K);
/// getType - Return the type of this expression.
Type getType() const { return Ty; }
/// setType - Sets the type of this expression.
void setType(Type T) { Ty = T; }
/// \brief Return the source range of the expression.
SourceRange getSourceRange() const;
/// getStartLoc - Return the location of the start of the expression.
SourceLoc getStartLoc() const { return getSourceRange().Start; }
/// \brief Retrieve the location of the end of the expression.
SourceLoc getEndLoc() const { return getSourceRange().End; }
/// getLoc - Return the caret location of this expression.
SourceLoc getLoc() const;
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();
}
/// walk - This recursively walks the AST rooted at this expression.
Expr *walk(ASTWalker &walker);
Expr *walk(ASTWalker &&walker) { return walk(walker); }
/// findExistingInitializerContext - Given that this expression is
/// an initializer that belongs in some sort of Initializer
/// context, look through it for any existing context object.
Initializer *findExistingInitializerContext();
/// Determine whether this expression refers to a statically-derived metatype.
///
/// A statically-derived metatype is a metatype value that comes from
/// referring to a named type directly.
bool isStaticallyDerivedMetatype() const;
/// isImplicit - Determines whether this expression was implicitly-generated,
/// rather than explicitly written in the AST.
bool isImplicit() const {
return ExprBits.Implicit;
}
void setImplicit(bool Implicit = true) {
ExprBits.Implicit = Implicit;
}
/// Determine whether this expression is 'super', possibly converted to
/// a base class.
bool isSuperExpr() 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();
LLVM_ATTRIBUTE_DEPRECATED(
void dump() const LLVM_ATTRIBUTE_USED,
"only for use within the debugger");
void dump(raw_ostream &OS) const;
void print(raw_ostream &OS, unsigned Indent = 0) const;
void print(ASTPrinter &Printer, const PrintOptions &Opts) const;
// Only allow allocation of Exprs using the allocator in ASTContext
// or by doing a placement new.
void *operator new(size_t Bytes, ASTContext &C,
unsigned Alignment = alignof(Expr));
// Make placement new and vanilla new/delete illegal for Exprs.
void *operator new(size_t Bytes) throw() = delete;
void operator delete(void *Data) throw() = delete;
void *operator new(size_t Bytes, void *Mem) {
assert(Mem);
return Mem;
}
};
/// 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;
}
};
/// LiteralExpr - Common base class between the literals.
class LiteralExpr : public Expr {
public:
LiteralExpr(ExprKind Kind, bool Implicit) : Expr(Kind, Implicit) {}
static bool classof(const Expr *E) {
return E->getKind() >= ExprKind::First_LiteralExpr &&
E->getKind() <= ExprKind::Last_LiteralExpr;
}
};
/// \brief The 'nil' literal.
///
class NilLiteralExpr : public LiteralExpr {
SourceLoc Loc;
public:
NilLiteralExpr(SourceLoc Loc, bool Implicit = false)
: LiteralExpr(ExprKind::NilLiteral, Implicit), Loc(Loc) {
}
SourceRange getSourceRange() const {
return Loc;
}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::NilLiteral;
}
};
/// \brief Integer literal with a '+' or '-' sign, like '+4' or '- 2'.
///
/// After semantic analysis assigns types, this is guaranteed to only have
/// a BuiltinIntegerType.
class IntegerLiteralExpr : public LiteralExpr {
/// The value of the literal as an ASTContext-owned string. Underscores must
/// be stripped.
StringRef Val; // Use StringRef instead of APInt, APInt leaks.
SourceLoc MinusLoc;
SourceLoc DigitsLoc;
public:
IntegerLiteralExpr(StringRef Val, SourceLoc DigitsLoc, bool Implicit)
: LiteralExpr(ExprKind::IntegerLiteral, Implicit), Val(Val),
DigitsLoc(DigitsLoc) {
IntegerLiteralExprBits.IsNegative = false;
}
APInt getValue() const;
static APInt getValue(StringRef Text, unsigned BitWidth);
bool isNegative() const { return IntegerLiteralExprBits.IsNegative; }
void setNegative(SourceLoc Loc) {
MinusLoc = Loc;
IntegerLiteralExprBits.IsNegative = true;
}
StringRef getDigitsText() const { return Val; }
SourceRange getSourceRange() const {
if (isNegative())
return { MinusLoc, DigitsLoc };
else
return DigitsLoc;
}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::IntegerLiteral;
}
};
/// FloatLiteralExpr - Floating point literal, like '4.0'. After semantic
/// analysis assigns types, this is guaranteed to only have a
/// BuiltinFloatingPointType.
class FloatLiteralExpr : public LiteralExpr {
/// The value of the literal as an ASTContext-owned string. Underscores must
/// be stripped.
StringRef Val; // Use StringRef instead of APFloat, APFloat leaks.
SourceLoc Loc;
public:
FloatLiteralExpr(StringRef Val, SourceLoc Loc, bool Implicit)
: LiteralExpr(ExprKind::FloatLiteral, Implicit), Val(Val), Loc(Loc) {}
APFloat getValue() const;
static APFloat getValue(StringRef Text, const llvm::fltSemantics &Semantics);
StringRef getText() const { return Val; }
SourceRange getSourceRange() const { return Loc; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::FloatLiteral;
}
};
/// \brief A Boolean literal ('true' or 'false')
///
class BooleanLiteralExpr : public LiteralExpr {
SourceLoc Loc;
public:
BooleanLiteralExpr(bool Value, SourceLoc Loc, bool Implicit = false)
: LiteralExpr(ExprKind::BooleanLiteral, Implicit), Loc(Loc) {
BooleanLiteralExprBits.Value = Value;
}
/// Retrieve the Boolean value of this literal.
bool getValue() const { return BooleanLiteralExprBits.Value; }
SourceRange getSourceRange() const {
return Loc;
}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::BooleanLiteral;
}
};
/// CharacterLiteral - Character literal, like 'x'. After semantic analysis
/// assigns types, this is guaranteed to only have a 32-bit BuiltinIntegerType.
class CharacterLiteralExpr : public LiteralExpr {
uint32_t Val;
SourceLoc Loc;
public:
CharacterLiteralExpr(uint32_t Val, SourceLoc Loc)
: LiteralExpr(ExprKind::CharacterLiteral, /*Implicit=*/false),
Val(Val), Loc(Loc) {}
uint32_t getValue() const { return Val; }
SourceRange getSourceRange() const { return Loc; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::CharacterLiteral;
}
};
/// StringLiteralExpr - String literal, like '"foo"'. After semantic
/// analysis assigns types, this is guaranteed to only have a
/// BuiltinRawPointerType.
class StringLiteralExpr : public LiteralExpr {
StringRef Val;
SourceRange Range;
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);
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>(StringLiteralExprBits.Encoding);
}
/// Set the encoding that should be used for this string literal.
void setEncoding(Encoding encoding) {
StringLiteralExprBits.Encoding = static_cast<unsigned>(encoding);
}
bool isSingleUnicodeScalar() const {
return StringLiteralExprBits.IsSingleUnicodeScalar;
}
bool isSingleExtendedGraphemeCluster() const {
return StringLiteralExprBits.IsSingleExtendedGraphemeCluster;
}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::StringLiteral;
}
};
/// InterpolatedStringLiteral - An interpolated string literal.
///
/// An interpolated string literal mixes expressions (which are evaluated and
/// converted into string form) within a string literal.
///
/// \code
/// "[\(min)..\(max)]"
/// \endcode
class InterpolatedStringLiteralExpr : public LiteralExpr {
SourceLoc Loc;
MutableArrayRef<Expr *> Segments;
Expr *SemanticExpr;
public:
InterpolatedStringLiteralExpr(SourceLoc Loc, MutableArrayRef<Expr *> Segments)
: LiteralExpr(ExprKind::InterpolatedStringLiteral, /*Implicit=*/false),
Loc(Loc), Segments(Segments), SemanticExpr() { }
MutableArrayRef<Expr *> getSegments() { return Segments; }
ArrayRef<Expr *> getSegments() const { return Segments; }
/// \brief Retrieve the expression that actually evaluates the resulting
/// string, typically with a series of '+' operations.
Expr *getSemanticExpr() const { return SemanticExpr; }
void setSemanticExpr(Expr *SE) { SemanticExpr = SE; }
SourceRange getSourceRange() const { return Loc; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::InterpolatedStringLiteral;
}
};
/// MagicIdentifierLiteralExpr - A magic identifier like __FILE__ which expands
/// out to a literal at SILGen time.
class MagicIdentifierLiteralExpr : public LiteralExpr {
public:
enum Kind : unsigned {
File, Line, Column, Function, DSOHandle
};
private:
SourceLoc Loc;
public:
MagicIdentifierLiteralExpr(Kind kind, SourceLoc loc, bool implicit)
: LiteralExpr(ExprKind::MagicIdentifierLiteral, implicit), Loc(loc)
{
MagicIdentifierLiteralExprBits.Kind = static_cast<unsigned>(kind);
MagicIdentifierLiteralExprBits.StringEncoding
= static_cast<unsigned>(StringLiteralExpr::UTF8);
}
Kind getKind() const {
return static_cast<Kind>(MagicIdentifierLiteralExprBits.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");
}
bool isDSOHandle() const {
return getKind() == DSOHandle;
}
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>(
MagicIdentifierLiteralExprBits.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");
MagicIdentifierLiteralExprBits.StringEncoding
= static_cast<unsigned>(encoding);
}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::MagicIdentifierLiteral;
}
};
/// 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 {
/// This is used when the reference is specialized, e.g "GenCls<Int>", to
/// hold information about the generic arguments.
struct SpecializeInfo {
ConcreteDeclRef D;
ArrayRef<TypeRepr*> GenericArgs;
};
/// \brief The declaration pointer or SpecializeInfo pointer if it was
/// explicitly specialized with <...>.
llvm::PointerUnion<ConcreteDeclRef, SpecializeInfo *> DOrSpecialized;
SourceLoc Loc;
SpecializeInfo *getSpecInfo() const {
return DOrSpecialized.dyn_cast<SpecializeInfo*>();
}
public:
DeclRefExpr(ConcreteDeclRef D, SourceLoc Loc, bool Implicit,
AccessSemantics semantics = AccessSemantics::Ordinary,
Type Ty = Type())
: Expr(ExprKind::DeclRef, Implicit, Ty), DOrSpecialized(D), Loc(Loc) {
DeclRefExprBits.Semantics = (unsigned) semantics;
}
/// 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) DeclRefExprBits.Semantics;
}
/// Retrieve the concrete declaration reference.
ConcreteDeclRef getDeclRef() const {
if (auto Spec = getSpecInfo())
return Spec->D;
return DOrSpecialized.get<ConcreteDeclRef>();
}
/// Set the declaration.
void setDeclRef(ConcreteDeclRef ref);
void setSpecialized();
/// \brief Determine whether this declaration reference was immediately
/// specialized by <...>.
bool isSpecialized() const { return getSpecInfo() != nullptr; }
/// Set the generic arguments.
///
/// This copies the array using ASTContext's allocator.
void setGenericArgs(ArrayRef<TypeRepr*> GenericArgs);
/// Returns the generic arguments if it was specialized or an empty array
/// otherwise.
ArrayRef<TypeRepr *> getGenericArgs() const {
if (auto Spec = getSpecInfo())
return Spec->GenericArgs;
return ArrayRef<TypeRepr *>();
}
SourceRange getSourceRange() const { return Loc; }
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);
// 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);
/// Return a TypeExpr for a TypeDecl and the specified location.
static TypeExpr *createForDecl(SourceLoc Loc, TypeDecl *D);
static TypeExpr *createForSpecializedDecl(SourceLoc Loc, TypeDecl *D,
ArrayRef<TypeRepr*> args,
SourceRange angleLocs);
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(); }
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;
SourceLoc Loc;
public:
OtherConstructorDeclRefExpr(ConcreteDeclRef Ctor, SourceLoc Loc,
bool Implicit, Type Ty = {})
: Expr(ExprKind::OtherConstructorDeclRef, Implicit, Ty),
Ctor(Ctor), Loc(Loc)
{}
ConstructorDecl *getDecl() const;
ConcreteDeclRef getDeclRef() const { return Ctor; }
SourceLoc getConstructorLoc() const { return Loc; }
SourceRange getSourceRange() const { return Loc; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::OtherConstructorDeclRef;
}
};
/// An unresolved reference to a constructor member of a value. Resolves to a
/// DotSyntaxCall involving the value and the resolved constructor.
class UnresolvedConstructorExpr : public Expr {
Expr *SubExpr;
SourceLoc DotLoc;
SourceLoc ConstructorLoc;
public:
UnresolvedConstructorExpr(Expr *SubExpr, SourceLoc DotLoc,
SourceLoc ConstructorLoc, bool Implicit)
: Expr(ExprKind::UnresolvedConstructor, Implicit),
SubExpr(SubExpr), DotLoc(DotLoc), ConstructorLoc(ConstructorLoc)
{}
Expr *getSubExpr() const { return SubExpr; }
void setSubExpr(Expr *e) { SubExpr = e; }
SourceLoc getLoc() const { return ConstructorLoc; }
SourceLoc getConstructorLoc() const { return ConstructorLoc; }
SourceLoc getDotLoc() const { return DotLoc; }
SourceRange getSourceRange() const {
return SourceRange(SubExpr->getStartLoc(), ConstructorLoc);
}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::UnresolvedConstructor;
}
};
/// 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, bool Implicit,
Type Ty)
: Expr(Kind, Implicit, Ty), Decls(decls) {}
public:
ArrayRef<ValueDecl*> getDecls() const { return Decls; }
/// 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;
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 : public OverloadSetRefExpr {
SourceLoc Loc;
bool IsSpecialized = false;
bool IsPotentiallyDelayedGlobalOperator = false;
public:
OverloadedDeclRefExpr(ArrayRef<ValueDecl*> Decls, SourceLoc Loc,
bool Implicit, Type Ty = Type())
: OverloadSetRefExpr(ExprKind::OverloadedDeclRef, Decls, Implicit, Ty),
Loc(Loc) { }
SourceLoc getLoc() const { return Loc; }
SourceRange getSourceRange() const { return Loc; }
void setSpecialized(bool specialized) { IsSpecialized = specialized; }
/// \brief Determine whether this declaration reference was immediately
/// specialized by <...>.
bool isSpecialized() const { return IsSpecialized; }
void setIsPotentiallyDelayedGlobalOperator() {
IsPotentiallyDelayedGlobalOperator = true;
}
bool isPotentiallyDelayedGlobalOperator() const {
return IsPotentiallyDelayedGlobalOperator;
}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::OverloadedDeclRef;
}
};
/// OverloadedMemberRefExpr - A reference to an overloaded name that is a
/// member, relative to some base expression, that will eventually be
/// resolved to some kind of member-reference expression.
class OverloadedMemberRefExpr : public OverloadSetRefExpr {
Expr *SubExpr;
SourceLoc DotLoc;
SourceLoc MemberLoc;
public:
OverloadedMemberRefExpr(Expr *SubExpr, SourceLoc DotLoc,
ArrayRef<ValueDecl *> Decls, SourceLoc MemberLoc,
bool Implicit, Type Ty = Type())
: OverloadSetRefExpr(ExprKind::OverloadedMemberRef, Decls, Implicit, Ty),
SubExpr(SubExpr), DotLoc(DotLoc), MemberLoc(MemberLoc) { }
SourceLoc getDotLoc() const { return DotLoc; }
SourceLoc getMemberLoc() const { return MemberLoc; }
Expr *getBase() const { return SubExpr; }
void setBase(Expr *E) { SubExpr = E; }
SourceLoc getLoc() const { return MemberLoc; }
SourceLoc getStartLoc() const {
return DotLoc.isValid()? SubExpr->getStartLoc() : MemberLoc;
}
SourceLoc getEndLoc() const { return MemberLoc; }
SourceRange getSourceRange() const {
return SourceRange(getStartLoc(), MemberLoc);
}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::OverloadedMemberRef;
}
};
/// 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 {
Identifier Name;
SourceLoc Loc;
DeclRefKind RefKind;
bool IsSpecialized = false;
public:
UnresolvedDeclRefExpr(Identifier name, DeclRefKind refKind, SourceLoc loc)
: Expr(ExprKind::UnresolvedDeclRef, /*Implicit=*/loc.isInvalid()),
Name(name), Loc(loc), RefKind(refKind) {
}
bool hasName() const { return !Name.empty(); }
Identifier getName() const { return Name; }
DeclRefKind getRefKind() const { return RefKind; }
void setSpecialized(bool specialized) { IsSpecialized = specialized; }
/// \brief Determine whether this declaration reference was immediately
/// specialized by <...>.
bool isSpecialized() const { return IsSpecialized; }
SourceRange getSourceRange() const { return Loc; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::UnresolvedDeclRef;
}
};
/// MemberRefExpr - This represents 'a.b' where we are referring to a member
/// of a type, such as a property or variable.
///
/// Note that methods found via 'dot' syntax are expressed as DotSyntaxCallExpr
/// nodes, because 'a.f' is actually an application of 'a' (the implicit object
/// argument) to the function 'f'.
class MemberRefExpr : public Expr {
Expr *Base;
ConcreteDeclRef Member;
SourceLoc DotLoc;
SourceRange NameRange;
public:
MemberRefExpr(Expr *base, SourceLoc dotLoc, ConcreteDeclRef member,
SourceRange nameRange, bool Implicit,
AccessSemantics semantics = AccessSemantics::Ordinary);
Expr *getBase() const { return Base; }
ConcreteDeclRef getMember() const { return Member; }
SourceLoc getNameLoc() const { return NameRange.Start; }
SourceLoc getDotLoc() const { return DotLoc; }
void setBase(Expr *E) { Base = E; }
/// Return true if this member access is direct, meaning that it
/// does not call the getter or setter.
AccessSemantics getAccessSemantics() const {
return (AccessSemantics) MemberRefExprBits.Semantics;
}
/// Determine whether this member reference refers to the
/// superclass's property.
bool isSuper() const { return MemberRefExprBits.IsSuper; }
/// Set whether this member reference refers to the superclass's
/// property.
void setIsSuper(bool isSuper) { MemberRefExprBits.IsSuper = isSuper; }
SourceLoc getLoc() const { return NameRange.Start; }
SourceRange getSourceRange() const {
if (Base->isImplicit())
return NameRange;
return SourceRange(Base->getStartLoc(), NameRange.End);
}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::MemberRef;
}
};
/// Common base for expressions that involve dynamic lookup, which
/// determines at runtime whether a particular method, property, or
/// subscript is available.
class DynamicLookupExpr : public Expr {
protected:
explicit DynamicLookupExpr(ExprKind kind) : Expr(kind, /*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 {
Expr *Base;
ConcreteDeclRef Member;
SourceLoc DotLoc;
SourceLoc NameLoc;
public:
DynamicMemberRefExpr(Expr *base, SourceLoc dotLoc,
ConcreteDeclRef member,
SourceLoc nameLoc)
: DynamicLookupExpr(ExprKind::DynamicMemberRef),
Base(base), Member(member), DotLoc(dotLoc), NameLoc(nameLoc) {
}
/// Retrieve the base of the expression.
Expr *getBase() const { return Base; }
/// Replace the base of the expression.
void setBase(Expr *base) { Base = base; }
/// Retrieve the member to which this access refers.
ConcreteDeclRef getMember() const { return Member; }
/// Retrieve the location of the member name.
SourceLoc getNameLoc() const { return NameLoc; }
/// Retrieve the location of the '.'.
SourceLoc getDotLoc() const { return DotLoc; }
SourceLoc getLoc() const { return NameLoc; }
SourceRange getSourceRange() const {
if (Base->isImplicit())
return SourceRange(NameLoc);
return SourceRange(Base->getStartLoc(), NameLoc);
}
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 : public DynamicLookupExpr {
Expr *Base;
Expr *Index;
ConcreteDeclRef Member;
public:
DynamicSubscriptExpr(Expr *base, Expr *index,
ConcreteDeclRef member)
: DynamicLookupExpr(ExprKind::DynamicSubscript),
Base(base), Index(index), Member(member) { }
/// Retrieve the base of the expression.
Expr *getBase() const { return Base; }
/// Replace the base of the expression.
void setBase(Expr *base) { Base = base; }
/// getIndex - Retrieve the index of the subscript expression, i.e., the
/// "offset" into the base value.
Expr *getIndex() const { return Index; }
void setIndex(Expr *E) { Index = E; }
/// Retrieve the member to which this access refers.
ConcreteDeclRef getMember() const { return Member; }
SourceLoc getLoc() const { return Index->getStartLoc(); }
SourceRange getSourceRange() const {
return SourceRange(Base->getStartLoc(), 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 : public Expr {
SourceLoc DotLoc;
SourceLoc NameLoc;
Identifier Name;
Expr *Argument;
public:
UnresolvedMemberExpr(SourceLoc dotLoc, SourceLoc nameLoc,
Identifier name, Expr *argument)
: Expr(ExprKind::UnresolvedMember, /*Implicit=*/false),
DotLoc(dotLoc), NameLoc(nameLoc), Name(name), Argument(argument) {
}
Identifier getName() const { return Name; }
SourceLoc getNameLoc() const { return NameLoc; }
SourceLoc getDotLoc() const { return DotLoc; }
Expr *getArgument() const { return Argument; }
void setArgument(Expr *argument) { Argument = argument; }
SourceLoc getLoc() const { return NameLoc; }
SourceRange getSourceRange() const;
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::UnresolvedMember;
}
};
/// An expression node that does not affect the evaluation of its subexpression.
class IdentityExpr : public Expr {
Expr *SubExpr;
// FIXME: Hack for CollectionExpr::getElements()
friend class CollectionExpr;
public:
IdentityExpr(ExprKind kind,
Expr *subExpr, Type ty = Type())
: Expr(kind, /*implicit*/ false, 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; }
SourceRange getSourceRange() const {
return {getSubExpr()->getStartLoc(), 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;
/// \brief Whether we're wrapping a trailing closure expression.
/// FIXME: Pack bit into superclass.
bool HasTrailingClosure;
public:
ParenExpr(SourceLoc lploc, Expr *subExpr, SourceLoc rploc,
bool hasTrailingClosure,
Type ty = Type())
: IdentityExpr(ExprKind::Paren, subExpr, ty),
LParenLoc(lploc), RParenLoc(rploc),
HasTrailingClosure(hasTrailingClosure) {
assert(lploc.isValid() == rploc.isValid() &&
"Mismatched source location information");
}
SourceLoc getLParenLoc() const { return LParenLoc; }
SourceLoc getRParenLoc() const { return RParenLoc; }
SourceRange getSourceRange() const {
// When the locations of the parentheses are invalid, ask our subexpression
// for its source range instead.
if (LParenLoc.isInvalid())
return getSubExpr()->getSourceRange();
// If we have a trailing closure, our end point is the end of the trailing
// closure.
if (HasTrailingClosure)
return SourceRange(LParenLoc, getSubExpr()->getEndLoc());
return SourceRange(LParenLoc, RParenLoc);
}
/// \brief Whether this expression has a trailing closure as its argument.
bool hasTrailingClosure() const { return 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 : public Expr {
SourceLoc LParenLoc;
SourceLoc RParenLoc;
unsigned NumElements;
/// Retrieve the buffer containing the element names.
MutableArrayRef<Identifier> getElementNamesBuffer() {
if (!hasElementNames())
return { };
return { reinterpret_cast<Identifier *>(
getElements().data() + getNumElements()),
getNumElements() };
}
/// Retrieve the buffer containing the element name locations.
MutableArrayRef<SourceLoc> getElementNameLocsBuffer() {
if (!hasElementNameLocs())
return { };
return { reinterpret_cast<SourceLoc *>(
getElementNamesBuffer().data() + getNumElements()),
getNumElements() };
}
TupleExpr(SourceLoc LParenLoc, ArrayRef<Expr *> SubExprs,
ArrayRef<Identifier> ElementNames,
ArrayRef<SourceLoc> ElementNameLocs,
SourceLoc RParenLoc, bool HasTrailingClosure, bool Implicit,
Type Ty);
public:
/// Create a tuple.
static TupleExpr *create(ASTContext &ctx,
SourceLoc LParenLoc,
ArrayRef<Expr *> SubExprs,
ArrayRef<Identifier> ElementNames,
ArrayRef<SourceLoc> ElementNameLocs,
SourceLoc RParenLoc, bool HasTrailingClosure,
bool Implicit, Type Ty = Type());
/// Create an empty tuple.
static TupleExpr *createEmpty(ASTContext &ctx, SourceLoc LParenLoc,
SourceLoc RParenLoc, bool Implicit);
/// Create an implicit tuple with no source information.
static TupleExpr *createImplicit(ASTContext &ctx, ArrayRef<Expr *> SubExprs,
ArrayRef<Identifier> ElementNames);
SourceLoc getLParenLoc() const { return LParenLoc; }
SourceLoc getRParenLoc() const { return RParenLoc; }
SourceRange getSourceRange() const;
/// \brief Whether this expression has a trailing closure as its argument.
bool hasTrailingClosure() const { return TupleExprBits.HasTrailingClosure; }
/// Retrieve the elements of this tuple.
MutableArrayRef<Expr*> getElements() {
return { reinterpret_cast<Expr **>(this + 1), getNumElements() };
}
/// Retrieve the elements of this tuple.
ArrayRef<Expr*> getElements() const {
return { reinterpret_cast<Expr *const *>(this + 1), getNumElements() };
}
unsigned getNumElements() const { return 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 TupleExprBits.HasElementNames;
}
/// Retrieve the element names for a tuple.
ArrayRef<Identifier> getElementNames() const {
if (!hasElementNames())
return { };
return { reinterpret_cast<const Identifier *>(
getElements().data() + getNumElements()),
getNumElements() };
}
/// 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 TupleExprBits.HasElementNameLocations;
}
/// Retrieve the locations of the element names for a tuple.
ArrayRef<SourceLoc> getElementNameLocs() const {
if (!hasElementNameLocs())
return { };
return { reinterpret_cast<const SourceLoc *>(
getElementNames().data() + getNumElements()),
getNumElements() };
}
/// Retrieve the location of the ith label, if known.
SourceLoc getElementNameLoc(unsigned i) const {
if (hasElementNameLocs())
return getElementNameLocs()[i];
return SourceLoc();
}
static bool classof(const Expr *E) { return E->getKind() == ExprKind::Tuple; }
};
/// \brief A collection literal expression.
///
/// The subexpression is represented as a TupleExpr or ParenExpr and
/// passed on to the appropriate semantics-providing conversion
/// operation.
class CollectionExpr : public Expr {
SourceLoc LBracketLoc;
SourceLoc RBracketLoc;
Expr *SubExpr;
Expr *SemanticExpr;
protected:
CollectionExpr(ExprKind Kind, SourceLoc LBracketLoc, Expr *SubExpr,
SourceLoc RBracketLoc, Type Ty)
: Expr(Kind, /*Implicit=*/false, Ty),
LBracketLoc(LBracketLoc), RBracketLoc(RBracketLoc),
SubExpr(SubExpr), SemanticExpr(nullptr) { }
public:
/// Get the ParenExpr or TupleExpr representing the literal contents
/// of the container.
Expr *getSubExpr() const { return SubExpr; }
void setSubExpr(Expr *e) { SubExpr = e; }
/// Retrieve the elements stored in the collection.
ArrayRef<Expr *> getElements() const;
SourceLoc getLBracketLoc() const { return LBracketLoc; }
SourceLoc getRBracketLoc() const { return RBracketLoc; }
SourceRange getSourceRange() const {
return SourceRange(LBracketLoc, RBracketLoc);
}
Expr *getSemanticExpr() const { return SemanticExpr; }
void setSemanticExpr(Expr *e) { SemanticExpr = e; }
static bool classof(const Expr *e) {
return e->getKind() >= ExprKind::First_CollectionExpr &&
e->getKind() <= ExprKind::Last_CollectionExpr;
}
};
/// \brief An array literal expression [a, b, c].
class ArrayExpr : public CollectionExpr {
public:
ArrayExpr(SourceLoc LBracketLoc, Expr *SubExpr, SourceLoc RBracketLoc,
Type Ty = Type())
: CollectionExpr(ExprKind::Array, LBracketLoc, SubExpr, RBracketLoc, Ty) { }
static bool classof(const Expr *e) {
return e->getKind() == ExprKind::Array;
}
};
/// \brief A dictionary literal expression [a : x, b : y, c : z].
class DictionaryExpr : public CollectionExpr {
public:
DictionaryExpr(SourceLoc LBracketLoc, Expr *SubExpr, SourceLoc RBracketLoc,
Type Ty = Type())
: CollectionExpr(ExprKind::Dictionary, LBracketLoc, SubExpr, RBracketLoc,
Ty) { }
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 : public Expr {
ConcreteDeclRef TheDecl;
Expr *Base;
Expr *Index;
public:
SubscriptExpr(Expr *base, Expr *index,
ConcreteDeclRef decl = ConcreteDeclRef(),
bool implicit = false,
AccessSemantics semantics = AccessSemantics::Ordinary)
: Expr(ExprKind::Subscript, implicit, Type()),
TheDecl(decl), Base(base), Index(index) {
SubscriptExprBits.Semantics = (unsigned) semantics;
SubscriptExprBits.IsSuper = false;
}
/// getBase - Retrieve the base of the subscript expression, i.e., the
/// value being indexed.
Expr *getBase() const { return Base; }
void setBase(Expr *E) { Base = E; }
/// getIndex - Retrieve the index of the subscript expression, i.e., the
/// "offset" into the base value.
Expr *getIndex() const { return Index; }
void setIndex(Expr *E) { Index = E; }
/// Determine whether this subscript reference should bypass the
/// ordinary accessors.
AccessSemantics getAccessSemantics() const {
return (AccessSemantics) SubscriptExprBits.Semantics;
}
/// Determine whether this member reference refers to the
/// superclass's property.
bool isSuper() const { return SubscriptExprBits.IsSuper; }
/// Set whether this member reference refers to the superclass's
/// property.
void setIsSuper(bool isSuper) { SubscriptExprBits.IsSuper = isSuper; }
/// Determine whether subscript operation has a known underlying
/// subscript declaration or not.
bool hasDecl() const { return static_cast<bool>(TheDecl); }
/// Retrieve the subscript declaration that this subscripting
/// operation refers to. Only valid when \c hasDecl() is true.
ConcreteDeclRef getDecl() const {
assert(hasDecl() && "No subscript declaration known!");
return TheDecl;
}
SourceRange getSourceRange() const {
return SourceRange(Base->getStartLoc(), Index->getEndLoc());
}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::Subscript;
}
};
/// A member access (foo.bar) on an expression with unresolved type.
class UnresolvedDotExpr : public Expr {
Expr *SubExpr;
SourceLoc DotLoc;
SourceLoc NameLoc;
Identifier Name;
public:
UnresolvedDotExpr(Expr *subexpr, SourceLoc dotloc, Identifier name,
SourceLoc nameloc, bool Implicit)
: Expr(ExprKind::UnresolvedDot, Implicit), SubExpr(subexpr), DotLoc(dotloc),
NameLoc(nameloc), Name(name) {}
SourceLoc getLoc() const { return NameLoc; }
SourceRange getSourceRange() const {
if (DotLoc.isInvalid())
return SourceRange(NameLoc, NameLoc);
return SourceRange(SubExpr->getStartLoc(), NameLoc);
}
SourceLoc getDotLoc() const { return DotLoc; }
Expr *getBase() const { return SubExpr; }
void setBase(Expr *e) { SubExpr = e; }
Identifier getName() const { return Name; }
SourceLoc getNameLoc() const { return NameLoc; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::UnresolvedDot;
}
};
/// A selector-style member access (foo.bar:bas:) on an expression with
/// unresolved type.
class UnresolvedSelectorExpr : public Expr {
public:
// A selector component.
struct ComponentLoc {
SourceLoc NameLoc;
SourceLoc ColonLoc;
};
private:
Expr *SubExpr;
SourceLoc DotLoc;
DeclName Name;
MutableArrayRef<ComponentLoc> getComponentsBuf() {
return {reinterpret_cast<ComponentLoc*>(this+1),
Name.getArgumentNames().size() + 1};
}
UnresolvedSelectorExpr(Expr *subExpr, SourceLoc dotLoc,
DeclName name,
ArrayRef<ComponentLoc> components);
public:
static UnresolvedSelectorExpr *create(ASTContext &C,
Expr *subExpr,
SourceLoc dotLoc,
DeclName name,
ArrayRef<ComponentLoc> components);
ArrayRef<ComponentLoc> getComponentLocs() const {
return {reinterpret_cast<const ComponentLoc*>(this+1),
Name.getArgumentNames().size() + 1};
}
SourceLoc getLoc() const {
return getComponentLocs().front().NameLoc;
}
SourceRange getSourceRange() const {
return {SubExpr->getStartLoc(), getComponentLocs().back().ColonLoc};
}
SourceLoc getDotLoc() const { return DotLoc; }
Expr *getBase() const { return SubExpr; }
void setBase(Expr *e) { SubExpr = e; }
SourceRange getNameRange() const {
return {getComponentLocs().front().NameLoc,
getComponentLocs().back().ColonLoc};
}
DeclName getName() const { return Name; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::UnresolvedSelector;
}
};
/// ModuleExpr - Reference a module by name. The module being referenced is
/// captured in the type of the expression, which is always a ModuleType.
class ModuleExpr : public Expr {
SourceLoc Loc;
public:
ModuleExpr(SourceLoc Loc, Type Ty)
: Expr(ExprKind::Module, /*Implicit=*/false, Ty), Loc(Loc) {}
SourceRange getSourceRange() const { return SourceRange(Loc, Loc); }
SourceLoc getLoc() const { return Loc; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::Module;
}
};
/// TupleElementExpr - Refer to an element of a tuple,
/// e.g. "(1,field:2).field".
class TupleElementExpr : public Expr {
Expr *SubExpr;
SourceLoc NameLoc;
unsigned FieldNo;
SourceLoc DotLoc;
public:
TupleElementExpr(Expr *SubExpr, SourceLoc DotLoc, unsigned FieldNo,
SourceLoc NameLoc, Type Ty)
: Expr(ExprKind::TupleElement, /*Implicit=*/false, Ty), SubExpr(SubExpr),
NameLoc(NameLoc), FieldNo(FieldNo), DotLoc(DotLoc) {}
SourceLoc getLoc() const { return NameLoc; }
Expr *getBase() const { return SubExpr; }
void setBase(Expr *e) { SubExpr = e; }
unsigned getFieldNumber() const { return FieldNo; }
SourceLoc getNameLoc() const { return NameLoc; }
SourceLoc getDotLoc() const { return DotLoc; }
SourceRange getSourceRange() const {
return SourceRange(getBase()->getStartLoc(), getNameLoc());
}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::TupleElement;
}
};
/// \brief Describes a monadic bind from T? to T.
///
/// In a ?-chain expression, this is the part that's spelled with a
/// postfix ?.
///
/// A BindOptionalExpr must always appear within a
/// OptionalEvaluationExpr. If the operand of the BindOptionalExpr
/// evaluates to a missing value, the OptionalEvaluationExpr
/// immediately completes and produces a missing value in the result
/// type.
///
/// The depth of the BindOptionalExpr indicates which
/// OptionalEvaluationExpr is completed, in case the BindOptionalExpr
/// is contained within more than one such expression.
class BindOptionalExpr : public Expr {
Expr *SubExpr;
SourceLoc QuestionLoc;
public:
BindOptionalExpr(Expr *subExpr, SourceLoc questionLoc,
unsigned depth, Type ty = Type())
: Expr(ExprKind::BindOptional, /*Implicit=*/ questionLoc.isInvalid(), ty),
SubExpr(subExpr), QuestionLoc(questionLoc) {
BindOptionalExprBits.Depth = depth;
assert(BindOptionalExprBits.Depth == depth && "bitfield truncation");
}
SourceRange getSourceRange() const {
if (QuestionLoc.isInvalid())
return SubExpr->getSourceRange();
return SourceRange(SubExpr->getStartLoc(), QuestionLoc);
}
SourceLoc getLoc() const {
if (isImplicit())
return SubExpr->getLoc();
return getQuestionLoc();
}
SourceLoc getQuestionLoc() const { return QuestionLoc; }
unsigned getDepth() const { return BindOptionalExprBits.Depth; }
Expr *getSubExpr() const { return SubExpr; }
void setSubExpr(Expr *expr) { SubExpr = expr; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::BindOptional;
}
};
/// \brief Describes the outer limits of an operation containing
/// monadic binds of T? to T.
///
/// In a ?-chain expression, this is implicitly formed at the outer
/// limits of the chain. For example, in (foo?.bar?().baz).fred,
/// this is nested immediately within the parens.
///
/// This expression will always have optional type.
class OptionalEvaluationExpr : public Expr {
Expr *SubExpr;
public:
OptionalEvaluationExpr(Expr *subExpr, Type ty = Type())
: Expr(ExprKind::OptionalEvaluation, /*Implicit=*/ true, ty),
SubExpr(subExpr) {}
SourceRange getSourceRange() const { return SubExpr->getSourceRange(); }
SourceLoc getLoc() const { return SubExpr->getLoc(); }
Expr *getSubExpr() const { return SubExpr; }
void setSubExpr(Expr *expr) { SubExpr = expr; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::OptionalEvaluation;
}
};
/// \brief An expression that forces an optional to its underlying value.
///
/// \code
/// func parseInt(s : String) -> Int? { ... }
///
/// var maybeInt = parseInt("5") // returns an Int?
/// var forcedInt = parseInt("5")! // returns an Int; fails on empty optional
/// \endcode
///
class ForceValueExpr : public Expr {
Expr *SubExpr;
SourceLoc ExclaimLoc;
public:
ForceValueExpr(Expr *subExpr, SourceLoc exclaimLoc)
: Expr(ExprKind::ForceValue, /*Implicit=*/exclaimLoc.isInvalid(), Type()),
SubExpr(subExpr), ExclaimLoc(exclaimLoc) {}
SourceRange getSourceRange() const {
if (ExclaimLoc.isInvalid())
return SubExpr->getSourceRange();
return SourceRange(SubExpr->getStartLoc(), ExclaimLoc);
}
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; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::ForceValue;
}
};
/// \brief An expression that opens up a value of protocol or protocol
/// composition type and gives a name to its dynamic type.
///
/// This expression is implicitly created by the type checker in
/// narrow circumstances where we need a way to refer to the dynamic
/// type, i.e., when calling a method on a protocol that returns
/// Self. 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)
: Expr(ExprKind::OpenExistential, /*Implicit=*/ true, subExpr->getType()),
ExistentialValue(existentialValue), OpaqueValue(opaqueValue),
SubExpr(subExpr) { }
SourceRange getSourceRange() const {
return SubExpr->getSourceRange();
}
SourceLoc getLoc() const { return SubExpr->getLoc(); }
/// 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; }
/// Retrieve the opaque value representing the value (of archetype
/// type) stored in the existential.
OpaqueValueExpr *getOpaqueValue() const { return OpaqueValue; }
/// Retrieve the opened archetype, which can only be referenced
/// within this expression's subexpression.
ArchetypeType *getOpenedArchetype() const;
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::OpenExistential;
}
};
/// ImplicitConversionExpr - An abstract class for expressions which
/// implicitly convert the value of an expression in some way.
class ImplicitConversionExpr : public Expr {
Expr *SubExpr;
protected:
ImplicitConversionExpr(ExprKind kind, Expr *subExpr, Type ty)
: Expr(kind, /*Implicit=*/true, ty), SubExpr(subExpr) {}
public:
SourceRange getSourceRange() const { return SubExpr->getSourceRange(); }
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_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;
}
};
/// Conversion from a potentially unavailable declaration reference to an
/// optional.
class UnavailableToOptionalExpr : public ImplicitConversionExpr {
/// The reason the referenced declaration is potentially unavailable.
UnavailabilityReason Reason;
public:
UnavailableToOptionalExpr(Expr *subExpr, UnavailabilityReason Reason,
Type ty)
: ImplicitConversionExpr(ExprKind::UnavailableToOptional, subExpr, ty),
Reason(Reason) {}
/// Returns the reason the reference is potentially unavailable.
const UnavailabilityReason &getReason() const { return Reason; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::UnavailableToOptional;
}
};
/// Convert the address of an lvalue to a raw pointer.
class LValueToPointerExpr : public ImplicitConversionExpr {
Type AbstractionPattern;
public:
LValueToPointerExpr(Expr *subExpr, Type ty, Type abstractionTy)
: ImplicitConversionExpr(ExprKind::LValueToPointer, subExpr, ty),
AbstractionPattern(abstractionTy) {}
/// Get the declared type of the type for which we are performing this
/// conversion. This defines the abstraction level at which the lvalue should
/// be emitted before taking its address.
Type getAbstractionPatternType() const {
return AbstractionPattern;
}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::LValueToPointer;
}
};
/// 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) {}
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) {}
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;
}
};
/// TupleShuffleExpr - This represents a permutation of a tuple value to a new
/// tuple type. The expression's type is known to be a tuple type and the
/// subexpression is known to have a tuple type as well.
class TupleShuffleExpr : public ImplicitConversionExpr {
public:
enum : int {
/// The element mapping value indicating that a field of the destination
/// tuple should be default-initialized.
DefaultInitialize = -1,
/// The element mapping value signaling the first variadic field.
FirstVariadic = -2,
/// The element mapping value indicating that the field of the
/// destination tuple should be default-initialized with an expression
/// provided by the caller.
/// FIXME: Yet another indication that TupleShuffleExpr uses the wrong
/// formulation.
CallerDefaultInitialize = -3
};
private:
/// 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.
ArrayRef<int> ElementMapping;
/// 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;
MutableArrayRef<Expr *> CallerDefaultArgs;
public:
TupleShuffleExpr(Expr *subExpr, ArrayRef<int> elementMapping,
ConcreteDeclRef defaultArgsOwner,
MutableArrayRef<Expr *> CallerDefaultArgs, Type ty)
: ImplicitConversionExpr(ExprKind::TupleShuffle, subExpr, ty),
ElementMapping(elementMapping), VarargsArrayTy(),
DefaultArgsOwner(defaultArgsOwner), CallerDefaultArgs(CallerDefaultArgs)
{
}
ArrayRef<int> getElementMapping() const { return ElementMapping; }
/// Set the varargs array type to use.
void setVarargsArrayType(Type T) { VarargsArrayTy = T; }
Type getVarargsArrayType() const {
assert(!VarargsArrayTy.isNull());
return VarargsArrayTy;
}
Type getVarargsArrayTypeOrNull() const {
return VarargsArrayTy;
}
/// Retrieve the owner of the default arguments.
ConcreteDeclRef getDefaultArgsOwner() const { return DefaultArgsOwner; }
/// Retrieve the caller-defaulted arguments.
ArrayRef<Expr *> getCallerDefaultArgs() const { return CallerDefaultArgs; }
/// Retrieve the caller-defaulted arguments.
MutableArrayRef<Expr *> getCallerDefaultArgs() { return CallerDefaultArgs; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::TupleShuffle;
}
};
/// LoadExpr - Turn an l-value into an r-value by performing a "load"
/// operation. This operation may actually be a logical operation,
/// i.e. one implemented using a call to a potentially user-defined
/// function instead of a simple memory transaction.
class LoadExpr : public ImplicitConversionExpr {
public:
LoadExpr(Expr *subExpr, Type type)
: ImplicitConversionExpr(ExprKind::Load, subExpr, type) {}
static bool classof(const Expr *E) { return E->getKind() == ExprKind::Load; }
};
/// 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;
}
};
/// 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:
CollectionUpcastConversionExpr(Expr *subExpr, Type type,
bool bridgesToObjC)
: ImplicitConversionExpr(
ExprKind::CollectionUpcastConversion, subExpr, type) {
CollectionUpcastConversionExprBits.BridgesToObjC = bridgesToObjC;
}
/// Whether this upcast bridges the source elements to Objective-C.
bool bridgesToObjC() const {
return CollectionUpcastConversionExprBits.BridgesToObjC;
}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::CollectionUpcastConversion;
}
};
/// AnyErasureExpr - An abstract class for implicit conversions that
/// erase a type into an existential in some way.
///
/// 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 AnyErasureExpr : public ImplicitConversionExpr {
ArrayRef<ProtocolConformance *> Conformances;
protected:
AnyErasureExpr(ExprKind kind, Expr *subExpr, Type type,
ArrayRef<ProtocolConformance *> conformances)
: ImplicitConversionExpr(kind, subExpr, type),
Conformances(conformances) {}
public:
/// \brief Retrieve the mapping specifying how the type of the subexpression
/// maps to the resulting existential type. If the resulting existential
/// type involves several different protocols, there will be mappings for each
/// of those protocols, in the order in which the existential type expands
/// its properties.
///
/// The entries in this array may be null, indicating that the conformance
/// to the corresponding protocol is trivial (because the source
/// type is either an archetype or an existential type that conforms to
/// that corresponding protocol).
ArrayRef<ProtocolConformance *> getConformances() const {
return Conformances;
}
static bool classof(const Expr *E) {
return E->getKind() >= ExprKind::First_AnyErasureExpr
&& E->getKind() <= ExprKind::Last_AnyErasureExpr;
}
};
/// ErasureExpr - Perform type erasure by converting a value to existential
/// type. For example:
///
/// \code
/// protocol Printable {
/// func print()
/// }
///
/// struct Book {
/// func print() { ... }
/// }
///
/// var printable : Printable = Book() // erases type
/// \endcode
///
/// The result type is always a existential value (i.e. not an
/// existential metatype).
class ErasureExpr : public AnyErasureExpr {
public:
ErasureExpr(Expr *subExpr, Type ty,
ArrayRef<ProtocolConformance *> conformances)
: AnyErasureExpr(ExprKind::Erasure, subExpr, ty, conformances) {}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::Erasure;
}
};
/// MetatypeErasureExpr - Perform type erasure by converting a
/// metatype to an existential metatype type. For example:
///
/// \code
/// protocol Singleton {
/// static func getSingleton() -> Self
/// }
///
/// class Book : Singleton {
/// class func getSingleton() -> Self { ... }
/// }
///
/// var singletonType : Singleton.Type = Book.self // erases type
/// \endcode
///
/// The type is always an existential metatype; the operand may be a
/// concrete or existential metatype.
class MetatypeErasureExpr : public AnyErasureExpr {
public:
MetatypeErasureExpr(Expr *subExpr, Type ty,
ArrayRef<ProtocolConformance *> conformances)
: AnyErasureExpr(ExprKind::MetatypeErasure, subExpr, ty, conformances) {}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::MetatypeErasure;
}
};
/// UnresolvedSpecializeExpr - Represents an explicit specialization using
/// a type parameter list (e.g. "Vector<Int>") that has not been resolved.
class UnresolvedSpecializeExpr : public Expr {
Expr *SubExpr;
SourceLoc LAngleLoc;
SourceLoc RAngleLoc;
MutableArrayRef<TypeLoc> UnresolvedParams;
public:
UnresolvedSpecializeExpr(Expr *SubExpr,
SourceLoc LAngleLoc,
MutableArrayRef<TypeLoc> UnresolvedParams,
SourceLoc RAngleLoc)
: Expr(ExprKind::UnresolvedSpecialize, /*Implicit=*/false),
SubExpr(SubExpr),
LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc),
UnresolvedParams(UnresolvedParams) { }
Expr *getSubExpr() const { return SubExpr; }
void setSubExpr(Expr *e) { SubExpr = e; }
/// \brief Retrieve the list of type parameters. These parameters have not yet
/// been bound to archetypes of the entity to be specialized.
ArrayRef<TypeLoc> getUnresolvedParams() const { return UnresolvedParams; }
MutableArrayRef<TypeLoc> getUnresolvedParams() { return UnresolvedParams; }
SourceLoc getLoc() const { return LAngleLoc; }
SourceLoc getLAngleLoc() const { return LAngleLoc; }
SourceLoc getRAngleLoc() const { return RAngleLoc; }
SourceRange getSourceRange() const {
return SourceRange(SubExpr->getStartLoc(), RAngleLoc);
}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::UnresolvedSpecialize;
}
};
/// \brief Describes an implicit conversion from a subclass to one of its
/// superclasses.
class DerivedToBaseExpr : public ImplicitConversionExpr {
public:
DerivedToBaseExpr(Expr *subExpr, Type type)
: ImplicitConversionExpr(ExprKind::DerivedToBase, subExpr, type) {}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::DerivedToBase;
}
};
/// \brief Describes an implicit conversion from a value of archetype type to
/// its concrete superclass.
class ArchetypeToSuperExpr : public ImplicitConversionExpr {
public:
ArchetypeToSuperExpr(Expr *subExpr, Type type)
: ImplicitConversionExpr(ExprKind::ArchetypeToSuper, subExpr, type) {}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::ArchetypeToSuper;
}
};
/// ScalarToTupleExpr - Convert a scalar to tuple type.
class ScalarToTupleExpr : public ImplicitConversionExpr {
public:
/// Describes an element of the destination tuple, which can be the
/// caller-side default argument expression, the declaration from which the
/// callee-side default argument should be produced, or null to indicate the
/// 'hole' where the scalar expression should be placed.
typedef llvm::PointerUnion<Expr *, ConcreteDeclRef> Element;
private:
/// If we're doing a varargs shuffle, this is the array type to build.
Type VarargsArrayTy;
/// The elements of the destination tuple.
MutableArrayRef<Element> Elements;
public:
ScalarToTupleExpr(Expr *subExpr, Type type,
MutableArrayRef<Element> elements,
Type VarargsArrayTy = nullptr)
: ImplicitConversionExpr(ExprKind::ScalarToTuple, subExpr, type),
VarargsArrayTy(VarargsArrayTy), Elements(elements) {}
/// Retrieve the index of the scalar field within the destination tuple.
unsigned getScalarField() const;
/// Retrieve the array type for the variadic part of the tuple.
Type getVarargsArrayType() { return VarargsArrayTy; }
/// Retrieve the elements of the destination tuple.
MutableArrayRef<Element> getElements() { return Elements; }
ArrayRef<Element> getElements() const { return Elements; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::ScalarToTuple;
}
};
/// 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 type,
bool isImplicit = false)
: Expr(ExprKind::InOut, isImplicit, type),
SubExpr(subExpr), OperLoc(operLoc) {}
SourceRange getSourceRange() const {
return SourceRange(OperLoc, SubExpr->getEndLoc());
}
SourceLoc getLoc() const { return OperLoc; }
Expr *getSubExpr() const { return SubExpr; }
void setSubExpr(Expr *e) { SubExpr = e; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::InOut;
}
};
/// SequenceExpr - A list of binary operations which has not yet been
/// folded into a tree. The operands all have even indices, while the
/// subexpressions with odd indices are all (potentially overloaded)
/// references to binary operators.
class SequenceExpr : public Expr {
unsigned NumElements;
Expr **getSubExprs() { return reinterpret_cast<Expr **>(this + 1); }
Expr * const *getSubExprs() const {
return const_cast<SequenceExpr*>(this)->getSubExprs();
}
SequenceExpr(ArrayRef<Expr*> elements)
: Expr(ExprKind::Sequence, /*Implicit=*/false),
NumElements(elements.size()) {
assert(NumElements > 0 && "zero-length sequence!");
memcpy(getSubExprs(), elements.data(), elements.size() * sizeof(Expr*));
}
public:
static SequenceExpr *create(ASTContext &ctx, ArrayRef<Expr*> elements);
SourceRange getSourceRange() const {
return SourceRange(getElements()[0]->getStartLoc(),
getElements()[getNumElements() - 1]->getEndLoc());
}
unsigned getNumElements() const { return NumElements; }
MutableArrayRef<Expr*> getElements() {
return MutableArrayRef<Expr*>(getSubExprs(), NumElements);
}
ArrayRef<Expr*> getElements() const {
return ArrayRef<Expr*>(getSubExprs(), NumElements);
}
Expr *getElement(unsigned i) const {
assert(i < NumElements);
return getSubExprs()[i];
}
void setElement(unsigned i, Expr *e) {
assert(i < NumElements);
getSubExprs()[i] = e;
}
// Implement isa/cast/dyncast/etc.
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::Sequence;
}
};
/// \brief A base class for closure expressions.
class AbstractClosureExpr : public Expr, public DeclContext {
CaptureInfo Captures;
/// \brief The set of parameters.
Pattern *ParamPattern;
public:
AbstractClosureExpr(ExprKind Kind, Type FnType, bool Implicit,
unsigned Discriminator, DeclContext *Parent)
: Expr(Kind, Implicit, FnType),
DeclContext(DeclContextKind::AbstractClosureExpr, Parent),
ParamPattern(nullptr) {
AbstractClosureExprBits.Discriminator = Discriminator;
}
CaptureInfo &getCaptureInfo() { return Captures; }
const CaptureInfo &getCaptureInfo() const { return Captures; }
/// \brief Retrieve the parameters of this closure.
Pattern *getParams() { return ParamPattern; }
const Pattern *getParams() const { return ParamPattern; }
void setParams(Pattern *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 AbstractClosureExprBits.Discriminator;
}
void setDiscriminator(unsigned discriminator) {
assert(getDiscriminator() == InvalidDiscriminator);
assert(discriminator != InvalidDiscriminator);
AbstractClosureExprBits.Discriminator = discriminator;
}
enum : unsigned {
InvalidDiscriminator =
decltype(AbstractClosureExprBits)::InvalidDiscriminator
};
ArrayRef<Pattern *> getParamPatterns() { return ParamPattern; }
ArrayRef<const Pattern *> getParamPatterns() const { return ParamPattern; }
/// \brief Retrieve the result type of this closure.
Type getResultType() 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;
};
/// 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) {
}
};
/// \brief An explicit unnamed function expression, which can optionally have
/// named arguments.
///
/// \code
/// { $0 + $1 }
/// { a, b -> Int in a + b }
/// { (a : Int, b : Int) -> Int in a + b }
/// { [weak c] (a : Int) -> Int in a + c!.getFoo() }
/// \endcode
class ClosureExpr : public AbstractClosureExpr {
ArrayRef<CaptureListEntry> CaptureList;
/// \brief The location of the '->' denoting an explicit return type,
/// if present.
SourceLoc ArrowLoc;
/// The location of the "in", if present.
SourceLoc InLoc;
/// \brief The explicitly-specified result type.
TypeLoc ExplicitResultType;
/// \brief The body of the closure, along with a bit indicating whether it
/// was originally just a single expression.
llvm::PointerIntPair<BraceStmt *, 1, bool> Body;
public:
ClosureExpr(ArrayRef<CaptureListEntry> captureList,
Pattern *params, SourceLoc arrowLoc, SourceLoc inLoc,
TypeLoc explicitResultType, unsigned discriminator,
DeclContext *parent)
: AbstractClosureExpr(ExprKind::Closure, Type(), /*Implicit=*/false,
discriminator, parent),
CaptureList(captureList), ArrowLoc(arrowLoc), InLoc(inLoc),
ExplicitResultType(explicitResultType),
Body(nullptr) {
setParams(params);
ClosureExprBits.HasAnonymousClosureVars = false;
}
SourceRange getSourceRange() const;
SourceLoc getLoc() const;
BraceStmt *getBody() const { return Body.getPointer(); }
void setBody(BraceStmt *S, bool isSingleExpression) {
Body.setPointer(S);
Body.setInt(isSingleExpression);
}
ArrayRef<CaptureListEntry> getCaptureList() { return CaptureList; }
/// \brief Determine whether the parameters of this closure are actually
/// anonymous closure variables.
bool hasAnonymousClosureVars() const {
return ClosureExprBits.HasAnonymousClosureVars;
}
/// \brief Set the parameters of this closure along with a flag indicating
/// whether these parameters are actually anonymous closure variables.
void setHasAnonymousClosureVars() {
ClosureExprBits.HasAnonymousClosureVars = true;
}
/// \brief Determine whether this closure expression has an
/// explicitly-specified result type.
bool hasExplicitResultType() const { return ArrowLoc.isValid(); }
/// \brief Retrieve the location of the \c '->' for closures with an
/// explicit result type.
SourceLoc getArrowLoc() const {
assert(hasExplicitResultType() && "No arrow location");
return ArrowLoc;
}
/// retrieve the location of the \c in for a closure that has it.
SourceLoc getInLoc() const {
return InLoc;
}
/// \brief Retrieve the explicit result type location information.
TypeLoc &getExplicitResultTypeLoc() {
assert(hasExplicitResultType() && "No explicit result type");
return ExplicitResultType;
}
/// \brief Determine whether the closure has a single expression for its
/// body.
///
/// This will be true for closures such as, e.g.,
/// \code
/// { $0 + 1 }
/// \endcode
///
/// or
///
/// \code
/// { x, y in x > y }
/// \endcode
///
/// But not for empty closures nor
bool hasSingleExpressionBody() const {
return Body.getInt();
}
/// \brief Retrieve the body for closure that has a single expression for
/// its body.
///
/// Only valid when \c hasSingleExpressionBody() is true.
Expr *getSingleExpressionBody() const;
/// \brief Set the body for a closure that has a single expression as its
/// body.
///
/// This routine cannot change whether a closure has a single expression as
/// its body; it can only update that expression.
void setSingleExpressionBody(Expr *NewBody);
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::Closure;
}
};
/// \brief This is a closure of the contained subexpression that is formed
/// when an scalar expression is converted to @autoclosure function type.
/// For example:
/// \code
/// var x : @autoclosure () -> int = 4
/// \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;
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;
}
};
/// DynamicTypeExpr - "base.dynamicType" - Produces a metatype value.
///
/// The metatype value can comes from a evaluating an expression and then
/// getting its metatype.
class DynamicTypeExpr : public Expr {
Expr *Base;
SourceLoc MetatypeLoc;
public:
explicit DynamicTypeExpr(Expr *Base, SourceLoc MetatypeLoc, Type Ty)
: Expr(ExprKind::DynamicType, /*Implicit=*/false, Ty),
Base(Base), MetatypeLoc(MetatypeLoc) { }
Expr *getBase() const { return Base; }
void setBase(Expr *base) { Base = base; }
SourceLoc getLoc() const { return MetatypeLoc; }
SourceLoc getMetatypeLoc() const { return MetatypeLoc; }
SourceRange getSourceRange() const;
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;
bool UniquelyReferenced = false;
public:
explicit OpaqueValueExpr(SourceLoc Loc, Type Ty)
: Expr(ExprKind::OpaqueValue, /*Implicit=*/true, Ty), Loc(Loc) { }
/// Determine whether this opaque value is referenced at only one point in
/// the AST.
///
/// Opaque values referenced at only one place in the AST can be referenced
/// more efficiently, be eliminating extra retain/release traffic.
bool isUniquelyReferenced() const { return UniquelyReferenced; }
void setUniquelyReferenced(bool uniqueRef) { UniquelyReferenced = uniqueRef; }
SourceRange getSourceRange() const { return Loc; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::OpaqueValue;
}
};
/// ApplyExpr - Superclass of various function calls, which apply an argument to
/// a function to get a result.
class ApplyExpr : public Expr {
/// The function being called.
Expr *Fn;
/// The argument being passed to it, and whether it's a 'super' argument.
llvm::PointerIntPair<Expr *, 1, bool> ArgAndIsSuper;
protected:
ApplyExpr(ExprKind Kind, Expr *Fn, Expr *Arg, bool Implicit, Type Ty = Type())
: Expr(Kind, Implicit, Ty), Fn(Fn), ArgAndIsSuper(Arg, false) {
assert(classof((Expr*)this) && "ApplyExpr::classof out of date");
}
public:
Expr *getFn() const { return Fn; }
void setFn(Expr *e) { Fn = e; }
Expr *getArg() const { return ArgAndIsSuper.getPointer(); }
void setArg(Expr *e) {
assert((getKind() != ExprKind::Binary || isa<TupleExpr>(e)) &&
"BinaryExprs must have a TupleExpr as the argument");
ArgAndIsSuper = {e, ArgAndIsSuper.getInt()};
}
bool isSuper() const { return ArgAndIsSuper.getInt(); }
void setIsSuper(bool super) {
ArgAndIsSuper = {ArgAndIsSuper.getPointer(), super};
}
ValueDecl *getCalledValue() 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 : public ApplyExpr {
public:
CallExpr(Expr *fn, Expr *arg, bool Implicit, Type ty = Type())
: ApplyExpr(ExprKind::Call, fn, arg, Implicit, ty) {}
SourceRange getSourceRange() const;
SourceLoc getLoc() const {
SourceLoc FnLoc = getFn()->getLoc();
return FnLoc.isValid() ? FnLoc : getArg()->getLoc();
}
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(); }
SourceRange getSourceRange() const {
return SourceRange(getFn()->getStartLoc(), getArg()->getEndLoc());
}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::PrefixUnary;
}
};
/// PostfixUnaryExpr - Prefix unary expressions like '!y'.
class PostfixUnaryExpr : public ApplyExpr {
public:
PostfixUnaryExpr(Expr *Fn, Expr *Arg, Type Ty = Type())
: ApplyExpr(ExprKind::PostfixUnary, Fn, Arg, /*Implicit=*/false, Ty) {}
SourceLoc getLoc() const { return getFn()->getStartLoc(); }
SourceRange getSourceRange() const {
return SourceRange(getArg()->getStartLoc(), 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();
}
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();
}
SourceRange getSourceRange() const {
return SourceRange(getStartLoc(), 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(); }
SourceRange getSourceRange() const {
return SourceRange(getStartLoc(), 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)
: Expr(ExprKind::DotSyntaxBaseIgnored, /*Implicit=*/false, RHS->getType()),
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();
}
SourceRange getSourceRange() const {
return SourceRange(getStartLoc(), RHS->getEndLoc());
}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::DotSyntaxBaseIgnored;
}
};
/// \brief Represents an explicit cast, 'a as T' or 'a is T', where "T" is a
/// type, and "a" is the expression that will be converted to the type.
class ExplicitCastExpr : public Expr {
Expr *SubExpr;
SourceLoc AsLoc;
TypeLoc CastTy;
protected:
ExplicitCastExpr(ExprKind kind, Expr *sub, SourceLoc AsLoc, TypeLoc castTy,
Type resultTy)
: Expr(kind, /*Implicit=*/false), SubExpr(sub), AsLoc(AsLoc), CastTy(castTy)
{}
public:
Expr *getSubExpr() const { return SubExpr; }
/// Get the type syntactically spelled in the cast. For some forms of checked
/// cast this is different from the result type of the expression.
TypeLoc &getCastTypeLoc() { return CastTy; }
/// Get the type syntactically spelled in the cast. For some forms of checked
/// cast this is different from the result type of the expression.
TypeLoc getCastTypeLoc() const { return CastTy; }
void setSubExpr(Expr *E) { SubExpr = E; }
SourceLoc getLoc() const {
if (AsLoc.isValid())
return AsLoc;
return SubExpr->getLoc();
}
SourceRange getSourceRange() const {
if (CastTy.getSourceRange().isInvalid())
return SubExpr->getSourceRange();
auto startLoc = SubExpr ? SubExpr->getStartLoc() : AsLoc;
auto endLoc = CastTy.getSourceRange().End;
return {startLoc, endLoc};
}
/// True if the node has been processed by SequenceExpr folding.
bool isFolded() const { return SubExpr; }
static bool classof(const Expr *E) {
return E->getKind() >= ExprKind::First_ExplicitCastExpr &&
E->getKind() <= ExprKind::Last_ExplicitCastExpr;
}
};
/// Return a string representation of a CheckedCastKind.
StringRef getCheckedCastKindName(CheckedCastKind kind);
/// \brief Abstract base class for checked casts 'as' and 'is'. These represent
/// casts that can dynamically fail.
class CheckedCastExpr : public ExplicitCastExpr {
public:
CheckedCastExpr(ExprKind kind,
Expr *sub, SourceLoc asLoc, TypeLoc castTy, Type resultTy)
: ExplicitCastExpr(kind, sub, asLoc, castTy, resultTy)
{
CheckedCastExprBits.CastKind = unsigned(CheckedCastKind::Unresolved);
}
/// Return the semantic kind of cast performed.
CheckedCastKind getCastKind() const {
return CheckedCastKind(CheckedCastExprBits.CastKind);
}
void setCastKind(CheckedCastKind kind) {
CheckedCastExprBits.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 parsed cast "x as T" on which we have not yet performed
/// semantic analysis. Spelled 'a as T' and produces a value of type 'T'.
class UnresolvedCheckedCastExpr : public CheckedCastExpr {
public:
UnresolvedCheckedCastExpr(Expr *sub, SourceLoc asLoc, TypeLoc type)
: CheckedCastExpr(ExprKind::UnresolvedCheckedCast,
sub, asLoc, type, type.getType())
{ }
UnresolvedCheckedCastExpr(SourceLoc asLoc, TypeLoc type)
: UnresolvedCheckedCastExpr(nullptr, asLoc, type)
{}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::UnresolvedCheckedCast;
}
};
/// 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 {
public:
ForcedCheckedCastExpr(Expr *sub, SourceLoc asLoc, TypeLoc type)
: CheckedCastExpr(ExprKind::ForcedCheckedCast,
sub, asLoc, type, type.getType())
{
}
ForcedCheckedCastExpr(SourceLoc asLoc, TypeLoc type)
: ForcedCheckedCastExpr(nullptr, asLoc, type)
{
}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::ForcedCheckedCast;
}
};
/// \brief Represents an explicit conditional checked cast, which converts
/// from a type to some subtype and produces an Optional value, which will be
/// .Some(x) if the cast succeeds, or .None if the cast fails.
/// Spelled 'a as? T' and produces a value of type 'T?'.
class ConditionalCheckedCastExpr : public CheckedCastExpr {
SourceLoc QuestionLoc;
public:
ConditionalCheckedCastExpr(Expr *sub, SourceLoc asLoc, SourceLoc questionLoc,
TypeLoc type)
: CheckedCastExpr(ExprKind::ConditionalCheckedCast,
sub, asLoc, type, type.getType()),
QuestionLoc(questionLoc)
{ }
ConditionalCheckedCastExpr(SourceLoc asLoc, SourceLoc questionLoc,
TypeLoc type)
: ConditionalCheckedCastExpr(nullptr, asLoc, questionLoc, type)
{}
/// Retrieve the location of the '?' that follows 'as'.
SourceLoc getQuestionLoc() const { return QuestionLoc; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::ConditionalCheckedCast;
}
};
/// \brief Represents a runtime type check query, 'a is T', where 'T' is a type
/// and 'a' is a value of some related type. Evaluates to a Bool true if 'a' is
/// of the type and 'a as T' would succeed, false otherwise.
///
/// FIXME: We should support type queries with a runtime metatype value too.
class IsaExpr : public CheckedCastExpr {
public:
IsaExpr(Expr *sub, SourceLoc isLoc, TypeLoc type)
: CheckedCastExpr(ExprKind::Isa,
sub, isLoc, type, Type())
{}
IsaExpr(SourceLoc isLoc, TypeLoc type)
: IsaExpr(nullptr, isLoc, type)
{}
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::Isa;
}
};
/// \brief Represents an explicit coercion from a value to a specific type.
///
/// Spelled 'a as T' and produces a value of type 'T'.
class CoerceExpr : public ExplicitCastExpr {
public:
CoerceExpr(Expr *sub, SourceLoc asLoc, TypeLoc type)
: ExplicitCastExpr(ExprKind::Coerce, sub, asLoc, type, type.getType())
{ }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::Coerce;
}
};
/// \brief Represents the rebinding of 'self' in a constructor that calls out
/// to another constructor. The result of the subexpression is assigned to
/// 'self', and the expression returns void.
///
/// When a super.init or delegating initializer is invoked, 'self' is
/// reassigned to the result of the initializer (after being downcast in the
/// case of super.init).
///
/// This is needed for reference types with ObjC interop, where
/// reassigning 'self' is a supported feature, and for value type delegating
/// constructors, where the delegatee constructor is responsible for
/// initializing 'self' in-place before the delegator's logic executes.
class RebindSelfInConstructorExpr : public Expr {
Expr *SubExpr;
VarDecl *Self;
public:
RebindSelfInConstructorExpr(Expr *SubExpr, VarDecl *Self);
SourceLoc getLoc() const { return SubExpr->getLoc(); }
SourceRange getSourceRange() const { return SubExpr->getSourceRange(); }
VarDecl *getSelf() const { return Self; }
Expr *getSubExpr() const { return SubExpr; }
void setSubExpr(Expr *Sub) { SubExpr = Sub; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::RebindSelfInConstructor;
}
};
/// \brief The conditional expression 'x ? y : z'.
class IfExpr : public Expr {
Expr *CondExpr, *ThenExpr, *ElseExpr;
SourceLoc QuestionLoc, ColonLoc;
public:
IfExpr(Expr *CondExpr,
SourceLoc QuestionLoc, Expr *ThenExpr,
SourceLoc ColonLoc, Expr *ElseExpr,
Type Ty = Type())
: Expr(ExprKind::If, /*Implicit=*/false, Ty),
CondExpr(CondExpr), ThenExpr(ThenExpr), ElseExpr(ElseExpr),
QuestionLoc(QuestionLoc), ColonLoc(ColonLoc)
{}
IfExpr(SourceLoc QuestionLoc, Expr *ThenExpr, SourceLoc ColonLoc)
: IfExpr(nullptr, QuestionLoc, ThenExpr, ColonLoc, nullptr)
{}
SourceLoc getLoc() const { return QuestionLoc; }
SourceRange getSourceRange() const {
if (isFolded())
return {CondExpr->getStartLoc(), ElseExpr->getEndLoc()};
return {QuestionLoc, 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;
}
};
/// 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 { return EqualLoc; }
SourceRange getSourceRange() const;
/// True if the node has been processed by binary expression folding.
bool isFolded() const { return Dest && Src; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::Assign;
}
};
/// \brief An expression that describes the use of a default value, which may
/// come from the default argument of a function type or member initializer.
///
/// This expression is synthesized by type checking and cannot be written
/// directly by the user.
class DefaultValueExpr : public Expr {
Expr *subExpr;
public:
explicit DefaultValueExpr(Expr *subExpr)
: Expr(ExprKind::DefaultValue, /*Implicit=*/true, subExpr->getType()),
subExpr(subExpr) { }
Expr *getSubExpr() const { return subExpr; }
void setSubExpr(Expr *sub) { subExpr = sub; }
SourceRange getSourceRange() const { return SourceRange(); }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::DefaultValue;
}
};
/// \brief A pattern production that has been parsed but hasn't been resolved
/// into a complete pattern. Name binding converts these into standalone pattern
/// nodes or raises an error if a pattern production appears in an invalid
/// position.
class UnresolvedPatternExpr : public Expr {
Pattern *subPattern;
public:
explicit UnresolvedPatternExpr(Pattern *subPattern)
: Expr(ExprKind::UnresolvedPattern, /*Implicit=*/false),
subPattern(subPattern) { }
const Pattern *getSubPattern() const { return subPattern; }
Pattern *getSubPattern() { return subPattern; }
void setSubPattern(Pattern *p) { subPattern = p; }
SourceLoc getLoc() const;
SourceRange getSourceRange() const;
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::UnresolvedPattern;
}
};
/// \brief An expression that guards execution based on whether the run-time
/// configuration supports a given API, e.g., #os(OSX >= 10.9, iOS >= 7.0).
class AvailabilityQueryExpr : public Expr {
SourceLoc PoundLoc;
SourceLoc RParenLoc;
unsigned NumQueries;
/// The version range when this query will return true. This value is
/// filled in by Sema.
VersionRange AvailableRange;
AvailabilityQueryExpr(SourceLoc PoundLoc,
ArrayRef<VersionConstraintAvailabilitySpec *> queries,
SourceLoc RParenLoc,
VersionRange AvailableRange = VersionRange::empty(),
Type Ty = Type())
: Expr(ExprKind::AvailabilityQuery, /*Implicit=*/false, Ty),
PoundLoc(PoundLoc), RParenLoc(RParenLoc), NumQueries(queries.size()),
AvailableRange(AvailableRange) {
memcpy(getQueriesBuf(), queries.data(),
queries.size() * sizeof(VersionConstraintAvailabilitySpec *));
}
public:
static AvailabilityQueryExpr *
create(ASTContext &ctx, SourceLoc PoundLoc,
ArrayRef<VersionConstraintAvailabilitySpec *> queries,
SourceLoc RParenLoc);
ArrayRef<VersionConstraintAvailabilitySpec *> getQueries() const {
return ArrayRef<VersionConstraintAvailabilitySpec *>(getQueriesBuf(),
NumQueries);
}
SourceRange getSourceRange() const;
SourceLoc getLoc() const { return PoundLoc; }
const VersionRange &getAvailableRange() const { return AvailableRange; }
void setAvailableRange(const VersionRange &Range) { AvailableRange = Range; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::AvailabilityQuery;
}
private:
VersionConstraintAvailabilitySpec **getQueriesBuf() {
return reinterpret_cast<VersionConstraintAvailabilitySpec **>(this + 1);
}
VersionConstraintAvailabilitySpec *const *getQueriesBuf() const {
return const_cast<AvailabilityQueryExpr *>(this)->getQueriesBuf();
}
};
} // end namespace swift
#endif