Index: include/clang/Tooling/Tooling.h =================================================================== --- include/clang/Tooling/Tooling.h +++ include/clang/Tooling/Tooling.h @@ -296,22 +296,24 @@ /// arguments adjuster by calling the appendArgumentsAdjuster() method. class ClangTool { public: - /// \brief Constructs a clang tool to run over a list of files. + /// \brief Constructs a Clang tool to run over a list of files. /// /// \param Compilations The CompilationDatabase which contains the compile /// command lines for the given source paths. /// \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. + /// \param AlsoUseRealFileSystem Sets the Clang tool to also use the machine's + /// filesystem as the lowest layer to retrieve files from. ClangTool(const CompilationDatabase &Compilations, ArrayRef SourcePaths, std::shared_ptr PCHContainerOps = std::make_shared(), - IntrusiveRefCntPtr BaseFS = - vfs::getRealFileSystem()); + IntrusiveRefCntPtr FileSystem = nullptr, + bool AlsoUseRealFileSystem = true); ~ClangTool(); Index: lib/Tooling/Tooling.cpp =================================================================== --- lib/Tooling/Tooling.cpp +++ lib/Tooling/Tooling.cpp @@ -358,13 +358,22 @@ ClangTool::ClangTool(const CompilationDatabase &Compilations, ArrayRef SourcePaths, std::shared_ptr PCHContainerOps, - IntrusiveRefCntPtr BaseFS) + IntrusiveRefCntPtr FileSystem, + bool AlsoUseRealFileSystem) : Compilations(Compilations), SourcePaths(SourcePaths), PCHContainerOps(std::move(PCHContainerOps)), - OverlayFileSystem(new vfs::OverlayFileSystem(std::move(BaseFS))), - InMemoryFileSystem(new vfs::InMemoryFileSystem), - Files(new FileManager(FileSystemOptions(), OverlayFileSystem)) { + InMemoryFileSystem(new vfs::InMemoryFileSystem) { + assert(!(!AlsoUseRealFileSystem && !FileSystem) && "ClangTool initialized " + "without providing a FileSystem to get files from!"); + if (AlsoUseRealFileSystem) { + OverlayFileSystem = new vfs::OverlayFileSystem(vfs::getRealFileSystem()); + if (FileSystem) + OverlayFileSystem->pushOverlay(FileSystem); + } + else + OverlayFileSystem = new vfs::OverlayFileSystem(FileSystem); OverlayFileSystem->pushOverlay(InMemoryFileSystem); + Files = new FileManager(FileSystemOptions(), OverlayFileSystem); appendArgumentsAdjuster(getClangStripOutputAdjuster()); appendArgumentsAdjuster(getClangSyntaxOnlyAdjuster()); appendArgumentsAdjuster(getClangStripDependencyFileAdjuster()); Index: unittests/Tooling/ToolingTest.cpp =================================================================== --- unittests/Tooling/ToolingTest.cpp +++ unittests/Tooling/ToolingTest.cpp @@ -402,24 +402,48 @@ EXPECT_FALSE(Found); } -TEST(ClangToolTest, BaseVirtualFileSystemUsage) { +TEST(ClangToolVFSTest, MustGiveFileSystem) { + FixedCompilationDatabase Compilations("/", std::vector()); + + EXPECT_DEATH(ClangTool(Compilations, std::vector(), + std::make_shared(), + nullptr, false), + "without providing a FileSystem"); +} + +TEST(ClangToolVFSTest, VirtualFileSystemUsage) { FixedCompilationDatabase Compilations("/", std::vector()); - llvm::IntrusiveRefCntPtr OverlayFileSystem( - new vfs::OverlayFileSystem(vfs::getRealFileSystem())); llvm::IntrusiveRefCntPtr InMemoryFileSystem( - new vfs::InMemoryFileSystem); - OverlayFileSystem->pushOverlay(InMemoryFileSystem); + new vfs::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, false); std::unique_ptr Action( - newFrontendActionFactory()); + 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, false); + 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"});