diff options
author | Volodymyr Sapsai <vsapsai@apple.com> | 2018-11-16 01:15:54 +0000 |
---|---|---|
committer | Volodymyr Sapsai <vsapsai@apple.com> | 2018-11-16 01:15:54 +0000 |
commit | 7610033f56a9e7b04138774334590f0bdd3f79db (patch) | |
tree | 26cc17013470ad6388d0ee742d9181c4929dbf5a /llvm/lib/Support/VirtualFileSystem.cpp | |
parent | cac749ac884cfab87a0b2a805b43530c26a627c8 (diff) | |
download | bcm5719-llvm-7610033f56a9e7b04138774334590f0bdd3f79db.tar.gz bcm5719-llvm-7610033f56a9e7b04138774334590f0bdd3f79db.zip |
[VFS] Implement `RedirectingFileSystem::getRealPath`.
It fixes the case when Objective-C framework is added as a subframework
through a symlink. When parent framework infers a module map and fails
to detect a symlink, it would add a subframework as a submodule. And
when we parse module map for the subframework, we would encounter an
error like
> error: umbrella for module 'WithSubframework.Foo' already covers this directory
By implementing `getRealPath` "an egregious but useful hack" in
`ModuleMap::inferFrameworkModule` works as expected.
rdar://problem/45821279
Reviewers: bruno, benlangmuir, erik.pilkington
Reviewed By: bruno
Subscribers: hiraditya, dexonsmith, JDevlieghere, cfe-commits, llvm-commits
Differential Revision: https://reviews.llvm.org/D54245
llvm-svn: 347009
Diffstat (limited to 'llvm/lib/Support/VirtualFileSystem.cpp')
-rw-r--r-- | llvm/lib/Support/VirtualFileSystem.cpp | 33 |
1 files changed, 29 insertions, 4 deletions
diff --git a/llvm/lib/Support/VirtualFileSystem.cpp b/llvm/lib/Support/VirtualFileSystem.cpp index e8b0435b9cd..24581944fa8 100644 --- a/llvm/lib/Support/VirtualFileSystem.cpp +++ b/llvm/lib/Support/VirtualFileSystem.cpp @@ -1164,14 +1164,14 @@ private: /// Looks up the path <tt>[Start, End)</tt> in \p From, possibly /// recursing into the contents of \p From if it is a directory. ErrorOr<Entry *> lookupPath(sys::path::const_iterator Start, - sys::path::const_iterator End, Entry *From); + sys::path::const_iterator End, Entry *From) const; /// Get the status of a given an \c Entry. ErrorOr<Status> status(const Twine &Path, Entry *E); public: /// Looks up \p Path in \c Roots. - ErrorOr<Entry *> lookupPath(const Twine &Path); + ErrorOr<Entry *> lookupPath(const Twine &Path) const; /// Parses \p Buffer, which is expected to be in YAML format and /// returns a virtual file system representing its contents. @@ -1183,6 +1183,9 @@ public: ErrorOr<Status> status(const Twine &Path) override; ErrorOr<std::unique_ptr<File>> openFileForRead(const Twine &Path) override; + std::error_code getRealPath(const Twine &Path, + SmallVectorImpl<char> &Output) const override; + llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override { return ExternalFS->getCurrentWorkingDirectory(); } @@ -1726,7 +1729,7 @@ RedirectingFileSystem::create(std::unique_ptr<MemoryBuffer> Buffer, return FS.release(); } -ErrorOr<Entry *> RedirectingFileSystem::lookupPath(const Twine &Path_) { +ErrorOr<Entry *> RedirectingFileSystem::lookupPath(const Twine &Path_) const { SmallString<256> Path; Path_.toVector(Path); @@ -1757,7 +1760,8 @@ ErrorOr<Entry *> RedirectingFileSystem::lookupPath(const Twine &Path_) { ErrorOr<Entry *> RedirectingFileSystem::lookupPath(sys::path::const_iterator Start, - sys::path::const_iterator End, Entry *From) { + sys::path::const_iterator End, + Entry *From) const { #ifndef _WIN32 assert(!isTraversalComponent(*Start) && !isTraversalComponent(From->getName()) && @@ -1890,6 +1894,27 @@ RedirectingFileSystem::openFileForRead(const Twine &Path) { llvm::make_unique<FileWithFixedStatus>(std::move(*Result), S)); } +std::error_code +RedirectingFileSystem::getRealPath(const Twine &Path, + SmallVectorImpl<char> &Output) const { + ErrorOr<Entry *> Result = lookupPath(Path); + if (!Result) { + if (IsFallthrough && + Result.getError() == llvm::errc::no_such_file_or_directory) { + return ExternalFS->getRealPath(Path, Output); + } + return Result.getError(); + } + + if (auto *F = dyn_cast<RedirectingFileEntry>(*Result)) { + return ExternalFS->getRealPath(F->getExternalContentsPath(), Output); + } + // Even if there is a directory entry, fall back to ExternalFS if allowed, + // because directories don't have a single external contents path. + return IsFallthrough ? ExternalFS->getRealPath(Path, Output) + : llvm::errc::invalid_argument; +} + IntrusiveRefCntPtr<FileSystem> vfs::getVFSFromYAML(std::unique_ptr<MemoryBuffer> Buffer, SourceMgr::DiagHandlerTy DiagHandler, |