//===--- 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/TypeLoc.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/Support/raw_ostream.h" using namespace swift; /// getASTContext - Return the ASTContext for a specified DeclContetx by /// walking up to the translation unit and returning its ASTContext. ASTContext &DeclContext::getASTContext() { if (Module *M = dyn_cast(this)) return M->Ctx; return getParent()->getASTContext(); } Type DeclContext::getDeclaredTypeOfContext() const { switch (getContextKind()) { case DeclContextKind::BuiltinModule: case DeclContextKind::CapturingExpr: case DeclContextKind::TopLevelCodeDecl: case DeclContextKind::TranslationUnit: case DeclContextKind::SerializedModule: case DeclContextKind::ClangModule: case DeclContextKind::ConstructorDecl: case DeclContextKind::DestructorDecl: return Type(); case DeclContextKind::ExtensionDecl: return cast(this)->getExtendedType(); case DeclContextKind::NominalTypeDecl: return cast(this)->getDeclaredType(); } } Type DeclContext::getDeclaredTypeInContext() { switch (getContextKind()) { case DeclContextKind::BuiltinModule: case DeclContextKind::CapturingExpr: case DeclContextKind::TopLevelCodeDecl: case DeclContextKind::TranslationUnit: case DeclContextKind::SerializedModule: case DeclContextKind::ClangModule: case DeclContextKind::ConstructorDecl: case DeclContextKind::DestructorDecl: return Type(); case DeclContextKind::ExtensionDecl: { auto ty = cast(this)->getExtendedType(); if (auto unbound = ty->getAs()) return unbound->getDecl()->getDeclaredTypeInContext(); if (auto nominal = ty->getAs()) return nominal->getDecl()->getDeclaredTypeInContext(); return Type(); } case DeclContextKind::NominalTypeDecl: return cast(this)->getDeclaredTypeInContext(); } } GenericParamList *DeclContext::getGenericParamsOfContext() const { switch (getContextKind()) { case DeclContextKind::BuiltinModule: case DeclContextKind::TopLevelCodeDecl: case DeclContextKind::TranslationUnit: case DeclContextKind::SerializedModule: case DeclContextKind::ClangModule: return nullptr; case DeclContextKind::CapturingExpr: { if (auto funcE = dyn_cast(this)) { if (auto funcD = funcE->getDecl()) { if (auto gp = funcD->getGenericParams()) { return gp; } return funcD->getDeclContext()->getGenericParamsOfContext(); } } return nullptr; } case DeclContextKind::ConstructorDecl: { auto constructor = cast(this); if (auto gp = constructor->getGenericParams()) return gp; return constructor->getDeclContext()->getGenericParamsOfContext(); } case DeclContextKind::DestructorDecl: return cast(this)->getDeclContext() ->getGenericParamsOfContext(); case DeclContextKind::NominalTypeDecl: { auto nominal = cast(this); if (auto gp = nominal->getGenericParams()) return gp; return nominal->getDeclContext()->getGenericParamsOfContext(); } case DeclContextKind::ExtensionDecl: { auto extension = cast(this); auto extendedType = extension->getExtendedType(); if (auto unbound = extendedType->getAs()) { return unbound->getDecl()->getGenericParams(); } if (auto nominalTy = extendedType->getAs()) { auto nominalDecl = nominalTy->getDecl(); if (auto gp = nominalDecl->getGenericParams()) return gp; return nominalDecl->getDeclContext()->getGenericParamsOfContext(); } // FIXME: Eventually, extensions will be able to have their own // generic parameters. return nullptr; } } llvm_unreachable("Unhandled declaration context kind"); } // 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 DeclContext using the allocator in ASTContext. void *DeclContext::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); } Module *Decl::getModuleContext() const { DeclContext *dc = getDeclContext(); while (!dc->isModuleContext()) dc = dc->getParent(); return cast(dc); } // 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); } 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, ArrayRef Path, bool isStdlibImport) { void *buffer = Ctx.Allocate(sizeof(ImportDecl) + Path.size() * sizeof(AccessPathElement), alignof(ImportDecl)); return new (buffer) ImportDecl(DC, ImportLoc, Path, isStdlibImport); } ImportDecl::ImportDecl(DeclContext *DC, SourceLoc ImportLoc, ArrayRef Path, bool isStdlibImport) : Decl(DeclKind::Import, DC), ImportLoc(ImportLoc), IsStdlibImport(isStdlibImport), NumPathElements(Path.size()) { memcpy(getPathBuffer(), Path.data(), Path.size() * sizeof(AccessPathElement)); } SourceRange PatternBindingDecl::getSourceRange() const { if (Init && !Init->isImplicit()) return { VarLoc, Init->getSourceRange().End }; 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()); } static Type getRValueType(Type type) { CanType canType = type->getCanonicalType(); // Strip l-valueness. if (isa(canType)) { return type->castTo()->getObjectType(); // Ignore ownership qualification. } else if (isa(canType)) { return type->castTo()->getReferentType(); // No other transforms necessary. } else { return type; } } /// getTypeOfRValue - Return the type of an r-value reference to this value. Type ValueDecl::getTypeOfRValue() const { Type type = getType(); if (isReferencedAsLValue()) { type = getRValueType(type); } return type; } /// getTypeOfReference - Return the full type judgement for a non-member /// reference to this value. Type ValueDecl::getTypeOfReference(Type baseType) const { if (isReferencedAsLValue()) { // Determine the qualifiers we want. LValueType::Qual quals = (baseType ? LValueType::Qual::DefaultForMemberAccess : LValueType::Qual::DefaultForVar); if (!isSettableOnBase(baseType)) quals |= LValueType::Qual::NonSettable; return LValueType::get(getRValueType(getType()), quals, getASTContext()); } return Ty; } /// isDefinition - Return true if this is a definition of a decl, not a /// forward declaration (e.g. of a function) that is implemented outside of /// the swift code. bool ValueDecl::isDefinition() const { switch (getKind()) { case DeclKind::Import: case DeclKind::Extension: case DeclKind::PatternBinding: case DeclKind::Subscript: case DeclKind::TopLevelCode: case DeclKind::Constructor: case DeclKind::Destructor: case DeclKind::InfixOperator: case DeclKind::PrefixOperator: case DeclKind::PostfixOperator: llvm_unreachable("non-value decls shouldn't get here"); case DeclKind::Func: return cast(this)->getBody() != 0; case DeclKind::Var: case DeclKind::OneOf: case DeclKind::OneOfElement: case DeclKind::Struct: case DeclKind::Class: case DeclKind::TypeAlias: 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::TopLevelCode: case DeclKind::InfixOperator: case DeclKind::PrefixOperator: case DeclKind::PostfixOperator: llvm_unreachable("Not a ValueDecl"); case DeclKind::Class: case DeclKind::OneOf: case DeclKind::Protocol: case DeclKind::Struct: case DeclKind::TypeAlias: // 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::OneOfElement: // oneof 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; } std::pair ValueDecl::getDefaultArg(unsigned index) const { ArrayRef patterns; if (auto func = dyn_cast(this)) { patterns = func->getBody()->getArgParamPatterns(); // Skip the 'this' parameter; it is not counted. if (func->getDeclContext()->isTypeContext()) patterns = patterns.slice(1); } else { auto constructor = dyn_cast(this); patterns = constructor->getArguments(); } // 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 pattern = origPattern->getSemanticsProvidingPattern(); auto tuplePattern = dyn_cast(pattern); if (!tuplePattern) { if (index == 0) { return { DefaultArgumentKind::None, Type() }; } --index; continue; } for (auto &elt : tuplePattern->getFields()) { if (index == 0) { found = &elt; break; } --index; } if (found) break; } assert(found && "No argument with this index"); return { found->getDefaultArgKind(), found->getPattern()->getType() }; } Type TypeDecl::getDeclaredType() const { if (auto TAD = dyn_cast(this)) return TAD->getAliasType(); return cast(this)->getDeclaredType(); } 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()->getDeclaredType()); 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; } TypeAliasDecl::TypeAliasDecl(SourceLoc TypeAliasLoc, Identifier Name, SourceLoc NameLoc, TypeLoc UnderlyingTy, DeclContext *DC, MutableArrayRef Inherited) : TypeDecl(DeclKind::TypeAlias, DC, Name, Inherited, Type()), TypeAliasLoc(TypeAliasLoc), NameLoc(NameLoc), 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)); TypeAliasDeclBits.GenericParameter = false; } SourceRange TypeAliasDecl::getSourceRange() const { if (UnderlyingTy.hasLocation()) return { TypeAliasLoc, UnderlyingTy.getSourceRange().End }; // FIXME: Inherits clauses return { TypeAliasLoc, NameLoc }; } OneOfDecl::OneOfDecl(SourceLoc OneOfLoc, bool Enum, Identifier Name, SourceLoc NameLoc, MutableArrayRef Inherited, GenericParamList *GenericParams, DeclContext *Parent) : NominalTypeDecl(DeclKind::OneOf, Parent, Name, Inherited, GenericParams), OneOfLoc(OneOfLoc), NameLoc(NameLoc) { // Compute the associated type for this OneOfDecl. ASTContext &Ctx = Parent->getASTContext(); if (!GenericParams) DeclaredTy = OneOfType::get(this, Parent->getDeclaredTypeInContext(), Ctx); else DeclaredTy = UnboundGenericType::get(this, Parent->getDeclaredTypeInContext(), Ctx); // Set the type of the OneOfDecl to the right MetaTypeType. setType(MetaTypeType::get(DeclaredTy, Ctx)); } StructDecl::StructDecl(SourceLoc StructLoc, Identifier Name, SourceLoc NameLoc, MutableArrayRef Inherited, GenericParamList *GenericParams, DeclContext *Parent) : NominalTypeDecl(DeclKind::Struct, Parent, Name, Inherited, GenericParams), StructLoc(StructLoc), NameLoc(NameLoc){ // Compute the associated type for this StructDecl. ASTContext &Ctx = Parent->getASTContext(); if (!GenericParams) DeclaredTy = StructType::get(this, Parent->getDeclaredTypeInContext(), Ctx); else DeclaredTy = UnboundGenericType::get(this, Parent->getDeclaredTypeInContext(), Ctx); // Set the type of the StructDecl to the right MetaTypeType. setType(MetaTypeType::get(DeclaredTy, Ctx)); } ClassDecl::ClassDecl(SourceLoc ClassLoc, Identifier Name, SourceLoc NameLoc, MutableArrayRef Inherited, GenericParamList *GenericParams, DeclContext *Parent) : NominalTypeDecl(DeclKind::Class, Parent, Name, Inherited, GenericParams), ClassLoc(ClassLoc), NameLoc(NameLoc) { // Compute the associated type for this ClassDecl. ASTContext &Ctx = Parent->getASTContext(); if (!GenericParams) DeclaredTy = ClassType::get(this, Parent->getDeclaredTypeInContext(), Ctx); else DeclaredTy = UnboundGenericType::get(this, Parent->getDeclaredTypeInContext(), Ctx); // Set the type of the ClassDecl to the right MetaTypeType. setType(MetaTypeType::get(DeclaredTy, Ctx)); } OneOfElementDecl *OneOfDecl::getElement(Identifier Name) const { // FIXME: Linear search is not great for large oneof decls. for (Decl *D : getMembers()) if (OneOfElementDecl *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, Inherited, nullptr), ProtocolLoc(ProtocolLoc), NameLoc(NameLoc) { // Compute the associated type for this ClassDecl. ASTContext &Ctx = DC->getASTContext(); DeclaredTy = new (Ctx, AllocationArena::Permanent) ProtocolType(this, Ctx); // Set the type of the ProtocolDecl to the right MetaTypeType. setType(MetaTypeType::get(DeclaredTy, Ctx)); } 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 Inherited : Current->getInherited()) { SmallVector InheritedDecls; if (Inherited.getType()->isExistentialType(InheritedDecls)) { for (auto InheritedProto : InheritedDecls) { if (InheritedProto == Super) return true; else 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 IType : Current->getInherited()) { SmallVector InheritedDecls; if (IType.getType()->isExistentialType(InheritedDecls)) { for (auto InheritedProto : InheritedDecls) { if (Inherited.insert(InheritedProto)) Stack.push_back(InheritedProto); } } } } } bool ProtocolDecl::requiresClass() { return RequiresClass.cache([&] { // If we have the [class_protocol] attribute, we're trivially a class // protocol. if (getAttrs().isClassProtocol()) return true; // Check inherited protocols for class-ness. for (TypeLoc inherited : getInherited()) { SmallVector inheritedProtos; if (inherited.getType()->isExistentialType(inheritedProtos)) for (auto *proto : inheritedProtos) if (proto->requiresClass()) return true; } return false; }); } TypeAliasDecl *ProtocolDecl::getThis() const { for (auto member : getMembers()) { if (auto assocType = dyn_cast(member)) if (assocType->getName().str() == "This") return assocType; } llvm_unreachable("No 'This' associated type?"); } void VarDecl::setProperty(ASTContext &Context, SourceLoc LBraceLoc, FuncDecl *Get, FuncDecl *Set, SourceLoc RBraceLoc) { assert(!GetSet && "Variable is already a property?"); 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); } VarDecl *FuncDecl::getImplicitThisDecl() const { return Body->getImplicitThisDecl(); } /// getNaturalArgumentCount - Returns the "natural" number of /// argument clauses taken by this function. unsigned FuncDecl::getNaturalArgumentCount() const { return getBody()->getNaturalArgumentCount(); } ArrayRef FuncDecl::getCaptures() const { if (Body) return Body->getCaptures(); else return {}; } /// getExtensionType - If this is a method in a type extension for some type, /// return that type, otherwise return Type(). Type FuncDecl::getExtensionType() const { DeclContext *DC = getDeclContext(); switch (DC->getContextKind()) { case DeclContextKind::TranslationUnit: case DeclContextKind::BuiltinModule: case DeclContextKind::SerializedModule: case DeclContextKind::ClangModule: case DeclContextKind::CapturingExpr: case DeclContextKind::TopLevelCodeDecl: case DeclContextKind::ConstructorDecl: case DeclContextKind::DestructorDecl: return Type(); case DeclContextKind::NominalTypeDecl: return cast(DC)->getDeclaredType(); case DeclContextKind::ExtensionDecl: { auto ext = cast(DC); if (ext->isInvalid()) return ErrorType::get(getASTContext()); return ext->getExtendedType(); } } llvm_unreachable("bad context kind"); } /// computeThisType - If this is a method in a type extension for some type, /// compute and return the type to be used for the 'this' argument of the /// type (which varies based on whether the extended type is a reference type /// or not), or an empty Type() if no 'this' argument should exist. This can /// only be used after name binding has resolved types. Type FuncDecl::computeThisType(GenericParamList **OuterGenericParams) const { if (OuterGenericParams) *OuterGenericParams = nullptr; Type ContainerType = getExtensionType(); if (ContainerType.isNull()) return ContainerType; // For a protocol, the type of 'this' is the associated type 'This', not // the protocol itself. if (auto Protocol = ContainerType->getAs()) { TypeAliasDecl *This = 0; for (auto Member : Protocol->getDecl()->getMembers()) { This = dyn_cast(Member); if (!This) continue; // FIXME: Sane way to identify 'This'? if (This->getName().str() == "This") break; This = nullptr; } assert(This && "Missing 'This' associated type in protocol"); ContainerType = This->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 'this' 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::DefaultForByrefThis, getASTContext()); } bool FuncDecl::isUnaryOperator() const { if (!isOperator()) return false; unsigned opArgIndex = isa(getDeclContext()) ? 1 : 0; auto *argTuple = dyn_cast(getBody()->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(getBody()->getArgParamPatterns()[opArgIndex]); if (!argTuple) return false; return argTuple->getNumFields() == 2 || (argTuple->getNumFields() == 1 && argTuple->hasVararg()); } StringRef VarDecl::getObjCGetterSelector(llvm::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(llvm::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(llvm::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 = getBody()->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 StringRef(buffer.data(), buffer.size()); // 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 { return Body->getSourceRange(); } SourceRange OneOfElementDecl::getSourceRange() const { if (ResultType.hasLocation()) return {getStartLoc(), ResultType.getSourceRange().End}; if (ArgumentType.hasLocation()) return {getStartLoc(), ArgumentType.getSourceRange().End}; return {getStartLoc(), IdentifierLoc}; } SourceLoc SubscriptDecl::getLoc() const { return Indices->getStartLoc(); } SourceRange SubscriptDecl::getSourceRange() const { if (Braces.isValid()) return { SubscriptLoc, Braces.End }; return { SubscriptLoc, ElementTy.getSourceRange().End }; } SourceLoc ConstructorDecl::getLoc() const { return Arguments->getStartLoc(); } SourceRange ConstructorDecl::getSourceRange() const { 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: llvm_unreachable("Unhandled decl kind"); } } return { ConstructorLoc, Body->getEndLoc() }; } Type ConstructorDecl::computeThisType(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(llvm::SmallVectorImpl &buffer) const { assert(buffer.empty()); llvm::raw_svector_ostream out(buffer); // If it's an empty tuple pattern, it's the nullary selector "init". // FIXME: This leaves us without a way to describe "new". auto tuple = dyn_cast(Arguments); if (tuple && tuple->getNumFields() == 0) { out << "init"; out.flush(); return StringRef(buffer.data(), buffer.size()); } // If it's not a tuple at all, it's the unary selector "init:". // FIXME: Diagnose this? if (!tuple) { out << "init:"; out.flush(); return StringRef(buffer.data(), buffer.size()); } // For every element, add a selector component. for (auto &elt : tuple->getFields()) { 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 StringRef(buffer.data(), buffer.size()); } Type DestructorDecl::computeThisType(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 { return { DestructorLoc, Body->getEndLoc() }; }