[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:
Becca Royal-Gordon
2021-10-27 12:23:52 -07:00
parent b9480f12d0
commit 21f58ec78f
7 changed files with 48 additions and 50 deletions

View File

@@ -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.

View 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

View File

@@ -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); }

View File

@@ -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);

View File

@@ -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;
} }

View File

@@ -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;
} }

View File

@@ -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;
} }