| //===--- 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/CaptureInfo.h" |
| #include "swift/AST/ClangNode.h" |
| #include "swift/AST/ConcreteDeclRef.h" |
| #include "swift/AST/DefaultArgumentKind.h" |
| #include "swift/AST/DiagnosticConsumer.h" |
| #include "swift/AST/DiagnosticEngine.h" |
| #include "swift/AST/GenericParamKey.h" |
| #include "swift/AST/IfConfigClause.h" |
| #include "swift/AST/LayoutConstraint.h" |
| #include "swift/AST/StorageImpl.h" |
| #include "swift/AST/TypeAlignments.h" |
| #include "swift/AST/TypeWalker.h" |
| #include "swift/AST/Types.h" |
| #include "swift/AST/Witness.h" |
| #include "swift/Basic/ArrayRefView.h" |
| #include "swift/Basic/Compiler.h" |
| #include "swift/Basic/Debug.h" |
| #include "swift/Basic/InlineBitfield.h" |
| #include "swift/Basic/NullablePtr.h" |
| #include "swift/Basic/OptionalEnum.h" |
| #include "swift/Basic/Range.h" |
| #include "swift/Basic/Located.h" |
| #include "llvm/ADT/DenseSet.h" |
| #include "llvm/Support/TrailingObjects.h" |
| #include <type_traits> |
| |
| namespace swift { |
| enum class AccessSemantics : unsigned char; |
| class AccessorDecl; |
| class ApplyExpr; |
| class AvailabilityContext; |
| class GenericEnvironment; |
| class ArchetypeType; |
| class ASTContext; |
| struct ASTNode; |
| class ASTPrinter; |
| class ASTWalker; |
| class ConstructorDecl; |
| class DestructorDecl; |
| class DiagnosticEngine; |
| class DynamicSelfType; |
| class Type; |
| class Expr; |
| class CaptureListExpr; |
| class DeclRefExpr; |
| class ForeignAsyncConvention; |
| class ForeignErrorConvention; |
| class LiteralExpr; |
| class BraceStmt; |
| class DeclAttributes; |
| class GenericContext; |
| class GenericParamList; |
| class GenericSignature; |
| class GenericTypeParamDecl; |
| class GenericTypeParamType; |
| class ModuleDecl; |
| class NamedPattern; |
| class EnumCaseDecl; |
| class EnumElementDecl; |
| class ParameterList; |
| class ParameterTypeFlags; |
| class Pattern; |
| struct PrintOptions; |
| struct PropertyWrapperBackingPropertyInfo; |
| struct PropertyWrapperTypeInfo; |
| struct PropertyWrapperMutability; |
| class ProtocolDecl; |
| class ProtocolType; |
| struct RawComment; |
| enum class ResilienceExpansion : unsigned; |
| class TrailingWhereClause; |
| class TypeAliasDecl; |
| class Stmt; |
| class SubscriptDecl; |
| class UnboundGenericType; |
| class ValueDecl; |
| class VarDecl; |
| class OpaqueReturnTypeRepr; |
| |
| namespace ast_scope { |
| class AbstractPatternEntryScope; |
| 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<unsigned>(DeclKind::Last_Decl)) }; |
| |
| |
| /// Fine-grained declaration kind that provides a description of the |
| /// kind of entity a declaration represents, as it would be used in |
| /// diagnostics. |
| /// |
| /// For example, \c FuncDecl is a single declaration class, but it has |
| /// several descriptive entries depending on whether it is an |
| /// operator, global function, local function, method, (observing) |
| /// accessor, etc. |
| enum class DescriptiveDeclKind : uint8_t { |
| Import, |
| Extension, |
| EnumCase, |
| TopLevelCode, |
| IfConfig, |
| PoundDiagnostic, |
| PatternBinding, |
| Var, |
| Param, |
| Let, |
| Property, |
| StaticProperty, |
| ClassProperty, |
| InfixOperator, |
| PrefixOperator, |
| PostfixOperator, |
| PrecedenceGroup, |
| TypeAlias, |
| GenericTypeParam, |
| AssociatedType, |
| Type, |
| Enum, |
| Struct, |
| Class, |
| Protocol, |
| GenericEnum, |
| GenericStruct, |
| GenericClass, |
| GenericType, |
| Subscript, |
| StaticSubscript, |
| ClassSubscript, |
| Constructor, |
| Destructor, |
| LocalFunction, |
| GlobalFunction, |
| OperatorFunction, |
| Method, |
| StaticMethod, |
| ClassMethod, |
| Getter, |
| Setter, |
| Addressor, |
| MutableAddressor, |
| ReadAccessor, |
| ModifyAccessor, |
| WillSet, |
| DidSet, |
| EnumElement, |
| Module, |
| MissingMember, |
| Requirement, |
| OpaqueResultType, |
| OpaqueVarType |
| }; |
| |
| /// 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, |
| }; |
| |
| /// Diagnostic printing of \c StaticSpellingKind. |
| llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, StaticSpellingKind SSK); |
| |
| /// Encapsulation of the overload signature of a given declaration, |
| /// which is used to determine uniqueness of a declaration within a |
| /// given context. |
| /// |
| /// Two definitions in the same context may not have the same overload |
| /// signature. |
| struct OverloadSignature { |
| /// The full name of the declaration. |
| DeclName Name; |
| |
| /// The kind of unary operator. |
| UnaryOperatorKind UnaryOperator; |
| |
| /// 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 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 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), 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 { |
| protected: |
| union { uint64_t OpaqueBits; |
| |
| SWIFT_INLINE_BITFIELD_BASE(Decl, bitmax(NumDeclKindBits,8)+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 was added to the surrounding |
| /// DeclContext of an active #if config clause. |
| EscapedFromIfConfig : 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 |
| ); |
| |
| SWIFT_INLINE_BITFIELD_FULL(PatternBindingDecl, Decl, 1+2+16, |
| /// Whether this pattern binding declares static variables. |
| IsStatic : 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, |
| AlreadyInLookupTable : 1, |
| |
| /// Whether we have already checked whether this declaration is a |
| /// redeclaration. |
| CheckedRedeclaration : 1, |
| |
| /// Whether the decl can be accessed by swift users; for instance, |
| /// a.storage for lazy var a is a decl that cannot be accessed. |
| IsUserAccessible : 1 |
| ); |
| |
| SWIFT_INLINE_BITFIELD(AbstractStorageDecl, ValueDecl, 1, |
| /// Whether this property is a type property (currently unfortunately |
| /// called 'static'). |
| IsStatic : 1 |
| ); |
| |
| SWIFT_INLINE_BITFIELD(VarDecl, AbstractStorageDecl, 1+1+1+1+1+1, |
| /// Encodes whether this is a 'let' binding. |
| Introducer : 1, |
| |
| /// 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 |
| ); |
| |
| SWIFT_INLINE_BITFIELD(ParamDecl, VarDecl, 1+2+NumDefaultArgumentKindBits, |
| /// Whether we've computed the specifier yet. |
| SpecifierComputed : 1, |
| |
| /// The specifier associated with this parameter. This determines |
| /// the storage semantics of the value e.g. mutability. |
| Specifier : 2, |
| |
| /// Information about a symbolic default argument, like #file. |
| defaultArgumentKind : NumDefaultArgumentKindBits |
| ); |
| |
| SWIFT_INLINE_BITFIELD(SubscriptDecl, VarDecl, 2, |
| StaticSpelling : 2 |
| ); |
| SWIFT_INLINE_BITFIELD(AbstractFunctionDecl, ValueDecl, 3+8+1+1+1+1+1+1+1, |
| /// \see AbstractFunctionDecl::BodyKind |
| BodyKind : 3, |
| |
| /// 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 this member was synthesized as part of a derived |
| /// protocol conformance. |
| Synthesized : 1, |
| |
| /// Whether this member's body consists of a single expression. |
| HasSingleExpressionBody : 1, |
| |
| /// Whether peeking into this function detected nested type declarations. |
| /// This is set when skipping over the decl at parsing. |
| HasNestedTypeDeclarations : 1 |
| ); |
| |
| SWIFT_INLINE_BITFIELD(FuncDecl, AbstractFunctionDecl, 1+1+2+1+1+2+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 : 2, |
| |
| /// 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 |
| ); |
| |
| 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_EMPTY(AbstractTypeParamDecl, TypeDecl); |
| |
| SWIFT_INLINE_BITFIELD_FULL(GenericTypeParamDecl, AbstractTypeParamDecl, 16+16, |
| : NumPadBits, |
| |
| Depth : 16, |
| Index : 16 |
| ); |
| |
| SWIFT_INLINE_BITFIELD_EMPTY(GenericTypeDecl, TypeDecl); |
| |
| SWIFT_INLINE_BITFIELD(TypeAliasDecl, GenericTypeDecl, 1+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+8+16, |
| /// Whether the \c RequiresClass bit is valid. |
| RequiresClassValid : 1, |
| |
| /// Whether this is a class-bounded protocol. |
| RequiresClass : 1, |
| |
| /// Whether the \c ExistentialConformsToSelf bit is valid. |
| ExistentialConformsToSelfValid : 1, |
| |
| /// Whether the existential of this protocol conforms to itself. |
| ExistentialConformsToSelf : 1, |
| |
| /// Whether the \c ExistentialTypeSupported bit is valid. |
| ExistentialTypeSupportedValid : 1, |
| |
| /// Whether the existential of this protocol can be represented. |
| ExistentialTypeSupported : 1, |
| |
| /// True if the protocol has requirements that cannot be satisfied (e.g. |
| /// because they could not be imported from Objective-C). |
| HasMissingRequirements : 1, |
| |
| /// Whether we've computed the inherited protocols list yet. |
| InheritedProtocolsValid : 1, |
| |
| /// Whether we have a lazy-loaded requirement signature. |
| HasLazyRequirementSignature : 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. |
| |
| /// The number of requirements in the requirement signature. |
| NumRequirementsInSignature : 16 |
| ); |
| |
| SWIFT_INLINE_BITFIELD(ClassDecl, NominalTypeDecl, 1+1+2+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 |
| ); |
| |
| SWIFT_INLINE_BITFIELD( |
| StructDecl, NominalTypeDecl, 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); |
| |
| SWIFT_INLINE_BITFIELD(EnumDecl, NominalTypeDecl, 2+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 |
| ); |
| |
| SWIFT_INLINE_BITFIELD(ModuleDecl, TypeDecl, 1+1+1+1+1+1+1+1+1+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 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 |
| ); |
| |
| 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, 3+1, |
| /// An encoding of the default and maximum access level for this extension. |
| /// |
| /// This is encoded as (1 << (maxAccess-1)) | (1 << (defaultAccess-1)), |
| /// which works because the maximum is always greater than or equal to the |
| /// default, and 'private' is never used. 0 represents an uncomputed value. |
| DefaultAndMaxAccessLevel : 3, |
| |
| /// Whether there is are lazily-loaded conformances for this extension. |
| HasLazyConformances : 1 |
| ); |
| |
| SWIFT_INLINE_BITFIELD(IfConfigDecl, Decl, 1, |
| /// Whether this decl is missing its closing '#endif'. |
| HadMissingEnd : 1 |
| ); |
| |
| SWIFT_INLINE_BITFIELD(PoundDiagnosticDecl, Decl, 1+1, |
| /// `true` if the diagnostic is an error, `false` if it's a warning. |
| IsError : 1, |
| |
| /// Whether this diagnostic has already been emitted. |
| HasBeenEmitted : 1 |
| ); |
| |
| SWIFT_INLINE_BITFIELD(MissingMemberDecl, Decl, 1+2, |
| NumberOfFieldOffsetVectorEntries : 1, |
| NumberOfVTableEntries : 2 |
| ); |
| |
| } Bits; |
| |
| // Storage for the declaration attributes. |
| DeclAttributes Attrs; |
| |
| /// The next declaration in the list of declarations within this |
| /// member context. |
| Decl *NextDecl = nullptr; |
| |
| friend class DeclIterator; |
| friend class IterableDeclContext; |
| friend class MemberLookupTable; |
| |
| private: |
| llvm::PointerUnion<DeclContext *, ASTContext *> Context; |
| |
| Decl(const Decl&) = delete; |
| void operator=(const Decl&) = delete; |
| SourceLoc getLocFromSource() const; |
| |
| struct CachedExternalSourceLocs { |
| SourceLoc Loc; |
| SourceLoc StartLoc; |
| SourceLoc EndLoc; |
| SmallVector<CharSourceRange, 4> DocRanges; |
| }; |
| mutable CachedExternalSourceLocs const *CachedSerializedLocs = nullptr; |
| const CachedExternalSourceLocs *getSerializedLocs() const; |
| protected: |
| |
| Decl(DeclKind kind, llvm::PointerUnion<DeclContext *, ASTContext *> context) |
| : Context(context) { |
| Bits.OpaqueBits = 0; |
| Bits.Decl.Kind = unsigned(kind); |
| Bits.Decl.Invalid = false; |
| Bits.Decl.Implicit = false; |
| Bits.Decl.FromClang = false; |
| Bits.Decl.EscapedFromIfConfig = false; |
| Bits.Decl.Hoisted = 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<DeclContext *>()) |
| 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; |
| |
| /// getASTContext - Return the ASTContext that this decl lives in. |
| LLVM_READONLY |
| ASTContext &getASTContext() const { |
| if (auto dc = Context.dyn_cast<DeclContext *>()) |
| return dc->getASTContext(); |
| |
| return *Context.get<ASTContext *>(); |
| } |
| |
| const DeclAttributes &getAttrs() const { |
| return Attrs; |
| } |
| |
| DeclAttributes &getAttrs() { |
| return Attrs; |
| } |
| |
| /// 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. |
| Optional<llvm::VersionTuple> getIntroducedOSVersion(PlatformKind Kind) 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; |
| |
| SourceLoc TrailingSemiLoc; |
| |
| /// 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; |
| |
| /// 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; } |
| |
| public: |
| bool escapedFromIfConfig() const { |
| return Bits.Decl.EscapedFromIfConfig; |
| } |
| |
| void setEscapedFromIfConfig(bool Escaped) { |
| Bits.Decl.EscapedFromIfConfig = Escaped; |
| } |
| |
| /// \returns the unparsed comment attached to this declaration. |
| RawComment getRawComment(bool SerializedOK = false) const; |
| |
| Optional<StringRef> getGroupName() const; |
| |
| Optional<StringRef> getSourceFileName() const; |
| |
| Optional<unsigned> getSourceOrder() const; |
| |
| /// \returns the brief comment attached to this declaration. |
| StringRef getBriefComment() 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(); |
| } |
| |
| /// Return the GenericContext if the Decl has one. |
| LLVM_READONLY |
| const GenericContext *getAsGenericContext() const; |
| |
| bool hasUnderscoredNaming() const; |
| |
| bool isPrivateStdlibDecl(bool treatNonBuiltinProtocolsAsPublic = true) const; |
| |
| /// Check if this is a declaration defined at the top level of the Swift module |
| bool isStdlibDecl() const; |
| |
| AvailabilityContext 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. |
| /// Note that this does not consider whether it is final or whether |
| /// the class it's on is final. |
| /// |
| /// If this returns true, the decl can be safely casted to ValueDecl. |
| bool isPotentiallyOverridable() const; |
| |
| /// 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. |
| Optional<std::pair<CustomAttr *, NominalTypeDecl *>> |
| getGlobalActorAttr() 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; |
| |
| // 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<Identifier> getSPIGroups() const; |
| |
| /// Emit a diagnostic tied to this declaration. |
| template<typename ...ArgTypes> |
| InFlightDiagnostic diagnose( |
| Diag<ArgTypes...> ID, |
| typename detail::PassArgument<ArgTypes>::type... Args) const { |
| return getDiags().diagnose(this, ID, std::move(Args)...); |
| } |
| |
| /// Retrieve the diagnostic engine for diagnostics emission. |
| LLVM_READONLY |
| DiagnosticEngine &getDiags() const; |
| |
| // Make vanilla new/delete illegal for Decls. |
| void *operator new(size_t Bytes) = delete; |
| void operator delete(void *Data) = delete; |
| |
| // Only allow allocation of Decls using the allocator in ASTContext |
| // or by doing a placement new. |
| void *operator new(size_t Bytes, const ASTContext &C, |
| unsigned Alignment = alignof(Decl)); |
| void *operator new(size_t Bytes, void *Mem) { |
| assert(Mem); |
| return Mem; |
| } |
| }; |
| |
| /// 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 <typename DeclTy, typename AllocatorTy> |
| 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<char *>(mem) + alignof(DeclTy); |
| return mem; |
| } |
| |
| // A private class for forcing exact field layout. |
| class alignas(8) _GenericContext { |
| // Not really public. See GenericContext. |
| public: |
| llvm::PointerIntPair<GenericParamList *, 1, bool> GenericParamsAndBit; |
| |
| /// 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<GenericSignature, 1, bool> 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<T> { |
| /// func f1() {} // isGeneric == false |
| /// func f2<T>() {} // 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. |
| TypeArrayView<GenericTypeParamType> getInnermostGenericParamTypes() const; |
| |
| /// Retrieve the generic requirements. |
| ArrayRef<Requirement> 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_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<ImportDecl, ImportPath::Element> { |
| friend TrailingObjects; |
| friend class Decl; |
| |
| SourceLoc ImportLoc; |
| SourceLoc KindLoc; |
| |
| /// 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 Optional<ImportKind> findBestImportKind(ArrayRef<ValueDecl *> Decls); |
| |
| ImportKind getImportKind() const { |
| return static_cast<ImportKind>(Bits.ImportDecl.ImportKind); |
| } |
| |
| ImportPath getImportPath() const { |
| return ImportPath({ getTrailingObjects<ImportPath::Element>(), |
| static_cast<size_t>(Bits.ImportDecl.NumPathElements) }); |
| } |
| |
| ImportPath::Module getModulePath() const { |
| return getImportPath().getModulePath(getImportKind()); |
| } |
| |
| ImportPath::Access getAccessPath() const { |
| return getImportPath().getAccessPath(getImportKind()); |
| } |
| |
| bool isExported() const { |
| return getAttrs().hasAttribute<ExportedAttr>(); |
| } |
| |
| 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<ValueDecl *> getDecls() 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; |
| } |
| }; |
| |
| /// 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<NominalTypeDecl *, 1, bool> ExtendedNominal; |
| |
| ArrayRef<TypeLoc> 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<ExtensionDecl *, 1, bool> NextExtension |
| = {nullptr, false}; |
| |
| /// Note that we have added a member into the iterable declaration context. |
| void addedMember(Decl *member); |
| |
| friend class ExtensionIterator; |
| friend class NominalTypeDecl; |
| friend class MemberLookupTable; |
| friend class ConformanceLookupTable; |
| friend class IterableDeclContext; |
| |
| ExtensionDecl(SourceLoc extensionLoc, TypeRepr *extendedType, |
| ArrayRef<TypeLoc> 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<LazyMemberLoader *, uint64_t> takeConformanceLoader() { |
| if (!Bits.ExtensionDecl.HasLazyConformances) |
| return { nullptr, 0 }; |
| |
| return takeConformanceLoaderSlow(); |
| } |
| |
| /// Slow path for \c takeConformanceLoader(). |
| std::pair<LazyMemberLoader *, uint64_t> 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<TypeLoc> inherited, |
| DeclContext *parent, |
| TrailingWhereClause *trailingWhereClause, |
| ClangNode clangNode = ClangNode()); |
| |
| SourceLoc getStartLoc() const { return ExtensionLoc; } |
| SourceLoc getLocFromSource() const { return ExtensionLoc; } |
| SourceRange getSourceRange() const { |
| 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; |
| |
| /// Determine whether this extension has already been bound to a nominal |
| /// type declaration. |
| bool alreadyBoundToNominal() const { return NextExtension.getInt(); } |
| |
| /// Retrieve the extended type definition as written in the source, if it exists. |
| TypeRepr *getExtendedTypeRepr() const { return ExtendedTypeRepr; } |
| |
| /// Retrieve the set of protocols that this type inherits (i.e, |
| /// explicitly conforms to). |
| ArrayRef<TypeLoc> getInherited() const { return Inherited; } |
| |
| void setInherited(ArrayRef<TypeLoc> 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<unsigned>(defaultAccess) - 1)) | |
| (1 << (static_cast<unsigned>(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; |
| |
| // 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; |
| }; |
| |
| /// 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 { |
| Checked = 1 << 0, |
| 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<Pattern *, 3, OptionSet<Flags>> PatternAndFlags; |
| |
| 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. |
| Expr *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, |
| }; |
| /// The initializer context used for this pattern binding entry. |
| llvm::PointerIntPair<DeclContext *, 2, OptionSet<PatternFlags>> |
| 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::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; |
| |
| bool isFullyValidated() const { |
| return InitContextAndFlags.getInt().contains( |
| PatternFlags::IsFullyValidated); |
| } |
| void setFullyValidated() { |
| InitContextAndFlags.setInt(InitContextAndFlags.getInt() | |
| PatternFlags::IsFullyValidated); |
| } |
| |
| public: |
| /// \p E is the initializer as parsed. |
| PatternBindingEntry(Pattern *P, SourceLoc EqualLoc, Expr *E, |
| DeclContext *InitContext) |
| : PatternAndFlags(P, {}), InitExpr({E, E, EqualLoc}), |
| InitContextAndFlags({InitContext, None}) {} |
| |
| 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; |
| } |
| /// 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<char> &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 *); |
| |
| bool isInitializerChecked() const { |
| return PatternAndFlags.getInt().contains(Flags::Checked); |
| } |
| void setInitializerChecked() { |
| PatternAndFlags.setInt(PatternAndFlags.getInt() | Flags::Checked); |
| } |
| |
| bool isInitializerSubsumed() const { |
| return PatternAndFlags.getInt().contains(Flags::Subsumed); |
| } |
| void setInitializerSubsumed() { |
| PatternAndFlags.setInt(PatternAndFlags.getInt() | Flags::Subsumed); |
| } |
| |
| // Return the first variable initialized by this pattern. |
| VarDecl *getAnchoringVarDecl() const; |
| |
| // Retrieve the declaration context for the initializer. |
| DeclContext *getInitContext() const { |
| return InitContextAndFlags.getPointer(); |
| } |
| |
| /// Override the initializer context. |
| void setInitContext(DeclContext *dc) { InitContextAndFlags.setPointer(dc); } |
| |
| 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<PatternBindingDecl, PatternBindingEntry> { |
| friend TrailingObjects; |
| friend class Decl; |
| friend class PatternBindingEntryRequest; |
| |
| 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<PatternBindingEntry> 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); |
| |
| SourceLoc getStartLoc() const { |
| return StaticLoc.isValid() ? StaticLoc : VarLoc; |
| } |
| SourceRange getSourceRange() const; |
| |
| unsigned getNumPatternEntries() const { |
| return Bits.PatternBindingDecl.NumPatternEntries; |
| } |
| |
| ArrayRef<PatternBindingEntry> getPatternList() const { |
| return const_cast<PatternBindingDecl*>(this)->getMutablePatternList(); |
| } |
| |
| 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); |
| } |
| |
| Pattern *getPattern(unsigned i) const { |
| return getPatternList()[i].getPattern(); |
| } |
| |
| void setPattern(unsigned i, Pattern *Pat, DeclContext *InitContext); |
| |
| DeclContext *getInitContext(unsigned i) const { |
| return getPatternList()[i].getInitContext(); |
| } |
| |
| 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(); |
| } |
| |
| /// 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<StaticSpellingKind>( |
| 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<char> &scratch) const { |
| return getPatternList()[i].getInitStringRepresentation(scratch); |
| } |
| |
| static bool classof(const Decl *D) { |
| return D->getKind() == DeclKind::PatternBinding; |
| } |
| |
| private: |
| MutableArrayRef<PatternBindingEntry> getMutablePatternList() { |
| // Pattern entries are tail allocated. |
| return {getTrailingObjects<PatternBindingEntry>(), 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; |
| |
| 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; |
| }; |
| |
| /// SerializedTopLevelCodeDeclContext - This represents what was originally a |
| /// TopLevelCodeDecl during serialization. It is preserved only to maintain the |
| /// correct AST structure and remangling after deserialization. |
| class SerializedTopLevelCodeDeclContext : public SerializedLocalDeclContext { |
| public: |
| SerializedTopLevelCodeDeclContext(DeclContext *Parent) |
| : SerializedLocalDeclContext(LocalDeclContextKind::TopLevelCodeDecl, |
| Parent) {} |
| static bool classof(const DeclContext *DC) { |
| if (auto LDC = dyn_cast<SerializedLocalDeclContext>(DC)) |
| return LDC->getLocalDeclContextKind() == |
| LocalDeclContextKind::TopLevelCodeDecl; |
| return false; |
| } |
| }; |
| |
| /// IfConfigDecl - This class represents #if/#else/#endif blocks. |
| /// Active and inactive block members are stored separately, with the intention |
| /// being that active members will be handed back to the enclosing context. |
| class IfConfigDecl : public Decl { |
| /// An array of clauses controlling each of the #if/#elseif/#else conditions. |
| /// The array is ASTContext allocated. |
| ArrayRef<IfConfigClause> Clauses; |
| SourceLoc EndLoc; |
| SourceLoc getLocFromSource() const { return Clauses[0].Loc; } |
| friend class Decl; |
| public: |
| |
| IfConfigDecl(DeclContext *Parent, ArrayRef<IfConfigClause> Clauses, |
| SourceLoc EndLoc, bool HadMissingEnd) |
| : Decl(DeclKind::IfConfig, Parent), Clauses(Clauses), EndLoc(EndLoc) |
| { |
| Bits.IfConfigDecl.HadMissingEnd = HadMissingEnd; |
| } |
| |
| ArrayRef<IfConfigClause> getClauses() const { return Clauses; } |
| |
| /// Return the active clause, or null if there is no active one. |
| const IfConfigClause *getActiveClause() const { |
| for (auto &Clause : Clauses) |
| if (Clause.isActive) return &Clause; |
| return nullptr; |
| } |
| |
| const ArrayRef<ASTNode> getActiveClauseElements() const { |
| if (auto *Clause = getActiveClause()) |
| return Clause->Elements; |
| return {}; |
| } |
| |
| SourceLoc getEndLoc() const { return EndLoc; } |
| |
| bool hadMissingEnd() const { return Bits.IfConfigDecl.HadMissingEnd; } |
| |
| SourceRange getSourceRange() const; |
| |
| static bool classof(const Decl *D) { |
| return D->getKind() == DeclKind::IfConfig; |
| } |
| }; |
| |
| class StringLiteralExpr; |
| |
| class PoundDiagnosticDecl : public Decl { |
| SourceLoc StartLoc; |
| SourceLoc EndLoc; |
| StringLiteralExpr *Message; |
| SourceLoc getLocFromSource() const { return StartLoc; } |
| friend class Decl; |
| public: |
| PoundDiagnosticDecl(DeclContext *Parent, bool IsError, SourceLoc StartLoc, |
| SourceLoc EndLoc, StringLiteralExpr *Message) |
| : Decl(DeclKind::PoundDiagnostic, Parent), StartLoc(StartLoc), |
| EndLoc(EndLoc), Message(Message) { |
| Bits.PoundDiagnosticDecl.IsError = IsError; |
| Bits.PoundDiagnosticDecl.HasBeenEmitted = false; |
| } |
| |
| DiagnosticKind getKind() const { |
| return isError() ? DiagnosticKind::Error : DiagnosticKind::Warning; |
| } |
| |
| StringLiteralExpr *getMessage() const { return Message; } |
| |
| bool isError() const { |
| return Bits.PoundDiagnosticDecl.IsError; |
| } |
| |
| bool hasBeenEmitted() const { |
| return Bits.PoundDiagnosticDecl.HasBeenEmitted; |
| } |
| |
| void markEmitted() { |
| Bits.PoundDiagnosticDecl.HasBeenEmitted = true; |
| } |
| |
| SourceLoc getEndLoc() const { return EndLoc; }; |
| |
| SourceRange getSourceRange() const { |
| return SourceRange(StartLoc, EndLoc); |
| } |
| |
| static bool classof(const Decl *D) { |
| return D->getKind() == DeclKind::PoundDiagnostic; |
| } |
| }; |
| |
| class OpaqueTypeDecl; |
| |
| /// ValueDecl - All named decls that are values in the language. These can |
| /// have a type, etc. |
| class ValueDecl : public Decl { |
| DeclName Name; |
| SourceLoc NameLoc; |
| llvm::PointerIntPair<Type, 3, OptionalEnum<AccessLevel>> TypeAndAccess; |
| unsigned LocalDiscriminator = 0; |
| |
| 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 "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 overriden. |
| 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; |
| } 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 Decl; |
| SourceLoc getLocFromSource() const { return NameLoc; } |
| protected: |
| ValueDecl(DeclKind K, |
| llvm::PointerUnion<DeclContext *, ASTContext *> context, |
| DeclName name, SourceLoc NameLoc) |
| : Decl(K, context), Name(name), NameLoc(NameLoc) { |
| Bits.ValueDecl.AlreadyInLookupTable = false; |
| Bits.ValueDecl.CheckedRedeclaration = false; |
| Bits.ValueDecl.IsUserAccessible = true; |
| } |
| |
| // MemberLookupTable borrows a bit from this type |
| friend class MemberLookupTable; |
| bool isAlreadyInLookupTable() { |
| return Bits.ValueDecl.AlreadyInLookupTable; |
| } |
| void setAlreadyInLookupTable(bool value = true) { |
| Bits.ValueDecl.AlreadyInLookupTable = value; |
| } |
| |
| /// 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: |
| /// Return true if this protocol member is a protocol requirement. |
| /// |
| /// Asserts if this is not a member of a protocol. |
| bool isProtocolRequirement() const; |
| |
| void setUserAccessible(bool Accessible) { |
| Bits.ValueDecl.IsUserAccessible = Accessible; |
| } |
| |
| bool isUserAccessible() const { |
| return Bits.ValueDecl.IsUserAccessible; |
| } |
| |
| bool hasName() const { return bool(Name); } |
| bool isOperator() const { return Name.isOperator(); } |
| |
| /// Retrieve the full name of the declaration. |
| 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 name to use for this declaration when interoperating |
| /// with the Objective-C runtime. |
| /// |
| /// \returns A "selector" containing the runtime name. For non-method |
| /// entities (classes, protocols, properties), this operation will |
| /// return a zero-parameter selector with the appropriate name in its |
| /// first slot. |
| Optional<ObjCSelector> 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; } |
| |
| 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; |
| |
| /// Determine whether this Decl has either Private or FilePrivate access, |
| /// and its DeclContext does not. |
| bool isOutermostPrivateOrFilePrivateScope() const; |
| |
| /// Returns the outermost DeclContext from which this declaration can be |
| /// accessed, or null if the declaration is public. |
| /// |
| /// This is used when calculating if access control is being used |
| /// consistently. If \p useDC is provided (the location where the value is |
| /// being used), features that affect formal access such as \c \@testable are |
| /// taken into account. |
| /// |
| /// \invariant |
| /// <code>value.isAccessibleFrom( |
| /// value.getFormalAccessScope().getDeclContext())</code> |
| /// |
| /// 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; |
| |
| /// 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); |
| |
| /// Retrieve the declaration that this declaration overrides, if any. |
| ValueDecl *getOverriddenDecl() const; |
| |
| /// Retrieve the declarations that this declaration overrides, if any. |
| llvm::TinyPtrVector<ValueDecl *> 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<ValueDecl *> 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 'final'? |
| bool isFinal() const; |
| |
| /// Is this declaration marked with 'dynamic'? |
| bool isDynamic() 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; |
| |
| bool isEffectiveLinkageMoreVisibleThan(ValueDecl *other) const { |
| return (std::min(getEffectiveAccess(), AccessLevel::Public) > |
| std::min(other->getEffectiveAccess(), AccessLevel::Public)); |
| } |
| |
| /// 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<ValueDecl *> |
| 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; |
| |
| /// Retrieve the location at which we should insert a new attribute or |
| /// modifier. |
| SourceLoc getAttributeInsertionLoc(bool forModifier) const; |
| |
| static bool classof(const Decl *D) { |
| return D->getKind() >= DeclKind::First_ValueDecl && |
| D->getKind() <= DeclKind::Last_ValueDecl; |
| } |
| |
| /// True if this is a C function that was imported as a member of a type in |
| /// Swift. |
| bool isImportAsMember() const; |
| |
| /// 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 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; |
| |
| /// Get the representative for this value's opaque result type, if it has one. |
| OpaqueReturnTypeRepr *getOpaqueResultTypeRepr() 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; |
| }; |
| |
| /// This is a common base class for declarations which declare a type. |
| class TypeDecl : public ValueDecl { |
| ArrayRef<TypeLoc> Inherited; |
| |
| protected: |
| TypeDecl(DeclKind K, llvm::PointerUnion<DeclContext *, ASTContext *> context, |
| Identifier name, SourceLoc NameLoc, |
| ArrayRef<TypeLoc> inherited) : |
| ValueDecl(K, context, name, NameLoc), Inherited(inherited) {} |
| |
| 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). |
| ArrayRef<TypeLoc> getInherited() const { return Inherited; } |
| |
| void setInherited(ArrayRef<TypeLoc> i) { Inherited = i; } |
| |
| static bool classof(const Decl *D) { |
| return D->getKind() >= DeclKind::First_TypeDecl && |
| D->getKind() <= DeclKind::Last_TypeDecl; |
| } |
| |
| /// Compute an ordering between two type declarations that is ABI-stable. |
| static int compare(const TypeDecl *type1, const TypeDecl *type2); |
| |
| /// 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<typename T> |
| static int compare(T * const* type1, T * const* type2) { |
| return compare(*type1, *type2); |
| } |
| }; |
| |
| /// A type declaration that can have generic parameters attached to it. Because |
| /// it has these generic parameters, it is always a DeclContext. |
| class GenericTypeDecl : public GenericContext, public TypeDecl { |
| public: |
| GenericTypeDecl(DeclKind K, DeclContext *DC, |
| Identifier name, SourceLoc nameLoc, |
| ArrayRef<TypeLoc> inherited, |
| GenericParamList *GenericParams); |
| |
| // Resolve ambiguity due to multiple base classes. |
| using TypeDecl::getASTContext; |
| using DeclContext::operator new; |
| using TypeDecl::getDeclaredInterfaceType; |
| |
| static bool classof(const DeclContext *C) { |
| 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. |
| /// |
| /// Currently, opaque types do not normally have an explicit spelling in source |
| /// code. One is formed implicitly when a declaration is written with an opaque |
| /// result type, as in: |
| /// |
| /// func foo() -> some SignedInteger { return 1 } |
| /// |
| /// The declared type is a special kind of ArchetypeType representing the |
| /// abstracted underlying type. |
| class OpaqueTypeDecl : public GenericTypeDecl { |
| /// The original declaration that "names" the opaque type. Although a specific |
| /// opaque type cannot be explicitly named, oapque types can propagate |
| /// arbitrarily through expressions, so we need to know *which* opaque type is |
| /// propagated. |
| ValueDecl *NamingDecl; |
| |
| /// The generic signature of the opaque interface to the type. This is the |
| /// outer generic signature with an added generic parameter representing the |
| /// underlying type. |
| GenericSignature OpaqueInterfaceGenericSignature; |
| |
| /// The generic parameter that represents the underlying type. |
| GenericTypeParamType *UnderlyingInterfaceType; |
| |
| /// 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. |
| Optional<SubstitutionMap> UnderlyingTypeSubstitutions; |
| |
| mutable Identifier OpaqueReturnTypeIdentifier; |
| |
| public: |
| OpaqueTypeDecl(ValueDecl *NamingDecl, |
| GenericParamList *GenericParams, |
| DeclContext *DC, |
| GenericSignature OpaqueInterfaceGenericSignature, |
| GenericTypeParamType *UnderlyingInterfaceType); |
| |
| ValueDecl *getNamingDecl() const { return NamingDecl; } |
| |
| void setNamingDecl(ValueDecl *D) { |
| assert(!NamingDecl && "already have naming decl"); |
| NamingDecl = 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 isOpaqueReturnTypeOfFunction(const AbstractFunctionDecl *func) const; |
| |
| GenericSignature getOpaqueInterfaceGenericSignature() const { |
| return OpaqueInterfaceGenericSignature; |
| } |
| |
| GenericTypeParamType *getUnderlyingInterfaceType() const { |
| return UnderlyingInterfaceType; |
| } |
| |
| Optional<SubstitutionMap> getUnderlyingTypeSubstitutions() const { |
| return UnderlyingTypeSubstitutions; |
| } |
| |
| void setUnderlyingTypeSubstitutions(SubstitutionMap subs) { |
| assert(!UnderlyingTypeSubstitutions.hasValue() && "resetting underlying type?!"); |
| UnderlyingTypeSubstitutions = subs; |
| } |
| |
| // 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; |
| } |
| }; |
| |
| /// 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; |
| } |
| }; |
| |
| /// Abstract class describing generic type parameters and associated types, |
| /// whose common purpose is to anchor the abstract type parameter and specify |
| /// requirements for any corresponding type argument. |
| class AbstractTypeParamDecl : public TypeDecl { |
| protected: |
| AbstractTypeParamDecl(DeclKind kind, DeclContext *dc, Identifier name, |
| SourceLoc NameLoc) |
| : TypeDecl(kind, dc, name, NameLoc, { }) { } |
| |
| public: |
| /// Return the superclass of the generic parameter. |
| Type getSuperclass() const; |
| |
| /// Retrieve the set of protocols to which this abstract type |
| /// parameter conforms. |
| ArrayRef<ProtocolDecl *> getConformingProtocols() const; |
| |
| static bool classof(const Decl *D) { |
| return D->getKind() >= DeclKind::First_AbstractTypeParamDecl && |
| D->getKind() <= DeclKind::Last_AbstractTypeParamDecl; |
| } |
| }; |
| |
| /// A declaration of a generic type parameter. |
| /// |
| /// A generic type parameter introduces a new, named type parameter along |
| /// with some set of requirements on any type argument used to realize this |
| /// type parameter. The requirements involve conformances to specific |
| /// protocols or inheritance from a specific class type. |
| /// |
| /// In the following example, 'T' is a generic type parameter with the |
| /// requirement that the type argument conform to the 'Comparable' protocol. |
| /// |
| /// \code |
| /// func min<T : Comparable>(x : T, y : T) -> T { ... } |
| /// \endcode |
| class GenericTypeParamDecl : public AbstractTypeParamDecl { |
| public: |
| static const unsigned InvalidDepth = 0xFFFF; |
| |
| /// Construct a new generic type parameter. |
| /// |
| /// \param dc The DeclContext in which the generic type parameter's owner |
| /// occurs. This should later be overwritten with the actual declaration |
| /// context that owns the type parameter. |
| /// |
| /// \param name The name of the generic parameter. |
| /// \param nameLoc The location of the name. |
| GenericTypeParamDecl(DeclContext *dc, Identifier name, SourceLoc nameLoc, |
| unsigned depth, unsigned index); |
| |
| /// The depth of this generic type parameter, i.e., the number of outer |
| /// levels of generic parameter lists that enclose this type parameter. |
| /// |
| /// \code |
| /// struct X<T> { |
| /// func f<U>() { } |
| /// } |
| /// \endcode |
| /// |
| /// Here 'T' has depth 0 and 'U' has depth 1. Both have index 0. |
| unsigned getDepth() const { return Bits.GenericTypeParamDecl.Depth; } |
| |
| /// Set the depth of this generic type parameter. |
| /// |
| /// \sa getDepth |
| void setDepth(unsigned depth) { |
| Bits.GenericTypeParamDecl.Depth = depth; |
| assert(Bits.GenericTypeParamDecl.Depth == depth && "Truncation"); |
| } |
| |
| /// The index of this generic type parameter within its generic parameter |
| /// list. |
| /// |
| /// \code |
| /// struct X<T, U> { |
| /// func f<V>() { } |
| /// } |
| /// \endcode |
| /// |
| /// Here 'T' and 'U' have indexes 0 and 1, respectively. 'V' has index 0. |
| unsigned getIndex() const { return Bits.GenericTypeParamDecl.Index; } |
| |
| SourceLoc getStartLoc() const { return getNameLoc(); } |
| SourceRange getSourceRange() const; |
| |
| static bool classof(const Decl *D) { |
| return D->getKind() == DeclKind::GenericTypeParam; |
| } |
| }; |
| |
| /// A declaration of an associated type. |
| /// |
| /// An associated type introduces a new, named type in a protocol that |
| /// can vary from one conforming type to the next. Associated types have a |
| /// set of requirements to which the type that replaces it much realize, |
| /// described via conformance to specific protocols, or inheritance from a |
| /// specific class type. |
| /// |
| /// In the following example, 'Element' is an associated type with no |
| /// requirements. |
| /// |
| /// \code |
| /// protocol Enumerator { |
| /// typealias Element |
| /// func getNext() -> Element? |
| /// } |
| /// \endcode |
| class AssociatedTypeDecl : public AbstractTypeParamDecl { |
| /// The location of the initial keyword. |
| SourceLoc KeywordLoc; |
| |
| /// The default definition. |
| TypeRepr *DefaultDefinition; |
| |
| /// The where clause attached to the associated type. |
| TrailingWhereClause *TrailingWhere; |
| |
| LazyMemberLoader *Resolver = nullptr; |
| uint64_t ResolverContextData; |
| |
| friend class DefaultDefinitionTypeRequest; |
| |
| public: |
| AssociatedTypeDecl(DeclContext *dc, SourceLoc keywordLoc, Identifier name, |
| SourceLoc nameLoc, TypeRepr *defaultDefinition, |
| TrailingWhereClause *trailingWhere); |
| AssociatedTypeDecl(DeclContext *dc, SourceLoc keywordLoc, Identifier name, |
| SourceLoc nameLoc, TrailingWhereClause *trailingWhere, |
| LazyMemberLoader *definitionResolver, |
| uint64_t resolverData); |
| |
| /// Get the protocol in which this associated type is declared. |
| ProtocolDecl *getProtocol() const { |
| return cast<ProtocolDecl>(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 || getDefaultDefinitionType(); |
| } |
| |
| /// Retrieve the default definition type. |
| Type getDefaultDefinitionType() const; |
| |
| /// Retrieve the default definition as written in the source. |
| TypeRepr *getDefaultDefinitionTypeRepr() const { |
| return DefaultDefinition; |
| } |
| |
| /// 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<AssociatedTypeDecl>( |
| AbstractTypeParamDecl::getOverriddenDecl()); |
| } |
| |
| /// Retrieve the set of associated types overridden by this associated |
| /// type. |
| llvm::TinyPtrVector<AssociatedTypeDecl *> getOverriddenDecls() const; |
| |
| SourceLoc getStartLoc() const { return KeywordLoc; } |
| SourceRange getSourceRange() const; |
| |
| static bool classof(const Decl *D) { |
| return D->getKind() == DeclKind::AssociatedType; |
| } |
| }; |
| |
| class MemberLookupTable; |
| class ConformanceLookupTable; |
| |
| // Kinds of 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<LazyMemberLoader *, uint64_t> takeConformanceLoader() { |
| if (!Bits.NominalTypeDecl.HasLazyConformances) |
| return { nullptr, 0 }; |
| |
| return takeConformanceLoaderSlow(); |
| } |
| |
| /// Slow path for \c takeConformanceLoader(). |
| std::pair<LazyMemberLoader *, uint64_t> takeConformanceLoaderSlow(); |
| |
| /// A lookup table containing all of the members of this type and |
| /// its extensions. |
| /// |
| /// The table itself is lazily constructed and updated when |
| /// lookupDirect() is called. |
| MemberLookupTable *LookupTable = nullptr; |
| |
| /// Prepare the lookup table to make it ready for lookups. |
| void prepareLookupTable(); |
| |
| /// Note that we have added a member into the iterable declaration context, |
| /// so that it can also be added to the lookup table (if needed). |
| void addedMember(Decl *member); |
| |
| /// 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<ValueDecl *> |
| getSatisfiedProtocolRequirementsForMember(const ValueDecl *Member, |
| bool Sorted) const; |
| |
| friend class ASTContext; |
| friend class MemberLookupTable; |
| friend class ConformanceLookupTable; |
| friend class ExtensionDecl; |
| friend class DeclContext; |
| friend class IterableDeclContext; |
| friend class DirectLookupRequest; |
| friend ArrayRef<ValueDecl *> |
| ValueDecl::getSatisfiedProtocolRequirements(bool Sorted) const; |
| |
| protected: |
| Type DeclaredTy; |
| Type DeclaredInterfaceTy; |
| |
| NominalTypeDecl(DeclKind K, DeclContext *DC, Identifier name, |
| SourceLoc NameLoc, |
| ArrayRef<TypeLoc> 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; } |
| |
| /// Should this declaration behave as if it must be accessed |
| /// resiliently, even when we're building a non-resilient module? |
| /// |
| /// This is used for diagnostics, because we do not want a behavior |
| /// change between builds with resilience enabled and disabled. |
| bool isFormallyResilient() const; |
| |
| /// Do we need to use resilient access patterns outside of this type's |
| /// resilience domain? |
| bool isResilient() const; |
| |
| /// Do we need to use resilient access patterns when accessing this |
| /// type from the given module? |
| bool isResilient(ModuleDecl *M, ResilienceExpansion expansion) const; |
| |
| /// Determine whether we have already attempted to add any |
| /// implicitly-defined initializers to this declaration. |
| bool addedImplicitInitializers() const { |
| return Bits.NominalTypeDecl.AddedImplicitInitializers; |
| } |
| |
| /// Note that we have attempted to add implicit initializers. |
| void setAddedImplicitInitializers() { |
| Bits.NominalTypeDecl.AddedImplicitInitializers = true; |
| } |
| |
| /// 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); |
| |
| /// Retrieve the set of extensions of this type. |
| ExtensionRange getExtensions(); |
| |
| /// 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 avoid loading lazy members from any new extensions that would otherwise be found |
| /// by deserialization. |
| /// |
| /// Used by the module loader to break recursion and as an optimization e.g. when it is known that a |
| /// particular member declaration will never appear in an extension. |
| IgnoreNewExtensions = 1 << 1, |
| }; |
| |
| /// 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<ValueDecl *> lookupDirect(DeclName name, |
| OptionSet<LookupDirectFlags> flags = |
| OptionSet<LookupDirectFlags>()); |
| |
| /// Collect the set of protocols to which this type should implicitly |
| /// conform, such as AnyObject (for classes). |
| void getImplicitProtocols(SmallVectorImpl<ProtocolDecl *> &protocols); |
| |
| /// Look for conformances of this nominal type to the given |
| /// protocol. |
| /// |
| /// \param module The module from which we initiate the search. |
| /// FIXME: This is currently unused. |
| /// |
| /// \param protocol The protocol whose conformance is requested. |
| /// \param conformances Will be populated with the set of protocol |
| /// conformances found for this protocol. |
| /// |
| /// \returns true if any conformances were found. |
| bool lookupConformance( |
| ModuleDecl *module, ProtocolDecl *protocol, |
| SmallVectorImpl<ProtocolConformance *> &conformances) const; |
| |
| /// Retrieve all of the protocols that this nominal type conforms to. |
| SmallVector<ProtocolDecl *, 2> getAllProtocols() const; |
| |
| /// Retrieve all of the protocol conformances for this nominal type. |
| SmallVector<ProtocolConformance *, 2> getAllConformances( |
| bool sorted = false) const; |
| |
| /// Register an externally-created protocol conformance in the |
| /// conformance lookup table. |
| /// |
| /// This is used by deserialization of module files to report |
| /// conformances. |
| void registerProtocolConformance(ProtocolConformance *conformance); |
| |
| void setConformanceLoader(LazyMemberLoader *resolver, uint64_t contextData); |
| |
| /// Is this the decl for Optional<T>? |
| bool isOptionalDecl() const; |
| |
| /// Is this a key path type? |
| Optional<KeyPathTypeKind> getKeyPathTypeKind() const; |
| |
| /// Retrieve information about this type as a property wrapper. |
| PropertyWrapperTypeInfo getPropertyWrapperTypeInfo() const; |
| |
| private: |
| /// Predicate used to filter StoredPropertyRange. |
| struct ToStoredProperty { |
| ToStoredProperty(bool skipInaccessible = false) : |
| skipUserInaccessible(skipInaccessible) {} |
| bool skipUserInaccessible; |
| Optional<VarDecl *> operator()(Decl *decl) const; |
| }; |
| |
| public: |
| /// A range for iterating the stored member variables of a structure. |
| using StoredPropertyRange = OptionalTransformRange<DeclRange, |
| ToStoredProperty>; |
| |
| /// Return a collection of the stored member variables of this type. |
| ArrayRef<VarDecl *> getStoredProperties() const; |
| |
| /// Return a collection of the stored member variables of this type, along |
| /// with placeholders for unimportable stored properties. |
| ArrayRef<Decl *> getStoredPropertiesAndMissingMemberPlaceholders() 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); |
| } |
| |
| /// 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; |
| |
| 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; |
| } |
| |
| // 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<T> { |
| /// 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<SemanticInfoFlags> SemanticFlags; |
| |
| friend class EnumRawValuesRequest; |
| friend class EnumRawTypeRequest; |
| |
| public: |
| EnumDecl(SourceLoc EnumLoc, Identifier Name, SourceLoc NameLoc, |
| ArrayRef<TypeLoc> 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<EnumElementDecl, DeclRange>; |
| |
| /// A range for iterating the cases of an enum. |
| using CaseRange = DowncastFilterRange<EnumCaseDecl, DeclRange>; |
| |
| /// Return a range that iterates over all the elements of an enum. |
| ElementRange getAllElements() const { |
| return ElementRange(getMembers()); |
| } |
| |
| unsigned getNumElements() const { |
| auto eltRange = getAllElements(); |
| return std::distance(eltRange.begin(), eltRange.end()); |
| } |
| |
| /// If this 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<EnumElementDecl*> &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<NominalTypeDecl>(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 the enum has cases. |
| bool hasCases() const { |
| return !getAllElements().empty(); |
| } |
| |
| /// True if the enum is marked 'indirect'. |
| bool isIndirect() const { |
| return getAttrs().hasAttribute<IndirectAttr>(); |
| } |
| |
| /// 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 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; |
| |
| public: |
| StructDecl(SourceLoc StructLoc, Identifier Name, SourceLoc NameLoc, |
| ArrayRef<TypeLoc> 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<NominalTypeDecl>(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; |
| } |
| |
| bool isCxxNonTrivial() const { return Bits.StructDecl.IsCxxNonTrivial; } |
| |
| void setIsCxxNonTrivial(bool v) { Bits.StructDecl.IsCxxNonTrivial = v; } |
| }; |
| |
| /// 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<AncestryFlags>; |
| |
| /// ClassDecl - This is the declaration of a class, for example: |
| /// |
| /// class Complex { var R : Double, I : Double } |
| /// |
| /// The type of the decl itself is a MetatypeType; use getDeclaredType() |
| /// to get the declared type ("Complex" in the above example). |
| class ClassDecl final : public NominalTypeDecl { |
| class ObjCMethodLookupTable; |
| |
| SourceLoc ClassLoc; |
| ObjCMethodLookupTable *ObjCMethodLookup = nullptr; |
| |
| /// Create the Objective-C member lookup table. |
| void createObjCMethodLookup(); |
| |
| struct { |
| /// The superclass decl and a bit to indicate whether the |
| /// superclass was computed yet or not. |
| llvm::PointerIntPair<ClassDecl *, 1, bool> SuperclassDecl; |
| |
| /// The superclass type and a bit to indicate whether the |
| /// superclass was computed yet or not. |
| llvm::PointerIntPair<Type, 1, bool> SuperclassType; |
| } LazySemanticInfo; |
| |
| Optional<bool> getCachedInheritsSuperclassInitializers() const { |
| if (Bits.ClassDecl.ComputedInheritsSuperclassInits) |
| return Bits.ClassDecl.InheritsSuperclassInits; |
| |
| return None; |
| } |
| |
| Optional<bool> 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<ClassDecl *>(this); |
| (void)mutableThis->lookupDirect(DeclBaseName::createConstructor()); |
| } |
| |
| if (Bits.ClassDecl.ComputedHasMissingDesignatedInitializers) |
| return Bits.ClassDecl.HasMissingDesignatedInitializers; |
| |
| return None; |
| } |
| |
| 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 SemanticMembersRequest; |
| friend class HasMissingDesignatedInitializersRequest; |
| friend class InheritsSuperclassInitializersRequest; |
| |
| public: |
| ClassDecl(SourceLoc ClassLoc, Identifier Name, SourceLoc NameLoc, |
| ArrayRef<TypeLoc> Inherited, |
| GenericParamList *GenericParams, DeclContext *DC); |
| |
| 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(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<TypeWalker::Action(ClassDecl *)> 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<ForeignKind>(Bits.ClassDecl.RawForeignKind); |
| } |
| void setForeignClassKind(ForeignKind kind) { |
| Bits.ClassDecl.RawForeignKind = static_cast<unsigned>(kind); |
| } |
| |
| /// Returns true if this class is any kind of "foreign class". |
| /// |
| /// \see getForeignClassKind |
| bool isForeign() const { |
| return getForeignClassKind() != ForeignKind::Normal; |
| } |
| |
| /// Whether the class is an actor. |
| bool isActor() const; |
| |
| /// Whether the class is (known to be) a default actor. |
| bool isDefaultActor() 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; |
| |
| /// Does this class explicitly declare any of the methods that |
| /// would prevent it from being a default actor? |
| bool hasExplicitCustomActorMethods() 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.) instead of the Swift model. |
| bool usesObjCObjectModel() const { |
| return checkAncestry(AncestryFlags::ObjCObjectModel); |
| } |
| |
| /// 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<char> &buffer) const; |
| |
| using NominalTypeDecl::lookupDirect; |
| |
| /// Look in this class and its extensions (but not any of its protocols or |
| /// superclasses) for declarations with a given Objective-C selector. |
| /// |
| /// Note that this can find methods, initializers, deinitializers, |
| /// getters, and setters. |
| /// |
| /// \param selector The Objective-C selector of the method we're |
| /// looking for. |
| /// |
| /// \param isInstance Whether we are looking for an instance method |
| /// (vs. a class method). |
| TinyPtrVector<AbstractFunctionDecl *> lookupDirect(ObjCSelector selector, |
| bool isInstance); |
| |
| /// Record the presence of an @objc method with the given selector. |
| void recordObjCMethod(AbstractFunctionDecl *method, ObjCSelector selector); |
| |
| // 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<NominalTypeDecl>(C); |
| return NTD && classof(NTD); |
| } |
| |
| /// Returns true if the decl uses the Objective-C generics model. |
| /// |
| /// This is true of imported Objective-C classes. |
| bool usesObjCGenericsModel() const { |
| return hasClangNode() && isGenericContext() && isObjC(); |
| } |
| |
| /// True if the class is known to be implemented in Swift. |
| bool hasKnownSwiftImplementation() const { |
| return !hasClangNode(); |
| } |
| }; |
| |
| /// A convenience wrapper around the \c SelfReferencePosition::Kind enum. |
| struct SelfReferencePosition final { |
| enum Kind : uint8_t { None, Covariant, Contravariant, Invariant }; |
| |
| private: |
| Kind kind; |
| |
| public: |
| SelfReferencePosition(Kind kind) : kind(kind) {} |
| |
| SelfReferencePosition flipped() const { |
| switch (kind) { |
| case None: |
| case Invariant: |
| return *this; |
| case Covariant: |
| return Contravariant; |
| case Contravariant: |
| return Covariant; |
| } |
| llvm_unreachable("unhandled self reference position!"); |
| } |
| |
| explicit operator bool() const { return kind > None; } |
| |
| operator Kind() const { return kind; } |
| }; |
| |
| /// Describes the least favorable positions at which a requirement refers |
| /// to 'Self' in terms of variance, for use in the is-inheritable and |
| /// is-available-existential checks. |
| struct SelfReferenceInfo final { |
| using Position = SelfReferencePosition; |
| |
| bool hasCovariantSelfResult; |
| Position selfRef; |
| Position assocTypeRef; |
| |
| /// A reference to 'Self'. |
| static SelfReferenceInfo forSelfRef(Position position) { |
| assert(position); |
| return SelfReferenceInfo(false, position, Position::None); |
| } |
| |
| /// A reference to 'Self' through an associated type. |
| static SelfReferenceInfo forAssocTypeRef(Position position) { |
| assert(position); |
| return SelfReferenceInfo(false, Position::None, position); |
| } |
| |
| SelfReferenceInfo operator|=(const SelfReferenceInfo &pos) { |
| hasCovariantSelfResult |= pos.hasCovariantSelfResult; |
| if (pos.selfRef > selfRef) { |
| selfRef = pos.selfRef; |
| } |
| if (pos.assocTypeRef > assocTypeRef) { |
| assocTypeRef = pos.assocTypeRef; |
| } |
| return *this; |
| } |
| |
| explicit operator bool() const { |
| return hasCovariantSelfResult || selfRef || assocTypeRef; |
| } |
| |
| SelfReferenceInfo() |
| : hasCovariantSelfResult(false), selfRef(Position::None), |
| assocTypeRef(Position::None) {} |
| |
| private: |
| SelfReferenceInfo(bool hasCovariantSelfResult, Position selfRef, |
| Position assocTypeRef) |
| : hasCovariantSelfResult(hasCovariantSelfResult), selfRef(selfRef), |
| assocTypeRef(assocTypeRef) {} |
| }; |
| |
| /// 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, |
| Actor, |
| // SWIFT_ENABLE_TENSORFLOW |
| PointwiseMultiplicative, |
| ElementaryFunctions, |
| KeyPathIterable, |
| TensorArrayProtocol, |
| TensorGroup, |
| VectorProtocol, |
| EuclideanDifferentiable, |
| // SWIFT_ENABLE_TENSORFLOW END |
| }; |
| |
| /// 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 Cloneable { |
| /// func clone() -> Self |
| /// } |
| /// |
| class ProtocolDecl final : public NominalTypeDecl { |
| SourceLoc ProtocolLoc; |
| |
| ArrayRef<ProtocolDecl *> InheritedProtocols; |
| |
| struct { |
| /// The superclass decl and a bit to indicate whether the |
| /// superclass was computed yet or not. |
| llvm::PointerIntPair<ClassDecl *, 1, bool> SuperclassDecl; |
| |
| /// The superclass type and a bit to indicate whether the |
| /// superclass was computed yet or not. |
| llvm::PointerIntPair<Type, 1, bool> SuperclassType; |
| } LazySemanticInfo; |
| |
| /// The generic signature representing exactly the new requirements introduced |
| /// by this protocol. |
| const Requirement *RequirementSignature = nullptr; |
| |
| /// Returns the cached result of \c requiresClass or \c None if it hasn't yet |
| /// been computed. |
| Optional<bool> getCachedRequiresClass() const { |
| if (Bits.ProtocolDecl.RequiresClassValid) |
| return Bits.ProtocolDecl.RequiresClass; |
| |
| return None; |
| } |
| |
| /// 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. |
| Optional<bool> getCachedExistentialConformsToSelf() const { |
| if (Bits.ProtocolDecl.ExistentialConformsToSelfValid) |
| return Bits.ProtocolDecl.ExistentialConformsToSelf; |
| |
| return None; |
| } |
| |
| /// Caches the result of \c existentialConformsToSelf |
| void setCachedExistentialConformsToSelf(bool result) { |
| Bits.ProtocolDecl.ExistentialConformsToSelfValid = true; |
| Bits.ProtocolDecl.ExistentialConformsToSelf = result; |
| } |
| |
| /// Returns the cached result of \c existentialTypeSupported or \c None if it |
| /// hasn't yet been computed. |
| Optional<bool> getCachedExistentialTypeSupported() { |
| if (Bits.ProtocolDecl.ExistentialTypeSupportedValid) |
| return Bits.ProtocolDecl.ExistentialTypeSupported; |
| |
| return None; |
| } |
| |
| /// Caches the result of \c existentialTypeSupported |
| void setCachedExistentialTypeSupported(bool supported) { |
| Bits.ProtocolDecl.ExistentialTypeSupportedValid = true; |
| Bits.ProtocolDecl.ExistentialTypeSupported = supported; |
| } |
| |
| bool hasLazyRequirementSignature() const { |
| return Bits.ProtocolDecl.HasLazyRequirementSignature; |
| } |
| |
| friend class SuperclassDeclRequest; |
| friend class SuperclassTypeRequest; |
| friend class RequirementSignatureRequest; |
| friend class ProtocolRequiresClassRequest; |
| friend class ExistentialConformsToSelfRequest; |
| friend class ExistentialTypeSupportedRequest; |
| friend class InheritedProtocolsRequest; |
| |
| public: |
| ProtocolDecl(DeclContext *DC, SourceLoc ProtocolLoc, SourceLoc NameLoc, |
| Identifier Name, ArrayRef<TypeLoc> Inherited, |
| TrailingWhereClause *TrailingWhere); |
| |
| using Decl::getASTContext; |
| |
| /// Retrieve the set of protocols inherited from this protocol. |
| ArrayRef<ProtocolDecl *> getInheritedProtocols() const; |
| |
| /// Determine whether this protocol has a superclass. |
| bool hasSuperclass() const { return (bool)getSuperclassDecl(); } |
| |
| /// Retrieve the superclass of this protocol, or null if there is no superclass. |
| Type getSuperclass() const; |
| |
| /// Retrieve the ClassDecl for the superclass of this protocol, or null if there |
| /// is no superclass. |
| ClassDecl *getSuperclassDecl() const; |
| |
| /// Set the superclass of this protocol. |
| void setSuperclass(Type superclass); |
| |
| /// Retrieve the set of AssociatedTypeDecl members of this protocol; this |
| /// saves loading the set of members in cases where there's no possibility of |
| /// a protocol having nested types (ObjC protocols). |
| llvm::TinyPtrVector<AssociatedTypeDecl *> getAssociatedTypeMembers() 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; |
| |
| /// 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<TypeWalker::Action(ProtocolDecl *)> 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; |
| |
| /// Find direct Self references within the given requirement. |
| /// |
| /// \param treatNonResultCovariantSelfAsInvariant If true, 'Self' is only |
| /// assumed to be covariant in a top-level non-function type, or in the |
| /// eventual result type of a top-level function type. |
| SelfReferenceInfo |
| findProtocolSelfReferences(const ValueDecl *decl, |
| bool treatNonResultCovariantSelfAsInvariant) const; |
| |
| /// Determine whether we are allowed to refer to an existential type |
| /// conforming to this protocol. This is only permitted if the type of |
| /// the member does not contain any associated types, and does not |
| /// contain 'Self' in 'parameter' or 'other' position. |
| bool isAvailableInExistential(const ValueDecl *decl) const; |
| |
| /// Determine whether we are allowed to refer to an existential type |
| /// conforming to this protocol. This is only permitted if the types of |
| /// all the members do not contain any associated types, and do not |
| /// contain 'Self' in 'parameter' or 'other' position. |
| bool existentialTypeSupported() const; |
| |
| private: |
| void computeKnownProtocolKind() const; |
| |
| bool areInheritedProtocolsValid() const { |
| return Bits.ProtocolDecl.InheritedProtocolsValid; |
| } |
| void setInheritedProtocolsValid() { |
| Bits.ProtocolDecl.InheritedProtocolsValid = true; |
| } |
| |
| public: |
| /// If this is known to be a compiler-known protocol, returns the kind. |
| /// Otherwise returns None. |
| Optional<KnownProtocolKind> getKnownProtocolKind() const { |
| if (Bits.ProtocolDecl.KnownProtocol == 0) |
| computeKnownProtocolKind(); |
| |
| if (Bits.ProtocolDecl.KnownProtocol == 1) |
| return None; |
| |
| return static_cast<KnownProtocolKind>(Bits.ProtocolDecl.KnownProtocol - 2); |
| } |
| |
| Optional<KnownDerivableProtocolKind> 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<char> &buffer) const; |
| |
| /// Retrieve the requirements that describe this protocol. |
| /// |
| /// These are the requirements including any inherited protocols |
| /// and conformances for associated types that are introduced in this |
| /// protocol. Requirements implied via any other protocol (e.g., inherited |
| /// protocols of the inherited protocols) are not mentioned. The conformance |
| /// requirements listed here become entries in the witness table. |
| ArrayRef<Requirement> getRequirementSignature() const; |
| |
| /// Is the requirement signature currently being computed? |
| bool isComputingRequirementSignature() const; |
| |
| /// Has the requirement signature been computed yet? |
| bool isRequirementSignatureComputed() const { |
| return RequirementSignature != nullptr; |
| } |
| |
| void setRequirementSignature(ArrayRef<Requirement> requirements); |
| |
| void setLazyRequirementSignature(LazyMemberLoader *lazyLoader, |
| uint64_t requirementSignatureData); |
| |
| private: |
| ArrayRef<Requirement> getCachedRequirementSignature() const; |
| |
| 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<NominalTypeDecl>(C); |
| return NTD && classof(NTD); |
| } |
| }; |
| |
| /// AbstractStorageDecl - This is the common superclass for VarDecl and |
| /// SubscriptDecl, representing potentially settable memory locations. |
| class AbstractStorageDecl : public ValueDecl { |
| 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<AccessorRecord, AccessorDecl*> { |
| 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<AccessorDecl*> accessors, |
| AccessorIndex accessorsCapacity); |
| public: |
| static AccessorRecord *create(ASTContext &ctx, SourceRange braces, |
| ArrayRef<AccessorDecl*> accessors); |
| |
| SourceRange getBracesRange() const { return Braces; } |
| |
| inline AccessorDecl *getAccessor(AccessorKind kind) const; |
| |
| ArrayRef<AccessorDecl *> getAllAccessors() const { |
| return { getTrailingObjects<AccessorDecl*>(), NumAccessors }; |
| } |
| |
| void addOpaqueAccessor(AccessorDecl *accessor); |
| |
| private: |
| MutableArrayRef<AccessorDecl *> getAccessorsBuffer() { |
| return { getTrailingObjects<AccessorDecl*>(), NumAccessors }; |
| } |
| |
| bool registerAccessor(AccessorDecl *accessor, AccessorIndex index); |
| }; |
| |
| llvm::PointerIntPair<AccessorRecord*, 3, OptionalEnum<AccessLevel>> Accessors; |
| |
| struct { |
| 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; |
| } 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; |
| } |
| |
| /// \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; |
| |
| /// Determine how this storage is implemented. |
| StorageImplInfo getImplInfo() const; |
| |
| /// Overwrite the registered implementation-info. This should be |
| /// used carefully. |
| void setImplInfo(StorageImplInfo implInfo) { |
| LazySemanticInfo.ImplInfoComputed = 1; |
| ImplInfo = 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 getImplInfo().hasStorage(); |
| } |
| |
| /// 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(); |
| } |
| |
| /// isSettable - Determine whether references to this decl may appear |
| /// on the left-hand side of an assignment or as the operand of a |
| /// `&` or 'inout' operator. |
| bool isSettable(const DeclContext *UseDC, |
| const DeclRefExpr *base = nullptr) const; |
| |
| /// 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<AccessorDecl*> getAllAccessors() const { |
| if (const auto *info = Accessors.getPointer()) |
| return info->getAllAccessors(); |
| return {}; |
| } |
| |
| /// 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<AccessorDecl*> |
| getOpaqueAccessors(llvm::SmallVectorImpl<AccessorDecl*> &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<void (AccessorDecl*)>) const; |
| |
| /// Visit all opaque accessor kinds. |
| void visitExpectedOpaqueAccessors( |
| llvm::function_ref<void (AccessorKind)>) const; |
| |
| /// Visit all opaque accessors. |
| void visitOpaqueAccessors(llvm::function_ref<void (AccessorDecl*)>) const; |
| |
| /// Visit all eagerly emitted accessors. |
| /// |
| /// This is the union of the parsed and opaque sets. |
| void visitEmittedAccessors(llvm::function_ref<void (AccessorDecl*)>) const; |
| |
| void setAccessors(SourceLoc lbraceLoc, ArrayRef<AccessorDecl*> 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 { |
| return getOpaqueReadOwnership() != OpaqueReadOwnership::Owned; |
| } |
| |
| /// 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 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<AbstractStorageDecl>(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) const; |
| |
| /// Should this declaration behave as if it must be accessed |
| /// resiliently, even when we're building a non-resilient module? |
| /// |
| /// This is used for diagnostics, because we do not want a behavior |
| /// change between builds with resilience enabled and disabled. |
| bool isFormallyResilient() const; |
| |
| /// 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 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; |
| |
| // 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; |
| NamedPattern *NamingPattern = nullptr; |
| |
| public: |
| enum class Introducer : uint8_t { |
| Let = 0, |
| Var = 1 |
| }; |
| |
| protected: |
| PointerUnion<PatternBindingDecl *, |
| Stmt *, |
| VarDecl *, |
| CaptureListExpr *> 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() : "_"; |
| } |
| |
| /// Get the type of the variable within its context. If the context is generic, |
| /// this will use archetypes. |
| Type getType() 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; |
| |
| /// Returns whether the var is settable in the specified context: this |
| /// is either because it is a stored var, because it has a custom setter, or |
| /// is a let member in an initializer. |
| /// |
| /// Pass a null context and null base to check if it's always settable. |
| bool isSettable(const DeclContext *UseDC, |
| const DeclRefExpr *base = nullptr) const; |
| |
| /// Return the parent pattern binding that may provide an initializer for this |
| /// VarDecl. This returns null if there is none associated with the VarDecl. |
| PatternBindingDecl *getParentPatternBinding() const { |
| if (!Parent) |
| return nullptr; |
| return Parent.dyn_cast<PatternBindingDecl *>(); |
| } |
| 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<Stmt *>(); |
| } |
| |
| 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<VarDecl *>(); |
| } |
| |
| /// 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<VarDecl> getCorrespondingFirstCaseLabelItemVarDecl() const; |
| |
| /// If this is a case stmt var decl, return the case body var decl that this |
| /// var decl maps to. |
| NullablePtr<VarDecl> 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 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<HasInitialValueAttr>() || |
| isParentInitialized(); |
| } |
| |
| VarDecl *getOverriddenDecl() const { |
| return cast_or_null<VarDecl>(AbstractStorageDecl::getOverriddenDecl()); |
| } |
| |
| /// Is this an immutable 'let' property? |
| /// |
| /// If this is a ParamDecl, isLet() is true iff |
| /// getSpecifier() == Specifier::Default. |
| bool isLet() const { return getIntroducer() == Introducer::Let; } |
| |
| /// Is this an "async let" property? |
| bool isAsyncLet() const; |
| |
| Introducer getIntroducer() const { |
| return Introducer(Bits.VarDecl.Introducer); |
| } |
| |
| void setIntroducer(Introducer value) { |
| Bits.VarDecl.Introducer = uint8_t(value); |
| } |
| |
| CaptureListExpr *getParentCaptureList() const { |
| if (!Parent) |
| return nullptr; |
| return Parent.dyn_cast<CaptureListExpr *>(); |
| } |
| |
| /// 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; |
| } |
| |
| /// 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; |
| } |
| |
| /// Is this the synthesized storage for a 'lazy' property? |
| bool isLazyStorageProperty() const { |
| return Bits.VarDecl.IsLazyStorageProperty; |
| } |
| void setLazyStorageProperty(bool IsLazyStorage) { |
| Bits.VarDecl.IsLazyStorageProperty = IsLazyStorage; |
| } |
| |
| /// 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; } |
| |
| /// 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<CustomAttr *> getAttachedPropertyWrappers() const; |
| |
| /// Whether this property has any attached property wrappers. |
| bool hasAttachedPropertyWrapper() 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; |
| |
| /// Retrieve information about the backing properties of the attached |
| /// property wrapper. |
| PropertyWrapperBackingPropertyInfo |
| getPropertyWrapperBackingPropertyInfo() const; |
| |
| /// Retrieve information about the mutability of the composed |
| /// property wrappers. |
| Optional<PropertyWrapperMutability> |
| 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`. |
| Optional<PropertyWrapperSynthesizedPropertyKind> |
| 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; |
| |
| /// Retreive the projection var for a property that has an attached |
| /// property wrapper with a \c projectedValue . |
| VarDecl *getPropertyWrapperProjectionVar() const; |
| |
| /// 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<void(VarDecl *)>) const; |
| |
| /// Retrieve the backing storage property for a lazy property. |
| VarDecl *getLazyStorageProperty() 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( |
| Optional<PropertyWrapperSynthesizedPropertyKind> kind = None) 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; |
| |
| /// 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<SemanticsAttr>()) { |
| return getAttrs().getAttributes<SemanticsAttr>(); |
| } |
| |
| /// Returns true if this VarDelc has the string \p attrValue as a semantics |
| /// attribute. |
| bool hasSemanticsAttr(StringRef attrValue) const { |
| return llvm::any_of(getSemanticsAttrs(), [&](const SemanticsAttr *attr) { |
| return attrValue.equals(attr->Value); |
| }); |
| } |
| |
| // Implement isa/cast/dyncast/etc. |
| static bool classof(const Decl *D) { |
| return D->getKind() == DeclKind::Var || D->getKind() == DeclKind::Param; |
| } |
| }; |
| |
| enum class ParamSpecifier : uint8_t { |
| Default = 0, |
| InOut = 1, |
| Shared = 2, |
| Owned = 3, |
| }; |
| |
| /// A function parameter declaration. |
| class ParamDecl : public VarDecl { |
| friend class DefaultArgumentInitContextRequest; |
| friend class DefaultArgumentExprRequest; |
| |
| llvm::PointerIntPair<Identifier, 1, bool> ArgumentNameAndDestructured; |
| SourceLoc ParameterNameLoc; |
| SourceLoc ArgumentNameLoc; |
| SourceLoc SpecifierLoc; |
| |
| TypeRepr *TyRepr = nullptr; |
| |
| struct StoredDefaultArgument { |
| PointerUnion<Expr *, VarDecl *> DefaultArg; |
| |
| /// Stores the context for the default argument as well as a bit to |
| /// indicate whether the default expression has been type-checked. |
| llvm::PointerIntPair<Initializer *, 1, bool> InitContextAndIsTypeChecked; |
| |
| StringRef StringRepresentation; |
| CaptureInfo Captures; |
| }; |
| |
| /// Retrieve the cached initializer context for the parameter's default |
| /// argument without triggering a request. |
| Optional<Initializer *> getCachedDefaultArgumentInitContext() const; |
| |
| enum class Flags : uint8_t { |
| /// Whether or not this parameter is vargs. |
| IsVariadic = 1 << 0, |
| |
| /// Whether or not this parameter is `@autoclosure`. |
| IsAutoClosure = 1 << 1, |
| }; |
| |
| /// The default value, if any, along with flags. |
| llvm::PointerIntPair<StoredDefaultArgument *, 2, OptionSet<Flags>> |
| DefaultValueAndFlags; |
| |
| friend class ParamSpecifierRequest; |
| |
| public: |
| ParamDecl(SourceLoc specifierLoc, SourceLoc argumentNameLoc, |
| Identifier argumentName, SourceLoc parameterNameLoc, |
| Identifier parameterName, DeclContext *dc); |
| |
| /// Create a new ParamDecl identical to the first except without the interface type. |
| static ParamDecl *cloneWithoutType(const ASTContext &Ctx, ParamDecl *PD); |
| |
| /// Retrieve the argument (API) name for this function parameter. |
| Identifier getArgumentName() const { |
| return ArgumentNameAndDestructured.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 TyRepr; } |
| void setTypeRepr(TypeRepr *repr) { TyRepr = repr; } |
| |
| bool isDestructured() const { return ArgumentNameAndDestructured.getInt(); } |
| void setDestructured(bool repr) { ArgumentNameAndDestructured.setInt(repr); } |
| |
| DefaultArgumentKind getDefaultArgumentKind() const { |
| return static_cast<DefaultArgumentKind>(Bits.ParamDecl.defaultArgumentKind); |
| } |
| bool isDefaultArgument() const { |
| return getDefaultArgumentKind() != DefaultArgumentKind::None; |
| } |
| void setDefaultArgumentKind(DefaultArgumentKind K) { |
| Bits.ParamDecl.defaultArgumentKind = static_cast<unsigned>(K); |
| } |
| |
| /// 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<Expr *>(); |
| return nullptr; |
| } |
| |
| VarDecl *getStoredProperty() const { |
| if (auto stored = DefaultValueAndFlags.getPointer()) |
| return stored->DefaultArg.dyn_cast<VarDecl *>(); |
| return nullptr; |
| } |
| |
| /// Sets a new default argument expression for this parameter. This should |
| /// only be called internally by ParamDecl and AST walkers. |
| /// |
| /// \param E The new default argument. |
| /// \param isTypeChecked Whether this argument should be used as the |
| /// parameter's fully type-checked default argument. |
| void setDefaultExpr(Expr *E, bool isTypeChecked); |
| |
| void setStoredProperty(VarDecl *var); |
| |
| /// Retrieve the initializer context for the parameter's default argument. |
| Initializer *getDefaultArgumentInitContext() const; |
| |
| void setDefaultArgumentInitContext(Initializer *initContext); |
| |
| CaptureInfo getDefaultArgumentCaptureInfo() const { |
| assert(DefaultValueAndFlags.getPointer()); |
| return DefaultValueAndFlags.getPointer()->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<char> &scratch) const; |
| |
| void setDefaultValueStringRepresentation(StringRef stringRepresentation); |
| |
| /// Whether or not this parameter is varargs. |
| bool isVariadic() const { |
| return DefaultValueAndFlags.getInt().contains(Flags::IsVariadic); |
| } |
| void setVariadic(bool value = true) { |
| auto flags = DefaultValueAndFlags.getInt(); |
| DefaultValueAndFlags.setInt(value ? flags | Flags::IsVariadic |
| : flags - Flags::IsVariadic); |
| } |
| |
| /// Whether or not this parameter is marked with `@autoclosure`. |
| bool isAutoClosure() const { |
| return DefaultValueAndFlags.getInt().contains(Flags::IsAutoClosure); |
| } |
| void setAutoClosure(bool value = true) { |
| auto flags = DefaultValueAndFlags.getInt(); |
| DefaultValueAndFlags.setInt(value ? flags | Flags::IsAutoClosure |
| : flags - Flags::IsAutoClosure); |
| } |
| |
| /// 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; |
| |
| Optional<Specifier> getCachedSpecifier() const { |
| if (Bits.ParamDecl.SpecifierComputed) |
| return Specifier(Bits.ParamDecl.Specifier); |
| |
| return None; |
| } |
| |
| /// Return the raw specifier value for this parameter. |
| Specifier getSpecifier() const; |
| void setSpecifier(Specifier Spec); |
| |
| /// Is the type of this parameter 'inout'? |
| bool isInOut() const { return getSpecifier() == Specifier::InOut; } |
| /// Is this an immutable 'shared' property? |
| bool isShared() const { return getSpecifier() == Specifier::Shared; } |
| /// Is this an immutable 'owned' property? |
| bool isOwned() const { return getSpecifier() == Specifier::Owned; } |
| |
| bool isImmutable() const { |
| return isImmutableSpecifier(getSpecifier()); |
| } |
| static bool isImmutableSpecifier(Specifier sp) { |
| switch (sp) { |
| case Specifier::Default: |
| case Specifier::Shared: |
| case Specifier::Owned: |
| return true; |
| case Specifier::InOut: |
| return false; |
| } |
| llvm_unreachable("unhandled specifier"); |
| } |
| |
| ValueOwnership getValueOwnership() const { |
| return getValueOwnershipForSpecifier(getSpecifier()); |
| } |
| |
| static ValueOwnership getValueOwnershipForSpecifier(Specifier specifier) { |
| switch (specifier) { |
| case Specifier::Default: |
| return ValueOwnership::Default; |
| case Specifier::InOut: |
| return ValueOwnership::InOut; |
| case Specifier::Shared: |
| return ValueOwnership::Shared; |
| case Specifier::Owned: |
| return ValueOwnership::Owned; |
| } |
| llvm_unreachable("unhandled specifier"); |
| } |
| |
| static Specifier |
| getParameterSpecifierForValueOwnership(ValueOwnership ownership) { |
| switch (ownership) { |
| case ValueOwnership::Default: |
| return Specifier::Default; |
| case ValueOwnership::Shared: |
| return Specifier::Shared; |
| case ValueOwnership::InOut: |
| return Specifier::InOut; |
| case ValueOwnership::Owned: |
| return Specifier::Owned; |
| } |
| 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; |
| } |
| }; |
| |
| /// 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; |
| SourceLoc EndLoc; |
| 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<unsigned>(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 *create(ASTContext &Context, DeclName Name, |
| SourceLoc StaticLoc, |
| StaticSpellingKind StaticSpelling, |
| SourceLoc SubscriptLoc, ParameterList *Indices, |
| SourceLoc ArrowLoc, TypeRepr *ElementTyR, |
| DeclContext *Parent, |
| GenericParamList *GenericParams); |
| |
| static SubscriptDecl *createImported(ASTContext &Context, DeclName Name, |
| SourceLoc SubscriptLoc, |
| ParameterList *Indices, |
| SourceLoc ArrowLoc, Type ElementTy, |
| DeclContext *Parent, ClangNode ClangN); |
| |
| /// \returns the way 'static'/'class' was spelled in the source. |
| StaticSpellingKind getStaticSpelling() const { |
| return static_cast<StaticSpellingKind>(Bits.SubscriptDecl.StaticSpelling); |
| } |
| |
| SourceLoc getStaticLoc() const { return StaticLoc; } |
| SourceLoc getSubscriptLoc() const { return getNameLoc(); } |
| |
| SourceLoc getStartLoc() const { |
| return getStaticLoc().isValid() ? getStaticLoc() : getSubscriptLoc(); |
| } |
| SourceLoc getEndLoc() const { return EndLoc; } |
| |
| void setEndLoc(SourceLoc sl) { EndLoc = sl; } |
| 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; |
| |
| 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<SubscriptDecl>( |
| 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 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; |
| } |
| }; |
| |
| /// Base class for function-like declarations. |
| class AbstractFunctionDecl : public GenericContext, public ValueDecl { |
| friend class NeedsNewVTableEntryRequest; |
| |
| public: |
| enum class BodyKind { |
| /// The function did not have a body in the source code file. |
| None, |
| |
| /// Function body is delayed, to be parsed later. |
| Unparsed, |
| |
| /// Function body is parsed and available as an AST subtree. |
| Parsed, |
| |
| /// Function body is not available, although it was written in the source. |
| Skipped, |
| |
| /// Function body will be synthesized on demand. |
| Synthesize, |
| |
| /// Function body is present and type-checked. |
| TypeChecked, |
| |
| /// This is a memberwise initializer that will be synthesized by SILGen. |
| MemberwiseInitializer, |
| |
| /// Function body text was deserialized from a .swiftmodule. |
| Deserialized |
| |
| // This enum currently needs to fit in a 3-bit bitfield. |
| }; |
| |
| BodyKind getBodyKind() const { |
| return BodyKind(Bits.AbstractFunctionDecl.BodyKind); |
| } |
| |
| struct BodySynthesizer { |
| std::pair<BraceStmt *, bool> (* 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<AutoDiffConfig> getDerivativeFunctionConfigurations(); |
| |
| /// Add the given derivative function configuration. |
| void addDerivativeFunctionConfiguration(AutoDiffConfig config); |
| |
| protected: |
| // If a function has a body at all, we have either a parsed body AST node or |
| // we have saved the end location of the unparsed body. |
| union { |
| /// This enum member is active if getBodyKind() is BodyKind::Parsed or |
| /// BodyKind::TypeChecked. |
| BraceStmt *Body; |
| |
| /// This enum member is active if getBodyKind() 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 or |
| /// BodyKind::Skipped. |
| SourceRange BodyRange; |
| }; |
| |
| friend class ParseAbstractFunctionBodyRequest; |
| friend class TypeCheckFunctionBodyRequest; |
| |
| CaptureInfo Captures; |
| |
| /// Location of the 'async' token. |
| SourceLoc AsyncLoc; |
| |
| /// Location of the 'throws' token. |
| SourceLoc ThrowsLoc; |
| |
| struct { |
| unsigned NeedsNewVTableEntryComputed : 1; |
| unsigned NeedsNewVTableEntry : 1; |
| } LazySemanticInfo = { }; |
| |
| AbstractFunctionDecl(DeclKind Kind, DeclContext *Parent, DeclName Name, |
| SourceLoc NameLoc, bool Async, SourceLoc AsyncLoc, |
| bool Throws, SourceLoc ThrowsLoc, |
| bool HasImplicitSelfDecl, |
| GenericParamList *GenericParams) |
| : GenericContext(DeclContextKind::AbstractFunctionDecl, Parent, GenericParams), |
| ValueDecl(Kind, Parent, Name, NameLoc), |
| Body(nullptr), AsyncLoc(AsyncLoc), ThrowsLoc(ThrowsLoc) { |
| setBodyKind(BodyKind::None); |
| Bits.AbstractFunctionDecl.HasImplicitSelfDecl = HasImplicitSelfDecl; |
| Bits.AbstractFunctionDecl.Overridden = false; |
| Bits.AbstractFunctionDecl.Async = Async; |
| Bits.AbstractFunctionDecl.Throws = Throws; |
| Bits.AbstractFunctionDecl.Synthesized = false; |
| Bits.AbstractFunctionDecl.HasSingleExpressionBody = false; |
| Bits.AbstractFunctionDecl.HasNestedTypeDeclarations = false; |
| } |
| |
| void setBodyKind(BodyKind K) { |
| Bits.AbstractFunctionDecl.BodyKind = unsigned(K); |
| } |
| |
| public: |
| void setHasSingleExpressionBody(bool Has = true) { |
| Bits.AbstractFunctionDecl.HasSingleExpressionBody = Has; |
| } |
| |
| bool hasSingleExpressionBody() const { |
| return Bits.AbstractFunctionDecl.HasSingleExpressionBody; |
| } |
| |
| Expr *getSingleExpressionBody() const; |
| void setSingleExpressionBody(Expr *NewBody); |
| |
| /// 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; } |
| |
| /// 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() || isAsyncHandler(); |
| } |
| |
| /// Returns true if the function is an @asyncHandler. |
| bool isAsyncHandler() const; |
| |
| /// Returns true if the function signature matches the form of an |
| /// @asyncHandler. |
| bool canBeAsyncHandler() const; |
| |
| /// Returns true if the function body throws. |
| bool hasThrows() const { return Bits.AbstractFunctionDecl.Throws; } |
| |
| // FIXME: Hack that provides names with keyword arguments for accessors. |
| DeclName getEffectiveFullName() const; |
| |
| /// Returns true if the function has a body written in the source file. |
| /// |
| /// Note that a true return value does not imply that the body was actually |
| /// parsed. |
| bool hasBody() const { |
| return getBodyKind() != BodyKind::None && |
| getBodyKind() != BodyKind::Skipped; |
| } |
| |
| /// 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 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 the body was skipped for this function. Function body |
| /// cannot be attached after this call. |
| void setBodySkipped(SourceRange bodyRange) { |
| // FIXME: Remove 'Parsed' from this list once we can always delay |
| // parsing bodies. The -experimental-skip-*-function-bodies options |
| // do currently skip parsing, unless disabled through other means in |
| // SourceFile::hasDelayedBodyParsing (eg. needing to build the full |
| // syntax tree due to -verify-syntax-tree). |
| assert(getBodyKind() == BodyKind::None || |
| getBodyKind() == BodyKind::Unparsed || |
| getBodyKind() == BodyKind::Parsed); |
| assert(bodyRange.isValid()); |
| BodyRange = bodyRange; |
| setBodyKind(BodyKind::Skipped); |
| } |
| |
| /// 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) { |
| setBody(S, BodyKind::Parsed); |
| } |
| |
| /// 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<BraceStmt *, bool> (* 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<ConstructorDecl>(this)); |
| setBodyKind(BodyKind::MemberwiseInitializer); |
| } |
| |
| /// 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<char> &scratch) const; |
| |
| void setBodyStringRepresentation(StringRef body) { |
| assert(getBodyKind() == BodyKind::None); |
| setBodyKind(BodyKind::Deserialized); |
| BodyStringRepresentation = body; |
| } |
| |
| bool isBodyTypeChecked() const { |
| return getBodyKind() == BodyKind::TypeChecked; |
| } |
| |
| bool isBodySkipped() const { |
| return getBodyKind() == BodyKind::Skipped; |
| } |
| |
| bool isMemberwiseInitializer() const { |
| return getBodyKind() == BodyKind::MemberwiseInitializer; |
| } |
| |
| /// For a method of a class, checks whether it will require a new entry in the |
| /// vtable. |
| bool needsNewVTableEntry() const; |
| |
| bool isSynthesized() const { |
| return Bits.AbstractFunctionDecl.Synthesized; |
| } |
| |
| void setSynthesized(bool value = true) { |
| Bits.AbstractFunctionDecl.Synthesized = value; |
| } |
| |
| 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 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 + patterns. |
| SourceRange getSignatureSourceRange() const; |
| |
| CaptureInfo getCaptureInfo() const { return Captures; } |
| void setCaptureInfo(CaptureInfo captures) { 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<AbstractFunctionDecl*>(this) |
| ->getImplicitSelfDecl(createIfNeeded); |
| } |
| ParamDecl *getImplicitSelfDecl(bool createIfNeeded=true); |
| |
| /// Retrieve the declaration that this method overrides, if any. |
| AbstractFunctionDecl *getOverriddenDecl() const { |
| return cast_or_null<AbstractFunctionDecl>(ValueDecl::getOverriddenDecl()); |
| } |
| |
| /// 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'. |
| Optional<ForeignErrorConvention> getForeignErrorConvention() const; |
| |
| /// If this is a foreign C function imported as a method, get the index of |
| /// the foreign parameter imported as `self`. If the function is imported |
| /// as a static method, `-1` is returned to represent the `self` parameter |
| /// being dropped altogether. `None` is returned for a normal function |
| /// or method. |
| Optional<int> 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'. |
| Optional<ForeignAsyncConvention> getForeignAsyncConvention() const; |
| |
| static bool classof(const Decl *D) { |
| return D->getKind() >= DeclKind::First_AbstractFunctionDecl && |
| D->getKind() <= DeclKind::Last_AbstractFunctionDecl; |
| } |
| |
| 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; |
| |
| using DeclContext::operator new; |
| using Decl::getASTContext; |
| }; |
| |
| class OperatorDecl; |
| |
| enum class SelfAccessKind : uint8_t { |
| NonMutating, |
| Mutating, |
| Consuming, |
| }; |
| |
| /// Diagnostic printing of \c SelfAccessKind. |
| llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, SelfAccessKind SAK); |
| |
| /// 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, |
| bool HasImplicitSelfDecl, |
| GenericParamList *GenericParams, DeclContext *Parent) |
| : AbstractFunctionDecl(Kind, Parent, |
| Name, NameLoc, |
| Async, AsyncLoc, |
| Throws, ThrowsLoc, |
| HasImplicitSelfDecl, GenericParams), |
| StaticLoc(StaticLoc), FuncLoc(FuncLoc) { |
| assert(!Name.getBaseName().isSpecial()); |
| |
| Bits.FuncDecl.StaticSpelling = static_cast<unsigned>(StaticSpelling); |
| |
| Bits.FuncDecl.ForcedStaticDispatch = false; |
| Bits.FuncDecl.SelfAccess = |
| static_cast<unsigned>(SelfAccessKind::NonMutating); |
| Bits.FuncDecl.SelfAccessComputed = false; |
| Bits.FuncDecl.IsStaticComputed = false; |
| Bits.FuncDecl.IsStatic = false; |
| Bits.FuncDecl.HasTopLevelLocalContextCaptures = 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, |
| GenericParamList *GenericParams, |
| DeclContext *Parent, |
| ClangNode ClangN); |
| |
| Optional<SelfAccessKind> getCachedSelfAccessKind() const { |
| if (Bits.FuncDecl.SelfAccessComputed) |
| return static_cast<SelfAccessKind>(Bits.FuncDecl.SelfAccess); |
| |
| return None; |
| } |
| |
| Optional<bool> getCachedIsStatic() const { |
| if (Bits.FuncDecl.IsStaticComputed) |
| return Bits.FuncDecl.IsStatic; |
| |
| return None; |
| } |
| |
| public: |
| /// Factory function only for use by deserialization. |
| static FuncDecl *createDeserialized(ASTContext &Context, |
| StaticSpellingKind StaticSpelling, |
| DeclName Name, bool Async, bool Throws, |
| 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, |
| GenericParamList *GenericParams, |
| ParameterList *BodyParams, TypeRepr *ResultTyR, |
| DeclContext *Parent); |
| |
| static FuncDecl *createImplicit(ASTContext &Context, |
| StaticSpellingKind StaticSpelling, |
| DeclName Name, SourceLoc NameLoc, bool Async, |
| bool Throws, GenericParamList *GenericParams, |
| ParameterList *BodyParams, Type FnRetType, |
| DeclContext *Parent); |
| |
| static FuncDecl *createImported(ASTContext &Context, SourceLoc FuncLoc, |
| DeclName Name, SourceLoc NameLoc, bool Async, |
| bool Throws, 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<StaticSpellingKind>(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 isNonMutating() const { |
| return getSelfAccessKind() == SelfAccessKind::NonMutating; |
| } |
| bool isConsuming() const { |
| return getSelfAccessKind() == SelfAccessKind::Consuming; |
| } |
| bool isCallAsFunctionMethod() const; |
| |
| bool isMainTypeMainMethod() const; |
| |
| /// Whether the given name is enqueue(partialTask:), which is used for |
| /// actors. |
| static bool isEnqueuePartialTaskName(ASTContext &ctx, DeclName name); |
| |
| /// Determine whether this function is the witness to the Actor protocol's |
| /// enqueue(partialTask:) operation within an actor. |
| bool isActorEnqueuePartialTaskWitness() const; |
| |
| SelfAccessKind getSelfAccessKind() const; |
| |
| void setSelfAccessKind(SelfAccessKind mod) { |
| Bits.FuncDecl.SelfAccess = static_cast<unsigned>(mod); |
| Bits.FuncDecl.SelfAccessComputed = true; |
| } |
| |
| SourceLoc getStaticLoc() const { return StaticLoc; } |
| SourceLoc getFuncLoc() const { return FuncLoc; } |
| |
| SourceLoc getStartLoc() const { |
| return StaticLoc.isValid() && !isa<AccessorDecl>(this) |
| ? 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; |
| |
| /// 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; |
| |
| void getLocalCaptures(SmallVectorImpl<CapturedValue> &Result) const { |
| return getCaptureInfo().getLocalCaptures(Result); |
| } |
| |
| ParamDecl **getImplicitSelfDeclStorage(); |
| |
| /// Get the supertype method this method overrides, if any. |
| FuncDecl *getOverriddenDecl() const { |
| return cast_or_null<FuncDecl>(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; |
| } |
| |
| 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<const Decl*>(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, |
| SourceLoc staticLoc, StaticSpellingKind staticSpelling, |
| bool throws, SourceLoc throwsLoc, |
| bool hasImplicitSelfDecl, GenericParamList *genericParams, |
| DeclContext *parent) |
| : FuncDecl(DeclKind::Accessor, |
| staticLoc, staticSpelling, /*func loc*/ declLoc, |
| /*name*/ Identifier(), /*name loc*/ declLoc, |
| /*Async=*/false, SourceLoc(), throws, throwsLoc, |
| hasImplicitSelfDecl, genericParams, parent), |
| AccessorKeywordLoc(accessorKeywordLoc), |
| Storage(storage) { |
| Bits.AccessorDecl.AccessorKind = unsigned(accessorKind); |
| } |
| |
| static AccessorDecl *createImpl(ASTContext &ctx, |
| SourceLoc declLoc, |
| SourceLoc accessorKeywordLoc, |
| AccessorKind accessorKind, |
| AbstractStorageDecl *storage, |
| SourceLoc staticLoc, |
| StaticSpellingKind staticSpelling, |
| bool throws, SourceLoc throwsLoc, |
| GenericParamList *genericParams, |
| DeclContext *parent, |
| ClangNode clangNode); |
| |
| Optional<bool> getCachedIsTransparent() const { |
| if (Bits.AccessorDecl.IsTransparentComputed) |
| return Bits.AccessorDecl.IsTransparent; |
| return None; |
| } |
| |
| friend class IsAccessorTransparentRequest; |
| |
| public: |
| static AccessorDecl *createDeserialized(ASTContext &ctx, |
| AccessorKind accessorKind, |
| AbstractStorageDecl *storage, |
| StaticSpellingKind staticSpelling, |
| bool throws, |
| GenericParamList *genericParams, |
| Type fnRetType, DeclContext *parent); |
| |
| static AccessorDecl *create(ASTContext &ctx, SourceLoc declLoc, |
| SourceLoc accessorKeywordLoc, |
| AccessorKind accessorKind, |
| AbstractStorageDecl *storage, |
| SourceLoc staticLoc, |
| StaticSpellingKind staticSpelling, |
| bool throws, SourceLoc throwsLoc, |
| GenericParamList *genericParams, |
| ParameterList *parameterList, |
| Type fnRetType, DeclContext *parent, |
| ClangNode clangNode = ClangNode()); |
| |
| 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 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"); |
| } |
| |
| /// \returns true if this is non-mutating due to applying a 'mutating' |
| /// attribute. For example a "mutating set" accessor. |
| bool isExplicitNonMutating() const; |
| |
| /// Is the accesor 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; |
| } |
| |
| static bool classof(const Decl *D) { |
| return D->getKind() == DeclKind::Accessor; |
| } |
| static bool classof(const AbstractFunctionDecl *D) { |
| return classof(static_cast<const Decl*>(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<EnumCaseDecl, EnumElementDecl *> { |
| friend TrailingObjects; |
| friend class Decl; |
| SourceLoc CaseLoc; |
| |
| EnumCaseDecl(SourceLoc CaseLoc, |
| ArrayRef<EnumElementDecl *> Elements, |
| DeclContext *DC) |
| : Decl(DeclKind::EnumCase, DC), |
| CaseLoc(CaseLoc) |
| { |
| Bits.EnumCaseDecl.NumElements = Elements.size(); |
| std::uninitialized_copy(Elements.begin(), Elements.end(), |
| getTrailingObjects<EnumElementDecl *>()); |
| } |
| SourceLoc getLocFromSource() const { return CaseLoc; } |
| |
| public: |
| static EnumCaseDecl *create(SourceLoc CaseLoc, |
| ArrayRef<EnumElementDecl*> Elements, |
| DeclContext *DC); |
| |
| /// Get the list of elements declared in this case. |
| ArrayRef<EnumElementDecl *> getElements() const { |
| return {getTrailingObjects<EnumElementDecl *>(), |
| Bits.EnumCaseDecl.NumElements}; |
| } |
| SourceRange getSourceRange() const; |
| |
| 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() : "_"; |
| } |
| |
| Type getArgumentInterfaceType() 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<EnumDecl>(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<IndirectAttr>(); |
| } |
| |
| /// 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 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 Throws, SourceLoc ThrowsLoc, |
| ParameterList *BodyParams, |
| GenericParamList *GenericParams, |
| DeclContext *Parent); |
| |
| static ConstructorDecl * |
| createImported(ASTContext &ctx, ClangNode clangNode, DeclName name, |
| SourceLoc constructorLoc, bool failable, |
| SourceLoc failabilityLoc, bool throws, SourceLoc throwsLoc, |
| 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<RequiredAttr>(); |
| } |
| |
| /// 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<ConstructorDecl>( |
| 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<const Decl*>(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; |
| |
| static bool classof(const Decl *D) { |
| return D->getKind() == DeclKind::Destructor; |
| } |
| static bool classof(const AbstractFunctionDecl *D) { |
| return classof(static_cast<const Decl*>(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<Relation*>(this + 1); |
| } |
| const Relation *getHigherThanBuffer() const { |
| return reinterpret_cast<const Relation*>(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<Relation> higherThan, |
| SourceLoc lowerThanLoc, ArrayRef<Relation> 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<Relation> higherThan, |
| SourceLoc lowerThanLoc, |
| ArrayRef<Relation> 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; |
| } |
| |
| ArrayRef<Relation> getHigherThan() const { |
| return { getHigherThanBuffer(), NumHigherThan }; |
| } |
| MutableArrayRef<Relation> getMutableHigherThan() { |
| return { getHigherThanBuffer(), NumHigherThan }; |
| } |
| |
| bool isLowerThanImplicit() const { |
| return LowerThanLoc.isInvalid(); |
| } |
| |
| /// Return the location of 'lowerThan' in: |
| /// lowerThan: MultiplicativePrecedence |
| SourceLoc getLowerThanLoc() const { |
| return LowerThanLoc; |
| } |
| |
| ArrayRef<Relation> getLowerThan() const { |
| return { getLowerThanBuffer(), NumLowerThan }; |
| } |
| MutableArrayRef<Relation> 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; |
| |
| ArrayRef<Located<Identifier>> Identifiers; |
| ArrayRef<NominalTypeDecl *> DesignatedNominalTypes; |
| SourceLoc getLocFromSource() const { return NameLoc; } |
| friend class Decl; |
| public: |
| OperatorDecl(DeclKind kind, DeclContext *DC, SourceLoc OperatorLoc, |
| Identifier Name, SourceLoc NameLoc, |
| ArrayRef<Located<Identifier>> Identifiers) |
| : Decl(kind, DC), OperatorLoc(OperatorLoc), NameLoc(NameLoc), name(Name), |
| Identifiers(Identifiers) {} |
| |
| OperatorDecl(DeclKind kind, DeclContext *DC, SourceLoc OperatorLoc, |
| Identifier Name, SourceLoc NameLoc, |
| ArrayRef<NominalTypeDecl *> DesignatedNominalTypes) |
| : Decl(kind, DC), OperatorLoc(OperatorLoc), NameLoc(NameLoc), name(Name), |
| DesignatedNominalTypes(DesignatedNominalTypes) {} |
| |
| /// 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("inavlid 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; } |
| |
| /// Get the list of identifiers after the colon in the operator declaration. |
| /// |
| /// This list includes the names of designated types. For infix operators, the |
| /// first item in the list is a precedence group instead. |
| /// |
| /// \todo These two purposes really ought to be in separate properties and the |
| /// designated type list should be of TypeReprs instead of Identifiers. |
| ArrayRef<Located<Identifier>> getIdentifiers() const { |
| return Identifiers; |
| } |
| |
| ArrayRef<NominalTypeDecl *> getDesignatedNominalTypes() const { |
| return DesignatedNominalTypes; |
| } |
| |
| void setDesignatedNominalTypes(ArrayRef<NominalTypeDecl *> nominalTypes) { |
| DesignatedNominalTypes = nominalTypes; |
| } |
| |
| 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; |
| |
| public: |
| InfixOperatorDecl(DeclContext *DC, SourceLoc operatorLoc, Identifier name, |
| SourceLoc nameLoc, SourceLoc colonLoc, |
| ArrayRef<Located<Identifier>> identifiers) |
| : OperatorDecl(DeclKind::InfixOperator, DC, operatorLoc, name, nameLoc, |
| identifiers), |
| ColonLoc(colonLoc) {} |
| |
| SourceLoc getEndLoc() const { |
| auto identifiers = getIdentifiers(); |
| if (identifiers.empty()) |
| return getNameLoc(); |
| |
| return identifiers.back().Loc; |
| } |
| |
| SourceRange getSourceRange() const { |
| return { getOperatorLoc(), getEndLoc() }; |
| } |
| |
| SourceLoc getColonLoc() const { return ColonLoc; } |
| |
| 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, |
| ArrayRef<Located<Identifier>> Identifiers) |
| : OperatorDecl(DeclKind::PrefixOperator, DC, OperatorLoc, Name, NameLoc, |
| Identifiers) {} |
| |
| PrefixOperatorDecl(DeclContext *DC, SourceLoc OperatorLoc, Identifier Name, |
| SourceLoc NameLoc, |
| ArrayRef<NominalTypeDecl *> designatedNominalTypes) |
| : OperatorDecl(DeclKind::PrefixOperator, DC, OperatorLoc, Name, NameLoc, |
| designatedNominalTypes) {} |
| |
| 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, |
| ArrayRef<Located<Identifier>> Identifiers) |
| : OperatorDecl(DeclKind::PostfixOperator, DC, OperatorLoc, Name, NameLoc, |
| Identifiers) {} |
| |
| PostfixOperatorDecl(DeclContext *DC, SourceLoc OperatorLoc, Identifier Name, |
| SourceLoc NameLoc, |
| ArrayRef<NominalTypeDecl *> designatedNominalTypes) |
| : OperatorDecl(DeclKind::PostfixOperator, DC, OperatorLoc, Name, NameLoc, |
| designatedNominalTypes) {} |
| |
| SourceRange getSourceRange() const { |
| return { getOperatorLoc(), getNameLoc() }; |
| } |
| |
| static bool classof(const Decl *D) { |
| return D->getKind() == DeclKind::PostfixOperator; |
| } |
| }; |
| |
| /// Represents a hole where a declaration should have been. |
| /// |
| /// Among other things, these are used to keep vtable layout consistent. |
| class MissingMemberDecl : public Decl { |
| DeclName Name; |
| |
| MissingMemberDecl(DeclContext *DC, DeclName name, |
| unsigned vtableEntries, |
| unsigned fieldOffsetVectorEntries) |
| : Decl(DeclKind::MissingMember, DC), Name(name) { |
| Bits.MissingMemberDecl.NumberOfVTableEntries = vtableEntries; |
| assert(getNumberOfVTableEntries() == vtableEntries && "not enough bits"); |
| Bits.MissingMemberDecl.NumberOfFieldOffsetVectorEntries = |
| fieldOffsetVectorEntries; |
| assert(getNumberOfFieldOffsetVectorEntries() == fieldOffsetVectorEntries |
| && "not enough bits"); |
| setImplicit(); |
| } |
| 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<ProtocolDecl>(DC) || isa<ClassDecl>(DC) && |
| "Only classes and protocols have vtable/witness table entries"); |
| assert(!hasStorage || !isa<ProtocolDecl>(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; |
| } |
| }; |
| |
| inline bool AbstractStorageDecl::isSettable(const DeclContext *UseDC, |
| const DeclRefExpr *base) const { |
| if (auto vd = dyn_cast<VarDecl>(this)) |
| return vd->isSettable(UseDC, base); |
| |
| auto sd = cast<SubscriptDecl>(this); |
| return sd->supportsMutation(); |
| } |
| |
| 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<ConstructorDecl>(this)->getImplicitSelfDeclStorage(); |
| case DeclKind::Destructor: |
| return cast<DestructorDecl>(this)->getImplicitSelfDeclStorage(); |
| case DeclKind::Func: |
| case DeclKind::Accessor: |
| return cast<FuncDecl>(this)->getImplicitSelfDeclStorage(); |
| } |
| } |
| |
| inline ParamDecl **FuncDecl::getImplicitSelfDeclStorage() { |
| if (!hasImplicitSelfDecl()) |
| return nullptr; |
| |
| if (!isa<AccessorDecl>(this)) { |
| assert(getKind() == DeclKind::Func && "no new kinds of functions"); |
| return reinterpret_cast<ParamDecl **>(this+1); |
| } |
| return reinterpret_cast<ParamDecl **>(static_cast<AccessorDecl*>(this)+1); |
| } |
| |
| inline DeclIterator &DeclIterator::operator++() { |
| Current = Current->NextDecl; |
| return *this; |
| } |
| |
| inline bool AbstractFunctionDecl::hasForcedStaticDispatch() const { |
| if (auto func = dyn_cast<FuncDecl>(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<AbstractStorageDecl>(this)) |
| return storage->isStatic(); |
| if (auto func = dyn_cast<FuncDecl>(this)) |
| return func->isStatic(); |
| return false; |
| } |
| |
| inline bool ValueDecl::isImportAsMember() const { |
| if (auto func = dyn_cast<AbstractFunctionDecl>(this)) |
| return func->isImportAsMember(); |
| return false; |
| } |
| |
| inline bool ValueDecl::hasCurriedSelf() const { |
| if (auto *afd = dyn_cast<AbstractFunctionDecl>(this)) |
| return afd->hasImplicitSelfDecl(); |
| if (isa<EnumElementDecl>(this)) |
| return true; |
| return false; |
| } |
| |
| inline bool ValueDecl::hasParameterList() const { |
| if (auto *eed = dyn_cast<EnumElementDecl>(this)) |
| return eed->hasAssociatedValues(); |
| return isa<AbstractFunctionDecl>(this) || isa<SubscriptDecl>(this); |
| } |
| |
| inline unsigned ValueDecl::getNumCurryLevels() const { |
| unsigned curryLevels = 0; |
| if (hasParameterList()) |
| curryLevels++; |
| if (hasCurriedSelf()) |
| curryLevels++; |
| return curryLevels; |
| } |
| |
| inline bool Decl::isPotentiallyOverridable() const { |
| if (isa<VarDecl>(this) || |
| isa<SubscriptDecl>(this) || |
| isa<FuncDecl>(this) || |
| isa<DestructorDecl>(this)) { |
| return getDeclContext()->getSelfClassDecl(); |
| } else { |
| return false; |
| } |
| } |
| |
| inline GenericParamKey::GenericParamKey(const GenericTypeParamDecl *d) |
| : Depth(d->getDepth()), Index(d->getIndex()) { } |
| |
| inline const GenericContext *Decl::getAsGenericContext() const { |
| switch (getKind()) { |
| default: return nullptr; |
| #define DECL(Id, Parent) // See previous line |
| #define GENERIC_DECL(Id, Parent) \ |
| case DeclKind::Id: \ |
| return static_cast<const Id##Decl*>(this); |
| #include "swift/AST/DeclNodes.def" |
| } |
| } |
| |
| inline bool DeclContext::classof(const Decl *D) { |
| switch (D->getKind()) { // |
| default: return false; |
| #define DECL(ID, PARENT) // See previous line |
| #define CONTEXT_DECL(ID, PARENT) \ |
| case DeclKind::ID: return true; |
| #include "swift/AST/DeclNodes.def" |
| } |
| } |
| |
| inline DeclContext *DeclContext::castDeclToDeclContext(const Decl *D) { |
| // XXX -- ModuleDecl is not defined in Decl.h, but because DeclContexts |
| // preface decls in memory, any DeclContext type will due. |
| const DeclContext *DC = static_cast<const ExtensionDecl*>(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<DeclContext *>(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, or nullputr if there |
| /// is none. |
| ParameterList *getParameterList(ValueDecl *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(const ValueDecl *source, unsigned index); |
| |
| void simple_display(llvm::raw_ostream &out, |
| OptionSet<NominalTypeDecl::LookupDirectFlags> 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<const Decl *>(decl)); |
| } |
| |
| /// Display NominalTypeDecls. |
| inline void simple_display(llvm::raw_ostream &out, |
| const NominalTypeDecl *decl) { |
| simple_display(out, static_cast<const Decl *>(decl)); |
| } |
| |
| inline void simple_display(llvm::raw_ostream &out, |
| const AssociatedTypeDecl *decl) { |
| simple_display(out, static_cast<const Decl *>(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 <typename T> |
| inline typename std::enable_if<std::is_same<T, GenericContext>::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<const Decl *>(ext)); |
| } |
| |
| /// Extract the source location from the given declaration. |
| inline SourceLoc extractNearestSourceLoc(const GenericTypeDecl *type) { |
| return extractNearestSourceLoc(static_cast<const Decl *>(type)); |
| } |
| |
| /// Extract the source location from the given declaration. |
| inline SourceLoc extractNearestSourceLoc(const NominalTypeDecl *type) { |
| return extractNearestSourceLoc(static_cast<const Decl *>(type)); |
| } |
| |
| /// Extract the source location from the given declaration. |
| inline SourceLoc extractNearestSourceLoc(const AbstractFunctionDecl *func) { |
| return extractNearestSourceLoc(static_cast<const Decl *>(func)); |
| } |
| |
| } // end namespace swift |
| |
| #endif |