| author | |
| committer | |
| log | 274949fdbb7a98d374d5e994110dbfd639c70acf |
| tree | 72c4009cdeee36154dd0d456a7f2cb656a7c852f |
| parent | 919a5dd8ce8c64d7b9a924ea12215fc5f0227e51 |
| signature |
`IntType.fromType` would previously set the signedness of any backing int
of a `packed union` to `unsigned` unconditionally which caused comparisons
of packed unions with large, signed backing integers to miscompile.
Packed unions are now lowered correctly to their actual backing int type.3 files changed, 30 insertions(+), 12 deletions(-)
src/codegen/wasm/CodeGen.zig+4-12| ... | @@ -2527,18 +2527,10 @@ const IntType = struct { | ... | @@ -2527,18 +2527,10 @@ const IntType = struct { |
| 2527 | .f16, .f32, .f64, .f80, .f128, .c_longdouble => unreachable, | 2527 | .f16, .f32, .f64, .f80, .f128, .c_longdouble => unreachable, |
| 2528 | .anyopaque, .void, .type, .comptime_int, .comptime_float, .noreturn, .null, .undefined, .enum_literal, .generic_poison => unreachable, | 2528 | .anyopaque, .void, .type, .comptime_int, .comptime_float, .noreturn, .null, .undefined, .enum_literal, .generic_poison => unreachable, |
| 2529 | }, | 2529 | }, |
| 2530 | .struct_type => { | 2530 | .enum_type, |
| 2531 | const loaded_struct = ip.loadStructType(ty_index); | 2531 | .struct_type, |
| 2532 | switch (loaded_struct.layout) { | 2532 | .union_type, |
| 2533 | .auto, .@"extern" => unreachable, | 2533 | => ty_index = Type.fromInterned(ty_index).backingIntType(zcu).toIntern(), |
| 2534 | .@"packed" => ty_index = loaded_struct.packed_backing_int_type, | ||
| 2535 | } | ||
| 2536 | }, | ||
| 2537 | .union_type => return switch (ip.loadUnionType(ty_index).layout) { | ||
| 2538 | .auto, .@"extern" => unreachable, | ||
| 2539 | .@"packed" => .{ .is_signed = false, .bits = @intCast(ty.bitSize(zcu)) }, | ||
| 2540 | }, | ||
| 2541 | .enum_type => ty_index = ip.loadEnumType(ty_index).int_tag_type, | ||
| 2542 | .error_set_type, .inferred_error_set_type => return .{ .is_signed = false, .bits = zcu.errorSetBits() }, | 2534 | .error_set_type, .inferred_error_set_type => return .{ .is_signed = false, .bits = zcu.errorSetBits() }, |
| 2543 | else => unreachable, | 2535 | else => unreachable, |
| 2544 | }; | 2536 | }; |
test/behavior/packed-struct.zig+13| ... | @@ -1261,3 +1261,16 @@ test "convert from/to backing int" { | ... | @@ -1261,3 +1261,16 @@ test "convert from/to backing int" { |
| 1261 | try S.doTheTest(.{ .a = 123, .b = .y, .c = 0.23 }); | 1261 | try S.doTheTest(.{ .a = 123, .b = .y, .c = 0.23 }); |
| 1262 | try comptime S.doTheTest(.{ .a = 123, .b = .y, .c = 0.23 }); | 1262 | try comptime S.doTheTest(.{ .a = 123, .b = .y, .c = 0.23 }); |
| 1263 | } | 1263 | } |
| 1264 | |||
| 1265 | test "equality with wide backing integer" { | ||
| 1266 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/35982 | ||
| 1267 | |||
| 1268 | const S = packed struct(i200) { | ||
| 1269 | x: u200, | ||
| 1270 | fn doTheTest(s: @This(), int: i200) !void { | ||
| 1271 | try expect(s == @as(@This(), @bitCast(int))); | ||
| 1272 | } | ||
| 1273 | }; | ||
| 1274 | try S.doTheTest(.{ .x = (1 << 200) - 1 }, -1); | ||
| 1275 | try comptime S.doTheTest(.{ .x = (1 << 200) - 1 }, -1); | ||
| 1276 | } |
test/behavior/packed-union.zig+13| ... | @@ -241,3 +241,16 @@ test "convert from/to backing int" { | ... | @@ -241,3 +241,16 @@ test "convert from/to backing int" { |
| 241 | try U.doTheTest(.{ .a = 123 }); | 241 | try U.doTheTest(.{ .a = 123 }); |
| 242 | try comptime U.doTheTest(.{ .a = 123 }); | 242 | try comptime U.doTheTest(.{ .a = 123 }); |
| 243 | } | 243 | } |
| 244 | |||
| 245 | test "equality with wide backing integer" { | ||
| 246 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/35982 | ||
| 247 | |||
| 248 | const U = packed union(i200) { | ||
| 249 | x: u200, | ||
| 250 | fn doTheTest(s: @This(), int: i200) !void { | ||
| 251 | try expect(s == @as(@This(), @bitCast(int))); | ||
| 252 | } | ||
| 253 | }; | ||
| 254 | try U.doTheTest(.{ .x = (1 << 200) - 1 }, -1); | ||
| 255 | try comptime U.doTheTest(.{ .x = (1 << 200) - 1 }, -1); | ||
| 256 | } |