mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
3157 lines
103 KiB
C++
3157 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) {
|
|
llvm::errs() << "Closure does not have an assigned discriminator:\n";
|
|
dump(llvm::errs());
|
|
abort();
|
|
}
|
|
|
|
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));
|
|
}
|
|
}
|