mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
2451 lines
85 KiB
C++
2451 lines
85 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() || !T->hasHole());
|
|
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);
|
|
auto Res =
|
|
Val.convertFromString(Text, llvm::APFloat::rmNearestTiesToEven);
|
|
assert(Res && "Sema didn't reject invalid number");
|
|
consumeError(Res.takeError());
|
|
if (IsNegative) {
|
|
auto NegVal = APFloat::getZero(Semantics, /*negative*/ true);
|
|
Res = NegVal.subtract(Val, llvm::APFloat::rmNearestTiesToEven);
|
|
assert(Res && "Sema didn't reject invalid number");
|
|
consumeError(Res.takeError());
|
|
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 {
|
|
auto &ctx = Var->getASTContext();
|
|
|
|
if (Var->getName() != ctx.Id_self)
|
|
return false;
|
|
|
|
if (auto *attr = Var->getAttrs().getAttribute<ReferenceOwnershipAttr>())
|
|
if (attr->get() == ReferenceOwnership::Weak)
|
|
return false;
|
|
|
|
if (Init->getPatternList().size() != 1)
|
|
return false;
|
|
|
|
auto *expr = Init->getInit(0);
|
|
|
|
if (auto *DRE = dyn_cast<DeclRefExpr>(expr)) {
|
|
if (auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
|
|
return VD->getName() == ctx.Id_self;
|
|
}
|
|
}
|
|
|
|
if (auto *UDRE = dyn_cast<UnresolvedDeclRefExpr>(expr)) {
|
|
return UDRE->getName().isSimpleName(ctx.Id_self);
|
|
}
|
|
|
|
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));
|
|
auto *expr = ::new(mem) CaptureListExpr(captureList, closureBody);
|
|
|
|
for (auto capture : captureList)
|
|
capture.Var->setParentCaptureList(expr);
|
|
|
|
return expr;
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
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();
|
|
}
|
|
|
|
void ClosureExpr::setExplicitResultType(Type ty) {
|
|
assert(ty && !ty->hasTypeVariable() && !ty->hasHole());
|
|
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;
|
|
}
|
|
|