wcc: drop @test fns from non-T builds, both stages (harec check.c:3941)

Splice @test N_FNDECLs out of the unit after the body-check passes,
mirroring harec's checked-but-not-emitted: a broken @test body still
errors loudly in non-T; @test-free units are emission-unchanged.
910/997 table rows pin keep/test x non-T/-T, head+consecutive unlink,
undef-body reject, and plain-calls-dropped loud link-fail. w6c+wwdump
combined.ww regen. (#6-team)
This commit is contained in:
2026-06-10 22:20:15 +09:00
parent 7470b1a5c3
commit 08a76cf4c8
10 changed files with 442 additions and 4 deletions

View File

@@ -15996,6 +15996,42 @@ export fn checkfile(c: *checker, file: *node) void = {
d = d.next;
};
// #6 harec-fidelity (ref/harec/src/check.c:3941): a @test fn is fully
// checked above (pass 2 + pass 3 walked it like every fn) but is NOT
// emitted in a non-test build. harec skips append_decl for
// FN_TEST && !is_test, so the fn never reaches the codegen decl list;
// the body is still checked, only the emission is dropped. ww shares
// one file.list across check + cgen (no separate checked-decl list),
// so we splice the already-checked @test fns out here, after all
// passes — they stay checked, never reach cgen. The -T path is
// untouched: its synth main calls the @test fns, so they must remain.
// Twin: cmd/wcc/check.c.
if (c.istest == 0) {
let prev: *node = nil;
let e: *node = file.list;
for (e != nil) {
let istest: bool = false;
if (e.kind == nkind.N_FNDECL) {
let at: *node = e.attr;
for (at != nil) {
if (at.kind == nkind.N_ATTR
&& streq(at.str, "test")) {
istest = true;
};
at = at.next;
};
};
let nx: *node = e.next;
if (istest) {
if (prev == nil) { file.list = nx; }
else { prev.next = nx; };
} else {
prev = e;
};
e = nx;
};
};
let empty: str;
c.curmod = empty;