https://github.com/jansvoboda11 updated https://github.com/llvm/llvm-project/pull/182063
>From a4bd1e4234e3c2ef81d1fe01ac78ba7163ec4e8b Mon Sep 17 00:00:00 2001 From: Jan Svoboda <[email protected]> Date: Tue, 17 Feb 2026 21:21:35 -0800 Subject: [PATCH 1/2] [clang][deps] Don't treat the 'make' output format specially --- .../DependencyScannerImpl.h | 12 ---- .../DependencyScanning/ModuleDepCollector.h | 3 + .../clang/Tooling/DependencyScanningTool.h | 1 + .../DependencyScannerImpl.cpp | 66 ++++--------------- .../DependencyScanning/ModuleDepCollector.cpp | 12 ++-- 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, 54 insertions(+), 85 deletions(-) diff --git a/clang/include/clang/DependencyScanning/DependencyScannerImpl.h b/clang/include/clang/DependencyScanning/DependencyScannerImpl.h index d50371512667d..3d55759d60d83 100644 --- a/clang/include/clang/DependencyScanning/DependencyScannerImpl.h +++ b/clang/include/clang/DependencyScanning/DependencyScannerImpl.h @@ -106,18 +106,6 @@ 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); - class CompilerInstanceWithContext { // Context DependencyScanningWorker &Worker; diff --git a/clang/include/clang/DependencyScanning/ModuleDepCollector.h b/clang/include/clang/DependencyScanning/ModuleDepCollector.h index 8f665daf03c69..2a581d72274f1 100644 --- a/clang/include/clang/DependencyScanning/ModuleDepCollector.h +++ b/clang/include/clang/DependencyScanning/ModuleDepCollector.h @@ -225,6 +225,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 96d21866dd7f9..5a94025191513 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 861e6e0042265..8d580012aae78 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 @@ createDependencyOutputOptions(const CompilerInvocation &Invocation) { 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; } @@ -790,9 +753,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); std::unique_ptr<FrontendAction> Action; @@ -901,7 +863,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 diff --git a/clang/lib/DependencyScanning/ModuleDepCollector.cpp b/clang/lib/DependencyScanning/ModuleDepCollector.cpp index 46a0f79bfd38e..ef56c894657e6 100644 --- a/clang/lib/DependencyScanning/ModuleDepCollector.cpp +++ b/clang/lib/DependencyScanning/ModuleDepCollector.cpp @@ -549,6 +549,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, @@ -950,12 +957,9 @@ void ModuleDepCollector::addVisibleModules() { static StringRef makeAbsoluteAndPreferred(CompilerInstance &CI, StringRef Path, SmallVectorImpl<char> &Storage) { - if (llvm::sys::path::is_absolute(Path) && - !llvm::sys::path::is_style_windows(llvm::sys::path::Style::native)) - return Path; Storage.assign(Path.begin(), Path.end()); CI.getFileManager().makeAbsolutePath(Storage); - llvm::sys::path::make_preferred(Storage); + llvm::sys::path::remove_dots(Storage, /*remove_dot_dot=*/true); return StringRef(Storage.data(), Storage.size()); } diff --git a/clang/lib/Tooling/DependencyScanningTool.cpp b/clang/lib/Tooling/DependencyScanningTool.cpp index 2ae149e8fb2cf..56f4e56fd13a1 100644 --- a/clang/lib/Tooling/DependencyScanningTool.cpp +++ b/clang/lib/Tooling/DependencyScanningTool.cpp @@ -40,7 +40,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 {} @@ -51,10 +55,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) { @@ -63,13 +70,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 @@ -182,12 +190,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 30fb8d47f8d5d..7f909ae34e595 100644 --- a/clang/tools/clang-scan-deps/ClangScanDeps.cpp +++ b/clang/tools/clang-scan-deps/ClangScanDeps.cpp @@ -1009,8 +1009,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 de42f7769b6208108493ff7cfdbeff5d55ae0e35 Mon Sep 17 00:00:00 2001 From: Jan Svoboda <[email protected]> Date: Wed, 18 Feb 2026 09:04:11 -0800 Subject: [PATCH 2/2] 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 56f4e56fd13a1..082417eba3b20 100644 --- a/clang/lib/Tooling/DependencyScanningTool.cpp +++ b/clang/lib/Tooling/DependencyScanningTool.cpp @@ -57,7 +57,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) _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
