Skip to content

Commit 5c08bfa

Browse files
authored
[clang][Dependency Scanning] Report only Regular File Size Changes When Computing Out-of-Date File System Cache Entries (#148082)
We noticed that when a directory's content changes, its size reported by `status` can change as well. We do not want to include such "false positive" cases. This PR revises the computation so that only regular file size changes are considered out-of-date. rdar://152247357
1 parent 1cd2165 commit 5c08bfa

File tree

2 files changed

+47
-7
lines changed

2 files changed

+47
-7
lines changed

clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,6 @@ DependencyScanningFilesystemSharedCache::getOutOfDateEntries(
117117
std::lock_guard<std::mutex> LockGuard(Shard.CacheLock);
118118
for (const auto &[Path, CachedPair] : Shard.CacheByFilename) {
119119
const CachedFileSystemEntry *Entry = CachedPair.first;
120-
121120
llvm::ErrorOr<llvm::vfs::Status> Status = UnderlyingFS.status(Path);
122121
if (Status) {
123122
if (Entry->getError()) {
@@ -128,12 +127,22 @@ DependencyScanningFilesystemSharedCache::getOutOfDateEntries(
128127
InvalidDiagInfo.emplace_back(Path.data());
129128
} else {
130129
llvm::vfs::Status CachedStatus = Entry->getStatus();
131-
uint64_t CachedSize = CachedStatus.getSize();
132-
uint64_t ActualSize = Status->getSize();
133-
if (CachedSize != ActualSize) {
134-
// This is the case where the cached file has a different size
135-
// from the actual file that comes from the underlying FS.
136-
InvalidDiagInfo.emplace_back(Path.data(), CachedSize, ActualSize);
130+
if (Status->getType() == llvm::sys::fs::file_type::regular_file &&
131+
Status->getType() == CachedStatus.getType()) {
132+
// We only check regular files. Directory files sizes could change
133+
// due to content changes, and reporting directory size changes can
134+
// lead to false positives.
135+
// TODO: At the moment, we do not detect symlinks to files whose
136+
// size may change. We need to decide if we want to detect cached
137+
// symlink size changes. We can also expand this to detect file
138+
// type changes.
139+
uint64_t CachedSize = CachedStatus.getSize();
140+
uint64_t ActualSize = Status->getSize();
141+
if (CachedSize != ActualSize) {
142+
// This is the case where the cached file has a different size
143+
// from the actual file that comes from the underlying FS.
144+
InvalidDiagInfo.emplace_back(Path.data(), CachedSize, ActualSize);
145+
}
137146
}
138147
}
139148
}

clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,3 +233,34 @@ TEST(DependencyScanningFilesystem, DiagnoseCachedFileSizeChange) {
233233
ASSERT_EQ(SizeInfo->CachedSize, 0u);
234234
ASSERT_EQ(SizeInfo->ActualSize, 8u);
235235
}
236+
237+
TEST(DependencyScanningFilesystem, DoNotDiagnoseDirSizeChange) {
238+
llvm::SmallString<128> Dir;
239+
ASSERT_FALSE(llvm::sys::fs::createUniqueDirectory("tmp", Dir));
240+
241+
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS =
242+
llvm::vfs::createPhysicalFileSystem();
243+
244+
DependencyScanningFilesystemSharedCache SharedCache;
245+
DependencyScanningWorkerFilesystem DepFS(SharedCache, FS);
246+
247+
// Trigger the file system cache.
248+
ASSERT_EQ(DepFS.exists(Dir), true);
249+
250+
// Add a file to the FS to change its size.
251+
// It seems that directory sizes reported are not meaningful,
252+
// and should not be used to check for size changes.
253+
// This test is setup only to trigger a size change so that we
254+
// know we are excluding directories from reporting.
255+
llvm::SmallString<128> FilePath = Dir;
256+
llvm::sys::path::append(FilePath, "file.h");
257+
{
258+
std::error_code EC;
259+
llvm::raw_fd_ostream TempFile(FilePath, EC);
260+
ASSERT_FALSE(EC);
261+
}
262+
263+
// We do not report directory size changes.
264+
auto InvalidEntries = SharedCache.getOutOfDateEntries(*FS);
265+
EXPECT_EQ(InvalidEntries.size(), 0u);
266+
}

0 commit comments

Comments
 (0)