authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-12-15 16:07:23+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-12-15 14:40:21-05:00
log8a2ab60fca405d97d2d86456c92db1e5606622e4
tree6abb6579ebe362777950dcfb649af93e4ba3f63c
parent8591f30b0d53a597682bebdfcd570f5f44339b26

stage1: Don't skip steps when analyzing union types

Don't cut any corner and properly run the type trough every single step even though it has no fields (or, better, the sum of the size of all its fields is zero). Fix the logic to consider an explicit non-zero-sized tag enough to treat the type as sized. Closes #7451

2 files changed, 34 insertions(+), 24 deletions(-)

src/stage1/analyze.cpp+7-24
...@@ -2550,8 +2550,8 @@ static Error resolve_union_alignment(CodeGen *g, ZigType *union_type) {...@@ -2550,8 +2550,8 @@ static Error resolve_union_alignment(CodeGen *g, ZigType *union_type) {
2550 union_type->data.unionation.gen_tag_index = 1;2550 union_type->data.unionation.gen_tag_index = 1;
2551 }2551 }
2552 } else {2552 } else {
2553 assert(most_aligned_union_member != nullptr);2553 union_type->abi_align = most_aligned_union_member?
2554 union_type->abi_align = most_aligned_union_member->align;2554 most_aligned_union_member->align : 0;
2555 union_type->data.unionation.gen_union_index = SIZE_MAX;2555 union_type->data.unionation.gen_union_index = SIZE_MAX;
2556 union_type->data.unionation.gen_tag_index = SIZE_MAX;2556 union_type->data.unionation.gen_tag_index = SIZE_MAX;
2557 }2557 }
...@@ -3535,33 +3535,13 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {...@@ -3535,33 +3535,13 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
3535 union_type->data.unionation.resolve_loop_flag_zero_bits = false;3535 union_type->data.unionation.resolve_loop_flag_zero_bits = false;
35363536
3537 union_type->data.unionation.gen_field_count = gen_field_index;3537 union_type->data.unionation.gen_field_count = gen_field_index;
3538 bool zero_bits = gen_field_index == 0 && (field_count < 2 || !src_have_tag);3538 bool zero_bits = gen_field_index == 0 &&
3539 (tag_type == nullptr || !type_has_bits(g, tag_type));
3539 if (!zero_bits) {3540 if (!zero_bits) {
3540 union_type->abi_size = SIZE_MAX;3541 union_type->abi_size = SIZE_MAX;
3541 union_type->size_in_bits = SIZE_MAX;3542 union_type->size_in_bits = SIZE_MAX;
3542 }3543 }
35433544
3544 if (zero_bits) {
3545 // Don't forget to resolve the types for each union member even though
3546 // the type is zero sized.
3547 // XXX: Do it in a nicer way in stage2.
3548 union_type->data.unionation.resolve_loop_flag_other = true;
3549
3550 for (uint32_t i = 0; i < field_count; i += 1) {
3551 TypeUnionField *union_field = &union_type->data.unionation.fields[i];
3552 ZigType *field_type = resolve_union_field_type(g, union_field);
3553 if (field_type == nullptr) {
3554 union_type->data.unionation.resolve_status = ResolveStatusInvalid;
3555 return ErrorSemanticAnalyzeFail;
3556 }
3557 }
3558
3559 union_type->data.unionation.resolve_loop_flag_other = false;
3560 union_type->data.unionation.resolve_status = ResolveStatusSizeKnown;
3561
3562 return ErrorNone;
3563 }
3564
3565 union_type->data.unionation.resolve_status = ResolveStatusZeroBitsKnown;3545 union_type->data.unionation.resolve_status = ResolveStatusZeroBitsKnown;
35663546
3567 return ErrorNone;3547 return ErrorNone;
...@@ -8877,6 +8857,9 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta...@@ -8877,6 +8857,9 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta
8877 union_type->llvm_type = get_llvm_type(g, tag_type);8857 union_type->llvm_type = get_llvm_type(g, tag_type);
8878 union_type->llvm_di_type = get_llvm_di_type(g, tag_type);8858 union_type->llvm_di_type = get_llvm_di_type(g, tag_type);
8879 }8859 }
8860
8861 union_type->data.unionation.gen_union_index = SIZE_MAX;
8862 union_type->data.unionation.gen_tag_index = SIZE_MAX;
8880 union_type->data.unionation.resolve_status = ResolveStatusLLVMFull;8863 union_type->data.unionation.resolve_status = ResolveStatusLLVMFull;
8881 return;8864 return;
8882 }8865 }
test/stage1/behavior/union.zig+27
...@@ -734,3 +734,30 @@ test "containers with single-field enums" {...@@ -734,3 +734,30 @@ test "containers with single-field enums" {
734 S.doTheTest();734 S.doTheTest();
735 comptime S.doTheTest();735 comptime S.doTheTest();
736}736}
737
738test "@unionInit on union w/ tag but no fields" {
739 const S = struct {
740 const Type = enum(u8) { no_op = 105 };
741
742 const Data = union(Type) {
743 no_op: void,
744
745 pub fn decode(buf: []const u8) !Data {
746 return @unionInit(Data, "no_op", {});
747 }
748 };
749
750 comptime {
751 expect(@sizeOf(Data) != 0);
752 }
753
754 fn doTheTest() void {
755 var data: Data = .{ .no_op = .{} };
756 var o = try Data.decode(&[_]u8{});
757 expectEqual(Type.no_op, o);
758 }
759 };
760
761 S.doTheTest();
762 comptime S.doTheTest();
763}