Passing a default-conv sx function to a `callconv(.c)` fn-pointer slot (e.g. pthread_create's start routine) used to silently mismatch ABIs: the C-side caller didn't supply __sx_ctx, so the sx-side body read its first user param as garbage. The bug surfaced as a SIGSEGV inside ANativeWindow_setBuffersGeometry on Android during chess bringup. Now the compiler rejects the coercion outright at the bare-fn name lookup site: error: call-convention mismatch: 'sx_handler' is declared with default sx convention but the target type expects callconv(.c) Also: `#foreign` declarations without an explicit `callconv` now default to `.c` instead of `.default`. Every external C symbol is by definition C-conv; the previous default silently typed `objc_msgSend` (et al.) as default-conv, so the check would fire on the consumer side when the user typed a fn-ptr as `callconv(.c)`. With the foreign-default fix, the existing typed-msgSend casts in `std/objc.sx` and `gpu/metal.sx` keep type-checking and the rule is "C-conv on both sides or neither." Caught by the new check (fixed in the same commit): - `ios_gl_proc` in `platform/uikit.sx` lacked callconv(.c) but was passed to `load_gl` whose `get_proc` slot expects it. - `ffi_apply_callback` / `ffi_apply_callback2` in `examples/ffi-06-callback.sx` had default-conv fn-ptr params but the C bodies (in the companion .c) are unambiguously C-conv. Regression test: `examples/131-callconv-mismatch-diagnostic.sx` locks in the diagnostic shape (sx-conv fn → callconv(.c) slot). 153/153 example tests pass. Chess green on macOS / iOS sim / Android.
15 lines
478 B
Plaintext
15 lines
478 B
Plaintext
// Passing a default-conv sx function as a callconv(.c) fn-pointer
|
|
// silently mismatches ABIs — historically that meant the C-side caller
|
|
// supplied no `__sx_ctx` slot 0 and the sx-side body read garbage.
|
|
// The compiler now rejects the coercion outright with a "call-convention
|
|
// mismatch" diagnostic.
|
|
|
|
#import "modules/std.sx";
|
|
|
|
sx_handler :: (arg: *void) -> *void { return arg; }
|
|
|
|
main :: () -> s32 {
|
|
fp : (*void) -> *void callconv(.c) = sx_handler;
|
|
return 0;
|
|
}
|