From b5b48db12ed915d2927ba6dc1f9fbe50b342de04 Mon Sep 17 00:00:00 2001 From: Cameron Desrochers Date: Mon, 11 Sep 2017 15:03:23 +0000 Subject: [PCH] Allow VFS to be used for tests that generate PCH files When using a virtual file-system (VFS) and a preamble file (PCH) is generated, it is generated on-disk in the real file-system instead of in the VFS (which makes sense, since the VFS is read-only). However, when subsequently reading the generated PCH, the frontend passes through the VFS it has been given -- resulting in an error and a failed parse (since the VFS doesn't contain the PCH; the real filesystem does). This patch fixes that by detecting when a VFS is being used for a parse that needs to work with a PCH file, and creating an overlay VFS that includes the PCH file from the real file-system. This allows tests to be written which make use of both PCH files and a VFS. Differential Revision: https://reviews.llvm.org/D37474 llvm-svn: 312917 --- clang/lib/Frontend/ASTUnit.cpp | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'clang/lib/Frontend/ASTUnit.cpp') diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp index 6efc9e7539e..b644ef81222 100644 --- a/clang/lib/Frontend/ASTUnit.cpp +++ b/clang/lib/Frontend/ASTUnit.cpp @@ -1009,6 +1009,24 @@ static void checkAndSanitizeDiags(SmallVectorImpl & } } +static IntrusiveRefCntPtr createVFSOverlayForPreamblePCH( + StringRef PCHFilename, + IntrusiveRefCntPtr RealFS, + IntrusiveRefCntPtr VFS) { + // We want only the PCH file from the real filesystem to be available, + // so we create an in-memory VFS with just that and overlay it on top. + auto Buf = RealFS->getBufferForFile(PCHFilename); + if (!Buf) + return VFS; + IntrusiveRefCntPtr + PCHFS(new vfs::InMemoryFileSystem()); + PCHFS->addFile(PCHFilename, 0, std::move(*Buf)); + IntrusiveRefCntPtr + Overlay(new vfs::OverlayFileSystem(VFS)); + Overlay->pushOverlay(PCHFS); + return Overlay; +} + /// Parse the source file into a translation unit using the given compiler /// invocation, replacing the current translation unit. /// @@ -1030,6 +1048,24 @@ bool ASTUnit::Parse(std::shared_ptr PCHContainerOps, Clang->setVirtualFileSystem(VFS); } + // Make sure we can access the PCH file even if we're using a VFS + if (!VFS && FileMgr) + VFS = FileMgr->getVirtualFileSystem(); + IntrusiveRefCntPtr RealFS = vfs::getRealFileSystem(); + if (OverrideMainBuffer && VFS && RealFS && VFS != RealFS && + !VFS->exists(Preamble->GetPCHPath())) { + // We have a slight inconsistency here -- we're using the VFS to + // read files, but the PCH was generated in the real file system. + VFS = createVFSOverlayForPreamblePCH(Preamble->GetPCHPath(), RealFS, VFS); + if (FileMgr) { + FileMgr = new FileManager(FileMgr->getFileSystemOpts(), VFS); + Clang->setFileManager(FileMgr.get()); + } + else { + Clang->setVirtualFileSystem(VFS); + } + } + // Recover resources if we crash before exiting this method. llvm::CrashRecoveryContextCleanupRegistrar CICleanup(Clang.get()); -- cgit v1.2.3