Skip to content

Commit 07b2001

Browse files
committed
[Serialization] Keep buffers alive if they may have diagnostics
This can only happen in one case today: a module imports a bridging header, but the header on disk has disappeared, and now we need to fall back to the (often inadequate) version that's stored inside the swiftmodule file. Even if the module fails to load, the bridging header has already been imported, and so anything else that happens might still emit diagnostics and need that text to be alive, which means we need to keep the buffer alive too.
1 parent a18dc11 commit 07b2001

File tree

4 files changed

+28
-1
lines changed

4 files changed

+28
-1
lines changed

include/swift/Serialization/ModuleFile.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -620,6 +620,13 @@ class ModuleFile
620620
return static_cast<Status>(Bits.Status);
621621
}
622622

623+
/// Transfers ownership of a buffer that might contain source code where
624+
/// other parts of the compiler could have emitted diagnostics, to keep them
625+
/// alive even if the ModuleFile is destroyed.
626+
///
627+
/// Should only be called when getStatus() indicates a failure.
628+
std::unique_ptr<llvm::MemoryBuffer> takeBufferForDiagnostics();
629+
623630
/// Returns the list of modules this module depends on.
624631
ArrayRef<Dependency> getDependencies() const {
625632
return Dependencies;

include/swift/Serialization/SerializedModuleLoader.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ class SerializedModuleLoader : public ModuleLoader {
2929
using LoadedModulePair = std::pair<std::unique_ptr<ModuleFile>, unsigned>;
3030
std::vector<LoadedModulePair> LoadedModuleFiles;
3131

32+
SmallVector<std::unique_ptr<llvm::MemoryBuffer>, 2> OrphanedMemoryBuffers;
33+
3234
explicit SerializedModuleLoader(ASTContext &ctx, DependencyTracker *tracker);
3335

3436
public:

lib/Serialization/ModuleFile.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1457,6 +1457,17 @@ Status ModuleFile::associateWithFileContext(FileUnit *file,
14571457
return getStatus();
14581458
}
14591459

1460+
std::unique_ptr<llvm::MemoryBuffer> ModuleFile::takeBufferForDiagnostics() {
1461+
assert(getStatus() != Status::Valid);
1462+
1463+
// Today, the only buffer that might have diagnostics in them is the input
1464+
// buffer, and even then only if it has imported module contents.
1465+
if (!importedHeaderInfo.contents.empty())
1466+
return std::move(ModuleInputBuffer);
1467+
1468+
return nullptr;
1469+
}
1470+
14601471
ModuleFile::~ModuleFile() { }
14611472

14621473
void ModuleFile::lookupValue(DeclName name,

lib/Serialization/SerializedModuleLoader.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,14 @@ FileUnit *SerializedModuleLoader::loadAST(
223223
M.removeFile(*fileUnit);
224224
}
225225

226-
// This is the failure path. If we have a location, diagnose the issue.
226+
// From here on is the failure path.
227+
228+
// Even though the module failed to load, it's possible its contents include
229+
// a source buffer that need to survive because it's already been used for
230+
// diagnostics.
231+
if (auto orphanedBuffer = loadedModuleFile->takeBufferForDiagnostics())
232+
OrphanedMemoryBuffers.push_back(std::move(orphanedBuffer));
233+
227234
if (!diagLoc)
228235
return nullptr;
229236

0 commit comments

Comments
 (0)