Files
BFM-decomp/cookbook/C0086.md
T

2.0 KiB

§75c — Class-B's remedy is the FULL §17a-1 PAIR (decl and call-site cast); a decl-only fix moves the error and looks like a new wall (Phase 29 SESSION-19, func_8012F14C)

§75a's class B is a genuine arity split — the same callee declared with two different arities across the fleet (func_8012F14C: 1,944 (s32) vs 968 (s32,s32,s32)). The obvious move is to make the shared macro's carried decl compatible with both, using the no-prototype () form that cdecl.compatible() measures as accepted in either order when no parameter default-promotes. That is half a fix, and the half that does not work.

What actually happens. () really does dissolve the declaration conflict — the byte-gate's classifier moved the failure from PLUMBING to CC1-FAIL, which is the tell that the first wall fell and a second appeared. Reading real cc1 stderr (hand-splice the macro into one member, build that object; do not trust a bare make … Error 33):

ov_SC01_001_jr_801734BC.c:2616: too many arguments to function `func_8012F14C'

C's composite-type rule: after void f(s32); then void f();, the composite is still void f(s32) — the earlier prototype wins. So a 3-argument call is a hard error no declaration spelling can rescue.

The remedy is the pair §17a-1 always specified (and what cast_call_sites.py implements):

extern void func_8012F14C();                                        /* conflict-free in either order */
((void (*)(s32, s32, s32))func_8012F14C)((s32)&mtx, (s32)&vec, (s32)&out);   /* call bypasses the prototype */

gcc-2.7.2 folds a cast of a known function symbol back to a direct jal, so the body's bytes are unchanged (byte-gated on all 3 existing members: 7ca772be / b3b95547 / 9885af74).

Rule: for class B, change the decl and the call together. A decl-only change is not a smaller version of the fix — it relocates the diagnostic, and a session reading only the failure class will record a fresh wall where there is none.