Files
sx/examples/1228-ffi-extern-c-non-transitive.sx
agra 717c35d26d test(ffi-linkage): Phase 5.0 prereq — xfail lib-less extern/#foreign C-import visibility equivalence
Cross-module example (main → b → c) referencing c's lib-less C imports
transitively. The non-transitive C-import gate (lower/decl.zig
c_import_bare) must police the legacy `#foreign` form and the new
`extern` keyword IDENTICALLY — same 'C function not visible' diagnostic,
not the generic top-level-name wording. Today the extern twin escapes the
c_import_bare gate (body is an empty block, not foreign_expr) and is only
caught by the general isNameVisible gate, yielding the generic message.
Expected snapshot pins the DESIRED equivalent wording; the next commit
aligns the gate to green it. Prerequisite for migrating the fn-decl
`#foreign` path onto `extern`.

443/444 corpus (1228 xfail), 444 unit.
2026-06-14 20:47:48 +03:00

20 lines
839 B
Plaintext

// `#import` is non-transitive for C-import functions: main imports b,
// b imports c, so main must NOT see c's lib-less `#foreign` / `extern`
// C functions directly. Referencing either is rejected by the
// C-import visibility gate (lower/decl.zig `c_import_bare`).
//
// Equivalence lock (FFI-linkage Part B): the legacy `#foreign` form and
// the new `extern` keyword are two spellings of the same lib-less
// C-symbol import, so they must produce the SAME "C function not
// visible" diagnostic — not the generic top-level-name wording. This
// pins that equivalence as a prerequisite for migrating the fn-decl
// `#foreign` path onto `extern`.
#import "modules/std.sx";
#import "1228-ffi-extern-c-non-transitive/b.sx";
main :: () -> i32 {
print("{}\n", c_foreign_abs(-3));
print("{}\n", c_extern_abs(-4));
return 0;
}