Author: Naveen Seth Hanig Date: 2026-05-28T14:19:44Z New Revision: a16511c2d9697e7c5a9a9bc10948762666573c3c
URL: https://github.com/llvm/llvm-project/commit/a16511c2d9697e7c5a9a9bc10948762666573c3c DIFF: https://github.com/llvm/llvm-project/commit/a16511c2d9697e7c5a9a9bc10948762666573c3c.diff LOG: [clang][modules-driver] Precompile std modules independently of -o and final phase (#199289) With this, Standard library modules are always precompiled as the primary output of their `-cc1` invocation, instead of being produced as a byproduct of compiling the Standard library modules to object files. This also keeps Standard library module precompilation independent of the final phase specified on the command line, so importing them keep working under `-fsyntax-only` (and other command-line options that specify the final phase). This also makes the Standard library module precompilation independent of the `-o` flag, so that a command like `clang -std=c++23 -fmodules-driver main.cpp -o main` no longer redirects the Standard library module outputs to 'main', breaking the compilation. Added: Modified: clang/include/clang/Driver/Types.def clang/lib/Driver/Driver.cpp clang/lib/Driver/ModulesDriver.cpp clang/lib/Driver/ToolChains/Clang.cpp clang/lib/Driver/Types.cpp clang/lib/Tooling/InterpolatingCompilationDatabase.cpp clang/test/Driver/modules-driver-dep-graph-stdlib-modules.cpp clang/test/Driver/modules-driver-import-std.cpp Removed: ################################################################################ diff --git a/clang/include/clang/Driver/Types.def b/clang/include/clang/Driver/Types.def index 76944ec656917..74563ff835179 100644 --- a/clang/include/clang/Driver/Types.def +++ b/clang/include/clang/Driver/Types.def @@ -73,6 +73,10 @@ TYPE("objective-c++-header-cpp-output", PP_ObjCXXHeader, INVALID,"mii", phases TYPE("objective-c++-header", ObjCXXHeader, PP_ObjCXXHeader, "h", phases::Preprocess, phases::Precompile) TYPE("c++-module", CXXModule, PP_CXXModule, "cppm", phases::Preprocess, phases::Precompile, phases::Compile, phases::Backend, phases::Assemble, phases::Link) TYPE("c++-module-cpp-output", PP_CXXModule, INVALID, "iim", phases::Precompile, phases::Compile, phases::Backend, phases::Assemble, phases::Link) +// Used only in -fmodules-driver for the implicitly generated Standard library +// module inputs. +TYPE("c++-std-module", CXXStdModule, PP_CXXStdModule, "cppm", phases::Preprocess, phases::Precompile) +TYPE("c++-std-module-output", PP_CXXStdModule, INVALID, "iim", phases::Precompile) // Other languages. TYPE("ada", Ada, INVALID, nullptr, phases::Compile, phases::Backend, phases::Assemble, phases::Link) diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 4a968a4ce5cc0..82e8977648b92 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -5275,6 +5275,13 @@ Action *Driver::ConstructPhaseAction( if (Args.hasArg(options::OPT_extract_api)) return C.MakeAction<ExtractAPIJobAction>(Input, types::TY_API_INFO); + // Standard library modules always precompile in -fmodules-driver mode, + // even when -fsyntax-only is specified. + if (Input->getType() == types::TY_CXXStdModule || + Input->getType() == types::TY_PP_CXXStdModule) + return C.MakeAction<PrecompileJobAction>( + Input, getPrecompiledType(Input->getType())); + // With 'fmodules-reduced-bmi', we don't want to run the // precompile phase unless the user specified '--precompile' or // '--precompile-reduced-bmi'. If '--precompile' is specified, we will try @@ -5471,6 +5478,14 @@ void Driver::BuildJobs(Compilation &C) const { A->getKind() == clang::driver::Action::BinaryTranslatorJobClass) continue; + // With -fmodules-driver, Standard library modules should not count toward + // the number of outputs, since they are implicitly added to the input + // list. + if (isa<PrecompileJobAction>(A) && !A->getInputs().empty() && + (A->getInputs().front()->getType() == types::TY_CXXStdModule || + A->getInputs().front()->getType() == types::TY_PP_CXXStdModule)) + continue; + if (A->getType() != types::TY_Nothing && !(A->getKind() == Action::IfsMergeJobClass || (A->getType() == clang::driver::types::TY_IFS_CPP && @@ -6472,6 +6487,31 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA, std::string BoundArch = sanitizeTargetIDInFileName(OrigBoundArch); llvm::PrettyStackTraceString CrashInfo("Computing output path"); + + auto CreateTempOutputPath = [&](StringRef Prefix) { + const char *Suffix = + types::getTypeTempSuffix(JA.getType(), IsCLMode() || IsDXCMode()); + // The non-offloading toolchain on Darwin requires deterministic input + // file name for binaries to be deterministic, therefore it needs unique + // directory. + const llvm::Triple Triple(C.getDriver().getTargetTriple()); + const bool NeedUniqueDirectory = + (JA.getOffloadingDeviceKind() == Action::OFK_None || + JA.getOffloadingDeviceKind() == Action::OFK_Host) && + Triple.isOSDarwin(); + return CreateTempFile(C, Prefix, Suffix, MultipleArchs, BoundArch, + NeedUniqueDirectory); + }; + + // Standard library output in -fmodules-driver? + if (isa<PrecompileJobAction>(JA) && !JA.getInputs().empty() && + (JA.getInputs().front()->getType() == types::TY_CXXStdModule || + JA.getInputs().front()->getType() == types::TY_PP_CXXStdModule)) { + StringRef Filename = llvm::sys::path::filename(BaseInput); + StringRef Stem = llvm::sys::path::stem(Filename); + return CreateTempOutputPath(Stem); + } + // Output to a user requested destination? if (AtTopLevel && !isa<DsymutilJobAction>(JA) && !isa<VerifyJobAction>(JA)) { if (Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o)) @@ -6570,19 +6610,7 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA, !C.getArgs().hasArg(options::OPT__SLASH_Fo)) || CCGenDiagnostics) { StringRef Name = llvm::sys::path::filename(BaseInput); - std::pair<StringRef, StringRef> Split = Name.split('.'); - const char *Suffix = - types::getTypeTempSuffix(JA.getType(), IsCLMode() || IsDXCMode()); - // The non-offloading toolchain on Darwin requires deterministic input - // file name for binaries to be deterministic, therefore it needs unique - // directory. - llvm::Triple Triple(C.getDriver().getTargetTriple()); - bool NeedUniqueDirectory = - (JA.getOffloadingDeviceKind() == Action::OFK_None || - JA.getOffloadingDeviceKind() == Action::OFK_Host) && - Triple.isOSDarwin(); - return CreateTempFile(C, Split.first, Suffix, MultipleArchs, BoundArch, - NeedUniqueDirectory); + return CreateTempOutputPath(Name.split('.').first); } SmallString<128> BasePath(BaseInput); diff --git a/clang/lib/Driver/ModulesDriver.cpp b/clang/lib/Driver/ModulesDriver.cpp index 3f7a9f346accd..e0a4503857871 100644 --- a/clang/lib/Driver/ModulesDriver.cpp +++ b/clang/lib/Driver/ModulesDriver.cpp @@ -146,7 +146,7 @@ void driver::modules::buildStdModuleManifestInputs( for (const auto &Entry : ManifestEntries) { auto *InputArg = makeInputArg(Args, Opts, Args.MakeArgString(Entry.SourcePath)); - Inputs.emplace_back(types::TY_CXXModule, InputArg); + Inputs.emplace_back(types::TY_CXXStdModule, InputArg); } } @@ -1213,7 +1213,8 @@ static bool validateScannedJobInputKinds( const auto &MainInput = Job.getInputInfos().front(); const bool DefinesNamedModule = !InputDeps.ModuleName.empty(); - if (DefinesNamedModule && MainInput.getType() != types::TY_CXXModule) { + if (DefinesNamedModule && MainInput.getType() != types::TY_CXXModule && + MainInput.getType() != types::TY_CXXStdModule) { Diags.Report(diag::err_module_defined_outside_of_module_source) << InputDeps.ModuleName << MainInput.getFilename(); return false; @@ -1597,6 +1598,18 @@ static void fixupNamedModuleCommandLines(Compilation &C, llvm::CastTo<NamedModuleJobNode>); for (NamedModuleJobNode *Node : NamedModuleNodes) { + const auto &Job = *Node->Job; + + // For Standard library modules, the driver already creates the module + // output as a temp file, so we can use that path directly. + const bool IsStdModule = + Job.getInputInfos().front().getType() == types::TY_CXXStdModule; + if (IsStdModule) { + StringRef ModuleOutputPath = Job.getOutputFilenames().front(); + propagateModuleFileMappingArg(C, *Node, ModuleOutputPath); + continue; + } + const StringRef ModuleName = Node->InputDeps.ModuleName; const auto ModuleOutputPath = createModuleOutputPath(C, ModuleName); C.addTempFile(C.getArgs().MakeArgString(ModuleOutputPath)); diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index a4c2de2dfbabb..0f915e9f222f7 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -349,6 +349,7 @@ static void addDashXForInput(const ArgList &Args, const InputInfo &Input, const char *ClangType; switch (Input.getType()) { case types::TY_CXXModule: + case types::TY_CXXStdModule: ClangType = "c++"; break; case types::TY_PP_CXXModule: @@ -5274,7 +5275,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (JA.getType() == types::TY_Nothing) CmdArgs.push_back("-fsyntax-only"); else if (JA.getType() == types::TY_ModuleFile) { - if (Args.hasArg(options::OPT__precompile_reduced_bmi)) + if (Args.hasArg(options::OPT__precompile_reduced_bmi) || + ((Input.getType() == types::TY_CXXStdModule || + Input.getType() == types::TY_PP_CXXStdModule) && + !Args.hasArg(options::OPT_fno_modules_reduced_bmi))) CmdArgs.push_back("-emit-reduced-module-interface"); else CmdArgs.push_back("-emit-module-interface"); diff --git a/clang/lib/Driver/Types.cpp b/clang/lib/Driver/Types.cpp index 08866e89ea447..7cf8af1d1af92 100644 --- a/clang/lib/Driver/Types.cpp +++ b/clang/lib/Driver/Types.cpp @@ -59,7 +59,8 @@ types::ID types::getPreprocessedType(ID Id) { } static bool isPreprocessedModuleType(ID Id) { - return Id == TY_CXXModule || Id == TY_PP_CXXModule; + return Id == TY_CXXModule || Id == TY_PP_CXXModule || Id == TY_CXXStdModule || + Id == TY_PP_CXXStdModule; } static bool isPreprocessedHeaderUnitType(ID Id) { @@ -101,13 +102,28 @@ bool types::onlyPrecompileType(ID Id) { bool types::canTypeBeUserSpecified(ID Id) { static const clang::driver::types::ID kStaticLangageTypes[] = { - TY_CUDA_DEVICE, TY_HIP_DEVICE, TY_PP_CHeader, - TY_PP_ObjCHeader, TY_PP_CXXHeader, TY_PP_ObjCXXHeader, - TY_PP_CXXModule, TY_LTO_IR, TY_LTO_BC, - TY_Plist, TY_RewrittenObjC, TY_RewrittenLegacyObjC, - TY_Remap, TY_PCH, TY_Object, - TY_Image, TY_dSYM, TY_Dependencies, - TY_CUDA_FATBIN, TY_HIP_FATBIN}; + TY_CUDA_DEVICE, + TY_HIP_DEVICE, + TY_PP_CHeader, + TY_PP_ObjCHeader, + TY_PP_CXXHeader, + TY_PP_ObjCXXHeader, + TY_PP_CXXModule, + TY_CXXStdModule, + TY_PP_CXXStdModule, + TY_LTO_IR, + TY_LTO_BC, + TY_Plist, + TY_RewrittenObjC, + TY_RewrittenLegacyObjC, + TY_Remap, + TY_PCH, + TY_Object, + TY_Image, + TY_dSYM, + TY_Dependencies, + TY_CUDA_FATBIN, + TY_HIP_FATBIN}; return !llvm::is_contained(kStaticLangageTypes, Id); } @@ -148,7 +164,10 @@ bool types::isAcceptedByClang(ID Id) { case TY_CXXHUHeader: case TY_PP_CXXHeaderUnit: case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader: - case TY_CXXModule: case TY_PP_CXXModule: + case TY_CXXModule: + case TY_PP_CXXModule: + case TY_CXXStdModule: + case TY_PP_CXXStdModule: case TY_AST: case TY_ModuleFile: case TY_PCH: case TY_LLVM_IR: case TY_LLVM_BC: case TY_API_INFO: @@ -209,6 +228,8 @@ bool types::isDerivedFromC(ID Id) { case TY_ObjCXXHeader: case TY_CXXModule: case TY_PP_CXXModule: + case TY_CXXStdModule: + case TY_PP_CXXStdModule: return true; } } @@ -253,6 +274,8 @@ bool types::isCXX(ID Id) { case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader: case TY_CXXModule: case TY_PP_CXXModule: + case TY_CXXStdModule: + case TY_PP_CXXStdModule: case TY_ModuleFile: case TY_PP_CLCXX: case TY_CUDA: case TY_PP_CUDA: case TY_CUDA_DEVICE: @@ -435,6 +458,7 @@ ID types::lookupHeaderTypeForSourceType(ID Id) { return types::TY_CHeader; case types::TY_CXX: case types::TY_CXXModule: + case types::TY_CXXStdModule: return types::TY_CXXHeader; case types::TY_ObjC: return types::TY_ObjCHeader; diff --git a/clang/lib/Tooling/InterpolatingCompilationDatabase.cpp b/clang/lib/Tooling/InterpolatingCompilationDatabase.cpp index 08ee02f639a4f..36d0775a80708 100644 --- a/clang/lib/Tooling/InterpolatingCompilationDatabase.cpp +++ b/clang/lib/Tooling/InterpolatingCompilationDatabase.cpp @@ -113,6 +113,8 @@ static types::ID foldType(types::ID Lang) { case types::TY_CXXHeader: case types::TY_CXXModule: case types::TY_PP_CXXModule: + case types::TY_CXXStdModule: + case types::TY_PP_CXXStdModule: return types::TY_CXX; case types::TY_ObjCXX: case types::TY_ObjCXXHeader: diff --git a/clang/test/Driver/modules-driver-dep-graph-stdlib-modules.cpp b/clang/test/Driver/modules-driver-dep-graph-stdlib-modules.cpp index 04108cfabea89..de6e917e115d4 100644 --- a/clang/test/Driver/modules-driver-dep-graph-stdlib-modules.cpp +++ b/clang/test/Driver/modules-driver-dep-graph-stdlib-modules.cpp @@ -34,18 +34,18 @@ // CHECK: digraph "Module Dependency Graph" { // -// CHECK: "[[PREFIX]]/main.cpp-x86_64-unknown-linux-gnu" [fillcolor=3, label="{ Filename: [[PREFIX]]/main.cpp | Triple: x86_64-unknown-linux-gnu }"]; -// CHECK-NEXT: "[[PREFIX]]/foo.cpp-x86_64-unknown-linux-gnu" [fillcolor=3, label="{ Filename: [[PREFIX]]/foo.cpp | Triple: x86_64-unknown-linux-gnu }"]; -// CHECK-NEXT: "std-x86_64-unknown-linux-gnu" [fillcolor=2, label="{ Filename: {{.*}} | Module type: Named module | Module name: std | Triple: x86_64-unknown-linux-gnu }"]; -// CHECK-NEXT: "std.compat-x86_64-unknown-linux-gnu" [fillcolor=2, label="{ Filename: {{.*}} | Module type: Named module | Module name: std.compat | Triple: x86_64-unknown-linux-gnu }"]; -// CHECK-NEXT: "core-x86_64-unknown-linux-gnu" [fillcolor=2, label="{ Filename: {{.*}} | Module type: Named module | Module name: core | Triple: x86_64-unknown-linux-gnu }"]; +// CHECK-DAG: "[[PREFIX]]/main.cpp-x86_64-unknown-linux-gnu" [fillcolor=3, label="{ Filename: [[PREFIX]]/main.cpp | Triple: x86_64-unknown-linux-gnu }"]; +// CHECK-DAG: "[[PREFIX]]/foo.cpp-x86_64-unknown-linux-gnu" [fillcolor=3, label="{ Filename: [[PREFIX]]/foo.cpp | Triple: x86_64-unknown-linux-gnu }"]; +// CHECK-DAG: "std-x86_64-unknown-linux-gnu" [fillcolor=2, label="{ Filename: {{.*}} | Module type: Named module | Module name: std | Triple: x86_64-unknown-linux-gnu }"]; +// CHECK-DAG: "std.compat-x86_64-unknown-linux-gnu" [fillcolor=2, label="{ Filename: {{.*}} | Module type: Named module | Module name: std.compat | Triple: x86_64-unknown-linux-gnu }"]; +// CHECK-DAG: "core-x86_64-unknown-linux-gnu" [fillcolor=2, label="{ Filename: {{.*}} | Module type: Named module | Module name: core | Triple: x86_64-unknown-linux-gnu }"]; // -// CHECK: "std-x86_64-unknown-linux-gnu" -> "[[PREFIX]]/main.cpp-x86_64-unknown-linux-gnu"; -// CHECK-NEXT: "std-x86_64-unknown-linux-gnu" -> "[[PREFIX]]/foo.cpp-x86_64-unknown-linux-gnu"; -// CHECK-NEXT: "std-x86_64-unknown-linux-gnu" -> "std.compat-x86_64-unknown-linux-gnu"; -// CHECK-NEXT: "std.compat-x86_64-unknown-linux-gnu" -> "[[PREFIX]]/main.cpp-x86_64-unknown-linux-gnu"; -// CHECK-NEXT: "core-x86_64-unknown-linux-gnu" -> "[[PREFIX]]/foo.cpp-x86_64-unknown-linux-gnu"; -// CHECK-NEXT: } +// CHECK-DAG: "std-x86_64-unknown-linux-gnu" -> "[[PREFIX]]/main.cpp-x86_64-unknown-linux-gnu"; +// CHECK-DAG: "std-x86_64-unknown-linux-gnu" -> "[[PREFIX]]/foo.cpp-x86_64-unknown-linux-gnu"; +// CHECK-DAG: "std-x86_64-unknown-linux-gnu" -> "std.compat-x86_64-unknown-linux-gnu"; +// CHECK-DAG: "std.compat-x86_64-unknown-linux-gnu" -> "[[PREFIX]]/main.cpp-x86_64-unknown-linux-gnu"; +// CHECK-DAG: "core-x86_64-unknown-linux-gnu" -> "[[PREFIX]]/foo.cpp-x86_64-unknown-linux-gnu"; +// CHECK: } //--- main.cpp diff --git a/clang/test/Driver/modules-driver-import-std.cpp b/clang/test/Driver/modules-driver-import-std.cpp index 3a51cab0406b2..a97ec84c716f6 100644 --- a/clang/test/Driver/modules-driver-import-std.cpp +++ b/clang/test/Driver/modules-driver-import-std.cpp @@ -51,15 +51,83 @@ int main() {} // RUN: %clang -std=c++23 -stdlib=libc++ \ // RUN: -fmodules-driver -Rmodules-driver -Rmodule-import \ -// RUN: -stdlib=libc++ \ // RUN: -resource-dir=%t/FakeSysroot/usr/lib/x86_64-linux-gnu \ // RUN: --sysroot=%t/FakeSysroot \ // RUN: -L%t/Inputs/usr/lib/x86_64-linux-gnu \ // RUN: --target=x86_64-linux-gnu \ // RUN: -c %t/main.cpp 2>&1 \ +// RUN: --verbose \ // RUN: | sed 's:\\\\\?:/:g' \ // RUN: | FileCheck -DPREFIX=%/t %s +// Skip past diagnostics omitted during the dependency scan. +// CHECK: clang: remark: printing module dependency graph [-Rmodules-driver] + +// Checks that the standard library modules are primary outputs. +// TODO: Test the same for -fno-modules-reduced-bmi when supported by +// -fmodules-driver. +// CHECK: -o {{.*std-[^ ]*\.pcm}} +// CHECK-SAME: -emit-reduced-module-interface +// CHECK-SAME: -main-file-name std.cppm +// CHECK: -o {{.*std\.compat-[^ ]*\.pcm}} +// CHECK-SAME: -emit-reduced-module-interface +// CHECK-SAME: -main-file-name std.compat.cppm + +// Checks that the object file is generated for the main TU. +// CHECK: -emit-obj +// CHECK-SAME: -main-file-name main.cpp + +// Checks that the standard library modules are successfully imported. // 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 + +// Checks that standard library modules are still precompiled with -emit-llvm. +// RUN: %clang -std=c++23 -stdlib=libc++ \ +// RUN: -fmodules-driver -Rmodules-driver -Rmodule-import \ +// RUN: -resource-dir=%t/FakeSysroot/usr/lib/x86_64-linux-gnu \ +// RUN: --sysroot=%t/FakeSysroot \ +// RUN: -L%t/Inputs/usr/lib/x86_64-linux-gnu \ +// RUN: --target=x86_64-linux-gnu \ +// RUN: %t/main.cpp -S -emit-llvm -o out.ll \ +// RUN: --verbose 2>&1 \ +// RUN: | sed 's:\\\\\?:/:g' \ +// RUN: | FileCheck -DPREFIX=%/t --check-prefix=CHECK-EMIT-LLVM %s + +// Skip past diagnostics omitted during the dependency scan. +// CHECK-EMIT-LLVM: clang: remark: printing module dependency graph [-Rmodules-driver] + +// CHECK-EMIT-LLVM: -o {{.*std-[^ ]*\.pcm}} +// CHECK-EMIT-LLVM-SAME: -emit-reduced-module-interface +// CHECK-EMIT-LLVM-SAME: -main-file-name std.cppm +// CHECK-EMIT-LLVM: -o {{.*std\.compat-[^ ]*\.pcm}} +// CHECK-EMIT-LLVM-SAME: -emit-reduced-module-interface +// CHECK-EMIT-LLVM-SAME: -main-file-name std.compat.cppm +// CHECK-EMIT-LLVM: -emit-llvm +// CHECK-EMIT-LLVM-SAME: -main-file-name main.cpp + +// Checks that standard library modules are still precompiled with -fsyntax-only. +// RUN: %clang -std=c++23 -stdlib=libc++ \ +// RUN: -fmodules-driver -Rmodules-driver -Rmodule-import \ +// RUN: -resource-dir=%t/FakeSysroot/usr/lib/x86_64-linux-gnu \ +// RUN: --sysroot=%t/FakeSysroot \ +// RUN: -L%t/Inputs/usr/lib/x86_64-linux-gnu \ +// RUN: --target=x86_64-linux-gnu \ +// RUN: -fsyntax-only \ +// RUN: %t/main.cpp \ +// RUN: --verbose 2>&1 \ +// RUN: | sed 's:\\\\\?:/:g' \ +// RUN: | FileCheck -DPREFIX=%/t --check-prefix=CHECK-SYNTAX-ONLY %s + +// Skip past diagnostics omitted during the dependency scan. +// CHECK-SYNTAX-ONLY: clang: remark: printing module dependency graph [-Rmodules-driver] + +// CHECK-SYNTAX-ONLY: -o {{.*std-[^ ]*\.pcm}} +// CHECK-SYNTAX-ONLY-SAME: -emit-reduced-module-interface +// CHECK-SYNTAX-ONLY-SAME: -main-file-name std.cppm +// CHECK-SYNTAX-ONLY: -o {{.*std\.compat-[^ ]*\.pcm}} +// CHECK-SYNTAX-ONLY-SAME: -emit-reduced-module-interface +// CHECK-SYNTAX-ONLY-SAME: -main-file-name std.compat.cppm + +// CHECK-SYNTAX-ONLY: -cc1 {{.*}} -Rmodules-driver +// CHECK-SYNTAX-ONLY-NOT: {{ -o }} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
