//===--- Decl.cpp - Swift Language Decl 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 Decl class and subclasses. // //===----------------------------------------------------------------------===// #include "swift/AST/Decl.h" #include "swift/AST/AST.h" #include "swift/AST/ASTContext.h" #include "swift/AST/Expr.h" #include "swift/AST/TypeLoc.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/Support/raw_ostream.h" using namespace swift; // Only allow allocation of Decls using the allocator in ASTContext. void *Decl::operator new(size_t Bytes, ASTContext &C, unsigned Alignment) { return C.Allocate(Bytes, Alignment); } // Only allow allocation of Modules using the allocator in ASTContext. void *Module::operator new(size_t Bytes, ASTContext &C, unsigned Alignment) { return C.Allocate(Bytes, Alignment); } StringRef Decl::getKindName(DeclKind K) { switch (K) { #define DECL(Id, Parent) case DeclKind::Id: return #Id; #include "swift/AST/DeclNodes.def" } } Module *Decl::getModuleContext() const { return getDeclContext()->getParentModule(); } // Helper functions to verify statically whether source-location // functions have been overridden. typedef const char (&TwoChars)[2]; template inline char checkSourceLocType(SourceLoc (Class::*)() const); inline TwoChars checkSourceLocType(SourceLoc (Decl::*)() const); template inline char checkSourceRangeType(SourceRange (Class::*)() const); inline TwoChars checkSourceRangeType(SourceRange (Decl::*)() const); SourceRange Decl::getSourceRange() const { switch (getKind()) { #define DECL(ID, PARENT) \ static_assert(sizeof(checkSourceRangeType(&ID##Decl::getSourceRange)) == 1, \ #ID "Decl is missing getSourceRange()"); \ case DeclKind::ID: return cast(this)->getSourceRange(); #include "swift/AST/DeclNodes.def" } llvm_unreachable("Unknown decl kind"); } SourceLoc Decl::getLoc() const { switch (getKind()) { #define DECL(ID, X) \ static_assert(sizeof(checkSourceLocType(&ID##Decl::getLoc)) == 1, \ #ID "Decl is missing getLoc()"); \ case DeclKind::ID: return cast(this)->getLoc(); #include "swift/AST/DeclNodes.def" } llvm_unreachable("Unknown decl kind"); } ClangNode Decl::getClangNodeSlow() { return getASTContext().getClangNode(this); } void Decl::setClangNode(ClangNode node) { DeclBits.FromClang = true; getASTContext().setClangNode(this, node); } bool Decl::isTransparent() const { // Check if the declaration had the attribute. if (getAttrs().isTransparent()) return true; // Check if this is a function declaration which is within a transparent // extension. if (const AbstractFunctionDecl *FD = dyn_cast(this)) { // FIXME: This is temporary: we do not support transparent on generics. if (FD->getGenericParams()) return false; if (const ExtensionDecl *ED = dyn_cast(FD->getParent())) return ED->isTransparent(); } return false; } GenericParamList::GenericParamList(SourceLoc LAngleLoc, ArrayRef Params, SourceLoc WhereLoc, MutableArrayRef Requirements, SourceLoc RAngleLoc) : Brackets(LAngleLoc, RAngleLoc), NumParams(Params.size()), WhereLoc(WhereLoc), Requirements(Requirements), OuterParameters(nullptr) { memcpy(this + 1, Params.data(), NumParams * sizeof(GenericParam)); } GenericParamList *GenericParamList::create(ASTContext &Context, SourceLoc LAngleLoc, ArrayRef Params, SourceLoc RAngleLoc) { unsigned Size = sizeof(GenericParamList) + sizeof(GenericParam) * Params.size(); void *Mem = Context.Allocate(Size, alignof(GenericParamList)); return new (Mem) GenericParamList(LAngleLoc, Params, SourceLoc(), MutableArrayRef(), RAngleLoc); } GenericParamList * GenericParamList::create(const ASTContext &Context, SourceLoc LAngleLoc, ArrayRef Params, SourceLoc WhereLoc, MutableArrayRef Requirements, SourceLoc RAngleLoc) { unsigned Size = sizeof(GenericParamList) + sizeof(GenericParam) * Params.size(); void *Mem = Context.Allocate(Size, alignof(GenericParamList)); return new (Mem) GenericParamList(LAngleLoc, Params, WhereLoc, Context.AllocateCopy(Requirements), RAngleLoc); } ImportDecl *ImportDecl::create(ASTContext &Ctx, DeclContext *DC, SourceLoc ImportLoc, ImportKind Kind, SourceLoc KindLoc, bool Exported, ArrayRef Path) { assert(!Path.empty()); assert(Kind == ImportKind::Module || Path.size() > 1); void *buffer = Ctx.Allocate(sizeof(ImportDecl) + Path.size() * sizeof(AccessPathElement), alignof(ImportDecl)); return new (buffer) ImportDecl(DC, ImportLoc, Kind, KindLoc, Exported, Path); } ImportDecl::ImportDecl(DeclContext *DC, SourceLoc ImportLoc, ImportKind K, SourceLoc KindLoc, bool Exported, ArrayRef Path) : Decl(DeclKind::Import, DC), ImportLoc(ImportLoc), KindLoc(KindLoc), NumPathElements(Path.size()) { ImportDeclBits.ImportKind = static_cast(K); assert(getImportKind() == K && "not enough bits for ImportKind"); ImportDeclBits.IsExported = Exported; std::uninitialized_copy(Path.begin(), Path.end(), getPathBuffer()); } SourceRange PatternBindingDecl::getSourceRange() const { if (Init) { SourceLoc EndLoc = Init->getSourceRange().End; if (EndLoc.isValid()) return { VarLoc, EndLoc }; } return { VarLoc, Pat->getSourceRange().End }; } SourceLoc TopLevelCodeDecl::getStartLoc() const { return Body->getStartLoc(); } SourceRange TopLevelCodeDecl::getSourceRange() const { return Body->getSourceRange(); } bool ValueDecl::isSettableOnBase(Type baseType) const { if (!isSettable()) return false; if (!baseType) return true; return (baseType->isSettableLValue() || baseType->getRValueType()->hasReferenceSemantics()); } bool ValueDecl::isDefinition() const { switch (getKind()) { case DeclKind::Import: case DeclKind::Extension: case DeclKind::PatternBinding: case DeclKind::EnumCase: case DeclKind::Subscript: case DeclKind::TopLevelCode: case DeclKind::InfixOperator: case DeclKind::PrefixOperator: case DeclKind::PostfixOperator: llvm_unreachable("non-value decls shouldn't get here"); case DeclKind::Func: case DeclKind::Constructor: case DeclKind::Destructor: return cast(this)->getBodyKind() != AbstractFunctionDecl::BodyKind::None; case DeclKind::Var: case DeclKind::Enum: case DeclKind::EnumElement: case DeclKind::Struct: case DeclKind::Class: case DeclKind::TypeAlias: case DeclKind::GenericTypeParam: case DeclKind::AssociatedType: case DeclKind::Protocol: return true; } } bool ValueDecl::isInstanceMember() const { DeclContext *DC = getDeclContext(); if (!DC->isTypeContext()) return false; switch (getKind()) { case DeclKind::Import: case DeclKind::Extension: case DeclKind::PatternBinding: case DeclKind::EnumCase: case DeclKind::TopLevelCode: case DeclKind::InfixOperator: case DeclKind::PrefixOperator: case DeclKind::PostfixOperator: llvm_unreachable("Not a ValueDecl"); case DeclKind::Class: case DeclKind::Enum: case DeclKind::Protocol: case DeclKind::Struct: case DeclKind::TypeAlias: case DeclKind::GenericTypeParam: case DeclKind::AssociatedType: // Types are not instance members. return false; case DeclKind::Constructor: // Constructors are not instance members. return false; case DeclKind::Destructor: // Destructors are technically instance members, although they // can't actually be referenced as such. return true; case DeclKind::Func: // Non-static methods are instance members. return !cast(this)->isStatic(); case DeclKind::EnumElement: // enum elements are not instance members. return false; case DeclKind::Subscript: // Subscripts are always instance members. return true; case DeclKind::Var: // Variables are always instance variables. // FIXME: Until we get static variables. return true; } } bool ValueDecl::needsCapture() const { // We don't need to capture anything from non-local contexts. if (!getDeclContext()->isLocalContext()) return false; // We don't need to capture types. if (isa(this)) return false; return true; } ValueDecl *ValueDecl::getOverriddenDecl() const { if (auto fd = dyn_cast(this)) { return fd->getOverriddenDecl(); } if (auto vd = dyn_cast(this)) { return vd->getOverriddenDecl(); } if (auto sd = dyn_cast(this)) { return sd->getOverriddenDecl(); } return nullptr; } bool ValueDecl::canBeAccessedByDynamicLookup() const { if (getName().empty()) return false; // Dynamic lookup can only find [objc] members. if (!isObjC()) return false; // Dynamic lookup can only find class and protocol members, or extensions of // classes. auto nominalDC =getDeclContext()->getDeclaredTypeOfContext()->getAnyNominal(); if (!nominalDC || (!isa(nominalDC) && !isa(nominalDC))) return false; // Dynamic lookup cannot find results within a generic context, because there // is no sensible way to infer the generic arguments. if (getDeclContext()->isGenericContext()) return false; // Dynamic lookup can find functions, variables, and subscripts. if (isa(this) || isa(this) || isa(this)) return true; return false; } Type TypeDecl::getDeclaredType() const { if (auto TAD = dyn_cast(this)) return TAD->getAliasType(); if (auto typeParam = dyn_cast(this)) return typeParam->getType()->castTo()->getInstanceType(); return cast(this)->getDeclaredType(); } void NominalTypeDecl::computeType() { assert(!hasType() && "Nominal type declaration already has a type"); // Compute the declared type. Type parentTy = getDeclContext()->getDeclaredTypeInContext(); ASTContext &ctx = getASTContext(); if (getGenericParams()) { DeclaredTy = UnboundGenericType::get(this, parentTy, ctx); } else if (auto proto = dyn_cast(this)) { DeclaredTy = new (ctx, AllocationArena::Permanent) ProtocolType(proto, ctx); } else { DeclaredTy = NominalType::get(this, parentTy, ctx); } // Set the type. setType(MetaTypeType::get(DeclaredTy, ctx)); } Type NominalTypeDecl::getDeclaredTypeInContext() { if (DeclaredTyInContext) return DeclaredTyInContext; Type Ty = getDeclaredType(); if (UnboundGenericType *UGT = Ty->getAs()) { // If we have an unbound generic type, bind the type to the archetypes // in the type's definition. NominalTypeDecl *D = UGT->getDecl(); SmallVector GenericArgs; for (auto Param : *D->getGenericParams()) GenericArgs.push_back(Param.getAsTypeParam()->getArchetype()); Ty = BoundGenericType::get(D, getDeclContext()->getDeclaredTypeInContext(), GenericArgs); } DeclaredTyInContext = Ty; return DeclaredTyInContext; } ExtensionRange NominalTypeDecl::getExtensions() { auto &context = Decl::getASTContext(); // If our list of extensions is out of date, update it now. if (context.getCurrentGeneration() > ExtensionGeneration) { unsigned previousGeneration = ExtensionGeneration; ExtensionGeneration = context.getCurrentGeneration(); context.loadExtensions(this, previousGeneration); } return ExtensionRange(ExtensionIterator(FirstExtension), ExtensionIterator()); } void NominalTypeDecl::addExtension(ExtensionDecl *extension) { assert(!extension->NextExtension.getInt() && "Already added extension"); extension->NextExtension.setInt(true); // First extension; set both first and last. if (!FirstExtension) { FirstExtension = extension; LastExtension = extension; return; } // Add to the end of the list. LastExtension->NextExtension.setPointer(extension); LastExtension = extension; } void NominalTypeDecl::getImplicitProtocols( SmallVectorImpl &protocols) { // If this is a class, it conforms to the DynamicLookup protocol. if (isa(this)) { if (auto dynamicLookup = getASTContext().getProtocol(KnownProtocolKind::DynamicLookup)) { protocols.push_back(dynamicLookup); } } } TypeAliasDecl::TypeAliasDecl(SourceLoc TypeAliasLoc, Identifier Name, SourceLoc NameLoc, TypeLoc UnderlyingTy, DeclContext *DC, MutableArrayRef Inherited) : TypeDecl(DeclKind::TypeAlias, DC, Name, NameLoc, Inherited), TypeAliasLoc(TypeAliasLoc), UnderlyingTy(UnderlyingTy) { // Set the type of the TypeAlias to the right MetaTypeType. ASTContext &Ctx = getASTContext(); AliasTy = new (Ctx, AllocationArena::Permanent) NameAliasType(this); setType(MetaTypeType::get(AliasTy, Ctx)); } SourceRange TypeAliasDecl::getSourceRange() const { if (UnderlyingTy.hasLocation()) return { TypeAliasLoc, UnderlyingTy.getSourceRange().End }; // FIXME: Inherits clauses return { TypeAliasLoc, getNameLoc() }; } GenericTypeParamDecl::GenericTypeParamDecl(DeclContext *dc, Identifier name, SourceLoc nameLoc, unsigned depth, unsigned index) : AbstractTypeParamDecl(DeclKind::GenericTypeParam, dc, name, nameLoc), Depth(depth), Index(index) { // FIXME: Arbitrarily consider this generic type parameter type to be // canonical. In the long run, it won't be. auto &ctx = dc->getASTContext(); auto type = new (ctx, AllocationArena::Permanent) GenericTypeParamType(this, &ctx); setType(MetaTypeType::get(type, ctx)); } SourceRange GenericTypeParamDecl::getSourceRange() const { SourceLoc endLoc = getNameLoc(); if (!getInherited().empty()) { endLoc = getInherited().back().getSourceRange().End; } return SourceRange(getNameLoc(), endLoc); } AssociatedTypeDecl::AssociatedTypeDecl(DeclContext *dc, SourceLoc keywordLoc, Identifier name, SourceLoc nameLoc) : AbstractTypeParamDecl(DeclKind::AssociatedType, dc, name, nameLoc), KeywordLoc(keywordLoc) { auto &ctx = dc->getASTContext(); auto type = new (ctx, AllocationArena::Permanent) AssociatedTypeType(this); setType(MetaTypeType::get(type, ctx)); } SourceRange AssociatedTypeDecl::getSourceRange() const { SourceLoc endLoc = getNameLoc(); if (!getInherited().empty()) { endLoc = getInherited().back().getSourceRange().End; } return SourceRange(KeywordLoc, endLoc); } EnumDecl::EnumDecl(SourceLoc EnumLoc, Identifier Name, SourceLoc NameLoc, MutableArrayRef Inherited, GenericParamList *GenericParams, DeclContext *Parent) : NominalTypeDecl(DeclKind::Enum, Parent, Name, NameLoc, Inherited, GenericParams), EnumLoc(EnumLoc) { EnumDeclBits.Circularity = static_cast(CircularityCheck::Unchecked); } StructDecl::StructDecl(SourceLoc StructLoc, Identifier Name, SourceLoc NameLoc, MutableArrayRef Inherited, GenericParamList *GenericParams, DeclContext *Parent) : NominalTypeDecl(DeclKind::Struct, Parent, Name, NameLoc, Inherited, GenericParams), StructLoc(StructLoc) { } ClassDecl::ClassDecl(SourceLoc ClassLoc, Identifier Name, SourceLoc NameLoc, MutableArrayRef Inherited, GenericParamList *GenericParams, DeclContext *Parent) : NominalTypeDecl(DeclKind::Class, Parent, Name, NameLoc, Inherited, GenericParams), ClassLoc(ClassLoc) { ClassDeclBits.Circularity = static_cast(CircularityCheck::Unchecked); } EnumCaseDecl *EnumCaseDecl::create(SourceLoc CaseLoc, ArrayRef Elements, DeclContext *DC) { void *buf = DC->getASTContext() .Allocate(sizeof(EnumCaseDecl) + sizeof(EnumElementDecl*) * Elements.size(), alignof(EnumCaseDecl)); return ::new (buf) EnumCaseDecl(CaseLoc, Elements, DC); } EnumElementDecl *EnumDecl::getElement(Identifier Name) const { // FIXME: Linear search is not great for large enum decls. for (Decl *D : getMembers()) if (EnumElementDecl *Elt = dyn_cast(D)) if (Elt->getName() == Name) return Elt; return 0; } ProtocolDecl::ProtocolDecl(DeclContext *DC, SourceLoc ProtocolLoc, SourceLoc NameLoc, Identifier Name, MutableArrayRef Inherited) : NominalTypeDecl(DeclKind::Protocol, DC, Name, NameLoc, Inherited, nullptr), ProtocolLoc(ProtocolLoc) { ProtocolDeclBits.RequiresClassValid = false; ProtocolDeclBits.RequiresClass = false; ProtocolDeclBits.ExistentialConformsToSelfValid = false; ProtocolDeclBits.ExistentialConformsToSelf = false; ProtocolDeclBits.KnownProtocol = 0; ProtocolDeclBits.Circularity = static_cast(CircularityCheck::Unchecked); } bool ProtocolDecl::inheritsFrom(const ProtocolDecl *Super) const { if (this == Super) return false; llvm::SmallPtrSet Visited; SmallVector Stack; Stack.push_back(this); Visited.insert(this); while (!Stack.empty()) { const ProtocolDecl *Current = Stack.back(); Stack.pop_back(); for (auto InheritedProto : Current->getProtocols()) { if (InheritedProto == Super) return true; if (Visited.insert(InheritedProto)) Stack.push_back(InheritedProto); } } return false; } void ProtocolDecl::collectInherited( llvm::SmallPtrSet &Inherited) { SmallVector Stack; Stack.push_back(this); while (!Stack.empty()) { const ProtocolDecl *Current = Stack.back(); Stack.pop_back(); for (auto InheritedProto : Current->getProtocols()) { if (Inherited.insert(InheritedProto)) Stack.push_back(InheritedProto); } } } bool ProtocolDecl::requiresClassSlow() { ProtocolDeclBits.RequiresClass = false; ProtocolDeclBits.RequiresClassValid = true; if (getAttrs().isClassProtocol()) { ProtocolDeclBits.RequiresClass = true; return true; } // Check inherited protocols for class-ness. for (auto *proto : getProtocols()) { if (proto->requiresClass()) { ProtocolDeclBits.RequiresClass = true; return true; } } return false; } AssociatedTypeDecl *ProtocolDecl::getSelf() const { for (auto member : getMembers()) { if (auto assocType = dyn_cast(member)) if (assocType->isSelf()) return assocType; } llvm_unreachable("No 'Self' associated type?"); } void VarDecl::setComputedAccessors(ASTContext &Context, SourceLoc LBraceLoc, FuncDecl *Get, FuncDecl *Set, SourceLoc RBraceLoc) { assert(!GetSet && "Variable already has accessors?"); void *Mem = Context.Allocate(sizeof(GetSetRecord), alignof(GetSetRecord)); GetSet = new (Mem) GetSetRecord; GetSet->Braces = SourceRange(LBraceLoc, RBraceLoc); GetSet->Get = Get; GetSet->Set = Set; if (Get) Get->makeGetter(this); if (Set) Set->makeSetter(this); } bool VarDecl::isAnonClosureParam() const { auto name = getName(); if (name.empty()) return false; auto nameStr = name.str(); if (nameStr.empty()) return false; return nameStr[0] == '$'; } VarDecl *AbstractFunctionDecl::getImplicitSelfDeclSlow() const { if (auto FD = dyn_cast(this)) { VarDecl *SelfDecl = FD->getImplicitSelfDeclImpl(); ImplicitSelfDeclAndIsCached.setPointerAndInt(SelfDecl, true); return SelfDecl; } ImplicitSelfDeclAndIsCached.setPointerAndInt(nullptr, true); return nullptr; } Type AbstractFunctionDecl::getExtensionType() const { return getDeclContext()->getDeclaredTypeInContext(); } std::pair AbstractFunctionDecl::getDefaultArg(unsigned Index) const { ArrayRef Patterns = getArgParamPatterns(); if (isa(this) && getImplicitSelfDecl()) { // Skip the 'self' parameter; it is not counted. Patterns = Patterns.slice(1); } // Find the (sub-)pattern for this index. // FIXME: This is O(n), which is lame. We should fix the FuncDecl // representation. const TuplePatternElt *Found = nullptr; for (auto OrigPattern : Patterns) { auto Params = dyn_cast(OrigPattern->getSemanticsProvidingPattern()); if (!Params) { if (Index == 0) { return { DefaultArgumentKind::None, Type() }; } --Index; continue; } for (auto &Elt : Params->getFields()) { if (Index == 0) { Found = &Elt; break; } --Index; } if (Found) break; } assert(Found && "No argument with this index"); return { Found->getDefaultArgKind(), Found->getPattern()->getType() }; } VarDecl *FuncDecl::getImplicitSelfDeclImpl() const { ArrayRef ArgParamPatterns = getArgParamPatterns(); if (ArgParamPatterns.empty()) return nullptr; // "self" is represented as (typed_pattern (named_pattern (var_decl 'self')). auto TP = dyn_cast(ArgParamPatterns[0]); if (!TP) return nullptr; // The decl should be named 'self' and have no location information. auto NP = dyn_cast(TP->getSubPattern()); if (NP && NP->getBoundName().str() == "self" && !NP->getLoc().isValid()) return NP->getDecl(); return nullptr; } FuncDecl *FuncDecl::createDeserialized(ASTContext &Context, SourceLoc StaticLoc, SourceLoc FuncLoc, Identifier Name, SourceLoc NameLoc, GenericParamList *GenericParams, Type Ty, unsigned NumParamPatterns, DeclContext *Parent) { assert(NumParamPatterns > 0); void *Mem = Context.Allocate( sizeof(FuncDecl) + 2 * NumParamPatterns * sizeof(Pattern *), alignof(FuncDecl)); return ::new (Mem) FuncDecl(StaticLoc, FuncLoc, Name, NameLoc, NumParamPatterns, GenericParams, Ty, Parent); } FuncDecl *FuncDecl::create(ASTContext &Context, SourceLoc StaticLoc, SourceLoc FuncLoc, Identifier Name, SourceLoc NameLoc, GenericParamList *GenericParams, Type Ty, ArrayRef ArgParams, ArrayRef BodyParams, TypeLoc FnRetType, DeclContext *Parent) { assert(ArgParams.size() == BodyParams.size()); const unsigned NumParamPatterns = ArgParams.size(); auto *FD = FuncDecl::createDeserialized( Context, StaticLoc, FuncLoc, Name, NameLoc, GenericParams, Ty, NumParamPatterns, Parent); FD->setDeserializedSignature(ArgParams, BodyParams, FnRetType); return FD; } void FuncDecl::setDeserializedSignature(ArrayRef ArgParams, ArrayRef BodyParams, TypeLoc FnRetType) { MutableArrayRef ArgParamsRef = getArgParamPatterns(); MutableArrayRef BodyParamsRef = getBodyParamPatterns(); const unsigned NumParamPatterns = ArgParamsRef.size(); assert(ArgParams.size() == BodyParams.size()); assert(NumParamPatterns == ArgParams.size()); for (unsigned i = 0; i != NumParamPatterns; ++i) ArgParamsRef[i] = ArgParams[i]; for (unsigned i = 0; i != NumParamPatterns; ++i) BodyParamsRef[i] = BodyParams[i]; this->FnRetType = FnRetType; } Type FuncDecl::computeSelfType(GenericParamList **OuterGenericParams) const { if (OuterGenericParams) *OuterGenericParams = nullptr; Type ContainerType = getExtensionType(); if (ContainerType.isNull()) return ContainerType; // For a protocol, the type of 'self' is the associated type 'Self', not // the protocol itself. if (auto Protocol = ContainerType->getAs()) { AssociatedTypeDecl *Self = 0; for (auto Member : Protocol->getDecl()->getMembers()) { Self = dyn_cast(Member); if (!Self) continue; if (Self->isSelf()) break; Self = nullptr; } assert(Self && "Missing 'Self' associated type in protocol"); ContainerType = Self->getDeclaredType(); } if (UnboundGenericType *UGT = ContainerType->getAs()) { // If we have an unbound generic type, bind the type to the archetypes // in the type's definition. NominalTypeDecl *D = UGT->getDecl(); ContainerType = getDeclContext()->getDeclaredTypeInContext(); if (OuterGenericParams) *OuterGenericParams = D->getGenericParams(); } else if (OuterGenericParams) { *OuterGenericParams = getDeclContext()->getGenericParamsOfContext(); } // 'static' functions have 'self' of type metatype. if (isStatic()) return MetaTypeType::get(ContainerType, getASTContext()); if (ContainerType->hasReferenceSemantics()) return ContainerType; // Otherwise, make an l-value type. return LValueType::get(ContainerType, LValueType::Qual::DefaultForInOutSelf, getASTContext()); } Type FuncDecl::getResultType(ASTContext &Ctx) const { Type resultTy = getType(); if (!resultTy || resultTy->is()) return resultTy; for (unsigned i = 0, e = getNaturalArgumentCount(); i != e; ++i) resultTy = resultTy->castTo()->getResult(); if (!resultTy) resultTy = TupleType::getEmpty(Ctx); return resultTy; } bool FuncDecl::isUnaryOperator() const { if (!isOperator()) return false; unsigned opArgIndex = isa(getDeclContext()) ? 1 : 0; auto *argTuple = dyn_cast(getArgParamPatterns()[opArgIndex]); if (!argTuple) return true; return argTuple->getNumFields() == 1 && !argTuple->hasVararg(); } bool FuncDecl::isBinaryOperator() const { if (!isOperator()) return false; unsigned opArgIndex = isa(getDeclContext()) ? 1 : 0; auto *argTuple = dyn_cast(getArgParamPatterns()[opArgIndex]); if (!argTuple) return false; return argTuple->getNumFields() == 2 || (argTuple->getNumFields() == 1 && argTuple->hasVararg()); } StringRef VarDecl::getObjCGetterSelector(SmallVectorImpl &buffer) const { llvm::raw_svector_ostream out(buffer); // The getter selector is the property name itself. // FIXME: 'is' prefix for boolean properties? out << getName().str(); return out.str(); } StringRef VarDecl::getObjCSetterSelector(SmallVectorImpl &buffer) const { llvm::raw_svector_ostream out(buffer); // The setter selector for, e.g., 'fooBar' is 'setFooBar:', with the // property name capitalized and preceded by 'set'. StringRef name = getName().str(); assert(name.size() >= 1 && "empty var name?!"); out << "set" << char(toupper(name[0])) << name.slice(1, name.size()) << ':'; return out.str(); } /// Produce the selector for this "Objective-C method" in the given buffer. StringRef FuncDecl::getObjCSelector(SmallVectorImpl &buffer) const { assert(buffer.empty()); // Property accessors should go through a different path. assert(!isGetterOrSetter()); llvm::raw_svector_ostream out(buffer); // Start with the method name. out << getName().str(); // We should always have exactly two levels of argument pattern. auto argPatterns = getArgParamPatterns(); assert(argPatterns.size() == 2); const Pattern *pattern = argPatterns[1]; auto tuple = dyn_cast(pattern); // If it's an empty tuple pattern, it's a nullary selector. if (tuple && tuple->getNumFields() == 0) return out.str(); // Otherwise, it's at least a unary selector. out << ':'; // If it's a unary selector, we're done. if (!tuple) { return out.str(); } // For every element except the first, add a selector component. for (auto &elt : tuple->getFields().slice(1)) { auto eltPattern = elt.getPattern()->getSemanticsProvidingPattern(); // Add a label to the selector component if there's a tag. if (auto named = dyn_cast(eltPattern)) { out << named->getBoundName().str(); } // Add the colon regardless. Yes, this can sometimes create a // component that's just a colon, and that's actually a legal // selector. out << ':'; } return out.str(); } SourceRange FuncDecl::getSourceRange() const { if (getBodyKind() == BodyKind::Unparsed || getBodyKind() == BodyKind::Skipped) return { FuncLoc, BodyEndLoc }; if (auto *B = getBody()) return { FuncLoc, B->getEndLoc() }; if (getBodyResultTypeLoc().hasLocation()) return { FuncLoc, getBodyResultTypeLoc().getSourceRange().End }; const Pattern *LastPat = getArgParamPatterns().back(); return { FuncLoc, LastPat->getEndLoc() }; } /// Determine whether the given type is (or bridges to) an /// Objective-C object type. static bool isObjCObjectOrBridgedType(Type type) { // FIXME: Bridged types info should be available here in the AST // library, rather than hard-coding them. if (auto structTy = type->getAs()) { auto structDecl = structTy->getDecl(); if (auto module = dyn_cast(structDecl->getDeclContext())) { if (module->Name.str().equals("swift") && !structDecl->getName().empty() && structDecl->getName().str().equals("String")) return true; } return false; } // Unwrap metatypes for remaining checks. if (auto metaTy = type->getAs()) type = metaTy->getInstanceType(); // Class types are Objective-C object types. if (type->is()) return true; // [objc] protocols if (auto protoTy = type->getAs()) { auto proto = protoTy->getDecl(); return proto->requiresClass() && proto->isObjC(); } return false; } /// Determine whether the given Swift type is an integral type, i.e., /// a type that wraps a builtin integer. static bool isIntegralType(Type type) { // Consider structs in the "swift" module that wrap a builtin // integer type to be integral types. if (auto structTy = type->getAs()) { auto structDecl = structTy->getDecl(); auto module = dyn_cast(structDecl->getDeclContext()); if (!module || !module->Name.str().equals("swift")) return false; // Find the single ivar. VarDecl *singleVar = nullptr; for (auto member : structDecl->getMembers()) { auto var = dyn_cast(member); if (!var || var->isComputed()) continue; if (singleVar) return false; singleVar = var; } if (!singleVar) return false; // Check whether it has integer type. return singleVar->getType()->is(); } return false; } ObjCSubscriptKind SubscriptDecl::getObjCSubscriptKind() const { auto indexTy = getIndices()->getType(); // Look through a named 1-tuple. if (auto tupleTy = indexTy->getAs()) { if (tupleTy->getNumElements() == 1 && !tupleTy->getFields()[0].isVararg()) { indexTy = tupleTy->getElementType(0); } } // If the index type is an integral type, we have an indexed // subscript. if (isIntegralType(indexTy)) return ObjCSubscriptKind::Indexed; // If the index type is an object type in Objective-C, we have a // keyed subscript. if (isObjCObjectOrBridgedType(indexTy)) return ObjCSubscriptKind::Keyed; return ObjCSubscriptKind::None; } StringRef SubscriptDecl::getObjCGetterSelector() const { switch (getObjCSubscriptKind()) { case ObjCSubscriptKind::None: llvm_unreachable("Not an Objective-C subscript"); case ObjCSubscriptKind::Indexed: return "objectAtIndexedSubscript:"; case ObjCSubscriptKind::Keyed: return "objectForKeyedSubscript:"; } } StringRef SubscriptDecl::getObjCSetterSelector() const { switch (getObjCSubscriptKind()) { case ObjCSubscriptKind::None: llvm_unreachable("Not an Objective-C subscript"); case ObjCSubscriptKind::Indexed: return "setObject:atIndexedSubscript:"; case ObjCSubscriptKind::Keyed: return "setObject:forKeyedSubscript:"; } } SourceRange EnumElementDecl::getSourceRange() const { if (RawValueExpr && !RawValueExpr->isImplicit()) return {getStartLoc(), RawValueExpr->getEndLoc()}; if (ResultType.hasLocation()) return {getStartLoc(), ResultType.getSourceRange().End}; if (ArgumentType.hasLocation()) return {getStartLoc(), ArgumentType.getSourceRange().End}; return {getStartLoc(), getNameLoc()}; } SourceRange SubscriptDecl::getSourceRange() const { if (Braces.isValid()) return { getSubscriptLoc(), Braces.End }; return { getSubscriptLoc(), ElementTy.getSourceRange().End }; } SourceRange ConstructorDecl::getSourceRange() const { if (getBodyKind() == BodyKind::Unparsed || getBodyKind() == BodyKind::Skipped) return { getConstructorLoc(), BodyEndLoc }; if (!Body || !Body->getEndLoc().isValid()) { const DeclContext *DC = getDeclContext(); switch (DC->getContextKind()) { case DeclContextKind::ExtensionDecl: return cast(DC)->getLoc(); case DeclContextKind::NominalTypeDecl: return cast(DC)->getLoc(); default: if (isInvalid()) return getConstructorLoc(); llvm_unreachable("Unhandled decl kind"); } } return { getConstructorLoc(), Body->getEndLoc() }; } Type ConstructorDecl::computeSelfType(GenericParamList **OuterGenericParams) const { Type ContainerType = getDeclContext()->getDeclaredTypeOfContext(); if (UnboundGenericType *UGT = ContainerType->getAs()) { // If we have an unbound generic type, bind the type to the archetypes // in the type's definition. NominalTypeDecl *D = UGT->getDecl(); ContainerType = getDeclContext()->getDeclaredTypeInContext(); if (OuterGenericParams) *OuterGenericParams = D->getGenericParams(); } else if (OuterGenericParams) { *OuterGenericParams = getDeclContext()->getGenericParamsOfContext(); } return ContainerType; } Type ConstructorDecl::getArgumentType() const { Type ArgTy = getType(); ArgTy = ArgTy->castTo()->getResult(); ArgTy = ArgTy->castTo()->getInput(); return ArgTy; } Type ConstructorDecl::getResultType() const { Type ArgTy = getType(); ArgTy = ArgTy->castTo()->getResult(); ArgTy = ArgTy->castTo()->getResult(); return ArgTy; } /// Produce the selector for this "Objective-C method" in the given buffer. StringRef ConstructorDecl::getObjCSelector(SmallVectorImpl &buffer) const { assert(buffer.empty()); llvm::raw_svector_ostream out(buffer); // In the beginning, there was 'init'. out << "init"; // If there are no parameters, this is just 'init'. auto tuple = cast(getArgParams()); if (tuple->getNumFields() == 0) { return out.str(); } // The first field is special: we uppercase the name. const auto &firstElt = tuple->getFields()[0]; auto firstPattern = firstElt.getPattern()->getSemanticsProvidingPattern(); if (auto firstNamed = dyn_cast(firstPattern)) { if (!firstNamed->getBoundName().empty()) { auto nameStr = firstNamed->getBoundName().str(); out << (char)toupper(nameStr[0]); out << nameStr.substr(1); } // If there is only a single parameter and its type is the empty tuple // type, we're done: don't add the trailing colon. if (tuple->getNumFields() == 1) { auto emptyTupleTy = TupleType::getEmpty(getASTContext()); if (!firstPattern->getType()->isEqual(emptyTupleTy)) out << ':'; return out.str(); } // Continue with the remaining selectors. out << ':'; } // For every remaining element, add a selector component. for (auto &elt : tuple->getFields().slice(1)) { auto eltPattern = elt.getPattern()->getSemanticsProvidingPattern(); // Add a label to the selector component if there's a tag. if (auto named = dyn_cast(eltPattern)) { out << named->getBoundName().str(); } // Add the colon regardless. Yes, this can sometimes create a // component that's just a colon, and that's actually a legal // selector. out << ':'; } return out.str(); } Type DestructorDecl::computeSelfType(GenericParamList **OuterGenericParams) const { Type ContainerType = getDeclContext()->getDeclaredTypeOfContext(); if (UnboundGenericType *UGT = ContainerType->getAs()) { // If we have an unbound generic type, bind the type to the archetypes // in the type's definition. NominalTypeDecl *D = UGT->getDecl(); ContainerType = getDeclContext()->getDeclaredTypeInContext(); if (OuterGenericParams) *OuterGenericParams = D->getGenericParams(); } else if (OuterGenericParams) { *OuterGenericParams = getDeclContext()->getGenericParamsOfContext(); } return ContainerType; } SourceRange DestructorDecl::getSourceRange() const { if (getBodyKind() == BodyKind::Unparsed || getBodyKind() == BodyKind::Skipped) return { getDestructorLoc(), BodyEndLoc }; if (getBodyKind() == BodyKind::None) return getDestructorLoc(); return { getDestructorLoc(), Body->getEndLoc() }; }