stage2 llvm: correct handling of zero-bit types in unionFieldPtr

Pointers to zero-bit types are not zero-bit types so the function should
return something.
Closes #12716
This commit is contained in:
Veikka Tuominen 2022-09-02 13:17:42 +03:00
parent 4462d08224
commit 7a8d9af4a9
2 changed files with 32 additions and 7 deletions

View File

@ -9051,7 +9051,7 @@ pub const FuncGen = struct {
}
},
},
.Union => return self.unionFieldPtr(inst, struct_ptr, struct_ty, field_index),
.Union => return self.unionFieldPtr(inst, struct_ptr, struct_ty),
else => unreachable,
}
}
@ -9061,16 +9061,13 @@ pub const FuncGen = struct {
inst: Air.Inst.Index,
union_ptr: *const llvm.Value,
union_ty: Type,
field_index: c_uint,
) !?*const llvm.Value {
const union_obj = union_ty.cast(Type.Payload.Union).?.data;
const field = &union_obj.fields.values()[field_index];
const result_llvm_ty = try self.dg.lowerType(self.air.typeOfIndex(inst));
if (!field.ty.hasRuntimeBitsIgnoreComptime()) {
return null;
}
const target = self.dg.module.getTarget();
const layout = union_ty.unionGetLayout(target);
if (layout.payload_size == 0) {
return self.builder.buildBitCast(union_ptr, result_llvm_ty, "");
}
const payload_index = @boolToInt(layout.tag_align >= layout.payload_align);
const union_field_ptr = self.builder.buildStructGEP(union_ptr, payload_index, "");
return self.builder.buildBitCast(union_field_ptr, result_llvm_ty, "");

View File

@ -1352,3 +1352,31 @@ test "@unionInit uses tag value instead of field index" {
}
try expect(@enumToInt(u) == 255);
}
test "union field ptr - zero sized payload" {
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
const U = union {
foo: void,
bar: void,
fn bar(_: *void) void {}
};
var u: U = .{ .foo = {} };
U.bar(&u.foo);
}
test "union field ptr - zero sized field" {
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
const U = union {
foo: void,
bar: u32,
fn bar(_: *void) void {}
};
var u: U = .{ .foo = {} };
U.bar(&u.foo);
}