From d77588df4553f0e93a74e6eab33e1ce87b576320 Mon Sep 17 00:00:00 2001 From: Jan Svoboda Date: Mon, 10 Jul 2023 10:10:38 -0700 Subject: [llvm][vfs] For virtual directories, use the virtual path as the real path A follow-up to D135841. This patch returns the virtual path for directories from `RedirectingFileSystem`. This ensures the contents of `Path` are the same as the contents of `FS->getRealPath(Path)`. This also means we can drop the workaround in Clang's module map canonicalization, where we couldn't use the real path for a directory if it resolved to a different `DirectoryEntry`. In addition to that, we can also avoid introducing new workaround for a bug triggered by the newly introduced test case. Reviewed By: benlangmuir Differential Revision: https://reviews.llvm.org/D135849 --- llvm/lib/Support/VirtualFileSystem.cpp | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) (limited to 'llvm/lib/Support/VirtualFileSystem.cpp') diff --git a/llvm/lib/Support/VirtualFileSystem.cpp b/llvm/lib/Support/VirtualFileSystem.cpp index bcf5389..acb0df2 100644 --- a/llvm/lib/Support/VirtualFileSystem.cpp +++ b/llvm/lib/Support/VirtualFileSystem.cpp @@ -2239,6 +2239,14 @@ RedirectingFileSystem::LookupResult::LookupResult( } } +void RedirectingFileSystem::LookupResult::getPath( + llvm::SmallVectorImpl &Result) const { + Result.clear(); + for (Entry *Parent : Parents) + llvm::sys::path::append(Result, Parent->getName()); + llvm::sys::path::append(Result, E->getName()); +} + std::error_code RedirectingFileSystem::makeCanonical(SmallVectorImpl &Path) const { if (std::error_code EC = makeAbsolute(Path)) @@ -2257,11 +2265,14 @@ ErrorOr RedirectingFileSystem::lookupPath(StringRef Path) const { sys::path::const_iterator Start = sys::path::begin(Path); sys::path::const_iterator End = sys::path::end(Path); + llvm::SmallVector Entries; for (const auto &Root : Roots) { ErrorOr Result = - lookupPathImpl(Start, End, Root.get()); - if (Result || Result.getError() != llvm::errc::no_such_file_or_directory) + lookupPathImpl(Start, End, Root.get(), Entries); + if (Result || Result.getError() != llvm::errc::no_such_file_or_directory) { + Result->Parents = std::move(Entries); return Result; + } } return make_error_code(llvm::errc::no_such_file_or_directory); } @@ -2269,7 +2280,8 @@ RedirectingFileSystem::lookupPath(StringRef Path) const { ErrorOr RedirectingFileSystem::lookupPathImpl( sys::path::const_iterator Start, sys::path::const_iterator End, - RedirectingFileSystem::Entry *From) const { + RedirectingFileSystem::Entry *From, + llvm::SmallVectorImpl &Entries) const { assert(!isTraversalComponent(*Start) && !isTraversalComponent(From->getName()) && "Paths should not contain traversal components"); @@ -2298,10 +2310,12 @@ RedirectingFileSystem::lookupPathImpl( auto *DE = cast(From); for (const std::unique_ptr &DirEntry : llvm::make_range(DE->contents_begin(), DE->contents_end())) { + Entries.push_back(From); ErrorOr Result = - lookupPathImpl(Start, End, DirEntry.get()); + lookupPathImpl(Start, End, DirEntry.get(), Entries); if (Result || Result.getError() != llvm::errc::no_such_file_or_directory) return Result; + Entries.pop_back(); } return make_error_code(llvm::errc::no_such_file_or_directory); @@ -2543,10 +2557,12 @@ RedirectingFileSystem::getRealPath(const Twine &OriginalPath, return P; } - // If we found a DirectoryEntry, still fallthrough to the original path if - // allowed, because directories don't have a single external contents path. - if (Redirection == RedirectKind::Fallthrough) - return ExternalFS->getRealPath(CanonicalPath, Output); + // We found a DirectoryEntry, which does not have a single external contents + // path. Use the canonical virtual path. + if (Redirection == RedirectKind::Fallthrough) { + Result->getPath(Output); + return {}; + } return llvm::errc::invalid_argument; } -- cgit v1.1