authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-03-07 13:36:58-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-03-07 13:36:58-07:00
logc467f6693eb815906088b15f25d4e21092526bb4
tree8519239a6cd49beb87e7245b039c84a62fac0257
parentf59cbd89e349fb3002500cb2a1d69ca5e6063338

stage2: fix union layout returning non-zero for zero-sized tag


2 files changed, 20 insertions(+), 8 deletions(-)

src/Module.zig+3-2
......@@ -1278,7 +1278,8 @@ pub const Union = struct {
12781278 var biggest_field: u32 = undefined;
12791279 var payload_size: u64 = 0;
12801280 var payload_align: u32 = 0;
1281 for (u.fields.values()) |field, i| {
1281 const fields = u.fields.values();
1282 for (fields) |field, i| {
12821283 if (!field.ty.hasRuntimeBits()) continue;
12831284
12841285 const field_align = a: {
......@@ -1300,7 +1301,7 @@ pub const Union = struct {
13001301 }
13011302 }
13021303 payload_align = @maximum(payload_align, 1);
1303 if (!have_tag) return .{
1304 if (!have_tag or fields.len <= 1) return .{
13041305 .abi_size = std.mem.alignForwardGeneric(u64, payload_size, payload_align),
13051306 .abi_align = payload_align,
13061307 .most_aligned_field = most_aligned_field,
test/behavior/union.zig+17-6
......@@ -1011,7 +1011,9 @@ test "cast from pointer to anonymous struct to pointer to union" {
10111011}
10121012
10131013test "switching on non exhaustive union" {
1014 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
1014 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
1015 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1016 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
10151017
10161018 const S = struct {
10171019 const E = enum(u8) {
......@@ -1027,7 +1029,8 @@ test "switching on non exhaustive union" {
10271029 var a = U{ .a = 2 };
10281030 switch (a) {
10291031 .a => |val| try expect(val == 2),
1030 .b => unreachable,
1032 .b => return error.Fail,
1033 _ => return error.Fail,
10311034 }
10321035 }
10331036 };
......@@ -1036,7 +1039,9 @@ test "switching on non exhaustive union" {
10361039}
10371040
10381041test "containers with single-field enums" {
1039 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
1042 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1043 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1044 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
10401045
10411046 const S = struct {
10421047 const A = union(enum) { f1 };
......@@ -1061,8 +1066,10 @@ test "containers with single-field enums" {
10611066 comptime try S.doTheTest();
10621067}
10631068
1064test "@unionInit on union w/ tag but no fields" {
1065 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
1069test "@unionInit on union with tag but no fields" {
1070 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1071 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1072 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
10661073
10671074 const S = struct {
10681075 const Type = enum(u8) { no_op = 105 };
......@@ -1077,7 +1084,11 @@ test "@unionInit on union w/ tag but no fields" {
10771084 };
10781085
10791086 comptime {
1080 std.debug.assert(@sizeOf(Data) != 0);
1087 if (builtin.zig_backend == .stage1) {
1088 // stage1 gets the wrong answer here
1089 } else {
1090 std.debug.assert(@sizeOf(Data) == 0);
1091 }
10811092 }
10821093
10831094 fn doTheTest() !void {