Index: include/clang/Basic/VirtualFileSystem.h =================================================================== --- include/clang/Basic/VirtualFileSystem.h +++ include/clang/Basic/VirtualFileSystem.h @@ -309,6 +309,11 @@ iterator overlays_end() { return FSList.rend(); } }; +/// \brief Creates a \p vfs::OverlayFileSystem which overlays the given file +/// system above the 'real' file system, as seen by the operating system. +IntrusiveRefCntPtr +createOverlayOnRealFilesystem(IntrusiveRefCntPtr TopFS); + namespace detail { class InMemoryDirectory; Index: include/clang/Tooling/Tooling.h =================================================================== --- include/clang/Tooling/Tooling.h +++ include/clang/Tooling/Tooling.h @@ -303,14 +303,16 @@ /// \param SourcePaths The source files to run over. If a source files is /// not found in Compilations, it is skipped. /// \param PCHContainerOps The PCHContainerOperations for loading and creating - /// clang modules. - /// \param BaseFS VFS used for all underlying file accesses when running the - /// tool. + /// clang modules. + /// \param FileSystem The Virtual File System that is used to retrieve file + /// contents by the tool. In most cases, this should be an overlay upon + /// the real file system. (See \p vfs::createOverlayOnRealFilesystem + /// for easily creating an overlay.) ClangTool(const CompilationDatabase &Compilations, ArrayRef SourcePaths, std::shared_ptr PCHContainerOps = std::make_shared(), - IntrusiveRefCntPtr BaseFS = + IntrusiveRefCntPtr FileSystem = vfs::getRealFileSystem()); ~ClangTool(); Index: lib/Basic/VirtualFileSystem.cpp =================================================================== --- lib/Basic/VirtualFileSystem.cpp +++ lib/Basic/VirtualFileSystem.cpp @@ -325,6 +325,7 @@ } void OverlayFileSystem::pushOverlay(IntrusiveRefCntPtr FS) { + // FIXME: OverlayFS containing another one in its stack could be flattened. FSList.push_back(FS); // Synchronize added file systems by duplicating the working directory from // the first one in the list. @@ -366,6 +367,14 @@ return {}; } +IntrusiveRefCntPtr +vfs::createOverlayOnRealFilesystem(IntrusiveRefCntPtr TopFS) { + IntrusiveRefCntPtr OverlayFS = + new OverlayFileSystem(getRealFileSystem()); + OverlayFS->pushOverlay(TopFS); + return OverlayFS; +} + clang::vfs::detail::DirIterImpl::~DirIterImpl() = default; namespace { Index: lib/Tooling/Tooling.cpp =================================================================== --- lib/Tooling/Tooling.cpp +++ lib/Tooling/Tooling.cpp @@ -358,10 +358,10 @@ ClangTool::ClangTool(const CompilationDatabase &Compilations, ArrayRef SourcePaths, std::shared_ptr PCHContainerOps, - IntrusiveRefCntPtr BaseFS) + IntrusiveRefCntPtr FileSystem) : Compilations(Compilations), SourcePaths(SourcePaths), PCHContainerOps(std::move(PCHContainerOps)), - OverlayFileSystem(new vfs::OverlayFileSystem(std::move(BaseFS))), + OverlayFileSystem(new vfs::OverlayFileSystem(std::move(FileSystem))), InMemoryFileSystem(new vfs::InMemoryFileSystem), Files(new FileManager(FileSystemOptions(), OverlayFileSystem)) { OverlayFileSystem->pushOverlay(InMemoryFileSystem); Index: unittests/Tooling/ToolingTest.cpp =================================================================== --- unittests/Tooling/ToolingTest.cpp +++ unittests/Tooling/ToolingTest.cpp @@ -402,24 +402,39 @@ EXPECT_FALSE(Found); } -TEST(ClangToolTest, BaseVirtualFileSystemUsage) { +TEST(ClangToolVFSTest, VirtualFileSystemUsage) { FixedCompilationDatabase Compilations("/", std::vector()); - llvm::IntrusiveRefCntPtr OverlayFileSystem( - new vfs::OverlayFileSystem(vfs::getRealFileSystem())); llvm::IntrusiveRefCntPtr InMemoryFileSystem( new vfs::InMemoryFileSystem); - OverlayFileSystem->pushOverlay(InMemoryFileSystem); InMemoryFileSystem->addFile( - "a.cpp", 0, llvm::MemoryBuffer::getMemBuffer("int main() {}")); + "/a.cpp", 0, llvm::MemoryBuffer::getMemBuffer("int main() {}")); - ClangTool Tool(Compilations, std::vector(1, "a.cpp"), - std::make_shared(), OverlayFileSystem); + ClangTool Tool(Compilations, std::vector(1, "/a.cpp"), + std::make_shared(), + InMemoryFileSystem); std::unique_ptr Action( newFrontendActionFactory()); EXPECT_EQ(0, Tool.run(Action.get())); } +TEST(ClangToolVFSTest, VFSDoesntContainEveryFile) { + FixedCompilationDatabase Compilations("/", std::vector()); + llvm::IntrusiveRefCntPtr InMemoryFileSystem( + new vfs::InMemoryFileSystem); + + InMemoryFileSystem->addFile( + "/a.cpp", 0, llvm::MemoryBuffer::getMemBuffer("#include \n" + "int main() {}")); + + ClangTool Tool(Compilations, std::vector(1, "/a.cpp"), + std::make_shared(), + InMemoryFileSystem); + std::unique_ptr Action( + newFrontendActionFactory()); + EXPECT_NE(0, Tool.run(Action.get())); +} + // Check getClangStripDependencyFileAdjuster doesn't strip args after -MD/-MMD. TEST(ClangToolTest, StripDependencyFileAdjuster) { FixedCompilationDatabase Compilations("/", {"-MD", "-c", "-MMD", "-w"});