wcc_ww/check: inferred struct-lit let plants the synthesized TNAME — field(SB) name-leak + tagged-field assign bound (#24)
For an annotation-less `let p = pt{...}` checkletassign planted exprtype's
N_STRUCTLIT result — the struct decl's BODY node (N_TSTRUCT, per #66) — as
the let's type. Every cgen local-arm dispatch (cgdot read, cgassign
tagged-field store, the alias peel) is N_TNAME-keyed, so the body matched
no arm: field reads fell to the module-qualified fallback and emitted the
FIELD NAME as a global symbol (MOVQ f(SB) — link-fail, #211 name-leak
family; silent corruption if a same-named global exists), and a tagged-
field assign fell to the assign-resolver TY_TAGGED loud bound. Both PG5
wwstage symptoms, one root; plain structs leaked too. Normalizing the
inferred binding to the synthesized TNAME (mktname + tinfofornode stamp)
routes every consumer down the already-byte-id annotated path. cstage
needs no twin: check.c:1477 clet carries Sym.type (tinfo) and its
emission is annotation-invariant (probed). Test 811: 10 rows x 2 drivers
+ 10 asm-byte-id; pre-fix wwstage link-fails every unannotated row
(incl. the `...` autofill and parenthesized forms; nested s.f.g ran
but cs!=ww asm).
This commit is contained in:
@@ -14627,6 +14627,24 @@ fn checkletassign(c: *checker, n: *node) void = {
|
||||
// Defaulting (untyped_int → i32, etc.) is exprtype's job at use
|
||||
// sites, not the binding site.
|
||||
if (n.lhs == nil) {
|
||||
// #24 (fold-5 prereq): a struct-lit init's exprtype returns the
|
||||
// decl's BODY node (N_TSTRUCT, L3103 per #66) — but every cgen
|
||||
// local-arm dispatch (cgdot read, cgassign tagged-field store,
|
||||
// cgun addr-of) is N_TNAME-keyed, so planting the body dropped
|
||||
// `p.f` to the module-qualified `MOVQ f(SB)` fallback (link-fail
|
||||
// name-leak; #211 family). Normalize to the synthesized TNAME so
|
||||
// the inferred binding is indistinguishable from the annotated
|
||||
// one downstream. cstage needs no twin: check.c:1477 clet carries
|
||||
// Sym.type (tinfo), and its emission is annotation-invariant
|
||||
// (probed identical asm annotated vs not).
|
||||
if (src != nil && src.kind == nkind.N_TSTRUCT
|
||||
&& n.rhs.kind == nkind.N_STRUCTLIT
|
||||
&& n.rhs.lhs != nil && n.rhs.lhs.kind == nkind.N_IDENT) {
|
||||
let ltn: *node = mktname(c, n.rhs.lhs.str);
|
||||
ltn.type_ = tinfofornode(c, ltn): *void;
|
||||
n.lhs = ltn;
|
||||
return;
|
||||
};
|
||||
if (src != nil) { n.lhs = src; };
|
||||
return;
|
||||
};
|
||||
|
||||
@@ -4363,6 +4363,24 @@ fn checkletassign(c: *checker, n: *node) void = {
|
||||
// Defaulting (untyped_int → i32, etc.) is exprtype's job at use
|
||||
// sites, not the binding site.
|
||||
if (n.lhs == nil) {
|
||||
// #24 (fold-5 prereq): a struct-lit init's exprtype returns the
|
||||
// decl's BODY node (N_TSTRUCT, L3103 per #66) — but every cgen
|
||||
// local-arm dispatch (cgdot read, cgassign tagged-field store,
|
||||
// cgun addr-of) is N_TNAME-keyed, so planting the body dropped
|
||||
// `p.f` to the module-qualified `MOVQ f(SB)` fallback (link-fail
|
||||
// name-leak; #211 family). Normalize to the synthesized TNAME so
|
||||
// the inferred binding is indistinguishable from the annotated
|
||||
// one downstream. cstage needs no twin: check.c:1477 clet carries
|
||||
// Sym.type (tinfo), and its emission is annotation-invariant
|
||||
// (probed identical asm annotated vs not).
|
||||
if (src != nil && src.kind == nkind.N_TSTRUCT
|
||||
&& n.rhs.kind == nkind.N_STRUCTLIT
|
||||
&& n.rhs.lhs != nil && n.rhs.lhs.kind == nkind.N_IDENT) {
|
||||
let ltn: *node = mktname(c, n.rhs.lhs.str);
|
||||
ltn.type_ = tinfofornode(c, ltn): *void;
|
||||
n.lhs = ltn;
|
||||
return;
|
||||
};
|
||||
if (src != nil) { n.lhs = src; };
|
||||
return;
|
||||
};
|
||||
|
||||
@@ -14627,6 +14627,24 @@ fn checkletassign(c: *checker, n: *node) void = {
|
||||
// Defaulting (untyped_int → i32, etc.) is exprtype's job at use
|
||||
// sites, not the binding site.
|
||||
if (n.lhs == nil) {
|
||||
// #24 (fold-5 prereq): a struct-lit init's exprtype returns the
|
||||
// decl's BODY node (N_TSTRUCT, L3103 per #66) — but every cgen
|
||||
// local-arm dispatch (cgdot read, cgassign tagged-field store,
|
||||
// cgun addr-of) is N_TNAME-keyed, so planting the body dropped
|
||||
// `p.f` to the module-qualified `MOVQ f(SB)` fallback (link-fail
|
||||
// name-leak; #211 family). Normalize to the synthesized TNAME so
|
||||
// the inferred binding is indistinguishable from the annotated
|
||||
// one downstream. cstage needs no twin: check.c:1477 clet carries
|
||||
// Sym.type (tinfo), and its emission is annotation-invariant
|
||||
// (probed identical asm annotated vs not).
|
||||
if (src != nil && src.kind == nkind.N_TSTRUCT
|
||||
&& n.rhs.kind == nkind.N_STRUCTLIT
|
||||
&& n.rhs.lhs != nil && n.rhs.lhs.kind == nkind.N_IDENT) {
|
||||
let ltn: *node = mktname(c, n.rhs.lhs.str);
|
||||
ltn.type_ = tinfofornode(c, ltn): *void;
|
||||
n.lhs = ltn;
|
||||
return;
|
||||
};
|
||||
if (src != nil) { n.lhs = src; };
|
||||
return;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user