cgen: peel *fn field types for local struct-field callees

fnptrcalleetfn's N_DOT arm accepted only a bare N_TFN field tnode, so
a call through a field declared `cb: *fn(...)` missed, fell through to
the name registry, and emitted CALL cb(SB) — an undefined symbol
(loud at link; cstage calls the stamped ptr-to-fn indirectly). Same
TPTR peel the N_IDENT arm already had. Fixture fnptrfield_call covers
the by-value and via-pointer shapes; corpus pin 1478/2956.
This commit is contained in:
2026-08-08 02:28:33 +09:00
parent 939d0938e2
commit 6553d60e91
4 changed files with 40 additions and 6 deletions

View File

@@ -108,6 +108,18 @@ fn fnptrcalleetfn(c: *cgen, callee: *syntax.node) *syntax.node = {
let ft: *syntax.node = fi.tnode;
if (ft != nil) {
if (ft.kind == syntax.nkind.N_TFN) { return ft; };
// `cb: *fn(...)` — same TPTR peel as the N_IDENT
// arm above; without it the field-call fell through
// to the name registry and emitted CALL <leaf>(SB)
// (undefined symbol — loud at link, but cstage
// resolves the stamped ptr-to-fn and calls indirect).
if (ft.kind == syntax.nkind.N_TPTR) {
if (ft.lhs != nil) {
if (ft.lhs.kind == syntax.nkind.N_TFN) {
return ft.lhs;
};
};
};
};
return nil;
};