//===--- Decl.h - Swift Language Declaration ASTs ---------------*- C++ -*-===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://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/AccessScope.h" #include "swift/AST/Attr.h" #include "swift/AST/CaptureInfo.h" #include "swift/AST/ClangNode.h" #include "swift/AST/ConcreteDeclRef.h" #include "swift/AST/DefaultArgumentKind.h" #include "swift/AST/DiagnosticConsumer.h" #include "swift/AST/GenericParamKey.h" #include "swift/AST/IfConfigClause.h" #include "swift/AST/LayoutConstraint.h" #include "swift/AST/TypeAlignments.h" #include "swift/AST/TypeWalker.h" #include "swift/AST/Witness.h" #include "swift/Basic/Compiler.h" #include "swift/Basic/InlineBitfield.h" #include "swift/Basic/OptionalEnum.h" #include "swift/Basic/Range.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" #include "llvm/Support/TrailingObjects.h" namespace swift { enum class AccessSemantics : unsigned char; class AccessorDecl; class ApplyExpr; class GenericEnvironment; class ArchetypeType; class ASTContext; struct ASTNode; class ASTPrinter; class ASTWalker; class ConstructorDecl; class DestructorDecl; class DiagnosticEngine; class DynamicSelfType; class Type; class Expr; class DeclRefExpr; class ForeignErrorConvention; class LiteralExpr; class BraceStmt; class DeclAttributes; class GenericContext; class GenericSignature; class GenericTypeParamDecl; class GenericTypeParamType; class LazyResolver; class ModuleDecl; class NameAliasType; class EnumCaseDecl; class EnumElementDecl; class ParameterList; class ParameterTypeFlags; class Pattern; struct PrintOptions; class ProtocolDecl; class ProtocolType; struct RawComment; enum class ResilienceExpansion : unsigned; class TypeAliasDecl; class Stmt; class SubscriptDecl; class UnboundGenericType; class ValueDecl; class VarDecl; enum class DeclKind : uint8_t { #define DECL(Id, Parent) Id, #define LAST_DECL(Id) Last_Decl = Id, #define DECL_RANGE(Id, FirstId, LastId) \ First_##Id##Decl = FirstId, Last_##Id##Decl = LastId, #include "swift/AST/DeclNodes.def" }; enum : unsigned { NumDeclKindBits = countBitsUsed(static_cast(DeclKind::Last_Decl)) }; /// 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, PoundDiagnostic, PatternBinding, Var, Param, Let, StaticVar, StaticLet, ClassVar, ClassLet, InfixOperator, PrefixOperator, PostfixOperator, PrecedenceGroup, 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, Module, MissingMember, }; /// 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 whether 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, }; /// Keeps track of whether an enum has cases that have associated values. enum class AssociatedValueCheck { /// We have not yet checked. Unchecked, /// The enum contains no cases or all cases contain no associated values. NoAssociatedValues, /// The enum contains at least one case with associated values. HasAssociatedValues, }; /// 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 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; /// Whether this signature is part of a protocol extension. bool InProtocolExtension = false; }; /// Determine whether two overload signatures conflict. bool conflicting(const OverloadSignature& sig1, const OverloadSignature& sig2, bool skipProtocolExtensionCheck = false); /// Decl - Base class for all declarations in Swift. class alignas(1 << DeclAlignInBits) Decl { protected: union { uint64_t OpaqueBits; SWIFT_INLINE_BITFIELD_BASE(Decl, bitmax(NumDeclKindBits,8)+1+1+1+1+1+1+1, Kind : bitmax(NumDeclKindBits,8), /// \brief Whether this declaration is invalid. Invalid : 1, /// \brief Whether this declaration was implicitly created, e.g., /// an implicit constructor in a struct. Implicit : 1, /// \brief Whether this declaration was mapped directly from a Clang AST. /// /// Use getClangNode() to retrieve the corresponding Clang AST. FromClang : 1, /// \brief Whether we've already performed early attribute validation. /// FIXME: This is ugly. EarlyAttrValidation : 1, /// \brief Whether this declaration is currently being validated. BeingValidated : 1, /// \brief Whether we have started validating the declaration; this *isn't* /// reset after finishing it. ValidationStarted : 1, /// \brief Whether this declaration was added to the surrounding /// DeclContext of an active #if config clause. EscapedFromIfConfig : 1 ); SWIFT_INLINE_BITFIELD_FULL(PatternBindingDecl, Decl, 1+2+16, /// \brief Whether this pattern binding declares static variables. IsStatic : 1, /// \brief Whether 'static' or 'class' was used. StaticSpelling : 2, : NumPadBits, /// \brief The number of pattern binding declarations. NumPatternEntries : 16 ); SWIFT_INLINE_BITFIELD_FULL(EnumCaseDecl, Decl, 32, : NumPadBits, /// The number of tail-allocated element pointers. NumElements : 32 ); SWIFT_INLINE_BITFIELD(ValueDecl, Decl, 1+1+1, AlreadyInLookupTable : 1, /// Whether we have already checked whether this declaration is a /// redeclaration. CheckedRedeclaration : 1, /// Whether the decl can be accessed by swift users; for instance, /// a.storage for lazy var a is a decl that cannot be accessed. IsUserAccessible : 1 ); SWIFT_INLINE_BITFIELD(AbstractStorageDecl, ValueDecl, 1+1+1+4, /// Whether we are overridden later Overridden : 1, /// Whether the getter is mutating. IsGetterMutating : 1, /// Whether the setter is mutating. IsSetterMutating : 1, /// The storage kind. StorageKind : 4 ); SWIFT_INLINE_BITFIELD(VarDecl, AbstractStorageDecl, 1+2+1+1+1, /// \brief Whether this property is a type property (currently unfortunately /// called 'static'). IsStatic : 1, /// \brief The specifier associated with this variable or parameter. This /// determines the storage semantics of the value e.g. mutability. Specifier : 2, /// \brief Whether this declaration was an element of a capture list. IsCaptureList : 1, /// \brief Whether this vardecl has an initial value bound to it in a way /// that isn't represented in the AST with an initializer in the pattern /// binding. This happens in cases like "for i in ...", switch cases, etc. HasNonPatternBindingInit : 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. IsDebuggerVar : 1 ); SWIFT_INLINE_BITFIELD(ParamDecl, VarDecl, 1 + NumDefaultArgumentKindBits, /// True if the type is implicitly specified in the source, but this has an /// apparently valid typeRepr. This is used in accessors, which look like: /// set (value) { /// but need to get the typeRepr from the property as a whole so Sema can /// resolve the type. IsTypeLocImplicit : 1, /// Information about a symbolic default argument, like #file. defaultArgumentKind : NumDefaultArgumentKindBits ); SWIFT_INLINE_BITFIELD(EnumElementDecl, ValueDecl, 3, /// \brief Whether or not this element has an associated value. HasArgumentType : 1, /// \brief Whether or not this element directly or indirectly references /// the enum type. Recursiveness : 2 ); SWIFT_INLINE_BITFIELD(AbstractFunctionDecl, ValueDecl, 3+8+5+1+1+1+1+1, /// \see AbstractFunctionDecl::BodyKind BodyKind : 3, /// Import as member status. IAMStatus : 8, /// Number of curried parameter lists. NumParameterLists : 5, /// Whether we are overridden later. Overridden : 1, /// Whether the function body throws. Throws : 1, /// Whether this function requires a new vtable entry. NeedsNewVTableEntry : 1, /// Whether NeedsNewVTableEntry is valid. HasComputedNeedsNewVTableEntry : 1, /// The ResilienceExpansion to use for default arguments. DefaultArgumentResilienceExpansion : 1 ); SWIFT_INLINE_BITFIELD(FuncDecl, AbstractFunctionDecl, 1+2+1+1+2, /// Whether this function is a 'static' method. IsStatic : 1, /// \brief Whether 'static' or 'class' was used. StaticSpelling : 2, /// Whether we are statically dispatched even if overridable ForcedStaticDispatch : 1, /// Whether this function has a dynamic Self return type. HasDynamicSelf : 1, /// Backing bits for 'self' access kind. SelfAccess : 2 ); SWIFT_INLINE_BITFIELD(AccessorDecl, FuncDecl, 3+3, /// The kind of accessor this is. AccessorKind : 3, /// The kind of addressor this is. AddressorKind : 3 ); SWIFT_INLINE_BITFIELD(ConstructorDecl, AbstractFunctionDecl, 3+2+2+1, /// 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. ComputedBodyInitKind : 3, /// The kind of initializer we have. InitKind : 2, /// The failability of this initializer, which is an OptionalTypeKind. Failability : 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. HasStubImplementation : 1 ); SWIFT_INLINE_BITFIELD(TypeDecl, ValueDecl, 1, /// Whether we have already checked the inheritance clause. /// /// FIXME: Is this too fine-grained? CheckedInheritanceClause : 1 ); SWIFT_INLINE_BITFIELD_EMPTY(AbstractTypeParamDecl, TypeDecl); SWIFT_INLINE_BITFIELD_FULL(GenericTypeParamDecl, AbstractTypeParamDecl, 16+16, : NumPadBits, Depth : 16, Index : 16 ); SWIFT_INLINE_BITFIELD_EMPTY(GenericTypeDecl, TypeDecl); SWIFT_INLINE_BITFIELD(TypeAliasDecl, GenericTypeDecl, 1, /// Whether the typealias forwards perfectly to its underlying type. IsCompatibilityAlias : 1 ); SWIFT_INLINE_BITFIELD(NominalTypeDecl, GenericTypeDecl, 1+1+1, /// Whether we have already added implicitly-defined initializers /// to this declaration. AddedImplicitInitializers : 1, /// Whether there is are lazily-loaded conformances for this nominal type. HasLazyConformances : 1, /// Whether we have already validated all members of the type that /// affect layout. HasValidatedLayout : 1 ); SWIFT_INLINE_BITFIELD_FULL(ProtocolDecl, NominalTypeDecl, 1+1+1+1+1+1+1+2+8+16, /// Whether the \c RequiresClass bit is valid. RequiresClassValid : 1, /// Whether this is a class-bounded protocol. RequiresClass : 1, /// Whether the \c ExistentialConformsToSelf bit is valid. ExistentialConformsToSelfValid : 1, /// Whether the existential of this protocol conforms to itself. ExistentialConformsToSelf : 1, /// Whether the \c ExistentialTypeSupported bit is valid. ExistentialTypeSupportedValid : 1, /// Whether the existential of this protocol can be represented. ExistentialTypeSupported : 1, /// True if the protocol has requirements that cannot be satisfied (e.g. /// because they could not be imported from Objective-C). HasMissingRequirements : 1, /// The stage of the circularity check for this protocol. Circularity : 2, : NumPadBits, /// If this is a compiler-known protocol, this will be a KnownProtocolKind /// value, plus one. Otherwise, it will be 0. KnownProtocol : 8, // '8' for speed. This only needs 6. /// The number of requirements in the requirement signature. NumRequirementsInSignature : 16 ); SWIFT_INLINE_BITFIELD(ClassDecl, NominalTypeDecl, 1+2+2+2+1+3+1+1, /// Whether this class requires all of its instance variables to /// have in-class initializers. RequiresStoredPropertyInits : 1, /// The stage of the inheritance circularity check for this class. Circularity : 2, /// Whether this class inherits its superclass's convenience /// initializers. /// /// This is a value of \c StoredInheritsSuperclassInits. InheritsSuperclassInits : 2, /// \see ClassDecl::ForeignKind RawForeignKind : 2, /// 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. HasDestructorDecl : 1, /// Whether the class has @objc ancestry. ObjCKind : 3, HasMissingDesignatedInitializers : 1, HasMissingVTableEntries : 1 ); SWIFT_INLINE_BITFIELD(StructDecl, NominalTypeDecl, 1, /// True if this struct has storage for fields that aren't accessible in /// Swift. HasUnreferenceableStorage : 1 ); SWIFT_INLINE_BITFIELD(EnumDecl, NominalTypeDecl, 2+2, /// The stage of the raw type circularity check for this class. Circularity : 2, /// True if the enum has cases and at least one case has associated values. HasAssociatedValues : 2 ); SWIFT_INLINE_BITFIELD(PrecedenceGroupDecl, Decl, 1+2, /// Is this an assignment operator? IsAssignment : 1, /// The group's associativity. A value of the Associativity enum. Associativity : 2 ); SWIFT_INLINE_BITFIELD(AssociatedTypeDecl, TypeDecl, 1+1, ComputedOverridden : 1, HasOverridden : 1 ); SWIFT_INLINE_BITFIELD(ImportDecl, Decl, 3+8, ImportKind : 3, /// The number of elements in this path. NumPathElements : 8 ); SWIFT_INLINE_BITFIELD(ExtensionDecl, Decl, 3+1+1, /// An encoding of the default and maximum access level for this extension. /// /// This is encoded as (1 << (maxAccess-1)) | (1 << (defaultAccess-1)), /// which works because the maximum is always greater than or equal to the /// default, and 'private' is never used. 0 represents an uncomputed value. DefaultAndMaxAccessLevel : 3, /// Whether we have already checked the inheritance clause. /// /// FIXME: Is this too fine-grained? CheckedInheritanceClause : 1, /// Whether there is are lazily-loaded conformances for this extension. HasLazyConformances : 1 ); SWIFT_INLINE_BITFIELD(IfConfigDecl, Decl, 1, /// Whether this decl is missing its closing '#endif'. HadMissingEnd : 1 ); SWIFT_INLINE_BITFIELD(PoundDiagnosticDecl, Decl, 1+1, /// `true` if the diagnostic is an error, `false` if it's a warning. IsError : 1, /// Whether this diagnostic has already been emitted. HasBeenEmitted : 1 ); SWIFT_INLINE_BITFIELD(MissingMemberDecl, Decl, 1+2, NumberOfFieldOffsetVectorEntries : 1, NumberOfVTableEntries : 2 ); } Bits; // 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: llvm::PointerUnion Context; Decl(const Decl&) = delete; void operator=(const Decl&) = delete; protected: Decl(DeclKind kind, llvm::PointerUnion context) : Context(context) { Bits.OpaqueBits = 0; Bits.Decl.Kind = unsigned(kind); Bits.Decl.Invalid = false; Bits.Decl.Implicit = false; Bits.Decl.FromClang = false; Bits.Decl.EarlyAttrValidation = false; Bits.Decl.BeingValidated = false; Bits.Decl.ValidationStarted = false; Bits.Decl.EscapedFromIfConfig = false; } /// \brief Get the Clang node associated with this declaration. ClangNode getClangNodeImpl() const; /// \brief Set the Clang node associated with this declaration. void setClangNode(ClangNode Node); void updateClangNode(ClangNode node) { assert(hasClangNode()); setClangNode(node); } friend class ClangImporter; DeclContext *getDeclContextForModule() const; public: DeclKind getKind() const { return DeclKind(Bits.Decl.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); /// Whether swift users should be able to access this decl. For instance, /// var a.storage for lazy var a is an inaccessible decl. An inaccessible decl /// has to be implicit; but an implicit decl does not have to be inaccessible, /// for instance, self. bool isUserAccessible() const; /// Determine if the decl can have a comment. If false, a comment will /// not be serialized. bool canHaveComment() const; DeclContext *getDeclContext() const { if (auto dc = Context.dyn_cast()) return dc; return getDeclContextForModule(); } 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() const; /// \brief Retrieve the module in which this declaration resides. ModuleDecl *getModuleContext() const; /// getASTContext - Return the ASTContext that this decl lives in. ASTContext &getASTContext() const { if (auto dc = Context.dyn_cast()) return dc->getASTContext(); return *Context.get(); } 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; /// Returns the source range of the declaration including its attributes. SourceRange getSourceRangeIncludingAttrs() const; SourceLoc TrailingSemiLoc; LLVM_ATTRIBUTE_DEPRECATED( void dump() const LLVM_ATTRIBUTE_USED, "only for use within the debugger"); LLVM_ATTRIBUTE_DEPRECATED( void dump(const char *filename) 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 Return whether this declaration has been determined invalid. bool isInvalid() const { return Bits.Decl.Invalid; } /// \brief Mark this declaration invalid. void setInvalid(bool isInvalid = true) { Bits.Decl.Invalid = isInvalid; } /// \brief Determine whether this declaration was implicitly generated by the /// compiler (rather than explicitly written in source code). bool isImplicit() const { return Bits.Decl.Implicit; } /// \brief Mark this declaration as implicit. void setImplicit(bool implicit = true) { Bits.Decl.Implicit = implicit; } /// Whether we have already done early attribute validation. bool didEarlyAttrValidation() const { return Bits.Decl.EarlyAttrValidation; } /// Set whether we've performed early attribute validation. void setEarlyAttrValidation(bool validated = true) { Bits.Decl.EarlyAttrValidation = validated; } /// Whether the declaration has a valid interface type and /// generic signature. bool isBeingValidated() const { return Bits.Decl.BeingValidated; } /// Toggle whether or not the declaration is being validated. void setIsBeingValidated(bool ibv = true) { assert(Bits.Decl.BeingValidated != ibv); Bits.Decl.BeingValidated = ibv; if (ibv) { Bits.Decl.ValidationStarted = true; } } bool hasValidationStarted() const { return Bits.Decl.ValidationStarted; } /// Manually indicate that validation has started for the declaration. /// /// This is implied by setIsBeingValidated(true) (i.e. starting validation) /// and so rarely needs to be called directly. void setValidationStarted() { Bits.Decl.ValidationStarted = true; } bool escapedFromIfConfig() const { return Bits.Decl.EscapedFromIfConfig; } void setEscapedFromIfConfig(bool Escaped) { Bits.Decl.EscapedFromIfConfig = Escaped; } /// \returns the unparsed comment attached to this declaration. RawComment getRawComment() const; Optional getGroupName() const; Optional getSourceFileName() const; Optional getSourceOrder() 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 Bits.Decl.FromClang; } /// \brief Retrieve the Clang AST node from which this declaration was /// synthesized, if any. ClangNode getClangNode() const { if (!Bits.Decl.FromClang) return ClangNode(); return getClangNodeImpl(); } /// \brief Retrieve the Clang declaration from which this declaration was /// synthesized, if any. const clang::Decl *getClangDecl() const { if (!Bits.Decl.FromClang) return nullptr; return getClangNodeImpl().getAsDecl(); } /// \brief Retrieve the Clang macro from which this declaration was /// synthesized, if any. const clang::MacroInfo *getClangMacro() { if (!Bits.Decl.FromClang) return nullptr; return getClangNodeImpl().getAsMacro(); } /// \brief Return the GenericContext if the Decl has one. const GenericContext *getAsGenericContext() const; bool isPrivateStdlibDecl(bool treatNonBuiltinProtocolsAsPublic = true) const; /// Whether this declaration is weak-imported. bool isWeakImported(ModuleDecl *fromModule) const; /// Returns true if the nature of this declaration allows overrides. /// Note that this does not consider whether it is final or whether /// the class it's on is final. /// /// If this returns true, the decl can be safely casted to ValueDecl. bool isPotentiallyOverridable() const; // Make vanilla new/delete illegal for Decls. void *operator new(size_t Bytes) = delete; void operator delete(void *Data) SWIFT_DELETE_OPERATOR_DELETED; // Only allow allocation of Decls using the allocator in ASTContext // or by doing a placement new. void *operator new(size_t Bytes, const ASTContext &C, unsigned Alignment = alignof(Decl)); void *operator new(size_t Bytes, void *Mem) { assert(Mem); return Mem; } }; /// \brief Allocates memory for a Decl with the given \p baseSize. If necessary, /// it includes additional space immediately preceding the Decl for a ClangNode. /// \note \p baseSize does not need to include space for a ClangNode if /// requested -- the necessary space will be added automatically. template void *allocateMemoryForDecl(AllocatorTy &allocator, size_t baseSize, bool includeSpaceForClangNode) { static_assert(alignof(DeclTy) >= sizeof(void *), "A pointer must fit in the alignment of the DeclTy!"); size_t size = baseSize; if (includeSpaceForClangNode) size += alignof(DeclTy); void *mem = allocator.Allocate(size, alignof(DeclTy)); if (includeSpaceForClangNode) mem = reinterpret_cast(mem) + alignof(DeclTy); return mem; } enum class RequirementReprKind : unsigned { /// A type bound T : P, where T is a type that depends on a generic /// parameter and P is some type that should bound T, either as a concrete /// supertype or a protocol to which T must conform. TypeConstraint, /// A same-type requirement T == U, where T and U are types that shall be /// equivalent. SameType, /// A layout bound T : L, where T is a type that depends on a generic /// parameter and L is some layout specification that should bound T. LayoutConstraint, // Note: there is code that packs this enum in a 2-bit bitfield. Audit users // when adding enumerators. }; /// \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. /// /// \c GenericParamList assumes these are POD-like. class RequirementRepr { SourceLoc SeparatorLoc; RequirementReprKind Kind : 2; bool Invalid : 1; TypeLoc FirstType; /// The second element represents the right-hand side of the constraint. /// It can be e.g. a type or a layout constraint. union { TypeLoc SecondType; LayoutConstraintLoc SecondLayout; }; /// Set during deserialization; used to print out the requirements accurately /// for the generated interface. StringRef AsWrittenString; RequirementRepr(SourceLoc SeparatorLoc, RequirementReprKind Kind, TypeLoc FirstType, TypeLoc SecondType) : SeparatorLoc(SeparatorLoc), Kind(Kind), Invalid(false), FirstType(FirstType), SecondType(SecondType) { } RequirementRepr(SourceLoc SeparatorLoc, RequirementReprKind Kind, TypeLoc FirstType, LayoutConstraintLoc SecondLayout) : SeparatorLoc(SeparatorLoc), Kind(Kind), Invalid(false), FirstType(FirstType), SecondLayout(SecondLayout) { } void printImpl(ASTPrinter &OS, bool AsWritten) const; public: /// \brief Construct a new type-constraint 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 getTypeConstraint(TypeLoc Subject, SourceLoc ColonLoc, TypeLoc Constraint) { return { ColonLoc, RequirementReprKind::TypeConstraint, 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, RequirementReprKind::SameType, FirstType, SecondType }; } /// \brief Construct a new layout-constraint requirement. /// /// \param Subject The type that must conform to the given layout /// requirement. /// \param ColonLoc The location of the ':', or an invalid location if /// this requirement was implied. /// \param Layout The layout requirement to which the /// subject must conform. static RequirementRepr getLayoutConstraint(TypeLoc Subject, SourceLoc ColonLoc, LayoutConstraintLoc Layout) { return {ColonLoc, RequirementReprKind::LayoutConstraint, Subject, Layout}; } /// \brief Determine the kind of requirement RequirementReprKind 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 type-bound requirement, return the subject of the /// conformance relationship. Type getSubject() const { assert(getKind() == RequirementReprKind::TypeConstraint || getKind() == RequirementReprKind::LayoutConstraint); return FirstType.getType(); } TypeRepr *getSubjectRepr() const { assert(getKind() == RequirementReprKind::TypeConstraint || getKind() == RequirementReprKind::LayoutConstraint); return FirstType.getTypeRepr(); } TypeLoc &getSubjectLoc() { assert(getKind() == RequirementReprKind::TypeConstraint || getKind() == RequirementReprKind::LayoutConstraint); return FirstType; } const TypeLoc &getSubjectLoc() const { assert(getKind() == RequirementReprKind::TypeConstraint || getKind() == RequirementReprKind::LayoutConstraint); return FirstType; } /// \brief For a type-bound requirement, return the protocol or to which /// the subject conforms or superclass it inherits. Type getConstraint() const { assert(getKind() == RequirementReprKind::TypeConstraint); return SecondType.getType(); } TypeRepr *getConstraintRepr() const { assert(getKind() == RequirementReprKind::TypeConstraint); return SecondType.getTypeRepr(); } TypeLoc &getConstraintLoc() { assert(getKind() == RequirementReprKind::TypeConstraint); return SecondType; } const TypeLoc &getConstraintLoc() const { assert(getKind() == RequirementReprKind::TypeConstraint); return SecondType; } LayoutConstraint getLayoutConstraint() const { assert(getKind() == RequirementReprKind::LayoutConstraint); return SecondLayout.getLayoutConstraint(); } LayoutConstraintLoc &getLayoutConstraintLoc() { assert(getKind() == RequirementReprKind::LayoutConstraint); return SecondLayout; } const LayoutConstraintLoc &getLayoutConstraintLoc() const { assert(getKind() == RequirementReprKind::LayoutConstraint); return SecondLayout; } /// \brief Retrieve the location of the ':' in an explicitly-written /// conformance requirement. SourceLoc getColonLoc() const { assert(getKind() == RequirementReprKind::TypeConstraint || getKind() == RequirementReprKind::LayoutConstraint); return SeparatorLoc; } /// \brief Retrieve the first type of a same-type requirement. Type getFirstType() const { assert(getKind() == RequirementReprKind::SameType); return FirstType.getType(); } TypeRepr *getFirstTypeRepr() const { assert(getKind() == RequirementReprKind::SameType); return FirstType.getTypeRepr(); } TypeLoc &getFirstTypeLoc() { assert(getKind() == RequirementReprKind::SameType); return FirstType; } const TypeLoc &getFirstTypeLoc() const { assert(getKind() == RequirementReprKind::SameType); return FirstType; } /// \brief Retrieve the second type of a same-type requirement. Type getSecondType() const { assert(getKind() == RequirementReprKind::SameType); return SecondType.getType(); } TypeRepr *getSecondTypeRepr() const { assert(getKind() == RequirementReprKind::SameType); return SecondType.getTypeRepr(); } TypeLoc &getSecondTypeLoc() { assert(getKind() == RequirementReprKind::SameType); return SecondType; } const TypeLoc &getSecondTypeLoc() const { assert(getKind() == RequirementReprKind::SameType); return SecondType; } /// \brief Retrieve the location of the '==' in an explicitly-written /// same-type requirement. SourceLoc getEqualLoc() const { assert(getKind() == RequirementReprKind::SameType); return SeparatorLoc; } SourceRange getSourceRange() const { if (getKind() == RequirementReprKind::LayoutConstraint) return SourceRange(FirstType.getSourceRange().Start, SecondLayout.getSourceRange().End); return SourceRange(FirstType.getSourceRange().Start, SecondType.getSourceRange().End); } LLVM_ATTRIBUTE_DEPRECATED( void dump() const LLVM_ATTRIBUTE_USED, "only for use within the debugger"); void print(raw_ostream &OS) const; void print(ASTPrinter &Printer) const; }; /// 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 final : private llvm::TrailingObjects { friend TrailingObjects; SourceRange Brackets; unsigned NumParams; SourceLoc WhereLoc; MutableArrayRef Requirements; GenericParamList *OuterParameters; SourceLoc TrailingWhereLoc; unsigned FirstTrailingWhereArg; GenericParamList(SourceLoc LAngleLoc, ArrayRef Params, SourceLoc WhereLoc, MutableArrayRef Requirements, SourceLoc RAngleLoc); // 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, ArrayRef Requirements, SourceLoc RAngleLoc); MutableArrayRef getParams() { return {getTrailingObjects(), NumParams}; } ArrayRef getParams() const { return {getTrailingObjects(), NumParams}; } 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(); } /// \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; } /// Retrieve only those requirements that are written within the brackets, /// which does not include any requirements written in a trailing where /// clause. ArrayRef getNonTrailingRequirements() const { return Requirements.slice(0, FirstTrailingWhereArg); } /// Retrieve only those requirements written in a trailing where /// clause. ArrayRef getTrailingRequirements() const { return Requirements.slice(FirstTrailingWhereArg); } /// Determine whether the generic parameters have a trailing where clause. bool hasTrailingWhereClause() const { return FirstTrailingWhereArg < Requirements.size(); } /// Add a trailing 'where' clause to the list of requirements. /// /// Trailing where clauses are written outside the angle brackets, after the /// main part of a declaration's signature. void addTrailingWhereClause(ASTContext &ctx, SourceLoc trailingWhereLoc, ArrayRef trailingRequirements); /// \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 { /// init(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 source range covering the where clause. SourceRange getWhereClauseSourceRange() const { if (WhereLoc.isInvalid()) return SourceRange(); auto endLoc = Requirements[FirstTrailingWhereArg-1].getSourceRange().End; return SourceRange(WhereLoc, endLoc); } /// Retrieve the source range covering the trailing where clause. SourceRange getTrailingWhereClauseSourceRange() const { if (!hasTrailingWhereClause()) return SourceRange(); return SourceRange(TrailingWhereLoc, Requirements.back().getSourceRange().End); } /// 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; } /// Create a copy of the generic parameter list and all of its generic /// parameter declarations. The copied generic parameters are re-parented /// to the given DeclContext. GenericParamList *clone(DeclContext *dc) const; void print(raw_ostream &OS); void dump(); }; /// A trailing where clause. class alignas(RequirementRepr) TrailingWhereClause final : private llvm::TrailingObjects { friend TrailingObjects; SourceLoc WhereLoc; /// The number of requirements. The actual requirements are tail-allocated. unsigned NumRequirements; TrailingWhereClause(SourceLoc whereLoc, ArrayRef requirements); public: /// Create a new trailing where clause with the given set of requirements. static TrailingWhereClause *create(ASTContext &ctx, SourceLoc whereLoc, ArrayRef requirements); /// Retrieve the location of the 'where' keyword. SourceLoc getWhereLoc() const { return WhereLoc; } /// Retrieve the set of requirements. MutableArrayRef getRequirements() { return {getTrailingObjects(), NumRequirements}; } /// Retrieve the set of requirements. ArrayRef getRequirements() const { return {getTrailingObjects(), NumRequirements}; } /// Compute the source range containing this trailing where clause. SourceRange getSourceRange() const { return SourceRange(WhereLoc, getRequirements().back().getSourceRange().End); } }; // A private class for forcing exact field layout. class _GenericContext { // Not really public. See GenericContext. public: GenericParamList *GenericParams = nullptr; /// The trailing where clause. /// /// Note that this is not currently serialized, because semantic analysis /// moves the trailing where clause into the generic parameter list. TrailingWhereClause *TrailingWhere = nullptr; /// The generic signature or environment of this declaration. /// /// When this declaration stores only a signature, the generic /// environment will be lazily loaded. mutable llvm::PointerUnion GenericSigOrEnv; }; class GenericContext : private _GenericContext, public DeclContext { /// Lazily populate the generic environment. GenericEnvironment *getLazyGenericEnvironmentSlow() const; protected: GenericContext(DeclContextKind Kind, DeclContext *Parent) : _GenericContext(), DeclContext(Kind, Parent) { } public: /// \brief Retrieve the set of parameters to a generic context, or null if /// this context is not generic. GenericParamList *getGenericParams() const { return GenericParams; } void setGenericParams(GenericParamList *GenericParams); /// \brief Determine whether this context has generic parameters /// of its own. bool isGeneric() const { return GenericParams != nullptr; } /// Retrieve the trailing where clause for this extension, if any. TrailingWhereClause *getTrailingWhereClause() const { return TrailingWhere; } /// Set the trailing where clause for this extension. void setTrailingWhereClause(TrailingWhereClause *trailingWhereClause) { TrailingWhere = trailingWhereClause; } /// Retrieve the generic signature for this context. GenericSignature *getGenericSignature() const; /// Retrieve the generic context for this context. GenericEnvironment *getGenericEnvironment() const; /// Retrieve the innermost generic parameter types. TypeArrayView getInnermostGenericParamTypes() const; /// Retrieve the generic requirements. ArrayRef getGenericRequirements() const; /// Set a lazy generic environment. void setLazyGenericEnvironment(LazyMemberLoader *lazyLoader, GenericSignature *genericSig, uint64_t genericEnvData); /// Whether this generic context has a lazily-created generic environment /// that has not yet been constructed. bool hasLazyGenericEnvironment() const; /// Set the generic context of this context. void setGenericEnvironment(GenericEnvironment *genericEnv); }; static_assert(sizeof(_GenericContext) + sizeof(DeclContext) == sizeof(GenericContext), "Please add fields to _GenericContext"); /// 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 final : public Decl, private llvm::TrailingObjects> { friend TrailingObjects; public: typedef std::pair AccessPathElement; private: SourceLoc ImportLoc; SourceLoc KindLoc; /// The resolved module. ModuleDecl *Mod = nullptr; /// The resolved decls if this is a decl import. ArrayRef Decls; 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, ClangNode ClangN = ClangNode()); /// 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-homogeneous, or if there is more than one decl that /// cannot be overloaded, returns None. static Optional findBestImportKind(ArrayRef Decls); ArrayRef getFullAccessPath() const { return {getTrailingObjects(), Bits.ImportDecl.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(Bits.ImportDecl.ImportKind); } bool isExported() const { return getAttrs().hasAttribute(); } ModuleDecl *getModule() const { return Mod; } void setModule(ModuleDecl *M) { Mod = M; } ArrayRef getDecls() const { return Decls; } void setDecls(ArrayRef Ds) { Decls = Ds; } const clang::Module *getClangModule() const { return getClangNode().getClangModule(); } 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 GenericContext, public Decl, public IterableDeclContext { SourceLoc ExtensionLoc; // Location of 'extension' keyword. SourceRange Braces; /// The type being extended. TypeLoc ExtendedType; MutableArrayRef Inherited; /// \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 ConformanceLookupTable; friend class IterableDeclContext; ExtensionDecl(SourceLoc extensionLoc, TypeLoc extendedType, MutableArrayRef inherited, DeclContext *parent, TrailingWhereClause *trailingWhereClause); /// Retrieve the conformance loader (if any), and removing it in the /// same operation. The caller is responsible for loading the /// conformances. std::pair takeConformanceLoader() { if (!Bits.ExtensionDecl.HasLazyConformances) return { nullptr, 0 }; return takeConformanceLoaderSlow(); } /// Slow path for \c takeConformanceLoader(). std::pair takeConformanceLoaderSlow(); public: using Decl::getASTContext; /// Create a new extension declaration. static ExtensionDecl *create(ASTContext &ctx, SourceLoc extensionLoc, TypeLoc extendedType, MutableArrayRef inherited, DeclContext *parent, TrailingWhereClause *trailingWhereClause, 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 type being extended. Type getExtendedType() const { return ExtendedType.getType(); } /// Retrieve the extended type location. TypeLoc &getExtendedTypeLoc() { return ExtendedType; } /// Retrieve the extended type location. const TypeLoc &getExtendedTypeLoc() const { return ExtendedType; } /// \brief Retrieve the set of protocols that this type inherits (i.e, /// explicitly conforms to). MutableArrayRef getInherited() { return Inherited; } ArrayRef getInherited() const { return Inherited; } void setInherited(MutableArrayRef i) { Inherited = i; } /// Whether we have fully checked the extension. bool hasValidSignature() const { return hasValidationStarted() && !isBeingValidated(); } /// Whether we already type-checked the inheritance clause. bool checkedInheritanceClause() const { return Bits.ExtensionDecl.CheckedInheritanceClause; } /// Note that we have already type-checked the inheritance clause. void setCheckedInheritanceClause(bool checked = true) { Bits.ExtensionDecl.CheckedInheritanceClause = checked; } bool hasDefaultAccessLevel() const { return Bits.ExtensionDecl.DefaultAndMaxAccessLevel != 0; } AccessLevel getDefaultAccessLevel() const { assert(hasDefaultAccessLevel() && "not computed yet"); if (Bits.ExtensionDecl.DefaultAndMaxAccessLevel & (1 << (static_cast(AccessLevel::FilePrivate) - 1))) return AccessLevel::FilePrivate; if (Bits.ExtensionDecl.DefaultAndMaxAccessLevel & (1 << (static_cast(AccessLevel::Internal) - 1))) return AccessLevel::Internal; return AccessLevel::Public; } AccessLevel getMaxAccessLevel() const { assert(hasDefaultAccessLevel() && "not computed yet"); if (Bits.ExtensionDecl.DefaultAndMaxAccessLevel & (1 << (static_cast(AccessLevel::Public) - 1))) return AccessLevel::Public; if (Bits.ExtensionDecl.DefaultAndMaxAccessLevel & (1 << (static_cast(AccessLevel::Internal) - 1))) return AccessLevel::Internal; return AccessLevel::FilePrivate; } void setDefaultAndMaxAccess(AccessLevel defaultAccess, AccessLevel maxAccess) { assert(!hasDefaultAccessLevel() && "default access level already set"); assert(maxAccess >= defaultAccess); assert(maxAccess != AccessLevel::Private && "private not valid"); assert(defaultAccess != AccessLevel::Private && "private not valid"); Bits.ExtensionDecl.DefaultAndMaxAccessLevel = (1 << (static_cast(defaultAccess) - 1)) | (1 << (static_cast(maxAccess) - 1)); assert(getDefaultAccessLevel() == defaultAccess && "not enough bits"); assert(getMaxAccessLevel() == maxAccess && "not enough bits"); } void setConformanceLoader(LazyMemberLoader *resolver, uint64_t contextData); /// Determine whether this is a constrained extension, which adds additional /// requirements beyond those of the nominal type. bool isConstrainedExtension() const; /// Determine whether this extension context is interchangeable with the /// original nominal type context. /// /// False if any of the following properties hold: /// - the extension is defined in a different module from the original /// nominal type decl, /// - the extension is constrained, or /// - the extension is to a protocol. /// FIXME: In a world where protocol extensions are dynamically dispatched, /// "extension is to a protocol" would no longer be a reason to use the /// extension mangling, because an extension method implementation could be /// resiliently moved into the original protocol itself. bool isEquivalentToExtendedContext() const; // 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; } }; /// This represents one entry in a PatternBindingDecl, which are pairs of /// Pattern and Initialization expression. The pattern is always present, but /// the initializer can be null if there is none. class PatternBindingEntry { Pattern *ThePattern; enum class Flags { Checked = 1 << 0, Removed = 1 << 1 }; // When the initializer is removed we don't actually clear the pointer // because we might need to get initializer's source range. Since the // initializer is ASTContext-allocated it is safe. llvm::PointerIntPair> InitCheckedAndRemoved; /// The initializer context used for this pattern binding entry. DeclContext *InitContext = nullptr; friend class PatternBindingInitializer; public: PatternBindingEntry(Pattern *P, Expr *E, DeclContext *InitContext) : ThePattern(P), InitCheckedAndRemoved(E, {}), InitContext(InitContext) {} Pattern *getPattern() const { return ThePattern; } void setPattern(Pattern *P) { ThePattern = P; } Expr *getInit() const { return (InitCheckedAndRemoved.getInt().contains(Flags::Removed)) ? nullptr : InitCheckedAndRemoved.getPointer(); } SourceRange getOrigInitRange() const; void setInit(Expr *E); /// Retrieve the initializer as it was written in the source. Expr *getInitAsWritten() const { return InitCheckedAndRemoved.getPointer(); } bool isInitializerChecked() const { return InitCheckedAndRemoved.getInt().contains(Flags::Checked); } void setInitializerChecked() { InitCheckedAndRemoved.setInt( InitCheckedAndRemoved.getInt() | Flags::Checked); } // Return the first variable initialized by this pattern. VarDecl *getAnchoringVarDecl() const; // Retrieve the declaration context for the initializer. DeclContext *getInitContext() const { return InitContext; } /// Override the initializer context. void setInitContext(DeclContext *dc) { InitContext = dc; } /// Retrieve the source range covered by this pattern binding. /// /// \param omitAccessors Whether the computation should omit the accessors /// from the source range. SourceRange getSourceRange(bool omitAccessors = false) const; }; /// \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(), (c,d) = bar() /// \endcode /// /// this includes two entries in the pattern list. The first contains the /// pattern "(a, b)" and the initializer "foo()". The second contains the /// pattern "(c, d)" and the initializer "bar()". /// class PatternBindingDecl final : public Decl, private llvm::TrailingObjects { friend TrailingObjects; SourceLoc StaticLoc; ///< Location of the 'static/class' keyword, if present. SourceLoc VarLoc; ///< Location of the 'var' keyword. friend class Decl; PatternBindingDecl(SourceLoc StaticLoc, StaticSpellingKind StaticSpelling, SourceLoc VarLoc, unsigned NumPatternEntries, DeclContext *Parent); public: static PatternBindingDecl *create(ASTContext &Ctx, SourceLoc StaticLoc, StaticSpellingKind StaticSpelling, SourceLoc VarLoc, ArrayRef PatternList, DeclContext *Parent); static PatternBindingDecl *create(ASTContext &Ctx, SourceLoc StaticLoc, StaticSpellingKind StaticSpelling, SourceLoc VarLoc, Pattern *Pat, Expr *E, DeclContext *Parent); static PatternBindingDecl *createDeserialized( ASTContext &Ctx, SourceLoc StaticLoc, StaticSpellingKind StaticSpelling, SourceLoc VarLoc, unsigned NumPatternEntries, DeclContext *Parent); SourceLoc getStartLoc() const { return StaticLoc.isValid() ? StaticLoc : VarLoc; } SourceLoc getLoc() const { return VarLoc; } SourceRange getSourceRange() const; unsigned getNumPatternEntries() const { return Bits.PatternBindingDecl.NumPatternEntries; } ArrayRef getPatternList() const { return const_cast(this)->getMutablePatternList(); } Expr *getInit(unsigned i) const { return getPatternList()[i].getInit(); } SourceRange getOrigInitRange(unsigned i) const { return getPatternList()[i].getOrigInitRange(); } void setInit(unsigned i, Expr *E) { getMutablePatternList()[i].setInit(E); } Pattern *getPattern(unsigned i) const { return getPatternList()[i].getPattern(); } void setPattern(unsigned i, Pattern *Pat, DeclContext *InitContext); /// Given that this PBD is the parent pattern for the specified VarDecl, /// return the entry of the VarDecl in our PatternList. For example, in: /// /// let (a,b) = foo(), (c,d) = bar() /// /// "a" and "b" will have index 0, since they correspond to the first pattern, /// and "c" and "d" will have index 1 since they correspond to the second one. unsigned getPatternEntryIndexForVarDecl(const VarDecl *VD) const; /// Return the PatternEntry (a pattern + initializer pair) for the specified /// VarDecl. PatternBindingEntry getPatternEntryForVarDecl(const VarDecl *VD) const { return getPatternList()[getPatternEntryIndexForVarDecl(VD)]; } bool isInitializerChecked(unsigned i) const { return getPatternList()[i].isInitializerChecked(); } void setInitializerChecked(unsigned i) { getMutablePatternList()[i].setInitializerChecked(); } /// Does this binding declare something that requires storage? bool hasStorage() const; /// Determines whether this binding either has an initializer expression, or is /// default initialized, without performing any type checking on it. /// /// This is only valid to check for bindings which have storage. bool isDefaultInitializable() const { assert(hasStorage()); for (unsigned i = 0, e = getNumPatternEntries(); i < e; ++i) if (!isDefaultInitializable(i)) return false; return true; } /// Can the pattern at index i be default initialized? bool isDefaultInitializable(unsigned i) const; /// When the pattern binding contains only a single variable with no /// destructuring, retrieve that variable. VarDecl *getSingleVar() const; bool isStatic() const { return Bits.PatternBindingDecl.IsStatic; } void setStatic(bool s) { Bits.PatternBindingDecl.IsStatic = s; } SourceLoc getStaticLoc() const { return StaticLoc; } /// \returns the way 'static'/'class' was spelled in the source. StaticSpellingKind getStaticSpelling() const { return static_cast( Bits.PatternBindingDecl.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; } private: MutableArrayRef getMutablePatternList() { // Pattern entries are tail allocated. return {getTrailingObjects(), getNumPatternEntries()}; } }; /// 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 DeclContext, public Decl { BraceStmt *Body; public: TopLevelCodeDecl(DeclContext *Parent, BraceStmt *Body = nullptr) : DeclContext(DeclContextKind::TopLevelCodeDecl, Parent), Decl(DeclKind::TopLevelCode, 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; }; /// SerializedTopLevelCodeDeclContext - This represents what was originally a /// TopLevelCodeDecl during serialization. It is preserved only to maintain the /// correct AST structure and remangling after deserialization. class SerializedTopLevelCodeDeclContext : public SerializedLocalDeclContext { public: SerializedTopLevelCodeDeclContext(DeclContext *Parent) : SerializedLocalDeclContext(LocalDeclContextKind::TopLevelCodeDecl, Parent) {} static bool classof(const DeclContext *DC) { if (auto LDC = dyn_cast(DC)) return LDC->getLocalDeclContextKind() == LocalDeclContextKind::TopLevelCodeDecl; return false; } }; /// IfConfigDecl - This class represents #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 context. 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; public: IfConfigDecl(DeclContext *Parent, ArrayRef Clauses, SourceLoc EndLoc, bool HadMissingEnd) : Decl(DeclKind::IfConfig, Parent), Clauses(Clauses), EndLoc(EndLoc) { Bits.IfConfigDecl.HadMissingEnd = HadMissingEnd; } ArrayRef getClauses() const { return Clauses; } /// Return the active clause, or null if there is no active one. const IfConfigClause *getActiveClause() const { for (auto &Clause : Clauses) if (Clause.isActive) return &Clause; return nullptr; } const ArrayRef getActiveClauseElements() const { if (auto *Clause = getActiveClause()) return Clause->Elements; return {}; } SourceLoc getEndLoc() const { return EndLoc; } SourceLoc getLoc() const { return Clauses[0].Loc; } bool hadMissingEnd() const { return Bits.IfConfigDecl.HadMissingEnd; } SourceRange getSourceRange() const; static bool classof(const Decl *D) { return D->getKind() == DeclKind::IfConfig; } }; class StringLiteralExpr; class PoundDiagnosticDecl : public Decl { SourceLoc StartLoc; SourceLoc EndLoc; StringLiteralExpr *Message; public: PoundDiagnosticDecl(DeclContext *Parent, bool IsError, SourceLoc StartLoc, SourceLoc EndLoc, StringLiteralExpr *Message) : Decl(DeclKind::PoundDiagnostic, Parent), StartLoc(StartLoc), EndLoc(EndLoc), Message(Message) { Bits.PoundDiagnosticDecl.IsError = IsError; Bits.PoundDiagnosticDecl.HasBeenEmitted = false; } DiagnosticKind getKind() { return isError() ? DiagnosticKind::Error : DiagnosticKind::Warning; } StringLiteralExpr *getMessage() { return Message; } bool isError() { return Bits.PoundDiagnosticDecl.IsError; } bool hasBeenEmitted() { return Bits.PoundDiagnosticDecl.HasBeenEmitted; } void markEmitted() { Bits.PoundDiagnosticDecl.HasBeenEmitted = true; } SourceLoc getEndLoc() const { return EndLoc; }; SourceLoc getLoc() const { return StartLoc; } SourceRange getSourceRange() const { return SourceRange(StartLoc, EndLoc); } static bool classof(const Decl *D) { return D->getKind() == DeclKind::PoundDiagnostic; } }; /// 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, llvm::PointerUnion context, DeclName name, SourceLoc NameLoc) : Decl(K, context), Name(name), NameLoc(NameLoc) { Bits.ValueDecl.AlreadyInLookupTable = false; Bits.ValueDecl.CheckedRedeclaration = false; Bits.ValueDecl.IsUserAccessible = true; } // MemberLookupTable borrows a bit from this type friend class MemberLookupTable; bool isAlreadyInLookupTable() { return Bits.ValueDecl.AlreadyInLookupTable; } void setAlreadyInLookupTable(bool value = true) { Bits.ValueDecl.AlreadyInLookupTable = value; } 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; /// \brief Return true if this protocol member is a protocol requirement. /// /// Asserts if this is not a member of a protocol. bool isProtocolRequirement() const; /// Determine whether we have already checked whether this /// declaration is a redeclaration. bool alreadyCheckedRedeclaration() const { return Bits.ValueDecl.CheckedRedeclaration; } /// Set whether we have already checked this declaration as a /// redeclaration. void setCheckedRedeclaration(bool checked) { Bits.ValueDecl.CheckedRedeclaration = checked; } void setUserAccessible(bool Accessible) { Bits.ValueDecl.IsUserAccessible = Accessible; } bool isUserAccessible() const { return Bits.ValueDecl.IsUserAccessible; } bool hasName() const { return bool(Name); } bool isOperator() const { return Name.isOperator(); } /// Retrieve the full name of the declaration. /// TODO: Rename to getName? DeclName getFullName() const { return Name; } void setName(DeclName name) { Name = name; } /// Retrieve the base name of the declaration, ignoring any argument /// names. DeclBaseName getBaseName() const { return Name.getBaseName(); } /// Retrieve the name to use for this declaration when interoperating /// with the Objective-C runtime. /// /// \returns A "selector" containing the runtime name. For non-method /// entities (classes, protocols, properties), this operation will /// return a zero-parameter selector with the appropriate name in its /// first slot. Optional getObjCRuntimeName() const; /// Determine whether the given declaration can infer @objc, or the /// Objective-C name, if used to satisfy the given requirement. bool canInferObjCFromRequirement(ValueDecl *requirement); SourceLoc getNameLoc() const { return NameLoc; } SourceLoc getLoc() const { return NameLoc; } bool hasAccess() const { return TypeAndAccess.getInt().hasValue(); } /// \see getFormalAccess AccessLevel getFormalAccessImpl(const DeclContext *useDC) const; bool isVersionedInternalDecl() const; /// Returns the access level specified explicitly by the user, or provided by /// default according to language rules. /// /// This is the access used when calculating if access control is being used /// consistently. If \p useDC is provided (the location where the value is /// being used), features that affect formal access such as \c \@testable are /// taken into account. /// /// \sa getFormalAccessScope AccessLevel getFormalAccess(const DeclContext *useDC = nullptr, bool respectVersionedAttr = false) const { assert(hasAccess() && "access not computed yet"); AccessLevel result = TypeAndAccess.getInt().getValue(); if (respectVersionedAttr && result == AccessLevel::Internal && isVersionedInternalDecl()) { assert(!useDC); return AccessLevel::Public; } if (useDC && (result == AccessLevel::Internal || result == AccessLevel::Public)) return getFormalAccessImpl(useDC); return result; } /// Determine whether this Decl has either Private or FilePrivate access. bool isOutermostPrivateOrFilePrivateScope() const; /// Returns the outermost DeclContext from which this declaration can be /// accessed, or null if the declaration is public. /// /// This is used when calculating if access control is being used /// consistently. If \p useDC is provided (the location where the value is /// being used), features that affect formal access such as \c \@testable are /// taken into account. /// /// \invariant /// value.isAccessibleFrom(value.getFormalAccessScope()) /// /// \sa getFormalAccess /// \sa isAccessibleFrom AccessScope getFormalAccessScope(const DeclContext *useDC = nullptr, bool respectVersionedAttr = false) const; /// Copy the formal access level and @_versioned attribute from source. void copyFormalAccessAndVersionedAttrFrom(ValueDecl *source); /// Returns the access level that actually controls how a declaration should /// be emitted and may be used. /// /// This is the access used when making optimization and code generation /// decisions. It should not be used at the AST or semantic level. AccessLevel getEffectiveAccess() const; void setAccess(AccessLevel access) { assert(!hasAccess() && "access already set"); overwriteAccess(access); } /// Overwrite the access of this declaration. /// /// This is needed in the LLDB REPL. void overwriteAccess(AccessLevel 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; /// Retrieve the "interface" type of this value, which uses /// GenericTypeParamType if the declaration is generic. For a generic /// function, this will have a GenericFunctionType with a /// GenericSignature inside the type. Type getInterfaceType() const; bool hasInterfaceType() const; /// Set the interface type for the given value. void setInterfaceType(Type type); bool hasValidSignature() const; /// 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(const DeclContext *UseDC, const DeclRefExpr *base = nullptr) 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 untyped overload signature for this declaration. OverloadSignature getOverloadSignature() const; /// Retrieve the type used to describe this entity for the purposes of /// overload resolution. CanType getOverloadSignatureType() 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 and set with a call to /// markAsObjC(). 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 the protocol requirements that this decl conforms to. ArrayRef getSatisfiedProtocolRequirements(bool Sorted = false) const; /// 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; /// Print a reference to the given declaration. std::string printRef() const; /// Dump a reference to the given declaration. void dumpRef(raw_ostream &os) const; /// Dump a reference to the given declaration. void dumpRef() const; /// Returns true if the declaration is a static member of a type. /// /// This is not necessarily the opposite of "isInstanceMember()". Both /// predicates will be false for declarations that either categorically /// can't be "static" or are in a context where "static" doesn't make sense. bool isStatic() const; /// Retrieve the location at which we should insert a new attribute or /// modifier. SourceLoc getAttributeInsertionLoc(bool forModifier) const; static bool classof(const Decl *D) { return D->getKind() >= DeclKind::First_ValueDecl && D->getKind() <= DeclKind::Last_ValueDecl; } /// True if this is a C function that was imported as a member of a type in /// Swift. bool isImportAsMember() const; }; /// This is a common base class for declarations which declare a type. class TypeDecl : public ValueDecl { MutableArrayRef Inherited; protected: TypeDecl(DeclKind K, llvm::PointerUnion context, Identifier name, SourceLoc NameLoc, MutableArrayRef inherited) : ValueDecl(K, context, name, NameLoc), Inherited(inherited) { Bits.TypeDecl.CheckedInheritanceClause = false; } public: Identifier getName() const { return getFullName().getBaseIdentifier(); } /// Returns the string for the base name, or "_" if this is unnamed. StringRef getNameStr() const { assert(!getFullName().isSpecial() && "Cannot get string for special names"); return hasName() ? getBaseName().getIdentifier().str() : "_"; } /// The type of this declaration's values. For the type of the /// declaration itself, use getInterfaceType(), which returns a /// metatype. 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 Bits.TypeDecl.CheckedInheritanceClause; } /// Note that we have already type-checked the inheritance clause. void setCheckedInheritanceClause(bool checked = true) { Bits.TypeDecl.CheckedInheritanceClause = checked; } void setInherited(MutableArrayRef i) { Inherited = i; } static bool classof(const Decl *D) { return D->getKind() >= DeclKind::First_TypeDecl && D->getKind() <= DeclKind::Last_TypeDecl; } /// Compute an ordering between two type declarations that is ABI-stable. static int compare(const TypeDecl *type1, const TypeDecl *type2); }; /// A type declaration that can have generic parameters attached to it. Because /// it has these generic parameters, it is always a DeclContext. class GenericTypeDecl : public GenericContext, public TypeDecl { public: GenericTypeDecl(DeclKind K, DeclContext *DC, Identifier name, SourceLoc nameLoc, MutableArrayRef inherited, GenericParamList *GenericParams); // Resolve ambiguity due to multiple base classes. using TypeDecl::getASTContext; using DeclContext::operator new; using TypeDecl::getDeclaredInterfaceType; static bool classof(const DeclContext *C) { return C->getContextKind() == DeclContextKind::GenericTypeDecl; } static bool classof(const Decl *D) { return D->getKind() >= DeclKind::First_GenericTypeDecl && D->getKind() <= DeclKind::Last_GenericTypeDecl; } }; /// TypeAliasDecl - This is a declaration of a typealias, for example: /// /// typealias Foo = Int /// /// TypeAliasDecl's always have 'MetatypeType' type. /// class TypeAliasDecl : public GenericTypeDecl { /// The location of the 'typealias' keyword SourceLoc TypeAliasLoc; /// The location of the equal '=' token SourceLoc EqualLoc; /// The location of the right-hand side of the typealias binding TypeLoc UnderlyingTy; public: TypeAliasDecl(SourceLoc TypeAliasLoc, SourceLoc EqualLoc, Identifier Name, SourceLoc NameLoc, GenericParamList *GenericParams, DeclContext *DC); SourceLoc getStartLoc() const { return TypeAliasLoc; } SourceRange getSourceRange() const; /// Returns the location of the equal '=' token SourceLoc getEqualLoc() const { return EqualLoc; } TypeLoc &getUnderlyingTypeLoc() { return UnderlyingTy; } const TypeLoc &getUnderlyingTypeLoc() const { return UnderlyingTy; } /// Set the underlying type, for deserialization and synthesized /// aliases. void setUnderlyingType(Type type); /// For generic typealiases, return the unbound generic type. UnboundGenericType *getUnboundGenericType() const; bool isCompatibilityAlias() const { return Bits.TypeAliasDecl.IsCompatibilityAlias; } void markAsCompatibilityAlias(bool newValue = true) { Bits.TypeAliasDecl.IsCompatibilityAlias = newValue; } static bool classof(const Decl *D) { return D->getKind() == DeclKind::TypeAlias; } static bool classof(const GenericTypeDecl *D) { return D->getKind() == DeclKind::TypeAlias; } static bool classof(const DeclContext *C) { auto GTD = dyn_cast(C); return GTD && classof(GTD); } }; /// 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 { protected: AbstractTypeParamDecl(DeclKind kind, DeclContext *dc, Identifier name, SourceLoc NameLoc) : TypeDecl(kind, dc, name, NameLoc, { }) { } public: /// Return the superclass of the generic parameter. Type getSuperclass() const; /// Retrieve the set of protocols to which this abstract type /// parameter conforms. ArrayRef getConformingProtocols() const; 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 { public: static const unsigned InvalidDepth = 0xFFFF; /// 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 Bits.GenericTypeParamDecl.Depth; } /// Set the depth of this generic type parameter. /// /// \sa getDepth void setDepth(unsigned depth) { Bits.GenericTypeParamDecl.Depth = depth; assert(Bits.GenericTypeParamDecl.Depth == depth && "Truncation"); } /// 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 Bits.GenericTypeParamDecl.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, /// described 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; /// The where clause attached to the associated type. TrailingWhereClause *TrailingWhere; LazyMemberLoader *Resolver = nullptr; uint64_t ResolverContextData; public: AssociatedTypeDecl(DeclContext *dc, SourceLoc keywordLoc, Identifier name, SourceLoc nameLoc, TypeLoc defaultDefinition, TrailingWhereClause *trailingWhere); AssociatedTypeDecl(DeclContext *dc, SourceLoc keywordLoc, Identifier name, SourceLoc nameLoc, TrailingWhereClause *trailingWhere, 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(); } /// Retrieve the trailing where clause for this associated type, if any. TrailingWhereClause *getTrailingWhereClause() const { return TrailingWhere; } /// Set the trailing where clause for this associated type. void setTrailingWhereClause(TrailingWhereClause *trailingWhereClause) { TrailingWhere = trailingWhereClause; } /// computeType - Compute the type (and declared type) of this associated /// type; can only be called after the alias type has been resolved. void computeType(); /// Retrieve the associated type "anchor", which is the associated type /// declaration that will be used to describe this associated type in the /// ABI. /// /// The associated type "anchor" is an associated type that does not /// override any other associated type. There may be several such associated /// types; select one deterministically. AssociatedTypeDecl *getAssociatedTypeAnchor() const; /// Retrieve the (first) overridden associated type declaration, if any. AssociatedTypeDecl *getOverriddenDecl() const; /// Retrieve the set of associated types overridden by this associated /// type. ArrayRef getOverriddenDecls() const; /// Whether the overridden declarations have already been computed. bool overriddenDeclsComputed() const { return Bits.AssociatedTypeDecl.ComputedOverridden; } /// Record the set of overridden declarations. /// /// \returns the array recorded in the AST. ArrayRef setOverriddenDecls( ArrayRef overridden); SourceLoc getStartLoc() const { return KeywordLoc; } SourceRange getSourceRange() const; static bool classof(const Decl *D) { return D->getKind() == DeclKind::AssociatedType; } }; class MemberLookupTable; class ConformanceLookupTable; /// 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_UnsafeMutableRawPointer, PTK_UnsafeRawPointer, PTK_UnsafeMutablePointer, PTK_UnsafePointer, PTK_AutoreleasingUnsafeMutablePointer, }; static inline bool isRawPointerKind(PointerTypeKind PTK) { switch (PTK) { case PTK_UnsafeMutableRawPointer: case PTK_UnsafeRawPointer: return true; case PTK_UnsafeMutablePointer: case PTK_UnsafePointer: case PTK_AutoreleasingUnsafeMutablePointer: return false; } llvm_unreachable("Unhandled PointerTypeKind in switch."); } /// NominalTypeDecl - a declaration of a nominal type, like a struct. class NominalTypeDecl : public GenericTypeDecl, public IterableDeclContext { SourceRange Braces; /// \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; /// Prepare to traverse the list of extensions. void prepareExtensions(); /// Retrieve the conformance loader (if any), and removing it in the /// same operation. The caller is responsible for loading the /// conformances. std::pair takeConformanceLoader() { if (!Bits.NominalTypeDecl.HasLazyConformances) return { nullptr, 0 }; return takeConformanceLoaderSlow(); } /// Slow path for \c takeConformanceLoader(). std::pair takeConformanceLoaderSlow(); /// \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(bool ignoreNewExtensions); /// 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); /// \brief A lookup table used to find the protocol conformances of /// a given nominal type. mutable ConformanceLookupTable *ConformanceTable = nullptr; /// Prepare the conformance table. void prepareConformanceTable() const; /// Returns the protocol requirements that \c Member conforms to. ArrayRef getSatisfiedProtocolRequirementsForMember(const ValueDecl *Member, bool Sorted) const; friend class ASTContext; friend class MemberLookupTable; friend class ConformanceLookupTable; friend class ExtensionDecl; friend class DeclContext; friend class IterableDeclContext; friend ArrayRef ValueDecl::getSatisfiedProtocolRequirements(bool Sorted) const; protected: Type DeclaredTy; Type DeclaredTyInContext; Type DeclaredInterfaceTy; NominalTypeDecl(DeclKind K, DeclContext *DC, Identifier name, SourceLoc NameLoc, MutableArrayRef inherited, GenericParamList *GenericParams) : GenericTypeDecl(K, DC, name, NameLoc, inherited, GenericParams), IterableDeclContext(IterableDeclContextKind::NominalTypeDecl) { setGenericParams(GenericParams); Bits.NominalTypeDecl.AddedImplicitInitializers = false; ExtensionGeneration = 0; Bits.NominalTypeDecl.HasLazyConformances = false; Bits.NominalTypeDecl.HasValidatedLayout = false; } friend class ProtocolType; public: using GenericTypeDecl::getASTContext; SourceRange getBraces() const { return Braces; } void setBraces(SourceRange braces) { Braces = braces; } /// \brief Should this declaration behave as if it must be accessed /// resiliently, even when we're building a non-resilient module? /// /// This is used for diagnostics, because we do not want a behavior /// change between builds with resilience enabled and disabled. bool isFormallyResilient() const; /// \brief Do we need to use resilient access patterns outside of this type's /// resilience domain? bool isResilient() const; /// \brief Do we need to use resilient access patterns when accessing this /// type from the given module? bool isResilient(ModuleDecl *M, ResilienceExpansion expansion) const; /// Determine whether we have already attempted to add any /// implicitly-defined initializers to this declaration. bool addedImplicitInitializers() const { return Bits.NominalTypeDecl.AddedImplicitInitializers; } /// Note that we have attempted to add implicit initializers. void setAddedImplicitInitializers() { Bits.NominalTypeDecl.AddedImplicitInitializers = true; } /// Determine whether we have already validated any members /// which affect layout. bool hasValidatedLayout() const { return Bits.NominalTypeDecl.HasValidatedLayout; } /// Note that we have attempted to validate any members /// which affect layout. void setHasValidatedLayout() { Bits.NominalTypeDecl.HasValidatedLayout = true; } /// Compute the type of this nominal type. void computeType(); /// getDeclaredType - Retrieve the type declared by this entity, without /// any generic parameters bound if this is a generic type. Type getDeclaredType() const; /// getDeclaredTypeInContext - Retrieve the type declared by this entity, with /// context archetypes bound if this is a generic type. Type getDeclaredTypeInContext() const; /// getDeclaredInterfaceType - Retrieve the type declared by this entity, with /// generic parameters bound if this is a generic type. Type getDeclaredInterfaceType() 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. /// /// \param ignoreNewExtensions Whether to avoid loading any new extension. /// Used by the module loader to break recursion. TinyPtrVector lookupDirect(DeclName name, bool ignoreNewExtensions = false); /// Collect the set of protocols to which this type should implicitly /// conform, such as AnyObject (for classes). void getImplicitProtocols(SmallVectorImpl &protocols); /// Look for conformances of this nominal type to the given /// protocol. /// /// \param module The module from which we initiate the search. /// FIXME: This is currently unused. /// /// \param protocol The protocol whose conformance is requested. /// \param conformances Will be populated with the set of protocol /// conformances found for this protocol. /// /// \returns true if any conformances were found. bool lookupConformance( ModuleDecl *module, ProtocolDecl *protocol, SmallVectorImpl &conformances) const; /// Retrieve all of the protocols that this nominal type conforms to. SmallVector getAllProtocols() const; /// Retrieve all of the protocol conformances for this nominal type. SmallVector getAllConformances( bool sorted = false) const; /// Register an externally-created protocol conformance in the /// conformance lookup table. /// /// This is used by deserialization of module files to report /// conformances. void registerProtocolConformance(ProtocolConformance *conformance); void setConformanceLoader(LazyMemberLoader *resolver, uint64_t contextData); /// Is this the decl for Optional? bool isOptionalDecl() const; private: /// Predicate used to filter StoredPropertyRange. struct ToStoredProperty { ToStoredProperty(bool skipInaccessible = false) : skipUserInaccessible(skipInaccessible) {} bool skipUserInaccessible; Optional operator()(Decl *decl) const; }; 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(bool skipInaccessible = false) const { return StoredPropertyRange(getMembers(), ToStoredProperty(skipInaccessible)); } private: /// Predicate used to filter StoredPropertyRange. struct ToStoredPropertyOrMissingMemberPlaceholder { Optional operator()(Decl *decl) const; }; public: /// A range for iterating the stored member variables of a structure. using StoredPropertyOrMissingMemberPlaceholderRange = OptionalTransformRange; /// Return a collection of the stored member variables of this type, along /// with placeholders for unimportable stored properties. StoredPropertyOrMissingMemberPlaceholderRange getStoredPropertiesAndMissingMemberPlaceholders() const { return StoredPropertyOrMissingMemberPlaceholderRange(getMembers(), ToStoredPropertyOrMissingMemberPlaceholder()); } // 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 GenericTypeDecl *D) { return D->getKind() >= DeclKind::First_NominalTypeDecl && D->getKind() <= DeclKind::Last_NominalTypeDecl; } static bool classof(const DeclContext *C) { auto GTD = dyn_cast(C); return GTD && classof(GTD); } 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; } }; /// \brief This is the declaration of an enum. /// /// For example: /// /// \code /// enum Bool { /// case false /// case true /// } /// /// enum Optional { /// case none /// case some(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 final : public NominalTypeDecl { SourceLoc EnumLoc; struct { /// The raw type and a bit to indicate whether the /// raw was computed yet or not. llvm::PointerIntPair RawType; } LazySemanticInfo; friend class IterativeTypeChecker; 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; /// A range for iterating the cases of an enum. using CaseRange = DowncastFilterRange; /// Return a range that iterates over all the elements of an enum. ElementRange getAllElements() const { return ElementRange(getMembers()); } unsigned getNumElements() const { auto eltRange = getAllElements(); return std::distance(eltRange.begin(), eltRange.end()); } /// If this is an enum with two cases, return the other case. Otherwise, /// return nullptr. EnumElementDecl *getOppositeBinaryDecl(EnumElementDecl *decl) const { ElementRange range = getAllElements(); auto iter = range.begin(); if (iter == range.end()) return nullptr; bool seenDecl = false; EnumElementDecl *result = nullptr; if (*iter == decl) { seenDecl = true; } else { result = *iter; } ++iter; if (iter == range.end()) return nullptr; if (seenDecl) { assert(!result); result = *iter; } else { if (decl != *iter) return nullptr; seenDecl = true; } ++iter; // If we reach this point, we saw the decl we were looking for and one other // case. If we have any additional cases, then we do not have a binary enum. if (iter != range.end()) return nullptr; // This is always true since we have already returned earlier nullptr if we // did not see the decl at all. assert(seenDecl); return result; } /// If this enum has a unique element, return it. A unique element can /// either hold a value or not, and the existence of one unique element does /// not imply the existence or non-existence of the opposite unique element. EnumElementDecl *getUniqueElement(bool hasValue) const; /// Return a range that iterates over all the cases of an enum. CaseRange getAllCases() const { return CaseRange(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(Bits.EnumDecl.Circularity); } /// Record the current stage of circularity checking. void setCircularityCheck(CircularityCheck circularity) { Bits.EnumDecl.Circularity = static_cast(circularity); } // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() == DeclKind::Enum; } static bool classof(const GenericTypeDecl *D) { return D->getKind() == DeclKind::Enum; } static bool classof(const NominalTypeDecl *D) { return D->getKind() == DeclKind::Enum; } static bool classof(const DeclContext *C) { auto GTD = dyn_cast(C); return GTD && classof(static_cast(GTD)); } static bool classof(const IterableDeclContext *C) { auto NTD = dyn_cast(C); return NTD && classof(NTD); } /// Determine whether this enum declares a raw type in its inheritance clause. bool hasRawType() const { return (bool)LazySemanticInfo.RawType.getPointer(); } /// Retrieve the declared raw type of the enum from its inheritance clause, /// or null if it has none. Type getRawType() const { return LazySemanticInfo.RawType.getPointer(); } /// Set the raw type of the enum from its inheritance clause. void setRawType(Type rawType) { LazySemanticInfo.RawType.setPointerAndInt(rawType, true); } /// True if none of the enum cases have associated values. /// /// Note that this is true for enums with absolutely no cases. bool hasOnlyCasesWithoutAssociatedValues() const; /// True if the enum has cases. bool hasCases() const { return !getAllElements().empty(); } /// True if the enum is marked 'indirect'. bool isIndirect() const { return getAttrs().hasAttribute(); } }; /// 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 final : 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 GenericTypeDecl *D) { return D->getKind() == DeclKind::Struct; } static bool classof(const NominalTypeDecl *D) { return D->getKind() == DeclKind::Struct; } static bool classof(const DeclContext *C) { auto GTD = dyn_cast(C); return GTD && classof(static_cast(GTD)); } static bool classof(const IterableDeclContext *C) { auto NTD = dyn_cast(C); return NTD && classof(NTD); } /// Does this struct contain unreferenceable storage, such as C fields that /// cannot be represented in Swift? bool hasUnreferenceableStorage() const { return Bits.StructDecl.HasUnreferenceableStorage; } void setHasUnreferenceableStorage(bool v) { Bits.StructDecl.HasUnreferenceableStorage = v; } }; /// The kind of artificial main to generate for a class. enum class ArtificialMainKind : uint8_t { NSApplicationMain, UIApplicationMain, }; enum class ObjCClassKind : uint8_t { /// Neither the class nor any of its superclasses are @objc. NonObjC, /// One of the superclasses is @objc but another superclass or the /// class itself has generic parameters, so while it cannot be /// directly represented in Objective-C, it has implicitly @objc /// members. ObjCMembers, /// The top-level ancestor of this class is not @objc, but the /// class itself is. ObjCWithSwiftRoot, /// The class is bona-fide @objc. ObjC, }; /// 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 final : public NominalTypeDecl { class ObjCMethodLookupTable; SourceLoc ClassLoc; ObjCMethodLookupTable *ObjCMethodLookup = nullptr; /// Create the Objective-C member lookup table. void createObjCMethodLookup(); struct { /// The superclass type and a bit to indicate whether the /// superclass was computed yet or not. llvm::PointerIntPair Superclass; } LazySemanticInfo; friend class IterativeTypeChecker; 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)getSuperclass(); } /// Retrieve the superclass of this class, or null if there is no superclass. Type getSuperclass() const { return LazySemanticInfo.Superclass.getPointer(); } /// Retrieve the ClassDecl for the superclass of this class, or null if there /// is no superclass. ClassDecl *getSuperclassDecl() const; /// Set the superclass of this class. void setSuperclass(Type superclass); /// Retrieve the status of circularity checking for class inheritance. CircularityCheck getCircularityCheck() const { return static_cast(Bits.ClassDecl.Circularity); } /// Record the current stage of circularity checking. void setCircularityCheck(CircularityCheck circularity) { Bits.ClassDecl.Circularity = static_cast(circularity); } //// Whether this class requires all of its stored properties to //// have initializers in the class definition. bool requiresStoredPropertyInits() const { return Bits.ClassDecl.RequiresStoredPropertyInits; } /// Set whether this class requires all of its stored properties to /// have initializers in the class definition. void setRequiresStoredPropertyInits(bool requiresInits) { Bits.ClassDecl.RequiresStoredPropertyInits = requiresInits; } /// \see getForeignClassKind enum class ForeignKind : uint8_t { /// A normal Swift or Objective-C class. Normal = 0, /// An imported Core Foundation type. These are AnyObject-compatible but /// do not have runtime metadata. CFType, /// An imported Objective-C type whose class and metaclass symbols are not /// both available at link-time but can be accessed through the Objective-C /// runtime. RuntimeOnly }; /// 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. ForeignKind getForeignClassKind() const { return static_cast(Bits.ClassDecl.RawForeignKind); } void setForeignClassKind(ForeignKind kind) { Bits.ClassDecl.RawForeignKind = static_cast(kind); } /// Returns true if this class is any kind of "foreign class". /// /// \see getForeignClassKind bool isForeign() const { return getForeignClassKind() != ForeignKind::Normal; } /// Returns true if the class has designated initializers that are not listed /// in its members. /// /// This can occur, for example, if the class is an Objective-C class with /// initializers that cannot be represented in Swift. bool hasMissingDesignatedInitializers() const; void setHasMissingDesignatedInitializers(bool newValue = true) { Bits.ClassDecl.HasMissingDesignatedInitializers = newValue; } /// Returns true if the class has missing members that require vtable entries. /// /// In this case, the class cannot be subclassed, because we cannot construct /// the vtable for the subclass. bool hasMissingVTableEntries() const; void setHasMissingVTableEntries(bool newValue = true) { Bits.ClassDecl.HasMissingVTableEntries = newValue; } /// Find a method of a class that overrides a given method. /// Return nullptr, if no such method exists. AbstractFunctionDecl *findOverridingDecl( const AbstractFunctionDecl *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. AbstractFunctionDecl *findImplementingMethod( const AbstractFunctionDecl *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 Bits.ClassDecl.HasDestructorDecl; } /// Set the 'has destructor' flag. void setHasDestructor() { Bits.ClassDecl.HasDestructorDecl = 1; } /// Retrieve the destructor for this class. DestructorDecl *getDestructor(); /// Synthesize implicit, trivial destructor, add it to this ClassDecl /// and return it. void addImplicitDestructor(); /// 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); /// Figure out if this class has any @objc ancestors, in which case it should /// have implicitly @objc members. Note that a class with generic ancestry /// might have implicitly @objc members, but will never itself be @objc. ObjCClassKind checkObjCAncestry() const; /// The type of metaclass to use for a class. enum class MetaclassKind : uint8_t { ObjC, SwiftStub, }; /// Determine which sort of metaclass to use for this class MetaclassKind getMetaclassKind() const; /// Retrieve the name to use for this class when interoperating with /// the Objective-C runtime. StringRef getObjCRuntimeName(llvm::SmallVectorImpl &buffer) const; /// Returns the appropriate kind of entry point to generate for this class, /// based on its attributes. /// /// It is an error to call this on a class that does not have a /// *ApplicationMain attribute. ArtificialMainKind getArtificialMainKind() 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 GenericTypeDecl *D) { return D->getKind() == DeclKind::Class; } static bool classof(const NominalTypeDecl *D) { return D->getKind() == DeclKind::Class; } static bool classof(const DeclContext *C) { auto GTD = dyn_cast(C); return GTD && classof(static_cast(GTD)); } static bool classof(const IterableDeclContext *C) { auto NTD = dyn_cast(C); return NTD && classof(NTD); } /// Returns true if the decl uses the Objective-C generics model. /// /// This is true of imported Objective-C classes. bool usesObjCGenericsModel() const { return isObjC() && hasClangNode() && isGenericContext(); } /// True if the class is known to be implemented in Swift. bool hasKnownSwiftImplementation() const { return !hasClangNode(); } }; /// Describes whether a requirement refers to 'Self', for use in the /// is-inheritable and is-available-existential checks. struct SelfReferenceKind { bool result; bool parameter; bool requirement; bool other; /// The type does not refer to 'Self' at all. static SelfReferenceKind None() { return SelfReferenceKind(false, false, false, false); } /// The type refers to 'Self', but only as the result type of a method. static SelfReferenceKind Result() { return SelfReferenceKind(true, false, false, false); } /// The type refers to 'Self', but only as the parameter type of a method. static SelfReferenceKind Parameter() { return SelfReferenceKind(false, true, false, false); } /// The type refers to 'Self' within a same-type requiement. static SelfReferenceKind Requirement() { return SelfReferenceKind(false, false, true, false); } /// The type refers to 'Self' in a position that is invariant. static SelfReferenceKind Other() { return SelfReferenceKind(false, false, false, true); } SelfReferenceKind flip() const { return SelfReferenceKind(parameter, result, requirement, other); } SelfReferenceKind operator|=(SelfReferenceKind kind) { result |= kind.result; requirement |= kind.requirement; parameter |= kind.parameter; other |= kind.other; return *this; } operator bool() const { return result || parameter || requirement || other; } private: SelfReferenceKind(bool result, bool parameter, bool requirement, bool other) : result(result), parameter(parameter), requirement(requirement), other(other) { } }; /// ProtocolDecl - A declaration of a protocol, for example: /// /// protocol Drawable { /// func draw() /// } class ProtocolDecl final : public NominalTypeDecl { SourceLoc ProtocolLoc; /// The syntactic representation of the where clause in a protocol like /// `protocol ... where ... { ... }`. TrailingWhereClause *TrailingWhere; llvm::DenseMap DefaultWitnesses; /// The generic signature representing exactly the new requirements introduced /// by this protocol. const Requirement *RequirementSignature = nullptr; bool requiresClassSlow(); bool existentialConformsToSelfSlow(); bool existentialTypeSupportedSlow(LazyResolver *resolver); public: ProtocolDecl(DeclContext *DC, SourceLoc ProtocolLoc, SourceLoc NameLoc, Identifier Name, MutableArrayRef Inherited, TrailingWhereClause *TrailingWhere); using Decl::getASTContext; /// Retrieve the set of protocols inherited from this protocol. llvm::TinyPtrVector getInheritedProtocols() const; /// Retrieve the set of AssociatedTypeDecl members of this protocol; this /// saves loading the set of members in cases where there's no possibility of /// a protocol having nested types (ObjC protocols). llvm::TinyPtrVector getAssociatedTypeMembers() const; /// Walk all of the protocols inherited by this protocol, transitively, /// invoking the callback function for each protocol. /// /// \param fn The callback function that will be invoked for each inherited /// protocol. It can return \c Continue to continue the traversal, /// \c SkipChildren to avoid visiting the children of the given protocol /// but continue the search, and \c Stop to halt the search. /// /// \returns \c true if \c fn returned \c Stop for any protocol, \c false /// otherwise. bool walkInheritedProtocols( llvm::function_ref fn) const; /// \brief Determine whether this protocol inherits from the given ("super") /// protocol. bool inheritsFrom(const ProtocolDecl *Super) const; ProtocolType *getDeclaredType() const { return reinterpret_cast( NominalTypeDecl::getDeclaredType().getPointer()); } SourceLoc getStartLoc() const { return ProtocolLoc; } SourceRange getSourceRange() const { return SourceRange(ProtocolLoc, getBraces().End); } /// True if this protocol can only be conformed to by class types. bool requiresClass() const { if (Bits.ProtocolDecl.RequiresClassValid) return Bits.ProtocolDecl.RequiresClass; return const_cast(this)->requiresClassSlow(); } /// Specify that this protocol is class-bounded, e.g., because it was /// annotated with the 'class' keyword. void setRequiresClass(bool requiresClass = true) { Bits.ProtocolDecl.RequiresClassValid = true; Bits.ProtocolDecl.RequiresClass = requiresClass; } /// Determine whether an existential conforming to this protocol can be /// matched with a generic type parameter constrained to this protocol. /// This is only permitted if there is nothing "non-trivial" that we /// can do with the metatype, which means the protocol must not have /// any static methods and must be declared @objc. bool existentialConformsToSelf() const { if (Bits.ProtocolDecl.ExistentialConformsToSelfValid) return Bits.ProtocolDecl.ExistentialConformsToSelf; return const_cast(this) ->existentialConformsToSelfSlow(); } /// Find direct Self references within the given requirement. /// /// \param allowCovariantParameters If true, 'Self' is assumed to be /// covariant anywhere; otherwise, only in the return type of the top-level /// function type. /// /// \param skipAssocTypes If true, associated types of 'Self' are ignored; /// otherwise, they count as an 'other' usage of 'Self'. SelfReferenceKind findProtocolSelfReferences(const ValueDecl *decl, bool allowCovariantParameters, bool skipAssocTypes) const; /// Determine whether we are allowed to refer to an existential type /// conforming to this protocol. This is only permitted if the type of /// the member does not contain any associated types, and does not /// contain 'Self' in 'parameter' or 'other' position. bool isAvailableInExistential(const ValueDecl *decl) const; /// Determine whether we are allowed to refer to an existential type /// conforming to this protocol. This is only permitted if the types of /// all the members do not contain any associated types, and do not /// contain 'Self' in 'parameter' or 'other' position. bool existentialTypeSupported(LazyResolver *resolver) const { if (Bits.ProtocolDecl.ExistentialTypeSupportedValid) return Bits.ProtocolDecl.ExistentialTypeSupported; return const_cast(this) ->existentialTypeSupportedSlow(resolver); } /// Explicitly set the existentialTypeSupported flag, without computing /// it from members. Only called from deserialization, where the flag /// was stored in the serialized record. void setExistentialTypeSupported(bool supported) { Bits.ProtocolDecl.ExistentialTypeSupported = supported; Bits.ProtocolDecl.ExistentialTypeSupportedValid = true; } /// 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 (Bits.ProtocolDecl.KnownProtocol == 0) return None; return static_cast(Bits.ProtocolDecl.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"); Bits.ProtocolDecl.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(Bits.ProtocolDecl.Circularity); } /// Record the current stage of circularity checking. void setCircularityCheck(CircularityCheck circularity) { Bits.ProtocolDecl.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 Bits.ProtocolDecl.HasMissingRequirements; } void setHasMissingRequirements(bool newValue) { Bits.ProtocolDecl.HasMissingRequirements = newValue; } /// Returns the default witness for a requirement, or nullptr if there is /// no default. Witness getDefaultWitness(ValueDecl *requirement) const; /// Record the default witness for a requirement. void setDefaultWitness(ValueDecl *requirement, Witness witness); /// Retrieve the name to use for this protocol when interoperating /// with the Objective-C runtime. StringRef getObjCRuntimeName(llvm::SmallVectorImpl &buffer) const; /// Create the implicit generic parameter list for a protocol or /// extension thereof. GenericParamList *createGenericParams(DeclContext *dc); /// Create the generic parameters of this protocol if the haven't been /// created yet. void createGenericParamsIfMissing(); /// Retrieve the trailing where clause on this protocol, if it exists. TrailingWhereClause *getTrailingWhereClause() const { return TrailingWhere; } /// Retrieve the requirements that describe this protocol. /// /// These are the requirements including any inherited protocols /// and conformances for associated types that are introduced in this /// protocol. Requirements implied via any other protocol (e.g., inherited /// protocols of the inherited protocols) are not mentioned. The conformance /// requirements listed here become entries in the witness table. ArrayRef getRequirementSignature() const { assert(isRequirementSignatureComputed() && "getting requirement signature before computing it"); return llvm::makeArrayRef(RequirementSignature, Bits.ProtocolDecl.NumRequirementsInSignature); } /// Has the requirement signature been computed yet? bool isRequirementSignatureComputed() const { return RequirementSignature != nullptr; } void computeRequirementSignature(); void setRequirementSignature(ArrayRef requirements); // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() == DeclKind::Protocol; } static bool classof(const GenericTypeDecl *D) { return D->getKind() == DeclKind::Protocol; } static bool classof(const NominalTypeDecl *D) { return D->getKind() == DeclKind::Protocol; } static bool classof(const DeclContext *C) { auto GTD = dyn_cast(C); return GTD && classof(static_cast(GTD)); } static bool classof(const IterableDeclContext *C) { auto NTD = dyn_cast(C); return NTD && classof(NTD); } }; // Note that the values of these enums line up with %select values in // diagnostics. enum class AccessorKind { /// \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-family accessor for a property or /// subscript. It also has an addressor kind. IsAddressor = 5, /// \brief This is a mutableAddress-family accessor for a property /// or subscript. It also has an addressor kind. IsMutableAddressor = 6, }; /// The safety semantics of this addressor. enum class AddressorKind : unsigned char { /// \brief This is not an addressor. NotAddressor, /// \brief This is an unsafe addressor; it simply returns an address. Unsafe, /// \brief This is an owning addressor; it returns an AnyObject /// which should be released when the caller is done with the object. Owning, /// \brief This is an owning addressor; it returns a Builtin.NativeObject /// which should be released when the caller is done with the object. NativeOwning, /// \brief This is a pinning addressor; it returns a Builtin.NativeObject? /// which should be unpinned when the caller is done with the object. NativePinning, }; /// 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 is a VarDecl with storage defined by a property behavior; /// this access may initialize or reassign the storage based on dataflow. BehaviorStorage, /// 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, }; /// Information about a behavior instantiated by a storage declaration. /// /// TODO: Accessors, composed behaviors struct alignas(1 << 3) BehaviorRecord { // The behavior name. TypeRepr *ProtocolName; // The parameter expression, if any. Expr *Param; Optional Conformance = None; // The 'value' property from the behavior protocol that provides the property // implementation. VarDecl *ValueDecl = nullptr; // Storage declaration and initializer for use by definite initialization. VarDecl *StorageDecl = nullptr; ConcreteDeclRef InitStorageDecl = nullptr; bool needsInitialization() const { assert((bool)StorageDecl == (bool)InitStorageDecl && "DI state not consistent"); return StorageDecl != nullptr; } BehaviorRecord(TypeRepr *ProtocolName, Expr *Param) : ProtocolName(ProtocolName), Param(Param) {} SourceLoc getLoc() const; }; /// 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) When a stored property is accessed outside of the storage /// declaration's resilience domain, when the owning type or /// global variable 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 alignas(1 << 3) AddressorRecord { AccessorDecl *Address = nullptr; // User-defined address accessor AccessorDecl *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, AccessorDecl *addressor, AccessorDecl *mutableAddressor); struct alignas(1 << 3) GetSetRecord { SourceRange Braces; AccessorDecl *Get = nullptr; // User-defined getter AccessorDecl *Set = nullptr; // User-defined setter AccessorDecl *MaterializeForSet = nullptr; // optional materializeForSet accessor AddressorRecord *getAddressors() { // Relies on not-strictly-portable ABI layout assumptions. return reinterpret_cast(this) - 1; } }; void configureGetSetRecord(GetSetRecord *getSetRecord, AccessorDecl *getter, AccessorDecl *setter, AccessorDecl *materializeForSet); void configureSetRecord(GetSetRecord *getSetInfo, AccessorDecl *setter, AccessorDecl *materializeForSet); struct ObservingRecord : GetSetRecord { AccessorDecl *WillSet = nullptr; // willSet(value): AccessorDecl *DidSet = nullptr; // didSet: }; void configureObservingRecord(ObservingRecord *record, AccessorDecl *willSet, AccessorDecl *didSet); llvm::PointerIntPair> GetSetInfo; llvm::PointerIntPair> BehaviorInfo; ObservingRecord &getDidSetInfo() const { assert(hasObservers()); return *static_cast(GetSetInfo.getPointer()); } AddressorRecord &getAddressorInfo() const { assert(hasAddressors()); return *GetSetInfo.getPointer()->getAddressors(); } void setStorageKind(StorageKindTy K) { Bits.AbstractStorageDecl.StorageKind = unsigned(K); } protected: AbstractStorageDecl(DeclKind Kind, DeclContext *DC, DeclName Name, SourceLoc NameLoc) : ValueDecl(Kind, DC, Name, NameLoc), OverriddenDecl(nullptr) { Bits.AbstractStorageDecl.StorageKind = Stored; Bits.AbstractStorageDecl.IsGetterMutating = false; Bits.AbstractStorageDecl.IsSetterMutating = true; Bits.AbstractStorageDecl.Overridden = false; } public: /// \brief Should this declaration be treated as if annotated with transparent /// attribute. bool isTransparent() const; /// \brief Determine whether this storage is a static member, if it /// is a member. Currently only variables can be static. inline bool isStatic() const; // defined in this header /// \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) Bits.AbstractStorageDecl.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"); } /// \brief Return true if reading this storage requires the ability to /// modify the base value. bool isGetterMutating() const { return Bits.AbstractStorageDecl.IsGetterMutating; } void setIsGetterMutating(bool isMutating) { Bits.AbstractStorageDecl.IsGetterMutating = isMutating; } /// \brief Return true if modifying this storage requires the ability to /// modify the base value. bool isSetterMutating() const { return Bits.AbstractStorageDecl.IsSetterMutating; } void setIsSetterMutating(bool isMutating) { Bits.AbstractStorageDecl.IsSetterMutating = isMutating; } AccessorDecl *getAccessorFunction(AccessorKind accessor) const; /// \brief Push all of the accessor functions associated with this VarDecl /// onto `decls`. void getAllAccessorFunctions(SmallVectorImpl &decls) const; /// \brief Turn this into a computed variable, providing a getter and setter. void makeComputed(SourceLoc LBraceLoc, AccessorDecl *Get, AccessorDecl *Set, AccessorDecl *MaterializeForSet, SourceLoc RBraceLoc); /// \brief Turn this into a computed object, providing a getter and a mutable /// addressor. void makeComputedWithMutableAddress(SourceLoc lbraceLoc, AccessorDecl *getter, AccessorDecl *setter, AccessorDecl *materializeForSet, AccessorDecl *mutableAddressor, SourceLoc rbraceLoc); /// \brief Add trivial accessors to this Stored or Addressed object. void addTrivialAccessors(AccessorDecl *Get, AccessorDecl *Set, AccessorDecl *MaterializeForSet); /// \brief Turn this into a stored-with-observers var, providing the /// didSet/willSet specifiers. void makeStoredWithObservers(SourceLoc LBraceLoc, AccessorDecl *WillSet, AccessorDecl *DidSet, SourceLoc RBraceLoc); /// \brief Turn this into an inherited-with-observers var, providing /// the didSet/willSet specifiers. void makeInheritedWithObservers(SourceLoc LBraceLoc, AccessorDecl *WillSet, AccessorDecl *DidSet, SourceLoc RBraceLoc); /// \brief Turn this into an addressed var. void makeAddressed(SourceLoc LBraceLoc, AccessorDecl *Addressor, AccessorDecl *MutableAddressor, SourceLoc RBraceLoc); /// \brief Turn this into an addressed var with observing accessors. void makeAddressedWithObservers(SourceLoc LBraceLoc, AccessorDecl *Addressor, AccessorDecl *MutableAddressor, AccessorDecl *WillSet, AccessorDecl *DidSet, SourceLoc RBraceLoc); /// \brief Specify the synthesized get/set functions for a /// StoredWithObservers or AddressedWithObservers var. This is used by Sema. void setObservingAccessors(AccessorDecl *Get, AccessorDecl *Set, AccessorDecl *MaterializeForSet); /// \brief Add a setter to an existing Computed var. /// /// This should only be used by the ClangImporter. void setComputedSetter(AccessorDecl *Set); /// \brief Add a behavior to a property. void addBehavior(TypeRepr *Type, Expr *Param); /// \brief Set a materializeForSet accessor for this declaration. /// /// This should only be used by Sema. void setMaterializeForSetFunc(AccessorDecl *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. AccessorDecl *getGetter() const { if (auto info = GetSetInfo.getPointer()) return info->Get; return nullptr; } /// \brief Retrieve the setter used to mutate the value of this variable. AccessorDecl *getSetter() const { if (auto info = GetSetInfo.getPointer()) return info->Set; return nullptr; } AccessLevel getSetterFormalAccess() const { assert(hasAccess()); assert(GetSetInfo.getInt().hasValue()); return GetSetInfo.getInt().getValue(); } void setSetterAccess(AccessLevel accessLevel) { assert(!GetSetInfo.getInt().hasValue()); overwriteSetterAccess(accessLevel); } void overwriteSetterAccess(AccessLevel accessLevel); /// \brief Retrieve the materializeForSet function, if this /// declaration has one. AccessorDecl *getMaterializeForSetFunc() const { if (auto info = GetSetInfo.getPointer()) return info->MaterializeForSet; return nullptr; } /// \brief Return the decl for the 'address' accessor if it /// exists; this is only valid on a declaration with addressors. AccessorDecl *getAddressor() const { return getAddressorInfo().Address; } /// \brief Return the decl for the 'mutableAddress' accessors if /// it exists; this is only valid on a declaration with addressors. AccessorDecl *getMutableAddressor() const { return getAddressorInfo().MutableAddress; } /// \brief Return the appropriate addressor for the given access kind. AccessorDecl *getAddressorForAccess(AccessKind accessKind) const { if (accessKind == AccessKind::Read) return getAddressor(); return getMutableAddressor(); } /// \brief Return the decl for the willSet specifier if it exists, this is /// only valid on a declaration with Observing storage. AccessorDecl *getWillSetFunc() const { return getDidSetInfo().WillSet; } /// \brief Return the decl for the didSet specifier if it exists, this is /// only valid on a declaration with Observing storage. AccessorDecl *getDidSetFunc() const { return getDidSetInfo().DidSet; } /// Given that this is an Objective-C property or subscript declaration, /// produce its getter selector. ObjCSelector getObjCGetterSelector(Identifier preferredName = Identifier()) const; /// Given that this is an Objective-C property or subscript declaration, /// produce its setter selector. ObjCSelector getObjCSetterSelector(Identifier preferredName = Identifier()) const; AbstractStorageDecl *getOverriddenDecl() const { return OverriddenDecl; } void setOverriddenDecl(AbstractStorageDecl *over) { // FIXME: Hack due to broken class circularity checking. if (over == this) return; OverriddenDecl = over; over->setIsOverridden(); } /// The declaration has been overridden in the module /// /// Resolved during type checking void setIsOverridden() { Bits.AbstractStorageDecl.Overridden = true; } /// Whether the declaration is later overridden in the module /// /// Overrides are resolved during type checking; only query this field after /// the whole module has been checked bool isOverridden() const { return Bits.AbstractStorageDecl.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; /// \brief Should this declaration behave as if it must be accessed /// resiliently, even when we're building a non-resilient module? /// /// This is used for diagnostics, because we do not want a behavior /// change between builds with resilience enabled and disabled. bool isFormallyResilient() const; /// \brief Do we need to use resilient access patterns outside of this /// property's resilience domain? bool isResilient() const; /// \brief Do we need to use resilient access patterns when accessing this /// property from the given module? bool isResilient(ModuleDecl *M, ResilienceExpansion expansion) const; /// Returns the interface type of elements of storage represented by this /// declaration. /// /// For variables, this is the type of the variable itself. /// For subscripts, this is the type of the subscript element. Type getStorageInterfaceType() const; /// Does the storage use a behavior? bool hasBehavior() const { return BehaviorInfo.getPointer() != nullptr; } /// Does the storage use a behavior, and require definite initialization /// analysis. bool hasBehaviorNeedingInitialization() const { if (auto behavior = getBehavior()) { return behavior->needsInitialization(); } return false; } /// Get the behavior info. const BehaviorRecord *getBehavior() const { return BehaviorInfo.getPointer(); } BehaviorRecord *getMutableBehavior() { return BehaviorInfo.getPointer(); } // 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 { public: enum class Specifier : uint8_t { // For Var Decls Let = 0, Var = 1, // For Param Decls Owned = Let, InOut = 2, Shared = 3, }; protected: llvm::PointerUnion ParentPattern; VarDecl(DeclKind Kind, bool IsStatic, Specifier Sp, bool IsCaptureList, SourceLoc NameLoc, Identifier Name, Type Ty, DeclContext *DC) : AbstractStorageDecl(Kind, DC, Name, NameLoc) { Bits.VarDecl.IsStatic = IsStatic; Bits.VarDecl.Specifier = static_cast(Sp); Bits.VarDecl.IsCaptureList = IsCaptureList; Bits.VarDecl.IsDebuggerVar = false; Bits.VarDecl.HasNonPatternBindingInit = false; setType(Ty); } /// This is the type specified, including location information. TypeLoc typeLoc; Type typeInContext; public: VarDecl(bool IsStatic, Specifier Sp, bool IsCaptureList, SourceLoc NameLoc, Identifier Name, Type Ty, DeclContext *DC) : VarDecl(DeclKind::Var, IsStatic, Sp, IsCaptureList, NameLoc, Name, Ty, DC) {} SourceRange getSourceRange() const; Identifier getName() const { return getFullName().getBaseIdentifier(); } /// Returns the string for the base name, or "_" if this is unnamed. StringRef getNameStr() const { assert(!getFullName().isSpecial() && "Cannot get string for special names"); return hasName() ? getBaseName().getIdentifier().str() : "_"; } TypeLoc &getTypeLoc() { return typeLoc; } TypeLoc getTypeLoc() const { return typeLoc; } bool hasType() const { // We have a type if either the type has been computed already or if // this is a deserialized declaration with an interface type. return !typeInContext.isNull(); } /// Get the type of the variable within its context. If the context is generic, /// this will use archetypes. Type getType() const; /// Set the type of the variable within its context. void setType(Type t); void markInvalid(); /// Retrieve the source range of the variable type, or an invalid range if the /// variable's type is not explicitly written in the source. /// /// 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 and null base to check if it's always settable. bool isSettable(const DeclContext *UseDC, const DeclRefExpr *base = nullptr) const; /// Return the parent pattern binding that may provide an initializer for this /// VarDecl. This returns null if there is none associated with the VarDecl. PatternBindingDecl *getParentPatternBinding() const { return ParentPattern.dyn_cast(); } void setParentPatternBinding(PatternBindingDecl *PBD) { ParentPattern = PBD; } /// Return the Pattern involved in initializing this VarDecl. However, recall /// that the Pattern may be involved in initializing more than just this one /// vardecl. For example, if this is a VarDecl for "x", the pattern may be /// "(x, y)" and the initializer on the PatternBindingDecl may be "(1,2)" or /// "foo()". /// /// If this has no parent pattern binding decl or statement associated, it /// returns null. /// Pattern *getParentPattern() const; /// Return the statement that owns the pattern associated with this VarDecl, /// if one exists. Stmt *getParentPatternStmt() const { return ParentPattern.dyn_cast(); } void setParentPatternStmt(Stmt *S) { ParentPattern = S; } /// Return the initializer involved in this VarDecl. Recall that the /// initializer may be involved in initializing more than just this one /// vardecl though. For example, if this is a VarDecl for "x", the pattern /// may be "(x, y)" and the initializer on the PatternBindingDecl may be /// "(1,2)" or "foo()". /// /// If this has no parent pattern binding decl associated, or if that pattern /// binding has no initial value, this returns null. /// Expr *getParentInitializer() const { if (auto *PBD = getParentPatternBinding()) return PBD->getPatternEntryForVarDecl(this).getInit(); return nullptr; } VarDecl *getOverriddenDecl() const { return cast_or_null(AbstractStorageDecl::getOverriddenDecl()); } /// Determine whether this declaration is an anonymous closure parameter. bool isAnonClosureParam() const; /// Return the raw specifier value for this property or parameter. Specifier getSpecifier() const { return static_cast(Bits.VarDecl.Specifier); } void setSpecifier(Specifier Spec) { Bits.VarDecl.Specifier = static_cast(Spec); } /// Is the type of this parameter 'inout'? /// /// FIXME(Remove InOut): This is only valid on ParamDecls but multiple parts /// of the compiler check ParamDecls and VarDecls along the same paths. bool isInOut() const { // FIXME: Re-enable this assertion and fix callers. // assert((getKind() == DeclKind::Param) && "querying 'inout' on var decl?"); return getSpecifier() == Specifier::InOut; } /// Is this a type ('static') variable? bool isStatic() const { return Bits.VarDecl.IsStatic; } void setStatic(bool IsStatic) { Bits.VarDecl.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 getSpecifier() == Specifier::Let; } /// Is this an immutable 'shared' property? bool isShared() const { return getSpecifier() == Specifier::Shared; } /// Is this an element in a capture list? bool isCaptureList() const { return Bits.VarDecl.IsCaptureList; } /// Return true if this vardecl has an initial value bound to it in a way /// that isn't represented in the AST with an initializer in the pattern /// binding. This happens in cases like "for i in ...", switch cases, etc. bool hasNonPatternBindingInit() const { return Bits.VarDecl.HasNonPatternBindingInit; } void setHasNonPatternBindingInit(bool V = true) { Bits.VarDecl.HasNonPatternBindingInit = V; } /// Is this a special debugger variable? bool isDebuggerVar() const { return Bits.VarDecl.IsDebuggerVar; } void setDebuggerVar(bool IsDebuggerVar) { Bits.VarDecl.IsDebuggerVar = IsDebuggerVar; } /// Return the Objective-C runtime name for this property. Identifier getObjCPropertyName() const; /// Retrieve the default Objective-C selector for the getter of a /// property of the given name. static ObjCSelector getDefaultObjCGetterSelector(ASTContext &ctx, Identifier propertyName); /// Retrieve the default Objective-C selector for the setter of a /// property of the given name. static ObjCSelector getDefaultObjCSetterSelector(ASTContext &ctx, Identifier propertyName); /// If this is a simple 'let' constant, emit a note with a fixit indicating /// that it can be rewritten to a 'var'. This is used in situations where the /// compiler detects obvious attempts to mutate a constant. void emitLetToVarNoteIfSimple(DeclContext *UseDC) const; /// Returns true if the name is the self identifier and is implicit. bool isSelfParameter() const; // 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; SourceLoc SpecifierLoc; struct StoredDefaultArgument { Expr *DefaultArg = nullptr; Initializer *InitContext = nullptr; }; /// The default value, if any, along with whether this is varargs. llvm::PointerIntPair DefaultValueAndIsVariadic; public: ParamDecl(VarDecl::Specifier specifier, SourceLoc specifierLoc, SourceLoc argumentNameLoc, Identifier argumentName, SourceLoc parameterNameLoc, Identifier parameterName, Type ty, DeclContext *dc); /// Clone constructor, allocates a new ParamDecl identical to the first. /// Intentionally not defined as a typical copy constructor to avoid /// accidental copies. ParamDecl(ParamDecl *PD, bool withTypes); /// 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; } /// Retrieve the parameter type flags corresponding to the declaration of /// this parameter's argument type. ParameterTypeFlags getParameterFlags() const; SourceLoc getSpecifierLoc() const { return SpecifierLoc; } bool isTypeLocImplicit() const { return Bits.ParamDecl.IsTypeLocImplicit; } void setIsTypeLocImplicit(bool val) { Bits.ParamDecl.IsTypeLocImplicit = val; } DefaultArgumentKind getDefaultArgumentKind() const { return static_cast(Bits.ParamDecl.defaultArgumentKind); } bool isDefaultArgument() const { return getDefaultArgumentKind() != DefaultArgumentKind::None; } void setDefaultArgumentKind(DefaultArgumentKind K) { Bits.ParamDecl.defaultArgumentKind = static_cast(K); } Expr *getDefaultValue() const { if (auto stored = DefaultValueAndIsVariadic.getPointer()) return stored->DefaultArg; return nullptr; } void setDefaultValue(Expr *E); Initializer *getDefaultArgumentInitContext() const { if (auto stored = DefaultValueAndIsVariadic.getPointer()) return stored->InitContext; return nullptr; } void setDefaultArgumentInitContext(Initializer *initContext); /// Whether or not this parameter is varargs. bool isVariadic() const { return DefaultValueAndIsVariadic.getInt(); } void setVariadic(bool value = true) {DefaultValueAndIsVariadic.setInt(value);} /// Remove the type of this varargs element designator, without the array /// type wrapping it. A parameter like "Int..." will have formal parameter /// type of "[Int]" and this returns "Int". static Type getVarargBaseTy(Type VarArgT); /// Remove the type of this varargs element designator, without the array /// type wrapping it. Type getVarargBaseTy() const { assert(isVariadic()); return getVarargBaseTy(getInterfaceType()); } SourceRange getSourceRange() const; /// Create an implicit 'self' decl for a method in the specified decl context. /// If 'static' is true, then this is self for a static method in the type. /// /// Note that this decl is created, but it is returned with an incorrect /// DeclContext that needs to be set correctly. This is automatically handled /// when a function is created with this as part of its argument list. /// For a generic context, this also gives the parameter an unbound generic /// type with the expectation that type-checking will fill in the context /// generic parameters. static ParamDecl *createUnboundSelf(SourceLoc loc, DeclContext *DC); /// Create an implicit 'self' decl for a method in the specified decl context. /// If 'static' is true, then this is self for a static method in the type. /// /// Note that this decl is created, but it is returned with an incorrect /// DeclContext that needs to be set correctly. This is automatically handled /// when a function is created with this as part of its argument list. static ParamDecl *createSelf(SourceLoc loc, DeclContext *DC, bool isStatic = false, bool isInOut = false); // 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 GenericContext, public AbstractStorageDecl { SourceLoc ArrowLoc; ParameterList *Indices; TypeLoc ElementTy; public: SubscriptDecl(DeclName Name, SourceLoc SubscriptLoc, ParameterList *Indices, SourceLoc ArrowLoc, TypeLoc ElementTy, DeclContext *Parent, GenericParamList *GenericParams) : GenericContext(DeclContextKind::SubscriptDecl, Parent), AbstractStorageDecl(DeclKind::Subscript, Parent, Name, SubscriptLoc), ArrowLoc(ArrowLoc), Indices(nullptr), ElementTy(ElementTy) { setIndices(Indices); setGenericParams(GenericParams); } SourceLoc getSubscriptLoc() const { return getNameLoc(); } SourceLoc getStartLoc() const { return getSubscriptLoc(); } SourceRange getSourceRange() const; SourceRange getSignatureSourceRange() const; /// \brief Retrieve the indices for this subscript operation. ParameterList *getIndices() { return Indices; } const ParameterList *getIndices() const { return Indices; } void setIndices(ParameterList *p); /// Retrieve the interface type of the indices. Type getIndicesInterfaceType() const; /// \brief Retrieve the type of the element referenced by a subscript /// operation. Type getElementInterfaceType() const; 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; } static bool classof(const DeclContext *DC) { return DC->getContextKind() == DeclContextKind::SubscriptDecl; } using DeclContext::operator new; using Decl::getASTContext; }; /// Encodes imported-as-member status for C functions that get imported /// as methods. class ImportAsMemberStatus { friend class AbstractFunctionDecl; // non-0 denotes import-as-member. 1 denotes no self index. n+2 denotes self // index of n uint8_t rawValue; public: ImportAsMemberStatus(uint8_t rawValue = 0) : rawValue(rawValue) {} uint8_t getRawValue() const { return rawValue; } bool isImportAsMember() const { return rawValue != 0; } bool isInstance() const { return rawValue >= 2; } bool isStatic() const { return rawValue == 1; } uint8_t getSelfIndex() const { assert(isInstance() && "not set"); return rawValue - 2; } void setStatic() { assert(!isStatic() && "already set"); rawValue = 1; } void setSelfIndex(uint8_t idx) { assert(!isImportAsMember() && "already set"); assert(idx <= UINT8_MAX-2 && "out of bounds"); rawValue = idx + 2; } }; /// \brief Base class for function-like declarations. class AbstractFunctionDecl : public GenericContext, public ValueDecl { 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 is a memberwise initializer that will be synthesized by SILGen. MemberwiseInitializer // This enum currently needs to fit in a 3-bit bitfield. }; BodyKind getBodyKind() const { return BodyKind(Bits.AbstractFunctionDecl.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; }; CaptureInfo Captures; /// Location of the 'throws' token. SourceLoc ThrowsLoc; AbstractFunctionDecl(DeclKind Kind, DeclContext *Parent, DeclName Name, SourceLoc NameLoc, bool Throws, SourceLoc ThrowsLoc, unsigned NumParameterLists, GenericParamList *GenericParams) : GenericContext(DeclContextKind::AbstractFunctionDecl, Parent), ValueDecl(Kind, Parent, Name, NameLoc), Body(nullptr), ThrowsLoc(ThrowsLoc) { setBodyKind(BodyKind::None); setGenericParams(GenericParams); Bits.AbstractFunctionDecl.NumParameterLists = NumParameterLists; Bits.AbstractFunctionDecl.Overridden = false; Bits.AbstractFunctionDecl.Throws = Throws; Bits.AbstractFunctionDecl.NeedsNewVTableEntry = false; Bits.AbstractFunctionDecl.HasComputedNeedsNewVTableEntry = false; Bits.AbstractFunctionDecl.DefaultArgumentResilienceExpansion = unsigned(ResilienceExpansion::Maximal); // Verify no bitfield truncation. assert(Bits.AbstractFunctionDecl.NumParameterLists == NumParameterLists); } void setBodyKind(BodyKind K) { Bits.AbstractFunctionDecl.BodyKind = unsigned(K); } public: /// Returns the string for the base name, or "_" if this is unnamed. StringRef getNameStr() const { assert(!getFullName().isSpecial() && "Cannot get string for special names"); return hasName() ? getBaseName().getIdentifier().str() : "_"; } /// \brief Should this declaration be treated as if annotated with transparent /// attribute. bool isTransparent() const; // Expose our import as member status ImportAsMemberStatus getImportAsMemberStatus() const { return ImportAsMemberStatus(Bits.AbstractFunctionDecl.IAMStatus); } bool isImportAsMember() const { return getImportAsMemberStatus().isImportAsMember(); } bool isImportAsInstanceMember() const { return getImportAsMemberStatus().isInstance(); } bool isImportAsStaticMember() const { return getImportAsMemberStatus().isStatic(); } uint8_t getSelfIndex() const { return getImportAsMemberStatus().getSelfIndex(); } void setImportAsStaticMember() { auto newValue = getImportAsMemberStatus(); newValue.setStatic(); Bits.AbstractFunctionDecl.IAMStatus = newValue.getRawValue(); } void setSelfIndex(uint8_t idx) { auto newValue = getImportAsMemberStatus(); newValue.setSelfIndex(idx); Bits.AbstractFunctionDecl.IAMStatus = newValue.getRawValue(); } public: /// Retrieve the location of the 'throws' keyword, if present. SourceLoc getThrowsLoc() const { return ThrowsLoc; } /// Returns true if the function body throws. bool hasThrows() const { return Bits.AbstractFunctionDecl.Throws; } // FIXME: Hack that provides names with keyword arguments for accessors. DeclName getEffectiveFullName() 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 && "cannot set a body if it was skipped"); Body = S; setBodyKind(NewBodyKind); } /// \brief Note that the body was skipped for this function. Function body /// cannot 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); } /// Note that this is a memberwise initializer and thus the body will be /// generated by SILGen. void setIsMemberwiseInitializer() { assert(getBodyKind() == BodyKind::None); assert(isa(this)); setBodyKind(BodyKind::MemberwiseInitializer); } /// 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; } bool isMemberwiseInitializer() const { return getBodyKind() == BodyKind::MemberwiseInitializer; } void setNeedsNewVTableEntry(bool value) { Bits.AbstractFunctionDecl.HasComputedNeedsNewVTableEntry = true; Bits.AbstractFunctionDecl.NeedsNewVTableEntry = value; } bool needsNewVTableEntry() const { if (!Bits.AbstractFunctionDecl.HasComputedNeedsNewVTableEntry) const_cast(this)->computeNeedsNewVTableEntry(); return Bits.AbstractFunctionDecl.NeedsNewVTableEntry; } private: void computeNeedsNewVTableEntry(); public: /// 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(DeclName preferredName = DeclName()) const; /// Determine whether the given method would produce an Objective-C /// instance method. bool isObjCInstanceMethod() 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 an argument is an API name by default /// depending on the function context. bool argumentNameIsAPIByDefault() const; /// \brief Returns the "natural" number of argument clauses taken by this /// function. This value is one for free-standing functions, and two for /// methods. unsigned getNumParameterLists() const { return Bits.AbstractFunctionDecl.NumParameterLists; } /// \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 getParameterLists(); ArrayRef getParameterLists() const { auto paramLists = const_cast(this)->getParameterLists(); return ArrayRef(paramLists.data(),paramLists.size()); } ParameterList *getParameterList(unsigned i) { return getParameterLists()[i]; } const ParameterList *getParameterList(unsigned i) const { return getParameterLists()[i]; } /// \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. const ParamDecl *getImplicitSelfDecl() const { return const_cast(this)->getImplicitSelfDecl(); } ParamDecl *getImplicitSelfDecl(); /// Retrieve the declaration that this method overrides, if any. AbstractFunctionDecl *getOverriddenDecl() const; /// Returns true if a function declaration overrides a given /// method from its direct or indirect superclass. bool isOverridingDecl(const AbstractFunctionDecl *method) const; /// Whether the declaration is later overridden in the module /// /// Overrides are resolved during type checking; only query this field after /// the whole module has been checked bool isOverridden() const { return Bits.AbstractFunctionDecl.Overridden; } /// The declaration has been overridden in the module /// /// Resolved during type checking void setIsOverridden() { Bits.AbstractFunctionDecl.Overridden = true; } /// The ResilienceExpansion for default arguments. /// /// In Swift 4 mode, default argument expressions are serialized, and must /// obey the restrictions imposed upon inlineable function bodies. ResilienceExpansion getDefaultArgumentResilienceExpansion() const { return ResilienceExpansion( Bits.AbstractFunctionDecl.DefaultArgumentResilienceExpansion); } /// Set the ResilienceExpansion for default arguments. void setDefaultArgumentResilienceExpansion(ResilienceExpansion expansion) { Bits.AbstractFunctionDecl.DefaultArgumentResilienceExpansion = unsigned(expansion); } /// Set information about the foreign error convention used by this /// declaration. void setForeignErrorConvention(const ForeignErrorConvention &convention); /// Get information about the foreign error convention used by this /// declaration, given that it is @objc and 'throws'. Optional getForeignErrorConvention() const; /// If this is a foreign C function imported as a method, get the index of /// the foreign parameter imported as `self`. If the function is imported /// as a static method, `-1` is returned to represent the `self` parameter /// being dropped altogether. `None` is returned for a normal function /// or method. Optional getForeignFunctionAsMethodSelfParameterIndex() const; 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; } /// True if the declaration is forced to be statically dispatched. bool hasForcedStaticDispatch() const; /// Get the interface type of this decl and remove the Self context. Type getMethodInterfaceType() const; using DeclContext::operator new; using Decl::getASTContext; }; class OperatorDecl; /// Note: These align with '%select's in diagnostics. enum class SelfAccessKind : uint8_t { NonMutating = 0, Mutating = 1, __Consuming = 2, }; /// 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; /// \brief If this FuncDecl is an accessor for a property, this indicates /// which property and what kind of accessor. llvm::PointerUnion OverriddenOrBehaviorParamDecl; OperatorDecl *Operator; protected: ParameterList **getParameterListBuffer(); // defined inline below ParameterList * const *getParameterListBuffer() const { return const_cast(this)->getParameterListBuffer(); } FuncDecl(DeclKind Kind, SourceLoc StaticLoc, StaticSpellingKind StaticSpelling, SourceLoc FuncLoc, DeclName Name, SourceLoc NameLoc, bool Throws, SourceLoc ThrowsLoc, unsigned NumParameterLists, GenericParamList *GenericParams, DeclContext *Parent) : AbstractFunctionDecl(Kind, Parent, Name, NameLoc, Throws, ThrowsLoc, NumParameterLists, GenericParams), StaticLoc(StaticLoc), FuncLoc(FuncLoc), OverriddenOrBehaviorParamDecl(), Operator(nullptr) { Bits.FuncDecl.IsStatic = StaticLoc.isValid() || StaticSpelling != StaticSpellingKind::None; Bits.FuncDecl.StaticSpelling = static_cast(StaticSpelling); assert(NumParameterLists > 0 && "Must have at least an empty tuple arg"); Bits.FuncDecl.HasDynamicSelf = false; Bits.FuncDecl.ForcedStaticDispatch = false; Bits.FuncDecl.SelfAccess = static_cast(SelfAccessKind::NonMutating); } private: static FuncDecl *createImpl(ASTContext &Context, SourceLoc StaticLoc, StaticSpellingKind StaticSpelling, SourceLoc FuncLoc, DeclName Name, SourceLoc NameLoc, bool Throws, SourceLoc ThrowsLoc, GenericParamList *GenericParams, unsigned NumParameterLists, 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, bool Throws, SourceLoc ThrowsLoc, GenericParamList *GenericParams, unsigned NumParameterLists, DeclContext *Parent); static FuncDecl *create(ASTContext &Context, SourceLoc StaticLoc, StaticSpellingKind StaticSpelling, SourceLoc FuncLoc, DeclName Name, SourceLoc NameLoc, bool Throws, SourceLoc ThrowsLoc, GenericParamList *GenericParams, ArrayRef ParameterLists, TypeLoc FnRetType, DeclContext *Parent, ClangNode ClangN = ClangNode()); Identifier getName() const { return getFullName().getBaseIdentifier(); } bool isStatic() const { return Bits.FuncDecl.IsStatic; } /// \returns the way 'static'/'class' was spelled in the source. StaticSpellingKind getStaticSpelling() const { return static_cast(Bits.FuncDecl.StaticSpelling); } /// \returns the way 'static'/'class' should be spelled for this declaration. StaticSpellingKind getCorrectStaticSpelling() const; void setStatic(bool IsStatic = true) { Bits.FuncDecl.IsStatic = IsStatic; } bool isMutating() const { return getSelfAccessKind() == SelfAccessKind::Mutating; } bool isNonMutating() const { return getSelfAccessKind() == SelfAccessKind::NonMutating; } bool isConsuming() const { return getSelfAccessKind() == SelfAccessKind::__Consuming; } TypeLoc getReturnTypeLoc() const { return FnRetType; } SelfAccessKind getSelfAccessKind() const { return static_cast(Bits.FuncDecl.SelfAccess); } void setSelfAccessKind(SelfAccessKind mod) { Bits.FuncDecl.SelfAccess = static_cast(mod); } /// \brief Returns the parameter lists(s) for the function definition. /// /// The number of "top-level" elements will match the number of argument names /// in the compound name of the function or constructor. MutableArrayRef getParameterLists() { return {getParameterListBuffer(), getNumParameterLists()}; } ArrayRef getParameterLists() const { return {getParameterListBuffer(), getNumParameterLists()}; } ParameterList *getParameterList(unsigned i) { return getParameterLists()[i]; } const ParameterList *getParameterList(unsigned i) const { return getParameterLists()[i]; } /// \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 ParameterLists, TypeLoc FnRetType); SourceLoc getStaticLoc() const { return StaticLoc; } SourceLoc getFuncLoc() const { return FuncLoc; } SourceLoc getStartLoc() const { return StaticLoc.isValid() && !isa(this) ? StaticLoc : FuncLoc; } SourceRange getSourceRange() const; TypeLoc &getBodyResultTypeLoc() { return FnRetType; } const TypeLoc &getBodyResultTypeLoc() const { return FnRetType; } /// Retrieve the result interface type of this function. Type getResultInterfaceType() const; /// isUnaryOperator - Determine whether this is a unary operator /// implementation. This check is a syntactic rather than type-based check, /// which looks at the number of parameters specified, in order to allow /// for the definition of unary operators on tuples, as in: /// /// prefix func + (param : (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. This check is a syntactic rather than type-based check, /// which looks at the number of parameters specified, in order to allow /// distinguishing a binary operator from a unary operator on tuples, as in: /// /// prefix func + (_:(a:Int, b:Int)) // unary operator +(1,2) /// infix func + (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; /// Determine whether this function has a dynamic \c Self return /// type. bool hasDynamicSelf() const { return Bits.FuncDecl.HasDynamicSelf; } /// Set whether this function has a dynamic \c Self return or not. void setDynamicSelf(bool hasDynamicSelf) { Bits.FuncDecl.HasDynamicSelf = hasDynamicSelf; } void getLocalCaptures(SmallVectorImpl &Result) const { return getCaptureInfo().getLocalCaptures(Result); } /// Get the supertype method this method overrides, if any. FuncDecl *getOverriddenDecl() const { return OverriddenOrBehaviorParamDecl.dyn_cast(); } void setOverriddenDecl(FuncDecl *over) { // FIXME: Hack due to broken class circularity checking. if (over == this) return; // A function cannot be an override if it is also a derived global decl // (since derived decls are at global scope). assert((!OverriddenOrBehaviorParamDecl || OverriddenOrBehaviorParamDecl.get() == over) && "function can only be one of override, derived, or behavior param"); OverriddenOrBehaviorParamDecl = over; over->setIsOverridden(); } /// Get the property behavior this function serves as a parameter for, if /// any. BehaviorRecord *getParamBehavior() const { return OverriddenOrBehaviorParamDecl .dyn_cast(); } void setParamBehavior(BehaviorRecord *behavior) { // Behavior param blocks cannot be overrides or derived. assert((!OverriddenOrBehaviorParamDecl || OverriddenOrBehaviorParamDecl.is()) && "function can only be one of override, derived, or behavior param"); OverriddenOrBehaviorParamDecl = behavior; } 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 the function is forced to be statically dispatched. bool hasForcedStaticDispatch() const { return Bits.FuncDecl.ForcedStaticDispatch; } void setForcedStaticDispatch(bool flag) { Bits.FuncDecl.ForcedStaticDispatch = flag; } static bool classof(const Decl *D) { return D->getKind() == DeclKind::Func || D->getKind() == DeclKind::Accessor; } 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; } /// True if the function is a defer body. bool isDeferBody() const; /// Perform basic checking to determine whether the @IBAction attribute can /// be applied to this function. bool isPotentialIBActionTarget() const; }; /// \brief This represents an accessor function, such as a getter or setter. class AccessorDecl final : public FuncDecl { /// Location of the accessor keyword, e.g. 'set'. SourceLoc AccessorKeywordLoc; AbstractStorageDecl *Storage; AccessorDecl(SourceLoc declLoc, SourceLoc accessorKeywordLoc, AccessorKind accessorKind, AddressorKind addressorKind, AbstractStorageDecl *storage, SourceLoc staticLoc, StaticSpellingKind staticSpelling, bool throws, SourceLoc throwsLoc, unsigned numParameterLists, GenericParamList *genericParams, DeclContext *parent) : FuncDecl(DeclKind::Accessor, staticLoc, staticSpelling, /*func loc*/ declLoc, /*name*/ Identifier(), /*name loc*/ declLoc, throws, throwsLoc, numParameterLists, genericParams, parent), AccessorKeywordLoc(accessorKeywordLoc), Storage(storage) { Bits.AccessorDecl.AccessorKind = unsigned(accessorKind); Bits.AccessorDecl.AddressorKind = unsigned(addressorKind); } static AccessorDecl *createImpl(ASTContext &ctx, SourceLoc declLoc, SourceLoc accessorKeywordLoc, AccessorKind accessorKind, AddressorKind addressorKind, AbstractStorageDecl *storage, SourceLoc staticLoc, StaticSpellingKind staticSpelling, bool throws, SourceLoc throwsLoc, unsigned numParameterLists, GenericParamList *genericParams, DeclContext *parent, ClangNode clangNode); public: static AccessorDecl *createDeserialized(ASTContext &ctx, SourceLoc declLoc, SourceLoc accessorKeywordLoc, AccessorKind accessorKind, AddressorKind addressorKind, AbstractStorageDecl *storage, SourceLoc staticLoc, StaticSpellingKind staticSpelling, bool throws, SourceLoc throwsLoc, GenericParamList *genericParams, unsigned numParameterLists, DeclContext *parent); static AccessorDecl *create(ASTContext &ctx, SourceLoc declLoc, SourceLoc accessorKeywordLoc, AccessorKind accessorKind, AddressorKind addressorKind, AbstractStorageDecl *storage, SourceLoc staticLoc, StaticSpellingKind staticSpelling, bool throws, SourceLoc throwsLoc, GenericParamList *genericParams, ArrayRef parameterLists, TypeLoc fnRetType, DeclContext *parent, ClangNode clangNode = ClangNode()); SourceLoc getAccessorKeywordLoc() const { return AccessorKeywordLoc; } AbstractStorageDecl *getStorage() const { return Storage; } AccessorKind getAccessorKind() const { return AccessorKind(Bits.AccessorDecl.AccessorKind); } AddressorKind getAddressorKind() const { return AddressorKind(Bits.AccessorDecl.AddressorKind); } bool isGetter() const { return getAccessorKind() == AccessorKind::IsGetter; } bool isSetter() const { return getAccessorKind() == AccessorKind::IsSetter; } bool isMaterializeForSet() const { return getAccessorKind() == AccessorKind::IsMaterializeForSet; } bool isAnyAddressor() const { auto kind = getAccessorKind(); return kind == AccessorKind::IsAddressor || kind == AccessorKind::IsMutableAddressor; } /// isGetterOrSetter - Determine whether this is specifically a getter or /// a setter, as opposed to some other kind of accessor. /// /// For example, only getters and setters can be exposed to Objective-C. bool isGetterOrSetter() const { return isGetter() || isSetter(); } bool isObservingAccessor() const { return getAccessorKind() == AccessorKind::IsDidSet || getAccessorKind() == AccessorKind::IsWillSet; } static bool classof(const Decl *D) { return D->getKind() == DeclKind::Accessor; } 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; } }; inline ParameterList **FuncDecl::getParameterListBuffer() { if (!isa(this)) { assert(getKind() == DeclKind::Func && "no new kinds of functions"); return reinterpret_cast(this+1); } return reinterpret_cast(static_cast(this)+1); } /// \brief This represents a 'case' declaration in an 'enum', which may declare /// one or more individual comma-separated EnumElementDecls. class EnumCaseDecl final : public Decl, private llvm::TrailingObjects { friend TrailingObjects; SourceLoc CaseLoc; EnumCaseDecl(SourceLoc CaseLoc, ArrayRef Elements, DeclContext *DC) : Decl(DeclKind::EnumCase, DC), CaseLoc(CaseLoc) { Bits.EnumCaseDecl.NumElements = Elements.size(); std::uninitialized_copy(Elements.begin(), Elements.end(), getTrailingObjects()); } public: static EnumCaseDecl *create(SourceLoc CaseLoc, ArrayRef Elements, DeclContext *DC); /// Get the list of elements declared in this case. ArrayRef getElements() const { return {getTrailingObjects(), Bits.EnumCaseDecl.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, bool HasArgumentType, SourceLoc EqualsLoc, LiteralExpr *RawValueExpr, DeclContext *DC) : ValueDecl(DeclKind::EnumElement, DC, Name, IdentifierLoc), ArgumentType(ArgumentType), EqualsLoc(EqualsLoc), RawValueExpr(RawValueExpr) { Bits.EnumElementDecl.Recursiveness = static_cast(ElementRecursiveness::NotRecursive); Bits.EnumElementDecl.HasArgumentType = HasArgumentType; } Identifier getName() const { return getFullName().getBaseIdentifier(); } /// Returns the string for the base name, or "_" if this is unnamed. StringRef getNameStr() const { assert(!getFullName().isSpecial() && "Cannot get string for special names"); return hasName() ? getBaseName().getIdentifier().str() : "_"; } /// \returns false if there was an error during the computation rendering the /// EnumElementDecl invalid, true otherwise. bool computeType(); 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()); } /// Return the containing EnumCaseDecl. EnumCaseDecl *getParentCase() const; SourceLoc getStartLoc() const { return getNameLoc(); } SourceRange getSourceRange() const; ElementRecursiveness getRecursiveness() const { return static_cast(Bits.EnumElementDecl.Recursiveness); } void setRecursiveness(ElementRecursiveness recursiveness) { Bits.EnumElementDecl.Recursiveness = static_cast(recursiveness); } bool hasAssociatedValues() const { return Bits.EnumElementDecl.HasArgumentType; } static bool classof(const Decl *D) { return D->getKind() == DeclKind::EnumElement; } /// True if the case is marked 'indirect'. bool isIndirect() const { return getAttrs().hasAttribute(); } }; 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). /// /// 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 { /// The location of the '!' or '?' for a failable initializer. SourceLoc FailabilityLoc; ParameterList *ParameterLists[2]; /// 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, bool Throws, SourceLoc ThrowsLoc, ParamDecl *SelfParam, ParameterList *BodyParams, GenericParamList *GenericParams, DeclContext *Parent); Identifier getName() const { return getFullName().getBaseIdentifier(); } void setParameterLists(ParamDecl *selfParam, ParameterList *bodyParams); SourceLoc getConstructorLoc() const { return getNameLoc(); } SourceLoc getStartLoc() const { return getConstructorLoc(); } SourceRange getSourceRange() const; /// getArgumentInterfaceType - get the interface type of the argument tuple Type getArgumentInterfaceType() const; /// \brief Get the interface type of the constructed object. Type getResultInterfaceType() const; /// 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; } MutableArrayRef getParameterLists() { return { ParameterLists, 2 }; } ArrayRef getParameterLists() const { return AbstractFunctionDecl::getParameterLists(); } ParameterList *getParameterList(unsigned i) { return getParameterLists()[i]; } const ParameterList *getParameterList(unsigned i) const { return getParameterLists()[i]; } /// Returns the normal parameters to the initializer, not including self. ParameterList *getParameters() { return ParameterLists[1]; } /// Returns the normal parameters to the initializer, not including self. const ParameterList *getParameters() const { return ParameterLists[1]; } /// 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) const; /// Whether this constructor is required. bool isRequired() const { return getAttrs().hasAttribute(); } /// Determine the kind of initializer this is. CtorInitializerKind getInitKind() const { return static_cast(Bits.ConstructorDecl.InitKind); } /// Set whether this is a convenience initializer. void setInitKind(CtorInitializerKind kind) { Bits.ConstructorDecl.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(Bits.ConstructorDecl.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 Bits.ConstructorDecl.HasStubImplementation; } /// Set whether the implementation of this method is a stub that /// traps at runtime. void setStubImplementation(bool stub) { Bits.ConstructorDecl.HasStubImplementation = stub; } ConstructorDecl *getOverriddenDecl() const { return OverriddenDecl; } void setOverriddenDecl(ConstructorDecl *over) { // FIXME: Hack due to broken class circularity checking. if (over == this) return; OverriddenDecl = over; over->setIsOverridden(); } /// Determine whether this initializer falls into the special case for /// Objective-C initializers with selectors longer than "init", e.g., /// \c initForMemory. /// /// In such cases, one can write the Swift initializer /// with a single parameter of type '()', e.g, /// /// \code /// @objc init(forMemory: ()) /// \endcode bool isObjCZeroParameterWithLongSelector() const; 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 { ParameterList *SelfParameter; public: DestructorDecl(SourceLoc DestructorLoc, ParamDecl *selfDecl, DeclContext *Parent); void setSelfDecl(ParamDecl *selfDecl); MutableArrayRef getParameterLists() { return { &SelfParameter, 1 }; } ArrayRef getParameterLists() const { return { &SelfParameter, 1 }; } SourceLoc getDestructorLoc() const { return getNameLoc(); } SourceLoc getStartLoc() const { return getDestructorLoc(); } SourceRange getSourceRange() 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; } }; /// Declares a precedence group. For example: /// /// \code /// precedencegroup MultiplicativePrecedence { /// associativity: right /// higherThan: AdditivePrecedence /// } /// \endcode class PrecedenceGroupDecl : public Decl { public: struct Relation { SourceLoc NameLoc; Identifier Name; PrecedenceGroupDecl *Group; }; private: SourceLoc PrecedenceGroupLoc, NameLoc, LBraceLoc, RBraceLoc; SourceLoc AssociativityKeywordLoc, AssociativityValueLoc; SourceLoc AssignmentKeywordLoc, AssignmentValueLoc; SourceLoc HigherThanLoc, LowerThanLoc; Identifier Name; unsigned NumHigherThan, NumLowerThan; // Tail-allocated array of Relations Relation *getHigherThanBuffer() { return reinterpret_cast(this + 1); } const Relation *getHigherThanBuffer() const { return reinterpret_cast(this + 1); } Relation *getLowerThanBuffer() { return getHigherThanBuffer() + NumHigherThan; } const Relation *getLowerThanBuffer() const { return getHigherThanBuffer() + NumHigherThan; } PrecedenceGroupDecl(DeclContext *DC, SourceLoc precedenceGroupLoc, SourceLoc nameLoc, Identifier name, SourceLoc lbraceLoc, SourceLoc associativityKeywordLoc, SourceLoc associativityValueLoc, Associativity associativity, SourceLoc assignmentKeywordLoc, SourceLoc assignmentValueLoc, bool isAssignment, SourceLoc higherThanLoc, ArrayRef higherThan, SourceLoc lowerThanLoc, ArrayRef lowerThan, SourceLoc rbraceLoc); public: static PrecedenceGroupDecl *create(DeclContext *dc, SourceLoc precedenceGroupLoc, SourceLoc nameLoc, Identifier name, SourceLoc lbraceLoc, SourceLoc associativityKeywordLoc, SourceLoc associativityValueLoc, Associativity associativity, SourceLoc assignmentKeywordLoc, SourceLoc assignmentValueLoc, bool isAssignment, SourceLoc higherThanLoc, ArrayRef higherThan, SourceLoc lowerThanLoc, ArrayRef lowerThan, SourceLoc rbraceLoc); SourceLoc getLoc() const { return NameLoc; } SourceRange getSourceRange() const { return { PrecedenceGroupLoc, RBraceLoc }; } /// Return the location of 'precedencegroup' in: /// precedencegroup MultiplicativePrecedence { ... } SourceLoc getPrecedenceGroupLoc() const { return PrecedenceGroupLoc; } /// Return the location of 'MultiplicativePrecedence' in: /// precedencegroup MultiplicativePrecedence { ... } SourceLoc getNameLoc() const { return NameLoc; } Identifier getName() const { return Name; } SourceLoc getLBraceLoc() const { return LBraceLoc; } SourceLoc getRBraceLoc() const { return RBraceLoc; } bool isAssociativityImplicit() const { return AssociativityKeywordLoc.isInvalid(); } /// Return the location of 'associativity' in: /// associativity: left SourceLoc getAssociativityKeywordLoc() const { return AssociativityKeywordLoc; } /// Return the location of 'right' in: /// associativity: right SourceLoc getAssociativityValueLoc() const { return AssociativityValueLoc; } Associativity getAssociativity() const { return Associativity(Bits.PrecedenceGroupDecl.Associativity); } bool isLeftAssociative() const { return getAssociativity() == Associativity::Left; } bool isRightAssociative() const { return getAssociativity() == Associativity::Right; } bool isNonAssociative() const { return getAssociativity() == Associativity::None; } bool isAssignmentImplicit() const { return AssignmentKeywordLoc.isInvalid(); } /// Return the location of 'assignment' in: /// assignment: true SourceLoc getAssignmentKeywordLoc() const { return AssignmentKeywordLoc; } /// Return the location of 'assignment' in: /// assignment: true SourceLoc getAssignmentValueLoc() const { return AssignmentValueLoc; } bool isAssignment() const { return Bits.PrecedenceGroupDecl.IsAssignment; } bool isHigherThanImplicit() const { return HigherThanLoc.isInvalid(); } /// Return the location of 'higherThan' in: /// higherThan: AdditivePrecedence SourceLoc getHigherThanLoc() const { return HigherThanLoc; } ArrayRef getHigherThan() const { return { getHigherThanBuffer(), NumHigherThan }; } MutableArrayRef getMutableHigherThan() { return { getHigherThanBuffer(), NumHigherThan }; } bool isLowerThanImplicit() const { return LowerThanLoc.isInvalid(); } /// Return the location of 'lowerThan' in: /// lowerThan: MultiplicativePrecedence SourceLoc getLowerThanLoc() const { return LowerThanLoc; } ArrayRef getLowerThan() const { return { getLowerThanBuffer(), NumLowerThan }; } MutableArrayRef getMutableLowerThan() { return { getLowerThanBuffer(), NumLowerThan }; } static bool classof(const Decl *D) { return D->getKind() == DeclKind::PrecedenceGroup; } }; /// Abstract base class of operator declarations. class OperatorDecl : public Decl { SourceLoc OperatorLoc, NameLoc; Identifier name; public: OperatorDecl(DeclKind kind, DeclContext *DC, SourceLoc OperatorLoc, Identifier Name, SourceLoc NameLoc) : Decl(kind, DC), OperatorLoc(OperatorLoc), NameLoc(NameLoc), name(Name) {} SourceLoc getLoc() const { return NameLoc; } SourceLoc getOperatorLoc() const { return OperatorLoc; } SourceLoc getNameLoc() const { return NameLoc; } Identifier getName() const { return name; } static bool classof(const Decl *D) { // Workaround: http://llvm.org/PR35906 if (DeclKind::Last_Decl == DeclKind::Last_OperatorDecl) return D->getKind() >= DeclKind::First_OperatorDecl; return D->getKind() >= DeclKind::First_OperatorDecl && D->getKind() <= DeclKind::Last_OperatorDecl; } }; /// Declares the behavior of an infix operator. For example: /// /// \code /// infix operator /+/ : AdditivePrecedence /// \endcode class InfixOperatorDecl : public OperatorDecl { SourceLoc ColonLoc, PrecedenceGroupNameLoc; Identifier PrecedenceGroupName; PrecedenceGroupDecl *PrecedenceGroup = nullptr; public: InfixOperatorDecl(DeclContext *DC, SourceLoc operatorLoc, Identifier name, SourceLoc nameLoc, SourceLoc colonLoc, Identifier precedenceGroupName, SourceLoc precedenceGroupNameLoc) : OperatorDecl(DeclKind::InfixOperator, DC, operatorLoc, name, nameLoc), ColonLoc(colonLoc), PrecedenceGroupNameLoc(precedenceGroupNameLoc), PrecedenceGroupName(precedenceGroupName) { } SourceLoc getEndLoc() const { if (PrecedenceGroupName.empty()) return getNameLoc(); return PrecedenceGroupNameLoc; } SourceRange getSourceRange() const { return { getOperatorLoc(), getEndLoc() }; } SourceLoc getColonLoc() const { return ColonLoc; } SourceLoc getPrecedenceGroupNameLoc() const { return PrecedenceGroupNameLoc; } Identifier getPrecedenceGroupName() const { return PrecedenceGroupName; } PrecedenceGroupDecl *getPrecedenceGroup() const { return PrecedenceGroup; } void setPrecedenceGroup(PrecedenceGroupDecl *PGD) { PrecedenceGroup = PGD; } /// True if this decl's attributes conflict with those declared by another /// operator. bool conflictsWith(InfixOperatorDecl *other) { return getPrecedenceGroup() != other->getPrecedenceGroup(); } 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) : OperatorDecl(DeclKind::PrefixOperator, DC, OperatorLoc, Name, NameLoc) {} SourceRange getSourceRange() const { return { getOperatorLoc(), getNameLoc() }; } /// 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) : OperatorDecl(DeclKind::PostfixOperator, DC, OperatorLoc, Name, NameLoc) {} SourceRange getSourceRange() const { return { getOperatorLoc(), getNameLoc() }; } /// 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; } }; /// Represents a hole where a declaration should have been. /// /// Among other things, these are used to keep vtable layout consistent. class MissingMemberDecl : public Decl { DeclName Name; MissingMemberDecl(DeclContext *DC, DeclName name, unsigned vtableEntries, unsigned fieldOffsetVectorEntries) : Decl(DeclKind::MissingMember, DC), Name(name) { Bits.MissingMemberDecl.NumberOfVTableEntries = vtableEntries; assert(getNumberOfVTableEntries() == vtableEntries && "not enough bits"); Bits.MissingMemberDecl.NumberOfFieldOffsetVectorEntries = fieldOffsetVectorEntries; assert(getNumberOfFieldOffsetVectorEntries() == fieldOffsetVectorEntries && "not enough bits"); setImplicit(); } public: static MissingMemberDecl * forMethod(ASTContext &ctx, DeclContext *DC, DeclName name, bool hasNormalVTableEntry) { assert(!name || name.isCompoundName()); return new (ctx) MissingMemberDecl(DC, name, hasNormalVTableEntry, 0); } static MissingMemberDecl * forInitializer(ASTContext &ctx, DeclContext *DC, DeclName name, bool hasNormalVTableEntry, bool hasAllocatingVTableEntry) { unsigned entries = hasNormalVTableEntry + hasAllocatingVTableEntry; return new (ctx) MissingMemberDecl(DC, name, entries, 0); } static MissingMemberDecl * forStoredProperty(ASTContext &ctx, DeclContext *DC, DeclName name) { return new (ctx) MissingMemberDecl(DC, name, 0, 1); } DeclName getFullName() const { return Name; } unsigned getNumberOfVTableEntries() const { return Bits.MissingMemberDecl.NumberOfVTableEntries; } unsigned getNumberOfFieldOffsetVectorEntries() const { return Bits.MissingMemberDecl.NumberOfFieldOffsetVectorEntries; } SourceLoc getLoc() const { return SourceLoc(); } SourceRange getSourceRange() const { return SourceRange(); } static bool classof(const Decl *D) { return D->getKind() == DeclKind::MissingMember; } }; inline bool ValueDecl::isSettable(const DeclContext *UseDC, const DeclRefExpr *base) const { if (auto vd = dyn_cast(this)) { return vd->isSettable(UseDC, base); } 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() && (!skipUserInaccessible || var->isUserAccessible())) return var; } return None; } inline Optional NominalTypeDecl::ToStoredPropertyOrMissingMemberPlaceholder ::operator()(Decl *decl) const { if (auto var = dyn_cast(decl)) { if (!var->isStatic() && var->hasStorage()) return var; } if (auto missing = dyn_cast(decl)) { if (missing->getNumberOfFieldOffsetVectorEntries() > 0) return missing; } return None; } inline void AbstractStorageDecl::overwriteSetterAccess(AccessLevel accessLevel) { GetSetInfo.setInt(accessLevel); if (auto setter = getSetter()) setter->overwriteAccess(accessLevel); if (auto materializeForSet = getMaterializeForSetFunc()) materializeForSet->overwriteAccess(accessLevel); } inline bool AbstractStorageDecl::isStatic() const { if (auto var = dyn_cast(this)) { return var->isStatic(); } // Currently, subscripts are never static. return false; } inline MutableArrayRef AbstractFunctionDecl::getParameterLists() { switch (getKind()) { default: llvm_unreachable("Unknown AbstractFunctionDecl!"); case DeclKind::Constructor: return cast(this)->getParameterLists(); case DeclKind::Destructor: return cast(this)->getParameterLists(); case DeclKind::Func: case DeclKind::Accessor: return cast(this)->getParameterLists(); } } inline DeclIterator &DeclIterator::operator++() { Current = Current->NextDecl; return *this; } inline bool AbstractFunctionDecl::hasForcedStaticDispatch() const { if (auto func = dyn_cast(this)) return func->hasForcedStaticDispatch(); return false; } inline bool ValueDecl::isStatic() const { // Currently, only storage and function decls can be static/class. if (auto storage = dyn_cast(this)) return storage->isStatic(); if (auto func = dyn_cast(this)) return func->isStatic(); return false; } inline bool ValueDecl::isImportAsMember() const { if (auto func = dyn_cast(this)) return func->isImportAsMember(); return false; } inline bool Decl::isPotentiallyOverridable() const { if (isa(this) || isa(this) || isa(this)) { return getDeclContext()->getAsClassOrClassExtensionContext(); } else { return false; } } inline GenericParamKey::GenericParamKey(const GenericTypeParamDecl *d) : Depth(d->getDepth()), Index(d->getIndex()) { } inline const GenericContext *Decl::getAsGenericContext() const { switch (getKind()) { default: return nullptr; #define DECL(Id, Parent) // See previous line #define GENERIC_DECL(Id, Parent) \ case DeclKind::Id: \ return static_cast(this); #include "swift/AST/DeclNodes.def" } } inline bool DeclContext::classof(const Decl *D) { switch (D->getKind()) { // default: return false; #define DECL(ID, PARENT) // See previous line #define CONTEXT_DECL(ID, PARENT) \ case DeclKind::ID: return true; #include "swift/AST/DeclNodes.def" } } inline DeclContext *DeclContext::castDeclToDeclContext(const Decl *D) { // XXX -- ModuleDecl is not defined in Decl.h, but because DeclContexts // preface decls in memory, any DeclContext type will due. const DeclContext *DC = static_cast(D); switch (D->getKind()) { default: llvm_unreachable("Not a DeclContext"); #define DECL(ID, PARENT) // See previous line #define CONTEXT_DECL(ID, PARENT) \ case DeclKind::ID: #include "swift/AST/DeclNodes.def" return const_cast(DC); } } inline EnumElementDecl *EnumDecl::getUniqueElement(bool hasValue) const { EnumElementDecl *result = nullptr; bool found = false; for (auto elt : getAllElements()) { if (elt->hasAssociatedValues() == hasValue) { if (found) return nullptr; found = true; result = elt; } } return result; } } // end namespace swift #endif