diff --git a/clang-tools-extra/clangd/FS.cpp b/clang-tools-extra/clangd/FS.cpp --- a/clang-tools-extra/clangd/FS.cpp +++ b/clang-tools-extra/clangd/FS.cpp @@ -76,8 +76,9 @@ return File; } - llvm::ErrorOr status(const llvm::Twine &Path) override { - auto S = getUnderlyingFS().status(Path); + llvm::ErrorOr status(const llvm::Twine &Path, + bool Follow = true) override { + auto S = getUnderlyingFS().status(Path, Follow); if (S) StatCache.update(getUnderlyingFS(), *S); return S; @@ -99,10 +100,11 @@ const PreambleFileStatusCache &StatCache) : ProxyFileSystem(std::move(FS)), StatCache(StatCache) {} - llvm::ErrorOr status(const llvm::Twine &Path) override { + llvm::ErrorOr status(const llvm::Twine &Path, + bool Follow = true) override { if (auto S = StatCache.lookup(Path.str())) return *S; - return getUnderlyingFS().status(Path); + return getUnderlyingFS().status(Path, Follow); } private: diff --git a/clang-tools-extra/clangd/unittests/ClangdTests.cpp b/clang-tools-extra/clangd/unittests/ClangdTests.cpp --- a/clang-tools-extra/clangd/unittests/ClangdTests.cpp +++ b/clang-tools-extra/clangd/unittests/ClangdTests.cpp @@ -1015,9 +1015,10 @@ ++CountStats[llvm::sys::path::filename(Path.str())]; return ProxyFileSystem::openFileForRead(Path); } - llvm::ErrorOr status(const Twine &Path) override { + llvm::ErrorOr status(const Twine &Path, + bool Follow = true) override { ++CountStats[llvm::sys::path::filename(Path.str())]; - return ProxyFileSystem::status(Path); + return ProxyFileSystem::status(Path, Follow); } private: 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 @@ -149,7 +149,8 @@ : ProxyFileSystem(std::move(FS)), SharedCache(SharedCache), PPSkipMappings(PPSkipMappings) {} - llvm::ErrorOr status(const Twine &Path) override; + llvm::ErrorOr status(const Twine &Path, + bool Follow = true) override; llvm::ErrorOr> openFileForRead(const Twine &Path) override; 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 @@ -197,7 +197,8 @@ } llvm::ErrorOr -DependencyScanningWorkerFilesystem::status(const Twine &Path) { +DependencyScanningWorkerFilesystem::status(const Twine &Path, + bool Follow /*= true*/) { SmallString<256> OwnedFilename; StringRef Filename = Path.toStringRef(OwnedFilename); const llvm::ErrorOr Result = diff --git a/clang/unittests/Driver/DistroTest.cpp b/clang/unittests/Driver/DistroTest.cpp --- a/clang/unittests/Driver/DistroTest.cpp +++ b/clang/unittests/Driver/DistroTest.cpp @@ -348,9 +348,10 @@ public: CountingFileSystem() : ProxyFileSystem(llvm::vfs::getRealFileSystem()) {} - llvm::ErrorOr status(const llvm::Twine &Path) override { + llvm::ErrorOr status(const llvm::Twine &Path, + bool Follow = true) override { ++Count; - return llvm::vfs::ProxyFileSystem::status(Path); + return llvm::vfs::ProxyFileSystem::status(Path, Follow); } llvm::ErrorOr> diff --git a/llvm/include/llvm/Support/VirtualFileSystem.h b/llvm/include/llvm/Support/VirtualFileSystem.h --- a/llvm/include/llvm/Support/VirtualFileSystem.h +++ b/llvm/include/llvm/Support/VirtualFileSystem.h @@ -247,7 +247,12 @@ virtual ~FileSystem(); /// Get the status of the entry at \p Path, if one exists. - virtual llvm::ErrorOr status(const Twine &Path) = 0; + /// + /// @param Path Input path. + /// @param Follow When true, follows symlinks. Otherwise, the symlink itself + /// is statted. + virtual llvm::ErrorOr status(const Twine &Path, + bool Follow = true) = 0; /// Get a \p File object for the file at \p Path, if one exists. virtual llvm::ErrorOr> @@ -332,7 +337,7 @@ /// Pushes a file system on top of the stack. void pushOverlay(IntrusiveRefCntPtr FS); - llvm::ErrorOr status(const Twine &Path) override; + llvm::ErrorOr status(const Twine &Path, bool Follow = true) override; llvm::ErrorOr> openFileForRead(const Twine &Path) override; directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override; @@ -372,8 +377,8 @@ explicit ProxyFileSystem(IntrusiveRefCntPtr FS) : FS(std::move(FS)) {} - llvm::ErrorOr status(const Twine &Path) override { - return FS->status(Path); + llvm::ErrorOr status(const Twine &Path, bool Follow = true) override { + return FS->status(Path, Follow); } llvm::ErrorOr> openFileForRead(const Twine &Path) override { @@ -475,7 +480,7 @@ /// Return true if this file system normalizes . and .. in paths. bool useNormalizedPaths() const { return UseNormalizedPaths; } - llvm::ErrorOr status(const Twine &Path) override; + llvm::ErrorOr status(const Twine &Path, bool Follow = true) override; llvm::ErrorOr> openFileForRead(const Twine &Path) override; directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override; @@ -828,7 +833,7 @@ create(ArrayRef> RemappedFiles, bool UseExternalNames, FileSystem &ExternalFS); - ErrorOr status(const Twine &Path) override; + ErrorOr status(const Twine &Path, bool Follow = true) override; ErrorOr> openFileForRead(const Twine &Path) override; std::error_code getRealPath(const Twine &Path, diff --git a/llvm/lib/Support/FileCollector.cpp b/llvm/lib/Support/FileCollector.cpp --- a/llvm/lib/Support/FileCollector.cpp +++ b/llvm/lib/Support/FileCollector.cpp @@ -258,8 +258,9 @@ std::shared_ptr Collector) : FS(std::move(FS)), Collector(std::move(Collector)) {} - llvm::ErrorOr status(const Twine &Path) override { - auto Result = FS->status(Path); + llvm::ErrorOr status(const Twine &Path, + bool Follow /*= true*/) override { + auto Result = FS->status(Path, Follow); if (Result && Result->exists()) Collector->addFile(Path); return Result; diff --git a/llvm/lib/Support/VirtualFileSystem.cpp b/llvm/lib/Support/VirtualFileSystem.cpp --- a/llvm/lib/Support/VirtualFileSystem.cpp +++ b/llvm/lib/Support/VirtualFileSystem.cpp @@ -252,7 +252,7 @@ } } - ErrorOr status(const Twine &Path) override; + ErrorOr status(const Twine &Path, bool Follow = true) override; ErrorOr> openFileForRead(const Twine &Path) override; directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override; @@ -284,11 +284,12 @@ } // namespace -ErrorOr RealFileSystem::status(const Twine &Path) { +ErrorOr RealFileSystem::status(const Twine &Path, + bool Follow /*= true*/) { SmallString<256> Storage; sys::fs::file_status RealStatus; if (std::error_code EC = - sys::fs::status(adjustPath(Path, Storage), RealStatus)) + sys::fs::status(adjustPath(Path, Storage), RealStatus, Follow)) return EC; return Status::copyWithNewName(RealStatus, Path); } @@ -397,10 +398,11 @@ FS->setCurrentWorkingDirectory(getCurrentWorkingDirectory().get()); } -ErrorOr OverlayFileSystem::status(const Twine &Path) { +ErrorOr OverlayFileSystem::status(const Twine &Path, + bool Follow /*= true*/) { // FIXME: handle symlinks that cross file systems for (iterator I = overlays_begin(), E = overlays_end(); I != E; ++I) { - ErrorOr Status = (*I)->status(Path); + ErrorOr Status = (*I)->status(Path, Follow); if (Status || Status.getError() != llvm::errc::no_such_file_or_directory) return Status; } @@ -879,7 +881,9 @@ cast(*ToNode)); } -llvm::ErrorOr InMemoryFileSystem::status(const Twine &Path) { +llvm::ErrorOr InMemoryFileSystem::status(const Twine &Path, + bool Follow /*= true*/) { + // FIXME: Follow is not implemented for InMemoryFileSystem. auto Node = lookupInMemoryNode(*this, Root.get(), Path); if (Node) return detail::getNodeStatus(*Node, Path); @@ -1956,7 +1960,8 @@ return Status::copyWithNewName(DE->getStatus(), Path); } -ErrorOr RedirectingFileSystem::status(const Twine &Path_) { +ErrorOr RedirectingFileSystem::status(const Twine &Path_, + bool Follow /*= true*/) { SmallString<256> Path; Path_.toVector(Path); @@ -1966,13 +1971,13 @@ ErrorOr Result = lookupPath(Path); if (!Result) { if (shouldFallBackToExternalFS(Result.getError())) - return ExternalFS->status(Path); + return ExternalFS->status(Path, Follow); return Result.getError(); } ErrorOr S = status(Path, *Result); if (!S && shouldFallBackToExternalFS(S.getError(), Result->E)) - S = ExternalFS->status(Path); + S = ExternalFS->status(Path, Follow); return S; } diff --git a/llvm/unittests/Support/VirtualFileSystemTest.cpp b/llvm/unittests/Support/VirtualFileSystemTest.cpp --- a/llvm/unittests/Support/VirtualFileSystemTest.cpp +++ b/llvm/unittests/Support/VirtualFileSystemTest.cpp @@ -57,7 +57,7 @@ public: DummyFileSystem() : FSID(getNextFSID()), FileID(0) {} - ErrorOr status(const Twine &Path) override { + ErrorOr status(const Twine &Path, bool Follow = true) override { auto I = findEntry(Path); if (I == FilesAndDirs.end()) return make_error_code(llvm::errc::no_such_file_or_directory);