blob: 051c60acbad5c8cf8730a23005deb76bf6b5e5bf [file] [log] [blame]
//===--- FileUnit.h - The contents of a module ------------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2019 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
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_AST_FILEUNIT_H
#define SWIFT_AST_FILEUNIT_H
#include "swift/AST/Module.h"
namespace swift {
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();
friend class DirectOperatorLookupRequest;
friend class DirectPrecedenceGroupLookupRequest;
// 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) {
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(ImportPath::Access 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(ImportPath::Access 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(ImportPath::Access 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;
/// Find all SPI names imported from \p importedModule by this module,
/// collecting the identifiers in \p spiGroups.
virtual void lookupImportedSPIGroups(
const ModuleDecl *importedModule,
SmallSetVector<Identifier, 4> &spiGroups) const {};
virtual Optional<Fingerprint>
loadFingerprint(const IterableDeclContext *IDC) const { return None; }
protected:
/// Look up an operator declaration. Do not call directly, use
/// \c DirectOperatorLookupRequest instead.
///
/// \param name The operator name ("+", ">>", etc.)
///
/// \param fixity One of Prefix, Infix, or Postfix.
virtual void
lookupOperatorDirect(Identifier name, OperatorFixity fixity,
TinyPtrVector<OperatorDecl *> &results) const {}
/// Look up a precedence group. Do not call directly, use
/// \c DirectPrecedenceGroupLookupRequest instead.
///
/// \param name The precedence group name.
virtual void lookupPrecedenceGroupDirect(
Identifier name, TinyPtrVector<PrecedenceGroupDecl *> &results) const {}
public:
/// 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 Optional<BasicDeclLocs> getBasicLocsForDecl(const Decl *D) 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 {}
virtual void
getExportedPrespecializations(SmallVectorImpl<Decl *> &results) const {}
/// Finds top-level decls in this file 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 keep only
/// decls with matching attributes. The subclass SerializedASTFile checks the
/// attributes first to only deserialize decls with accepted attributes,
/// limiting deserialization work.
virtual void
getTopLevelDeclsWhereAttributesMatch(
SmallVectorImpl<Decl*> &Results,
llvm::function_ref<bool(DeclAttributes)> matchAttributes) const;
/// Finds all operator 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
getOperatorDecls(SmallVectorImpl<OperatorDecl *> &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<ImportedModule> &imports,
ModuleDecl::ImportFilter filter) const {}
/// \see ModuleDecl::getImportedModulesForLookup
virtual void getImportedModulesForLookup(
SmallVectorImpl<ImportedModule> &imports) const {
return getImportedModules(imports, ModuleDecl::ImportFilterKind::Exported);
}
/// Generates the list of libraries needed to link this file, based on its
/// imports.
virtual void
collectLinkLibraries(ModuleDecl::LinkLibraryCallback callback) const {}
/// Returns the path of the file or directory that defines the module
/// represented by this \c FileUnit, or empty string if there is none.
/// Cross-import overlay specifiers are found relative to this path.
virtual StringRef getModuleDefiningPath() const {
return "";
}
/// True if this file contains the main class for the module.
bool hasMainClass() const {
return getMainClass();
}
ClassDecl *getMainClass() const {
return dyn_cast_or_null<ClassDecl>(getMainDecl());
}
bool hasMainDecl() const { return getMainDecl(); }
virtual Decl *getMainDecl() const { return nullptr; }
FuncDecl *getMainFunc() const {
return dyn_cast_or_null<FuncDecl>(getMainDecl());
}
virtual bool hasEntryPoint() const {
return false;
}
virtual ModuleDecl *getUnderlyingModuleIfOverlay() const {
return nullptr;
}
/// 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&);
}
/// 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();
}
/// Returns the Swift module that overlays a Clang module.
virtual ModuleDecl *getOverlayModule() const { return nullptr; }
virtual bool isSystemModule() const { return false; }
/// Checks whether an error was encountered while loading the file.
virtual bool hadLoadError() 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));
}
};
void simple_display(llvm::raw_ostream &out, const FileUnit *file);
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();
}
} // end namespace swift
#endif