Files
swift-mirror/lib/AST/Expr.cpp
Hamish Knight edca7c85ad Adopt ABORT throughout the compiler
Convert a bunch of places where we're dumping to stderr and calling
`abort` over to using `ABORT` such that the message gets printed to
the pretty stack trace. This ensures it gets picked up by
CrashReporter.
2025-05-19 20:55:01 +01:00

3158 lines
103 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/Assertions.h"
#include "swift/Basic/Statistic.h"
#include "swift/Basic/Unicode.h"
#include "swift/Basic/SourceManager.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/ASTVisitor.h"
#include "swift/AST/Decl.h" // FIXME: Bad dependency
#include "swift/AST/ExistentialLayout.h"
#include "swift/AST/MacroDiscriminatorContext.h"
#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"
//===----------------------------------------------------------------------===//
// Expr methods.
//===----------------------------------------------------------------------===//
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->hasPlaceholder());
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;
}
bool Expr::printConstExprValue(llvm::raw_ostream *OS,
llvm::function_ref<bool(Expr*)> additionalCheck) const {
auto print = [&](StringRef text) {
if (OS) {
*OS << text;
}
};
auto *E = getSemanticsProvidingExpr();
assert(E);
switch(getKind()) {
case ExprKind::BooleanLiteral: {
auto isTrue = cast<BooleanLiteralExpr>(E)->getValue();
print(isTrue ? "true" : "false");
return true;
}
case ExprKind::IntegerLiteral:
case ExprKind::FloatLiteral: {
const auto *NE = cast<NumberLiteralExpr>(E);
auto digits = NE->getDigitsText();
assert(!digits.empty());
if (NE->getMinusLoc().isValid()) {
print("-");
}
print(digits);
return true;
}
case ExprKind::NilLiteral: {
print("nil");
return true;
}
case ExprKind::StringLiteral: {
auto *LE = cast<StringLiteralExpr>(E);
print("\"");
print(LE->getValue());
print("\"");
return true;
}
case ExprKind::KeyPath: {
// FIXME: print keypath
print("\\.<NOT_IMPLEMENTED>");
return true;
}
case ExprKind::Array:
case ExprKind::Dictionary: {
print("[");
auto *CE = cast<CollectionExpr>(E);
for (unsigned N = CE->getNumElements(), I = 0; I != N; I ++) {
auto Ele = CE->getElement(I);
auto needComma = I + 1 != N;
if (!Ele->printConstExprValue(OS, additionalCheck)) {
return false;
}
if (needComma)
print(", ");
}
print("]");
return true;
}
case ExprKind::Tuple: {
print("(");
auto *TE = cast<TupleExpr>(E);
for (unsigned N = TE->getNumElements(), I = 0; I != N; I ++) {
auto Ele = TE->getElement(I);
auto needComma = I + 1 != N;
if (!Ele->printConstExprValue(OS, additionalCheck)) {
return false;
}
if (needComma)
print(", ");
}
print(")");
return true;
}
default:
return additionalCheck && additionalCheck(const_cast<Expr*>(this));
}
}
bool Expr::isSemanticallyConstExpr(
llvm::function_ref<bool(Expr*)> additionalCheck) const {
return printConstExprValue(nullptr, additionalCheck);
}
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: \
if (auto sub = cast<Id##Expr>(this)->GetSubExpr()) \
return sub->getReferencedDecl(stopAtParenExpr); \
return ConcreteDeclRef();
NO_REFERENCE(Error);
SIMPLE_REFERENCE(NilLiteral, getInitializer);
SIMPLE_REFERENCE(IntegerLiteral, getInitializer);
SIMPLE_REFERENCE(FloatLiteral, getInitializer);
SIMPLE_REFERENCE(BooleanLiteral, getInitializer);
SIMPLE_REFERENCE(StringLiteral, getInitializer);
SIMPLE_REFERENCE(InterpolatedStringLiteral, getInitializer);
NO_REFERENCE(RegexLiteral);
NO_REFERENCE(ObjectLiteral);
NO_REFERENCE(MagicIdentifierLiteral);
NO_REFERENCE(DiscardAssignment);
NO_REFERENCE(LazyInitializer);
NO_REFERENCE(SingleValueStmt);
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(Unsafe, getSubExpr);
PASS_THROUGH_REFERENCE(Consume, getSubExpr);
PASS_THROUGH_REFERENCE(Copy, getSubExpr);
PASS_THROUGH_REFERENCE(Borrow, getSubExpr);
PASS_THROUGH_REFERENCE(Try, getSubExpr);
PASS_THROUGH_REFERENCE(ForceTry, getSubExpr);
PASS_THROUGH_REFERENCE(OptionalTry, getSubExpr);
PASS_THROUGH_REFERENCE(ExtractFunctionIsolation, getFunctionExpr);
NO_REFERENCE(Tuple);
SIMPLE_REFERENCE(Array, getInitializer);
SIMPLE_REFERENCE(Dictionary, getInitializer);
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(PackExpansion);
NO_REFERENCE(PackElement);
NO_REFERENCE(MaterializePack);
NO_REFERENCE(DynamicType);
PASS_THROUGH_REFERENCE(RebindSelfInConstructor, getSubExpr);
NO_REFERENCE(OpaqueValue);
NO_REFERENCE(PropertyWrapperValuePlaceholder);
NO_REFERENCE(AppliedPropertyWrapper);
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(ABISafeConversion, getSubExpr);
PASS_THROUGH_REFERENCE(FunctionConversion, getSubExpr);
PASS_THROUGH_REFERENCE(CovariantFunctionConversion, getSubExpr);
PASS_THROUGH_REFERENCE(CovariantReturnConversion, 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);
PASS_THROUGH_REFERENCE(Unreachable, getSubExpr);
PASS_THROUGH_REFERENCE(ActorIsolationErasure, getSubExpr);
PASS_THROUGH_REFERENCE(UnsafeCast, getSubExpr);
NO_REFERENCE(Coerce);
NO_REFERENCE(ForcedCheckedCast);
NO_REFERENCE(ConditionalCheckedCast);
NO_REFERENCE(Is);
NO_REFERENCE(Arrow);
NO_REFERENCE(Ternary);
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(CurrentContextIsolation, getActor);
NO_REFERENCE(Tap);
NO_REFERENCE(TypeJoin);
SIMPLE_REFERENCE(MacroExpansion, getMacroRef);
NO_REFERENCE(TypeValue);
#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;
/// Only walk the arguments of a macro, to represent the source as written.
MacroWalking getMacroWalkingBehavior() const override {
return MacroWalking::Arguments;
}
ChildWalker(llvm::function_ref<Expr *(Expr *)> callback, Expr *ThisNode)
: callback(callback), ThisNode(ThisNode) {}
PreWalkResult<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 Action::Continue(E);
// Otherwise we must be a child of our expression, enumerate it!
E = callback(E);
if (!E)
return Action::Stop();
// We're only interested in the immediate children, so don't walk any
// further.
return Action::SkipNode(E);
}
PreWalkResult<Stmt *> walkToStmtPre(Stmt *S) override {
return Action::SkipNode(S);
}
PreWalkResult<Pattern *> walkToPatternPre(Pattern *P) override {
return Action::SkipNode(P);
}
PreWalkAction walkToDeclPre(Decl *D) override {
return Action::SkipNode();
}
PreWalkAction walkToTypeReprPre(TypeRepr *T) override {
return Action::SkipNode();
}
};
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;
/// Only walk the arguments of a macro, to represent the source as written.
MacroWalking getMacroWalkingBehavior() const override {
return MacroWalking::Arguments;
}
ChildWalker(llvm::function_ref<Expr *(Expr *)> callback)
: callback(callback) {}
PreWalkResult<Expr *> walkToExprPre(Expr *E) override {
// Enumerate the node!
E = callback(E);
if (!E)
return Action::Stop();
return Action::Continue(E);
}
PreWalkResult<Stmt *> walkToStmtPre(Stmt *S) override {
return Action::SkipNode(S);
}
PreWalkResult<Pattern *> walkToPatternPre(Pattern *P) override {
return Action::SkipNode(P);
}
PreWalkAction walkToDeclPre(Decl *D) override {
return Action::SkipNode();
}
PreWalkAction walkToTypeReprPre(TypeRepr *T) override {
return Action::SkipNode();
}
};
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:
return false;
case ExprKind::NilLiteral:
case ExprKind::IntegerLiteral:
case ExprKind::FloatLiteral:
case ExprKind::BooleanLiteral:
case ExprKind::StringLiteral:
case ExprKind::InterpolatedStringLiteral:
case ExprKind::RegexLiteral:
case ExprKind::MagicIdentifierLiteral:
case ExprKind::ObjCSelector:
case ExprKind::KeyPath:
case ExprKind::SingleValueStmt:
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:
case ExprKind::ExtractFunctionIsolation:
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::Unsafe:
case ExprKind::Consume:
case ExprKind::Copy:
case ExprKind::Borrow:
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::AppliedPropertyWrapper:
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:
case ExprKind::PackExpansion:
case ExprKind::PackElement:
case ExprKind::MaterializePack:
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::ABISafeConversion:
case ExprKind::DestructureTuple:
case ExprKind::UnresolvedTypeConversion:
case ExprKind::FunctionConversion:
case ExprKind::CovariantFunctionConversion:
case ExprKind::CovariantReturnConversion:
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:
case ExprKind::Unreachable:
case ExprKind::ActorIsolationErasure:
case ExprKind::UnsafeCast:
case ExprKind::TypeValue:
// 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::Ternary:
case ExprKind::Assign:
case ExprKind::UnresolvedPattern:
case ExprKind::EditorPlaceholder:
case ExprKind::KeyPathDot:
case ExprKind::TypeJoin:
return false;
case ExprKind::Tap:
return true;
case ExprKind::MacroExpansion:
case ExprKind::CurrentContextIsolation:
return true;
}
llvm_unreachable("Unhandled ExprKind in switch.");
}
ArgumentList *Expr::getArgs() const {
if (auto *AE = dyn_cast<ApplyExpr>(this))
return AE->getArgs();
if (auto *SE = dyn_cast<SubscriptExpr>(this))
return SE->getArgs();
if (auto *DSE = dyn_cast<DynamicSubscriptExpr>(this))
return DSE->getArgs();
if (auto *OLE = dyn_cast<ObjectLiteralExpr>(this))
return OLE->getArgs();
if (auto *ME = dyn_cast<MacroExpansionExpr>(this))
return ME->getArgs();
return nullptr;
}
DeclNameLoc Expr::getNameLoc() const {
if (auto *DRE = dyn_cast<DeclRefExpr>(this))
return DRE->getNameLoc();
if (auto *UDRE = dyn_cast<UnresolvedDeclRefExpr>(this))
return UDRE->getNameLoc();
if (auto *ODRE = dyn_cast<OverloadedDeclRefExpr>(this))
return ODRE->getNameLoc();
if (auto *UDE = dyn_cast<UnresolvedDotExpr>(this))
return UDE->getNameLoc();
if (auto *UME = dyn_cast<UnresolvedMemberExpr>(this))
return UME->getNameLoc();
if (auto *MRE = dyn_cast<MemberRefExpr>(this))
return MRE->getNameLoc();
if (auto *DRME = dyn_cast<DynamicMemberRefExpr>(this))
return DRME->getNameLoc();
return DeclNameLoc();
}
llvm::DenseMap<Expr *, Expr *> Expr::getParentMap() {
class RecordingTraversal : public ASTWalker {
public:
llvm::DenseMap<Expr *, Expr *> &ParentMap;
/// Walk everything that's available.
MacroWalking getMacroWalkingBehavior() const override {
return MacroWalking::ArgumentsAndExpansion;
}
explicit RecordingTraversal(llvm::DenseMap<Expr *, Expr *> &parentMap)
: ParentMap(parentMap) { }
PreWalkResult<Expr *> walkToExprPre(Expr *E) override {
if (auto parent = Parent.getAsExpr())
ParentMap[E] = parent;
return Action::Continue(E);
}
};
llvm::DenseMap<Expr *, Expr *> parentMap;
RecordingTraversal traversal(parentMap);
walk(traversal);
return parentMap;
}
bool Expr::isValidParentOfTypeExpr(Expr *typeExpr) const {
// Allow references to types as a part of:
// - member references T.foo, T.Type, T.self, etc.
// - constructor calls T()
// - Subscripts T[]
//
// This is an exhaustive list of the accepted syntactic forms.
switch (getKind()) {
case ExprKind::Error:
case ExprKind::DotSelf:
case ExprKind::MemberRef:
case ExprKind::UnresolvedMember:
case ExprKind::DotSyntaxCall:
case ExprKind::ConstructorRefCall:
case ExprKind::UnresolvedDot:
case ExprKind::DotSyntaxBaseIgnored:
case ExprKind::UnresolvedSpecialize:
case ExprKind::OpenExistential:
case ExprKind::TypeValue:
return true;
// For these cases we need to ensure the type expr is the function or base.
// We do not permit e.g 'foo(T)'.
case ExprKind::Call:
return cast<CallExpr>(this)->getFn() == typeExpr;
case ExprKind::Subscript:
return cast<SubscriptExpr>(this)->getBase() == typeExpr;
case ExprKind::NilLiteral:
case ExprKind::BooleanLiteral:
case ExprKind::IntegerLiteral:
case ExprKind::FloatLiteral:
case ExprKind::StringLiteral:
case ExprKind::MagicIdentifierLiteral:
case ExprKind::InterpolatedStringLiteral:
case ExprKind::RegexLiteral:
case ExprKind::ObjectLiteral:
case ExprKind::DiscardAssignment:
case ExprKind::DeclRef:
case ExprKind::SuperRef:
case ExprKind::Type:
case ExprKind::OtherConstructorDeclRef:
case ExprKind::OverloadedDeclRef:
case ExprKind::UnresolvedDeclRef:
case ExprKind::DynamicMemberRef:
case ExprKind::DynamicSubscript:
case ExprKind::Sequence:
case ExprKind::Paren:
case ExprKind::Await:
case ExprKind::Unsafe:
case ExprKind::Consume:
case ExprKind::Copy:
case ExprKind::Borrow:
case ExprKind::UnresolvedMemberChainResult:
case ExprKind::Try:
case ExprKind::ForceTry:
case ExprKind::OptionalTry:
case ExprKind::Tuple:
case ExprKind::Array:
case ExprKind::Dictionary:
case ExprKind::KeyPathApplication:
case ExprKind::TupleElement:
case ExprKind::CaptureList:
case ExprKind::Closure:
case ExprKind::AutoClosure:
case ExprKind::InOut:
case ExprKind::VarargExpansion:
case ExprKind::PackExpansion:
case ExprKind::PackElement:
case ExprKind::MaterializePack:
case ExprKind::DynamicType:
case ExprKind::RebindSelfInConstructor:
case ExprKind::OpaqueValue:
case ExprKind::PropertyWrapperValuePlaceholder:
case ExprKind::AppliedPropertyWrapper:
case ExprKind::DefaultArgument:
case ExprKind::BindOptional:
case ExprKind::OptionalEvaluation:
case ExprKind::ForceValue:
case ExprKind::MakeTemporarilyEscapable:
case ExprKind::PrefixUnary:
case ExprKind::PostfixUnary:
case ExprKind::Binary:
case ExprKind::Load:
case ExprKind::DestructureTuple:
case ExprKind::UnresolvedTypeConversion:
case ExprKind::ABISafeConversion:
case ExprKind::FunctionConversion:
case ExprKind::CovariantFunctionConversion:
case ExprKind::CovariantReturnConversion:
case ExprKind::MetatypeConversion:
case ExprKind::CollectionUpcastConversion:
case ExprKind::Erasure:
case ExprKind::AnyHashableErasure:
case ExprKind::BridgeToObjC:
case ExprKind::BridgeFromObjC:
case ExprKind::ConditionalBridgeFromObjC:
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::UnderlyingToOpaque:
case ExprKind::Unreachable:
case ExprKind::DifferentiableFunction:
case ExprKind::LinearFunction:
case ExprKind::DifferentiableFunctionExtractOriginal:
case ExprKind::LinearFunctionExtractOriginal:
case ExprKind::LinearToDifferentiableFunction:
case ExprKind::ForcedCheckedCast:
case ExprKind::ConditionalCheckedCast:
case ExprKind::Is:
case ExprKind::Coerce:
case ExprKind::Arrow:
case ExprKind::Ternary:
case ExprKind::EnumIsCase:
case ExprKind::Assign:
case ExprKind::CodeCompletion:
case ExprKind::UnresolvedPattern:
case ExprKind::LazyInitializer:
case ExprKind::EditorPlaceholder:
case ExprKind::ObjCSelector:
case ExprKind::KeyPath:
case ExprKind::KeyPathDot:
case ExprKind::Tap:
case ExprKind::SingleValueStmt:
case ExprKind::TypeJoin:
case ExprKind::MacroExpansion:
case ExprKind::CurrentContextIsolation:
case ExprKind::ActorIsolationErasure:
case ExprKind::ExtractFunctionIsolation:
case ExprKind::UnsafeCast:
return false;
}
llvm_unreachable("Unhandled ExprKind in switch.");
}
//===----------------------------------------------------------------------===//
// Support methods for Exprs.
//===----------------------------------------------------------------------===//
StringRef LiteralExpr::getLiteralKindDescription() const {
switch (getKind()) {
case ExprKind::IntegerLiteral:
return "integer";
case ExprKind::FloatLiteral:
return "floating-point";
case ExprKind::BooleanLiteral:
return "boolean";
case ExprKind::StringLiteral:
return "string";
case ExprKind::InterpolatedStringLiteral:
return "string";
case ExprKind::RegexLiteral:
return "regular expression";
case ExprKind::MagicIdentifierLiteral:
return MagicIdentifierLiteralExpr::getKindString(
cast<MagicIdentifierLiteralExpr>(this)->getKind());
case ExprKind::NilLiteral:
return "nil";
case ExprKind::ObjectLiteral:
return "object";
// Define an unreachable case for all non-literal expressions.
// This way, if a new literal is added in the future, the compiler
// will warn that a case is missing from this switch.
#define LITERAL_EXPR(Id, Parent)
#define EXPR(Id, Parent) case ExprKind::Id:
#include "swift/AST/ExprNodes.def"
llvm_unreachable("Not a literal expression");
}
llvm_unreachable("Unhandled literal");
}
IntegerLiteralExpr * IntegerLiteralExpr::createFromUnsigned(ASTContext &C, unsigned value, SourceLoc loc) {
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, loc, /*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.isZero());
}
// Truncate down to the minimum number of bits required to express
// this value exactly.
auto requiredBits = value.getSignificantBits();
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)
: BuiltinLiteralExpr(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);
}
ObjectLiteralExpr::ObjectLiteralExpr(SourceLoc poundLoc, LiteralKind litKind,
ArgumentList *argList, bool implicit)
: LiteralExpr(ExprKind::ObjectLiteral, implicit), ArgList(argList),
PoundLoc(poundLoc) {
assert(argList);
Bits.ObjectLiteralExpr.LitKind = static_cast<unsigned>(litKind);
assert(getLiteralKind() == litKind);
}
ObjectLiteralExpr *
ObjectLiteralExpr::create(ASTContext &ctx, SourceLoc poundLoc, LiteralKind kind,
ArgumentList *args, bool implicit) {
return new (ctx) ObjectLiteralExpr(poundLoc, kind, args, implicit);
}
StringRef ObjectLiteralExpr::getLiteralKindRawName() const {
switch (getLiteralKind()) {
#define POUND_OBJECT_LITERAL(Name, Desc, Proto) case Name: return #Name;
#include "swift/AST/TokenKinds.def"
}
llvm_unreachable("unspecified literal");
}
StringRef ObjectLiteralExpr::
getLiteralKindPlainName(ObjectLiteralExpr::LiteralKind kind) {
switch (kind) {
#define POUND_OBJECT_LITERAL(Name, Desc, Proto) case Name: return Desc;
#include "swift/AST/TokenKinds.def"
}
llvm_unreachable("unspecified literal");
}
StringRef ObjectLiteralExpr::getLiteralKindPlainName() const {
return ObjectLiteralExpr::getLiteralKindPlainName(getLiteralKind());
}
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) {}
VarargExpansionExpr *VarargExpansionExpr::createParamExpansion(ASTContext &ctx, Expr *E) {
assert(E->getType() && "Expansion must have fully-resolved type!");
return new (ctx) VarargExpansionExpr(E, /*implicit*/ true, E->getType());
}
VarargExpansionExpr *VarargExpansionExpr::createArrayExpansion(ASTContext &ctx, ArrayExpr *AE) {
assert(AE->getType() && "Expansion must have fully-resolved type!");
return new (ctx) VarargExpansionExpr(AE, /*implicit*/ true, AE->getType());
}
PackExpansionExpr *
PackExpansionExpr::create(ASTContext &ctx, SourceLoc repeatLoc,
Expr *patternExpr, GenericEnvironment *environment,
bool implicit, Type type) {
return new (ctx) PackExpansionExpr(repeatLoc, patternExpr, environment,
implicit, type);
}
PackElementExpr *
PackElementExpr::create(ASTContext &ctx, SourceLoc eachLoc, Expr *packRefExpr,
bool implicit, Type type) {
return new (ctx) PackElementExpr(eachLoc, packRefExpr, implicit, type);
}
MaterializePackExpr *
MaterializePackExpr::create(ASTContext &ctx, Expr *fromExpr,
SourceLoc elementLoc,
Type type, bool implicit) {
return new (ctx) MaterializePackExpr(fromExpr, elementLoc,
type, implicit);
}
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,
ArrayRef<ConversionPair> argConversions) {
auto layout = type->getExistentialLayout();
assert(layout.getProtocols().size() == conformances.size());
auto size = totalSizeToAlloc<ProtocolConformanceRef, ConversionPair>(conformances.size(),
argConversions.size());
auto mem = ctx.Allocate(size, alignof(ErasureExpr));
return ::new (mem) ErasureExpr(subExpr, type, conformances, argConversions);
}
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);
}
CaptureListEntry::CaptureListEntry(PatternBindingDecl *PBD) : PBD(PBD) {
assert(PBD);
assert(PBD->getSingleVar() &&
"Capture lists only support single-var patterns");
}
CaptureListEntry CaptureListEntry::createParsed(
ASTContext &Ctx, ReferenceOwnership ownershipKind,
SourceRange ownershipRange, Identifier name, SourceLoc nameLoc,
SourceLoc equalLoc, Expr *initializer, DeclContext *DC) {
auto introducer =
(ownershipKind != ReferenceOwnership::Weak ? VarDecl::Introducer::Let
: VarDecl::Introducer::Var);
auto *VD =
new (Ctx) VarDecl(/*isStatic==*/false, introducer, nameLoc, name, DC);
if (ownershipKind != ReferenceOwnership::Strong)
VD->getAttrs().add(
new (Ctx) ReferenceOwnershipAttr(ownershipRange, ownershipKind));
auto *pattern = NamedPattern::createImplicit(Ctx, VD);
auto *PBD = PatternBindingDecl::create(Ctx, /*StaticLoc=*/SourceLoc(),
StaticSpellingKind::None, nameLoc,
pattern, equalLoc, initializer, DC);
CaptureListEntry CLE(PBD);
if (CLE.isSimpleSelfCapture())
VD->setIsSelfParamCapture();
return CLE;
}
VarDecl *CaptureListEntry::getVar() const {
return PBD->getSingleVar();
}
bool CaptureListEntry::isSimpleSelfCapture(bool excludeWeakCaptures) const {
auto *Var = getVar();
auto &ctx = Var->getASTContext();
if (Var->getName() != ctx.Id_self)
return false;
if (PBD->getPatternList().size() != 1)
return false;
auto *expr = PBD->getInit(0);
if (auto *attr = Var->getAttrs().getAttribute<ReferenceOwnershipAttr>()) {
if (attr->get() == ReferenceOwnership::Weak && excludeWeakCaptures) {
return false;
}
}
// Look through any ImplicitConversionExpr that may contain the DRE
if (auto conversion = dyn_cast_or_null<ImplicitConversionExpr>(expr)) {
expr = conversion->getSubExpr();
}
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,
AbstractClosureExpr *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.getVar()->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 {
auto start = LParenLoc;
if (start.isInvalid()) {
// Scan forward for the first valid source loc.
for (auto *expr : getElements()) {
start = expr->getStartLoc();
if (start.isValid())
break;
}
}
auto end = RParenLoc;
if (end.isInvalid()) {
// Scan backwards for a valid source loc.
for (auto *expr : llvm::reverse(getElements())) {
end = expr->getEndLoc();
if (end.isValid())
break;
}
}
if (start.isInvalid() || end.isInvalid())
return SourceRange();
return SourceRange(start, end);
}
TupleExpr::TupleExpr(SourceLoc LParenLoc, SourceLoc RParenLoc,
ArrayRef<Expr *> SubExprs,
ArrayRef<Identifier> ElementNames,
ArrayRef<SourceLoc> ElementNameLocs,
bool Implicit, Type Ty)
: Expr(ExprKind::Tuple, Implicit, Ty),
LParenLoc(LParenLoc), RParenLoc(RParenLoc) {
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 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, Implicit, Ty);
}
TupleExpr *TupleExpr::createEmpty(ASTContext &ctx, SourceLoc LParenLoc,
SourceLoc RParenLoc, bool Implicit) {
return create(ctx, LParenLoc, {}, {}, {}, RParenLoc, Implicit,
TupleType::getEmpty(ctx));
}
TupleExpr *TupleExpr::createImplicit(ASTContext &ctx, ArrayRef<Expr *> SubExprs,
ArrayRef<Identifier> ElementNames) {
return create(ctx, SourceLoc(), SubExprs, ElementNames, {}, SourceLoc(),
/*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, bool skipFunctionConversions) {
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(skipFunctionConversions);
if (skipFunctionConversions) {
if (auto fnConv = dyn_cast<FunctionConversionExpr>(E))
return getCalledValue(fnConv->getSubExpr(), skipFunctionConversions);
if (auto *actorErasure = dyn_cast<ActorIsolationErasureExpr>(E))
return getCalledValue(actorErasure->getSubExpr(),
skipFunctionConversions);
}
Expr *E2 = E->getValueProvidingExpr();
if (E != E2)
return getCalledValue(E2, skipFunctionConversions);
return nullptr;
}
OpaqueValueExpr *OpaqueValueExpr::createImplicit(ASTContext &ctx, Type Ty,
bool isPlaceholder,
AllocationArena arena) {
auto *mem =
ctx.Allocate(sizeof(OpaqueValueExpr), alignof(OpaqueValueExpr), arena);
return new (mem) OpaqueValueExpr(
/*Range=*/SourceRange(), Ty, isPlaceholder);
}
PropertyWrapperValuePlaceholderExpr *
PropertyWrapperValuePlaceholderExpr::create(ASTContext &ctx, SourceRange range,
Type ty, Expr *wrappedValue,
bool isAutoClosure) {
OpaqueValueExpr *placeholder = nullptr;
if (ty)
placeholder = new (ctx) OpaqueValueExpr(range, ty, /*isPlaceholder=*/true);
return new (ctx) PropertyWrapperValuePlaceholderExpr(
range, ty, placeholder, wrappedValue, isAutoClosure);
}
AppliedPropertyWrapperExpr *
AppliedPropertyWrapperExpr::create(ASTContext &ctx, ConcreteDeclRef callee,
const ParamDecl *param,
SourceLoc loc, Type Ty, Expr *value,
AppliedPropertyWrapperExpr::ValueKind kind) {
return new (ctx) AppliedPropertyWrapperExpr(callee, param, loc, Ty, value, kind);
}
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);
if (auto result = evaluateOrDefault(ctx.evaluator,
CallerSideDefaultArgExprRequest{mutableThis},
nullptr))
return result;
return new (ctx) ErrorExpr(getSourceRange(), getType());
}
ActorIsolation
DefaultArgumentExpr::getRequiredIsolation() const {
return getParamDecl()->getInitializerIsolation();
}
ValueDecl *ApplyExpr::getCalledValue(bool skipFunctionConversions) const {
return ::getCalledValue(Fn, skipFunctionConversions);
}
SubscriptExpr::SubscriptExpr(Expr *base, ArgumentList *argList,
ConcreteDeclRef decl, bool implicit,
AccessSemantics semantics)
: LookupExpr(ExprKind::Subscript, base, decl, implicit), ArgList(argList) {
Bits.SubscriptExpr.Semantics = (unsigned) semantics;
}
SubscriptExpr *SubscriptExpr::create(ASTContext &ctx, Expr *base,
ArgumentList *argList,
ConcreteDeclRef decl,
bool implicit,
AccessSemantics semantics) {
return new (ctx) SubscriptExpr(base, argList, decl, implicit, semantics);
}
DynamicSubscriptExpr::DynamicSubscriptExpr(Expr *base, ArgumentList *argList,
ConcreteDeclRef member,
bool implicit)
: DynamicLookupExpr(ExprKind::DynamicSubscript, member, base),
ArgList(argList) {
if (implicit) setImplicit(implicit);
}
DynamicSubscriptExpr *DynamicSubscriptExpr::create(ASTContext &ctx, Expr *base,
ArgumentList *argList,
ConcreteDeclRef member,
bool implicit) {
return new (ctx) DynamicSubscriptExpr(base, argList, member, implicit);
}
CallExpr::CallExpr(Expr *fn, ArgumentList *argList, bool implicit, Type ty)
: ApplyExpr(ExprKind::Call, fn, argList, implicit, ty) {
#ifndef NDEBUG
Expr *calleeFn = fn->getSemanticsProvidingExpr();
if (auto *calleeDRE = dyn_cast<DeclRefExpr>(calleeFn))
assert(!calleeDRE->getDecl()->isInstanceMember());
#endif
}
CallExpr *CallExpr::create(ASTContext &ctx, Expr *fn, ArgumentList *argList,
bool implicit) {
return new (ctx) CallExpr(fn, argList, implicit, Type());
}
CallExpr *CallExpr::createImplicitEmpty(ASTContext &ctx, Expr *fn) {
return createImplicit(ctx, fn, ArgumentList::createImplicit(ctx, {}));
}
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;
}
// Explicit specializations are currently invalid for function calls, but
// look through them for better recovery.
if (auto *spec = dyn_cast<UnresolvedSpecializeExpr>(fn)) {
fn = spec->getSubExpr();
continue;
}
return fn;
}
}
PrefixUnaryExpr *PrefixUnaryExpr::create(ASTContext &ctx, Expr *fn,
Expr *operand, Type ty) {
auto *argList = ArgumentList::forImplicitUnlabeled(ctx, {operand});
return new (ctx) PrefixUnaryExpr(fn, argList, ty);
}
PostfixUnaryExpr *PostfixUnaryExpr::create(ASTContext &ctx, Expr *fn,
Expr *operand, Type ty) {
auto *argList = ArgumentList::forImplicitUnlabeled(ctx, {operand});
return new (ctx) PostfixUnaryExpr(fn, argList, ty);
}
BinaryExpr *BinaryExpr::create(ASTContext &ctx, Expr *lhs, Expr *fn, Expr *rhs,
bool implicit, Type ty) {
auto *argList = ArgumentList::forImplicitUnlabeled(ctx, {lhs, rhs});
return new (ctx) BinaryExpr(fn, argList, implicit, ty);
}
DotSyntaxCallExpr *DotSyntaxCallExpr::create(ASTContext &ctx, Expr *fnExpr,
SourceLoc dotLoc, Argument baseArg,
Type ty) {
assert(!baseArg.hasLabel());
auto *argList = ArgumentList::forImplicitUnlabeled(ctx, {baseArg.getExpr()});
return new (ctx) DotSyntaxCallExpr(fnExpr, dotLoc, argList, ty);
}
SourceLoc DotSyntaxCallExpr::getLoc() const {
if (isImplicit()) {
SourceLoc baseLoc = getBase()->getLoc();
return baseLoc.isValid() ? baseLoc : getFn()->getLoc();
}
return getFn()->getLoc();
}
SourceLoc DotSyntaxCallExpr::getStartLoc() const {
if (isImplicit()) {
SourceLoc baseLoc = getBase()->getStartLoc();
return baseLoc.isValid() ? baseLoc : getFn()->getStartLoc();
}
return getBase()->getStartLoc();
}
SourceLoc DotSyntaxCallExpr::getEndLoc() const {
if (isImplicit()) {
SourceLoc fnLoc = getFn()->getEndLoc();
return fnLoc.isValid() ? fnLoc : getBase()->getEndLoc();
}
return getFn()->getEndLoc();
}
ConstructorRefCallExpr *ConstructorRefCallExpr::create(ASTContext &ctx,
Expr *fnExpr,
Expr *baseExpr,
Type ty) {
auto *argList = ArgumentList::forImplicitUnlabeled(ctx, {baseExpr});
return new (ctx) ConstructorRefCallExpr(fnExpr, argList, ty);
}
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;
}
// Look through open existential expressions
if (auto openExistentialExpr
= dyn_cast<OpenExistentialExpr>(candidate)) {
candidate = openExistentialExpr->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);
auto *unaryArg = apply->getArgs()->getUnaryExpr();
assert(unaryArg);
isChainToSuper = unaryArg->isSuperExpr();
return otherCtorRef;
}
unsigned AbstractClosureExpr::getDiscriminator() const {
auto raw = getRawDiscriminator();
if (raw != InvalidDiscriminator)
return raw;
ASTContext &ctx = getASTContext();
evaluateOrDefault(
ctx.evaluator, LocalDiscriminatorsRequest{getParent()}, 0);
#if NDEBUG
static constexpr bool useFallbackDiscriminator = true;
#else
static constexpr bool useFallbackDiscriminator = false;
#endif
// If we don't have a discriminator, and either
// 1. We have ill-formed code and we're able to assign a discriminator, or
// 2. We are in a macro expansion buffer
// 3. We are within top-level code where there's nothing to anchor to
//
// then assign the next discriminator now.
if (getRawDiscriminator() == InvalidDiscriminator &&
(ctx.Diags.hadAnyError() ||
getParentSourceFile()->getFulfilledMacroRole() != std::nullopt ||
getParent()->isModuleScopeContext() ||
useFallbackDiscriminator)) {
auto discriminator = ctx.getNextDiscriminator(getParent());
ctx.setMaxAssignedDiscriminator(getParent(), discriminator + 1);
const_cast<AbstractClosureExpr *>(this)->
Bits.AbstractClosureExpr.Discriminator = discriminator;
}
if (getRawDiscriminator() == InvalidDiscriminator) {
ABORT([&](auto &out) {
out << "Closure does not have an assigned discriminator:\n";
this->dump(out);
});
}
return getRawDiscriminator();
}
void AbstractClosureExpr::setParameterList(ParameterList *P) {
parameterList = P;
// Change the DeclContext of any parameters to be this closure.
if (P)
P->setDeclContextOfParamDecls(this);
}
BraceStmt * AbstractClosureExpr::getBody() const {
if (const AutoClosureExpr *autocls = dyn_cast<AutoClosureExpr>(this))
return autocls->getBody();
if (const ClosureExpr *cls = dyn_cast<ClosureExpr>(this))
return cls->getBody();
llvm_unreachable("Unknown closure expression");
}
BraceStmt *ClosureExpr::getExpandedBody() {
auto &ctx = getASTContext();
// Expand a body macro, if there is one.
BraceStmt *macroExpandedBody = nullptr;
if (auto bufferID = evaluateOrDefault(
ctx.evaluator,
ExpandBodyMacroRequest{this},
std::nullopt)) {
CharSourceRange bufferRange = ctx.SourceMgr.getRangeForBuffer(*bufferID);
auto bufferStart = bufferRange.getStart();
auto module = getParentModule();
auto macroSourceFile = module->getSourceFileContainingLocation(bufferStart);
if (macroSourceFile->getTopLevelItems().size() == 1) {
auto stmt = macroSourceFile->getTopLevelItems()[0].dyn_cast<Stmt *>();
macroExpandedBody = dyn_cast<BraceStmt>(stmt);
}
}
return macroExpandedBody;
}
bool AbstractClosureExpr::bodyHasExplicitReturnStmt() const {
return AnyFunctionRef(const_cast<AbstractClosureExpr *>(this))
.bodyHasExplicitReturnStmt();
}
void AbstractClosureExpr::getExplicitReturnStmts(
SmallVectorImpl<ReturnStmt *> &results) const {
AnyFunctionRef(const_cast<AbstractClosureExpr *>(this))
.getExplicitReturnStmts(results);
}
Type AbstractClosureExpr::getResultType(
llvm::function_ref<Type(Expr *)> getType) const {
auto *E = const_cast<AbstractClosureExpr *>(this);
Type T = getType(E);
if (!T || T->hasError())
return T;
return T->castTo<FunctionType>()->getResult();
}
std::optional<Type> AbstractClosureExpr::getEffectiveThrownType() const {
if (auto fnType = getType()->getAs<AnyFunctionType>())
return fnType->getEffectiveThrownErrorType();
return std::nullopt;
}
bool AbstractClosureExpr::isBodyThrowing() const {
if (!getType() || getType()->hasError()) {
// Scan the closure body to infer effects.
if (auto closure = dyn_cast<ClosureExpr>(this)) {
return evaluateOrDefault(
getASTContext().evaluator,
ClosureEffectsRequest{const_cast<ClosureExpr *>(closure)},
FunctionType::ExtInfo()).isThrowing();
}
return false;
}
return getType()->castTo<FunctionType>()->getExtInfo().isThrowing();
}
bool AbstractClosureExpr::isSendable() const {
if (!getType() || getType()->hasError()) {
// Scan the closure body to infer effects.
if (auto closure = dyn_cast<ClosureExpr>(this)) {
return evaluateOrDefault(
getASTContext().evaluator,
ClosureEffectsRequest{const_cast<ClosureExpr *>(closure)},
FunctionType::ExtInfo()).isSendable();
}
return false;
}
return getType()->castTo<FunctionType>()->getExtInfo().isSendable();
}
bool AbstractClosureExpr::isBodyAsync() const {
if (!getType() || getType()->hasError()) {
// Scan the closure body to infer effects.
if (auto closure = dyn_cast<ClosureExpr>(this)) {
return evaluateOrDefault(
getASTContext().evaluator,
ClosureEffectsRequest{const_cast<ClosureExpr *>(closure)},
FunctionType::ExtInfo()).isAsync();
}
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;
}
ActorIsolation
swift::__AbstractClosureExpr_getActorIsolation(AbstractClosureExpr *CE) {
return CE->getActorIsolation();
}
#define FORWARD_SOURCE_LOCS_TO(CLASS, NODE) \
SourceRange CLASS::getSourceRange() const { \
if (!NODE) { return SourceRange(); } \
return (NODE)->getSourceRange(); \
} \
SourceLoc CLASS::getStartLoc() const { \
if (!NODE) { return SourceLoc(); } \
return (NODE)->getStartLoc(); \
} \
SourceLoc CLASS::getEndLoc() const { \
if (!NODE) { return SourceLoc(); } \
return (NODE)->getEndLoc(); \
} \
SourceLoc CLASS::getLoc() const { \
if (!NODE) { return SourceLoc(); } \
return (NODE)->getStartLoc(); \
}
FORWARD_SOURCE_LOCS_TO(ClosureExpr, Body)
Expr *ClosureExpr::getSingleExpressionBody() const {
auto *body = getBody();
if (!body)
return nullptr;
// If we have a lone expression, use it.
if (auto *E = body->getSingleActiveExpression())
return E;
// Otherwise we must have a return of an expression.
auto elt = body->getSingleActiveStatement();
if (!elt)
return nullptr;
// Any lone ReturnStmt, even explicit, is treated as a single expression body.
auto *RS = dyn_cast<ReturnStmt>(elt);
if (!RS || !RS->hasResult())
return nullptr;
return RS->getResult();
}
bool ClosureExpr::hasEmptyBody() const {
return getBody()->empty();
}
Type ClosureExpr::getExplicitThrownType() const {
if (getThrowsLoc().isInvalid())
return Type();
ASTContext &ctx = getASTContext();
auto mutableThis = const_cast<ClosureExpr *>(this);
ExplicitCaughtTypeRequest request{&ctx, mutableThis};
return evaluateOrDefault(ctx.evaluator, request, Type());
}
void ClosureExpr::setExplicitResultType(Type ty) {
assert(ty && !ty->hasTypeVariable() && !ty->hasPlaceholder());
ExplicitResultTypeAndBodyState.getPointer()
->setType(MetatypeType::get(ty));
}
MacroDecl *
ClosureExpr::getResolvedMacro(CustomAttr *customAttr) {
auto &ctx = getASTContext();
auto declRef = evaluateOrDefault(
ctx.evaluator,
ResolveMacroRequest{customAttr, this},
ConcreteDeclRef());
return dyn_cast_or_null<MacroDecl>(declRef.getDecl());
}
FORWARD_SOURCE_LOCS_TO(AutoClosureExpr, Body)
void AutoClosureExpr::setBody(Expr *E) {
auto &Context = getASTContext();
auto *RS = ReturnStmt::createImplicit(Context, E);
Body = BraceStmt::create(Context, E->getStartLoc(), { RS }, E->getEndLoc());
}
Expr *AutoClosureExpr::getSingleExpressionBody() const {
return cast<ReturnStmt>(Body->getLastElement().get<Stmt *>())->getResult();
}
Expr *AutoClosureExpr::getUnwrappedCurryThunkExpr() const {
auto maybeUnwrapOpenExistential = [](Expr *expr) {
if (auto *openExistential = dyn_cast<OpenExistentialExpr>(expr)) {
expr = openExistential->getSubExpr()->getSemanticsProvidingExpr();
if (auto *ICE = dyn_cast<ImplicitConversionExpr>(expr))
expr = ICE->getSyntacticSubExpr();
}
return expr;
};
auto maybeUnwrapOptionalEval = [](Expr *expr) {
if (auto optEval = dyn_cast<OptionalEvaluationExpr>(expr))
expr = optEval->getSubExpr();
if (auto inject = dyn_cast<InjectIntoOptionalExpr>(expr))
expr = inject->getSubExpr();
if (auto erasure = dyn_cast<ErasureExpr>(expr))
expr = erasure->getSubExpr();
if (auto bind = dyn_cast<BindOptionalExpr>(expr))
expr = bind->getSubExpr();
return expr;
};
auto maybeUnwrapConversions = [](Expr *expr) {
if (auto *covariantReturn = dyn_cast<CovariantReturnConversionExpr>(expr))
expr = covariantReturn->getSubExpr();
if (auto *functionConversion = dyn_cast<FunctionConversionExpr>(expr))
expr = functionConversion->getSubExpr();
return expr;
};
switch (getThunkKind()) {
case AutoClosureExpr::Kind::None:
case AutoClosureExpr::Kind::AsyncLet:
break;
case AutoClosureExpr::Kind::SingleCurryThunk: {
auto *body = getSingleExpressionBody();
body = body->getSemanticsProvidingExpr();
body = maybeUnwrapOpenExistential(body);
body = maybeUnwrapOptionalEval(body);
body = maybeUnwrapConversions(body);
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();
innerBody = maybeUnwrapOpenExistential(innerBody);
innerBody = maybeUnwrapOptionalEval(innerBody);
innerBody = maybeUnwrapConversions(innerBody);
if (auto *outerCall = dyn_cast<ApplyExpr>(innerBody)) {
auto outerFn = maybeUnwrapConversions(outerCall->getFn());
if (auto *innerCall = dyn_cast<ApplyExpr>(outerFn)) {
return innerCall->getFn();
}
}
}
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 = UnqualifiedIdentTypeRepr::create(C, 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 = UnqualifiedIdentTypeRepr::create(C, 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());
// The base is the parent type.
auto *BaseTR = UnqualifiedIdentTypeRepr::create(C, ParentNameLoc,
Parent->createNameRef());
BaseTR->setValue(Parent, nullptr);
auto *QualIdentTR =
QualifiedIdentTypeRepr::create(C, BaseTR, NameLoc, Decl->createNameRef());
QualIdentTR->setValue(Decl, nullptr);
return new (C) TypeExpr(QualIdentTR);
}
TypeExpr *TypeExpr::createForMemberDecl(TypeRepr *ParentTR, DeclNameLoc NameLoc,
TypeDecl *Decl) {
ASTContext &C = Decl->getASTContext();
auto *QualIdentTR = QualifiedIdentTypeRepr::create(C, ParentTR, NameLoc,
Decl->createNameRef());
QualIdentTR->setValue(Decl, nullptr);
return new (C) TypeExpr(QualIdentTR);
}
TypeExpr *TypeExpr::createForSpecializedDecl(DeclRefTypeRepr *ParentTR,
ArrayRef<TypeRepr *> Args,
SourceRange AngleLocs,
ASTContext &C) {
DeclRefTypeRepr *specializedTR = nullptr;
auto *boundDecl = ParentTR->getBoundDecl();
if (!boundDecl || ParentTR->hasGenericArgList()) {
return nullptr;
}
if (isa<UnqualifiedIdentTypeRepr>(ParentTR)) {
specializedTR = UnqualifiedIdentTypeRepr::create(
C, ParentTR->getNameLoc(), ParentTR->getNameRef(), Args, AngleLocs);
specializedTR->setValue(boundDecl, ParentTR->getDeclContext());
} else {
auto *const qualIdentTR = cast<QualifiedIdentTypeRepr>(ParentTR);
specializedTR = QualifiedIdentTypeRepr::create(
C, qualIdentTR->getBase(), ParentTR->getNameLoc(),
ParentTR->getNameRef(), Args, AngleLocs);
specializedTR->setValue(boundDecl, ParentTR->getDeclContext());
}
return new (C) TypeExpr(specializedTR);
}
// 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;
}
TypeValueExpr *TypeValueExpr::createForDecl(DeclNameLoc loc, TypeDecl *decl,
DeclContext *dc) {
auto &ctx = decl->getASTContext();
ASSERT(loc.isValid());
auto repr = UnqualifiedIdentTypeRepr::create(ctx, loc, decl->createNameRef());
repr->setValue(decl, dc);
return new (ctx) TypeValueExpr(repr);
}
GenericTypeParamDecl *TypeValueExpr::getParamDecl() const {
auto declRefRepr = cast<DeclRefTypeRepr>(getRepr());
return cast<GenericTypeParamDecl>(declRefRepr->getBoundDecl());
}
SourceRange TypeValueExpr::getSourceRange() const {
return getRepr()->getSourceRange();
}
ExistentialArchetypeType *OpenExistentialExpr::getOpenedArchetype() const {
auto type = getOpaqueValue()->getType()->getRValueType();
while (auto metaTy = type->getAs<MetatypeType>())
type = metaTy->getInstanceType();
return type->castTo<ExistentialArchetypeType>();
}
KeyPathExpr::KeyPathExpr(SourceLoc startLoc, Expr *parsedRoot,
Expr *parsedPath, SourceLoc endLoc, bool hasLeadingDot,
bool isObjC, bool isImplicit)
: Expr(ExprKind::KeyPath, isImplicit), StartLoc(startLoc), EndLoc(endLoc),
ParsedRoot(parsedRoot), ParsedPath(parsedPath),
HasLeadingDot(hasLeadingDot) {
assert(!(isObjC && (parsedRoot || parsedPath)) &&
"Obj-C key paths should only have components");
Bits.KeyPathExpr.IsObjC = isObjC;
}
KeyPathExpr::KeyPathExpr(SourceLoc backslashLoc, Expr *parsedRoot,
Expr *parsedPath, bool hasLeadingDot, bool isImplicit)
: KeyPathExpr(backslashLoc, parsedRoot, parsedPath,
parsedPath ? parsedPath->getEndLoc()
: parsedRoot->getEndLoc(),
hasLeadingDot, /*isObjC*/ false, isImplicit) {
assert((parsedRoot || parsedPath) &&
"Key path must have either root or path");
}
KeyPathExpr::KeyPathExpr(ASTContext &ctx, SourceLoc startLoc,
ArrayRef<Component> components, SourceLoc endLoc,
bool isObjC, bool isImplicit)
: KeyPathExpr(startLoc, /*parsedRoot*/ nullptr, /*parsedPath*/ nullptr,
endLoc, /*hasLeadingDot*/ false, isObjC, isImplicit) {
assert(!components.empty());
Components = ctx.AllocateCopy(components);
}
KeyPathExpr *KeyPathExpr::createParsedPoundKeyPath(
ASTContext &ctx, SourceLoc keywordLoc, SourceLoc lParenLoc,
ArrayRef<Component> components, SourceLoc rParenLoc) {
return new (ctx) KeyPathExpr(ctx, keywordLoc, components, rParenLoc,
/*isObjC*/ true, /*isImplicit*/ false);
}
KeyPathExpr *KeyPathExpr::createParsed(ASTContext &ctx, SourceLoc backslashLoc,
Expr *parsedRoot, Expr *parsedPath,
bool hasLeadingDot) {
return new (ctx) KeyPathExpr(backslashLoc, parsedRoot, parsedPath,
hasLeadingDot, /*isImplicit*/ false);
}
KeyPathExpr *KeyPathExpr::createImplicit(ASTContext &ctx,
SourceLoc backslashLoc,
ArrayRef<Component> components,
SourceLoc endLoc) {
return new (ctx) KeyPathExpr(ctx, backslashLoc, components, endLoc,
/*isObjC*/ false, /*isImplicit*/ true);
}
KeyPathExpr *KeyPathExpr::createImplicit(ASTContext &ctx,
SourceLoc backslashLoc,
Expr *parsedRoot, Expr *parsedPath,
bool hasLeadingDot) {
return new (ctx) KeyPathExpr(backslashLoc, parsedRoot, parsedPath,
hasLeadingDot, /*isImplicit*/ true);
}
void
KeyPathExpr::setComponents(ASTContext &C,
ArrayRef<KeyPathExpr::Component> newComponents) {
// Reallocate the components array if it needs to be.
if (Components.size() < newComponents.size()) {
Components = C.Allocate<Component>(newComponents.size());
for (unsigned i : indices(Components)) {
::new ((void*)&Components[i]) Component{};
}
}
for (unsigned i : indices(newComponents)) {
Components[i] = newComponents[i];
}
Components = Components.slice(0, newComponents.size());
}
std::optional<unsigned> KeyPathExpr::findComponentWithSubscriptArg(Expr *arg) {
for (auto idx : indices(getComponents())) {
if (auto *args = getComponents()[idx].getArgs()) {
if (args->findArgumentExpr(arg))
return idx;
}
}
return std::nullopt;
}
BoundGenericType *KeyPathExpr::getKeyPathType() const {
auto type = getType();
if (!type)
return nullptr;
if (auto *existentialTy = type->getAs<ExistentialType>()) {
auto *sendableTy =
existentialTy->getConstraintType()->castTo<ProtocolCompositionType>();
assert(sendableTy->getMembers().size() == 2);
type = sendableTy->getExistentialLayout().explicitSuperclass;
assert(type->isKeyPath() || type->isWritableKeyPath() ||
type->isReferenceWritableKeyPath());
}
return type->castTo<BoundGenericType>();
}
Type KeyPathExpr::getRootType() const {
auto keyPathTy = getKeyPathType();
assert(keyPathTy && "key path type has not been set yet");
return keyPathTy->getGenericArgs()[0];
}
Type KeyPathExpr::getValueType() const {
auto keyPathTy = getKeyPathType();
assert(keyPathTy && "key path type has not been set yet");
return keyPathTy->getGenericArgs()[1];
}
KeyPathExpr::Component KeyPathExpr::Component::forSubscript(
ASTContext &ctx, ConcreteDeclRef subscript, ArgumentList *argList,
Type elementType, ArrayRef<ProtocolConformanceRef> indexHashables) {
return Component(subscript, argList, indexHashables, Kind::Subscript,
elementType, argList->getLParenLoc());
}
KeyPathExpr::Component
KeyPathExpr::Component::forUnresolvedSubscript(ASTContext &ctx,
ArgumentList *argList) {
return Component({}, argList, {}, Kind::UnresolvedSubscript, Type(),
argList->getLParenLoc());
}
KeyPathExpr::Component::Component(
DeclNameOrRef decl, ArgumentList *argList,
ArrayRef<ProtocolConformanceRef> indexHashables, Kind kind, Type type,
SourceLoc loc)
: Decl(decl), ArgList(argList), KindValue(kind), ComponentType(type),
Loc(loc) {
assert(kind == Kind::Subscript || kind == Kind::UnresolvedSubscript ||
kind == Kind::UnresolvedApply || kind == Kind::Apply);
assert(argList);
assert(argList->size() == indexHashables.size() || indexHashables.empty());
HashableConformancesData =
indexHashables.empty() ? nullptr : indexHashables.data();
}
SingleValueStmtExpr *SingleValueStmtExpr::create(ASTContext &ctx, Stmt *S,
DeclContext *DC) {
return new (ctx) SingleValueStmtExpr(S, DC);
}
SingleValueStmtExpr *SingleValueStmtExpr::createWithWrappedBranches(
ASTContext &ctx, Stmt *S, DeclContext *DC, bool mustBeExpr) {
assert(!(isa<DoStmt>(S) || isa<DoCatchStmt>(S)) ||
ctx.LangOpts.hasFeature(Feature::DoExpressions));
auto *SVE = create(ctx, S, DC);
// Attempt to wrap any branches that can be wrapped.
SmallVector<Stmt *, 4> scratch;
for (auto *branch : SVE->getBranches(scratch)) {
auto *BS = dyn_cast<BraceStmt>(branch);
if (!BS)
continue;
// Check to see if we can wrap an implicit last element of the brace.
if (!isLastElementImplicitResult(BS, ctx, mustBeExpr))
continue;
auto &result = BS->getElements().back();
assert(result.is<Expr *>() || result.is<Stmt *>());
// Wrap a statement in a SingleValueStmtExpr.
if (auto *S = result.dyn_cast<Stmt *>()) {
result = SingleValueStmtExpr::createWithWrappedBranches(ctx, S, DC,
mustBeExpr);
}
// Wrap an expression in an implicit 'then <expr>'.
if (auto *E = result.dyn_cast<Expr *>())
result = ThenStmt::createImplicit(ctx, E);
}
return SVE;
}
SingleValueStmtExpr *
SingleValueStmtExpr::tryDigOutSingleValueStmtExpr(Expr *E) {
class SVEFinder final : public ASTWalker {
public:
SingleValueStmtExpr *FoundSVE = nullptr;
PreWalkResult<Expr *> walkToExprPre(Expr *E) override {
if (auto *SVE = dyn_cast<SingleValueStmtExpr>(E)) {
FoundSVE = SVE;
return Action::Stop();
}
// Look through implicit exprs.
if (E->isImplicit())
return Action::Continue(E);
// Look through coercions.
if (isa<CoerceExpr>(E))
return Action::Continue(E);
// Look through try/await/unsafe (this is invalid, but we'll error on
// it in effect checking).
if (isa<AnyTryExpr>(E) || isa<AwaitExpr>(E) || isa<UnsafeExpr>(E))
return Action::Continue(E);
return Action::Stop();
}
PreWalkResult<Stmt *> walkToStmtPre(Stmt *S) override {
return Action::Stop();
}
PreWalkAction walkToDeclPre(Decl *D) override {
return Action::Stop();
}
PreWalkResult<Pattern *> walkToPatternPre(Pattern *P) override {
return Action::Stop();
}
PreWalkAction walkToTypeReprPre(TypeRepr *T) override {
return Action::Stop();
}
};
SVEFinder finder;
E->walk(finder);
return finder.FoundSVE;
}
bool SingleValueStmtExpr::isLastElementImplicitResult(
BraceStmt *BS, ASTContext &ctx, bool mustBeSingleValueStmt) {
if (BS->empty())
return false;
// We must either be allowing implicit last expressions, or we must have a
// single active element, which is guaranteed to be the last element.
if (!ctx.LangOpts.hasFeature(Feature::ImplicitLastExprResults) &&
!BS->getSingleActiveElement()) {
return false;
}
auto elt = BS->getLastElement();
// Expressions are always valid.
if (elt.is<Expr *>())
return true;
if (auto *S = elt.dyn_cast<Stmt *>()) {
if (mustBeSingleValueStmt) {
// If this must be a SingleValueStmtExpr, we can eagerly take any
// exhaustive if, switch, and do statement.
if (auto *IS = dyn_cast<IfStmt>(S))
return IS->isSyntacticallyExhaustive();
// Guaranteed to be exhaustive.
if (isa<SwitchStmt>(S))
return true;
if (ctx.LangOpts.hasFeature(Feature::DoExpressions)) {
if (auto *DCS = dyn_cast<DoCatchStmt>(S))
return DCS->isSyntacticallyExhaustive();
if (isa<DoStmt>(S))
return true;
}
return false;
}
// Otherwise do the semantic checking to verify the statement produces
// a single value.
return S->mayProduceSingleValue(ctx).isValid();
}
return false;
}
ThenStmt *SingleValueStmtExpr::getThenStmtFrom(BraceStmt *BS) {
if (BS->empty())
return nullptr;
// Must be the last statement in the brace.
return dyn_cast_or_null<ThenStmt>(BS->getLastElement().dyn_cast<Stmt *>());
}
SourceRange SingleValueStmtExpr::getSourceRange() const {
return S->getSourceRange();
}
SingleValueStmtExpr::Kind SingleValueStmtExpr::getStmtKind() const {
switch (getStmt()->getKind()) {
case StmtKind::If:
return Kind::If;
case StmtKind::Switch:
return Kind::Switch;
case StmtKind::Do:
return Kind::Do;
case StmtKind::DoCatch:
return Kind::DoCatch;
default:
llvm_unreachable("Unhandled kind!");
}
}
ArrayRef<Stmt *>
SingleValueStmtExpr::getBranches(SmallVectorImpl<Stmt *> &scratch) const {
assert(scratch.empty());
switch (getStmtKind()) {
case Kind::If:
return cast<IfStmt>(getStmt())->getBranches(scratch);
case Kind::Switch:
return cast<SwitchStmt>(getStmt())->getBranches(scratch);
case Kind::Do:
scratch.push_back(cast<DoStmt>(getStmt())->getBody());
return scratch;
case Kind::DoCatch:
return cast<DoCatchStmt>(getStmt())->getBranches(scratch);
}
llvm_unreachable("Unhandled case in switch!");
}
ArrayRef<ThenStmt *> SingleValueStmtExpr::getThenStmts(
SmallVectorImpl<ThenStmt *> &scratch) const {
assert(scratch.empty());
SmallVector<Stmt *, 4> stmtScratch;
for (auto *branch : getBranches(stmtScratch)) {
auto *BS = dyn_cast<BraceStmt>(branch);
if (!BS)
continue;
if (auto *TS = getThenStmtFrom(BS))
scratch.push_back(TS);
}
return scratch;
}
ArrayRef<Expr *> SingleValueStmtExpr::getResultExprs(
SmallVectorImpl<Expr *> &scratch) const {
assert(scratch.empty());
SmallVector<ThenStmt *, 4> stmtScratch;
for (auto *TS : getThenStmts(stmtScratch))
scratch.push_back(TS->getResult());
return scratch;
}
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) {
assert(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 *>());
}
SourceRange TapExpr::getSourceRange() const {
if (!SubExpr)
return Body->getSourceRange();
return SourceRange::combine(SubExpr->getSourceRange(),
Body->getSourceRange());
}
RegexLiteralExpr *RegexLiteralExpr::createParsed(ASTContext &ctx, SourceLoc loc,
StringRef regexText) {
return new (ctx) RegexLiteralExpr(&ctx, loc, regexText, /*implicit*/ false);
}
StringRef RegexLiteralExpr::getRegexToEmit() const {
auto &eval = getASTContext().evaluator;
return evaluateOrDefault(eval, RegexLiteralPatternInfoRequest{this}, {})
.RegexToEmit;
}
Type RegexLiteralExpr::getRegexType() const {
auto &eval = getASTContext().evaluator;
return evaluateOrDefault(eval, RegexLiteralPatternInfoRequest{this}, {})
.RegexType;
}
unsigned RegexLiteralExpr::getVersion() const {
auto &eval = getASTContext().evaluator;
return evaluateOrDefault(eval, RegexLiteralPatternInfoRequest{this}, {})
.Version;
}
ArrayRef<RegexLiteralPatternFeature>
RegexLiteralExpr::getPatternFeatures() const {
auto &eval = getASTContext().evaluator;
return evaluateOrDefault(eval, RegexLiteralPatternInfoRequest{this}, {})
.Features;
}
StringRef
RegexLiteralPatternFeatureKind::getDescription(ASTContext &ctx) const {
auto &eval = ctx.evaluator;
return evaluateOrDefault(
eval, RegexLiteralFeatureDescriptionRequest{*this, &ctx}, {});
}
AvailabilityRange
RegexLiteralPatternFeatureKind::getAvailability(ASTContext &ctx) const {
auto &eval = ctx.evaluator;
return evaluateOrDefault(eval,
RegexLiteralFeatureAvailabilityRequest{*this, &ctx},
AvailabilityRange::alwaysAvailable());
}
TypeJoinExpr::TypeJoinExpr(llvm::PointerUnion<DeclRefExpr *, TypeBase *> result,
ArrayRef<Expr *> elements, SingleValueStmtExpr *SVE)
: Expr(ExprKind::TypeJoin, /*implicit=*/true, Type()), Var(nullptr),
SVE(SVE) {
if (auto *varRef = result.dyn_cast<DeclRefExpr *>()) {
assert(varRef);
Var = varRef;
} else {
auto joinType = Type(result.get<TypeBase *>());
assert(joinType && "expected non-null type");
setType(joinType);
}
Bits.TypeJoinExpr.NumElements = elements.size();
// Copy elements.
std::uninitialized_copy(elements.begin(), elements.end(),
getTrailingObjects<Expr *>());
}
TypeJoinExpr *TypeJoinExpr::createImpl(
ASTContext &ctx, llvm::PointerUnion<DeclRefExpr *, TypeBase *> varOrType,
ArrayRef<Expr *> elements, AllocationArena arena,
SingleValueStmtExpr *SVE) {
size_t size = totalSizeToAlloc<Expr *>(elements.size());
void *mem = ctx.Allocate(size, alignof(TypeJoinExpr), arena);
return new (mem) TypeJoinExpr(varOrType, elements, SVE);
}
TypeJoinExpr *
TypeJoinExpr::forBranchesOfSingleValueStmtExpr(ASTContext &ctx, Type joinType,
SingleValueStmtExpr *SVE,
AllocationArena arena) {
return createImpl(ctx, joinType.getPointer(), /*elements*/ {}, arena, SVE);
}
MacroExpansionExpr *MacroExpansionExpr::create(
DeclContext *dc, SourceLoc sigilLoc,
DeclNameRef moduleName, DeclNameLoc moduleNameLoc,
DeclNameRef macroName, DeclNameLoc macroNameLoc,
SourceLoc leftAngleLoc,
ArrayRef<TypeRepr *> genericArgs, SourceLoc rightAngleLoc,
ArgumentList *argList, MacroRoles roles, bool isImplicit,
Type ty
) {
ASTContext &ctx = dc->getASTContext();
MacroExpansionInfo *info = new (ctx) MacroExpansionInfo{
sigilLoc,
moduleName,
moduleNameLoc,
macroName,
macroNameLoc,
leftAngleLoc,
rightAngleLoc,
genericArgs,
argList ? argList : ArgumentList::createImplicit(ctx, {})};
return new (ctx) MacroExpansionExpr(dc, info, roles, isImplicit, ty);
}
MacroExpansionDecl *MacroExpansionExpr::createSubstituteDecl() {
auto dc = DC;
if (auto *tlcd = dyn_cast_or_null<TopLevelCodeDecl>(dc->getAsDecl()))
dc = tlcd->getDeclContext();
SubstituteDecl =
new (DC->getASTContext()) MacroExpansionDecl(dc, getExpansionInfo());
return SubstituteDecl;
}
MacroExpansionDecl *MacroExpansionExpr::getSubstituteDecl() const {
return SubstituteDecl;
}
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());
}
void swift::simple_display(llvm::raw_ostream &out,
const Expr *expr) {
out << "expression";
}
SourceLoc swift::extractNearestSourceLoc(const ClosureExpr *expr) {
return expr->getLoc();
}
SourceLoc swift::extractNearestSourceLoc(const Expr *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;
}
Expr *Expr::getAlwaysLeftFoldedSubExpr() const {
if (auto *ATE = dyn_cast<AnyTryExpr>(this))
return ATE->getSubExpr();
if (auto *AE = dyn_cast<AwaitExpr>(this))
return AE->getSubExpr();
if (auto *UE = dyn_cast<UnsafeExpr>(this))
return UE->getSubExpr();
return nullptr;
}
const Expr *Expr::findOriginalValue() const {
auto *expr = this;
do {
expr = expr->getSemanticsProvidingExpr();
if (auto inout = dyn_cast<InOutExpr>(expr)) {
expr = inout->getSubExpr();
continue;
}
if (auto ice = dyn_cast<ImplicitConversionExpr>(expr)) {
expr = ice->getSubExpr();
continue;
}
if (auto open = dyn_cast<OpenExistentialExpr>(expr)) {
expr = open->getSubExpr();
continue;
}
break;
} while (true);
return expr;
}
Type Expr::findOriginalType() const {
auto *expr = findOriginalValue();
return expr->getType()->getRValueType();
}
ThrownErrorDestination
ThrownErrorDestination::forConversion(OpaqueValueExpr *thrownError,
Expr *conversion) {
ASTContext &ctx = thrownError->getType()->getASTContext();
auto conversionStorage = ctx.Allocate<Conversion>();
conversionStorage->thrownError = thrownError;
conversionStorage->conversion = conversion;
return ThrownErrorDestination(conversionStorage);
}
Type ThrownErrorDestination::getThrownErrorType() const {
if (!*this)
return Type();
if (auto type = storage.dyn_cast<TypeBase *>())
return Type(type);
auto conversion = storage.get<Conversion *>();
return conversion->thrownError->getType();
}
Type ThrownErrorDestination::getContextErrorType() const {
if (!*this)
return Type();
if (auto type = storage.dyn_cast<TypeBase *>())
return Type(type);
auto conversion = storage.get<Conversion *>();
return conversion->conversion->getType();
}
void AbstractClosureExpr::getIsolationCrossing(
SmallVectorImpl<std::tuple<CapturedValue, unsigned, ApplyIsolationCrossing>>
&foundIsolationCrossings) {
/// For each capture...
for (auto pair : llvm::enumerate(getCaptureInfo().getCaptures())) {
auto capture = pair.value();
// First check quickly if we have dynamic self metadata. This is Sendable
// data so we don't care about it.
if (capture.isDynamicSelfMetadata())
continue;
auto declIsolation = swift::getActorIsolation(capture.getDecl());
// Assert that we do not have an opaque value capture. These only appear in
// TypeLowering and should never appear in the AST itself.
assert(!capture.getOpaqueValue() &&
"This should only be created in TypeLowering");
// If our decl is actor isolated...
if (declIsolation.isActorIsolated()) {
// And our closure is also actor isolated, then add the apply isolation
// crossing if the actors are different.
if (actorIsolation.isActorIsolated()) {
if (declIsolation.getActor() == actorIsolation.getActor()) {
continue;
}
foundIsolationCrossings.emplace_back(
capture, pair.index(),
ApplyIsolationCrossing(declIsolation, actorIsolation));
continue;
}
// Otherwise, our closure is not actor isolated but our decl is actor
// isolated. Add it.
foundIsolationCrossings.emplace_back(
capture, pair.index(),
ApplyIsolationCrossing(declIsolation, actorIsolation));
continue;
}
if (!actorIsolation.isActorIsolated()) {
continue;
}
foundIsolationCrossings.emplace_back(
capture, pair.index(),
ApplyIsolationCrossing(declIsolation, actorIsolation));
}
}