[llvm] [VFS] Handle unavailable working directories when adding overlays (PR #228708)

Macro Terra via llvm-commits llvm-commits at lists.llvm.org
Sat Oct 3 06:16:25 PDT 2026


https://github.com/hongtaihu created https://github.com/llvm/llvm-project/pull/228708

`OverlayFileSystem::pushOverlay()` synchronizes the added file system's
working directory with the base file system. It currently calls `.get()`
on the result of `getCurrentWorkingDirectory()` without checking for an
error.

The query can fail when the process's current working directory has been
deleted. In clangd, a rename request creates an overlay for unsaved files
and reaches this unchecked access, triggering an `ErrorOr` assertion.

Only synchronize the working directory when the query succeeds. On
failure, retain the added file system's existing working directory. This
follows the pattern already used by the `RedirectingFileSystem`
constructor.

Add a unit test with a file system whose working directory query returns
`no_such_file_or_directory`. Verify that adding the overlay succeeds,
preserves its existing working directory, and allows absolute-path file
lookup.

Validation on the existing local assertions build, before rebasing onto
current main:

- The new unit test passes.
- Replaying the reported clangd scenario changes from an assertion failure
  to a completed rename response and normal process exit.

Fixes #210481

Assisted by Codex


>From 9aacbbf09841f94e8a59314ac8619b0aa462b7dc Mon Sep 17 00:00:00 2001
From: hongtaihu <13541229370 at qq.com>
Date: Sat, 3 Oct 2026 21:16:07 +0800
Subject: [PATCH] [VFS] Handle unavailable working directories when adding
 overlays

`OverlayFileSystem::pushOverlay()` synchronizes the added file system's
working directory with the base file system. It currently calls `.get()`
on the result of `getCurrentWorkingDirectory()` without checking for an
error.

The query can fail when the process's current working directory has been
deleted. In clangd, a rename request creates an overlay for unsaved files
and reaches this unchecked access, triggering an `ErrorOr` assertion.

Only synchronize the working directory when the query succeeds. On
failure, retain the added file system's existing working directory. This
follows the pattern already used by the `RedirectingFileSystem`
constructor.

Add a unit test with a file system whose working directory query returns
`no_such_file_or_directory`. Verify that adding the overlay succeeds,
preserves its existing working directory, and allows absolute-path file
lookup.

Validation on the existing local assertions build, before rebasing onto
current main:

- The new unit test passes.
- Replaying the reported clangd scenario changes from an assertion failure
  to a completed rename response and normal process exit.

Fixes #210481

Assisted by Codex
---
 llvm/lib/Support/VirtualFileSystem.cpp         |  3 ++-
 .../Support/VirtualFileSystemTest.cpp          | 18 ++++++++++++++++++
 2 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Support/VirtualFileSystem.cpp b/llvm/lib/Support/VirtualFileSystem.cpp
index 5d0a3949e60ca0..2e7b0ca80b5bcf 100644
--- a/llvm/lib/Support/VirtualFileSystem.cpp
+++ b/llvm/lib/Support/VirtualFileSystem.cpp
@@ -481,7 +481,8 @@ void OverlayFileSystem::pushOverlay(IntrusiveRefCntPtr<FileSystem> FS) {
   FSList.push_back(FS);
   // Synchronize added file systems by duplicating the working directory from
   // the first one in the list.
-  FS->setCurrentWorkingDirectory(getCurrentWorkingDirectory().get());
+  if (auto WorkingDir = getCurrentWorkingDirectory())
+    FS->setCurrentWorkingDirectory(*WorkingDir);
 }
 
 ErrorOr<Status> OverlayFileSystem::status(const Twine &Path) {
diff --git a/llvm/unittests/Support/VirtualFileSystemTest.cpp b/llvm/unittests/Support/VirtualFileSystemTest.cpp
index 507a0e4108a79e..0000558967c78b 100644
--- a/llvm/unittests/Support/VirtualFileSystemTest.cpp
+++ b/llvm/unittests/Support/VirtualFileSystemTest.cpp
@@ -312,6 +312,24 @@ TEST(VirtualFileSystemTest, GetRealPathInOverlay) {
   EXPECT_EQ(RealPath.str(), "/symlink");
 }
 
+TEST(VirtualFileSystemTest, OverlayWithUnavailableWorkingDirectory) {
+  class UnavailableWorkingDirectoryFS : public DummyFileSystem {
+    ErrorOr<std::string> getCurrentWorkingDirectory() const override {
+      return make_error_code(errc::no_such_file_or_directory);
+    }
+  };
+  auto Base = makeIntrusiveRefCnt<UnavailableWorkingDirectoryFS>();
+  auto Upper = makeIntrusiveRefCnt<DummyFileSystem>();
+  Upper->setCurrentWorkingDirectory("/upper");
+  Upper->addRegularFile("/foo");
+  auto Overlay = makeIntrusiveRefCnt<vfs::OverlayFileSystem>(Base);
+  Overlay->pushOverlay(Upper);
+  EXPECT_EQ(Overlay->getCurrentWorkingDirectory().getError(),
+            errc::no_such_file_or_directory);
+  EXPECT_EQ(*Upper->getCurrentWorkingDirectory(), "/upper");
+  EXPECT_TRUE(Overlay->status("/foo"));
+}
+
 TEST(VirtualFileSystemTest, OverlayFiles) {
   auto Base = makeIntrusiveRefCnt<DummyFileSystem>();
   auto Middle = makeIntrusiveRefCnt<DummyFileSystem>();



More information about the llvm-commits mailing list