fix(ffi-linkage): Phase 5.0 prereq — map extern C-variadic tail to ... like #foreign
Two gates were keyed on the `#foreign` (foreign_expr) body shape only: - declareFunction: the is_variadic drop (decl.zig) — a variadic extern kept its trailing slice param in the IR signature. - packVariadicCallArgs: the call-site early-out (pack.zig) — extras were slice-packed instead of passed through the C `...` slot. Both now also fire for `extern_export == .extern_`, so a variadic `extern` drops the trailing `..args: []T`, sets is_variadic, and passes extras through the C ABI with default argument promotion — byte-identical to its `#foreign` twin. Greens example 1229. 645 corpus / 444 unit, 0 failed.
This commit is contained in:
@@ -2094,7 +2094,12 @@ pub fn declareFunction(self: *Lowering, fd: *const ast.FnDecl, name: []const u8)
|
||||
const is_extern_decl = fd.extern_export == .extern_;
|
||||
var is_variadic = false;
|
||||
var effective_params = fd.params;
|
||||
if (is_foreign and fd.params.len > 0 and fd.params[fd.params.len - 1].is_variadic) {
|
||||
// The C-variadic `...` tail applies to BOTH lib-less C-import spellings:
|
||||
// the legacy `#foreign` (foreign_expr body) and the new `extern` keyword.
|
||||
// A migrated variadic `extern` must drop the trailing slice param and set
|
||||
// the flag exactly as its `#foreign` twin did (mirrored at the call site
|
||||
// by `packVariadicCallArgs`).
|
||||
if ((is_foreign or is_extern_decl) and fd.params.len > 0 and fd.params[fd.params.len - 1].is_variadic) {
|
||||
is_variadic = true;
|
||||
effective_params = fd.params[0 .. fd.params.len - 1];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user