From c467f6693eb815906088b15f25d4e21092526bb4 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 7 Mar 2022 13:36:58 -0700 Subject: [PATCH] stage2: fix union layout returning non-zero for zero-sized tag --- src/Module.zig | 5 +++-- test/behavior/union.zig | 23 +++++++++++++++++------ 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/Module.zig b/src/Module.zig index 33d5bb4c4c..0bcdc85c98 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -1278,7 +1278,8 @@ pub const Union = struct { var biggest_field: u32 = undefined; var payload_size: u64 = 0; var payload_align: u32 = 0; - for (u.fields.values()) |field, i| { + const fields = u.fields.values(); + for (fields) |field, i| { if (!field.ty.hasRuntimeBits()) continue; const field_align = a: { @@ -1300,7 +1301,7 @@ pub const Union = struct { } } payload_align = @maximum(payload_align, 1); - if (!have_tag) return .{ + if (!have_tag or fields.len <= 1) return .{ .abi_size = std.mem.alignForwardGeneric(u64, payload_size, payload_align), .abi_align = payload_align, .most_aligned_field = most_aligned_field, diff --git a/test/behavior/union.zig b/test/behavior/union.zig index 36202fcb3b..5152edd46e 100644 --- a/test/behavior/union.zig +++ b/test/behavior/union.zig @@ -1011,7 +1011,9 @@ test "cast from pointer to anonymous struct to pointer to union" { } test "switching on non exhaustive union" { - if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage1) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO const S = struct { const E = enum(u8) { @@ -1027,7 +1029,8 @@ test "switching on non exhaustive union" { var a = U{ .a = 2 }; switch (a) { .a => |val| try expect(val == 2), - .b => unreachable, + .b => return error.Fail, + _ => return error.Fail, } } }; @@ -1036,7 +1039,9 @@ test "switching on non exhaustive union" { } test "containers with single-field enums" { - if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO const S = struct { const A = union(enum) { f1 }; @@ -1061,8 +1066,10 @@ test "containers with single-field enums" { comptime try S.doTheTest(); } -test "@unionInit on union w/ tag but no fields" { - if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO +test "@unionInit on union with tag but no fields" { + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO const S = struct { const Type = enum(u8) { no_op = 105 }; @@ -1077,7 +1084,11 @@ test "@unionInit on union w/ tag but no fields" { }; comptime { - std.debug.assert(@sizeOf(Data) != 0); + if (builtin.zig_backend == .stage1) { + // stage1 gets the wrong answer here + } else { + std.debug.assert(@sizeOf(Data) == 0); + } } fn doTheTest() !void {