Route the 16 routable bare-primsize GUARD sites (is-primitive / struct-vs-prim dispatch) through the #101 aliasprimsize SSoT helper. Byte-NEUTRAL by construction: an alias-narrow name is already neutralized downstream by the same arm, so routing emits no new asm (the empty-flip-set ken oracled). Shape-A exclude-prim-early (3): cgenutil sretretsize / structparamsize / structfloatclass — `primsize>0 return` then structlookup→nil returns the same value; route returns it early, same. Shape-B prim-guard-then-structlookup (13): cgenutil 4604/4650 + cgenexpr 4136/10244 + the 9-site CALL/assign cluster — primsize==0 →structlookup→nil→fall to normal; route skips the block→same normal. Install the peellint bare-primsize FINALE (B7 lint-fuse contract): tools/peellint now rejects any bare primsize() in the ww stage outside the annotated whitelist. Evasion-hardened per the B7 lesson — a character scan (comments + string/char literals stripped first) and a LEFT+RIGHT word-bounded match of the bare `primsize` TOKEN (not just `primsize(`), so the aliasprimsize() wrapper is never a hit and every compiling spelling reds: the call primsize(nm), the paren-wrap (primsize)(nm), the function-value bind `let p = primsize`, and any line-split. ww-only (the C stage dealiases via type_chase_named, no primsize symbol). Two independent exemption windows (peel-ok vs primsize-ok) so neither rule blinds the other. Runs as a make-test dep. Whitelist the 6 designed exemptions with primsize-ok WHY-annotations: machinery — aliasprimsize body (SSoT chase) | typenodeprimresolved + exprprimresolved (#11/#33 prim-resolver chasers) | cgcast leaf-loop + cgenexpr #11 deref-store (own ps==0 fallback; route would regress #11) | the primsize oracle/definition itself (nothing below to chase). structural — elemsizeof x2 + paramfieldsize (chase lives in the -c twin elemsizeofc; threading c is the dormant #110). Empty-flip-set proof: zero C bytes; cstage binaries bit-identical; bootstrap byte-id 990-997 + 950 all green (w6c == w6c_ww on the full selfhost, self-rebuild identical); combined.ww (w6c + wwdump) regen idempotent; sizelint 0; peellint 0 (raw-peel AND bare-primsize over the whole tree = the close-by-construction proof, zero unwhitelisted survivors). Tests: 944_peellint_gate +14 rows (bare / space-before-paren / name-at-EOL split / string-blind opener / paren-wrap / fn-value-bind RED; aliasprimsize wrapper + primsize-ok annotated GREEN; corrupt annotation RED; independent peel/primsize windows; C-file out-of-scope). Closes the #101 primsize-alias family by construction. #109.
This commit is contained in:
@@ -17990,7 +17990,7 @@ export fn sretretsize(c: *cgen, t: *node) i32 = {
|
|||||||
};
|
};
|
||||||
if (r.kind != nkind.N_TNAME) { return 0; };
|
if (r.kind != nkind.N_TNAME) { return 0; };
|
||||||
// Primitives / aliased-to-primitives are never sret.
|
// Primitives / aliased-to-primitives are never sret.
|
||||||
if (primsize(r.str) > 0) { return 0; };
|
if (aliasprimsize(c, r.str) > 0) { return 0; };
|
||||||
if (streq(r.str, "str")) { return 0; };
|
if (streq(r.str, "str")) { return 0; };
|
||||||
let si: *structinfo = structlookup(c, r.str);
|
let si: *structinfo = structlookup(c, r.str);
|
||||||
if (si == nil) {
|
if (si == nil) {
|
||||||
@@ -18121,6 +18121,9 @@ fn fldnumidx(s: str) i32 = {
|
|||||||
return r;
|
return r;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// primsize-ok (#101/#109): the primitive-width oracle itself — this
|
||||||
|
// IS the SSoT table aliasprimsize wraps; there is nothing below it to
|
||||||
|
// chase.
|
||||||
fn primsize(name: str) i32 = {
|
fn primsize(name: str) i32 = {
|
||||||
if (streq(name, "u8")) { return 1; };
|
if (streq(name, "u8")) { return 1; };
|
||||||
if (streq(name, "i8")) { return 1; };
|
if (streq(name, "i8")) { return 1; };
|
||||||
@@ -18154,6 +18157,8 @@ fn primsize(name: str) i32 = {
|
|||||||
// at the twin sites; this is the ww align-up. The bare-primsize GUARD
|
// at the twin sites; this is the ww align-up. The bare-primsize GUARD
|
||||||
// family (is-primitive dispatch) is the #109 follow-on, NOT routed
|
// family (is-primitive dispatch) is the #109 follow-on, NOT routed
|
||||||
// here. #101.
|
// here. #101.
|
||||||
|
// primsize-ok (#101/#109): the SSoT chase body itself — primsize is
|
||||||
|
// the leaf-primitive probe this helper wraps, then aliaslookup chases.
|
||||||
fn aliasprimsize(c: *cgen, nm: str) i32 = {
|
fn aliasprimsize(c: *cgen, nm: str) i32 = {
|
||||||
let ps: i32 = primsize(nm);
|
let ps: i32 = primsize(nm);
|
||||||
if (ps > 0) { return ps; };
|
if (ps > 0) { return ps; };
|
||||||
@@ -18195,6 +18200,9 @@ export fn typenodeprimresolved(c: *cgen, t: *node,
|
|||||||
// dedicated `is_bool` path in cgcast owns bool→bool's
|
// dedicated `is_bool` path in cgcast owns bool→bool's
|
||||||
// ANDQ $255 on both stages.
|
// ANDQ $255 on both stages.
|
||||||
if (streq(nm, "bool")) { return; };
|
if (streq(nm, "bool")) { return; };
|
||||||
|
// primsize-ok (#101/#109): this fn IS a prim-resolver
|
||||||
|
// chaser (#33) — primsize is the leaf-primitive probe;
|
||||||
|
// aliaslookup below advances the walk on a miss.
|
||||||
let ps: i32 = primsize(nm);
|
let ps: i32 = primsize(nm);
|
||||||
if (ps > 0) {
|
if (ps > 0) {
|
||||||
*sz_out = ps;
|
*sz_out = ps;
|
||||||
@@ -18232,6 +18240,9 @@ export fn exprprimresolved(c: *cgen, n: *node,
|
|||||||
// mymode;` (mymode = enum u32).
|
// mymode;` (mymode = enum u32).
|
||||||
let s: str = n.tsuffix;
|
let s: str = n.tsuffix;
|
||||||
if (s.len > 0) {
|
if (s.len > 0) {
|
||||||
|
// primsize-ok (#101/#109): a typed-int literal suffix
|
||||||
|
// (`7u32`) is a builtin primitive name by grammar — no
|
||||||
|
// alias can reach here, so there is nothing to chase.
|
||||||
let ps: i32 = primsize(s);
|
let ps: i32 = primsize(s);
|
||||||
if (ps > 0) {
|
if (ps > 0) {
|
||||||
*sz_out = ps;
|
*sz_out = ps;
|
||||||
@@ -18707,7 +18718,7 @@ fn structparamsize(c: *cgen, t: *node) i32 = {
|
|||||||
if (r.kind != nkind.N_TNAME) { return 0; };
|
if (r.kind != nkind.N_TNAME) { return 0; };
|
||||||
let nm: str = r.str;
|
let nm: str = r.str;
|
||||||
if (streq(nm, "str")) { return 0; };
|
if (streq(nm, "str")) { return 0; };
|
||||||
if (primsize(nm) > 0) { return 0; };
|
if (aliasprimsize(c, nm) > 0) { return 0; };
|
||||||
let si: *structinfo = structlookup(c, nm);
|
let si: *structinfo = structlookup(c, nm);
|
||||||
if (si == nil) { return 0; };
|
if (si == nil) { return 0; };
|
||||||
if (si.totsize <= 0) { return 0; };
|
if (si.totsize <= 0) { return 0; };
|
||||||
@@ -18796,7 +18807,7 @@ fn structfloatclass(c: *cgen, t: *node) i32 = {
|
|||||||
if (r.kind != nkind.N_TNAME) { return 0; };
|
if (r.kind != nkind.N_TNAME) { return 0; };
|
||||||
let nm: str = r.str;
|
let nm: str = r.str;
|
||||||
if (streq(nm, "str")) { return 0; };
|
if (streq(nm, "str")) { return 0; };
|
||||||
if (primsize(nm) > 0) { return 0; };
|
if (aliasprimsize(c, nm) > 0) { return 0; };
|
||||||
let si: *structinfo = structlookup(c, nm);
|
let si: *structinfo = structlookup(c, nm);
|
||||||
if (si == nil) { return 0; };
|
if (si == nil) { return 0; };
|
||||||
if (si.totsize <= 0) { return 0; };
|
if (si.totsize <= 0) { return 0; };
|
||||||
@@ -20742,7 +20753,7 @@ fn cgstructlitfill(c: *cgen, si: *structinfo, lit: *node,
|
|||||||
if (fieldnode.lhs.kind == nkind.N_STRUCTLIT) {
|
if (fieldnode.lhs.kind == nkind.N_STRUCTLIT) {
|
||||||
if (fi.tnode != nil) {
|
if (fi.tnode != nil) {
|
||||||
if (fi.tnode.kind == nkind.N_TNAME) {
|
if (fi.tnode.kind == nkind.N_TNAME) {
|
||||||
if (primsize(fi.tnode.str) == 0) {
|
if (aliasprimsize(c, fi.tnode.str) == 0) {
|
||||||
let isi: *structinfo = structlookup(c, fi.tnode.str);
|
let isi: *structinfo = structlookup(c, fi.tnode.str);
|
||||||
if (isi != nil) {
|
if (isi != nil) {
|
||||||
cgstructlitfill(c, isi,
|
cgstructlitfill(c, isi,
|
||||||
@@ -20788,7 +20799,7 @@ fn cgstructlitfill(c: *cgen, si: *structinfo, lit: *node,
|
|||||||
if (fieldnode.lhs.kind == nkind.N_CALL) {
|
if (fieldnode.lhs.kind == nkind.N_CALL) {
|
||||||
if (fi.tnode != nil) {
|
if (fi.tnode != nil) {
|
||||||
if (fi.tnode.kind == nkind.N_TNAME) {
|
if (fi.tnode.kind == nkind.N_TNAME) {
|
||||||
if (primsize(fi.tnode.str) == 0) {
|
if (aliasprimsize(c, fi.tnode.str) == 0) {
|
||||||
let csi: *structinfo = structlookup(c, fi.tnode.str);
|
let csi: *structinfo = structlookup(c, fi.tnode.str);
|
||||||
if (csi != nil) {
|
if (csi != nil) {
|
||||||
// Inner struct's ABI size
|
// Inner struct's ABI size
|
||||||
@@ -22043,6 +22054,9 @@ fn cgcast(c: *cgen, n: *node) void = {
|
|||||||
else { if (lk == nkind.N_TENUM) { leaf_tn = leaf_tn.lhs; }
|
else { if (lk == nkind.N_TENUM) { leaf_tn = leaf_tn.lhs; }
|
||||||
else { if (lk == nkind.N_TNAME) {
|
else { if (lk == nkind.N_TNAME) {
|
||||||
let lnm: str = leaf_tn.str;
|
let lnm: str = leaf_tn.str;
|
||||||
|
// primsize-ok (#101/#109): this IS an alias chase loop
|
||||||
|
// — primsize is the leaf-primitive break test the loop
|
||||||
|
// wraps (aliaslookup advances the cursor on a miss).
|
||||||
if (primsize(lnm) > 0) { break; };
|
if (primsize(lnm) > 0) { break; };
|
||||||
let lal: *node = aliaslookup(c, lnm);
|
let lal: *node = aliaslookup(c, lnm);
|
||||||
if (lal == nil) { leaf_tn = nil; }
|
if (lal == nil) { leaf_tn = nil; }
|
||||||
@@ -25309,7 +25323,7 @@ fn cgdot(c: *cgen, n: *node) void = {
|
|||||||
if (streq(ofi.fname, innerfld)) {
|
if (streq(ofi.fname, innerfld)) {
|
||||||
let oft: *node = ofi.tnode;
|
let oft: *node = ofi.tnode;
|
||||||
if (oft != nil) { if (oft.kind == nkind.N_TNAME) {
|
if (oft != nil) { if (oft.kind == nkind.N_TNAME) {
|
||||||
if (primsize(oft.str) == 0) {
|
if (aliasprimsize(c, oft.str) == 0) {
|
||||||
let isi: *structinfo = structlookup(c, oft.str);
|
let isi: *structinfo = structlookup(c, oft.str);
|
||||||
if (isi != nil) {
|
if (isi != nil) {
|
||||||
let ffi: *fieldinfo = isi.fields;
|
let ffi: *fieldinfo = isi.fields;
|
||||||
@@ -28830,6 +28844,9 @@ fn cgassign(c: *cgen, n: *node) void = {
|
|||||||
else { if (streq(pe.str, "f64")) { elemfloat = true; }
|
else { if (streq(pe.str, "f64")) { elemfloat = true; }
|
||||||
else { if (streq(pe.str, "f32")) { elemfloat = true; elemf32 = true; }
|
else { if (streq(pe.str, "f32")) { elemfloat = true; elemf32 = true; }
|
||||||
else {
|
else {
|
||||||
|
// primsize-ok (#101/#109): this site OWNS its own ps==0
|
||||||
|
// typenodeprimresolved chase below — routing through
|
||||||
|
// aliasprimsize would double-resolve and regress #11.
|
||||||
let ps: i32 = primsize(pe.str);
|
let ps: i32 = primsize(pe.str);
|
||||||
// #11: primsize is name-keyed and
|
// #11: primsize is name-keyed and
|
||||||
// misses a `!`/enum/name alias
|
// misses a `!`/enum/name alias
|
||||||
@@ -30047,7 +30064,7 @@ fn cgassign(c: *cgen, n: *node) void = {
|
|||||||
&& n.rhs.kind == nkind.N_CALL
|
&& n.rhs.kind == nkind.N_CALL
|
||||||
&& fi.tnode != nil
|
&& fi.tnode != nil
|
||||||
&& fi.tnode.kind == nkind.N_TNAME
|
&& fi.tnode.kind == nkind.N_TNAME
|
||||||
&& primsize(fi.tnode.str) == 0) {
|
&& aliasprimsize(c, fi.tnode.str) == 0) {
|
||||||
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
||||||
if (ssi != nil) {
|
if (ssi != nil) {
|
||||||
let ssz: i32 = structabisize(ssi);
|
let ssz: i32 = structabisize(ssi);
|
||||||
@@ -30102,7 +30119,7 @@ fn cgassign(c: *cgen, n: *node) void = {
|
|||||||
&& n.rhs.kind == nkind.N_STRUCTLIT
|
&& n.rhs.kind == nkind.N_STRUCTLIT
|
||||||
&& fi.tnode != nil
|
&& fi.tnode != nil
|
||||||
&& fi.tnode.kind == nkind.N_TNAME
|
&& fi.tnode.kind == nkind.N_TNAME
|
||||||
&& primsize(fi.tnode.str) == 0) {
|
&& aliasprimsize(c, fi.tnode.str) == 0) {
|
||||||
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
||||||
if (ssi != nil) {
|
if (ssi != nil) {
|
||||||
cgstructlitfill(c, ssi, n.rhs, 1, lc.off, "",
|
cgstructlitfill(c, ssi, n.rhs, 1, lc.off, "",
|
||||||
@@ -30115,7 +30132,7 @@ fn cgassign(c: *cgen, n: *node) void = {
|
|||||||
&& n.rhs.kind == nkind.N_IDENT
|
&& n.rhs.kind == nkind.N_IDENT
|
||||||
&& fi.tnode != nil
|
&& fi.tnode != nil
|
||||||
&& fi.tnode.kind == nkind.N_TNAME
|
&& fi.tnode.kind == nkind.N_TNAME
|
||||||
&& primsize(fi.tnode.str) == 0) {
|
&& aliasprimsize(c, fi.tnode.str) == 0) {
|
||||||
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
||||||
let srhs: *local = localfindnode(c, n.rhs.str);
|
let srhs: *local = localfindnode(c, n.rhs.str);
|
||||||
if (ssi != nil) { if (srhs != nil) {
|
if (ssi != nil) { if (srhs != nil) {
|
||||||
@@ -30281,7 +30298,7 @@ fn cgassign(c: *cgen, n: *node) void = {
|
|||||||
&& n.rhs.kind == nkind.N_CALL
|
&& n.rhs.kind == nkind.N_CALL
|
||||||
&& fi.tnode != nil
|
&& fi.tnode != nil
|
||||||
&& fi.tnode.kind == nkind.N_TNAME
|
&& fi.tnode.kind == nkind.N_TNAME
|
||||||
&& primsize(fi.tnode.str) == 0) {
|
&& aliasprimsize(c, fi.tnode.str) == 0) {
|
||||||
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
||||||
if (ssi != nil) {
|
if (ssi != nil) {
|
||||||
let ssz: i32 = structabisize(ssi);
|
let ssz: i32 = structabisize(ssi);
|
||||||
@@ -30332,7 +30349,7 @@ fn cgassign(c: *cgen, n: *node) void = {
|
|||||||
&& n.rhs.kind == nkind.N_STRUCTLIT
|
&& n.rhs.kind == nkind.N_STRUCTLIT
|
||||||
&& fi.tnode != nil
|
&& fi.tnode != nil
|
||||||
&& fi.tnode.kind == nkind.N_TNAME
|
&& fi.tnode.kind == nkind.N_TNAME
|
||||||
&& primsize(fi.tnode.str) == 0) {
|
&& aliasprimsize(c, fi.tnode.str) == 0) {
|
||||||
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
||||||
if (ssi != nil) {
|
if (ssi != nil) {
|
||||||
cgstructlitfill(c, ssi, n.rhs, 0, 0, "",
|
cgstructlitfill(c, ssi, n.rhs, 0, 0, "",
|
||||||
@@ -30345,7 +30362,7 @@ fn cgassign(c: *cgen, n: *node) void = {
|
|||||||
&& n.rhs.kind == nkind.N_IDENT
|
&& n.rhs.kind == nkind.N_IDENT
|
||||||
&& fi.tnode != nil
|
&& fi.tnode != nil
|
||||||
&& fi.tnode.kind == nkind.N_TNAME
|
&& fi.tnode.kind == nkind.N_TNAME
|
||||||
&& primsize(fi.tnode.str) == 0) {
|
&& aliasprimsize(c, fi.tnode.str) == 0) {
|
||||||
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
||||||
let srhs: *local = localfindnode(c, n.rhs.str);
|
let srhs: *local = localfindnode(c, n.rhs.str);
|
||||||
if (ssi != nil) { if (srhs != nil) {
|
if (ssi != nil) { if (srhs != nil) {
|
||||||
@@ -30570,7 +30587,7 @@ fn cgassign(c: *cgen, n: *node) void = {
|
|||||||
&& n.rhs.kind == nkind.N_CALL
|
&& n.rhs.kind == nkind.N_CALL
|
||||||
&& fi.tnode != nil
|
&& fi.tnode != nil
|
||||||
&& fi.tnode.kind == nkind.N_TNAME
|
&& fi.tnode.kind == nkind.N_TNAME
|
||||||
&& primsize(fi.tnode.str) == 0) {
|
&& aliasprimsize(c, fi.tnode.str) == 0) {
|
||||||
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
||||||
if (ssi != nil) {
|
if (ssi != nil) {
|
||||||
let ssz: i32 = structabisize(ssi);
|
let ssz: i32 = structabisize(ssi);
|
||||||
@@ -30625,7 +30642,7 @@ fn cgassign(c: *cgen, n: *node) void = {
|
|||||||
&& n.rhs.kind == nkind.N_STRUCTLIT
|
&& n.rhs.kind == nkind.N_STRUCTLIT
|
||||||
&& fi.tnode != nil
|
&& fi.tnode != nil
|
||||||
&& fi.tnode.kind == nkind.N_TNAME
|
&& fi.tnode.kind == nkind.N_TNAME
|
||||||
&& primsize(fi.tnode.str) == 0) {
|
&& aliasprimsize(c, fi.tnode.str) == 0) {
|
||||||
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
||||||
if (ssi != nil) {
|
if (ssi != nil) {
|
||||||
cgstructlitfill(c, ssi, n.rhs, 2, 0, bn,
|
cgstructlitfill(c, ssi, n.rhs, 2, 0, bn,
|
||||||
@@ -30638,7 +30655,7 @@ fn cgassign(c: *cgen, n: *node) void = {
|
|||||||
&& n.rhs.kind == nkind.N_IDENT
|
&& n.rhs.kind == nkind.N_IDENT
|
||||||
&& fi.tnode != nil
|
&& fi.tnode != nil
|
||||||
&& fi.tnode.kind == nkind.N_TNAME
|
&& fi.tnode.kind == nkind.N_TNAME
|
||||||
&& primsize(fi.tnode.str) == 0) {
|
&& aliasprimsize(c, fi.tnode.str) == 0) {
|
||||||
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
||||||
let srhs: *local = localfindnode(c, n.rhs.str);
|
let srhs: *local = localfindnode(c, n.rhs.str);
|
||||||
if (ssi != nil) { if (srhs != nil) {
|
if (ssi != nil) { if (srhs != nil) {
|
||||||
@@ -31417,7 +31434,7 @@ fn cgassign(c: *cgen, n: *node) void = {
|
|||||||
if (streq(ofi.fname, innerfld)) {
|
if (streq(ofi.fname, innerfld)) {
|
||||||
let oft: *node = ofi.tnode;
|
let oft: *node = ofi.tnode;
|
||||||
if (oft != nil) { if (oft.kind == nkind.N_TNAME) {
|
if (oft != nil) { if (oft.kind == nkind.N_TNAME) {
|
||||||
if (primsize(oft.str) == 0) {
|
if (aliasprimsize(c, oft.str) == 0) {
|
||||||
let isi: *structinfo = structlookup(c, oft.str);
|
let isi: *structinfo = structlookup(c, oft.str);
|
||||||
if (isi != nil) {
|
if (isi != nil) {
|
||||||
let ffi: *fieldinfo = isi.fields;
|
let ffi: *fieldinfo = isi.fields;
|
||||||
|
|||||||
@@ -867,6 +867,9 @@ fn cgcast(c: *cgen, n: *node) void = {
|
|||||||
else { if (lk == nkind.N_TENUM) { leaf_tn = leaf_tn.lhs; }
|
else { if (lk == nkind.N_TENUM) { leaf_tn = leaf_tn.lhs; }
|
||||||
else { if (lk == nkind.N_TNAME) {
|
else { if (lk == nkind.N_TNAME) {
|
||||||
let lnm: str = leaf_tn.str;
|
let lnm: str = leaf_tn.str;
|
||||||
|
// primsize-ok (#101/#109): this IS an alias chase loop
|
||||||
|
// — primsize is the leaf-primitive break test the loop
|
||||||
|
// wraps (aliaslookup advances the cursor on a miss).
|
||||||
if (primsize(lnm) > 0) { break; };
|
if (primsize(lnm) > 0) { break; };
|
||||||
let lal: *node = aliaslookup(c, lnm);
|
let lal: *node = aliaslookup(c, lnm);
|
||||||
if (lal == nil) { leaf_tn = nil; }
|
if (lal == nil) { leaf_tn = nil; }
|
||||||
@@ -4133,7 +4136,7 @@ fn cgdot(c: *cgen, n: *node) void = {
|
|||||||
if (streq(ofi.fname, innerfld)) {
|
if (streq(ofi.fname, innerfld)) {
|
||||||
let oft: *node = ofi.tnode;
|
let oft: *node = ofi.tnode;
|
||||||
if (oft != nil) { if (oft.kind == nkind.N_TNAME) {
|
if (oft != nil) { if (oft.kind == nkind.N_TNAME) {
|
||||||
if (primsize(oft.str) == 0) {
|
if (aliasprimsize(c, oft.str) == 0) {
|
||||||
let isi: *structinfo = structlookup(c, oft.str);
|
let isi: *structinfo = structlookup(c, oft.str);
|
||||||
if (isi != nil) {
|
if (isi != nil) {
|
||||||
let ffi: *fieldinfo = isi.fields;
|
let ffi: *fieldinfo = isi.fields;
|
||||||
@@ -7654,6 +7657,9 @@ fn cgassign(c: *cgen, n: *node) void = {
|
|||||||
else { if (streq(pe.str, "f64")) { elemfloat = true; }
|
else { if (streq(pe.str, "f64")) { elemfloat = true; }
|
||||||
else { if (streq(pe.str, "f32")) { elemfloat = true; elemf32 = true; }
|
else { if (streq(pe.str, "f32")) { elemfloat = true; elemf32 = true; }
|
||||||
else {
|
else {
|
||||||
|
// primsize-ok (#101/#109): this site OWNS its own ps==0
|
||||||
|
// typenodeprimresolved chase below — routing through
|
||||||
|
// aliasprimsize would double-resolve and regress #11.
|
||||||
let ps: i32 = primsize(pe.str);
|
let ps: i32 = primsize(pe.str);
|
||||||
// #11: primsize is name-keyed and
|
// #11: primsize is name-keyed and
|
||||||
// misses a `!`/enum/name alias
|
// misses a `!`/enum/name alias
|
||||||
@@ -8871,7 +8877,7 @@ fn cgassign(c: *cgen, n: *node) void = {
|
|||||||
&& n.rhs.kind == nkind.N_CALL
|
&& n.rhs.kind == nkind.N_CALL
|
||||||
&& fi.tnode != nil
|
&& fi.tnode != nil
|
||||||
&& fi.tnode.kind == nkind.N_TNAME
|
&& fi.tnode.kind == nkind.N_TNAME
|
||||||
&& primsize(fi.tnode.str) == 0) {
|
&& aliasprimsize(c, fi.tnode.str) == 0) {
|
||||||
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
||||||
if (ssi != nil) {
|
if (ssi != nil) {
|
||||||
let ssz: i32 = structabisize(ssi);
|
let ssz: i32 = structabisize(ssi);
|
||||||
@@ -8926,7 +8932,7 @@ fn cgassign(c: *cgen, n: *node) void = {
|
|||||||
&& n.rhs.kind == nkind.N_STRUCTLIT
|
&& n.rhs.kind == nkind.N_STRUCTLIT
|
||||||
&& fi.tnode != nil
|
&& fi.tnode != nil
|
||||||
&& fi.tnode.kind == nkind.N_TNAME
|
&& fi.tnode.kind == nkind.N_TNAME
|
||||||
&& primsize(fi.tnode.str) == 0) {
|
&& aliasprimsize(c, fi.tnode.str) == 0) {
|
||||||
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
||||||
if (ssi != nil) {
|
if (ssi != nil) {
|
||||||
cgstructlitfill(c, ssi, n.rhs, 1, lc.off, "",
|
cgstructlitfill(c, ssi, n.rhs, 1, lc.off, "",
|
||||||
@@ -8939,7 +8945,7 @@ fn cgassign(c: *cgen, n: *node) void = {
|
|||||||
&& n.rhs.kind == nkind.N_IDENT
|
&& n.rhs.kind == nkind.N_IDENT
|
||||||
&& fi.tnode != nil
|
&& fi.tnode != nil
|
||||||
&& fi.tnode.kind == nkind.N_TNAME
|
&& fi.tnode.kind == nkind.N_TNAME
|
||||||
&& primsize(fi.tnode.str) == 0) {
|
&& aliasprimsize(c, fi.tnode.str) == 0) {
|
||||||
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
||||||
let srhs: *local = localfindnode(c, n.rhs.str);
|
let srhs: *local = localfindnode(c, n.rhs.str);
|
||||||
if (ssi != nil) { if (srhs != nil) {
|
if (ssi != nil) { if (srhs != nil) {
|
||||||
@@ -9105,7 +9111,7 @@ fn cgassign(c: *cgen, n: *node) void = {
|
|||||||
&& n.rhs.kind == nkind.N_CALL
|
&& n.rhs.kind == nkind.N_CALL
|
||||||
&& fi.tnode != nil
|
&& fi.tnode != nil
|
||||||
&& fi.tnode.kind == nkind.N_TNAME
|
&& fi.tnode.kind == nkind.N_TNAME
|
||||||
&& primsize(fi.tnode.str) == 0) {
|
&& aliasprimsize(c, fi.tnode.str) == 0) {
|
||||||
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
||||||
if (ssi != nil) {
|
if (ssi != nil) {
|
||||||
let ssz: i32 = structabisize(ssi);
|
let ssz: i32 = structabisize(ssi);
|
||||||
@@ -9156,7 +9162,7 @@ fn cgassign(c: *cgen, n: *node) void = {
|
|||||||
&& n.rhs.kind == nkind.N_STRUCTLIT
|
&& n.rhs.kind == nkind.N_STRUCTLIT
|
||||||
&& fi.tnode != nil
|
&& fi.tnode != nil
|
||||||
&& fi.tnode.kind == nkind.N_TNAME
|
&& fi.tnode.kind == nkind.N_TNAME
|
||||||
&& primsize(fi.tnode.str) == 0) {
|
&& aliasprimsize(c, fi.tnode.str) == 0) {
|
||||||
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
||||||
if (ssi != nil) {
|
if (ssi != nil) {
|
||||||
cgstructlitfill(c, ssi, n.rhs, 0, 0, "",
|
cgstructlitfill(c, ssi, n.rhs, 0, 0, "",
|
||||||
@@ -9169,7 +9175,7 @@ fn cgassign(c: *cgen, n: *node) void = {
|
|||||||
&& n.rhs.kind == nkind.N_IDENT
|
&& n.rhs.kind == nkind.N_IDENT
|
||||||
&& fi.tnode != nil
|
&& fi.tnode != nil
|
||||||
&& fi.tnode.kind == nkind.N_TNAME
|
&& fi.tnode.kind == nkind.N_TNAME
|
||||||
&& primsize(fi.tnode.str) == 0) {
|
&& aliasprimsize(c, fi.tnode.str) == 0) {
|
||||||
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
||||||
let srhs: *local = localfindnode(c, n.rhs.str);
|
let srhs: *local = localfindnode(c, n.rhs.str);
|
||||||
if (ssi != nil) { if (srhs != nil) {
|
if (ssi != nil) { if (srhs != nil) {
|
||||||
@@ -9394,7 +9400,7 @@ fn cgassign(c: *cgen, n: *node) void = {
|
|||||||
&& n.rhs.kind == nkind.N_CALL
|
&& n.rhs.kind == nkind.N_CALL
|
||||||
&& fi.tnode != nil
|
&& fi.tnode != nil
|
||||||
&& fi.tnode.kind == nkind.N_TNAME
|
&& fi.tnode.kind == nkind.N_TNAME
|
||||||
&& primsize(fi.tnode.str) == 0) {
|
&& aliasprimsize(c, fi.tnode.str) == 0) {
|
||||||
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
||||||
if (ssi != nil) {
|
if (ssi != nil) {
|
||||||
let ssz: i32 = structabisize(ssi);
|
let ssz: i32 = structabisize(ssi);
|
||||||
@@ -9449,7 +9455,7 @@ fn cgassign(c: *cgen, n: *node) void = {
|
|||||||
&& n.rhs.kind == nkind.N_STRUCTLIT
|
&& n.rhs.kind == nkind.N_STRUCTLIT
|
||||||
&& fi.tnode != nil
|
&& fi.tnode != nil
|
||||||
&& fi.tnode.kind == nkind.N_TNAME
|
&& fi.tnode.kind == nkind.N_TNAME
|
||||||
&& primsize(fi.tnode.str) == 0) {
|
&& aliasprimsize(c, fi.tnode.str) == 0) {
|
||||||
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
||||||
if (ssi != nil) {
|
if (ssi != nil) {
|
||||||
cgstructlitfill(c, ssi, n.rhs, 2, 0, bn,
|
cgstructlitfill(c, ssi, n.rhs, 2, 0, bn,
|
||||||
@@ -9462,7 +9468,7 @@ fn cgassign(c: *cgen, n: *node) void = {
|
|||||||
&& n.rhs.kind == nkind.N_IDENT
|
&& n.rhs.kind == nkind.N_IDENT
|
||||||
&& fi.tnode != nil
|
&& fi.tnode != nil
|
||||||
&& fi.tnode.kind == nkind.N_TNAME
|
&& fi.tnode.kind == nkind.N_TNAME
|
||||||
&& primsize(fi.tnode.str) == 0) {
|
&& aliasprimsize(c, fi.tnode.str) == 0) {
|
||||||
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
||||||
let srhs: *local = localfindnode(c, n.rhs.str);
|
let srhs: *local = localfindnode(c, n.rhs.str);
|
||||||
if (ssi != nil) { if (srhs != nil) {
|
if (ssi != nil) { if (srhs != nil) {
|
||||||
@@ -10241,7 +10247,7 @@ fn cgassign(c: *cgen, n: *node) void = {
|
|||||||
if (streq(ofi.fname, innerfld)) {
|
if (streq(ofi.fname, innerfld)) {
|
||||||
let oft: *node = ofi.tnode;
|
let oft: *node = ofi.tnode;
|
||||||
if (oft != nil) { if (oft.kind == nkind.N_TNAME) {
|
if (oft != nil) { if (oft.kind == nkind.N_TNAME) {
|
||||||
if (primsize(oft.str) == 0) {
|
if (aliasprimsize(c, oft.str) == 0) {
|
||||||
let isi: *structinfo = structlookup(c, oft.str);
|
let isi: *structinfo = structlookup(c, oft.str);
|
||||||
if (isi != nil) {
|
if (isi != nil) {
|
||||||
let ffi: *fieldinfo = isi.fields;
|
let ffi: *fieldinfo = isi.fields;
|
||||||
|
|||||||
@@ -1849,7 +1849,7 @@ export fn sretretsize(c: *cgen, t: *node) i32 = {
|
|||||||
};
|
};
|
||||||
if (r.kind != nkind.N_TNAME) { return 0; };
|
if (r.kind != nkind.N_TNAME) { return 0; };
|
||||||
// Primitives / aliased-to-primitives are never sret.
|
// Primitives / aliased-to-primitives are never sret.
|
||||||
if (primsize(r.str) > 0) { return 0; };
|
if (aliasprimsize(c, r.str) > 0) { return 0; };
|
||||||
if (streq(r.str, "str")) { return 0; };
|
if (streq(r.str, "str")) { return 0; };
|
||||||
let si: *structinfo = structlookup(c, r.str);
|
let si: *structinfo = structlookup(c, r.str);
|
||||||
if (si == nil) {
|
if (si == nil) {
|
||||||
@@ -1980,6 +1980,9 @@ fn fldnumidx(s: str) i32 = {
|
|||||||
return r;
|
return r;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// primsize-ok (#101/#109): the primitive-width oracle itself — this
|
||||||
|
// IS the SSoT table aliasprimsize wraps; there is nothing below it to
|
||||||
|
// chase.
|
||||||
fn primsize(name: str) i32 = {
|
fn primsize(name: str) i32 = {
|
||||||
if (streq(name, "u8")) { return 1; };
|
if (streq(name, "u8")) { return 1; };
|
||||||
if (streq(name, "i8")) { return 1; };
|
if (streq(name, "i8")) { return 1; };
|
||||||
@@ -2013,6 +2016,8 @@ fn primsize(name: str) i32 = {
|
|||||||
// at the twin sites; this is the ww align-up. The bare-primsize GUARD
|
// at the twin sites; this is the ww align-up. The bare-primsize GUARD
|
||||||
// family (is-primitive dispatch) is the #109 follow-on, NOT routed
|
// family (is-primitive dispatch) is the #109 follow-on, NOT routed
|
||||||
// here. #101.
|
// here. #101.
|
||||||
|
// primsize-ok (#101/#109): the SSoT chase body itself — primsize is
|
||||||
|
// the leaf-primitive probe this helper wraps, then aliaslookup chases.
|
||||||
fn aliasprimsize(c: *cgen, nm: str) i32 = {
|
fn aliasprimsize(c: *cgen, nm: str) i32 = {
|
||||||
let ps: i32 = primsize(nm);
|
let ps: i32 = primsize(nm);
|
||||||
if (ps > 0) { return ps; };
|
if (ps > 0) { return ps; };
|
||||||
@@ -2054,6 +2059,9 @@ export fn typenodeprimresolved(c: *cgen, t: *node,
|
|||||||
// dedicated `is_bool` path in cgcast owns bool→bool's
|
// dedicated `is_bool` path in cgcast owns bool→bool's
|
||||||
// ANDQ $255 on both stages.
|
// ANDQ $255 on both stages.
|
||||||
if (streq(nm, "bool")) { return; };
|
if (streq(nm, "bool")) { return; };
|
||||||
|
// primsize-ok (#101/#109): this fn IS a prim-resolver
|
||||||
|
// chaser (#33) — primsize is the leaf-primitive probe;
|
||||||
|
// aliaslookup below advances the walk on a miss.
|
||||||
let ps: i32 = primsize(nm);
|
let ps: i32 = primsize(nm);
|
||||||
if (ps > 0) {
|
if (ps > 0) {
|
||||||
*sz_out = ps;
|
*sz_out = ps;
|
||||||
@@ -2091,6 +2099,9 @@ export fn exprprimresolved(c: *cgen, n: *node,
|
|||||||
// mymode;` (mymode = enum u32).
|
// mymode;` (mymode = enum u32).
|
||||||
let s: str = n.tsuffix;
|
let s: str = n.tsuffix;
|
||||||
if (s.len > 0) {
|
if (s.len > 0) {
|
||||||
|
// primsize-ok (#101/#109): a typed-int literal suffix
|
||||||
|
// (`7u32`) is a builtin primitive name by grammar — no
|
||||||
|
// alias can reach here, so there is nothing to chase.
|
||||||
let ps: i32 = primsize(s);
|
let ps: i32 = primsize(s);
|
||||||
if (ps > 0) {
|
if (ps > 0) {
|
||||||
*sz_out = ps;
|
*sz_out = ps;
|
||||||
@@ -2566,7 +2577,7 @@ fn structparamsize(c: *cgen, t: *node) i32 = {
|
|||||||
if (r.kind != nkind.N_TNAME) { return 0; };
|
if (r.kind != nkind.N_TNAME) { return 0; };
|
||||||
let nm: str = r.str;
|
let nm: str = r.str;
|
||||||
if (streq(nm, "str")) { return 0; };
|
if (streq(nm, "str")) { return 0; };
|
||||||
if (primsize(nm) > 0) { return 0; };
|
if (aliasprimsize(c, nm) > 0) { return 0; };
|
||||||
let si: *structinfo = structlookup(c, nm);
|
let si: *structinfo = structlookup(c, nm);
|
||||||
if (si == nil) { return 0; };
|
if (si == nil) { return 0; };
|
||||||
if (si.totsize <= 0) { return 0; };
|
if (si.totsize <= 0) { return 0; };
|
||||||
@@ -2655,7 +2666,7 @@ fn structfloatclass(c: *cgen, t: *node) i32 = {
|
|||||||
if (r.kind != nkind.N_TNAME) { return 0; };
|
if (r.kind != nkind.N_TNAME) { return 0; };
|
||||||
let nm: str = r.str;
|
let nm: str = r.str;
|
||||||
if (streq(nm, "str")) { return 0; };
|
if (streq(nm, "str")) { return 0; };
|
||||||
if (primsize(nm) > 0) { return 0; };
|
if (aliasprimsize(c, nm) > 0) { return 0; };
|
||||||
let si: *structinfo = structlookup(c, nm);
|
let si: *structinfo = structlookup(c, nm);
|
||||||
if (si == nil) { return 0; };
|
if (si == nil) { return 0; };
|
||||||
if (si.totsize <= 0) { return 0; };
|
if (si.totsize <= 0) { return 0; };
|
||||||
@@ -4601,7 +4612,7 @@ fn cgstructlitfill(c: *cgen, si: *structinfo, lit: *node,
|
|||||||
if (fieldnode.lhs.kind == nkind.N_STRUCTLIT) {
|
if (fieldnode.lhs.kind == nkind.N_STRUCTLIT) {
|
||||||
if (fi.tnode != nil) {
|
if (fi.tnode != nil) {
|
||||||
if (fi.tnode.kind == nkind.N_TNAME) {
|
if (fi.tnode.kind == nkind.N_TNAME) {
|
||||||
if (primsize(fi.tnode.str) == 0) {
|
if (aliasprimsize(c, fi.tnode.str) == 0) {
|
||||||
let isi: *structinfo = structlookup(c, fi.tnode.str);
|
let isi: *structinfo = structlookup(c, fi.tnode.str);
|
||||||
if (isi != nil) {
|
if (isi != nil) {
|
||||||
cgstructlitfill(c, isi,
|
cgstructlitfill(c, isi,
|
||||||
@@ -4647,7 +4658,7 @@ fn cgstructlitfill(c: *cgen, si: *structinfo, lit: *node,
|
|||||||
if (fieldnode.lhs.kind == nkind.N_CALL) {
|
if (fieldnode.lhs.kind == nkind.N_CALL) {
|
||||||
if (fi.tnode != nil) {
|
if (fi.tnode != nil) {
|
||||||
if (fi.tnode.kind == nkind.N_TNAME) {
|
if (fi.tnode.kind == nkind.N_TNAME) {
|
||||||
if (primsize(fi.tnode.str) == 0) {
|
if (aliasprimsize(c, fi.tnode.str) == 0) {
|
||||||
let csi: *structinfo = structlookup(c, fi.tnode.str);
|
let csi: *structinfo = structlookup(c, fi.tnode.str);
|
||||||
if (csi != nil) {
|
if (csi != nil) {
|
||||||
// Inner struct's ABI size
|
// Inner struct's ABI size
|
||||||
|
|||||||
@@ -17990,7 +17990,7 @@ export fn sretretsize(c: *cgen, t: *node) i32 = {
|
|||||||
};
|
};
|
||||||
if (r.kind != nkind.N_TNAME) { return 0; };
|
if (r.kind != nkind.N_TNAME) { return 0; };
|
||||||
// Primitives / aliased-to-primitives are never sret.
|
// Primitives / aliased-to-primitives are never sret.
|
||||||
if (primsize(r.str) > 0) { return 0; };
|
if (aliasprimsize(c, r.str) > 0) { return 0; };
|
||||||
if (streq(r.str, "str")) { return 0; };
|
if (streq(r.str, "str")) { return 0; };
|
||||||
let si: *structinfo = structlookup(c, r.str);
|
let si: *structinfo = structlookup(c, r.str);
|
||||||
if (si == nil) {
|
if (si == nil) {
|
||||||
@@ -18121,6 +18121,9 @@ fn fldnumidx(s: str) i32 = {
|
|||||||
return r;
|
return r;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// primsize-ok (#101/#109): the primitive-width oracle itself — this
|
||||||
|
// IS the SSoT table aliasprimsize wraps; there is nothing below it to
|
||||||
|
// chase.
|
||||||
fn primsize(name: str) i32 = {
|
fn primsize(name: str) i32 = {
|
||||||
if (streq(name, "u8")) { return 1; };
|
if (streq(name, "u8")) { return 1; };
|
||||||
if (streq(name, "i8")) { return 1; };
|
if (streq(name, "i8")) { return 1; };
|
||||||
@@ -18154,6 +18157,8 @@ fn primsize(name: str) i32 = {
|
|||||||
// at the twin sites; this is the ww align-up. The bare-primsize GUARD
|
// at the twin sites; this is the ww align-up. The bare-primsize GUARD
|
||||||
// family (is-primitive dispatch) is the #109 follow-on, NOT routed
|
// family (is-primitive dispatch) is the #109 follow-on, NOT routed
|
||||||
// here. #101.
|
// here. #101.
|
||||||
|
// primsize-ok (#101/#109): the SSoT chase body itself — primsize is
|
||||||
|
// the leaf-primitive probe this helper wraps, then aliaslookup chases.
|
||||||
fn aliasprimsize(c: *cgen, nm: str) i32 = {
|
fn aliasprimsize(c: *cgen, nm: str) i32 = {
|
||||||
let ps: i32 = primsize(nm);
|
let ps: i32 = primsize(nm);
|
||||||
if (ps > 0) { return ps; };
|
if (ps > 0) { return ps; };
|
||||||
@@ -18195,6 +18200,9 @@ export fn typenodeprimresolved(c: *cgen, t: *node,
|
|||||||
// dedicated `is_bool` path in cgcast owns bool→bool's
|
// dedicated `is_bool` path in cgcast owns bool→bool's
|
||||||
// ANDQ $255 on both stages.
|
// ANDQ $255 on both stages.
|
||||||
if (streq(nm, "bool")) { return; };
|
if (streq(nm, "bool")) { return; };
|
||||||
|
// primsize-ok (#101/#109): this fn IS a prim-resolver
|
||||||
|
// chaser (#33) — primsize is the leaf-primitive probe;
|
||||||
|
// aliaslookup below advances the walk on a miss.
|
||||||
let ps: i32 = primsize(nm);
|
let ps: i32 = primsize(nm);
|
||||||
if (ps > 0) {
|
if (ps > 0) {
|
||||||
*sz_out = ps;
|
*sz_out = ps;
|
||||||
@@ -18232,6 +18240,9 @@ export fn exprprimresolved(c: *cgen, n: *node,
|
|||||||
// mymode;` (mymode = enum u32).
|
// mymode;` (mymode = enum u32).
|
||||||
let s: str = n.tsuffix;
|
let s: str = n.tsuffix;
|
||||||
if (s.len > 0) {
|
if (s.len > 0) {
|
||||||
|
// primsize-ok (#101/#109): a typed-int literal suffix
|
||||||
|
// (`7u32`) is a builtin primitive name by grammar — no
|
||||||
|
// alias can reach here, so there is nothing to chase.
|
||||||
let ps: i32 = primsize(s);
|
let ps: i32 = primsize(s);
|
||||||
if (ps > 0) {
|
if (ps > 0) {
|
||||||
*sz_out = ps;
|
*sz_out = ps;
|
||||||
@@ -18707,7 +18718,7 @@ fn structparamsize(c: *cgen, t: *node) i32 = {
|
|||||||
if (r.kind != nkind.N_TNAME) { return 0; };
|
if (r.kind != nkind.N_TNAME) { return 0; };
|
||||||
let nm: str = r.str;
|
let nm: str = r.str;
|
||||||
if (streq(nm, "str")) { return 0; };
|
if (streq(nm, "str")) { return 0; };
|
||||||
if (primsize(nm) > 0) { return 0; };
|
if (aliasprimsize(c, nm) > 0) { return 0; };
|
||||||
let si: *structinfo = structlookup(c, nm);
|
let si: *structinfo = structlookup(c, nm);
|
||||||
if (si == nil) { return 0; };
|
if (si == nil) { return 0; };
|
||||||
if (si.totsize <= 0) { return 0; };
|
if (si.totsize <= 0) { return 0; };
|
||||||
@@ -18796,7 +18807,7 @@ fn structfloatclass(c: *cgen, t: *node) i32 = {
|
|||||||
if (r.kind != nkind.N_TNAME) { return 0; };
|
if (r.kind != nkind.N_TNAME) { return 0; };
|
||||||
let nm: str = r.str;
|
let nm: str = r.str;
|
||||||
if (streq(nm, "str")) { return 0; };
|
if (streq(nm, "str")) { return 0; };
|
||||||
if (primsize(nm) > 0) { return 0; };
|
if (aliasprimsize(c, nm) > 0) { return 0; };
|
||||||
let si: *structinfo = structlookup(c, nm);
|
let si: *structinfo = structlookup(c, nm);
|
||||||
if (si == nil) { return 0; };
|
if (si == nil) { return 0; };
|
||||||
if (si.totsize <= 0) { return 0; };
|
if (si.totsize <= 0) { return 0; };
|
||||||
@@ -20742,7 +20753,7 @@ fn cgstructlitfill(c: *cgen, si: *structinfo, lit: *node,
|
|||||||
if (fieldnode.lhs.kind == nkind.N_STRUCTLIT) {
|
if (fieldnode.lhs.kind == nkind.N_STRUCTLIT) {
|
||||||
if (fi.tnode != nil) {
|
if (fi.tnode != nil) {
|
||||||
if (fi.tnode.kind == nkind.N_TNAME) {
|
if (fi.tnode.kind == nkind.N_TNAME) {
|
||||||
if (primsize(fi.tnode.str) == 0) {
|
if (aliasprimsize(c, fi.tnode.str) == 0) {
|
||||||
let isi: *structinfo = structlookup(c, fi.tnode.str);
|
let isi: *structinfo = structlookup(c, fi.tnode.str);
|
||||||
if (isi != nil) {
|
if (isi != nil) {
|
||||||
cgstructlitfill(c, isi,
|
cgstructlitfill(c, isi,
|
||||||
@@ -20788,7 +20799,7 @@ fn cgstructlitfill(c: *cgen, si: *structinfo, lit: *node,
|
|||||||
if (fieldnode.lhs.kind == nkind.N_CALL) {
|
if (fieldnode.lhs.kind == nkind.N_CALL) {
|
||||||
if (fi.tnode != nil) {
|
if (fi.tnode != nil) {
|
||||||
if (fi.tnode.kind == nkind.N_TNAME) {
|
if (fi.tnode.kind == nkind.N_TNAME) {
|
||||||
if (primsize(fi.tnode.str) == 0) {
|
if (aliasprimsize(c, fi.tnode.str) == 0) {
|
||||||
let csi: *structinfo = structlookup(c, fi.tnode.str);
|
let csi: *structinfo = structlookup(c, fi.tnode.str);
|
||||||
if (csi != nil) {
|
if (csi != nil) {
|
||||||
// Inner struct's ABI size
|
// Inner struct's ABI size
|
||||||
@@ -22043,6 +22054,9 @@ fn cgcast(c: *cgen, n: *node) void = {
|
|||||||
else { if (lk == nkind.N_TENUM) { leaf_tn = leaf_tn.lhs; }
|
else { if (lk == nkind.N_TENUM) { leaf_tn = leaf_tn.lhs; }
|
||||||
else { if (lk == nkind.N_TNAME) {
|
else { if (lk == nkind.N_TNAME) {
|
||||||
let lnm: str = leaf_tn.str;
|
let lnm: str = leaf_tn.str;
|
||||||
|
// primsize-ok (#101/#109): this IS an alias chase loop
|
||||||
|
// — primsize is the leaf-primitive break test the loop
|
||||||
|
// wraps (aliaslookup advances the cursor on a miss).
|
||||||
if (primsize(lnm) > 0) { break; };
|
if (primsize(lnm) > 0) { break; };
|
||||||
let lal: *node = aliaslookup(c, lnm);
|
let lal: *node = aliaslookup(c, lnm);
|
||||||
if (lal == nil) { leaf_tn = nil; }
|
if (lal == nil) { leaf_tn = nil; }
|
||||||
@@ -25309,7 +25323,7 @@ fn cgdot(c: *cgen, n: *node) void = {
|
|||||||
if (streq(ofi.fname, innerfld)) {
|
if (streq(ofi.fname, innerfld)) {
|
||||||
let oft: *node = ofi.tnode;
|
let oft: *node = ofi.tnode;
|
||||||
if (oft != nil) { if (oft.kind == nkind.N_TNAME) {
|
if (oft != nil) { if (oft.kind == nkind.N_TNAME) {
|
||||||
if (primsize(oft.str) == 0) {
|
if (aliasprimsize(c, oft.str) == 0) {
|
||||||
let isi: *structinfo = structlookup(c, oft.str);
|
let isi: *structinfo = structlookup(c, oft.str);
|
||||||
if (isi != nil) {
|
if (isi != nil) {
|
||||||
let ffi: *fieldinfo = isi.fields;
|
let ffi: *fieldinfo = isi.fields;
|
||||||
@@ -28830,6 +28844,9 @@ fn cgassign(c: *cgen, n: *node) void = {
|
|||||||
else { if (streq(pe.str, "f64")) { elemfloat = true; }
|
else { if (streq(pe.str, "f64")) { elemfloat = true; }
|
||||||
else { if (streq(pe.str, "f32")) { elemfloat = true; elemf32 = true; }
|
else { if (streq(pe.str, "f32")) { elemfloat = true; elemf32 = true; }
|
||||||
else {
|
else {
|
||||||
|
// primsize-ok (#101/#109): this site OWNS its own ps==0
|
||||||
|
// typenodeprimresolved chase below — routing through
|
||||||
|
// aliasprimsize would double-resolve and regress #11.
|
||||||
let ps: i32 = primsize(pe.str);
|
let ps: i32 = primsize(pe.str);
|
||||||
// #11: primsize is name-keyed and
|
// #11: primsize is name-keyed and
|
||||||
// misses a `!`/enum/name alias
|
// misses a `!`/enum/name alias
|
||||||
@@ -30047,7 +30064,7 @@ fn cgassign(c: *cgen, n: *node) void = {
|
|||||||
&& n.rhs.kind == nkind.N_CALL
|
&& n.rhs.kind == nkind.N_CALL
|
||||||
&& fi.tnode != nil
|
&& fi.tnode != nil
|
||||||
&& fi.tnode.kind == nkind.N_TNAME
|
&& fi.tnode.kind == nkind.N_TNAME
|
||||||
&& primsize(fi.tnode.str) == 0) {
|
&& aliasprimsize(c, fi.tnode.str) == 0) {
|
||||||
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
||||||
if (ssi != nil) {
|
if (ssi != nil) {
|
||||||
let ssz: i32 = structabisize(ssi);
|
let ssz: i32 = structabisize(ssi);
|
||||||
@@ -30102,7 +30119,7 @@ fn cgassign(c: *cgen, n: *node) void = {
|
|||||||
&& n.rhs.kind == nkind.N_STRUCTLIT
|
&& n.rhs.kind == nkind.N_STRUCTLIT
|
||||||
&& fi.tnode != nil
|
&& fi.tnode != nil
|
||||||
&& fi.tnode.kind == nkind.N_TNAME
|
&& fi.tnode.kind == nkind.N_TNAME
|
||||||
&& primsize(fi.tnode.str) == 0) {
|
&& aliasprimsize(c, fi.tnode.str) == 0) {
|
||||||
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
||||||
if (ssi != nil) {
|
if (ssi != nil) {
|
||||||
cgstructlitfill(c, ssi, n.rhs, 1, lc.off, "",
|
cgstructlitfill(c, ssi, n.rhs, 1, lc.off, "",
|
||||||
@@ -30115,7 +30132,7 @@ fn cgassign(c: *cgen, n: *node) void = {
|
|||||||
&& n.rhs.kind == nkind.N_IDENT
|
&& n.rhs.kind == nkind.N_IDENT
|
||||||
&& fi.tnode != nil
|
&& fi.tnode != nil
|
||||||
&& fi.tnode.kind == nkind.N_TNAME
|
&& fi.tnode.kind == nkind.N_TNAME
|
||||||
&& primsize(fi.tnode.str) == 0) {
|
&& aliasprimsize(c, fi.tnode.str) == 0) {
|
||||||
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
||||||
let srhs: *local = localfindnode(c, n.rhs.str);
|
let srhs: *local = localfindnode(c, n.rhs.str);
|
||||||
if (ssi != nil) { if (srhs != nil) {
|
if (ssi != nil) { if (srhs != nil) {
|
||||||
@@ -30281,7 +30298,7 @@ fn cgassign(c: *cgen, n: *node) void = {
|
|||||||
&& n.rhs.kind == nkind.N_CALL
|
&& n.rhs.kind == nkind.N_CALL
|
||||||
&& fi.tnode != nil
|
&& fi.tnode != nil
|
||||||
&& fi.tnode.kind == nkind.N_TNAME
|
&& fi.tnode.kind == nkind.N_TNAME
|
||||||
&& primsize(fi.tnode.str) == 0) {
|
&& aliasprimsize(c, fi.tnode.str) == 0) {
|
||||||
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
||||||
if (ssi != nil) {
|
if (ssi != nil) {
|
||||||
let ssz: i32 = structabisize(ssi);
|
let ssz: i32 = structabisize(ssi);
|
||||||
@@ -30332,7 +30349,7 @@ fn cgassign(c: *cgen, n: *node) void = {
|
|||||||
&& n.rhs.kind == nkind.N_STRUCTLIT
|
&& n.rhs.kind == nkind.N_STRUCTLIT
|
||||||
&& fi.tnode != nil
|
&& fi.tnode != nil
|
||||||
&& fi.tnode.kind == nkind.N_TNAME
|
&& fi.tnode.kind == nkind.N_TNAME
|
||||||
&& primsize(fi.tnode.str) == 0) {
|
&& aliasprimsize(c, fi.tnode.str) == 0) {
|
||||||
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
||||||
if (ssi != nil) {
|
if (ssi != nil) {
|
||||||
cgstructlitfill(c, ssi, n.rhs, 0, 0, "",
|
cgstructlitfill(c, ssi, n.rhs, 0, 0, "",
|
||||||
@@ -30345,7 +30362,7 @@ fn cgassign(c: *cgen, n: *node) void = {
|
|||||||
&& n.rhs.kind == nkind.N_IDENT
|
&& n.rhs.kind == nkind.N_IDENT
|
||||||
&& fi.tnode != nil
|
&& fi.tnode != nil
|
||||||
&& fi.tnode.kind == nkind.N_TNAME
|
&& fi.tnode.kind == nkind.N_TNAME
|
||||||
&& primsize(fi.tnode.str) == 0) {
|
&& aliasprimsize(c, fi.tnode.str) == 0) {
|
||||||
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
||||||
let srhs: *local = localfindnode(c, n.rhs.str);
|
let srhs: *local = localfindnode(c, n.rhs.str);
|
||||||
if (ssi != nil) { if (srhs != nil) {
|
if (ssi != nil) { if (srhs != nil) {
|
||||||
@@ -30570,7 +30587,7 @@ fn cgassign(c: *cgen, n: *node) void = {
|
|||||||
&& n.rhs.kind == nkind.N_CALL
|
&& n.rhs.kind == nkind.N_CALL
|
||||||
&& fi.tnode != nil
|
&& fi.tnode != nil
|
||||||
&& fi.tnode.kind == nkind.N_TNAME
|
&& fi.tnode.kind == nkind.N_TNAME
|
||||||
&& primsize(fi.tnode.str) == 0) {
|
&& aliasprimsize(c, fi.tnode.str) == 0) {
|
||||||
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
||||||
if (ssi != nil) {
|
if (ssi != nil) {
|
||||||
let ssz: i32 = structabisize(ssi);
|
let ssz: i32 = structabisize(ssi);
|
||||||
@@ -30625,7 +30642,7 @@ fn cgassign(c: *cgen, n: *node) void = {
|
|||||||
&& n.rhs.kind == nkind.N_STRUCTLIT
|
&& n.rhs.kind == nkind.N_STRUCTLIT
|
||||||
&& fi.tnode != nil
|
&& fi.tnode != nil
|
||||||
&& fi.tnode.kind == nkind.N_TNAME
|
&& fi.tnode.kind == nkind.N_TNAME
|
||||||
&& primsize(fi.tnode.str) == 0) {
|
&& aliasprimsize(c, fi.tnode.str) == 0) {
|
||||||
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
||||||
if (ssi != nil) {
|
if (ssi != nil) {
|
||||||
cgstructlitfill(c, ssi, n.rhs, 2, 0, bn,
|
cgstructlitfill(c, ssi, n.rhs, 2, 0, bn,
|
||||||
@@ -30638,7 +30655,7 @@ fn cgassign(c: *cgen, n: *node) void = {
|
|||||||
&& n.rhs.kind == nkind.N_IDENT
|
&& n.rhs.kind == nkind.N_IDENT
|
||||||
&& fi.tnode != nil
|
&& fi.tnode != nil
|
||||||
&& fi.tnode.kind == nkind.N_TNAME
|
&& fi.tnode.kind == nkind.N_TNAME
|
||||||
&& primsize(fi.tnode.str) == 0) {
|
&& aliasprimsize(c, fi.tnode.str) == 0) {
|
||||||
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
let ssi: *structinfo = structlookup(c, fi.tnode.str);
|
||||||
let srhs: *local = localfindnode(c, n.rhs.str);
|
let srhs: *local = localfindnode(c, n.rhs.str);
|
||||||
if (ssi != nil) { if (srhs != nil) {
|
if (ssi != nil) { if (srhs != nil) {
|
||||||
@@ -31417,7 +31434,7 @@ fn cgassign(c: *cgen, n: *node) void = {
|
|||||||
if (streq(ofi.fname, innerfld)) {
|
if (streq(ofi.fname, innerfld)) {
|
||||||
let oft: *node = ofi.tnode;
|
let oft: *node = ofi.tnode;
|
||||||
if (oft != nil) { if (oft.kind == nkind.N_TNAME) {
|
if (oft != nil) { if (oft.kind == nkind.N_TNAME) {
|
||||||
if (primsize(oft.str) == 0) {
|
if (aliasprimsize(c, oft.str) == 0) {
|
||||||
let isi: *structinfo = structlookup(c, oft.str);
|
let isi: *structinfo = structlookup(c, oft.str);
|
||||||
if (isi != nil) {
|
if (isi != nil) {
|
||||||
let ffi: *fieldinfo = isi.fields;
|
let ffi: *fieldinfo = isi.fields;
|
||||||
|
|||||||
@@ -22,6 +22,18 @@
|
|||||||
* `(*t).under`, ww `t. under`, and a string literal containing
|
* `(*t).under`, ww `t. under`, and a string literal containing
|
||||||
* a block-comment OPENER token that blinded the old regex
|
* a block-comment OPENER token that blinded the old regex
|
||||||
* comment-strip for the rest of the file.
|
* comment-strip for the rest of the file.
|
||||||
|
* 6. RULE 2 (#101/#109) — bare primsize() in the ww stage is the
|
||||||
|
* alias-blind width shape aliasprimsize() supersedes. A bare
|
||||||
|
* `primsize(` REDS; the SSoT wrapper `aliasprimsize(` must NOT
|
||||||
|
* (left word boundary); the evasion spellings (space-before-paren,
|
||||||
|
* name-at-EOL line split, string-blind block-comment opener in a
|
||||||
|
* literal, paren-wrap `(primsize)(nm)`, function-value bind
|
||||||
|
* `let p = primsize` — the last two reviewer-109-found, both
|
||||||
|
* compile + run) all RED; a
|
||||||
|
* `primsize-ok` annotation exempts; a corrupted one does not; the
|
||||||
|
* primsize-ok and peel-ok windows are independent (neither blinds
|
||||||
|
* the other's shape); and a C-file `primsize(` is out of scope
|
||||||
|
* (the C stage chases via type_chase_named, no primsize symbol).
|
||||||
*
|
*
|
||||||
* Scratch trees live under /tmp and exercise the lint via its ROOT
|
* Scratch trees live under /tmp and exercise the lint via its ROOT
|
||||||
* override (sizelint-style), so the real tree is never touched.
|
* override (sizelint-style), so the real tree is never touched.
|
||||||
@@ -159,6 +171,79 @@ static const struct lintrow lintrows[] = {
|
|||||||
{ "evade_c_string_blind", "cmd/w6c/x.c",
|
{ "evade_c_string_blind", "cmd/w6c/x.c",
|
||||||
"static const char *s = \"/*\";\n"
|
"static const char *s = \"/*\";\n"
|
||||||
"static Type *f(Type *t) { return t->under; }\n", 1 },
|
"static Type *f(Type *t) { return t->under; }\n", 1 },
|
||||||
|
/* RULE 2 (#101/#109): bare primsize() outside the chase is the
|
||||||
|
* forbidden alias-blind width shape; aliasprimsize is the SSoT. */
|
||||||
|
{ "prim_bare", "selfhost/cmd/wcc/x.ww",
|
||||||
|
"fn f(c: *cgen, nm: str) i32 = {\n"
|
||||||
|
"\tlet z: i32 = primsize(nm);\n"
|
||||||
|
"\treturn z;\n"
|
||||||
|
"};\n", 1 },
|
||||||
|
{ "prim_evade_spacing", "selfhost/cmd/wcc/x.ww",
|
||||||
|
"fn f(c: *cgen, nm: str) i32 = {\n"
|
||||||
|
"\tlet z: i32 = primsize (nm);\n"
|
||||||
|
"\treturn z;\n"
|
||||||
|
"};\n", 1 },
|
||||||
|
{ "prim_evade_linesplit", "selfhost/cmd/wcc/x.ww",
|
||||||
|
"fn f(c: *cgen, nm: str) i32 = {\n"
|
||||||
|
"\tlet z: i32 = primsize\n"
|
||||||
|
"\t (nm);\n"
|
||||||
|
"\treturn z;\n"
|
||||||
|
"};\n", 1 },
|
||||||
|
{ "prim_evade_string_blind", "selfhost/cmd/wcc/x.ww",
|
||||||
|
"fn f(c: *cgen) str = {\n"
|
||||||
|
"\tlet s: str = \"/*\";\n"
|
||||||
|
"\tlet z: i32 = primsize(s);\n"
|
||||||
|
"\treturn s;\n"
|
||||||
|
"};\n", 1 },
|
||||||
|
/* review-109 evasions: both COMPILE + run (verified) yet slipped a
|
||||||
|
* `primsize(`-only matcher — the token rule reds them. */
|
||||||
|
{ "prim_evade_parenwrap", "selfhost/cmd/wcc/x.ww",
|
||||||
|
"fn f(c: *cgen, nm: str) i32 = {\n"
|
||||||
|
"\tlet z: i32 = (primsize)(nm);\n"
|
||||||
|
"\treturn z;\n"
|
||||||
|
"};\n", 1 },
|
||||||
|
{ "prim_evade_fnvalue", "selfhost/cmd/wcc/x.ww",
|
||||||
|
"fn f(c: *cgen, nm: str) i32 = {\n"
|
||||||
|
"\tlet p = primsize;\n"
|
||||||
|
"\treturn p(nm);\n"
|
||||||
|
"};\n", 1 },
|
||||||
|
/* aliasprimsize() is the SSoT wrapper — its `primsize` suffix must
|
||||||
|
* NOT trip the left-word-bounded matcher (the central evasion). */
|
||||||
|
{ "prim_alias_wrapper_ok", "selfhost/cmd/wcc/x.ww",
|
||||||
|
"fn f(c: *cgen, nm: str) i32 = {\n"
|
||||||
|
"\tlet z: i32 = aliasprimsize(c, nm);\n"
|
||||||
|
"\treturn z;\n"
|
||||||
|
"};\n", 0 },
|
||||||
|
{ "prim_annotated_ok", "selfhost/cmd/wcc/x.ww",
|
||||||
|
"fn f(c: *cgen, nm: str) i32 = {\n"
|
||||||
|
"\t// primsize-ok: chase body\n"
|
||||||
|
"\tlet z: i32 = primsize(nm);\n"
|
||||||
|
"\treturn z;\n"
|
||||||
|
"};\n", 0 },
|
||||||
|
{ "prim_corrupt_annotation", "selfhost/cmd/wcc/x.ww",
|
||||||
|
"fn f(c: *cgen, nm: str) i32 = {\n"
|
||||||
|
"\t// primsize-okk-corrupt: nope\n"
|
||||||
|
"\tlet z: i32 = primsize(nm);\n"
|
||||||
|
"\treturn z;\n"
|
||||||
|
"};\n", 1 },
|
||||||
|
/* the two exemption windows are independent: primsize-ok must not
|
||||||
|
* blind an under-token peel, nor peel-ok a bare primsize. */
|
||||||
|
{ "prim_window_no_cross_under", "selfhost/cmd/wcc/x.ww",
|
||||||
|
"fn f(t: *tinfo) *tinfo = {\n"
|
||||||
|
"\t// primsize-ok: must NOT exempt the under peel below\n"
|
||||||
|
"\treturn t.under;\n"
|
||||||
|
"};\n", 1 },
|
||||||
|
{ "peel_window_no_cross_prim", "selfhost/cmd/wcc/x.ww",
|
||||||
|
"fn f(c: *cgen, nm: str) i32 = {\n"
|
||||||
|
"\t// peel-ok: must NOT exempt the primsize below\n"
|
||||||
|
"\tlet z: i32 = primsize(nm);\n"
|
||||||
|
"\treturn z;\n"
|
||||||
|
"};\n", 1 },
|
||||||
|
/* RULE 2 is ww-only: the C stage dealiases via type_chase_named and
|
||||||
|
* has no primsize symbol — a C `primsize(` is not in scope. */
|
||||||
|
{ "prim_c_file_out_of_scope", "cmd/w6c/x.c",
|
||||||
|
"static int primsize(const char *n) { return 0; }\n"
|
||||||
|
"int g(void) { return primsize(\"u8\"); }\n", 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|||||||
154
tools/peellint
154
tools/peellint
@@ -1,38 +1,66 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# tools/peellint — gate against raw TY_NAMED single-peel reads outside
|
# tools/peellint — gate against two raw single-resolve shapes that
|
||||||
# the chase accessors. The #5 alias-arc close-by-construction contract
|
# bypass the alias-chase accessors.
|
||||||
# (rob F2/B7 rulings): one chased accessor is the only spelled way to
|
|
||||||
# dealias — type_chase_named (cmd/wcc/type.c) on the C side, tichase
|
|
||||||
# (selfhost/cmd/wcc/cgenutil.ww) on the ww side. A raw `->under` /
|
|
||||||
# `.under` read peels exactly one NAMED layer; chain-of-aliases stacks
|
|
||||||
# two, so every kind-gated consumer downstream of a single peel falls
|
|
||||||
# to a scalar shape (the four-times-burned family: #60/#61/#62/#70…).
|
|
||||||
# ZERO raw under-token reads may exist in scope outside the annotated
|
|
||||||
# whitelist; this gate lands in the same commit that deletes the last
|
|
||||||
# raw read and keeps the class unwritable.
|
|
||||||
#
|
#
|
||||||
# What this does NOT close (stated honestly, per the f2-ruling): a
|
# RULE 1 (raw TY_NAMED single-peel reads) — the #5 alias-arc
|
||||||
|
# close-by-construction contract (rob F2/B7 rulings): one chased
|
||||||
|
# accessor is the only spelled way to dealias — type_chase_named
|
||||||
|
# (cmd/wcc/type.c) on the C side, tichase (selfhost/cmd/wcc/cgenutil.ww)
|
||||||
|
# on the ww side. A raw `->under` / `.under` read peels exactly one
|
||||||
|
# NAMED layer; chain-of-aliases stacks two, so every kind-gated consumer
|
||||||
|
# downstream of a single peel falls to a scalar shape (the four-times-
|
||||||
|
# burned family: #60/#61/#62/#70…). ZERO raw under-token reads may
|
||||||
|
# exist in scope outside the annotated whitelist.
|
||||||
|
#
|
||||||
|
# RULE 2 (bare primsize() name-keyed width) — the #101/#109 close-by-
|
||||||
|
# construction contract. primsize(name) is the ww-stage primitive-width
|
||||||
|
# table; it is ALIAS-BLIND — a narrow alias (`type my32 = u32`) returns
|
||||||
|
# 0, defaulting strides/widths to 8 (the #101 struct-fill miscompile and
|
||||||
|
# the #109 is-primitive GUARD family). aliasprimsize(c, name) is the
|
||||||
|
# SSoT chase (primsize else aliaslookup-chase, cgenutil.ww). A bare
|
||||||
|
# primsize() outside the chase machinery is the forbidden shape: the
|
||||||
|
# size/guard sites route through aliasprimsize so an alias resolves.
|
||||||
|
# This rule is ww-only — the C side dealiases via type_chase_named and
|
||||||
|
# has no primsize symbol. ZERO bare primsize() calls may exist in the
|
||||||
|
# ww stage outside the annotated whitelist.
|
||||||
|
#
|
||||||
|
# Both rules land in the same commit that deletes the last raw shape and
|
||||||
|
# keep the class unwritable.
|
||||||
|
#
|
||||||
|
# What rule 1 does NOT close (stated honestly, per the f2-ruling): a
|
||||||
# consumer that never spells `under` at all — a switch on t->kind that
|
# consumer that never spells `under` at all — a switch on t->kind that
|
||||||
# simply never peels — has no token to see here. That NO-PEEL class is
|
# simply never peels — has no token to see here. That NO-PEEL class is
|
||||||
# closed only where classification routes through the internalized
|
# closed only where classification routes through the internalized
|
||||||
# chasing helpers, and contained elsewhere by the acceptance-commit-
|
# chasing helpers, and contained elsewhere by the acceptance-commit-
|
||||||
# carries-tripwires doctrine.
|
# carries-tripwires doctrine. Rule 2 has the symmetric edge: a size
|
||||||
|
# computed by a hardcoded literal instead of primsize is caught by
|
||||||
|
# sizelint (rule 13), not here.
|
||||||
#
|
#
|
||||||
# Matcher: a character scan strips block/line comments and string/char
|
# Matcher: a character scan strips block/line comments and string/char
|
||||||
# literals first (a regex pass mis-nests `/*` inside a string — review
|
# literals first (a regex pass mis-nests `/*` inside a string — review
|
||||||
# probe E6), then the under-token is matched accessor-spelling-wide:
|
# probe E6), then the tokens are matched accessor-spelling-wide:
|
||||||
# `->under`/`.under` in C (deref-dot `(*t).under` is the same peel),
|
# rule 1: `->under`/`.under` in C (deref-dot `(*t).under` is the same
|
||||||
# `.under` in ww, with optional whitespace after the operator and a
|
# peel), `.under` in ww, with optional whitespace after the operator
|
||||||
# line-split continuation (`t->` at EOL, `under` next line) — all the
|
# and a line-split continuation (`t->` at EOL, `under` next line).
|
||||||
# compiling spellings the B7 review probes evaded with. Right token
|
# rule 2 (ww only): the bare `primsize` token, LEFT+RIGHT word-bounded
|
||||||
# bound keeps prose like "io.underread" (check.ww) out.
|
# so the superstring `aliasprimsize` is NOT a hit. Matching the
|
||||||
|
# standalone token (not just `primsize(`) closes the call form
|
||||||
|
# `primsize(nm)`, the paren-wrap `(primsize)(nm)`, the function-value
|
||||||
|
# bind `let p = primsize`, and every line-split — all of which
|
||||||
|
# compile and reintroduce the alias-blind width (review probes).
|
||||||
|
# Right/left token bounds keep prose like "io.underread" (check.ww) and
|
||||||
|
# "aliasprimsize" out.
|
||||||
#
|
#
|
||||||
# Exemption: a line containing `peel-ok` (or the equivalent landed
|
# Exemption: a line containing `peel-ok` (or the equivalent landed
|
||||||
# spelling `peellint-ok`) exempts itself and the following 9 lines —
|
# spelling `peellint-ok`) exempts rule-1 violations on itself and the
|
||||||
# wide enough that one annotation atop a short construction/chase body
|
# following 9 lines; a line containing `primsize-ok` exempts rule-2
|
||||||
# covers it, narrow enough that a stray peel can't hide behind a
|
# violations over the same window. The windows are kept separate so a
|
||||||
# distant annotation. Reasons stay WHY-only (rule 8): construction,
|
# rule-1 annotation cannot blind a rule-2 bug and vice versa. Wide
|
||||||
# chase body, recursive chase, resolve-state probe, or a cited task.
|
# enough that one annotation atop a short construction/chase body covers
|
||||||
|
# it, narrow enough that a stray shape can't hide behind a distant
|
||||||
|
# annotation. Reasons stay WHY-only (rule 8): construction, chase body,
|
||||||
|
# recursive chase, resolve-state probe, structural-by-design sizer, or a
|
||||||
|
# cited task.
|
||||||
#
|
#
|
||||||
# Scope: cmd/wcc cmd/w6c selfhost/cmd/wcc lib/ww (skip *.combined.ww).
|
# Scope: cmd/wcc cmd/w6c selfhost/cmd/wcc lib/ww (skip *.combined.ww).
|
||||||
# lib/ww/typ.ww is in scope deliberately — it is type.c's ww mirror,
|
# lib/ww/typ.ww is in scope deliberately — it is type.c's ww mirror,
|
||||||
@@ -62,17 +90,21 @@ BEGIN { nviol = 0 }
|
|||||||
FNR == 1 {
|
FNR == 1 {
|
||||||
cur_file = FILENAME
|
cur_file = FILENAME
|
||||||
is_c = (cur_file ~ /\.(c|h)$/)
|
is_c = (cur_file ~ /\.(c|h)$/)
|
||||||
exempt_until = 0
|
und_exempt_until = 0
|
||||||
|
prim_exempt_until = 0
|
||||||
in_block = 0
|
in_block = 0
|
||||||
pending = 0
|
pending_und = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
# Whitelist annotation: arm the exemption window on the RAW line so an
|
# Whitelist annotations: arm the exemption windows on the RAW line so an
|
||||||
# annotation inside a comment still counts. `peellint-ok` is the
|
# annotation inside a comment still counts. `peellint-ok` is the
|
||||||
# already-landed sibling spelling (check.ww construction) — accepted
|
# already-landed sibling spelling (check.ww construction) — accepted
|
||||||
# as-is, history is not re-spelled.
|
# as-is, history is not re-spelled. The two windows are independent.
|
||||||
tolower($0) ~ /peel(lint)?-ok([^a-z0-9_]|$)/ {
|
tolower($0) ~ /peel(lint)?-ok([^a-z0-9_]|$)/ {
|
||||||
if (FNR + 9 > exempt_until) exempt_until = FNR + 9
|
if (FNR + 9 > und_exempt_until) und_exempt_until = FNR + 9
|
||||||
|
}
|
||||||
|
tolower($0) ~ /primsize-ok([^a-z0-9_]|$)/ {
|
||||||
|
if (FNR + 9 > prim_exempt_until) prim_exempt_until = FNR + 9
|
||||||
}
|
}
|
||||||
|
|
||||||
# Strip comments and string/char literals by character scan: a comment
|
# Strip comments and string/char literals by character scan: a comment
|
||||||
@@ -110,28 +142,52 @@ tolower($0) ~ /peel(lint)?-ok([^a-z0-9_]|$)/ {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
if (FNR <= exempt_until) { pending = 0; next }
|
und_exempt = (FNR <= und_exempt_until)
|
||||||
# Both C spellings peel: p->under and (*p).under / v.under.
|
prim_exempt = (FNR <= prim_exempt_until)
|
||||||
if (is_c)
|
blank = (code ~ /^[ \t]*$/)
|
||||||
re = "(->|\\.)[ \t]*under([^A-Za-z0-9_]|$)"
|
|
||||||
else
|
# RULE 1 — raw under-token peel. Both C spellings peel:
|
||||||
re = "\\.[ \t]*under([^A-Za-z0-9_]|$)"
|
# p->under and (*p).under / v.under.
|
||||||
hit = (code ~ re)
|
if (!und_exempt) {
|
||||||
# Line-split continuation: operator at EOL, token opening the
|
|
||||||
# next code line. Comment-only lines keep the pend alive.
|
|
||||||
if (!hit && pending && code ~ /^[ \t]*under([^A-Za-z0-9_]|$)/)
|
|
||||||
hit = 1
|
|
||||||
if (hit) {
|
|
||||||
printf("%s:%d: raw under-token read outside the chase accessor; " \
|
|
||||||
"route via type_chase_named (C) / tichase (ww), or annotate " \
|
|
||||||
"peel-ok: <why>\n", cur_file, FNR)
|
|
||||||
nviol++
|
|
||||||
}
|
|
||||||
if (code !~ /^[ \t]*$/) {
|
|
||||||
if (is_c)
|
if (is_c)
|
||||||
pending = (code ~ /(->|\.)[ \t]*$/)
|
ure = "(->|\\.)[ \t]*under([^A-Za-z0-9_]|$)"
|
||||||
else
|
else
|
||||||
pending = (code ~ /\.[ \t]*$/)
|
ure = "\\.[ \t]*under([^A-Za-z0-9_]|$)"
|
||||||
|
uhit = (code ~ ure)
|
||||||
|
# Line-split continuation: operator at EOL, token opening the
|
||||||
|
# next code line. Comment-only lines keep the pend alive.
|
||||||
|
if (!uhit && pending_und && code ~ /^[ \t]*under([^A-Za-z0-9_]|$)/)
|
||||||
|
uhit = 1
|
||||||
|
if (uhit) {
|
||||||
|
printf("%s:%d: raw under-token read outside the chase accessor; " \
|
||||||
|
"route via type_chase_named (C) / tichase (ww), or annotate " \
|
||||||
|
"peel-ok: <why>\n", cur_file, FNR)
|
||||||
|
nviol++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# RULE 2 — bare primsize token (ww only). LEFT+RIGHT word bounds
|
||||||
|
# so the superstring aliasprimsize() is never a hit and a longer
|
||||||
|
# identifier with a primsize prefix is not matched. Matching the
|
||||||
|
# token (not `primsize(`) catches the paren-wrap `(primsize)(nm)`,
|
||||||
|
# the function-value bind `let p = primsize`, and every line-split —
|
||||||
|
# all compile and reintroduce the alias-blind width (review probes).
|
||||||
|
if (!is_c && !prim_exempt) {
|
||||||
|
if (code ~ /(^|[^A-Za-z0-9_])primsize([^A-Za-z0-9_]|$)/) {
|
||||||
|
printf("%s:%d: bare primsize outside the chase accessor; " \
|
||||||
|
"route via aliasprimsize (ww), or annotate " \
|
||||||
|
"primsize-ok: <why>\n", cur_file, FNR)
|
||||||
|
nviol++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Pending updates. An exempt line resets its pend (an annotated
|
||||||
|
# operator/name must not carry into a non-exempt next line); a blank
|
||||||
|
# or comment-only line keeps the pend alive; otherwise re-derive.
|
||||||
|
if (und_exempt) pending_und = 0
|
||||||
|
else if (!blank) {
|
||||||
|
if (is_c) pending_und = (code ~ /(->|\.)[ \t]*$/)
|
||||||
|
else pending_und = (code ~ /\.[ \t]*$/)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user