From 82ec4fde42176d315fd859514c3b3d0aa364acf0 Mon Sep 17 00:00:00 2001 From: Bruno Cardoso Lopes Date: Thu, 22 Dec 2016 07:06:03 +0000 Subject: [CrashReproducer] Add support for merging -ivfsoverlay Merge all VFS mapped files inside -ivfsoverlay inputs into the vfs overlay provided by the crash reproducer. This is the last missing piece to allow crash reproducers to fully work with user frameworks; when combined with headermaps, it allows clang to find additional frameworks. rdar://problem/27913709 llvm-svn: 290326 --- clang/lib/Basic/VirtualFileSystem.cpp | 47 ++++++++++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 3 deletions(-) (limited to 'clang/lib/Basic/VirtualFileSystem.cpp') diff --git a/clang/lib/Basic/VirtualFileSystem.cpp b/clang/lib/Basic/VirtualFileSystem.cpp index 88d08b4b669..50fcb22faf5 100644 --- a/clang/lib/Basic/VirtualFileSystem.cpp +++ b/clang/lib/Basic/VirtualFileSystem.cpp @@ -887,9 +887,6 @@ private: RedirectingFileSystem(IntrusiveRefCntPtr ExternalFS) : ExternalFS(std::move(ExternalFS)) {} - /// \brief Looks up \p Path in \c Roots. - ErrorOr lookupPath(const Twine &Path); - /// \brief 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, @@ -899,6 +896,9 @@ private: ErrorOr status(const Twine &Path, Entry *E); public: + /// \brief Looks up \p Path in \c Roots. + ErrorOr lookupPath(const Twine &Path); + /// \brief Parses \p Buffer, which is expected to be in YAML format and /// returns a virtual file system representing its contents. static RedirectingFileSystem * @@ -1606,6 +1606,47 @@ vfs::getVFSFromYAML(std::unique_ptr Buffer, std::move(ExternalFS)); } +static void getVFSEntries(Entry *SrcE, SmallVectorImpl &Path, + SmallVectorImpl &Entries) { + auto Kind = SrcE->getKind(); + if (Kind == EK_Directory) { + auto *DE = dyn_cast(SrcE); + assert(DE && "Must be a directory"); + for (std::unique_ptr &SubEntry : + llvm::make_range(DE->contents_begin(), DE->contents_end())) { + Path.push_back(SubEntry->getName()); + getVFSEntries(SubEntry.get(), Path, Entries); + Path.pop_back(); + } + return; + } + + assert(Kind == EK_File && "Must be a EK_File"); + auto *FE = dyn_cast(SrcE); + assert(FE && "Must be a file"); + SmallString<128> VPath; + for (auto &Comp : Path) + llvm::sys::path::append(VPath, Comp); + Entries.push_back(YAMLVFSEntry(VPath.c_str(), FE->getExternalContentsPath())); +} + +void vfs::collectVFSFromYAML(std::unique_ptr Buffer, + SourceMgr::DiagHandlerTy DiagHandler, + StringRef YAMLFilePath, + SmallVectorImpl &CollectedEntries, + void *DiagContext, + IntrusiveRefCntPtr ExternalFS) { + RedirectingFileSystem *VFS = RedirectingFileSystem::create( + std::move(Buffer), DiagHandler, YAMLFilePath, DiagContext, + std::move(ExternalFS)); + ErrorOr RootE = VFS->lookupPath("/"); + if (!RootE) + return; + SmallVector Components; + Components.push_back("/"); + getVFSEntries(*RootE, Components, CollectedEntries); +} + UniqueID vfs::getNextVirtualUniqueID() { static std::atomic UID; unsigned ID = ++UID; -- cgit v1.2.3