mirror of
https://github.com/ziglang/zig.git
synced 2026-01-26 17:25:25 +00:00
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
This commit is contained in:
parent
8591f30b0d
commit
8a2ab60fca
@ -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;
|
||||
}
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user