//===--- Decl.h - Swift Language Declaration ASTs ---------------*- C++ -*-===// // // 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 defines the Decl class and subclasses. // //===----------------------------------------------------------------------===// #ifndef SWIFT_DECL_H #define SWIFT_DECL_H #include "swift/AST/Attr.h" #include "swift/AST/CaptureInfo.h" #include "swift/AST/DeclContext.h" #include "swift/AST/DefaultArgumentKind.h" #include "swift/AST/KnownProtocols.h" #include "swift/AST/Identifier.h" #include "swift/AST/LazyResolver.h" #include "swift/AST/Requirement.h" #include "swift/AST/Substitution.h" #include "swift/AST/Type.h" #include "swift/AST/TypeLoc.h" #include "swift/Basic/OptionalEnum.h" #include "swift/Basic/Range.h" #include "swift/Basic/SourceLoc.h" #include "swift/Basic/STLExtras.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/SmallPtrSet.h" #include namespace clang { class Decl; class MacroInfo; class Module; class SourceLocation; class SourceRange; } namespace swift { enum class AccessSemantics : unsigned char; class ApplyExpr; class ArchetypeBuilder; class ArchetypeType; class ASTContext; class ASTPrinter; class ASTWalker; class DestructorDecl; class DiagnosticEngine; class DynamicSelfType; class Type; class Expr; class LiteralExpr; class FuncDecl; class BraceStmt; class DeclAttributes; class GenericSignature; class GenericTypeParamDecl; class GenericTypeParamType; class Module; class NameAliasType; class EnumElementDecl; class Pattern; struct PrintOptions; class ProtocolDecl; class ProtocolType; struct RawComment; enum class Resilience : unsigned char; class TypeAliasDecl; class Stmt; class SubscriptDecl; class ValueDecl; class VarDecl; /// Represents a clang declaration, macro, or module. class ClangNode { llvm::PointerUnion3 Ptr; public: ClangNode() = default; ClangNode(const clang::Decl *D) : Ptr(D) {} ClangNode(const clang::MacroInfo *MI) : Ptr(MI) {} ClangNode(const clang::Module *Mod) : Ptr(Mod) {} bool isNull() const { return Ptr.isNull(); } explicit operator bool() const { return !isNull(); } const clang::Decl *getAsDecl() const { return Ptr.dyn_cast(); } const clang::MacroInfo *getAsMacro() const { return Ptr.dyn_cast(); } const clang::Module *getAsModule() const { return Ptr.dyn_cast(); } const clang::Decl *castAsDecl() const { return Ptr.get(); } const clang::MacroInfo *castAsMacro() const { return Ptr.get(); } const clang::Module *castAsModule() const { return Ptr.get(); } clang::SourceLocation getLocation() const; clang::SourceRange getSourceRange() const; void *getOpaqueValue() const { return Ptr.getOpaqueValue(); } static inline ClangNode getFromOpaqueValue(void *VP) { ClangNode N; N.Ptr = decltype(Ptr)::getFromOpaqueValue(VP); return N; } }; enum class DeclKind : uint8_t { #define DECL(Id, Parent) Id, #define DECL_RANGE(Id, FirstId, LastId) \ First_##Id##Decl = FirstId, Last_##Id##Decl = LastId, #include "swift/AST/DeclNodes.def" }; /// Fine-grained declaration kind that provides a description of the /// kind of entity a declaration represents, as it would be used in /// diagnostics. /// /// For example, \c FuncDecl is a single declaration class, but it has /// several descriptive entries depending on whether it is an /// operator, global function, local function, method, (observing) /// accessor, etc. enum class DescriptiveDeclKind : uint8_t { Import, Extension, EnumCase, TopLevelCode, IfConfig, PatternBinding, Var, Param, Let, StaticVar, StaticLet, ClassVar, ClassLet, InfixOperator, PrefixOperator, PostfixOperator, TypeAlias, GenericTypeParam, AssociatedType, Enum, Struct, Class, Protocol, GenericEnum, GenericStruct, GenericClass, Subscript, Constructor, Destructor, LocalFunction, GlobalFunction, OperatorFunction, Method, StaticMethod, ClassMethod, Getter, Setter, MaterializeForSet, Addressor, MutableAddressor, WillSet, DidSet, EnumElement, }; /// Keeps track of stage of circularity checking for the given protocol. enum class CircularityCheck { /// Circularity has not yet been checked. Unchecked, /// We're currently checking circularity. Checking, /// Circularity has already been checked. Checked }; /// Keeps track of whrther a given class inherits initializers from its /// superclass. enum class StoredInheritsSuperclassInits { /// We have not yet checked. Unchecked, /// Superclass initializers are not inherited. NotInherited, /// Convenience initializers in the superclass are inherited. Inherited }; /// Describes which spelling was used in the source for the 'static' or 'class' /// keyword. enum class StaticSpellingKind : uint8_t { None, KeywordStatic, KeywordClass, }; /// Describes if an enum element constructor directly or indirectly references /// its enclosing type. enum class ElementRecursiveness { /// The element does not reference its enclosing type. NotRecursive, /// The element is currently being validated, and may references its enclosing /// type. PotentiallyRecursive, /// The element does not reference its enclosing type. Recursive }; /// Diagnostic printing of \c StaticSpellingKind. llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, StaticSpellingKind SSK); /// Encapsulation of the overload signature of a given declaration, /// which is used to determine uniqueness of a declaration within a /// given context. /// /// Two definitions in the same context may not have the same overload /// signature. struct OverloadSignature { /// The full name of the declaration. DeclName Name; /// The interface type of the declaration, when relevant to the /// overload signature. CanType InterfaceType; /// The kind of unary operator. UnaryOperatorKind UnaryOperator = UnaryOperatorKind::None; /// Whether this is an instance member. bool IsInstanceMember = false; /// Whether this is a property. bool IsProperty = false; }; /// Determine whether two overload signatures conflict. bool conflicting(const OverloadSignature& sig1, const OverloadSignature& sig2); /// Decl - Base class for all declarations in Swift. class alignas(1 << DeclAlignInBits) Decl { class DeclBitfields { friend class Decl; unsigned Kind : 8; /// \brief Whether this declaration is invalid. unsigned Invalid : 1; /// \brief Whether this declaration was implicitly created, e.g., /// an implicit constructor in a struct. unsigned Implicit : 1; /// \brief Whether this declaration was mapped directly from a Clang AST. /// /// Use getClangAST() to retrieve the corresponding Clang AST. unsigned FromClang : 1; /// \brief Whether we've already performed early attribute validation. /// FIXME: This is ugly. unsigned EarlyAttrValidation : 1; /// \brief Whether or not this declaration is currently being type-checked. unsigned BeingTypeChecked : 1; }; enum { NumDeclBits = 13 }; static_assert(NumDeclBits <= 32, "fits in an unsigned"); class PatternBindingDeclBitfields { friend class PatternBindingDecl; unsigned : NumDeclBits; /// \brief Whether this pattern binding declares static variables. unsigned IsStatic : 1; /// \brief Whether 'static' or 'class' was used. unsigned StaticSpelling : 2; /// \brief Whether this pattern binding appears in a conditional statement. unsigned Conditional : 1; }; enum { NumPatternBindingDeclBits = NumDeclBits + 4 }; static_assert(NumPatternBindingDeclBits <= 32, "fits in an unsigned"); class ValueDeclBitfields { friend class ValueDecl; friend class MemberLookupTable; unsigned : NumDeclBits; unsigned ConformsToProtocolRequrement : 1; unsigned AlreadyInLookupTable : 1; /// Whether we have already checked whether this declaration is a /// redeclaration. unsigned CheckedRedeclaration : 1; }; enum { NumValueDeclBits = NumDeclBits + 3 }; static_assert(NumValueDeclBits <= 32, "fits in an unsigned"); class AbstractStorageDeclBitfields { friend class AbstractStorageDecl; unsigned : NumValueDeclBits; /// Whether we are overridden later unsigned Overridden : 1; /// The storage kind. unsigned StorageKind : 4; }; enum { NumAbstractStorageDeclBits = NumValueDeclBits + 5 }; static_assert(NumAbstractStorageDeclBits <= 32, "fits in an unsigned"); class VarDeclBitfields { friend class VarDecl; unsigned : NumAbstractStorageDeclBits; /// \brief Whether this property is a type property (currently unfortunately /// called 'static'). unsigned IsStatic : 1; /// \brief Whether this is a 'let' property, which can only be initialized /// in its declaration, and never assigned to, making it immutable. unsigned IsLet : 1; /// \brief Whether this is a property used in expressions in the debugger. /// It is up to the debugger to instruct SIL how to access this variable. unsigned IsDebuggerVar : 1; }; enum { NumVarDeclBits = NumAbstractStorageDeclBits + 3 }; static_assert(NumVarDeclBits <= 32, "fits in an unsigned"); class EnumElementDeclBitfields { friend class EnumElementDecl; unsigned : NumValueDeclBits; /// \brief Whether or not this element directly or indirectly references /// the enum type. unsigned Recursiveness : 2; }; enum { NumEnumElementDeclBits = NumValueDeclBits + 2 }; static_assert(NumEnumElementDeclBits <= 32, "fits in an unsigned"); class AbstractFunctionDeclBitfields { friend class AbstractFunctionDecl; unsigned : NumValueDeclBits; /// \see AbstractFunctionDecl::BodyKind unsigned BodyKind : 3; /// Number of curried parameter patterns (tuples). unsigned NumParamPatterns : 6; /// Whether we are overridden later unsigned Overridden : 1; }; enum { NumAbstractFunctionDeclBits = NumValueDeclBits + 10 }; static_assert(NumAbstractFunctionDeclBits <= 32, "fits in an unsigned"); class FuncDeclBitfields { friend class FuncDecl; unsigned : NumAbstractFunctionDeclBits; /// Whether this function is a 'static' method. unsigned IsStatic : 1; /// \brief Whether 'static' or 'class' was used. unsigned StaticSpelling : 2; /// Whether this function is a 'mutating' method. unsigned Mutating : 1; /// Whether this function has a dynamic Self return type. unsigned HasDynamicSelf : 1; }; enum { NumFuncDeclBits = NumAbstractFunctionDeclBits + 5 }; static_assert(NumFuncDeclBits <= 32, "fits in an unsigned"); class ConstructorDeclBitfields { friend class ConstructorDecl; unsigned : NumAbstractFunctionDeclBits; /// The body initialization kind (+1), or zero if not yet computed. /// /// This value is cached but is not serialized, because it is a property /// of the definition of the constructor that is useful only to semantic /// analysis and SIL generation. unsigned ComputedBodyInitKind : 3; /// The kind of initializer we have. unsigned InitKind : 2; /// Whether this initializer is a stub placed into a subclass to /// catch invalid delegations to a designated initializer not /// overridden by the subclass. A stub will always trap at runtime. /// /// Initializer stubs can be invoked from Objective-C or through /// the Objective-C runtime; there is no way to directly express /// an object construction that will invoke a stub. unsigned HasStubImplementation : 1; }; enum { NumConstructorDeclBits = NumAbstractFunctionDeclBits + 6 }; static_assert(NumConstructorDeclBits <= 32, "fits in an unsigned"); class TypeDeclBitfields { friend class TypeDecl; unsigned : NumValueDeclBits; /// Whether we have already checked the inheritance clause. /// /// FIXME: Is this too fine-grained? unsigned CheckedInheritanceClause : 1; /// Whether we have already set the protocols to which this type conforms. unsigned ProtocolsSet : 1; }; enum { NumTypeDeclBits = NumValueDeclBits + 2 }; static_assert(NumTypeDeclBits <= 32, "fits in an unsigned"); class NominalTypeDeclBitFields { friend class NominalTypeDecl; unsigned : NumTypeDeclBits; /// Whether or not the nominal type decl has delayed protocol or member /// declarations. unsigned HasDelayedMembers : 1; /// Whether we have already added implicitly-defined initializers /// to this declaration. unsigned AddedImplicitInitializers : 1; }; enum { NumNominalTypeDeclBits = NumTypeDeclBits + 2 }; static_assert(NumNominalTypeDeclBits <= 32, "fits in an unsigned"); class ProtocolDeclBitfields { friend class ProtocolDecl; unsigned : NumNominalTypeDeclBits; /// Whether the \c RequiresClass bit is valid. unsigned RequiresClassValid : 1; /// Whether this is a class-bounded protocol. unsigned RequiresClass : 1; /// Whether the \c ExistentialConformsToSelf bit is valid. unsigned ExistentialConformsToSelfValid : 1; /// Whether the existential of this protocol conforms to itself. unsigned ExistentialConformsToSelf : 1; /// If this is a compiler-known protocol, this will be a KnownProtocolKind /// value, plus one. Otherwise, it will be 0. unsigned KnownProtocol : 5; /// The stage of the circularity check for this protocol. unsigned Circularity : 2; /// True if the protocol has requirements that cannot be satisfied (e.g. /// because they could not be imported from Objective-C). unsigned HasMissingRequirements : 1; }; enum { NumProtocolDeclBits = NumNominalTypeDeclBits + 12 }; static_assert(NumProtocolDeclBits <= 32, "fits in an unsigned"); class ClassDeclBitfields { friend class ClassDecl; unsigned : NumNominalTypeDeclBits; /// The stage of the inheritance circularity check for this class. unsigned Circularity : 2; /// Whether this class requires all of its instance variables to /// have in-class initializers. unsigned RequiresStoredPropertyInits : 1; /// Whether this class inherits its superclass's convenience /// initializers. /// /// This is a value of \c StoredInheritsSuperclassInits. unsigned InheritsSuperclassInits : 2; /// Whether this class is "foreign". unsigned Foreign : 1; /// Whether this class contains a destructor decl. /// /// A fully type-checked class always contains a destructor member, even if /// it is implicit. This bit is used during parsing and type-checking to /// control inserting the implicit destructor. unsigned HasDestructorDecl : 1; }; enum { NumClassDeclBits = NumNominalTypeDeclBits + 7 }; static_assert(NumClassDeclBits <= 32, "fits in an unsigned"); class StructDeclBitfields { friend class StructDecl; unsigned : NumNominalTypeDeclBits; /// True if this struct has storage for fields that aren't accessible in /// Swift. unsigned HasUnreferenceableStorage : 1; }; enum { NumStructDeclBits = NumNominalTypeDeclBits + 1 }; static_assert(NumStructDeclBits <= 32, "fits in an unsigned"); class EnumDeclBitfields { friend class EnumDecl; unsigned : NumNominalTypeDeclBits; /// The stage of the raw type circularity check for this class. unsigned Circularity : 2; }; enum { NumEnumDeclBits = NumNominalTypeDeclBits + 2 }; static_assert(NumEnumDeclBits <= 32, "fits in an unsigned"); class InfixOperatorDeclBitfields { friend class InfixOperatorDecl; unsigned : NumDeclBits; unsigned Associativity : 2; unsigned Precedence : 8; unsigned Assignment : 1; unsigned IsAssocImplicit : 1; unsigned IsPrecedenceImplicit : 1; unsigned IsAssignmentImplicit : 1; }; enum { NumInfixOperatorDeclBits = NumDeclBits + 14 }; static_assert(NumInfixOperatorDeclBits <= 32, "fits in an unsigned"); class ImportDeclBitfields { friend class ImportDecl; unsigned : NumDeclBits; unsigned ImportKind : 3; }; enum { NumImportDeclBits = NumDeclBits + 3 }; static_assert(NumImportDeclBits <= 32, "fits in an unsigned"); class ExtensionDeclBitfields { friend class ExtensionDecl; unsigned : NumDeclBits; /// Whether we have already checked the inheritance clause. /// /// FIXME: Is this too fine-grained? unsigned CheckedInheritanceClause : 1; /// Whether this extension has already been validated. unsigned Validated : 1; unsigned DefaultAccessLevel : 2; /// The number of ref-components following the ExtensionDecl. unsigned NumRefComponents : 8; }; enum { NumExtensionDeclBits = NumDeclBits + 12 }; static_assert(NumExtensionDeclBits <= 32, "fits in an unsigned"); protected: union { DeclBitfields DeclBits; PatternBindingDeclBitfields PatternBindingDeclBits; ValueDeclBitfields ValueDeclBits; AbstractStorageDeclBitfields AbstractStorageDeclBits; AbstractFunctionDeclBitfields AbstractFunctionDeclBits; VarDeclBitfields VarDeclBits; EnumElementDeclBitfields EnumElementDeclBits; FuncDeclBitfields FuncDeclBits; ConstructorDeclBitfields ConstructorDeclBits; TypeDeclBitfields TypeDeclBits; NominalTypeDeclBitFields NominalTypeDeclBits; ProtocolDeclBitfields ProtocolDeclBits; ClassDeclBitfields ClassDeclBits; StructDeclBitfields StructDeclBits; EnumDeclBitfields EnumDeclBits; InfixOperatorDeclBitfields InfixOperatorDeclBits; ImportDeclBitfields ImportDeclBits; ExtensionDeclBitfields ExtensionDeclBits; uint32_t OpaqueBits; }; // FIXME: Unused padding here. // Storage for the declaration attributes. DeclAttributes Attrs; /// The next declaration in the list of declarations within this /// member context. Decl *NextDecl = nullptr; friend class DeclIterator; friend class IterableDeclContext; friend class MemberLookupTable; private: DeclContext *Context; Decl(const Decl&) = delete; void operator=(const Decl&) = delete; protected: Decl(DeclKind kind, DeclContext *DC) : OpaqueBits(0), Context(DC) { DeclBits.Kind = unsigned(kind); DeclBits.Invalid = false; DeclBits.Implicit = false; DeclBits.FromClang = false; DeclBits.EarlyAttrValidation = false; DeclBits.BeingTypeChecked = false; } ClangNode getClangNodeImpl() const { assert(DeclBits.FromClang); return ClangNode::getFromOpaqueValue( *(reinterpret_cast(this) - 1)); } /// \brief Set the Clang node associated with this declaration. void setClangNode(ClangNode Node) { DeclBits.FromClang = true; // Extra memory is allocated for this. *(reinterpret_cast(this) - 1) = Node.getOpaqueValue(); } void updateClangNode(ClangNode node) { assert(hasClangNode()); setClangNode(node); } friend class ClangImporter; public: DeclKind getKind() const { return DeclKind(DeclBits.Kind); } /// \brief Retrieve the name of the given declaration kind. /// /// This name should only be used for debugging dumps and other /// developer aids, and should never be part of a diagnostic or exposed /// to the user of the compiler in any way. static StringRef getKindName(DeclKind K); /// Retrieve the descriptive kind for this declaration. DescriptiveDeclKind getDescriptiveKind() const; /// Produce a name for the given descriptive declaration kind, which /// is suitable for use in diagnostics. static StringRef getDescriptiveKindName(DescriptiveDeclKind K); DeclContext *getDeclContext() const { return Context; } void setDeclContext(DeclContext *DC); /// Retrieve the innermost declaration context corresponding to this /// declaration, which will either be the declaration itself (if it's /// also a declaration context) or its declaration context. DeclContext *getInnermostDeclContext(); /// \brief Retrieve the module in which this declaration resides. Module *getModuleContext() const; /// getASTContext - Return the ASTContext that this decl lives in. ASTContext &getASTContext() const { assert(Context && "Decl doesn't have an assigned context"); return Context->getASTContext(); } const DeclAttributes &getAttrs() const { return Attrs; } DeclAttributes &getAttrs() { return Attrs; } /// Returns the starting location of the entire declaration. SourceLoc getStartLoc() const { return getSourceRange().Start; } /// Returns the end location of the entire declaration. SourceLoc getEndLoc() const { return getSourceRange().End; } /// Returns the preferred location when referring to declarations /// in diagnostics. SourceLoc getLoc() const; /// Returns the source range of the entire declaration. SourceRange getSourceRange() const; SourceLoc TrailingSemiLoc; LLVM_ATTRIBUTE_DEPRECATED( void dump() const LLVM_ATTRIBUTE_USED, "only for use within the debugger"); void dump(raw_ostream &OS, unsigned Indent = 0) const; /// \brief Pretty-print the given declaration. /// /// \param OS Output stream to which the declaration will be printed. void print(raw_ostream &OS) const; void print(raw_ostream &OS, const PrintOptions &Opts) const; /// \brief Pretty-print the given declaration. /// /// \param Printer ASTPrinter object. /// /// \param Opts Options to control how pretty-printing is performed. /// /// \returns true if the declaration was printed or false if the print options /// required the declaration to be skipped from printing. bool print(ASTPrinter &Printer, const PrintOptions &Opts) const; /// \brief Determine whether this declaration should be printed when /// encountered in its declaration context's list of members. bool shouldPrintInContext(const PrintOptions &PO) const; bool walk(ASTWalker &walker); /// \brief Should this declaration be treated as if annotated with transparent /// attribute. bool isTransparent() const; /// \brief Return whether this declaration has been determined invalid. bool isInvalid() const { return DeclBits.Invalid; } /// \brief Mark this declaration invalid. void setInvalid() { DeclBits.Invalid = true; } /// \brief Determine whether this declaration was implicitly generated by the /// compiler (rather than explicitly written in source code). bool isImplicit() const { return DeclBits.Implicit; } /// \brief Mark this declaration as implicit. void setImplicit(bool implicit = true) { DeclBits.Implicit = implicit; } /// Whether we have already done early attribute validation. bool didEarlyAttrValidation() const { return DeclBits.EarlyAttrValidation; } /// Set whether we've performed early attribute validation. void setEarlyAttrValidation(bool validated = true) { DeclBits.EarlyAttrValidation = validated; } /// Whether the declaration is currently being validated. bool isBeingTypeChecked() { return DeclBits.BeingTypeChecked; } /// Toggle whether or not the declaration is being validated. void setIsBeingTypeChecked(bool ibt = true) { DeclBits.BeingTypeChecked = ibt; } /// \returns the unparsed comment attached to this declaration. RawComment getRawComment() const; /// \returns the brief comment attached to this declaration. StringRef getBriefComment() const; /// \brief Returns true if there is a Clang AST node associated /// with self. bool hasClangNode() const { return DeclBits.FromClang; } /// \brief Retrieve the Clang AST node from which this declaration was /// synthesized, if any. ClangNode getClangNode() const { if (!DeclBits.FromClang) return ClangNode(); return getClangNodeImpl(); } /// \brief Retrieve the Clang declaration from which this declaration was /// synthesized, if any. const clang::Decl *getClangDecl() const { if (!DeclBits.FromClang) return nullptr; return getClangNodeImpl().getAsDecl(); } /// \brief Retrieve the Clang macro from which this declaration was /// synthesized, if any. const clang::MacroInfo *getClangMacro() { if (!DeclBits.FromClang) return nullptr; return getClangNodeImpl().getAsMacro(); } bool isPrivateStdlibDecl() const; /// Whether this declaration is weak-imported. bool isWeakImported(Module *fromModule) const; // Make vanilla new/delete illegal for Decls. void *operator new(size_t Bytes) = delete; void operator delete(void *Data) = delete; // Only allow allocation of Decls using the allocator in ASTContext // or by doing a placement new. void *operator new(size_t Bytes, ASTContext &C, unsigned Alignment = alignof(Decl)); void *operator new(size_t Bytes, void *Mem) { assert(Mem); return Mem; } }; /// \brief A single requirement in a 'where' clause, which places additional /// restrictions on the generic parameters or associated types of a generic /// function, type, or protocol. /// /// This always represents a requirement spelled in the source code. It is /// never generated implicitly. class RequirementRepr { SourceLoc SeparatorLoc; RequirementKind Kind : 2; bool Invalid : 1; TypeLoc Types[2]; RequirementRepr(SourceLoc SeparatorLoc, RequirementKind Kind, TypeLoc FirstType, TypeLoc SecondType) : SeparatorLoc(SeparatorLoc), Kind(Kind), Invalid(false), Types{FirstType, SecondType} { } public: /// \brief Construct a new conformance requirement. /// /// \param Subject The type that must conform to the given protocol or /// composition, or be a subclass of the given class type. /// \param ColonLoc The location of the ':', or an invalid location if /// this requirement was implied. /// \param Constraint The protocol or protocol composition to which the /// subject must conform, or superclass from which the subject must inherit. static RequirementRepr getConformance(TypeLoc Subject, SourceLoc ColonLoc, TypeLoc Constraint) { return { ColonLoc, RequirementKind::Conformance, Subject, Constraint }; } /// \brief Construct a new same-type requirement. /// /// \param FirstType The first type. /// \param EqualLoc The location of the '==' in the same-type constraint, or /// an invalid location if this requirement was implied. /// \param SecondType The second type. static RequirementRepr getSameType(TypeLoc FirstType, SourceLoc EqualLoc, TypeLoc SecondType) { return { EqualLoc, RequirementKind::SameType, FirstType, SecondType }; } /// \brief Determine the kind of requirement RequirementKind getKind() const { return Kind; } /// \brief Determine whether this requirement is invalid. bool isInvalid() const { return Invalid; } /// \brief Mark this requirement invalid. void setInvalid() { Invalid = true; } /// \brief For a conformance requirement, return the subject of the /// conformance relationship. Type getSubject() const { assert(getKind() == RequirementKind::Conformance); return Types[0].getType(); } TypeRepr *getSubjectRepr() const { assert(getKind() == RequirementKind::Conformance); return Types[0].getTypeRepr(); } TypeLoc &getSubjectLoc() { assert(getKind() == RequirementKind::Conformance); return Types[0]; } const TypeLoc &getSubjectLoc() const { assert(getKind() == RequirementKind::Conformance); return Types[0]; } /// \brief For a conformance requirement, return the protocol or to which /// the subject conforms or superclass it inherits. Type getConstraint() const { assert(getKind() == RequirementKind::Conformance); return Types[1].getType(); } TypeLoc &getConstraintLoc() { assert(getKind() == RequirementKind::Conformance); return Types[1]; } const TypeLoc &getConstraintLoc() const { assert(getKind() == RequirementKind::Conformance); return Types[1]; } /// \brief Retrieve the location of the ':' in an explicitly-written /// conformance requirement. SourceLoc getColonLoc() const { assert(getKind() == RequirementKind::Conformance); return SeparatorLoc; } /// \brief Retrieve the first type of a same-type requirement. Type getFirstType() const { assert(getKind() == RequirementKind::SameType); return Types[0].getType(); } TypeRepr *getFirstTypeRepr() const { assert(getKind() == RequirementKind::SameType); return Types[0].getTypeRepr(); } TypeLoc &getFirstTypeLoc() { assert(getKind() == RequirementKind::SameType); return Types[0]; } const TypeLoc &getFirstTypeLoc() const { assert(getKind() == RequirementKind::SameType); return Types[0]; } /// \brief Retrieve the second type of a same-type requirement. Type getSecondType() const { assert(getKind() == RequirementKind::SameType); return Types[1].getType(); } TypeRepr *getSecondTypeRepr() const { assert(getKind() == RequirementKind::SameType); return Types[1].getTypeRepr(); } TypeLoc &getSecondTypeLoc() { assert(getKind() == RequirementKind::SameType); return Types[1]; } const TypeLoc &getSecondTypeLoc() const { assert(getKind() == RequirementKind::SameType); return Types[1]; } /// \brief Retrieve the location of the '==' in an explicitly-written /// same-type requirement. SourceLoc getEqualLoc() const { assert(getKind() == RequirementKind::SameType); return SeparatorLoc; } LLVM_ATTRIBUTE_DEPRECATED( void dump() const LLVM_ATTRIBUTE_USED, "only for use within the debugger"); void print(raw_ostream &OS) const; }; template (GenericParamList::*accessor)() const> class NestedGenericParamListIterator; /// GenericParamList - A list of generic parameters that is part of a generic /// function or type, along with extra requirements placed on those generic /// parameters and types derived from them. class GenericParamList { SourceRange Brackets; unsigned NumParams; SourceLoc WhereLoc; MutableArrayRef Requirements; ArrayRef AllArchetypes; GenericParamList *OuterParameters; /// The builder used to build archetypes for this list. ArchetypeBuilder *Builder; GenericParamList(SourceLoc LAngleLoc, ArrayRef Params, SourceLoc WhereLoc, MutableArrayRef Requirements, SourceLoc RAngleLoc); void getAsGenericSignatureElements(ASTContext &C, llvm::DenseMap &archetypeMap, SmallVectorImpl &genericParams, SmallVectorImpl &requirements) const; // Don't copy. GenericParamList(const GenericParamList &) = delete; GenericParamList &operator=(const GenericParamList &) = delete; public: /// create - Create a new generic parameter list within the given AST context. /// /// \param Context The ASTContext in which the generic parameter list will /// be allocated. /// \param LAngleLoc The location of the opening angle bracket ('<') /// \param Params The list of generic parameters, which will be copied into /// ASTContext-allocated memory. /// \param RAngleLoc The location of the closing angle bracket ('>') static GenericParamList *create(ASTContext &Context, SourceLoc LAngleLoc, ArrayRef Params, SourceLoc RAngleLoc); /// create - Create a new generic parameter list and "where" clause within /// the given AST context. /// /// \param Context The ASTContext in which the generic parameter list will /// be allocated. /// \param LAngleLoc The location of the opening angle bracket ('<') /// \param Params The list of generic parameters, which will be copied into /// ASTContext-allocated memory. /// \param WhereLoc The location of the 'where' keyword, if any. /// \param Requirements The list of requirements, which will be copied into /// ASTContext-allocated memory. /// \param RAngleLoc The location of the closing angle bracket ('>') static GenericParamList *create(const ASTContext &Context, SourceLoc LAngleLoc, ArrayRef Params, SourceLoc WhereLoc, MutableArrayRef Requirements, SourceLoc RAngleLoc); /// Create a new generic parameter list with the same parameters and /// requirements as this one, but parented to a different outer parameter /// list. GenericParamList *cloneWithOuterParameters(const ASTContext &Context, GenericParamList *Outer) { auto clone = create(Context, SourceLoc(), getParams(), SourceLoc(), getRequirements(), SourceLoc()); clone->setAllArchetypes(getAllArchetypes()); clone->setOuterParameters(Outer); return clone; } /// Create an empty generic parameter list. static GenericParamList *getEmpty(ASTContext &Context) { // TODO: Could probably unique this in the AST context. return create(Context, SourceLoc(), {}, SourceLoc(), {}, SourceLoc()); } MutableArrayRef getParams() { return { reinterpret_cast(this + 1), NumParams }; } ArrayRef getParams() const { return const_cast(this)->getParams(); } using iterator = GenericTypeParamDecl **; using const_iterator = const GenericTypeParamDecl * const *; unsigned size() const { return NumParams; } iterator begin() { return getParams().begin(); } iterator end() { return getParams().end(); } const_iterator begin() const { return getParams().begin(); } const_iterator end() const { return getParams().end(); } /// Get the total number of parameters, including those from parent generic /// parameter lists. unsigned totalSize() const { return NumParams + (OuterParameters ? OuterParameters->totalSize() : 0); } /// \brief Retrieve the location of the 'where' keyword, or an invalid /// location if 'where' was not present. SourceLoc getWhereLoc() const { return WhereLoc; } /// \brief Retrieve the set of additional requirements placed on these /// generic parameters and types derived from them. /// /// This list may contain both explicitly-written requirements as well as /// implicitly-generated requirements, and may be non-empty even if no /// 'where' keyword is present. MutableArrayRef getRequirements() { return Requirements; } /// \brief Retrieve the set of additional requirements placed on these /// generic parameters and types derived from them. /// /// This list may contain both explicitly-written requirements as well as /// implicitly-generated requirements, and may be non-empty even if no /// 'where' keyword is present. ArrayRef getRequirements() const { return Requirements; } /// \brief Override the set of requirements associated with this generic /// parameter list. /// /// \param NewRequirements The new set of requirements, which is expected /// to be a superset of the existing set of requirements (although this /// property is not checked here). It is assumed that the array reference /// refers to ASTContext-allocated memory. void overrideRequirements(MutableArrayRef NewRequirements) { Requirements = NewRequirements; } /// \brief Retrieves the list containing all archetypes described by this /// generic parameter clause. /// /// In this list of archetypes, the primary archetypes come first followed by /// any non-primary archetypes (i.e., those archetypes that encode associated /// types of another archetype). /// /// This does not include archetypes from the outer generic parameter list(s). ArrayRef getAllArchetypes() const { return AllArchetypes; } /// \brief Return the number of primary archetypes. unsigned getNumPrimaryArchetypes() const { return size(); } /// \brief Retrieves the list containing only the primary archetypes described /// by this generic parameter clause. This excludes archetypes for associated /// types of the primary archetypes. ArrayRef getPrimaryArchetypes() const { return getAllArchetypes().slice(0, getNumPrimaryArchetypes()); } /// \brief Retrieves the list containing only the associated archetypes. ArrayRef getAssociatedArchetypes() const { return getAllArchetypes().slice(getNumPrimaryArchetypes()); } /// \brief Sets all archetypes *without* copying the source array. void setAllArchetypes(ArrayRef AA) { assert(AA.size() >= size() && "allArchetypes is smaller than number of generic params?!"); AllArchetypes = AA; } using NestedArchetypeIterator = NestedGenericParamListIterator; using NestedGenericParamIterator = NestedGenericParamListIterator; /// \brief Retrieves a list containing all archetypes from this generic /// parameter clause and all outer generic parameter clauses in outer-to- /// inner order. Range getAllNestedArchetypes() const; /// \brief Retrieves a list containing all generic parameter records from /// this generic parameter clause and all outer generic parameter clauses in /// outer-to-inner order. Range getNestedGenericParams() const; /// \brief Retrieve the outer generic parameter list, which provides the /// generic parameters of the context in which this generic parameter list /// exists. /// /// Consider the following generic class: /// /// \code /// class Vector { /// constructor(range : R) { } /// } /// \endcode /// /// The generic parameter list has no outer parameters, because it is /// the outermost generic parameter list. The generic parameter list /// for the constructor has the generic parameter list as /// its outer generic parameter list. GenericParamList *getOuterParameters() const { return OuterParameters; } /// \brief Set the outer generic parameter list. See \c getOuterParameters /// for more information. void setOuterParameters(GenericParamList *Outer) { OuterParameters = Outer; } SourceLoc getLAngleLoc() const { return Brackets.Start; } SourceLoc getRAngleLoc() const { return Brackets.End; } SourceRange getSourceRange() const { return Brackets; } /// Retrieve the depth of this generic parameter list. unsigned getDepth() const { unsigned depth = 0; for (auto gp = getOuterParameters(); gp; gp = gp->getOuterParameters()) ++depth; return depth; } /// Get the generic parameter list as a GenericSignature in which the generic /// parameters have been canonicalized. /// /// \param archetypeMap This DenseMap is populated with a mapping of /// context primary archetypes to dependent generic /// types. GenericSignature *getAsCanonicalGenericSignature( llvm::DenseMap &archetypeMap, ASTContext &C) const; /// Derive a type substitution map for this generic parameter list from a /// matching substitution vector. TypeSubstitutionMap getSubstitutionMap(ArrayRef Subs) const; /// Derive the all-archetypes list for the given list of generic /// parameters. static ArrayRef deriveAllArchetypes(ArrayRef params, SmallVectorImpl &archetypes); void setBuilder(ArchetypeBuilder *builder) { Builder = builder; } ArchetypeBuilder *getBuilder() const { return Builder; } /// Collect the nested archetypes of an archetype into the given /// collection. /// /// \param known - the set of archetypes already present in `all` /// \param all - the output list of archetypes static void addNestedArchetypes(ArchetypeType *archetype, SmallPtrSetImpl &known, SmallVectorImpl &all); void print(raw_ostream &OS); void dump(); }; /// An iterator template for lazily walking a nested generic parameter list. template (GenericParamList::*accessor)() const> class NestedGenericParamListIterator { SmallVector stack; ArrayRef elements; void refreshElements() { while (elements.empty()) { stack.pop_back(); if (stack.empty()) break; elements = (stack.back()->*accessor)(); } } public: // Create a 'begin' iterator for a generic param list. NestedGenericParamListIterator(const GenericParamList *params) { // Walk up to the outermost list to create a stack of lists to walk. while (params) { stack.push_back(params); params = params->getOuterParameters(); } // If the stack is empty, be like the 'end' iterator. if (stack.empty()) return; elements = (stack.back()->*accessor)(); refreshElements(); } // Create an 'end' iterator. NestedGenericParamListIterator() {} // Iterator dereference. const T &operator*() const { return elements[0]; } const T *operator->() const { return &elements[0]; } // Iterator advancement. NestedGenericParamListIterator &operator++() { elements = elements.slice(1); refreshElements(); return *this; } NestedGenericParamListIterator operator++(int) { auto copy = *this; ++(*this); return copy; } // Ghetto comparison. Only true if end() == end(). bool operator==(const NestedGenericParamListIterator &o) const { return stack.empty() && o.stack.empty(); } bool operator!=(const NestedGenericParamListIterator &o) const { return !stack.empty() || !o.stack.empty(); } // An empty range of nested archetypes. static Range emptyRange() { return {{}, {}}; } }; using NestedArchetypeIterator = GenericParamList::NestedArchetypeIterator; using NestedGenericParamIterator = GenericParamList::NestedGenericParamIterator; inline Range GenericParamList::getAllNestedArchetypes() const { return {NestedArchetypeIterator(this), NestedArchetypeIterator()}; } inline Range GenericParamList::getNestedGenericParams() const { return {NestedGenericParamIterator(this), NestedGenericParamIterator()}; } /// Describes what kind of name is being imported. /// /// If the enumerators here are changed, make sure to update all diagnostics /// using ImportKind as a select index. enum class ImportKind : uint8_t { Module = 0, Type, Struct, Class, Enum, Protocol, Var, Func }; /// ImportDecl - This represents a single import declaration, e.g.: /// import Swift /// import typealias Swift.Int class ImportDecl : public Decl { public: typedef std::pair AccessPathElement; private: SourceLoc ImportLoc; SourceLoc KindLoc; /// The number of elements in this path. unsigned NumPathElements; /// The resolved module. Module *Mod = nullptr; /// The resolved decls if this is a decl import. ArrayRef Decls; AccessPathElement *getPathBuffer() { return reinterpret_cast(this+1); } const AccessPathElement *getPathBuffer() const { return reinterpret_cast(this+1); } ImportDecl(DeclContext *DC, SourceLoc ImportLoc, ImportKind K, SourceLoc KindLoc, ArrayRef Path); public: static ImportDecl *create(ASTContext &C, DeclContext *DC, SourceLoc ImportLoc, ImportKind Kind, SourceLoc KindLoc, ArrayRef Path, const clang::Module *Mod = nullptr); /// Returns the import kind that is most appropriate for \p VD. /// /// Note that this will never return \c Type; an imported typealias will use /// the more specific kind from its underlying type. static ImportKind getBestImportKind(const ValueDecl *VD); /// Returns the most appropriate import kind for the given list of decls. /// /// If the list is non-homogenous, or if there is more than one decl that /// cannot be overloaded, returns None. static Optional findBestImportKind(ArrayRef Decls); ArrayRef getFullAccessPath() const { return ArrayRef(getPathBuffer(), NumPathElements); } ArrayRef getModulePath() const { auto result = getFullAccessPath(); if (getImportKind() != ImportKind::Module) result = result.slice(0, result.size()-1); return result; } ArrayRef getDeclPath() const { if (getImportKind() == ImportKind::Module) return {}; return getFullAccessPath().back(); } ImportKind getImportKind() const { return static_cast(ImportDeclBits.ImportKind); } bool isExported() const { return getAttrs().hasAttribute(); } Module *getModule() const { return Mod; } void setModule(Module *M) { Mod = M; } ArrayRef getDecls() const { return Decls; } void setDecls(ArrayRef Ds) { Decls = Ds; } const clang::Module *getClangModule() const { if (ClangNode ClangN = getClangNode()) return ClangN.castAsModule(); return nullptr; } SourceLoc getStartLoc() const { return ImportLoc; } SourceLoc getLoc() const { return getFullAccessPath().front().second; } SourceRange getSourceRange() const { return SourceRange(ImportLoc, getFullAccessPath().back().second); } SourceLoc getKindLoc() const { return KindLoc; } static bool classof(const Decl *D) { return D->getKind() == DeclKind::Import; } }; /// ExtensionDecl - This represents a type extension containing methods /// associated with the type. This is not a ValueDecl and has no Type because /// there are no runtime values of the Extension's type. class ExtensionDecl final : public Decl, public DeclContext, public IterableDeclContext { public: /// A single component within the reference to the extended type. struct RefComponent { /// The name of the type being extended. Identifier Name; /// The location of the name. SourceLoc NameLoc; /// The generic parameters associated with this name. GenericParamList *GenericParams; }; private: SourceLoc ExtensionLoc; // Location of 'extension' keyword. SourceRange Braces; /// \brief The generic signature of this extension. /// /// This is the semantic representation of a generic parameters and the /// requirements placed on them. /// /// FIXME: The generic parameters here are also derivable from /// \c GenericParams. However, we likely want to make \c GenericParams /// the parsed representation, and not part of the module file. GenericSignature *GenericSig = nullptr; /// The type being extended. Type ExtendedType; MutableArrayRef Inherited; /// \brief The set of protocols to which this extension conforms. ArrayRef Protocols; /// \brief The set of protocol conformance mappings. The element order /// corresponds to the order of Protocols. LazyLoaderArray Conformances; /// \brief The next extension in the linked list of extensions. /// /// The bit indicates whether this extension has been resolved to refer to /// a known nominal type. llvm::PointerIntPair NextExtension = {nullptr, false}; /// Note that we have added a member into the iterable declaration context. void addedMember(Decl *member); friend class ExtensionIterator; friend class NominalTypeDecl; friend class MemberLookupTable; friend class IterableDeclContext; ExtensionDecl(SourceLoc extensionLoc, ArrayRef refComponents, MutableArrayRef inherited, DeclContext *parent); public: using Decl::getASTContext; /// Create a new extension declaration. static ExtensionDecl *create(ASTContext &ctx, SourceLoc extensionLoc, ArrayRef refComponents, MutableArrayRef inherited, DeclContext *parent, ClangNode clangNode = ClangNode()); SourceLoc getStartLoc() const { return ExtensionLoc; } SourceLoc getLoc() const { return ExtensionLoc; } SourceRange getSourceRange() const { return { ExtensionLoc, Braces.End }; } SourceRange getBraces() const { return Braces; } void setBraces(SourceRange braces) { Braces = braces; } /// Retrieve the reference components in the ArrayRef getRefComponents() const { return { reinterpret_cast(this + 1), ExtensionDeclBits.NumRefComponents }; } MutableArrayRef getRefComponents() { return { reinterpret_cast(this + 1), ExtensionDeclBits.NumRefComponents }; } /// Retrieve the innermost generic parameter list. GenericParamList *getGenericParams() const { return getRefComponents().back().GenericParams; } /// Retrieve the generic signature for this extension. GenericSignature *getGenericSignature() const { return GenericSig; } /// Set the generic signature of this extension. void setGenericSignature(GenericSignature *sig); /// Retrieve the type being extended. Type getExtendedType() const { return ExtendedType; } /// Set the type being extended. void setExtendedType(Type extended) { ExtendedType = extended; } /// Compute the source range that covers the extended type. SourceRange getExtendedTypeRange() const; /// \brief Retrieve the set of protocols that this type inherits (i.e, /// explicitly conforms to). MutableArrayRef getInherited() { return Inherited; } ArrayRef getInherited() const { return Inherited; } /// Whether we already validated this extension. bool validated() const { return ExtensionDeclBits.Validated; } /// Set whether we have validated this extension. void setValidated(bool validated = true) { ExtensionDeclBits.Validated = validated; } /// Whether we already type-checked the inheritance clause. bool checkedInheritanceClause() const { return ExtensionDeclBits.CheckedInheritanceClause; } /// Note that we have already type-checked the inheritance clause. void setCheckedInheritanceClause(bool checked = true) { ExtensionDeclBits.CheckedInheritanceClause = checked; } bool hasDefaultAccessibility() const { return ExtensionDeclBits.DefaultAccessLevel != 0; } Accessibility getDefaultAccessibility() const { assert(hasDefaultAccessibility() && "not computed yet"); return static_cast(ExtensionDeclBits.DefaultAccessLevel - 1); } void setDefaultAccessibility(Accessibility access) { assert(!hasDefaultAccessibility() && "default accessibility already set"); ExtensionDeclBits.DefaultAccessLevel = static_cast(access) + 1; } /// \brief Retrieve the set of protocols to which this extension conforms. ArrayRef getProtocols(bool forceDelayedMembers = true) const { return Protocols; } void setProtocols(ArrayRef protocols) { Protocols = protocols; } /// \brief Retrieve the set of protocol conformance mappings for this type. /// /// Calculated during type-checking. ArrayRef getConformances() const; void setConformances(ArrayRef c) { Conformances = c; } void setConformanceLoader(LazyMemberLoader *resolver, uint64_t contextData); DeclRange getMembers(bool forceDelayedMembers = true) const; void setMemberLoader(LazyMemberLoader *resolver, uint64_t contextData); bool hasLazyMembers() const { return IterableDeclContext::isLazy(); } // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() == DeclKind::Extension; } static bool classof(const DeclContext *C) { return C->getContextKind() == DeclContextKind::ExtensionDecl; } static bool classof(const IterableDeclContext *C) { return C->getIterableContextKind() == IterableDeclContextKind::ExtensionDecl; } using DeclContext::operator new; }; /// \brief Iterator that walks the extensions of a particular type. class ExtensionIterator { ExtensionDecl *current; public: ExtensionIterator() : current() { } explicit ExtensionIterator(ExtensionDecl *current) : current(current) { } ExtensionDecl *operator*() const { return current; } ExtensionDecl *operator->() const { return current; } ExtensionIterator &operator++() { current = current->NextExtension.getPointer(); return *this; } ExtensionIterator operator++(int) { ExtensionIterator tmp = *this; ++(*this); return tmp; } friend bool operator==(ExtensionIterator x, ExtensionIterator y) { return x.current == y.current; } friend bool operator!=(ExtensionIterator x, ExtensionIterator y) { return x.current != y.current; } }; /// \brief Range that covers a set of extensions. class ExtensionRange { ExtensionIterator first; ExtensionIterator last; public: ExtensionRange(ExtensionIterator first, ExtensionIterator last) : first(first), last(last) { } typedef ExtensionIterator iterator; iterator begin() const { return first; } iterator end() const { return last; } }; /// \brief This decl contains a pattern and optional initializer for a set /// of one or more VarDecls declared together. /// /// For example, in /// \code /// var (a, b) = foo() /// \endcode /// this contains the pattern "(a, b)" and the intializer "foo()". The same /// applies to simpler declarations like "var a = foo()". class PatternBindingDecl : public Decl { SourceLoc StaticLoc; ///< Location of the 'static/class' keyword, if present. SourceLoc VarLoc; ///< Location of the 'var' keyword. Pattern *Pat; ///< The pattern this decl binds. /// The initializer, and whether it's been type-checked already. llvm::PointerIntPair InitAndChecked; friend class Decl; public: PatternBindingDecl(SourceLoc StaticLoc, StaticSpellingKind StaticSpelling, SourceLoc VarLoc, Pattern *Pat, Expr *E, bool isConditional, DeclContext *Parent) : Decl(DeclKind::PatternBinding, Parent), StaticLoc(StaticLoc), VarLoc(VarLoc), Pat(Pat), InitAndChecked(E, false) { PatternBindingDeclBits.IsStatic = StaticLoc.isValid(); PatternBindingDeclBits.StaticSpelling = static_cast(StaticSpelling); PatternBindingDeclBits.Conditional = isConditional; } SourceLoc getStartLoc() const { return StaticLoc.isValid() ? StaticLoc : VarLoc; } SourceLoc getLoc() const { return VarLoc; } SourceRange getSourceRange() const; Pattern *getPattern() { return Pat; } const Pattern *getPattern() const { return Pat; } void setPattern(Pattern *P) { Pat = P; } bool hasInit() const { return InitAndChecked.getPointer(); } Expr *getInit() const { return InitAndChecked.getPointer(); } bool wasInitChecked() const { return InitAndChecked.getInt(); } void setInit(Expr *expr, bool checked) { InitAndChecked.setPointerAndInt(expr, checked); } /// Does this binding declare something that requires storage? bool hasStorage() const; /// Does this binding appear in an 'if' or 'while' condition? bool isConditional() const { return PatternBindingDeclBits.Conditional; } /// When the pattern binding contains only a single variable with no /// destructuring, retrieve that variable. VarDecl *getSingleVar() const; bool isStatic() const { return PatternBindingDeclBits.IsStatic; } void setStatic(bool s) { PatternBindingDeclBits.IsStatic = s; } SourceLoc getStaticLoc() const { return StaticLoc; } /// \returns the way 'static'/'class' was spelled in the source. StaticSpellingKind getStaticSpelling() const { return static_cast( PatternBindingDeclBits.StaticSpelling); } /// \returns the way 'static'/'class' should be spelled for this declaration. StaticSpellingKind getCorrectStaticSpelling() const; static bool classof(const Decl *D) { return D->getKind() == DeclKind::PatternBinding; } }; /// TopLevelCodeDecl - This decl is used as a container for top-level /// expressions and statements in the main module. It is always a direct /// child of a SourceFile. The primary reason for building these is to give /// top-level statements a DeclContext which is distinct from the file itself. /// This, among other things, makes it easier to distinguish between local /// top-level variables (which are not live past the end of the statement) and /// global variables. class TopLevelCodeDecl : public Decl, public DeclContext { BraceStmt *Body; public: TopLevelCodeDecl(DeclContext *Parent, BraceStmt *Body = nullptr) : Decl(DeclKind::TopLevelCode, Parent), DeclContext(DeclContextKind::TopLevelCodeDecl, Parent), Body(Body) {} BraceStmt *getBody() const { return Body; } void setBody(BraceStmt *b) { Body = b; } SourceLoc getStartLoc() const; SourceLoc getLoc() const { return getStartLoc(); } SourceRange getSourceRange() const; static bool classof(const Decl *D) { return D->getKind() == DeclKind::TopLevelCode; } static bool classof(const DeclContext *C) { return C->getContextKind() == DeclContextKind::TopLevelCodeDecl; } using DeclContext::operator new; }; /// This represents one part of a #if block. If the condition field is /// non-null, then this represents a #if or a #elseif, otherwise it represents /// an #else block. struct IfConfigDeclClause { /// The location of the #if, #elseif, or #else keyword. SourceLoc Loc; /// The condition guarding this #if or #elseif block. If this is null, this /// is a #else clause. Expr *Cond; ArrayRef Members; /// True if this is the active clause of the #if block. Since this is /// evaluated at parse time, this is always known. bool isActive; IfConfigDeclClause(SourceLoc Loc, Expr *Cond, ArrayRef Members, bool isActive) : Loc(Loc), Cond(Cond), Members(Members), isActive(isActive) { } }; /// IfConfigDecl - This class represents the declaration-side representation of /// #if/#else/#endif blocks. Active and inactive block members are stored /// separately, with the intention being that active members will be handed /// back to the enclosing declaration. class IfConfigDecl : public Decl { /// An array of clauses controlling each of the #if/#elseif/#else conditions. /// The array is ASTContext allocated. ArrayRef Clauses; SourceLoc EndLoc; bool HadMissingEnd; public: IfConfigDecl(DeclContext *Parent, ArrayRef Clauses, SourceLoc EndLoc, bool HadMissingEnd) : Decl(DeclKind::IfConfig, Parent), Clauses(Clauses), EndLoc(EndLoc), HadMissingEnd(HadMissingEnd) { } ArrayRef getClauses() const { return Clauses; } /// Return the active clause, or null if there is no active one. const IfConfigDeclClause *getActiveClause() const { for (auto &Clause : Clauses) if (Clause.isActive) return &Clause; return nullptr; } const ArrayRef getActiveMembers() const { if (auto *Clause = getActiveClause()) return Clause->Members; return {}; } SourceLoc getEndLoc() const { return EndLoc; } SourceLoc getLoc() const { return Clauses[0].Loc; } bool hadMissingEnd() const { return HadMissingEnd; } SourceRange getSourceRange() const; static bool classof(const Decl *D) { return D->getKind() == DeclKind::IfConfig; } }; /// ValueDecl - All named decls that are values in the language. These can /// have a type, etc. class ValueDecl : public Decl { DeclName Name; SourceLoc NameLoc; llvm::PointerIntPair> TypeAndAccess; protected: ValueDecl(DeclKind K, DeclContext *DC, DeclName name, SourceLoc NameLoc) : Decl(K, DC), Name(name), NameLoc(NameLoc) { ValueDeclBits.ConformsToProtocolRequrement = false; ValueDeclBits.AlreadyInLookupTable = false; ValueDeclBits.CheckedRedeclaration = false; } /// The interface type, mutable because some subclasses compute this lazily. mutable Type InterfaceTy; public: /// \brief 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 isDefinition() const; /// Determine whether we have already checked whether this /// declaration is a redeclaration. bool alreadyCheckedRedeclaration() const { return ValueDeclBits.CheckedRedeclaration; } /// Set whether we have already checked this declaration as a /// redeclaration. void setCheckedRedeclaration(bool checked) { ValueDeclBits.CheckedRedeclaration = checked; } bool hasName() const { return bool(Name); } /// TODO: Rename to getSimpleName? Identifier getName() const { return Name.getBaseName(); } bool isOperator() const { return Name.isOperator(); } /// Returns the string for the base name, or "_" if this is unnamed. StringRef getNameStr() const { return hasName() ? getName().str() : "_"; } /// Retrieve the full name of the declaration. /// TODO: Rename to getName? DeclName getFullName() const { return Name; } /// Retrieve the base name of the declaration, ignoring any argument /// names. DeclName getBaseName() const { return Name.getBaseName(); } SourceLoc getNameLoc() const { return NameLoc; } SourceLoc getLoc() const { return NameLoc; } bool hasType() const { return !TypeAndAccess.getPointer().isNull(); } Type getType() const { assert(hasType() && "declaration has no type set yet"); return TypeAndAccess.getPointer(); } /// Set the type of this declaration for the first time. void setType(Type T); /// Overwrite the type of this declaration. void overwriteType(Type T); bool hasAccessibility() const { return TypeAndAccess.getInt().hasValue(); } Accessibility getAccessibility() const { assert(hasAccessibility() && "accessibility not computed yet"); return TypeAndAccess.getInt().getValue(); } void setAccessibility(Accessibility access) { assert(!hasAccessibility() && "accessibility already set"); overwriteAccessibility(access); } /// Overwrite the accessibility of this declaration. // This is needed in the LLDB REPL. void overwriteAccessibility(Accessibility access) { TypeAndAccess.setInt(access); } /// Returns true if this declaration is accessible from the given context. /// /// A private declaration is accessible from any DeclContext within the same /// source file. /// /// An internal declaration is accessible from any DeclContext within the same /// module. /// /// A public declaration is accessible everywhere. /// /// If \p DC is null, returns true only if this declaration is public. bool isAccessibleFrom(const DeclContext *DC) const; /// Get the innermost declaration context that can provide generic /// parameters used within this declaration. DeclContext *getPotentialGenericDeclContext(); /// Get the innermost declaration context that can provide generic /// parameters used within this declaration. const DeclContext *getPotentialGenericDeclContext() const { return const_cast(this)->getPotentialGenericDeclContext(); } /// Retrieve the "interface" type of this value, which is the type used when /// the declaration is viewed from the outside. For a generic function, /// this will have generic function type using generic parameters rather than /// archetypes, while a generic nominal type's interface type will be the /// generic type specialized with its generic parameters. /// /// FIXME: Eventually, this will simply become the type of the value, and /// we will substitute in the appropriate archetypes within a particular /// context. Type getInterfaceType() const; bool hasInterfaceType() const { return !!InterfaceTy; } /// Set the interface type for the given value. void setInterfaceType(Type type); /// isSettable - Determine whether references to this decl may appear /// on the left-hand side of an assignment or as the operand of a /// `&` or 'inout' operator. bool isSettable(DeclContext *UseDC) const; /// isInstanceMember - Determine whether this value is an instance member /// of an enum or protocol. bool isInstanceMember() const; /// needsCapture - Check whether referring to this decl from a nested /// function requires capturing it. bool needsCapture() const; /// Retrieve the context discriminator for this local value, which /// is the index of this declaration in the sequence of /// discriminated declarations with the same name in the current /// context. Only local functions and variables with getters and /// setters have discriminators. unsigned getLocalDiscriminator() const; void setLocalDiscriminator(unsigned index); /// Retrieve the declaration that this declaration overrides, if any. ValueDecl *getOverriddenDecl() const; /// Compute the overload signature for this declaration. OverloadSignature getOverloadSignature() const; /// Returns true if the decl requires Objective-C interop. /// /// This can be true even if there is no 'objc' attribute on the declaration. /// In that case it was inferred by the type checker. bool isObjC() const { return getAttrs().hasAttribute(); } void setIsObjC(bool Value); /// Is this declaration marked with 'final'? bool isFinal() const { return getAttrs().hasAttribute(); } /// Is this declaration marked with 'dynamic'? bool isDynamic() const { return getAttrs().hasAttribute(); } /// Returns true if this decl can be found by id-style dynamic lookup. bool canBeAccessedByDynamicLookup() const; /// Returns true if this decl conforms to a protocol requirement. bool conformsToProtocolRequirement() const { return ValueDeclBits.ConformsToProtocolRequrement; } void setConformsToProtocolRequirement(bool Value = true) { ValueDeclBits.ConformsToProtocolRequrement = Value; } /// Returns the protocol requirements that this decl conforms to. ArrayRef getConformances(); /// Determines the kind of access that should be performed by a /// DeclRefExpr or MemberRefExpr use of this value in the specified /// context. AccessSemantics getAccessSemanticsFromContext(const DeclContext *DC) const; /// Dump a reference to the given declaration. void dumpRef(raw_ostream &os) const; /// Dump a reference to the given declaration. void dumpRef() const; static bool classof(const Decl *D) { return D->getKind() >= DeclKind::First_ValueDecl && D->getKind() <= DeclKind::Last_ValueDecl; } }; /// This is a common base class for declarations which declare a type. class TypeDecl : public ValueDecl { MutableArrayRef Inherited; protected: TypeDecl(DeclKind K, DeclContext *DC, Identifier name, SourceLoc NameLoc, MutableArrayRef inherited) : ValueDecl(K, DC, name, NameLoc), Inherited(inherited) { TypeDeclBits.CheckedInheritanceClause = false; TypeDeclBits.ProtocolsSet = false; } /// \brief The set of protocols to which this type conforms. ArrayRef Protocols; public: Type getDeclaredType() const; Type getDeclaredInterfaceType() const; /// \brief Retrieve the set of protocols that this type inherits (i.e, /// explicitly conforms to). MutableArrayRef getInherited() { return Inherited; } ArrayRef getInherited() const { return Inherited; } /// Whether we already type-checked the inheritance clause. bool checkedInheritanceClause() const { return TypeDeclBits.CheckedInheritanceClause; } /// Note that we have already type-checked the inheritance clause. void setCheckedInheritanceClause(bool checked = true) { TypeDeclBits.CheckedInheritanceClause = checked; } /// \brief Retrieve the set of protocols to which this type conforms. /// /// FIXME: Include protocol conformance from extensions? This will require /// semantic analysis to compute. ArrayRef getProtocols(bool forceDelayedMembers = true) const; /// \brief For declarations that are initially composed of a mix of delayed /// and non-delayed protocols, allow the setting of a temporary list of /// non-delayed protocols that will be copied over to the "official" protocol /// list when the delayed protocol declarations are forced. void setInitialUndelayedProtocols(ArrayRef protocols) { Protocols = protocols; } void setProtocols(ArrayRef protocols) { assert((!TypeDeclBits.ProtocolsSet || protocols.empty()) && "protocols already set"); TypeDeclBits.ProtocolsSet = true; Protocols = protocols; } bool isProtocolsValid() const { return TypeDeclBits.ProtocolsSet; } void setInherited(MutableArrayRef i) { Inherited = i; } static bool classof(const Decl *D) { return D->getKind() >= DeclKind::First_TypeDecl && D->getKind() <= DeclKind::Last_TypeDecl; } }; /// TypeAliasDecl - This is a declaration of a typealias, for example: /// /// typealias foo = int /// /// TypeAliasDecl's always have 'MetatypeType' type. /// class TypeAliasDecl : public TypeDecl { /// The type that represents this (sugared) name alias. mutable NameAliasType *AliasTy; SourceLoc TypeAliasLoc; // The location of the 'typalias' keyword TypeLoc UnderlyingTy; public: TypeAliasDecl(SourceLoc TypeAliasLoc, Identifier Name, SourceLoc NameLoc, TypeLoc UnderlyingTy, DeclContext *DC); SourceLoc getStartLoc() const { return TypeAliasLoc; } SourceRange getSourceRange() const; /// getUnderlyingType - Returns the underlying type, which is /// assumed to have been set. Type getUnderlyingType() const { assert(!UnderlyingTy.getType().isNull() && "getting invalid underlying type"); return UnderlyingTy.getType(); } /// \brief Determine whether this type alias has an underlying type. bool hasUnderlyingType() const { return !UnderlyingTy.getType().isNull(); } TypeLoc &getUnderlyingTypeLoc() { return UnderlyingTy; } const TypeLoc &getUnderlyingTypeLoc() const { return UnderlyingTy; } /// getAliasType - Return the sugared version of this decl as a Type. NameAliasType *getAliasType() const { return AliasTy; } static bool classof(const Decl *D) { return D->getKind() == DeclKind::TypeAlias; } }; /// Abstract class describing generic type parameters and associated types, /// whose common purpose is to anchor the abstract type parameter and specify /// requirements for any corresponding type argument. class AbstractTypeParamDecl : public TypeDecl { /// The superclass of the generic parameter. Type SuperclassTy; /// The archetype describing this abstract type parameter within its scope. ArchetypeType *Archetype; protected: AbstractTypeParamDecl(DeclKind kind, DeclContext *dc, Identifier name, SourceLoc NameLoc) : TypeDecl(kind, dc, name, NameLoc, { }), Archetype(nullptr) { } public: /// Return the superclass of the generic parameter. Type getSuperclass() const { return SuperclassTy; } /// Set the superclass of the generic parameter. void setSuperclass(Type superclassTy) { SuperclassTy = superclassTy; } /// Retrieve the archetype that describes this abstract type parameter /// within its scope. ArchetypeType *getArchetype() const { return Archetype; } /// Set the archetype used to describe this abstract type parameter within /// its scope. void setArchetype(ArchetypeType *archetype) { Archetype = archetype; } static bool classof(const Decl *D) { return D->getKind() >= DeclKind::First_AbstractTypeParamDecl && D->getKind() <= DeclKind::Last_AbstractTypeParamDecl; } }; /// A declaration of a generic type parameter. /// /// A generic type parameter introduces a new, named type parameter along /// with some set of requirements on any type argument used to realize this /// type parameter. The requirements involve conformances to specific /// protocols or inheritance from a specific class type. /// /// In the following example, 'T' is a generic type parameter with the /// requirement that the type argument conform to the 'Comparable' protocol. /// /// \code /// func min(x : T, y : T) -> T { ... } /// \endcode class GenericTypeParamDecl : public AbstractTypeParamDecl { unsigned Depth : 16; unsigned Index : 16; public: /// Construct a new generic type parameter. /// /// \param dc The DeclContext in which the generic type parameter's owner /// occurs. This should later be overwritten with the actual declaration /// context that owns the type parameter. /// /// \param name The name of the generic parameter. /// \param nameLoc The location of the name. GenericTypeParamDecl(DeclContext *dc, Identifier name, SourceLoc nameLoc, unsigned depth, unsigned index); /// The depth of this generic type parameter, i.e., the number of outer /// levels of generic parameter lists that enclose this type parameter. /// /// \code /// struct X { /// func f() { } /// } /// \endcode /// /// Here 'T' has depth 0 and 'U' has depth 1. Both have index 0. unsigned getDepth() const { return Depth; } /// Set the depth of this generic type parameter. /// /// \sa getDepth void setDepth(unsigned depth) { Depth = depth; } /// The index of this generic type parameter within its generic parameter /// list. /// /// \code /// struct X { /// func f() { } /// } /// \endcode /// /// Here 'T' and 'U' have indexes 0 and 1, respectively. 'V' has index 0. unsigned getIndex() const { return Index; } SourceLoc getStartLoc() const { return getNameLoc(); } SourceRange getSourceRange() const; static bool classof(const Decl *D) { return D->getKind() == DeclKind::GenericTypeParam; } }; /// A declaration of an associated type. /// /// An associated type introduces a new, named type in a protocol that /// can vary from one conforming type to the next. Associated types have a /// set of requirements to which the type that replaces it much realize, /// describes via conformance to specific protocols, or inheritance from a /// specific class type. /// /// In the following example, 'Element' is an associated type with no /// requirements. /// /// \code /// protocol Enumerator { /// typealias Element /// func getNext() -> Element? /// } /// \endcode /// /// Every protocol has an implicitly-created associated type 'Self' that /// describes a type that conforms to the protocol. class AssociatedTypeDecl : public AbstractTypeParamDecl { /// The location of the initial keyword. SourceLoc KeywordLoc; /// The default definition. TypeLoc DefaultDefinition; LazyMemberLoader *Resolver = nullptr; uint64_t ResolverContextData; public: AssociatedTypeDecl(DeclContext *dc, SourceLoc keywordLoc, Identifier name, SourceLoc nameLoc, TypeLoc defaultDefinition); AssociatedTypeDecl(DeclContext *dc, SourceLoc keywordLoc, Identifier name, SourceLoc nameLoc, LazyMemberLoader *definitionResolver, uint64_t resolverData); /// Get the protocol in which this associated type is declared. ProtocolDecl *getProtocol() const { return cast(getDeclContext()); } /// Retrieve the default definition type. Type getDefaultDefinitionType() const { return getDefaultDefinitionLoc().getType(); } TypeLoc &getDefaultDefinitionLoc(); const TypeLoc &getDefaultDefinitionLoc() const { return const_cast(this)->getDefaultDefinitionLoc(); } SourceLoc getStartLoc() const { return KeywordLoc; } SourceRange getSourceRange() const; static bool classof(const Decl *D) { return D->getKind() == DeclKind::AssociatedType; } }; class MemberLookupTable; /// Iterator that walks the generic parameter types declared in a generic /// signature and their dependent members. class GenericSignatureWitnessIterator { ArrayRef p; public: GenericSignatureWitnessIterator() = default; GenericSignatureWitnessIterator(ArrayRef p) : p(p) { assert(p.empty() || p.front().getKind() == RequirementKind::WitnessMarker); } GenericSignatureWitnessIterator &operator++() { do { p = p.slice(1); } while (!p.empty() && p.front().getKind() != RequirementKind::WitnessMarker); return *this; } GenericSignatureWitnessIterator operator++(int) { auto copy = *this; ++(*this); return copy; } Type operator*() const { assert(p.front().getKind() == RequirementKind::WitnessMarker); return p.front().getFirstType(); } Type operator->() const { assert(p.front().getKind() == RequirementKind::WitnessMarker); return p.front().getFirstType(); } bool operator==(const GenericSignatureWitnessIterator &o) { return p.data() == o.p.data() && p.size() == o.p.size(); } bool operator!=(const GenericSignatureWitnessIterator &o) { return p.data() != o.p.data() || p.size() != o.p.size(); } static GenericSignatureWitnessIterator emptyRange() { return GenericSignatureWitnessIterator(); } // Allow the witness iterator to be used with a ranged for. GenericSignatureWitnessIterator begin() const { return *this; } GenericSignatureWitnessIterator end() const { return GenericSignatureWitnessIterator({p.end(), p.end()}); } }; class GenericSignature; /// Describes the generic signature of a particular declaration, including /// both the generic type parameters and the requirements placed on those /// generic parameters. class GenericSignature : public llvm::FoldingSetNode { unsigned NumGenericParams; unsigned NumRequirements; // Make vanilla new/delete illegal. void *operator new(size_t Bytes) = delete; void operator delete(void *Data) = delete; /// Retrieve a mutable version of the generic parameters. MutableArrayRef getGenericParamsBuffer() { return { reinterpret_cast(this + 1), NumGenericParams }; } /// Retrieve a mutable verison of the requirements. MutableArrayRef getRequirementsBuffer() { void *genericParams = getGenericParamsBuffer().end(); return { reinterpret_cast(genericParams), NumRequirements }; } GenericSignature(ArrayRef params, ArrayRef requirements); llvm::PointerUnion CanonicalSignatureOrASTContext; static ASTContext &getASTContext(ArrayRef params, ArrayRef requirements); public: /// Create a new generic signature with the given type parameters and /// requirements. static GenericSignature *get(ArrayRef params, ArrayRef requirements); /// Create a new generic signature with the given type parameters and /// requirements, first canonicalizing the types. static CanGenericSignature getCanonical(ArrayRef params, ArrayRef requirements); /// Retrieve the generic parameters. ArrayRef getGenericParams() const { return { reinterpret_cast(this + 1), NumGenericParams }; } /// Retrieve the innermost generic parameters. /// /// Given a generic signature for a nested generic type, produce an /// array of the generic parameters for the innermost generic type. ArrayRef getInnermostGenericParams() const; /// Retrieve the requirements. ArrayRef getRequirements() const { const void *genericParams = getGenericParams().end(); return { reinterpret_cast(genericParams), NumRequirements }; } // Only allow allocation by doing a placement new. void *operator new(size_t Bytes, void *Mem) { assert(Mem); return Mem; } /// Build a substitution map from a vector of Substitutions that correspond to /// the generic parameters in this generic signature. The order of primary /// archetypes in the substitution vector must match the order of generic /// parameters in getGenericParams(). TypeSubstitutionMap getSubstitutionMap(ArrayRef args) const; /// Return a range that iterates through first all of the generic parameters /// of the signature, followed by all of their recursive member types exposed /// through protocol requirements. /// /// The member types are presented in the /// same order as GenericParamList::getAllArchetypes would present for an /// equivalent GenericParamList. GenericSignatureWitnessIterator getAllDependentTypes() const { return GenericSignatureWitnessIterator(getRequirements()); } bool isCanonical() const { return CanonicalSignatureOrASTContext.is(); } ASTContext &getASTContext() const; CanGenericSignature getCanonicalSignature(); /// Uniquing for the ASTContext. void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, getGenericParams(), getRequirements()); } static void Profile(llvm::FoldingSetNodeID &ID, ArrayRef genericParams, ArrayRef requirements); void print(raw_ostream &OS) const; void dump() const; }; inline CanGenericSignature::CanGenericSignature(GenericSignature *Signature) : Signature(Signature) { assert(!Signature || Signature->isCanonical()); } inline ArrayRef> CanGenericSignature::getGenericParams() const{ ArrayRef params = Signature->getGenericParams(); auto base = reinterpret_cast*>( params.data()); return {base, params.size()}; } /// Kinds of optional types. enum OptionalTypeKind : unsigned { /// The type is not an optional type. OTK_None = 0, /// The type is Optional. OTK_Optional, /// The type is ImplicitlyUnwrappedOptional. OTK_ImplicitlyUnwrappedOptional }; enum { NumOptionalTypeKinds = 2 }; // Kinds of pointer types. enum PointerTypeKind : unsigned { PTK_UnsafeMutablePointer, PTK_UnsafePointer, PTK_AutoreleasingUnsafeMutablePointer, }; /// An implicitly created member decl, used when importing a Clang enum type. /// These are not added to their enclosing type unless forced. typedef std::function &)> DelayedDecl; /// An implicitly created protocol decl, used when importing a Clang enum type. /// These are not added to their enclosing type unless forced. typedef std::function DelayedProtocolDecl; /// NominalTypeDecl - a declaration of a nominal type, like a struct. This /// decl is always a DeclContext. class NominalTypeDecl : public TypeDecl, public DeclContext, public IterableDeclContext { SourceRange Braces; /// \brief The sets of implicit members and protocols added to imported enum /// types. These members and protocols are added to the NominalDecl only if /// the nominal type is directly or indirectly referenced. /// /// FIXME: These should be side-table-allocated. ArrayRef DelayedMembers; ArrayRef DelayedProtocols; GenericParamList *GenericParams; /// Global declarations that were synthesized on this type's behalf, such as /// default operator definitions derived for protocol conformances. ArrayRef DerivedGlobalDecls; /// \brief The set of protocol conformance mappings. The element order /// corresponds to the order of Protocols returned by getProtocols(). // FIXME: We don't really need this correspondence any more. LazyLoaderArray Conformances; /// \brief The generic signature of this type. /// /// This is the semantic representation of a generic parameters and the /// requirements placed on them. /// /// FIXME: The generic parameters here are also derivable from /// \c GenericParams. However, we likely want to make \c GenericParams /// the parsed representation, and not part of the module file. GenericSignature *GenericSig = nullptr; /// \brief The first extension of this type. ExtensionDecl *FirstExtension = nullptr; /// \brief The last extension of this type, used solely for efficient /// insertion of new extensions. ExtensionDecl *LastExtension = nullptr; /// \brief The generation at which we last loaded extensions. unsigned ExtensionGeneration: 31; /// \brief Whether or not the generic signature of the type declaration is /// currently being validated. unsigned ValidatingGenericSignature: 1; /// \brief A lookup table containing all of the members of this type and /// its extensions. /// /// The table itself is lazily constructed and updated when /// lookupDirect() is called. The bit indicates whether the lookup /// table has already added members by walking the declarations in /// scope. llvm::PointerIntPair LookupTable; /// Prepare the lookup table to make it ready for lookups. void prepareLookupTable(); /// Note that we have added a member into the iterable declaration context, /// so that it can also be added to the lookup table (if needed). void addedMember(Decl *member); friend class MemberLookupTable; friend class ExtensionDecl; friend class IterableDeclContext; protected: Type DeclaredTy; Type DeclaredTyInContext; void setDeclaredType(Type declaredTy) { assert(DeclaredTy.isNull() && "Already set declared type"); DeclaredTy = declaredTy; } NominalTypeDecl(DeclKind K, DeclContext *DC, Identifier name, SourceLoc NameLoc, MutableArrayRef inherited, GenericParamList *GenericParams) : TypeDecl(K, DC, name, NameLoc, inherited), DeclContext(DeclContextKind::NominalTypeDecl, DC), IterableDeclContext(IterableDeclContextKind::NominalTypeDecl), GenericParams(nullptr), DeclaredTy(nullptr) { setGenericParams(GenericParams); NominalTypeDeclBits.HasDelayedMembers = false; NominalTypeDeclBits.AddedImplicitInitializers = false; ExtensionGeneration = 0; ValidatingGenericSignature = false; } friend class ProtocolType; public: using TypeDecl::getASTContext; DeclRange getMembers(bool forceDelayedMembers = true) const; SourceRange getBraces() const { return Braces; } void setBraces(SourceRange braces) { Braces = braces; } void setMemberLoader(LazyMemberLoader *resolver, uint64_t contextData); bool hasLazyMembers() const { return IterableDeclContext::isLazy(); } void setIsValidatingGenericSignature(bool ivgs = true) { ValidatingGenericSignature = ivgs; } bool IsValidatingGenericSignature() { return ValidatingGenericSignature; } /// \brief Returns true if this this decl contains delayed value or protocol /// declarations. bool hasDelayedMembers() const { return NominalTypeDeclBits.HasDelayedMembers; } /// \brief Mark this declaration as having delayed members or not. void setHasDelayedMembers(bool hasDelayedMembers = true) { NominalTypeDeclBits.HasDelayedMembers = hasDelayedMembers; } /// Determine whether we have already attempted to add any /// implicitly-defined initializers to this declaration. bool addedImplicitInitializers() const { return NominalTypeDeclBits.AddedImplicitInitializers; } /// Note that we have attempted to void setAddedImplicitInitializers() { NominalTypeDeclBits.AddedImplicitInitializers = true; } GenericParamList *getGenericParams() const { return GenericParams; } /// Provide the set of parameters to a generic type, or null if /// this function is not generic. void setGenericParams(GenericParamList *params); /// Set the generic signature of this type. void setGenericSignature(GenericSignature *sig); /// Retrieve the generic parameter types. ArrayRef getGenericParamTypes() const { if (!GenericSig) return { }; return GenericSig->getGenericParams(); } /// Retrieve the generic requirements. ArrayRef getGenericRequirements() const { if (!GenericSig) return { }; return GenericSig->getRequirements(); } /// Retrieve the generic signature. GenericSignature *getGenericSignature() const { return GenericSig; } /// getDeclaredType - Retrieve the type declared by this entity. Type getDeclaredType() const { return DeclaredTy; } /// Compute the type (and declared type) of this nominal type. void computeType(); Type getDeclaredTypeInContext() const; /// Get the "interface" type of the given nominal type, which is the /// type used to refer to the nominal type externally. /// /// For a generic type, or a member thereof, this is the a specialization /// of the type using its own generic parameters. Type computeInterfaceType() const; /// \brief Add a new extension to this nominal type. void addExtension(ExtensionDecl *extension); /// \brief Retrieve the set of extensions of this type. ExtensionRange getExtensions(); /// Make a member of this nominal type, or one of its extensions, /// immediately visible in the lookup table. /// /// A member of a nominal type or extension thereof will become /// visible to name lookup as soon as it is added. However, if the /// addition of a member is delayed---for example, because it's /// being introduced in response to name lookup---this method can be /// called to make it immediately visible. void makeMemberVisible(ValueDecl *member); /// Find all of the declarations with the given name within this nominal type /// and its extensions. /// /// This routine does not look into superclasses, nor does it consider /// protocols to which the nominal type conforms. Furthermore, the resulting /// set of declarations has not been filtered for visibility, nor have /// overridden declarations been removed. ArrayRef lookupDirect(DeclName name); /// Collect the set of protocols to which this type should implicitly /// conform, such as AnyObject (for classes). void getImplicitProtocols(SmallVectorImpl &protocols); /// \brief True if the type can implicitly derive a conformance for the given /// protocol. /// /// If true, explicit conformance checking will synthesize implicit /// declarations for requirements of the protocol that are not satisfied by /// the type's explicit members. bool derivesProtocolConformance(ProtocolDecl *protocol) const; /// \brief Retrieve the set of protocol conformance mappings for this type. /// /// Calculated during type-checking. ArrayRef getConformances() const; void setConformances(ArrayRef c) { Conformances = c; } void setConformanceLoader(LazyMemberLoader *resolver, uint64_t contextData); using TypeDecl::getDeclaredInterfaceType; /// classifyAsOptionalType - Decide whether this declaration is one /// of the library-intrinsic Optional or ImplicitlyUnwrappedOptional types. OptionalTypeKind classifyAsOptionalType() const; private: /// Predicate used to filter StoredPropertyRange. struct ToStoredProperty { Optional operator()(Decl *decl) const; }; /// Force delayed implicit protocol declarations to be added to the type /// declaration. void forceDelayedProtocolDecls(); /// Force delayed implicit member declarations to be added to the type /// declaration. void forceDelayedMemberDecls(); public: /// A range for iterating the stored member variables of a structure. using StoredPropertyRange = OptionalTransformRange; /// Return a collection of the stored member variables of this type. StoredPropertyRange getStoredProperties() const { return StoredPropertyRange(getMembers(), ToStoredProperty()); } ArrayRef getDerivedGlobalDecls() const { return DerivedGlobalDecls; } void setDerivedGlobalDecls(MutableArrayRef decls) { DerivedGlobalDecls = decls; } bool hasDelayedMemberDecls() { return DelayedMembers.size() != 0; } void setDelayedMemberDecls(ArrayRef delayedMembers) { DelayedMembers = delayedMembers; setHasDelayedMembers(); } bool hasDelayedProtocolDecls() { return DelayedProtocols.size() != 0; } void setDelayedProtocolDecls(ArrayRef delayedProtocols) { DelayedProtocols = delayedProtocols; setHasDelayedMembers(); } /// Force delayed implicit member and protocol declarations to be added to the /// type declaration. void forceDelayed() { forceDelayedProtocolDecls(); forceDelayedMemberDecls(); } /// Override of getProtocols that forces any delayed protocol members to be /// resolved before returning the protocol array. ArrayRef getProtocols(bool forceDelayedMembers = true) const; // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() >= DeclKind::First_NominalTypeDecl && D->getKind() <= DeclKind::Last_NominalTypeDecl; } static bool classof(const DeclContext *C) { return C->getContextKind() == DeclContextKind::NominalTypeDecl; } static bool classof(const IterableDeclContext *C) { return C->getIterableContextKind() == IterableDeclContextKind::NominalTypeDecl; } static bool classof(const NominalTypeDecl *D) { return true; } static bool classof(const ExtensionDecl *D) { return false; } using DeclContext::operator new; }; /// \brief This is the declaration of an enum. /// /// For example: /// /// \code /// enum Bool { /// case false /// case true /// } /// /// enum Optional { /// case None /// case Just(T) /// } /// \endcode /// /// The type of the decl itself is a MetatypeType; use getDeclaredType() /// to get the declared type ("Bool" or "Optional" in the above example). class EnumDecl : public NominalTypeDecl { SourceLoc EnumLoc; Type RawType; public: EnumDecl(SourceLoc EnumLoc, Identifier Name, SourceLoc NameLoc, MutableArrayRef Inherited, GenericParamList *GenericParams, DeclContext *DC); SourceLoc getStartLoc() const { return EnumLoc; } SourceRange getSourceRange() const { return SourceRange(EnumLoc, getBraces().End); } EnumElementDecl *getElement(Identifier Name) const; public: /// A range for iterating the elements of an enum. using ElementRange = DowncastFilterRange; /// Return a range that iterates over all the elements of an enum. ElementRange getAllElements() const { return ElementRange(getMembers()); } /// Insert all of the 'case' element declarations into a DenseSet. void getAllElements(llvm::DenseSet &elements) const { for (auto elt : getAllElements()) elements.insert(elt); } /// Retrieve the status of circularity checking for class inheritance. CircularityCheck getCircularityCheck() const { return static_cast(EnumDeclBits.Circularity); } /// Record the current stage of circularity checking. void setCircularityCheck(CircularityCheck circularity) { EnumDeclBits.Circularity = static_cast(circularity); } // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() == DeclKind::Enum; } static bool classof(const NominalTypeDecl *D) { return D->getKind() == DeclKind::Enum; } static bool classof(const DeclContext *C) { return isa(C) && classof(cast(C)); } static bool classof(const IterableDeclContext *C) { return isa(C) && classof(cast(C)); } /// Determine whether this enum declares a raw type in its inheritance clause. bool hasRawType() const { return (bool)RawType; } /// Retrieve the declared raw type of the enum from its inheritance clause, /// or null if it has none. Type getRawType() const { return RawType; } /// Set the raw type of the enum from its inheritance clause. void setRawType(Type rawType) { RawType = rawType; } /// True if the enum is a "simple" enum, and none of its cases have associated /// payloads. bool isSimpleEnum() const; }; /// StructDecl - This is the declaration of a struct, for example: /// /// struct Complex { var R : Double, I : Double } /// /// The type of the decl itself is a MetatypeType; use getDeclaredType() /// to get the declared type ("Complex" in the above example). class StructDecl : public NominalTypeDecl { SourceLoc StructLoc; public: StructDecl(SourceLoc StructLoc, Identifier Name, SourceLoc NameLoc, MutableArrayRef Inherited, GenericParamList *GenericParams, DeclContext *DC); SourceLoc getStartLoc() const { return StructLoc; } SourceRange getSourceRange() const { return SourceRange(StructLoc, getBraces().End); } // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() == DeclKind::Struct; } static bool classof(const NominalTypeDecl *D) { return D->getKind() == DeclKind::Struct; } static bool classof(const DeclContext *C) { return isa(C) && classof(cast(C)); } static bool classof(const IterableDeclContext *C) { return isa(C) && classof(cast(C)); } /// Does this struct contain unreferenceable storage, such as C fields that /// cannot be represented in Swift? bool hasUnreferenceableStorage() const { return StructDeclBits.HasUnreferenceableStorage; } void setHasUnreferenceableStorage(bool v) { StructDeclBits.HasUnreferenceableStorage = true; } }; /// ClassDecl - This is the declaration of a class, for example: /// /// class Complex { var R : Double, I : Double } /// /// The type of the decl itself is a MetatypeType; use getDeclaredType() /// to get the declared type ("Complex" in the above example). class ClassDecl : public NominalTypeDecl { class ObjCMethodLookupTable; SourceLoc ClassLoc; Type Superclass; ObjCMethodLookupTable *ObjCMethodLookup = nullptr; /// Create the Objective-C member lookup table. void createObjCMethodLookup(); public: ClassDecl(SourceLoc ClassLoc, Identifier Name, SourceLoc NameLoc, MutableArrayRef Inherited, GenericParamList *GenericParams, DeclContext *DC); SourceLoc getStartLoc() const { return ClassLoc; } SourceRange getSourceRange() const { return SourceRange(ClassLoc, getBraces().End); } /// Determine whether this class has a superclass. bool hasSuperclass() const { return (bool)Superclass; } /// Retrieve the superclass of this class, or null if there is no superclass. Type getSuperclass() const { return Superclass; } /// Set the superclass of this class. void setSuperclass(Type superclass) { Superclass = superclass; } /// Retrieve the status of circularity checking for class inheritance. CircularityCheck getCircularityCheck() const { return static_cast(ClassDeclBits.Circularity); } /// Record the current stage of circularity checking. void setCircularityCheck(CircularityCheck circularity) { ClassDeclBits.Circularity = static_cast(circularity); } //// Whether this class requires all of its stored properties to //// have initializers in the class definition. bool requiresStoredPropertyInits() const { return ClassDeclBits.RequiresStoredPropertyInits; } /// Set whether this class requires all of its stored properties to /// have initializers in the class definition. void setRequiresStoredPropertyInits(bool requiresInits) { ClassDeclBits.RequiresStoredPropertyInits = requiresInits; } /// Whether this class is "foreign", meaning that it is implemented /// by a runtime that Swift does not have first-class integration /// with. This generally means that: /// - class data is either abstracted or cannot be made to /// fit with Swift's metatype schema, and/or /// - there is no facility for subclassing or adding polymorphic /// methods to the class. /// /// We may find ourselves wanting to break this bit into more /// precise chunks later. bool isForeign() const { return ClassDeclBits.Foreign; } void setForeign(bool isForeign = true) { ClassDeclBits.Foreign = true; } /// Find a method of a class that overrides a given method. /// Return nullptr, if no such method exists. FuncDecl *findOverridingDecl(const FuncDecl *method) const; /// Find a method implementation which will be used when a given method /// is invoked on an instance of this class. This implementation may stem /// either from a class itself or its direct or indirect superclasses. FuncDecl *findImplementingMethod(const FuncDecl *method) const; /// True if the class has a destructor. /// /// Fully type-checked classes always contain destructors, but during parsing /// or type-checking, the implicit destructor may not have been synthesized /// yet if one was not explicitly declared. bool hasDestructor() const { return ClassDeclBits.HasDestructorDecl; } /// Set the 'has destructor' flag. void setHasDestructor() { ClassDeclBits.HasDestructorDecl = 1; } /// Retrieve the destructor for this class. DestructorDecl *getDestructor(); /// Determine whether this class inherits the convenience initializers /// from its superclass. /// /// \param resolver Used to resolve the signatures of initializers, which is /// required for name lookup. bool inheritsSuperclassInitializers(LazyResolver *resolver); /// Retrieve the name to use for this class when interoperating with /// the Objective-C runtime. StringRef getObjCRuntimeName(llvm::SmallVectorImpl &buffer) const; using NominalTypeDecl::lookupDirect; /// Look in this class and its extensions (but not any of its protocols or /// superclasses) for declarations with a given Objective-C selector. /// /// Note that this can find methods, initializers, deinitializers, /// getters, and setters. /// /// \param selector The Objective-C selector of the method we're /// looking for. /// /// \param isInstance Whether we are looking for an instance method /// (vs. a class method). MutableArrayRef lookupDirect(ObjCSelector selector, bool isInstance); /// Record the presence of an @objc method whose Objective-C name has been /// finalized. void recordObjCMethod(AbstractFunctionDecl *method); // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() == DeclKind::Class; } static bool classof(const NominalTypeDecl *D) { return D->getKind() == DeclKind::Class; } static bool classof(const DeclContext *C) { return isa(C) && classof(cast(C)); } static bool classof(const IterableDeclContext *C) { return isa(C) && classof(cast(C)); } }; /// ProtocolDecl - A declaration of a protocol, for example: /// /// protocol Drawable { /// func draw() /// } class ProtocolDecl : public NominalTypeDecl { SourceLoc ProtocolLoc; bool requiresClassSlow(); public: ProtocolDecl(DeclContext *DC, SourceLoc ProtocolLoc, SourceLoc NameLoc, Identifier Name, MutableArrayRef Inherited); using Decl::getASTContext; /// \brief Determine whether this protocol inherits from the given ("super") /// protocol. bool inheritsFrom(const ProtocolDecl *Super) const; /// \brief Collect all of the inherited protocols into the given set. void collectInherited(llvm::SmallPtrSet &Inherited); ProtocolType *getDeclaredType() const { return reinterpret_cast(DeclaredTy.getPointer()); } SourceLoc getStartLoc() const { return ProtocolLoc; } SourceRange getSourceRange() const { return SourceRange(ProtocolLoc, getBraces().End); } /// \brief Retrieve the generic parameter 'Self'. GenericTypeParamDecl *getSelf() const; /// True if this protocol can only be conformed to by class types. bool requiresClass() { if (ProtocolDeclBits.RequiresClassValid) return ProtocolDeclBits.RequiresClass; return requiresClassSlow(); } /// Specify that this protocol is class-bounded, e.g., because it was /// annotated with the 'class' keyword. void setRequiresClass() { ProtocolDeclBits.RequiresClassValid = true; ProtocolDeclBits.RequiresClass = true; } /// Determine whether an existential value conforming to just this protocol /// conforms to the protocol itself. /// /// \returns an empty optional if not yet known, true if the existential /// does conform to this protocol, and false otherwise. Optional existentialConformsToSelf() const { if (ProtocolDeclBits.ExistentialConformsToSelfValid) return ProtocolDeclBits.ExistentialConformsToSelf; return None; } /// Set whether the existential of this protocol type conforms to this /// protocol. void setExistentialConformsToSelf(bool conforms) { ProtocolDeclBits.ExistentialConformsToSelfValid = true; ProtocolDeclBits.ExistentialConformsToSelf = conforms; } /// If this is known to be a compiler-known protocol, returns the kind. /// Otherwise returns None. /// /// Note that this is only valid after type-checking. Optional getKnownProtocolKind() const { if (ProtocolDeclBits.KnownProtocol == 0) return None; return static_cast(ProtocolDeclBits.KnownProtocol - 1); } /// Check whether this protocol is of a specific, known protocol kind. bool isSpecificProtocol(KnownProtocolKind kind) const { if (auto knownKind = getKnownProtocolKind()) return *knownKind == kind; return false; } /// Records that this is a compiler-known protocol. void setKnownProtocolKind(KnownProtocolKind kind) { assert((!getKnownProtocolKind() || *getKnownProtocolKind() == kind) && "can't reset known protocol kind"); ProtocolDeclBits.KnownProtocol = static_cast(kind) + 1; assert(getKnownProtocolKind() && *getKnownProtocolKind() == kind && "not enough bits"); } /// Retrieve the status of circularity checking for protocol inheritance. CircularityCheck getCircularityCheck() const { return static_cast(ProtocolDeclBits.Circularity); } /// Record the current stage of circularity checking. void setCircularityCheck(CircularityCheck circularity) { ProtocolDeclBits.Circularity = static_cast(circularity); } /// Returns true if the protocol has requirements that are not listed in its /// members. /// /// This can occur, for example, if the protocol is an Objective-C protocol /// with requirements that cannot be represented in Swift. bool hasMissingRequirements() const { (void)getMembers(); return ProtocolDeclBits.HasMissingRequirements; } void setHasMissingRequirements(bool newValue) { ProtocolDeclBits.HasMissingRequirements = newValue; } /// Retrieve the name to use for this protocol when interoperating /// with the Objective-C runtime. StringRef getObjCRuntimeName(llvm::SmallVectorImpl &buffer) const; // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() == DeclKind::Protocol; } static bool classof(const NominalTypeDecl *D) { return D->getKind() == DeclKind::Protocol; } static bool classof(const DeclContext *C) { return isa(C) && classof(cast(C)); } static bool classof(const IterableDeclContext *C) { return isa(C) && classof(cast(C)); } }; // Note that the values of these enums line up with %select values in // diagnostics. enum class AccessorKind { /// \brief This is not a property accessor. NotAccessor = -1, /// \brief This is a getter for a property or subscript. IsGetter = 0, /// \brief This is a setter for a property or subscript. IsSetter = 1, /// \brief This is a willSet specifier for a property. IsWillSet = 2, /// \brief This is a didSet specifier for a property. IsDidSet = 3, /// \brief This is a materializeForSet accessor for a property. IsMaterializeForSet = 4, /// \brief This is an address accessor for a property or subscript. IsAddressor = 5, /// \brief This is a mutableAddress accessor for a property or subscript. IsMutableAddressor = 6, }; /// Whether an access to storage is for reading, writing, or both. enum class AccessKind : unsigned char { /// The access is just to read the current value. Read, /// The access is just to overwrite the current value. Write, /// The access may require either reading or writing the current value. ReadWrite }; /// The way to actually evaluate an access to storage. enum class AccessStrategy : unsigned char { /// The decl is a VarDecl with its own backing storage; evaluate its /// address directly. Storage, /// The decl has addressors; call the appropriate addressor for the /// access kind. These calls are currently always direct. Addressor, /// Directly call the getter, setter, or materializeForSet accessor. DirectToAccessor, /// Indirectly call the getter, setter, or materializeForSet accessor. DispatchToAccessor, }; /// AbstractStorageDecl - This is the common superclass for VarDecl and /// SubscriptDecl, representing potentially settable memory locations. class AbstractStorageDecl : public ValueDecl { public: enum StorageKindTy { /// There are bits stored in memory for this object, and they are accessed /// directly. This is not valid for a SubscriptDecl. Stored, /// This is a stored property with trivial accessors which simply get and /// set the underlying storage. This is not valid for a SubscriptDecl. /// /// These accessors are used for several different purposes: /// 1) In an @objc variable, these accessors are dynamically dispatched /// to and may be overridden. /// 2) When a stored property satisfies a protocol requirement, these /// accessors end up as entries in the witness table. /// 3) Perhaps someday these will be used by accesses outside of this /// resilience domain, when the owning type is resilient. /// StoredWithTrivialAccessors, /// This is a stored property with either a didSet specifier or a /// willSet specifier (or both). Sema synthesizes a setter which /// calls them at the appropriate points. StoredWithObservers, /// There are bits stored in memory for this object, but they are /// not allocated directly within the container; instead, there /// are accessors which return the address of the memory. The /// value is accessed directly through the returned address. /// /// This is legal on both VarDecls and SubscriptDecls. /// /// There is always at least an 'address' accessor; if the object /// is mutable, there will also be a 'mutableAddress' accessor. Addressed, /// Like Addressed, this object has address accessors. Like /// StoredWithTrivialAccessors, accessors have been synthesized /// which simply read and write through the addresses returned by /// the addressors. AddressedWithTrivialAccessors, /// Like Addressed, this object has address accessors. Like /// StoredWithObservers, it also has either a willSet specifier or /// a didSet specifier. Accessors have been synthesized, like /// with StoredWithObservers but using the address returned from /// the appropriate accessor instead. AddressedWithObservers, /// This is an override of an object which adds either a didSet /// specifier or a willSet specifier (or both). Sema synthesizes /// a setter which calls them at the appropriate points around /// delegating to the superclass's setter. InheritedWithObservers, /// There is no memory associated with this decl anywhere. It is /// accessed by calling a getter and setter. If the setter is /// absent, then the value is only loadable, but not storable. Computed, /// This object was specified with non-trivial getter and /// mutableAddress accessors. If it is accessed in a read-only /// manner, the getter is called; otherwise, mutableAddress is /// called. /// /// This turns out to the be the right thing for certain core data /// structures which, when they store a bridged object, cannot /// return the address at which the object is stored. ComputedWithMutableAddress, }; private: AbstractStorageDecl *OverriddenDecl; struct GetSetRecord; /// This is stored immediately before the GetSetRecord. struct AddressorRecord { FuncDecl *Address = nullptr; // User-defined address accessor FuncDecl *MutableAddress = nullptr; // User-defined mutableAddress accessor GetSetRecord *getGetSet() { // Relies on not-strictly-portable ABI layout assumptions. return reinterpret_cast(this+1); } }; void configureAddressorRecord(AddressorRecord *record, FuncDecl *addressor, FuncDecl *mutableAddressor); struct GetSetRecord { SourceRange Braces; FuncDecl *Get = nullptr; // User-defined getter FuncDecl *Set = nullptr; // User-defined setter FuncDecl *MaterializeForSet = nullptr; // optional materializeForSet accessor AddressorRecord *getAddressors() { // Relies on not-strictly-portable ABI layout assumptions. return reinterpret_cast(this) - 1; } }; void configureGetSetRecord(GetSetRecord *getSetRecord, FuncDecl *getter, FuncDecl *setter, FuncDecl *materializeForSet); void configureSetRecord(GetSetRecord *getSetInfo, FuncDecl *setter, FuncDecl *materializeForSet); struct ObservingRecord : GetSetRecord { FuncDecl *WillSet = nullptr; // willSet(value): FuncDecl *DidSet = nullptr; // didSet: }; void configureObservingRecord(ObservingRecord *record, FuncDecl *willSet, FuncDecl *didSet); struct GetSetRecordWithAddressors : AddressorRecord, GetSetRecord {}; struct ObservingRecordWithAddressors : AddressorRecord, ObservingRecord {}; llvm::PointerIntPair> GetSetInfo; ObservingRecord &getDidSetInfo() const { assert(hasObservers()); return *static_cast(GetSetInfo.getPointer()); } AddressorRecord &getAddressorInfo() const { assert(hasAddressors()); return *GetSetInfo.getPointer()->getAddressors(); } void setStorageKind(StorageKindTy K) { AbstractStorageDeclBits.StorageKind = unsigned(K); } protected: AbstractStorageDecl(DeclKind Kind, DeclContext *DC, DeclName Name, SourceLoc NameLoc) : ValueDecl(Kind, DC, Name, NameLoc), OverriddenDecl(nullptr) { AbstractStorageDeclBits.StorageKind = Stored; AbstractStorageDeclBits.Overridden = false; } public: /// \brief Determine whether this variable is computed, which means it /// has no storage but does have a user-defined getter or setter. /// StorageKindTy getStorageKind() const { return (StorageKindTy) AbstractStorageDeclBits.StorageKind; } /// \brief Return true if this is a VarDecl that has storage associated with /// it. bool hasStorage() const { switch (getStorageKind()) { case Stored: case StoredWithTrivialAccessors: case StoredWithObservers: return true; case InheritedWithObservers: case Computed: case ComputedWithMutableAddress: case Addressed: case AddressedWithTrivialAccessors: case AddressedWithObservers: return false; } llvm_unreachable("bad storage kind"); } /// \brief Return true if this object has a getter (and, if mutable, /// a setter and a materializeForSet). bool hasAccessorFunctions() const { switch (getStorageKind()) { case Addressed: case Stored: return false; case StoredWithTrivialAccessors: case StoredWithObservers: case InheritedWithObservers: case Computed: case ComputedWithMutableAddress: case AddressedWithTrivialAccessors: case AddressedWithObservers: return true; } llvm_unreachable("bad storage kind"); } /// \brief Return true if this object has observing accessors. /// /// It's generally not appropriate to use this predicate directly in /// a condition; instead, you should be switching on the storage kind. bool hasObservers() const { switch (getStorageKind()) { case Stored: case StoredWithTrivialAccessors: case Computed: case ComputedWithMutableAddress: case Addressed: case AddressedWithTrivialAccessors: return false; case StoredWithObservers: case InheritedWithObservers: case AddressedWithObservers: return true; } llvm_unreachable("bad storage kind"); } /// \brief Return true if this object has either an addressor or a /// mutable addressor. /// /// It's generally not appropriate to use this predicate directly in /// a condition; instead, you should be switching on the storage /// kind. Only use this for diagnostic, AST exploration, or /// assertion purposes. bool hasAddressors() const { switch (getStorageKind()) { case Stored: case StoredWithTrivialAccessors: case StoredWithObservers: case InheritedWithObservers: case Computed: return false; case ComputedWithMutableAddress: case Addressed: case AddressedWithTrivialAccessors: case AddressedWithObservers: return true; } llvm_unreachable("bad storage kind"); } FuncDecl *getAccessorFunction(AccessorKind accessor) const; /// \brief Turn this into a computed variable, providing a getter and setter. void makeComputed(SourceLoc LBraceLoc, FuncDecl *Get, FuncDecl *Set, FuncDecl *MaterializeForSet, SourceLoc RBraceLoc); /// \brief Turn this into a computed object, providing a getter and a mutable /// addressor. void makeComputedWithMutableAddress(SourceLoc lbraceLoc, FuncDecl *getter, FuncDecl *setter, FuncDecl *materializeForSet, FuncDecl *mutableAddressor, SourceLoc rbraceLoc); /// \brief Add trivial accessors to this Stored or Addressed object. void addTrivialAccessors(FuncDecl *Get, FuncDecl *Set, FuncDecl *MaterializeForSet); /// \brief Turn this into a stored-with-observers var, providing the /// didSet/willSet specifiers. void makeStoredWithObservers(SourceLoc LBraceLoc, FuncDecl *WillSet, FuncDecl *DidSet, SourceLoc RBraceLoc); /// \brief Turn this into an inherited-with-observers var, providing /// the didSet/willSet specifiers. void makeInheritedWithObservers(SourceLoc LBraceLoc, FuncDecl *WillSet, FuncDecl *DidSet, SourceLoc RBraceLoc); /// \brief Turn this into an addressed var. void makeAddressed(SourceLoc LBraceLoc, FuncDecl *Addressor, FuncDecl *MutableAddressor, SourceLoc RBraceLoc); /// \brief Turn this into an addressed var with observing accessors. void makeAddressedWithObservers(SourceLoc LBraceLoc, FuncDecl *Addressor, FuncDecl *MutableAddressor, FuncDecl *WillSet, FuncDecl *DidSet, SourceLoc RBraceLoc); /// \brief Specify the synthesized get/set functions for a /// StoredWithObservers or AddressedWithObservers var. This is used by Sema. void setObservingAccessors(FuncDecl *Get, FuncDecl *Set, FuncDecl *MaterializeForSet); /// \brief Add a setter to an existing Computed var. /// /// This should only be used by the ClangImporter. void setComputedSetter(FuncDecl *Set); /// \brief Set a materializeForSet accessor for this declaration. /// /// This should only be used by Sema. void setMaterializeForSetFunc(FuncDecl *materializeForSet); /// \brief Specify the braces range without adding accessors. /// /// This is used to record the braces range if the accessors were rejected. void setInvalidBracesRange(SourceRange BracesRange); SourceRange getBracesRange() const { if (auto info = GetSetInfo.getPointer()) return info->Braces; return SourceRange(); } /// \brief Retrieve the getter used to access the value of this variable. FuncDecl *getGetter() const { if (auto info = GetSetInfo.getPointer()) return info->Get; return nullptr; } /// \brief Retrieve the setter used to mutate the value of this variable. FuncDecl *getSetter() const { if (auto info = GetSetInfo.getPointer()) return info->Set; return nullptr; } Accessibility getSetterAccessibility() const { assert(hasAccessibility()); assert(GetSetInfo.getInt().hasValue()); return GetSetInfo.getInt().getValue(); } void setSetterAccessibility(Accessibility accessLevel) { assert(!GetSetInfo.getInt().hasValue()); overwriteSetterAccessibility(accessLevel); } void overwriteSetterAccessibility(Accessibility accessLevel); /// \brief Retrieve the materializeForSet function, if this /// declaration has one. FuncDecl *getMaterializeForSetFunc() const { if (auto info = GetSetInfo.getPointer()) return info->MaterializeForSet; return nullptr; } /// \brief Return the funcdecl for the 'address' accessor if it /// exists; this is only valid on a declaration with addressors. FuncDecl *getAddressor() const { return getAddressorInfo().Address; } /// \brief Return the funcdecl for the 'mutableAddress' accessors if /// it exists; this is only valid on a declaration with addressors. FuncDecl *getMutableAddressor() const { return getAddressorInfo().MutableAddress; } /// \brief Return the approproiate addressor for the given access kind. FuncDecl *getAddressorForAccess(AccessKind accessKind) const { if (accessKind == AccessKind::Read) return getAddressor(); return getMutableAddressor(); } /// \brief Return the funcdecl for the willSet specifier if it exists, this is /// only valid on a declaration with Observing storage. FuncDecl *getWillSetFunc() const { return getDidSetInfo().WillSet; } /// \brief Return the funcdecl for the didSet specifier if it exists, this is /// only valid on a declaration with Observing storage. FuncDecl *getDidSetFunc() const { return getDidSetInfo().DidSet; } /// Return true if this storage can (but doesn't have to) be accessed with /// Objective-C-compatible getters and setters. bool hasObjCGetterAndSetter() const; /// Return true if this storage *must* be accessed with Objective-C-compatible /// getters and setters. bool requiresObjCGetterAndSetter() const; /// Given that this is an Objective-C property or subscript declaration, /// produce its getter selector. ObjCSelector getObjCGetterSelector() const; /// Given that this is an Objective-C property or subscript declaration, /// produce its setter selector. ObjCSelector getObjCSetterSelector() const; AbstractStorageDecl *getOverriddenDecl() const { return OverriddenDecl; } void setOverriddenDecl(AbstractStorageDecl *over) { OverriddenDecl = over; over->setIsOverridden(); } /// The declaration has been overridden in the module /// /// Resolved during type checking void setIsOverridden() { AbstractStorageDeclBits.Overridden = true; } /// Whether the declaration is later overridden in the module /// /// Overriddes are resolved during type checking; only query this field after /// the whole module has been checked bool isOverridden() const { return AbstractStorageDeclBits.Overridden; } /// Returns the location of 'override' keyword, if any. SourceLoc getOverrideLoc() const; /// Returns true if this declaration has a setter accessible from the given /// context. /// /// If \p DC is null, returns true only if the setter is public. bool isSetterAccessibleFrom(const DeclContext *DC) const; /// Determine how this storage declaration should actually be accessed. AccessStrategy getAccessStrategy(AccessSemantics semantics, AccessKind accessKind) const; // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() >= DeclKind::First_AbstractStorageDecl && D->getKind() <= DeclKind::Last_AbstractStorageDecl; } }; /// VarDecl - 'var' and 'let' declarations. class VarDecl : public AbstractStorageDecl { protected: llvm::PointerUnion ParentPattern; VarDecl(DeclKind Kind, bool IsStatic, bool IsLet, SourceLoc NameLoc, Identifier Name, Type Ty, DeclContext *DC) : AbstractStorageDecl(Kind, DC, Name, NameLoc) { VarDeclBits.IsStatic = IsStatic; VarDeclBits.IsLet = IsLet; VarDeclBits.IsDebuggerVar = false; setType(Ty); } public: VarDecl(bool IsStatic, bool IsLet, SourceLoc NameLoc, Identifier Name, Type Ty, DeclContext *DC) : VarDecl(DeclKind::Var, IsStatic, IsLet, NameLoc, Name, Ty, DC) { } SourceLoc getStartLoc() const { return getNameLoc(); } SourceRange getSourceRange() const; /// \brief Retrieve the source range of the variable type. /// /// Only for use in diagnostics. It is not always possible to always /// precisely point to the variable type because of type aliases. SourceRange getTypeSourceRangeForDiagnostics() const; /// \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. /// /// Pass a null context to check if it's always settable. bool isSettable(DeclContext *UseDC) const; PatternBindingDecl *getParentPattern() const { return ParentPattern.dyn_cast(); } void setParentPattern(PatternBindingDecl *PBD) { ParentPattern = PBD; } VarDecl *getOverriddenDecl() const { return cast_or_null(AbstractStorageDecl::getOverriddenDecl()); } /// Determine whether this declaration is an anonymous closure parameter. bool isAnonClosureParam() const; /// Is this a type ('static') variable? bool isStatic() const { return VarDeclBits.IsStatic; } void setStatic(bool IsStatic) { VarDeclBits.IsStatic = IsStatic; } /// \returns the way 'static'/'class' should be spelled for this declaration. StaticSpellingKind getCorrectStaticSpelling() const; /// Is this an immutable 'let' property? bool isLet() const { return VarDeclBits.IsLet; } void setLet(bool IsLet) { VarDeclBits.IsLet = IsLet; } /// Is this a special debugger variable? bool isDebuggerVar() const { return VarDeclBits.IsDebuggerVar; } void setDebuggerVar(bool IsDebuggerVar) { VarDeclBits.IsDebuggerVar = IsDebuggerVar; } // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() == DeclKind::Var || D->getKind() == DeclKind::Param; } }; /// A function parameter declaration. class ParamDecl : public VarDecl { Identifier ArgumentName; SourceLoc ArgumentNameLoc; public: ParamDecl(bool isLet, SourceLoc argumentNameLoc, Identifier argumentName, SourceLoc parameterNameLoc, Identifier parameterName, Type ty, DeclContext *dc) : VarDecl(DeclKind::Param, /*IsState=*/false, isLet, parameterNameLoc, parameterName, ty, dc), ArgumentName(argumentName), ArgumentNameLoc(argumentNameLoc) { } /// Retrieve the argument (API) name for this function parameter. Identifier getArgumentName() const { return ArgumentName; } /// Retrieve the source location of the argument (API) name. /// /// The resulting source location will be valid if the argument name /// was specified separately from the parameter name. SourceLoc getArgumentNameLoc() const { return ArgumentNameLoc; } SourceRange getSourceRange() const { if (ArgumentNameLoc.isValid() && getNameLoc().isInvalid()) return ArgumentNameLoc; if (ArgumentNameLoc.isInvalid() && getNameLoc().isValid()) return getNameLoc(); return SourceRange(ArgumentNameLoc, getNameLoc()); } Pattern *getParamParentPattern() const { return ParentPattern.dyn_cast(); } void setParamParentPattern(Pattern *Pat) { ParentPattern = Pat; } // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() == DeclKind::Param; } }; /// Describes the kind of subscripting used in Objective-C. enum class ObjCSubscriptKind { /// Not an Objective-C subscripting kind. None, /// Objective-C indexed subscripting, which is based on an integral /// index. Indexed, /// Objective-C keyed subscripting, which is based on an object /// argument or metatype thereof. Keyed }; /// \brief Declares a subscripting operator for a type. /// /// A subscript declaration is defined as a get/set pair that produces a /// specific type. For example: /// /// \code /// subscript (i : Int) -> String { /// get { /* return ith String */ } /// set { /* set ith string to value */ } /// } /// \endcode /// /// A type with a subscript declaration can be used as the base of a subscript /// expression a[i], where a is of the subscriptable type and i is the type /// of the index. A subscript can have multiple indices: /// /// \code /// struct Matrix { /// subscript (i : Int, j : Int) -> Double { /// get { /* return element at position (i, j) */ } /// set { /* set element at position (i, j) */ } /// } /// } /// \endcode /// /// A given type can have multiple subscript declarations, so long as the /// signatures (indices and element type) are distinct. /// class SubscriptDecl : public AbstractStorageDecl { SourceLoc ArrowLoc; Pattern *Indices; TypeLoc ElementTy; public: SubscriptDecl(DeclName Name, SourceLoc SubscriptLoc, Pattern *Indices, SourceLoc ArrowLoc, TypeLoc ElementTy, DeclContext *Parent) : AbstractStorageDecl(DeclKind::Subscript, Parent, Name, SubscriptLoc), ArrowLoc(ArrowLoc), Indices(nullptr), ElementTy(ElementTy) { setIndices(Indices); } SourceLoc getSubscriptLoc() const { return getNameLoc(); } SourceLoc getStartLoc() const { return getSubscriptLoc(); } SourceRange getSourceRange() const; /// \brief Retrieve the indices for this subscript operation. Pattern *getIndices() { return Indices; } const Pattern *getIndices() const { return Indices; } void setIndices(Pattern *p); /// Retrieve the type of the indices. Type getIndicesType() const; /// Retrieve the interface type of the indices. Type getIndicesInterfaceType() const; /// \brief Retrieve the type of the element referenced by a subscript /// operation. Type getElementType() const { return ElementTy.getType(); } TypeLoc &getElementTypeLoc() { return ElementTy; } const TypeLoc &getElementTypeLoc() const { return ElementTy; } /// \brief Returns whether the result of the subscript operation can be set. bool isSettable() const; /// Determine the kind of Objective-C subscripting this declaration /// implies. ObjCSubscriptKind getObjCSubscriptKind() const; SubscriptDecl *getOverriddenDecl() const { return cast_or_null( AbstractStorageDecl::getOverriddenDecl()); } static bool classof(const Decl *D) { return D->getKind() == DeclKind::Subscript; } }; /// \brief Base class for function-like declarations. class AbstractFunctionDecl : public ValueDecl, public DeclContext { public: enum class BodyKind { /// The function did not have a body in the source code file. None, /// Function body is delayed, to be parsed later. Unparsed, /// Function body is parsed and available as an AST subtree. Parsed, /// Function body is not available, although it was written in the source. Skipped, /// Function body will be synthesized on demand. Synthesize, /// Function body is present and type-checked. TypeChecked, // This enum currently needs to fit in a 3-bit bitfield. }; BodyKind getBodyKind() const { return BodyKind(AbstractFunctionDeclBits.BodyKind); } using BodySynthesizer = void (*)(AbstractFunctionDecl *); protected: // If a function has a body at all, we have either a parsed body AST node or // we have saved the end location of the unparsed body. union { /// This enum member is active if getBodyKind() is BodyKind::Parsed or /// BodyKind::TypeChecked. BraceStmt *Body; /// This enum member is active if getBodyKind() == BodyKind::Synthesize. BodySynthesizer Synthesizer; /// The location of the function body when the body is delayed or skipped. /// /// This enum member is active if getBodyKind() is BodyKind::Unparsed or /// BodyKind::Skipped. SourceRange BodyRange; }; GenericParamList *GenericParams; CaptureInfo Captures; AbstractFunctionDecl(DeclKind Kind, DeclContext *Parent, DeclName Name, SourceLoc NameLoc, unsigned NumParamPatterns, GenericParamList *GenericParams) : ValueDecl(Kind, Parent, Name, NameLoc), DeclContext(DeclContextKind::AbstractFunctionDecl, Parent), Body(nullptr), GenericParams(nullptr) { setBodyKind(BodyKind::None); setGenericParams(GenericParams); AbstractFunctionDeclBits.NumParamPatterns = NumParamPatterns; AbstractFunctionDeclBits.Overridden = false; // Verify no bitfield truncation. assert(AbstractFunctionDeclBits.NumParamPatterns == NumParamPatterns); } MutableArrayRef getBodyParamBuffer(); void setBodyKind(BodyKind K) { AbstractFunctionDeclBits.BodyKind = unsigned(K); } void setGenericParams(GenericParamList *GenericParams); public: // FIXME: Hack that provides names with keyword arguments for accessors. DeclName getEffectiveFullName() const; /// \brief If this is a method in a type extension for some type, /// return that type, otherwise return Type(). Type getExtensionType() const; /// Returns true if the function has a body written in the source file. /// /// Note that a true return value does not imply that the body was actually /// parsed. bool hasBody() const { return getBodyKind() != BodyKind::None; } /// Returns the function body, if it was parsed, or nullptr otherwise. /// /// Note that a null return value does not imply that the source code did not /// have a body for this function. /// /// \sa hasBody() BraceStmt *getBody(bool canSynthesize = true) const { if (canSynthesize && getBodyKind() == BodyKind::Synthesize) { const_cast(this)->setBodyKind(BodyKind::None); (*Synthesizer)(const_cast(this)); } if (getBodyKind() == BodyKind::Parsed || getBodyKind() == BodyKind::TypeChecked) { return Body; } return nullptr; } void setBody(BraceStmt *S, BodyKind NewBodyKind = BodyKind::Parsed) { assert(getBodyKind() != BodyKind::Skipped && "can not set a body if it was skipped"); Body = S; setBodyKind(NewBodyKind); } /// \brief Note that the body was skipped for this function. Function body /// can not be attached after this call. void setBodySkipped(SourceRange bodyRange) { assert(getBodyKind() == BodyKind::None); BodyRange = bodyRange; setBodyKind(BodyKind::Skipped); } /// \brief Note that parsing for the body was delayed. void setBodyDelayed(SourceRange bodyRange) { assert(getBodyKind() == BodyKind::None); BodyRange = bodyRange; setBodyKind(BodyKind::Unparsed); } /// Note that parsing for the body was delayed. void setBodySynthesizer(BodySynthesizer synthesizer) { assert(getBodyKind() == BodyKind::None); Synthesizer = synthesizer; setBodyKind(BodyKind::Synthesize); } /// If a body has been loaded, flag that it's been type-checked. /// This is kindof a hacky operation, but it avoids some unnecessary /// duplication of work. void setBodyTypeCheckedIfPresent() { if (getBodyKind() == BodyKind::Parsed) setBodyKind(BodyKind::TypeChecked); } bool isBodyTypeChecked() const { return getBodyKind() == BodyKind::TypeChecked; } /// Retrieve the source range of the function body. SourceRange getBodySourceRange() const; /// Retrieve the source range of the function declaration name + patterns. SourceRange getSignatureSourceRange() const; CaptureInfo &getCaptureInfo() { return Captures; } const CaptureInfo &getCaptureInfo() const { return Captures; } /// Retrieve the Objective-C selector that names this method. ObjCSelector getObjCSelector() const; /// Determine the default argument kind and type for the given argument index /// in this declaration, which must be a function or constructor. /// /// \param Index The index of the argument for which we are querying the /// default argument. /// /// \returns the default argument kind and, if there is a default argument, /// the type of the corresponding parameter. std::pair getDefaultArg(unsigned Index) const; /// Determine whether the name of the ith argument is an API name by default. bool argumentNameIsAPIByDefault(unsigned i) const; unsigned getNumParamPatterns() const { return AbstractFunctionDeclBits.NumParamPatterns; } /// \brief Returns the "natural" number of argument clauses taken by this /// function. This value is always at least one, and it may be more if the /// function is implicitly or explicitly curried. /// /// For example, this function: /// \code /// func negate(x : Int) -> Int { return -x } /// \endcode /// has a natural argument count of 1 if it is freestanding. If it is /// a method, it has a natural argument count of 2, as does this /// curried function: /// \code /// func add(x : Int)(y : Int) -> Int { return x + y } /// \endcode /// /// This value never exceeds the number of chained function types /// in the function's type, but it can be less for functions which /// return a value of function type: /// \code /// func const(x : Int) -> () -> Int { return { x } } // NAC==1 /// \endcode unsigned getNaturalArgumentCount() const { return getNumParamPatterns(); } /// \brief Returns the parameter pattern(s) for the function definition that /// determine the parameter names bound in the function body. /// /// The number of "top-level" elements in this pattern will match the number /// of argument names in the compound name of the function or constructor. MutableArrayRef getBodyParamPatterns() { return getBodyParamBuffer(); } ArrayRef getBodyParamPatterns() const { auto Patterns = const_cast(this)->getBodyParamBuffer(); return ArrayRef(Patterns.data(), Patterns.size()); } /// \brief If this is a method in a type or extension thereof, compute /// and return the type to be used for the 'self' argument of the type, or an /// empty Type() if no 'self' argument should exist. This can /// only be used after name binding has resolved types. /// /// \param outerGenericParams If non-NULL, and this function is an instance /// of a generic type, will be set to the generic parameter list of that /// generic type. Type computeSelfType(GenericParamList **outerGenericParams = nullptr); /// \brief If this is a method in a type or extension thereof, compute /// and return the type to be used for the 'self' argument of the interface /// type, or an empty Type() if no 'self' argument should exist. This can /// only be used after name binding has resolved types. /// /// \param isInitializingCtor Specifies whether we're computing the 'self' /// type of an initializing constructor, which accepts an instance 'self' /// rather than a metatype 'self'. Type computeInterfaceSelfType(bool isInitializingCtor); /// \brief This method returns the implicit 'self' decl. /// /// Note that some functions don't have an implicit 'self' decl, for example, /// free functions. In this case nullptr is returned. VarDecl *getImplicitSelfDecl() const; /// \brief Retrieve the set of parameters to a generic function, or null if /// this function is not generic. GenericParamList *getGenericParams() const { return GenericParams; } /// \brief Determine whether this is a generic function, which can only be /// used when each of the archetypes is bound to a particular concrete type. bool isGeneric() const { return GenericParams != nullptr; } /// Retrieve the declaration that this method overrides, if any. AbstractFunctionDecl *getOverriddenDecl() const; /// Whether the declaration is later overridden in the module /// /// Overriddes are resolved during type checking; only query this field after /// the whole module has been checked bool isOverridden() const { return AbstractFunctionDeclBits.Overridden; } /// The declaration has been overridden in the module /// /// Resolved during type checking void setIsOverridden() { AbstractFunctionDeclBits.Overridden = true; } static bool classof(const Decl *D) { return D->getKind() >= DeclKind::First_AbstractFunctionDecl && D->getKind() <= DeclKind::Last_AbstractFunctionDecl; } static bool classof(const DeclContext *DC) { return DC->getContextKind() == DeclContextKind::AbstractFunctionDecl; } using DeclContext::operator new; using Decl::getASTContext; }; class OperatorDecl; /// FuncDecl - 'func' declaration. class FuncDecl : public AbstractFunctionDecl { friend class AbstractFunctionDecl; SourceLoc StaticLoc; // Location of the 'static' token or invalid. SourceLoc FuncLoc; // Location of the 'func' token. TypeLoc FnRetType; /// The result type as seen from the body of the function. /// /// \sa getBodyResultType() Type BodyResultType; /// \brief If this FuncDecl is an accessor for a property, this indicates /// which property and what kind of accessor. llvm::PointerIntPair AccessorDecl; llvm::PointerUnion OverriddenOrDerivedForDecl; OperatorDecl *Operator; FuncDecl(SourceLoc StaticLoc, StaticSpellingKind StaticSpelling, SourceLoc FuncLoc, DeclName Name, SourceLoc NameLoc, unsigned NumParamPatterns, GenericParamList *GenericParams, Type Ty, DeclContext *Parent) : AbstractFunctionDecl(DeclKind::Func, Parent, Name, NameLoc, NumParamPatterns, GenericParams), StaticLoc(StaticLoc), FuncLoc(FuncLoc), OverriddenOrDerivedForDecl(), Operator(nullptr) { FuncDeclBits.IsStatic = StaticLoc.isValid() || getName().isOperator(); FuncDeclBits.StaticSpelling = static_cast(StaticSpelling); assert(NumParamPatterns > 0 && "Must have at least an empty tuple arg"); setType(Ty); FuncDeclBits.Mutating = false; FuncDeclBits.HasDynamicSelf = false; } static FuncDecl *createImpl(ASTContext &Context, SourceLoc StaticLoc, StaticSpellingKind StaticSpelling, SourceLoc FuncLoc, DeclName Name, SourceLoc NameLoc, GenericParamList *GenericParams, Type Ty, unsigned NumParamPatterns, DeclContext *Parent, ClangNode ClangN); public: /// Factory function only for use by deserialization. static FuncDecl *createDeserialized(ASTContext &Context, SourceLoc StaticLoc, StaticSpellingKind StaticSpelling, SourceLoc FuncLoc, DeclName Name, SourceLoc NameLoc, GenericParamList *GenericParams, Type Ty, unsigned NumParamPatterns, DeclContext *Parent); static FuncDecl *create(ASTContext &Context, SourceLoc StaticLoc, StaticSpellingKind StaticSpelling, SourceLoc FuncLoc, DeclName Name, SourceLoc NameLoc, GenericParamList *GenericParams, Type Ty, ArrayRef BodyParams, TypeLoc FnRetType, DeclContext *Parent, ClangNode ClangN = ClangNode()); bool isStatic() const { return FuncDeclBits.IsStatic; } /// \returns the way 'static'/'class' was spelled in the source. StaticSpellingKind getStaticSpelling() const { return static_cast(FuncDeclBits.StaticSpelling); } /// \returns the way 'static'/'class' should be spelled for this declaration. StaticSpellingKind getCorrectStaticSpelling() const; bool isMutating() const { return FuncDeclBits.Mutating; } void setStatic(bool IsStatic = true) { FuncDeclBits.IsStatic = IsStatic; } void setMutating(bool Mutating = true) { FuncDeclBits.Mutating = Mutating; } /// \returns true if this is non-mutating due to applying a 'mutating' /// attribute. For example a "mutating set" accessor. bool isExplicitNonMutating() const; void setDeserializedSignature(ArrayRef BodyParams, TypeLoc FnRetType); SourceLoc getStaticLoc() const { return StaticLoc; } SourceLoc getFuncLoc() const { return FuncLoc; } SourceLoc getStartLoc() const { return StaticLoc.isValid() ? StaticLoc : FuncLoc; } SourceRange getSourceRange() const; TypeLoc &getBodyResultTypeLoc() { return FnRetType; } const TypeLoc &getBodyResultTypeLoc() const { return FnRetType; } /// Retrieve the result type of this function. /// /// \sa getBodyResultType Type getResultType() const; /// Retrieve the result type of this function for use within the function /// definition. /// /// FIXME: The statement below is a wish, not reality. /// The "body" result type will only differ from the result type within the /// interface to the function for a polymorphic function, where the interface /// may contain generic parameters while the definition will contain /// the corresponding archetypes. Type getBodyResultType() const { return BodyResultType; } /// Set the result type as viewed from the function body. /// /// \sa getBodyResultType void setBodyResultType(Type bodyResultType) { assert(BodyResultType.isNull() && "Already set body result type"); BodyResultType = bodyResultType; } /// Revert to an empty type. void revertType() { BodyResultType = Type(); overwriteType(Type()); } /// isUnaryOperator - Determine whether this is a unary operator /// implementation, in other words, the name of the function is an operator, /// and the argument list consists syntactically of a single-element tuple /// pattern. This check is syntactic rather than type-based in order to allow /// for the definition of unary operators on tuples, as in: /// func [prefix] + (_:(a:Int, b:Int)) /// This also allows the unary-operator-ness of a func decl to be determined /// prior to type checking. bool isUnaryOperator() const; /// isBinaryOperator - Determine whether this is a binary operator /// implementation, in other words, the name of the function is an operator, /// and the argument list consists syntactically of a two-element tuple /// pattern. This check is syntactic rather than type-based in order to /// distinguish a binary operator from a unary operator on tuples, as in: /// func [prefix] + (_:(a:Int, b:Int)) // unary operator +(1,2) /// func [infix] + (a:Int, b:Int) // binary operator 1 + 2 /// This also allows the binary-operator-ness of a func decl to be determined /// prior to type checking. bool isBinaryOperator() const; /// makeAccessor - Note that this function is an accessor for the given /// VarDecl or SubscriptDecl. void makeAccessor(AbstractStorageDecl *D, AccessorKind Kind) { assert(Kind != AccessorKind::NotAccessor && "Must specify an accessor kind"); AccessorDecl.setPointerAndInt(D, Kind); } AbstractStorageDecl *getAccessorStorageDecl() const { return AccessorDecl.getPointer(); } AccessorKind getAccessorKind() const { if (AccessorDecl.getPointer() == nullptr) return AccessorKind::NotAccessor; return AccessorDecl.getInt(); } bool isGetter() const { return getAccessorKind() == AccessorKind::IsGetter; } bool isSetter() const { return getAccessorKind() == AccessorKind::IsSetter; } /// isGetterOrSetter - Determine whether this is a getter or a setter vs. /// a normal function. bool isGetterOrSetter() const { return isGetter() || isSetter(); } bool isObservingAccessor() const { return getAccessorKind() == AccessorKind::IsDidSet || getAccessorKind() == AccessorKind::IsWillSet; } bool isAccessor() const { return getAccessorKind() != AccessorKind::NotAccessor; } /// Determine whether this function has a dynamic \c Self return /// type. bool hasDynamicSelf() const { return FuncDeclBits.HasDynamicSelf; } /// Set whether this function has a dynamic \c Self return or not. void setDynamicSelf(bool hasDynamicSelf) { FuncDeclBits.HasDynamicSelf = hasDynamicSelf; } /// Retrieve the dynamic \c Self type for this method, or a null type if /// this method does not have a dynamic \c Self return type. DynamicSelfType *getDynamicSelf() const; /// Retrieve the dynamic \c Self interface type for this method, or /// a null type if this method does not have a dynamic \c Self /// return type. DynamicSelfType *getDynamicSelfInterface() const; /// Given that this is an Objective-C method declaration, get its selector. ObjCSelector getObjCSelector() const; void getLocalCaptures(SmallVectorImpl &Result) const { return getCaptureInfo().getLocalCaptures(this, Result); } /// Get the supertype method this method overrides, if any. FuncDecl *getOverriddenDecl() const { return OverriddenOrDerivedForDecl.dyn_cast(); } void setOverriddenDecl(FuncDecl *over) { // A function cannot be an override if it is also a derived global decl // (since derived decls are at global scope). assert((!OverriddenOrDerivedForDecl || !OverriddenOrDerivedForDecl.is()) && "function cannot be both override and derived global"); OverriddenOrDerivedForDecl = over; over->setIsOverridden(); } /// Get the type this function was implicitly generated on the behalf of for /// a derived protocol conformance, if any. NominalTypeDecl *getDerivedForTypeDecl() const { return OverriddenOrDerivedForDecl.dyn_cast(); } void setDerivedForTypeDecl(NominalTypeDecl *ntd) { // A function cannot be an override if it is also a derived global decl // (since derived decls are at global scope). assert((!OverriddenOrDerivedForDecl || !OverriddenOrDerivedForDecl.is()) && "function cannot be both override and derived global"); OverriddenOrDerivedForDecl = ntd; } OperatorDecl *getOperatorDecl() const { return Operator; } void setOperatorDecl(OperatorDecl *o) { assert(isOperator() && "can't set an OperatorDecl for a non-operator"); Operator = o; } /// Returns true if a function declaration overrides a given /// method from its direct or indirect superclass. bool isOverridingDecl(const FuncDecl *method) const; static bool classof(const Decl *D) { return D->getKind() == DeclKind::Func; } static bool classof(const AbstractFunctionDecl *D) { return classof(static_cast(D)); } static bool classof(const DeclContext *DC) { if (auto fn = dyn_cast(DC)) return classof(fn); return false; } }; /// \brief This represents a 'case' declaration in an 'enum', which may declare /// one or more individual comma-separated EnumElementDecls. class EnumCaseDecl : public Decl { SourceLoc CaseLoc; /// The number of tail-allocated element pointers. unsigned NumElements; EnumCaseDecl(SourceLoc CaseLoc, ArrayRef Elements, DeclContext *DC) : Decl(DeclKind::EnumCase, DC), CaseLoc(CaseLoc), NumElements(Elements.size()) { memcpy(this + 1, Elements.begin(), NumElements * sizeof(EnumElementDecl*)); } EnumElementDecl * const *getElementsBuf() const { return reinterpret_cast(this + 1); } public: static EnumCaseDecl *create(SourceLoc CaseLoc, ArrayRef Elements, DeclContext *DC); /// Get the list of elements declared in this case. ArrayRef getElements() const { return {getElementsBuf(), NumElements}; } SourceLoc getLoc() const { return CaseLoc; } SourceRange getSourceRange() const; static bool classof(const Decl *D) { return D->getKind() == DeclKind::EnumCase; } }; /// \brief This represents a single case of an 'enum' declaration. /// /// For example, the X, Y, and Z in this enum: /// /// \code /// enum V { /// case X(Int), Y(Int) /// case Z /// } /// \endcode /// /// The type of an EnumElementDecl is always the EnumType for the containing /// enum. EnumElementDecls are represented in the AST as members of their /// parent EnumDecl, although syntactically they are subordinate to the /// EnumCaseDecl. class EnumElementDecl : public ValueDecl { /// This is the type specified with the enum element, for /// example 'Int' in 'case Y(Int)'. This is null if there is no type /// associated with this element, as in 'case Z' or in all elements of enum /// definitions. TypeLoc ArgumentType; SourceLoc EqualsLoc; /// The raw value literal for the enum element, or null. LiteralExpr *RawValueExpr; /// The type-checked raw value expression. Expr *TypeCheckedRawValueExpr = nullptr; public: EnumElementDecl(SourceLoc IdentifierLoc, Identifier Name, TypeLoc ArgumentType, SourceLoc EqualsLoc, LiteralExpr *RawValueExpr, DeclContext *DC) : ValueDecl(DeclKind::EnumElement, DC, Name, IdentifierLoc), ArgumentType(ArgumentType), EqualsLoc(EqualsLoc), RawValueExpr(RawValueExpr) { EnumElementDeclBits.Recursiveness = static_cast(ElementRecursiveness::NotRecursive); } bool hasArgumentType() const { return !ArgumentType.getType().isNull(); } Type getArgumentType() const { return ArgumentType.getType(); } Type getArgumentInterfaceType() const; TypeLoc &getArgumentTypeLoc() { return ArgumentType; } const TypeLoc &getArgumentTypeLoc() const { return ArgumentType; } bool hasRawValueExpr() const { return RawValueExpr; } LiteralExpr *getRawValueExpr() const { return RawValueExpr; } void setRawValueExpr(LiteralExpr *e) { RawValueExpr = e; } Expr *getTypeCheckedRawValueExpr() const { return TypeCheckedRawValueExpr; } void setTypeCheckedRawValueExpr(Expr *e) { TypeCheckedRawValueExpr = e; } /// Return the containing EnumDecl. EnumDecl *getParentEnum() const { return cast(getDeclContext()); } SourceLoc getStartLoc() const { return getNameLoc(); } SourceRange getSourceRange() const; ElementRecursiveness getRecursiveness() const { return static_cast(EnumElementDeclBits.Recursiveness); } void setRecursiveness(ElementRecursiveness recursiveness) { EnumElementDeclBits.Recursiveness = static_cast(recursiveness); } static bool classof(const Decl *D) { return D->getKind() == DeclKind::EnumElement; } }; inline SourceRange EnumCaseDecl::getSourceRange() const { auto subRange = getElements().back()->getSourceRange(); if (subRange.isValid()) return {CaseLoc, subRange.End}; return {}; } /// Describes the kind of initializer. enum class CtorInitializerKind { /// A designated initializer is an initializer responsible for initializing /// the stored properties of the current class and chaining to a superclass's /// designated initializer (for non-root classes). /// /// Designated initializers are never inherited. Designated, /// A convenience initializer is an initializer that initializes a complete /// object by delegating to another initializer (eventually reaching a /// designated initializer). /// /// A convenience initializer is written with a return type of "Self" in /// source code. /// /// Convenience initializers are inherited into subclasses that override /// all of their superclass's designated initializers. Convenience, /// A convenience factory initializer is a convenience initializer introduced /// by an imported Objective-C factory method. /// /// Convenience factory initializers cannot be expressed directly in /// Swift; rather, they are produced by the Clang importer when importing /// an instancetype factory method from Objective-C. ConvenienceFactory, /// A factory initializer is an initializer that is neither designated nor /// convenience: it can be used to create an object of the given type, but /// cannot be chained to via "super.init" nor is it inherited. /// /// A factory initializer is written with a return type of the class name /// itself. FIXME: However, this is only a presentation form, and at present /// the only factory initializers are produced by importing an Objective-C /// factory method that does not return instancetype. /// /// FIXME: Arguably, structs and enums only have factory initializers, and /// using designated initializers for them is a misnomer. Factory }; /// ConstructorDecl - Declares a constructor for a type. For example: /// /// \code /// struct X { /// var x : Int /// init(i : Int) { /// x = i /// } /// } /// \endcode class ConstructorDecl : public AbstractFunctionDecl { friend class AbstractFunctionDecl; /// The failability of this initializer, which is an OptionalTypeKind. unsigned Failability : 2; /// The location of the '!' or '?' for a failable initializer. SourceLoc FailabilityLoc; Pattern *BodyParams[2]; /// The type of the initializing constructor. Type InitializerType; /// The interface type of the initializing constructor. Type InitializerInterfaceType; /// The typechecked call to super.init expression, which needs to be /// inserted at the end of the initializer by SILGen. Expr *CallToSuperInit = nullptr; /// The constructor this overrides, which only makes sense when /// both the overriding and the overridden constructors are abstract. ConstructorDecl *OverriddenDecl = nullptr; public: ConstructorDecl(DeclName Name, SourceLoc ConstructorLoc, OptionalTypeKind Failability, SourceLoc FailabilityLoc, Pattern *SelfBodyParam, Pattern *BodyParams, GenericParamList *GenericParams, DeclContext *Parent); void setBodyParams(Pattern *selfPattern, Pattern *bodyParams); SourceLoc getConstructorLoc() const { return getNameLoc(); } SourceLoc getStartLoc() const { return getConstructorLoc(); } SourceRange getSourceRange() const; /// getArgumentType - get the type of the argument tuple Type getArgumentType() const; /// \brief Get the type of the constructed object. Type getResultType() const; /// Given that this is an Objective-C method declaration, get its selector. ObjCSelector getObjCSelector() const; /// Get the type of the initializing constructor. Type getInitializerType() const { return InitializerType; } void setInitializerType(Type t) { InitializerType = t; } /// Get the interface type of the initializing constructor. Type getInitializerInterfaceType(); void setInitializerInterfaceType(Type t); /// Get the typechecked call to super.init expression, which needs to be /// inserted at the end of the initializer by SILGen. Expr *getSuperInitCall() { return CallToSuperInit; } void setSuperInitCall(Expr *CallExpr) { CallToSuperInit = CallExpr; } /// Specifies the kind of initialization call performed within the body /// of the constructor, e.g., self.init or super.init. enum class BodyInitKind { /// There are no calls to self.init or super.init. None, /// There is a call to self.init, which delegates to another (peer) /// initializer. Delegating, /// There is a call to super.init, which chains to a superclass initializer. Chained, /// There are no calls to self.init or super.init explicitly in the body of /// the constructor, but a 'super.init' call will be implicitly added /// by semantic analysis. ImplicitChained }; /// Determine whether the body of this constructor contains any delegating /// or superclass initializations (\c self.init or \c super.init, /// respectively) within its body. /// /// \param diags If non-null, this check will ensure that the constructor /// body is consistent in its use of delegation vs. chaining and emit any /// diagnostics through the given diagnostic engine. /// /// \param init If non-null and there is an explicit \c self.init or /// \c super.init within the body, will be set to point at that /// initializer. BodyInitKind getDelegatingOrChainedInitKind(DiagnosticEngine *diags, ApplyExpr **init = nullptr); /// Whether this constructor is required. bool isRequired() const { return getAttrs().hasAttribute(); } /// Determine the kind of initializer this is. CtorInitializerKind getInitKind() const { return static_cast(ConstructorDeclBits.InitKind); } /// Set whether this is a convenience initializer. void setInitKind(CtorInitializerKind kind) { ConstructorDeclBits.InitKind = static_cast(kind); } /// Whether this is a designated initializer. bool isDesignatedInit() const { return getInitKind() == CtorInitializerKind::Designated; } /// Whether this is a convenience initializer. bool isConvenienceInit() const { return getInitKind() == CtorInitializerKind::Convenience || getInitKind() == CtorInitializerKind::ConvenienceFactory; } /// Whether this is a factory initializer. bool isFactoryInit() const { switch (getInitKind()) { case CtorInitializerKind::Designated: case CtorInitializerKind::Convenience: return false; case CtorInitializerKind::Factory: case CtorInitializerKind::ConvenienceFactory: return true; } llvm_unreachable("bad CtorInitializerKind"); } /// Determine whether this initializer is inheritable. bool isInheritable() const { switch (getInitKind()) { case CtorInitializerKind::Designated: case CtorInitializerKind::Factory: return false; case CtorInitializerKind::Convenience: case CtorInitializerKind::ConvenienceFactory: return true; } llvm_unreachable("bad CtorInitializerKind"); } /// Determine the failability of the initializer. OptionalTypeKind getFailability() const { return static_cast(Failability); } /// Retrieve the location of the '!' or '?' in a failable initializer. SourceLoc getFailabilityLoc() const { return FailabilityLoc; } /// Whether the implementation of this method is a stub that traps at runtime. bool hasStubImplementation() const { return ConstructorDeclBits.HasStubImplementation; } /// Set whether the implementation of this method is a stub that /// traps at runtime. void setStubImplementation(bool stub) { ConstructorDeclBits.HasStubImplementation = stub; } ConstructorDecl *getOverriddenDecl() const { return OverriddenDecl; } void setOverriddenDecl(ConstructorDecl *over) { OverriddenDecl = over; over->setIsOverridden(); } static bool classof(const Decl *D) { return D->getKind() == DeclKind::Constructor; } static bool classof(const AbstractFunctionDecl *D) { return classof(static_cast(D)); } static bool classof(const DeclContext *DC) { if (auto fn = dyn_cast(DC)) return classof(fn); return false; } }; /// DestructorDecl - Declares a destructor for a type. For example: /// /// \code /// struct X { /// var fd : Int /// deinit { /// close(fd) /// } /// } /// \endcode class DestructorDecl : public AbstractFunctionDecl { friend class AbstractFunctionDecl; Pattern *SelfPattern; public: DestructorDecl(Identifier NameHack, SourceLoc DestructorLoc, Pattern *SelfPattern, DeclContext *Parent); void setSelfPattern(Pattern *selfPattern); SourceLoc getDestructorLoc() const { return getNameLoc(); } SourceLoc getStartLoc() const { return getDestructorLoc(); } SourceRange getSourceRange() const; /// Retrieve the Objective-C selector associated with the destructor. /// /// This is always "dealloc". ObjCSelector getObjCSelector() const; static bool classof(const Decl *D) { return D->getKind() == DeclKind::Destructor; } static bool classof(const AbstractFunctionDecl *D) { return classof(static_cast(D)); } static bool classof(const DeclContext *DC) { if (auto fn = dyn_cast(DC)) return classof(fn); return false; } }; /// Abstract base class of operator declarations. class OperatorDecl : public Decl { SourceLoc OperatorLoc, NameLoc, LBraceLoc, RBraceLoc; Identifier name; public: OperatorDecl(DeclKind kind, DeclContext *DC, SourceLoc OperatorLoc, Identifier Name, SourceLoc NameLoc, SourceLoc LBraceLoc, SourceLoc RBraceLoc) : Decl(kind, DC), OperatorLoc(OperatorLoc), NameLoc(NameLoc), LBraceLoc(LBraceLoc), RBraceLoc(RBraceLoc), name(Name) {} SourceLoc getLoc() const { return NameLoc; } SourceRange getSourceRange() const { return {OperatorLoc, RBraceLoc}; } SourceLoc getOperatorLoc() const { return OperatorLoc; } SourceLoc getLBraceLoc() const { return LBraceLoc; } SourceLoc getRBraceLoc() const { return RBraceLoc; } Identifier getName() const { return name; } static bool classof(const Decl *D) { return D->getKind() >= DeclKind::First_OperatorDecl && D->getKind() <= DeclKind::Last_OperatorDecl; } }; /// Declares the behavior of an infix operator. For example: /// /// \code /// infix operator /+/ { /// associativity left /// precedence 123 /// } /// \endcode class InfixOperatorDecl : public OperatorDecl { SourceLoc AssociativityLoc, AssociativityValueLoc, PrecedenceLoc, PrecedenceValueLoc, AssignmentLoc; public: InfixOperatorDecl(DeclContext *DC, SourceLoc OperatorLoc, Identifier Name, SourceLoc NameLoc, SourceLoc LBraceLoc, bool IsAssocImplicit, SourceLoc AssociativityLoc, SourceLoc AssociativityValueLoc, bool IsPrecedenceImplicit, SourceLoc PrecedenceLoc, SourceLoc PrecedenceValueLoc, bool IsAssignmentImplicit, SourceLoc AssignmentLoc, SourceLoc RBraceLoc, InfixData InfixData) : OperatorDecl(DeclKind::InfixOperator, DC, OperatorLoc, Name, NameLoc, LBraceLoc, RBraceLoc), AssociativityLoc(AssociativityLoc), AssociativityValueLoc(AssociativityValueLoc), PrecedenceLoc(PrecedenceLoc), PrecedenceValueLoc(PrecedenceValueLoc), AssignmentLoc(AssignmentLoc) { if (!InfixData.isValid()) { setInvalid(); } else { assert((AssociativityLoc.isInvalid() || !IsAssocImplicit) && "Associativity cannot be implicit if it came from user source"); assert((PrecedenceLoc.isInvalid() || !IsPrecedenceImplicit) && "Precedence cannot be implicit if it came from user source"); InfixOperatorDeclBits.Precedence = InfixData.getPrecedence(); InfixOperatorDeclBits.Associativity = static_cast(InfixData.getAssociativity()); InfixOperatorDeclBits.Assignment = unsigned(InfixData.isAssignment()); InfixOperatorDeclBits.IsPrecedenceImplicit = IsPrecedenceImplicit; InfixOperatorDeclBits.IsAssocImplicit = IsAssocImplicit; InfixOperatorDeclBits.IsAssignmentImplicit = IsAssignmentImplicit; } } SourceLoc getAssociativityLoc() const { return AssociativityLoc; } SourceLoc getAssociativityValueLoc() const { return AssociativityValueLoc; } SourceLoc getPrecedenceLoc() const { return PrecedenceLoc; } SourceLoc getPrecedenceValueLoc() const { return PrecedenceValueLoc; } SourceLoc getAssignmentLoc() const { return AssignmentLoc; } unsigned getPrecedence() const { return InfixOperatorDeclBits.Precedence; } Associativity getAssociativity() const { return Associativity(InfixOperatorDeclBits.Associativity); } bool isAssignment() const { return InfixOperatorDeclBits.Assignment; } InfixData getInfixData() const { if (isInvalid()) return InfixData(); return InfixData(getPrecedence(), getAssociativity(), isAssignment()); } bool isAssociativityImplicit() const { return InfixOperatorDeclBits.IsAssocImplicit; } bool isPrecedenceImplicit() const { return InfixOperatorDeclBits.IsPrecedenceImplicit; } bool isAssignmentImplicit() const { return InfixOperatorDeclBits.IsAssignmentImplicit; } /// True if this decl's attributes conflict with those declared by another /// operator. bool conflictsWith(InfixOperatorDecl *other) { return getInfixData() != other->getInfixData(); } static bool classof(const Decl *D) { return D->getKind() == DeclKind::InfixOperator; } }; /// Declares the behavior of a prefix operator. For example: /// /// \code /// prefix operator /+/ {} /// \endcode class PrefixOperatorDecl : public OperatorDecl { public: PrefixOperatorDecl(DeclContext *DC, SourceLoc OperatorLoc, Identifier Name, SourceLoc NameLoc, SourceLoc LBraceLoc, SourceLoc RBraceLoc) : OperatorDecl(DeclKind::PrefixOperator, DC, OperatorLoc, Name, NameLoc, LBraceLoc, RBraceLoc) {} /// True if this decl's attributes conflict with those declared by another /// PrefixOperatorDecl. bool conflictsWith(PrefixOperatorDecl *other) { return false; } static bool classof(const Decl *D) { return D->getKind() == DeclKind::PrefixOperator; } }; /// Declares the behavior of a postfix operator. For example: /// /// \code /// postfix operator /+/ {} /// \endcode class PostfixOperatorDecl : public OperatorDecl { public: PostfixOperatorDecl(DeclContext *DC, SourceLoc OperatorLoc, Identifier Name, SourceLoc NameLoc, SourceLoc LBraceLoc, SourceLoc RBraceLoc) : OperatorDecl(DeclKind::PostfixOperator, DC, OperatorLoc, Name, NameLoc, LBraceLoc, RBraceLoc) {} /// True if this decl's attributes conflict with those declared by another /// PostfixOperatorDecl. bool conflictsWith(PostfixOperatorDecl *other) { return false; } static bool classof(const Decl *D) { return D->getKind() == DeclKind::PostfixOperator; } }; inline bool ValueDecl::isSettable(DeclContext *UseDC) const { if (auto vd = dyn_cast(this)) { return vd->isSettable(UseDC); } else if (auto sd = dyn_cast(this)) { return sd->isSettable(); } else return false; } inline Optional NominalTypeDecl::ToStoredProperty::operator()(Decl *decl) const { if (auto var = dyn_cast(decl)) { if (!var->isStatic() && var->hasStorage()) return var; } return None; } inline void AbstractStorageDecl::overwriteSetterAccessibility(Accessibility accessLevel) { GetSetInfo.setInt(accessLevel); if (auto setter = getSetter()) setter->overwriteAccessibility(accessLevel); if (auto materializeForSet = getMaterializeForSetFunc()) materializeForSet->overwriteAccessibility(accessLevel); } inline MutableArrayRef AbstractFunctionDecl::getBodyParamBuffer() { unsigned NumPatterns = AbstractFunctionDeclBits.NumParamPatterns; Pattern **Ptr; switch (getKind()) { default: llvm_unreachable("Unknown AbstractFunctionDecl!"); case DeclKind::Constructor: Ptr = cast(this)->BodyParams; break; case DeclKind::Destructor: Ptr = &cast(this)->SelfPattern; break; case DeclKind::Func: // Body patterns are tail allocated. Ptr = reinterpret_cast(cast(this) + 1); break; } return MutableArrayRef(Ptr, NumPatterns); } inline DeclIterator &DeclIterator::operator++() { Current = Current->NextDecl; return *this; } } // end namespace swift #endif