mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
666 lines
22 KiB
C++
666 lines
22 KiB
C++
//===--- DeclContext.h - Swift Language Context ASTs ------------*- C++ -*-===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See http://swift.org/LICENSE.txt for license information
|
|
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file defines the 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/Identifier.h"
|
|
#include "swift/AST/TypeAlignments.h"
|
|
#include "swift/Basic/LLVM.h"
|
|
#include "swift/Basic/SourceLoc.h"
|
|
#include "swift/Basic/STLExtras.h"
|
|
#include "llvm/ADT/PointerIntPair.h"
|
|
#include "llvm/ADT/PointerUnion.h"
|
|
|
|
namespace llvm {
|
|
class raw_ostream;
|
|
}
|
|
|
|
namespace swift {
|
|
class AbstractFunctionDecl;
|
|
class ASTContext;
|
|
class ASTWalker;
|
|
class CanType;
|
|
class Decl;
|
|
class DeclContext;
|
|
class EnumDecl;
|
|
class ExtensionDecl;
|
|
class Expr;
|
|
class GenericParamList;
|
|
class LazyResolver;
|
|
class LazyMemberLoader;
|
|
class GenericSignature;
|
|
class GenericTypeParamDecl;
|
|
class GenericTypeParamType;
|
|
class ProtocolDecl;
|
|
class Requirement;
|
|
class SourceFile;
|
|
class Type;
|
|
class ModuleDecl;
|
|
class GenericTypeDecl;
|
|
class NominalTypeDecl;
|
|
class ProtocolConformance;
|
|
class ValueDecl;
|
|
class Initializer;
|
|
class ClassDecl;
|
|
class SerializedAbstractClosureExpr;
|
|
class SerializedPatternBindingInitializer;
|
|
class SerializedDefaultArgumentInitializer;
|
|
class SerializedTopLevelCodeDecl;
|
|
|
|
enum class DeclContextKind : uint8_t {
|
|
AbstractClosureExpr,
|
|
Initializer,
|
|
TopLevelCodeDecl,
|
|
SubscriptDecl,
|
|
AbstractFunctionDecl,
|
|
SerializedLocal,
|
|
Last_LocalDeclContextKind = SerializedLocal,
|
|
|
|
Module,
|
|
FileUnit,
|
|
GenericTypeDecl,
|
|
ExtensionDecl,
|
|
Last_DeclContextKind = ExtensionDecl
|
|
};
|
|
|
|
/// Kinds of DeclContexts after deserialization.
|
|
///
|
|
/// \see SerializedLocalDeclContext.
|
|
enum class LocalDeclContextKind : uint8_t {
|
|
AbstractClosure,
|
|
PatternBindingInitializer,
|
|
DefaultArgumentInitializer,
|
|
TopLevelCodeDecl
|
|
};
|
|
|
|
/// Describes the kind of a particular conformance.
|
|
///
|
|
/// The following code involves conformances of the three different kinds:
|
|
/// \code
|
|
/// protocol P { }
|
|
/// protocol P2 : P { }
|
|
///
|
|
/// class Super : P2 { }
|
|
/// class Sub : Super { }
|
|
/// \endcode
|
|
///
|
|
/// \c Super conforms to \c P2 via an explicit conformance,
|
|
/// specified on the class declaration itself.
|
|
///
|
|
/// \c Super conforms to \c P via an implied conformance, whose
|
|
/// origin is the explicit conformance to \c P2.
|
|
///
|
|
/// \c Sub conforms to \c P2 and \c 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 implied conformances. Earlier conformance
|
|
/// kinds supersede later conformance kinds, possibly with a
|
|
/// diagnostic (e.g., if an inherited conformance supersedes an
|
|
/// explicit conformance).
|
|
enum class ConformanceEntryKind : unsigned {
|
|
/// Inherited from a superclass conformance.
|
|
Inherited,
|
|
|
|
/// Explicitly specified.
|
|
Explicit,
|
|
|
|
/// Implied by an explicitly-specified conformance.
|
|
Implied,
|
|
|
|
/// Implicitly synthesized.
|
|
Synthesized,
|
|
};
|
|
|
|
/// Describes the kind of conformance lookup desired.
|
|
enum class ConformanceLookupKind : unsigned {
|
|
/// All conformances.
|
|
All,
|
|
/// Only the explicit conformance.
|
|
OnlyExplicit,
|
|
};
|
|
|
|
/// 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;
|
|
};
|
|
|
|
/// 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.
|
|
///
|
|
/// Note that DeclContexts have stricter alignment requirements than AST nodes
|
|
/// in general, so if an AST node class multiply inherits from DeclContext
|
|
/// and another base class, it must 'using DeclContext::operator new;' in order
|
|
/// to use an allocator with the correct alignment.
|
|
class alignas(1 << DeclContextAlignInBits) DeclContext {
|
|
|
|
enum {
|
|
KindBits = DeclContextAlignInBits
|
|
};
|
|
static_assert(unsigned(DeclContextKind::Last_DeclContextKind) < 1U<<KindBits,
|
|
"Not enough KindBits for DeclContextKind");
|
|
|
|
llvm::PointerIntPair<DeclContext*, KindBits, DeclContextKind> 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
|
|
|
|
template<class A, class B, class C>
|
|
friend struct ::llvm::cast_convert_val;
|
|
|
|
static DeclContext *castDeclToDeclContext(const Decl *D);
|
|
|
|
public:
|
|
DeclContext(DeclContextKind Kind, DeclContext *Parent)
|
|
: ParentAndKind(Parent, Kind) {
|
|
assert((Parent != 0 || isModuleContext()) &&
|
|
"DeclContext must have a parent unless it is a module!");
|
|
}
|
|
|
|
/// Returns the kind of context this is.
|
|
DeclContextKind getContextKind() const {
|
|
return ParentAndKind.getInt();
|
|
}
|
|
|
|
/// 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;
|
|
}
|
|
|
|
/// isModuleContext - Return true if this is a subclass of Module.
|
|
bool isModuleContext() const {
|
|
return getContextKind() == DeclContextKind::Module;
|
|
}
|
|
|
|
/// \returns true if this is a context with module-wide scope, e.g. a module
|
|
/// or a source file.
|
|
bool isModuleScopeContext() const {
|
|
return getContextKind() == DeclContextKind::Module ||
|
|
getContextKind() == DeclContextKind::FileUnit;
|
|
}
|
|
|
|
/// \returns true if this is a type context, e.g., a struct, a class, an
|
|
/// enum, a protocol, or an extension.
|
|
bool isTypeContext() const {
|
|
return getContextKind() == DeclContextKind::GenericTypeDecl ||
|
|
getContextKind() == DeclContextKind::ExtensionDecl;
|
|
}
|
|
|
|
/// \brief Determine whether this is an extension context.
|
|
bool isExtensionContext() const {
|
|
return getContextKind() == DeclContextKind::ExtensionDecl;
|
|
}
|
|
|
|
/// If this DeclContext is a GenericType declaration or an
|
|
/// extension thereof, return the GenericTypeDecl.
|
|
GenericTypeDecl *getAsGenericTypeOrGenericTypeExtensionContext() const;
|
|
|
|
/// If this DeclContext is a NominalType declaration or an
|
|
/// extension thereof, return the NominalTypeDecl.
|
|
NominalTypeDecl *getAsNominalTypeOrNominalTypeExtensionContext() const;
|
|
|
|
/// If this DeclContext is a class, or an extension on a class, return the
|
|
/// ClassDecl, otherwise return null.
|
|
ClassDecl *getAsClassOrClassExtensionContext() const;
|
|
|
|
/// If this DeclContext is an enum, or an extension on an enum, return the
|
|
/// EnumDecl, otherwise return null.
|
|
EnumDecl *getAsEnumOrEnumExtensionContext() const;
|
|
|
|
/// If this DeclContext is a protocol, or an extension on a
|
|
/// protocol, return the ProtocolDecl, otherwise return null.
|
|
ProtocolDecl *getAsProtocolOrProtocolExtensionContext() const;
|
|
|
|
/// If this DeclContext is a protocol extension, return the extended protocol.
|
|
ProtocolDecl *getAsProtocolExtensionContext() const;
|
|
|
|
/// \brief Retrieve the generic parameter 'Self' from a protocol or
|
|
/// protocol extension.
|
|
///
|
|
/// Only valid if \c getAsProtocolOrProtocolExtensionContext().
|
|
GenericTypeParamDecl *getProtocolSelf() const;
|
|
|
|
/// getDeclaredTypeOfContext - For a type context, retrieves the declared
|
|
/// type of the context. Returns a null type for non-type contexts.
|
|
Type getDeclaredTypeOfContext() const;
|
|
|
|
/// getDeclaredTypeInContext - For a type context, retrieves the declared
|
|
/// type of the context as visible from within the context. Returns a null
|
|
/// type for non-type contexts.
|
|
Type getDeclaredTypeInContext() const;
|
|
|
|
/// getDeclaredInterfaceType - For a type context, retrieves the interface
|
|
/// type of the context as seen from outside the context. Returns a null
|
|
/// type for non-type contexts.
|
|
Type getDeclaredInterfaceType() const;
|
|
|
|
/// \brief Retrieve the innermost generic parameters introduced by this
|
|
/// context or one of its parent contexts, or null if this context is not
|
|
/// directly dependent on any generic parameters.
|
|
GenericParamList *getGenericParamsOfContext() const;
|
|
|
|
/// \brief Retrieve the interface generic type parameters and requirements
|
|
/// exposed by this context.
|
|
GenericSignature *getGenericSignatureOfContext() const;
|
|
|
|
/// Returns this or the first local parent context, or nullptr if it is not
|
|
/// contained in one.
|
|
DeclContext *getLocalContext();
|
|
const DeclContext *getLocalContext() const {
|
|
return const_cast<DeclContext*>(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.
|
|
AbstractFunctionDecl *getInnermostMethodContext();
|
|
const AbstractFunctionDecl *getInnermostMethodContext() const {
|
|
return const_cast<DeclContext*>(this)->getInnermostMethodContext();
|
|
}
|
|
|
|
/// 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.
|
|
DeclContext *getInnermostTypeContext();
|
|
const DeclContext *getInnermostTypeContext() const {
|
|
return const_cast<DeclContext *>(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.
|
|
Decl *getInnermostDeclarationDeclContext();
|
|
const Decl *getInnermostDeclarationDeclContext() const {
|
|
return
|
|
const_cast<DeclContext *>(this)->getInnermostDeclarationDeclContext();
|
|
}
|
|
|
|
/// 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();
|
|
}
|
|
|
|
/// 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 module context that contains this context.
|
|
ModuleDecl *getParentModule() const;
|
|
|
|
/// Returns the module scope context that contains this context.
|
|
///
|
|
/// This is either a \c Module or a \c FileUnit.
|
|
DeclContext *getModuleScopeContext() const;
|
|
|
|
/// Returns the source file that contains this context, or null if this
|
|
/// is not within a source file.
|
|
SourceFile *getParentSourceFile() 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 the innermost context is either a generic type context,
|
|
/// or a concrete type nested inside a generic type context.
|
|
bool isGenericTypeContext() const;
|
|
|
|
/// Determine the maximum depth of the current generic type context's generic
|
|
/// parameters. If the current context is not a generic type context, returns
|
|
/// the maximum depth of any generic parameter in this context.
|
|
unsigned getGenericTypeContextDepth() const;
|
|
|
|
/// Returns true if lookups within this context could affect downstream files.
|
|
///
|
|
/// \param functionsAreNonCascading If true, functions are considered non-
|
|
/// cascading contexts. If false, functions are considered non-cascading only
|
|
/// if implicitly or explicitly marked private. When concerned only with a
|
|
/// function's body, pass true.
|
|
bool isCascadingContextForLookup(bool functionsAreNonCascading) 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 typeResolver Used to resolve types, usually for overload purposes.
|
|
/// May be null.
|
|
///
|
|
/// \param[out] decls Will be populated with the declarations found by name
|
|
/// lookup.
|
|
///
|
|
/// \returns true if anything was found.
|
|
bool lookupQualified(Type type, DeclName member, unsigned options,
|
|
LazyResolver *typeResolver,
|
|
SmallVectorImpl<ValueDecl *> &decls) const;
|
|
|
|
/// Look up all Objective-C methods with the given selector visible
|
|
/// in the enclosing module.
|
|
void lookupAllObjCMethods(
|
|
ObjCSelector selector,
|
|
SmallVectorImpl<AbstractFunctionDecl *> &results) const;
|
|
|
|
/// Return the ASTContext for a specified DeclContext by
|
|
/// walking up to the enclosing module and returning its ASTContext.
|
|
ASTContext &getASTContext() 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.
|
|
///
|
|
/// \param diagnostics If non-null, will be populated with the set of
|
|
/// diagnostics that should be emitted for this declaration context.
|
|
///
|
|
/// \param sorted Whether to sort the results in a canonical order.
|
|
///
|
|
/// FIXME: This likely makes more sense on IterableDeclContext or
|
|
/// something similar.
|
|
SmallVector<ProtocolDecl *, 2>
|
|
getLocalProtocols(ConformanceLookupKind lookupKind
|
|
= ConformanceLookupKind::All,
|
|
SmallVectorImpl<ConformanceDiagnostic> *diagnostics
|
|
= nullptr,
|
|
bool sorted = false) const;
|
|
|
|
/// Retrieve the set of protocol conformances associated with this
|
|
/// declaration context.
|
|
///
|
|
/// \param lookupKind The kind of lookup to perform.
|
|
///
|
|
/// \param diagnostics If non-null, will be populated with the set of
|
|
/// diagnostics that should be emitted for this declaration context.
|
|
///
|
|
/// \param sorted Whether to sort the results in a canonical order.
|
|
///
|
|
/// FIXME: This likely makes more sense on IterableDeclContext or
|
|
/// something similar.
|
|
SmallVector<ProtocolConformance *, 2>
|
|
getLocalConformances(ConformanceLookupKind lookupKind
|
|
= ConformanceLookupKind::All,
|
|
SmallVectorImpl<ConformanceDiagnostic> *diagnostics
|
|
= nullptr,
|
|
bool sorted = false) const;
|
|
|
|
/// \returns true if traversal was aborted, false otherwise.
|
|
bool walkContext(ASTWalker &Walker);
|
|
|
|
void dumpContext() const;
|
|
unsigned printContext(llvm::raw_ostream &OS, unsigned indent = 0) const;
|
|
|
|
/// Get the type of `self` in this declaration context, if there is a
|
|
/// `self`.
|
|
Type getSelfTypeInContext() const;
|
|
/// Get the interface type of `self` in this declaration context, if there is
|
|
/// a `self`.
|
|
Type getSelfInterfaceType() const;
|
|
|
|
// Only allow allocation of DeclContext using the allocator in ASTContext.
|
|
void *operator new(size_t Bytes, ASTContext &C,
|
|
unsigned Alignment = alignof(DeclContext));
|
|
|
|
// Some Decls are DeclContexts, but not all.
|
|
static bool classof(const Decl *D);
|
|
};
|
|
|
|
/// SerializedLocalDeclContext - the base class for DeclContexts that were
|
|
/// serialized to preserve AST structure and accurate mangling after
|
|
/// deserialization.
|
|
class SerializedLocalDeclContext : public DeclContext {
|
|
private:
|
|
const LocalDeclContextKind LocalKind;
|
|
|
|
public:
|
|
SerializedLocalDeclContext(LocalDeclContextKind LocalKind,
|
|
DeclContext *Parent)
|
|
: DeclContext(DeclContextKind::SerializedLocal, Parent),
|
|
LocalKind(LocalKind) {}
|
|
|
|
LocalDeclContextKind getLocalDeclContextKind() const {
|
|
return LocalKind;
|
|
}
|
|
|
|
static bool classof(const DeclContext *DC) {
|
|
return DC->getContextKind() == DeclContextKind::SerializedLocal;
|
|
}
|
|
};
|
|
|
|
/// 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.
|
|
typedef IteratorRange<DeclIterator> DeclRange;
|
|
|
|
/// The kind of an \c IterableDeclContext.
|
|
enum class IterableDeclContextKind : uint8_t {
|
|
NominalTypeDecl,
|
|
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.
|
|
mutable Decl *FirstDecl = nullptr;
|
|
|
|
/// The last declaration in this context, used for efficient insertion,
|
|
/// along with the kind of iterable declaration context.
|
|
mutable llvm::PointerIntPair<Decl *, 2, IterableDeclContextKind>
|
|
LastDeclAndKind;
|
|
|
|
/// Lazy member loader, if any.
|
|
///
|
|
/// FIXME: Can we collapse this storage into something?
|
|
mutable LazyMemberLoader *LazyLoader = nullptr;
|
|
|
|
/// Lazy member loader context data.
|
|
uint64_t LazyLoaderContextData = 0;
|
|
|
|
/// Global declarations that were synthesized on this declaration's behalf,
|
|
/// such as default operator definitions derived for protocol conformances.
|
|
ArrayRef<Decl*> DerivedGlobalDecls;
|
|
|
|
template<class A, class B, class C>
|
|
friend struct ::llvm::cast_convert_val;
|
|
|
|
static IterableDeclContext *castDeclToIterableDeclContext(const Decl *D);
|
|
|
|
public:
|
|
IterableDeclContext(IterableDeclContextKind kind)
|
|
: LastDeclAndKind(nullptr, kind) { }
|
|
|
|
/// Determine the kind of iterable context we have.
|
|
IterableDeclContextKind getIterableContextKind() const {
|
|
return LastDeclAndKind.getInt();
|
|
}
|
|
|
|
/// Retrieve the set of members in this context.
|
|
DeclRange getMembers() const;
|
|
|
|
/// Add a member to this context. If the hint decl is specified, the new decl
|
|
/// is inserted immediately after the hint.
|
|
void addMember(Decl *member, Decl *hint = nullptr);
|
|
|
|
/// Retrieve the lazy member loader.
|
|
LazyMemberLoader *getLoader() const {
|
|
assert(isLazy());
|
|
return LazyLoader;
|
|
}
|
|
|
|
/// Retrieve the context data for the lazy member loader.
|
|
uint64_t getLoaderContextData() const {
|
|
assert(isLazy());
|
|
return LazyLoaderContextData;
|
|
}
|
|
|
|
/// Check whether there are lazily-loaded members.
|
|
bool isLazy() const {
|
|
return LazyLoader != nullptr;
|
|
}
|
|
|
|
/// Set the loader for lazily-loaded members.
|
|
void setLoader(LazyMemberLoader *loader, uint64_t contextData);
|
|
|
|
/// Load all of the members of this context.
|
|
void loadAllMembers() const;
|
|
|
|
/// Retrieve global declarations that were synthesized on this
|
|
/// declaration's behalf.
|
|
ArrayRef<Decl *> getDerivedGlobalDecls() const {
|
|
return DerivedGlobalDecls;
|
|
}
|
|
|
|
/// Set global declarations that were synthesized on this
|
|
/// declaration's behalf.
|
|
void setDerivedGlobalDecls(MutableArrayRef<Decl*> decls) {
|
|
DerivedGlobalDecls = decls;
|
|
}
|
|
|
|
// Some Decls are IterableDeclContexts, but not all.
|
|
static bool classof(const Decl *D);
|
|
|
|
private:
|
|
/// Add a member to the list for iteration purposes, but do not notify the
|
|
/// subclass that we have done so.
|
|
///
|
|
/// This is used internally when loading members, because loading a
|
|
/// member is an invisible addition.
|
|
void addMemberSilently(Decl *member, Decl *hint = nullptr) const;
|
|
};
|
|
|
|
} // end namespace swift
|
|
|
|
namespace llvm {
|
|
template<class FromTy>
|
|
struct cast_convert_val< ::swift::DeclContext, FromTy, FromTy> {
|
|
static ::swift::DeclContext *doit(const FromTy &Val) {
|
|
return ::swift::DeclContext::castDeclToDeclContext(Val);
|
|
}
|
|
};
|
|
|
|
template<class FromTy>
|
|
struct cast_convert_val< ::swift::IterableDeclContext, FromTy, FromTy> {
|
|
static ::swift::IterableDeclContext *doit(const FromTy &Val) {
|
|
return ::swift::IterableDeclContext::castDeclToIterableDeclContext(Val);
|
|
}
|
|
};
|
|
}
|
|
|
|
#endif
|