[clang] [clang][scan-deps] Report a scanned TU's visible modules (PR #147969)
Cyndy Ishida via cfe-commits
cfe-commits at lists.llvm.org
Thu Jul 10 07:03:23 PDT 2025
https://github.com/cyndyishida created https://github.com/llvm/llvm-project/pull/147969
Clients of the dependency scanning service may need to add dependencies based on the visibility of top-level modules, for example, when determining whether a Swift overlay dependency should be brought in based on whether there's a corresponding **visible** clang module for it.
This patch introduces a new field `VisibleModules` that contains all the visible top-level modules in a given TU.
Because visibility is determined by which headers or (sub)modules were imported, and not top-level module dependencies, the scanner now performs a separate DFS starting from what was directly imported for this computation.
In my local performance testing, there was no observable performance impact.
resolves: rdar://151416358
>From 7688e348f6da6f71f9c929ca9cfb7e68af8a421a Mon Sep 17 00:00:00 2001
From: Cyndy Ishida <cyndy_ishida at apple.com>
Date: Wed, 9 Jul 2025 21:50:44 -0700
Subject: [PATCH 1/2] [clang][scan-deps] Report a scanned TU's visible modules
---
.../DependencyScanningTool.h | 9 +++
.../DependencyScanningWorker.h | 2 +
.../DependencyScanning/ModuleDepCollector.h | 8 +++
.../DependencyScanningTool.cpp | 2 +
.../DependencyScanning/ModuleDepCollector.cpp | 31 +++++++-
clang/test/ClangScanDeps/visible-modules.c | 72 +++++++++++++++++++
clang/tools/clang-scan-deps/ClangScanDeps.cpp | 14 ++++
7 files changed, 137 insertions(+), 1 deletion(-)
create mode 100644 clang/test/ClangScanDeps/visible-modules.c
diff --git a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h
index ee24e5d1543d3..14de81a5ff2b6 100644
--- a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h
+++ b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h
@@ -57,6 +57,10 @@ struct TranslationUnitDeps {
/// determined that the differences are benign for this compilation.
std::vector<ModuleID> ClangModuleDeps;
+ /// A list of module names that are visible to this translation unit. This
+ /// includes both direct and transitive module dependencies.
+ std::vector<std::string> VisibleModules;
+
/// A list of the C++20 named modules this translation unit depends on.
std::vector<std::string> NamedModuleDeps;
@@ -188,6 +192,10 @@ class FullDependencyConsumer : public DependencyConsumer {
DirectModuleDeps.push_back(ID);
}
+ void handleVisibleModule(std::string ModuleName) override {
+ VisibleModules.push_back(ModuleName);
+ }
+
void handleContextHash(std::string Hash) override {
ContextHash = std::move(Hash);
}
@@ -210,6 +218,7 @@ class FullDependencyConsumer : public DependencyConsumer {
std::string ModuleName;
std::vector<std::string> NamedModuleDeps;
std::vector<ModuleID> DirectModuleDeps;
+ std::vector<std::string> VisibleModules;
std::vector<Command> Commands;
std::string ContextHash;
std::vector<std::string> OutputPaths;
diff --git a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h
index 3e232c79397ce..6060e4b43312e 100644
--- a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h
+++ b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h
@@ -59,6 +59,8 @@ class DependencyConsumer {
virtual void handleDirectModuleDependency(ModuleID MD) = 0;
+ virtual void handleVisibleModule(std::string ModuleName) = 0;
+
virtual void handleContextHash(std::string Hash) = 0;
};
diff --git a/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h b/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h
index e96c49883d3c6..4136cb73f7043 100644
--- a/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h
+++ b/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h
@@ -323,6 +323,11 @@ class ModuleDepCollector final : public DependencyCollector {
llvm::MapVector<const Module *, PrebuiltModuleDep> DirectPrebuiltModularDeps;
/// Working set of direct modular dependencies.
llvm::SetVector<const Module *> DirectModularDeps;
+ /// Working set of direct modular dependencies, as they were imported.
+ llvm::SmallPtrSet<const Module *, 32> DirectImports;
+ /// All direct and transitive visible modules.
+ llvm::StringSet<> VisibleModules;
+
/// Options that control the dependency output generation.
std::unique_ptr<DependencyOutputOptions> Opts;
/// A Clang invocation that's based on the original TU invocation and that has
@@ -337,6 +342,9 @@ class ModuleDepCollector final : public DependencyCollector {
/// Checks whether the module is known as being prebuilt.
bool isPrebuiltModule(const Module *M);
+ /// Computes all visible modules resolved from direct imports.
+ void addVisibleModules();
+
/// Adds \p Path to \c FileDeps, making it absolute if necessary.
void addFileDep(StringRef Path);
/// Adds \p Path to \c MD.FileDeps, making it absolute if necessary.
diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp
index 515211d47b348..d3d7641b83d48 100644
--- a/clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp
+++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp
@@ -40,6 +40,7 @@ class MakeDependencyPrinterConsumer : public DependencyConsumer {
void handlePrebuiltModuleDependency(PrebuiltModuleDep PMD) override {}
void handleModuleDependency(ModuleDeps MD) override {}
void handleDirectModuleDependency(ModuleID ID) override {}
+ void handleVisibleModule(std::string ModuleName) override {}
void handleContextHash(std::string Hash) override {}
void printDependencies(std::string &S) {
@@ -175,6 +176,7 @@ TranslationUnitDeps FullDependencyConsumer::takeTranslationUnitDeps() {
TU.NamedModuleDeps = std::move(NamedModuleDeps);
TU.FileDeps = std::move(Dependencies);
TU.PrebuiltModuleDeps = std::move(PrebuiltModuleDeps);
+ TU.VisibleModules = std::move(VisibleModules);
TU.Commands = std::move(Commands);
for (auto &&M : ClangModuleDeps) {
diff --git a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
index fa86d714ff69a..1a36171b0d483 100644
--- a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
+++ b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
@@ -673,8 +673,10 @@ void ModuleDepCollectorPP::handleImport(const Module *Imported) {
if (MDC.isPrebuiltModule(TopLevelModule))
MDC.DirectPrebuiltModularDeps.insert(
{TopLevelModule, PrebuiltModuleDep{TopLevelModule}});
- else
+ else {
MDC.DirectModularDeps.insert(TopLevelModule);
+ MDC.DirectImports.insert(Imported);
+ }
}
void ModuleDepCollectorPP::EndOfMainFile() {
@@ -706,6 +708,8 @@ void ModuleDepCollectorPP::EndOfMainFile() {
if (!MDC.isPrebuiltModule(M))
MDC.DirectModularDeps.insert(M);
+ MDC.addVisibleModules();
+
for (const Module *M : MDC.DirectModularDeps)
handleTopLevelModule(M);
@@ -727,6 +731,9 @@ void ModuleDepCollectorPP::EndOfMainFile() {
MDC.Consumer.handleDirectModuleDependency(It->second->ID);
}
+ for (auto &&I : MDC.VisibleModules)
+ MDC.Consumer.handleVisibleModule(std::string(I.getKey()));
+
for (auto &&I : MDC.FileDeps)
MDC.Consumer.handleFileDependency(I);
@@ -993,6 +1000,28 @@ bool ModuleDepCollector::isPrebuiltModule(const Module *M) {
return true;
}
+void ModuleDepCollector::addVisibleModules() {
+ llvm::DenseSet<Module *> ImportedModules;
+ auto InsertVisibleModules = [&](const Module *M) {
+ if (ImportedModules.contains(M))
+ return;
+
+ VisibleModules.insert(M->getTopLevelModuleName());
+ SmallVector<Module *> Stack(M->Imports.begin(), M->Imports.end());
+ while (!Stack.empty()) {
+ Module *CurrModule = Stack.pop_back_val();
+ if (ImportedModules.contains(CurrModule))
+ continue;
+ ImportedModules.insert(CurrModule);
+ VisibleModules.insert(CurrModule->getTopLevelModuleName());
+ CurrModule->getExportedModules(Stack);
+ }
+ };
+
+ for (const Module *Import : DirectImports)
+ InsertVisibleModules(Import);
+}
+
static StringRef makeAbsoluteAndPreferred(CompilerInstance &CI, StringRef Path,
SmallVectorImpl<char> &Storage) {
if (llvm::sys::path::is_absolute(Path) &&
diff --git a/clang/test/ClangScanDeps/visible-modules.c b/clang/test/ClangScanDeps/visible-modules.c
new file mode 100644
index 0000000000000..d2545237d48f7
--- /dev/null
+++ b/clang/test/ClangScanDeps/visible-modules.c
@@ -0,0 +1,72 @@
+// This test verifies that the modules visible to the translation unit are computed in dependency scanning.
+// "client" represents the translation unit that imports an explicit submodule, that only exports one other module.
+// Thus, the dependencies of the top level module for the submodule differ from what is visible to the TU.
+
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+// RUN: sed -e "s|DIR|%/t|g" %t/compile-commands.json.in > %t/compile-commands.json
+// RUN: clang-scan-deps -compilation-database %t/compile-commands.json \
+// RUN: -j 1 -format experimental-full 2>&1 > %t/result.json
+// RUN: cat %t/result.json | sed 's:\\\\\?:/:g' | FileCheck %s -DPREFIX=%/t
+
+// CHECK: "visible-clang-modules": [
+// CHECK-NEXT: "A",
+// CHECK-NEXT: "visible"
+// CHECK-NEXT: ]
+
+//--- compile-commands.json.in
+[
+{
+ "directory": "DIR",
+ "command": "clang -c DIR/client.c -isysroot DIR/Sysroot -IDIR/Sysroot/usr/include -fmodules -fmodules-cache-path=DIR/module-cache -fimplicit-module-maps",
+ "file": "DIR/client.c"
+}
+]
+
+//--- Sysroot/usr/include/A/module.modulemap
+module A {
+ explicit module visibleToTU {
+ header "visibleToTU.h"
+ }
+ explicit module invisibleToTU {
+ header "invisibleToTU.h"
+ }
+}
+//--- Sysroot/usr/include/A/visibleToTU.h
+#include <visible/visible.h>
+typedef int A_visibleToTU;
+
+//--- Sysroot/usr/include/A/invisibleToTU.h
+#include <invisible/invisible.h>
+typedef int A_invisibleToTU;
+
+//--- Sysroot/usr/include/invisible/module.modulemap
+module invisible {
+ umbrella "."
+}
+
+//--- Sysroot/usr/include/invisible/invisible.h
+typedef int invisible_t;
+
+//--- Sysroot/usr/include/visible/module.modulemap
+module visible {
+ umbrella "."
+}
+
+//--- Sysroot/usr/include/visible/visible.h
+#include <transitive/transitive.h>
+typedef int visible_t;
+
+//--- Sysroot/usr/include/transitive/module.modulemap
+module transitive {
+ umbrella "."
+}
+
+//--- Sysroot/usr/include/transitive/transitive.h
+typedef int transitive_t;
+
+//--- client.c
+#include <A/visibleToTU.h>
+// Both decls are not visible, thus should fail to actually compile.
+transitive_t foo_t(void);
+invisible_t foo(void);
diff --git a/clang/tools/clang-scan-deps/ClangScanDeps.cpp b/clang/tools/clang-scan-deps/ClangScanDeps.cpp
index 8b590bd57e1a3..cdff8400b322b 100644
--- a/clang/tools/clang-scan-deps/ClangScanDeps.cpp
+++ b/clang/tools/clang-scan-deps/ClangScanDeps.cpp
@@ -380,6 +380,14 @@ static auto toJSONSorted(llvm::json::OStream &JOS,
};
}
+static auto toJSONSorted(llvm::json::OStream &JOS, std::vector<std::string> V) {
+ llvm::sort(V);
+ return [&JOS, V = std::move(V)] {
+ for (const StringRef Entry : V)
+ JOS.value(Entry);
+ };
+}
+
// Thread safe.
class FullDeps {
public:
@@ -396,6 +404,7 @@ class FullDeps {
ID.NamedModule = std::move(TUDeps.ID.ModuleName);
ID.NamedModuleDeps = std::move(TUDeps.NamedModuleDeps);
ID.ClangModuleDeps = std::move(TUDeps.ClangModuleDeps);
+ ID.VisibleModules = std::move(TUDeps.VisibleModules);
ID.DriverCommandLine = std::move(TUDeps.DriverCommandLine);
ID.Commands = std::move(TUDeps.Commands);
@@ -519,6 +528,8 @@ class FullDeps {
});
JOS.attributeArray("clang-module-deps",
toJSONSorted(JOS, I.ClangModuleDeps));
+ JOS.attributeArray("visible-clang-modules",
+ toJSONSorted(JOS, I.VisibleModules));
JOS.attributeArray("command-line",
toJSONStrings(JOS, Cmd.Arguments));
JOS.attribute("executable", StringRef(Cmd.Executable));
@@ -539,6 +550,8 @@ class FullDeps {
});
JOS.attributeArray("clang-module-deps",
toJSONSorted(JOS, I.ClangModuleDeps));
+ JOS.attributeArray("visible-clang-modules",
+ toJSONSorted(JOS, I.VisibleModules));
JOS.attributeArray("command-line",
toJSONStrings(JOS, I.DriverCommandLine));
JOS.attribute("executable", "clang");
@@ -596,6 +609,7 @@ class FullDeps {
std::string NamedModule;
std::vector<std::string> NamedModuleDeps;
std::vector<ModuleID> ClangModuleDeps;
+ std::vector<std::string> VisibleModules;
std::vector<std::string> DriverCommandLine;
std::vector<Command> Commands;
};
>From 52a1a716d59a645b50d054c903b53f2fbc1e8bad Mon Sep 17 00:00:00 2001
From: Cyndy Ishida <cyndy_ishida at apple.com>
Date: Wed, 9 Jul 2025 22:04:06 -0700
Subject: [PATCH 2/2] Update tests with visible-clang-module section
---
clang/test/ClangScanDeps/diagnostics.c | 3 +++
.../header-search-pruning-transitive.c | 8 ++++++++
.../modules-context-hash-ignore-macros.c | 9 +++++++++
.../ClangScanDeps/modules-context-hash-outputs.c | 6 ++++++
.../ClangScanDeps/modules-context-hash-warnings.c | 6 ++++++
clang/test/ClangScanDeps/modules-context-hash.c | 6 ++++++
clang/test/ClangScanDeps/modules-dep-args.c | 4 ++++
.../test/ClangScanDeps/modules-extern-submodule.c | 4 ++++
.../test/ClangScanDeps/modules-extern-unrelated.m | 5 +++++
.../modules-fmodule-name-no-module-built.m | 4 ++++
.../ClangScanDeps/modules-full-output-tu-order.c | 2 ++
clang/test/ClangScanDeps/modules-full.cpp | 13 +++++++++++++
.../modules-has-include-umbrella-header.c | 6 ++++++
.../ClangScanDeps/modules-implementation-private.m | 4 ++++
.../ClangScanDeps/modules-implicit-dot-private.m | 3 +++
.../ClangScanDeps/modules-incomplete-umbrella.c | 8 ++++++++
clang/test/ClangScanDeps/modules-inferred.m | 3 +++
.../ClangScanDeps/modules-no-undeclared-includes.c | 3 +++
.../test/ClangScanDeps/modules-pch-common-stale.c | 9 +++++++++
.../ClangScanDeps/modules-pch-common-submodule.c | 7 +++++++
.../modules-pch-common-via-submodule.c | 6 ++++++
clang/test/ClangScanDeps/modules-pch.c | 12 ++++++++++++
.../test/ClangScanDeps/modules-priv-fw-from-pub.m | 4 ++++
clang/test/ClangScanDeps/multiple-commands.c | 14 ++++++++++++++
clang/test/ClangScanDeps/removed-args.c | 4 ++++
clang/test/ClangScanDeps/tu-buffer.c | 4 ++++
26 files changed, 157 insertions(+)
diff --git a/clang/test/ClangScanDeps/diagnostics.c b/clang/test/ClangScanDeps/diagnostics.c
index 8e3cf4c9f9fa6..4d09740d7b5ae 100644
--- a/clang/test/ClangScanDeps/diagnostics.c
+++ b/clang/test/ClangScanDeps/diagnostics.c
@@ -50,6 +50,9 @@ module mod { header "mod.h" }
// CHECK-NEXT: "module-name": "mod"
// CHECK-NEXT: }
// CHECK-NEXT: ],
+// CHECK-NEXT: "visible-clang-modules": [
+// CHECK-NEXT: "mod"
+// CHECK-NEXT: ],
// CHECK-NEXT: "command-line": [
// CHECK-NOT: "-fimplicit-modules"
// CHECK-NOT: "-fimplicit-module-maps"
diff --git a/clang/test/ClangScanDeps/header-search-pruning-transitive.c b/clang/test/ClangScanDeps/header-search-pruning-transitive.c
index 1e829bb02ddc4..680228d51a181 100644
--- a/clang/test/ClangScanDeps/header-search-pruning-transitive.c
+++ b/clang/test/ClangScanDeps/header-search-pruning-transitive.c
@@ -104,6 +104,10 @@ module X { header "X.h" }
// CHECK-NEXT: "module-name": "X"
// CHECK-NEXT: }
// CHECK-NEXT: ],
+// CHECK-NEXT: "visible-clang-modules": [
+// CHECK-NEXT: "X",
+// CHECK-NEXT: "Y"
+// CHECK-NEXT: ],
// CHECK-NEXT: "command-line": [
// CHECK: ],
// CHECK: "file-deps": [
@@ -159,6 +163,10 @@ module X { header "X.h" }
// CHECK-NEXT: "module-name": "X"
// CHECK-NEXT: }
// CHECK-NEXT: ],
+// CHECK-NEXT: "visible-clang-modules": [
+// CHECK-NEXT: "X",
+// CHECK-NEXT: "Y"
+// CHECK-NEXT: ],
// CHECK-NEXT: "command-line": [
// CHECK: ],
// CHECK: "file-deps": [
diff --git a/clang/test/ClangScanDeps/modules-context-hash-ignore-macros.c b/clang/test/ClangScanDeps/modules-context-hash-ignore-macros.c
index 9f7a62fb9eb74..065a10dfb4841 100644
--- a/clang/test/ClangScanDeps/modules-context-hash-ignore-macros.c
+++ b/clang/test/ClangScanDeps/modules-context-hash-ignore-macros.c
@@ -36,6 +36,9 @@
// CHECK-NEXT: "module-name": "Mod"
// CHECK-NEXT: }
// CHECK-NEXT: ]
+// CHECK-NEXT: "visible-clang-modules": [
+// CHECK-NEXT: "Mod"
+// CHECK-NEXT: ],
// CHECK-NEXT: "command-line": [
// CHECK-NOT: "-DFOO"
// CHECK-NOT: "FOO"
@@ -49,6 +52,9 @@
// CHECK-NEXT: "module-name": "Mod"
// CHECK-NEXT: }
// CHECK-NEXT: ]
+// CHECK-NEXT: "visible-clang-modules": [
+// CHECK-NEXT: "Mod"
+// CHECK-NEXT: ],
// CHECK-NEXT: "command-line": [
// CHECK: "-D"
// CHECK-NEXT: "FOO"
@@ -62,6 +68,9 @@
// CHECK-NEXT: "module-name": "Mod"
// CHECK-NEXT: }
// CHECK-NEXT: ]
+// CHECK-NEXT: "visible-clang-modules": [
+// CHECK-NEXT: "Mod"
+// CHECK-NEXT: ],
// CHECK-NEXT: "command-line": [
// CHECK: "-fmodules-ignore-macro=FOO"
// CHECK: "-D"
diff --git a/clang/test/ClangScanDeps/modules-context-hash-outputs.c b/clang/test/ClangScanDeps/modules-context-hash-outputs.c
index 5e63e60a70370..75f8f1c583d92 100644
--- a/clang/test/ClangScanDeps/modules-context-hash-outputs.c
+++ b/clang/test/ClangScanDeps/modules-context-hash-outputs.c
@@ -34,6 +34,9 @@
// CHECK-NEXT: "module-name": "Mod"
// CHECK-NEXT: }
// CHECK-NEXT: ]
+// CHECK-NEXT: "visible-clang-modules": [
+// CHECK-NEXT: "Mod"
+// CHECK-NEXT: ],
// CHECK-NEXT: "command-line": [
// CHECK: "-dependency-file"
// CHECK: ]
@@ -46,6 +49,9 @@
// CHECK-NEXT: "module-name": "Mod"
// CHECK-NEXT: }
// CHECK-NEXT: ]
+// CHECK-NEXT: "visible-clang-modules": [
+// CHECK-NEXT: "Mod"
+// CHECK-NEXT: ],
// CHECK-NEXT: "command-line": [
// CHECK-NOT: "-MF"
// CHECK-NOT: "-dependency-file"
diff --git a/clang/test/ClangScanDeps/modules-context-hash-warnings.c b/clang/test/ClangScanDeps/modules-context-hash-warnings.c
index 09d2f20b329e3..5a3d76e158c98 100644
--- a/clang/test/ClangScanDeps/modules-context-hash-warnings.c
+++ b/clang/test/ClangScanDeps/modules-context-hash-warnings.c
@@ -34,6 +34,9 @@
// CHECK-NEXT: "module-name": "Mod"
// CHECK-NEXT: }
// CHECK-NEXT: ]
+// CHECK-NEXT: "visible-clang-modules": [
+// CHECK-NEXT: "Mod"
+// CHECK-NEXT: ],
// CHECK-NEXT: "command-line": [
// CHECK: "-Wall"
// CHECK: ]
@@ -46,6 +49,9 @@
// CHECK-NEXT: "module-name": "Mod"
// CHECK-NEXT: }
// CHECK-NEXT: ]
+// CHECK-NEXT: "visible-clang-modules": [
+// CHECK-NEXT: "Mod"
+// CHECK-NEXT: ],
// CHECK-NEXT: "command-line": [
// CHECK-NOT: "-Wall"
// CHECK: ]
diff --git a/clang/test/ClangScanDeps/modules-context-hash.c b/clang/test/ClangScanDeps/modules-context-hash.c
index 9489563576d3b..6ea831f7aed08 100644
--- a/clang/test/ClangScanDeps/modules-context-hash.c
+++ b/clang/test/ClangScanDeps/modules-context-hash.c
@@ -51,6 +51,9 @@
// CHECK-NEXT: "module-name": "mod"
// CHECK-NEXT: }
// CHECK-NEXT: ],
+// CHECK-NEXT: "visible-clang-modules": [
+// CHECK-NEXT: "mod"
+// CHECK-NEXT: ],
// CHECK-NEXT: "command-line": [
// CHECK: ],
// CHECK: "file-deps": [
@@ -89,6 +92,9 @@
// CHECK: "module-name": "mod"
// CHECK-NEXT: }
// CHECK-NEXT: ],
+// CHECK-NEXT: "visible-clang-modules": [
+// CHECK-NEXT: "mod"
+// CHECK-NEXT: ],
// CHECK-NEXT: "command-line": [
// CHECK: ],
// CHECK: "file-deps": [
diff --git a/clang/test/ClangScanDeps/modules-dep-args.c b/clang/test/ClangScanDeps/modules-dep-args.c
index 19f915923b84c..310a33e9533cf 100644
--- a/clang/test/ClangScanDeps/modules-dep-args.c
+++ b/clang/test/ClangScanDeps/modules-dep-args.c
@@ -87,6 +87,10 @@ module Direct { header "direct.h" }
// CHECK-NEXT: "module-name": "Direct"
// CHECK-NEXT: }
// CHECK-NEXT: ],
+// CHECK-NEXT: "visible-clang-modules": [
+// CHECK-NEXT: "Direct",
+// CHECK-NEXT: "Transitive"
+// CHECK-NEXT: ],
// CHECK-NEXT: "command-line": [
// CHECK_CACHE: "-fmodule-file={{.*}}/cache/{{.*}}/Direct-{{.*}}.pcm"
// CHECK_BUILD: "-fmodule-file={{.*}}/build/{{.*}}/Direct-{{.*}}.pcm"
diff --git a/clang/test/ClangScanDeps/modules-extern-submodule.c b/clang/test/ClangScanDeps/modules-extern-submodule.c
index 01d3d6ba5e0d3..7a2b49879b97b 100644
--- a/clang/test/ClangScanDeps/modules-extern-submodule.c
+++ b/clang/test/ClangScanDeps/modules-extern-submodule.c
@@ -107,6 +107,10 @@ module third {}
// CHECK-NEXT: "module-name": "first"
// CHECK-NEXT: }
// CHECK-NEXT: ],
+// CHECK-NEXT: "visible-clang-modules": [
+// CHECK-NEXT: "first",
+// CHECK-NEXT: "second"
+// CHECK-NEXT: ],
// CHECK-NEXT: "command-line": [
// CHECK-NEXT: "-cc1",
// CHECK: "-fmodule-map-file=[[PREFIX]]/first/first/module.modulemap",
diff --git a/clang/test/ClangScanDeps/modules-extern-unrelated.m b/clang/test/ClangScanDeps/modules-extern-unrelated.m
index c003f0d9a2ee8..50ee7464419f7 100644
--- a/clang/test/ClangScanDeps/modules-extern-unrelated.m
+++ b/clang/test/ClangScanDeps/modules-extern-unrelated.m
@@ -113,6 +113,11 @@
// CHECK-NEXT: "module-name": "zeroth"
// CHECK-NEXT: }
// CHECK-NEXT: ],
+// CHECK-NEXT: "visible-clang-modules": [
+// CHECK-NEXT: "first",
+// CHECK-NEXT: "second",
+// CHECK-NEXT: "zeroth"
+// CHECK-NEXT: ],
// CHECK-NEXT: "command-line": [
// CHECK: ],
// CHECK-NEXT: "executable": "{{.*}}",
diff --git a/clang/test/ClangScanDeps/modules-fmodule-name-no-module-built.m b/clang/test/ClangScanDeps/modules-fmodule-name-no-module-built.m
index cfe29c2bf7cdb..0d91808e2bc04 100644
--- a/clang/test/ClangScanDeps/modules-fmodule-name-no-module-built.m
+++ b/clang/test/ClangScanDeps/modules-fmodule-name-no-module-built.m
@@ -41,6 +41,10 @@
// CHECK-NEXT: "module-name": "header2"
// CHECK-NEXT: }
// CHECK-NEXT: ],
+// CHECK-NEXT: "visible-clang-modules": [
+// CHECK-NEXT: "header2",
+// CHECK-NEXT: "header3"
+// CHECK-NEXT: ],
// CHECK-NEXT: "command-line": [
// CHECK: ],
// CHECK: "file-deps": [
diff --git a/clang/test/ClangScanDeps/modules-full-output-tu-order.c b/clang/test/ClangScanDeps/modules-full-output-tu-order.c
index 065b8ac8ae07f..79e2947c5f039 100644
--- a/clang/test/ClangScanDeps/modules-full-output-tu-order.c
+++ b/clang/test/ClangScanDeps/modules-full-output-tu-order.c
@@ -31,6 +31,7 @@
// CHECK-NEXT: {
// CHECK-NEXT: "clang-context-hash": "{{.*}}",
// CHECK-NEXT: "clang-module-deps": [],
+// CHECK-NEXT: "visible-clang-modules": [],
// CHECK-NEXT: "command-line": [
// CHECK: "-D"
// CHECK-NEXT: "ONE"
@@ -47,6 +48,7 @@
// CHECK-NEXT: {
// CHECK-NEXT: "clang-context-hash": "{{.*}}",
// CHECK-NEXT: "clang-module-deps": [],
+// CHECK-NEXT: "visible-clang-modules": [],
// CHECK-NEXT: "command-line": [
// CHECK: "-D"
// CHECK-NEXT: "TWO"
diff --git a/clang/test/ClangScanDeps/modules-full.cpp b/clang/test/ClangScanDeps/modules-full.cpp
index 38db3af4403bb..67da82eb35960 100644
--- a/clang/test/ClangScanDeps/modules-full.cpp
+++ b/clang/test/ClangScanDeps/modules-full.cpp
@@ -97,6 +97,10 @@
// CHECK-NEXT: "module-name": "header1"
// CHECK-NEXT: }
// CHECK-NEXT: ],
+// CHECK-NEXT: "visible-clang-modules": [
+// CHECK-NEXT: "header1",
+// CHECK-NEXT: "header2"
+// CHECK-NEXT: ],
// CHECK-NEXT: "command-line": [
// CHECK-NOT: "-fimplicit-modules"
// CHECK-NOT: "-fimplicit-module-maps"
@@ -120,6 +124,9 @@
// CHECK-NEXT: "module-name": "header1"
// CHECK-NEXT: }
// CHECK-NEXT: ],
+// CHECK-NEXT: "visible-clang-modules": [
+// CHECK-NEXT: "header1"
+// CHECK-NEXT: ],
// CHECK-NEXT: "command-line": [
// CHECK-NOT: "-fimplicit-modules"
// CHECK-NOT: "-fimplicit-module-maps"
@@ -143,6 +150,9 @@
// CHECK-NEXT: "module-name": "header1"
// CHECK-NEXT: }
// CHECK-NEXT: ],
+// CHECK-NEXT: "visible-clang-modules": [
+// CHECK-NEXT: "header1"
+// CHECK-NEXT: ],
// CHECK-NEXT: "command-line": [
// CHECK-NOT: "-fimplicit-modules"
// CHECK-NOT: "-fimplicit-module-maps"
@@ -166,6 +176,9 @@
// CHECK-NEXT: "module-name": "header1"
// CHECK-NEXT: }
// CHECK-NEXT: ],
+// CHECK-NEXT: "visible-clang-modules": [
+// CHECK-NEXT: "header1"
+// CHECK-NEXT: ],
// CHECK-NEXT: "command-line": [
// CHECK-NOT: "-fimplicit-modules"
// CHECK-NOT: "-fimplicit-module-maps"
diff --git a/clang/test/ClangScanDeps/modules-has-include-umbrella-header.c b/clang/test/ClangScanDeps/modules-has-include-umbrella-header.c
index 022c59ca65db2..f27ea8e1ed2eb 100644
--- a/clang/test/ClangScanDeps/modules-has-include-umbrella-header.c
+++ b/clang/test/ClangScanDeps/modules-has-include-umbrella-header.c
@@ -62,6 +62,12 @@ module Dependency { header "dependency.h" }
// CHECK-NEXT: "module-name": "FW_Private"
// CHECK-NEXT: }
// CHECK: ],
+// CHECK: "visible-clang-modules": [
+// CHECK-NEXT: "Dependency",
+// CHECK-NEXT: "FW_Private",
+// CHECK-NEXT: "Import",
+// CHECK-NEXT: "Poison"
+// CHECK-NEXT: ],
// CHECK-NEXT: "command-line": [
// CHECK: ],
// CHECK: "file-deps": [
diff --git a/clang/test/ClangScanDeps/modules-implementation-private.m b/clang/test/ClangScanDeps/modules-implementation-private.m
index b376073f4b9ee..59e77b85b7967 100644
--- a/clang/test/ClangScanDeps/modules-implementation-private.m
+++ b/clang/test/ClangScanDeps/modules-implementation-private.m
@@ -60,6 +60,10 @@
// CHECK-NEXT: "module-name": "FW_Private"
// CHECK-NEXT: }
// CHECK-NEXT: ],
+// CHECK-NEXT: "visible-clang-modules": [
+// CHECK-NEXT: "FW",
+// CHECK-NEXT: "FW_Private"
+// CHECK-NEXT: ],
// CHECK-NEXT: "command-line": [
// CHECK: ],
// CHECK: "file-deps": [
diff --git a/clang/test/ClangScanDeps/modules-implicit-dot-private.m b/clang/test/ClangScanDeps/modules-implicit-dot-private.m
index aa8caf3451dc4..5dfac2b09b316 100644
--- a/clang/test/ClangScanDeps/modules-implicit-dot-private.m
+++ b/clang/test/ClangScanDeps/modules-implicit-dot-private.m
@@ -75,6 +75,9 @@
// CHECK-NEXT: "module-name": "FW_Private"
// CHECK-NEXT: }
// CHECK-NEXT: ],
+// CHECK-NEXT: "visible-clang-modules": [
+// CHECK-NEXT: "FW_Private"
+// CHECK-NEXT: ],
// CHECK-NEXT: "command-line": [
// CHECK: "-fmodule-file={{.*}}/FW-{{.*}}.pcm"
// CHECK: "-fmodule-file={{.*}}/FW_Private-{{.*}}.pcm"
diff --git a/clang/test/ClangScanDeps/modules-incomplete-umbrella.c b/clang/test/ClangScanDeps/modules-incomplete-umbrella.c
index 696e621960b6f..bb5ccb31cfd30 100644
--- a/clang/test/ClangScanDeps/modules-incomplete-umbrella.c
+++ b/clang/test/ClangScanDeps/modules-incomplete-umbrella.c
@@ -88,6 +88,10 @@ framework module FW_Private {
// CHECK_TU-NEXT: "module-name": "FW_Private"
// CHECK_TU-NEXT: }
// CHECK_TU-NEXT: ],
+// CHECK_TU-NEXT: "visible-clang-modules": [
+// CHECK_TU-NEXT: "FW",
+// CHECK_TU-NEXT: "FW_Private"
+// CHECK_TU-NEXT: ],
// CHECK_TU-NEXT: "command-line": [
// CHECK_TU: "-fmodule-file={{.*}}/FW-{{.*}}.pcm"
// CHECK_TU: "-fmodule-file={{.*}}/FW_Private-{{.*}}.pcm"
@@ -201,6 +205,10 @@ module Mod { header "Mod.h" }
// CHECK_MODULE-NEXT: "module-name": "Mod"
// CHECK_MODULE-NEXT: }
// CHECK_MODULE-NEXT: ],
+// CHECK_MODULE-NEXT: "visible-clang-modules": [
+// CHECK_MODULE-NEXT: "FW",
+// CHECK_MODULE-NEXT: "Mod"
+// CHECK_MODULE-NEXT: ],
// CHECK_MODULE-NEXT: "command-line": [
// CHECK_MODULE: ],
// CHECK_MODULE: "file-deps": [
diff --git a/clang/test/ClangScanDeps/modules-inferred.m b/clang/test/ClangScanDeps/modules-inferred.m
index 4c7a4095c9bef..83c523b1de219 100644
--- a/clang/test/ClangScanDeps/modules-inferred.m
+++ b/clang/test/ClangScanDeps/modules-inferred.m
@@ -61,6 +61,9 @@
// CHECK-NEXT: "module-name": "Inferred"
// CHECK-NEXT: }
// CHECK-NEXT: ],
+// CHECK-NEXT: "visible-clang-modules": [
+// CHECK-NEXT: "Inferred"
+// CHECK-NEXT: ],
// CHECK-NEXT: "command-line": [
// CHECK: ],
// CHECK: "file-deps": [
diff --git a/clang/test/ClangScanDeps/modules-no-undeclared-includes.c b/clang/test/ClangScanDeps/modules-no-undeclared-includes.c
index 6110c419949f9..683d96988825f 100644
--- a/clang/test/ClangScanDeps/modules-no-undeclared-includes.c
+++ b/clang/test/ClangScanDeps/modules-no-undeclared-includes.c
@@ -60,6 +60,9 @@ module User [no_undeclared_includes] { header "user.h" }
// CHECK-NEXT: "module-name": "User"
// CHECK-NEXT: }
// CHECK-NEXT: ],
+// CHECK-NEXT: "visible-clang-modules": [
+// CHECK-NEXT: "User"
+// CHECK-NEXT: ],
// CHECK-NEXT: "command-line": [
// CHECK: ],
// CHECK: "file-deps": [
diff --git a/clang/test/ClangScanDeps/modules-pch-common-stale.c b/clang/test/ClangScanDeps/modules-pch-common-stale.c
index 72a4dc949b0f5..b3ffd188e66f7 100644
--- a/clang/test/ClangScanDeps/modules-pch-common-stale.c
+++ b/clang/test/ClangScanDeps/modules-pch-common-stale.c
@@ -68,6 +68,10 @@ module mod_tu_extra { header "mod_tu_extra.h" }
// CHECK-TU-CLEAN-NEXT: "module-name": "mod_tu"
// CHECK-TU-CLEAN-NEXT: }
// CHECK-TU-CLEAN-NEXT: ],
+// CHECK-TU-CLEAN-NEXT: "visible-clang-modules": [
+// CHECK-TU-CLEAN-NEXT: "mod_common",
+// CHECK-TU-CLEAN-NEXT: "mod_tu"
+// CHECK-TU-CLEAN-NEXT: ],
// CHECK-TU-CLEAN-NEXT: "command-line": [
// CHECK-TU-CLEAN: ],
// CHECK-TU-CLEAN-NEXT: "executable": "{{.*}}",
@@ -155,6 +159,11 @@ module mod_tu_extra { header "mod_tu_extra.h" }
// CHECK-TU-INCREMENTAL-NEXT: "module-name": "mod_tu"
// CHECK-TU-INCREMENTAL-NEXT: }
// CHECK-TU-INCREMENTAL-NEXT: ],
+// CHECK-TU-INCREMENTAL-NEXT: "visible-clang-modules": [
+// CHECK-TU-INCREMENTAL-NEXT: "mod_common",
+// CHECK-TU-INCREMENTAL-NEXT: "mod_tu",
+// CHECK-TU-INCREMENTAL-NEXT: "mod_tu_extra"
+// CHECK-TU-INCREMENTAL-NEXT: ],
// CHECK-TU-INCREMENTAL-NEXT: "command-line": [
// CHECK-TU-INCREMENTAL: ],
// CHECK-TU-INCREMENTAL-NEXT: "executable": "{{.*}}",
diff --git a/clang/test/ClangScanDeps/modules-pch-common-submodule.c b/clang/test/ClangScanDeps/modules-pch-common-submodule.c
index 59dd3f172d8ee..2c8da8b4f4ef8 100644
--- a/clang/test/ClangScanDeps/modules-pch-common-submodule.c
+++ b/clang/test/ClangScanDeps/modules-pch-common-submodule.c
@@ -44,6 +44,9 @@
// CHECK-PCH-NEXT: "module-name": "ModCommon"
// CHECK-PCH-NEXT: }
// CHECK-PCH-NEXT: ],
+// CHECK-PCH-NEXT: "visible-clang-modules": [
+// CHECK-PCH-NEXT: "ModCommon"
+// CHECK-PCH-NEXT: ],
// CHECK-PCH-NEXT: "command-line": [
// CHECK-PCH: ],
// CHECK-PCH: "file-deps": [
@@ -92,6 +95,10 @@
// CHECK-TU-NEXT: "module-name": "ModTU"
// CHECK-TU-NEXT: }
// CHECK-TU-NEXT: ],
+// CHECK-TU-NEXT: "visible-clang-modules": [
+// CHECK-TU-NEXT: "ModCommon",
+// CHECK-TU-NEXT: "ModTU"
+// CHECK-TU-NEXT: ],
// CHECK-TU-NEXT: "command-line": [
// CHECK-TU: ],
// CHECK-TU: "file-deps": [
diff --git a/clang/test/ClangScanDeps/modules-pch-common-via-submodule.c b/clang/test/ClangScanDeps/modules-pch-common-via-submodule.c
index a12492c0bec70..9d53b988c0d4a 100644
--- a/clang/test/ClangScanDeps/modules-pch-common-via-submodule.c
+++ b/clang/test/ClangScanDeps/modules-pch-common-via-submodule.c
@@ -40,6 +40,9 @@
// CHECK-PCH-NEXT: "module-name": "ModCommon"
// CHECK-PCH-NEXT: }
// CHECK-PCH-NEXT: ],
+// CHECK-PCH-NEXT: "visible-clang-modules": [
+// CHECK-PCH-NEXT: "ModCommon"
+// CHECK-PCH-NEXT: ],
// CHECK-PCH-NEXT: "command-line": [
// CHECK-PCH: ],
// CHECK-PCH: "file-deps": [
@@ -89,6 +92,9 @@
// CHECK-TU-NEXT: "module-name": "ModTU"
// CHECK-TU-NEXT: }
// CHECK-TU-NEXT: ],
+// CHECK-TU-NEXT: "visible-clang-modules": [
+// CHECK-TU-NEXT: "ModTU"
+// CHECK-TU-NEXT: ],
// CHECK-TU-NEXT: "command-line": [
// CHECK-TU: ],
// CHECK-TU: "file-deps": [
diff --git a/clang/test/ClangScanDeps/modules-pch.c b/clang/test/ClangScanDeps/modules-pch.c
index 92b7f41ac4b9f..7101b8ade1117 100644
--- a/clang/test/ClangScanDeps/modules-pch.c
+++ b/clang/test/ClangScanDeps/modules-pch.c
@@ -76,6 +76,11 @@
// CHECK-PCH-NEXT: "module-name": "ModPCH"
// CHECK-PCH-NEXT: }
// CHECK-PCH-NEXT: ],
+// CHECK-PCH-NEXT: "visible-clang-modules": [
+// CHECK-PCH-NEXT: "ModCommon1",
+// CHECK-PCH-NEXT: "ModCommon2",
+// CHECK-PCH-NEXT: "ModPCH"
+// CHECK-PCH-NEXT: ],
// CHECK-PCH-NEXT: "command-line": [
// CHECK-PCH: ],
// CHECK-PCH: "file-deps": [
@@ -129,6 +134,9 @@
// CHECK-TU-NEXT: "module-name": "ModTU"
// CHECK-TU-NEXT: }
// CHECK-TU-NEXT: ],
+// CHECK-TU-NEXT: "visible-clang-modules": [
+// CHECK-TU-NEXT: "ModTU"
+// CHECK-TU-NEXT: ],
// CHECK-TU-NEXT: "command-line": [
// CHECK-TU: ],
// CHECK-TU: "file-deps": [
@@ -179,6 +187,10 @@
// CHECK-TU-WITH-COMMON-NEXT: "module-name": "ModTUWithCommon"
// CHECK-TU-WITH-COMMON-NEXT: }
// CHECK-TU-WITH-COMMON-NEXT: ],
+// CHECK-TU-WITH-COMMON-NEXT: "visible-clang-modules": [
+// CHECK-TU-WITH-COMMON-NEXT: "ModCommon1",
+// CHECK-TU-WITH-COMMON-NEXT: "ModTUWithCommon"
+// CHECK-TU-WITH-COMMON-NEXT: ],
// CHECK-TU-WITH-COMMON-NEXT: "command-line": [
// CHECK-TU-WITH-COMMON: "-fmodule-file=[[PREFIX]]/build/{{.*}}/ModCommon2-{{.*}}.pcm"
// CHECK-TU-WITH-COMMON: ],
diff --git a/clang/test/ClangScanDeps/modules-priv-fw-from-pub.m b/clang/test/ClangScanDeps/modules-priv-fw-from-pub.m
index dd314e1a3006a..efbf423e76f15 100644
--- a/clang/test/ClangScanDeps/modules-priv-fw-from-pub.m
+++ b/clang/test/ClangScanDeps/modules-priv-fw-from-pub.m
@@ -108,6 +108,10 @@
// CHECK-NEXT: "module-name": "FW"
// CHECK-NEXT: }
// CHECK-NEXT: ],
+// CHECK-NEXT: "visible-clang-modules": [
+// CHECK-NEXT: "FW",
+// CHECK-NEXT: "FW_Private"
+// CHECK-NEXT: ],
// CHECK-NEXT: "command-line": [
// CHECK: ],
// CHECK: "file-deps": [
diff --git a/clang/test/ClangScanDeps/multiple-commands.c b/clang/test/ClangScanDeps/multiple-commands.c
index bb169ea10995a..810f7d0648b06 100644
--- a/clang/test/ClangScanDeps/multiple-commands.c
+++ b/clang/test/ClangScanDeps/multiple-commands.c
@@ -45,6 +45,7 @@
// CHECK-NEXT: {
// CHECK-NEXT: "clang-context-hash":
// CHECK-NEXT: "clang-module-deps": []
+// CHECK-NEXT: "visible-clang-modules": []
// CHECK-NEXT: "command-line": [
// CHECK-NEXT: "-cc1"
// CHECK: "-o"
@@ -57,6 +58,7 @@
// CHECK-NEXT: {
// CHECK-NEXT: "clang-context-hash":
// CHECK-NEXT: "clang-module-deps": []
+// CHECK-NEXT: "visible-clang-modules": []
// CHECK-NEXT: "command-line": [
// CHECK-NEXT: "-cc1"
// CHECK: "-o"
@@ -77,6 +79,9 @@
// CHECK: "module-name": "Mod"
// CHECK-NEXT: }
// CHECK-NEXT: ]
+// CHECK: "visible-clang-modules": [
+// CHECK-NEXT: "Mod"
+// CHECK-NEXT: ]
// CHECK-NEXT: "command-line": [
// CHECK-NEXT: "-cc1"
// CHECK: "-o"
@@ -94,6 +99,9 @@
// CHECK: "module-name": "Mod"
// CHECK-NEXT: }
// CHECK-NEXT: ]
+// CHECK: "visible-clang-modules": [
+// CHECK-NEXT: "Mod"
+// CHECK-NEXT: ]
// CHECK-NEXT: "command-line": [
// CHECK-NEXT: "-cc1"
// CHECK: "-o"
@@ -111,6 +119,9 @@
// CHECK: "module-name": "Mod"
// CHECK-NEXT: }
// CHECK-NEXT: ]
+// CHECK: "visible-clang-modules": [
+// CHECK-NEXT: "Mod"
+// CHECK-NEXT: ]
// CHECK-NEXT: "command-line": [
// CHECK-NEXT: "-cc1"
// CHECK: "-o"
@@ -127,6 +138,9 @@
// CHECK: "module-name": "Mod"
// CHECK-NEXT: }
// CHECK-NEXT: ]
+// CHECK: "visible-clang-modules": [
+// CHECK-NEXT: "Mod"
+// CHECK-NEXT: ]
// CHECK-NEXT: "command-line": [
// CHECK-NEXT: "-cc1as"
// CHECK: "-o"
diff --git a/clang/test/ClangScanDeps/removed-args.c b/clang/test/ClangScanDeps/removed-args.c
index 16f053f71e6ba..e09db0aefa95d 100644
--- a/clang/test/ClangScanDeps/removed-args.c
+++ b/clang/test/ClangScanDeps/removed-args.c
@@ -86,6 +86,10 @@
// CHECK-NEXT: "module-name": "ModTU"
// CHECK-NEXT: }
// CHECK-NEXT: ]
+// CHECK-NEXT: "visible-clang-modules": [
+// CHECK-NEXT: "ModHeader",
+// CHECK-NEXT: "ModTU"
+// CHECK-NEXT: ],
// CHECK-NEXT: "command-line": [
// CHECK-NEXT: "-cc1",
// CHECK-NOT: "-fmodules-cache-path=
diff --git a/clang/test/ClangScanDeps/tu-buffer.c b/clang/test/ClangScanDeps/tu-buffer.c
index b450b13ff434b..c0994a50390d2 100644
--- a/clang/test/ClangScanDeps/tu-buffer.c
+++ b/clang/test/ClangScanDeps/tu-buffer.c
@@ -98,6 +98,10 @@ module addition { header "addition.h" }
// CHECK-NEXT: "module-name": "root"
// CHECK-NEXT: }
// CHECK-NEXT: ],
+// CHECK-NEXT: "visible-clang-modules": [
+// CHECK-NEXT: "direct",
+// CHECK-NEXT: "root"
+// CHECK-NEXT: ],
// CHECK-NEXT: "command-line": [
// CHECK: ],
// CHECK: "file-deps": [
More information about the cfe-commits
mailing list