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 {...@@ -1278,7 +1278,8 @@ pub const Union = struct {
1278 var biggest_field: u32 = undefined;1278 var biggest_field: u32 = undefined;
1279 var payload_size: u64 = 0;1279 var payload_size: u64 = 0;
1280 var payload_align: u32 = 0;1280 var payload_align: u32 = 0;
1281 for (u.fields.values()) |field, i| {1281 const fields = u.fields.values();
1282 for (fields) |field, i| {
1282 if (!field.ty.hasRuntimeBits()) continue;1283 if (!field.ty.hasRuntimeBits()) continue;
12831284
1284 const field_align = a: {1285 const field_align = a: {
...@@ -1300,7 +1301,7 @@ pub const Union = struct {...@@ -1300,7 +1301,7 @@ pub const Union = struct {
1300 }1301 }
1301 }1302 }
1302 payload_align = @maximum(payload_align, 1);1303 payload_align = @maximum(payload_align, 1);
1303 if (!have_tag) return .{1304 if (!have_tag or fields.len <= 1) return .{
1304 .abi_size = std.mem.alignForwardGeneric(u64, payload_size, payload_align),1305 .abi_size = std.mem.alignForwardGeneric(u64, payload_size, payload_align),
1305 .abi_align = payload_align,1306 .abi_align = payload_align,
1306 .most_aligned_field = most_aligned_field,1307 .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" {...@@ -1011,7 +1011,9 @@ test "cast from pointer to anonymous struct to pointer to union" {
1011}1011}
10121012
1013test "switching on non exhaustive union" {1013test "switching on non exhaustive union" {
1014 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO1014 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
1016 const S = struct {1018 const S = struct {
1017 const E = enum(u8) {1019 const E = enum(u8) {
...@@ -1027,7 +1029,8 @@ test "switching on non exhaustive union" {...@@ -1027,7 +1029,8 @@ test "switching on non exhaustive union" {
1027 var a = U{ .a = 2 };1029 var a = U{ .a = 2 };
1028 switch (a) {1030 switch (a) {
1029 .a => |val| try expect(val == 2),1031 .a => |val| try expect(val == 2),
1030 .b => unreachable,1032 .b => return error.Fail,
1033 _ => return error.Fail,
1031 }1034 }
1032 }1035 }
1033 };1036 };
...@@ -1036,7 +1039,9 @@ test "switching on non exhaustive union" {...@@ -1036,7 +1039,9 @@ test "switching on non exhaustive union" {
1036}1039}
10371040
1038test "containers with single-field enums" {1041test "containers with single-field enums" {
1039 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO1042 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
1041 const S = struct {1046 const S = struct {
1042 const A = union(enum) { f1 };1047 const A = union(enum) { f1 };
...@@ -1061,8 +1066,10 @@ test "containers with single-field enums" {...@@ -1061,8 +1066,10 @@ test "containers with single-field enums" {
1061 comptime try S.doTheTest();1066 comptime try S.doTheTest();
1062}1067}
10631068
1064test "@unionInit on union w/ tag but no fields" {1069test "@unionInit on union with tag but no fields" {
1065 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO1070 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
1067 const S = struct {1074 const S = struct {
1068 const Type = enum(u8) { no_op = 105 };1075 const Type = enum(u8) { no_op = 105 };
...@@ -1077,7 +1084,11 @@ test "@unionInit on union w/ tag but no fields" {...@@ -1077,7 +1084,11 @@ test "@unionInit on union w/ tag but no fields" {
1077 };1084 };
10781085
1079 comptime {1086 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 }
1081 }1092 }
10821093
1083 fn doTheTest() !void {1094 fn doTheTest() !void {