[AST] Split FileUnit and its subclasses out of Module.h

Most of AST, Parse, and Sema deal with FileUnits regularly, but SIL
and IRGen certainly don't. Split FileUnit out into its own header to
cut down on recompilation times when something changes.

No functionality change.
This commit is contained in:
Jordan Rose
2019-09-17 17:20:28 -07:00
parent c99facb48b
commit 853caa66d4
74 changed files with 904 additions and 805 deletions

View File

@@ -219,29 +219,12 @@ private:
public:
EntryPointInfoTy() = default;
FileUnit *getEntryPointFile() const {
return storage.getPointer();
}
void setEntryPointFile(FileUnit *file) {
assert(!storage.getPointer());
storage.setPointer(file);
}
FileUnit *getEntryPointFile() const;
void setEntryPointFile(FileUnit *file);
bool hasEntryPoint() const;
bool hasEntryPoint() const {
return storage.getPointer();
}
bool markDiagnosedMultipleMainClasses() {
bool res = storage.getInt().contains(Flags::DiagnosedMultipleMainClasses);
storage.setInt(storage.getInt() | Flags::DiagnosedMultipleMainClasses);
return !res;
}
bool markDiagnosedMainClassWithScript() {
bool res = storage.getInt().contains(Flags::DiagnosedMainClassWithScript);
storage.setInt(storage.getInt() | Flags::DiagnosedMainClassWithScript);
return !res;
}
bool markDiagnosedMultipleMainClasses();
bool markDiagnosedMainClassWithScript();
};
/// Information about the file responsible for the module's entry point,
@@ -597,788 +580,6 @@ public:
unsigned Alignment = alignof(ModuleDecl));
};
static inline unsigned alignOfFileUnit();
/// A container for module-scope declarations that itself provides a scope; the
/// smallest unit of code organization.
///
/// FileUnit is an abstract base class; its subclasses represent different
/// sorts of containers that can each provide a set of decls, e.g. a source
/// file. A module can contain several file-units.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
class FileUnit : public DeclContext {
#pragma clang diagnostic pop
virtual void anchor();
// FIXME: Stick this in a PointerIntPair.
const FileUnitKind Kind;
protected:
FileUnit(FileUnitKind kind, ModuleDecl &M)
: DeclContext(DeclContextKind::FileUnit, &M), Kind(kind) {
}
public:
FileUnitKind getKind() const {
return Kind;
}
/// 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 this file.
///
/// This does a simple local lookup, not recursively looking through imports.
virtual void lookupValue(DeclName name, NLKind lookupKind,
SmallVectorImpl<ValueDecl*> &result) const = 0;
/// Look up a local type declaration by its mangled name.
///
/// This does a simple local lookup, not recursively looking through imports.
virtual TypeDecl *lookupLocalType(StringRef MangledName) const {
return nullptr;
}
/// Look up an opaque return type by the mangled name of the declaration
/// that defines it.
virtual OpaqueTypeDecl *lookupOpaqueResultType(StringRef MangledName,
LazyResolver *resolver) {
return nullptr;
}
/// Directly look for a nested type declared within this module inside the
/// given nominal type (including any extensions).
///
/// This is a fast-path hack to avoid circular dependencies in deserialization
/// and the Clang importer.
///
/// Private and fileprivate types should not be returned by this lookup.
virtual TypeDecl *lookupNestedType(Identifier name,
const NominalTypeDecl *parent) const {
return nullptr;
}
/// Find ValueDecls in the module and pass them to the given consumer object.
///
/// This does a simple local lookup, not recursively looking through imports.
virtual void lookupVisibleDecls(ModuleDecl::AccessPathTy accessPath,
VisibleDeclConsumer &consumer,
NLKind lookupKind) const {}
/// Finds all class members defined in this file.
///
/// This does a simple local lookup, not recursively looking through imports.
virtual void lookupClassMembers(ModuleDecl::AccessPathTy accessPath,
VisibleDeclConsumer &consumer) const {}
/// Finds class members defined in this file with the given name.
///
/// This does a simple local lookup, not recursively looking through imports.
virtual void lookupClassMember(ModuleDecl::AccessPathTy accessPath,
DeclName name,
SmallVectorImpl<ValueDecl*> &results) const {}
/// Find all Objective-C methods with the given selector.
virtual void lookupObjCMethods(
ObjCSelector selector,
SmallVectorImpl<AbstractFunctionDecl *> &results) const = 0;
/// Returns the comment attached to the given declaration.
///
/// This function is an implementation detail for comment serialization.
/// If you just want to get a comment attached to a decl, use
/// \c Decl::getRawComment() or \c Decl::getBriefComment().
virtual Optional<CommentInfo>
getCommentForDecl(const Decl *D) const {
return None;
}
virtual Optional<StringRef>
getGroupNameForDecl(const Decl *D) const {
return None;
}
virtual Optional<StringRef>
getSourceFileNameForDecl(const Decl *D) const {
return None;
}
virtual Optional<unsigned>
getSourceOrderForDecl(const Decl *D) const {
return None;
}
virtual Optional<StringRef>
getGroupNameByUSR(StringRef USR) const {
return None;
}
virtual void collectAllGroups(std::vector<StringRef> &Names) const {}
/// Returns an implementation-defined "discriminator" for \p D, which
/// distinguishes \p D from other declarations in the same module with the
/// same name.
///
/// Since this value is used in name mangling, it should be a valid ASCII-only
/// identifier.
virtual Identifier
getDiscriminatorForPrivateValue(const ValueDecl *D) const = 0;
/// Finds all top-level decls in this file.
///
/// This does a simple local lookup, not recursively looking through imports.
/// The order of the results is not guaranteed to be meaningful.
virtual void getTopLevelDecls(SmallVectorImpl<Decl*> &results) const {}
/// Finds all precedence group decls in this file.
///
/// This does a simple local lookup, not recursively looking through imports.
/// The order of the results is not guaranteed to be meaningful.
virtual void
getPrecedenceGroups(SmallVectorImpl<PrecedenceGroupDecl*> &Results) const {}
/// Finds all local type decls in this file.
///
/// This does a simple local lookup, not recursively looking through imports.
/// The order of the results is not guaranteed to be meaningful.
virtual void getLocalTypeDecls(SmallVectorImpl<TypeDecl*> &results) const {}
virtual void
getOpaqueReturnTypeDecls(SmallVectorImpl<OpaqueTypeDecl*> &results) const {}
/// Adds all top-level decls to the given vector.
///
/// This includes all decls that should be displayed to clients of the module.
/// 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.
virtual void getDisplayDecls(SmallVectorImpl<Decl*> &results) const {
getTopLevelDecls(results);
}
/// Looks up which modules are imported by this file.
///
/// \p filter controls whether public, private, or any imports are included
/// in this list.
virtual void
getImportedModules(SmallVectorImpl<ModuleDecl::ImportedModule> &imports,
ModuleDecl::ImportFilter filter) const {}
/// \see ModuleDecl::getImportedModulesForLookup
virtual void getImportedModulesForLookup(
SmallVectorImpl<ModuleDecl::ImportedModule> &imports) const {
return getImportedModules(imports, ModuleDecl::ImportFilterKind::Public);
}
/// Generates the list of libraries needed to link this file, based on its
/// imports.
virtual void
collectLinkLibraries(ModuleDecl::LinkLibraryCallback callback) const {}
/// True if this file contains the main class for the module.
bool hasMainClass() const {
return getMainClass();
}
virtual ClassDecl *getMainClass() const {
assert(hasEntryPoint());
return nullptr;
}
virtual bool hasEntryPoint() const {
return false;
}
/// Returns the associated clang module if one exists.
virtual const clang::Module *getUnderlyingClangModule() const {
return nullptr;
}
/// Returns the name to use when referencing entities in this file.
///
/// Usually this is the module name itself, but certain Clang features allow
/// substituting another name instead.
virtual StringRef getExportedModuleName() const {
return getParentModule()->getName().str();
}
/// Traverse the decls within this file.
///
/// \returns true if traversal was aborted, false if it completed
/// successfully.
virtual bool walk(ASTWalker &walker);
// Efficiency override for DeclContext::getParentModule().
ModuleDecl *getParentModule() const {
return const_cast<ModuleDecl *>(cast<ModuleDecl>(getParent()));
}
static bool classof(const DeclContext *DC) {
return DC->getContextKind() == DeclContextKind::FileUnit;
}
private:
// Make placement new and vanilla new/delete illegal for FileUnits.
void *operator new(size_t Bytes) throw() = delete;
void *operator new(size_t Bytes, void *Mem) throw() = delete;
void operator delete(void *Data) throw() = delete;
public:
// Only allow allocation of FileUnits using the allocator in ASTContext
// or by doing a placement new.
void *operator new(size_t Bytes, ASTContext &C,
unsigned Alignment = alignOfFileUnit());
};
static inline unsigned alignOfFileUnit() {
return alignof(FileUnit&);
}
/// A file containing Swift source code.
///
/// This is a .swift or .sil file (or a virtual file, such as the contents of
/// the REPL). Since it contains raw source, it must be parsed and name-bound
/// before being used for anything; a full type-check is also necessary for
/// IR generation.
class SourceFile final : public FileUnit {
public:
class Impl;
struct SourceFileSyntaxInfo;
/// The implicit module import that the SourceFile should get.
enum class ImplicitModuleImportKind {
None,
Builtin,
Stdlib
};
/// Possible attributes for imports in source files.
enum class ImportFlags {
/// The imported module is exposed to anyone who imports the parent module.
Exported = 0x1,
/// This source file has access to testable declarations in the imported
/// module.
Testable = 0x2,
/// This source file has access to private declarations in the imported
/// module.
PrivateImport = 0x4,
/// The imported module is an implementation detail of this file and should
/// not be required to be present if the main module is ever imported
/// elsewhere.
///
/// Mutually exclusive with Exported.
ImplementationOnly = 0x8
};
/// \see ImportFlags
using ImportOptions = OptionSet<ImportFlags>;
struct ImportedModuleDesc {
ModuleDecl::ImportedModule module;
ImportOptions importOptions;
StringRef filename;
ImportedModuleDesc(ModuleDecl::ImportedModule module, ImportOptions options,
StringRef filename = {})
: module(module), importOptions(options), filename(filename) {
assert(!(importOptions.contains(ImportFlags::Exported) &&
importOptions.contains(ImportFlags::ImplementationOnly)));
}
};
private:
std::unique_ptr<SourceLookupCache> Cache;
SourceLookupCache &getCache() const;
/// This is the list of modules that are imported by this module.
///
/// This is filled in by the Name Binding phase.
ArrayRef<ImportedModuleDesc> Imports;
/// A unique identifier representing this file; used to mark private decls
/// within the file to keep them from conflicting with other files in the
/// same module.
mutable Identifier PrivateDiscriminator;
/// The root TypeRefinementContext for this SourceFile.
///
/// This is set during type checking.
TypeRefinementContext *TRC = nullptr;
/// If non-null, used to track name lookups that happen within this file.
Optional<ReferencedNameTracker> ReferencedNames;
/// The class in this file marked \@NS/UIApplicationMain.
ClassDecl *MainClass = nullptr;
/// The source location of the main class.
SourceLoc MainClassDiagLoc;
/// A hash of all interface-contributing tokens that have been lexed for
/// this source file so far.
/// We only collect interface hash for primary input files.
llvm::Optional<llvm::MD5> InterfaceHash;
/// The ID for the memory buffer containing this file's source.
///
/// May be -1, to indicate no association with a buffer.
int BufferID;
/// Does this source file have any implementation-only imports?
/// If not, we can fast-path module checks.
bool HasImplementationOnlyImports = false;
/// The scope map that describes this source file.
std::unique_ptr<ASTScope> Scope;
friend ASTContext;
friend Impl;
public:
/// The list of top-level declarations in the source file.
std::vector<Decl*> Decls;
/// A cache of syntax nodes that can be reused when creating the syntax tree
/// for this file.
SyntaxParsingCache *SyntaxParsingCache = nullptr;
/// The list of local type declarations in the source file.
llvm::SetVector<TypeDecl *> LocalTypeDecls;
/// The set of validated opaque return type decls in the source file.
llvm::SmallVector<OpaqueTypeDecl *, 4> OpaqueReturnTypes;
llvm::StringMap<OpaqueTypeDecl *> ValidatedOpaqueReturnTypes;
/// The set of parsed decls with opaque return types that have not yet
/// been validated.
llvm::DenseSet<ValueDecl *> UnvalidatedDeclsWithOpaqueReturnTypes;
/// A set of special declaration attributes which require the
/// Foundation module to be imported to work. If the foundation
/// module is still not imported by the time type checking is
/// complete, we diagnose.
llvm::SetVector<const DeclAttribute *> AttrsRequiringFoundation;
/// A set of synthesized declarations that need to be type checked.
llvm::SmallVector<Decl *, 8> SynthesizedDecls;
/// We might perform type checking on the same source file more than once,
/// if its the main file or a REPL instance, so keep track of the last
/// checked synthesized declaration to avoid duplicating work.
unsigned LastCheckedSynthesizedDecl = 0;
/// A mapping from Objective-C selectors to the methods that have
/// those selectors.
llvm::DenseMap<ObjCSelector, llvm::TinyPtrVector<AbstractFunctionDecl *>>
ObjCMethods;
/// List of Objective-C methods, which is used for checking unintended
/// Objective-C overrides.
std::vector<AbstractFunctionDecl *> ObjCMethodList;
/// An unsatisfied, optional @objc requirement in a protocol conformance.
using ObjCUnsatisfiedOptReq = std::pair<DeclContext *, AbstractFunctionDecl *>;
/// List of optional @objc protocol requirements that have gone
/// unsatisfied, which might conflict with other Objective-C methods.
std::vector<ObjCUnsatisfiedOptReq> ObjCUnsatisfiedOptReqs;
using ObjCMethodConflict = std::tuple<ClassDecl *, ObjCSelector, bool>;
/// List of Objective-C member conflicts we have found during type checking.
std::vector<ObjCMethodConflict> ObjCMethodConflicts;
template <typename T>
using OperatorMap = llvm::DenseMap<Identifier,llvm::PointerIntPair<T,1,bool>>;
OperatorMap<InfixOperatorDecl*> InfixOperators;
OperatorMap<PostfixOperatorDecl*> PostfixOperators;
OperatorMap<PrefixOperatorDecl*> PrefixOperators;
OperatorMap<PrecedenceGroupDecl*> PrecedenceGroups;
/// Describes what kind of file this is, which can affect some type checking
/// and other behavior.
const SourceFileKind Kind;
enum ASTStage_t {
/// Parsing is underway.
Parsing,
/// Parsing has completed.
Parsed,
/// Name binding has completed.
NameBound,
/// Type checking has completed.
TypeChecked
};
/// Defines what phases of parsing and semantic analysis are complete for a
/// source file.
///
/// Only files that have been fully processed (i.e. type-checked) will be
/// forwarded on to IRGen.
ASTStage_t ASTStage = Parsing;
SourceFile(ModuleDecl &M, SourceFileKind K, Optional<unsigned> bufferID,
ImplicitModuleImportKind ModImpKind, bool KeepParsedTokens = false,
bool KeepSyntaxTree = false);
~SourceFile();
void addImports(ArrayRef<ImportedModuleDesc> IM);
enum ImportQueryKind {
/// Return the results for testable or private imports.
TestableAndPrivate,
/// Return the results only for testable imports.
TestableOnly,
/// Return the results only for private imports.
PrivateOnly
};
bool
hasTestableOrPrivateImport(AccessLevel accessLevel, const ValueDecl *ofDecl,
ImportQueryKind kind = TestableAndPrivate) const;
bool hasImplementationOnlyImports() const {
return HasImplementationOnlyImports;
}
bool isImportedImplementationOnly(const ModuleDecl *module) 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();
void cacheVisibleDecls(SmallVectorImpl<ValueDecl *> &&globals) const;
const SmallVectorImpl<ValueDecl *> &getCachedVisibleDecls() const;
virtual void lookupValue(DeclName name, NLKind lookupKind,
SmallVectorImpl<ValueDecl*> &result) const override;
virtual void lookupVisibleDecls(ModuleDecl::AccessPathTy accessPath,
VisibleDeclConsumer &consumer,
NLKind lookupKind) const override;
virtual void lookupClassMembers(ModuleDecl::AccessPathTy accessPath,
VisibleDeclConsumer &consumer) const override;
virtual void
lookupClassMember(ModuleDecl::AccessPathTy accessPath, DeclName name,
SmallVectorImpl<ValueDecl*> &results) const override;
void lookupObjCMethods(
ObjCSelector selector,
SmallVectorImpl<AbstractFunctionDecl *> &results) const override;
virtual void getTopLevelDecls(SmallVectorImpl<Decl*> &results) const override;
virtual void
getPrecedenceGroups(SmallVectorImpl<PrecedenceGroupDecl*> &results) const override;
virtual TypeDecl *lookupLocalType(llvm::StringRef MangledName) const override;
virtual void
getLocalTypeDecls(SmallVectorImpl<TypeDecl*> &results) const override;
virtual void
getOpaqueReturnTypeDecls(SmallVectorImpl<OpaqueTypeDecl*> &results) const override;
virtual void
getImportedModules(SmallVectorImpl<ModuleDecl::ImportedModule> &imports,
ModuleDecl::ImportFilter filter) const override;
virtual void
collectLinkLibraries(ModuleDecl::LinkLibraryCallback callback) const override;
Identifier getDiscriminatorForPrivateValue(const ValueDecl *D) const override;
Identifier getPrivateDiscriminator() const { return PrivateDiscriminator; }
virtual bool walk(ASTWalker &walker) override;
/// @{
/// Look up the given operator in this file.
///
/// The file must be name-bound already. If the operator is not found, or if
/// there is an ambiguity, returns null.
///
/// \param isCascading If true, the lookup of this operator may affect
/// downstream files.
InfixOperatorDecl *lookupInfixOperator(Identifier name, bool isCascading,
SourceLoc diagLoc = {});
PrefixOperatorDecl *lookupPrefixOperator(Identifier name, bool isCascading,
SourceLoc diagLoc = {});
PostfixOperatorDecl *lookupPostfixOperator(Identifier name, bool isCascading,
SourceLoc diagLoc = {});
PrecedenceGroupDecl *lookupPrecedenceGroup(Identifier name, bool isCascading,
SourceLoc diagLoc = {});
/// @}
ReferencedNameTracker *getReferencedNameTracker() {
return ReferencedNames ? ReferencedNames.getPointer() : nullptr;
}
const ReferencedNameTracker *getReferencedNameTracker() const {
return ReferencedNames ? ReferencedNames.getPointer() : nullptr;
}
void createReferencedNameTracker();
/// The buffer ID for the file that was imported, or None if there
/// is no associated buffer.
Optional<unsigned> getBufferID() const {
if (BufferID == -1)
return None;
return BufferID;
}
/// If this buffer corresponds to a file on disk, returns the path.
/// Otherwise, return an empty string.
StringRef getFilename() const;
/// Retrieve the scope that describes this source file.
ASTScope &getScope();
void dump() const;
void dump(raw_ostream &os) const;
/// Pretty-print the contents of this source file.
///
/// \param Printer The AST printer used for printing the contents.
/// \param PO Options controlling the printing process.
void print(ASTPrinter &Printer, const PrintOptions &PO);
void print(raw_ostream &OS, const PrintOptions &PO);
static bool classof(const FileUnit *file) {
return file->getKind() == FileUnitKind::Source;
}
static bool classof(const DeclContext *DC) {
return isa<FileUnit>(DC) && classof(cast<FileUnit>(DC));
}
/// True if this is a "script mode" source file that admits top-level code.
bool isScriptMode() const {
switch (Kind) {
case SourceFileKind::Main:
case SourceFileKind::REPL:
return true;
case SourceFileKind::Library:
case SourceFileKind::Interface:
case SourceFileKind::SIL:
return false;
}
llvm_unreachable("bad SourceFileKind");
}
ClassDecl *getMainClass() const override {
return MainClass;
}
SourceLoc getMainClassDiagLoc() const {
assert(hasMainClass());
return MainClassDiagLoc;
}
/// Register a "main" class for the module, complaining if there is more than
/// one.
///
/// Should only be called during type-checking.
bool registerMainClass(ClassDecl *mainClass, SourceLoc diagLoc);
/// True if this source file has an application entry point.
///
/// This is true if the source file either is in script mode or contains
/// a designated main class.
bool hasEntryPoint() const override {
return isScriptMode() || hasMainClass();
}
/// Get the root refinement context for the file. The root context may be
/// null if the context hierarchy has not been built yet. Use
/// TypeChecker::getOrBuildTypeRefinementContext() to get a built
/// root of the hierarchy.
TypeRefinementContext *getTypeRefinementContext();
/// Set the root refinement context for the file.
void setTypeRefinementContext(TypeRefinementContext *TRC);
void enableInterfaceHash() {
assert(!hasInterfaceHash());
InterfaceHash.emplace();
}
bool hasInterfaceHash() const {
return InterfaceHash.hasValue();
}
void recordInterfaceToken(StringRef token) {
assert(!token.empty());
InterfaceHash->update(token);
// Add null byte to separate tokens.
uint8_t a[1] = {0};
InterfaceHash->update(a);
}
void getInterfaceHash(llvm::SmallString<32> &str) {
llvm::MD5::MD5Result result;
InterfaceHash->final(result);
llvm::MD5::stringifyResult(result, str);
}
void dumpInterfaceHash(llvm::raw_ostream &out) {
llvm::SmallString<32> str;
getInterfaceHash(str);
out << str << '\n';
}
std::vector<Token> &getTokenVector();
ArrayRef<Token> getAllTokens() const;
bool shouldCollectToken() const;
bool shouldBuildSyntaxTree() const;
bool canBeParsedInFull() const;
bool isSuitableForASTScopes() const { return canBeParsedInFull(); }
syntax::SourceFileSyntax getSyntaxRoot() const;
void setSyntaxRoot(syntax::SourceFileSyntax &&Root);
bool hasSyntaxRoot() const;
OpaqueTypeDecl *lookupOpaqueResultType(StringRef MangledName,
LazyResolver *resolver) override;
void addUnvalidatedDeclWithOpaqueResultType(ValueDecl *vd) {
UnvalidatedDeclsWithOpaqueReturnTypes.insert(vd);
}
void markDeclWithOpaqueResultTypeAsValidated(ValueDecl *vd);
private:
/// If not None, the underlying vector should contain tokens of this source file.
Optional<std::vector<Token>> AllCorrectedTokens;
std::unique_ptr<SourceFileSyntaxInfo> SyntaxInfo;
};
/// This represents the compiler's implicitly generated declarations in the
/// Builtin module.
class BuiltinUnit final : public FileUnit {
public:
class LookupCache;
private:
std::unique_ptr<LookupCache> Cache;
LookupCache &getCache() const;
friend ASTContext;
~BuiltinUnit() = default;
public:
explicit BuiltinUnit(ModuleDecl &M);
virtual void lookupValue(DeclName name, NLKind lookupKind,
SmallVectorImpl<ValueDecl*> &result) const override;
/// Find all Objective-C methods with the given selector.
void lookupObjCMethods(
ObjCSelector selector,
SmallVectorImpl<AbstractFunctionDecl *> &results) const override;
Identifier
getDiscriminatorForPrivateValue(const ValueDecl *D) const override {
llvm_unreachable("no private values in the Builtin module");
}
static bool classof(const FileUnit *file) {
return file->getKind() == FileUnitKind::Builtin;
}
static bool classof(const DeclContext *DC) {
return isa<FileUnit>(DC) && classof(cast<FileUnit>(DC));
}
};
/// Represents an externally-loaded file of some kind.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
class LoadedFile : public FileUnit {
#pragma clang diagnostic pop
protected:
LoadedFile(FileUnitKind Kind, ModuleDecl &M) noexcept
: FileUnit(Kind, M) {
assert(classof(this) && "invalid kind");
}
public:
/// Returns an arbitrary string representing the storage backing this file.
///
/// This is usually a filesystem path.
virtual StringRef getFilename() const;
virtual StringRef getFilenameForPrivateDecl(const ValueDecl *decl) const {
return StringRef();
}
/// Look up an operator declaration.
///
/// \param name The operator name ("+", ">>", etc.)
///
/// \param fixity One of PrefixOperator, InfixOperator, or PostfixOperator.
virtual OperatorDecl *lookupOperator(Identifier name, DeclKind fixity) const {
return nullptr;
}
/// Look up a precedence group.
///
/// \param name The precedence group name.
virtual PrecedenceGroupDecl *lookupPrecedenceGroup(Identifier name) const {
return nullptr;
}
/// Returns the Swift module that overlays a Clang module.
virtual ModuleDecl *getOverlayModule() const { return nullptr; }
virtual bool isSystemModule() const { return false; }
/// Retrieve the set of generic signatures stored within this module.
///
/// \returns \c true if this module file supports retrieving all of the
/// generic signatures, \c false otherwise.
virtual bool getAllGenericSignatures(
SmallVectorImpl<GenericSignature*> &genericSignatures) {
return false;
}
static bool classof(const FileUnit *file) {
return file->getKind() == FileUnitKind::SerializedAST ||
file->getKind() == FileUnitKind::ClangModule ||
file->getKind() == FileUnitKind::DWARFModule;
}
static bool classof(const DeclContext *DC) {
return isa<FileUnit>(DC) && classof(cast<FileUnit>(DC));
}
};
inline SourceFile &
ModuleDecl::getMainSourceFile(SourceFileKind expectedKind) const {
assert(!Files.empty() && "No files added yet");
assert(cast<SourceFile>(Files.front())->Kind == expectedKind);
return *cast<SourceFile>(Files.front());
}
inline FileUnit &ModuleDecl::getMainFile(FileUnitKind expectedKind) const {
assert(expectedKind != FileUnitKind::Source &&
"must use specific source kind; see getMainSourceFile");
assert(!Files.empty() && "No files added yet");
assert(Files.front()->getKind() == expectedKind);
return *Files.front();
}
/// Wraps either a swift module or a clang one.
/// FIXME: Should go away once swift modules can support submodules natively.
class ModuleEntity {