authorgravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2025-03-09 15:44:26-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-04-11 15:30:20-04:00
logfa5915389640c2b00a093914fd803d7d87dc2e91
tree93e55c1055de800943b15c8941e27bbd8b58e008
parent90084f4ae329c89466bc8c74bd6e00db3f2a3803

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


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

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