//===--- 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/ASTWalker.h" #include "swift/AST/DiagnosticEngine.h" #include "swift/AST/DiagnosticsSema.h" #include "swift/AST/Expr.h" #include "swift/AST/TypeLoc.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/Support/raw_ostream.h" #include "swift/Basic/Range.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" } } DeclContext *Decl::getInnermostDeclContext() { if (auto func = dyn_cast(this)) return func; if (auto nominal = dyn_cast(this)) return nominal; if (auto ext = dyn_cast(this)) return ext; if (auto topLevel = dyn_cast(this)) return topLevel; return getDeclContext(); } 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() const { 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)) { if (const ExtensionDecl *ED = dyn_cast(FD->getParent())) return ED->isTransparent(); } // If this is a getter or a seter, check if the transparent attribute was set // on the value decl. if (const FuncDecl *FD = dyn_cast(this)) { if (ValueDecl *VD = FD->getGetterOrSetterDecl()) return VD->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); } GenericSignature * GenericParamList::getAsCanonicalGenericSignature( llvm::DenseMap &archetypeMap, ASTContext &C) const { SmallVector params; SmallVector requirements; getAsGenericSignatureElements(C, archetypeMap, params, requirements); // Canonicalize the types in the signature. for (auto ¶m : params) param = cast(param->getCanonicalType()); for (auto &reqt : requirements) reqt = Requirement(reqt.getKind(), reqt.getFirstType()->getCanonicalType(), reqt.getSecondType()->getCanonicalType()); return GenericSignature::get(params, requirements, C); } // Helper for getAsGenericSignatureElements to remap an archetype in a // requirement to a canonical dependent type. Type ArchetypeType::getAsDependentType( const llvm::DenseMap &archetypeMap) { // Map associated archetypes to DependentMemberTypes. if (auto parent = getParent()) { auto assocTy = getAssocType(); assert(assocTy); Type base = parent->getAsDependentType(archetypeMap); return DependentMemberType::get(base, assocTy, getASTContext()); } // Map primary archetypes to generic type parameters. auto found = archetypeMap.find(this); assert(found != archetypeMap.end() && "did not find generic param for archetype"); return found->second; } static Type getAsDependentType(Type t, const llvm::DenseMap &archetypeMap) { if (auto arch = t->getAs()) return arch->getAsDependentType(archetypeMap); return t; } // Helper to translate a RequirementRepr into a canonical Requirement expressed // in terms of dependent types. static void addRequirementForRepr(SmallVectorImpl &requirements, const RequirementRepr &repr, const llvm::DenseMap &archetypeMap) { switch (repr.getKind()) { case RequirementKind::Conformance: { // Primary conformance declarations would have already been gathered as // conformance requirements off the archetype. if (auto arch = repr.getSubject()->getAs()) { if (!arch->getParent()) return; } Requirement reqt(RequirementKind::Conformance, getAsDependentType(repr.getSubject(), archetypeMap), getAsDependentType(repr.getConstraint(), archetypeMap)); requirements.push_back(reqt); return; } case RequirementKind::SameType: { // FIXME: ArchetypeBuilder doesn't preserve the distinction between the // matched archetypes, so this ends up producing useless '$T == $T' // requirements. /* Requirement reqt(RequirementKind::SameType, getAsDependentType(repr.getFirstType(), archetypeMap), getAsDependentType(repr.getSecondType(), archetypeMap)); requirements.push_back(reqt); */ return; } case RequirementKind::WitnessMarker: llvm_unreachable("should not exist after typechecking (?)"); } } // A helper to recursively collect the generic parameters from the outer levels // of a generic parameter list. void GenericParamList::getAsGenericSignatureElements(ASTContext &C, llvm::DenseMap &archetypeMap, SmallVectorImpl &genericParams, SmallVectorImpl &requirements) const { // Collect outer generic parameters first. if (OuterParameters) { OuterParameters->getAsGenericSignatureElements(C, archetypeMap, genericParams, requirements); } // Collect our parameters. for (auto paramIndex : indices(getParams())) { auto param = getParams()[paramIndex]; GenericTypeParamDecl *typeParam = param.getAsTypeParam(); auto typeParamTy = typeParam->getDeclaredType() ->castTo(); // Make sure we didn't visit this param already in the parent. auto found = archetypeMap.find(typeParam->getArchetype()); if (found != archetypeMap.end()) { assert(found->second->isEqual(typeParamTy)); continue; } // Set up a mapping we can use to remap requirements to dependent types. ArchetypeType *archetype; // The 'Self' archetype doesn't show up in getAllArchetypes. if (hasSelfArchetype()) { if (paramIndex == 0) archetype = typeParam->getArchetype(); else archetype = getPrimaryArchetypes()[paramIndex - 1]; } else { archetype = getPrimaryArchetypes()[paramIndex]; } archetypeMap[archetype] = typeParamTy; genericParams.push_back(typeParamTy); // Collect conformance requirements declared on the archetype. if (auto super = archetype->getSuperclass()) { requirements.push_back(Requirement(RequirementKind::Conformance, typeParamTy, super)); } for (auto proto : archetype->getConformsTo()) { requirements.push_back(Requirement(RequirementKind::Conformance, typeParamTy, proto->getDeclaredType())); } } // Collect requirements from the 'where' clause. for (const auto &repr : getRequirements()) { addRequirementForRepr(requirements, repr, archetypeMap); } } 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()); } ImportKind ImportDecl::getBestImportKind(const ValueDecl *VD) { switch (VD->getKind()) { case DeclKind::Import: case DeclKind::Extension: case DeclKind::PatternBinding: case DeclKind::TopLevelCode: case DeclKind::InfixOperator: case DeclKind::PrefixOperator: case DeclKind::PostfixOperator: case DeclKind::EnumCase: llvm_unreachable("not a ValueDecl"); case DeclKind::AssociatedType: case DeclKind::Constructor: case DeclKind::Destructor: case DeclKind::GenericTypeParam: case DeclKind::Subscript: case DeclKind::EnumElement: llvm_unreachable("not a top-level ValueDecl"); case DeclKind::Protocol: return ImportKind::Protocol; case DeclKind::Class: return ImportKind::Class; case DeclKind::Enum: return ImportKind::Enum; case DeclKind::Struct: return ImportKind::Struct; case DeclKind::TypeAlias: { Type underlyingTy = cast(VD)->getUnderlyingType(); return getBestImportKind(underlyingTy->getAnyNominal()); } case DeclKind::Func: return ImportKind::Func; case DeclKind::Var: return ImportKind::Var; } } Optional ImportDecl::findBestImportKind(ArrayRef Decls) { assert(!Decls.empty()); ImportKind FirstKind = ImportDecl::getBestImportKind(Decls.front()); // Only functions can be overloaded. if (Decls.size() == 1) return FirstKind; if (FirstKind != ImportKind::Func) return Nothing; for (auto NextDecl : Decls.slice(1)) { if (ImportDecl::getBestImportKind(NextDecl) != FirstKind) return Nothing; } return FirstKind; } void ExtensionDecl::setConformances(ArrayRef c) { Conformances = c; } SourceRange PatternBindingDecl::getSourceRange() const { SourceLoc startLoc = getStartLoc(); if (auto init = getInit()) { SourceLoc EndLoc = init->getSourceRange().End; if (EndLoc.isValid()) return { startLoc, EndLoc }; } return { startLoc, Pat->getSourceRange().End }; } SourceLoc TopLevelCodeDecl::getStartLoc() const { return Body->getStartLoc(); } SourceRange TopLevelCodeDecl::getSourceRange() const { return Body->getSourceRange(); } 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: // Non-static variables are instance members. return !cast(this)->isStatic(); } } 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 sdd = dyn_cast(this)) return sdd->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 non-protocol generic context, // because there is no sensible way to infer the generic arguments. if (getDeclContext()->isGenericContext() && !isa(nominalDC)) return false; // Dynamic lookup can find functions, variables, and subscripts. if (isa(this) || isa(this) || isa(this)) return true; return false; } ArrayRef ValueDecl::getConformances() { if (!conformsToProtocolRequirement()) return ArrayRef(); return getASTContext().getConformances(this); } void ValueDecl::setType(Type T) { assert(Ty.isNull() && "changing type of declaration"); Ty = T; if (!T.isNull() && T->is()) setInvalid(); } /// Overwrite the type of this declaration. void ValueDecl::overwriteType(Type T) { Ty = T; if (!T.isNull() && T->is()) setInvalid(); } DeclContext *ValueDecl::getPotentialGenericDeclContext() { if (auto func = dyn_cast(this)) return func; return getDeclContext(); } Type ValueDecl::getInterfaceType() const { if (InterfaceTy) return InterfaceTy; if (auto nominal = dyn_cast(this)) return nominal->computeInterfaceType(); if (auto assocType = dyn_cast(this)) { auto proto = cast(getDeclContext()); (void)proto->getType(); // make sure we've computed the type. auto selfTy = proto->getGenericParamTypes()[0]; auto &ctx = getASTContext(); InterfaceTy = DependentMemberType::get( selfTy, const_cast(assocType), ctx); InterfaceTy = MetatypeType::get(InterfaceTy, ctx); return InterfaceTy; } if (!hasType()) return Type(); // If the type involves a type variable, don't cache it. auto type = getType(); assert((type.isNull() || !type->is()) && "decl has polymorphic function type but no interface type"); if (type->hasTypeVariable()) return type; InterfaceTy = type; return InterfaceTy; } void ValueDecl::setInterfaceType(Type type) { assert((type.isNull() || !type->hasTypeVariable()) && "Type variable in interface type"); assert((type.isNull() || !type->is()) && "setting polymorphic function type as interface type"); InterfaceTy = type; } 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(); } Type TypeDecl::getDeclaredInterfaceType() const { return getInterfaceType()->castTo()->getInstanceType(); } bool NominalTypeDecl::derivesProtocolConformance(ProtocolDecl *protocol) const { // Enums with raw types can derive their RawRepresentable conformance. if (auto *enumDecl = dyn_cast(this)) { auto rawRepresentable = getASTContext().getProtocol(KnownProtocolKind::RawRepresentable); return enumDecl->hasRawType() && protocol == rawRepresentable; } return false; } GenericSignature::GenericSignature(ArrayRef params, ArrayRef requirements) : NumGenericParams(params.size()), NumRequirements(requirements.size()) { std::copy(params.begin(), params.end(), getGenericParamsBuffer().data()); std::copy(requirements.begin(), requirements.end(), getRequirementsBuffer().data()); } GenericSignature *GenericSignature::get(ArrayRef params, ArrayRef requirements, ASTContext &ctx) { // Allocate storage for the object. size_t bytes = sizeof(GenericSignature) + sizeof(GenericTypeParamType *) * params.size() + sizeof(Requirement) * requirements.size(); void *mem = ctx.Allocate(bytes, alignof(GenericSignature)); return new (mem) GenericSignature(params, requirements); } GenericSignature *GenericSignature::getCanonical( ArrayRef params, ArrayRef requirements, ASTContext &ctx) { // Canonicalize the parameters and requirements. SmallVector canonicalParams; canonicalParams.reserve(params.size()); for (auto param : params) { canonicalParams.push_back(cast(param->getCanonicalType())); } SmallVector canonicalRequirements; canonicalRequirements.reserve(requirements.size()); for (auto &reqt : requirements) { canonicalRequirements.push_back(Requirement(reqt.getKind(), reqt.getFirstType()->getCanonicalType(), reqt.getSecondType().getCanonicalTypeOrNull())); } return get(canonicalParams, canonicalRequirements, ctx); } void NominalTypeDecl::setGenericSignature( ArrayRef params, ArrayRef requirements) { assert(!GenericSig && "Already have generic signature"); GenericSig = GenericSignature::get(params, requirements, getASTContext()); } void NominalTypeDecl::computeType() { assert(!hasType() && "Nominal type declaration already has a type"); // Compute the declared type. Type parentTy = getDeclContext()->getDeclaredTypeInContext(); ASTContext &ctx = getASTContext(); if (auto proto = dyn_cast(this)) { if (!DeclaredTy) DeclaredTy = ProtocolType::get(proto, ctx); } else if (getGenericParams()) { DeclaredTy = UnboundGenericType::get(this, parentTy, ctx); } else { DeclaredTy = NominalType::get(this, parentTy, ctx); } // Set the type. setType(MetatypeType::get(DeclaredTy, ctx)); // A protocol has an implicit generic parameter list consisting of a single // generic parameter, Self, that conforms to the protocol itself. This // parameter is always implicitly bound. // // If this protocol has been deserialized, it already has generic parameters. // Don't add them again. if (!getGenericParams()) { if (auto proto = dyn_cast(this)) { // The generic parameter 'Self'. auto selfId = ctx.getIdentifier("Self"); auto selfDecl = new (ctx) GenericTypeParamDecl(proto, selfId, proto->getLoc(), 0, 0); auto protoRef = new (ctx) SimpleIdentTypeRepr(proto->getLoc(), proto->getName()); protoRef->setValue(proto); TypeLoc selfInherited[1] = { TypeLoc(protoRef) }; selfInherited[0].setType(DeclaredTy); selfDecl->setInherited(ctx.AllocateCopy(selfInherited)); selfDecl->setImplicit(); // The generic parameter list itself. GenericParams = GenericParamList::create(ctx, SourceLoc(), GenericParam(selfDecl), SourceLoc()); } } } 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; } Type NominalTypeDecl::computeInterfaceType() const { if (InterfaceTy) return InterfaceTy; // Figure out the interface type of the parent. Type parentType; if (auto typeOfParentContext = getDeclContext()->getDeclaredTypeOfContext()) parentType = typeOfParentContext->getAnyNominal() ->getDeclaredInterfaceType(); Type type; if (auto proto = dyn_cast(this)) { type = ProtocolType::get(const_cast(proto),getASTContext()); } else if (auto params = getGenericParams()) { // If we have a generic type, bind the type to the archetypes // in the type's definition. SmallVector genericArgs; for (auto param : *params) genericArgs.push_back(param.getAsTypeParam()->getDeclaredType()); type = BoundGenericType::get(const_cast(this), parentType, genericArgs); } else { type = NominalType::get(const_cast(this), parentType, getASTContext()); } InterfaceTy = MetatypeType::get(type, getASTContext()); return InterfaceTy; } 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); } } } OptionalTypeKind NominalTypeDecl::classifyAsOptionalType() const { const ASTContext &ctx = getASTContext(); if (this == ctx.getOptionalDecl()) { return OTK_Optional; } else if (this == ctx.getUncheckedOptionalDecl()) { return OTK_UncheckedOptional; } else { return OTK_None; } } TypeAliasDecl::TypeAliasDecl(SourceLoc TypeAliasLoc, Identifier Name, SourceLoc NameLoc, TypeLoc UnderlyingTy, DeclContext *DC) : TypeDecl(DeclKind::TypeAlias, DC, Name, NameLoc, {}), 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) { auto &ctx = dc->getASTContext(); auto type = new (ctx, AllocationArena::Permanent) GenericTypeParamType(this); 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, TypeLoc defaultDefinition) : AbstractTypeParamDecl(DeclKind::AssociatedType, dc, name, nameLoc), KeywordLoc(keywordLoc), DefaultDefinition(defaultDefinition) { 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); ClassDeclBits.RequiresStoredPropertyInits = 0; } DestructorDecl *ClassDecl::getDestructor() { auto name = getASTContext().getIdentifier("destructor"); auto results = lookupDirect(name); assert(!results.empty() && "Class without destructor?"); assert(results.size() == 1 && "More than one destructor?"); return cast(results.front()); } 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; if (isProtocolsValid()) { // Only cache the result if it can not change in future. 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; } GenericTypeParamDecl *ProtocolDecl::getSelf() const { return getGenericParams()->getParams()[0].getAsTypeParam(); } void AbstractStorageDecl::setComputedAccessors(SourceLoc LBraceLoc, FuncDecl *Get, FuncDecl *Set, SourceLoc RBraceLoc) { auto &Context = getASTContext(); assert(!GetSetInfo && "Variable already has accessors?"); void *Mem = Context.Allocate(sizeof(GetSetRecord), alignof(GetSetRecord)); GetSetInfo = new (Mem) GetSetRecord; GetSetInfo->Braces = SourceRange(LBraceLoc, RBraceLoc); GetSetInfo->Get = Get; GetSetInfo->Set = Set; if (Get) Get->makeGetter(this); if (Set) Set->makeSetter(this); } /// \brief Returns whether the var is settable in the specified context: this /// is either because it is a stored var, because it has a custom setter, or /// is a let member in an initializer. bool VarDecl::isSettable(DeclContext *UseDC) const { // 'let' properties are generally immutable, unless they are a 'let' ivar // and we are in the init() for the type that holds the ivar. if (isLet()) { if (auto *CD = dyn_cast(UseDC)) if (CD->getDeclContext() == getDeclContext()) return true; return false; } // vars are settable unless they are computed and have no setter. return !isComputed() || getSetter(); } SourceRange VarDecl::getTypeSourceRangeForDiagnostics() const { if (!getParentPattern()) return getSourceRange(); auto *Pat = getParentPattern()->getPattern(); if (auto *VP = dyn_cast(Pat)) Pat = VP->getSubPattern(); if (auto *TP = dyn_cast(Pat)) return TP->getTypeLoc().getTypeRepr()->getSourceRange(); return getSourceRange(); } Type VarDecl::getGetterType() const { // If we have a getter, use its type. if (auto getter = getGetter()) return getter->getType(); // Otherwise, compute the type. GenericParamList *outerParams = nullptr; auto selfTy = getDeclContext()->getSelfTypeInContext(/*isStatic=*/isStatic(), /*@mutating*/false, &outerParams); // Form the getter type. auto &ctx = getASTContext(); Type getterTy = FunctionType::get(TupleType::getEmpty(ctx), getType()); // Add 'self', if we have one. if (selfTy) { if (outerParams) getterTy = PolymorphicFunctionType::get(selfTy, getterTy, outerParams); else getterTy = FunctionType::get(selfTy, getterTy); } return getterTy; } Type VarDecl::getGetterInterfaceType() const { // If we have a getter, use its type. if (auto getter = getGetter()) return getter->getInterfaceType(); // Otherwise, compute the type. auto selfTy = getDeclContext()->getInterfaceSelfType(/*isStatic=*/isStatic(), /*@mutating*/ false); // Form the getter type. auto &ctx = getASTContext(); Type getterTy = FunctionType::get(TupleType::getEmpty(ctx), getInterfaceType()); // Add 'self', if we have one. if (selfTy) { ArrayRef genericParams; ArrayRef requirements; std::tie(genericParams, requirements) = getDeclContext()->getGenericSignatureOfContext(); if (genericParams.empty() && requirements.empty()) getterTy = FunctionType::get(selfTy, getterTy); else getterTy = GenericFunctionType::get(genericParams, requirements, selfTy, getterTy, AnyFunctionType::ExtInfo()); } return getterTy; } Type VarDecl::getSetterType() const { // If we have a setter, use its type. if (auto setter = getSetter()) return setter->getType(); // Otherwise, compute the type. GenericParamList *outerParams = nullptr; auto selfTy = getDeclContext()->getSelfTypeInContext(/*isStatic=*/isStatic(), /*@mutating*/!isStatic(), &outerParams); // Form the element -> () function type. auto &ctx = getASTContext(); TupleTypeElt valueElt(getType(), ctx.getIdentifier("value")); Type setterTy = FunctionType::get(TupleType::get(valueElt, ctx), TupleType::getEmpty(ctx)); // Add the 'self' type, if we have one. if (selfTy) { if (outerParams) setterTy = PolymorphicFunctionType::get(selfTy, setterTy, outerParams); else setterTy = FunctionType::get(selfTy, setterTy); } return setterTy; } Type VarDecl::getSetterInterfaceType() const { // If we have a getter, use its type. if (auto setter = getSetter()) return setter->getInterfaceType(); // Otherwise, compute the type. auto selfTy = getDeclContext()->getInterfaceSelfType(/*isStatic=*/isStatic(), /*@mutating*/ !isStatic()); // Form the element -> () function type. auto &ctx = getASTContext(); TupleTypeElt valueElt(getInterfaceType(), ctx.getIdentifier("value")); Type setterTy = FunctionType::get(TupleType::get(valueElt, ctx), TupleType::getEmpty(ctx)); // Add the 'self' type, if we have one. if (selfTy) { ArrayRef genericParams; ArrayRef requirements; std::tie(genericParams, requirements) = getDeclContext()->getGenericSignatureOfContext(); if (genericParams.empty() && requirements.empty()) setterTy = FunctionType::get(selfTy, setterTy); else setterTy = GenericFunctionType::get(genericParams, requirements, selfTy, setterTy, AnyFunctionType::ExtInfo()); } return setterTy; } /// Return true if this stored property needs to be accessed with getters and /// setters for Objective-C. bool AbstractStorageDecl::usesObjCGetterAndSetter() const { // We don't export generic methods or subclasses to IRGen yet. auto *DC = getDeclContext(); if (DC->getDeclaredTypeInContext() && DC->getDeclaredTypeInContext()->is() && !isa(DC)) return false; if (auto override = getOverriddenDecl()) return override->usesObjCGetterAndSetter(); if (!isObjC()) return false; // Don't expose objc properties for variables with function type. We can't // autorelease them, and eventually we want to map them back to blocks. if (isa(this) && getType()->is()) return false; return true; } bool VarDecl::isAnonClosureParam() const { auto name = getName(); if (name.empty()) return false; auto nameStr = name.str(); if (nameStr.empty()) return false; return nameStr[0] == '$'; } /// 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(); const DeclContext *DC = structDecl->getDeclContext(); if (DC->isModuleScopeContext() && DC->getParentModule()->isStdlibModule()) { if (structDecl->getName().str() == "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(); const DeclContext *DC = structDecl->getDeclContext(); if (!DC->isModuleScopeContext() || !DC->getParentModule()->isStdlibModule()) 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; } Type SubscriptDecl::getGetterType() const { // If we have a getter, use its type. if (auto getter = getGetter()) return getter->getType(); // Otherwise, compute the type. GenericParamList *outerParams = nullptr; auto selfTy = getDeclContext()->getSelfTypeInContext(/*isStatic=*/false, /*@mutating*/false, &outerParams); // Form the () -> element function type. auto &ctx = getASTContext(); Type getterTy = FunctionType::get(TupleType::getEmpty(ctx), getElementType()); // Prepend the indices. getterTy = FunctionType::get(getIndices()->getType(), getterTy); // Prepend the 'self' type. if (outerParams) getterTy = PolymorphicFunctionType::get(selfTy, getterTy, outerParams); else getterTy = FunctionType::get(selfTy, getterTy); return getterTy; } Type SubscriptDecl::getGetterInterfaceType() const { // If we have a getter, use its type. if (auto getter = getGetter()) return getter->getInterfaceType(); // Otherwise, compute the type. auto selfTy = getDeclContext()->getInterfaceSelfType(/*isStatic=*/false, /*@mutating*/ false); auto interfaceTy = getInterfaceType()->castTo(); auto indicesTy = interfaceTy->getInput(); auto elementTy = interfaceTy->getResult(); // Form the () -> element function type. auto &ctx = getASTContext(); Type getterTy = FunctionType::get(TupleType::getEmpty(ctx), elementTy); // Prepend the indices. getterTy = FunctionType::get(indicesTy, getterTy); // Prepend the 'self' type. ArrayRef genericParams; ArrayRef requirements; std::tie(genericParams, requirements) = getDeclContext()->getGenericSignatureOfContext(); if (genericParams.empty() && requirements.empty()) getterTy = FunctionType::get(selfTy, getterTy); else getterTy = GenericFunctionType::get(genericParams, requirements, selfTy, getterTy, AnyFunctionType::ExtInfo()); return getterTy; } Type SubscriptDecl::getSetterType() const { // If we have a setter, use its type. if (auto setter = getSetter()) return setter->getType(); // Otherwise, compute the type. GenericParamList *outerParams = nullptr; auto selfTy = getDeclContext()->getSelfTypeInContext(/*isStatic=*/false, /*@mutating*/true, &outerParams); // Form the element -> () function type. auto &ctx = getASTContext(); TupleTypeElt valueElt(getElementType(), ctx.getIdentifier("value")); Type setterTy = FunctionType::get(TupleType::get(valueElt, ctx), TupleType::getEmpty(ctx)); // Prepend the indices. setterTy = FunctionType::get(getIndices()->getType(), setterTy); // Prepend the 'self' type. if (outerParams) setterTy = PolymorphicFunctionType::get(selfTy, setterTy, outerParams); else setterTy = FunctionType::get(selfTy, setterTy); return setterTy; } Type SubscriptDecl::getSetterInterfaceType() const { // If we have a setter, use its type. if (auto setter = getSetter()) return setter->getInterfaceType(); // Otherwise, compute the type. auto selfTy = getDeclContext()->getInterfaceSelfType(/*isStatic=*/false, /*@mutating*/ true); auto interfaceTy = getInterfaceType()->castTo(); auto indicesTy = interfaceTy->getInput(); auto elementTy = interfaceTy->getResult(); // Form the element -> () function type. auto &ctx = getASTContext(); TupleTypeElt valueElt(elementTy, ctx.getIdentifier("value")); Type setterTy = FunctionType::get(TupleType::get(valueElt, ctx), TupleType::getEmpty(ctx)); // Prepend the indices. setterTy = FunctionType::get(indicesTy, setterTy); // Prepend the 'self' type. ArrayRef genericParams; ArrayRef requirements; std::tie(genericParams, requirements) = getDeclContext()->getGenericSignatureOfContext(); if (genericParams.empty() && requirements.empty()) setterTy = FunctionType::get(selfTy, setterTy); else setterTy = GenericFunctionType::get(genericParams, requirements, selfTy, setterTy, AnyFunctionType::ExtInfo()); return setterTy; } 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 SubscriptDecl::getSourceRange() const { if (getBracesRange().isValid()) return { getSubscriptLoc(), getBracesRange().End }; return { getSubscriptLoc(), ElementTy.getSourceRange().End }; } Type AbstractFunctionDecl:: computeSelfType(GenericParamList **outerGenericParams) { bool isStatic = false; bool isMutating = false; if (auto *FD = dyn_cast(this)) { isStatic = FD->isStatic(); isMutating = FD->isMutating(); } else if (isa(this) || isa(this)) { // constructors and destructors of value types always have an implicitly // @inout self. isMutating = true; } return getDeclContext()->getSelfTypeInContext(isStatic, isMutating, outerGenericParams); } 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')). const Pattern *P = ArgParamPatterns[0]->getSemanticsProvidingPattern(); // The decl should be named 'self' and be implicit. auto NP = dyn_cast(P); if (NP && NP->getBoundName().str() == "self" && NP->isImplicit()) 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::getResultType() 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(getASTContext()); 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() }; } SourceRange EnumElementDecl::getSourceRange() const { if (RawValueExpr && !RawValueExpr->isImplicit()) return {getStartLoc(), RawValueExpr->getEndLoc()}; if (ArgumentType.hasLocation()) return {getStartLoc(), ArgumentType.getSourceRange().End}; return {getStartLoc(), getNameLoc()}; } 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)->getSourceRange(); case DeclContextKind::NominalTypeDecl: return cast(DC)->getSourceRange(); default: if (isInvalid()) return getConstructorLoc(); llvm_unreachable("Unhandled decl kind"); } } return { getConstructorLoc(), Body->getEndLoc() }; } 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 ConstructorDecl::getInitializerInterfaceType() { if (!InitializerInterfaceType) { assert((!InitializerType || !InitializerType->is()) && "polymorphic function type is invalid interface type"); // Don't cache type variable types. if (InitializerType->hasTypeVariable()) return InitializerType; InitializerInterfaceType = InitializerType; } return InitializerInterfaceType; } void ConstructorDecl::setInitializerInterfaceType(Type t) { assert(!t->is() && "polymorphic function type is invalid interface type"); InitializerInterfaceType = t; } ConstructorDecl::BodyInitKind ConstructorDecl::getDelegatingOrChainedInitKind(DiagnosticEngine *diags, Expr **init) { assert(hasBody() && "Constructor does not have a definition"); if (init) *init = nullptr; // If we already computed the result, return it. if (ConstructorDeclBits.ComputedBodyInitKind) { return static_cast( ConstructorDeclBits.ComputedBodyInitKind - 1); } struct FindReferenceToInitializer : ASTWalker { BodyInitKind Kind = BodyInitKind::None; Expr *InitExpr = nullptr; DiagnosticEngine *Diags; FindReferenceToInitializer(DiagnosticEngine *diags) : Diags(diags) { } std::pair walkToExprPre(Expr *E) override { if (auto apply = dyn_cast(E)) { if (isa( apply->getFn()->getSemanticsProvidingExpr())) { BodyInitKind myKind; if (isa(apply->getArg()->getSemanticsProvidingExpr())) myKind = BodyInitKind::Chained; else myKind = BodyInitKind::Delegating; if (Kind == BodyInitKind::None) { Kind = myKind; // If we're not emitting diagnostics, we're done. if (!Diags) { return { false, nullptr }; } InitExpr = E; return { true, E }; } assert(Diags && "Failed to abort traversal early"); // If the kind changed, complain. if (Kind != myKind) { // The kind changed. Complain. Diags->diagnose(E->getLoc(), diag::init_delegates_and_chains); Diags->diagnose(InitExpr->getLoc(), diag::init_delegation_or_chain, Kind == BodyInitKind::Chained); } return { true, E }; } } // Don't walk into closures. if (isa(E)) return { false, E }; return { true, E }; } } finder(diags); getBody()->walk(finder); // If we didn't find any delegating or chained initializers, check whether // we have a class with a superclass: it gets an implicit chained initializer. if (finder.Kind == BodyInitKind::None) { if (auto classDecl = getDeclContext()->getDeclaredTypeInContext() ->getClassOrBoundGenericClass()) { if (classDecl->getSuperclass()) finder.Kind = BodyInitKind::ImplicitChained; } } // Cache the result. ConstructorDeclBits.ComputedBodyInitKind = static_cast(finder.Kind) + 1; if (init) *init = finder.InitExpr; return finder.Kind; } SourceRange DestructorDecl::getSourceRange() const { if (getBodyKind() == BodyKind::Unparsed || getBodyKind() == BodyKind::Skipped) return { getDestructorLoc(), BodyEndLoc }; if (getBodyKind() == BodyKind::None) return getDestructorLoc(); return { getDestructorLoc(), Body->getEndLoc() }; }