[clang] 7aee393 - [clang][modules] Don't prune the top level module cache for implicitly built modules (#192171)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Apr 15 10:20:22 PDT 2026
Author: Michael Spencer
Date: 2026-04-15T10:20:17-07:00
New Revision: 7aee3933330033040ffc3edc75d752f6431c8dd7
URL: https://github.com/llvm/llvm-project/commit/7aee3933330033040ffc3edc75d752f6431c8dd7
DIFF: https://github.com/llvm/llvm-project/commit/7aee3933330033040ffc3edc75d752f6431c8dd7.diff
LOG: [clang][modules] Don't prune the top level module cache for implicitly built modules (#192171)
There are build systems that put explicitly built modules in the same
module cache directory as implicitly built modules. Pruning those in an
implicit build can cause the build to fail due to missing modules.
rdar://174790709
Added:
clang/test/Modules/prune-no-toplevel.m
Modified:
clang/include/clang/Serialization/ModuleCache.h
clang/lib/Serialization/ModuleCache.cpp
clang/tools/libclang/BuildSystem.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Serialization/ModuleCache.h b/clang/include/clang/Serialization/ModuleCache.h
index 82c4cde37c5ff..dcac8ee9890a9 100644
--- a/clang/include/clang/Serialization/ModuleCache.h
+++ b/clang/include/clang/Serialization/ModuleCache.h
@@ -70,7 +70,8 @@ class ModuleCache {
std::shared_ptr<ModuleCache> createCrossProcessModuleCache();
/// Shared implementation of `ModuleCache::maybePrune()`.
-void maybePruneImpl(StringRef Path, time_t PruneInterval, time_t PruneAfter);
+void maybePruneImpl(StringRef Path, time_t PruneInterval, time_t PruneAfter,
+ bool PruneTopLevel = false);
/// Shared implementation of `ModuleCache::write()`.
std::error_code writeImpl(StringRef Path, llvm::MemoryBufferRef Buffer);
diff --git a/clang/lib/Serialization/ModuleCache.cpp b/clang/lib/Serialization/ModuleCache.cpp
index 9ea4223a2eb83..d2d3d3fd9ed76 100644
--- a/clang/lib/Serialization/ModuleCache.cpp
+++ b/clang/lib/Serialization/ModuleCache.cpp
@@ -26,7 +26,7 @@ static void writeTimestampFile(StringRef TimestampFile) {
}
void clang::maybePruneImpl(StringRef Path, time_t PruneInterval,
- time_t PruneAfter) {
+ time_t PruneAfter, bool PruneTopLevel) {
if (PruneInterval <= 0 || PruneAfter <= 0)
return;
@@ -95,7 +95,8 @@ void clang::maybePruneImpl(StringRef Path, time_t PruneInterval,
Dir != DirEnd && !EC; Dir.increment(EC)) {
// If we don't have a directory, try to prune it as a file in the root.
if (!llvm::sys::fs::is_directory(Dir->path())) {
- TryPruneFile(Dir->path());
+ if (PruneTopLevel)
+ TryPruneFile(Dir->path());
continue;
}
diff --git a/clang/test/Modules/prune-no-toplevel.m b/clang/test/Modules/prune-no-toplevel.m
new file mode 100644
index 0000000000000..93810b66d399c
--- /dev/null
+++ b/clang/test/Modules/prune-no-toplevel.m
@@ -0,0 +1,24 @@
+// NetBSD: noatime mounts currently inhibit 'touch -a' updates
+// UNSUPPORTED: system-netbsd
+
+// Test that implicit module builds don't prune top-level files in the module
+// cache directory.
+
+// Set up a module cache with a timestamp old enough to trigger pruning, a
+// top-level .pcm, and a stale .pcm in a subdirectory.
+// RUN: rm -rf %t
+// RUN: mkdir -p %t/cache/subdir
+// RUN: touch -m -a -t 201101010000 %t/cache/modules.timestamp
+// RUN: touch -a -t 201101010000 %t/cache/toplevel.pcm
+// RUN: touch -a -t 201101010000 %t/cache/subdir/stale.pcm
+
+// Run the compiler to trigger pruning.
+// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t/cache -fmodules-prune-interval=172800 -fmodules-prune-after=345600 %s -verify
+
+// The top-level .pcm file should still exist.
+// RUN: ls %t/cache/toplevel.pcm
+
+// The subdirectory .pcm file should have been pruned.
+// RUN: not ls %t/cache/subdir/stale.pcm
+
+// expected-no-diagnostics
diff --git a/clang/tools/libclang/BuildSystem.cpp b/clang/tools/libclang/BuildSystem.cpp
index e81f69d9960f2..c2319e184f5ef 100644
--- a/clang/tools/libclang/BuildSystem.cpp
+++ b/clang/tools/libclang/BuildSystem.cpp
@@ -155,5 +155,6 @@ void clang_ModuleMapDescriptor_dispose(CXModuleMapDescriptor MMD) {
void clang_ModuleCache_prune(const char *Path, time_t PruneInterval,
time_t PruneAfter) {
if (Path)
- clang::maybePruneImpl(Path, PruneInterval, PruneAfter);
+ clang::maybePruneImpl(Path, PruneInterval, PruneAfter,
+ /*PruneTopLevel=*/true);
}
More information about the cfe-commits
mailing list