From fe2478d44e4f7f191c43fef629ac7a23d0251e72 Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Mon, 11 Apr 2022 14:50:28 -0700 Subject: [VFS] RedirectingFileSystem only replace path if not already mapped If the `ExternalFS` has already remapped to an external path then `RedirectingFileSystem` should not change it to the originally provided path. This fixes the original path always being used if multiple VFS overlays were provided and the path wasn't found in the highest (ie. first in the chain). For now this is accomplished through the use of a new `ExposesExternalVFSPath` field on `vfs::Status`. This flag is true when the `Status` has an external path that's different from its virtual path, ie. the contained path is the external path. See the plan in `FileManager::getFileRef` for where this is going - eventually we won't need `IsVFSMapped` any more and all returned paths should be virtual. Resolves rdar://90578880 and llvm-project#53306. Reviewed By: dexonsmith Differential Revision: https://reviews.llvm.org/D123398 --- llvm/lib/Support/VirtualFileSystem.cpp | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) (limited to 'llvm/lib/Support/VirtualFileSystem.cpp') diff --git a/llvm/lib/Support/VirtualFileSystem.cpp b/llvm/lib/Support/VirtualFileSystem.cpp index cb34fa60d801..c9273f00ad73 100644 --- a/llvm/lib/Support/VirtualFileSystem.cpp +++ b/llvm/lib/Support/VirtualFileSystem.cpp @@ -2163,9 +2163,16 @@ RedirectingFileSystem::lookupPathImpl( static Status getRedirectedFileStatus(const Twine &OriginalPath, bool UseExternalNames, Status ExternalStatus) { + // The path has been mapped by some nested VFS and exposes an external path, + // don't override it with the original path. + if (ExternalStatus.ExposesExternalVFSPath) + return ExternalStatus; + Status S = ExternalStatus; if (!UseExternalNames) S = Status::copyWithNewName(S, OriginalPath); + else + S.ExposesExternalVFSPath = true; S.IsVFSMapped = true; return S; } @@ -2194,11 +2201,13 @@ ErrorOr RedirectingFileSystem::status( ErrorOr RedirectingFileSystem::getExternalStatus(const Twine &CanonicalPath, const Twine &OriginalPath) const { - if (auto Result = ExternalFS->status(CanonicalPath)) { - return Result.get().copyWithNewName(Result.get(), OriginalPath); - } else { - return Result.getError(); - } + auto Result = ExternalFS->status(CanonicalPath); + + // The path has been mapped by some nested VFS, don't override it with the + // original path. + if (!Result || Result->ExposesExternalVFSPath) + return Result; + return Status::copyWithNewName(Result.get(), OriginalPath); } ErrorOr RedirectingFileSystem::status(const Twine &OriginalPath) { @@ -2268,7 +2277,9 @@ public: ErrorOr> File::getWithPath(ErrorOr> Result, const Twine &P) { - if (!Result) + // See \c getRedirectedFileStatus - don't update path if it's exposing an + // external path. + if (!Result || (*Result)->status()->ExposesExternalVFSPath) return Result; ErrorOr> F = std::move(*Result); -- cgit v1.2.3