fix(ffi-linkage): Phase 5.0 prereq — validate extern LIB refs like #foreign
checkForeignRefs now reads a library reference from either spelling — the legacy #foreign body (foreign_expr.library_ref) or the new extern keyword (extern_lib) — and validates both against the declared #library / #import c units. The diagnostic names the surface keyword the user wrote (#foreign vs extern), so example 1620 (#foreign) is byte-unchanged and example 1231 (extern) gets the parallel 'extern library ... not declared'. Greens 1231. 647 corpus / 444 unit, 0 failed.
This commit is contained in:
@@ -332,10 +332,20 @@ fn checkForeignRefs(valid: *const std.StringHashMap(void), decls: []const *Node,
|
||||
for (decls) |d| {
|
||||
switch (d.data) {
|
||||
.fn_decl => |fd| {
|
||||
if (fd.body.data != .foreign_expr) continue;
|
||||
const ref = fd.body.data.foreign_expr.library_ref orelse continue;
|
||||
// A library reference rides on the legacy `#foreign` body
|
||||
// (foreign_expr.library_ref) OR the new `extern LIB` keyword
|
||||
// (extern_lib); both must name a declared #library / #import c
|
||||
// unit. The diagnostic names the surface keyword the user wrote
|
||||
// so the two spellings stay self-describing.
|
||||
const kw: []const u8, const ref: []const u8 = switch (fd.body.data) {
|
||||
.foreign_expr => |fe| .{ "#foreign", fe.library_ref orelse continue },
|
||||
else => if (fd.extern_export == .extern_)
|
||||
.{ "extern", fd.extern_lib orelse continue }
|
||||
else
|
||||
continue,
|
||||
};
|
||||
if (!valid.contains(ref)) {
|
||||
diags.addFmt(.err, d.span, "#foreign library '{s}' is not declared; expected a #library constant or a named '#import c' unit", .{ref});
|
||||
diags.addFmt(.err, d.span, "{s} library '{s}' is not declared; expected a #library constant or a named '#import c' unit", .{ kw, ref });
|
||||
}
|
||||
},
|
||||
.namespace_decl => |ns| checkForeignRefs(valid, ns.decls, diags),
|
||||
|
||||
Reference in New Issue
Block a user