https://github.com/jansvoboda11 updated https://github.com/llvm/llvm-project/pull/182063
>From a7a5e00996eb5f1c784a27d3b6747e83db19e09c Mon Sep 17 00:00:00 2001 From: Jan Svoboda <[email protected]> Date: Tue, 17 Feb 2026 21:21:35 -0800 Subject: [PATCH 1/5] [clang][deps] Don't treat the 'make' output format specially --- .../DependencyScannerImpl.h | 12 ---- .../DependencyScanning/ModuleDepCollector.h | 3 + .../clang/Tooling/DependencyScanningTool.h | 1 + .../DependencyScannerImpl.cpp | 64 ++++--------------- .../DependencyScanning/ModuleDepCollector.cpp | 7 ++ clang/lib/Tooling/DependencyScanningTool.cpp | 26 +++++--- clang/test/ClangScanDeps/modules-cc1.cpp | 2 +- .../modules-has-include-umbrella-header.c | 3 +- clang/tools/clang-scan-deps/ClangScanDeps.cpp | 4 +- .../Tooling/DependencyScannerTest.cpp | 10 +-- 10 files changed, 52 insertions(+), 80 deletions(-) diff --git a/clang/include/clang/DependencyScanning/DependencyScannerImpl.h b/clang/include/clang/DependencyScanning/DependencyScannerImpl.h index 55dcbd6fe0e9f..3a27a041755b3 100644 --- a/clang/include/clang/DependencyScanning/DependencyScannerImpl.h +++ b/clang/include/clang/DependencyScanning/DependencyScannerImpl.h @@ -114,18 +114,6 @@ getInitialStableDirs(const CompilerInstance &ScanInstance); std::optional<PrebuiltModulesAttrsMap> computePrebuiltModulesASTMap(CompilerInstance &ScanInstance, SmallVector<StringRef> &StableDirs); - -/// Create the dependency collector that will collect the produced -/// dependencies. May return the created ModuleDepCollector depending -/// on the scanning format. -std::shared_ptr<ModuleDepCollector> initializeScanInstanceDependencyCollector( - CompilerInstance &ScanInstance, - std::unique_ptr<DependencyOutputOptions> DepOutputOpts, - StringRef WorkingDirectory, DependencyConsumer &Consumer, - DependencyScanningService &Service, CompilerInvocation &Inv, - DependencyActionController &Controller, - PrebuiltModulesAttrsMap PrebuiltModulesASTMap, - llvm::SmallVector<StringRef> &StableDirs); } // namespace dependencies } // namespace clang diff --git a/clang/include/clang/DependencyScanning/ModuleDepCollector.h b/clang/include/clang/DependencyScanning/ModuleDepCollector.h index e7dd907a00381..108127fbbe523 100644 --- a/clang/include/clang/DependencyScanning/ModuleDepCollector.h +++ b/clang/include/clang/DependencyScanning/ModuleDepCollector.h @@ -228,6 +228,9 @@ class ModuleDepCollectorPP final : public PPCallbacks { void LexedFileChanged(FileID FID, LexedFileChangeReason Reason, SrcMgr::CharacteristicKind FileType, FileID PrevFID, SourceLocation Loc) override; + void HasInclude(SourceLocation Loc, StringRef FileName, bool IsAngled, + OptionalFileEntryRef File, + SrcMgr::CharacteristicKind FileType) override; void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, diff --git a/clang/include/clang/Tooling/DependencyScanningTool.h b/clang/include/clang/Tooling/DependencyScanningTool.h index c845e212ce153..c368e93fa6286 100644 --- a/clang/include/clang/Tooling/DependencyScanningTool.h +++ b/clang/include/clang/Tooling/DependencyScanningTool.h @@ -47,6 +47,7 @@ class DependencyScanningTool { /// dependency file contents otherwise. std::optional<std::string> getDependencyFile(ArrayRef<std::string> CommandLine, StringRef CWD, + dependencies::LookupModuleOutputCallback LookupModuleOutput, DiagnosticConsumer &DiagConsumer); /// Collect the module dependency in P1689 format for C++20 named modules. diff --git a/clang/lib/DependencyScanning/DependencyScannerImpl.cpp b/clang/lib/DependencyScanning/DependencyScannerImpl.cpp index 40a7d1b908a6c..f0d91a7d61c73 100644 --- a/clang/lib/DependencyScanning/DependencyScannerImpl.cpp +++ b/clang/lib/DependencyScanning/DependencyScannerImpl.cpp @@ -27,32 +27,6 @@ using namespace clang; using namespace dependencies; -namespace { -/// Forwards the gatherered dependencies to the consumer. -class DependencyConsumerForwarder : public DependencyFileGenerator { -public: - DependencyConsumerForwarder(std::unique_ptr<DependencyOutputOptions> Opts, - StringRef WorkingDirectory, DependencyConsumer &C) - : DependencyFileGenerator(*Opts), WorkingDirectory(WorkingDirectory), - Opts(std::move(Opts)), C(C) {} - - void finishedMainFile(DiagnosticsEngine &Diags) override { - C.handleDependencyOutputOpts(*Opts); - llvm::SmallString<256> CanonPath; - for (const auto &File : getDependencies()) { - CanonPath = File; - llvm::sys::path::remove_dots(CanonPath, /*remove_dot_dot=*/true); - llvm::sys::path::make_absolute(WorkingDirectory, CanonPath); - C.handleFileDependency(CanonPath); - } - } - -private: - StringRef WorkingDirectory; - std::unique_ptr<DependencyOutputOptions> Opts; - DependencyConsumer &C; -}; - static bool checkHeaderSearchPaths(const HeaderSearchOptions &HSOpts, const HeaderSearchOptions &ExistingHSOpts, DiagnosticsEngine *Diags, @@ -77,6 +51,8 @@ static bool checkHeaderSearchPaths(const HeaderSearchOptions &HSOpts, return false; } +namespace { + using PrebuiltModuleFilesT = decltype(HeaderSearchOptions::PrebuiltModuleFiles); /// A listener that collects the imported modules and the input @@ -527,31 +503,18 @@ dependencies::createDependencyOutputOptions( return Opts; } -std::shared_ptr<ModuleDepCollector> -dependencies::initializeScanInstanceDependencyCollector( +static std::shared_ptr<ModuleDepCollector> +initializeScanInstanceDependencyCollector( CompilerInstance &ScanInstance, std::unique_ptr<DependencyOutputOptions> DepOutputOpts, - StringRef WorkingDirectory, DependencyConsumer &Consumer, - DependencyScanningService &Service, CompilerInvocation &Inv, - DependencyActionController &Controller, + DependencyConsumer &Consumer, DependencyScanningService &Service, + CompilerInvocation &Inv, DependencyActionController &Controller, PrebuiltModulesAttrsMap PrebuiltModulesASTMap, - llvm::SmallVector<StringRef> &StableDirs) { - std::shared_ptr<ModuleDepCollector> MDC; - switch (Service.getOpts().Format) { - case ScanningOutputFormat::Make: - ScanInstance.addDependencyCollector( - std::make_shared<DependencyConsumerForwarder>( - std::move(DepOutputOpts), WorkingDirectory, Consumer)); - break; - case ScanningOutputFormat::P1689: - case ScanningOutputFormat::Full: - MDC = std::make_shared<ModuleDepCollector>( - Service, std::move(DepOutputOpts), ScanInstance, Consumer, Controller, - Inv, std::move(PrebuiltModulesASTMap), StableDirs); - ScanInstance.addDependencyCollector(MDC); - break; - } - + SmallVector<StringRef> &StableDirs) { + auto MDC = std::make_shared<ModuleDepCollector>( + Service, std::move(DepOutputOpts), ScanInstance, Consumer, Controller, + Inv, std::move(PrebuiltModulesASTMap), StableDirs); + ScanInstance.addDependencyCollector(MDC); return MDC; } @@ -804,9 +767,8 @@ bool DependencyScanningAction::runInvocation( auto DepOutputOpts = createDependencyOutputOptions(*OriginalInvocation); MDC = initializeScanInstanceDependencyCollector( - ScanInstance, std::move(DepOutputOpts), WorkingDirectory, Consumer, - Service, *OriginalInvocation, Controller, *MaybePrebuiltModulesASTMap, - StableDirs); + ScanInstance, std::move(DepOutputOpts), Consumer, Service, + *OriginalInvocation, Controller, *MaybePrebuiltModulesASTMap, StableDirs); if (ScanInstance.getDiagnostics().hasErrorOccurred()) return false; diff --git a/clang/lib/DependencyScanning/ModuleDepCollector.cpp b/clang/lib/DependencyScanning/ModuleDepCollector.cpp index f9bc4cc3098ef..127b26bf2e0f7 100644 --- a/clang/lib/DependencyScanning/ModuleDepCollector.cpp +++ b/clang/lib/DependencyScanning/ModuleDepCollector.cpp @@ -551,6 +551,13 @@ void ModuleDepCollectorPP::LexedFileChanged(FileID FID, MDC.addFileDep(llvm::sys::path::remove_leading_dotslash(*Filename)); } +void ModuleDepCollectorPP::HasInclude(SourceLocation Loc, StringRef FileName, + bool IsAngled, OptionalFileEntryRef File, + SrcMgr::CharacteristicKind FileType) { + if (File) + MDC.addFileDep(File->getName()); +} + void ModuleDepCollectorPP::InclusionDirective( SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File, diff --git a/clang/lib/Tooling/DependencyScanningTool.cpp b/clang/lib/Tooling/DependencyScanningTool.cpp index 1d4ab579f5827..887077b299bb6 100644 --- a/clang/lib/Tooling/DependencyScanningTool.cpp +++ b/clang/lib/Tooling/DependencyScanningTool.cpp @@ -45,7 +45,11 @@ class MakeDependencyPrinterConsumer : public DependencyConsumer { // set of deps, and handleFileDependency handles enough for implicitly // built modules to work. void handlePrebuiltModuleDependency(PrebuiltModuleDep PMD) override {} - void handleModuleDependency(ModuleDeps MD) override {} + void handleModuleDependency(ModuleDeps MD) override { + MD.forEachFileDep([this](StringRef File) { + ModuleDependencies.push_back(std::string(File)); + }); + } void handleDirectModuleDependency(ModuleID ID) override {} void handleVisibleModule(std::string ModuleName) override {} void handleContextHash(std::string Hash) override {} @@ -56,10 +60,13 @@ class MakeDependencyPrinterConsumer : public DependencyConsumer { class DependencyPrinter : public DependencyFileGenerator { public: DependencyPrinter(DependencyOutputOptions &Opts, - ArrayRef<std::string> Dependencies) - : DependencyFileGenerator(Opts) { + ArrayRef<std::string> Dependencies, + ArrayRef<std::string> ModuleDependencies) + : DependencyFileGenerator(Opts) { for (const auto &Dep : Dependencies) addDependency(Dep); + for (const auto &Dep : ModuleDependencies) + addDependency(Dep); } void printDependencies(std::string &S) { @@ -68,13 +75,14 @@ class MakeDependencyPrinterConsumer : public DependencyConsumer { } }; - DependencyPrinter Generator(*Opts, Dependencies); + DependencyPrinter Generator(*Opts, Dependencies, ModuleDependencies); Generator.printDependencies(S); } protected: std::unique_ptr<DependencyOutputOptions> Opts; std::vector<std::string> Dependencies; + std::vector<std::string> ModuleDependencies; }; } // anonymous namespace @@ -187,12 +195,12 @@ bool tooling::computeDependencies( Controller, DiagConsumer, OverlayFS); } -std::optional<std::string> -DependencyScanningTool::getDependencyFile(ArrayRef<std::string> CommandLine, - StringRef CWD, - DiagnosticConsumer &DiagConsumer) { +std::optional<std::string> DependencyScanningTool::getDependencyFile( + ArrayRef<std::string> CommandLine, StringRef CWD, + LookupModuleOutputCallback LookupModuleOutput, + DiagnosticConsumer &DiagConsumer) { MakeDependencyPrinterConsumer DepConsumer; - CallbackActionController Controller(nullptr); + CallbackActionController Controller(LookupModuleOutput); if (!computeDependencies(Worker, CWD, CommandLine, DepConsumer, Controller, DiagConsumer)) return std::nullopt; diff --git a/clang/test/ClangScanDeps/modules-cc1.cpp b/clang/test/ClangScanDeps/modules-cc1.cpp index 04a365249f379..28fc020847d56 100644 --- a/clang/test/ClangScanDeps/modules-cc1.cpp +++ b/clang/test/ClangScanDeps/modules-cc1.cpp @@ -16,7 +16,7 @@ module header1 { header "header.h" } [{ "file": "DIR/modules_cc1.cpp", "directory": "DIR", - "command": "clang -cc1 DIR/modules_cc1.cpp -fimplicit-module-maps -o modules_cc1.o" + "command": "clang -cc1 DIR/modules_cc1.cpp -fmodules -fmodules-cache-path=DIR/cache -fimplicit-module-maps -o modules_cc1.o" }] // RUN: sed "s|DIR|%/t|g" %t/cdb.json.template > %t/cdb.json diff --git a/clang/test/ClangScanDeps/modules-has-include-umbrella-header.c b/clang/test/ClangScanDeps/modules-has-include-umbrella-header.c index 022c59ca65db2..f7f804794ab41 100644 --- a/clang/test/ClangScanDeps/modules-has-include-umbrella-header.c +++ b/clang/test/ClangScanDeps/modules-has-include-umbrella-header.c @@ -65,7 +65,8 @@ module Dependency { header "dependency.h" } // CHECK-NEXT: "command-line": [ // CHECK: ], // CHECK: "file-deps": [ -// CHECK-NEXT: "[[PREFIX]]/tu.c" +// CHECK-NEXT: "[[PREFIX]]/tu.c", +// CHECK-NEXT: "[[PREFIX]]/frameworks/FW.framework/PrivateHeaders/B.h" // CHECK-NEXT: ], // CHECK-NEXT: "input-file": "[[PREFIX]]/tu.c" // CHECK-NEXT: } diff --git a/clang/tools/clang-scan-deps/ClangScanDeps.cpp b/clang/tools/clang-scan-deps/ClangScanDeps.cpp index 1d80ac519bb20..8944c5fc48e30 100644 --- a/clang/tools/clang-scan-deps/ClangScanDeps.cpp +++ b/clang/tools/clang-scan-deps/ClangScanDeps.cpp @@ -1010,8 +1010,8 @@ 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, DiagConsumer); + auto MaybeFile = WorkerTool.getDependencyFile( + Input->CommandLine, CWD, LookupOutput, 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 79fd5a312d2b9..86d4e0ee1b8c5 100644 --- a/clang/unittests/Tooling/DependencyScannerTest.cpp +++ b/clang/unittests/Tooling/DependencyScannerTest.cpp @@ -235,8 +235,9 @@ TEST(DependencyScanner, ScanDepsWithFS) { DependencyScanningTool ScanTool(Service); TextDiagnosticBuffer DiagConsumer; - std::optional<std::string> DepFile = - ScanTool.getDependencyFile(CommandLine, CWD, DiagConsumer); + std::optional<std::string> DepFile = ScanTool.getDependencyFile( + CommandLine, CWD, CallbackActionController::lookupUnreachableModuleOutput, + 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,8 +298,9 @@ TEST(DependencyScanner, ScanDepsWithModuleLookup) { // matter, the point of the test is to check that files are not read // unnecessarily. TextDiagnosticBuffer DiagConsumer; - std::optional<std::string> DepFile = - ScanTool.getDependencyFile(CommandLine, CWD, DiagConsumer); + std::optional<std::string> DepFile = ScanTool.getDependencyFile( + CommandLine, CWD, CallbackActionController::lookupUnreachableModuleOutput, + DiagConsumer); ASSERT_FALSE(DepFile.has_value()); EXPECT_TRUE(!llvm::is_contained(InterceptFS->StatPaths, OtherPath)); >From a813ae80bc05ab54d056752550ae1f334fc8558a Mon Sep 17 00:00:00 2001 From: Jan Svoboda <[email protected]> Date: Wed, 18 Feb 2026 09:04:11 -0800 Subject: [PATCH 2/5] clang-format --- clang/lib/Tooling/DependencyScanningTool.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/Tooling/DependencyScanningTool.cpp b/clang/lib/Tooling/DependencyScanningTool.cpp index 887077b299bb6..74d7be5b90ada 100644 --- a/clang/lib/Tooling/DependencyScanningTool.cpp +++ b/clang/lib/Tooling/DependencyScanningTool.cpp @@ -62,7 +62,7 @@ class MakeDependencyPrinterConsumer : public DependencyConsumer { DependencyPrinter(DependencyOutputOptions &Opts, ArrayRef<std::string> Dependencies, ArrayRef<std::string> ModuleDependencies) - : DependencyFileGenerator(Opts) { + : DependencyFileGenerator(Opts) { for (const auto &Dep : Dependencies) addDependency(Dep); for (const auto &Dep : ModuleDependencies) >From 516cebb1078b11552295e0948c0ff5140579af94 Mon Sep 17 00:00:00 2001 From: Jan Svoboda <[email protected]> Date: Mon, 16 Mar 2026 15:38:47 -0700 Subject: [PATCH 3/5] Rebase fixes --- .../clang/DependencyScanning/DependencyScannerImpl.h | 11 +++++++++++ .../lib/DependencyScanning/DependencyScannerImpl.cpp | 4 ++-- clang/lib/Tooling/DependencyScanningTool.cpp | 2 +- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/clang/include/clang/DependencyScanning/DependencyScannerImpl.h b/clang/include/clang/DependencyScanning/DependencyScannerImpl.h index 3a27a041755b3..31dcffb2f01dd 100644 --- a/clang/include/clang/DependencyScanning/DependencyScannerImpl.h +++ b/clang/include/clang/DependencyScanning/DependencyScannerImpl.h @@ -114,6 +114,17 @@ getInitialStableDirs(const CompilerInstance &ScanInstance); std::optional<PrebuiltModulesAttrsMap> computePrebuiltModulesASTMap(CompilerInstance &ScanInstance, SmallVector<StringRef> &StableDirs); + +/// Create the dependency collector that will collect the produced +/// dependencies. May return the created ModuleDepCollector depending +/// on the scanning format. +std::shared_ptr<ModuleDepCollector> initializeScanInstanceDependencyCollector( + CompilerInstance &ScanInstance, + std::unique_ptr<DependencyOutputOptions> DepOutputOpts, + DependencyConsumer &Consumer, DependencyScanningService &Service, + CompilerInvocation &Inv, DependencyActionController &Controller, + PrebuiltModulesAttrsMap PrebuiltModulesASTMap, + SmallVector<StringRef> &StableDirs); } // namespace dependencies } // namespace clang diff --git a/clang/lib/DependencyScanning/DependencyScannerImpl.cpp b/clang/lib/DependencyScanning/DependencyScannerImpl.cpp index f0d91a7d61c73..224413bb99cbc 100644 --- a/clang/lib/DependencyScanning/DependencyScannerImpl.cpp +++ b/clang/lib/DependencyScanning/DependencyScannerImpl.cpp @@ -503,8 +503,8 @@ dependencies::createDependencyOutputOptions( return Opts; } -static std::shared_ptr<ModuleDepCollector> -initializeScanInstanceDependencyCollector( +std::shared_ptr<ModuleDepCollector> +dependencies::initializeScanInstanceDependencyCollector( CompilerInstance &ScanInstance, std::unique_ptr<DependencyOutputOptions> DepOutputOpts, DependencyConsumer &Consumer, DependencyScanningService &Service, diff --git a/clang/lib/Tooling/DependencyScanningTool.cpp b/clang/lib/Tooling/DependencyScanningTool.cpp index 74d7be5b90ada..c604ef00120fa 100644 --- a/clang/lib/Tooling/DependencyScanningTool.cpp +++ b/clang/lib/Tooling/DependencyScanningTool.cpp @@ -548,7 +548,7 @@ bool CompilerInstanceWithContext::computeDependencies( }); auto MDC = initializeScanInstanceDependencyCollector( - CI, std::make_unique<DependencyOutputOptions>(*OutputOpts), CWD, Consumer, + CI, std::make_unique<DependencyOutputOptions>(*OutputOpts), Consumer, Worker.Service, /* The MDC's constructor makes a copy of the OriginalInvocation, so we can pass it in without worrying that it might be changed across >From 12609cd9079b78b1b6afef74cb49a18229127712 Mon Sep 17 00:00:00 2001 From: Jan Svoboda <[email protected]> Date: Fri, 8 May 2026 10:10:07 -0700 Subject: [PATCH 4/5] Canonicalize dot dot --- clang/lib/Tooling/DependencyScanningTool.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/clang/lib/Tooling/DependencyScanningTool.cpp b/clang/lib/Tooling/DependencyScanningTool.cpp index c604ef00120fa..2b253b90bb8c2 100644 --- a/clang/lib/Tooling/DependencyScanningTool.cpp +++ b/clang/lib/Tooling/DependencyScanningTool.cpp @@ -38,7 +38,9 @@ class MakeDependencyPrinterConsumer : public DependencyConsumer { } void handleFileDependency(StringRef File) override { - Dependencies.push_back(std::string(File)); + SmallString<128> NormalizedFile = File; + llvm::sys::path::remove_dots(NormalizedFile, /*remove_dot_dot=*/true); + Dependencies.emplace_back(NormalizedFile.str()); } // These are ignored for the make format as it can't support the full >From 2d773546a6ec0efe6640f06182ddea922cddaace Mon Sep 17 00:00:00 2001 From: Jan Svoboda <[email protected]> Date: Fri, 8 May 2026 10:25:32 -0700 Subject: [PATCH 5/5] Rename variable --- clang/lib/Tooling/DependencyScanningTool.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clang/lib/Tooling/DependencyScanningTool.cpp b/clang/lib/Tooling/DependencyScanningTool.cpp index 2b253b90bb8c2..d9d368c6ffde3 100644 --- a/clang/lib/Tooling/DependencyScanningTool.cpp +++ b/clang/lib/Tooling/DependencyScanningTool.cpp @@ -49,7 +49,7 @@ class MakeDependencyPrinterConsumer : public DependencyConsumer { void handlePrebuiltModuleDependency(PrebuiltModuleDep PMD) override {} void handleModuleDependency(ModuleDeps MD) override { MD.forEachFileDep([this](StringRef File) { - ModuleDependencies.push_back(std::string(File)); + DependenciesFromModules.push_back(std::string(File)); }); } void handleDirectModuleDependency(ModuleID ID) override {} @@ -77,14 +77,14 @@ class MakeDependencyPrinterConsumer : public DependencyConsumer { } }; - DependencyPrinter Generator(*Opts, Dependencies, ModuleDependencies); + DependencyPrinter Generator(*Opts, Dependencies, DependenciesFromModules); Generator.printDependencies(S); } protected: std::unique_ptr<DependencyOutputOptions> Opts; std::vector<std::string> Dependencies; - std::vector<std::string> ModuleDependencies; + std::vector<std::string> DependenciesFromModules; }; } // anonymous namespace _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
