Skip to content

Commit f661260

Browse files
committed
fix cenv: the freestanding branch must emit -fno-short-wchar unconditionally
bb0437d dropped the freestanding ? 32 : native_wchar_bits(os) special case that 7097acd had added, on the grounds that it was wrong on Windows hosts. That is right for the -U_<WIN32>-stripped probe, but for the REAL compile (the one whose cflags the engine broadcasts to the package's own translation units) the toolchain's freestanding default on Windows is host-contaminated: clang on Windows emits a 16-bit wchar_t by default for -target=riscv64-none-elf unless told otherwise. So a declaration of wchar=32 needs -fno-short-wchar on every freestanding target regardless of what native_wchar_bits(os) says, and the previous "if (decl.wcharBits != native)" gate lets a 32-bit declaration through to a 16-bit compile on Windows freestanding. Symmetric for wchar=16: a freestanding Linux/macOS host's default wchar is 32, and the declaration 16 needs -fshort-wchar. The "hosted" branch (the else-if) keeps the old behaviour; only the freestanding branch is restructured. Verified locally with openkal-musl#37 and openkal-llvm-runtime#24's matrix against mcpp built from this branch.
1 parent 534b1ee commit f661260

1 file changed

Lines changed: 27 additions & 13 deletions

File tree

src/toolchain/cenv.cppm

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -383,22 +383,36 @@ inline std::expected<Realisation, std::string> realise(
383383
// `wchar_t` is 16 bits there — and a `decl.wcharBits = 32` (musl's
384384
// declaration) would compile to a 16-bit `wchar_t` because no token
385385
// was added. The probe caught this; the right fix is here, not in the
386-
// probe: always emit `-fno-short-wchar` when the declaration asks for
387-
// 32, so the compiler produces 32-bit `wchar_t` regardless of what its
388-
// host-contaminated default would have been. Same for `wchar=16` on
389-
// a target that would otherwise default to 32: `-fshort-wchar` keeps
390-
// the compile honest.
386+
// probe: a freestanding target ALWAYS gets `-fno-short-wchar` for
387+
// `wchar=32`, so the compiler produces 32-bit `wchar_t` regardless of
388+
// what its host-contaminated default would have been. Symmetric for
389+
// `wchar=16`: a freestanding target's toolchain default on Linux/macOS
390+
// is 32, so `-fshort-wchar` is always needed too. The hosted cases
391+
// are unchanged — `native_wchar_bits(os)` is correct for every hosted
392+
// target, because the host's toolchain default is what the real
393+
// compile actually sees (Windows host has `-fshort-wchar` baked in
394+
// via MinGW headers; Linux/macOS hosts have 32 bits).
391395
//
392396
// The probe below then measures what this engine actually produced
393-
// (32 bits, with the flag) — not the host's leak — and the declaration
394-
// holds. There is no measurement-side workaround here: the previous
395-
// version had a "freestanding target skips the wchar flag" rule that
396-
// was wrong on Windows hosts, and removing it costs nothing on
397-
// Linux/macOS hosts (they default to 32, so adding the flag there is
398-
// redundant but harmless).
397+
// (32 bits on a freestanding target, with the flag) — not the host's
398+
// leak — and the declaration holds. There is no measurement-side
399+
// workaround here: the previous version had a "freestanding target
400+
// skips the wchar flag" rule that was wrong on Windows hosts, and
401+
// adding it costs nothing on Linux/macOS hosts (they default to 32,
402+
// so the flag is redundant but harmless on the hosted freestanding
403+
// builds that don't exist; for hosted Linux/macOS, no flag is added).
399404
if (decl.hasWchar) {
400-
const int native = native_wchar_bits(os);
401-
if (decl.wcharBits != native) {
405+
if (freestanding) {
406+
// Freestanding: the toolchain's host-contaminated default is
407+
// not something this engine can trust. Always emit the
408+
// token that makes the compile match the declaration.
409+
r.tokens.push_back(decl.wcharBits == 32 ? "-fno-short-wchar"
410+
: "-fshort-wchar");
411+
} else if (decl.wcharBits != native_wchar_bits(os)) {
412+
// Hosted: the target's own default is what the compile sees,
413+
// and `native_wchar_bits(os)` correctly captures it
414+
// (16 on Windows because MinGW headers bake in
415+
// `-fshort-wchar`; 32 on Linux and macOS).
402416
r.tokens.push_back(decl.wcharBits == 32 ? "-fno-short-wchar"
403417
: "-fshort-wchar");
404418
}

0 commit comments

Comments
 (0)