blob: 5cff707bd07e2810ac72d187efe45d90830481af [file] [log] [blame]
//===--- Module.h - Swift Language Module 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 Module class and its subclasses.
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_MODULE_H
#define SWIFT_MODULE_H
#include "swift/AST/Decl.h"
#include "swift/AST/DeclContext.h"
#include "swift/AST/Identifier.h"
#include "swift/AST/Import.h"
#include "swift/AST/LookupKinds.h"
#include "swift/AST/RawComment.h"
#include "swift/AST/Type.h"
#include "swift/Basic/Compiler.h"
#include "swift/Basic/OptionSet.h"
#include "swift/Basic/STLExtras.h"
#include "swift/Basic/SourceLoc.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MD5.h"
#include <set>
namespace clang {
class Module;
}
namespace swift {
enum class ArtificialMainKind : uint8_t;
class ASTContext;
class ASTWalker;
class BraceStmt;
class Decl;
class DeclAttribute;
class TypeDecl;
enum class DeclKind : uint8_t;
class ExtensionDecl;
class DebuggerClient;
class DeclName;
class FileUnit;
class FuncDecl;
class InfixOperatorDecl;
class LinkLibrary;
class ModuleLoader;
class NominalTypeDecl;
class EnumElementDecl;
class OperatorDecl;
class PostfixOperatorDecl;
class PrefixOperatorDecl;
class ProtocolConformance;
class ProtocolDecl;
struct PrintOptions;
class Token;
class TupleType;
class Type;
class TypeRefinementContext;
class ValueDecl;
class VarDecl;
class VisibleDeclConsumer;
class SyntaxParsingCache;
class ASTScope;
class SourceLookupCache;
namespace syntax {
class SourceFileSyntax;
}
namespace ast_scope {
class ASTSourceFileScope;
}
/// Discriminator for file-units.
enum class FileUnitKind {
/// For a .swift source file.
Source,
/// For the compiler Builtin module.
Builtin,
/// A serialized Swift AST.
SerializedAST,
/// A synthesized file.
Synthesized,
/// An imported Clang module.
ClangModule,
/// A Clang module imported from DWARF.
DWARFModule
};
enum class SourceFileKind {
Library, ///< A normal .swift file.
Main, ///< A .swift file that can have top-level code.
SIL, ///< Came from a .sil file.
Interface ///< Came from a .swiftinterface file, representing another module.
};
/// Contains information about where a particular path is used in
/// \c SourceFiles.
struct SourceFilePathInfo {
struct Comparator {
bool operator () (SourceLoc lhs, SourceLoc rhs) const {
return lhs.getOpaquePointerValue() <
rhs.getOpaquePointerValue();
}
};
SourceLoc physicalFileLoc{};
std::set<SourceLoc, Comparator> virtualFileLocs{}; // std::set for sorting
SourceFilePathInfo() = default;
void merge(const SourceFilePathInfo &other) {
if (other.physicalFileLoc.isValid()) {
assert(!physicalFileLoc.isValid());
physicalFileLoc = other.physicalFileLoc;
}
for (auto &elem : other.virtualFileLocs) {
virtualFileLocs.insert(elem);
}
}
bool operator == (const SourceFilePathInfo &other) const {
return physicalFileLoc == other.physicalFileLoc &&
virtualFileLocs == other.virtualFileLocs;
}
};
/// Discriminator for resilience strategy.
enum class ResilienceStrategy : unsigned {
/// Public nominal types: fragile
/// Non-inlinable function bodies: resilient
///
/// This is the default behavior without any flags.
Default,
/// Public nominal types: resilient
/// Non-inlinable function bodies: resilient
///
/// This is the behavior with -enable-library-evolution.
Resilient
};
class OverlayFile;
/// The minimum unit of compilation.
///
/// A module is made up of several file-units, which are all part of the same
/// output binary and logical module (such as a single library or executable).
///
/// \sa FileUnit
class ModuleDecl : public DeclContext, public TypeDecl {
friend class DirectOperatorLookupRequest;
friend class DirectPrecedenceGroupLookupRequest;
public:
/// Produces the components of a given module's full name in reverse order.
///
/// For a Swift module, this will only ever have one component, but an
/// imported Clang module might actually be a submodule.
class ReverseFullNameIterator {
public:
// Make this look like a valid STL iterator.
using difference_type = int;
using value_type = StringRef;
using pointer = StringRef *;
using reference = StringRef;
using iterator_category = std::forward_iterator_tag;
private:
PointerUnion<const ModuleDecl *, const /* clang::Module */ void *> current;
public:
ReverseFullNameIterator() = default;
explicit ReverseFullNameIterator(const ModuleDecl *M);
explicit ReverseFullNameIterator(const clang::Module *clangModule) {
current = clangModule;
}
StringRef operator*() const;
ReverseFullNameIterator &operator++();
friend bool operator==(ReverseFullNameIterator left,
ReverseFullNameIterator right) {
return left.current == right.current;
}
friend bool operator!=(ReverseFullNameIterator left,
ReverseFullNameIterator right) {
return !(left == right);
}
/// This is a convenience function that writes the entire name, in forward
/// order, to \p out.
void printForward(raw_ostream &out, StringRef delim = ".") const;
};
private:
/// If non-NULL, a plug-in that should be used when performing external
/// lookups.
// FIXME: Do we really need to bloat all modules with this?
DebuggerClient *DebugClient = nullptr;
SmallVector<FileUnit *, 2> Files;
llvm::SmallDenseMap<Identifier, SmallVector<OverlayFile *, 1>>
declaredCrossImports;
/// A description of what should be implicitly imported by each file of this
/// module.
const ImplicitImportInfo ImportInfo;
std::unique_ptr<SourceLookupCache> Cache;
SourceLookupCache &getSourceLookupCache() const;
/// Tracks the file that will generate the module's entry point, either
/// because it contains a class marked with \@UIApplicationMain
/// or \@NSApplicationMain, or because it is a script file.
class EntryPointInfoTy {
enum class Flags {
DiagnosedMultipleMainClasses = 1 << 0,
DiagnosedMainClassWithScript = 1 << 1
};
llvm::PointerIntPair<FileUnit *, 2, OptionSet<Flags>> storage;
public:
EntryPointInfoTy() = default;
FileUnit *getEntryPointFile() const;
void setEntryPointFile(FileUnit *file);
bool hasEntryPoint() const;
bool markDiagnosedMultipleMainClasses();
bool markDiagnosedMainClassWithScript();
};
/// Information about the file responsible for the module's entry point,
/// if any.
///
/// \see EntryPointInfoTy
EntryPointInfoTy EntryPointInfo;
ModuleDecl(Identifier name, ASTContext &ctx, ImplicitImportInfo importInfo);
public:
/// Creates a new module with a given \p name.
///
/// \param importInfo Information about which modules should be implicitly
/// imported by each file of this module.
static ModuleDecl *
create(Identifier name, ASTContext &ctx,
ImplicitImportInfo importInfo = ImplicitImportInfo()) {
return new (ctx) ModuleDecl(name, ctx, importInfo);
}
static ModuleDecl *
createMainModule(ASTContext &ctx, Identifier name, ImplicitImportInfo iinfo) {
auto *Mod = ModuleDecl::create(name, ctx, iinfo);
Mod->Bits.ModuleDecl.IsMainModule = true;
return Mod;
}
using Decl::getASTContext;
/// Retrieves information about which modules are implicitly imported by
/// each file of this module.
const ImplicitImportInfo &getImplicitImportInfo() const { return ImportInfo; }
/// Retrieve a list of modules that each file of this module implicitly
/// imports.
ImplicitImportList getImplicitImports() const;
ArrayRef<FileUnit *> getFiles() {
assert(!Files.empty() || failedToLoad());
return Files;
}
ArrayRef<const FileUnit *> getFiles() const {
return { Files.begin(), Files.size() };
}
void addFile(FileUnit &newFile);
/// Creates a map from \c #filePath strings to corresponding \c #fileID
/// strings, diagnosing any conflicts.
///
/// A given \c #filePath string always maps to exactly one \c #fileID string,
/// but it is possible for \c #sourceLocation directives to introduce
/// duplicates in the opposite direction. If there are such conflicts, this
/// method will diagnose the conflict and choose a "winner" among the paths
/// in a reproducible way. The \c bool paired with the \c #fileID string is
/// \c true for paths which did not have a conflict or won a conflict, and
/// \c false for paths which lost a conflict. Thus, if you want to generate a
/// reverse mapping, you should drop or special-case the \c #fileID strings
/// that are paired with \c false.
llvm::StringMap<std::pair<std::string, /*isWinner=*/bool>>
computeFileIDMap(bool shouldDiagnose) const;
/// Add a file declaring a cross-import overlay.
void addCrossImportOverlayFile(StringRef file);
/// Collect cross-import overlay names from a given YAML file path.
static llvm::SmallSetVector<Identifier, 4>
collectCrossImportOverlay(ASTContext &ctx, StringRef file,
StringRef moduleName, StringRef& bystandingModule);
/// If this method returns \c false, the module does not declare any
/// cross-import overlays.
///
/// This is a quick check you can use to bail out of expensive logic early;
/// however, a \c true return doesn't guarantee that the module declares
/// cross-import overlays--it only means that it \em might declare some.
///
/// (Specifically, this method checks if the module loader found any
/// swiftoverlay files, but does not load the files to see if they list any
/// overlay modules.)
bool mightDeclareCrossImportOverlays() const;
/// Append to \p overlayNames the names of all modules that this module
/// declares should be imported when \p bystanderName is imported.
///
/// This operation is asymmetric: you will get different results if you
/// reverse the positions of the two modules involved in the cross-import.
void findDeclaredCrossImportOverlays(
Identifier bystanderName, SmallVectorImpl<Identifier> &overlayNames,
SourceLoc diagLoc) const;
/// Get the list of all modules this module declares a cross-import with.
void getDeclaredCrossImportBystanders(
SmallVectorImpl<Identifier> &bystanderNames);
private:
/// A cache of this module's underlying module and required bystander if it's
/// an underscored cross-import overlay.
Optional<std::pair<ModuleDecl *, Identifier>> declaringModuleAndBystander;
/// If this module is an underscored cross import overlay, gets the underlying
/// module that declared it (which may itself be a cross-import overlay),
/// along with the name of the required bystander module. Used by tooling to
/// present overlays as if they were part of their underlying module.
std::pair<ModuleDecl *, Identifier> getDeclaringModuleAndBystander();
/// If this is a traditional (non-cross-import) overlay, get its underlying
/// module if one exists.
ModuleDecl *getUnderlyingModuleIfOverlay() const;
public:
/// Returns true if this module is an underscored cross import overlay
/// declared by \p other or its underlying clang module, either directly or
/// transitively (via intermediate cross-import overlays - for cross-imports
/// involving more than two modules).
bool isCrossImportOverlayOf(ModuleDecl *other);
/// If this module is an underscored cross-import overlay, returns the
/// non-underscored underlying module that declares it as an overlay, either
/// directly or transitively (via intermediate cross-import overlays - for
/// cross-imports involving more than two modules).
ModuleDecl *getDeclaringModuleIfCrossImportOverlay();
/// If this module is an underscored cross-import overlay of \p declaring or
/// its underlying clang module, either directly or transitively, populates
/// \p bystanderNames with the set of bystander modules that must be present
/// alongside \p declaring for the overlay to be imported and returns true.
/// Returns false otherwise.
bool getRequiredBystandersIfCrossImportOverlay(
ModuleDecl *declaring, SmallVectorImpl<Identifier> &bystanderNames);
/// Walks and loads the declared, underscored cross-import overlays of this
/// module and its underlying clang module, transitively, to find all cross
/// import overlays this module underlies.
///
/// This is used by tooling to present these overlays as part of this module.
void findDeclaredCrossImportOverlaysTransitive(
SmallVectorImpl<ModuleDecl *> &overlays);
/// Convenience accessor for clients that know what kind of file they're
/// dealing with.
SourceFile &getMainSourceFile() const;
/// Convenience accessor for clients that know what kind of file they're
/// dealing with.
FileUnit &getMainFile(FileUnitKind expectedKind) const;
DebuggerClient *getDebugClient() const { return DebugClient; }
void setDebugClient(DebuggerClient *R) {
assert(!DebugClient && "Debugger client already set");
DebugClient = R;
}
/// Returns true if this module was or is being compiled for testing.
bool isTestingEnabled() const {
return Bits.ModuleDecl.TestingEnabled;
}
void setTestingEnabled(bool enabled = true) {
Bits.ModuleDecl.TestingEnabled = enabled;
}
// Returns true if this module is compiled with implicit dynamic.
bool isImplicitDynamicEnabled() const {
return Bits.ModuleDecl.ImplicitDynamicEnabled;
}
void setImplicitDynamicEnabled(bool enabled = true) {
Bits.ModuleDecl.ImplicitDynamicEnabled = enabled;
}
/// Returns true if this module was or is begin compile with
/// `-enable-private-imports`.
bool arePrivateImportsEnabled() const {
return Bits.ModuleDecl.PrivateImportsEnabled;
}
void setPrivateImportsEnabled(bool enabled = true) {
Bits.ModuleDecl.PrivateImportsEnabled = true;
}
/// Returns true if there was an error trying to load this module.
bool failedToLoad() const {
return Bits.ModuleDecl.FailedToLoad;
}
void setFailedToLoad(bool failed = true) {
Bits.ModuleDecl.FailedToLoad = failed;
}
bool hasResolvedImports() const {
return Bits.ModuleDecl.HasResolvedImports;
}
void setHasResolvedImports() {
Bits.ModuleDecl.HasResolvedImports = true;
}
ResilienceStrategy getResilienceStrategy() const {
return ResilienceStrategy(Bits.ModuleDecl.RawResilienceStrategy);
}
void setResilienceStrategy(ResilienceStrategy strategy) {
Bits.ModuleDecl.RawResilienceStrategy = unsigned(strategy);
}
/// Returns true if this module was or is being compiled for testing.
bool hasIncrementalInfo() const { return Bits.ModuleDecl.HasIncrementalInfo; }
void setHasIncrementalInfo(bool enabled = true) {
Bits.ModuleDecl.HasIncrementalInfo = enabled;
}
/// \returns true if this module is a system module; note that the StdLib is
/// considered a system module.
bool isSystemModule() const {
return Bits.ModuleDecl.IsSystemModule;
}
void setIsSystemModule(bool flag = true) {
Bits.ModuleDecl.IsSystemModule = flag;
}
/// Returns true if this module is a non-Swift module that was imported into
/// Swift.
///
/// Right now that's just Clang modules.
bool isNonSwiftModule() const {
return Bits.ModuleDecl.IsNonSwiftModule;
}
/// \see #isNonSwiftModule
void setIsNonSwiftModule(bool flag = true) {
Bits.ModuleDecl.IsNonSwiftModule = flag;
}
bool isMainModule() const {
return Bits.ModuleDecl.IsMainModule;
}
/// For the main module, retrieves the list of primary source files being
/// compiled, that is, the files we're generating code for.
ArrayRef<SourceFile *> getPrimarySourceFiles() const;
/// Retrieve the top-level module. If this module is already top-level, this
/// returns itself. If this is a submodule such as \c Foo.Bar.Baz, this
/// returns the module \c Foo.
ModuleDecl *getTopLevelModule(bool overlay = false);
bool isResilient() const {
return getResilienceStrategy() != ResilienceStrategy::Default;
}
/// Look up a (possibly overloaded) value set at top-level scope
/// (but with the specified access path, which may come from an import decl)
/// within the current module.
///
/// This does a simple local lookup, not recursively looking through imports.
void lookupValue(DeclName Name, NLKind LookupKind,
SmallVectorImpl<ValueDecl*> &Result) const;
/// Look up a local type declaration by its mangled name.
///
/// This does a simple local lookup, not recursively looking through imports.
TypeDecl *lookupLocalType(StringRef MangledName) const;
/// Look up an opaque return type by the mangled name of the declaration
/// that defines it.
OpaqueTypeDecl *lookupOpaqueResultType(StringRef MangledName);
/// Find ValueDecls in the module and pass them to the given consumer object.
///
/// This does a simple local lookup, not recursively looking through imports.
void lookupVisibleDecls(ImportPath::Access AccessPath,
VisibleDeclConsumer &Consumer,
NLKind LookupKind) const;
/// This is a hack for 'main' file parsing and the integrated REPL.
///
/// FIXME: Refactor main file parsing to not pump the parser incrementally.
/// FIXME: Remove the integrated REPL.
void clearLookupCache();
/// Finds all class members defined in this module.
///
/// This does a simple local lookup, not recursively looking through imports.
void lookupClassMembers(ImportPath::Access accessPath,
VisibleDeclConsumer &consumer) const;
/// Finds class members defined in this module with the given name.
///
/// This does a simple local lookup, not recursively looking through imports.
void lookupClassMember(ImportPath::Access accessPath,
DeclName name,
SmallVectorImpl<ValueDecl*> &results) const;
/// Look for the conformance of the given type to the given protocol.
///
/// This routine determines whether the given \c type conforms to the given
/// \c protocol.
///
/// \param type The type for which we are computing conformance.
///
/// \param protocol The protocol to which we are computing conformance.
///
/// \returns The result of the conformance search, which will be
/// None if the type does not conform to the protocol or contain a
/// ProtocolConformanceRef if it does conform.
ProtocolConformanceRef lookupConformance(Type type, ProtocolDecl *protocol);
/// Look for the conformance of the given existential type to the given
/// protocol.
ProtocolConformanceRef lookupExistentialConformance(Type type,
ProtocolDecl *protocol);
/// Exposes TypeChecker functionality for querying protocol conformance.
/// Returns a valid ProtocolConformanceRef only if all conditional
/// requirements are successfully resolved.
ProtocolConformanceRef conformsToProtocol(Type sourceTy,
ProtocolDecl *targetProtocol);
/// Find a member named \p name in \p container that was declared in this
/// module.
///
/// \p container may be \c this for a top-level lookup.
///
/// If \p privateDiscriminator is non-empty, only matching private decls are
/// returned; otherwise, only non-private decls are returned.
void lookupMember(SmallVectorImpl<ValueDecl*> &results,
DeclContext *container, DeclName name,
Identifier privateDiscriminator) const;
/// Find all Objective-C methods with the given selector.
void lookupObjCMethods(
ObjCSelector selector,
SmallVectorImpl<AbstractFunctionDecl *> &results) const;
Optional<Fingerprint>
loadFingerprint(const IterableDeclContext *IDC) const;
/// Find all SPI names imported from \p importedModule by this module,
/// collecting the identifiers in \p spiGroups.
void lookupImportedSPIGroups(
const ModuleDecl *importedModule,
llvm::SmallSetVector<Identifier, 4> &spiGroups) const;
// Is \p attr accessible as an explictly imported SPI from this module?
bool isImportedAsSPI(const SpecializeAttr *attr,
const ValueDecl *targetDecl) const;
// Is \p spiGroup accessible as an explictly imported SPI from this module?
bool isImportedAsSPI(Identifier spiGroup, const ModuleDecl *fromModule) const;
/// \sa getImportedModules
enum class ImportFilterKind {
/// Include imports declared with `@_exported`.
Exported = 1 << 0,
/// Include "regular" imports with no special annotation.
Default = 1 << 1,
/// Include imports declared with `@_implementationOnly`.
ImplementationOnly = 1 << 2,
/// Include imports of SPIs declared with `@_spi`
SPIAccessControl = 1 << 3,
/// Include imports shadowed by a cross-import overlay. Unshadowed imports
/// are included whether or not this flag is specified.
ShadowedByCrossImportOverlay = 1 << 4
};
/// \sa getImportedModules
using ImportFilter = OptionSet<ImportFilterKind>;
/// Looks up which modules are imported by this module.
///
/// \p filter controls whether public, private, or any imports are included
/// in this list.
void getImportedModules(SmallVectorImpl<ImportedModule> &imports,
ImportFilter filter = ImportFilterKind::Exported) const;
/// Looks up which modules are imported by this module, ignoring any that
/// won't contain top-level decls.
///
/// This is a performance hack. Do not use for anything but name lookup.
/// May go away in the future.
void
getImportedModulesForLookup(SmallVectorImpl<ImportedModule> &imports) const;
/// Has \p module been imported via an '@_implementationOnly' import
/// instead of another kind of import?
///
/// This assumes that \p module was imported.
bool isImportedImplementationOnly(const ModuleDecl *module) const;
/// Finds all top-level decls of this module.
///
/// This does a simple local lookup, not recursively looking through imports.
/// The order of the results is not guaranteed to be meaningful.
void getTopLevelDecls(SmallVectorImpl<Decl*> &Results) const;
void getExportedPrespecializations(SmallVectorImpl<Decl *> &results) const;
/// Finds top-level decls of this module filtered by their attributes.
///
/// This does a simple local lookup, not recursively looking through imports.
/// The order of the results is not guaranteed to be meaningful.
///
/// \param Results Vector collecting the decls.
///
/// \param matchAttributes Check on the attributes of a decl to
/// filter which decls to fully deserialize. Only decls with accepted
/// attributes are deserialized and added to Results.
void getTopLevelDeclsWhereAttributesMatch(
SmallVectorImpl<Decl*> &Results,
llvm::function_ref<bool(DeclAttributes)> matchAttributes) const;
/// Finds all local type decls of this module.
///
/// This does a simple local lookup, not recursively looking through imports.
/// The order of the results is not guaranteed to be meaningful.
void getLocalTypeDecls(SmallVectorImpl<TypeDecl*> &Results) const;
/// Finds all operator decls of this module.
///
/// This does a simple local lookup, not recursively looking through imports.
/// The order of the results is not guaranteed to be meaningful.
void getOperatorDecls(SmallVectorImpl<OperatorDecl *> &results) const;
/// Finds all precedence group decls of this module.
///
/// This does a simple local lookup, not recursively looking through imports.
/// The order of the results is not guaranteed to be meaningful.
void getPrecedenceGroups(SmallVectorImpl<PrecedenceGroupDecl*> &Results) const;
/// Finds all top-level decls that should be displayed to a client of this
/// module.
///
/// This includes types, variables, functions, and extensions.
/// This does a simple local lookup, not recursively looking through imports.
/// The order of the results is not guaranteed to be meaningful.
///
/// This can differ from \c getTopLevelDecls, e.g. it returns decls from a
/// shadowed clang module.
void getDisplayDecls(SmallVectorImpl<Decl*> &results) const;
using LinkLibraryCallback = llvm::function_ref<void(LinkLibrary)>;
/// Generate the list of libraries needed to link this module, based on its
/// imports.
void collectLinkLibraries(LinkLibraryCallback callback) const;
/// Get the path for the file that this module came from, or an empty
/// string if this is not applicable.
StringRef getModuleFilename() const;
/// \returns true if this module is the "swift" standard library module.
bool isStdlibModule() const;
/// \returns true if this module is the "SwiftShims" module;
bool isSwiftShimsModule() const;
/// \returns true if this module is the "builtin" module.
bool isBuiltinModule() const;
/// \returns true if this module is the "SwiftOnoneSupport" module;
bool isOnoneSupportModule() const;
/// \returns true if this module is the "Foundation" module;
bool isFoundationModule() const;
/// \returns true if traversal was aborted, false otherwise.
bool walk(ASTWalker &Walker);
/// Register the file responsible for generating this module's entry point.
///
/// \returns true if there was a problem adding this file.
bool registerEntryPointFile(FileUnit *file, SourceLoc diagLoc,
Optional<ArtificialMainKind> kind);
/// \returns true if this module has a main entry point.
bool hasEntryPoint() const {
return EntryPointInfo.hasEntryPoint();
}
/// Returns the associated clang module if one exists.
const clang::Module *findUnderlyingClangModule() const;
/// Returns a generator with the components of this module's full,
/// hierarchical name.
///
/// For a Swift module, this will only ever have one component, but an
/// imported Clang module might actually be a submodule.
ReverseFullNameIterator getReverseFullModuleName() const {
return ReverseFullNameIterator(this);
}
SourceRange getSourceRange() const { return SourceRange(); }
static bool classof(const DeclContext *DC) {
if (auto D = DC->getAsDecl())
return classof(D);
return false;
}
static bool classof(const Decl *D) {
return D->getKind() == DeclKind::Module;
}
private:
// Make placement new and vanilla new/delete illegal for Modules.
void *operator new(size_t Bytes) throw() = delete;
void operator delete(void *Data) throw() = delete;
void *operator new(size_t Bytes, void *Mem) throw() = delete;
public:
// Only allow allocation of Modules using the allocator in ASTContext
// or by doing a placement new.
void *operator new(size_t Bytes, const ASTContext &C,
unsigned Alignment = alignof(ModuleDecl));
};
/// Wraps either a swift module or a clang one.
/// FIXME: Should go away once swift modules can support submodules natively.
class ModuleEntity {
llvm::PointerUnion<const ModuleDecl *, const /* clang::Module */ void *> Mod;
public:
ModuleEntity() = default;
ModuleEntity(const ModuleDecl *Mod) : Mod(Mod) {}
ModuleEntity(const clang::Module *Mod) : Mod(static_cast<const void *>(Mod)){}
StringRef getName() const;
std::string getFullName() const;
bool isSystemModule() const;
bool isBuiltinModule() const;
const ModuleDecl *getAsSwiftModule() const;
const clang::Module *getAsClangModule() const;
void *getOpaqueValue() const {
assert(!Mod.isNull());
return Mod.getOpaqueValue();
}
explicit operator bool() const { return !Mod.isNull(); }
};
inline bool DeclContext::isModuleContext() const {
if (auto D = getAsDecl())
return ModuleDecl::classof(D);
return false;
}
inline bool DeclContext::isModuleScopeContext() const {
if (ParentAndKind.getInt() == ASTHierarchy::FileUnit)
return true;
return isModuleContext();
}
/// Extract the source location from the given module declaration.
inline SourceLoc extractNearestSourceLoc(const ModuleDecl *mod) {
return extractNearestSourceLoc(static_cast<const Decl *>(mod));
}
} // end namespace swift
#endif