[clang] [clang][clang-scan-deps] Add named modules to format 'experimental-full' (PR #145221)

Naveen Seth Hanig via cfe-commits cfe-commits at lists.llvm.org
Sun Jun 22 01:37:04 PDT 2025


https://github.com/naveen-seth created https://github.com/llvm/llvm-project/pull/145221

This adds standard C++ named modules to the scanning output format 'experimental-full'.

This is motivated by an effort to provide native support for explicit module builds from the Clang driver.
The driver support for explicit module builds is planned to support combined usage of Clang modules and C++ named modules. With this, only a single scan is required to capture dependencies for both module types.

>From 981742eea871868d58293e9a2b58fb3ef2569e7c Mon Sep 17 00:00:00 2001
From: Naveen Seth Hanig <naveen.hanig at outlook.com>
Date: Sat, 21 Jun 2025 18:54:38 +0200
Subject: [PATCH] [clang][clang-scan-deps] Add named modules to format
 'experimental-full'

This adds standard C++ named modules to the scanning output format
'experimental-full'.

This is motivated by an effort to provide native support for explicit
module builds from the Clang driver.
The driver support for explicit module builds is planned to support
combined usage of Clang modules and C++ named modules.
With this, only a single scan is required to capture dependencies for
both module types.
---
 .../DependencyScanningTool.h                  |  14 +
 .../DependencyScanningTool.cpp                |   2 +
 .../DependencyScanning/ModuleDepCollector.cpp |   4 +-
 clang/test/ClangScanDeps/diagnostics.c        |   2 +-
 .../header-search-pruning-transitive.c        |   4 +-
 .../ClangScanDeps/modules-context-hash-cwd.c  |  18 +-
 .../test/ClangScanDeps/modules-context-hash.c |   4 +-
 clang/test/ClangScanDeps/modules-dep-args.c   |   2 +-
 .../ClangScanDeps/modules-extern-submodule.c  |   2 +-
 .../ClangScanDeps/modules-extern-unrelated.m  |   2 +-
 .../modules-fmodule-name-no-module-built.m    |   2 +-
 .../modules-full-named-modules.cppm           | 347 ++++++++++++++++++
 .../modules-full-output-tu-order.c            |   4 +-
 clang/test/ClangScanDeps/modules-full.cpp     |   8 +-
 .../modules-has-include-umbrella-header.c     |   2 +-
 .../modules-implementation-private.m          |   2 +-
 .../modules-implicit-dot-private.m            |   2 +-
 .../modules-incomplete-umbrella.c             |   4 +-
 clang/test/ClangScanDeps/modules-inferred.m   |   2 +-
 .../modules-no-undeclared-includes.c          |   2 +-
 .../ClangScanDeps/modules-pch-common-stale.c  |   4 +-
 .../modules-pch-common-submodule.c            |   4 +-
 .../modules-pch-common-via-submodule.c        |   4 +-
 clang/test/ClangScanDeps/modules-pch.c        |   6 +-
 .../ClangScanDeps/modules-priv-fw-from-pub.m  |   2 +-
 clang/test/ClangScanDeps/multiple-commands.c  |   4 +-
 clang/test/ClangScanDeps/removed-args.c       |   2 +-
 clang/test/ClangScanDeps/tu-buffer.c          |   2 +-
 clang/tools/clang-scan-deps/ClangScanDeps.cpp |  24 +-
 29 files changed, 431 insertions(+), 50 deletions(-)
 create mode 100644 clang/test/ClangScanDeps/modules-full-named-modules.cppm

diff --git a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h
index cb5d7e36d21c9..ee24e5d1543d3 100644
--- a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h
+++ b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h
@@ -15,6 +15,7 @@
 #include "clang/Tooling/JSONCompilationDatabase.h"
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/MapVector.h"
+#include "llvm/ADT/STLExtras.h"
 #include <functional>
 #include <optional>
 #include <string>
@@ -56,6 +57,9 @@ struct TranslationUnitDeps {
   /// determined that the differences are benign for this compilation.
   std::vector<ModuleID> ClangModuleDeps;
 
+  /// A list of the C++20 named modules this translation unit depends on.
+  std::vector<std::string> NamedModuleDeps;
+
   /// The sequence of commands required to build the translation unit. Commands
   /// should be executed in order.
   ///
@@ -188,6 +192,14 @@ class FullDependencyConsumer : public DependencyConsumer {
     ContextHash = std::move(Hash);
   }
 
+  void handleProvidedAndRequiredStdCXXModules(
+      std::optional<P1689ModuleInfo> Provided,
+      std::vector<P1689ModuleInfo> Requires) override {
+    ModuleName = Provided ? Provided->ModuleName : "";
+    llvm::transform(Requires, std::back_inserter(NamedModuleDeps),
+                    [](const auto &Module) { return Module.ModuleName; });
+  }
+
   TranslationUnitDeps takeTranslationUnitDeps();
   ModuleDepsGraph takeModuleGraphDeps();
 
@@ -195,6 +207,8 @@ class FullDependencyConsumer : public DependencyConsumer {
   std::vector<std::string> Dependencies;
   std::vector<PrebuiltModuleDep> PrebuiltModuleDeps;
   llvm::MapVector<ModuleID, ModuleDeps> ClangModuleDeps;
+  std::string ModuleName;
+  std::vector<std::string> NamedModuleDeps;
   std::vector<ModuleID> DirectModuleDeps;
   std::vector<Command> Commands;
   std::string ContextHash;
diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp
index b015e79f400cf..515211d47b348 100644
--- a/clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp
+++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp
@@ -171,6 +171,8 @@ TranslationUnitDeps FullDependencyConsumer::takeTranslationUnitDeps() {
   TranslationUnitDeps TU;
 
   TU.ID.ContextHash = std::move(ContextHash);
+  TU.ID.ModuleName = std::move(ModuleName);
+  TU.NamedModuleDeps = std::move(NamedModuleDeps);
   TU.FileDeps = std::move(Dependencies);
   TU.PrebuiltModuleDeps = std::move(PrebuiltModuleDeps);
   TU.Commands = std::move(Commands);
diff --git a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
index b1495163ccc24..894b52a0a5673 100644
--- a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
+++ b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
@@ -714,7 +714,9 @@ void ModuleDepCollectorPP::EndOfMainFile() {
 
   MDC.Consumer.handleDependencyOutputOpts(*MDC.Opts);
 
-  if (MDC.Service.getFormat() == ScanningOutputFormat::P1689)
+  if (const auto Format = MDC.Service.getFormat();
+      Format == ScanningOutputFormat::P1689 ||
+      Format == ScanningOutputFormat::Full)
     MDC.Consumer.handleProvidedAndRequiredStdCXXModules(
         MDC.ProvidedStdCXXModule, MDC.RequiredStdCXXModules);
 
diff --git a/clang/test/ClangScanDeps/diagnostics.c b/clang/test/ClangScanDeps/diagnostics.c
index 8e3cf4c9f9fa6..5e99ba10b89f2 100644
--- a/clang/test/ClangScanDeps/diagnostics.c
+++ b/clang/test/ClangScanDeps/diagnostics.c
@@ -44,7 +44,7 @@ module mod { header "mod.h" }
 // CHECK-NEXT:   "translation-units": [
 // CHECK-NEXT:     {
 // CHECK:            "clang-context-hash": "[[HASH_TU:.*]],
-// CHECK-NEXT:       "clang-module-deps": [
+// CHECK:            "clang-module-deps": [
 // CHECK-NEXT:         {
 // CHECK-NEXT:           "context-hash": "[[HASH_MOD]]",
 // CHECK-NEXT:           "module-name": "mod"
diff --git a/clang/test/ClangScanDeps/header-search-pruning-transitive.c b/clang/test/ClangScanDeps/header-search-pruning-transitive.c
index 1e829bb02ddc4..09a746e9af26b 100644
--- a/clang/test/ClangScanDeps/header-search-pruning-transitive.c
+++ b/clang/test/ClangScanDeps/header-search-pruning-transitive.c
@@ -98,7 +98,7 @@ module X { header "X.h" }
 // CHECK-NEXT:   "translation-units": [
 // CHECK-NEXT:     {
 // CHECK:            "clang-context-hash": "{{.*}}",
-// CHECK-NEXT:       "clang-module-deps": [
+// CHECK:            "clang-module-deps": [
 // CHECK-NEXT:         {
 // CHECK-NEXT:           "context-hash": "[[HASH_X]]",
 // CHECK-NEXT:           "module-name": "X"
@@ -153,7 +153,7 @@ module X { header "X.h" }
 // CHECK-NEXT:   "translation-units": [
 // CHECK-NEXT:     {
 // CHECK:            "clang-context-hash": "{{.*}}",
-// CHECK-NEXT:       "clang-module-deps": [
+// CHECK:            "clang-module-deps": [
 // CHECK-NEXT:         {
 // CHECK-NEXT:           "context-hash": "{{.*}}",
 // CHECK-NEXT:           "module-name": "X"
diff --git a/clang/test/ClangScanDeps/modules-context-hash-cwd.c b/clang/test/ClangScanDeps/modules-context-hash-cwd.c
index c609a7dcbc80e..82cee2a19e2dc 100644
--- a/clang/test/ClangScanDeps/modules-context-hash-cwd.c
+++ b/clang/test/ClangScanDeps/modules-context-hash-cwd.c
@@ -75,7 +75,7 @@ module mod {
 // CHECK:     {
 // CHECK-NEXT:  "modules": [
 // CHECK-NEXT:   {
-// CHECK-NEXT:     "clang-module-deps": [],
+// CHECK:          "clang-module-deps": [],
 // CHECK:          "context-hash": "[[HASH:.*]]",
 // CHECK:        }
 // CHECK:       "translation-units": [
@@ -83,7 +83,7 @@ module mod {
 // CHECK:          "commands": [
 // CHECK:          {
 // CHECK-NEXT:        "clang-context-hash": "{{.*}}",
-// CHECK-NEXT:        "clang-module-deps": [
+// CHECK:             "clang-module-deps": [
 // CHECK-NEXT:          {
 // CHECK-NEXT:            "context-hash": "[[HASH]]",
 // CHECK-NEXT:            "module-name": "mod"
@@ -100,7 +100,7 @@ module mod {
 // CHECK:           "commands": [
 // CHECK:           {
 // CHECK-NEXT:         "clang-context-hash": "{{.*}}",
-// CHECK-NEXT:         "clang-module-deps": [
+// CHECK:              "clang-module-deps": [
 // CHECK-NEXT:           {
 // CHECK-NEXT:             "context-hash": "[[HASH]]",
 // CHECK-NEXT:             "module-name": "mod"
@@ -112,7 +112,7 @@ module mod {
 // SKIPOPT:      {
 // SKIPOPT-NEXT:   "modules": [
 // SKIPOPT-NEXT:    {
-// SKIPOPT-NEXT:      "clang-module-deps": [],
+// SKIPOPT:           "clang-module-deps": [],
 // SKIPOPT:           "context-hash": "[[HASH0:.*]]",
 // SKIPOPT:         }
 // SKIPOPT:        "translation-units": [
@@ -120,7 +120,7 @@ module mod {
 // SKIPOPT:            "commands": [
 // SKIPOPT:             {
 // SKIPOPT-NEXT:          "clang-context-hash": "{{.*}}",
-// SKIPOPT-NEXT:          "clang-module-deps": [
+// SKIPOPT:               "clang-module-deps": [
 // SKIPOPT-NEXT:            {
 // SKIPOPT-NEXT:              "context-hash": "[[HASH0]]",
 // SKIPOPT-NEXT:              "module-name": "mod"
@@ -129,7 +129,7 @@ module mod {
 // SKIPOPT:      {
 // SKIPOPT-NEXT:   "modules": [
 // SKIPOPT-NEXT:     {
-// SKIPOPT-NEXT:       "clang-module-deps": [],
+// SKIPOPT:            "clang-module-deps": [],
 // SKIPOPT-NOT:        "context-hash": "[[HASH0]]",
 // SKIPOPT:            "context-hash": "[[HASH2:.*]]",
 // SKIPOPT:          }
@@ -138,7 +138,7 @@ module mod {
 // SKIPOPT:           "commands": [
 // SKIPOPT:             {
 // SKIPOPT-NEXT:          "clang-context-hash": "{{.*}}",
-// SKIPOPT-NEXT:          "clang-module-deps": [
+// SKIPOPT:               "clang-module-deps": [
 // SKIPOPT-NEXT:            {
 // SKIPOPT-NOT:              "context-hash": "[[HASH0]]",
 // SKIPOPT-NEXT:             "context-hash": "[[HASH2]]"
@@ -160,7 +160,7 @@ module mod {
 // RELPATH:            "commands": [
 // RELPATH:             {
 // RELPATH-NEXT:          "clang-context-hash": "{{.*}}",
-// RELPATH-NEXT:          "clang-module-deps": [
+// RELPATH:               "clang-module-deps": [
 // RELPATH-NEXT:            {
 // RELPATH-NEXT:              "context-hash": "[[HASH3]]",
 // RELPATH-NEXT:              "module-name": "mod"
@@ -178,7 +178,7 @@ module mod {
 // RELPATH:           "commands": [
 // RELPATH:             {
 // RELPATH-NEXT:          "clang-context-hash": "{{.*}}",
-// RELPATH-NEXT:          "clang-module-deps": [
+// RELPATH:               "clang-module-deps": [
 // RELPATH-NEXT:            {
 // RELPATH-NOT:              "context-hash": "[[HASH3]]",
 // RELPATH-NEXT:             "context-hash": "[[HASH4]]"
diff --git a/clang/test/ClangScanDeps/modules-context-hash.c b/clang/test/ClangScanDeps/modules-context-hash.c
index 9489563576d3b..0622e1dd96974 100644
--- a/clang/test/ClangScanDeps/modules-context-hash.c
+++ b/clang/test/ClangScanDeps/modules-context-hash.c
@@ -45,7 +45,7 @@
 // CHECK-NEXT:   "translation-units": [
 // CHECK-NEXT:     {
 // CHECK:            "clang-context-hash": "{{.*}}",
-// CHECK-NEXT:       "clang-module-deps": [
+// CHECK:            "clang-module-deps": [
 // CHECK-NEXT:         {
 // CHECK-NEXT:           "context-hash": "[[HASH_MOD_A]]",
 // CHECK-NEXT:           "module-name": "mod"
@@ -83,7 +83,7 @@
 // CHECK-NEXT:   "translation-units": [
 // CHECK-NEXT:     {
 // CHECK:            "clang-context-hash": "{{.*}}",
-// CHECK-NEXT:       "clang-module-deps": [
+// CHECK:            "clang-module-deps": [
 // CHECK-NEXT:         {
 // CHECK-NOT:            "context-hash": "[[HASH_MOD_A]]",
 // CHECK:                "module-name": "mod"
diff --git a/clang/test/ClangScanDeps/modules-dep-args.c b/clang/test/ClangScanDeps/modules-dep-args.c
index 19f915923b84c..41b06580fabb7 100644
--- a/clang/test/ClangScanDeps/modules-dep-args.c
+++ b/clang/test/ClangScanDeps/modules-dep-args.c
@@ -81,7 +81,7 @@ module Direct { header "direct.h" }
 // CHECK-NEXT:   "translation-units": [
 // CHECK-NEXT:     {
 // CHECK:            "clang-context-hash": "{{.*}}",
-// CHECK-NEXT:       "clang-module-deps": [
+// CHECK:            "clang-module-deps": [
 // CHECK-NEXT:         {
 // CHECK-NEXT:           "context-hash": "{{.*}}",
 // CHECK-NEXT:           "module-name": "Direct"
diff --git a/clang/test/ClangScanDeps/modules-extern-submodule.c b/clang/test/ClangScanDeps/modules-extern-submodule.c
index 01d3d6ba5e0d3..757bcdf46edac 100644
--- a/clang/test/ClangScanDeps/modules-extern-submodule.c
+++ b/clang/test/ClangScanDeps/modules-extern-submodule.c
@@ -101,7 +101,7 @@ module third {}
 // CHECK-NEXT:       "commands": [
 // CHECK-NEXT:         {
 // CHECK-NEXT:           "clang-context-hash": "{{.*}}",
-// CHECK-NEXT:           "clang-module-deps": [
+// CHECK:                "clang-module-deps": [
 // CHECK-NEXT:             {
 // CHECK-NEXT:               "context-hash": "{{.*}}",
 // CHECK-NEXT:               "module-name": "first"
diff --git a/clang/test/ClangScanDeps/modules-extern-unrelated.m b/clang/test/ClangScanDeps/modules-extern-unrelated.m
index c003f0d9a2ee8..b81dad896c1ff 100644
--- a/clang/test/ClangScanDeps/modules-extern-unrelated.m
+++ b/clang/test/ClangScanDeps/modules-extern-unrelated.m
@@ -107,7 +107,7 @@
 // CHECK-NEXT:       "commands": [
 // CHECK-NEXT:         {
 // CHECK-NEXT:           "clang-context-hash": "{{.*}}",
-// CHECK-NEXT:           "clang-module-deps": [
+// CHECK:                "clang-module-deps": [
 // CHECK-NEXT:             {
 // CHECK-NEXT:               "context-hash": "{{.*}}",
 // CHECK-NEXT:               "module-name": "zeroth"
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..1078545848f20 100644
--- a/clang/test/ClangScanDeps/modules-fmodule-name-no-module-built.m
+++ b/clang/test/ClangScanDeps/modules-fmodule-name-no-module-built.m
@@ -35,7 +35,7 @@
 // CHECK-NEXT:   "translation-units": [
 // CHECK-NEXT:     {
 // CHECK:            "clang-context-hash": "[[HASH_TU:[A-Z0-9]+]]",
-// CHECK-NEXT:       "clang-module-deps": [
+// CHECK:            "clang-module-deps": [
 // CHECK-NEXT:         {
 // CHECK-NEXT:           "context-hash": "[[HASH_H2]]",
 // CHECK-NEXT:           "module-name": "header2"
diff --git a/clang/test/ClangScanDeps/modules-full-named-modules.cppm b/clang/test/ClangScanDeps/modules-full-named-modules.cppm
new file mode 100644
index 0000000000000..e042b702a1fa7
--- /dev/null
+++ b/clang/test/ClangScanDeps/modules-full-named-modules.cppm
@@ -0,0 +1,347 @@
+// This check that clang-scan-deps properly outputs named module dependencies 
+// when using the the scanning output format 'experimental-full'.
+//
+// See commit 72304.
+// UNSUPPORTED: target={{.*}}-aix{{.*}}
+//
+// The slash direction in linux and windows are different.
+// UNSUPPORTED: system-windows
+//
+// RUN: rm -fr %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
+// Check the separated dependency format.
+// RUN: sed "s|DIR|%/t|g" %t/compile_commands.json.in > %t/compile_commands.json
+// RUN: clang-scan-deps -format=experimental-full \
+// RUN:   -- %clang++ -std=c++20 -c -fprebuilt-module-path=%t %t/M.cppm -o %t/M.o \
+// RUN:   | FileCheck %t/M.cppm -DPREFIX=%/t
+// RUN: clang-scan-deps -format=experimental-full \
+// RUN:   -- %clang++ -std=c++20 -c -fprebuilt-module-path=%t %t/Impl.cpp -o %t/Impl.o \
+// RUN:   | FileCheck %t/Impl.cpp -DPREFIX=%/t
+// RUN: clang-scan-deps -format=experimental-full \
+// RUN:   -- %clang++ -std=c++20 -c -fprebuilt-module-path=%t %t/impl_part.cppm -o %t/impl_part.o \
+// RUN:   | FileCheck %t/impl_part.cppm -DPREFIX=%/t
+// RUN: clang-scan-deps -format=experimental-full \
+// RUN:   -- %clang++ -std=c++20 -c -fprebuilt-module-path=%t %t/interface_part.cppm -o %t/interface_part.o \
+// RUN:   | FileCheck %t/interface_part.cppm -DPREFIX=%/t
+// RUN: clang-scan-deps -format=experimental-full \
+// RUN:   -- %clang++ -std=c++20 -c -fprebuilt-module-path=%t %t/User.cpp -o %t/User.o \
+// RUN:   | FileCheck %t/User.cpp -DPREFIX=%/t
+//
+// Check the combined dependency format.
+// RUN: clang-scan-deps -compilation-database %t/compile_commands.json -format=experimental-full \
+// RUN:   | FileCheck %t/Checks.cpp -DPREFIX=%/t
+// RUN: clang-scan-deps --mode=preprocess-dependency-directives -compilation-database %t/compile_commands.json -format=experimental-full \
+// RUN:   | FileCheck %t/Checks.cpp -DPREFIX=%/t
+
+//--- compile_commands.json.in
+[
+{
+  "directory": "DIR",
+  "command": "clang++ -std=c++20 DIR/M.cppm -c -o DIR/M.o -MT DIR/M.o.ddi -MD -MF DIR/P1689.dep",
+  "file": "DIR/M.cppm",
+  "output": "DIR/M.o"
+},
+{
+  "directory": "DIR",
+  "command": "clang++ -std=c++20 DIR/Impl.cpp -c -o DIR/Impl.o -MT DIR/Impl.o.ddi -MD -MF DIR/P1689.dep",
+  "file": "DIR/Impl.cpp",
+  "output": "DIR/Impl.o"
+},
+{
+  "directory": "DIR",
+  "command": "clang++ -std=c++20 DIR/impl_part.cppm -c -o DIR/impl_part.o -MT DIR/impl_part.o.ddi -MD -MF DIR/P1689.dep",
+  "file": "DIR/impl_part.cppm",
+  "output": "DIR/impl_part.o"
+},
+{
+  "directory": "DIR",
+  "command": "clang++ -std=c++20 DIR/interface_part.cppm -c -o DIR/interface_part.o -MT DIR/interface_part.o.ddi -MD -MF DIR/P1689.dep",
+  "file": "DIR/interface_part.cppm",
+  "output": "DIR/interface_part.o"
+},
+{
+  "directory": "DIR",
+  "command": "clang++ -std=c++20 DIR/User.cpp -c -o DIR/User.o -MT DIR/User.o.ddi -MD -MF DIR/P1689.dep",
+  "file": "DIR/User.cpp",
+  "output": "DIR/User.o"
+}
+]
+
+//--- M.cppm
+export module M;
+export import :interface_part;
+import :impl_part;
+export void Hello();
+
+// CHECK:       {
+// CHECK:         "modules": []
+// CHECK:         "translation-units": [
+// CHECK-NEXT:      {
+// CHECK:             "commands": [
+// CHECK-NEXT:          {
+// CHECK:                 "module-name": "M"
+// CHECK-NEXT:            "named-module-deps": [
+// CHECK-NEXT:              "M:interface_part",
+// CHECK-NEXT:              "M:impl_part"
+// CHECK-NEXT:             ]
+// CHECK:                 "command-line": [
+// CHECK:                   "-o",
+// CHECK-NEXT:              "{{.*}}/M-{{.*}}.pcm"
+// CHECK:                 ]
+// CHECK:                 "input-file": "[[PREFIX]]/M.cppm"
+// CHECK:               },
+// CHECK-NEXT:          {
+// CHECK:                 "command-line": [
+// CHECK:                   "-o",
+// CHECK-NEXT:              "[[PREFIX]]/M.o"
+// CHECK:                 ]
+// CHECK:                 "input-file": "[[PREFIX]]/M.cppm"
+// CHECK:               }
+// CHECK:             ]
+// CHECK:           }
+// CHECK:         ]
+// CHECK:       }
+
+//--- Impl.cpp
+module;
+#include "header.mock"
+module M;
+void Hello() {
+    std::cout << "Hello ";
+}
+
+// CHECK:       {
+// CHECK:         "modules": []
+// CHECK:         "translation-units": [
+// CHECK-NEXT:      {
+// CHECK:             "commands": [
+// CHECK-NEXT:          {
+// CHECK-NOT:             "module-name":
+// CHECK:                 "named-module-deps": [
+// CHECK-NEXT:              "M"
+// CHECK-NEXT:             ]
+// CHECK:                 "command-line": [
+// CHECK:                   "-o",
+// CHECK-NEXT:              "[[PREFIX]]/Impl.o"
+// CHECK:                 ]
+// CHECK:                 "input-file": "[[PREFIX]]/Impl.cpp"
+// CHECK:               }
+// CHECK:             ]
+// CHECK:           }
+// CHECK:         ]
+// CHECK:       }
+
+//--- impl_part.cppm
+module;
+#include "header.mock"
+module M:impl_part;
+import :interface_part;
+
+std::string W = "World.";
+void World() {
+    std::cout << W << std::endl;
+}
+
+// CHECK:       {
+// CHECK:         "modules": [],
+// CHECK:         "translation-units": [
+// CHECK-NEXT:      {
+// CHECK:             "commands": [
+// CHECK-NEXT:          {
+// CHECK:                 "module-name": "M:impl_part"
+// CHECK-NEXT:            "named-module-deps": [
+// CHECK-NEXT:              "M:interface_part"
+// CHECK-NEXT:             ]
+// CHECK:                 "command-line": [
+// CHECK:                   "-o",
+// CHECK-NEXT:              "{{.*}}/impl_part-{{.*}}.pcm",
+// CHECK:                 ]
+// CHECK:                 "input-file": "[[PREFIX]]/impl_part.cppm"
+// CHECK:               },
+// CHECK-NEXT:          {
+// CHECK:                 "module-name": "M:impl_part"
+// CHECK-NEXT:            "named-module-deps": [
+// CHECK-NEXT:              "M:interface_part"
+// CHECK-NEXT:             ]
+// CHECK:                 "command-line": [
+// CHECK:                   "-o",
+// CHECK-NEXT:              "[[PREFIX]]/impl_part.o",
+// CHECK:                 ]
+// CHECK:                 "input-file": "[[PREFIX]]/impl_part.cppm"
+// CHECK:               }
+// CHECK:             ]
+// CHECK:           }
+// CHECK:         ]
+// CHECK:       }
+
+//--- interface_part.cppm
+export module M:interface_part;
+export void World();
+
+// CHECK:       {
+// CHECK:         "modules": []
+// CHECK:         "translation-units": [
+// CHECK-NEXT:      {
+// CHECK:             "commands": [
+// CHECK-NEXT:          {
+// CHECK:                 "module-name": "M:interface_part"
+// CHECK-NEXT:            "named-module-deps": []
+// CHECK:                 "command-line": [
+// CHECK:                   "-o",
+// CHECK-NEXT:              "{{.*}}/interface_part-{{.*}}.pcm",
+// CHECK:                 ]
+// CHECK:                 "input-file": "[[PREFIX]]/interface_part.cppm"
+// CHECK:               },
+// CHECK-NEXT:          {
+// CHECK:                 "module-name": "M:interface_part"
+// CHECK-NEXT:            "named-module-deps": []
+// CHECK:                 "command-line": [
+// CHECK:                   "-o",
+// CHECK-NEXT:              "[[PREFIX]]/interface_part.o",
+// CHECK:                 ]
+// CHECK:                 "input-file": "[[PREFIX]]/interface_part.cppm"
+// CHECK:               }
+// CHECK:             ]
+// CHECK:           }
+// CHECK:         ]
+// CHECK:       }
+
+//--- User.cpp
+import M;
+import third_party_module;
+int main() {
+    Hello();
+    World();
+    return 0;
+}
+
+// CHECK:       {
+// CHECK-NEXT:    "modules": []
+// CHECK-NEXT:    "translation-units": [
+// CHECK-NEXT:      {
+// CHECK-NEXT:        "commands": [
+// CHECK-NEXT:          {
+// CHECK-NOT:             "module-name":
+// CHECK:                 "named-module-deps": [
+// CHECK-NEXT:              "M"
+// CHECK-NEXT:              "third_party_module"
+// CHECK-NEXT:             ]
+// CHECK:                 "command-line": [
+// CHECK:                   "-o",
+// CHECK-NEXT:              "[[PREFIX]]/User.o",
+// CHECK:                 ]
+// CHECK:                 "input-file": "[[PREFIX]]/User.cpp
+// CHECK:               }
+// CHECK:             ]
+// CHECK-NEXT:      }
+// CHECK-NEXT:    ]
+// CHECK:       }
+
+//--- header.mock
+  
+//--- Checks.cpp
+// CHECK:       {
+// CHECK:         "modules": []
+// CHECK:         "translation-units": [
+// CHECK-NEXT:      {
+// CHECK:             "commands": [
+// CHECK-NEXT:          {
+// CHECK:                 "module-name": "M"
+// CHECK-NEXT:            "named-module-deps": [
+// CHECK-NEXT:              "M:interface_part",
+// CHECK-NEXT:              "M:impl_part"
+// CHECK-NEXT:             ]
+// CHECK:                 "command-line": [
+// CHECK:                   "-o",
+// CHECK-NEXT:              "{{.*}}/M-{{.*}}.pcm"
+// CHECK:                 ]
+// CHECK:                 "input-file": "[[PREFIX]]/M.cppm"
+// CHECK:               },
+// CHECK-NEXT:          {
+// CHECK:                 "command-line": [
+// CHECK:                   "-o",
+// CHECK-NEXT:              "[[PREFIX]]/M.o"
+// CHECK:                 ]
+// CHECK:                 "input-file": "[[PREFIX]]/M.cppm"
+// CHECK:               },
+// CHECK:               {
+// CHECK-NOT:             "module-name":
+// CHECK:                 "named-module-deps": [
+// CHECK-NEXT:              "M"
+// CHECK-NEXT:             ]
+// CHECK:                 "command-line": [
+// CHECK:                   "-o",
+// CHECK-NEXT:              "[[PREFIX]]/Impl.o"
+// CHECK:                 ]
+// CHECK:                 "input-file": "[[PREFIX]]/Impl.cpp"
+// CHECK:               }
+// CHECK:             ]
+// CHECK-NEXT:      },
+// CHECK-NEXT:      {
+// CHECK:             "commands": [
+// CHECK-NEXT:          {
+// CHECK:                 "module-name": "M:impl_part"
+// CHECK-NEXT:            "named-module-deps": [
+// CHECK-NEXT:              "M:interface_part"
+// CHECK-NEXT:             ]
+// CHECK:                 "command-line": [
+// CHECK:                   "-o",
+// CHECK-NEXT:              "{{.*}}/impl_part-{{.*}}.pcm",
+// CHECK:                 ]
+// CHECK:                 "input-file": "[[PREFIX]]/impl_part.cppm"
+// CHECK:               },
+// CHECK-NEXT:          {
+// CHECK:                 "module-name": "M:impl_part"
+// CHECK-NEXT:            "named-module-deps": [
+// CHECK-NEXT:              "M:interface_part"
+// CHECK-NEXT:             ]
+// CHECK:                 "command-line": [
+// CHECK:                   "-o",
+// CHECK-NEXT:              "[[PREFIX]]/impl_part.o",
+// CHECK:                 ]
+// CHECK:                 "input-file": "[[PREFIX]]/impl_part.cppm"
+// CHECK:               }
+// CHECK:             ]
+// CHECK-NEXT:      },
+// CHECK-NEXT:      {
+// CHECK:             "commands": [
+// CHECK-NEXT:          {
+// CHECK:                 "module-name": "M:interface_part"
+// CHECK-NEXT:            "named-module-deps": []
+// CHECK:                 "command-line": [
+// CHECK:                   "-o",
+// CHECK-NEXT:              "{{.*}}/interface_part-{{.*}}.pcm",
+// CHECK:                 ]
+// CHECK:                 "input-file": "[[PREFIX]]/interface_part.cppm"
+// CHECK:               },
+// CHECK-NEXT:          {
+// CHECK:                 "module-name": "M:interface_part"
+// CHECK-NEXT:            "named-module-deps": []
+// CHECK:                 "command-line": [
+// CHECK:                   "-o",
+// CHECK-NEXT:              "[[PREFIX]]/interface_part.o",
+// CHECK:                 ]
+// CHECK:                 "input-file": "[[PREFIX]]/interface_part.cppm"
+// CHECK:               }
+// CHECK:             ]
+// CHECK-NEXT:      },
+// CHECK-NEXT:      {
+// CHECK:             "commands": [
+// CHECK-NEXT:          {
+// CHECK-NOT:             "module-name":
+// CHECK:                 "named-module-deps": [
+// CHECK-NEXT:              "M"
+// CHECK-NEXT:              "third_party_module"
+// CHECK-NEXT:             ]
+// CHECK:                 "command-line": [
+// CHECK:                   "-o",
+// CHECK-NEXT:              "[[PREFIX]]/User.o",
+// CHECK:                 ]
+// CHECK:                 "input-file": "[[PREFIX]]/User.cpp
+// CHECK:               } 
+// CHECK:             ]
+// CHECK:           }
+// CHECK:         ]
+// CHECK:       }
diff --git a/clang/test/ClangScanDeps/modules-full-output-tu-order.c b/clang/test/ClangScanDeps/modules-full-output-tu-order.c
index 065b8ac8ae07f..4f5f753fe831e 100644
--- a/clang/test/ClangScanDeps/modules-full-output-tu-order.c
+++ b/clang/test/ClangScanDeps/modules-full-output-tu-order.c
@@ -30,7 +30,7 @@
 // CHECK-NEXT:       "commands": [
 // CHECK-NEXT:         {
 // CHECK-NEXT:           "clang-context-hash": "{{.*}}",
-// CHECK-NEXT:           "clang-module-deps": [],
+// CHECK:                "clang-module-deps": [],
 // CHECK-NEXT:           "command-line": [
 // CHECK:                  "-D"
 // CHECK-NEXT:             "ONE"
@@ -46,7 +46,7 @@
 // CHECK-NEXT:       "commands": [
 // CHECK-NEXT:         {
 // CHECK-NEXT:           "clang-context-hash": "{{.*}}",
-// CHECK-NEXT:           "clang-module-deps": [],
+// CHECK:                "clang-module-deps": [],
 // 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..044fab3a72af8 100644
--- a/clang/test/ClangScanDeps/modules-full.cpp
+++ b/clang/test/ClangScanDeps/modules-full.cpp
@@ -91,7 +91,7 @@
 // CHECK-NEXT:       "commands": [
 // CHECK-NEXT:         {
 // CHECK-NEXT:           "clang-context-hash": "[[HASH_TU_DINCLUDE:[A-Z0-9]+]]",
-// CHECK-NEXT:           "clang-module-deps": [
+// CHECK:                "clang-module-deps": [
 // CHECK-NEXT:             {
 // CHECK-NEXT:               "context-hash": "[[HASH_H1_DINCLUDE]]",
 // CHECK-NEXT:               "module-name": "header1"
@@ -114,7 +114,7 @@
 // CHECK-NEXT:       "commands": [
 // CHECK-NEXT:         {
 // CHECK-NEXT:           "clang-context-hash": "[[HASH_TU:[A-Z0-9]+]]",
-// CHECK-NEXT:           "clang-module-deps": [
+// CHECK:                "clang-module-deps": [
 // CHECK-NEXT:             {
 // CHECK-NEXT:               "context-hash": "[[HASH_H1]]",
 // CHECK-NEXT:               "module-name": "header1"
@@ -137,7 +137,7 @@
 // CHECK-NEXT:       "commands": [
 // CHECK-NEXT:         {
 // CHECK-NEXT:           "clang-context-hash": "[[HASH_TU:[A-Z0-9]+]]",
-// CHECK-NEXT:           "clang-module-deps": [
+// CHECK:                "clang-module-deps": [
 // CHECK-NEXT:             {
 // CHECK-NEXT:               "context-hash": "[[HASH_H1]]",
 // CHECK-NEXT:               "module-name": "header1"
@@ -160,7 +160,7 @@
 // CHECK-NEXT:       "commands": [
 // CHECK-NEXT:         {
 // CHECK-NEXT:           "clang-context-hash": "[[HASH_TU:[A-Z0-9]+]]",
-// CHECK-NEXT:           "clang-module-deps": [
+// CHECK:                "clang-module-deps": [
 // CHECK-NEXT:             {
 // CHECK-NEXT:               "context-hash": "[[HASH_H1]]",
 // CHECK-NEXT:               "module-name": "header1"
diff --git a/clang/test/ClangScanDeps/modules-has-include-umbrella-header.c b/clang/test/ClangScanDeps/modules-has-include-umbrella-header.c
index 022c59ca65db2..8996d83b0eede 100644
--- a/clang/test/ClangScanDeps/modules-has-include-umbrella-header.c
+++ b/clang/test/ClangScanDeps/modules-has-include-umbrella-header.c
@@ -56,7 +56,7 @@ module Dependency { header "dependency.h" }
 // CHECK-NEXT:       "commands": [
 // CHECK-NEXT:         {
 // CHECK-NEXT:           "clang-context-hash": "{{.*}}",
-// CHECK-NEXT:           "clang-module-deps": [
+// CHECK:                "clang-module-deps": [
 // CHECK-NEXT:             {
 // CHECK-NEXT:               "context-hash": "{{.*}}",
 // CHECK-NEXT:               "module-name": "FW_Private"
diff --git a/clang/test/ClangScanDeps/modules-implementation-private.m b/clang/test/ClangScanDeps/modules-implementation-private.m
index b376073f4b9ee..c52156dbe9d0f 100644
--- a/clang/test/ClangScanDeps/modules-implementation-private.m
+++ b/clang/test/ClangScanDeps/modules-implementation-private.m
@@ -54,7 +54,7 @@
 // CHECK-NEXT:       "commands": [
 // CHECK-NEXT:         {
 // CHECK-NEXT:           "clang-context-hash": "{{.*}}",
-// CHECK-NEXT:           "clang-module-deps": [
+// CHECK:                "clang-module-deps": [
 // CHECK-NEXT:             {
 // CHECK-NEXT:               "context-hash": "{{.*}}",
 // CHECK-NEXT:               "module-name": "FW_Private"
diff --git a/clang/test/ClangScanDeps/modules-implicit-dot-private.m b/clang/test/ClangScanDeps/modules-implicit-dot-private.m
index aa8caf3451dc4..bc39e2020e230 100644
--- a/clang/test/ClangScanDeps/modules-implicit-dot-private.m
+++ b/clang/test/ClangScanDeps/modules-implicit-dot-private.m
@@ -65,7 +65,7 @@
 // CHECK-NEXT:   "translation-units": [
 // CHECK-NEXT:     {
 // CHECK:            "clang-context-hash": "{{.*}}",
-// CHECK-NEXT:       "clang-module-deps": [
+// CHECK:            "clang-module-deps": [
 // CHECK-NEXT:         {
 // CHECK-NEXT:           "context-hash": "{{.*}}",
 // CHECK-NEXT:           "module-name": "FW"
diff --git a/clang/test/ClangScanDeps/modules-incomplete-umbrella.c b/clang/test/ClangScanDeps/modules-incomplete-umbrella.c
index 696e621960b6f..bb4f1e6220f1c 100644
--- a/clang/test/ClangScanDeps/modules-incomplete-umbrella.c
+++ b/clang/test/ClangScanDeps/modules-incomplete-umbrella.c
@@ -78,7 +78,7 @@ framework module FW_Private {
 // CHECK_TU-NEXT:   "translation-units": [
 // CHECK_TU-NEXT:     {
 // CHECK_TU:            "clang-context-hash": "{{.*}}",
-// CHECK_TU-NEXT:       "clang-module-deps": [
+// CHECK_TU:            "clang-module-deps": [
 // CHECK_TU-NEXT:         {
 // CHECK_TU-NEXT:           "context-hash": "{{.*}}",
 // CHECK_TU-NEXT:           "module-name": "FW"
@@ -195,7 +195,7 @@ module Mod { header "Mod.h" }
 // CHECK_MODULE-NEXT:   "translation-units": [
 // CHECK_MODULE-NEXT:     {
 // CHECK_MODULE:            "clang-context-hash": "{{.*}}",
-// CHECK_MODULE-NEXT:       "clang-module-deps": [
+// CHECK_MODULE:            "clang-module-deps": [
 // CHECK_MODULE-NEXT:         {
 // CHECK_MODULE-NEXT:           "context-hash": "{{.*}}",
 // CHECK_MODULE-NEXT:           "module-name": "Mod"
diff --git a/clang/test/ClangScanDeps/modules-inferred.m b/clang/test/ClangScanDeps/modules-inferred.m
index 4c7a4095c9bef..ea146993c48df 100644
--- a/clang/test/ClangScanDeps/modules-inferred.m
+++ b/clang/test/ClangScanDeps/modules-inferred.m
@@ -55,7 +55,7 @@
 // CHECK-NEXT:       "commands": [
 // CHECK-NEXT:         {
 // CHECK-NEXT:           "clang-context-hash": "{{.*}}",
-// CHECK-NEXT:           "clang-module-deps": [
+// CHECK:                "clang-module-deps": [
 // CHECK-NEXT:             {
 // CHECK-NEXT:               "context-hash": "{{.*}}",
 // CHECK-NEXT:               "module-name": "Inferred"
diff --git a/clang/test/ClangScanDeps/modules-no-undeclared-includes.c b/clang/test/ClangScanDeps/modules-no-undeclared-includes.c
index 6110c419949f9..fdfb7057f9724 100644
--- a/clang/test/ClangScanDeps/modules-no-undeclared-includes.c
+++ b/clang/test/ClangScanDeps/modules-no-undeclared-includes.c
@@ -54,7 +54,7 @@ module User [no_undeclared_includes] { header "user.h" }
 // CHECK-NEXT:   "translation-units": [
 // CHECK-NEXT:     {
 // CHECK:            "clang-context-hash": "{{.*}}"
-// CHECK-NEXT:       "clang-module-deps": [
+// CHECK:            "clang-module-deps": [
 // CHECK-NEXT:         {
 // CHECK-NEXT:           "context-hash": "{{.*}}"
 // CHECK-NEXT:           "module-name": "User"
diff --git a/clang/test/ClangScanDeps/modules-pch-common-stale.c b/clang/test/ClangScanDeps/modules-pch-common-stale.c
index 72a4dc949b0f5..620d50f9f2819 100644
--- a/clang/test/ClangScanDeps/modules-pch-common-stale.c
+++ b/clang/test/ClangScanDeps/modules-pch-common-stale.c
@@ -62,7 +62,7 @@ module mod_tu_extra { header "mod_tu_extra.h" }
 // CHECK-TU-CLEAN-NEXT:       "commands": [
 // CHECK-TU-CLEAN-NEXT:         {
 // CHECK-TU-CLEAN-NEXT:           "clang-context-hash": "{{.*}}",
-// CHECK-TU-CLEAN-NEXT:           "clang-module-deps": [
+// CHECK-TU-CLEAN:                "clang-module-deps": [
 // CHECK-TU-CLEAN-NEXT:             {
 // CHECK-TU-CLEAN-NEXT:               "context-hash": "{{.*}}",
 // CHECK-TU-CLEAN-NEXT:               "module-name": "mod_tu"
@@ -149,7 +149,7 @@ module mod_tu_extra { header "mod_tu_extra.h" }
 // CHECK-TU-INCREMENTAL-NEXT:       "commands": [
 // CHECK-TU-INCREMENTAL-NEXT:         {
 // CHECK-TU-INCREMENTAL-NEXT:           "clang-context-hash": "{{.*}}",
-// CHECK-TU-INCREMENTAL-NEXT:           "clang-module-deps": [
+// CHECK-TU-INCREMENTAL:                "clang-module-deps": [
 // CHECK-TU-INCREMENTAL-NEXT:             {
 // CHECK-TU-INCREMENTAL-NEXT:               "context-hash": "{{.*}}",
 // CHECK-TU-INCREMENTAL-NEXT:               "module-name": "mod_tu"
diff --git a/clang/test/ClangScanDeps/modules-pch-common-submodule.c b/clang/test/ClangScanDeps/modules-pch-common-submodule.c
index 59dd3f172d8ee..06e14a8fc1e0e 100644
--- a/clang/test/ClangScanDeps/modules-pch-common-submodule.c
+++ b/clang/test/ClangScanDeps/modules-pch-common-submodule.c
@@ -38,7 +38,7 @@
 // CHECK-PCH-NEXT:   "translation-units": [
 // CHECK-PCH-NEXT:     {
 // CHECK-PCH:            "clang-context-hash": "[[HASH_PCH:.*]]",
-// CHECK-PCH-NEXT:       "clang-module-deps": [
+// CHECK-PCH:            "clang-module-deps": [
 // CHECK-PCH-NEXT:         {
 // CHECK-PCH-NEXT:           "context-hash": "[[HASH_MOD_COMMON]]",
 // CHECK-PCH-NEXT:           "module-name": "ModCommon"
@@ -86,7 +86,7 @@
 // CHECK-TU-NEXT:   "translation-units": [
 // CHECK-TU-NEXT:     {
 // CHECK-TU:            "clang-context-hash": "[[HASH_TU:.*]]",
-// CHECK-TU-NEXT:       "clang-module-deps": [
+// CHECK-TU:            "clang-module-deps": [
 // CHECK-TU-NEXT:         {
 // CHECK-TU-NEXT:           "context-hash": "[[HASH_MOD_TU]]"
 // CHECK-TU-NEXT:           "module-name": "ModTU"
diff --git a/clang/test/ClangScanDeps/modules-pch-common-via-submodule.c b/clang/test/ClangScanDeps/modules-pch-common-via-submodule.c
index a12492c0bec70..13eee81b8ec85 100644
--- a/clang/test/ClangScanDeps/modules-pch-common-via-submodule.c
+++ b/clang/test/ClangScanDeps/modules-pch-common-via-submodule.c
@@ -34,7 +34,7 @@
 // CHECK-PCH-NEXT:   "translation-units": [
 // CHECK-PCH-NEXT:     {
 // CHECK-PCH:            "clang-context-hash": "[[HASH_PCH:.*]]",
-// CHECK-PCH-NEXT:       "clang-module-deps": [
+// CHECK-PCH:            "clang-module-deps": [
 // CHECK-PCH-NEXT:         {
 // CHECK-PCH-NEXT:           "context-hash": "[[HASH_MOD_COMMON]]",
 // CHECK-PCH-NEXT:           "module-name": "ModCommon"
@@ -83,7 +83,7 @@
 // CHECK-TU-NEXT:   "translation-units": [
 // CHECK-TU-NEXT:     {
 // CHECK-TU:            "clang-context-hash": "[[HASH_TU:.*]]",
-// CHECK-TU-NEXT:       "clang-module-deps": [
+// CHECK-TU:            "clang-module-deps": [
 // CHECK-TU-NEXT:         {
 // CHECK-TU-NEXT:           "context-hash": "[[HASH_MOD_TU]]"
 // CHECK-TU-NEXT:           "module-name": "ModTU"
diff --git a/clang/test/ClangScanDeps/modules-pch.c b/clang/test/ClangScanDeps/modules-pch.c
index 92b7f41ac4b9f..7998b69e87fd0 100644
--- a/clang/test/ClangScanDeps/modules-pch.c
+++ b/clang/test/ClangScanDeps/modules-pch.c
@@ -66,7 +66,7 @@
 // CHECK-PCH-NEXT:   "translation-units": [
 // CHECK-PCH-NEXT:     {
 // CHECK-PCH:            "clang-context-hash": "[[HASH_PCH:.*]]",
-// CHECK-PCH-NEXT:       "clang-module-deps": [
+// CHECK-PCH:            "clang-module-deps": [
 // CHECK-PCH-NEXT:         {
 // CHECK-PCH-NEXT:           "context-hash": "[[HASH_MOD_COMMON_1]]",
 // CHECK-PCH-NEXT:           "module-name": "ModCommon1"
@@ -123,7 +123,7 @@
 // CHECK-TU-NEXT:   "translation-units": [
 // CHECK-TU-NEXT:     {
 // CHECK-TU:            "clang-context-hash": "[[HASH_TU:.*]]",
-// CHECK-TU-NEXT:       "clang-module-deps": [
+// CHECK-TU:            "clang-module-deps": [
 // CHECK-TU-NEXT:         {
 // CHECK-TU-NEXT:           "context-hash": "[[HASH_MOD_TU]]",
 // CHECK-TU-NEXT:           "module-name": "ModTU"
@@ -173,7 +173,7 @@
 // CHECK-TU-WITH-COMMON-NEXT:   "translation-units": [
 // CHECK-TU-WITH-COMMON-NEXT:     {
 // CHECK-TU-WITH-COMMON:            "clang-context-hash": "[[HASH_TU_WITH_COMMON:.*]]",
-// CHECK-TU-WITH-COMMON-NEXT:       "clang-module-deps": [
+// CHECK-TU-WITH-COMMON:            "clang-module-deps": [
 // CHECK-TU-WITH-COMMON-NEXT:         {
 // CHECK-TU-WITH-COMMON-NEXT:           "context-hash": "[[HASH_MOD_TU_WITH_COMMON]]",
 // CHECK-TU-WITH-COMMON-NEXT:           "module-name": "ModTUWithCommon"
diff --git a/clang/test/ClangScanDeps/modules-priv-fw-from-pub.m b/clang/test/ClangScanDeps/modules-priv-fw-from-pub.m
index dd314e1a3006a..acc1c797fbae4 100644
--- a/clang/test/ClangScanDeps/modules-priv-fw-from-pub.m
+++ b/clang/test/ClangScanDeps/modules-priv-fw-from-pub.m
@@ -102,7 +102,7 @@
 // CHECK-NEXT:       "commands": [
 // CHECK-NEXT:         {
 // CHECK-NEXT:           "clang-context-hash": "{{.*}}",
-// CHECK-NEXT:           "clang-module-deps": [
+// CHECK:                "clang-module-deps": [
 // CHECK-NEXT:             {
 // CHECK-NEXT:               "context-hash": "{{.*}}",
 // CHECK-NEXT:               "module-name": "FW"
diff --git a/clang/test/ClangScanDeps/multiple-commands.c b/clang/test/ClangScanDeps/multiple-commands.c
index bb169ea10995a..1eb8ed5f6b853 100644
--- a/clang/test/ClangScanDeps/multiple-commands.c
+++ b/clang/test/ClangScanDeps/multiple-commands.c
@@ -44,7 +44,7 @@
 // CHECK:          "commands": [
 // CHECK-NEXT:       {
 // CHECK-NEXT:         "clang-context-hash":
-// CHECK-NEXT:         "clang-module-deps": []
+// CHECK:              "clang-module-deps": []
 // CHECK-NEXT:         "command-line": [
 // CHECK-NEXT:           "-cc1"
 // CHECK:                "-o"
@@ -56,7 +56,7 @@
 // CHECK-NEXT:       }
 // CHECK-NEXT:       {
 // CHECK-NEXT:         "clang-context-hash":
-// CHECK-NEXT:         "clang-module-deps": []
+// CHECK:              "clang-module-deps": []
 // CHECK-NEXT:         "command-line": [
 // CHECK-NEXT:           "-cc1"
 // CHECK:                "-o"
diff --git a/clang/test/ClangScanDeps/removed-args.c b/clang/test/ClangScanDeps/removed-args.c
index 16f053f71e6ba..1f8d5e09b5c0d 100644
--- a/clang/test/ClangScanDeps/removed-args.c
+++ b/clang/test/ClangScanDeps/removed-args.c
@@ -76,7 +76,7 @@
 // CHECK-NEXT:   "translation-units": [
 // CHECK-NEXT:     {
 // CHECK:            "clang-context-hash": "[[HASH_TU:.*]]",
-// CHECK-NEXT:       "clang-module-deps": [
+// CHECK:            "clang-module-deps": [
 // CHECK-NEXT:         {
 // CHECK-NEXT:           "context-hash": "[[HASH_MOD_HEADER]]",
 // CHECK-NEXT:           "module-name": "ModHeader"
diff --git a/clang/test/ClangScanDeps/tu-buffer.c b/clang/test/ClangScanDeps/tu-buffer.c
index b450b13ff434b..84dcb73d84243 100644
--- a/clang/test/ClangScanDeps/tu-buffer.c
+++ b/clang/test/ClangScanDeps/tu-buffer.c
@@ -92,7 +92,7 @@ module addition { header "addition.h" }
 // CHECK-NEXT:       "commands": [
 // CHECK-NEXT:         {
 // CHECK-NEXT:           "clang-context-hash": "{{.*}}",
-// CHECK-NEXT:           "clang-module-deps": [
+// CHECK:                "clang-module-deps": [
 // CHECK-NEXT:             {
 // CHECK-NEXT:               "context-hash": "{{.*}}",
 // CHECK-NEXT:               "module-name": "root"
diff --git a/clang/tools/clang-scan-deps/ClangScanDeps.cpp b/clang/tools/clang-scan-deps/ClangScanDeps.cpp
index 921ba7aadd67d..6476d3fe02354 100644
--- a/clang/tools/clang-scan-deps/ClangScanDeps.cpp
+++ b/clang/tools/clang-scan-deps/ClangScanDeps.cpp
@@ -393,7 +393,9 @@ class FullDeps {
     ID.FileName = std::string(Input);
     ID.ContextHash = std::move(TUDeps.ID.ContextHash);
     ID.FileDeps = std::move(TUDeps.FileDeps);
-    ID.ModuleDeps = std::move(TUDeps.ClangModuleDeps);
+    ID.ModuleName = std::move(TUDeps.ID.ModuleName);
+    ID.NamedModuleDeps = std::move(TUDeps.NamedModuleDeps);
+    ID.ClangModuleDeps = std::move(TUDeps.ClangModuleDeps);
     ID.DriverCommandLine = std::move(TUDeps.DriverCommandLine);
     ID.Commands = std::move(TUDeps.Commands);
 
@@ -508,8 +510,14 @@ class FullDeps {
                   JOS.object([&] {
                     JOS.attribute("clang-context-hash",
                                   StringRef(I.ContextHash));
+                    if (I.ModuleName.size())
+                      JOS.attribute("module-name", (I.ModuleName));
+                    JOS.attributeArray("named-module-deps", [&] {
+                      for (const auto &Dep : I.NamedModuleDeps)
+                        JOS.value(Dep);
+                    });
                     JOS.attributeArray("clang-module-deps",
-                                       toJSONSorted(JOS, I.ModuleDeps));
+                                       toJSONSorted(JOS, I.ClangModuleDeps));
                     JOS.attributeArray("command-line",
                                        toJSONStrings(JOS, Cmd.Arguments));
                     JOS.attribute("executable", StringRef(Cmd.Executable));
@@ -521,8 +529,14 @@ class FullDeps {
               } else {
                 JOS.object([&] {
                   JOS.attribute("clang-context-hash", StringRef(I.ContextHash));
+                  if (I.ModuleName.size())
+                    JOS.attribute("module-name", (I.ModuleName));
+                  JOS.attributeArray("named-module-deps", [&] {
+                    for (const auto &Dep : I.NamedModuleDeps)
+                      JOS.value(Dep);
+                  });
                   JOS.attributeArray("clang-module-deps",
-                                     toJSONSorted(JOS, I.ModuleDeps));
+                                     toJSONSorted(JOS, I.ClangModuleDeps));
                   JOS.attributeArray("command-line",
                                      toJSONStrings(JOS, I.DriverCommandLine));
                   JOS.attribute("executable", "clang");
@@ -577,7 +591,9 @@ class FullDeps {
     std::string FileName;
     std::string ContextHash;
     std::vector<std::string> FileDeps;
-    std::vector<ModuleID> ModuleDeps;
+    std::string ModuleName;
+    std::vector<std::string> NamedModuleDeps;
+    std::vector<ModuleID> ClangModuleDeps;
     std::vector<std::string> DriverCommandLine;
     std::vector<Command> Commands;
   };



More information about the cfe-commits mailing list