diff --git a/clang-tools-extra/clangd/ScanningProjectModules.cpp b/clang-tools-extra/clangd/ScanningProjectModules.cpp index e2d710e3794d..b1338634e0c2 100644 --- a/clang-tools-extra/clangd/ScanningProjectModules.cpp +++ b/clang-tools-extra/clangd/ScanningProjectModules.cpp @@ -35,8 +35,9 @@ public: ModuleDependencyScanner( std::shared_ptr CDB, const ThreadsafeFS &TFS) - : CDB(CDB), TFS(TFS), Service([] { + : CDB(CDB), Service([&TFS] { dependencies::DependencyScanningServiceOptions Opts; + Opts.MakeVFS = [&] { return TFS.view(std::nullopt); }; Opts.Mode = dependencies::ScanningMode::CanonicalPreprocessing; Opts.Format = dependencies::ScanningOutputFormat::P1689; return Opts; @@ -79,7 +80,6 @@ public: private: std::shared_ptr CDB; - const ThreadsafeFS &TFS; // Whether the scanner has scanned the project globally. bool GlobalScanned = false; @@ -109,9 +109,7 @@ ModuleDependencyScanner::scan(PathRef FilePath, using namespace clang::tooling; - llvm::SmallString<128> FilePathDir(FilePath); - llvm::sys::path::remove_filename(FilePathDir); - DependencyScanningTool ScanningTool(Service, TFS.view(FilePathDir)); + DependencyScanningTool ScanningTool(Service); std::string S; llvm::raw_string_ostream OS(S); diff --git a/clang/include/clang/DependencyScanning/DependencyScanningService.h b/clang/include/clang/DependencyScanning/DependencyScanningService.h index 509b6a579ecb..20ba86bd097b 100644 --- a/clang/include/clang/DependencyScanning/DependencyScanningService.h +++ b/clang/include/clang/DependencyScanning/DependencyScanningService.h @@ -80,6 +80,11 @@ enum class ScanningOptimizations { struct DependencyScanningServiceOptions { DependencyScanningServiceOptions(); + /// The function invoked to create each worker's VFS. This function and the + /// VFS itself must be thread-safe whenever using multiple workers + /// concurrently or whenever \c AsyncScanModules is true. + std::function()> + MakeVFS; // = [] { return llvm::vfs::createPhysicalFileSystem(); } /// Whether to use optimized dependency directive scan or full preprocessing. ScanningMode Mode = ScanningMode::DependencyDirectivesScan; /// What output format are we expected to produce. diff --git a/clang/include/clang/DependencyScanning/DependencyScanningWorker.h b/clang/include/clang/DependencyScanning/DependencyScanningWorker.h index 2a48f342335d..e1e0c14c7b52 100644 --- a/clang/include/clang/DependencyScanning/DependencyScanningWorker.h +++ b/clang/include/clang/DependencyScanning/DependencyScanningWorker.h @@ -87,9 +87,7 @@ public: /// Construct a dependency scanning worker. /// /// @param Service The parent service. Must outlive the worker. - /// @param BaseFS The filesystem for the worker to use. - DependencyScanningWorker(DependencyScanningService &Service, - IntrusiveRefCntPtr BaseFS); + DependencyScanningWorker(DependencyScanningService &Service); ~DependencyScanningWorker(); diff --git a/clang/include/clang/Tooling/DependencyScanningTool.h b/clang/include/clang/Tooling/DependencyScanningTool.h index fe719aceaef1..96d21866dd7f 100644 --- a/clang/include/clang/Tooling/DependencyScanningTool.h +++ b/clang/include/clang/Tooling/DependencyScanningTool.h @@ -36,10 +36,8 @@ public: /// Construct a dependency scanning tool. /// /// @param Service The parent service. Must outlive the tool. - /// @param FS The filesystem for the tool to use. Defaults to the physical FS. - DependencyScanningTool(dependencies::DependencyScanningService &Service, - llvm::IntrusiveRefCntPtr FS = - llvm::vfs::createPhysicalFileSystem()); + DependencyScanningTool(dependencies::DependencyScanningService &Service) + : Worker(Service) {} /// Print out the dependency information into a string using the dependency /// file format that is specified in the options (-MD is the default) and diff --git a/clang/lib/DependencyScanning/DependencyScannerImpl.cpp b/clang/lib/DependencyScanning/DependencyScannerImpl.cpp index 28fa2571a24d..3cb63a1a055c 100644 --- a/clang/lib/DependencyScanning/DependencyScannerImpl.cpp +++ b/clang/lib/DependencyScanning/DependencyScannerImpl.cpp @@ -620,10 +620,9 @@ struct AsyncModuleCompile : PPCallbacks { if (!LockErr && !Owned) return; // We should build the PCM. - // FIXME: Pass the correct BaseFS to the worker FS. IntrusiveRefCntPtr VFS = llvm::makeIntrusiveRefCnt( - Service.getSharedCache(), llvm::vfs::getRealFileSystem()); + Service.getSharedCache(), Service.getOpts().MakeVFS()); VFS = createVFSFromCompilerInvocation(CI.getInvocation(), CI.getDiagnostics(), std::move(VFS)); auto DC = std::make_unique(); diff --git a/clang/lib/DependencyScanning/DependencyScanningService.cpp b/clang/lib/DependencyScanning/DependencyScanningService.cpp index 3651b9b20a70..eb06c86040f0 100644 --- a/clang/lib/DependencyScanning/DependencyScanningService.cpp +++ b/clang/lib/DependencyScanning/DependencyScanningService.cpp @@ -14,5 +14,6 @@ using namespace clang; using namespace dependencies; DependencyScanningServiceOptions::DependencyScanningServiceOptions() - : BuildSessionTimestamp( + : MakeVFS([] { return llvm::vfs::createPhysicalFileSystem(); }), + BuildSessionTimestamp( llvm::sys::toTimeT(std::chrono::system_clock::now())) {} diff --git a/clang/lib/DependencyScanning/DependencyScanningWorker.cpp b/clang/lib/DependencyScanning/DependencyScanningWorker.cpp index 7d0c93138d78..60e5103fde6e 100644 --- a/clang/lib/DependencyScanning/DependencyScanningWorker.cpp +++ b/clang/lib/DependencyScanning/DependencyScanningWorker.cpp @@ -20,8 +20,7 @@ using namespace clang; using namespace dependencies; DependencyScanningWorker::DependencyScanningWorker( - DependencyScanningService &Service, - llvm::IntrusiveRefCntPtr BaseFS) + DependencyScanningService &Service) : Service(Service) { PCHContainerOps = std::make_shared(); // We need to read object files from PCH built outside the scanner. @@ -30,6 +29,8 @@ DependencyScanningWorker::DependencyScanningWorker( // The scanner itself writes only raw ast files. PCHContainerOps->registerWriter(std::make_unique()); + auto BaseFS = Service.getOpts().MakeVFS(); + if (Service.getOpts().TraceVFS) BaseFS = llvm::makeIntrusiveRefCnt( std::move(BaseFS)); diff --git a/clang/lib/Tooling/DependencyScanningTool.cpp b/clang/lib/Tooling/DependencyScanningTool.cpp index cc4c88fc42f5..2ae149e8fb2c 100644 --- a/clang/lib/Tooling/DependencyScanningTool.cpp +++ b/clang/lib/Tooling/DependencyScanningTool.cpp @@ -14,7 +14,6 @@ #include "clang/Frontend/Utils.h" #include "llvm/ADT/SmallVectorExtras.h" #include "llvm/ADT/iterator.h" -#include "llvm/Support/VirtualFileSystem.h" #include "llvm/TargetParser/Host.h" #include @@ -22,11 +21,6 @@ using namespace clang; using namespace tooling; using namespace dependencies; -DependencyScanningTool::DependencyScanningTool( - DependencyScanningService &Service, - llvm::IntrusiveRefCntPtr FS) - : Worker(Service, std::move(FS)) {} - namespace { /// Prints out all of the gathered dependencies into a string. class MakeDependencyPrinterConsumer : public DependencyConsumer { diff --git a/clang/unittests/DependencyScanning/DependencyScanningWorkerTest.cpp b/clang/unittests/DependencyScanning/DependencyScanningWorkerTest.cpp index ca51fc3f6fbc..9fbebcbc4e1c 100644 --- a/clang/unittests/DependencyScanning/DependencyScanningWorkerTest.cpp +++ b/clang/unittests/DependencyScanning/DependencyScanningWorkerTest.cpp @@ -32,9 +32,10 @@ TEST(DependencyScanner, ScanDepsWithDiagConsumer) { VFS->addFile(AsmPath, 0, llvm::MemoryBuffer::getMemBuffer("")); DependencyScanningServiceOptions Opts; + Opts.MakeVFS = [&] { return VFS; }; Opts.Format = ScanningOutputFormat::Make; DependencyScanningService Service(std::move(Opts)); - DependencyScanningWorker Worker(Service, VFS); + DependencyScanningWorker Worker(Service); llvm::DenseSet AlreadySeen; FullDependencyConsumer DC(AlreadySeen); diff --git a/clang/unittests/Tooling/DependencyScannerTest.cpp b/clang/unittests/Tooling/DependencyScannerTest.cpp index a764a206c467..79fd5a312d2b 100644 --- a/clang/unittests/Tooling/DependencyScannerTest.cpp +++ b/clang/unittests/Tooling/DependencyScannerTest.cpp @@ -229,9 +229,10 @@ TEST(DependencyScanner, ScanDepsWithFS) { llvm::MemoryBuffer::getMemBuffer("#include \"header.h\"\n")); DependencyScanningServiceOptions Opts; + Opts.MakeVFS = [&] { return VFS; }; Opts.Format = ScanningOutputFormat::Make; DependencyScanningService Service(std::move(Opts)); - DependencyScanningTool ScanTool(Service, VFS); + DependencyScanningTool ScanTool(Service); TextDiagnosticBuffer DiagConsumer; std::optional DepFile = @@ -287,9 +288,10 @@ TEST(DependencyScanner, ScanDepsWithModuleLookup) { auto InterceptFS = llvm::makeIntrusiveRefCnt(VFS); DependencyScanningServiceOptions Opts; + Opts.MakeVFS = [&] { return InterceptFS; }; Opts.Format = ScanningOutputFormat::Make; DependencyScanningService Service(std::move(Opts)); - DependencyScanningTool ScanTool(Service, InterceptFS); + DependencyScanningTool ScanTool(Service); // This will fail with "fatal error: module 'Foo' not found" but it doesn't // matter, the point of the test is to check that files are not read