[clang][deps] Enable calling DepScanFile::getBuffer() repeatedly (#168789)

This PR makes it possible to call `getBuffer()` on `DepScanFile` (a
`llvm::vfs::File`) repeatedly. Previously, this function would return a
moved-from `unique_ptr`. This doesn't fix any existing bugs, I
discovered this while experimenting with the VFSs in the scanner. Note
that the returned instances of `llvm::MemoryBuffer` are non-owning and
share the underlying buffer storage.
This commit is contained in:
Jan Svoboda
2025-11-19 16:03:30 -08:00
committed by GitHub
parent 80f862b692
commit 835951325e
2 changed files with 35 additions and 1 deletions

View File

@@ -366,7 +366,8 @@ public:
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
getBuffer(const Twine &Name, int64_t FileSize, bool RequiresNullTerminator,
bool IsVolatile) override {
return std::move(Buffer);
return llvm::MemoryBuffer::getMemBuffer(Buffer->getMemBufferRef(),
RequiresNullTerminator);
}
std::error_code close() override { return {}; }

View File

@@ -13,6 +13,39 @@
using namespace clang::tooling::dependencies;
TEST(DependencyScanningFilesystem, OpenFileAndGetBufferRepeatedly) {
auto InMemoryFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
InMemoryFS->setCurrentWorkingDirectory("/");
InMemoryFS->addFile("/foo", 0, llvm::MemoryBuffer::getMemBuffer("content"));
DependencyScanningFilesystemSharedCache SharedCache;
DependencyScanningWorkerFilesystem DepFS(SharedCache, InMemoryFS);
auto FileOrErr1 = DepFS.openFileForRead("foo");
auto FileOrErr2 = DepFS.openFileForRead("foo");
ASSERT_EQ(FileOrErr1.getError(), std::error_code{});
ASSERT_EQ(FileOrErr1.getError(), std::error_code{});
std::unique_ptr<llvm::vfs::File> File1 = std::move(*FileOrErr1);
std::unique_ptr<llvm::vfs::File> File2 = std::move(*FileOrErr2);
ASSERT_NE(File1, nullptr);
ASSERT_NE(File2, nullptr);
auto BufOrErr11 = File1->getBuffer("buf11");
auto BufOrErr12 = File1->getBuffer("buf12");
auto BufOrErr21 = File1->getBuffer("buf21");
ASSERT_EQ(BufOrErr11.getError(), std::error_code{});
ASSERT_EQ(BufOrErr12.getError(), std::error_code{});
ASSERT_EQ(BufOrErr21.getError(), std::error_code{});
std::unique_ptr<llvm::MemoryBuffer> Buf11 = std::move(*BufOrErr11);
std::unique_ptr<llvm::MemoryBuffer> Buf12 = std::move(*BufOrErr12);
std::unique_ptr<llvm::MemoryBuffer> Buf21 = std::move(*BufOrErr21);
ASSERT_NE(Buf11, nullptr);
ASSERT_NE(Buf12, nullptr);
ASSERT_NE(Buf21, nullptr);
ASSERT_EQ(Buf11->getBuffer().data(), Buf12->getBuffer().data());
ASSERT_EQ(Buf11->getBuffer().data(), Buf21->getBuffer().data());
EXPECT_EQ(Buf11->getBuffer(), "content");
}
TEST(DependencyScanningWorkerFilesystem, CacheStatusFailures) {
auto InMemoryFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();