mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[NFC] Attach SynthesizedFile to any FileUnit
Gives us a place to stuff synthesized declarations for, among other things, imported Clang decls.
This commit is contained in:
@@ -17,7 +17,11 @@
|
|||||||
#include "swift/AST/RawComment.h"
|
#include "swift/AST/RawComment.h"
|
||||||
#include "swift/Basic/BasicSourceInfo.h"
|
#include "swift/Basic/BasicSourceInfo.h"
|
||||||
|
|
||||||
|
#include "llvm/ADT/PointerIntPair.h"
|
||||||
|
|
||||||
namespace swift {
|
namespace swift {
|
||||||
|
class SynthesizedFileUnit;
|
||||||
|
|
||||||
/// A container for module-scope declarations that itself provides a scope; the
|
/// A container for module-scope declarations that itself provides a scope; the
|
||||||
/// smallest unit of code organization.
|
/// smallest unit of code organization.
|
||||||
///
|
///
|
||||||
@@ -33,19 +37,25 @@ class FileUnit : public DeclContext, public ASTAllocated<FileUnit> {
|
|||||||
friend class DirectOperatorLookupRequest;
|
friend class DirectOperatorLookupRequest;
|
||||||
friend class DirectPrecedenceGroupLookupRequest;
|
friend class DirectPrecedenceGroupLookupRequest;
|
||||||
|
|
||||||
// FIXME: Stick this in a PointerIntPair.
|
// The pointer is FileUnit insted of SynthesizedFileUnit to break circularity.
|
||||||
const FileUnitKind Kind;
|
llvm::PointerIntPair<FileUnit *, 3, FileUnitKind> SynthesizedFileAndKind;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
FileUnit(FileUnitKind kind, ModuleDecl &M)
|
FileUnit(FileUnitKind kind, ModuleDecl &M)
|
||||||
: DeclContext(DeclContextKind::FileUnit, &M), Kind(kind) {
|
: DeclContext(DeclContextKind::FileUnit, &M),
|
||||||
|
SynthesizedFileAndKind(nullptr, kind) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FileUnitKind getKind() const {
|
FileUnitKind getKind() const {
|
||||||
return Kind;
|
return SynthesizedFileAndKind.getInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the synthesized file for this source file, if it exists.
|
||||||
|
SynthesizedFileUnit *getSynthesizedFile() const;
|
||||||
|
|
||||||
|
SynthesizedFileUnit &getOrCreateSynthesizedFile();
|
||||||
|
|
||||||
/// Look up a (possibly overloaded) value set at top-level scope
|
/// Look up a (possibly overloaded) value set at top-level scope
|
||||||
/// (but with the specified access path, which may come from an import decl)
|
/// (but with the specified access path, which may come from an import decl)
|
||||||
/// within this file.
|
/// within this file.
|
||||||
|
|||||||
@@ -89,9 +89,6 @@ private:
|
|||||||
/// same module.
|
/// same module.
|
||||||
mutable Identifier PrivateDiscriminator;
|
mutable Identifier PrivateDiscriminator;
|
||||||
|
|
||||||
/// A synthesized file corresponding to this file, created on-demand.
|
|
||||||
SynthesizedFileUnit *SynthesizedFile = nullptr;
|
|
||||||
|
|
||||||
/// The root TypeRefinementContext for this SourceFile.
|
/// The root TypeRefinementContext for this SourceFile.
|
||||||
///
|
///
|
||||||
/// This is set during type checking.
|
/// This is set during type checking.
|
||||||
@@ -409,11 +406,6 @@ public:
|
|||||||
Optional<ExternalSourceLocs::RawLocs>
|
Optional<ExternalSourceLocs::RawLocs>
|
||||||
getExternalRawLocsForDecl(const Decl *D) const override;
|
getExternalRawLocsForDecl(const Decl *D) const override;
|
||||||
|
|
||||||
/// Returns the synthesized file for this source file, if it exists.
|
|
||||||
SynthesizedFileUnit *getSynthesizedFile() const { return SynthesizedFile; };
|
|
||||||
|
|
||||||
SynthesizedFileUnit &getOrCreateSynthesizedFile();
|
|
||||||
|
|
||||||
virtual bool walk(ASTWalker &walker) override;
|
virtual bool walk(ASTWalker &walker) override;
|
||||||
|
|
||||||
/// The buffer ID for the file that was imported, or None if there
|
/// The buffer ID for the file that was imported, or None if there
|
||||||
|
|||||||
@@ -18,14 +18,12 @@
|
|||||||
|
|
||||||
namespace swift {
|
namespace swift {
|
||||||
|
|
||||||
class SourceFile;
|
|
||||||
|
|
||||||
/// A container for synthesized declarations, attached to a `SourceFile`.
|
/// A container for synthesized declarations, attached to a `SourceFile`.
|
||||||
///
|
///
|
||||||
/// Currently, only module-level synthesized declarations are supported.
|
/// Currently, only module-level synthesized declarations are supported.
|
||||||
class SynthesizedFileUnit final : public FileUnit {
|
class SynthesizedFileUnit final : public FileUnit {
|
||||||
/// The parent source file.
|
/// The parent source file.
|
||||||
SourceFile &SF;
|
FileUnit &FU;
|
||||||
|
|
||||||
/// Synthesized top level declarations.
|
/// Synthesized top level declarations.
|
||||||
TinyPtrVector<Decl *> TopLevelDecls;
|
TinyPtrVector<Decl *> TopLevelDecls;
|
||||||
@@ -36,11 +34,11 @@ class SynthesizedFileUnit final : public FileUnit {
|
|||||||
mutable Identifier PrivateDiscriminator;
|
mutable Identifier PrivateDiscriminator;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SynthesizedFileUnit(SourceFile &SF);
|
SynthesizedFileUnit(FileUnit &FU);
|
||||||
~SynthesizedFileUnit() = default;
|
~SynthesizedFileUnit() = default;
|
||||||
|
|
||||||
/// Returns the parent source file.
|
/// Returns the parent source file.
|
||||||
SourceFile &getSourceFile() const { return SF; }
|
FileUnit &getFileUnit() const { return FU; }
|
||||||
|
|
||||||
/// Add a synthesized top-level declaration.
|
/// Add a synthesized top-level declaration.
|
||||||
void addTopLevelDecl(Decl *D) { TopLevelDecls.push_back(D); }
|
void addTopLevelDecl(Decl *D) { TopLevelDecls.push_back(D); }
|
||||||
|
|||||||
@@ -2857,7 +2857,8 @@ ASTScope &SourceFile::getScope() {
|
|||||||
|
|
||||||
Identifier
|
Identifier
|
||||||
SourceFile::getDiscriminatorForPrivateValue(const ValueDecl *D) const {
|
SourceFile::getDiscriminatorForPrivateValue(const ValueDecl *D) const {
|
||||||
assert(D->getDeclContext()->getModuleScopeContext() == this);
|
assert(D->getDeclContext()->getModuleScopeContext() == this ||
|
||||||
|
D->getDeclContext()->getModuleScopeContext() == getSynthesizedFile());
|
||||||
|
|
||||||
if (!PrivateDiscriminator.empty())
|
if (!PrivateDiscriminator.empty())
|
||||||
return PrivateDiscriminator;
|
return PrivateDiscriminator;
|
||||||
@@ -2896,11 +2897,19 @@ SourceFile::getDiscriminatorForPrivateValue(const ValueDecl *D) const {
|
|||||||
return PrivateDiscriminator;
|
return PrivateDiscriminator;
|
||||||
}
|
}
|
||||||
|
|
||||||
SynthesizedFileUnit &SourceFile::getOrCreateSynthesizedFile() {
|
SynthesizedFileUnit *FileUnit::getSynthesizedFile() const {
|
||||||
if (SynthesizedFile)
|
return cast_or_null<SynthesizedFileUnit>(SynthesizedFileAndKind.getPointer());
|
||||||
return *SynthesizedFile;
|
}
|
||||||
SynthesizedFile = new (getASTContext()) SynthesizedFileUnit(*this);
|
|
||||||
getParentModule()->addFile(*SynthesizedFile);
|
SynthesizedFileUnit &FileUnit::getOrCreateSynthesizedFile() {
|
||||||
|
auto SynthesizedFile = getSynthesizedFile();
|
||||||
|
if (!SynthesizedFile) {
|
||||||
|
if (auto thisSynth = dyn_cast<SynthesizedFileUnit>(this))
|
||||||
|
return *thisSynth;
|
||||||
|
SynthesizedFile = new (getASTContext()) SynthesizedFileUnit(*this);
|
||||||
|
SynthesizedFileAndKind.setPointer(SynthesizedFile);
|
||||||
|
getParentModule()->addFile(*SynthesizedFile);
|
||||||
|
}
|
||||||
return *SynthesizedFile;
|
return *SynthesizedFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2950,9 +2959,9 @@ SourceFile::lookupOpaqueResultType(StringRef MangledName) {
|
|||||||
// SynthesizedFileUnit Implementation
|
// SynthesizedFileUnit Implementation
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
SynthesizedFileUnit::SynthesizedFileUnit(SourceFile &SF)
|
SynthesizedFileUnit::SynthesizedFileUnit(FileUnit &FU)
|
||||||
: FileUnit(FileUnitKind::Synthesized, *SF.getParentModule()), SF(SF) {
|
: FileUnit(FileUnitKind::Synthesized, *FU.getParentModule()), FU(FU) {
|
||||||
SF.getASTContext().addDestructorCleanup(*this);
|
FU.getASTContext().addDestructorCleanup(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
Identifier
|
Identifier
|
||||||
@@ -2963,23 +2972,15 @@ SynthesizedFileUnit::getDiscriminatorForPrivateValue(const ValueDecl *D) const {
|
|||||||
if (!PrivateDiscriminator.empty())
|
if (!PrivateDiscriminator.empty())
|
||||||
return PrivateDiscriminator;
|
return PrivateDiscriminator;
|
||||||
|
|
||||||
StringRef sourceFileName = getSourceFile().getFilename();
|
// Start with the discriminator that the file we belong to would use.
|
||||||
if (sourceFileName.empty()) {
|
auto ownerDiscriminator = getFileUnit().getDiscriminatorForPrivateValue(D);
|
||||||
assert(1 == count_if(getParentModule()->getFiles(),
|
|
||||||
[](const FileUnit *FU) -> bool {
|
|
||||||
return isa<SourceFile>(FU) &&
|
|
||||||
cast<SourceFile>(FU)->getFilename().empty();
|
|
||||||
}) &&
|
|
||||||
"Cannot promise uniqueness if multiple source files are nameless");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use a discriminator invariant across Swift version: a hash of the module
|
// Hash that with a special string to produce a different value that preserves
|
||||||
// name, the parent source file name, and a special string.
|
// the entropy of the original.
|
||||||
llvm::MD5 hash;
|
|
||||||
hash.update(getParentModule()->getName().str());
|
|
||||||
hash.update(llvm::sys::path::filename(sourceFileName));
|
|
||||||
// TODO: Use a more robust discriminator for synthesized files. Pick something
|
// TODO: Use a more robust discriminator for synthesized files. Pick something
|
||||||
// that cannot conflict with `SourceFile` discriminators.
|
// that cannot conflict with `SourceFile` discriminators.
|
||||||
|
llvm::MD5 hash;
|
||||||
|
hash.update(ownerDiscriminator.str());
|
||||||
hash.update("SYNTHESIZED FILE");
|
hash.update("SYNTHESIZED FILE");
|
||||||
llvm::MD5::MD5Result result;
|
llvm::MD5::MD5Result result;
|
||||||
hash.final(result);
|
hash.final(result);
|
||||||
|
|||||||
@@ -68,10 +68,9 @@ TinyPtrVector<FileUnit *> IRGenDescriptor::getFilesToEmit() const {
|
|||||||
TinyPtrVector<FileUnit *> files;
|
TinyPtrVector<FileUnit *> files;
|
||||||
files.push_back(primary);
|
files.push_back(primary);
|
||||||
|
|
||||||
if (auto *SF = dyn_cast<SourceFile>(primary)) {
|
if (auto *synthesizedFile = primary->getSynthesizedFile())
|
||||||
if (auto *synthesizedFile = SF->getSynthesizedFile())
|
files.push_back(synthesizedFile);
|
||||||
files.push_back(synthesizedFile);
|
|
||||||
}
|
|
||||||
return files;
|
return files;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3946,8 +3946,8 @@ NormalProtocolConformance *GetImplicitSendableRequest::evaluate(
|
|||||||
nominal->addExtension(extension);
|
nominal->addExtension(extension);
|
||||||
|
|
||||||
// Make it accessible to getTopLevelDecls()
|
// Make it accessible to getTopLevelDecls()
|
||||||
if (auto sf = dyn_cast<SourceFile>(nominal->getModuleScopeContext()))
|
if (auto file = dyn_cast<FileUnit>(nominal->getModuleScopeContext()))
|
||||||
sf->getOrCreateSynthesizedFile().addTopLevelDecl(extension);
|
file->getOrCreateSynthesizedFile().addTopLevelDecl(extension);
|
||||||
|
|
||||||
conformanceDC = extension;
|
conformanceDC = extension;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1203,10 +1203,8 @@ void TBDGenVisitor::visit(const TBDGenDescriptor &desc) {
|
|||||||
visitFile(singleFile);
|
visitFile(singleFile);
|
||||||
|
|
||||||
// Visit synthesized file, if it exists.
|
// Visit synthesized file, if it exists.
|
||||||
if (auto *SF = dyn_cast<SourceFile>(singleFile)) {
|
if (auto *synthesizedFile = singleFile->getSynthesizedFile())
|
||||||
if (auto *synthesizedFile = SF->getSynthesizedFile())
|
visitFile(synthesizedFile);
|
||||||
visitFile(synthesizedFile);
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user