diff --git a/selfhost/cmd/w6c/main.combined.ww b/selfhost/cmd/w6c/main.combined.ww index e9f998cd..e9f28870 100644 --- a/selfhost/cmd/w6c/main.combined.ww +++ b/selfhost/cmd/w6c/main.combined.ww @@ -13424,14 +13424,29 @@ fn exprtype(c: *checker, e: *node, hint: *node) *node = { let isalign: bool = streq(bname, "align"); let isoffset: bool = streq(bname, "offset"); if (issize || isalign || isoffset) { - let shadowed: bool = false; - if (c.curmod.len > 0) { - if (scopelookupinmodule(c.cur, c.curmod, bname) != nil) { - shadowed = true; + // #38/F2 (review item 7): UNCONDITIONAL intercept — cstage + // gates size/align/offset on NOTHING (cmd/wcc/check.c:1538- + // 1578), unlike user-shadowable alloc/abort/assert + // (check.c:1625/1740/1755). The removed same-module shadow + // gate had no cstage twin (its "Mirrors check.c:907-960" + // cite was stale — that range is N_TFN/N_TSTRUCT layout) and + // was already dead for primary-file decls (declmod "" → + // curmod.len==0 skipped it). + if (e.list != nil) { + // size/align resolve the arg as a TYPE; an unresolvable + // name (`size(localvar)`) is LOUD here, mirroring cstage + // resolve_type "unknown type '%s'" (check.c:93) — astsize + // otherwise folded the unresolved N_TNAME to 0 silently + // (rc=0 wrong binary). offset's arg is a value N_DOT and + // keeps its own "no field" diagnostic below. + if ((issize || isalign) && e.list.kind == nkind.N_TNAME + && tinfofornode(c, e.list) == nil) { + cerr(e.list.file); + cerr(": error: unknown type '"); + cerr(e.list.str); + cerr("'\n"); + c.errs += 1; }; - }; - if (!shadowed) { - if (e.list != nil) { // Post-fold the node IS an N_INTLIT-shaped // untyped_int constant. Mirrors cstage // cmd/wcc/check.c:926/958 which stamps @@ -13478,7 +13493,6 @@ fn exprtype(c: *checker, e: *node, hint: *node) *node = { return mktname(c, "i32"); }; }; - }; }; }; }; diff --git a/selfhost/cmd/wcc/check.ww b/selfhost/cmd/wcc/check.ww index 837017b1..ea923d74 100644 --- a/selfhost/cmd/wcc/check.ww +++ b/selfhost/cmd/wcc/check.ww @@ -3004,14 +3004,29 @@ fn exprtype(c: *checker, e: *node, hint: *node) *node = { let isalign: bool = streq(bname, "align"); let isoffset: bool = streq(bname, "offset"); if (issize || isalign || isoffset) { - let shadowed: bool = false; - if (c.curmod.len > 0) { - if (scopelookupinmodule(c.cur, c.curmod, bname) != nil) { - shadowed = true; + // #38/F2 (review item 7): UNCONDITIONAL intercept — cstage + // gates size/align/offset on NOTHING (cmd/wcc/check.c:1538- + // 1578), unlike user-shadowable alloc/abort/assert + // (check.c:1625/1740/1755). The removed same-module shadow + // gate had no cstage twin (its "Mirrors check.c:907-960" + // cite was stale — that range is N_TFN/N_TSTRUCT layout) and + // was already dead for primary-file decls (declmod "" → + // curmod.len==0 skipped it). + if (e.list != nil) { + // size/align resolve the arg as a TYPE; an unresolvable + // name (`size(localvar)`) is LOUD here, mirroring cstage + // resolve_type "unknown type '%s'" (check.c:93) — astsize + // otherwise folded the unresolved N_TNAME to 0 silently + // (rc=0 wrong binary). offset's arg is a value N_DOT and + // keeps its own "no field" diagnostic below. + if ((issize || isalign) && e.list.kind == nkind.N_TNAME + && tinfofornode(c, e.list) == nil) { + cerr(e.list.file); + cerr(": error: unknown type '"); + cerr(e.list.str); + cerr("'\n"); + c.errs += 1; }; - }; - if (!shadowed) { - if (e.list != nil) { // Post-fold the node IS an N_INTLIT-shaped // untyped_int constant. Mirrors cstage // cmd/wcc/check.c:926/958 which stamps @@ -3058,7 +3073,6 @@ fn exprtype(c: *checker, e: *node, hint: *node) *node = { return mktname(c, "i32"); }; }; - }; }; }; }; diff --git a/selfhost/cmd/wwdump/main.combined.ww b/selfhost/cmd/wwdump/main.combined.ww index 906ea588..4296dc1f 100644 --- a/selfhost/cmd/wwdump/main.combined.ww +++ b/selfhost/cmd/wwdump/main.combined.ww @@ -13424,14 +13424,29 @@ fn exprtype(c: *checker, e: *node, hint: *node) *node = { let isalign: bool = streq(bname, "align"); let isoffset: bool = streq(bname, "offset"); if (issize || isalign || isoffset) { - let shadowed: bool = false; - if (c.curmod.len > 0) { - if (scopelookupinmodule(c.cur, c.curmod, bname) != nil) { - shadowed = true; + // #38/F2 (review item 7): UNCONDITIONAL intercept — cstage + // gates size/align/offset on NOTHING (cmd/wcc/check.c:1538- + // 1578), unlike user-shadowable alloc/abort/assert + // (check.c:1625/1740/1755). The removed same-module shadow + // gate had no cstage twin (its "Mirrors check.c:907-960" + // cite was stale — that range is N_TFN/N_TSTRUCT layout) and + // was already dead for primary-file decls (declmod "" → + // curmod.len==0 skipped it). + if (e.list != nil) { + // size/align resolve the arg as a TYPE; an unresolvable + // name (`size(localvar)`) is LOUD here, mirroring cstage + // resolve_type "unknown type '%s'" (check.c:93) — astsize + // otherwise folded the unresolved N_TNAME to 0 silently + // (rc=0 wrong binary). offset's arg is a value N_DOT and + // keeps its own "no field" diagnostic below. + if ((issize || isalign) && e.list.kind == nkind.N_TNAME + && tinfofornode(c, e.list) == nil) { + cerr(e.list.file); + cerr(": error: unknown type '"); + cerr(e.list.str); + cerr("'\n"); + c.errs += 1; }; - }; - if (!shadowed) { - if (e.list != nil) { // Post-fold the node IS an N_INTLIT-shaped // untyped_int constant. Mirrors cstage // cmd/wcc/check.c:926/958 which stamps @@ -13478,7 +13493,6 @@ fn exprtype(c: *checker, e: *node, hint: *node) *node = { return mktname(c, "i32"); }; }; - }; }; }; };