From e86c7ef3b71e29dfc9d879eec7a7795b752d03d4 Mon Sep 17 00:00:00 2001 From: Jan Svoboda Date: Mon, 21 Jul 2025 10:56:26 -0700 Subject: [PATCH 1/3] [clang][deps] Stop using `tooling::ToolAction` --- .../DependencyScanningWorker.cpp | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp index 9bd85479d9810..f64fbd5c8a47c 100644 --- a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp @@ -24,7 +24,6 @@ #include "clang/Tooling/DependencyScanning/DependencyScanningService.h" #include "clang/Tooling/DependencyScanning/InProcessModuleCache.h" #include "clang/Tooling/DependencyScanning/ModuleDepCollector.h" -#include "clang/Tooling/Tooling.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Error.h" @@ -376,7 +375,7 @@ class ScanningDependencyDirectivesGetter : public DependencyDirectivesGetter { /// A clang tool that runs the preprocessor in a mode that's optimized for /// dependency scanning for the given compiler invocation. -class DependencyScanningAction : public tooling::ToolAction { +class DependencyScanningAction { public: DependencyScanningAction( DependencyScanningService &Service, StringRef WorkingDirectory, @@ -390,7 +389,7 @@ class DependencyScanningAction : public tooling::ToolAction { bool runInvocation(std::shared_ptr Invocation, FileManager *DriverFileMgr, std::shared_ptr PCHContainerOps, - DiagnosticConsumer *DiagConsumer) override { + DiagnosticConsumer *DiagConsumer) { // Make a deep copy of the original Clang invocation. CompilerInvocation OriginalInvocation(*Invocation); // Restore the value of DisableFree, which may be modified by Tooling. @@ -716,11 +715,19 @@ static bool createAndRunToolInvocation( // Save executable path before providing CommandLine to ToolInvocation std::string Executable = CommandLine[0]; - ToolInvocation Invocation(std::move(CommandLine), &Action, &FM, - PCHContainerOps); - Invocation.setDiagnosticConsumer(Diags.getClient()); - Invocation.setDiagnosticOptions(&Diags.getDiagnosticOptions()); - if (!Invocation.run()) + + llvm::opt::ArgStringList Argv; + for (const std::string &Str : ArrayRef(CommandLine).drop_front()) + Argv.push_back(Str.c_str()); + + auto Invocation = std::make_shared(); + if (!CompilerInvocation::CreateFromArgs(*Invocation, Argv, Diags)) { + // FIXME: Should we just go on like cc1_main does? + return false; + } + + if (!Action.runInvocation(std::move(Invocation), &FM, PCHContainerOps, + Diags.getClient())) return false; std::vector Args = Action.takeLastCC1Arguments(); From 983df920190f76fa84ae1d6df19212fadf174b5f Mon Sep 17 00:00:00 2001 From: Jan Svoboda Date: Mon, 21 Jul 2025 11:43:52 -0700 Subject: [PATCH 2/3] [clang][deps] Stop creating `FileManager` --- .../DependencyScanningWorker.cpp | 50 +++++++------------ 1 file changed, 19 insertions(+), 31 deletions(-) diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp index f64fbd5c8a47c..3a80f3237b743 100644 --- a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp @@ -387,7 +387,7 @@ class DependencyScanningAction { DisableFree(DisableFree), ModuleName(ModuleName) {} bool runInvocation(std::shared_ptr Invocation, - FileManager *DriverFileMgr, + IntrusiveRefCntPtr FS, std::shared_ptr PCHContainerOps, DiagnosticConsumer *DiagConsumer) { // Make a deep copy of the original Clang invocation. @@ -418,8 +418,8 @@ class DependencyScanningAction { // Create the compiler's actual diagnostics engine. sanitizeDiagOpts(ScanInstance.getDiagnosticOpts()); assert(!DiagConsumerFinished && "attempt to reuse finished consumer"); - ScanInstance.createDiagnostics(DriverFileMgr->getVirtualFileSystem(), - DiagConsumer, /*ShouldOwnClient=*/false); + ScanInstance.createDiagnostics(*FS, DiagConsumer, + /*ShouldOwnClient=*/false); if (!ScanInstance.hasDiagnostics()) return false; @@ -440,9 +440,9 @@ class DependencyScanningAction { any(Service.getOptimizeArgs() & ScanningOptimizations::VFS); // Support for virtual file system overlays. - auto FS = createVFSFromCompilerInvocation( - ScanInstance.getInvocation(), ScanInstance.getDiagnostics(), - DriverFileMgr->getVirtualFileSystemPtr()); + FS = createVFSFromCompilerInvocation(ScanInstance.getInvocation(), + ScanInstance.getDiagnostics(), + std::move(FS)); // Create a new FileManager to match the invocation's FileSystemOptions. auto *FileMgr = ScanInstance.createFileManager(FS); @@ -553,9 +553,6 @@ class DependencyScanningAction { if (Result) setLastCC1Arguments(std::move(OriginalInvocation)); - // Propagate the statistics to the parent FileManager. - DriverFileMgr->AddStats(ScanInstance.getFileManager()); - return Result; } @@ -668,15 +665,14 @@ llvm::Error DependencyScanningWorker::computeDependencies( } static bool forEachDriverJob( - ArrayRef ArgStrs, DiagnosticsEngine &Diags, FileManager &FM, + ArrayRef ArgStrs, DiagnosticsEngine &Diags, + IntrusiveRefCntPtr FS, llvm::function_ref Callback) { SmallVector Argv; Argv.reserve(ArgStrs.size()); for (const std::string &Arg : ArgStrs) Argv.push_back(Arg.c_str()); - llvm::vfs::FileSystem *FS = &FM.getVirtualFileSystem(); - std::unique_ptr Driver = std::make_unique( Argv[0], llvm::sys::getDefaultTargetTriple(), Diags, "clang LLVM compiler", FS); @@ -686,7 +682,8 @@ static bool forEachDriverJob( bool CLMode = driver::IsClangCL( driver::getDriverMode(Argv[0], ArrayRef(Argv).slice(1))); - if (llvm::Error E = driver::expandResponseFiles(Argv, CLMode, Alloc, FS)) { + if (llvm::Error E = + driver::expandResponseFiles(Argv, CLMode, Alloc, FS.get())) { Diags.Report(diag::err_drv_expand_response_file) << llvm::toString(std::move(E)); return false; @@ -709,7 +706,7 @@ static bool forEachDriverJob( static bool createAndRunToolInvocation( std::vector CommandLine, DependencyScanningAction &Action, - FileManager &FM, + IntrusiveRefCntPtr FS, std::shared_ptr &PCHContainerOps, DiagnosticsEngine &Diags, DependencyConsumer &Consumer) { @@ -726,8 +723,8 @@ static bool createAndRunToolInvocation( return false; } - if (!Action.runInvocation(std::move(Invocation), &FM, PCHContainerOps, - Diags.getClient())) + if (!Action.runInvocation(std::move(Invocation), std::move(FS), + PCHContainerOps, Diags.getClient())) return false; std::vector Args = Action.takeLastCC1Arguments(); @@ -740,23 +737,14 @@ bool DependencyScanningWorker::scanDependencies( DependencyConsumer &Consumer, DependencyActionController &Controller, DiagnosticConsumer &DC, llvm::IntrusiveRefCntPtr FS, std::optional ModuleName) { - auto FileMgr = - llvm::makeIntrusiveRefCnt(FileSystemOptions{}, FS); - std::vector CCommandLine(CommandLine.size(), nullptr); llvm::transform(CommandLine, CCommandLine.begin(), [](const std::string &Str) { return Str.c_str(); }); auto DiagOpts = CreateAndPopulateDiagOpts(CCommandLine); sanitizeDiagOpts(*DiagOpts); - IntrusiveRefCntPtr Diags = - CompilerInstance::createDiagnostics(FileMgr->getVirtualFileSystem(), - *DiagOpts, &DC, - /*ShouldOwnClient=*/false); - - // Although `Diagnostics` are used only for command-line parsing, the - // custom `DiagConsumer` might expect a `SourceManager` to be present. - SourceManager SrcMgr(*Diags, *FileMgr); - Diags->setSourceManager(&SrcMgr); + auto Diags = CompilerInstance::createDiagnostics(*FS, *DiagOpts, &DC, + /*ShouldOwnClient=*/false); + // DisableFree is modified by Tooling for running // in-process; preserve the original value, which is // always true for a driver invocation. @@ -766,11 +754,11 @@ bool DependencyScanningWorker::scanDependencies( bool Success = false; if (CommandLine[1] == "-cc1") { - Success = createAndRunToolInvocation(CommandLine, Action, *FileMgr, + Success = createAndRunToolInvocation(CommandLine, Action, FS, PCHContainerOps, *Diags, Consumer); } else { Success = forEachDriverJob( - CommandLine, *Diags, *FileMgr, [&](const driver::Command &Cmd) { + CommandLine, *Diags, FS, [&](const driver::Command &Cmd) { if (StringRef(Cmd.getCreator().getName()) != "clang") { // Non-clang command. Just pass through to the dependency // consumer. @@ -789,7 +777,7 @@ bool DependencyScanningWorker::scanDependencies( // system to ensure that any file system requests that // are made by the driver do not go through the // dependency scanning filesystem. - return createAndRunToolInvocation(std::move(Argv), Action, *FileMgr, + return createAndRunToolInvocation(std::move(Argv), Action, FS, PCHContainerOps, *Diags, Consumer); }); } From 898f7f618c3f55b3acdafe465eaf0e89e8c29c3a Mon Sep 17 00:00:00 2001 From: Jan Svoboda Date: Mon, 21 Jul 2025 14:22:59 -0700 Subject: [PATCH 3/3] Restore disable-free suppression --- .../DependencyScanningWorker.cpp | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp index 3a80f3237b743..8ce2706cb1062 100644 --- a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp @@ -381,10 +381,10 @@ class DependencyScanningAction { DependencyScanningService &Service, StringRef WorkingDirectory, DependencyConsumer &Consumer, DependencyActionController &Controller, llvm::IntrusiveRefCntPtr DepFS, - bool DisableFree, std::optional ModuleName = std::nullopt) + std::optional ModuleName = std::nullopt) : Service(Service), WorkingDirectory(WorkingDirectory), Consumer(Consumer), Controller(Controller), DepFS(std::move(DepFS)), - DisableFree(DisableFree), ModuleName(ModuleName) {} + ModuleName(ModuleName) {} bool runInvocation(std::shared_ptr Invocation, IntrusiveRefCntPtr FS, @@ -392,8 +392,6 @@ class DependencyScanningAction { DiagnosticConsumer *DiagConsumer) { // Make a deep copy of the original Clang invocation. CompilerInvocation OriginalInvocation(*Invocation); - // Restore the value of DisableFree, which may be modified by Tooling. - OriginalInvocation.getFrontendOpts().DisableFree = DisableFree; if (any(Service.getOptimizeArgs() & ScanningOptimizations::Macros)) canonicalizeDefines(OriginalInvocation.getPreprocessorOpts()); @@ -430,6 +428,7 @@ class DependencyScanningAction { ScanInstance.getHeaderSearchOpts().BuildSessionTimestamp = Service.getBuildSessionTimestamp(); + ScanInstance.getFrontendOpts().DisableFree = false; ScanInstance.getFrontendOpts().GenerateGlobalModuleIndex = false; ScanInstance.getFrontendOpts().UseGlobalModuleIndex = false; // This will prevent us compiling individual modules asynchronously since @@ -580,7 +579,6 @@ class DependencyScanningAction { DependencyConsumer &Consumer; DependencyActionController &Controller; llvm::IntrusiveRefCntPtr DepFS; - bool DisableFree; std::optional ModuleName; std::optional ScanInstanceStorage; std::shared_ptr MDC; @@ -745,12 +743,8 @@ bool DependencyScanningWorker::scanDependencies( auto Diags = CompilerInstance::createDiagnostics(*FS, *DiagOpts, &DC, /*ShouldOwnClient=*/false); - // DisableFree is modified by Tooling for running - // in-process; preserve the original value, which is - // always true for a driver invocation. - bool DisableFree = true; DependencyScanningAction Action(Service, WorkingDirectory, Consumer, - Controller, DepFS, DisableFree, ModuleName); + Controller, DepFS, ModuleName); bool Success = false; if (CommandLine[1] == "-cc1") {