[llvm] Fix overlay vfs iteration over empty directories (PR #126093)
Thomas Gibson-Robinson via llvm-commits
llvm-commits at lists.llvm.org
Thu Feb 6 09:23:32 PST 2025
https://github.com/tomgr created https://github.com/llvm/llvm-project/pull/126093
Before this fix, iterating over an empty directory with a OverlayFileSystem would incorrectly return an
errc::no_such_file_or_directory error.
>From cad6e54504dfe2d7ca76aa083bb2c2dcc2c7fce8 Mon Sep 17 00:00:00 2001
From: Thomas Gibson-Robinson <tom at cocotec.io>
Date: Thu, 6 Feb 2025 17:20:24 +0000
Subject: [PATCH] Fix overlay vfs iteration over empty directories
Before this fix, iterating over an empty directory with a
OverlayFileSystem would incorrectly return an
errc::no_such_file_or_directory error.
---
llvm/lib/Support/VirtualFileSystem.cpp | 14 ++++++-----
.../Support/VirtualFileSystemTest.cpp | 24 +++++++++++++++++++
2 files changed, 32 insertions(+), 6 deletions(-)
diff --git a/llvm/lib/Support/VirtualFileSystem.cpp b/llvm/lib/Support/VirtualFileSystem.cpp
index e489282281d269e..2e09a0ea2a53dac 100644
--- a/llvm/lib/Support/VirtualFileSystem.cpp
+++ b/llvm/lib/Support/VirtualFileSystem.cpp
@@ -546,16 +546,13 @@ class CombiningDirIterImpl : public llvm::vfs::detail::DirIterImpl {
/// Sets \c CurrentDirIter to the next iterator in the list, or leaves it as
/// is (at its end position) if we've already gone through them all.
- std::error_code incrementIter(bool IsFirstTime) {
+ std::error_code incrementIter() {
while (!IterList.empty()) {
CurrentDirIter = IterList.back();
IterList.pop_back();
if (CurrentDirIter != directory_iterator())
break; // found
}
-
- if (IsFirstTime && CurrentDirIter == directory_iterator())
- return errc::no_such_file_or_directory;
return {};
}
@@ -563,10 +560,15 @@ class CombiningDirIterImpl : public llvm::vfs::detail::DirIterImpl {
assert((IsFirstTime || CurrentDirIter != directory_iterator()) &&
"incrementing past end");
std::error_code EC;
- if (!IsFirstTime)
+ if (IsFirstTime) {
+ // If the list of iterators is empty then this mmust mean that none of the
+ // overlays have this directory.
+ if (IterList.empty())
+ EC = errc::no_such_file_or_directory;
+ } else
CurrentDirIter.increment(EC);
if (!EC && CurrentDirIter == directory_iterator())
- EC = incrementIter(IsFirstTime);
+ EC = incrementIter();
return EC;
}
diff --git a/llvm/unittests/Support/VirtualFileSystemTest.cpp b/llvm/unittests/Support/VirtualFileSystemTest.cpp
index eb590e474c2ecc0..66396e6cc3301cf 100644
--- a/llvm/unittests/Support/VirtualFileSystemTest.cpp
+++ b/llvm/unittests/Support/VirtualFileSystemTest.cpp
@@ -3675,3 +3675,27 @@ TEST(TracingFileSystemTest, PrintOutput) {
" InMemoryFileSystem\n",
Output);
}
+
+TEST(VirtualFileSystemTest, RecursiveDirectoryIteratorEmpty) {
+ TempDir TestDirectory("virtual-file-system-test", /*Unique*/ true);
+ auto FS = llvm::makeIntrusiveRefCnt<llvm::vfs::OverlayFileSystem>(
+ vfs::getRealFileSystem());
+
+ // An empty directory should not fail
+ {
+ std::error_code EC;
+ vfs::recursive_directory_iterator I =
+ vfs::recursive_directory_iterator(*FS, TestDirectory.path(), EC);
+ ASSERT_FALSE(EC);
+ EXPECT_EQ(vfs::recursive_directory_iterator(), I);
+ }
+
+ // But a non-existent directory should fail
+ {
+ std::error_code EC;
+ vfs::recursive_directory_iterator I =
+ vfs::recursive_directory_iterator(*FS, "/non-existent", EC);
+ ASSERT_EQ(EC, std::errc::no_such_file_or_directory);
+ EXPECT_EQ(vfs::recursive_directory_iterator(), I);
+ }
+}
More information about the llvm-commits
mailing list