//===--- Decl.h - Swift Language Declaration ASTs ---------------*- C++ -*-===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2020 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/AvailabilityRange.h" #include "swift/AST/CaptureInfo.h" #include "swift/AST/ClangNode.h" #include "swift/AST/ConcreteDeclRef.h" #include "swift/AST/DefaultArgumentKind.h" #include "swift/AST/DiagnosticEngine.h" #include "swift/AST/ForeignAsyncConvention.h" #include "swift/AST/ForeignErrorConvention.h" #include "swift/AST/FreestandingMacroExpansion.h" #include "swift/AST/GenericParamKey.h" #include "swift/AST/IfConfigClause.h" #include "swift/AST/Import.h" #include "swift/AST/Initializer.h" #include "swift/AST/LayoutConstraint.h" #include "swift/AST/LifetimeAnnotation.h" #include "swift/AST/ProtocolConformanceOptions.h" #include "swift/AST/ReferenceCounting.h" #include "swift/AST/RequirementSignature.h" #include "swift/AST/StorageImpl.h" #include "swift/AST/TypeAlignments.h" #include "swift/AST/TypeResolutionStage.h" #include "swift/AST/TypeWalker.h" #include "swift/AST/Types.h" #include "swift/Basic/ArrayRefView.h" #include "swift/Basic/Compiler.h" #include "swift/Basic/Debug.h" #include "swift/Basic/InlineBitfield.h" #include "swift/Basic/Located.h" #include "swift/Basic/Nullability.h" #include "swift/Basic/NullablePtr.h" #include "swift/Basic/OptionalEnum.h" #include "swift/Basic/Range.h" #include "swift/Basic/SwiftObjectHeader.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/TinyPtrVector.h" #include "llvm/Support/TrailingObjects.h" #include #include namespace clang { class PointerAuthQualifier; } // end namespace clang namespace swift { enum class AccessSemantics : unsigned char; class AccessorDecl; class ApplyExpr; class AvailabilityRange; class AvailabilityDomain; class GenericEnvironment; class ArchetypeType; class ASTContext; struct ASTNode; class ASTPrinter; class ASTWalker; enum class BuiltinMacroKind: uint8_t; class ConstructorDecl; class DestructorDecl; class DiagnosticEngine; class DynamicSelfType; class Type; class Expr; struct ExternalSourceLocs; class CaptureListExpr; class DeclRefExpr; class LiteralExpr; class BraceStmt; class DeclAttributes; class GenericContext; class GenericParamList; class GenericSignature; class GenericTypeParamDecl; class GenericTypeParamType; class MacroDecl; class MacroDefinition; class ModuleDecl; class NamedPattern; enum NLOptions : unsigned; class EnumCaseDecl; class EnumElementDecl; class ParameterList; class ParameterTypeFlags; class Pattern; struct PrintOptions; struct PropertyWrapperAuxiliaryVariables; class PropertyWrapperInitializerInfo; struct PropertyWrapperTypeInfo; struct PropertyWrapperMutability; class ProtocolDecl; class PolymorphicEffectRequirementList; class ProtocolType; struct RawComment; enum class ResilienceExpansion : unsigned; class ReturnStmt; enum class EffectKind : uint8_t; enum class PolymorphicEffectKind : uint8_t; class TrailingWhereClause; class TypeAliasDecl; class Stmt; class SubscriptDecl; class UnboundGenericType; class ValueDecl; class VarDecl; class OpaqueReturnTypeRepr; class Witness; namespace ast_scope { class AbstractPatternEntryScope; class GenericParamScope; class PatternEntryDeclScope; class PatternEntryInitializerScope; } // namespace ast_scope 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, PatternBinding, Var, Param, Let, Property, StaticProperty, ClassProperty, DistributedProperty, InfixOperator, PrefixOperator, PostfixOperator, PrecedenceGroup, TypeAlias, GenericTypeAlias, GenericTypeParam, AssociatedType, Type, Enum, Struct, Class, Actor, DistributedActor, Protocol, GenericEnum, GenericStruct, GenericClass, GenericActor, GenericDistributedActor, Subscript, StaticSubscript, ClassSubscript, Constructor, Destructor, LocalFunction, GlobalFunction, OperatorFunction, Method, StaticMethod, ClassMethod, DistributedMethod, Getter, Setter, InitAccessor, Addressor, MutableAddressor, ReadAccessor, ModifyAccessor, WillSet, DidSet, EnumElement, Module, Missing, MissingMember, Requirement, OpaqueResultType, OpaqueVarType, Macro, MacroExpansion }; /// 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, }; /// An explicit declaration of the safety of enum class ExplicitSafety { /// There was no explicit declaration of the safety of the given entity. Unspecified, /// The entity was explicitly declared safe with @safe. Safe, /// The entity was explicitly declared unsafe with @unsafe. Unsafe }; /// Diagnostic printing of \c StaticSpellingKind. llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, StaticSpellingKind SSK); /// Diagnostic printing of \c ReferenceOwnership. llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, ReferenceOwnership RO); enum class SelfAccessKind : uint8_t { NonMutating, Mutating, LegacyConsuming, Consuming, Borrowing, LastSelfAccessKind = Borrowing, }; enum : unsigned { NumSelfAccessKindBits = countBitsUsed(static_cast(SelfAccessKind::LastSelfAccessKind)) }; static_assert(uint8_t(SelfAccessKind::LastSelfAccessKind) < (NumSelfAccessKindBits << 1), "Self Access Kind is too small to fit in SelfAccess kind bits. " "Please expand "); /// Diagnostic printing of \c SelfAccessKind. llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, SelfAccessKind SAK); /// 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; /// Whether this is an instance member. unsigned IsInstanceMember : 1; /// Whether this is a variable. unsigned IsVariable : 1; /// Whether this is a function. unsigned IsFunction : 1; /// Whether this is an async function. unsigned IsAsyncFunction : 1; /// Whether this is an distributed function. unsigned IsDistributed : 1; /// Whether this is a enum element. unsigned IsEnumElement : 1; /// Whether this is a nominal type. unsigned IsNominal : 1; /// Whether this is a type alias. unsigned IsTypeAlias : 1; /// Whether this is a macro. unsigned IsMacro : 1; /// Whether this signature is part of a protocol extension. unsigned InProtocolExtension : 1; /// Whether this signature is of a member defined in an extension of a generic /// type. unsigned InExtensionOfGenericType : 1; /// Whether this declaration has an opaque return type. unsigned HasOpaqueReturnType : 1; OverloadSignature() : UnaryOperator(UnaryOperatorKind::None), IsInstanceMember(false), IsVariable(false), IsFunction(false), IsAsyncFunction(false), IsDistributed(false), InProtocolExtension(false), InExtensionOfGenericType(false), HasOpaqueReturnType(false) { } }; /// Determine whether two overload signatures conflict. /// /// \param sig1 The overload signature of the first declaration. /// \param sig2 The overload signature of the second declaration. /// \param skipProtocolExtensionCheck If \c true, members of protocol extensions /// will be allowed to conflict with members of protocol declarations. bool conflicting(const OverloadSignature& sig1, const OverloadSignature& sig2, bool skipProtocolExtensionCheck = false); /// Determine whether two overload signatures and overload types conflict. /// /// \param ctx The AST context. /// \param sig1 The overload signature of the first declaration. /// \param sig1Type The overload type of the first declaration. /// \param sig2 The overload signature of the second declaration. /// \param sig2Type The overload type of the second declaration. /// \param wouldConflictInSwift5 If non-null, the referenced boolean will be set /// to \c true iff the function returns \c false for this version of /// Swift, but the given overloads will conflict in Swift 5 mode. /// \param skipProtocolExtensionCheck If \c true, members of protocol extensions /// will be allowed to conflict with members of protocol declarations. bool conflicting(ASTContext &ctx, const OverloadSignature& sig1, CanType sig1Type, const OverloadSignature& sig2, CanType sig2Type, bool *wouldConflictInSwift5 = nullptr, bool skipProtocolExtensionCheck = false); /// The kind of artificial main to generate. enum class ArtificialMainKind : uint8_t { NSApplicationMain, UIApplicationMain, TypeMain, }; /// Decl - Base class for all declarations in Swift. class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated, public SwiftObjectHeader { protected: // clang-format off // // We format these different than clang-format wishes us to... so turn if off // for the inline bitfields. union { uint64_t OpaqueBits; SWIFT_INLINE_BITFIELD_BASE(Decl, bitmax(NumDeclKindBits,8)+1+1+1+1+1+1+1+1+1+1+1+1, Kind : bitmax(NumDeclKindBits,8), /// Whether this declaration is invalid. Invalid : 1, /// Whether this declaration was implicitly created, e.g., /// an implicit constructor in a struct. Implicit : 1, /// Whether this declaration was mapped directly from a Clang AST. /// /// Use getClangNode() to retrieve the corresponding Clang AST. FromClang : 1, /// Whether this declaration is syntactically scoped inside of /// a local context, but should behave like a top-level /// declaration for name lookup purposes. This is used by /// lldb. Hoisted : 1, /// Whether the set of semantic attributes has been computed. SemanticAttrsComputed : 1, /// True if \c ObjCInterfaceAndImplementationRequest has been computed /// and did \em not find anything. This is the fast path where we can bail /// out without checking other caches or computing anything. LacksObjCInterfaceOrImplementation : 1, /// True if we're in the common case where the ExpandMemberAttributeMacros /// request returned an empty array. NoMemberAttributeMacros : 1, /// True if we're in the common case where the ExpandPeerMacroRequest /// request returned an empty array. NoPeerMacros : 1, /// True if we're in the common case where the GlobalActorAttributeRequest /// request returned a pair of null pointers. NoGlobalActorAttribute : 1, /// True if we're in the common case where the SPIGroupsRequest /// request returned an empty array of identifiers. NoSPIGroups : 1, /// True if we have computed whether this declaration is unsafe. IsUnsafeComputed : 1, /// True if this declaration has been determined to be "unsafe". IsUnsafe : 1 ); SWIFT_INLINE_BITFIELD_FULL(PatternBindingDecl, Decl, 1+1+2+16, /// Whether this pattern binding declares static variables. IsStatic : 1, /// Whether this pattern binding is synthesized by the debugger. IsDebugger : 1, /// Whether 'static' or 'class' was used. StaticSpelling : 2, : NumPadBits, /// 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+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, /// Whether this member was synthesized as part of a derived /// protocol conformance. Synthesized : 1 ); SWIFT_INLINE_BITFIELD(AbstractStorageDecl, ValueDecl, 1, /// Whether this property is a type property (currently unfortunately /// called 'static'). IsStatic : 1 ); SWIFT_INLINE_BITFIELD(VarDecl, AbstractStorageDecl, 2+1+1+1+1+1+1+1, /// Encodes whether this is a 'let' binding. Introducer : 2, /// Whether this declaration captures the 'self' param under the same name. IsSelfParamCapture : 1, /// 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, /// Whether this is the backing storage for a lazy property. IsLazyStorageProperty : 1, /// Whether this is the backing storage for a property wrapper. IsPropertyWrapperBackingProperty : 1, /// Whether this is a lazily top-level global variable from the main file. IsTopLevelGlobal : 1, /// Whether this variable has no attached property wrappers. NoAttachedPropertyWrappers : 1, /// Whether this variable has no property wrapper auxiliary variables. NoPropertyWrapperAuxiliaryVariables : 1 ); SWIFT_INLINE_BITFIELD(ParamDecl, VarDecl, 1+2+NumDefaultArgumentKindBits, /// The specifier associated with this parameter + 1, or zero if the /// specifier has not been computed yet. This determines /// the ownership semantics of the parameter. OwnershipSpecifier : 3, /// Information about a symbolic default argument, like #file. defaultArgumentKind : NumDefaultArgumentKindBits ); SWIFT_INLINE_BITFIELD(SubscriptDecl, VarDecl, 2, StaticSpelling : 2 ); SWIFT_INLINE_BITFIELD(AbstractFunctionDecl, ValueDecl, 3+2+2+2+8+1+1+1+1+1+1, /// \see AbstractFunctionDecl::BodyKind BodyKind : 3, /// \see AbstractFunctionDecl::BodySkippedStatus BodySkippedStatus : 2, /// \see AbstractFunctionDecl::BodyExpandedStatus BodyExpandedStatus : 2, /// \see AbstractFunctionDecl::SILSynthesizeKind SILSynthesizeKind : 2, /// Import as member status. IAMStatus : 8, /// Whether the function has an implicit 'self' parameter. HasImplicitSelfDecl : 1, /// Whether we are overridden later. Overridden : 1, /// Whether the function is async. Async : 1, /// Whether the function body throws. Throws : 1, /// Whether peeking into this function detected nested type declarations. /// This is set when skipping over the decl at parsing. HasNestedTypeDeclarations : 1, /// Whether this function is a distributed thunk for a distributed /// function or computed property. DistributedThunk : 1 ); SWIFT_INLINE_BITFIELD(FuncDecl, AbstractFunctionDecl, 1+1+2+1+1+NumSelfAccessKindBits+1+1, /// Whether we've computed the 'static' flag yet. IsStaticComputed : 1, /// Whether this function is a 'static' method. IsStatic : 1, /// Whether 'static' or 'class' was used. StaticSpelling : 2, /// Whether we are statically dispatched even if overridable ForcedStaticDispatch : 1, /// Whether we've computed the 'self' access kind yet. SelfAccessComputed : 1, /// Backing bits for 'self' access kind. SelfAccess : NumSelfAccessKindBits, /// Whether this is a top-level function which should be treated /// as if it were in local context for the purposes of capture /// analysis. HasTopLevelLocalContextCaptures : 1, /// Set to true if this FuncDecl has a 'sending' result. HasSendingResult : 1 ); SWIFT_INLINE_BITFIELD(AccessorDecl, FuncDecl, 4 + 1 + 1, /// The kind of accessor this is. AccessorKind : 4, /// Whether the accessor is transparent. IsTransparent : 1, /// Whether we have computed the above. IsTransparentComputed : 1 ); SWIFT_INLINE_BITFIELD(ConstructorDecl, AbstractFunctionDecl, 1+1, /// Whether this constructor can fail, by building an Optional type. Failable : 1, /// 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_EMPTY(TypeDecl, ValueDecl); SWIFT_INLINE_BITFIELD_FULL(GenericTypeParamDecl, TypeDecl, 16+16+3+1, Depth : 16, Index : 16, ParamKind : 3, /// Whether this generic parameter represents an opaque type. IsOpaqueType : 1 ); SWIFT_INLINE_BITFIELD_FULL(AssociatedTypeDecl, TypeDecl, 1, /// Whether we have computed the default type. IsDefaultDefinitionTypeComputed : 1 ); SWIFT_INLINE_BITFIELD_EMPTY(GenericTypeDecl, TypeDecl); SWIFT_INLINE_BITFIELD(TypeAliasDecl, GenericTypeDecl, 1+1, /// Whether the typealias forwards perfectly to its underlying type. IsCompatibilityAlias : 1, /// Whether this was a global typealias synthesized by the debugger. IsDebuggerAlias : 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 this nominal type is having its semantic members resolved. IsComputingSemanticMembers : 1 ); SWIFT_INLINE_BITFIELD_FULL(ProtocolDecl, NominalTypeDecl, 1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+8, /// 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 HasSelfOrAssociatedTypeRequirements bit is valid. HasSelfOrAssociatedTypeRequirementsValid : 1, /// Whether this protocol has \c Self or associated type requirements. /// See \c hasSelfOrAssociatedTypeRequirements() for clarification. HasSelfOrAssociatedTypeRequirements : 1, /// True if the protocol has requirements that cannot be satisfied (e.g. /// because they could not be imported from Objective-C). HasMissingRequirements : 1, /// Whether we've computed the InheritedProtocolsRequest. InheritedProtocolsValid : 1, /// Whether we've computed the AllInheritedProtocolsRequest. AllInheritedProtocolsValid : 1, /// Whether we have computed a requirement signature. HasRequirementSignature : 1, /// Whether we have a lazy-loaded requirement signature. HasLazyRequirementSignature : 1, /// Whether we have computed the list of associated types. HasAssociatedTypes : 1, /// Whether we have a lazy-loaded list of associated types. HasLazyAssociatedTypes : 1, /// Whether we have a lazy-loaded list of primary associated types. HasLazyPrimaryAssociatedTypes : 1, /// Whether we've computed the protocol requirements list yet. ProtocolRequirementsValid : 1, : 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. ); SWIFT_INLINE_BITFIELD(ClassDecl, NominalTypeDecl, 1+1+2+1+1+1+1+1+1, /// Whether this class inherits its superclass's convenience initializers. InheritsSuperclassInits : 1, ComputedInheritsSuperclassInits : 1, /// \see ClassDecl::ForeignKind RawForeignKind : 2, HasMissingDesignatedInitializers : 1, ComputedHasMissingDesignatedInitializers : 1, HasMissingVTableEntries : 1, ComputedHasMissingVTableEntries : 1, /// Whether instances of this class are incompatible /// with weak and unowned references. IsIncompatibleWithWeakReferences : 1, /// Set when the class represents an actor IsActor : 1 ); SWIFT_INLINE_BITFIELD(StructDecl, NominalTypeDecl, 1 + 1 + 1, /// True if this struct has storage for fields that /// aren't accessible in Swift. HasUnreferenceableStorage : 1, /// True if this struct is imported from C++ and does /// not have trivial value witness functions. IsCxxNonTrivial : 1, /// True if this struct is imported from C and has /// address diversified ptrauth qualified field. IsNonTrivialPtrAuth : 1); SWIFT_INLINE_BITFIELD(EnumDecl, NominalTypeDecl, 2+1+1, /// True if the enum has cases and at least one case has associated values. HasAssociatedValues : 2, /// True if the enum has at least one case that has some availability /// attribute. A single bit because it's lazily computed along with the /// HasAssociatedValues bit. HasAnyUnavailableValues : 1, /// True if \c isAvailableDuringLowering() is false for any cases. Lazily /// computed along with HasAssociatedValues. HasAnyUnavailableDuringLoweringValues : 1 ); SWIFT_INLINE_BITFIELD(ModuleDecl, TypeDecl, 1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+8, /// If the module is compiled as static library. StaticLibrary : 1, /// If the module was or is being compiled with `-enable-testing`. TestingEnabled : 1, /// If the module failed to load FailedToLoad : 1, /// Whether the module is resilient. /// /// \sa ResilienceStrategy RawResilienceStrategy : 1, /// Whether the module was rebuilt from a module interface instead of being /// build from the full source. IsBuiltFromInterface : 1, /// Whether all imports have been resolved. Used to detect circular imports. HasResolvedImports : 1, /// If the module was or is being compiled with `-enable-private-imports`. PrivateImportsEnabled : 1, /// If the module is compiled with `-enable-implicit-dynamic`. ImplicitDynamicEnabled : 1, /// Whether the module is a system module. IsSystemModule : 1, /// Whether the module was imported from Clang (or, someday, maybe another /// language). IsNonSwiftModule : 1, /// Whether this module is the main module. IsMainModule : 1, /// Whether this module has incremental dependency information available. HasIncrementalInfo : 1, /// Whether this module was built with -experimental-hermetic-seal-at-link. HasHermeticSealAtLink : 1, /// Whether this module was built with embedded Swift. IsEmbeddedSwiftModule : 1, /// Whether this module has been compiled with comprehensive checking for /// concurrency, e.g., Sendable checking. IsConcurrencyChecked : 1, /// If the map from @objc provided name to top level swift::Decl in this /// module is populated ObjCNameLookupCachePopulated : 1, /// Whether this module has been built with C++ interoperability enabled. HasCxxInteroperability : 1, /// Whether this module uses the platform default C++ stdlib, or an /// overridden C++ stdlib. CXXStdlibKind : 8, /// Whether this module has been built with -allow-non-resilient-access. AllowNonResilientAccess : 1, /// Whether this module has been built with -package-cmo. SerializePackageEnabled : 1, /// Whether this module has enabled strict memory safety checking. StrictMemorySafety : 1 ); 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(ImportDecl, Decl, 3+8, ImportKind : 3, /// The number of elements in this path. NumPathElements : 8 ); SWIFT_INLINE_BITFIELD(ExtensionDecl, Decl, 4+1, /// An encoding of the default and maximum access level for this extension. /// The value 4 corresponds to AccessLevel::Public /// /// 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 : 4, /// Whether there is are lazily-loaded conformances for this extension. HasLazyConformances : 1 ); SWIFT_INLINE_BITFIELD(MissingMemberDecl, Decl, 1+2, NumberOfFieldOffsetVectorEntries : 1, NumberOfVTableEntries : 2 ); } Bits; // Turn back on clang-format now that we have defined our inline bitfields. // clang-format on // 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; friend class DeclDeserializer; friend class RawCommentRequest; friend class ExpandMemberAttributeMacros; friend class ExpandPeerMacroRequest; friend class GlobalActorAttributeRequest; friend class SPIGroupsRequest; private: llvm::PointerUnion Context; Decl(const Decl&) = delete; void operator=(const Decl&) = delete; SourceLoc getLocFromSource() const; static SwiftMetatype getDeclMetatype(DeclKind kind); /// Returns the serialized locations of this declaration from the /// corresponding .swiftsourceinfo file. "Empty" (ie. \c BufferID of 0, an /// invalid \c Loc, and empty \c DocRanges) if either there is no /// .swiftsourceinfo or the buffer could not be created, eg. if the file /// no longer exists. const ExternalSourceLocs *getSerializedLocs() const; /// Directly set the invalid bit void setInvalidBit(); bool hasNoMemberAttributeMacros() const { return Bits.Decl.NoMemberAttributeMacros; } void setHasNoMemberAttributeMacros() { Bits.Decl.NoMemberAttributeMacros = true; } bool hasNoPeerMacros() const { return Bits.Decl.NoPeerMacros; } void setHasNoPeerMacros() { Bits.Decl.NoPeerMacros = true; } bool hasNoGlobalActorAttribute() const { return Bits.Decl.NoGlobalActorAttribute; } void setHasNoGlobalActorAttribute() { Bits.Decl.NoGlobalActorAttribute = true; } bool hasNoSPIGroups() const { return Bits.Decl.NoSPIGroups; } void setHasNoSPIGroups() { Bits.Decl.NoSPIGroups = true; } protected: Decl(DeclKind kind, llvm::PointerUnion context) : SwiftObjectHeader(getDeclMetatype(kind)), Context(context) { Bits.OpaqueBits = 0; Bits.Decl.Kind = unsigned(kind); Bits.Decl.Invalid = false; Bits.Decl.Implicit = false; Bits.Decl.FromClang = false; Bits.Decl.Hoisted = false; Bits.Decl.LacksObjCInterfaceOrImplementation = false; Bits.Decl.NoMemberAttributeMacros = false; Bits.Decl.NoGlobalActorAttribute = false; Bits.Decl.NoSPIGroups = false; Bits.Decl.IsUnsafeComputed = false; Bits.Decl.IsUnsafe = false; } /// Get the Clang node associated with this declaration. ClangNode getClangNodeImpl() const; /// 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); } /// 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; LLVM_READONLY 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; /// Retrieve the module in which this declaration resides. LLVM_READONLY ModuleDecl *getModuleContext() const; /// Retrieve the module in which this declaration would be found by name /// lookup queries. The result can differ from that of `getModuleContext()` /// when the decl was imported via Cxx interop. LLVM_READONLY ModuleDecl *getModuleContextForNameLookup() const; /// getASTContext - Return the ASTContext that this decl lives in. LLVM_READONLY 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 attributes that were directly attached to this declaration /// as written in source, ie. does not include semantic attributes or ones /// generated by macro expansions. ParsedDeclAttributes getParsedAttrs() const; /// Returns the attributes attached to this declaration, /// including attributes that are generated as the result of member /// attribute macro expansion. DeclAttributes getExpandedAttrs() const; /// Returns all semantic attributes attached to this declaration, /// including attributes that are generated as the result of member /// attribute macro expansion. DeclAttributes getSemanticAttrs() const; /// Register the relationship between \c this and \p attr->abiDecl , assuming /// that \p attr is attached to \c this . This is necessary for /// \c ABIRoleInfo::ABIRoleInfo() to determine that \c attr->abiDecl /// is ABI-only and locate its API counterpart. void recordABIAttr(ABIAttr *attr); /// Set this declaration's attributes to the specified attribute list, /// applying any post-processing logic appropriate for attributes parsed /// from source code. void attachParsedAttrs(DeclAttributes attrs); /// Retrieve the custom name in the \c @objc attribute, if present. std::optional getExplicitObjCName(bool allowInvalid = false) const; /// True if this declaration provides an implementation for an imported /// Objective-C declaration. This implies various restrictions and special /// behaviors for it and, if it's an extension, its members. bool isObjCImplementation() const; using AuxiliaryDeclCallback = llvm::function_ref; /// Iterate over the auxiliary declarations for this declaration, /// invoking the given callback with each auxiliary decl. /// /// Auxiliary declarations can be property wrapper backing variables, /// backing variables for 'lazy' vars, or peer macro expansions. /// /// When \p visitFreestandingExpanded is true (the default), this will also /// visit the declarations produced by a freestanding macro expansion. void visitAuxiliaryDecls( AuxiliaryDeclCallback callback, bool visitFreestandingExpanded = true ) const; using MacroCallback = llvm::function_ref; /// Iterate over each attached macro with the given role, invoking the /// given callback with each macro custom attribute and corresponding macro /// declaration. void forEachAttachedMacro(MacroRole role, MacroCallback) const; /// Returns the resolved macro for the given custom attribute /// attached to this declaration. MacroDecl *getResolvedMacro(CustomAttr *attr) const; /// Retrieve the discriminator for the given custom attribute that names /// an attached macro. unsigned getAttachedMacroDiscriminator(DeclBaseName macroName, MacroRole role, const CustomAttr *attr) const; /// Returns the resolved type for the give custom attribute attached to this /// declaration. Type getResolvedCustomAttrType(CustomAttr *attr) const; /// Determines if this declaration is exposed to clients of the module it is /// defined in. For example, `public` declarations are exposed to clients. bool isExposedToClients() const; /// Returns the innermost enclosing decl with an availability annotation. const Decl *getInnermostDeclWithAvailability() const; /// Returns the introduced OS version in the given platform kind specified /// by @available attribute. /// This function won't consider the parent context to get the information. std::optional getIntroducedOSVersion(PlatformKind Kind) const; /// Returns the OS version in which the decl became ABI as specified by the /// `@backDeployed` attribute. std::optional getBackDeployedBeforeOSVersion(ASTContext &Ctx, bool forTargetVariant = false) const; /// Returns true if the decl has an active `@backDeployed` attribute for the /// given context. bool isBackDeployed(ASTContext &Ctx) const; /// 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(bool SerializedOK = true) 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; /// Retrieve the location at which we should insert a new attribute or /// modifier. SourceLoc getAttributeInsertionLoc(bool forModifier) const; using ImportAccessLevel = std::optional>; /// Returns the import that may restrict the access to this decl /// from \p useDC. /// /// If this decl and \p useDC are from the same module it returns /// \c std::nullopt. If there are many imports, it returns the most /// permissive one. ImportAccessLevel getImportAccessFrom(const DeclContext *useDC) const; SourceLoc TrailingSemiLoc; /// Whether this declaration is within a macro expansion relative to /// its decl context. If the decl context is itself in a macro expansion, /// the method returns \c true if this decl is in a different macro /// expansion buffer than the context. /// /// \Note this method returns \c false if this declaration was /// constructed from a serialized module. bool isInMacroExpansionInContext() 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 type that does not have either an /// *ApplicationMain or an main attribute. ArtificialMainKind getArtificialMainKind() const; SWIFT_DEBUG_DUMP; SWIFT_DEBUG_DUMPER(dump(const char *filename)); void dump(raw_ostream &OS, unsigned Indent = 0) const; /// 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; void printInherited(ASTPrinter &Printer, const PrintOptions &Options) const; /// 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; /// 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); /// Return whether this declaration has been determined invalid. bool isInvalid() const; /// Mark this declaration invalid. void setInvalid(); /// Determine whether this declaration was implicitly generated by the /// compiler (rather than explicitly written in source code). bool isImplicit() const { return Bits.Decl.Implicit; } /// Mark this declaration as implicit. void setImplicit(bool implicit = true) { Bits.Decl.Implicit = implicit; } /// Determine whether this declaration is syntactically scoped inside of /// a local context, but should behave like a top-level declaration /// for name lookup purposes. This is used by lldb. bool isHoisted() const { return Bits.Decl.Hoisted; } /// Set whether this declaration should be syntactically scoped inside /// of a local context, but should behave like a top-level declaration, /// but should behave like a top-level declaration. This is used by lldb. void setHoisted(bool hoisted = true) { Bits.Decl.Hoisted = hoisted; } /// Whether this declaration predates the introduction of concurrency. bool preconcurrency() const; /// Query whether this declaration was explicitly declared to be safe or /// unsafe. ExplicitSafety getExplicitSafety() const; private: bool isUnsafeComputed() const { return Bits.Decl.IsUnsafeComputed; } bool isUnsafeRaw() const { return Bits.Decl.IsUnsafe; } void setUnsafe(bool value) { assert(!Bits.Decl.IsUnsafeComputed); Bits.Decl.IsUnsafe = value; Bits.Decl.IsUnsafeComputed = true; } public: bool getSemanticAttrsComputed() const { return Bits.Decl.SemanticAttrsComputed; } void setSemanticAttrsComputed(bool Computed) { Bits.Decl.SemanticAttrsComputed = Computed; } /// \returns the unparsed comment attached to this declaration. RawComment getRawComment() const; std::optional getGroupName() const; std::optional getSourceFileName() const; std::optional getSourceOrder() const; /// Get the declaration that actually provides a doc comment for another. const Decl *getDocCommentProvidingDecl() const; /// \returns The brief comment attached to this declaration, or the brief /// comment attached to the comment providing decl. StringRef getSemanticBriefComment() const; /// Returns true if there is a Clang AST node associated /// with self. bool hasClangNode() const { return Bits.Decl.FromClang; } /// Retrieve the Clang AST node from which this declaration was /// synthesized, if any. LLVM_READONLY ClangNode getClangNode() const { if (!Bits.Decl.FromClang) return ClangNode(); return getClangNodeImpl(); } /// Retrieve the Clang declaration from which this declaration was /// synthesized, if any. LLVM_READONLY const clang::Decl *getClangDecl() const { if (!Bits.Decl.FromClang) return nullptr; return getClangNodeImpl().getAsDecl(); } /// Retrieve the Clang macro from which this declaration was /// synthesized, if any. LLVM_READONLY const clang::MacroInfo *getClangMacro() { if (!Bits.Decl.FromClang) return nullptr; return getClangNodeImpl().getAsMacro(); } /// If this is the Swift implementation of a declaration imported from ObjC, /// returns the imported declaration. (If there are several, only the main /// class body will be returned.) Otherwise return \c nullptr. /// /// \seeAlso ExtensionDecl::isObjCInterface() Decl *getImplementedObjCDecl() const { auto impls = getAllImplementedObjCDecls(); if (impls.empty()) return nullptr; return impls.front(); } /// If this is the Swift implementation of a declaration imported from ObjC, /// returns the imported declarations. (There may be several for a main class /// body; if so, the first will be the class itself.) Otherwise return an empty list. /// /// \seeAlso ExtensionDecl::isObjCInterface() llvm::TinyPtrVector getAllImplementedObjCDecls() const; /// If this is the ObjC interface of a declaration implemented in Swift, /// returns the implementating declaration. Otherwise return \c nullptr. /// /// \seeAlso ExtensionDecl::isObjCInterface() Decl *getObjCImplementationDecl() const; bool getCachedLacksObjCInterfaceOrImplementation() const { return Bits.Decl.LacksObjCInterfaceOrImplementation; } void setCachedLacksObjCInterfaceOrImplementation(bool value) { Bits.Decl.LacksObjCInterfaceOrImplementation = value; } /// Return the GenericContext if the Decl has one. LLVM_READONLY const GenericContext *getAsGenericContext() const; bool hasUnderscoredNaming() const; /// Whether this declaration is from a system module and should be considered /// implicitly private. bool isPrivateSystemDecl(bool treatNonBuiltinProtocolsAsPublic = true) const; /// Check if this is a declaration defined at the top level of the Swift module bool isStdlibDecl() const; /// The effective lifetime resulting from the decorations on the declaration. /// /// Usually, this, not getLifetimeAnnotationFromAttributes should be used. LifetimeAnnotation getLifetimeAnnotation() const; /// The source-level lifetime attribute, either @_eagerMove or @_noEagerMove /// that the declaration bears. /// /// Usually getLifetimeAnnotation should be used. /// /// Needed to access the attributes before the AST has been fully formed, such /// as when printing. LifetimeAnnotation getLifetimeAnnotationFromAttributes() const; bool isNoImplicitCopy() const { return getAttrs().hasAttribute(); } AvailabilityRange getAvailabilityForLinkage() const; /// Whether this declaration or one of its outer contexts has the /// @_weakLinked attribute. bool isAlwaysWeakImported() const; /// Whether this declaration is weak-imported from the given module, /// either because of the presence of the @_weakLinked attribute, or /// because of availability. /// /// Note that \p fromModule should either be the "main module" or /// nullptr. (This is because when it is non-null, we query the /// current deployment target, and not the deployment target that /// the module was built with.) /// /// If \p fromModule is the main module, this returns false when the /// declaration is part of the main module, or if the declaration is /// at least as available as the current deployment target. /// /// If \p fromModule is null, we instead return true if the /// declaration is meant to be weak linked with _some_ deployment /// target; that is, the presence of the @_weakLinked attribute or /// any kind of availability is enough, irrespective of the current /// deployment target. bool isWeakImported(ModuleDecl *fromModule) const; /// Returns true if the nature of this declaration allows overrides syntactically. /// /// If this returns true, the decl can be safely casted to ValueDecl. bool isSyntacticallyOverridable() const; /// Retrieve the global actor attribute that applies to this declaration, /// if any. /// /// This is the "raw" global actor attribute as written directly on the /// declaration, along with the nominal type declaration to which it refers, /// without any inference rules applied. std::optional> getGlobalActorAttr() const; /// Determine whether there is an explicit isolation attribute /// of any kind. bool hasExplicitIsolationAttribute() const; /// If an alternative module name is specified for this decl, e.g. using /// @_originalDefinedIn attribute, this function returns this module name. StringRef getAlternateModuleName() const; /// Is this Decl an SPI? It can be directly marked with @_spi or is defined in /// an @_spi context. bool isSPI() const; /// Returns true if the attribute providing the platform availability /// introduction for this decl is an `@_spi_available` attribute. bool isAvailableAsSPI() const; /// Determine whether this Decl has either Private or FilePrivate access, /// and its DeclContext does not. bool isOutermostPrivateOrFilePrivateScope() const; /// Returns an iterable list of the valid `AvailableAttr` and /// `AvailabilityDomain` pairs. Unless \p includeInactive is true, attributes /// that are considered inactive for the compilation context are filtered out. SemanticAvailableAttributes getSemanticAvailableAttrs(bool includeInactive = true) const; /// Returns the SemanticAvailableAttr associated with the given /// `AvailableAttr` that is attached to this decl. Returns `std::nullopt` if a /// valid semantic version of the attribute cannot be constructed (e.g. the /// domain cannot be resolved). std::optional getSemanticAvailableAttr(const AvailableAttr *attr) const; /// Returns the active platform-specific `@available` attribute for this decl. /// There may be multiple `@available` attributes that are relevant to the /// current platform, but the returned one has the highest priority. std::optional getActiveAvailableAttrForCurrentPlatform() const; /// Returns the active platform-specific `@available` attribute that should be /// used to determine the platform introduction version of the decl. /// /// If the declaration does not have a platform introduction attribute of its /// own and is a member of an extension then the platform introduction /// attribute attached to the extension will be returned instead unless \p /// checkExtension is false. std::optional getAvailableAttrForPlatformIntroduction(bool checkExtension = true) const; /// Returns true if the declaration is deprecated at the current deployment /// target. bool isDeprecated() const { return getDeprecatedAttr().has_value(); } /// Returns the first `@available` attribute that indicates that this decl /// is deprecated on current deployment target, or `nullptr` otherwise. std::optional getDeprecatedAttr() const; /// Returns the first `@available` attribute that indicates that this decl /// will be deprecated in the future, or `nullptr` otherwise. std::optional getSoftDeprecatedAttr() const; /// Returns the first @available attribute that indicates this decl is /// unavailable from asynchronous contexts, or `nullptr` otherwise. std::optional getNoAsyncAttr() const; /// Returns true if the decl has been marked unavailable in the Swift language /// version that is currently active. bool isUnavailableInCurrentSwiftVersion() const; /// Returns true if the decl is always unavailable in the current compilation /// context. For example, the decl could be marked explicitly unavailable on /// either the current platform or in the current language mode. Returns false /// for declarations that are only _potentially_ unavailable because of a /// condition that could be satisfied at runtime (like requiring an operating /// system version that is higher than the current deployment target). /// /// Note that this query only considers the attributes that are attached /// directly to this decl (or the extension it is declared in, if applicable). bool isUnavailable() const { return getUnavailableAttr().has_value(); } /// If the decl is always unavailable in the current compilation /// context, returns the attribute attached to the decl (or its parent /// extension) that makes it unavailable. std::optional getUnavailableAttr() const; /// Returns true if code associated with this declaration should be considerd /// unreachable at runtime because the declaration is unavailable in all /// execution contexts in which the code may run. This result takes the /// availability of parent declarations into account. bool isUnreachableAtRuntime() const; /// Returns true if this declaration should be considered available during /// SIL/IR lowering. A declaration would not be available during lowering if, /// for example, it is annotated as unavailable with `@available` and /// optimization settings require that it be omitted. Canonical SIL must not /// contain any references to declarations that are unavailable during /// lowering because the resulting IR could reference non-existent symbols /// and fail to link. bool isAvailableDuringLowering() const; /// Returns true if ABI compatibility stubs must be emitted for the given /// declaration. Decls marked unavailable with `@available` require these /// stubs if the compiler flags have enabled unavailable declaration ABI /// compatibility mode. bool requiresUnavailableDeclABICompatibilityStubs() const; // List the SPI groups declared with @_spi or inherited by this decl. // // SPI groups are inherited from the parent contexts only if the local decl // doesn't declare any @_spi. ArrayRef getSPIGroups() const; /// Returns true if this declaration has any `@backDeployed` attributes. bool hasBackDeployedAttr() const; /// Return the declaration upon which the attributes for this declaration /// would appear in concrete syntax. This function is necessary because for /// semantic analysis, the parser attaches attributes to declarations other /// than those on which they, concretely, appear. const Decl *getConcreteSyntaxDeclForAttributes() const; /// Return the declaration to which the parser actually attaches attributes in /// the abstract syntax tree (see `getConcreteSyntaxDeclForAttributes()`). const Decl *getAbstractSyntaxDeclForAttributes() const; /// Apply the specified function to decls that should be placed _next_ to /// this decl when constructing AST. void forEachDeclToHoist(llvm::function_ref callback) const; /// Emit a diagnostic tied to this declaration. template InFlightDiagnostic diagnose( Diag ID, typename detail::PassArgument::type... Args) const { return getDiags().diagnose(this, ID, std::move(Args)...); } /// Retrieve the diagnostic engine for diagnostics emission. LLVM_READONLY DiagnosticEngine &getDiags() const; }; /// 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; } /// A convenience function object for filtering out decls that are not available /// during lowering. template struct AvailableDuringLoweringDeclFilter { std::optional operator()(T *decl) const { if (decl->isAvailableDuringLowering()) return decl; return std::nullopt; } }; // A private class for forcing exact field layout. class alignas(8) _GenericContext { // Not really public. See GenericContext. public: /// The state of the generic parameters. enum class GenericParamsState: uint8_t { /// The stored generic parameters represent parsed generic parameters, /// written in the source. Parsed = 0, /// The stored generic parameters represent generic parameters that are /// synthesized by the type checker but were not written in the source. TypeChecked = 1, /// The stored generic parameters represent both the parsed and /// type-checked generic parameters. ParsedAndTypeChecked = 2, }; llvm::PointerIntPair GenericParamsAndState; /// 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 of this declaration. llvm::PointerIntPair GenericSigAndBit; }; class GenericContext : private _GenericContext, public DeclContext { friend class GenericParamListRequest; friend class GenericSignatureRequest; protected: GenericContext(DeclContextKind Kind, DeclContext *Parent, GenericParamList *Params); public: /// Retrieve the set of parameters to a generic context, or null if /// this context is not generic. GenericParamList *getGenericParams() const; /// Retrieve the generic parameters as written in source. Unlike /// getGenericParams() this will not synthesize generic parameters for /// extensions, protocols and certain type aliases. GenericParamList *getParsedGenericParams() const; /// Determine whether this context has generic parameters /// of its own. /// /// \code /// class C { /// func f1() {} // isGeneric == false /// func f2() {} // isGeneric == true /// } /// /// protocol P { // isGeneric == true due to implicit Self param /// func p() // isGeneric == false /// } /// \endcode bool isGeneric() const { return getGenericParams() != nullptr; } bool hasComputedGenericSignature() const; bool isComputingGenericSignature() const; /// 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. ArrayRef getInnermostGenericParamTypes() const; /// Retrieve the generic requirements. ArrayRef getGenericRequirements() const; /// Set the generic signature of this context. void setGenericSignature(GenericSignature genericSig); /// Retrieve the position of any where clause for this context's /// generic parameters. SourceRange getGenericTrailingWhereClauseSourceRange() const; static bool classof(const Decl *D); }; static_assert(sizeof(_GenericContext) + sizeof(DeclContext) == sizeof(GenericContext), "Please add fields to _GenericContext"); /// 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; friend class Decl; SourceLoc ImportLoc; SourceLoc KindLoc; /// Used to store the real module name corresponding to this import decl in /// case module aliasing is used. For example if '-module-alias Foo=Bar' was /// passed and this decl is 'import Foo', the real name 'Bar' will be stored. Identifier RealModuleName; /// The resolved module. ModuleDecl *Mod = nullptr; ImportDecl(DeclContext *DC, SourceLoc ImportLoc, ImportKind K, SourceLoc KindLoc, ImportPath Path); public: static ImportDecl *create(ASTContext &C, DeclContext *DC, SourceLoc ImportLoc, ImportKind Kind, SourceLoc KindLoc, ImportPath 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 std::optional findBestImportKind(ArrayRef Decls); ImportKind getImportKind() const { return static_cast(Bits.ImportDecl.ImportKind); } /// Retrieves the import path as written in the source code. /// /// \returns An \c ImportPath corresponding to this import decl. If module aliasing /// was used, this will contain the aliased name of the module; for instance, /// if you wrote 'import Foo' but passed '-module-alias Foo=Bar', this import /// path will include 'Foo'. This return value is always owned by \c ImportDecl /// (which is owned by the AST context), so it can be persisted. ImportPath getImportPath() const { return ImportPath({ getTrailingObjects(), static_cast(Bits.ImportDecl.NumPathElements) }); } /// Retrieves the import path, replacing any module aliases with real names. /// /// \param scratch An \c ImportPath::Builder which may, if necessary, be used to /// construct the return value. It may go unused, so you should not try to /// read the result from it; use the return value instead. /// \returns An \c ImportPath corresponding to this import decl. If module aliasing /// was used, this will contain the real name of the module; for instance, /// if you wrote 'import Foo' but passed '-module-alias Foo=Bar', this import /// path will include 'Bar'. This return value may be owned by \p scratch, /// so it should not be used after \p scratch is destroyed. ImportPath getRealImportPath(ImportPath::Builder &scratch) const; /// Retrieves the part of the import path that contains the module name, /// as written in the source code. /// /// \returns A \c ImportPath::Module corresponding to this import decl. If module /// aliasing was used, this will contain the aliased name of the module; for /// instance, if you wrote 'import Foo' but passed '-module-alias Foo=Bar', /// this module path will contain 'Foo'. This return value is always owned by /// \c ImportDecl (which is owned by the AST context), so it can be persisted. ImportPath::Module getModulePath() const { return getImportPath().getModulePath(getImportKind()); } /// Retrieves the part of the import path that contains the module name, /// replacing any module aliases with real names. /// /// \param scratch An \c ImportPath::Builder which may, if necessary, be used to /// construct the return value. It may go unused, so you should not try to /// read the result from it; use the return value instead. /// \returns An \c ImportPath::Module corresponding to this import decl. If module /// aliasing was used, this will contain the real name of the module; for /// instance, if you wrote 'import Foo' but passed '-module-alias Foo=Bar', /// the returned path will contain 'Bar'. This return value may be owned /// by \p scratch, so it should not be used after \p scratch is destroyed. ImportPath::Module getRealModulePath(ImportPath::Builder &scratch) const { return getRealImportPath(scratch).getModulePath(getImportKind()); } ImportPath::Access getAccessPath() const { return getImportPath().getAccessPath(getImportKind()); } bool isExported() const { return getAttrs().hasAttribute(); } bool isTestable() const { return getAttrs().hasAttribute(); } ModuleDecl *getModule() const { return Mod; } void setModule(ModuleDecl *M) { Mod = M; } /// For a scoped import such as 'import class Foundation.NSString', retrieve /// the decls it references. Otherwise, returns an empty array. ArrayRef getDecls() const; /// Access level of this import, either explicitly declared or implicit. AccessLevel getAccessLevel() const; /// Is the access level of this import implicit, aka a default import? bool isAccessLevelImplicit() const; const clang::Module *getClangModule() const { return getClangNode().getClangModule(); } SourceLoc getStartLoc() const { return ImportLoc; } SourceLoc getLocFromSource() const { return getImportPath().getSourceRange().Start; } SourceRange getSourceRange() const { return SourceRange(ImportLoc, getImportPath().getSourceRange().End); } SourceLoc getKindLoc() const { return KindLoc; } static bool classof(const Decl *D) { return D->getKind() == DeclKind::Import; } }; /// An entry in the "inherited" list of a type or extension. struct InheritedEntry : public TypeLoc { private: /// Options on a protocol conformance that are expressed as attributes. unsigned RawOptions: 8; /// Whether there was a ~ indicating suppression. /// /// This is true in cases like ~Copyable but not (P & ~Copyable). bool IsSuppressed : 1; /// The global actor isolation provided (for a conformance). TypeExpr *globalActorIsolationType = nullptr; public: InheritedEntry(const TypeLoc &typeLoc); InheritedEntry(const TypeLoc &typeLoc, ProtocolConformanceOptions options, bool isSuppressed = false) : TypeLoc(typeLoc), RawOptions(options.toRaw()), IsSuppressed(isSuppressed), globalActorIsolationType(options.getGlobalActorIsolationType()) {} ProtocolConformanceOptions getOptions() const { return ProtocolConformanceOptions(RawOptions, globalActorIsolationType); } bool isUnchecked() const { return getOptions().contains(ProtocolConformanceFlags::Unchecked); } bool isRetroactive() const { return getOptions().contains(ProtocolConformanceFlags::Retroactive); } bool isPreconcurrency() const { return getOptions().contains(ProtocolConformanceFlags::Preconcurrency); } bool isNonisolated() const { return getOptions().contains(ProtocolConformanceFlags::Nonisolated); } TypeExpr *getGlobalActorIsolationType() const { return globalActorIsolationType; } ExplicitSafety getExplicitSafety() const { if (getOptions().contains(ProtocolConformanceFlags::Unsafe)) return ExplicitSafety::Unsafe; return ExplicitSafety::Unspecified; } bool isSuppressed() const { return IsSuppressed; } void setOption(ProtocolConformanceFlags flag) { RawOptions = (getOptions() | flag).toRaw(); } void setOption(ExplicitSafety safety) { RawOptions = (getOptions() - ProtocolConformanceFlags::Unsafe).toRaw(); switch (safety) { case ExplicitSafety::Unspecified: case ExplicitSafety::Safe: break; case ExplicitSafety::Unsafe: RawOptions = (getOptions() | ProtocolConformanceFlags::Unsafe).toRaw(); break; } } void setSuppressed() { assert(!IsSuppressed && "setting suppressed again!?"); IsSuppressed = true; } void dump(raw_ostream &os) const; SWIFT_DEBUG_DUMP; }; /// A wrapper for the collection of inherited types for either a `TypeDecl` or /// an `ExtensionDecl`. class InheritedTypes { llvm::PointerUnion Decl; ArrayRef Entries; public: InheritedTypes( llvm::PointerUnion decl); InheritedTypes(const class Decl *decl); InheritedTypes(const TypeDecl *typeDecl); InheritedTypes(const ExtensionDecl *extensionDecl); bool empty() const { return Entries.empty(); } size_t size() const { return Entries.size(); } IntRange const getIndices() { return indices(Entries); } /// Returns the ASTContext associated with the wrapped declaration. ASTContext &getASTContext() const; /// Returns the `TypeRepr *` for the entry of the inheritance clause at the /// given index. TypeRepr *getTypeRepr(unsigned i) const { return Entries[i].getTypeRepr(); } /// Returns the `Type` for the entry of the inheritance clause at the given /// index, resolved at the given stage, or `Type()` if resolution fails. Type getResolvedType(unsigned i, TypeResolutionStage stage = TypeResolutionStage::Interface) const; /// Returns the underlying array of inherited type entries. /// /// NOTE: The `Type` associated with an entry may not be resolved yet. ArrayRef getEntries() const { return Entries; } /// Returns the entry of the inheritance clause at the given index. /// /// NOTE: The `Type` associated with the entry may not be resolved yet. const InheritedEntry &getEntry(unsigned i) const { return Entries[i]; } // Retrieve the location of the colon character introducing the inheritance // clause. SourceLoc getColonLoc() const; /// Returns the source location of the beginning of the inheritance clause. SourceLoc getStartLoc() const { return getEntries().front().getSourceRange().Start; } /// Returns the source location of the end of the inheritance clause. SourceLoc getEndLoc() const { return getEntries().back().getSourceRange().End; } /// Compute the SourceRange to be used when removing entry \c i from the /// inheritance clause. Accounts for commas and colons as-needed. SourceRange getRemovalRange(unsigned i) const; }; /// 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. TypeRepr *ExtendedTypeRepr; /// The nominal type being extended. /// /// The bit indicates whether binding has been attempted. The pointer can be /// null if either no binding was attempted or if binding could not find the /// extended nominal. llvm::PointerIntPair ExtendedNominal; ArrayRef Inherited; /// 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; friend class InheritedTypes; ExtensionDecl(SourceLoc extensionLoc, TypeRepr *extendedType, ArrayRef 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(); friend class ExtendedNominalRequest; friend class Decl; public: using Decl::getASTContext; /// Create a new extension declaration. static ExtensionDecl *create(ASTContext &ctx, SourceLoc extensionLoc, TypeRepr *extendedType, ArrayRef inherited, DeclContext *parent, TrailingWhereClause *trailingWhereClause, ClangNode clangNode = ClangNode()); SourceLoc getStartLoc() const { return ExtensionLoc; } SourceLoc getLocFromSource() const { return ExtensionLoc; } SourceRange getSourceRange() const { if (!Braces.isValid()) return SourceRange(ExtensionLoc); return { ExtensionLoc, Braces.End }; } SourceRange getBraces() const { return Braces; } void setBraces(SourceRange braces) { Braces = braces; } bool hasBeenBound() const { return ExtendedNominal.getInt(); } void setExtendedNominal(NominalTypeDecl *n) { ExtendedNominal.setPointerAndInt(n, true); } /// Retrieve the type being extended. /// /// Only use this entry point when the complete type, as spelled in the source, /// is required. For most clients, \c getExtendedNominal(), which provides /// only the \c NominalTypeDecl, will suffice. Type getExtendedType() const; /// Retrieve the nominal type declaration that is being extended. /// Will trip an assertion if the declaration has not already been computed. /// In order to fail fast when type checking work is attempted /// before extension binding has taken place. NominalTypeDecl *getExtendedNominal() const; /// Compute the nominal type declaration that is being extended. NominalTypeDecl *computeExtendedNominal() const; /// \c hasBeenBound means nothing if this extension can never been bound /// because it is not at the top level. bool canNeverBeBound() const; bool hasValidParent() const; /// Retrieve the extended type definition as written in the source, if it exists. /// /// Repr would not be available if the extension was been loaded /// from a serialized module. TypeRepr *getExtendedTypeRepr() const { return ExtendedTypeRepr; } /// Retrieve the set of protocols that this type inherits (i.e, /// explicitly conforms to). InheritedTypes getInherited() const { return InheritedTypes(this); } void setInherited(ArrayRef i) { Inherited = i; } bool hasDefaultAccessLevel() const { return Bits.ExtensionDecl.DefaultAndMaxAccessLevel != 0; } uint8_t getDefaultAndMaxAccessLevelBits() const { return Bits.ExtensionDecl.DefaultAndMaxAccessLevel; } void setDefaultAndMaxAccessLevelBits(AccessLevel defaultAccess, AccessLevel maxAccess) { Bits.ExtensionDecl.DefaultAndMaxAccessLevel = (1 << (static_cast(defaultAccess) - 1)) | (1 << (static_cast(maxAccess) - 1)); } AccessLevel getDefaultAccessLevel() const; AccessLevel getMaxAccessLevel() const; 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"); setDefaultAndMaxAccessLevelBits(defaultAccess, maxAccess); 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; /// Determine whether this extension context is in the same defining module as /// the original nominal type context. bool isInSameDefiningModule() const; /// Determine whether this extension is equivalent to one that requires at /// at least some constraints to be written in the source. /// /// This result will differ from `isConstrainedExtension()` when any of /// the generic parameters of the type are invertible, e.g., /// \code /// struct X: ~Copyable { } /// /// // Implies `T: Copyable`. This extension `!isWrittenWithConstraints()` /// // and `isConstrainedExtension()`. /// extension X { } /// /// // This extension `isWrittenWithConstraints()` /// // and `!isConstrainedExtension()`. /// extension X where T: ~Copyable { } /// /// // Implies `T: Copyable`. This extension `isWrittenWithConstraints()` /// // and `isConstrainedExtension()`. /// extension X where T: P { } /// /// // This extension `isWrittenWithConstraints()` /// // and `isConstrainedExtension()`. /// extension X where T: Q, T: ~Copyable { } /// \endcode bool isWrittenWithConstraints() const; /// Does this extension add conformance to an invertible protocol for the /// extended type? /// /// Returns \c nullopt if the extension does not add conformance to any /// invertible protocol. Returns one of the invertible protocols being /// conformed to otherwise. std::optional isAddingConformanceToInvertible() const; /// If this extension represents an imported Objective-C category, returns the /// category's name. Otherwise returns the empty identifier. Identifier getObjCCategoryName() const; // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() == DeclKind::Extension; } static bool classof(const DeclContext *C) { if (auto D = C->getAsDecl()) return classof(D); return false; } static bool classof(const IterableDeclContext *C) { return C->getIterableContextKind() == IterableDeclContextKind::ExtensionDecl; } using DeclContext::operator new; using DeclContext::operator delete; }; /// 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; } }; /// 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 { enum class Flags { // 1 << 0 is available Removed = 1 << 1, /// Whether the contents of this initializer were subsumed by /// some other initialization, e.g., a lazy property's initializer /// gets subsumed by the getter body. Subsumed = 1 << 2, }; llvm::PointerIntPair> PatternAndFlags; enum class InitializerStatus { /// The init expression has not been typechecked. NotChecked = 0, /// The init expression has been typechecked but not contextualized. Checked, /// The init expression has been typechecked and contextualized. CheckedAndContextualized, }; struct InitializerAndEqualLoc { // When the initializer is removed we don't actually clear the pointers // because we might need to get initializer's source range. Since the // initializer is ASTContext-allocated it is safe. /// Exactly the expr the programmer wrote Expr *originalInit; /// Might be transformed, e.g. for a property wrapper. In the absence of /// transformation or synthesis, holds the expr as parsed. llvm::PointerIntPair initAfterSynthesis; /// The location of the equal '=' token. SourceLoc EqualLoc; }; union { /// The initializer expression and its '=' token loc. InitializerAndEqualLoc InitExpr; /// The text of the initializer expression if deserialized from a module. StringRef InitStringRepresentation; }; enum class PatternFlags { IsText = 1 << 0, IsFullyValidated = 1 << 1, IsFromDebugger = 1 << 2, }; /// The initializer context used for this pattern binding entry. llvm::PointerIntPair> InitContextAndFlags; /// Values captured by this initializer. CaptureInfo Captures; friend class Parser; friend class PatternBindingInitializer; friend class PatternBindingDecl; friend class ast_scope::AbstractPatternEntryScope; friend class ast_scope::GenericParamScope; friend class ast_scope::PatternEntryDeclScope; friend class ast_scope::PatternEntryInitializerScope; private: // FIXME: This API is transitional. Once the callers of // typeCheckPatternBinding are requestified, merge this bit with // Flags::Checked. friend class PatternBindingEntryRequest; friend class PatternBindingCheckedAndContextualizedInitRequest; bool isFullyValidated() const { return InitContextAndFlags.getInt().contains( PatternFlags::IsFullyValidated); } void setFullyValidated() { InitContextAndFlags.setInt(InitContextAndFlags.getInt() | PatternFlags::IsFullyValidated); } /// Set if this pattern binding came from the debugger. /// /// Stay away unless you are \c PatternBindingDecl::createForDebugger void setFromDebugger() { InitContextAndFlags.setInt(InitContextAndFlags.getInt() | PatternFlags::IsFromDebugger); } public: /// \p E is the initializer as parsed. PatternBindingEntry(Pattern *P, SourceLoc EqualLoc, Expr *E, PatternBindingInitializer *InitContext) : PatternAndFlags(P, {}), InitExpr({E, {E, InitializerStatus::NotChecked}, EqualLoc}), InitContextAndFlags({InitContext, std::nullopt}) {} private: Pattern *getPattern() const { return PatternAndFlags.getPointer(); } void setPattern(Pattern *P) { PatternAndFlags.setPointer(P); } /// Whether the given pattern binding entry is initialized. /// /// \param onlyExplicit Only consider explicit initializations (rather /// than implicitly-generated ones). bool isInitialized(bool onlyExplicit = false) const; Expr *getInit() const { if (PatternAndFlags.getInt().contains(Flags::Removed) || InitContextAndFlags.getInt().contains(PatternFlags::IsText)) return nullptr; return InitExpr.initAfterSynthesis.getPointer(); } /// Retrieve the initializer if it should be executed to initialize this /// particular pattern binding. Expr *getExecutableInit() const { return isInitializerSubsumed() ? nullptr : getInit(); } SourceRange getOriginalInitRange() const; void setInit(Expr *E); /// Gets the text of the initializer expression, stripping out inactive /// branches of any #ifs inside the expression. StringRef getInitStringRepresentation(SmallVectorImpl &scratch) const; /// Sets the initializer string representation to the string that was /// deserialized from a partial module. void setInitStringRepresentation(StringRef str) { InitStringRepresentation = str; InitContextAndFlags.setInt(InitContextAndFlags.getInt() | PatternFlags::IsText); } /// Whether this pattern entry can generate a string representation of its /// initializer expression. bool hasInitStringRepresentation() const; /// Retrieve the location of the equal '=' token. SourceLoc getEqualLoc() const { return InitContextAndFlags.getInt().contains(PatternFlags::IsText) ? SourceLoc() : InitExpr.EqualLoc; } /// Set the location of the equal '=' token. void setEqualLoc(SourceLoc equalLoc) { assert(!InitContextAndFlags.getInt().contains(PatternFlags::IsText) && "cannot set equal loc for textual initializer"); InitExpr.EqualLoc = equalLoc; } /// Retrieve the initializer after the =, if any, as it was written in the /// source. Expr *getOriginalInit() const; /// Set the initializer after the = as it was written in the source. void setOriginalInit(Expr *); InitializerStatus initializerStatus() const { if (InitContextAndFlags.getInt().contains(PatternFlags::IsText)) return InitializerStatus::NotChecked; return InitExpr.initAfterSynthesis.getInt(); } bool isInitializerChecked() const { return initializerStatus() != InitializerStatus::NotChecked; } void setInitializerChecked() { assert(!InitContextAndFlags.getInt().contains(PatternFlags::IsText)); InitExpr.initAfterSynthesis.setInt(InitializerStatus::Checked); } bool isInitializerCheckedAndContextualized() const { return initializerStatus() == InitializerStatus::CheckedAndContextualized; } void setInitializerCheckedAndContextualized() { assert(!InitContextAndFlags.getInt().contains(PatternFlags::IsText)); InitExpr.initAfterSynthesis.setInt( InitializerStatus::CheckedAndContextualized); } bool isInitializerSubsumed() const { return PatternAndFlags.getInt().contains(Flags::Subsumed); } void setInitializerSubsumed() { PatternAndFlags.setInt(PatternAndFlags.getInt() | Flags::Subsumed); } /// Returns \c true if the debugger created this pattern binding entry. bool isFromDebugger() const { return InitContextAndFlags.getInt().contains(PatternFlags::IsFromDebugger); } // Return the first variable initialized by this pattern. VarDecl *getAnchoringVarDecl() const; // Retrieve the declaration context for the initializer. PatternBindingInitializer *getInitContext() const { return InitContextAndFlags.getPointer(); } /// Override the initializer context. void setInitContext(PatternBindingInitializer *init) { InitContextAndFlags.setPointer(init); } SourceLoc getStartLoc() const; /// Retrieve the end location covered by this pattern binding entry. /// /// \param omitAccessors Whether the computation should omit the accessors /// from the source range. SourceLoc getEndLoc(bool omitAccessors = false) const; /// Retrieve the source range covered by this pattern binding entry. /// /// \param omitAccessors Whether the computation should omit the accessors /// from the source range. SourceRange getSourceRange(bool omitAccessors = false) const; CaptureInfo getCaptureInfo() const { return Captures; } void setCaptureInfo(CaptureInfo captures) { Captures = captures; } private: SourceLoc getLastAccessorEndLoc() const; }; /// 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; friend class Decl; friend class PatternBindingEntryRequest; friend class PatternBindingCheckedAndContextualizedInitRequest; 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); SourceLoc getLocFromSource() const { return VarLoc; } 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, SourceLoc EqualLoc, Expr *E, DeclContext *Parent); static PatternBindingDecl *createImplicit(ASTContext &Ctx, StaticSpellingKind StaticSpelling, Pattern *Pat, Expr *E, DeclContext *Parent, SourceLoc VarLoc = SourceLoc()); static PatternBindingDecl *createDeserialized( ASTContext &Ctx, SourceLoc StaticLoc, StaticSpellingKind StaticSpelling, SourceLoc VarLoc, unsigned NumPatternEntries, DeclContext *Parent); // A dedicated entrypoint that allows LLDB to create pattern bindings // that look implicit to the compiler but contain user code. static PatternBindingDecl *createForDebugger(ASTContext &Ctx, StaticSpellingKind Spelling, Pattern *Pat, Expr *E, DeclContext *Parent); SourceLoc getStartLoc() const { return StaticLoc.isValid() ? StaticLoc : VarLoc; } SourceRange getSourceRange() const; unsigned getNumPatternEntries() const { return Bits.PatternBindingDecl.NumPatternEntries; } ArrayRef getPatternList() const { return const_cast(this)->getMutablePatternList(); } /// Returns the typechecked binding entry at the given index. const PatternBindingEntry *getCheckedPatternBindingEntry(unsigned i) const; /// Clean up walking the initializers for the pattern class InitIterator { const PatternBindingDecl &decl; unsigned currentPatternEntryIndex; void next() { ++currentPatternEntryIndex; } public: using value_type = Expr *; using pointer = value_type; using reference = value_type; using difference_type = unsigned; InitIterator(const PatternBindingDecl &decl, unsigned start = 0) : decl(decl), currentPatternEntryIndex(start) {} InitIterator &operator++() { next(); return *this; } InitIterator operator++(int) { InitIterator newIterator(decl, currentPatternEntryIndex); newIterator.next(); return newIterator; } pointer operator->() { return decl.getInit(currentPatternEntryIndex); } pointer operator*() { return decl.getInit(currentPatternEntryIndex); } difference_type operator-(const InitIterator &other) { return currentPatternEntryIndex - other.currentPatternEntryIndex; } bool operator==(const InitIterator &other) const { return &decl == &other.decl && currentPatternEntryIndex == other.currentPatternEntryIndex; } bool operator!=(const InitIterator &other) const { return !(*this == other); } }; InitIterator beginInits() const { return InitIterator(*this); } InitIterator endInits() const { return InitIterator(*this, getNumPatternEntries()); } llvm::iterator_range initializers() const { return llvm::make_range(beginInits(), endInits()); } void setInitStringRepresentation(unsigned i, StringRef str) { getMutablePatternList()[i].setInitStringRepresentation(str); } /// Whether the given pattern entry is initialized. bool isInitialized(unsigned i) const { return getPatternList()[i].isInitialized(); } Expr *getInit(unsigned i) const { return getPatternList()[i].getInit(); } Expr *getExecutableInit(unsigned i) const { return getPatternList()[i].getExecutableInit(); } Expr *getOriginalInit(unsigned i) const { return getPatternList()[i].getOriginalInit(); } SourceRange getOriginalInitRange(unsigned i) const { return getPatternList()[i].getOriginalInitRange(); } void setInit(unsigned i, Expr *E) { getMutablePatternList()[i].setInit(E); } void setOriginalInit(unsigned i, Expr *E) { getMutablePatternList()[i].setOriginalInit(E); } /// Returns a typechecked init expression for the pattern at the given /// index. Expr *getContextualizedInit(unsigned i) const; /// Returns an init expression for the pattern at the given index. /// The initializer is fully type checked, including effects checking. Expr *getCheckedAndContextualizedInit(unsigned i) const; /// Returns the result of `getCheckedAndContextualizedInit()` if the init is /// not subsumed. Otherwise, returns `nullptr`. Expr *getCheckedAndContextualizedExecutableInit(unsigned i) const; Pattern *getPattern(unsigned i) const { return getPatternList()[i].getPattern(); } void setPattern(unsigned i, Pattern *P, bool isFullyValidated = false); bool isFullyValidated(unsigned i) const { return getPatternList()[i].isFullyValidated(); } PatternBindingInitializer *getInitContext(unsigned i) const { return getPatternList()[i].getInitContext(); } void setInitContext(unsigned i, PatternBindingInitializer *init) { if (init) { init->setBinding(this, i); } getMutablePatternList()[i].setInitContext(init); } CaptureInfo getCaptureInfo(unsigned i) const { return getPatternList()[i].getCaptureInfo(); } void setCaptureInfo(unsigned i, CaptureInfo captures) { getMutablePatternList()[i].setCaptureInfo(captures); } /// 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; bool isInitializerChecked(unsigned i) const { return getPatternList()[i].isInitializerChecked(); } void setInitializerChecked(unsigned i) { getMutablePatternList()[i].setInitializerChecked(); } bool isInitializerSubsumed(unsigned i) const { return getPatternList()[i].isInitializerSubsumed(); } void setInitializerSubsumed(unsigned i) { getMutablePatternList()[i].setInitializerSubsumed(); } ActorIsolation getInitializerIsolation(unsigned i) const; /// 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. bool isDefaultInitializable() const { for (unsigned i : range(getNumPatternEntries())) if (!isDefaultInitializable(i)) return false; return true; } /// Can the pattern at index i be default initialized? bool isDefaultInitializable(unsigned i) const; /// Can the property wrapper be used to provide default initialization? bool isDefaultInitializableViaPropertyWrapper(unsigned i) const; /// Does this pattern have a user-provided initializer expression? bool isExplicitlyInitialized(unsigned i) const; /// Whether the pattern entry at the given index can generate a string /// representation of its initializer expression. bool hasInitStringRepresentation(unsigned i) const { return getPatternList()[i].hasInitStringRepresentation(); } SourceLoc getEqualLoc(unsigned i) const; /// When the pattern binding contains only a single variable with no /// destructuring, retrieve that variable. VarDecl *getSingleVar() const; /// Return the first variable initialized by the pattern at the given index. VarDecl *getAnchoringVarDecl(unsigned i) 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; /// Is the pattern binding entry for this variable currently being computed? bool isComputingPatternBindingEntry(const VarDecl *vd) const; /// Is this an "async let" declaration? bool isAsyncLet() const; /// Gets the text of the initializer expression for the pattern entry at the /// given index, stripping out inactive branches of any #ifs inside the /// expression. StringRef getInitStringRepresentation(unsigned i, SmallVectorImpl &scratch) const { return getPatternList()[i].getInitStringRepresentation(scratch); } /// Returns \c true if this pattern binding was created by the debugger. bool isDebuggerBinding() const { return Bits.PatternBindingDecl.IsDebugger; } /// Returns the \c VarDecl in this PBD at the same offset in the same /// pattern entry as \p otherVar is in its PBD, or \c nullptr if this PBD is /// too different from \p otherVar 's to find an equivalent variable. VarDecl *getVarAtSimilarStructuralPosition(VarDecl *otherVar); 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; SourceLoc getLocFromSource() const { return getStartLoc(); } friend class Decl; 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; SourceRange getSourceRange() const; LLVM_READONLY ASTContext &getASTContext() const { return DeclContext::getASTContext(); } static bool classof(const Decl *D) { return D->getKind() == DeclKind::TopLevelCode; } static bool classof(const DeclContext *C) { if (auto D = C->getAsDecl()) return classof(D); return false; } using DeclContext::operator new; using DeclContext::operator delete; }; /// 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 DeclContext { public: SerializedTopLevelCodeDeclContext(DeclContext *Parent) : DeclContext(DeclContextKind::SerializedTopLevelCodeDecl, Parent) {} static bool classof(const DeclContext *DC) { return DC->getContextKind() == DeclContextKind::SerializedTopLevelCodeDecl; } }; class OpaqueTypeDecl; /// ValueDecl - All named decls that are values in the language. These can /// have a type, etc. class ValueDecl : public Decl { public: enum : unsigned { InvalidDiscriminator = 0xFFFF }; private: DeclName Name; SourceLoc NameLoc; llvm::PointerIntPair> TypeAndAccess; unsigned LocalDiscriminator = InvalidDiscriminator; struct { /// Whether the "IsObjC" bit has been computed yet. unsigned isObjCComputed : 1; /// Whether this declaration is exposed to Objective-C. unsigned isObjC : 1; /// Whether the "overridden" declarations have been computed already. unsigned hasOverriddenComputed : 1; /// Whether there are any "overridden" declarations. The actual overridden /// declarations are kept in a side table in the ASTContext. unsigned hasOverridden : 1; /// Whether the "isDynamic" bit has been computed yet. unsigned isDynamicComputed : 1; /// Whether this declaration is 'dynamic', meaning that all uses of /// the declaration will go through an extra level of indirection that /// allows the entity to be replaced at runtime. unsigned isDynamic : 1; /// Whether the DynamicallyReplacedDeclRequest request was evaluated and /// output a null pointer. unsigned noDynamicallyReplacedDecl : 1; /// Whether the OpaqueResultTypeRequest request was evaluated and produced /// a null pointer. unsigned noOpaqueResultType : 1; /// Whether the "isFinal" bit has been computed yet. unsigned isFinalComputed : 1; /// Whether this declaration is 'final'. A final class can't be subclassed, /// a final class member can't be overridden. unsigned isFinal : 1; /// Whether the "isIUO" bit" has been computed yet. unsigned isIUOComputed : 1; /// Whether this declaration produces an implicitly unwrapped /// optional result. unsigned isIUO : 1; /// Whether we've evaluated the ApplyAccessNoteRequest. unsigned accessNoteApplied : 1; } LazySemanticInfo = { }; friend class DynamicallyReplacedDeclRequest; friend class OverriddenDeclsRequest; friend class IsObjCRequest; friend class IsFinalRequest; friend class IsDynamicRequest; friend class IsImplicitlyUnwrappedOptionalRequest; friend class InterfaceTypeRequest; friend class CheckRedeclarationRequest; friend class ActorIsolationRequest; friend class OpaqueResultTypeRequest; friend class ApplyAccessNoteRequest; friend class Decl; SourceLoc getLocFromSource() const { return NameLoc; } 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; Bits.ValueDecl.Synthesized = false; } // 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; } /// 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() { Bits.ValueDecl.CheckedRedeclaration = true; } public: /// Find the import that makes the given declaration available. std::optional> findImport(const DeclContext *fromDC) const; /// Return true if this protocol member is a protocol requirement. /// /// Asserts if this is not a member of a protocol. bool isProtocolRequirement() const; /// Return true if this is a member implementation for an \c @_objcImplementation /// extension. bool isObjCMemberImplementation() const; void setUserAccessible(bool Accessible) { Bits.ValueDecl.IsUserAccessible = Accessible; } bool isUserAccessible() const { return Bits.ValueDecl.IsUserAccessible; } /// Whether this decl has been synthesized by the compiler for use by the /// user. /// /// This is a refinement of isImplicit; all synthesized decls are implicit, /// but not all implicit decls are synthesized. The difference comes down to /// whether or not the decl is user-facing, e.g the implicit memberwise /// initializer is considered synthesized. Decls that are only meant for the /// compiler, e.g the implicit FuncDecl for a DeferStmt, are not considered /// synthesized. bool isSynthesized() const { return Bits.ValueDecl.Synthesized; } void setSynthesized(bool value = true) { Bits.ValueDecl.Synthesized = value; } /// Does this have a 'distributed' modifier? /// /// Only member methods and computed properties of a `distributed actor` /// can be distributed. bool isDistributed() const; /// Is this a '_distributed_get' accessor? /// /// These are special accessors used by distributed thunks, implementing /// `distributed var get { }` accessors. bool isDistributedGetAccessor() const; bool hasName() const { return bool(Name); } bool isOperator() const { return Name.isOperator(); } /// Retrieve the full name of the declaration. DeclName getName() 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(); } Identifier getBaseIdentifier() const { return Name.getBaseIdentifier(); } /// Generates a DeclNameRef referring to this declaration with as much /// specificity as possible. DeclNameRef createNameRef() const { return DeclNameRef(Name); } /// Retrieve the C declaration name that names this function, or empty /// string if it has none. StringRef getCDeclName() const; /// 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. std::optional getObjCRuntimeName(bool skipIsObjCResolution = false) 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; } /// Returns \c true if this value decl is inlinable with attributes /// \c \@usableFromInline, \c \@inlinalbe, and \c \@_alwaysEmitIntoClient bool isUsableFromInline() const; /// Returns \c true if this declaration is *not* intended to be used directly /// by application developers despite the visibility. bool shouldHideFromEditor() const; bool hasAccess() const { return TypeAndAccess.getInt().hasValue(); } /// Access control is done by Requests. friend class AccessLevelRequest; /// Returns the access level specified explicitly by the user, or provided by /// default according to language rules. /// /// Most of the time this is not the interesting value to check; access is /// limited by enclosing scopes per SE-0025. Use #getFormalAccessScope to /// check if access control is being used consistently, and to take features /// such as \c \@testable and \c \@usableFromInline into account. /// /// \sa getFormalAccessScope /// \sa hasOpenAccess AccessLevel getFormalAccess() 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().getDeclContext()) /// /// If \p treatUsableFromInlineAsPublic is true, declarations marked with the /// \c \@usableFromInline attribute are treated as public. This is normally /// false for name lookup and other source language concerns, but true when /// computing the linkage of generated functions. /// /// \sa getFormalAccess /// \sa isAccessibleFrom /// \sa hasOpenAccess AccessScope getFormalAccessScope(const DeclContext *useDC = nullptr, bool treatUsableFromInlineAsPublic = false) const; /// Copy the formal access level and @usableFromInline attribute from /// \p source. /// /// If \p sourceIsParentContext is true, an access level of \c private will /// be copied as \c fileprivate, to ensure that this declaration will be /// available everywhere \p source is. void copyFormalAccessFrom(const ValueDecl *source, bool sourceIsParentContext = false); /// 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. /// /// If \p forConformance is true, we ignore the visibility of the protocol /// when evaluating protocol extension members. This language rule allows a /// protocol extension of a private protocol to provide default /// implementations for the requirements of a public protocol, even when /// the default implementations are not visible to name lookup. bool isAccessibleFrom(const DeclContext *DC, bool forConformance = false, bool allowUsableFromInline = false) const; /// Returns whether this declaration should be treated as \c open from /// \p useDC. This is very similar to #getFormalAccess, but takes /// \c \@testable into account. /// /// This is mostly only useful when considering requirements on an override: /// if the base declaration is \c open, the override might have to be too. bool hasOpenAccess(const DeclContext *useDC) const; /// True if opted in to bypass a resilience check at the use site in the /// \p accessingModule that references decls defined in a module /// that allows non-resilient access within the same package. bool bypassResilienceInPackage(ModuleDecl *accessingModule) const; /// FIXME: This is deprecated. bool isRecursiveValidation() 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); /// isInstanceMember - Determine whether this value is an instance member /// of an enum or protocol. bool isInstanceMember() 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); /// Whether this declaration has a local discriminator. bool hasLocalDiscriminator() const; /// Return the "raw" local discriminator, without computing it. unsigned getRawLocalDiscriminator() const { return LocalDiscriminator; } /// Retrieve the declaration that this declaration overrides, if any. ValueDecl *getOverriddenDecl() const; /// Retrieve the declaration that this declaration overrides, including super /// deinit. ValueDecl *getOverriddenDeclOrSuperDeinit() const; /// Retrieve the declarations that this declaration overrides, if any. llvm::TinyPtrVector getOverriddenDecls() const; /// Set the declaration that this declaration overrides. void setOverriddenDecl(ValueDecl *overridden) { setOverriddenDecls(overridden); } /// Set the declarations that this declaration overrides. void setOverriddenDecls(ArrayRef overridden); /// Whether the overridden declarations have already been computed. bool overriddenDeclsComputed() 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; /// Note whether this declaration is known to be exposed to Objective-C. void setIsObjC(bool Value); /// Is this declaration semantically 'final', meaning that the type checker /// should treat it as final even if the ABI does not? bool isSemanticallyFinal() const; /// Is this declaration 'final'? bool isFinal() const; /// Is this declaration marked with 'dynamic'? bool isDynamic() const; /// Returns whether accesses to this declaration are asynchronous. /// If the declaration is neither `AbstractFunctionDecl` nor /// `AbstractStorageDecl`, returns `false`. bool isAsync() const; private: bool isObjCDynamic() const { return isObjC() && isDynamic(); } bool isNativeDynamic() const { return !isObjC() && isDynamic(); } bool isObjCDynamicInGenericClass() const; public: /// Should we use Objective-C method dispatch for this decl. bool shouldUseObjCDispatch() const { return isObjCDynamic(); } /// Should we use native dynamic function replacement dispatch for this decl. bool shouldUseNativeDynamicDispatch() const { return isNativeDynamic(); } /// Should we use Objective-C category based function replacement for this /// decl. /// This is all `@objc dynamic` methods except for such methods in native /// generic classes. We can't use a category for generic classes so we use /// native replacement instead (this behavior is only enabled with /// -enable-implicit-dynamic). bool shouldUseObjCMethodReplacement() const; /// Should we use native dynamic function replacement mechanism for this decl. /// This is all native dynamic methods except for `@objc dynamic` methods in /// generic classes (see above). bool shouldUseNativeMethodReplacement() const; /// Is this a native dynamic function replacement based replacement. /// This is all @_dynamicReplacement(for:) of native functions and @objc /// dynamic methods on generic classes (see above). bool isNativeMethodReplacement() const; /// Returns if this declaration has more visible formal access than 'other'. bool isMoreVisibleThan(ValueDecl *other) const; /// Set whether this type is 'dynamic' or not. void setIsDynamic(bool value); /// Whether the 'dynamic' bit has been computed already. bool isDynamicComputed() const { return LazySemanticInfo.isDynamicComputed; } /// Returns true if this decl can be found by id-style dynamic lookup. bool canBeAccessedByDynamicLookup() const; /// Returns true if this declaration has an implicitly unwrapped optional /// result. The precise meaning depends on the declaration kind: /// - for properties, the value is IUO /// - for subscripts, the element type is IUO /// - for functions, the result type is IUO /// - for constructors, the failability kind is IUO bool isImplicitlyUnwrappedOptional() const; /// Should only be set on imported and deserialized declarations; parsed /// declarations compute this lazily via a request. void setImplicitlyUnwrappedOptional(bool isIUO) { LazySemanticInfo.isIUOComputed = 1; LazySemanticInfo.isIUO = isIUO; } /// 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. /// /// \param DC The declaration context. /// /// \param isAccessOnSelf Whether this is a member access on the implicit /// 'self' declaration of the declaration context. AccessSemantics getAccessSemanticsFromContext(const DeclContext *DC, bool isAccessOnSelf) const; /// Determines if a reference to this declaration from a nested function /// should be treated like a capture of a local value. bool isLocalCapture() 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. SWIFT_DEBUG_DUMPER(dumpRef()); /// 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; 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; /// Returns true if the declaration's interface type is a function type with a /// curried self parameter. bool hasCurriedSelf() const; /// Returns true if the declaration has a parameter list associated with it. /// /// Note that not all declarations with function interface types have /// parameter lists, for example an enum element without associated values. bool hasParameterList() const; /// Returns the parameter list directly associated with this declaration, /// or `nullptr` if there is none. /// /// Note that some declarations with function interface types do not have /// parameter lists. For example, an enum element without associated values. ParameterList *getParameterList(); const ParameterList *getParameterList() const; /// Returns the number of curry levels in the declaration's interface type. unsigned getNumCurryLevels() const; /// Get the decl for this value's opaque result type, if it has one. OpaqueTypeDecl *getOpaqueResultTypeDecl() const; /// Gets the decl for this value's opaque result type if it has already been /// computed, or `nullopt` otherwise. This should only be used for dumping. std::optional getCachedOpaqueResultTypeDecl() const; /// Get the representative for this value's opaque result type, if it has one. /// Returns a `TypeRepr` instead of an `OpaqueReturnTypeRepr` because 'some' /// types might appear in one or more structural positions, e.g. (some P, /// some Q), or we might have a `NamedOpaqueReturnTypeRepr`. TypeRepr *getOpaqueResultTypeRepr() const; /// Get the representative for this value's result type, if it has one. TypeRepr *getResultTypeRepr() const; /// Retrieve the attribute associating this declaration with a /// result builder, if there is one. CustomAttr *getAttachedResultBuilder() const; /// Retrieve the @resultBuilder type attached to this declaration, /// if there is one. Type getResultBuilderType() const; /// If this value or its backing storage is annotated /// @_dynamicReplacement(for: ...), compute the original declaration /// that this declaration dynamically replaces. ValueDecl *getDynamicallyReplacedDecl() const; /// Performs a request to look up the decl that this decl has been renamed to /// if `attr` indicates that it has been renamed. ValueDecl *getRenamedDecl(const AvailableAttr *attr) const; /// Directly sets the renamed decl corresponding to `attr`. This should only /// be used when synthesizing an `AvailableAttr`, before calling /// `getRenamedDecl()`. void setRenamedDecl(const AvailableAttr *attr, ValueDecl *renameDecl) const; }; /// This is a common base class for declarations which declare a type. class TypeDecl : public ValueDecl { private: ArrayRef Inherited; protected: TypeDecl(DeclKind K, llvm::PointerUnion context, Identifier name, SourceLoc NameLoc, ArrayRef inherited) : ValueDecl(K, context, name, NameLoc), Inherited(inherited) {} friend class InheritedTypes; public: Identifier getName() const { return getBaseIdentifier(); } /// Returns the string for the base name, or "_" if this is unnamed. StringRef getNameStr() const { return hasName() ? getBaseIdentifier().str() : "_"; } /// The type of this declaration's values. For the type of the /// declaration itself, use getInterfaceType(), which returns a /// metatype. Type getDeclaredInterfaceType() const; /// Retrieve the set of protocols that this type inherits (i.e, /// explicitly conforms to). InheritedTypes getInherited() const { return InheritedTypes(this); } void setInherited(ArrayRef i) { Inherited = i; } struct CanBeInvertible { /// Indicates how "strongly" a TypeDecl will conform to an invertible /// protocol. Supports inequality comparisons and casts to bool. enum Result : unsigned { Never = 0, // Never conforms. Conditionally = 1, // Conditionally conforms. Always = 2, // Always conforms. }; }; 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); /// Compute an ordering between two type declarations that is ABI-stable. /// This version takes a pointer-to-a-pointer for use with /// llvm::array_pod_sort() and similar. template static int compare(T * const* type1, T * const* type2) { return compare(*type1, *type2); } }; /// A type declaration that 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, ArrayRef inherited, GenericParamList *GenericParams); // Resolve ambiguity due to multiple base classes. using TypeDecl::getASTContext; using DeclContext::operator new; using DeclContext::operator delete; using TypeDecl::getDeclaredInterfaceType; static bool classof(const DeclContext *C) { if (auto D = C->getAsDecl()) return classof(D); return false; } static bool classof(const Decl *D) { return D->getKind() >= DeclKind::First_GenericTypeDecl && D->getKind() <= DeclKind::Last_GenericTypeDecl; } }; /// OpaqueTypeDecl - This is a declaration of an opaque type. The opaque type /// is formally equivalent to its underlying type, but abstracts it away from /// clients of the opaque type, only exposing the type as something conforming /// to a given set of constraints. /// /// An `OpaqueTypeDecl` is formed implicitly when a declaration is written with /// an opaque result type, as in the following example: /// /// func foo() -> some SignedInteger { return 1 } /// /// The declared type uses a special kind of archetype type to represent /// abstracted types, e.g. `(some P, some Q)` becomes `((opaque archetype 0), /// (opaque archetype 1))`. class OpaqueTypeDecl final : public GenericTypeDecl, private llvm::TrailingObjects { friend TrailingObjects; friend class UniqueUnderlyingTypeSubstitutionsRequest; public: /// A set of substitutions that represents a possible underlying type iff /// associated set of availability conditions is met. class ConditionallyAvailableSubstitutions; private: /// The original declaration that "names" the opaque type. Although a specific /// opaque type cannot be explicitly named, opaque types can propagate /// arbitrarily through expressions, so we need to know *which* opaque type is /// propagated. /// /// The bit indicates whether there are any trailing /// OpaqueReturnTypeReprs. llvm::PointerIntPair NamingDeclAndHasOpaqueReturnTypeRepr; /// The generic signature of the opaque interface to the type. This is the /// outer generic signature with added generic parameters representing the /// abstracted underlying types. GenericSignature OpaqueInterfaceGenericSignature; /// If known, the underlying type and conformances of the opaque type, /// expressed as a SubstitutionMap for the opaque interface generic signature. /// This maps types in the interface generic signature to the outer generic /// signature of the original declaration. std::optional UniqueUnderlyingType; /// A set of substitutions which are used based on the availability /// checks performed at runtime. This set of only populated if there /// is no single unique underlying type for this opaque type declaration. /// /// It always contains one or more conditionally available substitutions /// followed by a universally available type used as a fallback. std::optional> ConditionallyAvailableTypes = std::nullopt; mutable Identifier OpaqueReturnTypeIdentifier; struct { unsigned UniqueUnderlyingTypeComputed : 1; } LazySemanticInfo = { }; OpaqueTypeDecl(ValueDecl *NamingDecl, GenericParamList *GenericParams, DeclContext *DC, GenericSignature OpaqueInterfaceGenericSignature, ArrayRef OpaqueReturnTypeReprs); unsigned getNumOpaqueReturnTypeReprs() const { return NamingDeclAndHasOpaqueReturnTypeRepr.getInt() ? getOpaqueGenericParams().size() : 0; } size_t numTrailingObjects(OverloadToken) const { return getNumOpaqueReturnTypeReprs(); } public: static OpaqueTypeDecl *get( ValueDecl *NamingDecl, GenericParamList *GenericParams, DeclContext *DC, GenericSignature OpaqueInterfaceGenericSignature, ArrayRef OpaqueReturnTypeReprs); ValueDecl *getNamingDecl() const { return NamingDeclAndHasOpaqueReturnTypeRepr.getPointer(); } void setNamingDecl(ValueDecl *D) { assert(!getNamingDecl() && "already have naming decl"); NamingDeclAndHasOpaqueReturnTypeRepr.setPointer(D); } /// Is this opaque type the opaque return type of the given function? /// /// This is more complex than just checking `getNamingDecl` because the /// function could also be the getter of a storage declaration. bool isOpaqueReturnTypeOf(const Decl *owner) const; /// Get the ordinal of the anonymous opaque parameter of this decl with type /// repr `repr`, as introduce implicitly by an occurrence of "some" in return /// position e.g. `func f() -> some P`. Returns -1 if `repr` is not found. std::optional getAnonymousOpaqueParamOrdinal(TypeRepr *repr) const; GenericSignature getOpaqueInterfaceGenericSignature() const { return OpaqueInterfaceGenericSignature; } /// Retrieve the generic parameters that represent the opaque types described by this opaque /// type declaration. ArrayRef getOpaqueGenericParams() const { return OpaqueInterfaceGenericSignature.getInnermostGenericParams(); } /// Whether the generic parameters of this opaque type declaration were /// explicit, i.e., for named opaque result types. bool hasExplicitGenericParams() const; /// When the generic parameters were explicit, returns the generic parameter /// corresponding to the given ordinal. /// /// Otherwise, returns \c nullptr. GenericTypeParamDecl *getExplicitGenericParam(unsigned ordinal) const; /// Retrieve the buffer containing the opaque return type /// representations that correspond to the opaque generic parameters. ArrayRef getOpaqueReturnTypeReprs() const { return { getTrailingObjects(), getNumOpaqueReturnTypeReprs() }; } /// Should the underlying type be visible to clients outside of the module? bool exportUnderlyingType() const; /// The substitutions that map the generic parameters of the opaque type to /// the unique underlying types, when that information is known. std::optional getUniqueUnderlyingTypeSubstitutions() const; void setUniqueUnderlyingTypeSubstitutions(SubstitutionMap subs) { assert(!UniqueUnderlyingType.has_value() && "resetting underlying type?!"); UniqueUnderlyingType = subs; } bool hasConditionallyAvailableSubstitutions() const { return ConditionallyAvailableTypes.has_value(); } ArrayRef getConditionallyAvailableSubstitutions() const { assert(ConditionallyAvailableTypes); return ConditionallyAvailableTypes.value(); } void setConditionallyAvailableSubstitutions( ArrayRef substitutions); // Opaque type decls are currently always implicit SourceRange getSourceRange() const { return SourceRange(); } // Get the identifier string that can be used to cross-reference unnamed // opaque return types across files. Identifier getOpaqueReturnTypeIdentifier() const; static bool classof(const Decl *D) { return D->getKind() == DeclKind::OpaqueType; } static bool classof(const GenericTypeDecl *D) { return D->getKind() == DeclKind::OpaqueType; } static bool classof(const DeclContext *C) { if (auto D = C->getAsDecl()) return classof(D); return false; } using AvailabilityCondition = std::pair; class ConditionallyAvailableSubstitutions final : private llvm::TrailingObjects< ConditionallyAvailableSubstitutions, AvailabilityCondition> { friend TrailingObjects; unsigned NumAvailabilityConditions; SubstitutionMap Substitutions; /// A type with limited availability described by the provided set /// of availability conditions (with `and` relationship). ConditionallyAvailableSubstitutions( ArrayRef availabilityContext, SubstitutionMap substitutions) : NumAvailabilityConditions(availabilityContext.size()), Substitutions(substitutions) { assert(!availabilityContext.empty()); std::uninitialized_copy(availabilityContext.begin(), availabilityContext.end(), getTrailingObjects()); } public: ArrayRef getAvailability() const { return {getTrailingObjects(), NumAvailabilityConditions}; } SubstitutionMap getSubstitutions() const { return Substitutions; } static ConditionallyAvailableSubstitutions * get(ASTContext &ctx, ArrayRef availabilityContext, SubstitutionMap substitutions); }; }; /// TypeAliasDecl - This is a declaration of a typealias, for example: /// /// typealias Foo = Int /// /// TypeAliasDecl's always have 'MetatypeType' type. /// class TypeAliasDecl : public GenericTypeDecl { friend class UnderlyingTypeRequest; /// The location of the 'typealias' keyword SourceLoc TypeAliasLoc; /// The location of the equal '=' token SourceLoc EqualLoc; /// The end of the type, valid even when the type cannot be parsed SourceLoc TypeEndLoc; /// 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; } void setTypeEndLoc(SourceLoc e) { TypeEndLoc = e; } /// Retrieve the TypeRepr corresponding to the parsed underlying type. TypeRepr *getUnderlyingTypeRepr() const { return UnderlyingTy.getTypeRepr(); } void setUnderlyingTypeRepr(TypeRepr *repr) { UnderlyingTy = repr; } /// Retrieve the interface type of the underlying type. Type getUnderlyingType() const; void setUnderlyingType(Type type); /// Returns the interface type of the underlying type if computed, null /// otherwise. Should only be used for dumping. Type getCachedUnderlyingType() const { return UnderlyingTy.getType(); } /// For generic typealiases, return the unbound generic type. /// /// Since UnboundGenericType is on its way out, so is this method. Try to /// avoid introducing new callers if possible. Instead of passing around /// an UnboundGenericType, considering passing around the Decl itself /// instead. UnboundGenericType *getUnboundGenericType() const; /// Retrieve a sugared interface type containing the structure of the interface /// type before any semantic validation has occurred. Type getStructuralType() const; /// Whether the typealias forwards perfectly to its underlying type. /// /// If true, this typealias was created by ClangImporter to preserve source /// compatibility with a previous language version's name for a type. Many /// checks in Sema look through compatibility aliases even when they would /// operate on other typealiases. /// /// \warning This has absolutely nothing to do with the Objective-C /// \c compatibility_alias keyword. bool isCompatibilityAlias() const { return Bits.TypeAliasDecl.IsCompatibilityAlias; } /// Sets whether the typealias forwards perfectly to its underlying type. /// /// Marks this typealias as having been created by ClangImporter to preserve /// source compatibility with a previous language version's name for a type. /// Many checks in Sema look through compatibility aliases even when they /// would operate on other typealiases. /// /// \warning This has absolutely nothing to do with the Objective-C /// \c compatibility_alias keyword. void markAsCompatibilityAlias(bool newValue = true) { Bits.TypeAliasDecl.IsCompatibilityAlias = newValue; } /// Is this a special debugger variable? bool isDebuggerAlias() const { return Bits.TypeAliasDecl.IsDebuggerAlias; } void markAsDebuggerAlias(bool isDebuggerAlias) { Bits.TypeAliasDecl.IsDebuggerAlias = isDebuggerAlias; } 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) { if (auto D = C->getAsDecl()) return classof(D); return false; } }; /// 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 final : public TypeDecl, private llvm::TrailingObjects { friend TrailingObjects; size_t numTrailingObjects(OverloadToken) const { return isOpaqueType() ? 1 : 0; } size_t numTrailingObjects(OverloadToken) const { if (isParameterPack() || isValue()) { return 1; } return 0; } /// 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. /// \param specifierLoc The location of the 'each' or 'let' keyword for pack /// or value parameters. /// \param depth The generic signature depth. /// \param index The index of the parameter in the generic signature. /// \param paramKind The kind of generic type parameter this is. /// \param isOpaqueType Whether the generic parameter is written as an opaque /// parameter e.g 'some Collection'. /// \param opaqueTypeRepr The TypeRepr of an opaque generic parameter. /// GenericTypeParamDecl(DeclContext *dc, Identifier name, SourceLoc nameLoc, SourceLoc specifierLoc, unsigned depth, unsigned index, GenericTypeParamKind paramKind, bool isOpaqueType, TypeRepr *opaqueTypeRepr); /// 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. /// \param specifierLoc The location of the 'each' or 'let' keyword for pack /// or value parameters. /// \param depth The generic signature depth. /// \param index The index of the parameter in the generic signature. /// \param paramKind The kind of generic type parameter this is. /// \param isOpaqueType Whether the generic parameter is written as an opaque /// parameter e.g 'some Collection'. /// \param opaqueTypeRepr The TypeRepr of an opaque generic parameter. /// static GenericTypeParamDecl *create(DeclContext *dc, Identifier name, SourceLoc nameLoc, SourceLoc specifierLoc, unsigned depth, unsigned index, GenericTypeParamKind paramKind, bool isOpaqueType, TypeRepr *opaqueTypeRepr); public: static const unsigned InvalidDepth = 0xFFFF; /// Construct a new generic type parameter. This should only be used by the /// ClangImporter, use \c GenericTypeParamDecl::create[...] instead. GenericTypeParamDecl(DeclContext *dc, Identifier name, SourceLoc nameLoc, SourceLoc specifierLoc, unsigned depth, unsigned index, GenericTypeParamKind paramKind) : GenericTypeParamDecl(dc, name, nameLoc, specifierLoc, depth, index, paramKind, false, nullptr) { } /// Construct a deserialized 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 depth The generic signature depth. /// \param index The index of the parameter in the generic signature. /// \param paramKind The kind of generic type parameter this is. /// \param isOpaqueType Whether the generic parameter is written as an opaque /// parameter e.g 'some Collection'. /// static GenericTypeParamDecl * createDeserialized(DeclContext *dc, Identifier name, unsigned depth, unsigned index, GenericTypeParamKind paramKind, bool isOpaqueType); /// Construct a new parsed 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. /// \param specifierLoc The location of the 'each' or 'let' keyword for pack /// or value parameters. /// \param index The index of the parameter in the generic signature. /// \param paramKind The kind of generic type parameter this is. /// static GenericTypeParamDecl *createParsed(DeclContext *dc, Identifier name, SourceLoc nameLoc, SourceLoc specifierLoc, unsigned index, GenericTypeParamKind paramKind); /// Construct a new implicit 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 depth The generic signature depth. /// \param index The index of the parameter in the generic signature. /// \param paramKind The kind of generic type parameter this is. /// \param opaqueTypeRepr The TypeRepr of an opaque generic parameter. /// \param nameLoc The location of the name. /// \param specifierLoc The location of the 'each' or 'let' keyword for pack /// or value parameters. /// static GenericTypeParamDecl * createImplicit(DeclContext *dc, Identifier name, unsigned depth, unsigned index, GenericTypeParamKind paramKind, TypeRepr *opaqueTypeRepr = nullptr, SourceLoc nameLoc = {}, SourceLoc specifierLoc = {}); /// 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 kind of generic type parameter this is. GenericTypeParamKind getParamKind() const { return (GenericTypeParamKind) Bits.GenericTypeParamDecl.ParamKind; } /// Returns \c true if this generic type parameter is declared as a type /// parameter pack. /// /// \code /// func foo(_ : for each T) { } /// struct Foo { } /// \endcode bool isParameterPack() const { return getParamKind() == GenericTypeParamKind::Pack; } /// Returns \c true if this generic type parameter is declared as a value /// type parameter. /// /// \code /// struct InlineArray /// \endcode bool isValue() const { return getParamKind() == GenericTypeParamKind::Value; } /// Returns the underlying value type associated with this generic value /// parameter. E.g. if this is 'let N: Int' returns 'Int'. Type getValueType() const; /// Determine whether this generic parameter represents an opaque type. /// /// \code /// // "some P" is represented by a generic type parameter. /// func f() -> [some P] { ... } /// \endcode bool isOpaqueType() const { return Bits.GenericTypeParamDecl.IsOpaqueType; } /// Retrieve the opaque return type representation described by this /// generic parameter, or NULL if any of the following are true: /// - the generic parameter does not describe an opaque type /// - the opaque type was introduced via the "named opaque parameters" /// extension, meaning that it was specified explicitly /// - the enclosing declaration was deserialized, in which case it lost /// the source location information and has no type representation. TypeRepr *getOpaqueTypeRepr() const { if (!isOpaqueType()) return nullptr; return *getTrailingObjects(); } /// 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; } /// Retrieve either the 'each' keyword or the 'let' keyword location for this /// generic parameter depending on if it's a parameter pack or a value. SourceLoc getSpecifierLoc() const { if (!isParameterPack() && !isValue()) return SourceLoc(); return *getTrailingObjects(); } /// Retrieve the 'each' keyword location for a type parameter pack \c each T. SourceLoc getEachLoc() const { if (!isParameterPack()) return SourceLoc(); return *getTrailingObjects(); } /// Retrieve the 'let' keyword location for a value parameter \c let N. SourceLoc getLetLoc() const { if (!isValue()) return SourceLoc(); return *getTrailingObjects(); } 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 class AssociatedTypeDecl : public TypeDecl { /// The location of the initial keyword. SourceLoc KeywordLoc; /// The default definition. TypeLoc DefaultDefinition; /// The where clause attached to the associated type. TrailingWhereClause *TrailingWhere; friend class DefaultDefinitionTypeRequest; AssociatedTypeDecl(DeclContext *dc, SourceLoc keywordLoc, Identifier name, SourceLoc nameLoc, TypeRepr *defaultDefinition, TrailingWhereClause *trailingWhere); public: static AssociatedTypeDecl *createParsed(ASTContext &ctx, DeclContext *dc, SourceLoc keywordLoc, Identifier name, SourceLoc nameLoc, TypeRepr *defaultDefinition, TrailingWhereClause *trailingWhere); static AssociatedTypeDecl *createDeserialized( ASTContext &ctx, DeclContext *dc, SourceLoc keywordLoc, Identifier name, SourceLoc nameLoc, TrailingWhereClause *trailingWhere, LazyMemberLoader *lazyLoader, uint64_t defaultDefinitionTypeData); /// Get the protocol in which this associated type is declared. ProtocolDecl *getProtocol() const { return cast(getDeclContext()); } /// Check if we have a default definition type. bool hasDefaultDefinitionType() const { // If we have a TypeRepr, return true immediately without kicking off // a request. return DefaultDefinition.getTypeRepr() || getDefaultDefinitionType(); } /// Retrieve the default definition type. Type getDefaultDefinitionType() const; /// Retrieve the default definition type if computed, `None` otherwise. /// /// \Note Should only be used for dumping. std::optional getCachedDefaultDefinitionType() const; private: /// Set the computed default definition type. void setDefaultDefinitionType(Type ty); public: /// Retrieve the default definition as written in the source. TypeRepr *getDefaultDefinitionTypeRepr() const { return DefaultDefinition.getTypeRepr(); } /// 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; } /// 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 { return cast_or_null( TypeDecl::getOverriddenDecl()); } /// Retrieve the set of associated types overridden by this associated /// type. llvm::TinyPtrVector getOverriddenDecls() const; SourceLoc getStartLoc() const { return KeywordLoc; } SourceRange getSourceRange() const; static bool classof(const Decl *D) { return D->getKind() == DeclKind::AssociatedType; } }; class MemberLookupTable; class ObjCMethodLookupTable; class ConformanceLookupTable; // 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."); } // Kinds of buffer pointer types. enum BufferPointerTypeKind : unsigned { BPTK_UnsafeMutableRawBufferPointer, BPTK_UnsafeRawBufferPointer, BPTK_UnsafeMutableBufferPointer, BPTK_UnsafeBufferPointer, }; enum KeyPathTypeKind : unsigned char { KPTK_AnyKeyPath, KPTK_PartialKeyPath, KPTK_KeyPath, KPTK_WritableKeyPath, KPTK_ReferenceWritableKeyPath }; /// NominalTypeDecl - a declaration of a nominal type, like a struct. class NominalTypeDecl : public GenericTypeDecl, public IterableDeclContext { SourceRange Braces; /// The first extension of this type. ExtensionDecl *FirstExtension = nullptr; /// The last extension of this type, used solely for efficient /// insertion of new extensions. ExtensionDecl *LastExtension = nullptr; /// 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(); /// A lookup table containing all of the members of this type and /// its extensions, together with a bit indicating if the table /// has been prepared. /// /// The table itself is lazily constructed and updated when /// lookupDirect() is called. llvm::PointerIntPair LookupTable; /// Get the lookup table, lazily constructing an empty table if /// necessary. MemberLookupTable *getLookupTable(); /// Prepare the lookup table to make it ready for lookups. /// Does nothing when called more than once. void prepareLookupTable(); /// Note that we have added a member into the iterable declaration context, /// so that it can also be added to the lookup table (if needed). void addedMember(Decl *member); /// Note that we have added an extension into the nominal type, /// so that its members can eventually be added to the lookup table. void addedExtension(ExtensionDecl *ext); /// 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; ObjCMethodLookupTable *ObjCMethodLookup = nullptr; /// Create the Objective-C method lookup table, or return \c false if this /// kind of type cannot have Objective-C methods. bool createObjCMethodLookup(); friend class ASTContext; friend class MemberLookupTable; friend class ConformanceLookupTable; friend class ExtensionDecl; friend class DeclContext; friend class IterableDeclContext; friend class DirectLookupRequest; friend class LookupAllConformancesInContextRequest; friend ArrayRef ValueDecl::getSatisfiedProtocolRequirements(bool Sorted) const; protected: Type DeclaredTy; Type DeclaredInterfaceTy; NominalTypeDecl(DeclKind K, DeclContext *DC, Identifier name, SourceLoc NameLoc, ArrayRef inherited, GenericParamList *GenericParams) : GenericTypeDecl(K, DC, name, NameLoc, inherited, GenericParams), IterableDeclContext(IterableDeclContextKind::NominalTypeDecl) { Bits.NominalTypeDecl.AddedImplicitInitializers = false; ExtensionGeneration = 0; Bits.NominalTypeDecl.HasLazyConformances = false; Bits.NominalTypeDecl.IsComputingSemanticMembers = false; } friend class ProtocolType; public: using GenericTypeDecl::getASTContext; SourceRange getBraces() const { return Braces; } void setBraces(SourceRange braces) { Braces = braces; } /// Returns whether this declaration is resilient at the definition site, i.e. /// must be accessed resiliently even when its defining module is built /// non-resiliently. /// /// This is used for diagnostics, because we do not want a behavior /// change between builds with resilience enabled and disabled. bool isFormallyResilient() const; /// Returns whether this decl is resilient at the definition site /// \c isFormallyResilient or whether its defining module /// is built resiliently. bool isResilient() const; /// True if the decl is resilient AND also its defining module does /// _not_ allow non-resilient access; the module can allow such access /// if package optimization is enabled so its client modules within the /// same package can have a direct access to this decl even if it's /// resilient. bool isStrictlyResilient() const; /// Returns whether this decl is accessed non/resiliently at the _use_ site /// in \p accessingModule, depending on \p expansion. /// /// If \p expansion is maximal, the decl could be treated as non-resilient /// even though the decl is resilient by definition or its defining module is built /// resiliently. For example, if accessing a decl defined in the same module or /// another module in the same package as the \p accessingModule, the /// decl could be treated as non-resilient (with package optimization enabled in /// case of different modules); this enables bypassing resilience checks at the /// use site so the decl can be accessed directly. /// /// \p accessingModule The module from which this decl is accessed. Might /// be the same module as its defining module. /// \p expansion Used to determine whether non-resilience / direct access /// to this decl is possible. bool isResilient(ModuleDecl *accessingModule, 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; } /// getDeclaredType - Retrieve the type declared by this entity, without /// any generic parameters bound if this is a generic type. /// /// Since UnboundGenericType is on its way out, so is this method. Try to /// avoid introducing new callers if possible. Instead of passing around /// an UnboundGenericType, considering passing around the Decl itself /// instead. Type getDeclaredType() const; /// getDeclaredInterfaceType - Retrieve the type declared by this entity, with /// generic parameters bound if this is a generic type. Type getDeclaredInterfaceType() const; /// Add a new extension to this nominal type. void addExtension(ExtensionDecl *extension); /// Add a member to this decl's lookup table. /// /// Calls "prepareLookupTable" as a side effect. void addMemberToLookupTable(Decl *member); /// Retrieve the set of extensions of this type. ExtensionRange getExtensions(); /// Retrieve the extension most recently added to this type. Helpful to /// determine if an extension has been added. ExtensionDecl *getLastExtension() const { return LastExtension; } /// Special-behaviour flags passed to lookupDirect() enum class LookupDirectFlags { /// Whether to include @_implements members. /// Used by conformance-checking to find special @_implements members. IncludeAttrImplements = 1 << 0, /// Whether to exclude members of macro expansions. ExcludeMacroExpansions = 1 << 1, /// If @abi attributes are present, return the decls representing the ABI, /// not the API. ABIProviding = 1 << 2, }; /// 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. TinyPtrVector lookupDirect(DeclName name, SourceLoc loc = SourceLoc(), OptionSet flags = OptionSet()); /// Find the distributed actor system instance of this distributed actor. VarDecl *getDistributedActorSystemProperty() const; /// Find, or potentially synthesize, the implicit 'id' property of this actor. VarDecl *getDistributedActorIDProperty() const; /// Find the 'RemoteCallTarget.init(_:)' initializer function. ConstructorDecl *getDistributedRemoteCallTargetInitFunction() const; /// Find the 'RemoteCallArgument(label:name:value:)' initializer function. ConstructorDecl *getDistributedRemoteCallArgumentInitFunction() const; /// Get the move-only `enqueue(ExecutorJob)` protocol requirement function on the `Executor` protocol. AbstractFunctionDecl *getExecutorOwnedEnqueueFunction() const; /// This method should be deprecated and removed /// Get the move-only `enqueue(Job)` protocol requirement function on the `Executor` protocol. AbstractFunctionDecl *getExecutorLegacyOwnedEnqueueFunction() const; /// Get the move-only `enqueue(UnownedJob)` protocol requirement function on the `Executor` protocol. AbstractFunctionDecl *getExecutorLegacyUnownedEnqueueFunction() const; /// 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 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( ProtocolDecl *protocol, SmallVectorImpl &conformances) const; /// Retrieve all of the protocols that this nominal type conforms to. /// /// \param sorted Whether to sort the protocols in canonical order. SmallVector getAllProtocols(bool sorted = false) 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(NormalProtocolConformance *conformance, bool synthesized = false); void setConformanceLoader(LazyMemberLoader *resolver, uint64_t contextData); /// Look in this type 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). TinyPtrVector lookupDirect(ObjCSelector selector, bool isInstance); /// Record the presence of an @objc method with the given selector. No-op if /// the type is of a kind which cannot contain @objc methods. void recordObjCMethod(AbstractFunctionDecl *method, ObjCSelector selector); /// Is this the decl for Optional? bool isOptionalDecl() const; /// Is this a key path type? std::optional getKeyPathTypeKind() const; /// Retrieve information about this type as a property wrapper. PropertyWrapperTypeInfo getPropertyWrapperTypeInfo() const; /// Return a collection of the stored member variables of this type. ArrayRef getStoredProperties() const; /// Return a collection of all properties with init accessors in /// this type. ArrayRef getInitAccessorProperties() const; /// Return a collection of all properties that will be part of the memberwise /// initializer. ArrayRef getMemberwiseInitProperties() const; /// Establish a mapping between properties that could be iniitalized /// via other properties by means of init accessors. This mapping is /// one-to-many because we allow intersecting `initializes(...)`. void collectPropertiesInitializableByInitAccessors( std::multimap &result) const; /// Return a collection of the stored member variables of this type, along /// with placeholders for unimportable stored properties. ArrayRef getStoredPropertiesAndMissingMemberPlaceholders() const; /// Whether this nominal type qualifies as an actor, meaning that it is /// either an actor type or a protocol whose `Self` type conforms to the /// `Actor` protocol. bool isActor() const; /// Whether this nominal type qualifies as a distributed actor, meaning that /// it is either a distributed actor or a DistributedActor constrained protocol. bool isDistributedActor() const; /// Whether this nominal type qualifies as any actor (plain or distributed). bool isAnyActor() const; /// Whether this nominal type is the `MainActor` global actor. bool isMainActor() const; /// Return the range of semantics attributes attached to this NominalTypeDecl. auto getSemanticsAttrs() const -> decltype(getAttrs().getSemanticsAttrs()) { return getAttrs().getSemanticsAttrs(); } bool hasSemanticsAttr(StringRef attrValue) const { return getAttrs().hasSemanticsAttr(attrValue); } /// Returns true if we should emit assembly vision remarks on all methods of /// this nominal type. bool shouldEmitAssemblyVisionRemarksOnMethods() const { return getAttrs().hasAttribute(); } /// Whether this declaration has a synthesized memberwise initializer. bool hasMemberwiseInitializer() const; /// Retrieves the synthesized memberwise initializer for this declaration, /// or \c nullptr if it does not have one. ConstructorDecl *getMemberwiseInitializer() const; /// Retrieves the effective memberwise initializer for this declaration, or /// \c nullptr if it does not have one. /// /// An effective memberwise initializer is either a synthesized memberwise /// initializer or a user-defined initializer with the same type. /// /// The access level of the memberwise initializer is set to the minimum of: /// - Public, by default. This enables public nominal types to have public /// memberwise initializers. /// - The `public` default is important for synthesized member types, e.g. /// `TangentVector` structs synthesized during `Differentiable` derived /// conformances. Manually extending these types to define a public /// memberwise initializer causes a redeclaration error. /// - The minimum access level of memberwise-initialized properties in the /// nominal type declaration. /// /// Effective memberwise initializers are used only by derived conformances /// for `Self`-returning protocol requirements like `AdditiveArithmetic.+`. /// Such derived conformances require memberwise initialization. ConstructorDecl *getEffectiveMemberwiseInitializer(); /// Whether this declaration has a synthesized zero parameter default /// initializer. bool hasDefaultInitializer() const; bool isTypeErasedGenericClass() const; /// Retrieves the synthesized zero parameter default initializer for this /// declaration, or \c nullptr if it doesn't have one. ConstructorDecl *getDefaultInitializer() const; /// Force the synthesis of all members named \c member requiring semantic /// analysis and install them in the member list of this nominal type. /// /// \Note The use of this method in the compiler signals an architectural /// problem with the caller. Use \c TypeChecker::lookup* instead of /// introducing new usages. /// /// FIXME: This method presents a problem with respect to the consistency /// and idempotency of lookups in the compiler. If we instead had a model /// where lookup requests would explicitly return semantic members or parsed /// members this function could disappear. void synthesizeSemanticMembersIfNeeded(DeclName member); /// Retrieves the static 'shared' property of a global actor type, which /// is used to extract the actor instance. /// /// \returns the static 'shared' property for a global actor, or \c nullptr /// for types that are not global actors. VarDecl *getGlobalActorInstance() const; /// Whether this type is a global actor, which can be used as an /// attribute to decorate declarations for inclusion in the actor-isolated /// state denoted by this type. bool isGlobalActor() const { return getGlobalActorInstance() != nullptr; } /// Return the `DestructorDecl` for a struct or enum's `deinit` declaration. /// Returns null if the type is a class, or does not have a declared `deinit`. DestructorDecl *getValueTypeDestructor(); /// Does a conformance for a given invertible protocol exist for this /// type declaration. CanBeInvertible::Result canConformTo(InvertibleProtocolKind kind) const; /// "Does a conformance for Copyable exist for this type declaration?" /// /// This doesn't mean that all instance of this type are Copyable, because /// if a conditional conformance to Copyable exists, this method will return /// true. /// /// If you need a more precise answer, ask this Decl's corresponding /// Type if it `isCopyable` instead of using this. CanBeInvertible::Result canBeCopyable() const; /// "Does a conformance for Escapable exist for this type declaration?" /// /// This doesn't mean that all instance of this type are Escapable, because /// if a conditional conformance to Escapable exists, this method will return /// true. /// /// If you need a more precise answer, ask this Decl's corresponding /// Type if it `isEscapable` instead of using this. CanBeInvertible::Result canBeEscapable() const; bool suppressesConformance(KnownProtocolKind kp) const; // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() >= DeclKind::First_NominalTypeDecl && D->getKind() <= DeclKind::Last_NominalTypeDecl; } static bool classof(const GenericTypeDecl *D) { return D->getKind() >= DeclKind::First_NominalTypeDecl && D->getKind() <= DeclKind::Last_NominalTypeDecl; } static bool classof(const DeclContext *C) { if (auto D = C->getAsDecl()) return classof(D); return false; } 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; } }; /// 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; enum SemanticInfoFlags : uint8_t { // Is the raw type valid? HasComputedRawType = 1 << 0, // Is the complete set of (auto-incremented) raw values available? HasFixedRawValues = 1 << 1, // Is the complete set of raw values type checked? HasFixedRawValuesAndTypes = 1 << 2, }; OptionSet SemanticFlags; friend class EnumRawValuesRequest; friend class EnumRawTypeRequest; public: EnumDecl(SourceLoc EnumLoc, Identifier Name, SourceLoc NameLoc, ArrayRef Inherited, GenericParamList *GenericParams, DeclContext *DC); SourceLoc getStartLoc() const { return EnumLoc; } SourceRange getSourceRange() const { return SourceRange(EnumLoc, getBraces().End); } public: /// A range for iterating the elements of an enum. using ElementRange = DowncastFilterRange; /// A range for iterating the elements of an enum that are available during /// lowering. using ElementRangeForLowering = OptionalTransformRange< ElementRange, AvailableDuringLoweringDeclFilter>; /// 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()); } /// Returns a range that iterates over all the elements of an enum for which /// \c isAvailableDuringLowering() is true. ElementRangeForLowering getAllElementsForLowering() const { return ElementRangeForLowering( getAllElements(), AvailableDuringLoweringDeclFilter()); } /// 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); } /// Whether this enum has a raw value type that recursively references itself. bool hasCircularRawValue() const; /// Record that this enum has had all of its raw values computed. void setHasFixedRawValues(); // 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) { if (auto D = C->getAsDecl()) return classof(D); return false; } 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)getRawType(); } /// Retrieve the declared raw type of the enum from its inheritance clause, /// or null if it has none. Type getRawType() const; /// Set the raw type of the enum from its inheritance clause. void setRawType(Type rawType); /// 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 any of the enum cases have availability annotations. /// /// Note that this is false for enums with absolutely no cases. bool hasPotentiallyUnavailableCaseValue() const; /// True if \c isAvailableDuringLowering() is false for any cases. /// /// Note that this is false for enums with absolutely no cases. bool hasCasesUnavailableDuringLowering() 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(); } /// True if the enum can be exhaustively switched within \p useDC. /// /// Note that this property is \e not necessarily true for all children of /// \p useDC. In particular, an inlinable function does not get to switch /// exhaustively over a non-exhaustive enum declared in the same module. /// /// This is the predicate used when deciding if a switch statement needs a /// default case. It should not be used for optimization or code generation. /// /// \sa isEffectivelyExhaustive bool isFormallyExhaustive(const DeclContext *useDC) const; /// True if \s isFormallyExhaustive is true or the use site's module belongs /// to the same package as this enum's defining module. If in same package /// even though `isFormallyExhaustive` is false, we can skip requiring /// `@unknown default` at the use site switch stmts because package modules /// are expected to be built together whether they are resiliently built or /// not. Used for diagnostics during typechecks only; if /// `isFormallyExhaustive` is false, it should be reflected in SILgen. bool treatAsExhaustiveForDiags(const DeclContext *useDC) const; /// True if the enum can be exhaustively switched within a function defined /// within \p M, with \p expansion specifying whether the function is /// inlinable. /// /// This is the predicate used when making optimization and code generation /// decisions. It should not be used at the AST or semantic level. /// /// \sa isFormallyExhaustive bool isEffectivelyExhaustive(ModuleDecl *M, ResilienceExpansion expansion) const; }; /// StructDecl - This is the declaration of a struct, for example: /// /// struct Complex { var R : Double, I : Double } /// /// The type of the decl itself is a MetatypeType; use getDeclaredType() /// to get the declared type ("Complex" in the above example). class StructDecl final : public NominalTypeDecl { SourceLoc StructLoc; // We import C++ class templates as generic structs. Then when in Swift code // we want to substitute generic parameters with actual arguments, we // convert the arguments to C++ equivalents and ask Clang to instantiate the // C++ template. Then we import the C++ class template instantiation // as a non-generic structs with a name prefixed with `__CxxTemplateInst`. // // To reiterate: // 1) We need to have a C++ class template declaration in the Clang AST. This // declaration is simply imported from a Clang module. // 2) We need a Swift generic struct in the Swift AST. This will provide // template arguments to Clang. // 3) We produce a C++ class template instantiation in the Clang AST // using 1) and 2). This declaration does not exist in the Clang module // AST initially in the general case, it's added there on instantiation. // 4) We import the instantiation as a Swift struct, with the name prefixed // with `__CxxTemplateInst`. // // This causes a problem for serialization/deserialization of the Swift // module. Imagine the Swift struct from 4) is used in the function return // type. We cannot just serialize the non generic Swift struct, because on // deserialization we would need to find its backing Clang declaration // (the C++ class template instantiation), and it won't be found in the // general case. Only the C++ class template from step 1) is in the Clang // AST. // // What we need is to serialize enough information to be // able to instantiate C++ class template on deserialization. It turns out // that all that information is conveniently covered by the BoundGenericType, // which we store in this field. The field is set during the typechecking at // the time when we instantiate the C++ class template. // // Alternative, and likely better solution long term, is to serialize the // C++ class template instantiation into a synthetic Clang module, and load // this Clang module on deserialization. Type TemplateInstantiationType = Type(); public: StructDecl(SourceLoc StructLoc, Identifier Name, SourceLoc NameLoc, ArrayRef 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) { if (auto D = C->getAsDecl()) return classof(D); return false; } 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; } /// Does this struct represent a non-trivial (for the purpose of calls, as /// defined by Itanium ABI) C++ record. A C++ record is considered non-trivial /// for the purpose of calls if either its constructor, copy-constructor, or /// destructor is non-trivial. As such, a C++ record with a non-trivial /// copy-assignment operator but other trivial members is considered to be /// trivial. bool isCxxNonTrivial() const { return Bits.StructDecl.IsCxxNonTrivial; } void setIsCxxNonTrivial(bool v) { Bits.StructDecl.IsCxxNonTrivial = v; } bool isNonTrivialPtrAuth() const { return Bits.StructDecl.IsNonTrivialPtrAuth; } void setHasNonTrivialPtrAuth(bool v) { Bits.StructDecl.IsNonTrivialPtrAuth = v; } Type getTemplateInstantiationType() const { return TemplateInstantiationType; } void setTemplateInstantiationType(Type t) { TemplateInstantiationType = t; } }; /// This is the base type for AncestryOptions. Each flag describes possible /// interesting kinds of superclasses that a class may have. enum class AncestryFlags : uint8_t { /// The class or one of its superclasses is @objc. ObjC = (1<<0), /// The class or one of its superclasses is @objcMembers. ObjCMembers = (1<<1), /// The class or one of its superclasses is generic. Generic = (1<<2), /// The class or one of its superclasses is resilient. Resilient = (1<<3), /// The class or one of its superclasses has resilient metadata and is in a /// different resilience domain. ResilientOther = (1<<4), /// The class or one of its superclasses is imported from Clang. ClangImported = (1<<5), /// The class or one of its superclasses requires stored property initializers. RequiresStoredPropertyInits = (1<<6), /// The class uses the ObjC object model (reference counting, /// isa encoding, etc.). ObjCObjectModel = (1<<7), }; /// Return type of ClassDecl::checkAncestry(). Describes a set of interesting /// kinds of superclasses that a class may have. using AncestryOptions = OptionSet; /// 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 { SourceLoc ClassLoc; struct { /// The superclass decl and a bit to indicate whether the /// superclass was computed yet or not. llvm::PointerIntPair SuperclassDecl; /// The superclass type and a bit to indicate whether the /// superclass was computed yet or not. llvm::PointerIntPair SuperclassType; } LazySemanticInfo; std::optional getCachedInheritsSuperclassInitializers() const { if (Bits.ClassDecl.ComputedInheritsSuperclassInits) return Bits.ClassDecl.InheritsSuperclassInits; return std::nullopt; } std::optional getCachedHasMissingDesignatedInitializers() const { if (!Bits.ClassDecl.ComputedHasMissingDesignatedInitializers) { // Force loading all the members, which will add this attribute if any of // members are determined to be missing while loading. auto mutableThis = const_cast(this); (void)mutableThis->lookupDirect(DeclBaseName::createConstructor(), getStartLoc()); } if (Bits.ClassDecl.ComputedHasMissingDesignatedInitializers) return Bits.ClassDecl.HasMissingDesignatedInitializers; return std::nullopt; } void setHasMissingDesignatedInitializers(bool value) { Bits.ClassDecl.HasMissingDesignatedInitializers = value; Bits.ClassDecl.ComputedHasMissingDesignatedInitializers = true; } /// Marks that this class inherits convenience initializers from its /// superclass. void setInheritsSuperclassInitializers(bool value) { Bits.ClassDecl.InheritsSuperclassInits = value; Bits.ClassDecl.ComputedInheritsSuperclassInits = true; } friend class SuperclassDeclRequest; friend class SuperclassTypeRequest; friend class ABIMembersRequest; friend class HasMissingDesignatedInitializersRequest; friend class InheritsSuperclassInitializersRequest; public: ClassDecl(SourceLoc ClassLoc, Identifier Name, SourceLoc NameLoc, ArrayRef Inherited, GenericParamList *GenericParams, DeclContext *DC, bool isActor); SourceLoc getStartLoc() const { return ClassLoc; } SourceRange getSourceRange() const { return SourceRange(ClassLoc, getBraces().End); } /// Determine whether the member area of this class's metadata (which consists /// of field offsets and vtable entries) is to be considered opaque by clients. /// /// Note that even @_fixed_layout classes have resilient metadata if they are /// in a resilient module. bool hasResilientMetadata() const; /// Determine whether this class has resilient metadata when accessed from the /// given module and resilience expansion. bool hasResilientMetadata(ModuleDecl *M, ResilienceExpansion expansion) const; /// Determine whether this class has a superclass. bool hasSuperclass() const { return (bool)getSuperclassDecl(); } /// Retrieve the superclass of this class, or null if there is no superclass. Type getSuperclass() const; /// Retrieve the ClassDecl for the superclass of this class, or null if there /// is no superclass. ClassDecl *getSuperclassDecl() const; /// Check if this class is a superclass or equal to the given class. bool isSuperclassOf(const ClassDecl *other) const; /// Set the superclass of this class. void setSuperclass(Type superclass); /// Walk this class and all of the superclasses of this class, transitively, /// invoking the callback function for each class. /// /// \param fn The callback function that will be invoked for each superclass. /// It can return \c Continue to continue the traversal. Returning /// \c SkipChildren halts the search and returns \c false, while returning /// \c Stop halts the search and returns \c true. /// /// \returns \c true if \c fn returned \c Stop for any class, \c false /// otherwise. bool walkSuperclasses( llvm::function_ref fn) const; //// Whether this class requires all of its stored properties to //// have initializers in the class definition. bool requiresStoredPropertyInits() const { return checkAncestry(AncestryFlags::RequiresStoredPropertyInits); } /// \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 || const_cast(this)->isForeignReferenceType(); } /// Whether the class is (known to be) a default actor. bool isDefaultActor() const; bool isDefaultActor(ModuleDecl *M, ResilienceExpansion expansion) const; /// Whether the class is known to be a *root* default actor, /// i.e. the first class in its hierarchy that is a default actor. bool isRootDefaultActor() const; bool isRootDefaultActor(ModuleDecl *M, ResilienceExpansion expansion) const; /// It is a `distributed actor` with a custom executor. bool isNonDefaultExplicitDistributedActor() const; bool isNonDefaultExplicitDistributedActor(ModuleDecl *M, ResilienceExpansion expansion) const; /// Whether the class was explicitly declared with the `actor` keyword. bool isExplicitActor() const { return Bits.ClassDecl.IsActor; } /// Whether the class was explicitly declared with the `distributed actor` keywords. bool isExplicitDistributedActor() const { return isExplicitActor() && getAttrs().hasAttribute(); } /// Get the closest-to-root superclass that's an actor class. const ClassDecl *getRootActorClass() const; /// Fetch this class's unownedExecutor property, if it has one. const VarDecl *getUnownedExecutorProperty() const; /// Is this the NSObject class type? bool isNSObject() const; /// Whether the class directly inherits from NSObject but should use /// Swift's native object model. bool isNativeNSObjectSubclass() const; /// Whether the class uses the ObjC object model (reference counting, /// allocation, etc.), the Swift model, or has no reference counting at all. ReferenceCounting getObjectModel() const; LayoutConstraintKind getLayoutConstraintKind() const { if (getObjectModel() == ReferenceCounting::ObjC) return LayoutConstraintKind::Class; return LayoutConstraintKind::NativeClass; } /// 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; /// 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.ComputedHasMissingVTableEntries = 1; Bits.ClassDecl.HasMissingVTableEntries = newValue; } /// Returns true if this class cannot be used with weak or unowned /// references. /// /// Note that this is true if this class or any of its ancestor classes /// are marked incompatible. bool isIncompatibleWithWeakReferences() const; void setIsIncompatibleWithWeakReferences(bool newValue = true) { Bits.ClassDecl.IsIncompatibleWithWeakReferences = 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; /// Retrieve the destructor for this class. DestructorDecl *getDestructor() const; /// Determine whether this class inherits the convenience initializers /// from its superclass. bool inheritsSuperclassInitializers() const; /// Walks the class hierarchy starting from this class, checking various /// conditions. AncestryOptions checkAncestry() const; /// Check if the class has ancestry of the given kind. bool checkAncestry(AncestryFlags flag) const { return checkAncestry().contains(flag); } /// 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; /// Return the imported declaration(s) for the category with the given name; this /// will either be a single imported \c ExtensionDecl, an imported /// \c ClassDecl followed by zero or more imported \c ExtensionDecl s (if /// \p name is empty; the extensions are for any class extensions), or empty /// if the class was not imported from Objective-C or does not have a /// category by that name. llvm::TinyPtrVector getImportedObjCCategory(Identifier name) const; /// Return a map of category names to extensions with that category name, /// whether imported or otherwise. llvm::DenseMap> getObjCCategoryNameMap(); // 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) { if (auto D = C->getAsDecl()) return classof(D); return false; } 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 isTypeErasedGenericClass() const { return hasClangNode() && isGenericContext() && isObjC(); } /// True if the class is known to be implemented in Swift. bool hasKnownSwiftImplementation() const { return !hasClangNode(); } /// Used to determine if this class decl is a foreign reference type. I.e., a /// non-reference-counted swift reference type that was imported from a C++ /// record. bool isForeignReferenceType() const; bool hasRefCountingAnnotations() const; }; /// The set of known protocols for which derived conformances are supported. enum class KnownDerivableProtocolKind : uint8_t { RawRepresentable, OptionSet, CaseIterable, Comparable, Equatable, Hashable, BridgedNSError, CodingKey, Encodable, Decodable, AdditiveArithmetic, Differentiable, Identifiable, Actor, DistributedActor, DistributedActorSystem, }; using PrimaryAssociatedTypeName = std::pair; /// A wrapper for a dictionary that maps Obj-C protocol requirement selectors to /// a list of function decls. class ObjCRequirementMap { public: using FunctionList = TinyPtrVector; private: using MethodKey = std::pair; llvm::SmallDenseMap storage; static MethodKey getObjCMethodKey(AbstractFunctionDecl *func); public: void addRequirement(AbstractFunctionDecl *requirement) { storage[getObjCMethodKey(requirement)].push_back(requirement); } /// Retrieve the Objective-C requirements in this protocol that have the /// given Objective-C method key. FunctionList getRequirements(AbstractFunctionDecl *requirement) const { auto key = getObjCMethodKey(requirement); auto known = storage.find(key); if (known == storage.end()) return {}; return known->second; } }; /// ProtocolDecl - A declaration of a protocol, for example: /// /// protocol Drawable { /// func draw() /// } /// /// Every protocol has an implicitly-created 'Self' generic parameter that /// stands for a type that conforms to the protocol. For example, /// /// protocol Clonable { /// func clone() -> Self /// } /// class ProtocolDecl final : public NominalTypeDecl { SourceLoc ProtocolLoc; ArrayRef PrimaryAssociatedTypeNames; ArrayRef InheritedProtocols; ArrayRef AllInheritedProtocols; ArrayRef AssociatedTypes; ArrayRef ProtocolRequirements; struct { /// The superclass decl and a bit to indicate whether the /// superclass was computed yet or not. llvm::PointerIntPair SuperclassDecl; } LazySemanticInfo; /// The generic signature representing exactly the new requirements introduced /// by this protocol. RequirementSignature RequirementSig; /// Returns the cached result of \c requiresClass or \c None if it hasn't yet /// been computed. std::optional getCachedRequiresClass() const { if (Bits.ProtocolDecl.RequiresClassValid) return Bits.ProtocolDecl.RequiresClass; return std::nullopt; } /// Caches the result of \c requiresClass void setCachedRequiresClass(bool requiresClass) { Bits.ProtocolDecl.RequiresClassValid = true; Bits.ProtocolDecl.RequiresClass = requiresClass; } /// Returns the cached result of \c existentialConformsToSelf or \c None if it /// hasn't yet been computed. std::optional getCachedExistentialConformsToSelf() const { if (Bits.ProtocolDecl.ExistentialConformsToSelfValid) return Bits.ProtocolDecl.ExistentialConformsToSelf; return std::nullopt; } /// Caches the result of \c existentialConformsToSelf void setCachedExistentialConformsToSelf(bool result) { Bits.ProtocolDecl.ExistentialConformsToSelfValid = true; Bits.ProtocolDecl.ExistentialConformsToSelf = result; } /// Returns the cached result of \c hasSelfOrAssociatedTypeRequirements or /// \c None if it hasn't yet been computed. std::optional getCachedHasSelfOrAssociatedTypeRequirements() { if (Bits.ProtocolDecl.HasSelfOrAssociatedTypeRequirementsValid) return static_cast(Bits.ProtocolDecl.HasSelfOrAssociatedTypeRequirements); return std::nullopt; } /// Caches the result of \c hasSelfOrAssociatedTypeRequirements void setCachedHasSelfOrAssociatedTypeRequirements(bool value) { Bits.ProtocolDecl.HasSelfOrAssociatedTypeRequirementsValid = true; Bits.ProtocolDecl.HasSelfOrAssociatedTypeRequirements = value; } bool hasLazyRequirementSignature() const { return Bits.ProtocolDecl.HasLazyRequirementSignature; } bool hasLazyPrimaryAssociatedTypes() const { return Bits.ProtocolDecl.HasLazyPrimaryAssociatedTypes; } friend class SuperclassDeclRequest; friend class SuperclassTypeRequest; friend class StructuralRequirementsRequest; friend class TypeAliasRequirementsRequest; friend class ProtocolDependenciesRequest; friend class RequirementSignatureRequest; friend class ProtocolRequiresClassRequest; friend class ExistentialConformsToSelfRequest; friend class HasSelfOrAssociatedTypeRequirementsRequest; friend class InheritedProtocolsRequest; friend class AllInheritedProtocolsRequest; friend class PrimaryAssociatedTypesRequest; friend class ProtocolRequirementsRequest; public: ProtocolDecl(DeclContext *DC, SourceLoc ProtocolLoc, SourceLoc NameLoc, Identifier Name, ArrayRef PrimaryAssociatedTypeNames, ArrayRef Inherited, TrailingWhereClause *TrailingWhere); using Decl::getASTContext; /// Retrieve the set of protocols inherited from this protocol. ArrayRef getInheritedProtocols() const; /// Retrieve the transitive closure of the inherited protocols, not including /// this protocol itself. ArrayRef getAllInheritedProtocols() const; /// Determine whether this protocol has a superclass. bool hasSuperclass() const { return (bool)getSuperclassDecl(); } /// Retrieve the ClassDecl for the superclass of this protocol, or null if there /// is no superclass. ClassDecl *getSuperclassDecl() 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). ArrayRef getAssociatedTypeMembers() const; /// Returns the list of primary associated type names. These are the associated /// types that is parametrized with same-type requirements in a /// parametrized protocol type of the form SomeProtocol. ArrayRef getPrimaryAssociatedTypeNames() const { return PrimaryAssociatedTypeNames; } /// Returns the list of primary associated types. These are the associated /// types that is parametrized with same-type requirements in a /// parametrized protocol type of the form SomeProtocol. ArrayRef getPrimaryAssociatedTypes() const; /// Returns the list of all requirements (associated type and value) /// associated with this protocol. ArrayRef getProtocolRequirements() const; /// Returns a protocol requirement with the given name, or nullptr if the /// name has multiple overloads, or no overloads at all. ValueDecl *getSingleRequirement(DeclName name) const; /// Returns an associated type with the given name, or nullptr if one does /// not exist. AssociatedTypeDecl *getAssociatedType(Identifier name) const; /// Returns the existential type for this protocol. Type getDeclaredExistentialType() const { return ExistentialType::get(getDeclaredInterfaceType()); } /// Walk this protocol and 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; /// Determine whether this protocol inherits from the given ("super") /// protocol. bool inheritsFrom(const ProtocolDecl *Super) const; 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; /// 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; /// Does this protocol require a self-conformance witness table? bool requiresSelfConformanceWitnessTable() const; /// Determine whether this protocol has `Self` or associated type /// requirements. /// /// This is true if one of the following conditions is met for this protocol /// or an inherited protocol: /// - The protocol has an associated type requirement. /// - `Self` appears in non-covariant position in the type signature of a /// value requirement. bool hasSelfOrAssociatedTypeRequirements() const; /// Returns a list of protocol requirements that must be assessed to /// determine a concrete's conformance effect polymorphism kind. PolymorphicEffectRequirementList getPolymorphicEffectRequirements( EffectKind kind) const; bool hasPolymorphicEffect(EffectKind kind) const; /// Determine whether this is a "marker" protocol, meaning that is indicates /// semantics but has no corresponding witness table. bool isMarkerProtocol() const; /// Determine if this is an invertible protocol and return its kind, /// i.e., for a protocol P, returns the kind if inverse constraint ~P exists. std::optional getInvertibleProtocolKind() const; /// Returns a dictionary that maps Obj-C protocol requirement selectors to a /// list of function decls. ObjCRequirementMap getObjCRequiremenMap() const; private: void computeKnownProtocolKind() const; bool areInheritedProtocolsValid() const { return Bits.ProtocolDecl.InheritedProtocolsValid; } void setInheritedProtocolsValid() { Bits.ProtocolDecl.InheritedProtocolsValid = true; } bool areAllInheritedProtocolsValid() const { return Bits.ProtocolDecl.AllInheritedProtocolsValid; } void setAllInheritedProtocolsValid() { Bits.ProtocolDecl.AllInheritedProtocolsValid = true; } bool areProtocolRequirementsValid() const { return Bits.ProtocolDecl.ProtocolRequirementsValid; } void setProtocolRequirementsValid() { Bits.ProtocolDecl.ProtocolRequirementsValid = true; } public: /// If this is known to be a compiler-known protocol, returns the kind. /// Otherwise returns None. std::optional getKnownProtocolKind() const { if (Bits.ProtocolDecl.KnownProtocol == 0) computeKnownProtocolKind(); if (Bits.ProtocolDecl.KnownProtocol == 1) return std::nullopt; return static_cast(Bits.ProtocolDecl.KnownProtocol - 2); } std::optional getKnownDerivableProtocolKind() const; /// 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; } /// Whether this protocol has a circular reference in its list of inherited /// protocols. bool hasCircularInheritedProtocols() const; /// 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 type witness for an associated type, or a null /// type if there is no default. Type getDefaultTypeWitness(AssociatedTypeDecl *assocType) const; /// Set the default type witness for an associated type. void setDefaultTypeWitness(AssociatedTypeDecl *assocType, Type witness); /// 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); /// Returns the default associated conformance witness for an associated /// type, or \c None if there is no default. ProtocolConformanceRef getDefaultAssociatedConformanceWitness(CanType association, ProtocolDecl *requirement) const; /// Set the default associated conformance witness for the given /// associated conformance. void setDefaultAssociatedConformanceWitness( CanType association, ProtocolDecl *requirement, ProtocolConformanceRef conformance); /// Retrieve the name to use for this protocol when interoperating /// with the Objective-C runtime. StringRef getObjCRuntimeName(llvm::SmallVectorImpl &buffer) const; /// Retrieve the original requirements written in source, as structural types. /// /// The requirement machine builds the requirement signature from structural /// requirements. Almost everywhere else should use getRequirementSignature() /// instead. ArrayRef getStructuralRequirements() const; /// Retrieve same-type requirements implied by protocol typealiases with the /// same name as associated types, and diagnose cases that are better expressed /// via a 'where' clause. ArrayRef getTypeAliasRequirements() const; /// Get the list of protocols appearing on the right hand side of conformance /// requirements. Computed from the structural requirements, above. ArrayRef getProtocolDependencies() const; /// Retrieve the requirements that describe this protocol from the point of /// view of the generic system; see RequirementSignature.h for details. RequirementSignature getRequirementSignature() const; /// Is the requirement signature currently being computed? bool isComputingRequirementSignature() const; /// Has the requirement signature been computed yet? bool isRequirementSignatureComputed() const { return Bits.ProtocolDecl.HasRequirementSignature; } void setRequirementSignature(RequirementSignature requirementSig); void setLazyRequirementSignature(LazyMemberLoader *lazyLoader, uint64_t requirementSignatureData); void setLazyAssociatedTypeMembers(LazyMemberLoader *lazyLoader, uint64_t associatedTypesData); void setLazyPrimaryAssociatedTypeMembers(LazyMemberLoader *lazyLoader, uint64_t associatedTypesData); public: // 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) { if (auto D = C->getAsDecl()) return classof(D); return false; } static bool classof(const IterableDeclContext *C) { auto NTD = dyn_cast(C); return NTD && classof(NTD); } }; /// This is the special singleton Builtin.TheTupleType. It is not directly /// visible in the source language, but we use it to attach extensions /// and conformances for tuple types. /// /// - The declared interface type is the special TheTupleType singleton. /// - The generic parameter list has one pack generic parameter, /// - The generic signature has no requirements, /// - The self interface type is the tuple type containing a single pack /// expansion, (repeat each Element). class BuiltinTupleDecl final : public NominalTypeDecl { public: BuiltinTupleDecl(Identifier Name, DeclContext *Parent); SourceRange getSourceRange() const { return SourceRange(); } TupleType *getTupleSelfType(const ExtensionDecl *owner) const; // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() == DeclKind::BuiltinTuple; } static bool classof(const GenericTypeDecl *D) { return D->getKind() == DeclKind::BuiltinTuple; } static bool classof(const NominalTypeDecl *D) { return D->getKind() == DeclKind::BuiltinTuple; } static bool classof(const DeclContext *C) { if (auto D = C->getAsDecl()) return classof(D); return false; } static bool classof(const IterableDeclContext *C) { auto NTD = dyn_cast(C); return NTD && classof(NTD); } }; /// Describes whether a particular storage declaration is mutable. enum class StorageMutability { /// The storage is immutable, meaning that it can neither be assigned /// to nor passed inout. Immutable, /// The storage is mutable, meaning that it can be assigned and pased /// inout. Mutable, /// The storage is immutable, but can be asigned for the purposes of /// initialization. Initializable }; /// AbstractStorageDecl - This is the common superclass for VarDecl and /// SubscriptDecl, representing potentially settable memory locations. class AbstractStorageDecl : public ValueDecl { friend class HasStorageRequest; friend class SetterAccessLevelRequest; friend class IsGetterMutatingRequest; friend class IsSetterMutatingRequest; friend class OpaqueReadOwnershipRequest; friend class StorageImplInfoRequest; friend class RequiresOpaqueAccessorsRequest; friend class RequiresOpaqueModifyCoroutineRequest; friend class SynthesizeAccessorRequest; public: static const size_t MaxNumAccessors = 255; private: /// A record of the accessors for the declaration. class alignas(1 << 3) AccessorRecord final : private llvm::TrailingObjects { friend TrailingObjects; using AccessorIndex = uint8_t; static const AccessorIndex InvalidIndex = 0; /// The range of the braces around the accessor clause. SourceRange Braces; /// The number of accessors currently stored in this record. AccessorIndex NumAccessors; /// The storage capacity of this record for accessors. Always includes /// enough space for adding opaque accessors to the record, which are the /// only accessors that should ever be added retroactively; hence this /// field is only here for the purposes of safety checks. AccessorIndex AccessorsCapacity; /// Either 0, meaning there is no registered accessor of the given kind, /// or the index+1 of the accessor in the accessors array. AccessorIndex AccessorIndices[NumAccessorKinds]; AccessorRecord(SourceRange braces, ArrayRef accessors, AccessorIndex accessorsCapacity); public: static AccessorRecord *create(ASTContext &ctx, SourceRange braces, ArrayRef accessors); SourceRange getBracesRange() const { return Braces; } inline AccessorDecl *getAccessor(AccessorKind kind) const; ArrayRef getAllAccessors() const { return { getTrailingObjects(), NumAccessors }; } void addOpaqueAccessor(AccessorDecl *accessor); void removeAccessor(AccessorDecl *accessor); private: MutableArrayRef getAccessorsBuffer() { return { getTrailingObjects(), NumAccessors }; } bool registerAccessor(AccessorDecl *accessor, AccessorIndex index); }; llvm::PointerIntPair> Accessors; struct { unsigned HasStorageComputed : 1; unsigned HasStorage : 1; unsigned IsGetterMutatingComputed : 1; unsigned IsGetterMutating : 1; unsigned IsSetterMutatingComputed : 1; unsigned IsSetterMutating : 1; unsigned OpaqueReadOwnershipComputed : 1; unsigned OpaqueReadOwnership : 2; unsigned ImplInfoComputed : 1; unsigned RequiresOpaqueAccessorsComputed : 1; unsigned RequiresOpaqueAccessors : 1; unsigned RequiresOpaqueModifyCoroutineComputed : 1; unsigned RequiresOpaqueModifyCoroutine : 1; unsigned RequiresOpaqueModify2CoroutineComputed : 1; unsigned RequiresOpaqueModify2Coroutine : 1; } LazySemanticInfo = { }; /// The implementation info for the accessors. StorageImplInfo ImplInfo; /// Add a synthesized accessor. void setSynthesizedAccessor(AccessorKind kind, AccessorDecl *getter); protected: AbstractStorageDecl(DeclKind Kind, bool IsStatic, DeclContext *DC, DeclName Name, SourceLoc NameLoc, StorageIsMutable_t supportsMutation) : ValueDecl(Kind, DC, Name, NameLoc), ImplInfo(StorageImplInfo::getSimpleStored(supportsMutation)) { Bits.AbstractStorageDecl.IsStatic = IsStatic; } public: /// Should this declaration be treated as if annotated with transparent /// attribute. bool isTransparent() const; /// Is this a type ('static') variable? bool isStatic() const { return Bits.AbstractStorageDecl.IsStatic; } void setStatic(bool IsStatic) { Bits.AbstractStorageDecl.IsStatic = IsStatic; } bool isCompileTimeLiteral() const; bool isConstValue() const; /// \returns the way 'static'/'class' should be spelled for this declaration. StaticSpellingKind getCorrectStaticSpelling() const; /// Return the interface type of the stored value. Type getValueInterfaceType() const; /// 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; /// Determine how this storage is implemented. StorageImplInfo getImplInfo() const; /// Overwrite the registered implementation-info. This should be /// used carefully. void setImplInfo(StorageImplInfo implInfo); /// Cache the implementation-info, for use by the request-evaluator. void cacheImplInfo(StorageImplInfo implInfo); ReadImplKind getReadImpl() const { return getImplInfo().getReadImpl(); } WriteImplKind getWriteImpl() const { return getImplInfo().getWriteImpl(); } ReadWriteImplKind getReadWriteImpl() const { return getImplInfo().getReadWriteImpl(); } /// Return true if this is a VarDecl that has storage associated with /// it. bool hasStorage() const; /// Return true if this is a VarDecl that has init accessor associated /// with it. bool hasInitAccessor() const; /// Return true if this is a property that either has storage /// or init accessor associated with it. bool supportsInitialization() const { return hasStorage() || hasInitAccessor(); } /// Return true if this storage has the basic accessors/capability /// to be mutated. This is generally constant after the accessors are /// installed by the parser/importer/whatever. /// /// Note that this is different from the mutability of the declaration /// in the user language: sometimes we can assign to declarations that /// don't support mutation (e.g. to initialize them), and sometimes we /// can't mutate things that do support mutation (e.g. because their /// setter is private). StorageIsMutable_t supportsMutation() const { return getImplInfo().supportsMutation(); } /// Determine whether references to this storage declaration may appear /// on the left-hand side of an assignment, as the operand of a /// `&` or 'inout' operator, or as a component in a writable key path. bool isSettable(const DeclContext *useDC) const { switch (mutability(useDC)) { case StorageMutability::Immutable: return false; case StorageMutability::Mutable: case StorageMutability::Initializable: return true; } } /// Determine the mutability of this storage declaration when /// accessed from a given declaration context. StorageMutability mutability( const DeclContext *useDC, std::optional base = std::nullopt) const; /// Determine the mutability of this storage declaration when /// accessed from a given declaration context in Swift. /// /// This method differs only from 'mutability()' in its handling of /// 'optional' storage requirements, which lack support for direct /// writes in Swift. StorageMutability mutabilityInSwift( const DeclContext *useDC, std::optional base = std::nullopt) const; /// Determine whether references to this storage declaration in Swift may /// appear on the left-hand side of an assignment, as the operand of a /// `&` or 'inout' operator, or as a component in a writable key path. /// /// This method is equivalent to \c isSettable with the exception of /// 'optional' storage requirements, which lack support for direct writes /// in Swift. bool isSettableInSwift(const DeclContext *useDC) const { switch (mutabilityInSwift(useDC)) { case StorageMutability::Immutable: return false; case StorageMutability::Mutable: case StorageMutability::Initializable: return true; } } /// Does this storage declaration have explicitly-defined accessors /// written in the source? bool hasParsedAccessors() const; /// Return the ownership of values opaquely read from this storage. OpaqueReadOwnership getOpaqueReadOwnership() const; void setOpaqueReadOwnership(OpaqueReadOwnership ownership) { LazySemanticInfo.OpaqueReadOwnership = unsigned(ownership); LazySemanticInfo.OpaqueReadOwnershipComputed = true; } /// Return true if reading this storage requires the ability to /// modify the base value. bool isGetterMutating() const; void setIsGetterMutating(bool isMutating) { LazySemanticInfo.IsGetterMutating = isMutating; LazySemanticInfo.IsGetterMutatingComputed = true; } /// Return true if modifying this storage requires the ability to /// modify the base value. bool isSetterMutating() const; void setIsSetterMutating(bool isMutating) { LazySemanticInfo.IsSetterMutating = isMutating; LazySemanticInfo.IsSetterMutatingComputed = true; } AccessorDecl *getAccessor(AccessorKind kind) const { if (auto info = Accessors.getPointer()) return info->getAccessor(kind); return nullptr; } ArrayRef getAllAccessors() const { if (const auto *info = Accessors.getPointer()) return info->getAllAccessors(); return {}; } void removeAccessor(AccessorDecl *accessor) { if (auto *info = Accessors.getPointer()) return info->removeAccessor(accessor); } /// This is the primary mechanism by which we can easily determine whether /// this storage decl has any effects. /// /// \returns the getter decl iff this decl has only one accessor that is /// a 'get' with an effect (i.e., 'async', 'throws', or both). /// Otherwise returns nullptr. AccessorDecl *getEffectfulGetAccessor() const; /// Performs a "limit check" on an effect possibly exhibited by this storage /// decl with respect to some other storage decl that serves as the "limit." /// This check says that \c this is less effectful than \c other if /// \c this either does not exhibit the effect, or if it does, then \c other /// also exhibits the effect. Thus, it is conceptually equivalent to /// a less-than-or-equal (≤) check like so: /// /// \verbatim /// /// this->hasEffect(E) ≤ other->hasEffect(E) /// /// \endverbatim /// /// \param kind the single effect we are performing a check for. /// /// \returns true iff \c this decl either does not exhibit the effect, /// or \c other also exhibits the effect. bool isLessEffectfulThan(AbstractStorageDecl const* other, EffectKind kind) const; /// Return an accessor that this storage is expected to have, synthesizing /// one if necessary. Note that will always synthesize one, even if the /// accessor is not part of the expected opaque set for the storage, so use /// with caution. AccessorDecl *getSynthesizedAccessor(AccessorKind kind) const; /// Return an accessor part of the set of opaque accessors dictated by the /// requirements of the ABI. /// /// This will synthesize the accessor if one is required but not specified /// in source; for example, most of the time a mutable property is required /// to have a 'modify' accessor, but if the property was only written with /// 'get' and 'set' accessors, 'modify' will be synthesized to call 'get' /// followed by 'set'. /// /// If the accessor is not needed for ABI reasons, this returns nullptr. /// To ensure an accessor is always returned, use getSynthesizedAccessor(). AccessorDecl *getOpaqueAccessor(AccessorKind kind) const; /// Collect all opaque accessors. ArrayRef getOpaqueAccessors(llvm::SmallVectorImpl &scratch) const; /// Return an accessor that was written in source. Returns null if the /// accessor was not explicitly defined by the user. AccessorDecl *getParsedAccessor(AccessorKind kind) const; /// Visit all parsed accessors. void visitParsedAccessors(llvm::function_ref) const; /// Visit all opaque accessor kinds. void visitExpectedOpaqueAccessors( llvm::function_ref) const; /// Visit all opaque accessors. void visitOpaqueAccessors(llvm::function_ref) const; /// Visit all eagerly emitted accessors. /// /// This is the union of the parsed and opaque sets. void visitEmittedAccessors(llvm::function_ref) const; void setAccessors(SourceLoc lbraceLoc, ArrayRef accessors, SourceLoc rbraceLoc); /// Add a setter to an existing Computed var. /// /// This should only be used by the ClangImporter. void setComputedSetter(AccessorDecl *Set); /// Does this storage require opaque accessors of any kind? bool requiresOpaqueAccessors() const; /// Does this storage require an opaque accessor of the given kind? bool requiresOpaqueAccessor(AccessorKind kind) const; /// Does this storage require a 'get' accessor in its opaque-accessors set? bool requiresOpaqueGetter() const { return getOpaqueReadOwnership() != OpaqueReadOwnership::Borrowed; } /// Does this storage require a '_read' accessor in its opaque-accessors set? bool requiresOpaqueReadCoroutine() const; /// Does this storage require a 'read' accessor in its opaque-accessors set? bool requiresOpaqueRead2Coroutine() const; /// Does this storage require a 'set' accessor in its opaque-accessors set? bool requiresOpaqueSetter() const { return supportsMutation(); } /// Does this storage require a '_modify' accessor in its opaque-accessors /// set? bool requiresOpaqueModifyCoroutine() const; /// Does this storage require a 'modify' accessor in its opaque-accessors /// set? bool requiresOpaqueModify2Coroutine() const; /// Given that CoroutineAccessors is enabled, is _read/_modify required for /// ABI stability? bool requiresCorrespondingUnderscoredCoroutineAccessor( AccessorKind kind, AccessorDecl const *decl = nullptr) const; /// Does this storage have any explicit observers (willSet or didSet) attached /// to it? bool hasObservers() const { return getParsedAccessor(AccessorKind::WillSet) || getParsedAccessor(AccessorKind::DidSet); } SourceRange getBracesRange() const { if (auto info = Accessors.getPointer()) return info->getBracesRange(); return SourceRange(); } AccessLevel getSetterFormalAccess() const; AccessScope getSetterFormalAccessScope(const DeclContext *useDC = nullptr, bool treatUsableFromInlineAsPublic = false) const; void setSetterAccess(AccessLevel accessLevel) { assert(!Accessors.getInt().hasValue()); overwriteSetterAccess(accessLevel); } void overwriteSetterAccess(AccessLevel accessLevel); /// 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 cast_or_null(ValueDecl::getOverriddenDecl()); } /// 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. /// /// See \c isAccessibleFrom for a discussion of the \p forConformance /// parameter. bool isSetterAccessibleFrom(const DeclContext *DC, bool forConformance=false) const; /// Determine how this storage declaration should actually be accessed. AccessStrategy getAccessStrategy(AccessSemantics semantics, AccessKind accessKind, ModuleDecl *module, ResilienceExpansion expansion, bool useOldABI) const; /// Do we need to use resilient access patterns outside of this /// property's resilience domain? bool isResilient() const; /// Do we need to use resilient access patterns when accessing this /// property from the given module? bool isResilient(ModuleDecl *M, ResilienceExpansion expansion) const; /// True if the decl is resilient AND also its defining module does /// _not_ allow non-resilient access; the module can allow such access /// if package optimization is enabled so its client modules within the /// same package can have a direct access to this decl even if it's /// resilient. bool isStrictlyResilient() const; /// True if the storage can be referenced by a keypath directly. /// Otherwise, its override must be referenced. bool isValidKeyPathComponent() const; /// True if the storage exports a property descriptor for key paths in /// other modules. bool exportsPropertyDescriptor() const; /// True if any of the accessors to the storage is private or fileprivate. bool hasPrivateAccessor() const; bool hasDidSetOrWillSetDynamicReplacement() const; bool hasAnyNativeDynamicAccessors() const; /// Return a distributed thunk if this computed property is marked as /// 'distributed' and and nullptr otherwise. FuncDecl *getDistributedThunk() const; // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() >= DeclKind::First_AbstractStorageDecl && D->getKind() <= DeclKind::Last_AbstractStorageDecl; } }; /// Describes which synthesized property for a property with an attached /// wrapper is being referenced. enum class PropertyWrapperSynthesizedPropertyKind { /// The backing storage property, which is a stored property of the /// wrapper type. Backing, /// A projection (e.g., `$foo`), which is a computed property to access the /// wrapper instance's \c projectedValue property. Projection, }; /// VarDecl - 'var' and 'let' declarations. class VarDecl : public AbstractStorageDecl { friend class NamingPatternRequest; friend class AttachedPropertyWrappersRequest; friend class PropertyWrapperAuxiliaryVariablesRequest; NamedPattern *NamingPattern = nullptr; bool hasNoAttachedPropertyWrappers() const { return Bits.VarDecl.NoAttachedPropertyWrappers; } void setHasNoAttachedPropertyWrappers() { Bits.VarDecl.NoAttachedPropertyWrappers = true; } bool hasNoPropertyWrapperAuxiliaryVariables() const { return Bits.VarDecl.NoPropertyWrapperAuxiliaryVariables; } void setHasNoPropertyWrapperAuxiliaryVariables() { Bits.VarDecl.NoPropertyWrapperAuxiliaryVariables = true; } public: enum class Introducer : uint8_t { Let = 0, Var = 1, InOut = 2, Borrowing = 3, }; static StringRef getIntroducerStringRef(Introducer i) { switch (i) { case VarDecl::Introducer::Let: return "let"; case VarDecl::Introducer::Var: return "var"; case VarDecl::Introducer::InOut: return "inout"; case VarDecl::Introducer::Borrowing: return "_borrowing"; } } protected: PointerUnion Parent; VarDecl(DeclKind kind, bool isStatic, Introducer introducer, SourceLoc nameLoc, Identifier name, DeclContext *dc, StorageIsMutable_t supportsMutation); public: VarDecl(bool isStatic, Introducer introducer, SourceLoc nameLoc, Identifier name, DeclContext *dc) : VarDecl(DeclKind::Var, isStatic, introducer, nameLoc, name, dc, StorageIsMutable_t(introducer == Introducer::Var)) {} SourceRange getSourceRange() const; Identifier getName() const { return getBaseIdentifier(); } /// Returns the string for the base name, or "_" if this is unnamed. StringRef getNameStr() const { return hasName() ? getBaseIdentifier().str() : "_"; } /// Maps the interface type of the variable declaration into the generic /// environment of its parent DeclContext. Make sure this is what you want /// and not just getInterfaceType(). Type getTypeInContext() const; /// Determine the mutability of this variable declaration when /// accessed from a given declaration context. StorageMutability mutability( const DeclContext *useDC, std::optional base = std::nullopt) 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 { if (!Parent) return nullptr; return Parent.dyn_cast(); } void setParentPatternBinding(PatternBindingDecl *PBD) { assert(PBD); Parent = 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; /// Returns the parsed type of this variable declaration. For parameters, this /// is the parsed type the user explicitly wrote. For variables, this is the /// type the user wrote in the typed pattern that binds this variable. /// /// Note that there are many cases where the user may elide types. This will /// return null in those cases. TypeRepr *getTypeReprOrParentPatternTypeRepr() const; /// Return the statement that owns the pattern associated with this VarDecl, /// if one exists. /// /// NOTE: After parsing and before type checking, all VarDecls from /// CaseLabelItem's Patterns return their CaseStmt. After type checking, we /// will have constructed the CaseLabelItem VarDecl linked list implying this /// will return nullptr. After type checking, if one wishes to find a parent /// pattern of a VarDecl of a CaseStmt, \see getRecursiveParentPatternStmt /// instead. Stmt *getParentPatternStmt() const { if (!Parent) return nullptr; return Parent.dyn_cast(); } void setParentPatternStmt(Stmt *s) { assert(s); Parent = s; } /// Look for the parent pattern stmt of this var decl, recursively /// looking through var decl pointers and then through any /// fallthroughts. Stmt *getRecursiveParentPatternStmt() const; /// Returns the var decl that this var decl is an implicit reference to if /// such a var decl exists. VarDecl *getParentVarDecl() const { if (!Parent) return nullptr; return Parent.dyn_cast(); } /// Set \p v to be the pattern produced VarDecl that is the parent of this /// var decl. void setParentVarDecl(VarDecl *v) { assert(v && v != this); Parent = v; } NamedPattern *getNamingPattern() const; void setNamingPattern(NamedPattern *Pat); /// If this is a VarDecl that does not belong to a CaseLabelItem's pattern, /// return this. Otherwise, this VarDecl must belong to a CaseStmt's /// CaseLabelItem. In that case, return the first case label item of the first /// case stmt in a sequence of case stmts that fallthrough into each other. /// /// NOTE: During type checking, we emit an error if we have a single case /// label item with a pattern that has multiple var decls of the same /// name. This means that during type checking and before type checking, we /// may have a _malformed_ switch stmt var decl linked list since var decls in /// the same case label item that have the same name will point at the same /// canonical var decl, namely the first var decl with the name in the /// canonical case label item's var decl list. This is ok, since we are going /// to emit the error, but it requires us to be more careful/cautious before /// type checking has been complete when relying on canonical var decls /// matching up. VarDecl *getCanonicalVarDecl() const; /// If this is a case stmt var decl, return the var decl that corresponds to /// this var decl in the first case label item of the case stmt. Returns /// nullptr if this isn't a VarDecl that is part of a case stmt. NullablePtr getCorrespondingFirstCaseLabelItemVarDecl() const; /// If this is a case stmt var decl, return the case body var decl that this /// var decl maps to. NullablePtr getCorrespondingCaseBodyVariable() const; /// Return true if this var decl is an implicit var decl belonging to a case /// stmt's body. bool isCaseBodyVariable() const; /// True if the global stored property requires lazy initialization. bool isLazilyInitializedGlobal() const; /// 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()) { const auto i = PBD->getPatternEntryIndexForVarDecl(this); return PBD->getInit(i); } return nullptr; } /// Whether there exists an initializer for this \c VarDecl. bool isParentInitialized() const { if (auto *PBD = getParentPatternBinding()) { const auto i = PBD->getPatternEntryIndexForVarDecl(this); return PBD->isInitialized(i); } return false; } /// Return the initializer that will initializer this VarDecl at runtime. /// This is equivalent to `getParentInitializer()`, but returns `null` if the /// initializer itself was subsumed, e.g., by a macro or property wrapper. Expr *getParentExecutableInitializer() const; /// Whether this variable has an initializer that will be code-generated. bool isParentExecutabledInitialized() const { return getParentExecutableInitializer() != nullptr; } /// Get the required actor isolation for evaluating the initializer /// expression synchronously (if there is one). /// /// If this VarDecl is a stored instance property, the initializer /// can only be used in an `init` that meets the required isolation. /// Otherwise, the property must be explicitly initialized in the `init`. /// /// If this is a ParamDecl, the initializer isolation is required at /// the call-site in order to use the default argument for this parameter. /// If the required isolation is not met, an argument must be written /// explicitly at the call-site. ActorIsolation getInitializerIsolation() const; // Return whether this VarDecl has an initial value, either by checking // if it has an initializer in its parent pattern binding or if it has // the @_hasInitialValue attribute. bool hasInitialValue() const { return getAttrs().hasAttribute() || isParentInitialized(); } VarDecl *getOverriddenDecl() const { return cast_or_null(AbstractStorageDecl::getOverriddenDecl()); } /// Is this an immutable 'let' property? /// /// For \c ParamDecl instances, using \c isImmutable is preferred. bool isLet() const; /// Is this an "async let" property? bool isAsyncLet() const; /// Is this var known to be a "local" distributed actor, /// if so the implicit throwing and some isolation checks can be skipped. bool isKnownToBeLocal() const; /// Is this a stored property that will _not_ trigger any user-defined code /// upon any kind of access? bool isOrdinaryStoredProperty() const; /// Set the introducer kind. /// Note: do not call this after type checking begun. void setIntroducer(Introducer value) { Bits.VarDecl.Introducer = uint8_t(value); } Introducer getIntroducer() const { return Introducer(Bits.VarDecl.Introducer); } StringRef getIntroducerStringRef() const { return getIntroducerStringRef(getIntroducer()); } CaptureListExpr *getParentCaptureList() const { if (!Parent) return nullptr; return Parent.dyn_cast(); } /// Set \p v to be the pattern produced VarDecl that is the parent of this /// var decl. void setParentCaptureList(CaptureListExpr *expr) { assert(expr != nullptr); Parent = expr; } /// Is this an element in a capture list? bool isCaptureList() const { return getParentCaptureList() != nullptr; } /// Is this a capture of the self param? bool isSelfParamCapture() const { return Bits.VarDecl.IsSelfParamCapture; } void setIsSelfParamCapture(bool IsSelfParamCapture = true) { Bits.VarDecl.IsSelfParamCapture = IsSelfParamCapture; } /// Check whether this capture of the self param is actor-isolated. bool isSelfParamCaptureIsolated() const; /// Determines if this var has an initializer expression that should be /// exposed to clients. /// /// There's a very narrow case when we would: if the decl is an instance /// member with an initializer expression and the parent type is /// @frozen and resides in a resilient module. bool isInitExposedToClients() const; /// Determines if this var is exposed as part of the layout of a /// @frozen struct. /// /// From the standpoint of access control and exportability checking, this /// var will behave as if it was public, even if it is internal or private. bool isLayoutExposedToClients() const; /// Is this a special debugger variable? bool isDebuggerVar() const { return Bits.VarDecl.IsDebuggerVar; } void setDebuggerVar(bool IsDebuggerVar) { Bits.VarDecl.IsDebuggerVar = IsDebuggerVar; } /// Visit all auxiliary declarations to this VarDecl. /// /// An auxiliary declaration is a declaration synthesized by the compiler to support /// this VarDecl, such as synthesized property wrapper variables. /// /// \note this function only visits auxiliary decls that are not part of the AST. void visitAuxiliaryDecls(llvm::function_ref) const; /// Is this the synthesized storage for a 'lazy' property? bool isLazyStorageProperty() const { return Bits.VarDecl.IsLazyStorageProperty; } void setLazyStorageProperty(bool IsLazyStorage) { Bits.VarDecl.IsLazyStorageProperty = IsLazyStorage; } /// Retrieve the backing storage property for a lazy property. VarDecl *getLazyStorageProperty() const; /// True if this is a top-level global variable from the main source file. bool isTopLevelGlobal() const { return Bits.VarDecl.IsTopLevelGlobal; } void setTopLevelGlobal(bool b) { Bits.VarDecl.IsTopLevelGlobal = b; } /// True if this is any storage of static duration (global scope or static). bool isGlobalStorage() const; /// Retrieve the custom attributes that attach property wrappers to this /// property. The returned list contains all of the attached property wrapper /// attributes in source order, which means the outermost wrapper attribute /// is provided first. llvm::TinyPtrVector getAttachedPropertyWrappers() const; /// Retrieve the outermost property wrapper attribute associated with /// this declaration. For example: /// /// \code /// @A @B @C var : Bool = ... /// \endcode /// /// The outermost attribute in this case is `@A` and it has /// complete wrapper type `A>>`. CustomAttr *getOutermostAttachedPropertyWrapper() const { auto wrappers = getAttachedPropertyWrappers(); return wrappers.empty() ? nullptr : wrappers.front(); } /// Whether this property has any attached property wrappers. bool hasAttachedPropertyWrapper() const; /// Whether this var has an implicit property wrapper attribute. bool hasImplicitPropertyWrapper() const; /// Whether this var is a parameter with an attached property wrapper /// that has an external effect on the function. bool hasExternalPropertyWrapper() const; /// Whether all of the attached property wrappers have an init(wrappedValue:) /// initializer. bool allAttachedPropertyWrappersHaveWrappedValueInit() const; /// Retrieve the type of the attached property wrapper as a contextual /// type. /// /// \param index Which property wrapper type is being computed, where 0 /// indicates the first (outermost) attached property wrapper. /// /// \returns a NULL type for properties without attached wrappers, /// an error type when the property wrapper type itself is erroneous, /// or the wrapper type itself, which may involve unbound generic /// types. Type getAttachedPropertyWrapperType(unsigned index) const; /// Retrieve information about the attached property wrapper type. /// /// \param i Which attached property wrapper type is being queried, where 0 is the outermost (first) /// attached property wrapper type. PropertyWrapperTypeInfo getAttachedPropertyWrapperTypeInfo(unsigned i) const; /// Retrieve the fully resolved attached property wrapper type. /// /// This type will be the fully-resolved form of /// \c getAttachedPropertyWrapperType(0), which will not contain any /// unbound generic types. It will be the type of the backing property. Type getPropertyWrapperBackingPropertyType() const; /// If there is an attached property wrapper, retrieve the synthesized /// auxiliary variables. PropertyWrapperAuxiliaryVariables getPropertyWrapperAuxiliaryVariables() const; /// If there is an attached property wrapper, retrieve information about /// how to initialize the backing property. PropertyWrapperInitializerInfo getPropertyWrapperInitializerInfo() const; /// Retrieve information about the mutability of the composed /// property wrappers. std::optional getPropertyWrapperMutability() const; /// Returns whether this property is the backing storage property or a storage /// wrapper for wrapper instance's projectedValue. If this property is /// neither, then it returns `None`. std::optional getPropertyWrapperSynthesizedPropertyKind() const; /// Retrieve the backing storage property for a property that has an /// attached property wrapper. /// /// The backing storage property will be a stored property of the /// wrapper's type. This will be equivalent to /// \c getAttachedPropertyWrapperType(0) when it is fully-specified; /// if \c getAttachedPropertyWrapperType(0) involves an unbound /// generic type, the backing storage property will be the appropriate /// bound generic version. VarDecl *getPropertyWrapperBackingProperty() const; /// Retrieve the projection var for a property that has an attached /// property wrapper with a \c projectedValue . VarDecl *getPropertyWrapperProjectionVar() const; /// Retrieve the local wrapped value var for a parameter that has /// an attached property wrapper. VarDecl *getPropertyWrapperWrappedValueVar() const; /// Return true if this property either has storage or has an attached property /// wrapper that has storage. bool hasStorageOrWrapsStorage() const; /// Whether the memberwise initializer parameter for a property with a /// property wrapper type uses the wrapped type. This will occur, for example, /// when there is an explicitly-specified initializer like: /// /// \code /// @Lazy var i = 17 /// \endcode /// /// Or when there is no initializer but each composed property wrapper has /// a suitable `init(wrappedValue:)`. bool isPropertyMemberwiseInitializedWithWrappedType() const; /// Return the interface type of the value used for the 'wrappedValue:' /// parameter when initializing a property wrapper. /// /// If the property has an attached property wrapper and the 'wrappedValue:' /// parameter is an autoclosure, return a function type returning the stored /// value. Otherwise, return the interface type of the stored value. Type getPropertyWrapperInitValueInterfaceType() const; /// If this property is the backing storage for a property with an attached /// property wrapper, return the original property. /// /// \param kind If not \c None, only returns the original property when /// \c this property is the specified synthesized property. VarDecl *getOriginalWrappedProperty( std::optional kind = std::nullopt) const; /// Set the property that wraps to this property as it's backing /// property. void setOriginalWrappedProperty(VarDecl *originalProperty); /// 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; /// Check whether the variable is the "self" of an actor method. bool isActorSelf() const; /// Determine whether this property will be part of the implicit memberwise /// initializer. /// /// \param preferDeclaredProperties When encountering a `lazy` property /// or a property that has an attached property wrapper, prefer the /// actual declared property (which may or may not be considered "stored" /// as the moment) to the backing storage property. Otherwise, the stored /// backing property will be treated as the member-initialized property. bool isMemberwiseInitialized(bool preferDeclaredProperties) const; /// Return the range of semantics attributes attached to this VarDecl. auto getSemanticsAttrs() const -> decltype(getAttrs().getAttributes()) { return getAttrs().getAttributes(); } /// Returns true if this VarDecl has the string \p attrValue as a semantics /// attribute. bool hasSemanticsAttr(StringRef attrValue) const { return llvm::any_of(getSemanticsAttrs(), [&](const SemanticsAttr *attr) { return attrValue == attr->Value; }); } clang::PointerAuthQualifier getPointerAuthQualifier() const; static VarDecl *createImplicitStringInterpolationVar(DeclContext *DC); // 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 { friend class ParameterList; friend class DefaultArgumentInitContextRequest; friend class DefaultArgumentExprRequest; friend class DefaultArgumentTypeRequest; enum class ArgumentNameFlags : uint8_t { /// Whether or not this parameter is destructed. Destructured = 1 << 0, /// Whether or not this parameter is '_const'. IsCompileTimeLiteral = 1 << 1, /// Whether or not this parameter is '@const'. IsConstValue = 1 << 2, }; llvm::PointerIntPair> ArgumentNameAndFlags; SourceLoc ParameterNameLoc; SourceLoc ArgumentNameLoc; SourceLoc SpecifierLoc; struct alignas(1 << StoredDefaultArgumentAlignInBits) StoredDefaultArgument { PointerUnion DefaultArg; /// The type of the default argument expression. Type ExprType; /// Stores the context for the default argument as well as a bit to /// indicate whether the default expression has been type-checked. llvm::PointerIntPair InitContextAndIsTypeChecked; StringRef StringRepresentation; CaptureInfo Captures; }; /// Retrieve the cached initializer context for the parameter's default /// argument without triggering a request. std::optional getCachedDefaultArgumentInitContext() const; /// NOTE: This is stored using bits from TyReprAndFlags and /// DefaultValueAndFlags. enum class Flag : uint8_t { /// Whether or not this parameter is vargs. IsVariadic = 1 << 0, /// Whether or not this parameter is `@autoclosure`. IsAutoClosure = 1 << 1, /// Whether or not this parameter is 'isolated'. IsIsolated = 1 << 2, /// Whether this parameter is `@_addressable`. IsAddressable = 1 << 3, /// Whether or not this parameter is 'sending'. IsSending = 1 << 4, }; /// The type repr and 3 bits used for flags. llvm::PointerIntPair::type> TyReprAndFlags; /// The default value, if any, along with 3 bits for flags. llvm::PointerIntPair::type> DefaultValueAndFlags; OptionSet getOptions() const { uint8_t result = 0; result |= TyReprAndFlags.getInt(); result |= DefaultValueAndFlags.getInt() << 3; return OptionSet(result); } /// Set the current set of options to \p newFlags. void setOptions(OptionSet newFlags) { uint8_t bits = newFlags.toRaw(); TyReprAndFlags.setInt(bits & 0x7); DefaultValueAndFlags.setInt(bits >> 3); } void setOptionsAndPointers(TypeRepr *tyRepr, StoredDefaultArgument *storedArgs, OptionSet newFlags) { uint8_t bits = newFlags.toRaw(); TyReprAndFlags.setPointerAndInt(tyRepr, bits & 0x7); DefaultValueAndFlags.setPointerAndInt(storedArgs, bits >> 3); } void addFlag(Flag newFlag) { auto flagBits = uint8_t(newFlag); if (uint8_t(newFlag) < (1 << 3)) { flagBits &= 0x7; TyReprAndFlags.setInt(TyReprAndFlags.getInt() | flagBits); return; } flagBits >>= 3; DefaultValueAndFlags.setInt(DefaultValueAndFlags.getInt() | flagBits); } void removeFlag(Flag newFlag) { auto flagBits = uint8_t(newFlag); if (uint8_t(newFlag) < (1 << 3)) { flagBits &= 0x7; TyReprAndFlags.setInt(TyReprAndFlags.getInt() & ~flagBits); return; } flagBits >>= 3; DefaultValueAndFlags.setInt(DefaultValueAndFlags.getInt() & ~flagBits); } friend class ParamSpecifierRequest; public: ParamDecl(SourceLoc specifierLoc, SourceLoc argumentNameLoc, Identifier argumentName, SourceLoc parameterNameLoc, Identifier parameterName, DeclContext *dc); /// Create a new `ParamDecl` identical to the given one except without the /// interface type. /// /// \param PD The parameter to clone. /// \param defaultArgKind The default argument kind for the cloned parameter. /// If \c std::nullopt, use the default argument kind of \p PD. static ParamDecl *cloneWithoutType( const ASTContext &Ctx, ParamDecl *PD, std::optional defaultArgKind = std::nullopt); /// Create a an identical copy of this ParamDecl. static ParamDecl *clone(const ASTContext &Ctx, ParamDecl *PD); static ParamDecl * createImplicit(ASTContext &Context, SourceLoc specifierLoc, SourceLoc argumentNameLoc, Identifier argumentName, SourceLoc parameterNameLoc, Identifier parameterName, Type interfaceType, DeclContext *Parent, ParamSpecifier specifier = ParamSpecifier::Default); static ParamDecl * createImplicit(ASTContext &Context, Identifier argumentName, Identifier parameterName, Type interfaceType, DeclContext *Parent, ParamSpecifier specifier = ParamSpecifier::Default); static ParamDecl *createParsed( ASTContext &Context, SourceLoc specifierLoc, SourceLoc argumentNameLoc, Identifier argumentName, SourceLoc parameterNameLoc, Identifier parameterName, Expr *defaultValue, DefaultArgumentInitializer *defaultValueInitContext, DeclContext *dc); /// Retrieve the argument (API) name for this function parameter. Identifier getArgumentName() const { return ArgumentNameAndFlags.getPointer(); } /// Retrieve the parameter (local) name for this function parameter. Identifier getParameterName() const { return getName(); } /// 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; } SourceLoc getParameterNameLoc() const { return ParameterNameLoc; } SourceLoc getSpecifierLoc() const { return SpecifierLoc; } /// Retrieve the TypeRepr corresponding to the parsed type of the parameter, if it exists. TypeRepr *getTypeRepr() const { return TyReprAndFlags.getPointer(); } /// Set the parsed TypeRepr on the parameter. void setTypeRepr(TypeRepr *repr); bool isDestructured() const { auto flags = ArgumentNameAndFlags.getInt(); return flags.contains(ArgumentNameFlags::Destructured); } void setDestructured(bool repr) { auto flags = ArgumentNameAndFlags.getInt(); flags = repr ? flags | ArgumentNameFlags::Destructured : flags - ArgumentNameFlags::Destructured; ArgumentNameAndFlags.setInt(flags); } DefaultArgumentKind getDefaultArgumentKind() const { return static_cast(Bits.ParamDecl.defaultArgumentKind); } bool isDefaultArgument() const { return getDefaultArgumentKind() != DefaultArgumentKind::None; } void setDefaultArgumentKind(DefaultArgumentKind K); void setDefaultArgumentKind(ArgumentAttrs K) { setDefaultArgumentKind(K.argumentKind); } /// Whether this parameter has a default argument expression available. /// /// Note that this will return false for deserialized declarations, which only /// have a textual representation of their default expression. bool hasDefaultExpr() const; /// Whether this parameter has a caller-side default argument expression /// such as the magic literal \c #function. bool hasCallerSideDefaultExpr() const; /// Retrieve the fully type-checked default argument expression for this /// parameter, or \c nullptr if there is no default expression. /// /// Note that while this will produce a type-checked expression for /// caller-side default arguments such as \c #function, this is done purely to /// check whether the code is valid. Such default arguments get re-created /// at the call site in order to have the correct context information. Expr *getTypeCheckedDefaultExpr() const; /// Retrieve the potentially un-type-checked default argument expression for /// this parameter, which can be queried for information such as its source /// range and textual representation. Returns \c nullptr if there is no /// default expression. Expr *getStructuralDefaultExpr() const { if (auto stored = DefaultValueAndFlags.getPointer()) return stored->DefaultArg.dyn_cast(); return nullptr; } /// Retrieve the type of the default expression (if any) associated with /// this parameter declaration. Type getTypeOfDefaultExpr() const; VarDecl *getStoredProperty() const { if (auto stored = DefaultValueAndFlags.getPointer()) return stored->DefaultArg.dyn_cast(); return nullptr; } /// Sets a new default argument expression for this parameter. This should /// only be called internally by `ParamDecl` and `ASTWalker`. /// /// \param E The new default argument. void setDefaultExpr(Expr *E); // FIXME: private: /// Sets a type-checked default argument expression for this parameter. This /// should only be called by the `DefaultArgumentExprRequest` request. /// /// \param E The type-checked default argument. void setTypeCheckedDefaultExpr(Expr *E); public: /// Sets a type of default expression associated with this parameter. /// This should only be called by deserialization. void setDefaultExprType(Type type); void setStoredProperty(VarDecl *var); /// Retrieve the initializer context for the parameter's default argument. Initializer *getDefaultArgumentInitContext() const; void setDefaultArgumentInitContext(DefaultArgumentInitializer *initContext); CaptureInfo getDefaultArgumentCaptureInfo() const; std::optional getCachedDefaultArgumentCaptureInfo() const { assert(DefaultValueAndFlags.getPointer()); const auto &captures = DefaultValueAndFlags.getPointer()->Captures; if (!captures.hasBeenComputed()) return std::nullopt; return captures; } void setDefaultArgumentCaptureInfo(CaptureInfo captures); /// Extracts the text of the default argument attached to the provided /// ParamDecl, removing all inactive #if clauses and providing only the /// text of active #if clauses. /// /// For example, the default argument: /// ``` /// { /// #if false /// print("false") /// #else /// print("true") /// #endif /// } /// ``` /// will return /// ``` /// { /// print("true") /// } /// ``` /// \sa getDefaultValue StringRef getDefaultValueStringRepresentation( SmallVectorImpl &scratch) const; void setDefaultValueStringRepresentation(StringRef stringRepresentation); /// Whether or not this parameter is old-style variadic. bool isVariadic() const; void setVariadic(bool value = true) { if (value) addFlag(Flag::IsVariadic); else removeFlag(Flag::IsVariadic); } /// Whether or not this parameter is marked with `@autoclosure`. bool isAutoClosure() const { return getOptions().contains(Flag::IsAutoClosure); } void setAutoClosure(bool value = true) { if (value) addFlag(Flag::IsAutoClosure); else removeFlag(Flag::IsAutoClosure); } /// Whether or not this parameter is marked with 'isolated'. bool isIsolated() const { return getOptions().contains(Flag::IsIsolated); } void setIsolated(bool value = true) { if (value) addFlag(Flag::IsIsolated); else removeFlag(Flag::IsIsolated); } /// Whether or not this parameter is marked with 'sending'. bool isSending() const { return getOptions().contains(Flag::IsSending); } void setSending(bool value = true) { if (value) addFlag(Flag::IsSending); else removeFlag(Flag::IsSending); } /// Whether or not this parameter is marked with '@_addressable'. bool isAddressable() const { return getOptions().contains(Flag::IsAddressable); } void setAddressable(bool value = true) { if (value) addFlag(Flag::IsAddressable); else removeFlag(Flag::IsAddressable); } /// Whether or not this parameter is marked with '_const'. bool isCompileTimeLiteral() const { return ArgumentNameAndFlags.getInt().contains( ArgumentNameFlags::IsCompileTimeLiteral); } void setCompileTimeLiteral(bool value = true) { auto flags = ArgumentNameAndFlags.getInt(); flags = value ? flags | ArgumentNameFlags::IsCompileTimeLiteral : flags - ArgumentNameFlags::IsCompileTimeLiteral; ArgumentNameAndFlags.setInt(flags); } /// Whether or not this parameter is marked with '@const'. bool isConstVal() const { return ArgumentNameAndFlags.getInt().contains( ArgumentNameFlags::IsConstValue); } void setConstValue(bool value = true) { auto flags = ArgumentNameAndFlags.getInt(); flags = value ? flags | ArgumentNameFlags::IsConstValue : flags - ArgumentNameFlags::IsConstValue; ArgumentNameAndFlags.setInt(flags); } /// Does this parameter reject temporary pointer conversions? bool isNonEphemeral() const; /// Attempt to apply an implicit `@_nonEphemeral` attribute to this parameter. void setNonEphemeralIfPossible(); /// 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()); } /// Determine whether this declaration is an anonymous closure parameter. bool isAnonClosureParam() const; using Specifier = ParamSpecifier; std::optional getCachedSpecifier() const { if (Bits.ParamDecl.OwnershipSpecifier != 0) return Specifier(Bits.ParamDecl.OwnershipSpecifier - 1); return std::nullopt; } /// Return the raw specifier value for this parameter. Specifier getSpecifier() const; void setSpecifier(Specifier Spec); LifetimeAnnotation getLifetimeAnnotation() const; /// Is the type of this parameter 'inout'? bool isInOut() const { return getSpecifier() == Specifier::InOut; } bool isImmutableInFunctionBody() const { return isSpecifierImmutableInFunctionBody(getSpecifier()); } static bool isSpecifierImmutableInFunctionBody(Specifier sp) { switch (sp) { case Specifier::Default: case Specifier::Borrowing: case Specifier::LegacyShared: case Specifier::LegacyOwned: return true; case Specifier::Consuming: case Specifier::InOut: case Specifier::ImplicitlyCopyableConsuming: return false; } llvm_unreachable("unhandled specifier"); } ValueOwnership getValueOwnership() const { return getValueOwnershipForSpecifier(getSpecifier()); } static ValueOwnership getValueOwnershipForSpecifier(Specifier specifier) { switch (specifier) { case ParamSpecifier::InOut: return ValueOwnership::InOut; case ParamSpecifier::Borrowing: case ParamSpecifier::LegacyShared: return ValueOwnership::Shared; case ParamSpecifier::Consuming: case ParamSpecifier::ImplicitlyCopyableConsuming: case ParamSpecifier::LegacyOwned: return ValueOwnership::Owned; case ParamSpecifier::Default: return ValueOwnership::Default; } llvm_unreachable("invalid ParamSpecifier"); } static Specifier getParameterSpecifierForValueOwnership(ValueOwnership ownership) { // TODO: switch over to consuming/borrowing once they're fully supported switch (ownership) { case ValueOwnership::Default: return Specifier::Default; case ValueOwnership::Shared: return Specifier::LegacyShared; // should become Borrowing case ValueOwnership::InOut: return Specifier::InOut; case ValueOwnership::Owned: return Specifier::LegacyOwned; // should become Consuming } llvm_unreachable("unhandled ownership"); } SourceRange getSourceRange() const; AnyFunctionType::Param toFunctionParam(Type type = Type()) const; // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() == DeclKind::Param; } /// Get the source code spelling of a parameter specifier value as a string. static StringRef getSpecifierSpelling(Specifier spec); }; inline ValueOwnership ParameterTypeFlags::getValueOwnership() const { return ParamDecl::getValueOwnershipForSpecifier(getOwnershipSpecifier()); } inline ValueOwnership YieldTypeFlags::getValueOwnership() const { return ParamDecl::getValueOwnershipForSpecifier(getOwnershipSpecifier()); } /// Describes the kind of subscripting used in Objective-C. enum class ObjCSubscriptKind { /// 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 }; /// 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 { friend class ResultTypeRequest; SourceLoc StaticLoc; SourceLoc ArrowLoc; ParameterList *Indices; TypeLoc ElementTy; void setElementInterfaceType(Type type); SubscriptDecl(DeclName Name, SourceLoc StaticLoc, StaticSpellingKind StaticSpelling, SourceLoc SubscriptLoc, ParameterList *Indices, SourceLoc ArrowLoc, TypeRepr *ElementTyR, DeclContext *Parent, GenericParamList *GenericParams) : GenericContext(DeclContextKind::SubscriptDecl, Parent, GenericParams), AbstractStorageDecl(DeclKind::Subscript, StaticSpelling != StaticSpellingKind::None, Parent, Name, SubscriptLoc, /*will be overwritten*/ StorageIsNotMutable), StaticLoc(StaticLoc), ArrowLoc(ArrowLoc), Indices(nullptr), ElementTy(ElementTyR) { Bits.SubscriptDecl.StaticSpelling = static_cast(StaticSpelling); setIndices(Indices); } public: /// Factory function only for use by deserialization. static SubscriptDecl *createDeserialized(ASTContext &Context, DeclName Name, StaticSpellingKind StaticSpelling, Type ElementTy, DeclContext *Parent, GenericParamList *GenericParams); static SubscriptDecl *createParsed(ASTContext &Context, SourceLoc StaticLoc, StaticSpellingKind StaticSpelling, SourceLoc SubscriptLoc, ParameterList *Indices, SourceLoc ArrowLoc, TypeRepr *ElementTyR, DeclContext *Parent, GenericParamList *GenericParams); static SubscriptDecl *create(ASTContext &Context, DeclName Name, SourceLoc StaticLoc, StaticSpellingKind StaticSpelling, SourceLoc SubscriptLoc, ParameterList *Indices, SourceLoc ArrowLoc, Type ElementTy, DeclContext *Parent, GenericParamList *GenericParams); static SubscriptDecl *createImported(ASTContext &Context, DeclName Name, SourceLoc SubscriptLoc, ParameterList *Indices, SourceLoc ArrowLoc, Type ElementTy, DeclContext *Parent, GenericParamList *GenericParams, ClangNode ClangN); /// \returns the way 'static'/'class' was spelled in the source. StaticSpellingKind getStaticSpelling() const { return static_cast(Bits.SubscriptDecl.StaticSpelling); } SourceLoc getStaticLoc() const { return StaticLoc; } SourceLoc getSubscriptLoc() const { return getNameLoc(); } SourceRange getSourceRange() const; SourceRange getSignatureSourceRange() const; /// Retrieve the indices for this subscript operation. ParameterList *getIndices() { return Indices; } const ParameterList *getIndices() const { return Indices; } void setIndices(ParameterList *p); /// Retrieve the type of the element referenced by a subscript /// operation. Type getElementInterfaceType() const; std::optional getCachedElementInterfaceType() const; TypeRepr *getElementTypeRepr() const { return ElementTy.getTypeRepr(); } SourceRange getElementTypeSourceRange() const { return ElementTy.getSourceRange(); } /// 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) { if (auto D = DC->getAsDecl()) return classof(D); return false; } using DeclContext::operator new; using DeclContext::operator delete; 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; } }; class BodyAndFingerprint { llvm::PointerIntPair BodyAndHasFp; Fingerprint Fp; public: BodyAndFingerprint(BraceStmt *body, std::optional fp) : BodyAndHasFp(body, fp.has_value()), Fp(fp.has_value() ? *fp : Fingerprint::ZERO()) {} BodyAndFingerprint() : BodyAndFingerprint(nullptr, std::nullopt) {} BraceStmt *getBody() const { return BodyAndHasFp.getPointer(); } std::optional getFingerprint() const { if (BodyAndHasFp.getInt()) return Fp; else return std::nullopt; } void setFingerprint(std::optional fp) { if (fp.has_value()) { Fp = *fp; BodyAndHasFp.setInt(true); } else { Fp = Fingerprint::ZERO(); BodyAndHasFp.setInt(false); } } }; void simple_display(llvm::raw_ostream &out, BodyAndFingerprint value); /// Base class for function-like declarations. class AbstractFunctionDecl : public GenericContext, public ValueDecl { friend class NeedsNewVTableEntryRequest; friend class ExplicitCaughtTypeRequest; public: /// records the kind of SILGen-synthesized body this decl represents enum class SILSynthesizeKind { None, MemberwiseInitializer, DistributedActorFactory // This enum currently needs to fit in a 2-bit bitfield. }; 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 will be synthesized on demand. Synthesize, /// Function body is present and type-checked. TypeChecked, // Function body will be synthesized by SILGen. SILSynthesize, /// Function body text was deserialized from a .swiftmodule. Deserialized // This enum currently needs to fit in a 3-bit bitfield. }; enum class BodySkippedStatus { Unknown, Skipped, NotSkipped, // This enum needs to fit in a 2-bit bitfield. }; enum class BodyExpandedStatus { /// We haven't tried to expand any body macros. NotExpanded, /// We tried to expand body macros, and there weren't any. NoMacros, /// The body was expanded from a body macro. Expanded, // This enum needs to fit in a 2-bit bitfield. }; BodyKind getBodyKind() const { return BodyKind(Bits.AbstractFunctionDecl.BodyKind); } struct BodySynthesizer { std::pair (* Fn)(AbstractFunctionDecl *, void *); void *Context; }; private: ParameterList *Params; private: /// The generation at which we last loaded derivative function configurations. unsigned DerivativeFunctionConfigGeneration = 0; /// Prepare to traverse the list of derivative function configurations. void prepareDerivativeFunctionConfigurations(); /// A uniqued list of derivative function configurations. /// - `@differentiable` and `@derivative` attribute type-checking is /// responsible for populating derivative function configurations specified /// in the current module. /// - Module loading is responsible for populating derivative function /// configurations from imported modules. struct DerivativeFunctionConfigurationList; DerivativeFunctionConfigurationList *DerivativeFunctionConfigs = nullptr; public: /// Get all derivative function configurations. ArrayRef getDerivativeFunctionConfigurations(); /// Add the given derivative function configuration. void addDerivativeFunctionConfiguration(const AutoDiffConfig &config); std::optional> getLifetimeDependencies() const; 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. BodyAndFingerprint BodyAndFP; /// This enum member is active if getBodyKind() is BodyKind::Deserialized. StringRef BodyStringRepresentation; /// 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. SourceRange BodyRange; }; friend class ParseAbstractFunctionBodyRequest; friend class TypeCheckFunctionBodyRequest; friend class IsFunctionBodySkippedRequest; friend class LifetimeDependenceInfoRequest; CaptureInfo Captures; /// Location of the 'async' token. SourceLoc AsyncLoc; /// Location of the 'throws' token. SourceLoc ThrowsLoc; /// The error type that is being thrown. TypeLoc ThrownType; struct { unsigned NeedsNewVTableEntryComputed : 1; unsigned NeedsNewVTableEntry : 1; unsigned NoLifetimeDependenceInfo : 1; } LazySemanticInfo = { }; AbstractFunctionDecl(DeclKind Kind, DeclContext *Parent, DeclName Name, SourceLoc NameLoc, bool Async, SourceLoc AsyncLoc, bool Throws, SourceLoc ThrowsLoc, TypeLoc ThrownTy, bool HasImplicitSelfDecl, GenericParamList *GenericParams) : GenericContext(DeclContextKind::AbstractFunctionDecl, Parent, GenericParams), ValueDecl(Kind, Parent, Name, NameLoc), BodyAndFP(), AsyncLoc(AsyncLoc), ThrowsLoc(ThrowsLoc), ThrownType(ThrownTy) { setBodyKind(BodyKind::None); setBodyExpandedStatus(BodyExpandedStatus::NotExpanded); Bits.AbstractFunctionDecl.HasImplicitSelfDecl = HasImplicitSelfDecl; Bits.AbstractFunctionDecl.Overridden = false; Bits.AbstractFunctionDecl.Async = Async; Bits.AbstractFunctionDecl.Throws = Throws; Bits.AbstractFunctionDecl.HasNestedTypeDeclarations = false; Bits.AbstractFunctionDecl.DistributedThunk = false; } void setBodyKind(BodyKind K) { Bits.AbstractFunctionDecl.BodyKind = unsigned(K); } BodySkippedStatus getBodySkippedStatus() const { return BodySkippedStatus(Bits.AbstractFunctionDecl.BodySkippedStatus); } void setBodySkippedStatus(BodySkippedStatus status) { Bits.AbstractFunctionDecl.BodySkippedStatus = unsigned(status); } BodyExpandedStatus getBodyExpandedStatus() const { return BodyExpandedStatus(Bits.AbstractFunctionDecl.BodyExpandedStatus); } void setBodyExpandedStatus(BodyExpandedStatus status) { Bits.AbstractFunctionDecl.BodyExpandedStatus = unsigned(status); } void setSILSynthesizeKind(SILSynthesizeKind K) { Bits.AbstractFunctionDecl.SILSynthesizeKind = unsigned(K); } SILSynthesizeKind getSILSynthesizeKind() const { return SILSynthesizeKind(Bits.AbstractFunctionDecl.SILSynthesizeKind); } public: /// Returns the string for the base name, or "_" if this is unnamed. StringRef getNameStr() const { assert(!getName().isSpecial() && "Cannot get string for special names"); return hasName() ? getBaseIdentifier().str() : "_"; } /// 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(); } /// Retrieve the location of the 'async' keyword, if present. SourceLoc getAsyncLoc() const { return AsyncLoc; } /// Retrieve the location of the 'throws' keyword, if present. SourceLoc getThrowsLoc() const { return ThrowsLoc; } /// Returns true if the function is marked as `async`. The /// type of the function will be `async` as well. bool hasAsync() const { return Bits.AbstractFunctionDecl.Async; } /// Determine whether the given function is concurrent. /// /// A function is concurrent if it has the @Sendable attribute. bool isSendable() const; /// Returns true if the function is a suitable 'async' context. /// /// Functions that are an 'async' context can make calls to 'async' functions. bool isAsyncContext() const { return hasAsync(); } /// Returns true if the function body throws. bool hasThrows() const { return Bits.AbstractFunctionDecl.Throws; } /// Retrieves the type representation for the thrown type. TypeRepr *getThrownTypeRepr() const { return ThrownType.getTypeRepr(); } /// Retrieves the thrown interface type. Type getThrownInterfaceType() const; /// Returns the thrown interface type of this function if it has already been /// computed, otherwise `nullopt`. This should only be used for dumping. std::optional getCachedThrownInterfaceType() const; /// Retrieve the "effective" thrown interface type, or std::nullopt if /// this function cannot throw. /// /// Functions with untyped throws will produce "any Error", functions that /// cannot throw or are specified to throw "Never" will return std::nullopt. std::optional getEffectiveThrownErrorType() const; /// Returns if the function throws or is async. bool hasEffect(EffectKind kind) const; /// Returns if the function is 'rethrows' or 'reasync'. bool hasPolymorphicEffect(EffectKind kind) const; /// Is this a thunk function used to access a distributed method /// or computed property outside of its actor isolation context? bool isDistributedThunk() const { return Bits.AbstractFunctionDecl.DistributedThunk; } void setDistributedThunk(bool isThunk) { Bits.AbstractFunctionDecl.DistributedThunk = isThunk; } /// For a 'distributed' target (func or computed property), /// get the 'thunk' responsible for performing the 'remoteCall'. /// /// \return the synthesized thunk, or null if the base of the call has /// diagnosed errors during type checking. FuncDecl *getDistributedThunk() const; PolymorphicEffectKind getPolymorphicEffectKind(EffectKind kind) const; // 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; /// Returns a boolean value indicating whether the body, if any, contains /// an explicit `return` statement. /// /// \returns `true` if the body contains an explicit `return` statement, /// `false` otherwise. bool bodyHasExplicitReturnStmt() const; /// Finds occurrences of explicit `return` statements within the body, if any. /// /// \param results An out container to which the results are added. void getExplicitReturnStmts(SmallVectorImpl &results) const; /// Returns true if the text of this function's body can be retrieved either /// by extracting the text from the source buffer or reading the inlinable /// body from a deserialized swiftmodule. bool hasInlinableBodyText() const; /// 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; /// Retrieve the body after macro expansion, which might also have been /// type-checked. BraceStmt *getMacroExpandedBody() const; /// Retrieve the type-checked body of the given function, or \c nullptr if /// there's no body available. BraceStmt *getTypecheckedBody() const; /// Set a new body for the function. void setBody(BraceStmt *S, BodyKind NewBodyKind); /// Note that parsing for the body was delayed. void setBodyDelayed(SourceRange bodyRange) { assert(getBodyKind() == BodyKind::None); assert(bodyRange.isValid()); BodyRange = bodyRange; setBodyKind(BodyKind::Unparsed); } void setBodyToBeReparsed(SourceRange bodyRange); /// Provide the parsed body for the function. void setBodyParsed(BraceStmt *S, std::optional fp = std::nullopt) { setBody(S, BodyKind::Parsed); BodyAndFP.setFingerprint(fp); } /// Was there a nested type declaration detected when parsing this /// function was skipped? bool hasNestedTypeDeclarations() const { return Bits.AbstractFunctionDecl.HasNestedTypeDeclarations; } void setHasNestedTypeDeclarations(bool value) { Bits.AbstractFunctionDecl.HasNestedTypeDeclarations = value; } /// Note that parsing for the body was delayed. /// /// The function should return the body statement and a flag indicating /// whether that body is already type-checked. void setBodySynthesizer( std::pair (* fn)(AbstractFunctionDecl *, void *), void *context = nullptr) { assert(getBodyKind() == BodyKind::None); Synthesizer = {fn, context}; 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::SILSynthesize); setSILSynthesizeKind(SILSynthesizeKind::MemberwiseInitializer); } /// Mark that the body should be filled in to be a factory method for creating /// a distributed actor. void setDistributedActorFactory() { assert(getBodyKind() == BodyKind::None); assert(isa(this)); setBodyKind(BodyKind::SILSynthesize); setSILSynthesizeKind(SILSynthesizeKind::DistributedActorFactory); } /// Gets the body of this function, stripping the unused portions of #if /// configs inside the body. If this function was not deserialized from a /// .swiftmodule, this body is reconstructed from the original /// source buffer. StringRef getInlinableBodyText(SmallVectorImpl &scratch) const; void setBodyStringRepresentation(StringRef body) { assert(getBodyKind() == BodyKind::None); setBodyKind(BodyKind::Deserialized); BodyStringRepresentation = body; } bool isBodyTypeChecked() const { return getBodyKind() == BodyKind::TypeChecked; } bool isBodySILSynthesize() const { return getBodyKind() == BodyKind::SILSynthesize; } /// Indicates whether the body of this function is skipped during /// typechecking. bool isBodySkipped() const; bool isMemberwiseInitializer() const { return getBodyKind() == BodyKind::SILSynthesize && getSILSynthesizeKind() == SILSynthesizeKind::MemberwiseInitializer; } /// Determines whether this function represents a distributed actor /// initialization factory. Such functions do not have a body that is /// representable in the AST, so it must be synthesized during SILGen. bool isDistributedActorFactory() const { return getBodyKind() == BodyKind::SILSynthesize && getSILSynthesizeKind() == SILSynthesizeKind::DistributedActorFactory; } /// Return a vector of distributed requirements that this distributed method /// is implementing. /// /// If the method is witness to multiple requirements this is incorrect and /// should be diagnosed during type-checking as it may make remoteCalls /// ambiguous. llvm::ArrayRef getDistributedMethodWitnessedProtocolRequirements() const; /// Determines whether this function is a 'remoteCall' function, /// which is used as ad-hoc protocol requirement by the /// 'DistributedActorSystem' protocol. bool isDistributedActorSystemRemoteCall(bool isVoidReturn) const; /// Determines whether this function is a 'makeInvocationEncoder' function, /// which is used as ad-hoc protocol requirement by the /// 'DistributedActorSystem' protocol. bool isDistributedActorSystemMakeInvocationEncoder() const; /// Determines if this function is a 'recordGenericSubstitution' function, /// which is used as ad-hoc protocol requirement by the /// 'DistributedTargetInvocationEncoder' protocol. bool isDistributedTargetInvocationEncoderRecordGenericSubstitution() const; /// Determines if this function is a 'recordArgument' function, /// which is used as ad-hoc protocol requirement by the /// 'DistributedTargetInvocationEncoder' protocol. bool isDistributedTargetInvocationEncoderRecordArgument() const; /// Determines if this function is a 'recordReturnType' function, /// which is used as ad-hoc protocol requirement by the /// 'DistributedTargetInvocationEncoder' protocol. bool isDistributedTargetInvocationEncoderRecordReturnType() const; /// Determines if this function is a 'recordErrorType' function, /// which is used as ad-hoc protocol requirement by the /// 'DistributedTargetInvocationEncoder' protocol. bool isDistributedTargetInvocationEncoderRecordErrorType() const; /// Determines if this function is a 'decodeNextArgument' function, /// which is used as ad-hoc protocol requirement by the /// 'DistributedTargetInvocationDecoder' protocol. bool isDistributedTargetInvocationDecoderDecodeNextArgument() const; /// Determines if this function is a 'onReturn' function, /// which is used as ad-hoc protocol requirement by the /// 'DistributedTargetInvocationResultHandler' protocol. bool isDistributedTargetInvocationResultHandlerOnReturn() const; /// Determines whether this declaration is a witness to a /// protocol requirement with ad-hoc `SerializationRequirement` /// conformance. bool isDistributedWitnessWithAdHocSerializationRequirement() const { return isDistributedActorSystemRemoteCall(/*isVoidResult=*/false) || isDistributedTargetInvocationEncoderRecordArgument() || isDistributedTargetInvocationEncoderRecordReturnType() || isDistributedTargetInvocationDecoderDecodeNextArgument() || isDistributedTargetInvocationResultHandlerOnReturn(); } /// For a method of a class, checks whether it will require a new entry in the /// vtable. bool needsNewVTableEntry() const; /// True if the decl is a method which introduces a new witness table entry. bool requiresNewWitnessTableEntry() const { return getOverriddenDecls().empty(); } public: /// Retrieve the source range of the function body. SourceRange getBodySourceRange() const; /// Keep current \c getBodySourceRange() as the "original" body source range /// iff the this method hasn't been called on this object. The current body /// source range must be in the same buffer as the location of the declaration /// itself. void keepOriginalBodySourceRange(); /// Retrieve the fingerprint of the body. Note that this is not affected by /// the body of the local functions or the members of the local types in this /// function. std::optional getBodyFingerprint() const; /// Retrieve the fingerprint of the body including the local type members and /// the local function bodies. std::optional getBodyFingerprintIncludingLocalTypeMembers() const; /// Retrieve the source range of the *original* function body. /// /// This may be different from \c getBodySourceRange() that returns the source /// range of the *current* body. It happens when the body is parsed from other /// source buffers for e.g. code-completion. SourceRange getOriginalBodySourceRange() const; /// Retrieve the source range of the function declaration name and parameter list. SourceRange getParameterListSourceRange() const; /// Retrieve the source range of the function declaration name, parameter list, /// and effects. For FuncDecl, this does not include the return type. SourceRange getSignatureSourceRange() const; CaptureInfo getCaptureInfo() const; std::optional getCachedCaptureInfo() const { if (!Captures.hasBeenComputed()) return std::nullopt; return Captures; } void setCaptureInfo(CaptureInfo captures) { assert(captures.hasBeenComputed()); Captures = captures; } /// Retrieve the Objective-C selector that names this method. ObjCSelector getObjCSelector(DeclName preferredName = DeclName(), bool skipIsObjCResolution = false) const; /// Determine whether the given method would produce an Objective-C /// instance method. bool isObjCInstanceMethod() const; /// Determine whether the name of an argument is an API name by default /// depending on the function context. bool argumentNameIsAPIByDefault() const; /// Retrieve the function's parameter list, not including 'self' if present. ParameterList *getParameters() { return Params; } const ParameterList *getParameters() const { return Params; } void setParameters(ParameterList *Params); bool hasImplicitSelfDecl() const { return Bits.AbstractFunctionDecl.HasImplicitSelfDecl; } ParamDecl **getImplicitSelfDeclStorage(); /// Retrieve the implicit 'self' parameter for methods. Returns nullptr for /// free functions. const ParamDecl *getImplicitSelfDecl(bool createIfNeeded=true) const { return const_cast(this) ->getImplicitSelfDecl(createIfNeeded); } ParamDecl *getImplicitSelfDecl(bool createIfNeeded=true); /// Retrieve the declaration that this method overrides, if any. AbstractFunctionDecl *getOverriddenDecl() const { return cast_or_null(ValueDecl::getOverriddenDecl()); } std::optional getExecutionBehavior() 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; } /// 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'. std::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. std::optional getForeignFunctionAsMethodSelfParameterIndex() const; /// Set information about the foreign async convention used by this /// declaration. void setForeignAsyncConvention(const ForeignAsyncConvention &convention); /// Get information about the foreign async convention used by this /// declaration, given that it is @objc and 'async'. std::optional getForeignAsyncConvention() const; /// Whether the given DeclKind is for an AbstractFunctionDecl. static bool isKind(DeclKind kind) { return kind >= DeclKind::First_AbstractFunctionDecl && kind <= DeclKind::Last_AbstractFunctionDecl; } static bool classof(const Decl *D) { return isKind(D->getKind()); } static bool classof(const DeclContext *DC) { if (auto D = DC->getAsDecl()) return classof(D); return false; } /// True if the declaration is forced to be statically dispatched. bool hasForcedStaticDispatch() const; /// Get the type of this declaration without the Self clause. /// Asserts if not in type context. Type getMethodInterfaceType() const; /// Tests if this is a function returning a DynamicSelfType, or a /// constructor. bool hasDynamicSelfResult() const; /// The async function marked as the alternative to this function, if any. AbstractFunctionDecl *getAsyncAlternative() const; /// True if the storage can be referenced by a keypath directly. /// Otherwise, its override must be referenced. bool isValidKeyPathComponent() const; /// Do we need to use resilient access patterns outside of this /// method's resilience domain? bool isResilient() const; /// Do we need to use resilient access patterns when accessing this /// method from the given module? bool isResilient(ModuleDecl *M, ResilienceExpansion expansion) const; /// If \p asyncAlternative is set, then compare its parameters to this /// (presumed synchronous) function's parameters to find the index of the /// completion handler parameter. This should be the only missing /// parameter in \p asyncAlternative, ignoring defaulted parameters if they /// have the same label. It must have a void-returning function type and be /// attributed with @escaping but not @autoclosure. /// /// Returns the last index of the parameter that looks like a completion /// handler if \p asyncAlternative is not set (with the same conditions on /// its type as above). std::optional findPotentialCompletionHandlerParam( const AbstractFunctionDecl *asyncAlternative = nullptr) const; using DeclContext::operator new; using DeclContext::operator delete; using Decl::getASTContext; }; class OperatorDecl; /// FuncDecl - 'func' declaration. class FuncDecl : public AbstractFunctionDecl { friend class AbstractFunctionDecl; friend class SelfAccessKindRequest; friend class IsStaticRequest; friend class ResultTypeRequest; SourceLoc StaticLoc; // Location of the 'static' token or invalid. SourceLoc FuncLoc; // Location of the 'func' token. TypeLoc FnRetType; protected: FuncDecl(DeclKind Kind, SourceLoc StaticLoc, StaticSpellingKind StaticSpelling, SourceLoc FuncLoc, DeclName Name, SourceLoc NameLoc, bool Async, SourceLoc AsyncLoc, bool Throws, SourceLoc ThrowsLoc, TypeLoc ThrownTy, bool HasImplicitSelfDecl, GenericParamList *GenericParams, DeclContext *Parent) : AbstractFunctionDecl(Kind, Parent, Name, NameLoc, Async, AsyncLoc, Throws, ThrowsLoc, ThrownTy, HasImplicitSelfDecl, GenericParams), StaticLoc(StaticLoc), FuncLoc(FuncLoc) { assert(!Name.getBaseName().isSpecial()); Bits.FuncDecl.StaticSpelling = static_cast(StaticSpelling); Bits.FuncDecl.ForcedStaticDispatch = false; Bits.FuncDecl.SelfAccess = static_cast(SelfAccessKind::NonMutating); Bits.FuncDecl.SelfAccessComputed = false; Bits.FuncDecl.IsStaticComputed = false; Bits.FuncDecl.IsStatic = false; Bits.FuncDecl.HasTopLevelLocalContextCaptures = false; Bits.FuncDecl.HasSendingResult = false; } void setResultInterfaceType(Type type); private: static FuncDecl *createImpl(ASTContext &Context, SourceLoc StaticLoc, StaticSpellingKind StaticSpelling, SourceLoc FuncLoc, DeclName Name, SourceLoc NameLoc, bool Async, SourceLoc AsyncLoc, bool Throws, SourceLoc ThrowsLoc, TypeLoc ThrownTy, GenericParamList *GenericParams, DeclContext *Parent, ClangNode ClangN); std::optional getCachedSelfAccessKind() const { if (Bits.FuncDecl.SelfAccessComputed) return static_cast(Bits.FuncDecl.SelfAccess); return std::nullopt; } std::optional getCachedIsStatic() const { if (Bits.FuncDecl.IsStaticComputed) return Bits.FuncDecl.IsStatic; return std::nullopt; } public: /// Factory function only for use by deserialization. static FuncDecl *createDeserialized(ASTContext &Context, StaticSpellingKind StaticSpelling, DeclName Name, bool Async, bool Throws, Type ThrownType, GenericParamList *GenericParams, Type FnRetType, DeclContext *Parent); static FuncDecl *create(ASTContext &Context, SourceLoc StaticLoc, StaticSpellingKind StaticSpelling, SourceLoc FuncLoc, DeclName Name, SourceLoc NameLoc, bool Async, SourceLoc AsyncLoc, bool Throws, SourceLoc ThrowsLoc, TypeRepr *ThrownTyR, GenericParamList *GenericParams, ParameterList *BodyParams, TypeRepr *ResultTyR, DeclContext *Parent); static FuncDecl *createImplicit(ASTContext &Context, StaticSpellingKind StaticSpelling, DeclName Name, SourceLoc NameLoc, bool Async, bool Throws, Type ThrownType, GenericParamList *GenericParams, ParameterList *BodyParams, Type FnRetType, DeclContext *Parent); static FuncDecl *createImported(ASTContext &Context, SourceLoc FuncLoc, DeclName Name, SourceLoc NameLoc, bool Async, bool Throws, Type ThrownType, ParameterList *BodyParams, Type FnRetType, GenericParamList *GenericParams, DeclContext *Parent, ClangNode ClangN); bool isStatic() const; /// \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.IsStaticComputed = true; Bits.FuncDecl.IsStatic = IsStatic; } bool isMutating() const { return getSelfAccessKind() == SelfAccessKind::Mutating; } bool isCallAsFunctionMethod() const; bool isMainTypeMainMethod() const; SelfAccessKind getSelfAccessKind() const; LifetimeAnnotation getLifetimeAnnotation() const; void setSelfAccessKind(SelfAccessKind mod) { Bits.FuncDecl.SelfAccess = static_cast(mod); Bits.FuncDecl.SelfAccessComputed = true; } SourceLoc getStaticLoc() const { return StaticLoc; } SourceLoc getFuncLoc() const { return FuncLoc; } SourceLoc getStartLoc() const { return StaticLoc.isValid() ? StaticLoc : FuncLoc; } SourceRange getSourceRange() const; TypeRepr *getResultTypeRepr() const { return FnRetType.getTypeRepr(); } SourceRange getResultTypeSourceRange() const { return FnRetType.getSourceRange(); } /// Retrieve the result interface type of this function. Type getResultInterfaceType() const; /// Returns the result interface type of this function if it has already been /// computed, otherwise `nullopt`. This should only be used for dumping. std::optional getCachedResultInterfaceType() 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; ParamDecl **getImplicitSelfDeclStorage(); /// Get the supertype method this method overrides, if any. FuncDecl *getOverriddenDecl() const { return cast_or_null(AbstractFunctionDecl::getOverriddenDecl()); } OperatorDecl *getOperatorDecl() const; /// 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; } /// Returns true if this FuncDecl has a sending result... returns false /// otherwise. bool hasSendingResult() const { return Bits.FuncDecl.HasSendingResult; } void setSendingResult(bool newValue = true) { Bits.FuncDecl.HasSendingResult = newValue; } 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 D = DC->getAsDecl()) return classof(D); return false; } /// True if the function is a defer body. bool isDeferBody() const; /// Perform basic checking to determine whether the @IBAction or /// @IBSegueAction attribute can be applied to this function. bool isPotentialIBActionTarget() const; bool hasTopLevelLocalContextCaptures() const { return Bits.FuncDecl.HasTopLevelLocalContextCaptures; } void setHasTopLevelLocalContextCaptures(bool hasCaptures=true); }; /// 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, AbstractStorageDecl *storage, bool async, SourceLoc asyncLoc, bool throws, SourceLoc throwsLoc, TypeLoc thrownTy, bool hasImplicitSelfDecl, DeclContext *parent) : FuncDecl(DeclKind::Accessor, /*StaticLoc*/ SourceLoc(), StaticSpellingKind::None, /*func loc*/ declLoc, /*name*/ Identifier(), /*name loc*/ declLoc, async, asyncLoc, throws, throwsLoc, thrownTy, hasImplicitSelfDecl, /*genericParams*/ nullptr, parent), AccessorKeywordLoc(accessorKeywordLoc), Storage(storage) { assert(!async || (accessorKind == AccessorKind::Get || accessorKind == AccessorKind::DistributedGet) && "only get accessors can be async"); Bits.AccessorDecl.AccessorKind = unsigned(accessorKind); } static AccessorDecl * createImpl(ASTContext &ctx, SourceLoc declLoc, SourceLoc accessorKeywordLoc, AccessorKind accessorKind, AbstractStorageDecl *storage, bool async, SourceLoc asyncLoc, bool throws, SourceLoc throwsLoc, TypeLoc thrownTy, DeclContext *parent, ClangNode clangNode); std::optional getCachedIsTransparent() const { if (Bits.AccessorDecl.IsTransparentComputed) return Bits.AccessorDecl.IsTransparent; return std::nullopt; } friend class IsAccessorTransparentRequest; public: static AccessorDecl * createDeserialized(ASTContext &ctx, AccessorKind accessorKind, AbstractStorageDecl *storage, bool async, bool throws, Type thrownType, Type fnRetType, DeclContext *parent); static AccessorDecl * create(ASTContext &ctx, SourceLoc declLoc, SourceLoc accessorKeywordLoc, AccessorKind accessorKind, AbstractStorageDecl *storage, bool async, SourceLoc asyncLoc, bool throws, SourceLoc throwsLoc, TypeLoc thrownType, ParameterList *parameterList, Type fnRetType, DeclContext *parent, ClangNode clangNode = ClangNode()); static AccessorDecl *createImplicit(ASTContext &Context, AccessorKind accessorKind, AbstractStorageDecl *storage, bool async, bool throws, TypeLoc thrownType, Type fnRetType, DeclContext *parent); /// Create a parsed accessor. /// /// \param paramList A parameter list for e.g \c set(newValue), or \c nullptr /// if the accessor doesn't have any user-specified arguments. static AccessorDecl *createParsed(ASTContext &ctx, AccessorKind accessorKind, AbstractStorageDecl *storage, SourceLoc declLoc, SourceLoc accessorKeywordLoc, ParameterList *paramList, SourceLoc asyncLoc, SourceLoc throwsLoc, TypeRepr *thrownType, DeclContext *dc); /// Retrieve the implicit parameter name for the given accessor kind (e.g /// \c oldValue for `didSet`, `newValue` for `set`), or an empty string if /// the kind does not have an implicit parameter name. static StringRef implicitParameterNameFor(AccessorKind kind); SourceLoc getAccessorKeywordLoc() const { return AccessorKeywordLoc; } AbstractStorageDecl *getStorage() const { return Storage; } AccessorKind getAccessorKind() const { return AccessorKind(Bits.AccessorDecl.AccessorKind); } bool isGetter() const { return getAccessorKind() == AccessorKind::Get; } bool isDistributedGetter() const { return getAccessorKind() == AccessorKind::DistributedGet; } bool isSetter() const { return getAccessorKind() == AccessorKind::Set; } bool isAnyAddressor() const { auto kind = getAccessorKind(); return kind == AccessorKind::Address || kind == AccessorKind::MutableAddress; } /// 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 { switch (getAccessorKind()) { #define OBSERVING_ACCESSOR(ID, KEYWORD) \ case AccessorKind::ID: return true; #define ACCESSOR(ID) \ case AccessorKind::ID: return false; #include "swift/AST/AccessorKinds.def" } llvm_unreachable("bad accessor kind"); } bool isInitAccessor() const { return (getAccessorKind() == AccessorKind::Init); } /// \returns true if this is non-mutating due to applying a 'mutating' /// attribute. For example a "mutating set" accessor. bool isExplicitNonMutating() const; /// Is the accessor one of the kinds that's assumed nonmutating by default? bool isAssumedNonMutating() const; /// Is this accessor one of the kinds that's implicitly a coroutine? bool isCoroutine() const { switch (getAccessorKind()) { #define COROUTINE_ACCESSOR(ID, KEYWORD) \ case AccessorKind::ID: return true; #define ACCESSOR(ID) \ case AccessorKind::ID: return false; #include "swift/AST/AccessorKinds.def" } llvm_unreachable("bad accessor kind"); } bool isImplicitGetter() const { return isGetter() && getAccessorKeywordLoc().isInvalid(); } /// Is this accessor a "simple" didSet? A "simple" didSet does not /// use the implicit oldValue parameter in its body or does not have /// an explicit parameter in its parameter list. bool isSimpleDidSet() const; void setIsTransparent(bool transparent) { Bits.AccessorDecl.IsTransparent = transparent; Bits.AccessorDecl.IsTransparentComputed = 1; } /// A representation of the name to be displayed to users. \c getNameStr /// for anything other than a getter or setter. void printUserFacingName(llvm::raw_ostream &out) const; /// If this is an init accessor, retrieve a list of instance properties /// initialized by it. ArrayRef getInitializedProperties() const; /// If this is an init accessor, retrieve a list of instance properties /// accessed by it. ArrayRef getAccessedProperties() const; /// Whether this accessor should have a body. Note that this will be true /// even when it does not have one _yet_. bool doesAccessorHaveBody() const; /// Whether this accessor is a protocol requirement for which a default /// implementation must be provided for back-deployment. For example, read2 /// and modify2 requirements with early enough availability. bool isRequirementWithSynthesizedDefaultImplementation() const; 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 D = DC->getAsDecl()) return classof(D); return false; } }; inline AccessorDecl * AbstractStorageDecl::AccessorRecord::getAccessor(AccessorKind kind) const { if (auto optIndex = AccessorIndices[unsigned(kind)]) { auto accessor = getAllAccessors()[optIndex - 1]; assert(accessor && accessor->getAccessorKind() == kind); return accessor; } return nullptr; } /// 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; friend class Decl; 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()); } SourceLoc getLocFromSource() const { return CaseLoc; } public: static EnumCaseDecl *create(SourceLoc CaseLoc, ArrayRef Elements, DeclContext *DC); /// Get the list of elements declared in this case. ArrayRef getElements() const { return {getTrailingObjects(), static_cast(Bits.EnumCaseDecl.NumElements)}; } SourceRange getSourceRange() const; /// Returns the first of the member elements or null if there are no elements. /// The attributes written with an EnumCaseDecl will be attached to each of /// the elements instead so inspecting the attributes of the first element is /// often useful. EnumElementDecl *getFirstElement() const { auto elements = getElements(); return elements.empty() ? nullptr : elements.front(); } static bool classof(const Decl *D) { return D->getKind() == DeclKind::EnumCase; } }; /// 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 DeclContext, public ValueDecl { friend class EnumRawValuesRequest; /// 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. ParameterList *Params; SourceLoc EqualsLoc; /// The raw value literal for the enum element, or null. LiteralExpr *RawValueExpr; public: EnumElementDecl(SourceLoc IdentifierLoc, DeclName Name, ParameterList *Params, SourceLoc EqualsLoc, LiteralExpr *RawValueExpr, DeclContext *DC); /// Returns the string for the base name, or "_" if this is unnamed. StringRef getNameStr() const { assert(!getName().isSpecial() && "Cannot get string for special names"); return hasName() ? getBaseIdentifier().str() : "_"; } /// Retrieve the payload type for the enum element, which is a tuple of the /// associated values, or null if there are no associated values. Type getPayloadInterfaceType() const; /// Retrieve the parameters of the implicit case constructor for the enum /// element. ArrayRef getCaseConstructorParams() const; void setParameterList(ParameterList *params); ParameterList *getParameterList() const { return Params; } /// Retrieves a fully typechecked raw value expression associated /// with this enum element, if it exists. LiteralExpr *getRawValueExpr() const; /// Retrieves a "structurally" checked raw value expression associated /// with this enum element, if it exists. /// /// The structural raw value may or may not have a type set, but it is /// guaranteed to be suitable for retrieving any non-semantic information /// like digit text for an integral raw value or user text for a string raw value. LiteralExpr *getStructuralRawValueExpr() const; /// Reset the raw value expression. void setRawValueExpr(LiteralExpr *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; bool hasAssociatedValues() const { return getParameterList() != nullptr; } /// True if the case is marked 'indirect'. bool isIndirect() const { return getAttrs().hasAttribute(); } /// Do not call this! /// It exists to let the AST walkers get the raw value without forcing a request. LiteralExpr *getRawValueUnchecked() const { return RawValueExpr; } static bool classof(const Decl *D) { return D->getKind() == DeclKind::EnumElement; } static bool classof(const DeclContext *DC) { if (auto D = DC->getAsDecl()) return classof(D); return false; } using DeclContext::operator new; using DeclContext::operator delete; using Decl::getASTContext; }; 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 }; /// 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 }; struct BodyInitKindAndExpr { BodyInitKind initKind; ApplyExpr *initExpr; BodyInitKindAndExpr() : initKind(BodyInitKind::None), initExpr(nullptr) {} BodyInitKindAndExpr(BodyInitKind initKind, ApplyExpr *initExpr) : initKind(initKind), initExpr(initExpr) {} friend bool operator==(BodyInitKindAndExpr lhs, BodyInitKindAndExpr rhs) { return (lhs.initKind == rhs.initKind && lhs.initExpr == rhs.initExpr); } }; /// 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; ParamDecl *SelfDecl; /// 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; public: ConstructorDecl(DeclName Name, SourceLoc ConstructorLoc, bool Failable, SourceLoc FailabilityLoc, bool Async, SourceLoc AsyncLoc, bool Throws, SourceLoc ThrowsLoc, TypeLoc thrownTy, ParameterList *BodyParams, GenericParamList *GenericParams, DeclContext *Parent); static ConstructorDecl * createImported(ASTContext &ctx, ClangNode clangNode, DeclName name, SourceLoc constructorLoc, bool failable, SourceLoc failabilityLoc, bool async, SourceLoc asyncLoc, bool throws, SourceLoc throwsLoc, Type thrownTy, ParameterList *bodyParams, GenericParamList *genericParams, DeclContext *parent); SourceLoc getConstructorLoc() const { return getNameLoc(); } SourceLoc getStartLoc() const { return getConstructorLoc(); } SourceRange getSourceRange() const; /// Get the interface type of the constructed object. Type getResultInterfaceType() const; /// Get the interface type of the initializing constructor. Type getInitializerInterfaceType(); /// 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; } ParamDecl **getImplicitSelfDeclStorage() { return &SelfDecl; } /// Determine whether the body of this constructor contains any delegating /// or superclass initializations (\c self.init or \c super.init, /// respectively) within its body. BodyInitKindAndExpr getDelegatingOrChainedInitKind() const; void clearCachedDelegatingOrChainedInitKind(); /// Whether this constructor is required. bool isRequired() const { return getAttrs().hasAttribute(); } /// Determine the kind of initializer this is. CtorInitializerKind getInitKind() const; /// 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 if this is a failable initializer. bool isFailable() const { return Bits.ConstructorDecl.Failable; } /// 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 cast_or_null( AbstractFunctionDecl::getOverriddenDecl()); } /// 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 D = DC->getAsDecl()) return classof(D); 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 { ParamDecl *SelfDecl; public: DestructorDecl(SourceLoc DestructorLoc, DeclContext *Parent); ParamDecl **getImplicitSelfDeclStorage() { return &SelfDecl; } SourceLoc getDestructorLoc() const { return getNameLoc(); } SourceLoc getStartLoc() const { return getDestructorLoc(); } SourceRange getSourceRange() const; /// Retrieve the Objective-C selector for destructors. ObjCSelector getObjCSelector() const; /// Retrieves destructor decl from the superclass, or nil if there is no /// superclass DestructorDecl *getSuperDeinit() 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 D = DC->getAsDecl()) return classof(D); 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); friend class Decl; SourceLoc getLocFromSource() const { return NameLoc; } 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); 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; } // This is needed to allow templated code to work with both ValueDecls and // PrecedenceGroupDecls. DeclBaseName getBaseName() 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; } /// Retrieve the array of \c Relation objects containing those precedence /// groups with higher precedence than this precedence group. /// /// The elements of this array may be invalid, in which case they will have /// null \c PrecedenceGroupDecl elements. 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; } /// Retrieve the array of \c Relation objects containing those precedence /// groups with lower precedence than this precedence group. /// /// The elements of this array may be invalid, in which case they will have /// null \c PrecedenceGroupDecl elements. ArrayRef getLowerThan() const { return { getLowerThanBuffer(), NumLowerThan }; } MutableArrayRef getMutableLowerThan() { return { getLowerThanBuffer(), NumLowerThan }; } static bool classof(const Decl *D) { return D->getKind() == DeclKind::PrecedenceGroup; } }; /// The fixity of an OperatorDecl. enum class OperatorFixity : uint8_t { Infix, Prefix, Postfix }; inline void simple_display(llvm::raw_ostream &out, OperatorFixity fixity) { switch (fixity) { case OperatorFixity::Infix: out << "infix"; return; case OperatorFixity::Prefix: out << "prefix"; return; case OperatorFixity::Postfix: out << "postfix"; return; } llvm_unreachable("Unhandled case in switch"); } /// Abstract base class of operator declarations. class OperatorDecl : public Decl { SourceLoc OperatorLoc, NameLoc; Identifier name; SourceLoc getLocFromSource() const { return NameLoc; } friend class Decl; public: OperatorDecl(DeclKind kind, DeclContext *DC, SourceLoc OperatorLoc, Identifier Name, SourceLoc NameLoc) : Decl(kind, DC), OperatorLoc(OperatorLoc), NameLoc(NameLoc), name(Name) {} /// Retrieve the operator's fixity, corresponding to the concrete subclass /// of the OperatorDecl. OperatorFixity getFixity() const { switch (getKind()) { #define DECL(Id, Name) case DeclKind::Id: llvm_unreachable("Not an operator!"); #define OPERATOR_DECL(Id, Name) #include "swift/AST/DeclNodes.def" case DeclKind::InfixOperator: return OperatorFixity::Infix; case DeclKind::PrefixOperator: return OperatorFixity::Prefix; case DeclKind::PostfixOperator: return OperatorFixity::Postfix; } llvm_unreachable("invalid decl kind"); } SourceLoc getOperatorLoc() const { return OperatorLoc; } SourceLoc getNameLoc() const { return NameLoc; } Identifier getName() const { return name; } // This is needed to allow templated code to work with both ValueDecls and // OperatorDecls. DeclBaseName getBaseName() 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 /+/ : AdditionPrecedence, Numeric /// \endcode class InfixOperatorDecl : public OperatorDecl { SourceLoc ColonLoc, PrecedenceGroupLoc; Identifier PrecedenceGroupName; public: InfixOperatorDecl(DeclContext *DC, SourceLoc operatorLoc, Identifier name, SourceLoc nameLoc, SourceLoc colonLoc, Identifier precedenceGroupName, SourceLoc precedenceGroupLoc) : OperatorDecl(DeclKind::InfixOperator, DC, operatorLoc, name, nameLoc), ColonLoc(colonLoc), PrecedenceGroupLoc(precedenceGroupLoc), PrecedenceGroupName(precedenceGroupName) {} SourceLoc getEndLoc() const { if (getPrecedenceGroupLoc().isValid()) return getPrecedenceGroupLoc(); return getNameLoc(); } SourceRange getSourceRange() const { return { getOperatorLoc(), getEndLoc() }; } SourceLoc getColonLoc() const { return ColonLoc; } Identifier getPrecedenceGroupName() const { return PrecedenceGroupName; } SourceLoc getPrecedenceGroupLoc() const { return PrecedenceGroupLoc; } PrecedenceGroupDecl *getPrecedenceGroup() const; 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() }; } 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() }; } static bool classof(const Decl *D) { return D->getKind() == DeclKind::PostfixOperator; } }; class MacroExpansionDecl; /// Represents a missing declaration in the source code. /// /// This is used for parser recovery, e.g. when parsing a floating /// attribute list, and to represent placeholders for unexpanded /// declarations generated by macros. class MissingDecl : public Decl { /// If this missing decl represents an unexpanded peer generated by a macro, /// \c unexpandedMacro contains the macro reference and the base declaration /// where the macro expansion applies. struct { llvm::PointerUnion macroRef; Decl *baseDecl; } unexpandedMacro; /// The location that the decl would be if it wasn't missing. SourceLoc Loc; MissingDecl(DeclContext *DC, SourceLoc loc) : Decl(DeclKind::Missing, DC), Loc(loc) { setImplicit(); } friend class Decl; SourceLoc getLocFromSource() const { return Loc; } public: static MissingDecl *create(ASTContext &ctx, DeclContext *DC, SourceLoc loc) { return new (ctx) MissingDecl(DC, loc); } SourceRange getSourceRange() const { return SourceRange(Loc); } static MissingDecl * forUnexpandedMacro( llvm::PointerUnion macroRef, Decl *baseDecl) { auto &ctx = baseDecl->getASTContext(); auto *dc = baseDecl->getDeclContext(); auto *missing = new (ctx) MissingDecl(dc, SourceLoc()); missing->unexpandedMacro.macroRef = macroRef; missing->unexpandedMacro.baseDecl = baseDecl; return missing; } using MacroExpandedDeclCallback = llvm::function_ref; void forEachMacroExpandedDecl(MacroExpandedDeclCallback callback); static bool classof(const Decl *D) { return D->getKind() == DeclKind::Missing; } }; /// 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(); } friend class Decl; SourceLoc getLocFromSource() const { return SourceLoc(); } public: static MissingMemberDecl * create(ASTContext &ctx, DeclContext *DC, DeclName name, unsigned numVTableEntries, bool hasStorage) { assert(!numVTableEntries || isa(DC) || isa(DC) && "Only classes and protocols have vtable/witness table entries"); assert(!hasStorage || !isa(DC) && "Protocols cannot have missing stored properties"); return new (ctx) MissingMemberDecl(DC, name, numVTableEntries, hasStorage); } DeclName getName() const { return Name; } unsigned getNumberOfVTableEntries() const { return Bits.MissingMemberDecl.NumberOfVTableEntries; } unsigned getNumberOfFieldOffsetVectorEntries() const { return Bits.MissingMemberDecl.NumberOfFieldOffsetVectorEntries; } SourceRange getSourceRange() const { return SourceRange(); } static bool classof(const Decl *D) { return D->getKind() == DeclKind::MissingMember; } }; /// Provides a declaration of a macro. /// /// Macros are declared within the source code with the `macro` introducer. /// /// Macros are defined externally via conformances to the 'Macro' type /// that is part of swift-syntax, and are introduced into the compiler via /// various mechanisms (e.g., in-process macros provided as builtins or /// loaded via shared library, and so on). class MacroDecl : public GenericContext, public ValueDecl { public: /// The location of the 'macro' keyword. SourceLoc macroLoc; /// The parameter list. ParameterList *parameterList; /// Where the '->' is located, if present. SourceLoc arrowLoc; /// The result type. TypeLoc resultType; /// The macro definition, which should always be a /// \c MacroExpansionExpr in well-formed code. Expr *definition; MacroDecl(SourceLoc macroLoc, DeclName name, SourceLoc nameLoc, GenericParamList *genericParams, ParameterList *parameterList, SourceLoc arrowLoc, TypeRepr *resultType, Expr *definition, DeclContext *parent); SourceRange getSourceRange() const; /// Retrieve the interface type produced when expanding this macro. Type getResultInterfaceType() const; /// Returns the result interface type of this macro if it has already been /// computed, otherwise `nullopt`. This should only be used for dumping. std::optional getCachedResultInterfaceType() const; /// Determine the contexts in which this macro can be applied. MacroRoles getMacroRoles() const; /// Retrieve the attribute that declared the given macro role. const MacroRoleAttr *getMacroRoleAttr(MacroRole role) const; /// Populate the \c names vector with the decl names introduced /// by a given role of this macro. void getIntroducedNames(MacroRole role, ValueDecl *attachedTo, SmallVectorImpl &names) const; /// Populate the \c conformances vector with the protocols that /// this macro generates conformances to. /// /// Only extension macros can add conformances; no results will /// be added if this macro does not contain an extension role. void getIntroducedConformances( NominalTypeDecl *attachedTo, MacroRole role, SmallVectorImpl &conformances) const; /// Returns a DeclName that represents arbitrary names. static DeclName getArbitraryName() { return DeclName(); } /// Returns a DeclName that acts as a stand-in for all unique names that /// are manufactured by the macro expansion context's `makeUniqueName`. static DeclName getUniqueNamePlaceholder(ASTContext &ctx); /// Determine whether the given name is the unique-name placeholder /// produced by `getUniqueNamePlaceholder`. static bool isUniqueNamePlaceholder(DeclName name); /// Determine whether the given name is one of the unique names manufactured /// by the macro expansion context's `makeUniqueName`. static bool isUniqueMacroName(StringRef name); /// Determine whether the given name is one of the unique names manufactured /// by the macro expansion context's `makeUniqueName`. static bool isUniqueMacroName(DeclBaseName name); /// Retrieve the definition of this macro. MacroDefinition getDefinition() const; /// Set the definition of this macro void setDefinition(MacroDefinition definition); /// Retrieve the parameter list of this macro. ParameterList *getParameterList() const { return parameterList; } /// Retrieve the builtin macro kind for this macro, or \c None if it is a /// user-defined macro with no special semantics. std::optional getBuiltinKind() const; static bool classof(const DeclContext *C) { if (auto D = C->getAsDecl()) return classof(D); return false; } static bool classof(const Decl *D) { return D->getKind() == DeclKind::Macro; } using DeclContext::operator new; using DeclContext::operator delete; using Decl::getASTContext; }; class MacroExpansionDecl : public Decl, public FreestandingMacroExpansion { public: MacroExpansionDecl(DeclContext *dc, MacroExpansionInfo *info); static MacroExpansionDecl *create(DeclContext *dc, SourceLoc poundLoc, DeclNameRef macro, DeclNameLoc macroLoc, SourceLoc leftAngleLoc, ArrayRef genericArgs, SourceLoc rightAngleLoc, ArgumentList *args); DeclContext *getDeclContext() const { return Decl::getDeclContext(); } SourceRange getSourceRange() const { return getExpansionInfo()->getSourceRange(); } SourceLoc getLocFromSource() const { return getExpansionInfo()->SigilLoc; } /// Enumerate the nodes produced by expanding this macro expansion. void forEachExpandedNode(llvm::function_ref callback) const; static bool classof(const Decl *D) { return D->getKind() == DeclKind::MacroExpansion; } static bool classof(const FreestandingMacroExpansion *expansion) { return expansion->getFreestandingMacroKind() == FreestandingMacroKind::Decl; } }; inline void AbstractStorageDecl::overwriteSetterAccess(AccessLevel accessLevel) { Accessors.setInt(accessLevel); if (auto setter = getAccessor(AccessorKind::Set)) setter->overwriteAccess(accessLevel); if (auto modify = getAccessor(AccessorKind::Modify)) modify->overwriteAccess(accessLevel); if (auto mutableAddressor = getAccessor(AccessorKind::MutableAddress)) mutableAddressor->overwriteAccess(accessLevel); } /// Constructors and destructors always have a 'self' parameter, /// which is stored in an instance member. Functions only have a /// 'self' if they are declared inside of a nominal type or extension, /// in which case we tail-allocate storage for it. inline ParamDecl **AbstractFunctionDecl::getImplicitSelfDeclStorage() { switch (getKind()) { default: llvm_unreachable("Unknown AbstractFunctionDecl!"); case DeclKind::Constructor: return cast(this)->getImplicitSelfDeclStorage(); case DeclKind::Destructor: return cast(this)->getImplicitSelfDeclStorage(); case DeclKind::Func: case DeclKind::Accessor: return cast(this)->getImplicitSelfDeclStorage(); } } inline ParamDecl **FuncDecl::getImplicitSelfDeclStorage() { if (!hasImplicitSelfDecl()) return nullptr; if (!isa(this)) { assert(getKind() == DeclKind::Func && "no new kinds of functions"); return reinterpret_cast(this+1); } return reinterpret_cast(static_cast(this)+1); } 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 ValueDecl::hasCurriedSelf() const { if (auto *afd = dyn_cast(this)) return afd->hasImplicitSelfDecl(); if (isa(this)) return true; return false; } inline unsigned ValueDecl::getNumCurryLevels() const { unsigned curryLevels = 0; if (hasParameterList()) curryLevels++; if (hasCurriedSelf()) curryLevels++; return curryLevels; } inline bool Decl::isSyntacticallyOverridable() const { if (isa(this) || isa(this) || isa(this) || isa(this)) { if (static_cast(this)->isFinal()) { return false; } auto classDecl = getDeclContext()->getSelfClassDecl(); return classDecl && !classDecl->isActor() && !classDecl->isFinal(); } else { return false; } } inline GenericParamKey::GenericParamKey(const GenericTypeParamDecl *d) : ParameterPack(d->isParameterPack()), 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 bool GenericContext::classof(const Decl *D) { switch (D->getKind()) { // default: return false; #define DECL(ID, PARENT) // See previous line #define GENERIC_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; } /// Retrieve the parameter list for a given declaration context, or nullptr if /// there is none. ParameterList *getParameterList(DeclContext *source); /// Retrieve parameter declaration from the given source at given index, or /// nullptr if the source does not have a parameter list. const ParamDecl *getParameterAt(ConcreteDeclRef declRef, unsigned index); /// Retrieve parameter declaration from the given source at given index, or /// nullptr if the source does not have a parameter list. const ParamDecl *getParameterAt(const ValueDecl *source, unsigned index); /// Retrieve parameter declaration from the given source at given index, or /// nullptr if the source does not have a parameter list. const ParamDecl *getParameterAt(const DeclContext *source, unsigned index); class ABIRole { public: enum Value : uint8_t { Neither = 0, ProvidesABI = 1 << 0, ProvidesAPI = 1 << 1, Either = ProvidesABI | ProvidesAPI, }; Value value; ABIRole(Value value) : value(value) { } ABIRole() : ABIRole(Neither) { } explicit ABIRole(NLOptions opts); template explicit ABIRole(OptionSet flags) : value(flags.contains(FlagType::ABIProviding) ? ProvidesABI : ProvidesAPI) { } inline ABIRole operator|(ABIRole rhs) const { return ABIRole(ABIRole::Value(value | rhs.value)); } inline ABIRole &operator|=(ABIRole rhs) { value = ABIRole::Value(value | rhs.value); return *this; } inline ABIRole operator&(ABIRole rhs) const { return ABIRole(ABIRole::Value(value & rhs.value)); } inline ABIRole &operator&=(ABIRole rhs) { value = ABIRole::Value(value & rhs.value); return *this; } inline ABIRole operator~() const { return ABIRole(ABIRole::Value(~value)); } operator bool() const { return value != Neither; } }; namespace abi_role_detail { using Storage = llvm::PointerIntPair; Storage computeStorage(Decl *decl); } /// Specifies the \c ABIAttr -related behavior of this declaration /// and provides access to its counterpart. /// /// A given declaration may provide the API, the ABI, or both. If it provides /// API, the counterpart is the matching ABI-providing decl; if it provides /// ABI, the countepart is the matching API-providing decl. A declaration /// which provides both API and ABI is its own counterpart. /// /// If the counterpart is \c nullptr , this indicates a fundamental mismatch /// between decl and counterpart. Sometimes this mismatch is a difference in /// decl kind; in these cases, \c getCounterpartUnchecked() will return the /// incorrect counterpart. template class ABIRoleInfo { friend abi_role_detail::Storage abi_role_detail::computeStorage(Decl *); abi_role_detail::Storage counterpartAndFlags; ABIRoleInfo(abi_role_detail::Storage storage) : counterpartAndFlags(storage) { } public: explicit ABIRoleInfo(const SpecificDecl *decl) : ABIRoleInfo(abi_role_detail::computeStorage(const_cast(decl))) { } Decl *getCounterpartUnchecked() const { return counterpartAndFlags.getPointer(); } SpecificDecl *getCounterpart() const { return dyn_cast_or_null(getCounterpartUnchecked()); } ABIRole getRole() const { return ABIRole(ABIRole::Value(counterpartAndFlags.getInt())); } bool matches(ABIRole desiredRole) const { return getRole() & desiredRole; } template bool matchesOptions(Options opts) const { return matches(ABIRole(opts)); } bool providesABI() const { return matches(ABIRole::ProvidesABI); } bool providesAPI() const { return matches(ABIRole::ProvidesAPI); } bool hasABIAttr() const { return !providesABI(); } }; template ABIRoleInfo(const SpecificDecl *decl) -> ABIRoleInfo; StringRef getAccessorNameForDiagnostic(AccessorDecl *accessor, bool article, std::optional underscored = std::nullopt); StringRef getAccessorNameForDiagnostic(AccessorKind accessorKind, bool article, bool underscored); void simple_display(llvm::raw_ostream &out, OptionSet options); /// Display Decl subclasses. void simple_display(llvm::raw_ostream &out, const Decl *decl); /// Display ValueDecl subclasses. void simple_display(llvm::raw_ostream &out, const ValueDecl *decl); /// Display ExtensionDecls. inline void simple_display(llvm::raw_ostream &out, const ExtensionDecl *decl) { simple_display(out, static_cast(decl)); } /// Display NominalTypeDecls. inline void simple_display(llvm::raw_ostream &out, const NominalTypeDecl *decl) { simple_display(out, static_cast(decl)); } inline void simple_display(llvm::raw_ostream &out, const AssociatedTypeDecl *decl) { simple_display(out, static_cast(decl)); } /// Display GenericContext. /// /// The template keeps this sorted down in the overload set relative to the /// more concrete overloads with Decl pointers thereby breaking a potential ambiguity. template inline typename std::enable_if::value>::type simple_display(llvm::raw_ostream &out, const T *GC) { simple_display(out, GC->getAsDecl()); } /// Display GenericParamList. void simple_display(llvm::raw_ostream &out, const GenericParamList *GPL); /// Extract the source location from the given declaration. SourceLoc extractNearestSourceLoc(const Decl *decl); /// Extract the source location from the given declaration. inline SourceLoc extractNearestSourceLoc(const ExtensionDecl *ext) { return extractNearestSourceLoc(static_cast(ext)); } /// Extract the source location from the given declaration. inline SourceLoc extractNearestSourceLoc(const GenericTypeDecl *type) { return extractNearestSourceLoc(static_cast(type)); } /// Extract the source location from the given declaration. inline SourceLoc extractNearestSourceLoc(const NominalTypeDecl *type) { return extractNearestSourceLoc(static_cast(type)); } /// Extract the source location from the given declaration. inline SourceLoc extractNearestSourceLoc(const AbstractFunctionDecl *func) { return extractNearestSourceLoc(static_cast(func)); } } // end namespace swift #endif