[clang] [clang-tools-extra] [clang][deps] Prefer `DiagnosticConsumer` over `llvm::{Error,Expected}` (PR #172389)
Jan Svoboda via cfe-commits
cfe-commits at lists.llvm.org
Tue Dec 16 07:57:58 PST 2025
https://github.com/jansvoboda11 updated https://github.com/llvm/llvm-project/pull/172389
>From f03aa7558c7ffe22261bc7e901633c1840bada64 Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Mon, 15 Dec 2025 16:15:10 -0800
Subject: [PATCH 1/5] [clang][deps] Prefer `DiagnosticConsumer` over
`llvm::{Error,Expected}`
---
.../DependencyScanningWorker.h | 10 --
.../clang/Tooling/DependencyScanningTool.h | 20 ++--
.../DependencyScanningWorker.cpp | 15 ---
clang/lib/Tooling/DependencyScanningTool.cpp | 39 ++++---
clang/test/ClangScanDeps/error.cpp | 6 +-
clang/tools/clang-scan-deps/ClangScanDeps.cpp | 104 ++++++------------
.../Tooling/DependencyScannerTest.cpp | 19 ++--
7 files changed, 78 insertions(+), 135 deletions(-)
diff --git a/clang/include/clang/DependencyScanning/DependencyScanningWorker.h b/clang/include/clang/DependencyScanning/DependencyScanningWorker.h
index 489fba4ed3f6b..3c5e7660a8c7b 100644
--- a/clang/include/clang/DependencyScanning/DependencyScanningWorker.h
+++ b/clang/include/clang/DependencyScanning/DependencyScanningWorker.h
@@ -107,16 +107,6 @@ class DependencyScanningWorker {
DiagnosticConsumer &DiagConsumer,
std::optional<llvm::MemoryBufferRef> TUBuffer = std::nullopt);
- /// Run the dependency scanning tool for a given clang driver command-line
- /// for a specific translation unit via file system or memory buffer.
- ///
- /// \returns A \c StringError with the diagnostic output if clang errors
- /// occurred, success otherwise.
- llvm::Error computeDependencies(
- StringRef WorkingDirectory, ArrayRef<std::string> CommandLine,
- DependencyConsumer &Consumer, DependencyActionController &Controller,
- std::optional<llvm::MemoryBufferRef> TUBuffer = std::nullopt);
-
/// The three method below implements a new interface for by name
/// dependency scanning. They together enable the dependency scanning worker
/// to more effectively perform scanning for a sequence of modules
diff --git a/clang/include/clang/Tooling/DependencyScanningTool.h b/clang/include/clang/Tooling/DependencyScanningTool.h
index e796ed648db35..c231da621e164 100644
--- a/clang/include/clang/Tooling/DependencyScanningTool.h
+++ b/clang/include/clang/Tooling/DependencyScanningTool.h
@@ -47,8 +47,9 @@ class DependencyScanningTool {
///
/// \returns A \c StringError with the diagnostic output if clang errors
/// occurred, dependency file contents otherwise.
- llvm::Expected<std::string>
- getDependencyFile(ArrayRef<std::string> CommandLine, StringRef CWD);
+ std::optional<std::string>
+ getDependencyFile(StringRef CWD, ArrayRef<std::string> CommandLine,
+ DiagnosticConsumer &DiagConsumer);
/// Collect the module dependency in P1689 format for C++20 named modules.
///
@@ -61,17 +62,19 @@ class DependencyScanningTool {
///
/// \returns A \c StringError with the diagnostic output if clang errors
/// occurred, P1689 dependency format rules otherwise.
- llvm::Expected<P1689Rule>
+ std::optional<P1689Rule>
getP1689ModuleDependencyFile(const CompileCommand &Command, StringRef CWD,
std::string &MakeformatOutput,
- std::string &MakeformatOutputPath);
- llvm::Expected<P1689Rule>
- getP1689ModuleDependencyFile(const CompileCommand &Command, StringRef CWD) {
+ std::string &MakeformatOutputPath,
+ DiagnosticConsumer &DiagConsumer);
+ std::optional<P1689Rule>
+ getP1689ModuleDependencyFile(const CompileCommand &Command, StringRef CWD,
+ DiagnosticConsumer &DiagConsumer) {
std::string MakeformatOutput;
std::string MakeformatOutputPath;
return getP1689ModuleDependencyFile(Command, CWD, MakeformatOutput,
- MakeformatOutputPath);
+ MakeformatOutputPath, DiagConsumer);
}
/// Given a Clang driver command-line for a translation unit, gather the
@@ -91,9 +94,10 @@ class DependencyScanningTool {
///
/// \returns a \c StringError with the diagnostic output if clang errors
/// occurred, \c TranslationUnitDeps otherwise.
- llvm::Expected<dependencies::TranslationUnitDeps>
+ std::optional<dependencies::TranslationUnitDeps>
getTranslationUnitDependencies(
ArrayRef<std::string> CommandLine, StringRef CWD,
+ DiagnosticConsumer &DiagConsumer,
const llvm::DenseSet<dependencies::ModuleID> &AlreadySeen,
dependencies::LookupModuleOutputCallback LookupModuleOutput,
std::optional<llvm::MemoryBufferRef> TUBuffer = std::nullopt);
diff --git a/clang/lib/DependencyScanning/DependencyScanningWorker.cpp b/clang/lib/DependencyScanning/DependencyScanningWorker.cpp
index 99fe082634524..ea2a6d67948c3 100644
--- a/clang/lib/DependencyScanning/DependencyScanningWorker.cpp
+++ b/clang/lib/DependencyScanning/DependencyScanningWorker.cpp
@@ -40,21 +40,6 @@ DependencyScanningWorker::DependencyScanningWorker(
DependencyScanningWorker::~DependencyScanningWorker() = default;
DependencyActionController::~DependencyActionController() = default;
-llvm::Error DependencyScanningWorker::computeDependencies(
- StringRef WorkingDirectory, ArrayRef<std::string> CommandLine,
- DependencyConsumer &Consumer, DependencyActionController &Controller,
- std::optional<llvm::MemoryBufferRef> TUBuffer) {
- // Capture the emitted diagnostics and report them to the client
- // in the case of a failure.
- TextDiagnosticsPrinterWithOutput DiagPrinterWithOS(CommandLine);
-
- if (computeDependencies(WorkingDirectory, CommandLine, Consumer, Controller,
- DiagPrinterWithOS.DiagPrinter, TUBuffer))
- return llvm::Error::success();
- return llvm::make_error<llvm::StringError>(
- DiagPrinterWithOS.DiagnosticsOS.str(), llvm::inconvertibleErrorCode());
-}
-
static bool forEachDriverJob(
ArrayRef<std::string> ArgStrs, DiagnosticsEngine &Diags,
IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
diff --git a/clang/lib/Tooling/DependencyScanningTool.cpp b/clang/lib/Tooling/DependencyScanningTool.cpp
index 3687db03628f4..b9ca21da359d3 100644
--- a/clang/lib/Tooling/DependencyScanningTool.cpp
+++ b/clang/lib/Tooling/DependencyScanningTool.cpp
@@ -74,23 +74,23 @@ class MakeDependencyPrinterConsumer : public DependencyConsumer {
};
} // anonymous namespace
-llvm::Expected<std::string>
-DependencyScanningTool::getDependencyFile(ArrayRef<std::string> CommandLine,
- StringRef CWD) {
- MakeDependencyPrinterConsumer Consumer;
+std::optional<std::string>
+DependencyScanningTool::getDependencyFile(StringRef CWD,
+ ArrayRef<std::string> CommandLine,
+ DiagnosticConsumer &DiagConsumer) {
+ MakeDependencyPrinterConsumer DepConsumer;
CallbackActionController Controller(nullptr);
- auto Result =
- Worker.computeDependencies(CWD, CommandLine, Consumer, Controller);
- if (Result)
- return std::move(Result);
+ if (!Worker.computeDependencies(CWD, CommandLine, DepConsumer, Controller,
+ DiagConsumer))
+ return std::nullopt;
std::string Output;
- Consumer.printDependencies(Output);
+ DepConsumer.printDependencies(Output);
return Output;
}
-llvm::Expected<P1689Rule> DependencyScanningTool::getP1689ModuleDependencyFile(
+std::optional<P1689Rule> DependencyScanningTool::getP1689ModuleDependencyFile(
const CompileCommand &Command, StringRef CWD, std::string &MakeformatOutput,
- std::string &MakeformatOutputPath) {
+ std::string &MakeformatOutputPath, DiagnosticConsumer &DiagConsumer) {
class P1689ModuleDependencyPrinterConsumer
: public MakeDependencyPrinterConsumer {
public:
@@ -132,10 +132,9 @@ llvm::Expected<P1689Rule> DependencyScanningTool::getP1689ModuleDependencyFile(
P1689Rule Rule;
P1689ModuleDependencyPrinterConsumer Consumer(Rule, Command);
P1689ActionController Controller;
- auto Result = Worker.computeDependencies(CWD, Command.CommandLine, Consumer,
- Controller);
- if (Result)
- return std::move(Result);
+ if (!Worker.computeDependencies(CWD, Command.CommandLine, Consumer,
+ Controller, DiagConsumer))
+ return std::nullopt;
MakeformatOutputPath = Consumer.getMakeFormatDependencyOutputPath();
if (!MakeformatOutputPath.empty())
@@ -143,19 +142,19 @@ llvm::Expected<P1689Rule> DependencyScanningTool::getP1689ModuleDependencyFile(
return Rule;
}
-llvm::Expected<TranslationUnitDeps>
+std::optional<TranslationUnitDeps>
DependencyScanningTool::getTranslationUnitDependencies(
ArrayRef<std::string> CommandLine, StringRef CWD,
+ DiagnosticConsumer &DiagConsumer,
const llvm::DenseSet<ModuleID> &AlreadySeen,
LookupModuleOutputCallback LookupModuleOutput,
std::optional<llvm::MemoryBufferRef> TUBuffer) {
FullDependencyConsumer Consumer(AlreadySeen);
CallbackActionController Controller(LookupModuleOutput);
- llvm::Error Result = Worker.computeDependencies(CWD, CommandLine, Consumer,
- Controller, TUBuffer);
- if (Result)
- return std::move(Result);
+ if (!Worker.computeDependencies(CWD, CommandLine, Consumer, Controller,
+ DiagConsumer, TUBuffer))
+ return std::nullopt;
return Consumer.takeTranslationUnitDeps();
}
diff --git a/clang/test/ClangScanDeps/error.cpp b/clang/test/ClangScanDeps/error.cpp
index 593dbf35edca5..03126d8812613 100644
--- a/clang/test/ClangScanDeps/error.cpp
+++ b/clang/test/ClangScanDeps/error.cpp
@@ -7,7 +7,7 @@
// RUN: not clang-scan-deps -- %clang -c %t/missing_tu.c 2>%t/missing_tu.errs
// RUN: echo EOF >> %t/missing_tu.errs
// RUN: cat %t/missing_tu.errs | sed 's:\\\\\?:/:g' | FileCheck %s --check-prefix=CHECK-MISSING-TU -DPREFIX=%/t
-// CHECK-MISSING-TU: Error while scanning dependencies for [[PREFIX]]/missing_tu.c
+// CHECK-MISSING-TU: Diagnostics while scanning dependencies for '[[PREFIX]]/missing_tu.c':
// CHECK-MISSING-TU-NEXT: error: no such file or directory: '[[PREFIX]]/missing_tu.c'
// CHECK-MISSING-TU-NEXT: error: no input files
// CHECK-MISSING-TU-NEXT: error:
@@ -16,6 +16,6 @@
// RUN: not clang-scan-deps -- %clang -c %t/missing_header.c 2>%t/missing_header.errs
// RUN: echo EOF >> %t/missing_header.errs
// RUN: cat %t/missing_header.errs | sed 's:\\\\\?:/:g' | FileCheck %s --check-prefix=CHECK-MISSING-HEADER -DPREFIX=%/t
-// CHECK-MISSING-HEADER: Error while scanning dependencies for [[PREFIX]]/missing_header.c
-// CHECK-MISSING-HEADER-NEXT: fatal error: 'missing.h' file not found
+// CHECK-MISSING-HEADER: Diagnostics while scanning dependencies for '[[PREFIX]]/missing_header.c':
+// CHECK-MISSING-HEADER-NEXT: [[PREFIX]]/missing_header.c:1:10: fatal error: 'missing.h' file not found
// CHECK-MISSING-HEADER-NEXT: EOF
diff --git a/clang/tools/clang-scan-deps/ClangScanDeps.cpp b/clang/tools/clang-scan-deps/ClangScanDeps.cpp
index 9acd0aca737ba..7a6e56214f680 100644
--- a/clang/tools/clang-scan-deps/ClangScanDeps.cpp
+++ b/clang/tools/clang-scan-deps/ClangScanDeps.cpp
@@ -325,26 +325,16 @@ class ResourceDirectoryCache {
} // end anonymous namespace
-/// Takes the result of a dependency scan and prints error / dependency files
-/// based on the result.
-///
-/// \returns True on error.
-static bool
-handleMakeDependencyToolResult(const std::string &Input,
- llvm::Expected<std::string> &MaybeFile,
- SharedStream &OS, SharedStream &Errs) {
- if (!MaybeFile) {
- llvm::handleAllErrors(
- MaybeFile.takeError(), [&Input, &Errs](llvm::StringError &Err) {
- Errs.applyLocked([&](raw_ostream &OS) {
- OS << "Error while scanning dependencies for " << Input << ":\n";
- OS << Err.getMessage();
- });
- });
- return true;
- }
- OS.applyLocked([&](raw_ostream &OS) { OS << *MaybeFile; });
- return false;
+/// Prints any diagnostics produced during a dependency scan.
+static void handleDiagnostics(StringRef Input, StringRef Diagnostics,
+ SharedStream &Errs) {
+ if (Diagnostics.empty())
+ return;
+
+ Errs.applyLocked([&](raw_ostream &OS) {
+ OS << "Diagnostics while scanning dependencies for '" << Input << "':\n";
+ OS << Diagnostics;
+ });
}
template <typename Container>
@@ -627,23 +617,6 @@ class FullDeps {
std::vector<InputDeps> Inputs;
};
-static bool handleTranslationUnitResult(
- StringRef Input, llvm::Expected<TranslationUnitDeps> &MaybeTUDeps,
- FullDeps &FD, size_t InputIndex, SharedStream &OS, SharedStream &Errs) {
- if (!MaybeTUDeps) {
- llvm::handleAllErrors(
- MaybeTUDeps.takeError(), [&Input, &Errs](llvm::StringError &Err) {
- Errs.applyLocked([&](raw_ostream &OS) {
- OS << "Error while scanning dependencies for " << Input << ":\n";
- OS << Err.getMessage();
- });
- });
- return true;
- }
- FD.mergeDeps(Input, std::move(*MaybeTUDeps), InputIndex);
- return false;
-}
-
static bool handleModuleResult(StringRef ModuleName,
llvm::Expected<TranslationUnitDeps> &MaybeTUDeps,
FullDeps &FD, size_t InputIndex,
@@ -741,24 +714,6 @@ class P1689Deps {
std::vector<P1689Rule> Rules;
};
-static bool
-handleP1689DependencyToolResult(const std::string &Input,
- llvm::Expected<P1689Rule> &MaybeRule,
- P1689Deps &PD, SharedStream &Errs) {
- if (!MaybeRule) {
- llvm::handleAllErrors(
- MaybeRule.takeError(), [&Input, &Errs](llvm::StringError &Err) {
- Errs.applyLocked([&](raw_ostream &OS) {
- OS << "Error while scanning dependencies for " << Input << ":\n";
- OS << Err.getMessage();
- });
- });
- return true;
- }
- PD.addRules(*MaybeRule);
- return false;
-}
-
/// Construct a path for the explicitly built PCM.
static std::string constructPCMPath(ModuleID MID, StringRef OutputDir) {
SmallString<256> ExplicitPCMPath(OutputDir);
@@ -1036,6 +991,12 @@ int clang_scan_deps_main(int argc, char **argv, const llvm::ToolContext &) {
std::string Filename = std::move(Input->Filename);
std::string CWD = std::move(Input->Directory);
+ std::string S;
+ llvm::raw_string_ostream OS(S);
+ DiagnosticOptions DiagOpts;
+ DiagOpts.ShowCarets = false;
+ TextDiagnosticPrinter DiagConsumer(OS, DiagOpts);
+
std::string OutputDir(ModuleFilesDir);
if (OutputDir.empty())
OutputDir = getModuleCachePath(Input->CommandLine);
@@ -1045,9 +1006,12 @@ int clang_scan_deps_main(int argc, char **argv, const llvm::ToolContext &) {
// Run the tool on it.
if (Format == ScanningOutputFormat::Make) {
- auto MaybeFile = WorkerTool.getDependencyFile(Input->CommandLine, CWD);
- if (handleMakeDependencyToolResult(Filename, MaybeFile, DependencyOS,
- Errs))
+ auto MaybeFile =
+ WorkerTool.getDependencyFile(CWD, Input->CommandLine, DiagConsumer);
+ handleDiagnostics(Filename, S, Errs);
+ if (MaybeFile)
+ DependencyOS.applyLocked([&](raw_ostream &OS) { OS << *MaybeFile; });
+ else
HadErrors = true;
} else if (Format == ScanningOutputFormat::P1689) {
// It is useful to generate the make-format dependency output during
@@ -1058,9 +1022,11 @@ int clang_scan_deps_main(int argc, char **argv, const llvm::ToolContext &) {
std::string MakeformatOutput;
auto MaybeRule = WorkerTool.getP1689ModuleDependencyFile(
- *Input, CWD, MakeformatOutput, MakeformatOutputPath);
-
- if (handleP1689DependencyToolResult(Filename, MaybeRule, PD, Errs))
+ *Input, CWD, MakeformatOutput, MakeformatOutputPath, DiagConsumer);
+ handleDiagnostics(Filename, S, Errs);
+ if (MaybeRule)
+ PD.addRules(*MaybeRule);
+ else
HadErrors = true;
if (!MakeformatOutputPath.empty() && !MakeformatOutput.empty() &&
@@ -1086,10 +1052,8 @@ int clang_scan_deps_main(int argc, char **argv, const llvm::ToolContext &) {
}
SharedStream MakeformatOS(OSIter->second);
- llvm::Expected<std::string> MaybeOutput(MakeformatOutput);
- if (handleMakeDependencyToolResult(Filename, MaybeOutput,
- MakeformatOS, Errs))
- HadErrors = true;
+ MakeformatOS.applyLocked(
+ [&](raw_ostream &OS) { OS << MakeformatOutput; });
}
} else if (ModuleNames) {
StringRef ModuleNameRef(*ModuleNames);
@@ -1150,10 +1114,12 @@ int clang_scan_deps_main(int argc, char **argv, const llvm::ToolContext &) {
Filename = TU->getBufferIdentifier();
}
auto MaybeTUDeps = WorkerTool.getTranslationUnitDependencies(
- Input->CommandLine, CWD, AlreadySeenModules, LookupOutput,
- TUBuffer);
- if (handleTranslationUnitResult(Filename, MaybeTUDeps, *FD, LocalIndex,
- DependencyOS, Errs))
+ Input->CommandLine, CWD, DiagConsumer, AlreadySeenModules,
+ LookupOutput, TUBuffer);
+ handleDiagnostics(Filename, S, Errs);
+ if (MaybeTUDeps)
+ FD->mergeDeps(Filename, *MaybeTUDeps, LocalIndex);
+ else
HadErrors = true;
}
}
diff --git a/clang/unittests/Tooling/DependencyScannerTest.cpp b/clang/unittests/Tooling/DependencyScannerTest.cpp
index da47252b37097..4efcb32020a26 100644
--- a/clang/unittests/Tooling/DependencyScannerTest.cpp
+++ b/clang/unittests/Tooling/DependencyScannerTest.cpp
@@ -235,12 +235,11 @@ TEST(DependencyScanner, ScanDepsWithFS) {
ScanningOutputFormat::Make);
DependencyScanningTool ScanTool(Service, VFS);
- std::string DepFile;
- ASSERT_THAT_ERROR(
- ScanTool.getDependencyFile(CommandLine, CWD).moveInto(DepFile),
- llvm::Succeeded());
- using llvm::sys::path::convert_to_slash;
- EXPECT_EQ(convert_to_slash(DepFile),
+ IgnoringDiagConsumer DiagConsumer;
+ std::optional<std::string> DepFile =
+ ScanTool.getDependencyFile(CWD, CommandLine, DiagConsumer);
+ ASSERT_TRUE(DepFile.has_value());
+ EXPECT_EQ(llvm::sys::path::convert_to_slash(*DepFile),
"test.cpp.o: /root/test.cpp /root/header.h\n");
}
@@ -296,10 +295,10 @@ TEST(DependencyScanner, ScanDepsWithModuleLookup) {
// 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
// unnecessarily.
- std::string DepFile;
- ASSERT_THAT_ERROR(
- ScanTool.getDependencyFile(CommandLine, CWD).moveInto(DepFile),
- llvm::Failed());
+ IgnoringDiagConsumer DiagConsumer;
+ std::optional<std::string> DepFile =
+ ScanTool.getDependencyFile(CWD, CommandLine, DiagConsumer);
+ ASSERT_FALSE(DepFile.has_value());
EXPECT_TRUE(!llvm::is_contained(InterceptFS->StatPaths, OtherPath));
EXPECT_EQ(InterceptFS->ReadFiles, std::vector<std::string>{"test.m"});
>From b6cc04aff318acdabf7b1eee2e5917f2c45bab82 Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Mon, 15 Dec 2025 16:33:51 -0800
Subject: [PATCH 2/5] Documentation
---
clang/include/clang/Tooling/DependencyScanningTool.h | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/clang/include/clang/Tooling/DependencyScanningTool.h b/clang/include/clang/Tooling/DependencyScanningTool.h
index c231da621e164..58e1cd50f5426 100644
--- a/clang/include/clang/Tooling/DependencyScanningTool.h
+++ b/clang/include/clang/Tooling/DependencyScanningTool.h
@@ -45,8 +45,8 @@ class DependencyScanningTool {
/// file format that is specified in the options (-MD is the default) and
/// return it.
///
- /// \returns A \c StringError with the diagnostic output if clang errors
- /// occurred, dependency file contents otherwise.
+ /// \returns std::nullopt if errors occurred (reported to the DiagConsumer),
+ /// dependency file contents otherwise.
std::optional<std::string>
getDependencyFile(StringRef CWD, ArrayRef<std::string> CommandLine,
DiagnosticConsumer &DiagConsumer);
@@ -60,8 +60,8 @@ class DependencyScanningTool {
/// \param MakeformatOutputPath The output parameter for the path to
/// \param MakeformatOutput.
///
- /// \returns A \c StringError with the diagnostic output if clang errors
- /// occurred, P1689 dependency format rules otherwise.
+ /// \returns std::nullopt if errors occurred (reported to the DiagConsumer),
+ /// P1689 dependency format rules otherwise.
std::optional<P1689Rule>
getP1689ModuleDependencyFile(const CompileCommand &Command, StringRef CWD,
std::string &MakeformatOutput,
@@ -92,8 +92,8 @@ class DependencyScanningTool {
/// TUBuffer is nullopt, the input should be included in the
/// Commandline already.
///
- /// \returns a \c StringError with the diagnostic output if clang errors
- /// occurred, \c TranslationUnitDeps otherwise.
+ /// \returns std::nullopt if errors occurred (reported to the DiagConsumer),
+ /// translation unit dependencies otherwise.
std::optional<dependencies::TranslationUnitDeps>
getTranslationUnitDependencies(
ArrayRef<std::string> CommandLine, StringRef CWD,
>From 377be45cf183d5fae7a1fcf3f915db87dca6a702 Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Mon, 15 Dec 2025 16:59:24 -0800
Subject: [PATCH 3/5] Revert parameter ordering change
---
clang/include/clang/Tooling/DependencyScanningTool.h | 2 +-
clang/lib/Tooling/DependencyScanningTool.cpp | 4 ++--
clang/tools/clang-scan-deps/ClangScanDeps.cpp | 2 +-
clang/unittests/Tooling/DependencyScannerTest.cpp | 4 ++--
4 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/clang/include/clang/Tooling/DependencyScanningTool.h b/clang/include/clang/Tooling/DependencyScanningTool.h
index 58e1cd50f5426..baf846bb4b8c7 100644
--- a/clang/include/clang/Tooling/DependencyScanningTool.h
+++ b/clang/include/clang/Tooling/DependencyScanningTool.h
@@ -48,7 +48,7 @@ class DependencyScanningTool {
/// \returns std::nullopt if errors occurred (reported to the DiagConsumer),
/// dependency file contents otherwise.
std::optional<std::string>
- getDependencyFile(StringRef CWD, ArrayRef<std::string> CommandLine,
+ getDependencyFile(ArrayRef<std::string> CommandLine, StringRef CWD,
DiagnosticConsumer &DiagConsumer);
/// Collect the module dependency in P1689 format for C++20 named modules.
diff --git a/clang/lib/Tooling/DependencyScanningTool.cpp b/clang/lib/Tooling/DependencyScanningTool.cpp
index b9ca21da359d3..06fa431abdbc4 100644
--- a/clang/lib/Tooling/DependencyScanningTool.cpp
+++ b/clang/lib/Tooling/DependencyScanningTool.cpp
@@ -75,8 +75,8 @@ class MakeDependencyPrinterConsumer : public DependencyConsumer {
} // anonymous namespace
std::optional<std::string>
-DependencyScanningTool::getDependencyFile(StringRef CWD,
- ArrayRef<std::string> CommandLine,
+DependencyScanningTool::getDependencyFile(ArrayRef<std::string> CommandLine,
+ StringRef CWD,
DiagnosticConsumer &DiagConsumer) {
MakeDependencyPrinterConsumer DepConsumer;
CallbackActionController Controller(nullptr);
diff --git a/clang/tools/clang-scan-deps/ClangScanDeps.cpp b/clang/tools/clang-scan-deps/ClangScanDeps.cpp
index 7a6e56214f680..256a70568a3bf 100644
--- a/clang/tools/clang-scan-deps/ClangScanDeps.cpp
+++ b/clang/tools/clang-scan-deps/ClangScanDeps.cpp
@@ -1007,7 +1007,7 @@ int clang_scan_deps_main(int argc, char **argv, const llvm::ToolContext &) {
// Run the tool on it.
if (Format == ScanningOutputFormat::Make) {
auto MaybeFile =
- WorkerTool.getDependencyFile(CWD, Input->CommandLine, DiagConsumer);
+ WorkerTool.getDependencyFile(Input->CommandLine, CWD, DiagConsumer);
handleDiagnostics(Filename, S, Errs);
if (MaybeFile)
DependencyOS.applyLocked([&](raw_ostream &OS) { OS << *MaybeFile; });
diff --git a/clang/unittests/Tooling/DependencyScannerTest.cpp b/clang/unittests/Tooling/DependencyScannerTest.cpp
index 4efcb32020a26..3fdafaa387e17 100644
--- a/clang/unittests/Tooling/DependencyScannerTest.cpp
+++ b/clang/unittests/Tooling/DependencyScannerTest.cpp
@@ -237,7 +237,7 @@ TEST(DependencyScanner, ScanDepsWithFS) {
IgnoringDiagConsumer DiagConsumer;
std::optional<std::string> DepFile =
- ScanTool.getDependencyFile(CWD, CommandLine, DiagConsumer);
+ ScanTool.getDependencyFile(CommandLine, CWD, DiagConsumer);
ASSERT_TRUE(DepFile.has_value());
EXPECT_EQ(llvm::sys::path::convert_to_slash(*DepFile),
"test.cpp.o: /root/test.cpp /root/header.h\n");
@@ -297,7 +297,7 @@ TEST(DependencyScanner, ScanDepsWithModuleLookup) {
// unnecessarily.
IgnoringDiagConsumer DiagConsumer;
std::optional<std::string> DepFile =
- ScanTool.getDependencyFile(CWD, CommandLine, DiagConsumer);
+ ScanTool.getDependencyFile(CommandLine, CWD, DiagConsumer);
ASSERT_FALSE(DepFile.has_value());
EXPECT_TRUE(!llvm::is_contained(InterceptFS->StatPaths, OtherPath));
>From c269bba3c719c3b99e5305596f734c99331a179b Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Mon, 15 Dec 2025 17:29:43 -0800
Subject: [PATCH 4/5] Don't use IgnoringDiagConsumer
---
clang/unittests/Tooling/DependencyScannerTest.cpp | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/clang/unittests/Tooling/DependencyScannerTest.cpp b/clang/unittests/Tooling/DependencyScannerTest.cpp
index 3fdafaa387e17..3874b40ff8461 100644
--- a/clang/unittests/Tooling/DependencyScannerTest.cpp
+++ b/clang/unittests/Tooling/DependencyScannerTest.cpp
@@ -14,6 +14,7 @@
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendAction.h"
#include "clang/Frontend/FrontendActions.h"
+#include "clang/Frontend/TextDiagnosticBuffer.h"
#include "clang/Tooling/CompilationDatabase.h"
#include "clang/Tooling/DependencyScanningTool.h"
#include "clang/Tooling/Tooling.h"
@@ -235,7 +236,7 @@ TEST(DependencyScanner, ScanDepsWithFS) {
ScanningOutputFormat::Make);
DependencyScanningTool ScanTool(Service, VFS);
- IgnoringDiagConsumer DiagConsumer;
+ TextDiagnosticBuffer DiagConsumer;
std::optional<std::string> DepFile =
ScanTool.getDependencyFile(CommandLine, CWD, DiagConsumer);
ASSERT_TRUE(DepFile.has_value());
@@ -295,7 +296,7 @@ TEST(DependencyScanner, ScanDepsWithModuleLookup) {
// 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
// unnecessarily.
- IgnoringDiagConsumer DiagConsumer;
+ TextDiagnosticBuffer DiagConsumer;
std::optional<std::string> DepFile =
ScanTool.getDependencyFile(CommandLine, CWD, DiagConsumer);
ASSERT_FALSE(DepFile.has_value());
>From cbaa0873f8cf445ca769ae329fa3a66d6f711543 Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Tue, 16 Dec 2025 07:57:43 -0800
Subject: [PATCH 5/5] Fix scanner usage in clangd
---
.../clangd/ScanningProjectModules.cpp | 18 ++++++++++++------
1 file changed, 12 insertions(+), 6 deletions(-)
diff --git a/clang-tools-extra/clangd/ScanningProjectModules.cpp b/clang-tools-extra/clangd/ScanningProjectModules.cpp
index e1b6cbe1ae818..860ce377be532 100644
--- a/clang-tools-extra/clangd/ScanningProjectModules.cpp
+++ b/clang-tools-extra/clangd/ScanningProjectModules.cpp
@@ -110,12 +110,18 @@ ModuleDependencyScanner::scan(PathRef FilePath,
llvm::sys::path::remove_filename(FilePathDir);
DependencyScanningTool ScanningTool(Service, TFS.view(FilePathDir));
- llvm::Expected<P1689Rule> ScanningResult =
- ScanningTool.getP1689ModuleDependencyFile(Cmd, Cmd.Directory);
-
- if (auto E = ScanningResult.takeError()) {
- elog("Scanning modules dependencies for {0} failed: {1}", FilePath,
- llvm::toString(std::move(E)));
+ std::string S;
+ llvm::raw_string_ostream OS(S);
+ DiagnosticOptions DiagOpts;
+ DiagOpts.ShowCarets = false;
+ TextDiagnosticPrinter DiagConsumer(OS, DiagOpts);
+
+ std::optional<P1689Rule> ScanningResult =
+ ScanningTool.getP1689ModuleDependencyFile(Cmd, Cmd.Directory,
+ DiagConsumer);
+
+ if (!ScanningResult) {
+ elog("Scanning modules dependencies for {0} failed: {1}", FilePath, S);
return std::nullopt;
}
More information about the cfe-commits
mailing list