diff --git a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h --- a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h +++ b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h @@ -46,7 +46,7 @@ /// mismatching size of the file. If file is not minimized, the full file is /// read and copied into memory to ensure that it's not memory mapped to avoid /// running out of file descriptors. - static CachedFileSystemEntry createFileEntry(StringRef Filename, + static CachedFileSystemEntry createFileEntry(llvm::vfs::Status &&Stat, llvm::vfs::FileSystem &FS, bool Minimize = true); @@ -173,6 +173,9 @@ return It == Cache.end() ? nullptr : It->getValue(); } + llvm::ErrorOr + getOrCreateFileSystemEntry(const StringRef Filename); + DependencyScanningFilesystemSharedCache &SharedCache; /// The local cache is used by the worker thread to cache file system queries /// locally instead of querying the global cache every time. diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp --- a/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp @@ -15,22 +15,19 @@ using namespace tooling; using namespace dependencies; + CachedFileSystemEntry CachedFileSystemEntry::createFileEntry( - StringRef Filename, llvm::vfs::FileSystem &FS, bool Minimize) { + llvm::vfs::Status &&Stat, llvm::vfs::FileSystem &FS, bool Minimize) { // Load the file and its content from the file system. + StringRef Filename = Stat.getName(); llvm::ErrorOr> MaybeFile = FS.openFileForRead(Filename); if (!MaybeFile) return MaybeFile.getError(); - llvm::ErrorOr Stat = (*MaybeFile)->status(); - if (!Stat) - return Stat.getError(); - if (Stat->isDirectory()) - return std::make_error_code(std::errc::is_a_directory); llvm::vfs::File &F = **MaybeFile; llvm::ErrorOr> MaybeBuffer = - F.getBuffer(Stat->getName()); + F.getBuffer(Filename); if (!MaybeBuffer) return MaybeBuffer.getError(); @@ -44,7 +41,7 @@ // if the minimization failed. // FIXME: Propage the diagnostic if desired by the client. CachedFileSystemEntry Result; - Result.MaybeStat = std::move(*Stat); + Result.MaybeStat = Stat; Result.Contents.reserve(Buffer->getBufferSize() + 1); Result.Contents.append(Buffer->getBufferStart(), Buffer->getBufferEnd()); // Implicitly null terminate the contents for Clang's lexer. @@ -55,10 +52,10 @@ CachedFileSystemEntry Result; size_t Size = MinimizedFileContents.size(); - Result.MaybeStat = llvm::vfs::Status(Stat->getName(), Stat->getUniqueID(), - Stat->getLastModificationTime(), - Stat->getUser(), Stat->getGroup(), Size, - Stat->getType(), Stat->getPermissions()); + Result.MaybeStat = llvm::vfs::Status(Stat.getName(), Stat.getUniqueID(), + Stat.getLastModificationTime(), + Stat.getUser(), Stat.getGroup(), Size, + Stat.getType(), Stat.getPermissions()); // The contents produced by the minimizer must be null terminated. assert(MinimizedFileContents.data()[MinimizedFileContents.size()] == '\0' && "not null terminated contents"); @@ -124,14 +121,11 @@ return It.first->getValue(); } -llvm::ErrorOr -DependencyScanningWorkerFilesystem::status(const Twine &Path) { - SmallString<256> OwnedFilename; - StringRef Filename = Path.toStringRef(OwnedFilename); - - // Check the local cache first. - if (const CachedFileSystemEntry *Entry = getCachedEntry(Filename)) - return Entry->getStatus(); +llvm::ErrorOr +DependencyScanningWorkerFilesystem::getOrCreateFileSystemEntry(const StringRef Filename) { + if (const CachedFileSystemEntry* Entry = getCachedEntry(Filename)) { + return Entry; + } // FIXME: Handle PCM/PCH files. // FIXME: Handle module map files. @@ -139,7 +133,7 @@ bool KeepOriginalSource = IgnoredFiles.count(Filename); DependencyScanningFilesystemSharedCache::SharedFileSystemEntry &SharedCacheEntry = SharedCache.get(Filename); - const CachedFileSystemEntry *Result; + CachedFileSystemEntry *Result; { std::unique_lock LockGuard(SharedCacheEntry.ValueLock); CachedFileSystemEntry &CacheEntry = SharedCacheEntry.Value; @@ -154,7 +148,7 @@ std::move(*MaybeStatus)); else CacheEntry = CachedFileSystemEntry::createFileEntry( - Filename, FS, !KeepOriginalSource); + std::move(*MaybeStatus), FS, !KeepOriginalSource); } Result = &CacheEntry; @@ -162,7 +156,17 @@ // Store the result in the local cache. setCachedEntry(Filename, Result); - return Result->getStatus(); + return Result; +} + +llvm::ErrorOr +DependencyScanningWorkerFilesystem::status(const Twine &Path) { + SmallString<256> OwnedFilename; + StringRef Filename = Path.toStringRef(OwnedFilename); + const llvm::ErrorOr Result = getOrCreateFileSystemEntry(Filename); + if (!Result) + return Result.getError(); + return (*Result)->getStatus(); } namespace { @@ -219,36 +223,8 @@ SmallString<256> OwnedFilename; StringRef Filename = Path.toStringRef(OwnedFilename); - // Check the local cache first. - if (const CachedFileSystemEntry *Entry = getCachedEntry(Filename)) - return createFile(Entry, PPSkipMappings); - - // FIXME: Handle PCM/PCH files. - // FIXME: Handle module map files. - - bool KeepOriginalSource = IgnoredFiles.count(Filename); - DependencyScanningFilesystemSharedCache::SharedFileSystemEntry - &SharedCacheEntry = SharedCache.get(Filename); - const CachedFileSystemEntry *Result; - { - std::unique_lock LockGuard(SharedCacheEntry.ValueLock); - CachedFileSystemEntry &CacheEntry = SharedCacheEntry.Value; - - if (!CacheEntry.isValid()) { - CacheEntry = CachedFileSystemEntry::createFileEntry( - Filename, getUnderlyingFS(), !KeepOriginalSource); - if (CacheEntry.getError() == std::errc::is_a_directory) { - // Reset the CacheEntry to avoid setting an error entry in the - // cache for the given directory path. - CacheEntry = CachedFileSystemEntry(); - return llvm::ErrorOr>(std::errc::is_a_directory); - } - } - - Result = &CacheEntry; - } - - // Store the result in the local cache. - setCachedEntry(Filename, Result); - return createFile(Result, PPSkipMappings); + const llvm::ErrorOr Result = getOrCreateFileSystemEntry(Filename); + if (!Result) + return Result.getError(); + return createFile(Result.get(), PPSkipMappings); }