Index: llvm/include/llvm/Support/VirtualFileSystem.h =================================================================== --- llvm/include/llvm/Support/VirtualFileSystem.h +++ llvm/include/llvm/Support/VirtualFileSystem.h @@ -296,6 +296,13 @@ std::error_code makeAbsolute(SmallVectorImpl &Path) const; }; +/// Interface for virtual file system implementations that have external paths. +class ExternalFileSystem : public FileSystem { +public: + virtual llvm::ErrorOr + getExternalPath(const Twine &Path) const = 0; +}; + /// Gets an \p vfs::FileSystem for the 'real' file system, as seen by /// the operating system. IntrusiveRefCntPtr getRealFileSystem(); Index: llvm/lib/Support/VirtualFileSystem.cpp =================================================================== --- llvm/lib/Support/VirtualFileSystem.cpp +++ llvm/lib/Support/VirtualFileSystem.cpp @@ -229,7 +229,7 @@ namespace { /// The file system according to your operating system. -class RealFileSystem : public FileSystem { +class RealFileSystem : public ExternalFileSystem { public: ErrorOr status(const Twine &Path) override; ErrorOr> openFileForRead(const Twine &Path) override; @@ -240,6 +240,7 @@ std::error_code isLocal(const Twine &Path, bool &Result) override; std::error_code getRealPath(const Twine &Path, SmallVectorImpl &Output) const override; + llvm::ErrorOr getExternalPath(const Twine &Path) const override; private: mutable std::mutex CWDMutex; @@ -303,6 +304,11 @@ return llvm::sys::fs::real_path(Path, Output); } +llvm::ErrorOr +RealFileSystem::getExternalPath(const Twine &Path) const { + return Path.str(); +} + IntrusiveRefCntPtr vfs::getRealFileSystem() { static IntrusiveRefCntPtr FS = new RealFileSystem(); return FS; @@ -1112,7 +1118,7 @@ /// In both cases, the 'name' field may contain multiple path components (e.g. /// /path/to/file). However, any directory that contains more than one child /// must be uniquely represented by a directory entry. -class RedirectingFileSystem : public vfs::FileSystem { +class RedirectingFileSystem : public ExternalFileSystem { friend class RedirectingFileSystemParser; /// The root(s) of the virtual file system. @@ -1164,14 +1170,14 @@ /// Looks up the path [Start, End) in \p From, possibly /// recursing into the contents of \p From if it is a directory. ErrorOr 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(const Twine &Path, Entry *E); public: /// Looks up \p Path in \c Roots. - ErrorOr lookupPath(const Twine &Path); + ErrorOr 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. @@ -1195,6 +1201,8 @@ return ExternalFS->isLocal(Path, Result); } + llvm::ErrorOr getExternalPath(const Twine &Path) const override; + directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override { ErrorOr E = lookupPath(Dir); if (!E) { @@ -1726,7 +1734,7 @@ return FS.release(); } -ErrorOr RedirectingFileSystem::lookupPath(const Twine &Path_) { +ErrorOr RedirectingFileSystem::lookupPath(const Twine &Path_) const { SmallString<256> Path; Path_.toVector(Path); @@ -1757,7 +1765,8 @@ ErrorOr 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()) && @@ -1835,6 +1844,24 @@ return status(Path, *Result); } +ErrorOr +RedirectingFileSystem::getExternalPath(const Twine &Path) const { + ErrorOr E = lookupPath(Path); + if (!E) { + if (IsFallthrough && + E.getError() == llvm::errc::no_such_file_or_directory) { + return Path.str(); + } + return E.getError(); + } + + auto *F = dyn_cast(*E); + if (!F) + return make_error_code(llvm::errc::not_supported); + + return F->getExternalContentsPath(); +} + namespace { /// Provide a file wrapper with an overriden status.