aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/stage1/analyze.cpp31
-rw-r--r--test/stage1/behavior/union.zig27
2 files changed, 34 insertions, 24 deletions
diff --git a/src/stage1/analyze.cpp b/src/stage1/analyze.cpp
index ed0a033592..3f95456c3f 100644
--- a/src/stage1/analyze.cpp
+++ b/src/stage1/analyze.cpp
@@ -2550,8 +2550,8 @@ static Error resolve_union_alignment(CodeGen *g, ZigType *union_type) {
union_type->data.unionation.gen_tag_index = 1;
}
} else {
- assert(most_aligned_union_member != nullptr);
- union_type->abi_align = most_aligned_union_member->align;
+ union_type->abi_align = most_aligned_union_member?
+ most_aligned_union_member->align : 0;
union_type->data.unionation.gen_union_index = SIZE_MAX;
union_type->data.unionation.gen_tag_index = SIZE_MAX;
}
@@ -3535,33 +3535,13 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
union_type->data.unionation.resolve_loop_flag_zero_bits = false;
union_type->data.unionation.gen_field_count = gen_field_index;
- bool zero_bits = gen_field_index == 0 && (field_count < 2 || !src_have_tag);
+ bool zero_bits = gen_field_index == 0 &&
+ (tag_type == nullptr || !type_has_bits(g, tag_type));
if (!zero_bits) {
union_type->abi_size = SIZE_MAX;
union_type->size_in_bits = SIZE_MAX;
}
- if (zero_bits) {
- // Don't forget to resolve the types for each union member even though
- // the type is zero sized.
- // XXX: Do it in a nicer way in stage2.
- union_type->data.unionation.resolve_loop_flag_other = true;
-
- for (uint32_t i = 0; i < field_count; i += 1) {
- TypeUnionField *union_field = &union_type->data.unionation.fields[i];
- ZigType *field_type = resolve_union_field_type(g, union_field);
- if (field_type == nullptr) {
- union_type->data.unionation.resolve_status = ResolveStatusInvalid;
- return ErrorSemanticAnalyzeFail;
- }
- }
-
- union_type->data.unionation.resolve_loop_flag_other = false;
- union_type->data.unionation.resolve_status = ResolveStatusSizeKnown;
-
- return ErrorNone;
- }
-
union_type->data.unionation.resolve_status = ResolveStatusZeroBitsKnown;
return ErrorNone;
@@ -8877,6 +8857,9 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta
union_type->llvm_type = get_llvm_type(g, tag_type);
union_type->llvm_di_type = get_llvm_di_type(g, tag_type);
}
+
+ union_type->data.unionation.gen_union_index = SIZE_MAX;
+ union_type->data.unionation.gen_tag_index = SIZE_MAX;
union_type->data.unionation.resolve_status = ResolveStatusLLVMFull;
return;
}
diff --git a/test/stage1/behavior/union.zig b/test/stage1/behavior/union.zig
index 915f412c51..b243cee11e 100644
--- a/test/stage1/behavior/union.zig
+++ b/test/stage1/behavior/union.zig
@@ -734,3 +734,30 @@ test "containers with single-field enums" {
S.doTheTest();
comptime S.doTheTest();
}
+
+test "@unionInit on union w/ tag but no fields" {
+ const S = struct {
+ const Type = enum(u8) { no_op = 105 };
+
+ const Data = union(Type) {
+ no_op: void,
+
+ pub fn decode(buf: []const u8) !Data {
+ return @unionInit(Data, "no_op", {});
+ }
+ };
+
+ comptime {
+ expect(@sizeOf(Data) != 0);
+ }
+
+ fn doTheTest() void {
+ var data: Data = .{ .no_op = .{} };
+ var o = try Data.decode(&[_]u8{});
+ expectEqual(Type.no_op, o);
+ }
+ };
+
+ S.doTheTest();
+ comptime S.doTheTest();
+}