From: Jan Svoboda Date: Tue, 11 Oct 2022 23:02:10 +0000 (-0700) Subject: [clang][deps] Don't share in-memory VFS across scans X-Git-Tag: upstream/17.0.6~30744 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=98672596626862e4b21319da7c01737bf7e20ae4;p=platform%2Fupstream%2Fllvm.git [clang][deps] Don't share in-memory VFS across scans The dependency scanning worker may create an in-memory VFS and inject that into its `FileManager`. (Implemented in D109485.) This VFS currently persists between scans, which is not correct: in-memory files created in one scan could affect subsequent scans. This patch changes things so that the in-memory VFS is local to `DependencyScanningWorker::computeDependencies()`. To test this, one would first scan for dependencies of a named module and then run second scan (on the same worker) for something unrelated, which would pick up the in-memory file created in the first scan. This set up is impossible to achieve with `clang-scan-deps`. We could set this up in `ToolingTests`, but the scanner needs to access the physical filesystem to store `.pcm` files. AFAIK we don't have a good way to propagate something like `%t` into unit tests to make that feasible. (This could be achieved with something like the virtualized `OutputManager`.) Reviewed By: Bigcheese Differential Revision: https://reviews.llvm.org/D135414 --- diff --git a/clang/include/clang/Basic/FileManager.h b/clang/include/clang/Basic/FileManager.h index d3dc54a..ec62e00 100644 --- a/clang/include/clang/Basic/FileManager.h +++ b/clang/include/clang/Basic/FileManager.h @@ -243,6 +243,10 @@ public: const FileSystemOptions &getFileSystemOpts() const { return FileSystemOpts; } llvm::vfs::FileSystem &getVirtualFileSystem() const { return *FS; } + llvm::IntrusiveRefCntPtr + getVirtualFileSystemPtr() const { + return FS; + } void setVirtualFileSystem(IntrusiveRefCntPtr FS) { this->FS = std::move(FS); diff --git a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h index c5776ac..134ac91 100644 --- a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h +++ b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h @@ -91,14 +91,13 @@ public: private: std::shared_ptr PCHContainerOps; - - /// The physical filesystem overlaid by `InMemoryFS`. - llvm::IntrusiveRefCntPtr RealFS; - /// The in-memory filesystem laid on top the physical filesystem in `RealFS`. - llvm::IntrusiveRefCntPtr InMemoryFS; - /// The file system that is used by each worker when scanning for - /// dependencies. This filesystem persists across multiple compiler - /// invocations. + /// The file system to be used during the scan. + /// This is either \c FS passed in the constructor (when performing canonical + /// preprocessing), or \c DepFS (when performing dependency directives scan). + llvm::IntrusiveRefCntPtr BaseFS; + /// When performing dependency directives scan, this is the caching (and + /// dependency-directives-extracting) filesystem overlaid on top of \c FS + /// (passed in the constructor). llvm::IntrusiveRefCntPtr DepFS; ScanningOutputFormat Format; /// Whether to optimize the modules' command-line arguments. diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp index 2da3de3..1810d8f 100644 --- a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp @@ -209,7 +209,8 @@ public: // Support for virtual file system overlays on top of the caching // filesystem. FileMgr->setVirtualFileSystem(createVFSFromCompilerInvocation( - ScanInstance.getInvocation(), ScanInstance.getDiagnostics(), DepFS)); + ScanInstance.getInvocation(), ScanInstance.getDiagnostics(), + FileMgr->getVirtualFileSystemPtr())); llvm::IntrusiveRefCntPtr LocalDepFS = DepFS; @@ -324,15 +325,17 @@ DependencyScanningWorker::DependencyScanningWorker( PCHContainerOps->registerWriter( std::make_unique()); - auto OverlayFS = - llvm::makeIntrusiveRefCnt(std::move(FS)); - InMemoryFS = llvm::makeIntrusiveRefCnt(); - OverlayFS->pushOverlay(InMemoryFS); - RealFS = OverlayFS; - - if (Service.getMode() == ScanningMode::DependencyDirectivesScan) - DepFS = new DependencyScanningWorkerFilesystem(Service.getSharedCache(), - RealFS); + switch (Service.getMode()) { + case ScanningMode::DependencyDirectivesScan: + DepFS = + new DependencyScanningWorkerFilesystem(Service.getSharedCache(), FS); + BaseFS = DepFS; + break; + case ScanningMode::CanonicalPreprocessing: + DepFS = nullptr; + BaseFS = FS; + break; + } } llvm::Error DependencyScanningWorker::computeDependencies( @@ -386,22 +389,32 @@ bool DependencyScanningWorker::computeDependencies( DependencyConsumer &Consumer, DiagnosticConsumer &DC, llvm::Optional ModuleName) { // Reset what might have been modified in the previous worker invocation. - RealFS->setCurrentWorkingDirectory(WorkingDirectory); - - FileSystemOptions FSOpts; - FSOpts.WorkingDir = WorkingDirectory.str(); - auto FileMgr = llvm::makeIntrusiveRefCnt(FSOpts, RealFS); + BaseFS->setCurrentWorkingDirectory(WorkingDirectory); Optional> ModifiedCommandLine; + llvm::IntrusiveRefCntPtr ModifiedFS; if (ModuleName) { ModifiedCommandLine = CommandLine; - InMemoryFS->addFile(*ModuleName, 0, llvm::MemoryBuffer::getMemBuffer("")); ModifiedCommandLine->emplace_back(*ModuleName); + + auto OverlayFS = llvm::makeIntrusiveRefCnt( + std::move(BaseFS)); + auto InMemoryFS = + llvm::makeIntrusiveRefCnt(); + InMemoryFS->setCurrentWorkingDirectory(WorkingDirectory); + InMemoryFS->addFile(*ModuleName, 0, llvm::MemoryBuffer::getMemBuffer("")); + OverlayFS->pushOverlay(InMemoryFS); + ModifiedFS = OverlayFS; } const std::vector &FinalCommandLine = ModifiedCommandLine ? *ModifiedCommandLine : CommandLine; + FileSystemOptions FSOpts; + FSOpts.WorkingDir = WorkingDirectory.str(); + auto FileMgr = llvm::makeIntrusiveRefCnt( + FSOpts, ModifiedFS ? ModifiedFS : BaseFS); + std::vector FinalCCommandLine(CommandLine.size(), nullptr); llvm::transform(CommandLine, FinalCCommandLine.begin(), [](const std::string &Str) { return Str.c_str(); });