w6c+selfhost+lib: zero-init multi-word no-rhs lets

`let x: T;` for str/slice/tuple/struct/tagged previously left the slot
holding stack garbage — only 8B-primitive slots were zeroed. This bit
`expectbindname` in lib/ww/parse: `let empty: str; *into = empty;` was
copying stack bytes (often a recently-vacated str descriptor) into the
caller's `id`, so wwstage emitted `_` discard nodes carrying random
text instead of "". Both stages now zero the full slot on no-rhs lets;
`[N]T` arrays keep the per-index-write contract.

Also tightens the two known buggy sites: parse.ww `expectbindname`
writes `*into = ""` directly, expr.ww `_` primary returns the bare
newnode (amalloc already zeroes).
This commit is contained in:
2026-05-13 12:46:02 +09:00
parent b6cf68f2b8
commit 956a20701b
7 changed files with 155 additions and 43 deletions

View File

@@ -64,5 +64,13 @@ Fixed (no workaround needed):
selfhost/cmd/wcc/cgenutil.ww slotsize N_TARRAY follows
`aliaslookup` on a TNAME element, and `aliaslookup` strips a
`pkg.` prefix so cross-module references resolve.
- Bare `let x: T;` (no rhs) of a multi-word composite — str (16B),
slice (24B), tuple, struct, tagged — now zero-inits the slot.
Previously only 8B-primitive slots were zeroed; larger slots
read whatever the stack held, so `let empty: str; *into = empty;`
copied stack garbage into the caller's slot. `[N]T` arrays still
follow the per-index-write contract and stay uninit. See
cmd/w6c/cgen.c N_LET (else branch, sz > 8 && !TY_ARRAY) and
selfhost/cmd/wcc/cgenstmt.ww cglet no-rhs branch.
If a port "should work" but the binary is wrong, suspect these first.