Skip to content

Reland "[clang][modules-driver] Add support for C++ named modules and import std" (2nd attempt)#194475

Merged
naveen-seth merged 2 commits into
llvm:mainfrom
naveen-seth:reland-modules-driver-cxx-modules-attempt-2
Apr 27, 2026
Merged

Reland "[clang][modules-driver] Add support for C++ named modules and import std" (2nd attempt)#194475
naveen-seth merged 2 commits into
llvm:mainfrom
naveen-seth:reland-modules-driver-cxx-modules-attempt-2

Conversation

@naveen-seth

Copy link
Copy Markdown
Contributor

This reverts #193857 and relands #193312.

This adds basic support for explicit C++ named module builds, managed natively by the Clang driver, including support for use of the Standard library modules. This follows #187606, which adds the same for Clang modules.

Current limitations:

  • Standard library modules are still compiled to object files instead of using the provided shared library. (This will be addressed in a follow-up soon.)
  • Caching is not supported yet (but likely to be added during the upcoming GSoC cycle).
  • Importing C++ standard library modules into Clang modules is not supported (and not expected in the near term).

RFC:
https://discourse.llvm.org/t/rfc-modules-support-simple-c-20-modules-use-from-the-clang-driver-without-a-build-system

…d `import std`"

This reverts llvm#193677 and relands llvm#193312.

This adds basic support for explicit C++ named module builds, managed natively
by the Clang driver, including support for use of the Standard library modules.
This follows llvm#187606, which adds the same for Clang modules.

Current limitations:
- Standard library modules are still compiled to object files instead of
using the provided shared library. (This will be addressed in a
follow-up soon.)
- Caching is not supported yet (but likely to be added during the
upcoming GSoC cycle).
- Importing C++ standard library modules into Clang modules is not
supported (and not expected in the near term).

RFC:
https://discourse.llvm.org/t/rfc-modules-support-simple-c-20-modules-use-from-the-clang-driver-without-a-build-system
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Apr 27, 2026
@naveen-seth naveen-seth changed the title Reland "[clang][modules-driver] Add support for C++ named modules and import std" (2nd attempt) Reland "[clang][modules-driver] Add support for C++ named modules and import std" (2nd attempt) Apr 27, 2026
@llvmbot

llvmbot commented Apr 27, 2026

Copy link
Copy Markdown
Member

@llvm/pr-subscribers-clang

@llvm/pr-subscribers-clang-driver

Author: Naveen Seth Hanig (naveen-seth)

Changes

This reverts #193857 and relands #193312.

This adds basic support for explicit C++ named module builds, managed natively by the Clang driver, including support for use of the Standard library modules. This follows #187606, which adds the same for Clang modules.

Current limitations:

  • Standard library modules are still compiled to object files instead of using the provided shared library. (This will be addressed in a follow-up soon.)
  • Caching is not supported yet (but likely to be added during the upcoming GSoC cycle).
  • Importing C++ standard library modules into Clang modules is not supported (and not expected in the near term).

RFC:
https://discourse.llvm.org/t/rfc-modules-support-simple-c-20-modules-use-from-the-clang-driver-without-a-build-system


Full diff: https://github.com/llvm/llvm-project/pull/194475.diff

8 Files Affected:

  • (modified) clang/include/clang/Basic/DiagnosticDriverKinds.td (+2)
  • (modified) clang/include/clang/Driver/ModulesDriver.h (+4)
  • (modified) clang/lib/Driver/Driver.cpp (+2)
  • (modified) clang/lib/Driver/ModulesDriver.cpp (+89-11)
  • (added) clang/test/Driver/modules-driver-both-modules-types.cpp (+111)
  • (added) clang/test/Driver/modules-driver-cxx-modules-only.cpp (+88)
  • (added) clang/test/Driver/modules-driver-import-std.cpp (+60)
  • (added) clang/test/Driver/modules-driver-incompatible-options.cpp (+10)
diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 469045948a47c..2e38c5f7d450f 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -613,6 +613,8 @@ def err_drv_reduced_module_output_overrided : Warning<
   "please consider use '-fmodule-output=' to specify the output file for reduced BMI explicitly">,
   InGroup<DiagGroup<"reduced-bmi-output-overrided">>;
 
+def err_drv_modules_driver_requires_reduced_bmi : Error<
+  "'-fmodules-driver' is currently incompatible with '-fno-modules-reduced-bmi'">;
 def remark_performing_driver_managed_module_build : Remark<
   "performing driver managed module build">, InGroup<ModulesDriver>;
 def remark_modules_manifest_not_found : Remark<
