From 6c46a9bfc0f3eed6ce7398f9a83efe96619e73da Mon Sep 17 00:00:00 2001 From: kcbanner Date: Sun, 9 Mar 2025 15:44:26 -0400 Subject: [PATCH] Value: ensure that extern structs have their layout resolved in ptrField --- src/Value.zig | 1 + test/behavior/globals.zig | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/src/Value.zig b/src/Value.zig index 40e5331c4ef6..b74996cb0110 100644 --- a/src/Value.zig +++ b/src/Value.zig @@ -3779,6 +3779,7 @@ pub fn ptrField(parent_ptr: Value, field_idx: u32, pt: Zcu.PerThread) !Value { .auto => break :field .{ field_ty, try aggregate_ty.fieldAlignmentSema(field_idx, pt) }, .@"extern" => { // Well-defined layout, so just offset the pointer appropriately. + try aggregate_ty.resolveLayout(pt); const byte_off = aggregate_ty.structFieldOffset(field_idx, zcu); const field_align = a: { const parent_align = if (parent_ptr_info.flags.alignment == .none) pa: { diff --git a/test/behavior/globals.zig b/test/behavior/globals.zig index c11fa7cb2531..b07c5116f8f8 100644 --- a/test/behavior/globals.zig +++ b/test/behavior/globals.zig @@ -167,3 +167,31 @@ test "global var can be indirectly self-referential" { try std.testing.expect(S.bar.other == &S.foo); try std.testing.expect(S.bar.other.other == &S.bar); } + +pub const Callbacks = extern struct { + key_callback: *const fn (key: i32) callconv(.c) i32, +}; + +var callbacks: Callbacks = undefined; +var callbacks_loaded: bool = false; + +test "function pointer field call on global extern struct, conditional on global" { + if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; + + if (callbacks_loaded) { + try std.testing.expectEqual(42, callbacks.key_callback(42)); + } +} + +test "function pointer field call on global extern struct" { + if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; + + const S = struct { + fn keyCallback(key: i32) callconv(.c) i32 { + return key; + } + }; + + callbacks = Callbacks{ .key_callback = S.keyCallback }; + try std.testing.expectEqual(42, callbacks.key_callback(42)); +}