//===--- DeclContext.h - Swift Language Context ASTs ------------*- C++ -*-===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// // // This file defines the DeclContext class. A DeclContext is the semantic // construct that a declaration belongs to, such as the enclosing // AbstractClosureExpr or declaration. // //===----------------------------------------------------------------------===// #ifndef SWIFT_DECLCONTEXT_H #define SWIFT_DECLCONTEXT_H #include "swift/AST/ASTAllocated.h" #include "swift/AST/AvailabilityDomain.h" #include "swift/AST/Identifier.h" #include "swift/AST/LookupKinds.h" #include "swift/AST/ResilienceExpansion.h" #include "swift/AST/TypeAlignments.h" #include "swift/Basic/Debug.h" #include "swift/Basic/Fingerprint.h" #include "swift/Basic/LLVM.h" #include "swift/Basic/STLExtras.h" #include "swift/Basic/SourceLoc.h" #include "llvm/ADT/PointerEmbeddedInt.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/Support/raw_ostream.h" #include #include namespace llvm { class raw_ostream; } namespace swift { class AbstractFunctionDecl; class GenericEnvironment; class ASTContext; class ASTWalker; class CanType; class Decl; class DeclContext; class EnumDecl; class ExtensionDecl; class Expr; class GenericParamList; class LazyMemberLoader; class GenericContext; class GenericSignature; class GenericTypeParamDecl; class GenericTypeParamType; class InfixOperatorDecl; class InfixOperatorLookupResult; enum class PlatformKind: uint8_t; class PrecedenceGroupDecl; class ProtocolDecl; class Requirement; class SourceFile; class Type; class ModuleDecl; class PackageUnit; class GenericTypeDecl; class NominalTypeDecl; class PrecedenceGroupLookupResult; class PostfixOperatorDecl; class PrefixOperatorDecl; class ProtocolConformance; class ValueDecl; class VarDecl; class Initializer; class ClassDecl; class SerializedAbstractClosureExpr; class SerializedTopLevelCodeDecl; class StructDecl; class AccessorDecl; class ClosureExpr; template struct AvailableDuringLoweringDeclFilter; namespace serialization { using DeclID = llvm::PointerEmbeddedInt; } enum class DeclContextKind : unsigned { AbstractClosureExpr, Initializer, TopLevelCodeDecl, SubscriptDecl, EnumElementDecl, AbstractFunctionDecl, SerializedAbstractClosure, SerializedTopLevelCodeDecl, MacroDecl, Last_LocalDeclContextKind = MacroDecl, Package, Module, FileUnit, GenericTypeDecl, ExtensionDecl, Last_DeclContextKind = ExtensionDecl }; /// Describes the kind of a particular conformance. /// /// The following code involves conformances of the three different kinds: /// /// protocol P { } /// protocol P2 : P { } /// /// class Super : P2 { } /// class Sub : Super { } /// /// `Super` conforms to `P2` via an explicit conformance, /// specified on the class declaration itself. /// /// `Super` conforms to `P` via an implied conformance, whose /// origin is the explicit conformance to `P2`. /// /// `Sub` conforms to `P2` and `P` via inherited conformances, /// which link back to the conformances described above. /// /// The enumerators are ordered in terms of decreasing preference: /// an inherited conformance is best, followed by explicit /// conformances, then synthesized and implied conformances. Earlier /// conformance kinds supersede later conformance kinds, possibly with a /// diagnostic (e.g., if an inherited conformance supersedes an /// explicit conformance). /// /// - Important: The raw values of these cases are relied upon by /// `declared_protocol_conformance_here`. /// - If you add a new case, give it an explicit raw value. /// - If you change the cases, make sure they remain in sync with the /// aforementioned diagnostic. enum class ConformanceEntryKind : unsigned { /// Inherited from a superclass conformance. Inherited = 0, /// Explicitly specified. Explicit = 1, /// The conformance is generated by a macro that has not been /// expanded yet. PreMacroExpansion = 2, /// Implicitly synthesized. Synthesized = 3, /// Implied by an explicitly-specified conformance. Implied = 4, Last_Kind = Implied }; /// Describes the kind of conformance lookup desired. enum class ConformanceLookupKind : unsigned { /// All conformances. All, /// Only the explicit conformance. OnlyExplicit, /// All conformances except for inherited ones. NonInherited, /// All conformances except structurally-derived conformances, of which /// Sendable is the only one. NonStructural, }; /// Describes a diagnostic for a conflict between two protocol /// conformances. struct ConformanceDiagnostic { /// The protocol with conflicting conformances. ProtocolDecl *Protocol; /// The location at which the diagnostic should occur. SourceLoc Loc; /// The kind of conformance that was superseded. ConformanceEntryKind Kind; /// The explicitly-specified protocol whose conformance implied the /// conflicting conformance. ProtocolDecl *ExplicitProtocol; /// The declaration context that declares the existing conformance. DeclContext *ExistingDC; /// The kind of existing conformance. ConformanceEntryKind ExistingKind; /// The explicitly-specified protocol whose conformance implied the /// existing conflicting conformance. ProtocolDecl *ExistingExplicitProtocol; }; /// Used in diagnostic %selects. struct FragileFunctionKind { enum Kind : unsigned { Transparent, Inlinable, AlwaysEmitIntoClient, DefaultArgument, PropertyInitializer, BackDeploy, None }; Kind kind = None; friend bool operator==(FragileFunctionKind lhs, FragileFunctionKind rhs) { return lhs.kind == rhs.kind; } /// Casts to `unsigned` for diagnostic %selects. unsigned getSelector() { return static_cast(kind); } }; /// A DeclContext is an AST object which acts as a semantic container /// for declarations. As a policy matter, we currently define /// contexts broadly: a lambda expression in a function is a new /// DeclContext, but a new brace statement is not. There's no /// particular mandate for this, though. /// /// Please note that DeclContext assumes that it prefaces AST type hierarchies /// and therefore can safely access trailing memory. If you need to create a /// macro context, please see GenericContext for how to minimize new entries in /// the ASTHierarchy enum below. /// /// The hierarchy between DeclContext subclasses is set in their ctors. For /// example, FileUnit ctor takes ModuleDecl as its parent DeclContext. The /// hierarchy from the most to least restrictive order is: /// decl/expr (e.g. ClassDecl) -> FileUnit -> ModuleDecl -> PackageUnit -> nullptr /// /// There's an exception, however; the parent of ModuleDecl is set nullptr, not /// set to PackageUnit; ModuleDecl has a pointer to PackageUnit as its field, /// and it is treated as the enclosing scope of ModuleDecl. class alignas(1 << DeclContextAlignInBits) DeclContext : public ASTAllocated { enum class ASTHierarchy : unsigned { Decl, Expr, FileUnit, Package, Initializer, SerializedAbstractClosure, SerializedTopLevelCodeDecl, // If you add a new AST hierarchies, then update the static_assert() below. }; static_assert(unsigned(ASTHierarchy::SerializedTopLevelCodeDecl) < (1 << DeclContextAlignInBits), "ASTHierarchy exceeds bits available"); llvm::PointerIntPair ParentAndKind; /// Change the parent of this context. This should only be used /// very carefully. void setParent(DeclContext *parent) { ParentAndKind.setPointer(parent); } friend class Initializer; // uses setParent friend class AutoClosureExpr; // uses setParent friend class AbstractClosureExpr; // uses setParent friend class Decl; // uses setParent template friend struct ::llvm::CastInfo; // See swift/AST/Decl.h static DeclContext *castDeclToDeclContext(const Decl *D); /// If this DeclContext is a GenericType declaration or an /// extension thereof, return the GenericTypeDecl. GenericTypeDecl *getSelfTypeDecl() const; static ASTHierarchy getASTHierarchyFromKind(DeclContextKind Kind) { switch (Kind) { case DeclContextKind::AbstractClosureExpr: return ASTHierarchy::Expr; case DeclContextKind::Initializer: return ASTHierarchy::Initializer; case DeclContextKind::SerializedAbstractClosure: return ASTHierarchy::SerializedAbstractClosure; case DeclContextKind::SerializedTopLevelCodeDecl: return ASTHierarchy::SerializedTopLevelCodeDecl; case DeclContextKind::FileUnit: return ASTHierarchy::FileUnit; case DeclContextKind::Package: return ASTHierarchy::Package; case DeclContextKind::Module: case DeclContextKind::TopLevelCodeDecl: case DeclContextKind::AbstractFunctionDecl: case DeclContextKind::SubscriptDecl: case DeclContextKind::EnumElementDecl: case DeclContextKind::GenericTypeDecl: case DeclContextKind::ExtensionDecl: case DeclContextKind::MacroDecl: return ASTHierarchy::Decl; } llvm_unreachable("Unhandled DeclContextKind"); } public: LLVM_READONLY Decl *getAsDecl() { return ParentAndKind.getInt() == ASTHierarchy::Decl ? reinterpret_cast(this + 1) : nullptr; } const Decl *getAsDecl() const { return const_cast(this)->getAsDecl(); } DeclContext(DeclContextKind Kind, DeclContext *Parent) : ParentAndKind(Parent, getASTHierarchyFromKind(Kind)) { // if Module kind, it may (or may not) have Package as its parent if (Kind != DeclContextKind::Package && Kind != DeclContextKind::Module) assert(Parent != nullptr && "DeclContext must have a parent context"); } /// Returns the kind of context this is. DeclContextKind getContextKind() const; /// Returns whether this context asynchronous bool isAsyncContext() const; /// Returns whether this context has value semantics. bool hasValueSemantics() const; /// Returns whether this context is an extension constrained to a class type. bool isClassConstrainedProtocolExtension() const; /// Determines whether this context is itself a local scope in a /// code block. A context that appears in such a scope, like a /// local type declaration, does not itself become a local context. bool isLocalContext() const { return getContextKind() <= DeclContextKind::Last_LocalDeclContextKind; } /// \returns true if this is a package context LLVM_READONLY bool isPackageContext() const; // see swift/AST/Module.h /// isModuleContext - Return true if this is a subclass of Module. LLVM_READONLY bool isModuleContext() const; // see swift/AST/Module.h /// \returns true if this is a context with module-wide scope, e.g. a module /// or a source file. LLVM_READONLY bool isModuleScopeContext() const; // see swift/AST/Module.h /// \returns true if this is a type context, e.g., a struct, a class, an /// enum, a protocol, or an extension. LLVM_READONLY bool isTypeContext() const; /// If this DeclContext is a NominalType declaration or an /// extension thereof, return the NominalTypeDecl. LLVM_READONLY NominalTypeDecl *getSelfNominalTypeDecl() const; /// If this DeclContext is a class, or an extension on a class, return the /// ClassDecl, otherwise return null. LLVM_READONLY ClassDecl *getSelfClassDecl() const; /// If this DeclContext is an enum, or an extension on an enum, return the /// EnumDecl, otherwise return null. LLVM_READONLY EnumDecl *getSelfEnumDecl() const; /// If this DeclContext is a struct, or an extension on a struct, return the /// StructDecl, otherwise return null. LLVM_READONLY StructDecl *getSelfStructDecl() const; /// If this DeclContext is a protocol, or an extension on a /// protocol, return the ProtocolDecl, otherwise return null. LLVM_READONLY ProtocolDecl *getSelfProtocolDecl() const; /// If this DeclContext is a protocol extension, return the extended protocol. LLVM_READONLY ProtocolDecl *getExtendedProtocolDecl() const; /// If this DeclContext is the initializer expression of a global or instance /// property, return the VarDecl, otherwise return null. LLVM_READONLY VarDecl *getNonLocalVarDecl() const; /// Gets the type being declared by this context. /// /// - Generic types return a bound generic type using archetypes. /// - Non-type contexts return a null type. Type getDeclaredTypeInContext() const; /// Gets the type being declared by this context. /// /// - Generic types return a bound generic type using interface types. /// - Non-type contexts return a null type. Type getDeclaredInterfaceType() const; /// Get the type of `self` in this context. /// /// - Protocol types return the `Self` archetype. /// - Everything else falls back on getDeclaredTypeInContext(). Type getSelfTypeInContext() const; /// Get the type of `self` in this context. /// /// - Protocol types return the `Self` interface type. /// - Everything else falls back on getDeclaredInterfaceType(). Type getSelfInterfaceType() const; /// Visit the generic parameter list of every outer context, innermost first. void forEachGenericContext( llvm::function_ref fn) const; /// Returns the depth of this generic context, or in other words, /// the number of nested generic contexts minus one. /// /// This is (unsigned)-1 if none of the outer contexts are generic. unsigned getGenericContextDepth() const; /// Retrieve the innermost generic signature of this context or any /// of its parents. GenericSignature getGenericSignatureOfContext() const; /// Retrieve the innermost archetypes of this context or any /// of its parents. GenericEnvironment *getGenericEnvironmentOfContext() const; /// Map an interface type to a contextual type within this context. Type mapTypeIntoContext(Type type) const; /// Returns this or the first local parent context, or nullptr if it is not /// contained in one. LLVM_READONLY DeclContext *getLocalContext(); const DeclContext *getLocalContext() const { return const_cast(this)->getLocalContext(); } /// Returns the innermost method context. /// /// This routine looks through closure, initializer, and local function /// contexts to find the innermost method (including constructors and /// destructors). /// /// \returns the innermost method, or null if there is no such method. LLVM_READONLY AbstractFunctionDecl *getInnermostMethodContext(); const AbstractFunctionDecl *getInnermostMethodContext() const { return const_cast(this)->getInnermostMethodContext(); } /// Returns the innermost accessor context that belongs to a property. /// /// This routine looks through closure, initializer, and local function /// contexts to find the innermost accessor declaration. /// /// \returns the innermost accessor, or null if there is no such context. LLVM_READONLY AccessorDecl *getInnermostPropertyAccessorContext(); const AccessorDecl *getInnermostPropertyAccessorContext() const { return const_cast(this)->getInnermostPropertyAccessorContext(); } /// Returns the innermost type context. /// /// This routine looks through closure, initializer, and local function /// contexts to find the innermost type context -- nominal type or /// extension. LLVM_READONLY DeclContext *getInnermostTypeContext(); const DeclContext *getInnermostTypeContext() const { return const_cast(this)->getInnermostTypeContext(); } /// Returns the innermost context that is a declaration. /// /// This routine looks through contexts to find the innermost /// declaration context that is itself a declaration. LLVM_READONLY Decl *getInnermostDeclarationDeclContext(); const Decl *getInnermostDeclarationDeclContext() const { return const_cast(this)->getInnermostDeclarationDeclContext(); } /// Returns the topmost context that is a declaration, excluding ModuleDecl. /// /// This may return itself. LLVM_READONLY Decl *getTopmostDeclarationDeclContext(); const Decl *getTopmostDeclarationDeclContext() const { return const_cast(this)->getTopmostDeclarationDeclContext(); } /// This routine looks through closure, initializer, and local function /// contexts to find the outermost function declaration. /// /// \returns the outermost function, or null if there is no such context. LLVM_READONLY DeclContext *getOutermostFunctionContext(); const DeclContext *getOutermostFunctionContext() const { return const_cast(this)->getOutermostFunctionContext(); } /// Returns the innermost context that is an AbstractFunctionDecl whose /// body has been skipped. LLVM_READONLY DeclContext *getInnermostSkippedFunctionContext(); const DeclContext *getInnermostSkippedFunctionContext() const { return const_cast(this)->getInnermostSkippedFunctionContext(); } /// Returns the innermost ClosureExpr context that can propagate its captures /// to this DeclContext. LLVM_READONLY ClosureExpr *getInnermostClosureForCaptures(); const ClosureExpr *getInnermostClosureForCaptures() const { return const_cast(this)->getInnermostClosureForCaptures(); } /// Returns the semantic parent of this context. A context has a /// parent if and only if it is not a module context. DeclContext *getParent() const { return ParentAndKind.getPointer(); } /// Returns the semantic parent for purposes of name lookup. DeclContext *getParentForLookup() const; /// Return true if this is a child of the specified other decl context. bool isChildContextOf(const DeclContext *Other) const { if (this == Other) return false; for (const DeclContext *CurContext = this; CurContext; CurContext = CurContext->getParent()) if (CurContext == Other) return true; return false; } /// Returns the package unit of this context. /// \p lookupIfNotCurrent If the current decl context is not PackageUnit, look /// it up via parent module LLVM_READONLY PackageUnit *getPackageContext(bool lookupIfNotCurrent = false) const; /// Returns the module context that contains this context. LLVM_READONLY ModuleDecl *getParentModule() const; /// Returns the module scope context that contains this context. /// /// This is either a \c Module or a \c FileUnit. LLVM_READONLY DeclContext *getModuleScopeContext() const; /// If this DeclContext is an \c \@_objcImplementation extension, returns the /// \c DeclContext for the Objective-C declaration it implements. Otherwise /// returns \c this. DeclContext *getImplementedObjCContext() const; /// Returns the source file that contains this context, or null if this /// is not within a source file. LLVM_READONLY SourceFile *getParentSourceFile() const; /// Returns the "outermost" source file that contains this context, /// looking through any source files for generated code, such as /// macro expansions. LLVM_READONLY SourceFile *getOutermostParentSourceFile() const; /// Returns true if the source file that contains the context is a /// `.swiftinterface` file. LLVM_READONLY bool isInSwiftinterface() const; /// Determine whether this declaration context is generic, meaning that it or /// any of its parents have generic parameters. bool isGenericContext() const; /// Determine whether the innermost context is generic. bool isInnermostContextGeneric() const; /// Determine whether this or any parent context is a `@_specialize` extension /// context. bool isInSpecializeExtensionContext() const; /// Returns whether this declaration context is a protocol in an unsupported /// context. bool isUnsupportedNestedProtocol() const; /// Get the most optimal resilience expansion for code in this context. /// If the body is able to be inlined into functions in other resilience /// domains, this ensures that only sufficiently-conservative access patterns /// are used. ResilienceExpansion getResilienceExpansion() const; /// Get the fragile function kind for the code in this context, which /// is used for diagnostics. FragileFunctionKind getFragileFunctionKind() const; /// Returns true if this context may possibly contain members visible to /// AnyObject dynamic lookup. bool mayContainMembersAccessedByDynamicLookup() const; /// Extensions are only allowed at the level in a file /// FIXME: do this for Protocols, too someday bool canBeParentOfExtension() const; /// Look for the set of declarations with the given name within a type, /// its extensions and, optionally, its supertypes. /// /// This routine performs name lookup within a given type, its extensions /// and, optionally, its supertypes and their extensions, from the perspective /// of the current DeclContext. It can eliminate non-visible, hidden, and /// overridden declarations from the result set. It does not, however, perform /// any filtering based on the semantic usefulness of the results. /// /// \param type The type to look into. /// /// \param member The member to search for. /// /// \param options Options that control name lookup, based on the /// \c NL_* constants in \c NameLookupOptions. /// /// \param[out] decls Will be populated with the declarations found by name /// lookup. /// /// \returns true if anything was found. bool lookupQualified(Type type, DeclNameRef member, SourceLoc loc, NLOptions options, SmallVectorImpl &decls) const; /// Look for the set of declarations with the given name within the /// given set of nominal type declarations. /// /// \param types The type declarations to look into. /// /// \param member The member to search for. /// /// \param options Options that control name lookup, based on the /// \c NL_* constants in \c NameLookupOptions. /// /// \param[out] decls Will be populated with the declarations found by name /// lookup. /// /// \returns true if anything was found. bool lookupQualified(ArrayRef types, DeclNameRef member, SourceLoc loc, NLOptions options, SmallVectorImpl &decls) const; /// Perform qualified lookup for the given member in the given module. bool lookupQualified(ModuleDecl *module, DeclNameRef member, SourceLoc loc, NLOptions options, SmallVectorImpl &decls) const; /// Look up all Objective-C methods with the given selector visible /// in the enclosing module. void lookupAllObjCMethods( ObjCSelector selector, SmallVectorImpl &results) const; /// Look up the custom availability domains matching the given identifier that /// are visible from this context. void lookupAvailabilityDomains(Identifier identifier, SmallVectorImpl &results) const; /// Looks up an infix operator with a given \p name. /// /// This returns a vector of results, as it's possible to find multiple infix /// operators with different precedence groups. InfixOperatorLookupResult lookupInfixOperator(Identifier name) const; /// Looks up an prefix operator with a given \p name. /// /// If multiple results are found, one is chosen in a stable manner, as /// prefix operator decls cannot differ other than in name. If no results are /// found, returns \c nullptr. PrefixOperatorDecl *lookupPrefixOperator(Identifier name) const; /// Looks up an postfix operator with a given \p name. /// /// If multiple results are found, one is chosen in a stable manner, as /// postfix operator decls cannot differ other than in name. If no results are /// found, returns \c nullptr. PostfixOperatorDecl *lookupPostfixOperator(Identifier name) const; /// Looks up a precedence group with a given \p name. PrecedenceGroupLookupResult lookupPrecedenceGroup(Identifier name) const; /// Returns true if the parent module of \p decl is imported by this context. bool isDeclImported(const Decl *decl) const; /// Return the ASTContext for a specified DeclContext by /// walking up to the enclosing module and returning its ASTContext. LLVM_READONLY ASTContext &getASTContext() const; /// Retrieves a list of separately imported overlays which are shadowing /// \p declaring. If any \p overlays are returned, qualified lookups into /// \p declaring should be performed into \p overlays instead; since they /// are overlays, they will re-export \p declaring, but will also augment it /// with additional symbols. void getSeparatelyImportedOverlays( ModuleDecl *declaring, SmallVectorImpl &overlays) const; /// Retrieve the syntactic depth of this declaration context, i.e., /// the number of non-module-scoped contexts. /// /// For an extension of a nested type, the extension is depth 1. unsigned getSyntacticDepth() const; /// Retrieve the semantic depth of this declaration context, i.e., /// the number of non-module-scoped contexts. /// /// For an extension of a nested type, the depth of the nested type itself /// is also included. unsigned getSemanticDepth() const; /// Returns if this extension is always available on the current deployment /// target. Used for conformance lookup disambiguation. bool isAlwaysAvailableConformanceContext() const; /// \returns true if traversal was aborted, false otherwise. bool walkContext(ASTWalker &Walker); SWIFT_DEBUG_DUMPER(dumpContext()); unsigned printContext(llvm::raw_ostream &OS, unsigned indent = 0, bool onlyAPartialLine = false) const; // Some Decls are DeclContexts, but not all. See swift/AST/Decl.h static bool classof(const Decl *D); }; /// An iterator that walks through a list of declarations stored /// within some iterable declaration context. class DeclIterator { Decl *Current; public: typedef std::forward_iterator_tag iterator_category; typedef Decl *value_type; typedef Decl *reference; typedef Decl *pointer; // Non-standard but convenient typedef std::ptrdiff_t difference_type; DeclIterator(Decl *current = nullptr) : Current(current) { } reference operator*() const { return Current; } pointer operator->() const { return Current; } DeclIterator &operator++(); DeclIterator operator++(int) { DeclIterator old = *this; ++*this; return old; } friend bool operator==(DeclIterator lhs, DeclIterator rhs) { return lhs.Current == rhs.Current; } friend bool operator!=(DeclIterator lhs, DeclIterator rhs) { return !(lhs == rhs); } }; /// The range of declarations stored within an iterable declaration /// context. using DeclRange = iterator_range; /// The kind of an \c IterableDeclContext. enum class IterableDeclContextKind : uint8_t { NominalTypeDecl = 0, ExtensionDecl, }; /// A declaration context that tracks the declarations it (directly) /// owns and permits iteration over them. /// /// Note that an iterable declaration context must inherit from both /// \c IterableDeclContext and \c DeclContext. class IterableDeclContext { /// The first declaration in this context along with a bit indicating whether /// the members of this context will be lazily produced. mutable llvm::PointerIntPair FirstDeclAndLazyMembers; /// The last declaration in this context, used for efficient insertion, /// along with the kind of iterable declaration context. mutable llvm::PointerIntPair LastDeclAndKind; /// The DeclID this IDC was deserialized from, if any. Used for named lazy /// member loading, as a key when doing lookup in this IDC. serialization::DeclID SerialID; /// Whether we have already added the parsed members into the context. unsigned AddedParsedMembers : 1; /// Whether delayed parsing detected a possible operator definition /// while skipping the body of this context. unsigned HasOperatorDeclarations : 1; /// Whether delayed parsing detect a possible nested class definition /// while skipping the body of this context. unsigned HasNestedClassDeclarations : 1; /// Whether we were inside a freestanding macro argument when we were parsed. /// We must restore this when delayed parsing the body. unsigned InFreestandingMacroArgument : 1; /// Whether delayed parsing detect a possible custom derivative definition /// while skipping the body of this context. unsigned HasDerivativeDeclarations : 1; /// Members of a decl are deserialized lazily. This is set when /// deserialization of all members is done, regardless of errors. unsigned DeserializedMembers : 1; /// Deserialization errors are attempted to be recovered later or /// silently dropped due to `EnableDeserializationRecovery` being /// on by default. The following flag is set when deserializing /// members fails regardless of the `EnableDeserializationRecovery` /// value and is used to prevent decl containing such members from /// being accessed non-resiliently. unsigned HasDeserializeMemberError : 1; /// Used to track whether members of this decl and their respective /// members were checked for deserialization errors recursively. unsigned CheckedForDeserializeMemberError : 1; template friend struct ::llvm::CastInfo; static IterableDeclContext *castDeclToIterableDeclContext(const Decl *D); friend class LookupAllConformancesInContextRequest; /// Retrieve the \c ASTContext in which this iterable context occurs. ASTContext &getASTContext() const; void setCheckedForDeserializeMemberError(bool checked) { CheckedForDeserializeMemberError = checked; } bool checkedForDeserializeMemberError() const { return CheckedForDeserializeMemberError; } public: IterableDeclContext(IterableDeclContextKind kind) : LastDeclAndKind(nullptr, kind) { AddedParsedMembers = 0; HasOperatorDeclarations = 0; HasDerivativeDeclarations = 0; HasNestedClassDeclarations = 0; InFreestandingMacroArgument = 0; DeserializedMembers = 0; HasDeserializeMemberError = 0; CheckedForDeserializeMemberError = 0; } /// Determine the kind of iterable context we have. IterableDeclContextKind getIterableContextKind() const { return LastDeclAndKind.getInt(); } SourceRange getBraces() const; bool hasUnparsedMembers() const; void setDeserializedMembers(bool deserialized) { DeserializedMembers = deserialized; } bool didDeserializeMembers() const { return DeserializedMembers; } void setHasDeserializeMemberError(bool hasError) { HasDeserializeMemberError = hasError; } bool hasDeserializeMemberError() const { return HasDeserializeMemberError; } /// This recursively checks whether members of this decl and their respective /// members were deserialized correctly and emits a diagnostic in case of an error. /// Requires accessing module and this decl's module are in the same package, /// and this decl's module has package optimization enabled. void checkDeserializeMemberErrorInPackage(ModuleDecl *accessingModule); bool maybeHasOperatorDeclarations() const { return HasOperatorDeclarations; } void setMaybeHasOperatorDeclarations() { assert(hasUnparsedMembers()); HasOperatorDeclarations = 1; } bool maybeHasNestedClassDeclarations() const { return HasNestedClassDeclarations; } void setMaybeHasNestedClassDeclarations() { assert(hasUnparsedMembers()); HasNestedClassDeclarations = 1; } bool inFreestandingMacroArgument() const { return InFreestandingMacroArgument; } void setInFreestandingMacroArgument() { assert(hasUnparsedMembers()); InFreestandingMacroArgument = 1; } bool maybeHasDerivativeDeclarations() const { return HasDerivativeDeclarations; } void setMaybeHasDerivativeDeclarations() { assert(hasUnparsedMembers()); HasDerivativeDeclarations = 1; } /// Retrieve the current set of members in this context. /// /// NOTE: This operation is an alias of \c getCurrentMembers() that is considered /// deprecated. Most clients should not use this or \c getCurrentMembers(), but /// instead should use one of the projections of members that provides a semantic /// view, e.g., \c getParsedMembers(), \c getABIMembers(), \c getAllMembers(), and so /// on. DeclRange getMembers() const; /// Retrieve the current set of members in this context, without triggering /// the creation of new members via code synthesis, macro expansion, etc. /// /// This operation should only be used in narrow places where any side-effect /// producing operations have been done earlier. DeclRange getCurrentMembers() const; /// Get the members that were syntactically present in the source code, /// and will not contain any members that are implicitly synthesized by /// the implementation. ArrayRef getParsedMembers() const; /// Get all of the members within this context that can affect ABI, including /// any implicitly-synthesized members. /// /// The resulting list of members will be stable across translation units. ArrayRef getABIMembers() const; /// Get all of the members within this context, including any /// implicitly-synthesized members. /// /// The resulting list of members will be stable across translation units. ArrayRef getAllMembers() const; /// Retrieve the set of members in this context without loading any from the /// associated lazy loader; this should only be used as part of implementing /// abstractions on top of member loading, such as a name lookup table. DeclRange getCurrentMembersWithoutLoading() const; /// Return the context that contains the actual implemented members. This /// is \em usually just \c this, but if \c this is an imported class or /// category, it may be a Swift extension instead. IterableDeclContext *getImplementationContext(); /// Add a member to this context. /// /// If the hint decl is specified, the new decl is inserted immediately /// after the hint. /// /// If insertAtHead is set, the new decl is inserted at the beginning of /// the list. /// /// Otherwise, it is inserted at the end. void addMember(Decl *member, Decl *hint = nullptr, bool insertAtHead = false); /// Add a member in the right place to preserve source order. This should /// only be called from the code completion delayed parsing path. void addMemberPreservingSourceOrder(Decl *member); /// Check whether there are lazily-loaded members. bool hasLazyMembers() const { return FirstDeclAndLazyMembers.getInt(); } /// Setup the loader for lazily-loaded members. void setMemberLoader(LazyMemberLoader *loader, uint64_t contextData); /// Externally tell this context that it has no more lazy members, i.e. all lazy member loading is complete. void setHasLazyMembers(bool hasLazyMembers) const; /// Load all of the members of this context. void loadAllMembers() const; /// Determine whether this was deserialized (and thus SerialID is /// valid). bool wasDeserialized() const; /// Retrieve the set of protocols whose conformances will be /// associated with this declaration context. /// /// This function differs from \c getLocalConformances() in that it /// returns protocol declarations, not protocol conformances, and /// therefore does not require the protocol conformances to be /// formed. /// /// \param lookupKind The kind of lookup to perform. SmallVector getLocalProtocols(ConformanceLookupKind lookupKind = ConformanceLookupKind::All) const; /// Retrieve the set of protocol conformances associated with this /// declaration context. /// /// \param lookupKind The kind of lookup to perform. SmallVector getLocalConformances(ConformanceLookupKind lookupKind = ConformanceLookupKind::All) const; /// Retrieve diagnostics discovered while expanding conformances for this /// declaration context. This operation then removes those diagnostics from /// consideration, so subsequent calls to this function with the same /// declaration context that have not had any new extensions bound /// will see an empty array. SmallVector takeConformanceDiagnostics() const; /// Return 'this' as a \c Decl. const Decl *getDecl() const; /// Return 'this' as a \c GenericContext. GenericContext *getAsGenericContext(); const GenericContext *getAsGenericContext() const { return const_cast(this)->getAsGenericContext(); } /// Get the DeclID this Decl was deserialized from. serialization::DeclID getDeclID() const { assert(wasDeserialized()); return SerialID; } /// Set the DeclID this Decl was deserialized from. void setDeclID(serialization::DeclID d) { assert(wasDeserialized()); SerialID = d; } // Some Decls are IterableDeclContexts, but not all. static bool classof(const Decl *D); /// Return a hash of all tokens in the body for dependency analysis, if /// available. std::optional getBodyFingerprint() const; private: /// Add a member to the list for iteration purposes, but do not notify the /// subclass that we have done so. void addMemberSilently(Decl *member, Decl *hint, bool insertAtHead) const; }; /// Define simple_display for DeclContexts but not for subclasses in order to /// avoid ambiguities with Decl* arguments. template ::value>::type> void simple_display(llvm::raw_ostream &out, const ParamT *dc) { if (dc) dc->printContext(out, 0, true); else out << "(null)"; } void simple_display(llvm::raw_ostream &out, const IterableDeclContext *idc); /// Extract the source location from the given declaration context. SourceLoc extractNearestSourceLoc(const DeclContext *dc); /// Extract the source location from the given declaration context. SourceLoc extractNearestSourceLoc(const IterableDeclContext *idc); } // end namespace swift namespace llvm { template struct CastInfo<::swift::DeclContext, FromTy, std::enable_if_t::value>> : public CastIsPossible<::swift::DeclContext, FromTy>, public DefaultDoCastIfPossible<::swift::DeclContext *, FromTy, CastInfo<::swift::DeclContext, FromTy>> { static inline ::swift::DeclContext *castFailed() { return nullptr; } static inline ::swift::DeclContext *doCast(const FromTy &val) { return ::swift::DeclContext::castDeclToDeclContext(val); } }; template struct CastInfo<::swift::GenericContext, FromTy, std::enable_if_t::value>> : public CastIsPossible<::swift::GenericContext, FromTy>, public DefaultDoCastIfPossible<::swift::GenericContext *, FromTy, CastInfo<::swift::GenericContext, FromTy>> { static inline ::swift::GenericContext *castFailed() { return nullptr; } static inline ::swift::GenericContext *doCast(const FromTy &val) { auto *genCtxt = val->getAsGenericContext(); assert(genCtxt); return const_cast<::swift::GenericContext *>(genCtxt); } }; template struct CastInfo<::swift::IterableDeclContext, FromTy, std::enable_if_t::value>> : public CastIsPossible<::swift::IterableDeclContext, FromTy>, public DefaultDoCastIfPossible<::swift::IterableDeclContext *, FromTy, CastInfo<::swift::IterableDeclContext, FromTy>> { static inline ::swift::IterableDeclContext *castFailed() { return nullptr; } static inline ::swift::IterableDeclContext *doCast(const FromTy &val) { return ::swift::IterableDeclContext::castDeclToIterableDeclContext(val); } }; } #endif