| author | |
| committer | |
| log | 7a8d9af4a94caeb74361c9462cd44a1e4356150b |
| tree | c1496557509bcd1aa9581e6541bfecd1374160dc |
| parent | 4462d082240d71e671a8d3d5fb3da81e70c4760e |
Pointers to zero-bit types are not zero-bit types so the function should
return something.
Closes #127162 files changed, 32 insertions(+), 7 deletions(-)
src/codegen/llvm.zig+4-7| ... | ... | @@ -9051,7 +9051,7 @@ pub const FuncGen = struct { |
| 9051 | 9051 | } |
| 9052 | 9052 | }, |
| 9053 | 9053 | }, |
| 9054 | .Union => return self.unionFieldPtr(inst, struct_ptr, struct_ty, field_index), | |
| 9054 | .Union => return self.unionFieldPtr(inst, struct_ptr, struct_ty), | |
| 9055 | 9055 | else => unreachable, |
| 9056 | 9056 | } |
| 9057 | 9057 | } |
| ... | ... | @@ -9061,16 +9061,13 @@ pub const FuncGen = struct { |
| 9061 | 9061 | inst: Air.Inst.Index, |
| 9062 | 9062 | union_ptr: *const llvm.Value, |
| 9063 | 9063 | union_ty: Type, |
| 9064 | field_index: c_uint, | |
| 9065 | 9064 | ) !?*const llvm.Value { |
| 9066 | const union_obj = union_ty.cast(Type.Payload.Union).?.data; | |
| 9067 | const field = &union_obj.fields.values()[field_index]; | |
| 9068 | 9065 | const result_llvm_ty = try self.dg.lowerType(self.air.typeOfIndex(inst)); |
| 9069 | if (!field.ty.hasRuntimeBitsIgnoreComptime()) { | |
| 9070 | return null; | |
| 9071 | } | |
| 9072 | 9066 | const target = self.dg.module.getTarget(); |
| 9073 | 9067 | const layout = union_ty.unionGetLayout(target); |
| 9068 | if (layout.payload_size == 0) { | |
| 9069 | return self.builder.buildBitCast(union_ptr, result_llvm_ty, ""); | |
| 9070 | } | |
| 9074 | 9071 | const payload_index = @boolToInt(layout.tag_align >= layout.payload_align); |
| 9075 | 9072 | const union_field_ptr = self.builder.buildStructGEP(union_ptr, payload_index, ""); |
| 9076 | 9073 | return self.builder.buildBitCast(union_field_ptr, result_llvm_ty, ""); |
test/behavior/union.zig+28| ... | ... | @@ -1352,3 +1352,31 @@ test "@unionInit uses tag value instead of field index" { |
| 1352 | 1352 | } |
| 1353 | 1353 | try expect(@enumToInt(u) == 255); |
| 1354 | 1354 | } |
| 1355 | ||
| 1356 | test "union field ptr - zero sized payload" { | |
| 1357 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | |
| 1358 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | |
| 1359 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 1360 | ||
| 1361 | const U = union { | |
| 1362 | foo: void, | |
| 1363 | bar: void, | |
| 1364 | fn bar(_: *void) void {} | |
| 1365 | }; | |
| 1366 | var u: U = .{ .foo = {} }; | |
| 1367 | U.bar(&u.foo); | |
| 1368 | } | |
| 1369 | ||
| 1370 | test "union field ptr - zero sized field" { | |
| 1371 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | |
| 1372 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | |
| 1373 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 1374 | ||
| 1375 | const U = union { | |
| 1376 | foo: void, | |
| 1377 | bar: u32, | |
| 1378 | fn bar(_: *void) void {} | |
| 1379 | }; | |
| 1380 | var u: U = .{ .foo = {} }; | |
| 1381 | U.bar(&u.foo); | |
| 1382 | } |