Symptom
A C++20 project that writes import std; is refused on Windows, where mcpp's
default toolchain is clang targeting x86_64-pc-windows-msvc:
error: source imports std but toolchain 'clang 20.1.7 (x86_64-pc-windows-msvc)'
provides the std module only from c++23 up, while [package].standard
resolves to 'c++20'; raise the standard or drop `import std;`
The same sources build at c++20 with GCC 16.1.0 on Linux, with llvm 22.1.8 on
Linux, and on macOS.
Why this looks wrong
The MSVC STL's named modules are documented as needing /std:c++20 or later,
and mcpp already knows how to decide this — msvc.cppm probes the installation
rather than assuming:
// src/toolchain/msvc.cppm:1040-1042
if (tc.hasImportStd) {
tc.importStdMinLevel = std_module_min_level(tc); // reads the cl banner version
}
The clang-on-Windows path, which falls back to the same std.ixx, does not
call it:
// src/toolchain/clang.cppm:153-166
#if defined(_WIN32)
// Fallback: if libc++ std.cppm not found, look for MSVC STL's std.ixx.
if (!tc.hasImportStd && msvTarget) {
if (auto p = mcpp::toolchain::msvc::find_std_module_source()) {
tc.stdModuleSource = *p;
tc.hasImportStd = true;
// This is MSVC STL's std.ixx — the STL's own C++20 policy applies,
// not libc++'s. tc.version is clang's here, so it cannot answer the
// cl-banner question; stay strict (the STL is the binding side).
tc.importStdMinLevel = 23;
}
}
#endif
The comment states the reason exactly: tc.version is clang's, so that field
cannot answer the question — and the code then assumes the worst instead of
asking the component that can. prepare.cppm describes the intended policy as
version-dependent, not family-dependent:
// src/build/prepare.cppm:9738-9741
// Every toolchain mcpp ships answers 20; only an MSVC STL older than
// microsoft/STL#3977 answers 23, and those users would otherwise get an
// error from inside std.ixx.
So on a machine whose STL is newer than microsoft/STL#3977 — a GitHub
windows-2022 runner has VS 2022 17.14, VC tools 14.44.35207 — clang + that
STL should answer 20, and answers 23 only because the probe is skipped.
Suggested fix
Call the existing probe from the clang path. The STL version is discoverable
there through the same msvc:: helpers that found std.ixx, and it is the
binding side either way:
tc.importStdMinLevel = mcpp::toolchain::msvc::std_module_min_level_for_stl(...);
Falling back to 23 when the STL version genuinely cannot be determined would
keep the safety the current comment is after, without penalising every modern
installation.
Reproducing
# mcpp.toml
[package]
standard = "c++20"
export module app;
import std;
int main() {}
mcpp build on Windows with mcpp 2026.9.10.2 and no libc++ present.
Impact
A project that wants a header-free module unit needs import std; — on GCC and
Clang+libc++ std::type_info and friends are otherwise only reachable through
a global module fragment. Pinning standard = "c++23" works around it, but a
module graph has exactly one standard, so raising it for this reason also
raises it for every dependency in the graph.
Symptom
A C++20 project that writes
import std;is refused on Windows, where mcpp'sdefault toolchain is clang targeting
x86_64-pc-windows-msvc:The same sources build at c++20 with GCC 16.1.0 on Linux, with llvm 22.1.8 on
Linux, and on macOS.
Why this looks wrong
The MSVC STL's named modules are documented as needing
/std:c++20or later,and mcpp already knows how to decide this —
msvc.cppmprobes the installationrather than assuming:
The clang-on-Windows path, which falls back to the same
std.ixx, does notcall it:
The comment states the reason exactly:
tc.versionis clang's, so that fieldcannot answer the question — and the code then assumes the worst instead of
asking the component that can.
prepare.cppmdescribes the intended policy asversion-dependent, not family-dependent:
So on a machine whose STL is newer than microsoft/STL#3977 — a GitHub
windows-2022runner has VS 2022 17.14, VC tools 14.44.35207 — clang + thatSTL should answer 20, and answers 23 only because the probe is skipped.
Suggested fix
Call the existing probe from the clang path. The STL version is discoverable
there through the same
msvc::helpers that foundstd.ixx, and it is thebinding side either way:
Falling back to 23 when the STL version genuinely cannot be determined would
keep the safety the current comment is after, without penalising every modern
installation.
Reproducing
mcpp buildon Windows with mcpp 2026.9.10.2 and no libc++ present.Impact
A project that wants a header-free module unit needs
import std;— on GCC andClang+libc++
std::type_infoand friends are otherwise only reachable througha global module fragment. Pinning
standard = "c++23"works around it, but amodule graph has exactly one standard, so raising it for this reason also
raises it for every dependency in the graph.