mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
When a module has been imported `@preconcurrency` in source, when it is printed in a `swiftinterface` file it should be printed along with the attribute to ensure that type checking of the module's public declarations behaves consistently. This fix is a little unsatisfying because it adds another a linear scan over all imports in the source for each printed import. This should be improved, but it can be done later. Resolves rdar://136857313.
513 lines
18 KiB
C++
513 lines
18 KiB
C++
//===--- 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"
|
|
#include "swift/AST/RawComment.h"
|
|
#include "swift/Basic/BasicSourceInfo.h"
|
|
#include "swift/Basic/Debug.h"
|
|
#include "swift/Basic/Version.h"
|
|
|
|
#include "llvm/ADT/PointerIntPair.h"
|
|
|
|
namespace swift {
|
|
class SynthesizedFileUnit;
|
|
|
|
/// 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, public ASTAllocated<FileUnit> {
|
|
#pragma clang diagnostic pop
|
|
virtual void anchor();
|
|
|
|
friend class DirectOperatorLookupRequest;
|
|
friend class DirectPrecedenceGroupLookupRequest;
|
|
|
|
/// The pointer is FileUnit insted of SynthesizedFileUnit to break
|
|
/// circularity.
|
|
llvm::PointerIntPair<FileUnit *, 3, FileUnitKind> SynthesizedFileAndKind;
|
|
|
|
protected:
|
|
FileUnit(FileUnitKind kind, ModuleDecl &M)
|
|
: DeclContext(DeclContextKind::FileUnit, &M),
|
|
SynthesizedFileAndKind(nullptr, kind) {
|
|
}
|
|
|
|
public:
|
|
FileUnitKind getKind() const {
|
|
return SynthesizedFileAndKind.getInt();
|
|
}
|
|
|
|
/// Returns the synthesized file for this source file, if it exists.
|
|
SynthesizedFileUnit *getSynthesizedFile() const;
|
|
|
|
/// Returns the synthesized file for this source file, creating one and
|
|
/// inserting it into the module if it does not exist.
|
|
SynthesizedFileUnit &getOrCreateSynthesizedFile();
|
|
|
|
/// 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,
|
|
OptionSet<ModuleLookupFlags> Flags,
|
|
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,
|
|
llvm::SmallSetVector<Identifier, 4> &spiGroups) const {};
|
|
|
|
/// Returns true if any import of \p importedModule has the `@preconcurrency`
|
|
/// attribute.
|
|
virtual bool
|
|
isModuleImportedPreconcurrency(const ModuleDecl *importedModule) const {
|
|
return false;
|
|
};
|
|
|
|
/// Find all availability domains defined in this module with the given
|
|
/// identifier.
|
|
///
|
|
/// This does a simple local lookup, not recursively looking through imports.
|
|
virtual void lookupAvailabilityDomains(
|
|
Identifier identifier,
|
|
SmallVectorImpl<AvailabilityDomain> &results) const {};
|
|
|
|
virtual std::optional<Fingerprint>
|
|
loadFingerprint(const IterableDeclContext *IDC) const {
|
|
return std::nullopt;
|
|
}
|
|
|
|
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::getSemanticBriefComment().
|
|
virtual std::optional<CommentInfo> getCommentForDecl(const Decl *D) const {
|
|
return std::nullopt;
|
|
}
|
|
|
|
/// For a serialized AST file, returns \c true if an adjacent swiftdoc has been
|
|
/// loaded. Otherwise, returns \c false.
|
|
virtual bool hasLoadedSwiftDoc() const { return false; }
|
|
|
|
virtual std::optional<StringRef> getGroupNameForDecl(const Decl *D) const {
|
|
return std::nullopt;
|
|
}
|
|
|
|
virtual std::optional<StringRef>
|
|
getSourceFileNameForDecl(const Decl *D) const {
|
|
return std::nullopt;
|
|
}
|
|
|
|
virtual std::optional<unsigned> getSourceOrderForDecl(const Decl *D) const {
|
|
return std::nullopt;
|
|
}
|
|
|
|
virtual std::optional<StringRef> getGroupNameByUSR(StringRef USR) const {
|
|
return std::nullopt;
|
|
}
|
|
|
|
virtual std::optional<ExternalSourceLocs::RawLocs>
|
|
getExternalRawLocsForDecl(const Decl *D) const {
|
|
return std::nullopt;
|
|
}
|
|
|
|
virtual void collectAllGroups(SmallVectorImpl<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
|
|
getDiscriminatorForPrivateDecl(const Decl *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 top-level decls in this file with their auxiliary decls such as
|
|
/// macro expansions.
|
|
///
|
|
/// This does a simple local lookup, not recursively looking through imports.
|
|
/// The order of the results is not guaranteed to be meaningful.
|
|
void getTopLevelDeclsWithAuxiliaryDecls(
|
|
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, bool recursive = false) 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 {}
|
|
|
|
/// Looks up which external macros are defined by this file.
|
|
virtual void
|
|
getExternalMacros(SmallVectorImpl<ExternalMacroPlugin> ¯os) const {}
|
|
|
|
/// Lists modules that are not imported from this file and used in API.
|
|
virtual void getImplicitImportsForModuleInterface(
|
|
SmallVectorImpl<ImportedModule> &imports) 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 {}
|
|
|
|
/// Load extra dependencies of this module to satisfy a testable import.
|
|
virtual void loadDependenciesForTestable(SourceLoc diagLoc) 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 ValueDecl *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 real name of the enclosing module to use when referencing entities in this file.
|
|
/// The 'real name' is the actual binary name of the module, which can be different from the 'name'
|
|
/// if module aliasing was used (via -module-alias flag).
|
|
///
|
|
/// This is usually the module real name which can be overriden by an
|
|
/// `export_as` definition of a clang module, or `-export-as` flag on an
|
|
/// imported Swift module. Swift modules built from source do not apply
|
|
/// their own `-export-as` flag, this way the swiftinterface can be
|
|
/// verified.
|
|
virtual StringRef getExportedModuleName() const {
|
|
return getParentModule()->getRealName().str();
|
|
}
|
|
|
|
/// Returns the public facing name of this module, only if it is set
|
|
/// explicitly.
|
|
virtual StringRef getPublicModuleName() const {
|
|
return {};
|
|
}
|
|
|
|
/// Returns the version of the Swift compiler used to create generate
|
|
/// .swiftinterface file if this file is produced from one.
|
|
virtual version::Version getSwiftInterfaceCompilerVersion() const {
|
|
return {};
|
|
}
|
|
|
|
SWIFT_DEBUG_DUMPER(dumpDisplayDecls());
|
|
SWIFT_DEBUG_DUMPER(dumpTopLevelDecls());
|
|
|
|
/// 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;
|
|
}
|
|
|
|
using ASTAllocated<FileUnit>::operator new;
|
|
using ASTAllocated<FileUnit>::operator delete;
|
|
};
|
|
|
|
/// 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,
|
|
OptionSet<ModuleLookupFlags> Flags,
|
|
SmallVectorImpl<ValueDecl*> &result) const override;
|
|
|
|
/// Find all Objective-C methods with the given selector.
|
|
void lookupObjCMethods(
|
|
ObjCSelector selector,
|
|
SmallVectorImpl<AbstractFunctionDecl *> &results) const override;
|
|
|
|
Identifier
|
|
getDiscriminatorForPrivateDecl(const Decl *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 the language version that was used to compile the contents of this
|
|
/// file. An empty `Version` is returned if the information is not available.
|
|
virtual version::Version getLanguageVersionBuiltWith() const = 0;
|
|
|
|
/// Returns an arbitrary string representing the storage backing this file.
|
|
///
|
|
/// This is usually a filesystem path.
|
|
virtual StringRef getFilename() const;
|
|
|
|
/// Get the path to the file loaded by the compiler. Usually the binary
|
|
/// swiftmodule file or a pcm in the cache. Returns an empty string if not
|
|
/// applicable.
|
|
virtual StringRef getLoadedFilename() const { return StringRef(); }
|
|
|
|
/// Returns the path of the file for the module represented by this
|
|
/// \c FileUnit, or an empty string if there is none. For modules either
|
|
/// built by or adjacent to a module interface, returns the module
|
|
/// interface instead.
|
|
virtual StringRef getSourceFilename() const {
|
|
return getModuleDefiningPath();
|
|
}
|
|
|
|
virtual StringRef getFilenameForPrivateDecl(const Decl *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;
|
|
}
|
|
|
|
virtual void collectBasicSourceFileInfo(
|
|
llvm::function_ref<void(const BasicSourceFileInfo &)> callback) const {}
|
|
|
|
virtual void collectSerializedSearchPath(
|
|
llvm::function_ref<void(StringRef)> callback) const {}
|
|
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");
|
|
|
|
auto files = getFiles();
|
|
assert(!files.empty() && "No files in module");
|
|
assert(files.front()->getKind() == expectedKind);
|
|
return *files.front();
|
|
}
|
|
|
|
} // end namespace swift
|
|
|
|
#endif
|