Repository navigation
clang on Windows hardcodes importStdMinLevel = 23 instead of probing the MSVC STL #603
Description
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;
}
}
#endifThe 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.
Activity
feat(mcpp): pin the examples to c++23, and report why they have to
feat(templates): pin c++23, for the same reason the examples do
docs: name the module path by what it is, not by one standard
feat(templates): pin c++23, for the same reason the examples do
docs: name the module path by what it is, not by one standard
feat(templates): pin c++23, for the same reason the examples do
docs: name the module path by what it is, not by one standard
feat(mcpp): pin the examples to c++23, and report why they have to
docs(triage): six open issues, and where three of the reports are wro…
fix(scanner, host modules, toolchain, config, bench): five open issue…
Five open issues, three of them misdiagnosed by their reports, and st…
Sunrisepeak commentedon Sep 11, 2026
Fixed in #607, released in 2026.9.11.2. The clang-on-Windows path reads the level from the MSVC STL whose
std.ixxit selected, throughmsvc::std_module_min_level_for_stl, instead of hardcoding 23.tc.versionis clang's and could not answer the question. Confirmed on main at c688fca insrc/toolchain/clang.cppm.