authorgravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2025-03-09 15:44:26-04:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2025-04-11 21:35:42+02:00
log527df938e19574cc254100e9394581a9f46e644c
tree9891ce505362ea7deccbb1af09e7e2bf6889e3db
parent1d34616236521176b3173935951f14b5224b53a3
signaturebadge-check Signed by SSH key SHA256:7B/LJ7bpR1eX8aCXSr4mtd5M45VMPKcx9zY8e95b5QM

Value: ensure that extern structs have their layout resolved in ptrField


2 files changed, 29 insertions(+), 0 deletions(-)

src/Value.zig+1
...@@ -3779,6 +3779,7 @@ pub fn ptrField(parent_ptr: Value, field_idx: u32, pt: Zcu.PerThread) !Value {...@@ -3779,6 +3779,7 @@ pub fn ptrField(parent_ptr: Value, field_idx: u32, pt: Zcu.PerThread) !Value {
3779 .auto => break :field .{ field_ty, try aggregate_ty.fieldAlignmentSema(field_idx, pt) },3779 .auto => break :field .{ field_ty, try aggregate_ty.fieldAlignmentSema(field_idx, pt) },
3780 .@"extern" => {3780 .@"extern" => {
3781 // Well-defined layout, so just offset the pointer appropriately.3781 // Well-defined layout, so just offset the pointer appropriately.
3782 try aggregate_ty.resolveLayout(pt);
3782 const byte_off = aggregate_ty.structFieldOffset(field_idx, zcu);3783 const byte_off = aggregate_ty.structFieldOffset(field_idx, zcu);
3783 const field_align = a: {3784 const field_align = a: {
3784 const parent_align = if (parent_ptr_info.flags.alignment == .none) pa: {3785 const parent_align = if (parent_ptr_info.flags.alignment == .none) pa: {
test/behavior/globals.zig+28
...@@ -167,3 +167,31 @@ test "global var can be indirectly self-referential" {...@@ -167,3 +167,31 @@ test "global var can be indirectly self-referential" {
167 try std.testing.expect(S.bar.other == &S.foo);167 try std.testing.expect(S.bar.other == &S.foo);
168 try std.testing.expect(S.bar.other.other == &S.bar);168 try std.testing.expect(S.bar.other.other == &S.bar);
169}169}
170
171pub const Callbacks = extern struct {
172 key_callback: *const fn (key: i32) callconv(.c) i32,
173};
174
175var callbacks: Callbacks = undefined;
176var callbacks_loaded: bool = false;
177
178test "function pointer field call on global extern struct, conditional on global" {
179 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
180
181 if (callbacks_loaded) {
182 try std.testing.expectEqual(42, callbacks.key_callback(42));
183 }
184}
185
186test "function pointer field call on global extern struct" {
187 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
188
189 const S = struct {
190 fn keyCallback(key: i32) callconv(.c) i32 {
191 return key;
192 }
193 };
194
195 callbacks = Callbacks{ .key_callback = S.keyCallback };
196 try std.testing.expectEqual(42, callbacks.key_callback(42));
197}