diff --git a/clang/include/clang/Driver/ModulesDriver.h b/clang/include/clang/Driver/ModulesDriver.h
index 4f5fe7a7dfc1a..7146d2f6b143f 100644
--- a/clang/include/clang/Driver/ModulesDriver.h
+++ b/clang/include/clang/Driver/ModulesDriver.h
@@ -32,6 +32,10 @@ class Compilation;
 
 namespace clang::driver::modules {
 
+/// Emits diagnostics for arguments incompatible with -fmodules-driver.
+void diagnoseModulesDriverArgs(llvm::opt::DerivedArgList &DAL,
+                               DiagnosticsEngine &Diags);
+
 /// The parsed Standard library module manifest.
 struct StdModuleManifest {
   struct Module {
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index a7f8820fc991a..c98ac919f7d2a 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -1837,6 +1837,8 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
   if (UseModulesDriver) {
     Diags.Report(diag::remark_performing_driver_managed_module_build);
 
+    modules::diagnoseModulesDriverArgs(C->getArgs(), Diags);
+
     // Read the Standard library module manifest and, if available, add all
     // discovered modules to this Compilation. Jobs for modules specified in
     // the manifest that are not required by any command-line input are pruned
diff --git a/clang/lib/Driver/ModulesDriver.cpp b/clang/lib/Driver/ModulesDriver.cpp
index 826ee4966a647..f439c7e733954 100644
--- a/clang/lib/Driver/ModulesDriver.cpp
+++ b/clang/lib/Driver/ModulesDriver.cpp
@@ -21,6 +21,7 @@
 #include "clang/Driver/Job.h"
 #include "clang/Driver/Tool.h"
 #include "clang/Driver/ToolChain.h"
+#include "clang/Driver/Types.h"
 #include "clang/Frontend/StandaloneDiagnostic.h"
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/DepthFirstIterator.h"
@@ -47,6 +48,14 @@ using namespace clang;
 using namespace driver;
 using namespace modules;
 
+void driver::modules::diagnoseModulesDriverArgs(llvm::opt::DerivedArgList &DAL,
+                                                DiagnosticsEngine &Diags) {
+  if (!DAL.hasFlag(options::OPT_fmodules_reduced_bmi,
+                   options::OPT_fno_modules_reduced_bmi, true)) {
+    Diags.Report(diag::err_drv_modules_driver_requires_reduced_bmi);
+  }
+}
+
 namespace clang::driver::modules {
 static bool fromJSON(const llvm::json::Value &Params,
                      StdModuleManifest::Module::LocalArguments &LocalArgs,
@@ -1252,6 +1261,16 @@ static SmallVector<JobNode *> createNodesForUnusedStdlibModuleJobs(
   return StdlibModuleNodesToPrune;
 }
 
+// Returns the derived argument list for the tool chain responsible
+// for creating \p Job.
+static const DerivedArgList &getToolChainArgs(Compilation &C,
+                                              const Command &Job) {
+  const auto &TC = Job.getCreator().getToolChain();
+  const auto &SourceAction = Job.getSource();
+  return C.getArgsForToolChain(&TC, SourceAction.getOffloadingArch(),
+                               SourceAction.getOffloadingDeviceKind());
+}
+
 /// Creates a job for the Clang module described by \p MD.
 static std::unique_ptr<Command>
 createClangModulePrecompileJob(Compilation &C, const Command &ImportingJob,
@@ -1263,9 +1282,7 @@ createClangModulePrecompileJob(Compilation &C, const Command &ImportingJob,
   Action *PA = C.MakeAction<PrecompileJobAction>(IA, types::ID::TY_ModuleFile);
   PA->propagateOffloadInfo(&ImportingJob.getSource());
 
-  const auto &TC = ImportingJob.getCreator().getToolChain();
-  const auto &TCArgs = C.getArgsForToolChain(&TC, PA->getOffloadingArch(),
-                                             PA->getOffloadingDeviceKind());
+  const auto &TCArgs = getToolChainArgs(C, ImportingJob);
 
   const auto &BuildArgs = MD.getBuildArguments();
   ArgStringList JobArgs;
@@ -1319,12 +1336,7 @@ installScanCommandLines(Compilation &C,
     ArgStringList JobArgs;
     JobArgs.reserve(BuildArgs.size());
 
-    const auto &SourceAction = Job.getSource();
-    const auto &TC = Job.getCreator().getToolChain();
-    auto &TCArgs =
-        C.getArgsForToolChain(&TC, SourceAction.getOffloadingArch(),
-                              SourceAction.getOffloadingDeviceKind());
-
+    auto &TCArgs = getToolChainArgs(C, Job);
     for (const auto &Arg : BuildArgs)
       JobArgs.push_back(TCArgs.MakeArgString(Arg));
 
@@ -1527,6 +1539,73 @@ static void createAndConnectRoot(CompilationGraph &Graph) {
   }
 }
 
+/// Creates a temporary output path for \p ModuleName.
+static std::string createModuleOutputPath(const Compilation &C,
+                                          StringRef ModuleName) {
+  // Sanitize the ':' included in parition names. It is illegal for filenames on
+  // Windows.
+  SmallString<32> SanitizedModuleName(ModuleName);
+  llvm::replace(SanitizedModuleName, ':', '-');
+  auto ModuleOutputPath = C.getDriver().GetTemporaryPath(
+      SanitizedModuleName, types::getTypeTempSuffix(types::TY_ModuleFile));
+  return ModuleOutputPath;
+}
+
+/// Adds the '-fmodule-output=' argument for the module produced by \p Node.
+static void configureNamedModuleOutputArg(Compilation &C,
+                                          NamedModuleJobNode &Node,
+                                          StringRef ModuleOutputPath) {
+  auto &Job = *Node.Job;
+  const auto &TCArgs = getToolChainArgs(C, Job);
+  auto JobArgs = Job.getArguments();
+  JobArgs.push_back(
+      TCArgs.MakeArgString("-fmodule-output=" + ModuleOutputPath));
+  Job.replaceArguments(std::move(JobArgs));
+}
+
+/// Propagates the '-fmodule-file=' mapping for the named module described by
+/// \p Node to each dependent job.
+static void propagateModuleFileMappingArg(Compilation &C,
+                                          NamedModuleJobNode &Node,
+                                          StringRef ModuleOutputPath) {
+  const StringRef ModuleName = Node.InputDeps.ModuleName;
+
+  auto DependentNodes = llvm::drop_begin(llvm::depth_first<CGNode *>(&Node));
+  auto DependentScannedNodes = llvm::map_range(
+      llvm::make_filter_range(DependentNodes, llvm::IsaPred<ScannedJobNode>),
+      llvm::CastTo<ScannedJobNode>);
+
+  for (ScannedJobNode *DependentNode : DependentScannedNodes) {
+    auto &DependentJob = *DependentNode->Job;
+    const auto &TCArgs = getToolChainArgs(C, DependentJob);
+    auto JobArgs = DependentJob.getArguments();
+    JobArgs.push_back(TCArgs.MakeArgString("-fmodule-file=" + ModuleName + "=" +
+                                           ModuleOutputPath));
+    DependentJob.replaceArguments(std::move(JobArgs));
+  }
+}
+
+/// Finalizes command lines for C++20 named module dependencies.
+///
+/// The command lines produced by dependency scanning are only adjusted to
+/// handle discovered Clang modules. For C++20 named modules, we update the
+/// command-lines here.
+static void fixupNamedModuleCommandLines(Compilation &C,
+                                         CompilationGraph &Graph) {
+  const auto NamedModuleNodes = llvm::map_range(
+      llvm::make_filter_range(Graph, llvm::IsaPred<NamedModuleJobNode>),
+      llvm::CastTo<NamedModuleJobNode>);
+
+  for (NamedModuleJobNode *Node : NamedModuleNodes) {
+    const StringRef ModuleName = Node->InputDeps.ModuleName;
+    const auto ModuleOutputPath = createModuleOutputPath(C, ModuleName);
+    C.addTempFile(C.getArgs().MakeArgString(ModuleOutputPath));
+
+    configureNamedModuleOutputArg(C, *Node, ModuleOutputPath);
+    propagateModuleFileMappingArg(C, *Node, ModuleOutputPath);
+  }
+}
+
 /// Moves jobs from \p Graph into \p C in the graph's topological order.
 static void feedJobsBackIntoCompilation(Compilation &C,
                                         CompilationGraph &&Graph) {
@@ -1600,7 +1679,6 @@ void driver::modules::runModulesDriver(
   if (!Diags.isLastDiagnosticIgnored())
     llvm::WriteGraph<const CompilationGraph *>(llvm::errs(), &Graph);
 
-  // TODO: Fix-up command-lines for named module imports.
-
+  fixupNamedModuleCommandLines(C, Graph);
   feedJobsBackIntoCompilation(C, std::move(Graph));
 }
diff --git a/clang/test/Driver/modules-driver-both-modules-types.cpp b/clang/test/Driver/modules-driver-both-modules-types.cpp
new file mode 100644
index 0000000000000..0a88917165e37
--- /dev/null
+++ b/clang/test/Driver/modules-driver-both-modules-types.cpp
@@ -0,0 +1,111 @@
+// Checks that -fmodules-driver correctly handles compilations using both
+// Standard C++20 modules and Clang modules.
+// Importing a Standard C++20 module into Clang module is not supported yet.
+
+// RUN: split-file %s %t
+// RUN: rm -rf %t/modules-cache
+
+// RUN: %clang -c -std=c++23 \
+// RUN:   -fmodules-driver -Rmodules-driver \
+// RUN:   -fmodules -Rmodule-import \
+// RUN:   -fmodule-map-file=%t/module.modulemap \
+// RUN:   -fmodules-cache-path=%t/modules-cache \
+// RUN:   %t/main.cpp %t/A.cppm %t/A-part1.cppm %t/A-part1-impl.cppm 2>&1 \
+// RUN:   | sed 's:\\\\\?:/:g' \
+// RUN:   | FileCheck -DPREFIX=%/t --check-prefix=CHECK-REMARKS %s
+
+// The scan itself will also produce [-Rmodule-import] remarks.
+// Let's skip past them, we only care about the final -cc1 commands.
+// CHECK-REMARKS:       clang: remark: printing module dependency graph [-Rmodules-driver]
+// CHECK-REMARKS-NEXT:  digraph "Module Dependency Graph" {
+// CHECK-REMARKS:       }
+
+// CHECK-REMARKS: [[PREFIX]]/A-part1-impl.cppm:2:2: remark: importing module 'root' from
+// CHECK-REMARKS: [[PREFIX]]/A-part1.cppm:2:2: remark: importing module 'root' from
+// CHECK-REMARKS: [[PREFIX]]/A.cppm:2:2: remark: importing module 'root' from
+// CHECK-REMARKS: [[PREFIX]]/A.cppm:4:8: remark: importing module 'A:part1' from
+// CHECK-REMARKS: [[PREFIX]]/A.cppm:4:8: remark: importing module 'root' into 'A:part1' from
+// CHECK-REMARKS: [[PREFIX]]/main.cpp:1:1: remark: importing module 'A' from
+// CHECK-REMARKS: [[PREFIX]]/main.cpp:1:1: remark: importing module 'root' into 'A' from
+// CHECK-REMARKS: [[PREFIX]]/main.cpp:1:1: remark: importing module 'A:part1' into 'A' from
+// CHECK-REMARKS: [[PREFIX]]/main.cpp:1:1: remark: importing module 'root' into 'A:part1' from
+
+// RUN: %clang -std=c++23 \
+// RUN:   -fmodules-driver -Rmodules-driver \
+// RUN:   -fmodules -Rmodule-import \
+// RUN:   -fmodule-map-file=%t/module.modulemap \
+// RUN:   -fmodules-cache-path=%t/modules-cache \
+// RUN:   %t/main.cpp %t/A.cppm %t/A-part1.cppm %t/A-part1-impl.cppm \
+// RUN:   -### 2>&1 \
+// RUN:   | sed 's:\\\\\?:/:g' \
+// RUN:   | FileCheck -DPREFIX=%/t --check-prefix=CHECK-CC1 %s
+
+// CHECK-CC1: "-cc1"
+// CHECK-CC1-SAME: "-o" "[[ROOTPCM:[^"]+]]"
+// CHECK-CC1-SAME: "-emit-module"
+// CHECK-CC1-SAME: "[[PREFIX]]/module.modulemap"
+// CHECK-CC1-SAME: "-fmodule-name=root"
+// CHECK-CC1-SAME: "-fno-implicit-modules"
+
+// CHECK-CC1: "-cc1"
+// CHECK-CC1-SAME: "[[PREFIX]]/A-part1-impl.cppm"
+// CHECK-CC1-SAME: "-fmodule-file=root=[[ROOTPCM]]"
+// CHECK-CC1-SAME: "-fno-implicit-modules"
+// CHECK-CC1-SAME: "-fmodule-output=[[A_PART1_IMPL_PCM:[^"]+]]"
+
+// CHECK-CC1: "-cc1"
+// CHECK-CC1-SAME: "[[PREFIX]]/A-part1.cppm"
+// CHECK-CC1-SAME: "-fmodule-file=root=[[ROOTPCM]]"
+// CHECK-CC1-SAME: "-fno-implicit-modules"
+// CHECK-CC1-SAME: "-fmodule-output=[[A_PART1_PCM:[^"]+]]"
+
+// CHECK-CC1: "-cc1"
+// CHECK-CC1-SAME: "[[PREFIX]]/A.cppm"
+// CHECK-CC1-SAME: "-fmodule-file=root=[[ROOTPCM]]"
+// CHECK-CC1-SAME: "-fno-implicit-modules"
+// CHECK-CC1-SAME: "-fmodule-output=[[A_PCM:[^"]+]]"
+// CHECK-CC1-SAME: "-fmodule-file=A:part1=[[A_PART1_PCM]]"
+
+// CHECK-CC1: "-cc1"
+// CHECK-CC1-SAME: "[[PREFIX]]/main.cpp"
+// CHECK-CC1-SAME: "-fno-implicit-modules"
+// CHECK-CC1-SAME: "-fmodule-file=A=[[A_PCM]]"
+// CHECK-CC1-SAME: "-fmodule-file=A:part1=[[A_PART1_PCM]]"
+
+//--- main.cpp
+import A;
+
+int main() {
+  a();
+}
+
+//--- A.cppm
+module;
+#include "root.h"
+export module A;
+export import :part1;
+
+export int a() {
+  return part1() + root();
+}
+
+//--- A-part1.cppm
+module;
+#include "root.h"
+export module A:part1;
+export int part1();
+
+//--- A-part1-impl.cppm
+module;
+#include "root.h"
+module A:part1_impl;
+
+int part1() {
+  return root();
+}
+
+//--- module.modulemap
+module root { header "root.h" export * }
+
+//--- root.h
+inline int root() { return 1; }
diff --git a/clang/test/Driver/modules-driver-cxx-modules-only.cpp b/clang/test/Driver/modules-driver-cxx-modules-only.cpp
new file mode 100644
index 0000000000000..1206983e32f7b
--- /dev/null
+++ b/clang/test/Driver/modules-driver-cxx-modules-only.cpp
@@ -0,0 +1,88 @@
+// Checks that -fmodules-driver correctly handles compilations using
+// Standard C++20 modules.
+
+// RUN: split-file %s %t
+
+// RUN: %clang -c -std=c++23 \
+// RUN:   -fmodules-driver -Rmodules-driver -Rmodule-import \
+// RUN:   %t/main.cpp %t/A.cppm %t/A-part1.cppm %t/A-part1-impl.cppm %t/B.cppm 2>&1 \
+// RUN:   | sed 's:\\\\\?:/:g' \
+// RUN:   | FileCheck -DPREFIX=%/t --check-prefix=CHECK-REMARKS %s
+
+// CHECK-REMARKS: [[PREFIX]]/A.cppm:2:8: remark: importing module 'A:part1' from
+// CHECK-REMARKS: [[PREFIX]]/A.cppm:3:1: remark: importing module 'B' from
+// CHECK-REMARKS: [[PREFIX]]/main.cpp:1:1: remark: importing module 'A' from
+// CHECK-REMARKS: [[PREFIX]]/main.cpp:1:1: remark: importing module 'A:part1' into 'A' from
+// CHECK-REMARKS: [[PREFIX]]/main.cpp:1:1: remark: importing module 'B' into 'A' from
+// CHECK-REMARKS: [[PREFIX]]/main.cpp:2:1: remark: importing module 'B' from
+
+// RUN: %clang -std=c++23 \
+// RUN:   -fmodules-driver -Rmodules-driver -Rmodule-import \
+// RUN:   %t/main.cpp %t/A.cppm %t/A-part1.cppm %t/A-part1-impl.cppm %t/B.cppm \
+// RUN:   -### 2>&1 \
+// RUN:   | sed 's:\\\\\?:/:g' \
+// RUN:   | FileCheck --check-prefix=CHECK-CC1 %s
+
+// CHECK-CC1: "-cc1"
+// CHECK-CC1-SAME: "{{.*}}/B.cppm"
+// CHECK-CC1-SAME: "-fno-implicit-modules"
+// CHECK-CC1-SAME: "-fmodule-output=[[B_PCM:[^"]+]]"
+
+// CHECK-CC1: "-cc1"
+// CHECK-CC1-SAME: "{{.*}}/A-part1-impl.cppm"
+// CHECK-CC1-SAME: "-fno-implicit-modules"
+// CHECK-CC1-SAME: "-fmodule-output=[[A_PART1_IMPL_PCM:[^"]+]]"
+
+// CHECK-CC1: "-cc1"
+// CHECK-CC1-SAME: "{{.*}}/A-part1.cppm"
+// CHECK-CC1-SAME: "-fno-implicit-modules"
+// CHECK-CC1-SAME: "-fmodule-output=[[A_PART1_PCM:[^"]+]]"
+
+// CHECK-CC1: "-cc1"
+// CHECK-CC1-SAME: "{{.*}}/A.cppm"
+// CHECK-CC1-SAME: "-fno-implicit-modules"
+// CHECK-CC1-SAME: "-fmodule-output=[[A_PCM:[^"]+]]"
+// CHECK-CC1-SAME: "-fmodule-file=A:part1=[[A_PART1_PCM]]"
+// CHECK-CC1-SAME: "-fmodule-file=B=[[B_PCM]]"
+
+// CHECK-CC1: "-cc1"
+// CHECK-CC1-SAME: "{{.*}}/main.cpp"
+// CHECK-CC1-SAME: "-fno-implicit-modules"
+// CHECK-CC1-SAME: "-fmodule-file=A=[[A_PCM]]"
+// CHECK-CC1-SAME: "-fmodule-file=A:part1=[[A_PART1_PCM]]"
+// CHECK-CC1-SAME: "-fmodule-file=B=[[B_PCM]]"
+
+//--- main.cpp
+import A;
+import B;
+
+int main() {
+  return a() + b();
+}
+
+//--- A.cppm
+export module A;
+export import :part1;
+import B;
+
+export int a() {
+  return part1() + b();
+}
+
+//--- A-part1.cppm
+export module A:part1;
+export int part1();
+
+//--- A-part1-impl.cppm
+module A:part1_impl;
+
+int part1() {
+  return 30;
+}
+
+//--- B.cppm
+export module B;
+
+export int b() {
+  return 12;
+}
diff --git a/clang/test/Driver/modules-driver-import-std.cpp b/clang/test/Driver/modules-driver-import-std.cpp
new file mode 100644
index 0000000000000..25dc059b73ec7
--- /dev/null
+++ b/clang/test/Driver/modules-driver-import-std.cpp
@@ -0,0 +1,60 @@
+// Checks that -fmodules-driver correctly handles the import of Standard library
+// modules.
+
+// The standard library modules manifest (libc++.modules.json) is discovered
+// relative to the installed C++ standard library runtime libraries
+// We need to create them in order for Clang to find the manifest.
+// RUN: rm -rf %t && split-file %s %t
+// RUN: mkdir -p %t/Inputs/usr/lib/x86_64-linux-gnu
+// RUN: touch %t/Inputs/usr/lib/x86_64-linux-gnu/libc++.so
+// RUN: touch %t/Inputs/usr/lib/x86_64-linux-gnu/libc++.a
+
+// RUN: sed "s|DIR|%/t|g" %t/libc++.modules.json.in > \
+// RUN:   %t/Inputs/usr/lib/x86_64-linux-gnu/libc++.modules.json
+
+// RUN: mkdir -p %t/Inputs/usr/lib/share/libc++/v1
+// RUN: cat %t/std.cppm > %t/Inputs/usr/lib/share/libc++/v1/std.cppm
+// RUN: cat %t/std.compat.cppm > %t/Inputs/usr/lib/share/libc++/v1/std.compat.cppm
+
+//--- libc++.modules.json.in
+{
+  "version": 1,
+  "revision": 1,
+  "modules": [
+    {
+      "logical-name": "std",
+      "source-path": "../share/libc++/v1/std.cppm",
+      "is-std-library": true
+    },
+    {
+      "logical-name": "std.compat",
+      "source-path": "../share/libc++/v1/std.compat.cppm",
+      "is-std-library": true
+    }
+  ]
+}
+
+//--- std.cppm
+export module std;
+
+//--- std.compat.cppm
+export module std.compat;
+import std;
+
+//--- main.cpp
+import std.compat;
+import std;
+
+int main() {}
+
+// RUN: %clang -std=c++23 -c -fmodules-driver -Rmodules-driver -Rmodule-import \
+// RUN:   -stdlib=libc++ \
+// RUN:   -resource-dir=%t/Inputs/usr/lib/x86_64-linux-gnu \
+// RUN:   --target=x86_64-linux-gnu \
+// RUN:   %t/main.cpp 2>&1 \
+// RUN:   | sed 's:\\\\\?:/:g' \
+// RUN:   | FileCheck -DPREFIX=%/t %s
+
+// CHECK: [[PREFIX]]/main.cpp:1:1: remark: importing module 'std.compat' from
+// CHECK: [[PREFIX]]/main.cpp:1:1: remark: importing module 'std' into 'std.compat' from
+// CHECK: [[PREFIX]]/main.cpp:2:1: remark: importing module 'std' from
diff --git a/clang/test/Driver/modules-driver-incompatible-options.cpp b/clang/test/Driver/modules-driver-incompatible-options.cpp
new file mode 100644
index 0000000000000..88de9a6eac0e9
--- /dev/null
+++ b/clang/test/Driver/modules-driver-incompatible-options.cpp
@@ -0,0 +1,10 @@
+// Checks for diagnostics that report incompatibilities between
+// -fmodules-driver and other options.
+
+// RUN: split-file %s %t
+// RUN: not %clang -std=c++20 -fmodules-driver -fno-modules-reduced-bmi main.cpp -###
+
+// CHECK: clang: error: '-fmodules-driver' is currently incompatible with '-fno-modules-reduced-bmi'
+
+//--- main.cpp
+int main() {}

Looking at other tests, using sysroot seems like the more robust test for this.
@naveen-seth naveen-seth added the skip-precommit-approval PR for CI feedback, not intended for review label Apr 27, 2026
@naveen-seth
naveen-seth merged commit c1e78ed into llvm:main Apr 27, 2026
10 of 11 checks passed
@naveen-seth

Copy link
Copy Markdown
Contributor Author

Fix in 2nd commit of this PR.
This is the 2nd attempt at relanding and if we fail build-bot tests again without any output, I'll remove clang/test/Driver/modules-driver-import-std.cpp and reland that test later separately.

@llvm-ci

llvm-ci commented Apr 28, 2026

Copy link
Copy Markdown

LLVM Buildbot has detected a new failure on builder llvm-clang-aarch64-darwin running on doug-worker-4 while building clang at step 6 "test-build-unified-tree-check-all".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/190/builds/41510

Here is the relevant piece of the build log for the reference
Step 6 (test-build-unified-tree-check-all) failure: test (failure)
******************** TEST 'Clang :: Driver/modules-driver-import-std.cpp' FAILED ********************
Exit Code: 1

Command Output (stdout):
--
# RUN: at line 7
rm -rf /Volumes/RAMDisk/buildbot-root/aarch64-darwin/build/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp && split-file /Users/buildbot/buildbot-root/llvm-project/clang/test/Driver/modules-driver-import-std.cpp /Volumes/RAMDisk/buildbot-root/aarch64-darwin/build/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp
# executed command: rm -rf /Volumes/RAMDisk/buildbot-root/aarch64-darwin/build/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp
# note: command had no output on stdout or stderr
# executed command: split-file /Users/buildbot/buildbot-root/llvm-project/clang/test/Driver/modules-driver-import-std.cpp /Volumes/RAMDisk/buildbot-root/aarch64-darwin/build/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp
# note: command had no output on stdout or stderr
# RUN: at line 8
mkdir -p /Volumes/RAMDisk/buildbot-root/aarch64-darwin/build/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp/FakeSysroot/usr/lib/x86_64-linux-gnu
# executed command: mkdir -p /Volumes/RAMDisk/buildbot-root/aarch64-darwin/build/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp/FakeSysroot/usr/lib/x86_64-linux-gnu
# note: command had no output on stdout or stderr
# RUN: at line 9
touch /Volumes/RAMDisk/buildbot-root/aarch64-darwin/build/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp/FakeSysroot/usr/lib/x86_64-linux-gnu/libc++.so
# executed command: touch /Volumes/RAMDisk/buildbot-root/aarch64-darwin/build/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp/FakeSysroot/usr/lib/x86_64-linux-gnu/libc++.so
# note: command had no output on stdout or stderr
# RUN: at line 10
touch /Volumes/RAMDisk/buildbot-root/aarch64-darwin/build/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp/FakeSysroot/usr/lib/x86_64-linux-gnu/libc++.a
# executed command: touch /Volumes/RAMDisk/buildbot-root/aarch64-darwin/build/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp/FakeSysroot/usr/lib/x86_64-linux-gnu/libc++.a
# note: command had no output on stdout or stderr
# RUN: at line 12
sed "s|DIR|/Volumes/RAMDisk/buildbot-root/aarch64-darwin/build/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp|g" /Volumes/RAMDisk/buildbot-root/aarch64-darwin/build/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp/libc++.modules.json.in >    /Volumes/RAMDisk/buildbot-root/aarch64-darwin/build/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp/FakeSysroot/usr/lib/x86_64-linux-gnu/libc++.modules.json
# executed command: sed 's|DIR|/Volumes/RAMDisk/buildbot-root/aarch64-darwin/build/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp|g' /Volumes/RAMDisk/buildbot-root/aarch64-darwin/build/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp/libc++.modules.json.in
# note: command had no output on stdout or stderr
# RUN: at line 15
mkdir -p /Volumes/RAMDisk/buildbot-root/aarch64-darwin/build/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp/FakeSysroot/usr/lib/share/libc++/v1
# executed command: mkdir -p /Volumes/RAMDisk/buildbot-root/aarch64-darwin/build/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp/FakeSysroot/usr/lib/share/libc++/v1
# note: command had no output on stdout or stderr
# RUN: at line 16
cat /Volumes/RAMDisk/buildbot-root/aarch64-darwin/build/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp/std.cppm > /Volumes/RAMDisk/buildbot-root/aarch64-darwin/build/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp/FakeSysroot/usr/lib/share/libc++/v1/std.cppm
# executed command: cat /Volumes/RAMDisk/buildbot-root/aarch64-darwin/build/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp/std.cppm
# note: command had no output on stdout or stderr
# RUN: at line 17
cat /Volumes/RAMDisk/buildbot-root/aarch64-darwin/build/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp/std.compat.cppm > /Volumes/RAMDisk/buildbot-root/aarch64-darwin/build/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp/FakeSysroot/usr/lib/share/libc++/v1/std.compat.cppm
# executed command: cat /Volumes/RAMDisk/buildbot-root/aarch64-darwin/build/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp/std.compat.cppm
# note: command had no output on stdout or stderr
# RUN: at line 50
/Volumes/RAMDisk/buildbot-root/aarch64-darwin/build/bin/clang -std=c++23 -stdlib=libc++    -fmodules-driver -Rmodules-driver -Rmodule-import    -stdlib=libc++    -resource-dir=/Volumes/RAMDisk/buildbot-root/aarch64-darwin/build/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp/FakeSysroot/usr/lib/x86_64-linux-gnu    --sysroot=/Volumes/RAMDisk/buildbot-root/aarch64-darwin/build/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp/FakeSysroot    -L/Volumes/RAMDisk/buildbot-root/aarch64-darwin/build/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp/Inputs/usr/lib/x86_64-linux-gnu    --target=x86_64-linux-gnu    -c /Volumes/RAMDisk/buildbot-root/aarch64-darwin/build/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp/main.cpp 2>&1    | sed 's:\\\\\?:/:g'    | /Volumes/RAMDisk/buildbot-root/aarch64-darwin/build/bin/FileCheck -DPREFIX=/Volumes/RAMDisk/buildbot-root/aarch64-darwin/build/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp /Users/buildbot/buildbot-root/llvm-project/clang/test/Driver/modules-driver-import-std.cpp
# executed command: /Volumes/RAMDisk/buildbot-root/aarch64-darwin/build/bin/clang -std=c++23 -stdlib=libc++ -fmodules-driver -Rmodules-driver -Rmodule-import -stdlib=libc++ -resource-dir=/Volumes/RAMDisk/buildbot-root/aarch64-darwin/build/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp/FakeSysroot/usr/lib/x86_64-linux-gnu --sysroot=/Volumes/RAMDisk/buildbot-root/aarch64-darwin/build/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp/FakeSysroot -L/Volumes/RAMDisk/buildbot-root/aarch64-darwin/build/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp/Inputs/usr/lib/x86_64-linux-gnu --target=x86_64-linux-gnu -c /Volumes/RAMDisk/buildbot-root/aarch64-darwin/build/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp/main.cpp
# note: command had no output on stdout or stderr
# error: command failed with exit status: 1
# executed command: sed 's:\\\\\?:/:g'
# note: command had no output on stdout or stderr
# executed command: /Volumes/RAMDisk/buildbot-root/aarch64-darwin/build/bin/FileCheck -DPREFIX=/Volumes/RAMDisk/buildbot-root/aarch64-darwin/build/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp /Users/buildbot/buildbot-root/llvm-project/clang/test/Driver/modules-driver-import-std.cpp
# note: command had no output on stdout or stderr

--
...

@llvm-ci

llvm-ci commented Apr 28, 2026

Copy link
Copy Markdown

LLVM Buildbot has detected a new failure on builder clang-aarch64-quick running on linaro-clang-aarch64-quick while building clang at step 5 "ninja check 1".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/65/builds/33672

Here is the relevant piece of the build log for the reference
Step 5 (ninja check 1) failure: stage 1 checked (failure)
******************** TEST 'Clang :: Driver/modules-driver-import-std.cpp' FAILED ********************
Exit Code: 1

Command Output (stdout):
--
# RUN: at line 7
rm -rf /home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp && split-file /home/tcwg-buildbot/worker/clang-aarch64-quick/llvm/clang/test/Driver/modules-driver-import-std.cpp /home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp
# executed command: rm -rf /home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp
# executed command: split-file /home/tcwg-buildbot/worker/clang-aarch64-quick/llvm/clang/test/Driver/modules-driver-import-std.cpp /home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp
# RUN: at line 8
mkdir -p /home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp/FakeSysroot/usr/lib/x86_64-linux-gnu
# executed command: mkdir -p /home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp/FakeSysroot/usr/lib/x86_64-linux-gnu
# RUN: at line 9
touch /home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp/FakeSysroot/usr/lib/x86_64-linux-gnu/libc++.so
# executed command: touch /home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp/FakeSysroot/usr/lib/x86_64-linux-gnu/libc++.so
# RUN: at line 10
touch /home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp/FakeSysroot/usr/lib/x86_64-linux-gnu/libc++.a
# executed command: touch /home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp/FakeSysroot/usr/lib/x86_64-linux-gnu/libc++.a
# RUN: at line 12
sed "s|DIR|/home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp|g" /home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp/libc++.modules.json.in >    /home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp/FakeSysroot/usr/lib/x86_64-linux-gnu/libc++.modules.json
# executed command: sed 's|DIR|/home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp|g' /home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp/libc++.modules.json.in
# RUN: at line 15
mkdir -p /home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp/FakeSysroot/usr/lib/share/libc++/v1
# executed command: mkdir -p /home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp/FakeSysroot/usr/lib/share/libc++/v1
# RUN: at line 16
cat /home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp/std.cppm > /home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp/FakeSysroot/usr/lib/share/libc++/v1/std.cppm
# executed command: cat /home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp/std.cppm
# RUN: at line 17
cat /home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp/std.compat.cppm > /home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp/FakeSysroot/usr/lib/share/libc++/v1/std.compat.cppm
# executed command: cat /home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp/std.compat.cppm
# RUN: at line 50
/home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/bin/clang -std=c++23 -stdlib=libc++    -fmodules-driver -Rmodules-driver -Rmodule-import    -stdlib=libc++    -resource-dir=/home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp/FakeSysroot/usr/lib/x86_64-linux-gnu    --sysroot=/home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp/FakeSysroot    -L/home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp/Inputs/usr/lib/x86_64-linux-gnu    --target=x86_64-linux-gnu    -c /home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp/main.cpp 2>&1    | sed 's:\\\\\?:/:g'    | /home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/bin/FileCheck -DPREFIX=/home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp /home/tcwg-buildbot/worker/clang-aarch64-quick/llvm/clang/test/Driver/modules-driver-import-std.cpp
# executed command: /home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/bin/clang -std=c++23 -stdlib=libc++ -fmodules-driver -Rmodules-driver -Rmodule-import -stdlib=libc++ -resource-dir=/home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp/FakeSysroot/usr/lib/x86_64-linux-gnu --sysroot=/home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp/FakeSysroot -L/home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp/Inputs/usr/lib/x86_64-linux-gnu --target=x86_64-linux-gnu -c /home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp/main.cpp
# note: command had no output on stdout or stderr
# error: command failed with exit status: 1
# executed command: sed 's:\\\\\?:/:g'
# executed command: /home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/bin/FileCheck -DPREFIX=/home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/tools/clang/test/Driver/Output/modules-driver-import-std.cpp.tmp /home/tcwg-buildbot/worker/clang-aarch64-quick/llvm/clang/test/Driver/modules-driver-import-std.cpp

--

********************


naveen-seth added a commit that referenced this pull request Apr 28, 2026
See
#194475 (comment).
This constrains the test to not run on aarch64, where it fails on
`clang-aarch64-quick` and `llvm-clang-aarch64-darwin` builders.
The failing builders don't show any output, and the test will be
re-enabled for aarch64 in a later follow-up.

Co-authored-by: Naveen Seth Hanig <naveen.hanig@oulook.com>
@naveen-seth

Copy link
Copy Markdown
Contributor Author

Aarch64 buildbot failures addressed in #194502.

llvm-sync Bot pushed a commit to arm/arm-toolchain that referenced this pull request Apr 28, 2026
…test (#194502)

See
llvm/llvm-project#194475 (comment).
This constrains the test to not run on aarch64, where it fails on
`clang-aarch64-quick` and `llvm-clang-aarch64-darwin` builders.
The failing builders don't show any output, and the test will be
re-enabled for aarch64 in a later follow-up.

Co-authored-by: Naveen Seth Hanig <naveen.hanig@oulook.com>
llvm-upstreamsync Bot pushed a commit to qualcomm/cpullvm-toolchain that referenced this pull request Apr 28, 2026
…test (#194502)

See
llvm/llvm-project#194475 (comment).
This constrains the test to not run on aarch64, where it fails on
`clang-aarch64-quick` and `llvm-clang-aarch64-darwin` builders.
The failing builders don't show any output, and the test will be
re-enabled for aarch64 in a later follow-up.

Co-authored-by: Naveen Seth Hanig <naveen.hanig@oulook.com>
cpullvm-upstream-sync Bot pushed a commit to navaneethshan/cpullvm-toolchain-1 that referenced this pull request Apr 28, 2026
…test (#194502)

See
llvm/llvm-project#194475 (comment).
This constrains the test to not run on aarch64, where it fails on
`clang-aarch64-quick` and `llvm-clang-aarch64-darwin` builders.
The failing builders don't show any output, and the test will be
re-enabled for aarch64 in a later follow-up.

Co-authored-by: Naveen Seth Hanig <naveen.hanig@oulook.com>
@mikaelholmen

Copy link
Copy Markdown
Contributor

Is there some race-condition going on for the
clang/test/Driver/modules-driver-both-modules-types.cpp
testcase?

I've randomly seen

clang: ../../clang/lib/DependencyScanning/InProcessModuleCache.cpp:148: virtual std::error_code {anonymous}::InProcessModuleCache::write(llvm::StringRef, llvm::MemoryBufferRef, off_t&, time_t&): Assertion `Entry.Buffer && *Entry.Buffer == Buffer && "Wrote the same PCM with different contents"' failed.

in one of our downstream build bots when running that testcase.

@naveen-seth

Copy link
Copy Markdown
Contributor Author

Is there some race-condition going on for the clang/test/Driver/modules-driver-both-modules-types.cpp testcase?

I've randomly seen

clang: ../../clang/lib/DependencyScanning/InProcessModuleCache.cpp:148: virtual std::error_code {anonymous}::InProcessModuleCache::write(llvm::StringRef, llvm::MemoryBufferRef, off_t&, time_t&): Assertion `Entry.Buffer && *Entry.Buffer == Buffer && "Wrote the same PCM with different contents"' failed.

in one of our downstream build bots when running that testcase.

Pinging @jansvoboda11 for his expertise on InProcessModuleCache.
I would have time to look into this using tsan after work today otherwise.

@rorth

rorth commented Apr 28, 2026

Copy link
Copy Markdown
Contributor

This PR broke the Solaris/sparcv9 buildbot because the Clang::modules-driver-import-std.cpp test unconditionally uses --target=x86_64-linux-gnu which is only available with -DLLVM_TARGETS_TO_BUILD=all or on native x86 targets.

@naveen-seth

Copy link
Copy Markdown
Contributor Author

This PR broke the Solaris/sparcv9 buildbot because the Clang::modules-driver-import-std.cpp test unconditionally uses --target=x86_64-linux-gnu which is only available with -DLLVM_TARGETS_TO_BUILD=all or on native x86 targets.

Sorry for the breakage! Should be fixed by #194604.

@antmox

antmox commented Apr 28, 2026

Copy link
Copy Markdown
Contributor

Hi, this also breaks bot clang-armv8-quick : https://lab.llvm.org/buildbot/#/builders/154

naveen-seth added a commit that referenced this pull request Apr 28, 2026
The root cause for the failing test was found in
#194475 (comment).
The test uses `--target=x86_64-linux-gnu` which is only available with
`-DLLVM_TARGETS_TO_BUILD=all` or on native x86 targets.
llvm-upstreamsync Bot pushed a commit to qualcomm/cpullvm-toolchain that referenced this pull request Apr 28, 2026
…(#194604)

The root cause for the failing test was found in
llvm/llvm-project#194475 (comment).
The test uses `--target=x86_64-linux-gnu` which is only available with
`-DLLVM_TARGETS_TO_BUILD=all` or on native x86 targets.
llvm-sync Bot pushed a commit to arm/arm-toolchain that referenced this pull request Apr 28, 2026
…(#194604)

The root cause for the failing test was found in
llvm/llvm-project#194475 (comment).
The test uses `--target=x86_64-linux-gnu` which is only available with
`-DLLVM_TARGETS_TO_BUILD=all` or on native x86 targets.
cpullvm-upstream-sync Bot pushed a commit to navaneethshan/cpullvm-toolchain-1 that referenced this pull request Apr 28, 2026
…(#194604)

The root cause for the failing test was found in
llvm/llvm-project#194475 (comment).
The test uses `--target=x86_64-linux-gnu` which is only available with
`-DLLVM_TARGETS_TO_BUILD=all` or on native x86 targets.
@jansvoboda11

Copy link
Copy Markdown
Contributor

Is there some race-condition going on for the clang/test/Driver/modules-driver-both-modules-types.cpp testcase?
I've randomly seen

clang: ../../clang/lib/DependencyScanning/InProcessModuleCache.cpp:148: virtual std::error_code {anonymous}::InProcessModuleCache::write(llvm::StringRef, llvm::MemoryBufferRef, off_t&, time_t&): Assertion `Entry.Buffer && *Entry.Buffer == Buffer && "Wrote the same PCM with different contents"' failed.

in one of our downstream build bots when running that testcase.

Pinging @jansvoboda11 for his expertise on InProcessModuleCache. I would have time to look into this using tsan after work today otherwise.

I added that assertion recently. Essentially it only fires if the scanner wrote two different PCMs to the same path within single scanning service lifetime. This may happen if the FS changes, which we should be mostly protected from by the caching VFS. The other cause could be a collision in the strict context hash, where we're scanning the module with two different compiler invocations but some of the options are not contributing to the context hash even though the may change the PCM contents. My first guess would be we don't do this for reduced BMIs, or something specific to C++ modules, because I haven't seen this on pure ObjC scans before.

@naveen-seth

naveen-seth commented Apr 28, 2026

Copy link
Copy Markdown
Contributor Author

@jansvoboda11 @mikaelholmen I’ve started investigating, but have not been able to reproduce it yet. I think finding the root cause for this will take some time.
What should be the immediate action?
I would like to not revert this PR/test if possible, but I guess this bug could randomly reappear.

(Also noticed this has nothing to do with tsan. Please ignore my earlier mention of that ^^)

@jansvoboda11

Copy link
Copy Markdown
Contributor

If it's just a single lit test, you could add // UNSUPPORTED: true at the top.

naveen-seth added a commit to naveen-seth/llvm-project that referenced this pull request Apr 29, 2026
…ilds.

Fixes llvm#194475 (comment).

This assert was thrown because of the following scenario:

Say threads 1 and 2 both try to compile the same module.
and both concurrently call findOrCompileModuleAndReadAST() and both have a cache
miss.
Both will then go and call compileModuleBehindLockOrRead().
If thread 1 completes the compilation, locking and unlocking before thread 2
even tries to lock, thread 2 will also compile the module a second time.

This adds a check after acquiring the lock to prevent such situations.

Since the original bug occurred randomly, this fix was tested by running the
failing test ~20 times while deleting the module cache after each run.
yingopq pushed a commit to yingopq/llvm-project that referenced this pull request Apr 29, 2026
… import std" (2nd attempt) (llvm#194475)

This reverts llvm#193857 and relands llvm#193312.

This adds basic support for explicit C++ named module builds, managed
natively by the Clang driver, including support for use of the Standard
library modules. This follows llvm#187606, which adds the same for Clang
modules.

Current limitations:
- Standard library modules are still compiled to object files instead of
using the provided shared library. (This will be addressed in a
follow-up soon.)
- Caching is not supported yet (but likely to be added during the
upcoming GSoC cycle).
- Importing C++ standard library modules into Clang modules is not
supported (and not expected in the near term).

RFC:

https://discourse.llvm.org/t/rfc-modules-support-simple-c-20-modules-use-from-the-clang-driver-without-a-build-system
yingopq pushed a commit to yingopq/llvm-project that referenced this pull request Apr 29, 2026
…194502)

See
llvm#194475 (comment).
This constrains the test to not run on aarch64, where it fails on
`clang-aarch64-quick` and `llvm-clang-aarch64-darwin` builders.
The failing builders don't show any output, and the test will be
re-enabled for aarch64 in a later follow-up.

Co-authored-by: Naveen Seth Hanig <naveen.hanig@oulook.com>
KHicketts pushed a commit to KHicketts/llvm-project that referenced this pull request Apr 30, 2026
… import std" (2nd attempt) (llvm#194475)

This reverts llvm#193857 and relands llvm#193312.

This adds basic support for explicit C++ named module builds, managed
natively by the Clang driver, including support for use of the Standard
library modules. This follows llvm#187606, which adds the same for Clang
modules.

Current limitations:
- Standard library modules are still compiled to object files instead of
using the provided shared library. (This will be addressed in a
follow-up soon.)
- Caching is not supported yet (but likely to be added during the
upcoming GSoC cycle).
- Importing C++ standard library modules into Clang modules is not
supported (and not expected in the near term).

RFC:

https://discourse.llvm.org/t/rfc-modules-support-simple-c-20-modules-use-from-the-clang-driver-without-a-build-system
KHicketts pushed a commit to KHicketts/llvm-project that referenced this pull request Apr 30, 2026
…194502)

See
llvm#194475 (comment).
This constrains the test to not run on aarch64, where it fails on
`clang-aarch64-quick` and `llvm-clang-aarch64-darwin` builders.
The failing builders don't show any output, and the test will be
re-enabled for aarch64 in a later follow-up.

Co-authored-by: Naveen Seth Hanig <naveen.hanig@oulook.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category skip-precommit-approval PR for CI feedback, not intended for review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants