You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(standard): make c++20 a first-class level, keep c++23 the default
`import std;` is a C++23 library feature, but named modules are C++20 and all
three implementations provide the std module in C++20 mode too — libstdc++'s
bits/std.cc and libc++'s std.cppm carry no __cplusplus guard, and MSVC STL
unblocked it in microsoft/STL#3977 ("purely a policy choice, no technical
reason"). So the level and the ability to import std are separate questions.
Verified by replaying mcpp's own recorded std-module build commands (sysroot,
-B, -isystem and hermetic link model included) with -std=c++20 substituted, then
compiling, linking and running a consumer TU: gcc 15.1.0 / 16.1.0 across
glibc / musl / mingw-cross and clang 22.1.8 + libc++ (std and std.compat) all
pass. musl and mingw run via -static natively and under wine.
- allow-list: c++20 / c++2a / gnu++20 / gnu++2a (level 20). C++20 is the floor —
named modules do not exist below it. Default stays c++23: unset manifests
fingerprint byte-identically, and `mcpp new` templates keep using std::println.
- `import std` availability becomes two-dimensional: Toolchain::importStdMinLevel,
filled by each provider next to hasImportStd (GCC and libc++ answer 20; MSVC
answers 20 from cl 19.38 = VS 2022 17.8 per STL#3977, 23 below that, so those
users get an actionable error instead of one from inside std.ixx).
- no cache work needed: the standard was already part of the fingerprint, the std
BMI identity and the dependency build-cache key. The compiler is the backstop —
cross-level BMI reuse is rejected with "language dialect differs".
Also fixes build.mcpp under standard = "c++fly" / "c++latest": it concatenated
"-std=" + canonical, and those canonicals are not valid -std= spellings, so the
host compile died on an unknown dialect. It now goes through the same dialect
layer as the main build, resolved against the host toolchain that runs it.
The previous Manifest.RejectImportStdWithoutCpp23 test asserted this manifest is
rejected, but the only thing rejecting it was the standard allow-list — there has
never been an import_std-specific rule. It now asserts what it always meant to.
Design: .agents/docs/2026-07-31-cpp20-standard-support-design.md
Plan: .agents/docs/2026-07-31-cpp20-implementation-plan.md
`standard` is the first-class setting for the C++ language standard. Recommended values:
52
52
53
53
-`c++23`: the default, suited to the current module-based default templates.
54
+
-`c++20`: the lowest level mcpp accepts — named modules are a C++20 feature, so nothing below it exists for this build model. Use it when an external constraint (an older in-house rule, a third-party API that stops at C++20) forces the level down. `import std;` still works there: it is a C++23 *library* feature, but GCC (≥ 15), Clang + libc++ (≥ 17) and the MSVC STL all provide the `std` module in C++20 mode as well. Note that C++23 library facilities (`std::print`, `std::expected`, …) are not available, including in the code generated by `mcpp new`.
54
55
-`c++26`: use when you need C++26 language features.
55
-
-`c++2c`: a compatibility alias, normalized to `c++26` after parsing.
56
-
-`gnu++23` / `gnu++26`: use when you need a GNU dialect; this enters the fingerprint and the std BMI cache key.
56
+
-`c++2a` / `c++2c`: compatibility aliases, normalized to`c++20` /`c++26` after parsing.
57
+
-`gnu++20` / `gnu++23` / `gnu++26`: use when you need a GNU dialect; this enters the fingerprint and the std BMI cache key.
57
58
-`c++latest`: resolves to the newest standard level the resolved toolchain supports. Good for local experimentation, but not recommended for release packages that require reproducibility.
58
59
-`c++fly`: `c++latest`**plus every experimental standard feature the resolved toolchain can enable** (language + standard library). On GCC ≥ 16 this turns on C++26 reflection (`-freflection`) and contracts; on Clang/libc++ it adds `-fexperimental-library`; unsupported gates are skipped with a printed summary. Deliberately toolchain-dependent — the bleeding-edge playground mode, never for published packages.
59
60
61
+
Two properties worth knowing:
62
+
63
+
-**The standard is module-graph-global.** The root package's `standard` applies to every
64
+
translation unit in the build, dependencies included — a dependency's own `standard` is not
65
+
used when it is being built as a dependency. This is not a simplification: BMIs are not
66
+
compatible across levels (GCC rejects them with `language dialect differs`), so a single
67
+
graph physically cannot hold two levels.
68
+
-**Levels never share caches.** The standard is part of the fingerprint, the `import std` BMI
69
+
identity and the dependency build-cache key, so switching between `c++20` and `c++23` gives
70
+
each level its own target directory and its own std BMI instead of a corrupt hit.
71
+
72
+
If the sources `import std;` at a level the resolved toolchain does not provide the `std`
73
+
module for, mcpp fails before compiling and names both the toolchain and the project level.
0 commit comments