https://github.com/naveen-seth updated 
https://github.com/llvm/llvm-project/pull/171238

>From 436c999cb584b966b19bca4cce79684eea7fe354 Mon Sep 17 00:00:00 2001
From: Naveen Seth Hanig <[email protected]>
Date: Tue, 9 Dec 2025 02:04:46 +0100
Subject: [PATCH 1/3] [clang][DependencyScanning] Move driver-command logic for
 by-name scanning into DependencyScanningTool

This is the second patch in a series that removes the dependency of
clangDependencyScanning on clangDriver, splitting the work
from #169964 into smaller changes (see comment linked below).

This patch updates the by-name scanning interface in
DependencyScanningWorker to accept only -cc1 command lines and moves
the logic for handling driver-style command lines into
DependencyScanningTool in clangTooling.

Support for -cc1 command lines in by-name scanning is introduced in
this patch.

The next patch will update the remaining parts of
DependencyScanningWorker to operate only on -cc1 command lines,
allowing its dependency on clangDriver to be removed.

https://github.com/llvm/llvm-project/pull/169964#pullrequestreview-3545879529
---
 .../DependencyScannerImpl.h                   |  32 ++---
 .../DependencyScanningWorker.h                |  46 +++----
 .../clang/Tooling/DependencyScanningTool.h    |  12 +-
 .../DependencyScannerImpl.cpp                 |  64 ++++------
 .../DependencyScanningWorker.cpp              |  47 ++++----
 clang/lib/Tooling/DependencyScanningTool.cpp  | 113 ++++++++++++++----
 .../ClangScanDeps/modules-full-by-mod-name.c  |  11 ++
 .../modules-full-by-mult-mod-names.c          |  11 ++
 clang/tools/clang-scan-deps/ClangScanDeps.cpp |   6 +-
 9 files changed, 205 insertions(+), 137 deletions(-)

diff --git a/clang/include/clang/DependencyScanning/DependencyScannerImpl.h 
b/clang/include/clang/DependencyScanning/DependencyScannerImpl.h
index 352a0ad44fb7f..9e23c0f87f273 100644
--- a/clang/include/clang/DependencyScanning/DependencyScannerImpl.h
+++ b/clang/include/clang/DependencyScanning/DependencyScannerImpl.h
@@ -17,6 +17,7 @@
 #include "clang/Frontend/CompilerInvocation.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
 #include "clang/Serialization/ObjectFilePCHContainerReader.h"
