https://github.com/qiongsiwu updated 
https://github.com/llvm/llvm-project/pull/135703

>From d4b1210c16b4fccc6faa9445bee457a1e330a025 Mon Sep 17 00:00:00 2001
From: Qiongsi Wu <qiongsi...@apple.com>
Date: Mon, 14 Apr 2025 16:49:07 -0700
Subject: [PATCH 1/5] Initial commit.

---
 .../DependencyScanningFilesystem.h            |  8 ++++++
 .../DependencyScanningFilesystem.cpp          | 26 +++++++++++++++++
 .../DependencyScanningFilesystemTest.cpp      | 28 +++++++++++++++++++
 3 files changed, 62 insertions(+)

diff --git 
a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h 
b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h
index d12814e7c9253..648158c5287c6 100644
--- 
a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h
+++ 
b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h
@@ -220,6 +220,14 @@ class DependencyScanningFilesystemSharedCache {
   CacheShard &getShardForFilename(StringRef Filename) const;
   CacheShard &getShardForUID(llvm::sys::fs::UniqueID UID) const;
 
+  /// Visits all cached entries and re-stat an entry using the UnderlyingFS if
+  /// it is negatively stat cached. If the re-stat succeeds, print diagnostics
+  /// information to OS indicating that negative stat caching has been
+  /// invalidated.
+  void
+  diagnoseNegativeStatCachedPaths(llvm::raw_ostream &OS,
+                                  llvm::vfs::FileSystem &UnderlyingFS) const;
+
 private:
   std::unique_ptr<CacheShard[]> CacheShards;
   unsigned NumShards;
diff --git 
a/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp 
b/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp
index 4d738e4bea41a..fe72a1a91909e 100644
--- a/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp
+++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp
@@ -108,6 +108,32 @@ DependencyScanningFilesystemSharedCache::getShardForUID(
   return CacheShards[Hash % NumShards];
 }
 
+void DependencyScanningFilesystemSharedCache::diagnoseNegativeStatCachedPaths(
+    llvm::raw_ostream &OS, llvm::vfs::FileSystem &UnderlyingFS) const {
+  // Iterate through all shards and look for cached stat errors.
+  for (unsigned i = 0; i < NumShards; i++) {
+    const CacheShard &Shard = CacheShards[i];
+    for (const auto &Path : Shard.CacheByFilename.keys()) {
+      auto CachedPairIt = Shard.CacheByFilename.find(Path);
+      auto CachedPair = CachedPairIt->getValue();
+      const CachedFileSystemEntry *Entry = CachedPair.first;
+
+      if (Entry->getError()) {
+        // Only examine cached errors.
+        llvm::ErrorOr<llvm::vfs::Status> Stat = UnderlyingFS.status(Path);
+        if (Stat) {
+          // This is the case where we have negatively cached the non-existence
+          // of the file at Path, but the cache is later invalidated. Report
+          // diagnostics.
+          OS << Path << " did not exist when it was first searched "
+             << "but was created later. This may have led to a build failure "
+                "due to missing files.\n";
+        }
+      }
+    }
+  }
+}
+
 const CachedFileSystemEntry *
 DependencyScanningFilesystemSharedCache::CacheShard::findEntryByFilename(
     StringRef Filename) const {
diff --git 
a/clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp
 
b/clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp
index 111351fb90cee..02b192f1ba587 100644
--- 
a/clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp
+++ 
b/clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp
@@ -178,3 +178,31 @@ TEST(DependencyScanningFilesystem, CacheStatFailures) {
   DepFS.exists("/cache/a.pcm");
   EXPECT_EQ(InstrumentingFS->NumStatusCalls, 5u);
 }
+
+TEST(DependencyScanningFilesystem, DiagnoseStaleStatFailures) {
+  auto InMemoryFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
+  InMemoryFS->setCurrentWorkingDirectory("/");
+  InMemoryFS->addFile("/dir", 0, llvm::MemoryBuffer::getMemBuffer(""));
+
+  DependencyScanningFilesystemSharedCache SharedCache;
+  DependencyScanningWorkerFilesystem DepFS(SharedCache, InMemoryFS);
+
+  bool Path1Exists = DepFS.exists("/path1");
+  EXPECT_EQ(Path1Exists, false);
+
+  // Adding a file that has been stat-ed,
+  InMemoryFS->addFile("/path1", 0, llvm::MemoryBuffer::getMemBuffer(""));
+  Path1Exists = DepFS.exists("/path1");
+  // Due to caching in SharedCache, path1 should not exist in
+  // DepFS's eyes.
+  EXPECT_EQ(Path1Exists, false);
+
+  std::string Diags;
+  llvm::raw_string_ostream DiagsStream(Diags);
+  SharedCache.diagnoseNegativeStatCachedPaths(DiagsStream, *InMemoryFS.get());
+
+  ASSERT_STREQ(
+      "/path1 did not exist when it was first searched but was created later. "
+      "This may have led to a build failure due to missing files.\n",
+      Diags.c_str());
+}

>From b1058390940f40c9f62e9bcf745b4381a40db5e5 Mon Sep 17 00:00:00 2001
From: Qiongsi Wu <qiongsi...@apple.com>
Date: Tue, 15 Apr 2025 10:37:52 -0700
Subject: [PATCH 2/5] Address code review.

---
 .../DependencyScanningFilesystem.cpp                  | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git 
a/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp 
b/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp
index fe72a1a91909e..e61d8afeb51bb 100644
--- a/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp
+++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp
@@ -113,18 +113,17 @@ void 
DependencyScanningFilesystemSharedCache::diagnoseNegativeStatCachedPaths(
   // Iterate through all shards and look for cached stat errors.
   for (unsigned i = 0; i < NumShards; i++) {
     const CacheShard &Shard = CacheShards[i];
-    for (const auto &Path : Shard.CacheByFilename.keys()) {
-      auto CachedPairIt = Shard.CacheByFilename.find(Path);
-      auto CachedPair = CachedPairIt->getValue();
+    std::lock_guard<std::mutex> LockGuard(Shard.CacheLock);
+    for (const auto &[Path, CachedPair] : Shard.CacheByFilename) {
       const CachedFileSystemEntry *Entry = CachedPair.first;
 
       if (Entry->getError()) {
         // Only examine cached errors.
         llvm::ErrorOr<llvm::vfs::Status> Stat = UnderlyingFS.status(Path);
         if (Stat) {
-          // This is the case where we have negatively cached the non-existence
-          // of the file at Path, but the cache is later invalidated. Report
-          // diagnostics.
+          // This is the case where we have cached the non-existence
+          // of the file at Path, but the file is created but the cache is
+          // not invalidated. Report diagnostics.
           OS << Path << " did not exist when it was first searched "
              << "but was created later. This may have led to a build failure "
                 "due to missing files.\n";

>From 17a3426d04ca69c6c01b7240e9811946c00819bd Mon Sep 17 00:00:00 2001
From: Qiongsi Wu <qiongsi...@apple.com>
Date: Tue, 15 Apr 2025 14:34:17 -0700
Subject: [PATCH 3/5] Shorten the error message.

---
 .../DependencyScanningFilesystem.cpp                | 13 ++++++++++---
 .../DependencyScanningFilesystemTest.cpp            |  6 +++---
 2 files changed, 13 insertions(+), 6 deletions(-)

diff --git 
a/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp 
b/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp
index e61d8afeb51bb..bdd8695991f17 100644
--- a/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp
+++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp
@@ -111,6 +111,7 @@ DependencyScanningFilesystemSharedCache::getShardForUID(
 void DependencyScanningFilesystemSharedCache::diagnoseNegativeStatCachedPaths(
     llvm::raw_ostream &OS, llvm::vfs::FileSystem &UnderlyingFS) const {
   // Iterate through all shards and look for cached stat errors.
+  SmallVector<StringRef, 4> InvalidCachedPaths;
   for (unsigned i = 0; i < NumShards; i++) {
     const CacheShard &Shard = CacheShards[i];
     std::lock_guard<std::mutex> LockGuard(Shard.CacheLock);
@@ -124,13 +125,19 @@ void 
DependencyScanningFilesystemSharedCache::diagnoseNegativeStatCachedPaths(
           // This is the case where we have cached the non-existence
           // of the file at Path, but the file is created but the cache is
           // not invalidated. Report diagnostics.
-          OS << Path << " did not exist when it was first searched "
-             << "but was created later. This may have led to a build failure "
-                "due to missing files.\n";
+          InvalidCachedPaths.push_back(Path);
         }
       }
     }
   }
+
+  if (InvalidCachedPaths.size()) {
+    OS << "The following paths did not exist when they were first searched, "
+          "but files they point to were created later:\n";
+    for (const auto P : InvalidCachedPaths)
+      OS << "\t" << P << "\n";
+    OS << "Files missing at the paths above may have caused build errors.\n";
+  }
 }
 
 const CachedFileSystemEntry *
diff --git 
a/clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp
 
b/clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp
index 02b192f1ba587..0e5c31f52cce2 100644
--- 
a/clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp
+++ 
b/clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp
@@ -182,7 +182,6 @@ TEST(DependencyScanningFilesystem, CacheStatFailures) {
 TEST(DependencyScanningFilesystem, DiagnoseStaleStatFailures) {
   auto InMemoryFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
   InMemoryFS->setCurrentWorkingDirectory("/");
-  InMemoryFS->addFile("/dir", 0, llvm::MemoryBuffer::getMemBuffer(""));
 
   DependencyScanningFilesystemSharedCache SharedCache;
   DependencyScanningWorkerFilesystem DepFS(SharedCache, InMemoryFS);
@@ -202,7 +201,8 @@ TEST(DependencyScanningFilesystem, 
DiagnoseStaleStatFailures) {
   SharedCache.diagnoseNegativeStatCachedPaths(DiagsStream, *InMemoryFS.get());
 
   ASSERT_STREQ(
-      "/path1 did not exist when it was first searched but was created later. "
-      "This may have led to a build failure due to missing files.\n",
+      "The following paths did not exist when they were first searched, but "
+      "files they point to were created later:\n\t/path1\nFiles missing at the 
"
+      "paths above may have caused build errors.\n",
       Diags.c_str());
 }

>From 54b679ed6b00f37c1092e4f14fc9906221abe945 Mon Sep 17 00:00:00 2001
From: Qiongsi Wu <qiongsi...@apple.com>
Date: Thu, 17 Apr 2025 13:20:28 -0700
Subject: [PATCH 4/5] Address code review.

---
 .../DependencyScanningFilesystem.h            | 15 +++++++------
 .../DependencyScanningFilesystem.cpp          | 22 +++++++------------
 .../DependencyScanningFilesystemTest.cpp      | 15 +++++--------
 3 files changed, 22 insertions(+), 30 deletions(-)

diff --git 
a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h 
b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h
index 648158c5287c6..f19ad19013aa7 100644
--- 
a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h
+++ 
b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h
@@ -220,13 +220,14 @@ class DependencyScanningFilesystemSharedCache {
   CacheShard &getShardForFilename(StringRef Filename) const;
   CacheShard &getShardForUID(llvm::sys::fs::UniqueID UID) const;
 
-  /// Visits all cached entries and re-stat an entry using the UnderlyingFS if
-  /// it is negatively stat cached. If the re-stat succeeds, print diagnostics
-  /// information to OS indicating that negative stat caching has been
-  /// invalidated.
-  void
-  diagnoseNegativeStatCachedPaths(llvm::raw_ostream &OS,
-                                  llvm::vfs::FileSystem &UnderlyingFS) const;
+  /// Visits all cached entries and re-stat an entry using FS if
+  /// it is negatively stat cached. If re-stat succeeds on a path,
+  /// the path is added to InvalidPaths, indicating that the cache
+  /// may have erroneously negatively cached it. The caller can then
+  /// use InvalidPaths to issue diagnostics.
+  void diagnoseInvalidNegativeStatCachedPaths(
+      std::vector<std::string> &InvalidPaths,
+      llvm::vfs::FileSystem &UnderlyingFS) const;
 
 private:
   std::unique_ptr<CacheShard[]> CacheShards;
diff --git 
a/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp 
b/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp
index bdd8695991f17..8af6ad3265fa1 100644
--- a/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp
+++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp
@@ -108,10 +108,11 @@ DependencyScanningFilesystemSharedCache::getShardForUID(
   return CacheShards[Hash % NumShards];
 }
 
-void DependencyScanningFilesystemSharedCache::diagnoseNegativeStatCachedPaths(
-    llvm::raw_ostream &OS, llvm::vfs::FileSystem &UnderlyingFS) const {
+void DependencyScanningFilesystemSharedCache::
+    diagnoseInvalidNegativeStatCachedPaths(
+        std::vector<std::string> &InvalidPaths,
+        llvm::vfs::FileSystem &UnderlyingFS) const {
   // Iterate through all shards and look for cached stat errors.
-  SmallVector<StringRef, 4> InvalidCachedPaths;
   for (unsigned i = 0; i < NumShards; i++) {
     const CacheShard &Shard = CacheShards[i];
     std::lock_guard<std::mutex> LockGuard(Shard.CacheLock);
@@ -123,21 +124,14 @@ void 
DependencyScanningFilesystemSharedCache::diagnoseNegativeStatCachedPaths(
         llvm::ErrorOr<llvm::vfs::Status> Stat = UnderlyingFS.status(Path);
         if (Stat) {
           // This is the case where we have cached the non-existence
-          // of the file at Path, but the file is created but the cache is
-          // not invalidated. Report diagnostics.
-          InvalidCachedPaths.push_back(Path);
+          // of the file at Path first, and a a file at the path is created
+          // later. The cache entry is not invalidated (as we have no good
+          // way to do it now), which may lead to missing file build errors.
+          InvalidPaths.push_back(std::string(Path));
         }
       }
     }
   }
-
-  if (InvalidCachedPaths.size()) {
-    OS << "The following paths did not exist when they were first searched, "
-          "but files they point to were created later:\n";
-    for (const auto P : InvalidCachedPaths)
-      OS << "\t" << P << "\n";
-    OS << "Files missing at the paths above may have caused build errors.\n";
-  }
 }
 
 const CachedFileSystemEntry *
diff --git 
a/clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp
 
b/clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp
index 0e5c31f52cce2..4c537ee455e78 100644
--- 
a/clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp
+++ 
b/clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp
@@ -196,13 +196,10 @@ TEST(DependencyScanningFilesystem, 
DiagnoseStaleStatFailures) {
   // DepFS's eyes.
   EXPECT_EQ(Path1Exists, false);
 
-  std::string Diags;
-  llvm::raw_string_ostream DiagsStream(Diags);
-  SharedCache.diagnoseNegativeStatCachedPaths(DiagsStream, *InMemoryFS.get());
-
-  ASSERT_STREQ(
-      "The following paths did not exist when they were first searched, but "
-      "files they point to were created later:\n\t/path1\nFiles missing at the 
"
-      "paths above may have caused build errors.\n",
-      Diags.c_str());
+  std::vector<std::string> InvalidPaths;
+  SharedCache.diagnoseInvalidNegativeStatCachedPaths(InvalidPaths,
+                                                     *InMemoryFS.get());
+
+  EXPECT_EQ(InvalidPaths.size(), 1u);
+  ASSERT_STREQ("/path1", InvalidPaths[0].c_str());
 }

>From be6edb001fd2b5257a65efc581e9516a4bb939dc Mon Sep 17 00:00:00 2001
From: Qiongsi Wu <qiongsi...@apple.com>
Date: Thu, 17 Apr 2025 16:00:00 -0700
Subject: [PATCH 5/5] Address code review.

---
 .../DependencyScanning/DependencyScanningFilesystem.h    | 5 ++---
 .../DependencyScanning/DependencyScanningFilesystem.cpp  | 9 +++++----
 .../DependencyScanningFilesystemTest.cpp                 | 7 +++----
 3 files changed, 10 insertions(+), 11 deletions(-)

diff --git 
a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h 
b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h
index f19ad19013aa7..74b40f7452edb 100644
--- 
a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h
+++ 
b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h
@@ -225,9 +225,8 @@ class DependencyScanningFilesystemSharedCache {
   /// the path is added to InvalidPaths, indicating that the cache
   /// may have erroneously negatively cached it. The caller can then
   /// use InvalidPaths to issue diagnostics.
-  void diagnoseInvalidNegativeStatCachedPaths(
-      std::vector<std::string> &InvalidPaths,
-      llvm::vfs::FileSystem &UnderlyingFS) const;
+  std::vector<StringRef>
+  getInvalidNegativeStatCachedPaths(llvm::vfs::FileSystem &UnderlyingFS) const;
 
 private:
   std::unique_ptr<CacheShard[]> CacheShards;
diff --git 
a/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp 
b/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp
index 8af6ad3265fa1..da596a46f8240 100644
--- a/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp
+++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp
@@ -108,11 +108,11 @@ DependencyScanningFilesystemSharedCache::getShardForUID(
   return CacheShards[Hash % NumShards];
 }
 
-void DependencyScanningFilesystemSharedCache::
-    diagnoseInvalidNegativeStatCachedPaths(
-        std::vector<std::string> &InvalidPaths,
-        llvm::vfs::FileSystem &UnderlyingFS) const {
+std::vector<StringRef>
+DependencyScanningFilesystemSharedCache::getInvalidNegativeStatCachedPaths(
+    llvm::vfs::FileSystem &UnderlyingFS) const {
   // Iterate through all shards and look for cached stat errors.
+  std::vector<StringRef> InvalidPaths;
   for (unsigned i = 0; i < NumShards; i++) {
     const CacheShard &Shard = CacheShards[i];
     std::lock_guard<std::mutex> LockGuard(Shard.CacheLock);
@@ -132,6 +132,7 @@ void DependencyScanningFilesystemSharedCache::
       }
     }
   }
+  return InvalidPaths;
 }
 
 const CachedFileSystemEntry *
diff --git 
a/clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp
 
b/clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp
index 4c537ee455e78..5ea8d02353dc3 100644
--- 
a/clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp
+++ 
b/clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp
@@ -196,10 +196,9 @@ TEST(DependencyScanningFilesystem, 
DiagnoseStaleStatFailures) {
   // DepFS's eyes.
   EXPECT_EQ(Path1Exists, false);
 
-  std::vector<std::string> InvalidPaths;
-  SharedCache.diagnoseInvalidNegativeStatCachedPaths(InvalidPaths,
-                                                     *InMemoryFS.get());
+  std::vector<llvm::StringRef> InvalidPaths =
+      SharedCache.getInvalidNegativeStatCachedPaths(*InMemoryFS.get());
 
   EXPECT_EQ(InvalidPaths.size(), 1u);
-  ASSERT_STREQ("/path1", InvalidPaths[0].c_str());
+  ASSERT_STREQ("/path1", InvalidPaths[0].str().c_str());
 }

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to