Files
swift-mirror/lib/AST/Expr.cpp
Frederick Kellison-Linn f5845666e6 [AST] Introduce UnresolvedMemberChainResultExpr
Introduce a new expression type for representing the result of an unresolved member chain. Use this expression type instead of an implicit ParenExpr for giving unresolved member chain result types representation in the AST during type checking.
2020-08-26 22:42:29 -04:00

2498 lines
88 KiB
C++

//===--- Expr.cpp - Swift Language Expression ASTs ------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file implements the Expr class and subclasses.
//
//===----------------------------------------------------------------------===//
#include "swift/AST/Expr.h"
#include "swift/Basic/Statistic.h"
#include "swift/Basic/Unicode.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/ASTVisitor.h"
#include "swift/AST/Decl.h" // FIXME: Bad dependency
#include "swift/AST/ParameterList.h"
#include "swift/AST/Stmt.h"
#include "swift/AST/ASTWalker.h"
#include "swift/AST/AvailabilitySpec.h"
#include "swift/AST/PrettyStackTrace.h"
#include "swift/AST/TypeCheckRequests.h"
#include "swift/AST/TypeLoc.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/Twine.h"
using namespace swift;
#define EXPR(Id, _) \
static_assert(IsTriviallyDestructible<Id##Expr>::value, \
"Exprs are BumpPtrAllocated; the destructor is never called");
#include "swift/AST/ExprNodes.def"
StringRef swift::getFunctionRefKindStr(FunctionRefKind refKind) {
switch (refKind) {
case FunctionRefKind::Unapplied:
return "unapplied";
case FunctionRefKind::SingleApply:
return "single";
case FunctionRefKind::DoubleApply:
return "double";
case FunctionRefKind::Compound:
return "compound";
}
llvm_unreachable("Unhandled FunctionRefKind in switch.");
}
//===----------------------------------------------------------------------===//
// Expr methods.
//===----------------------------------------------------------------------===//
// Only allow allocation of Stmts using the allocator in ASTContext.
void *Expr::operator new(size_t Bytes, ASTContext &C,
unsigned Alignment) {
return C.Allocate(Bytes, Alignment);
}
StringRef Expr::getKindName(ExprKind K) {
switch (K) {
#define EXPR(Id, Parent) case ExprKind::Id: return #Id;
#include "swift/AST/ExprNodes.def"
}
llvm_unreachable("bad ExprKind");
}
template <class T> static SourceLoc getStartLocImpl(const T *E);
template <class T> static SourceLoc getEndLocImpl(const T *E);
template <class T> static SourceLoc getLocImpl(const T *E);
// Helper functions to check statically whether a method has been
// overridden from its implementation in Expr. The sort of thing you
// need when you're avoiding v-tables.
namespace {
template <typename ReturnType, typename Class>
constexpr bool isOverriddenFromExpr(ReturnType (Class::*)() const) {
return true;
}
template <typename ReturnType>
constexpr bool isOverriddenFromExpr(ReturnType (Expr::*)() const) {
return false;
}
template <bool IsOverridden> struct Dispatch;
/// Dispatch down to a concrete override.
template <> struct Dispatch<true> {
template <class T> static SourceLoc getStartLoc(const T *E) {
return E->getStartLoc();
}
template <class T> static SourceLoc getEndLoc(const T *E) {
return E->getEndLoc();
}
template <class T> static SourceLoc getLoc(const T *E) {
return E->getLoc();
}
template <class T> static SourceRange getSourceRange(const T *E) {
return E->getSourceRange();
}
};
/// Default implementations for when a method isn't overridden.
template <> struct Dispatch<false> {
template <class T> static SourceLoc getStartLoc(const T *E) {
return E->getSourceRange().Start;
}
template <class T> static SourceLoc getEndLoc(const T *E) {
return E->getSourceRange().End;
}
template <class T> static SourceLoc getLoc(const T *E) {
return getStartLocImpl(E);
}
template <class T> static SourceRange getSourceRange(const T *E) {
if (E->getStartLoc().isInvalid() != E->getEndLoc().isInvalid())
return SourceRange();
return { E->getStartLoc(), E->getEndLoc() };
}
};
} // end anonymous namespace
void Expr::setType(Type T) {
assert(!T || !T->hasTypeVariable());
Ty = T;
}
void Expr::setImplicit(bool Implicit) {
assert(!isa<TypeExpr>(this) || getType() &&
"Cannot make a TypeExpr implicit without a contextual type.");
Bits.Expr.Implicit = Implicit;
}
template <class T> static SourceRange getSourceRangeImpl(const T *E) {
static_assert(isOverriddenFromExpr(&T::getSourceRange) ||
(isOverriddenFromExpr(&T::getStartLoc) &&
isOverriddenFromExpr(&T::getEndLoc)),
"Expr subclass must implement either getSourceRange() "
"or getStartLoc()/getEndLoc()");
return Dispatch<isOverriddenFromExpr(&T::getSourceRange)>::getSourceRange(E);
}
SourceRange Expr::getSourceRange() const {
switch (getKind()) {
#define EXPR(ID, PARENT) \
case ExprKind::ID: return getSourceRangeImpl(cast<ID##Expr>(this));
#include "swift/AST/ExprNodes.def"
}
llvm_unreachable("expression type not handled!");
}
template <class T> static SourceLoc getStartLocImpl(const T *E) {
return Dispatch<isOverriddenFromExpr(&T::getStartLoc)>::getStartLoc(E);
}
SourceLoc Expr::getStartLoc() const {
switch (getKind()) {
#define EXPR(ID, PARENT) \
case ExprKind::ID: return getStartLocImpl(cast<ID##Expr>(this));
#include "swift/AST/ExprNodes.def"
}
llvm_unreachable("expression type not handled!");
}
template <class T> static SourceLoc getEndLocImpl(const T *E) {
return Dispatch<isOverriddenFromExpr(&T::getEndLoc)>::getEndLoc(E);
}
SourceLoc Expr::getEndLoc() const {
switch (getKind()) {
#define EXPR(ID, PARENT) \
case ExprKind::ID: return getEndLocImpl(cast<ID##Expr>(this));
#include "swift/AST/ExprNodes.def"
}
llvm_unreachable("expression type not handled!");
}
template <class T> static SourceLoc getLocImpl(const T *E) {
return Dispatch<isOverriddenFromExpr(&T::getLoc)>::getLoc(E);
}
SourceLoc Expr::getLoc() const {
switch (getKind()) {
#define EXPR(ID, PARENT) \
case ExprKind::ID: return getLocImpl(cast<ID##Expr>(this));
#include "swift/AST/ExprNodes.def"
}
llvm_unreachable("expression type not handled!");
}
Expr *Expr::getSemanticsProvidingExpr() {
if (auto *IE = dyn_cast<IdentityExpr>(this))
return IE->getSubExpr()->getSemanticsProvidingExpr();
if (auto *TE = dyn_cast<TryExpr>(this))
return TE->getSubExpr()->getSemanticsProvidingExpr();
return this;
}
Expr *Expr::getValueProvidingExpr() {
Expr *E = getSemanticsProvidingExpr();
if (auto TE = dyn_cast<ForceTryExpr>(E))
return TE->getSubExpr()->getValueProvidingExpr();
// TODO:
// - tuple literal projection, which may become interestingly idiomatic
return E;
}
DeclRefExpr *Expr::getMemberOperatorRef() {
auto expr = this;
if (!expr->isImplicit()) return nullptr;
auto dotSyntax = dyn_cast<DotSyntaxCallExpr>(expr);
if (!dotSyntax) return nullptr;
auto operatorRef = dyn_cast<DeclRefExpr>(dotSyntax->getFn());
if (!operatorRef) return nullptr;
auto func = dyn_cast<FuncDecl>(operatorRef->getDecl());
if (!func) return nullptr;
if (!func->isOperator()) return nullptr;
return operatorRef;
}
ConcreteDeclRef Expr::getReferencedDecl(bool stopAtParenExpr) const {
switch (getKind()) {
// No declaration reference.
#define NO_REFERENCE(Id) case ExprKind::Id: return ConcreteDeclRef()
#define SIMPLE_REFERENCE(Id, Getter) \
case ExprKind::Id: \
return cast<Id##Expr>(this)->Getter()
#define PASS_THROUGH_REFERENCE(Id, GetSubExpr) \
case ExprKind::Id: \
return cast<Id##Expr>(this) \
->GetSubExpr()->getReferencedDecl(stopAtParenExpr)
NO_REFERENCE(Error);
NO_REFERENCE(NilLiteral);
NO_REFERENCE(IntegerLiteral);
NO_REFERENCE(FloatLiteral);
NO_REFERENCE(BooleanLiteral);
NO_REFERENCE(StringLiteral);
NO_REFERENCE(InterpolatedStringLiteral);
NO_REFERENCE(ObjectLiteral);
NO_REFERENCE(MagicIdentifierLiteral);
NO_REFERENCE(DiscardAssignment);
NO_REFERENCE(LazyInitializer);
SIMPLE_REFERENCE(DeclRef, getDeclRef);
SIMPLE_REFERENCE(SuperRef, getSelf);
NO_REFERENCE(Type);
SIMPLE_REFERENCE(OtherConstructorDeclRef, getDeclRef);
PASS_THROUGH_REFERENCE(DotSyntaxBaseIgnored, getRHS);
// FIXME: Return multiple results?
case ExprKind::OverloadedDeclRef:
return ConcreteDeclRef();
NO_REFERENCE(UnresolvedDeclRef);
SIMPLE_REFERENCE(MemberRef, getMember);
SIMPLE_REFERENCE(DynamicMemberRef, getMember);
SIMPLE_REFERENCE(DynamicSubscript, getMember);
PASS_THROUGH_REFERENCE(UnresolvedSpecialize, getSubExpr);
NO_REFERENCE(UnresolvedMember);
NO_REFERENCE(UnresolvedDot);
NO_REFERENCE(Sequence);
case ExprKind::Paren:
if (stopAtParenExpr) return ConcreteDeclRef();
return cast<ParenExpr>(this)
->getSubExpr()->getReferencedDecl(stopAtParenExpr);
PASS_THROUGH_REFERENCE(UnresolvedMemberChainResult, getSubExpr);
PASS_THROUGH_REFERENCE(DotSelf, getSubExpr);
PASS_THROUGH_REFERENCE(Await, getSubExpr);
PASS_THROUGH_REFERENCE(Try, getSubExpr);
PASS_THROUGH_REFERENCE(ForceTry, getSubExpr);
PASS_THROUGH_REFERENCE(OptionalTry, getSubExpr);
NO_REFERENCE(Tuple);
NO_REFERENCE(Array);
NO_REFERENCE(Dictionary);
case ExprKind::Subscript: {
auto subscript = cast<SubscriptExpr>(this);
if (subscript->hasDecl()) return subscript->getDecl();
return ConcreteDeclRef();
}
NO_REFERENCE(KeyPathApplication);
NO_REFERENCE(TupleElement);
NO_REFERENCE(CaptureList);
NO_REFERENCE(Closure);
PASS_THROUGH_REFERENCE(AutoClosure, getSingleExpressionBody);
PASS_THROUGH_REFERENCE(InOut, getSubExpr);
NO_REFERENCE(VarargExpansion);
NO_REFERENCE(DynamicType);
PASS_THROUGH_REFERENCE(RebindSelfInConstructor, getSubExpr);
NO_REFERENCE(OpaqueValue);
NO_REFERENCE(PropertyWrapperValuePlaceholder);
NO_REFERENCE(DefaultArgument);
PASS_THROUGH_REFERENCE(BindOptional, getSubExpr);
PASS_THROUGH_REFERENCE(OptionalEvaluation, getSubExpr);
PASS_THROUGH_REFERENCE(ForceValue, getSubExpr);
PASS_THROUGH_REFERENCE(OpenExistential, getSubExpr);
NO_REFERENCE(Call);
NO_REFERENCE(PrefixUnary);
NO_REFERENCE(PostfixUnary);
NO_REFERENCE(Binary);
NO_REFERENCE(DotSyntaxCall);
NO_REFERENCE(MakeTemporarilyEscapable);
NO_REFERENCE(ConstructorRefCall);
PASS_THROUGH_REFERENCE(Load, getSubExpr);
NO_REFERENCE(DestructureTuple);
NO_REFERENCE(UnresolvedTypeConversion);
PASS_THROUGH_REFERENCE(FunctionConversion, getSubExpr);
PASS_THROUGH_REFERENCE(CovariantFunctionConversion, getSubExpr);
PASS_THROUGH_REFERENCE(CovariantReturnConversion, getSubExpr);
PASS_THROUGH_REFERENCE(ImplicitlyUnwrappedFunctionConversion, getSubExpr);
PASS_THROUGH_REFERENCE(MetatypeConversion, getSubExpr);
PASS_THROUGH_REFERENCE(CollectionUpcastConversion, getSubExpr);
PASS_THROUGH_REFERENCE(Erasure, getSubExpr);
PASS_THROUGH_REFERENCE(AnyHashableErasure, getSubExpr);
PASS_THROUGH_REFERENCE(DerivedToBase, getSubExpr);
PASS_THROUGH_REFERENCE(ArchetypeToSuper, getSubExpr);
PASS_THROUGH_REFERENCE(InjectIntoOptional, getSubExpr);
PASS_THROUGH_REFERENCE(ClassMetatypeToObject, getSubExpr);
PASS_THROUGH_REFERENCE(ExistentialMetatypeToObject, getSubExpr);
PASS_THROUGH_REFERENCE(ProtocolMetatypeToObject, getSubExpr);
PASS_THROUGH_REFERENCE(InOutToPointer, getSubExpr);
PASS_THROUGH_REFERENCE(ArrayToPointer, getSubExpr);
PASS_THROUGH_REFERENCE(StringToPointer, getSubExpr);
PASS_THROUGH_REFERENCE(PointerToPointer, getSubExpr);
PASS_THROUGH_REFERENCE(ForeignObjectConversion, getSubExpr);
PASS_THROUGH_REFERENCE(UnevaluatedInstance, getSubExpr);
PASS_THROUGH_REFERENCE(DifferentiableFunction, getSubExpr);
PASS_THROUGH_REFERENCE(LinearFunction, getSubExpr);
PASS_THROUGH_REFERENCE(DifferentiableFunctionExtractOriginal, getSubExpr);
PASS_THROUGH_REFERENCE(LinearFunctionExtractOriginal, getSubExpr);
PASS_THROUGH_REFERENCE(LinearToDifferentiableFunction, getSubExpr);
PASS_THROUGH_REFERENCE(BridgeToObjC, getSubExpr);
PASS_THROUGH_REFERENCE(BridgeFromObjC, getSubExpr);
PASS_THROUGH_REFERENCE(ConditionalBridgeFromObjC, getSubExpr);
PASS_THROUGH_REFERENCE(UnderlyingToOpaque, getSubExpr);
NO_REFERENCE(Coerce);
NO_REFERENCE(ForcedCheckedCast);
NO_REFERENCE(ConditionalCheckedCast);
NO_REFERENCE(Is);
NO_REFERENCE(Arrow);
NO_REFERENCE(If);
NO_REFERENCE(EnumIsCase);
NO_REFERENCE(Assign);
NO_REFERENCE(CodeCompletion);
NO_REFERENCE(UnresolvedPattern);
NO_REFERENCE(EditorPlaceholder);
NO_REFERENCE(ObjCSelector);
NO_REFERENCE(KeyPath);
NO_REFERENCE(KeyPathDot);
PASS_THROUGH_REFERENCE(OneWay, getSubExpr);
NO_REFERENCE(Tap);
#undef SIMPLE_REFERENCE
#undef NO_REFERENCE
#undef PASS_THROUGH_REFERENCE
}
return ConcreteDeclRef();
}
/// Enumerate each immediate child expression of this node, invoking the
/// specific functor on it. This ignores statements and other non-expression
/// children.
void Expr::
forEachImmediateChildExpr(llvm::function_ref<Expr *(Expr *)> callback) {
struct ChildWalker : ASTWalker {
llvm::function_ref<Expr *(Expr *)> callback;
Expr *ThisNode;
ChildWalker(llvm::function_ref<Expr *(Expr *)> callback, Expr *ThisNode)
: callback(callback), ThisNode(ThisNode) {}
std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
// When looking at the current node, of course we want to enter it. We
// also don't want to enumerate it.
if (E == ThisNode)
return { true, E };
// Otherwise we must be a child of our expression, enumerate it!
return { false, callback(E) };
}
std::pair<bool, Stmt *> walkToStmtPre(Stmt *S) override {
return { false, S };
}
std::pair<bool, Pattern*> walkToPatternPre(Pattern *P) override {
return { false, P };
}
bool walkToDeclPre(Decl *D) override { return false; }
bool walkToTypeReprPre(TypeRepr *T) override { return false; }
};
this->walk(ChildWalker(callback, this));
}
/// Enumerate each immediate child expression of this node, invoking the
/// specific functor on it. This ignores statements and other non-expression
/// children.
void Expr::forEachChildExpr(llvm::function_ref<Expr *(Expr *)> callback) {
struct ChildWalker : ASTWalker {
llvm::function_ref<Expr *(Expr *)> callback;
ChildWalker(llvm::function_ref<Expr *(Expr *)> callback)
: callback(callback) {}
std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
// Enumerate the node!
return { true, callback(E) };
}
std::pair<bool, Stmt *> walkToStmtPre(Stmt *S) override {
return { false, S };
}
std::pair<bool, Pattern*> walkToPatternPre(Pattern *P) override {
return { false, P };
}
bool walkToDeclPre(Decl *D) override { return false; }
bool walkToTypeReprPre(TypeRepr *T) override { return false; }
};
this->walk(ChildWalker(callback));
}
bool Expr::isTypeReference(llvm::function_ref<Type(Expr *)> getType,
llvm::function_ref<Decl *(Expr *)> getDecl) const {
Expr *expr = const_cast<Expr *>(this);
// If the result isn't a metatype, there's nothing else to do.
if (!getType(expr)->is<AnyMetatypeType>())
return false;
do {
// Skip syntax.
expr = expr->getSemanticsProvidingExpr();
// Direct reference to a type.
if (auto declRef = dyn_cast<DeclRefExpr>(expr))
if (isa<TypeDecl>(declRef->getDecl()))
return true;
if (isa<TypeExpr>(expr))
return true;
// A "." expression that refers to a member.
if (auto memberRef = dyn_cast<MemberRefExpr>(expr))
return isa<TypeDecl>(memberRef->getMember().getDecl());
// Any other expressions which might be referencing
// a declaration e.g. not yet type-checked ones like
// `UnresolvedDotExpr`.
if (auto *decl = getDecl(expr))
return isa<TypeDecl>(decl);
// When the base of a "." expression is ignored, look at the member.
if (auto ignoredDot = dyn_cast<DotSyntaxBaseIgnoredExpr>(expr)) {
expr = ignoredDot->getRHS();
continue;
}
if (auto *USE = dyn_cast<UnresolvedSpecializeExpr>(expr)) {
expr = USE->getSubExpr();
continue;
}
// Anything else is not statically derived.
return false;
} while (true);
}
bool Expr::isStaticallyDerivedMetatype(
llvm::function_ref<Type(Expr *)> getType,
llvm::function_ref<bool(Expr *)> isTypeReference) const {
// The expression must first be a type reference.
if (!isTypeReference(const_cast<Expr *>(this)))
return false;
auto type = getType(const_cast<Expr *>(this))
->castTo<AnyMetatypeType>()
->getInstanceType();
// Archetypes are never statically derived.
if (type->is<ArchetypeType>())
return false;
// Dynamic Self is never statically derived.
if (type->is<DynamicSelfType>())
return false;
// Everything else is statically derived.
return true;
}
bool Expr::isSuperExpr() const {
const Expr *expr = this;
do {
expr = expr->getSemanticsProvidingExpr();
if (isa<SuperRefExpr>(expr))
return true;
if (auto derivedToBase = dyn_cast<DerivedToBaseExpr>(expr)) {
expr = derivedToBase->getSubExpr();
continue;
}
if (auto metatypeConversion = dyn_cast<MetatypeConversionExpr>(expr)) {
expr = metatypeConversion->getSubExpr();
continue;
}
return false;
} while (true);
}
bool Expr::canAppendPostfixExpression(bool appendingPostfixOperator) const {
switch (getKind()) {
case ExprKind::Error:
case ExprKind::CodeCompletion:
case ExprKind::LazyInitializer:
case ExprKind::OneWay:
return false;
case ExprKind::NilLiteral:
case ExprKind::IntegerLiteral:
case ExprKind::FloatLiteral:
case ExprKind::BooleanLiteral:
case ExprKind::StringLiteral:
case ExprKind::InterpolatedStringLiteral:
case ExprKind::MagicIdentifierLiteral:
case ExprKind::ObjCSelector:
case ExprKind::KeyPath:
return true;
case ExprKind::ObjectLiteral:
return true;
case ExprKind::DiscardAssignment:
// Legal but pointless.
return true;
case ExprKind::DeclRef:
return !cast<DeclRefExpr>(this)->getDecl()->isOperator();
case ExprKind::SuperRef:
case ExprKind::OtherConstructorDeclRef:
case ExprKind::DotSyntaxBaseIgnored:
return true;
case ExprKind::Type:
return cast<TypeExpr>(this)->getTypeRepr()->isSimple();
case ExprKind::OverloadedDeclRef: {
auto *overloadedExpr = cast<OverloadedDeclRefExpr>(this);
if (overloadedExpr->getDecls().empty())
return false;
return !overloadedExpr->getDecls().front()->isOperator();
}
case ExprKind::UnresolvedDeclRef:
return cast<UnresolvedDeclRefExpr>(this)->getName().isOperator();
case ExprKind::MemberRef:
case ExprKind::DynamicMemberRef:
case ExprKind::DynamicSubscript:
case ExprKind::UnresolvedSpecialize:
case ExprKind::UnresolvedMember:
case ExprKind::UnresolvedDot:
return true;
case ExprKind::Sequence:
return false;
case ExprKind::Paren:
case ExprKind::DotSelf:
case ExprKind::UnresolvedMemberChainResult:
case ExprKind::Tuple:
case ExprKind::Array:
case ExprKind::Dictionary:
case ExprKind::Subscript:
case ExprKind::KeyPathApplication:
case ExprKind::TupleElement:
return true;
case ExprKind::CaptureList:
case ExprKind::Closure:
case ExprKind::AutoClosure:
return false;
case ExprKind::DynamicType:
return true;
case ExprKind::Await:
case ExprKind::Try:
case ExprKind::ForceTry:
case ExprKind::OptionalTry:
case ExprKind::InOut:
return false;
case ExprKind::RebindSelfInConstructor:
case ExprKind::OpaqueValue:
case ExprKind::PropertyWrapperValuePlaceholder:
case ExprKind::DefaultArgument:
case ExprKind::BindOptional:
case ExprKind::OptionalEvaluation:
return false;
case ExprKind::ForceValue:
return true;
case ExprKind::OpenExistential:
case ExprKind::MakeTemporarilyEscapable:
case ExprKind::VarargExpansion:
return false;
case ExprKind::Call:
case ExprKind::DotSyntaxCall:
case ExprKind::ConstructorRefCall:
return true;
case ExprKind::PostfixUnary:
return !appendingPostfixOperator;
case ExprKind::PrefixUnary:
case ExprKind::Binary:
return false;
case ExprKind::Load:
case ExprKind::DestructureTuple:
case ExprKind::UnresolvedTypeConversion:
case ExprKind::FunctionConversion:
case ExprKind::CovariantFunctionConversion:
case ExprKind::CovariantReturnConversion:
case ExprKind::ImplicitlyUnwrappedFunctionConversion:
case ExprKind::MetatypeConversion:
case ExprKind::CollectionUpcastConversion:
case ExprKind::Erasure:
case ExprKind::AnyHashableErasure:
case ExprKind::DerivedToBase:
case ExprKind::ArchetypeToSuper:
case ExprKind::InjectIntoOptional:
case ExprKind::ClassMetatypeToObject:
case ExprKind::ExistentialMetatypeToObject:
case ExprKind::ProtocolMetatypeToObject:
case ExprKind::InOutToPointer:
case ExprKind::ArrayToPointer:
case ExprKind::StringToPointer:
case ExprKind::PointerToPointer:
case ExprKind::ForeignObjectConversion:
case ExprKind::UnevaluatedInstance:
case ExprKind::DifferentiableFunction:
case ExprKind::LinearFunction:
case ExprKind::DifferentiableFunctionExtractOriginal:
case ExprKind::LinearFunctionExtractOriginal:
case ExprKind::LinearToDifferentiableFunction:
case ExprKind::EnumIsCase:
case ExprKind::ConditionalBridgeFromObjC:
case ExprKind::BridgeFromObjC:
case ExprKind::BridgeToObjC:
case ExprKind::UnderlyingToOpaque:
// Implicit conversion nodes have no syntax of their own; defer to the
// subexpression.
return cast<ImplicitConversionExpr>(this)->getSubExpr()
->canAppendPostfixExpression(appendingPostfixOperator);
case ExprKind::ForcedCheckedCast:
case ExprKind::ConditionalCheckedCast:
case ExprKind::Is:
case ExprKind::Coerce:
return false;
case ExprKind::Arrow:
case ExprKind::If:
case ExprKind::Assign:
case ExprKind::UnresolvedPattern:
case ExprKind::EditorPlaceholder:
case ExprKind::KeyPathDot:
return false;
case ExprKind::Tap:
return true;
}
llvm_unreachable("Unhandled ExprKind in switch.");
}
llvm::DenseMap<Expr *, Expr *> Expr::getParentMap() {
class RecordingTraversal : public ASTWalker {
public:
llvm::DenseMap<Expr *, Expr *> &ParentMap;
explicit RecordingTraversal(llvm::DenseMap<Expr *, Expr *> &parentMap)
: ParentMap(parentMap) { }
std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
if (auto parent = Parent.getAsExpr())
ParentMap[E] = parent;
return { true, E };
}
};
llvm::DenseMap<Expr *, Expr *> parentMap;
RecordingTraversal traversal(parentMap);
walk(traversal);
return parentMap;
}
//===----------------------------------------------------------------------===//
// Support methods for Exprs.
//===----------------------------------------------------------------------===//
IntegerLiteralExpr * IntegerLiteralExpr::createFromUnsigned(ASTContext &C, unsigned value) {
llvm::SmallString<8> Scratch;
llvm::APInt(sizeof(unsigned)*8, value).toString(Scratch, 10, /*signed*/ false);
auto Text = C.AllocateCopy(StringRef(Scratch));
return new (C) IntegerLiteralExpr(Text, SourceLoc(), /*implicit*/ true);
}
APInt IntegerLiteralExpr::getRawValue() const {
return BuiltinIntegerWidth::arbitrary().parse(getDigitsText(), /*radix*/0,
isNegative());
}
APInt IntegerLiteralExpr::getValue() const {
assert(!getType().isNull() && "Semantic analysis has not completed");
assert(!getType()->hasError() && "Should have a valid type");
if (!getType()->is<AnyBuiltinIntegerType>())
return getRawValue();
auto width = getType()->castTo<AnyBuiltinIntegerType>()->getWidth();
return width.parse(getDigitsText(), /*radix*/ 0, isNegative());
}
APInt BuiltinIntegerWidth::parse(StringRef text, unsigned radix, bool negate,
bool *hadError) const {
if (hadError) *hadError = false;
// Parse an unsigned value from the string.
APInt value;
// Swift doesn't treat a leading zero as signifying octal, but
// StringRef::getAsInteger does. Force decimal parsing in this case.
if (radix == 0 && text.size() >= 2 && text[0] == '0' && isdigit(text[1]))
radix = 10;
bool error = text.getAsInteger(radix, value);
if (error) {
if (hadError) *hadError = true;
return value;
}
// If we're producing an arbitrary-precision value, we don't need to do
// much additional processing.
if (isArbitraryWidth()) {
// The parser above always produces a non-negative value, so if the sign
// bit is set we need to give it some breathing room.
if (value.isNegative())
value = value.zext(value.getBitWidth() + 1);
assert(!value.isNegative());
// Now we can safely negate.
if (negate) {
value = -value;
assert(value.isNegative() || value.isNullValue());
}
// Truncate down to the minimum number of bits required to express
// this value exactly.
auto requiredBits = value.getMinSignedBits();
if (value.getBitWidth() > requiredBits)
value = value.trunc(requiredBits);
// If we have a fixed-width type (including abstract ones), we need to do
// fixed-width transformations, which can overflow.
} else {
unsigned width = getGreatestWidth();
// The overflow diagnostics in this case can't be fully correct because
// we don't know whether we're supposed to be producing a signed number
// or an unsigned one.
if (hadError && value.getActiveBits() > width)
*hadError = true;
value = value.zextOrTrunc(width);
if (negate) {
value = -value;
if (hadError && !value.isNegative())
*hadError = true;
}
assert(value.getBitWidth() == width);
}
return value;
}
static APFloat getFloatLiteralValue(bool IsNegative, StringRef Text,
const llvm::fltSemantics &Semantics) {
APFloat Val(Semantics);
llvm::Expected<APFloat::opStatus> MaybeRes =
Val.convertFromString(Text, llvm::APFloat::rmNearestTiesToEven);
assert(MaybeRes && *MaybeRes != APFloat::opInvalidOp &&
"Sema didn't reject invalid number");
(void)MaybeRes;
if (IsNegative) {
auto NegVal = APFloat::getZero(Semantics, /*negative*/ true);
auto Res = NegVal.subtract(Val, llvm::APFloat::rmNearestTiesToEven);
assert(Res != APFloat::opInvalidOp && "Sema didn't reject invalid number");
(void)Res;
return NegVal;
}
return Val;
}
APFloat FloatLiteralExpr::getValue(StringRef Text,
const llvm::fltSemantics &Semantics,
bool Negative) {
return getFloatLiteralValue(Negative, Text, Semantics);
}
llvm::APFloat FloatLiteralExpr::getValue() const {
assert(!getType().isNull() && "Semantic analysis has not completed");
assert(!getType()->hasError() && "Should have a valid type");
Type ty = getType();
if (!ty->is<BuiltinFloatType>()) {
assert(!getBuiltinType().isNull() && "Semantic analysis has not completed");
assert(!getBuiltinType()->hasError() && "Should have a valid type");
ty = getBuiltinType();
}
return getFloatLiteralValue(
isNegative(), getDigitsText(),
ty->castTo<BuiltinFloatType>()->getAPFloatSemantics());
}
StringLiteralExpr::StringLiteralExpr(StringRef Val, SourceRange Range,
bool Implicit)
: LiteralExpr(ExprKind::StringLiteral, Implicit), Val(Val),
Range(Range) {
Bits.StringLiteralExpr.Encoding = static_cast<unsigned>(UTF8);
Bits.StringLiteralExpr.IsSingleUnicodeScalar =
unicode::isSingleUnicodeScalar(Val);
Bits.StringLiteralExpr.IsSingleExtendedGraphemeCluster =
unicode::isSingleExtendedGraphemeCluster(Val);
}
static ArrayRef<Identifier> getArgumentLabelsFromArgument(
Expr *arg, SmallVectorImpl<Identifier> &scratch,
SmallVectorImpl<SourceLoc> *sourceLocs = nullptr,
bool *hasTrailingClosure = nullptr,
llvm::function_ref<Type(Expr *)> getType = [](Expr *E) -> Type {
return E->getType();
}) {
if (sourceLocs) sourceLocs->clear();
if (hasTrailingClosure) *hasTrailingClosure = false;
// A parenthesized expression is a single, unlabeled argument.
if (auto paren = dyn_cast<ParenExpr>(arg)) {
scratch.clear();
scratch.push_back(Identifier());
if (hasTrailingClosure) *hasTrailingClosure = paren->hasTrailingClosure();
return scratch;
}
// A tuple expression stores its element names, if they exist.
if (auto tuple = dyn_cast<TupleExpr>(arg)) {
if (sourceLocs && tuple->hasElementNameLocs()) {
sourceLocs->append(tuple->getElementNameLocs().begin(),
tuple->getElementNameLocs().end());
}
if (hasTrailingClosure) *hasTrailingClosure = tuple->hasTrailingClosure();
if (tuple->hasElementNames()) {
assert(tuple->getElementNames().size() == tuple->getNumElements());
return tuple->getElementNames();
}
scratch.assign(tuple->getNumElements(), Identifier());
return scratch;
}
// Otherwise, use the type information.
auto type = getType(arg);
if (type->hasParenSugar()) {
scratch.clear();
scratch.push_back(Identifier());
return scratch;
}
// FIXME: Should be a dyn_cast.
if (auto tupleTy = type->getAs<TupleType>()) {
scratch.clear();
for (const auto &elt : tupleTy->getElements())
scratch.push_back(elt.getName());
return scratch;
}
// FIXME: Shouldn't get here.
scratch.clear();
scratch.push_back(Identifier());
return scratch;
}
/// Compute the type of an argument to a call (or call-like) AST
static void
computeSingleArgumentType(ASTContext &ctx, Expr *arg, bool implicit,
llvm::function_ref<Type(Expr *)> getType) {
// Propagate 'implicit' to the argument.
if (implicit) {
arg->setImplicit(true);
}
// Handle parenthesized expressions.
if (auto paren = dyn_cast<ParenExpr>(arg)) {
if (auto type = getType(paren->getSubExpr())) {
auto parenFlags = ParameterTypeFlags().withInOut(type->is<InOutType>());
arg->setType(ParenType::get(ctx, type->getInOutObjectType(), parenFlags));
}
return;
}
// Handle tuples.
auto tuple = dyn_cast<TupleExpr>(arg);
SmallVector<TupleTypeElt, 4> typeElements;
for (unsigned i = 0, n = tuple->getNumElements(); i != n; ++i) {
auto type = getType(tuple->getElement(i));
if (!type) return;
bool isInOut = tuple->getElement(i)->isSemanticallyInOutExpr();
typeElements.push_back(TupleTypeElt(type->getInOutObjectType(),
tuple->getElementName(i),
ParameterTypeFlags().withInOut(isInOut)));
}
arg->setType(TupleType::get(typeElements, ctx));
}
Expr *swift::packSingleArgument(ASTContext &ctx, SourceLoc lParenLoc,
ArrayRef<Expr *> args,
ArrayRef<Identifier> &argLabels,
ArrayRef<SourceLoc> &argLabelLocs,
SourceLoc rParenLoc,
ArrayRef<TrailingClosure> trailingClosures,
bool implicit,
SmallVectorImpl<Identifier> &argLabelsScratch,
SmallVectorImpl<SourceLoc> &argLabelLocsScratch,
llvm::function_ref<Type(Expr *)> getType) {
// Clear out our scratch space.
argLabelsScratch.clear();
argLabelLocsScratch.clear();
// Construct a TupleExpr or ParenExpr, as appropriate, for the argument.
if (trailingClosures.empty()) {
// Do we have a single, unlabeled argument?
if (args.size() == 1 && (argLabels.empty() || argLabels[0].empty())) {
auto arg = new (ctx) ParenExpr(lParenLoc, args[0], rParenLoc,
/*hasTrailingClosure=*/false);
computeSingleArgumentType(ctx, arg, implicit, getType);
argLabelsScratch.push_back(Identifier());
argLabels = argLabelsScratch;
argLabelLocs = { };
return arg;
}
// Make sure we have argument labels.
if (argLabels.empty()) {
argLabelsScratch.assign(args.size(), Identifier());
argLabels = argLabelsScratch;
}
// Construct the argument tuple.
if (argLabels.empty() && !args.empty()) {
argLabelsScratch.assign(args.size(), Identifier());
argLabels = argLabelsScratch;
}
auto arg = TupleExpr::create(ctx, lParenLoc, args, argLabels, argLabelLocs,
rParenLoc, /*HasTrailingClosure=*/false,
implicit);
computeSingleArgumentType(ctx, arg, implicit, getType);
return arg;
}
// If we have no other arguments, represent the a single trailing closure as a
// parenthesized expression.
if (args.empty() && trailingClosures.size() == 1 &&
trailingClosures.front().LabelLoc.isInvalid()) {
auto &trailingClosure = trailingClosures.front();
auto arg =
new (ctx) ParenExpr(lParenLoc, trailingClosure.ClosureExpr, rParenLoc,
/*hasTrailingClosure=*/true);
computeSingleArgumentType(ctx, arg, implicit, getType);
argLabelsScratch.push_back(Identifier());
argLabels = argLabelsScratch;
argLabelLocs = { };
return arg;
}
assert(argLabels.empty() || args.size() == argLabels.size());
unsigned numRegularArgs = args.size();
// Form a tuple, including the trailing closure.
SmallVector<Expr *, 4> argsScratch;
argsScratch.reserve(numRegularArgs + trailingClosures.size());
argsScratch.append(args.begin(), args.end());
for (const auto &closure : trailingClosures)
argsScratch.push_back(closure.ClosureExpr);
args = argsScratch;
{
if (argLabels.empty()) {
argLabelsScratch.resize(numRegularArgs);
} else {
argLabelsScratch.append(argLabels.begin(), argLabels.end());
}
for (const auto &closure : trailingClosures)
argLabelsScratch.push_back(closure.Label);
argLabels = argLabelsScratch;
}
{
if (argLabelLocs.empty()) {
argLabelLocsScratch.resize(numRegularArgs);
} else {
argLabelLocsScratch.append(argLabelLocs.begin(), argLabelLocs.end());
}
for (const auto &closure : trailingClosures)
argLabelLocsScratch.push_back(closure.LabelLoc);
argLabelLocs = argLabelLocsScratch;
}
Optional<unsigned> unlabeledTrailingClosureIndex;
if (!trailingClosures.empty() && trailingClosures[0].Label.empty())
unlabeledTrailingClosureIndex = args.size() - trailingClosures.size();
auto arg = TupleExpr::create(ctx, lParenLoc, rParenLoc, args, argLabels,
argLabelLocs,
unlabeledTrailingClosureIndex,
/*Implicit=*/false);
computeSingleArgumentType(ctx, arg, implicit, getType);
return arg;
}
Optional<unsigned>
Expr::getUnlabeledTrailingClosureIndexOfPackedArgument() const {
if (auto PE = dyn_cast<ParenExpr>(this))
return PE->getUnlabeledTrailingClosureIndexOfPackedArgument();
if (auto TE = dyn_cast<TupleExpr>(this))
return TE->getUnlabeledTrailingClosureIndexOfPackedArgument();
return None;
}
ObjectLiteralExpr::ObjectLiteralExpr(SourceLoc PoundLoc, LiteralKind LitKind,
Expr *Arg,
ArrayRef<Identifier> argLabels,
ArrayRef<SourceLoc> argLabelLocs,
bool hasTrailingClosure,
bool implicit)
: LiteralExpr(ExprKind::ObjectLiteral, implicit),
Arg(Arg), PoundLoc(PoundLoc) {
Bits.ObjectLiteralExpr.LitKind = static_cast<unsigned>(LitKind);
assert(getLiteralKind() == LitKind);
Bits.ObjectLiteralExpr.NumArgLabels = argLabels.size();
Bits.ObjectLiteralExpr.HasArgLabelLocs = !argLabelLocs.empty();
Bits.ObjectLiteralExpr.HasTrailingClosure = hasTrailingClosure;
initializeCallArguments(argLabels, argLabelLocs);
}
ObjectLiteralExpr *
ObjectLiteralExpr::create(ASTContext &ctx, SourceLoc poundLoc, LiteralKind kind,
Expr *arg, bool implicit,
llvm::function_ref<Type(Expr *)> getType) {
// Inspect the argument to dig out the argument labels, their location, and
// whether there is a trailing closure.
SmallVector<Identifier, 4> argLabelsScratch;
SmallVector<SourceLoc, 4> argLabelLocs;
bool hasTrailingClosure = false;
auto argLabels = getArgumentLabelsFromArgument(arg, argLabelsScratch,
&argLabelLocs,
&hasTrailingClosure,
getType);
size_t size = totalSizeToAlloc(argLabels, argLabelLocs);
void *memory = ctx.Allocate(size, alignof(ObjectLiteralExpr));
return new (memory) ObjectLiteralExpr(poundLoc, kind, arg, argLabels,
argLabelLocs, hasTrailingClosure,
implicit);
}
ObjectLiteralExpr *ObjectLiteralExpr::create(ASTContext &ctx,
SourceLoc poundLoc,
LiteralKind kind,
SourceLoc lParenLoc,
ArrayRef<Expr *> args,
ArrayRef<Identifier> argLabels,
ArrayRef<SourceLoc> argLabelLocs,
SourceLoc rParenLoc,
ArrayRef<TrailingClosure> trailingClosures,
bool implicit) {
SmallVector<Identifier, 4> argLabelsScratch;
SmallVector<SourceLoc, 4> argLabelLocsScratch;
Expr *arg = packSingleArgument(ctx, lParenLoc, args, argLabels, argLabelLocs,
rParenLoc,
trailingClosures, implicit, argLabelsScratch,
argLabelLocsScratch);
size_t size = totalSizeToAlloc(argLabels, argLabelLocs);
void *memory = ctx.Allocate(size, alignof(ObjectLiteralExpr));
return new (memory) ObjectLiteralExpr(poundLoc, kind, arg, argLabels,
argLabelLocs,
trailingClosures.size() == 1, implicit);
}
StringRef ObjectLiteralExpr::getLiteralKindRawName() const {
switch (getLiteralKind()) {
#define POUND_OBJECT_LITERAL(Name, Desc, Proto) case Name: return #Name;
#include "swift/Syntax/TokenKinds.def"
}
llvm_unreachable("unspecified literal");
}
StringRef ObjectLiteralExpr::getLiteralKindPlainName() const {
switch (getLiteralKind()) {
#define POUND_OBJECT_LITERAL(Name, Desc, Proto) case Name: return Desc;
#include "swift/Syntax/TokenKinds.def"
}
llvm_unreachable("unspecified literal");
}
ConstructorDecl *OtherConstructorDeclRefExpr::getDecl() const {
return cast_or_null<ConstructorDecl>(Ctor.getDecl());
}
MemberRefExpr::MemberRefExpr(Expr *base, SourceLoc dotLoc,
ConcreteDeclRef member, DeclNameLoc nameLoc,
bool Implicit, AccessSemantics semantics)
: LookupExpr(ExprKind::MemberRef, base, member, Implicit),
DotLoc(dotLoc), NameLoc(nameLoc) {
Bits.MemberRefExpr.Semantics = (unsigned) semantics;
}
Type OverloadSetRefExpr::getBaseType() const {
if (isa<OverloadedDeclRefExpr>(this))
return Type();
llvm_unreachable("Unhandled overloaded set reference expression");
}
bool OverloadSetRefExpr::hasBaseObject() const {
if (Type BaseTy = getBaseType())
return !BaseTy->is<AnyMetatypeType>();
return false;
}
InOutExpr::InOutExpr(SourceLoc operLoc, Expr *subExpr, Type baseType,
bool isImplicit)
: Expr(ExprKind::InOut, isImplicit,
baseType.isNull() ? baseType : InOutType::get(baseType)),
SubExpr(subExpr), OperLoc(operLoc) {}
SequenceExpr *SequenceExpr::create(ASTContext &ctx, ArrayRef<Expr*> elements) {
assert(elements.size() & 1 && "even number of elements in sequence");
size_t bytes = totalSizeToAlloc<Expr *>(elements.size());
void *Buffer = ctx.Allocate(bytes, alignof(SequenceExpr));
return ::new(Buffer) SequenceExpr(elements);
}
ErasureExpr *ErasureExpr::create(ASTContext &ctx, Expr *subExpr, Type type,
ArrayRef<ProtocolConformanceRef> conformances){
auto size = totalSizeToAlloc<ProtocolConformanceRef>(conformances.size());
auto mem = ctx.Allocate(size, alignof(ErasureExpr));
return ::new(mem) ErasureExpr(subExpr, type, conformances);
}
UnresolvedSpecializeExpr *UnresolvedSpecializeExpr::create(ASTContext &ctx,
Expr *SubExpr, SourceLoc LAngleLoc,
ArrayRef<TypeRepr *> UnresolvedParams,
SourceLoc RAngleLoc) {
auto size = totalSizeToAlloc<TypeRepr *>(UnresolvedParams.size());
auto mem = ctx.Allocate(size, alignof(UnresolvedSpecializeExpr));
return ::new(mem) UnresolvedSpecializeExpr(SubExpr, LAngleLoc,
UnresolvedParams, RAngleLoc);
}
bool CaptureListEntry::isSimpleSelfCapture() const {
if (Init->getPatternList().size() != 1)
return false;
if (auto *DRE = dyn_cast<DeclRefExpr>(Init->getInit(0)))
if (auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
return (VD->isSelfParameter() || VD->isSelfParamCapture())
&& VD->getName() == Var->getName();
}
return false;
}
CaptureListExpr *CaptureListExpr::create(ASTContext &ctx,
ArrayRef<CaptureListEntry> captureList,
ClosureExpr *closureBody) {
auto size = totalSizeToAlloc<CaptureListEntry>(captureList.size());
auto mem = ctx.Allocate(size, alignof(CaptureListExpr));
return ::new(mem) CaptureListExpr(captureList, closureBody);
}
DestructureTupleExpr *
DestructureTupleExpr::create(ASTContext &ctx,
ArrayRef<OpaqueValueExpr *> destructuredElements,
Expr *srcExpr, Expr *dstExpr, Type ty) {
auto size = totalSizeToAlloc<OpaqueValueExpr *>(destructuredElements.size());
auto mem = ctx.Allocate(size, alignof(DestructureTupleExpr));
return ::new(mem) DestructureTupleExpr(destructuredElements,
srcExpr, dstExpr, ty);
}
SourceRange TupleExpr::getSourceRange() const {
SourceLoc start = SourceLoc();
SourceLoc end = SourceLoc();
if (LParenLoc.isValid()) {
start = LParenLoc;
} else if (getNumElements() == 0) {
return { SourceLoc(), SourceLoc() };
} else {
// Scan forward for the first valid source loc.
for (Expr *expr : getElements()) {
start = expr->getStartLoc();
if (start.isValid()) {
break;
}
}
}
if (hasAnyTrailingClosures() || RParenLoc.isInvalid()) {
if (getNumElements() == 0) {
return { SourceLoc(), SourceLoc() };
} else {
// Scan backwards for a valid source loc.
bool hasSingleTrailingClosure = hasTrailingClosure();
for (Expr *expr : llvm::reverse(getElements())) {
// Default arguments are located at the start of their parent tuple, so
// skip over them.
if (isa<DefaultArgumentExpr>(expr))
continue;
SourceLoc newEnd = expr->getEndLoc();
if (newEnd.isInvalid())
continue;
// There is a quirk with the backward scan logic for trailing
// closures that can cause arguments to be flipped. If there is a
// single trailing closure, only stop when the "end" point we hit comes
// after the close parenthesis (if there is one).
if (end.isInvalid() ||
end.getOpaquePointerValue() < newEnd.getOpaquePointerValue()) {
end = newEnd;
}
if (!hasSingleTrailingClosure || RParenLoc.isInvalid() ||
RParenLoc.getOpaquePointerValue() < end.getOpaquePointerValue())
break;
}
}
} else {
end = RParenLoc;
}
if (start.isValid() && end.isValid()) {
return { start, end };
} else {
return { SourceLoc(), SourceLoc() };
}
}
TupleExpr::TupleExpr(SourceLoc LParenLoc, SourceLoc RParenLoc,
ArrayRef<Expr *> SubExprs,
ArrayRef<Identifier> ElementNames,
ArrayRef<SourceLoc> ElementNameLocs,
Optional<unsigned> FirstTrailingArgumentAt,
bool Implicit, Type Ty)
: Expr(ExprKind::Tuple, Implicit, Ty),
LParenLoc(LParenLoc), RParenLoc(RParenLoc),
FirstTrailingArgumentAt(FirstTrailingArgumentAt) {
Bits.TupleExpr.HasElementNames = !ElementNames.empty();
Bits.TupleExpr.HasElementNameLocations = !ElementNameLocs.empty();
Bits.TupleExpr.NumElements = SubExprs.size();
assert(LParenLoc.isValid() == RParenLoc.isValid() &&
"Mismatched parenthesis location information validity");
assert(ElementNames.empty() || ElementNames.size() == SubExprs.size());
assert(ElementNameLocs.empty() ||
ElementNames.size() == ElementNameLocs.size());
// Copy elements.
std::uninitialized_copy(SubExprs.begin(), SubExprs.end(),
getTrailingObjects<Expr *>());
// Copy element names, if provided.
if (hasElementNames()) {
std::uninitialized_copy(ElementNames.begin(), ElementNames.end(),
getTrailingObjects<Identifier>());
}
// Copy element name locations, if provided.
if (hasElementNameLocs()) {
std::uninitialized_copy(ElementNameLocs.begin(), ElementNameLocs.end(),
getTrailingObjects<SourceLoc>());
}
}
TupleExpr *TupleExpr::create(ASTContext &ctx,
SourceLoc LParenLoc,
ArrayRef<Expr *> SubExprs,
ArrayRef<Identifier> ElementNames,
ArrayRef<SourceLoc> ElementNameLocs,
SourceLoc RParenLoc,
bool HasTrailingClosure,
bool Implicit, Type Ty) {
Optional<unsigned> FirstTrailingArgumentAt =
HasTrailingClosure ? SubExprs.size() - 1 : Optional<unsigned>();
return create(ctx, LParenLoc, RParenLoc, SubExprs, ElementNames,
ElementNameLocs, FirstTrailingArgumentAt, Implicit, Ty);
}
TupleExpr *TupleExpr::create(ASTContext &ctx,
SourceLoc LParenLoc,
SourceLoc RParenLoc,
ArrayRef<Expr *> SubExprs,
ArrayRef<Identifier> ElementNames,
ArrayRef<SourceLoc> ElementNameLocs,
Optional<unsigned> FirstTrailingArgumentAt,
bool Implicit, Type Ty) {
assert(!Ty || isa<TupleType>(Ty.getPointer()));
auto hasNonEmptyIdentifier = [](ArrayRef<Identifier> Ids) -> bool {
for (auto ident : Ids) {
if (!ident.empty())
return true;
}
return false;
};
assert((Implicit || ElementNames.size() == ElementNameLocs.size() ||
(!hasNonEmptyIdentifier(ElementNames) && ElementNameLocs.empty())) &&
"trying to create non-implicit tuple-expr without name locations");
(void)hasNonEmptyIdentifier;
size_t size =
totalSizeToAlloc<Expr *, Identifier, SourceLoc>(SubExprs.size(),
ElementNames.size(),
ElementNameLocs.size());
void *mem = ctx.Allocate(size, alignof(TupleExpr));
return new (mem) TupleExpr(LParenLoc, RParenLoc, SubExprs, ElementNames,
ElementNameLocs,
FirstTrailingArgumentAt, Implicit, Ty);
}
TupleExpr *TupleExpr::createEmpty(ASTContext &ctx, SourceLoc LParenLoc,
SourceLoc RParenLoc, bool Implicit) {
return create(ctx, LParenLoc, RParenLoc, {}, {}, {},
/*FirstTrailingArgumentAt=*/None, Implicit,
TupleType::getEmpty(ctx));
}
TupleExpr *TupleExpr::createImplicit(ASTContext &ctx, ArrayRef<Expr *> SubExprs,
ArrayRef<Identifier> ElementNames) {
return create(ctx, SourceLoc(), SourceLoc(), SubExprs, ElementNames, {},
/*FirstTrailingArgumentAt=*/None, /*Implicit=*/true, Type());
}
ArrayExpr *ArrayExpr::create(ASTContext &C, SourceLoc LBracketLoc,
ArrayRef<Expr*> Elements,
ArrayRef<SourceLoc> CommaLocs,
SourceLoc RBracketLoc, Type Ty) {
auto Size = totalSizeToAlloc<Expr *, SourceLoc>(Elements.size(),
CommaLocs.size());
auto Mem = C.Allocate(Size, alignof(ArrayExpr));
return new (Mem) ArrayExpr(LBracketLoc, Elements, CommaLocs, RBracketLoc, Ty);
}
Type ArrayExpr::getElementType() {
auto init = getInitializer();
if (!init)
return Type();
auto *decl = cast<ConstructorDecl>(init.getDecl());
return decl->getMethodInterfaceType()
->getAs<AnyFunctionType>()
->getParams()[0]
.getPlainType()
.subst(init.getSubstitutions());
}
Type DictionaryExpr::getElementType() {
auto init = getInitializer();
if (!init)
return Type();
auto *decl = cast<ConstructorDecl>(init.getDecl());
return decl->getMethodInterfaceType()
->getAs<AnyFunctionType>()
->getParams()[0]
.getPlainType()
.subst(init.getSubstitutions());
}
DictionaryExpr *DictionaryExpr::create(ASTContext &C, SourceLoc LBracketLoc,
ArrayRef<Expr*> Elements,
ArrayRef<SourceLoc> CommaLocs,
SourceLoc RBracketLoc,
Type Ty) {
auto Size = totalSizeToAlloc<Expr *, SourceLoc>(Elements.size(),
CommaLocs.size());
auto Mem = C.Allocate(Size, alignof(DictionaryExpr));
return new (Mem) DictionaryExpr(LBracketLoc, Elements, CommaLocs, RBracketLoc,
Ty);
}
static ValueDecl *getCalledValue(Expr *E) {
if (auto *DRE = dyn_cast<DeclRefExpr>(E))
return DRE->getDecl();
if (auto *OCRE = dyn_cast<OtherConstructorDeclRefExpr>(E))
return OCRE->getDecl();
// Look through SelfApplyExpr.
if (auto *SAE = dyn_cast<SelfApplyExpr>(E))
return SAE->getCalledValue();
Expr *E2 = E->getValueProvidingExpr();
if (E != E2)
return getCalledValue(E2);
return nullptr;
}
PropertyWrapperValuePlaceholderExpr *
PropertyWrapperValuePlaceholderExpr::create(ASTContext &ctx, SourceRange range,
Type ty, Expr *wrappedValue,
bool isAutoClosure) {
auto *placeholder =
new (ctx) OpaqueValueExpr(range, ty, /*isPlaceholder=*/true);
return new (ctx) PropertyWrapperValuePlaceholderExpr(
range, ty, placeholder, wrappedValue, isAutoClosure);
}
const ParamDecl *DefaultArgumentExpr::getParamDecl() const {
return getParameterAt(DefaultArgsOwner.getDecl(), ParamIndex);
}
bool DefaultArgumentExpr::isCallerSide() const {
return getParamDecl()->hasCallerSideDefaultExpr();
}
Expr *DefaultArgumentExpr::getCallerSideDefaultExpr() const {
assert(isCallerSide());
auto &ctx = DefaultArgsOwner.getDecl()->getASTContext();
auto *mutableThis = const_cast<DefaultArgumentExpr *>(this);
return evaluateOrDefault(ctx.evaluator,
CallerSideDefaultArgExprRequest{mutableThis},
new (ctx) ErrorExpr(getSourceRange(), getType()));
}
ValueDecl *ApplyExpr::getCalledValue() const {
return ::getCalledValue(Fn);
}
SubscriptExpr::SubscriptExpr(Expr *base, Expr *index,
ArrayRef<Identifier> argLabels,
ArrayRef<SourceLoc> argLabelLocs,
bool hasTrailingClosure,
ConcreteDeclRef decl,
bool implicit, AccessSemantics semantics)
: LookupExpr(ExprKind::Subscript, base, decl, implicit),
Index(index) {
Bits.SubscriptExpr.Semantics = (unsigned) semantics;
Bits.SubscriptExpr.NumArgLabels = argLabels.size();
Bits.SubscriptExpr.HasArgLabelLocs = !argLabelLocs.empty();
Bits.SubscriptExpr.HasTrailingClosure = hasTrailingClosure;
initializeCallArguments(argLabels, argLabelLocs);
}
SubscriptExpr *SubscriptExpr::create(ASTContext &ctx, Expr *base, Expr *index,
ConcreteDeclRef decl, bool implicit,
AccessSemantics semantics,
llvm::function_ref<Type(Expr *)> getType) {
// Inspect the argument to dig out the argument labels, their location, and
// whether there is a trailing closure.
SmallVector<Identifier, 4> argLabelsScratch;
SmallVector<SourceLoc, 4> argLabelLocs;
bool hasTrailingClosure = false;
auto argLabels = getArgumentLabelsFromArgument(index, argLabelsScratch,
&argLabelLocs,
&hasTrailingClosure,
getType);
size_t size = totalSizeToAlloc(argLabels, argLabelLocs);
void *memory = ctx.Allocate(size, alignof(SubscriptExpr));
return new (memory) SubscriptExpr(base, index, argLabels, argLabelLocs,
hasTrailingClosure, decl, implicit,
semantics);
}
SubscriptExpr *SubscriptExpr::create(ASTContext &ctx, Expr *base,
SourceLoc lSquareLoc,
ArrayRef<Expr *> indexArgs,
ArrayRef<Identifier> indexArgLabels,
ArrayRef<SourceLoc> indexArgLabelLocs,
SourceLoc rSquareLoc,
ArrayRef<TrailingClosure> trailingClosures,
ConcreteDeclRef decl,
bool implicit,
AccessSemantics semantics) {
SmallVector<Identifier, 4> indexArgLabelsScratch;
SmallVector<SourceLoc, 4> indexArgLabelLocsScratch;
Expr *index = packSingleArgument(ctx, lSquareLoc, indexArgs, indexArgLabels,
indexArgLabelLocs, rSquareLoc,
trailingClosures, implicit,
indexArgLabelsScratch,
indexArgLabelLocsScratch);
size_t size = totalSizeToAlloc(indexArgLabels, indexArgLabelLocs);
void *memory = ctx.Allocate(size, alignof(SubscriptExpr));
return new (memory) SubscriptExpr(base, index, indexArgLabels,
indexArgLabelLocs,
trailingClosures.size() == 1,
decl, implicit, semantics);
}
DynamicSubscriptExpr::DynamicSubscriptExpr(Expr *base, Expr *index,
ArrayRef<Identifier> argLabels,
ArrayRef<SourceLoc> argLabelLocs,
bool hasTrailingClosure,
ConcreteDeclRef member,
bool implicit)
: DynamicLookupExpr(ExprKind::DynamicSubscript, member, base),
Index(index) {
Bits.DynamicSubscriptExpr.NumArgLabels = argLabels.size();
Bits.DynamicSubscriptExpr.HasArgLabelLocs = !argLabelLocs.empty();
Bits.DynamicSubscriptExpr.HasTrailingClosure = hasTrailingClosure;
initializeCallArguments(argLabels, argLabelLocs);
if (implicit) setImplicit(implicit);
}
DynamicSubscriptExpr *
DynamicSubscriptExpr::create(ASTContext &ctx, Expr *base, Expr *index,
ConcreteDeclRef decl, bool implicit,
llvm::function_ref<Type(Expr *)> getType) {
// Inspect the argument to dig out the argument labels, their location, and
// whether there is a trailing closure.
SmallVector<Identifier, 4> argLabelsScratch;
SmallVector<SourceLoc, 4> argLabelLocs;
bool hasTrailingClosure = false;
auto argLabels = getArgumentLabelsFromArgument(index, argLabelsScratch,
&argLabelLocs,
&hasTrailingClosure,
getType);
size_t size = totalSizeToAlloc(argLabels, argLabelLocs);
void *memory = ctx.Allocate(size, alignof(DynamicSubscriptExpr));
return new (memory) DynamicSubscriptExpr(base, index, argLabels, argLabelLocs,
hasTrailingClosure, decl, implicit);
}
UnresolvedMemberExpr::UnresolvedMemberExpr(SourceLoc dotLoc,
DeclNameLoc nameLoc,
DeclNameRef name, Expr *argument,
ArrayRef<Identifier> argLabels,
ArrayRef<SourceLoc> argLabelLocs,
bool hasTrailingClosure,
bool implicit)
: Expr(ExprKind::UnresolvedMember, implicit),
DotLoc(dotLoc), NameLoc(nameLoc), Name(name), Argument(argument) {
Bits.UnresolvedMemberExpr.HasArguments = (argument != nullptr);
Bits.UnresolvedMemberExpr.NumArgLabels = argLabels.size();
Bits.UnresolvedMemberExpr.HasArgLabelLocs = !argLabelLocs.empty();
Bits.UnresolvedMemberExpr.HasTrailingClosure = hasTrailingClosure;
initializeCallArguments(argLabels, argLabelLocs);
}
UnresolvedMemberExpr *UnresolvedMemberExpr::create(ASTContext &ctx,
SourceLoc dotLoc,
DeclNameLoc nameLoc,
DeclNameRef name,
bool implicit) {
size_t size = totalSizeToAlloc({ }, { });
void *memory = ctx.Allocate(size, alignof(UnresolvedMemberExpr));
return new (memory) UnresolvedMemberExpr(dotLoc, nameLoc, name, nullptr,
{ }, { },
/*hasTrailingClosure=*/false,
implicit);
}
UnresolvedMemberExpr *
UnresolvedMemberExpr::create(ASTContext &ctx, SourceLoc dotLoc,
DeclNameLoc nameLoc, DeclNameRef name,
SourceLoc lParenLoc,
ArrayRef<Expr *> args,
ArrayRef<Identifier> argLabels,
ArrayRef<SourceLoc> argLabelLocs,
SourceLoc rParenLoc,
ArrayRef<TrailingClosure> trailingClosures,
bool implicit) {
SmallVector<Identifier, 4> argLabelsScratch;
SmallVector<SourceLoc, 4> argLabelLocsScratch;
Expr *arg = packSingleArgument(ctx, lParenLoc, args, argLabels, argLabelLocs,
rParenLoc, trailingClosures, implicit,
argLabelsScratch, argLabelLocsScratch);
size_t size = totalSizeToAlloc(argLabels, argLabelLocs);
void *memory = ctx.Allocate(size, alignof(UnresolvedMemberExpr));
return new (memory) UnresolvedMemberExpr(dotLoc, nameLoc, name, arg,
argLabels, argLabelLocs,
trailingClosures.size() == 1,
implicit);
}
ArrayRef<Identifier> ApplyExpr::getArgumentLabels(
SmallVectorImpl<Identifier> &scratch) const {
// Unary operators and 'self' applications have a single, unlabeled argument.
if (isa<PrefixUnaryExpr>(this) || isa<PostfixUnaryExpr>(this) ||
isa<SelfApplyExpr>(this)) {
scratch.clear();
scratch.push_back(Identifier());
return scratch;
}
// Binary operators have two unlabeled arguments.
if (isa<BinaryExpr>(this)) {
scratch.clear();
scratch.reserve(2);
scratch.push_back(Identifier());
scratch.push_back(Identifier());
return scratch;
}
// For calls, get the argument labels directly.
auto call = cast<CallExpr>(this);
return call->getArgumentLabels();
}
bool ApplyExpr::hasTrailingClosure() const {
if (auto call = dyn_cast<CallExpr>(this))
return call->hasTrailingClosure();
return false;
}
Optional<unsigned> ApplyExpr::getUnlabeledTrailingClosureIndex() const {
if (auto call = dyn_cast<CallExpr>(this))
return call->getUnlabeledTrailingClosureIndex();
return None;
}
CallExpr::CallExpr(Expr *fn, Expr *arg, bool Implicit,
ArrayRef<Identifier> argLabels,
ArrayRef<SourceLoc> argLabelLocs,
bool hasTrailingClosure,
Type ty)
: ApplyExpr(ExprKind::Call, fn, arg, Implicit, ty)
{
Bits.CallExpr.NumArgLabels = argLabels.size();
Bits.CallExpr.HasArgLabelLocs = !argLabelLocs.empty();
Bits.CallExpr.HasTrailingClosure = hasTrailingClosure;
initializeCallArguments(argLabels, argLabelLocs);
}
CallExpr *CallExpr::create(ASTContext &ctx, Expr *fn, Expr *arg,
ArrayRef<Identifier> argLabels,
ArrayRef<SourceLoc> argLabelLocs,
bool hasTrailingClosure,
bool implicit, Type type,
llvm::function_ref<Type(Expr *)> getType) {
SmallVector<Identifier, 4> argLabelsScratch;
SmallVector<SourceLoc, 4> argLabelLocsScratch;
if (argLabels.empty()) {
// Inspect the argument to dig out the argument labels, their location, and
// whether there is a trailing closure.
argLabels = getArgumentLabelsFromArgument(arg, argLabelsScratch,
&argLabelLocsScratch,
&hasTrailingClosure,
getType);
argLabelLocs = argLabelLocsScratch;
}
size_t size = totalSizeToAlloc(argLabels, argLabelLocs);
void *memory = ctx.Allocate(size, alignof(CallExpr));
return new (memory) CallExpr(fn, arg, implicit, argLabels, argLabelLocs,
hasTrailingClosure, type);
}
CallExpr *CallExpr::create(ASTContext &ctx, Expr *fn, SourceLoc lParenLoc,
ArrayRef<Expr *> args,
ArrayRef<Identifier> argLabels,
ArrayRef<SourceLoc> argLabelLocs,
SourceLoc rParenLoc,
ArrayRef<TrailingClosure> trailingClosures,
bool implicit,
llvm::function_ref<Type(Expr *)> getType) {
SmallVector<Identifier, 4> argLabelsScratch;
SmallVector<SourceLoc, 4> argLabelLocsScratch;
Expr *arg = packSingleArgument(ctx, lParenLoc, args, argLabels, argLabelLocs,
rParenLoc, trailingClosures, implicit,
argLabelsScratch, argLabelLocsScratch,
getType);
size_t size = totalSizeToAlloc(argLabels, argLabelLocs);
void *memory = ctx.Allocate(size, alignof(CallExpr));
return new (memory) CallExpr(fn, arg, implicit, argLabels, argLabelLocs,
trailingClosures.size() == 1, Type());
}
Expr *CallExpr::getDirectCallee() const {
auto fn = getFn();
while (true) {
fn = fn->getSemanticsProvidingExpr();
if (auto force = dyn_cast<ForceValueExpr>(fn)) {
fn = force->getSubExpr();
continue;
}
if (auto bind = dyn_cast<BindOptionalExpr>(fn)) {
fn = bind->getSubExpr();
continue;
}
if (auto ctorCall = dyn_cast<ConstructorRefCallExpr>(fn)) {
fn = ctorCall->getFn();
continue;
}
return fn;
}
}
void ExplicitCastExpr::setCastType(Type type) {
CastTy->setType(MetatypeType::get(type));
}
ForcedCheckedCastExpr *ForcedCheckedCastExpr::create(ASTContext &ctx,
SourceLoc asLoc,
SourceLoc exclaimLoc,
TypeRepr *tyRepr) {
return new (ctx) ForcedCheckedCastExpr(nullptr, asLoc, exclaimLoc,
new (ctx) TypeExpr(tyRepr));
}
ForcedCheckedCastExpr *
ForcedCheckedCastExpr::createImplicit(ASTContext &ctx, Expr *sub, Type castTy) {
auto *const expr = new (ctx) ForcedCheckedCastExpr(
sub, SourceLoc(), SourceLoc(), TypeExpr::createImplicit(castTy, ctx));
expr->setType(castTy);
expr->setImplicit();
return expr;
}
ConditionalCheckedCastExpr *
ConditionalCheckedCastExpr::create(ASTContext &ctx, SourceLoc asLoc,
SourceLoc questionLoc, TypeRepr *tyRepr) {
return new (ctx) ConditionalCheckedCastExpr(nullptr, asLoc, questionLoc,
new (ctx) TypeExpr(tyRepr));
}
ConditionalCheckedCastExpr *
ConditionalCheckedCastExpr::createImplicit(ASTContext &ctx, Expr *sub,
Type castTy) {
auto *const expr = new (ctx) ConditionalCheckedCastExpr(
sub, SourceLoc(), SourceLoc(), TypeExpr::createImplicit(castTy, ctx));
expr->setType(OptionalType::get(castTy));
expr->setImplicit();
return expr;
}
IsExpr *IsExpr::create(ASTContext &ctx, SourceLoc isLoc, TypeRepr *tyRepr) {
return new (ctx) IsExpr(nullptr, isLoc, new (ctx) TypeExpr(tyRepr));
}
CoerceExpr *CoerceExpr::create(ASTContext &ctx, SourceLoc asLoc,
TypeRepr *tyRepr) {
return new (ctx) CoerceExpr(nullptr, asLoc, new (ctx) TypeExpr(tyRepr));
}
CoerceExpr *CoerceExpr::createImplicit(ASTContext &ctx, Expr *sub,
Type castTy) {
auto *const expr = new (ctx)
CoerceExpr(sub, SourceLoc(), TypeExpr::createImplicit(castTy, ctx));
expr->setType(castTy);
expr->setImplicit();
return expr;
}
CoerceExpr *CoerceExpr::forLiteralInit(ASTContext &ctx, Expr *literal,
SourceRange range,
TypeRepr *literalTyRepr) {
auto *const expr =
new (ctx) CoerceExpr(range, literal, new (ctx) TypeExpr(literalTyRepr));
expr->setImplicit();
return expr;
}
RebindSelfInConstructorExpr::RebindSelfInConstructorExpr(Expr *SubExpr,
VarDecl *Self)
: Expr(ExprKind::RebindSelfInConstructor, /*Implicit=*/true,
TupleType::getEmpty(Self->getASTContext())),
SubExpr(SubExpr), Self(Self)
{}
OtherConstructorDeclRefExpr *
RebindSelfInConstructorExpr::getCalledConstructor(bool &isChainToSuper) const {
// Dig out the OtherConstructorDeclRefExpr. Note that this is the reverse
// of what we do in pre-checking.
Expr *candidate = getSubExpr();
while (true) {
// Look through identity expressions.
if (auto identity = dyn_cast<IdentityExpr>(candidate)) {
candidate = identity->getSubExpr();
continue;
}
// Look through force-value expressions.
if (auto force = dyn_cast<ForceValueExpr>(candidate)) {
candidate = force->getSubExpr();
continue;
}
// Look through all try expressions.
if (auto tryExpr = dyn_cast<AnyTryExpr>(candidate)) {
candidate = tryExpr->getSubExpr();
continue;
}
// Look through covariant return expressions.
if (auto covariantExpr
= dyn_cast<CovariantReturnConversionExpr>(candidate)) {
candidate = covariantExpr->getSubExpr();
continue;
}
// Look through inject into optional expressions
if (auto injectIntoOptionalExpr
= dyn_cast<InjectIntoOptionalExpr>(candidate)) {
candidate = injectIntoOptionalExpr->getSubExpr();
continue;
}
break;
}
// We hit an application, find the constructor reference.
OtherConstructorDeclRefExpr *otherCtorRef;
const ApplyExpr *apply;
do {
apply = cast<ApplyExpr>(candidate);
candidate = apply->getFn();
auto candidateUnwrapped = candidate->getSemanticsProvidingExpr();
otherCtorRef = dyn_cast<OtherConstructorDeclRefExpr>(candidateUnwrapped);
} while (!otherCtorRef);
isChainToSuper = apply->getArg()->isSuperExpr();
return otherCtorRef;
}
void AbstractClosureExpr::setParameterList(ParameterList *P) {
parameterList = P;
// Change the DeclContext of any parameters to be this closure.
if (P)
P->setDeclContextOfParamDecls(this);
}
Type AbstractClosureExpr::getResultType(
llvm::function_ref<Type(Expr *)> getType) const {
auto *E = const_cast<AbstractClosureExpr *>(this);
if (getType(E)->hasError())
return getType(E);
return getType(E)->castTo<FunctionType>()->getResult();
}
bool AbstractClosureExpr::isBodyThrowing() const {
if (getType()->hasError())
return false;
return getType()->castTo<FunctionType>()->getExtInfo().isThrowing();
}
bool AbstractClosureExpr::isBodyAsync() const {
if (getType()->hasError())
return false;
return getType()->castTo<FunctionType>()->getExtInfo().isAsync();
}
bool AbstractClosureExpr::hasSingleExpressionBody() const {
if (auto closure = dyn_cast<ClosureExpr>(this))
return closure->hasSingleExpressionBody();
return true;
}
Expr *AbstractClosureExpr::getSingleExpressionBody() const {
if (auto closure = dyn_cast<ClosureExpr>(this))
return closure->getSingleExpressionBody();
else if (auto autoclosure = dyn_cast<AutoClosureExpr>(this))
return autoclosure->getSingleExpressionBody();
return nullptr;
}
#define FORWARD_SOURCE_LOCS_TO(CLASS, NODE) \
SourceRange CLASS::getSourceRange() const { \
return (NODE)->getSourceRange(); \
} \
SourceLoc CLASS::getStartLoc() const { \
return (NODE)->getStartLoc(); \
} \
SourceLoc CLASS::getEndLoc() const { \
return (NODE)->getEndLoc(); \
} \
SourceLoc CLASS::getLoc() const { \
return (NODE)->getStartLoc(); \
}
FORWARD_SOURCE_LOCS_TO(ClosureExpr, Body.getPointer())
Expr *ClosureExpr::getSingleExpressionBody() const {
assert(hasSingleExpressionBody() && "Not a single-expression body");
auto body = getBody()->getFirstElement();
if (auto stmt = body.dyn_cast<Stmt *>()) {
if (auto braceStmt = dyn_cast<BraceStmt>(stmt))
return braceStmt->getFirstElement().get<Expr *>();
return cast<ReturnStmt>(stmt)->getResult();
}
return body.get<Expr *>();
}
bool ClosureExpr::hasEmptyBody() const {
return getBody()->empty();
}
bool ClosureExpr::capturesSelfEnablingImplictSelf() const {
if (auto *VD = getCapturedSelfDecl()) {
if (!VD->isSelfParamCapture())
return false;
if (auto *attr = VD->getAttrs().getAttribute<ReferenceOwnershipAttr>())
return attr->get() != ReferenceOwnership::Weak;
return true;
}
return false;
}
void ClosureExpr::setExplicitResultType(Type ty) {
assert(ty && !ty->hasTypeVariable());
ExplicitResultTypeAndBodyState.getPointer()
->setType(MetatypeType::get(ty));
}
FORWARD_SOURCE_LOCS_TO(AutoClosureExpr, Body)
void AutoClosureExpr::setBody(Expr *E) {
auto &Context = getASTContext();
auto *RS = new (Context) ReturnStmt(SourceLoc(), E);
Body = BraceStmt::create(Context, E->getStartLoc(), { RS }, E->getEndLoc());
}
Expr *AutoClosureExpr::getSingleExpressionBody() const {
return cast<ReturnStmt>(Body->getFirstElement().get<Stmt *>())->getResult();
}
Expr *AutoClosureExpr::getUnwrappedCurryThunkExpr() const {
switch (getThunkKind()) {
case AutoClosureExpr::Kind::None:
break;
case AutoClosureExpr::Kind::SingleCurryThunk: {
auto *body = getSingleExpressionBody();
body = body->getSemanticsProvidingExpr();
if (auto *openExistential = dyn_cast<OpenExistentialExpr>(body)) {
body = openExistential->getSubExpr()->getSemanticsProvidingExpr();
}
if (auto *outerCall = dyn_cast<ApplyExpr>(body)) {
return outerCall->getFn();
}
assert(false && "Malformed curry thunk?");
break;
}
case AutoClosureExpr::Kind::DoubleCurryThunk: {
auto *body = getSingleExpressionBody();
if (auto *innerClosure = dyn_cast<AutoClosureExpr>(body)) {
assert(innerClosure->getThunkKind() ==
AutoClosureExpr::Kind::SingleCurryThunk);
auto *innerBody = innerClosure->getSingleExpressionBody();
innerBody = innerBody->getSemanticsProvidingExpr();
if (auto *openExistential = dyn_cast<OpenExistentialExpr>(innerBody)) {
innerBody = openExistential->getSubExpr()->getSemanticsProvidingExpr();
if (auto *ICE = dyn_cast<ImplicitConversionExpr>(innerBody))
innerBody = ICE->getSyntacticSubExpr();
}
if (auto *outerCall = dyn_cast<ApplyExpr>(innerBody)) {
if (auto *innerCall = dyn_cast<ApplyExpr>(outerCall->getFn())) {
if (auto *declRef = dyn_cast<DeclRefExpr>(innerCall->getFn())) {
return declRef;
}
}
}
}
assert(false && "Malformed curry thunk?");
break;
}
}
return nullptr;
}
FORWARD_SOURCE_LOCS_TO(UnresolvedPatternExpr, subPattern)
TypeExpr::TypeExpr(TypeRepr *Repr)
: Expr(ExprKind::Type, /*implicit*/false), Repr(Repr) {}
TypeExpr *TypeExpr::createImplicit(Type Ty, ASTContext &C) {
assert(Ty);
auto *result = new (C) TypeExpr(nullptr);
result->setType(MetatypeType::get(Ty, Ty->getASTContext()));
result->setImplicit();
return result;
}
// The type of a TypeExpr is always a metatype type. Return the instance
// type or null if not set yet.
Type TypeExpr::getInstanceType() const {
auto ty = getType();
if (!ty)
return Type();
if (auto metaType = ty->getAs<MetatypeType>())
return metaType->getInstanceType();
return ErrorType::get(ty->getASTContext());
}
TypeExpr *TypeExpr::createForDecl(DeclNameLoc Loc, TypeDecl *Decl,
DeclContext *DC) {
ASTContext &C = Decl->getASTContext();
assert(Loc.isValid());
auto *Repr = new (C) SimpleIdentTypeRepr(Loc, Decl->createNameRef());
Repr->setValue(Decl, DC);
return new (C) TypeExpr(Repr);
}
TypeExpr *TypeExpr::createImplicitForDecl(DeclNameLoc Loc, TypeDecl *Decl,
DeclContext *DC, Type ty) {
ASTContext &C = Decl->getASTContext();
auto *Repr = new (C) SimpleIdentTypeRepr(Loc, Decl->createNameRef());
Repr->setValue(Decl, DC);
auto result = new (C) TypeExpr(Repr);
assert(ty && !ty->hasTypeParameter());
result->setType(ty);
result->setImplicit();
return result;
}
TypeExpr *TypeExpr::createForMemberDecl(DeclNameLoc ParentNameLoc,
TypeDecl *Parent,
DeclNameLoc NameLoc,
TypeDecl *Decl) {
ASTContext &C = Decl->getASTContext();
assert(ParentNameLoc.isValid());
assert(NameLoc.isValid());
// Create a new list of components.
SmallVector<ComponentIdentTypeRepr *, 2> Components;
// The first component is the parent type.
auto *ParentComp = new (C) SimpleIdentTypeRepr(ParentNameLoc,
Parent->createNameRef());
ParentComp->setValue(Parent, nullptr);
Components.push_back(ParentComp);
// The second component is the member we just found.
auto *NewComp = new (C) SimpleIdentTypeRepr(NameLoc,
Decl->createNameRef());
NewComp->setValue(Decl, nullptr);
Components.push_back(NewComp);
auto *NewTypeRepr = IdentTypeRepr::create(C, Components);
return new (C) TypeExpr(NewTypeRepr);
}
TypeExpr *TypeExpr::createForMemberDecl(IdentTypeRepr *ParentTR,
DeclNameLoc NameLoc,
TypeDecl *Decl) {
ASTContext &C = Decl->getASTContext();
// Create a new list of components.
SmallVector<ComponentIdentTypeRepr *, 2> Components;
for (auto *Component : ParentTR->getComponentRange())
Components.push_back(Component);
assert(!Components.empty());
// Add a new component for the member we just found.
auto *NewComp = new (C) SimpleIdentTypeRepr(NameLoc, Decl->createNameRef());
NewComp->setValue(Decl, nullptr);
Components.push_back(NewComp);
auto *NewTypeRepr = IdentTypeRepr::create(C, Components);
return new (C) TypeExpr(NewTypeRepr);
}
TypeExpr *TypeExpr::createForSpecializedDecl(IdentTypeRepr *ParentTR,
ArrayRef<TypeRepr*> Args,
SourceRange AngleLocs,
ASTContext &C) {
// Create a new list of components.
SmallVector<ComponentIdentTypeRepr *, 2> components;
for (auto *component : ParentTR->getComponentRange()) {
components.push_back(component);
}
auto *last = components.back();
components.pop_back();
if (isa<SimpleIdentTypeRepr>(last) &&
last->getBoundDecl()) {
if (isa<TypeAliasDecl>(last->getBoundDecl())) {
// If any of our parent types are unbound, bail out and let
// the constraint solver can infer generic parameters for them.
//
// This is because a type like GenericClass.GenericAlias<Int>
// cannot be represented directly.
//
// This also means that [GenericClass.GenericAlias<Int>]()
// won't parse correctly, whereas if we fully specialize
// GenericClass, it does.
//
// FIXME: Once we can model generic typealiases properly, rip
// this out.
for (auto *component : components) {
auto *componentDecl = dyn_cast_or_null<GenericTypeDecl>(
component->getBoundDecl());
if (isa<SimpleIdentTypeRepr>(component) &&
componentDecl &&
componentDecl->isGeneric())
return nullptr;
}
}
auto *genericComp = GenericIdentTypeRepr::create(C,
last->getNameLoc(), last->getNameRef(),
Args, AngleLocs);
genericComp->setValue(last->getBoundDecl(), last->getDeclContext());
components.push_back(genericComp);
auto *genericRepr = IdentTypeRepr::create(C, components);
return new (C) TypeExpr(genericRepr);
}
return nullptr;
}
// 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.
TypeExpr *TypeExpr::createImplicitHack(SourceLoc Loc, Type Ty, ASTContext &C) {
// FIXME: This is horrible.
assert(Ty);
if (Loc.isInvalid()) return createImplicit(Ty, C);
auto *Repr = new (C) FixedTypeRepr(Ty, Loc);
auto *Res = new (C) TypeExpr(Repr);
Res->setType(MetatypeType::get(Ty, C));
Res->setImplicit();
return Res;
}
SourceRange TypeExpr::getSourceRange() const {
if (!getTypeRepr()) return SourceRange();
return getTypeRepr()->getSourceRange();
}
bool Expr::isSelfExprOf(const AbstractFunctionDecl *AFD, bool sameBase) const {
auto *E = getSemanticsProvidingExpr();
if (auto IOE = dyn_cast<InOutExpr>(E))
E = IOE->getSubExpr();
while (auto ICE = dyn_cast<ImplicitConversionExpr>(E)) {
if (sameBase && isa<DerivedToBaseExpr>(ICE))
return false;
E = ICE->getSubExpr();
}
if (auto DRE = dyn_cast<DeclRefExpr>(E))
return DRE->getDecl() == AFD->getImplicitSelfDecl();
return false;
}
OpenedArchetypeType *OpenExistentialExpr::getOpenedArchetype() const {
auto type = getOpaqueValue()->getType()->getRValueType();
while (auto metaTy = type->getAs<MetatypeType>())
type = metaTy->getInstanceType();
return type->castTo<OpenedArchetypeType>();
}
KeyPathExpr::KeyPathExpr(ASTContext &C, SourceLoc keywordLoc,
SourceLoc lParenLoc, ArrayRef<Component> components,
SourceLoc rParenLoc, bool isImplicit)
: Expr(ExprKind::KeyPath, isImplicit), StartLoc(keywordLoc),
LParenLoc(lParenLoc), EndLoc(rParenLoc),
Components(C.AllocateUninitialized<Component>(components.size())) {
// Copy components into the AST context.
std::uninitialized_copy(components.begin(), components.end(),
Components.begin());
Bits.KeyPathExpr.IsObjC = true;
}
void
KeyPathExpr::resolveComponents(ASTContext &C,
ArrayRef<KeyPathExpr::Component> resolvedComponents) {
// Reallocate the components array if it needs to be.
if (Components.size() < resolvedComponents.size()) {
Components = C.Allocate<Component>(resolvedComponents.size());
for (unsigned i : indices(Components)) {
::new ((void*)&Components[i]) Component{};
}
}
for (unsigned i : indices(resolvedComponents)) {
Components[i] = resolvedComponents[i];
}
Components = Components.slice(0, resolvedComponents.size());
}
KeyPathExpr::Component
KeyPathExpr::Component::forSubscript(ASTContext &ctx,
ConcreteDeclRef subscript,
SourceLoc lSquareLoc,
ArrayRef<Expr *> indexArgs,
ArrayRef<Identifier> indexArgLabels,
ArrayRef<SourceLoc> indexArgLabelLocs,
SourceLoc rSquareLoc,
ArrayRef<TrailingClosure> trailingClosures,
Type elementType,
ArrayRef<ProtocolConformanceRef> indexHashables) {
SmallVector<Identifier, 4> indexArgLabelsScratch;
SmallVector<SourceLoc, 4> indexArgLabelLocsScratch;
Expr *index = packSingleArgument(ctx, lSquareLoc, indexArgs, indexArgLabels,
indexArgLabelLocs, rSquareLoc,
trailingClosures, /*implicit*/ false,
indexArgLabelsScratch,
indexArgLabelLocsScratch);
return forSubscriptWithPrebuiltIndexExpr(subscript, index,
indexArgLabels,
elementType,
lSquareLoc,
indexHashables);
}
KeyPathExpr::Component
KeyPathExpr::Component::forUnresolvedSubscript(ASTContext &ctx,
SourceLoc lSquareLoc,
ArrayRef<Expr *> indexArgs,
ArrayRef<Identifier> indexArgLabels,
ArrayRef<SourceLoc> indexArgLabelLocs,
SourceLoc rSquareLoc,
ArrayRef<TrailingClosure> trailingClosures) {
SmallVector<Identifier, 4> indexArgLabelsScratch;
SmallVector<SourceLoc, 4> indexArgLabelLocsScratch;
Expr *index = packSingleArgument(
ctx, lSquareLoc, indexArgs, indexArgLabels, indexArgLabelLocs, rSquareLoc,
trailingClosures, /*implicit*/ false,
indexArgLabelsScratch, indexArgLabelLocsScratch);
return forUnresolvedSubscriptWithPrebuiltIndexExpr(ctx, index, indexArgLabels,
lSquareLoc);
}
KeyPathExpr::Component::Component(ASTContext *ctxForCopyingLabels,
DeclNameOrRef decl,
Expr *indexExpr,
ArrayRef<Identifier> subscriptLabels,
ArrayRef<ProtocolConformanceRef> indexHashables,
Kind kind,
Type type,
SourceLoc loc)
: Decl(decl), SubscriptIndexExpr(indexExpr), KindValue(kind),
ComponentType(type), Loc(loc)
{
assert(kind != Kind::TupleElement || subscriptLabels.empty());
assert(subscriptLabels.size() == indexHashables.size()
|| indexHashables.empty());
SubscriptLabelsData = subscriptLabels.data();
SubscriptHashableConformancesData = indexHashables.empty()
? nullptr : indexHashables.data();
SubscriptSize = subscriptLabels.size();
}
KeyPathExpr::Component
KeyPathExpr::Component::forSubscriptWithPrebuiltIndexExpr(
ConcreteDeclRef subscript, Expr *index, ArrayRef<Identifier> labels,
Type elementType, SourceLoc loc,
ArrayRef<ProtocolConformanceRef> indexHashables) {
return Component(&elementType->getASTContext(),
subscript, index, labels, indexHashables,
Kind::Subscript, elementType, loc);
}
void KeyPathExpr::Component::setSubscriptIndexHashableConformances(
ArrayRef<ProtocolConformanceRef> hashables) {
switch (getKind()) {
case Kind::Subscript:
assert(hashables.size() == SubscriptSize);
SubscriptHashableConformancesData = getComponentType()->getASTContext()
.AllocateCopy(hashables)
.data();
return;
case Kind::UnresolvedSubscript:
case Kind::Invalid:
case Kind::OptionalChain:
case Kind::OptionalWrap:
case Kind::OptionalForce:
case Kind::UnresolvedProperty:
case Kind::Property:
case Kind::Identity:
case Kind::TupleElement:
case Kind::DictionaryKey:
llvm_unreachable("no hashable conformances for this kind");
}
}
void InterpolatedStringLiteralExpr::forEachSegment(ASTContext &Ctx,
llvm::function_ref<void(bool, CallExpr *)> callback) {
auto appendingExpr = getAppendingExpr();
for (auto stmt : appendingExpr->getBody()->getElements()) {
if (auto expr = stmt.dyn_cast<Expr*>()) {
if (auto call = dyn_cast<CallExpr>(expr)) {
DeclName name;
if (auto fn = call->getCalledValue()) {
name = fn->getName();
} else if (auto unresolvedDot =
dyn_cast<UnresolvedDotExpr>(call->getFn())) {
name = unresolvedDot->getName().getFullName();
}
bool isInterpolation = (name.getBaseName() ==
Ctx.Id_appendInterpolation);
callback(isInterpolation, call);
}
}
}
}
TapExpr::TapExpr(Expr * SubExpr, BraceStmt *Body)
: Expr(ExprKind::Tap, /*Implicit=*/true),
SubExpr(SubExpr), Body(Body) {
if (Body) {
assert(!Body->empty() &&
Body->getFirstElement().isDecl(DeclKind::Var) &&
"First element of Body should be a variable to init with the subExpr");
}
}
VarDecl * TapExpr::getVar() const {
return dyn_cast<VarDecl>(Body->getFirstElement().dyn_cast<Decl *>());
}
SourceLoc TapExpr::getEndLoc() const {
// Include the body in the range, assuming the body follows the SubExpr.
// Also, be (perhaps overly) defensive about null pointers & invalid
// locations.
if (auto *const b = getBody()) {
const auto be = b->getEndLoc();
if (be.isValid())
return be;
}
if (auto *const se = getSubExpr())
return se->getEndLoc();
return SourceLoc();
}
void swift::simple_display(llvm::raw_ostream &out, const ClosureExpr *CE) {
if (!CE) {
out << "(null)";
return;
}
out << "closure";
}
void swift::simple_display(llvm::raw_ostream &out,
const DefaultArgumentExpr *expr) {
if (!expr) {
out << "(null)";
return;
}
out << "default arg for param ";
out << "#" << expr->getParamIndex() + 1 << " ";
out << "of ";
simple_display(out, expr->getDefaultArgsOwner().getDecl());
}
SourceLoc swift::extractNearestSourceLoc(const DefaultArgumentExpr *expr) {
return expr->getLoc();
}
// See swift/Basic/Statistic.h for declaration: this enables tracing Exprs, is
// defined here to avoid too much layering violation / circular linkage
// dependency.
struct ExprTraceFormatter : public UnifiedStatsReporter::TraceFormatter {
void traceName(const void *Entity, raw_ostream &OS) const override {
if (!Entity)
return;
const Expr *E = static_cast<const Expr *>(Entity);
OS << Expr::getKindName(E->getKind());
}
void traceLoc(const void *Entity, SourceManager *SM,
clang::SourceManager *CSM, raw_ostream &OS) const override {
if (!Entity)
return;
const Expr *E = static_cast<const Expr *>(Entity);
E->getSourceRange().print(OS, *SM, false);
}
};
static ExprTraceFormatter TF;
template<>
const UnifiedStatsReporter::TraceFormatter*
FrontendStatsTracer::getTraceFormatter<const Expr *>() {
return &TF;
}