+#include "llvm/Support/VirtualFileSystem.h"
 
 namespace clang {
 class DiagnosticConsumer;
@@ -63,15 +64,15 @@ class DependencyScanningAction {
 std::unique_ptr<DiagnosticOptions>
 createDiagOptions(ArrayRef<std::string> CommandLine);
 
-struct DignosticsEngineWithDiagOpts {
+struct DiagnosticsEngineWithDiagOpts {
   // We need to bound the lifetime of the DiagOpts used to create the
   // DiganosticsEngine with the DiagnosticsEngine itself.
   std::unique_ptr<DiagnosticOptions> DiagOpts;
   IntrusiveRefCntPtr<DiagnosticsEngine> DiagEngine;
 
-  DignosticsEngineWithDiagOpts(ArrayRef<std::string> CommandLine,
-                               IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
-                               DiagnosticConsumer &DC);
+  DiagnosticsEngineWithDiagOpts(ArrayRef<std::string> CommandLine,
+                                IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
+                                DiagnosticConsumer &DC);
 };
 
 struct TextDiagnosticsPrinterWithOutput {
@@ -143,22 +144,11 @@ class CompilerInstanceWithContext {
   llvm::StringRef CWD;
   std::vector<std::string> CommandLine;
 
-  // Context - file systems
-  llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFS;
-
   // Context - Diagnostics engine.
-  std::unique_ptr<TextDiagnosticsPrinterWithOutput> DiagPrinterWithOS;
-  // DiagConsumer may points to DiagPrinterWithOS->DiagPrinter, or a custom
-  // DiagnosticConsumer passed in from initialize.
   DiagnosticConsumer *DiagConsumer = nullptr;
-  std::unique_ptr<DignosticsEngineWithDiagOpts> DiagEngineWithCmdAndOpts;
+  std::unique_ptr<DiagnosticsEngineWithDiagOpts> DiagEngineWithCmdAndOpts;
 
   // Context - compiler invocation
-  // Compilation's command's arguments may be owned by Alloc when expanded from
-  // response files, so we need to keep Alloc alive in the context.
-  llvm::BumpPtrAllocator Alloc;
-  std::unique_ptr<clang::driver::Driver> Driver;
-  std::unique_ptr<clang::driver::Compilation> Compilation;
   std::unique_ptr<CompilerInvocation> OriginalInvocation;
 
   // Context - output options
@@ -180,15 +170,13 @@ class CompilerInstanceWithContext {
       : Worker(Worker), CWD(CWD), CommandLine(CMD) {};
 
   // The three methods below returns false when they fail, with the detail
-  // accumulated in DiagConsumer.
-  bool initialize(DiagnosticConsumer *DC);
+  // accumulated in \c DiagEngineWithDiagOpts's diagnostic consumer.
+  bool initialize(
+      std::unique_ptr<DiagnosticsEngineWithDiagOpts> DiagEngineWithDiagOpts,
+      IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFS);
   bool computeDependencies(StringRef ModuleName, DependencyConsumer &Consumer,
                            DependencyActionController &Controller);
   bool finalize();
-
-  // The method below turns the return status from the above methods
-  // into an llvm::Error using a default DiagnosticConsumer.
-  llvm::Error handleReturnStatus(bool Success);
 };
 } // namespace dependencies
 } // namespace clang
diff --git a/clang/include/clang/DependencyScanning/DependencyScanningWorker.h 
b/clang/include/clang/DependencyScanning/DependencyScanningWorker.h
index ebd7d42786753..489fba4ed3f6b 100644
--- a/clang/include/clang/DependencyScanning/DependencyScanningWorker.h
+++ b/clang/include/clang/DependencyScanning/DependencyScanningWorker.h
@@ -12,12 +12,14 @@
 #include "clang/Basic/DiagnosticOptions.h"
 #include "clang/Basic/FileManager.h"
 #include "clang/Basic/LLVM.h"
+#include "clang/DependencyScanning/DependencyScannerImpl.h"
 #include "clang/DependencyScanning/DependencyScanningService.h"
 #include "clang/DependencyScanning/ModuleDepCollector.h"
 #include "clang/Frontend/PCHContainerOperations.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/MemoryBufferRef.h"
+#include "llvm/Support/VirtualFileSystem.h"
 #include <optional>
 #include <string>
 
@@ -119,13 +121,28 @@ class DependencyScanningWorker {
   /// dependency scanning. They together enable the dependency scanning worker
   /// to more effectively perform scanning for a sequence of modules
   /// by name when the CWD and CommandLine do not change across the queries.
+  /// The initialization function asks the client for a DiagnosticsConsumer
+  /// that it direct the diagnostics to.
 
   /// @brief Initializing the context and the compiler instance.
   /// @param CWD The current working directory used during the scan.
   /// @param CommandLine The commandline used for the scan.
-  /// @return Error if the initializaiton fails.
-  llvm::Error initializeCompilerInstanceWithContextOrError(
-      StringRef CWD, ArrayRef<std::string> CommandLine);
+  /// @return False if the initializaiton fails.
+  bool initializeCompilerInstanceWithContext(StringRef CWD,
+                                             ArrayRef<std::string> CommandLine,
+                                             DiagnosticConsumer &DC);
+
+  /// @brief Initializing the context and the compiler instance.
+  /// @param CWD The current working directory used during the scan.
+  /// @param CommandLine The commandline used for the scan.
+  /// @param DiagEngineWithCmdAndOpts Preconfigured diagnostics engine and
+  /// options associated with the cc1 command line.
+  /// @param FS The overlay file system to use for this compiler instance.
+  /// @return False if the initializaiton fails.
+  bool initializeCompilerInstanceWithContext(
+      StringRef CWD, ArrayRef<std::string> CommandLine,
+      std::unique_ptr<DiagnosticsEngineWithDiagOpts> DiagEngineWithCmdAndOpts,
+      IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFS);
 
   /// @brief Performaces dependency scanning for the module whose name is
   ///        specified.
@@ -133,28 +150,15 @@ class DependencyScanningWorker {
   ///                    scanned.
   /// @param Consumer The dependency consumer that stores the results.
   /// @param Controller The controller for the dependency scanning action.
-  /// @return Error if the scanner incurs errors.
-  llvm::Error computeDependenciesByNameWithContextOrError(
-      StringRef ModuleName, DependencyConsumer &Consumer,
-      DependencyActionController &Controller);
-
-  /// @brief Finalizes the diagnostics engine and deletes the compiler 
instance.
-  /// @return Error if errors occur during finalization.
-  llvm::Error finalizeCompilerInstanceWithContextOrError();
-
-  /// The three methods below provides the same functionality as the
-  /// three methods above. Instead of returning `llvm::Error`s, these
-  /// three methods return a flag to indicate if the call is successful.
-  /// The initialization function asks the client for a DiagnosticsConsumer
-  /// that it direct the diagnostics to.
-  bool initializeCompilerInstanceWithContext(StringRef CWD,
-                                             ArrayRef<std::string> CommandLine,
-                                             DiagnosticConsumer *DC = nullptr);
+  /// @return False if the scanner incurs errors.
   bool
   computeDependenciesByNameWithContext(StringRef ModuleName,
                                        DependencyConsumer &Consumer,
                                        DependencyActionController &Controller);
-  bool finalizeCompilerInstance();
+
+  /// @brief Finalizes the diagnostics engine and deletes the compiler 
instance.
+  /// @return False if errors occur during finalization.
+  bool finalizeCompilerInstanceWithContext();
 
   llvm::vfs::FileSystem &getVFS() const { return *DepFS; }
 
diff --git a/clang/include/clang/Tooling/DependencyScanningTool.h 
b/clang/include/clang/Tooling/DependencyScanningTool.h
index 0af07ea8ca97a..44d7a338a87f7 100644
--- a/clang/include/clang/Tooling/DependencyScanningTool.h
+++ b/clang/include/clang/Tooling/DependencyScanningTool.h
@@ -9,6 +9,7 @@
 #ifndef LLVM_CLANG_TOOLING_DEPENDENCYSCANNINGTOOL_H
 #define LLVM_CLANG_TOOLING_DEPENDENCYSCANNINGTOOL_H
 
+#include "clang/DependencyScanning/DependencyScannerImpl.h"
 #include "clang/DependencyScanning/DependencyScanningService.h"
 #include "clang/DependencyScanning/DependencyScanningUtils.h"
 #include "clang/DependencyScanning/DependencyScanningWorker.h"
@@ -119,9 +120,8 @@ class DependencyScanningTool {
   /// @param CWD The current working directory used during the scan.
   /// @param CommandLine The commandline used for the scan.
   /// @return Error if the initializaiton fails.
-  llvm::Error
-  initializeCompilerInstanceWithContext(StringRef CWD,
-                                        ArrayRef<std::string> CommandLine);
+  llvm::Error initializeCompilerInstanceWithContextOrError(
+      StringRef CWD, ArrayRef<std::string> CommandLine);
 
   /// @brief Computes the dependeny for the module named ModuleName.
   /// @param ModuleName The name of the module for which this method computes
@@ -137,8 +137,8 @@ class DependencyScanningTool {
   ///                           arguments for dependencies.
   /// @return An instance of \c TranslationUnitDeps if the scan is successful.
   ///         Otherwise it returns an error.
-  llvm::Expected<dependencies::TranslationUnitDeps>
-  computeDependenciesByNameWithContext(
+  llvm::Expected<clang::dependencies::TranslationUnitDeps>
+  computeDependenciesByNameWithContextOrError(
       StringRef ModuleName,
       const llvm::DenseSet<dependencies::ModuleID> &AlreadySeen,
       dependencies::LookupModuleOutputCallback LookupModuleOutput);
@@ -147,7 +147,7 @@ class DependencyScanningTool {
   ///        diagnostics and deletes the compiler instance. Call this method
   ///        once all names for a same commandline are scanned.
   /// @return Error if an error occured during finalization.
-  llvm::Error finalizeCompilerInstanceWithContext();
+  llvm::Error finalizeCompilerInstanceWithContextOrError();
 
   llvm::vfs::FileSystem &getWorkerVFS() const { return Worker.getVFS(); }
 
diff --git a/clang/lib/DependencyScanning/DependencyScannerImpl.cpp 
b/clang/lib/DependencyScanning/DependencyScannerImpl.cpp
index acd05cc50daa8..d379680323d22 100644
--- a/clang/lib/DependencyScanning/DependencyScannerImpl.cpp
+++ b/clang/lib/DependencyScanning/DependencyScannerImpl.cpp
@@ -13,6 +13,7 @@
 #include "clang/Driver/Driver.h"
 #include "clang/Frontend/FrontendActions.h"
 #include "llvm/ADT/ScopeExit.h"
+#include "llvm/Support/VirtualFileSystem.h"
 #include "llvm/TargetParser/Host.h"
 
 using namespace clang;
@@ -367,7 +368,7 @@ dependencies::createDiagOptions(ArrayRef<std::string> 
CommandLine) {
   return DiagOpts;
 }
 
-DignosticsEngineWithDiagOpts::DignosticsEngineWithDiagOpts(
+DiagnosticsEngineWithDiagOpts::DiagnosticsEngineWithDiagOpts(
     ArrayRef<std::string> CommandLine,
     IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS, DiagnosticConsumer &DC) {
   std::vector<const char *> CCommandLine(CommandLine.size(), nullptr);
@@ -713,38 +714,31 @@ bool DependencyScanningAction::runInvocation(
   return Result;
 }
 
-bool CompilerInstanceWithContext::initialize(DiagnosticConsumer *DC) {
-  if (DC) {
-    DiagConsumer = DC;
-  } else {
-    DiagPrinterWithOS =
-        std::make_unique<TextDiagnosticsPrinterWithOutput>(CommandLine);
-    DiagConsumer = &DiagPrinterWithOS->DiagPrinter;
+bool CompilerInstanceWithContext::initialize(
+    std::unique_ptr<DiagnosticsEngineWithDiagOpts> DiagEngineWithDiagOpts,
+    IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFS) {
+  assert(DiagEngineWithDiagOpts && "Valid diagnostics engine required!");
+  DiagEngineWithCmdAndOpts = std::move(DiagEngineWithDiagOpts);
+  DiagConsumer = DiagEngineWithCmdAndOpts->DiagEngine->getClient();
+
+  IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS = Worker.DepFS;
+  if (OverlayFS) {
+#ifndef NDEBUG
+    bool SawDepFS = false;
+    OverlayFS->visit([&](llvm::vfs::FileSystem &VFS) {
+      SawDepFS |= &VFS == Worker.DepFS.get();
+    });
+    assert(SawDepFS && "OverlayFS not based on DepFS");
+#endif
+    FS = std::move(OverlayFS);
   }
 
-  std::tie(OverlayFS, CommandLine) = initVFSForByNameScanning(
-      Worker.DepFS, CommandLine, CWD, "ScanningByName");
-
-  DiagEngineWithCmdAndOpts = std::make_unique<DignosticsEngineWithDiagOpts>(
-      CommandLine, OverlayFS, *DiagConsumer);
-
-  std::tie(Driver, Compilation) = buildCompilation(
-      CommandLine, *DiagEngineWithCmdAndOpts->DiagEngine, OverlayFS, Alloc);
-
-  if (!Compilation)
-    return false;
+  // Reset what might have been modified in the previous worker invocation.
+  FS->setCurrentWorkingDirectory(CWD);
 
-  assert(Compilation->getJobs().size() &&
-         "Must have a job list of non-zero size");
-  const driver::Command &Command = *(Compilation->getJobs().begin());
-  const auto &CommandArgs = Command.getArguments();
-  assert(!CommandArgs.empty() && "Cannot have a command with 0 args");
-  assert(StringRef(CommandArgs[0]) == "-cc1" && "Requires a cc1 job.");
-  OriginalInvocation = std::make_unique<CompilerInvocation>();
-
-  if (!CompilerInvocation::CreateFromArgs(*OriginalInvocation, CommandArgs,
-                                          
*DiagEngineWithCmdAndOpts->DiagEngine,
-                                          Command.getExecutable())) {
+  OriginalInvocation = createCompilerInvocation(
+      CommandLine, *DiagEngineWithCmdAndOpts->DiagEngine);
+  if (!OriginalInvocation) {
     DiagEngineWithCmdAndOpts->DiagEngine->Report(
         diag::err_fe_expected_compiler_job)
         << llvm::join(CommandLine, " ");
@@ -763,7 +757,7 @@ bool 
CompilerInstanceWithContext::initialize(DiagnosticConsumer *DC) {
   auto &CI = *CIPtr;
 
   if (!initializeScanCompilerInstance(
-          CI, OverlayFS, DiagEngineWithCmdAndOpts->DiagEngine->getClient(),
+          CI, FS, DiagEngineWithCmdAndOpts->DiagEngine->getClient(),
           Worker.Service, Worker.DepFS))
     return false;
 
@@ -876,11 +870,3 @@ bool CompilerInstanceWithContext::finalize() {
   DiagConsumer->finish();
   return true;
 }
-
-llvm::Error CompilerInstanceWithContext::handleReturnStatus(bool Success) {
-  assert(DiagPrinterWithOS && "Must use the default DiagnosticConsumer.");
-  return Success ? llvm::Error::success()
-                 : llvm::make_error<llvm::StringError>(
-                       DiagPrinterWithOS->DiagnosticsOS.str(),
-                       llvm::inconvertibleErrorCode());
-}
diff --git a/clang/lib/DependencyScanning/DependencyScanningWorker.cpp 
b/clang/lib/DependencyScanning/DependencyScanningWorker.cpp
index 7b03abd8e3138..ef16b14e7cc6e 100644
--- a/clang/lib/DependencyScanning/DependencyScanningWorker.cpp
+++ b/clang/lib/DependencyScanning/DependencyScanningWorker.cpp
@@ -7,10 +7,13 @@
 
//===----------------------------------------------------------------------===//
 
 #include "clang/DependencyScanning/DependencyScanningWorker.h"
+#include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/DiagnosticFrontend.h"
 #include "clang/DependencyScanning/DependencyScannerImpl.h"
 #include "clang/Driver/Driver.h"
 #include "clang/Driver/Tool.h"
+#include "clang/Serialization/ObjectFilePCHContainerReader.h"
+#include "llvm/Support/VirtualFileSystem.h"
 
 using namespace clang;
 using namespace dependencies;
@@ -100,7 +103,7 @@ bool DependencyScanningWorker::scanDependencies(
     FS = std::move(OverlayFS);
   }
 
-  DignosticsEngineWithDiagOpts DiagEngineWithCmdAndOpts(CommandLine, FS, DC);
+  DiagnosticsEngineWithDiagOpts DiagEngineWithCmdAndOpts(CommandLine, FS, DC);
   DependencyScanningAction Action(Service, WorkingDirectory, Consumer,
                                   Controller, DepFS);
 
@@ -165,33 +168,29 @@ bool DependencyScanningWorker::computeDependencies(
                           DC);
 }
 
-llvm::Error
-DependencyScanningWorker::initializeCompilerInstanceWithContextOrError(
-    StringRef CWD, ArrayRef<std::string> CommandLine) {
-  bool Success = initializeCompilerInstanceWithContext(CWD, CommandLine);
-  return CIWithContext->handleReturnStatus(Success);
-}
-
-llvm::Error
-DependencyScanningWorker::computeDependenciesByNameWithContextOrError(
-    StringRef ModuleName, DependencyConsumer &Consumer,
-    DependencyActionController &Controller) {
-  bool Success =
-      computeDependenciesByNameWithContext(ModuleName, Consumer, Controller);
-  return CIWithContext->handleReturnStatus(Success);
-}
-
-llvm::Error
-DependencyScanningWorker::finalizeCompilerInstanceWithContextOrError() {
-  bool Success = finalizeCompilerInstance();
-  return CIWithContext->handleReturnStatus(Success);
+bool DependencyScanningWorker::initializeCompilerInstanceWithContext(
+    StringRef CWD, ArrayRef<std::string> CommandLine, DiagnosticConsumer &DC) {
+  auto OverlayFSAndArgs =
+      initVFSForByNameScanning(DepFS, CommandLine, CWD, "ScanningByName");
+  auto &OverlayFS = OverlayFSAndArgs.first;
+  const auto &ModifiedCommandLine = OverlayFSAndArgs.second;
+
+  auto DiagEngineWithCmdAndOpts =
+      std::make_unique<DiagnosticsEngineWithDiagOpts>(ModifiedCommandLine,
+                                                      OverlayFS, DC);
+
+  return initializeCompilerInstanceWithContext(
+      CWD, ModifiedCommandLine, std::move(DiagEngineWithCmdAndOpts), 
OverlayFS);
 }
 
 bool DependencyScanningWorker::initializeCompilerInstanceWithContext(
-    StringRef CWD, ArrayRef<std::string> CommandLine, DiagnosticConsumer *DC) {
+    StringRef CWD, ArrayRef<std::string> CommandLine,
+    std::unique_ptr<DiagnosticsEngineWithDiagOpts> DiagEngineWithDiagOpts,
+    IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFS) {
   CIWithContext =
       std::make_unique<CompilerInstanceWithContext>(*this, CWD, CommandLine);
-  return CIWithContext->initialize(DC);
+  return CIWithContext->initialize(std::move(DiagEngineWithDiagOpts),
+                                   OverlayFS);
 }
 
 bool DependencyScanningWorker::computeDependenciesByNameWithContext(
@@ -201,6 +200,6 @@ bool 
DependencyScanningWorker::computeDependenciesByNameWithContext(
   return CIWithContext->computeDependencies(ModuleName, Consumer, Controller);
 }
 
-bool DependencyScanningWorker::finalizeCompilerInstance() {
+bool DependencyScanningWorker::finalizeCompilerInstanceWithContext() {
   return CIWithContext->finalize();
 }
diff --git a/clang/lib/Tooling/DependencyScanningTool.cpp 
b/clang/lib/Tooling/DependencyScanningTool.cpp
index 9c0b095705d49..e138aa20da964 100644
--- a/clang/lib/Tooling/DependencyScanningTool.cpp
+++ b/clang/lib/Tooling/DependencyScanningTool.cpp
@@ -7,6 +7,9 @@
 
//===----------------------------------------------------------------------===//
 
 #include "clang/Tooling/DependencyScanningTool.h"
+#include "clang/Basic/DiagnosticFrontend.h"
+#include "clang/DependencyScanning/DependencyScannerImpl.h"
+#include "clang/Driver/Tool.h"
 #include "clang/Frontend/Utils.h"
 #include <optional>
 
@@ -161,43 +164,109 @@ DependencyScanningTool::getModuleDependencies(
     StringRef ModuleName, ArrayRef<std::string> CommandLine, StringRef CWD,
     const llvm::DenseSet<ModuleID> &AlreadySeen,
     LookupModuleOutputCallback LookupModuleOutput) {
-  FullDependencyConsumer Consumer(AlreadySeen);
-  CallbackActionController Controller(LookupModuleOutput);
   if (auto Error =
-          Worker.initializeCompilerInstanceWithContextOrError(CWD, 
CommandLine))
-    return std::move(Error);
+          initializeCompilerInstanceWithContextOrError(CWD, CommandLine))
+    return Error;
 
-  auto Result = Worker.computeDependenciesByNameWithContextOrError(
-      ModuleName, Consumer, Controller);
+  auto Result = computeDependenciesByNameWithContextOrError(
+      ModuleName, AlreadySeen, LookupModuleOutput);
 
-  if (auto Error = Worker.finalizeCompilerInstanceWithContextOrError())
-    return std::move(Error);
+  if (auto Error = finalizeCompilerInstanceWithContextOrError())
+    return Error;
 
-  if (Result)
-    return std::move(Result);
+  return Result;
+}
 
-  return Consumer.takeTranslationUnitDeps();
+/// Constructs the full -cc1 command line, including executable, for the given
+/// driver \c Cmd.
+static std::vector<std::string>
+buildCC1CommandLine(const driver::Command &Cmd) {
+  const auto &Args = Cmd.getArguments();
+  std::vector<std::string> Out;
+  Out.reserve(Args.size() + 1);
+  Out.emplace_back(Cmd.getExecutable());
+  llvm::append_range(Out, Args);
+  return Out;
 }
 
-llvm::Error DependencyScanningTool::initializeCompilerInstanceWithContext(
+static std::optional<std::vector<std::string>> getFirstCC1CommandLine(
+    ArrayRef<std::string> CommandLine, DiagnosticsEngine &Diags,
+    llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> ScanFS) {
+  // Compilation holds a non-owning a reference to the Driver, hence we need to
+  // keep the Driver alive when we use Compilation. Arguments to commands may 
be
+  // owned by Alloc when expanded from response files.
+  llvm::BumpPtrAllocator Alloc;
+  const auto [Driver, Compilation] =
+      buildCompilation(CommandLine, Diags, ScanFS, Alloc);
+  if (!Compilation)
+    return std::nullopt;
+
+  const auto IsClangCmd = [](const driver::Command &Cmd) {
+    return StringRef(Cmd.getCreator().getName()) == "clang";
+  };
+  const auto CC1CommandLineRange = llvm::map_range(
+      llvm::make_filter_range(Compilation->getJobs(), IsClangCmd),
+      buildCC1CommandLine);
+
+  if (CC1CommandLineRange.empty())
+    return std::nullopt;
+  return *CC1CommandLineRange.begin();
+}
+
+static llvm::Error makeErrorFromDiagnosticsOS(
+    TextDiagnosticsPrinterWithOutput &DiagPrinterWithOS) {
+  return llvm::make_error<llvm::StringError>(
+      DiagPrinterWithOS.DiagnosticsOS.str(), llvm::inconvertibleErrorCode());
+}
+
+llvm::Error
+DependencyScanningTool::initializeCompilerInstanceWithContextOrError(
     StringRef CWD, ArrayRef<std::string> CommandLine) {
-  return Worker.initializeCompilerInstanceWithContextOrError(CWD, CommandLine);
+  DiagPrinterWithOS =
+      std::make_unique<TextDiagnosticsPrinterWithOutput>(CommandLine);
+
+  if (CommandLine.size() >= 2 && CommandLine[1] == "-cc1") {
+    if (Worker.initializeCompilerInstanceWithContext(
+            CWD, CommandLine, DiagPrinterWithOS->DiagPrinter))
+      return llvm::Error::success();
+    return makeErrorFromDiagnosticsOS(*DiagPrinterWithOS);
+  }
+
+  auto OverlayFSAndArgs = initVFSForByNameScanning(
+      &Worker.getVFS(), CommandLine, CWD, "ScanningByName");
+  auto &OverlayFS = OverlayFSAndArgs.first;
+  const auto &ModifiedCommandLine = OverlayFSAndArgs.second;
+
+  auto DiagEngineWithCmdAndOpts =
+      std::make_unique<DiagnosticsEngineWithDiagOpts>(
+          ModifiedCommandLine, OverlayFS, DiagPrinterWithOS->DiagPrinter);
+
+  const auto MaybeFirstCC1 = getFirstCC1CommandLine(
+      ModifiedCommandLine, *DiagEngineWithCmdAndOpts->DiagEngine, OverlayFS);
+  if (!MaybeFirstCC1)
+    return makeErrorFromDiagnosticsOS(*DiagPrinterWithOS);
+
+  if (Worker.initializeCompilerInstanceWithContext(
+          CWD, *MaybeFirstCC1, std::move(DiagEngineWithCmdAndOpts), OverlayFS))
+    return llvm::Error::success();
+  return makeErrorFromDiagnosticsOS(*DiagPrinterWithOS);
 }
 
 llvm::Expected<TranslationUnitDeps>
-DependencyScanningTool::computeDependenciesByNameWithContext(
+DependencyScanningTool::computeDependenciesByNameWithContextOrError(
     StringRef ModuleName, const llvm::DenseSet<ModuleID> &AlreadySeen,
     LookupModuleOutputCallback LookupModuleOutput) {
   FullDependencyConsumer Consumer(AlreadySeen);
   CallbackActionController Controller(LookupModuleOutput);
-  llvm::Error Result = Worker.computeDependenciesByNameWithContextOrError(
-      ModuleName, Consumer, Controller);
-  if (Result)
-    return std::move(Result);
-
-  return Consumer.takeTranslationUnitDeps();
+  if (Worker.computeDependenciesByNameWithContext(ModuleName, Consumer,
+                                                  Controller))
+    return Consumer.takeTranslationUnitDeps();
+  return makeErrorFromDiagnosticsOS(*DiagPrinterWithOS);
 }
 
-llvm::Error DependencyScanningTool::finalizeCompilerInstanceWithContext() {
-  return Worker.finalizeCompilerInstanceWithContextOrError();
+llvm::Error
+DependencyScanningTool::finalizeCompilerInstanceWithContextOrError() {
+  if (Worker.finalizeCompilerInstanceWithContext())
+    return llvm::Error::success();
+  return makeErrorFromDiagnosticsOS(*DiagPrinterWithOS);
 }
diff --git a/clang/test/ClangScanDeps/modules-full-by-mod-name.c 
b/clang/test/ClangScanDeps/modules-full-by-mod-name.c
index edb99636aaf25..2d2c9acd30011 100644
--- a/clang/test/ClangScanDeps/modules-full-by-mod-name.c
+++ b/clang/test/ClangScanDeps/modules-full-by-mod-name.c
@@ -28,6 +28,17 @@ module transitive { header "transitive.h" }
 // RUN: clang-scan-deps -compilation-database %t/cdb.json -format 
experimental-full -module-names=root > %t/result.json
 // RUN: cat %t/result.json | sed 's:\\\\\?:/:g' | FileCheck -DPREFIX=%/t %s
 
+//--- cdb.cc1.json.template
+[{
+  "file": "",
+  "directory": "DIR",
+  "command": "clang -cc1 -fmodules -fimplicit-module-maps 
-fmodules-cache-path=DIR/cache -I DIR -x c"
+}]
+
+// RUN: sed "s|DIR|%/t|g" %t/cdb.cc1.json.template > %t/cdb.cc1.json
+// RUN: clang-scan-deps -compilation-database %t/cdb.cc1.json -format 
experimental-full -module-names=root > %t/result.cc1.json
+// RUN: cat %t/result.cc1.json | sed 's:\\\\\?:/:g' | FileCheck -DPREFIX=%/t %s
+
 // CHECK:      {
 // CHECK-NEXT:   "modules": [
 // CHECK-NEXT:     {
diff --git a/clang/test/ClangScanDeps/modules-full-by-mult-mod-names.c 
b/clang/test/ClangScanDeps/modules-full-by-mult-mod-names.c
index 030f7f3427810..fdfd7b1e45d5d 100644
--- a/clang/test/ClangScanDeps/modules-full-by-mult-mod-names.c
+++ b/clang/test/ClangScanDeps/modules-full-by-mult-mod-names.c
@@ -33,6 +33,17 @@ module root1 { header "root1.h"}
 // RUN: clang-scan-deps -compilation-database %t/cdb.json -format 
experimental-full -module-names=root,root1,direct > %t/result.json
 // RUN: cat %t/result.json | sed 's:\\\\\?:/:g' | FileCheck -DPREFIX=%/t %s
 
+//--- cdb.cc1.json.template
+[{
+  "file": "",
+  "directory": "DIR",
+  "command": "clang -cc1 -fmodules -fimplicit-module-maps 
-fmodules-cache-path=DIR/cache -I DIR -x c"
+}]
+
+// RUN: sed "s|DIR|%/t|g" %t/cdb.cc1.json.template > %t/cdb.cc1.json
+// RUN: clang-scan-deps -compilation-database %t/cdb.cc1.json -format 
experimental-full -module-names=root,root1,direct > %t/result.cc1.json
+// RUN: cat %t/result.cc1.json | sed 's:\\\\\?:/:g' | FileCheck -DPREFIX=%/t %s
+
 // CHECK:      {
 // CHECK-NEXT:   "modules": [
 // CHECK-NEXT:     {
diff --git a/clang/tools/clang-scan-deps/ClangScanDeps.cpp 
b/clang/tools/clang-scan-deps/ClangScanDeps.cpp
index 07157ae2dc06a..9acd0aca737ba 100644
--- a/clang/tools/clang-scan-deps/ClangScanDeps.cpp
+++ b/clang/tools/clang-scan-deps/ClangScanDeps.cpp
@@ -1105,7 +1105,7 @@ int clang_scan_deps_main(int argc, char **argv, const 
llvm::ToolContext &) {
             HadErrors = true;
         } else {
           if (llvm::Error Err =
-                  WorkerTool.initializeCompilerInstanceWithContext(
+                  WorkerTool.initializeCompilerInstanceWithContextOrError(
                       CWD, Input->CommandLine)) {
             handleErrorWithInfoString(
                 "Compiler instance with context setup error", std::move(Err),
@@ -1116,7 +1116,7 @@ int clang_scan_deps_main(int argc, char **argv, const 
llvm::ToolContext &) {
 
           for (auto N : Names) {
             auto MaybeModuleDepsGraph =
-                WorkerTool.computeDependenciesByNameWithContext(
+                WorkerTool.computeDependenciesByNameWithContextOrError(
                     N, AlreadySeenModules, LookupOutput);
             if (handleModuleResult(N, MaybeModuleDepsGraph, *FD, LocalIndex,
                                    DependencyOS, Errs)) {
@@ -1126,7 +1126,7 @@ int clang_scan_deps_main(int argc, char **argv, const 
llvm::ToolContext &) {
           }
 
           if (llvm::Error Err =
-                  WorkerTool.finalizeCompilerInstanceWithContext()) {
+                  WorkerTool.finalizeCompilerInstanceWithContextOrError()) {
             handleErrorWithInfoString(
                 "Compiler instance with context finialization error",
                 std::move(Err), DependencyOS, Errs);

>From c3a23a41b18f7224850945e9fb241ceb27aa78a4 Mon Sep 17 00:00:00 2001
From: Naveen Seth Hanig <[email protected]>
Date: Tue, 9 Dec 2025 20:20:30 +0100
Subject: [PATCH 2/3] Simplify getFirstCC1CommandLine

---
 clang/lib/Tooling/DependencyScanningTool.cpp | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/clang/lib/Tooling/DependencyScanningTool.cpp 
b/clang/lib/Tooling/DependencyScanningTool.cpp
index e138aa20da964..5265bcc537752 100644
--- a/clang/lib/Tooling/DependencyScanningTool.cpp
+++ b/clang/lib/Tooling/DependencyScanningTool.cpp
@@ -204,13 +204,11 @@ static std::optional<std::vector<std::string>> 
getFirstCC1CommandLine(
   const auto IsClangCmd = [](const driver::Command &Cmd) {
     return StringRef(Cmd.getCreator().getName()) == "clang";
   };
-  const auto CC1CommandLineRange = llvm::map_range(
-      llvm::make_filter_range(Compilation->getJobs(), IsClangCmd),
-      buildCC1CommandLine);
 
-  if (CC1CommandLineRange.empty())
-    return std::nullopt;
-  return *CC1CommandLineRange.begin();
+  const auto &Jobs = Compilation->getJobs();
+  if (const auto It = llvm::find_if(Jobs, IsClangCmd); It != Jobs.end())
+    return buildCC1CommandLine(*It);
+  return std::nullopt;
 }
 
 static llvm::Error makeErrorFromDiagnosticsOS(

>From 99838242e9b803830854e15100b3143548bd86a7 Mon Sep 17 00:00:00 2001
From: Naveen Seth Hanig <[email protected]>
Date: Tue, 9 Dec 2025 20:21:11 +0100
Subject: [PATCH 3/3] Remove unnecessary namespace qualifier

---
 clang/include/clang/Tooling/DependencyScanningTool.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/include/clang/Tooling/DependencyScanningTool.h 
b/clang/include/clang/Tooling/DependencyScanningTool.h
index 44d7a338a87f7..e796ed648db35 100644
--- a/clang/include/clang/Tooling/DependencyScanningTool.h
+++ b/clang/include/clang/Tooling/DependencyScanningTool.h
@@ -137,7 +137,7 @@ class DependencyScanningTool {
   ///                           arguments for dependencies.
   /// @return An instance of \c TranslationUnitDeps if the scan is successful.
   ///         Otherwise it returns an error.
-  llvm::Expected<clang::dependencies::TranslationUnitDeps>
+  llvm::Expected<dependencies::TranslationUnitDeps>
   computeDependenciesByNameWithContextOrError(
       StringRef ModuleName,
       const llvm::DenseSet<dependencies::ModuleID> &AlreadySeen,

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to