//===--- Expr.cpp - Swift Language Expression ASTs ------------------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See http://swift.org/LICENSE.txt for license information // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// // // This file implements the Expr class and subclasses. // //===----------------------------------------------------------------------===// #include "swift/AST/Expr.h" #include "swift/Basic/Unicode.h" #include "swift/AST/Decl.h" // FIXME: Bad dependency #include "swift/AST/Stmt.h" #include "swift/AST/AST.h" #include "swift/AST/ASTWalker.h" #include "swift/AST/AvailabilitySpec.h" #include "swift/AST/PrettyStackTrace.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; //===----------------------------------------------------------------------===// // Expr methods. //===----------------------------------------------------------------------===// // Only allow allocation of Stmts using the allocator in ASTContext. void *Expr::operator new(size_t Bytes, ASTContext &C, unsigned Alignment) { return C.Allocate(Bytes, Alignment); } StringRef Expr::getKindName(ExprKind K) { switch (K) { #define EXPR(Id, Parent) case ExprKind::Id: return #Id; #include "swift/AST/ExprNodes.def" } llvm_unreachable("bad ExprKind"); } template static SourceLoc getStartLocImpl(const T *E); template static SourceLoc getEndLocImpl(const T *E); template 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 constexpr bool isOverriddenFromExpr(ReturnType (Class::*)() const) { return true; } template constexpr bool isOverriddenFromExpr(ReturnType (Expr::*)() const) { return false; } template struct Dispatch; /// Dispatch down to a concrete override. template <> struct Dispatch { template static SourceLoc getStartLoc(const T *E) { return E->getStartLoc(); } template static SourceLoc getEndLoc(const T *E) { return E->getEndLoc(); } template static SourceLoc getLoc(const T *E) { return E->getLoc(); } template static SourceRange getSourceRange(const T *E) { return E->getSourceRange(); } }; /// Default implementations for when a method isn't overridden. template <> struct Dispatch { template static SourceLoc getStartLoc(const T *E) { return E->getSourceRange().Start; } template static SourceLoc getEndLoc(const T *E) { return E->getSourceRange().End; } template static SourceLoc getLoc(const T *E) { return getStartLocImpl(E); } template static SourceRange getSourceRange(const T *E) { return { E->getStartLoc(), E->getEndLoc() }; } }; } template 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::getSourceRange(E); } SourceRange Expr::getSourceRange() const { switch (getKind()) { #define EXPR(ID, PARENT) \ case ExprKind::ID: return getSourceRangeImpl(cast(this)); #include "swift/AST/ExprNodes.def" } llvm_unreachable("expression type not handled!"); } template static SourceLoc getStartLocImpl(const T *E) { return Dispatch::getStartLoc(E); } SourceLoc Expr::getStartLoc() const { switch (getKind()) { #define EXPR(ID, PARENT) \ case ExprKind::ID: return getStartLocImpl(cast(this)); #include "swift/AST/ExprNodes.def" } llvm_unreachable("expression type not handled!"); } template static SourceLoc getEndLocImpl(const T *E) { return Dispatch::getEndLoc(E); } SourceLoc Expr::getEndLoc() const { switch (getKind()) { #define EXPR(ID, PARENT) \ case ExprKind::ID: return getEndLocImpl(cast(this)); #include "swift/AST/ExprNodes.def" } llvm_unreachable("expression type not handled!"); } template static SourceLoc getLocImpl(const T *E) { return Dispatch::getLoc(E); } SourceLoc Expr::getLoc() const { switch (getKind()) { #define EXPR(ID, PARENT) \ case ExprKind::ID: return getLocImpl(cast(this)); #include "swift/AST/ExprNodes.def" } llvm_unreachable("expression type not handled!"); } Expr *Expr::getSemanticsProvidingExpr() { if (IdentityExpr *IE = dyn_cast(this)) return IE->getSubExpr()->getSemanticsProvidingExpr(); if (DefaultValueExpr *DE = dyn_cast(this)) return DE->getSubExpr()->getSemanticsProvidingExpr(); return this; } Expr *Expr::getValueProvidingExpr() { // For now, this is totally equivalent to the above. // TODO: // - tuple literal projection, which may become interestingly idiomatic return getSemanticsProvidingExpr(); } Initializer *Expr::findExistingInitializerContext() { struct FindExistingInitializer : ASTWalker { Initializer *TheInitializer = nullptr; std::pair walkToExprPre(Expr *E) override { assert(!TheInitializer && "continuing to walk after finding context?"); if (auto closure = dyn_cast(E)) { TheInitializer = cast(closure->getParent()); return { false, nullptr }; } return { true, E }; } } finder; walk(finder); return finder.TheInitializer; } bool Expr::isStaticallyDerivedMetatype() const { // IF the result isn't a metatype, there's nothing else to do. if (!getType()->is()) return false; const Expr *expr = this; do { // Skip syntax. expr = expr->getSemanticsProvidingExpr(); // Direct reference to a type. if (auto declRef = dyn_cast(expr)) return isa(declRef->getDecl()); if (isa(expr)) return true; // A "." expression that refers to a member. if (auto memberRef = dyn_cast(expr)) return isa(memberRef->getMember().getDecl()); // When the base of a "." expression is ignored, look at the member. if (auto ignoredDot = dyn_cast(expr)) { expr = ignoredDot->getRHS(); continue; } // Anything else is not statically derived. return false; } while (true); } bool Expr::isSuperExpr() const { const Expr *expr = this; do { expr = expr->getSemanticsProvidingExpr(); if (isa(expr)) return true; if (auto derivedToBase = dyn_cast(expr)) { expr = derivedToBase->getSubExpr(); continue; } if (auto metatypeConversion = dyn_cast(expr)) { expr = metatypeConversion->getSubExpr(); continue; } return false; } while (true); } bool Expr::canAppendCallParentheses() const { switch (getKind()) { case ExprKind::Error: return false; case ExprKind::NilLiteral: case ExprKind::IntegerLiteral: case ExprKind::FloatLiteral: case ExprKind::BooleanLiteral: case ExprKind::CharacterLiteral: case ExprKind::StringLiteral: case ExprKind::InterpolatedStringLiteral: case ExprKind::MagicIdentifierLiteral: return true; case ExprKind::DiscardAssignment: // Legal but pointless. return true; case ExprKind::DeclRef: return !cast(this)->getDecl()->getName().isOperator(); case ExprKind::SuperRef: case ExprKind::Type: case ExprKind::OtherConstructorDeclRef: case ExprKind::UnresolvedConstructor: case ExprKind::DotSyntaxBaseIgnored: return true; case ExprKind::OverloadedDeclRef: { auto *overloadedExpr = cast(this); if (overloadedExpr->getDecls().empty()) return false; return !overloadedExpr->getDecls().front()->getName().isOperator(); } case ExprKind::OverloadedMemberRef: return true; case ExprKind::UnresolvedDeclRef: return cast(this)->getName().isOperator(); case ExprKind::MemberRef: case ExprKind::DynamicMemberRef: case ExprKind::DynamicSubscript: case ExprKind::UnresolvedSpecialize: case ExprKind::UnresolvedMember: case ExprKind::UnresolvedDot: case ExprKind::UnresolvedSelector: return true; case ExprKind::Sequence: return false; case ExprKind::Paren: case ExprKind::DotSelf: case ExprKind::Tuple: case ExprKind::Array: case ExprKind::Dictionary: case ExprKind::Subscript: case ExprKind::TupleElement: return true; case ExprKind::CaptureList: case ExprKind::Closure: case ExprKind::AutoClosure: return false; case ExprKind::Module: case ExprKind::DynamicType: return true; case ExprKind::Throw: case ExprKind::Try: case ExprKind::InOut: return false; case ExprKind::RebindSelfInConstructor: case ExprKind::OpaqueValue: case ExprKind::BindOptional: case ExprKind::OptionalEvaluation: return false; case ExprKind::ForceValue: return true; case ExprKind::OpenExistential: return false; case ExprKind::Call: case ExprKind::PostfixUnary: case ExprKind::DotSyntaxCall: case ExprKind::ConstructorRefCall: return true; case ExprKind::PrefixUnary: case ExprKind::Binary: return false; case ExprKind::Load: case ExprKind::TupleShuffle: case ExprKind::FunctionConversion: case ExprKind::CovariantFunctionConversion: case ExprKind::CovariantReturnConversion: case ExprKind::MetatypeConversion: case ExprKind::CollectionUpcastConversion: case ExprKind::Erasure: case ExprKind::MetatypeErasure: case ExprKind::DerivedToBase: case ExprKind::ArchetypeToSuper: case ExprKind::ScalarToTuple: case ExprKind::InjectIntoOptional: case ExprKind::UnavailableToOptional: case ExprKind::ClassMetatypeToObject: case ExprKind::ExistentialMetatypeToObject: case ExprKind::ProtocolMetatypeToObject: case ExprKind::InOutToPointer: case ExprKind::ArrayToPointer: case ExprKind::StringToPointer: case ExprKind::PointerToPointer: case ExprKind::LValueToPointer: case ExprKind::ForeignObjectConversion: return false; case ExprKind::ForcedCheckedCast: case ExprKind::ConditionalCheckedCast: case ExprKind::Is: case ExprKind::Coerce: return false; case ExprKind::If: case ExprKind::Assign: case ExprKind::DefaultValue: case ExprKind::UnresolvedPattern: case ExprKind::AvailabilityQuery: case ExprKind::EditorPlaceholder: return false; } } llvm::DenseMap Expr::getParentMap() { class RecordingTraversal : public ASTWalker { public: llvm::DenseMap &ParentMap; explicit RecordingTraversal(llvm::DenseMap &parentMap) : ParentMap(parentMap) { } virtual std::pair walkToExprPre(Expr *E) { if (auto parent = Parent.getAsExpr()) ParentMap[E] = parent; return { true, E }; } }; llvm::DenseMap parentMap; RecordingTraversal traversal(parentMap); walk(traversal); return parentMap; } //===----------------------------------------------------------------------===// // Support methods for Exprs. //===----------------------------------------------------------------------===// static APInt getIntegerLiteralValue(bool IsNegative, StringRef Text, unsigned BitWidth) { llvm::APInt Value(BitWidth, 0); // swift encodes octal differently from C bool IsCOctal = Text.size() > 1 && Text[0] == '0' && isdigit(Text[1]); bool Error = Text.getAsInteger(IsCOctal ? 10 : 0, Value); assert(!Error && "Invalid IntegerLiteral formed"); (void)Error; if (IsNegative) Value = -Value; if (Value.getBitWidth() != BitWidth) Value = Value.sextOrTrunc(BitWidth); return Value; } APInt IntegerLiteralExpr::getValue(StringRef Text, unsigned BitWidth) { return getIntegerLiteralValue(/*IsNegative=*/false, Text, BitWidth); } APInt IntegerLiteralExpr::getValue() const { assert(!getType().isNull() && "Semantic analysis has not completed"); assert(!getType()->is() && "Should have a valid type"); return getIntegerLiteralValue( isNegative(), getDigitsText(), getType()->castTo()->getGreatestWidth()); } static APFloat getFloatLiteralValue(bool IsNegative, StringRef Text, const llvm::fltSemantics &Semantics) { APFloat Val(Semantics); APFloat::opStatus Res = Val.convertFromString(Text, llvm::APFloat::rmNearestTiesToEven); assert(Res != APFloat::opInvalidOp && "Sema didn't reject invalid number"); (void)Res; if (IsNegative) { auto NegVal = APFloat::getZero(Semantics, /*negative*/ true); Res = NegVal.subtract(Val, llvm::APFloat::rmNearestTiesToEven); assert(Res != APFloat::opInvalidOp && "Sema didn't reject invalid number"); (void)Res; return NegVal; } return Val; } APFloat FloatLiteralExpr::getValue(StringRef Text, const llvm::fltSemantics &Semantics) { return getFloatLiteralValue(/*IsNegative*/false, Text, Semantics); } llvm::APFloat FloatLiteralExpr::getValue() const { assert(!getType().isNull() && "Semantic analysis has not completed"); assert(!getType()->is() && "Should have a valid type"); return getFloatLiteralValue(isNegative(), getDigitsText(), getType()->castTo()->getAPFloatSemantics()); } StringLiteralExpr::StringLiteralExpr(StringRef Val, SourceRange Range) : LiteralExpr(ExprKind::StringLiteral, /*Implicit=*/false), Val(Val), Range(Range) { StringLiteralExprBits.Encoding = static_cast(UTF8); StringLiteralExprBits.IsSingleUnicodeScalar = unicode::isSingleUnicodeScalar(Val); StringLiteralExprBits.IsSingleExtendedGraphemeCluster = unicode::isSingleExtendedGraphemeCluster(Val); } void DeclRefExpr::setDeclRef(ConcreteDeclRef ref) { if (auto spec = getSpecInfo()) spec->D = ref; else DOrSpecialized = ref; } void DeclRefExpr::setSpecialized() { if (isSpecialized()) return; ConcreteDeclRef ref = getDeclRef(); void *Mem = ref.getDecl()->getASTContext().Allocate(sizeof(SpecializeInfo), alignof(SpecializeInfo)); auto Spec = new (Mem) SpecializeInfo; Spec->D = ref; DOrSpecialized = Spec; } void DeclRefExpr::setGenericArgs(ArrayRef GenericArgs) { ValueDecl *D = getDecl(); assert(D); setSpecialized(); getSpecInfo()->GenericArgs = D->getASTContext().AllocateCopy(GenericArgs); } ConstructorDecl *OtherConstructorDeclRefExpr::getDecl() const { return cast_or_null(Ctor.getDecl()); } MemberRefExpr::MemberRefExpr(Expr *base, SourceLoc dotLoc, ConcreteDeclRef member, SourceRange nameRange, bool Implicit, AccessSemantics semantics) : Expr(ExprKind::MemberRef, Implicit), Base(base), Member(member), DotLoc(dotLoc), NameRange(nameRange) { MemberRefExprBits.Semantics = (unsigned) semantics; MemberRefExprBits.IsSuper = false; } Type OverloadSetRefExpr::getBaseType() const { if (isa(this)) return Type(); if (auto *DRE = dyn_cast(this)) { return DRE->getBase()->getType()->getRValueType(); } llvm_unreachable("Unhandled overloaded set reference expression"); } bool OverloadSetRefExpr::hasBaseObject() const { if (Type BaseTy = getBaseType()) return !BaseTy->is(); return false; } SequenceExpr *SequenceExpr::create(ASTContext &ctx, ArrayRef elements) { void *Buffer = ctx.Allocate(sizeof(SequenceExpr) + elements.size() * sizeof(Expr*), alignof(SequenceExpr)); return ::new(Buffer) SequenceExpr(elements); } SourceLoc TupleExpr::getStartLoc() const { if (LParenLoc.isValid()) return LParenLoc; if (getNumElements() == 0) return SourceLoc(); return getElement(0)->getStartLoc(); } SourceLoc TupleExpr::getEndLoc() const { if (hasTrailingClosure() || RParenLoc.isInvalid()) { if (getNumElements() == 0) return SourceLoc(); return getElements().back()->getEndLoc(); } return RParenLoc; } TupleExpr::TupleExpr(SourceLoc LParenLoc, ArrayRef SubExprs, ArrayRef ElementNames, ArrayRef ElementNameLocs, SourceLoc RParenLoc, bool HasTrailingClosure, bool Implicit, Type Ty) : Expr(ExprKind::Tuple, Implicit, Ty), LParenLoc(LParenLoc), RParenLoc(RParenLoc), NumElements(SubExprs.size()) { TupleExprBits.HasTrailingClosure = HasTrailingClosure; TupleExprBits.HasElementNames = !ElementNames.empty(); TupleExprBits.HasElementNameLocations = !ElementNameLocs.empty(); 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. memcpy(getElements().data(), SubExprs.data(), SubExprs.size() * sizeof(Expr *)); // Copy element names, if provided. if (hasElementNames()) { memcpy(getElementNamesBuffer().data(), ElementNames.data(), ElementNames.size() * sizeof(Identifier)); } // Copy element name locations, if provided. if (hasElementNameLocs()) { memcpy(getElementNameLocsBuffer().data(), ElementNameLocs.data(), ElementNameLocs.size() * sizeof(SourceLoc)); } } TupleExpr *TupleExpr::create(ASTContext &ctx, SourceLoc LParenLoc, ArrayRef SubExprs, ArrayRef ElementNames, ArrayRef ElementNameLocs, SourceLoc RParenLoc, bool HasTrailingClosure, bool Implicit, Type Ty) { unsigned size = sizeof(TupleExpr); size += SubExprs.size() * sizeof(Expr*); size += ElementNames.size() * sizeof(Identifier); size += ElementNameLocs.size() * sizeof(SourceLoc); void *mem = ctx.Allocate(size, alignof(TupleExpr)); return new (mem) TupleExpr(LParenLoc, SubExprs, ElementNames, ElementNameLocs, RParenLoc, HasTrailingClosure, Implicit, Ty); } TupleExpr *TupleExpr::createEmpty(ASTContext &ctx, SourceLoc LParenLoc, SourceLoc RParenLoc, bool Implicit) { return create(ctx, LParenLoc, { }, { }, { }, RParenLoc, /*HasTrailingClosure=*/false, Implicit, TupleType::getEmpty(ctx)); } TupleExpr *TupleExpr::createImplicit(ASTContext &ctx, ArrayRef SubExprs, ArrayRef ElementNames) { return create(ctx, SourceLoc(), SubExprs, ElementNames, { }, SourceLoc(), /*HasTrailingClosure=*/false, /*Implicit=*/true, Type()); } ArrayRef CollectionExpr::getElements() const { if (auto paren = dyn_cast(SubExpr)) { // FIXME: Hack. When this goes away, remove IdentityExpr's friendship of // CollectionExpr. return llvm::makeArrayRef(&paren->SubExpr, 1); } if (auto tuple = dyn_cast(SubExpr)) return tuple->getElements(); return llvm::makeArrayRef(&SubExpr, 1); } static ValueDecl *getCalledValue(Expr *E) { if (DeclRefExpr *DRE = dyn_cast(E)) return DRE->getDecl(); Expr *E2 = E->getValueProvidingExpr(); if (E != E2) return getCalledValue(E2); return nullptr; } ValueDecl *ApplyExpr::getCalledValue() const { return ::getCalledValue(Fn); } RebindSelfInConstructorExpr::RebindSelfInConstructorExpr(Expr *SubExpr, VarDecl *Self) : Expr(ExprKind::RebindSelfInConstructor, /*Implicit=*/true, TupleType::getEmpty(Self->getASTContext())), SubExpr(SubExpr), Self(Self) {} void AbstractClosureExpr::setParams(Pattern *P) { ParamPattern = P; // Change the DeclContext of any parameters to be this closure. if (P) { P->forEachVariable([&](VarDecl *VD) { VD->setDeclContext(this); }); } } Type AbstractClosureExpr::getResultType() const { if (getType()->is()) return getType(); return getType()->castTo()->getResult(); } bool AbstractClosureExpr::hasSingleExpressionBody() const { if (auto closure = dyn_cast(this)) return closure->hasSingleExpressionBody(); return true; } #define FORWARD_SOURCE_LOCS_TO(CLASS, NODE) \ SourceRange CLASS::getSourceRange() const { \ return (NODE)->getSourceRange(); \ } \ SourceLoc CLASS::getStartLoc() const { \ return (NODE)->getStartLoc(); \ } \ SourceLoc CLASS::getEndLoc() const { \ return (NODE)->getEndLoc(); \ } \ SourceLoc CLASS::getLoc() const { \ return (NODE)->getStartLoc(); \ } FORWARD_SOURCE_LOCS_TO(ClosureExpr, Body.getPointer()) Expr *ClosureExpr::getSingleExpressionBody() const { assert(hasSingleExpressionBody() && "Not a single-expression body"); return cast(Body.getPointer()->getElements()[0].get()) ->getResult(); } void ClosureExpr::setSingleExpressionBody(Expr *NewBody) { cast(Body.getPointer()->getElements()[0].get()) ->setResult(NewBody); } FORWARD_SOURCE_LOCS_TO(AutoClosureExpr, Body) void AutoClosureExpr::setBody(Expr *E) { auto &Context = getASTContext(); auto *RS = new (Context) ReturnStmt(SourceLoc(), E); Body = BraceStmt::create(Context, E->getStartLoc(), { RS }, E->getEndLoc()); } Expr *AutoClosureExpr::getSingleExpressionBody() const { return cast(Body->getElements()[0].get())->getResult(); } FORWARD_SOURCE_LOCS_TO(UnresolvedPatternExpr, subPattern) UnresolvedSelectorExpr::UnresolvedSelectorExpr(Expr *subExpr, SourceLoc dotLoc, DeclName name, ArrayRef components) : Expr(ExprKind::UnresolvedSelector, /*implicit*/ false), SubExpr(subExpr), DotLoc(dotLoc), Name(name) { assert(name.getArgumentNames().size() + 1 == components.size() && "number of component locs does not match number of name components"); auto buf = getComponentsBuf(); std::uninitialized_copy(components.begin(), components.end(), buf.begin()); } UnresolvedSelectorExpr *UnresolvedSelectorExpr::create(ASTContext &C, Expr *subExpr, SourceLoc dotLoc, DeclName name, ArrayRef components) { assert(name.getArgumentNames().size() + 1 == components.size() && "number of component locs does not match number of name components"); void *buf = C.Allocate(sizeof(UnresolvedSelectorExpr) + (name.getArgumentNames().size() + 1) * sizeof(ComponentLoc), alignof(UnresolvedSelectorExpr)); return ::new (buf) UnresolvedSelectorExpr(subExpr, dotLoc, name, components); } unsigned ScalarToTupleExpr::getScalarField() const { unsigned result = std::find(Elements.begin(), Elements.end(), Element()) - Elements.begin(); assert(result != Elements.size() && "Tuple elements are missing the scalar 'hole'"); return result; } TypeExpr::TypeExpr(TypeLoc TyLoc) : Expr(ExprKind::Type, /*implicit*/false), Info(TyLoc) { Type Ty = TyLoc.getType(); if (Ty && Ty->hasCanonicalTypeComputed()) setType(MetatypeType::get(Ty, Ty->getASTContext())); } TypeExpr::TypeExpr(Type Ty) : Expr(ExprKind::Type, /*implicit*/true), Info(TypeLoc::withoutLoc(Ty)) { if (Ty->hasCanonicalTypeComputed()) setType(MetatypeType::get(Ty, Ty->getASTContext())); } /// Return a TypeExpr for a simple identifier and the specified location. TypeExpr *TypeExpr::createForDecl(SourceLoc Loc, TypeDecl *Decl) { ASTContext &C = Decl->getASTContext(); assert(Loc.isValid()); auto *Repr = new (C) SimpleIdentTypeRepr(Loc, Decl->getName()); Repr->setValue(Decl); return new (C) TypeExpr(TypeLoc(Repr, Type())); } TypeExpr *TypeExpr::createForSpecializedDecl(SourceLoc Loc, TypeDecl *D, ArrayRef args, SourceRange AngleLocs) { ASTContext &C = D->getASTContext(); assert(Loc.isValid()); auto *Repr = new (C) GenericIdentTypeRepr(Loc, D->getName(), args, AngleLocs); Repr->setValue(D); return new (C) TypeExpr(TypeLoc(Repr, Type())); } // 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. if (Loc.isInvalid()) return createImplicit(Ty, C); auto Name = C.getIdentifier("<>"); auto *Repr = new (C) SimpleIdentTypeRepr(Loc, Name); Repr->setValue(Ty); auto *Res = new (C) TypeExpr(TypeLoc(Repr, Ty)); Res->setImplicit(); Res->setType(MetatypeType::get(Ty, C)); return Res; } ArchetypeType *OpenExistentialExpr::getOpenedArchetype() const { auto type = getOpaqueValue()->getType(); if (auto metaTy = type->getAs()) type = metaTy->getInstanceType(); return type->castTo(); } AvailabilityQueryExpr *AvailabilityQueryExpr::create( ASTContext &ctx, SourceLoc PoundLoc, ArrayRef queries, SourceLoc RParenLoc) { unsigned size = sizeof(AvailabilityQueryExpr) + queries.size() * sizeof(VersionConstraintAvailabilitySpec *); void *Buffer = ctx.Allocate(size, alignof(AvailabilityQueryExpr)); return ::new (Buffer) AvailabilityQueryExpr(PoundLoc, queries, RParenLoc); } SourceLoc AvailabilityQueryExpr::getEndLoc() const { if (RParenLoc.isInvalid()) { if (NumQueries == 0) { return PoundLoc; } return getQueries()[NumQueries - 1]->getSourceRange().End; } return RParenLoc; } void AvailabilityQueryExpr::getPlatformKeywordRanges( SmallVectorImpl &PlatformRanges) { for (unsigned int i = 0; i < NumQueries; i ++) { auto Loc = (getQueriesBuf()[i])->getPlatformLoc(); auto Platform = (getQueriesBuf()[i])->getPlatform(); switch (Platform) { case PlatformKind::none: break; #define AVAILABILITY_PLATFORM(X, PrettyName) \ case PlatformKind::X: \ PlatformRanges.push_back(CharSourceRange(Loc, strlen(#X))); \ break; #include "swift/AST/PlatformKinds.def" } } }