From 62f13ef4efe5aab5030ea56442b552ad0c5fec42 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Sat, 26 Sep 2026 10:08:51 +0100 Subject: [PATCH] Zcu: fix overriding weak export with strong Our "multiple definitions" check in the frontend was a little overzealous! The only case which should actually be an error is when there are multiple *strong* definitions. In the future we will eliminate this frontend check entirely, because it's redundant with the check the linker will perform---but for now it's worth keeping since our linkers do not yet print useful source location information for Zig exports. Resolves: https://codeberg.org/ziglang/zig/issues/36678 --- src/Zcu/PerThread.zig | 4 ++++ test/cases/export_override_libc.zig | 16 ++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 test/cases/export_override_libc.zig diff --git a/src/Zcu/PerThread.zig b/src/Zcu/PerThread.zig index f0b1764f463dbe9d085e0fca931d20286e99255f..6635be1a1428d9971b6d23f8b0d61c2ec401681b 100644 --- a/src/Zcu/PerThread.zig +++ b/src/Zcu/PerThread.zig @@ -3655,6 +3655,10 @@ pub fn processExports(pt: Zcu.PerThread) (Allocator.Error || Io.Cancelable)!void for (alive_exports.items) |export_index| { const exp = export_index.ptr(zcu); + switch (exp.opts.linkage) { + .strong => {}, + .weak, .internal, .link_once => continue, + } const gop = exports_by_name.getOrPutAssumeCapacity(exp.opts.name); if (gop.found_existing) { const existing_exp = gop.value_ptr.*.ptr(zcu); diff --git a/test/cases/export_override_libc.zig b/test/cases/export_override_libc.zig new file mode 100644 index 0000000000000000000000000000000000000000..bc16cb8dd2cdfcb0f09da2da83715b2ec9715321 --- /dev/null +++ b/test/cases/export_override_libc.zig @@ -0,0 +1,16 @@ +/// This implementation is intentionally incorrect so we can check that it is +/// called instead of the libc symbol. +export fn isdigit(c: c_int) c_int { + return @intFromBool(c == '0'); +} + +pub fn main() void { + const static = struct { + extern fn isdigit(c_int) c_int; + }; + if (static.isdigit('0') == 0) @panic("override failed: isdigit('0') == 0"); + if (static.isdigit('1') != 0) @panic("override failed: isdigit('1') != 0"); +} + +// run +// link_libc=true -- 2.54.0