mirror of
https://github.com/ziglang/zig.git
synced 2026-01-20 22:35:24 +00:00
Merge pull request #4222 from LemonBoy/eutwouwth
Prevent crash with empty non-exhaustive enum
This commit is contained in:
commit
7bb4c855ad
@ -8312,7 +8312,7 @@ static void resolve_llvm_types_enum(CodeGen *g, ZigType *enum_type, ResolveStatu
|
||||
|
||||
uint32_t field_count = enum_type->data.enumeration.src_field_count;
|
||||
|
||||
assert(enum_type->data.enumeration.fields);
|
||||
assert(field_count == 0 || enum_type->data.enumeration.fields != nullptr);
|
||||
ZigLLVMDIEnumerator **di_enumerators = allocate<ZigLLVMDIEnumerator*>(field_count);
|
||||
|
||||
for (uint32_t i = 0; i < field_count; i += 1) {
|
||||
|
||||
11
src/ir.cpp
11
src/ir.cpp
@ -21614,7 +21614,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,
|
||||
case ZigTypeIdEnum: {
|
||||
if ((err = type_resolve(ira->codegen, target_type, ResolveStatusZeroBitsKnown)))
|
||||
return ira->codegen->invalid_instruction;
|
||||
if (target_type->data.enumeration.src_field_count < 2) {
|
||||
if (target_type->data.enumeration.src_field_count == 1) {
|
||||
TypeEnumField *only_field = &target_type->data.enumeration.fields[0];
|
||||
IrInstruction *result = ir_const(ira, &switch_target_instruction->base, target_type);
|
||||
bigint_init_bigint(&result->value->data.x_enum_tag, &only_field->value);
|
||||
@ -22351,6 +22351,15 @@ static IrInstruction *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrIns
|
||||
|
||||
assert(target->value->type->id == ZigTypeIdEnum);
|
||||
|
||||
if (target->value->type->data.enumeration.src_field_count == 1 &&
|
||||
!target->value->type->data.enumeration.non_exhaustive) {
|
||||
TypeEnumField *only_field = &target->value->type->data.enumeration.fields[0];
|
||||
ZigValue *array_val = create_const_str_lit(ira->codegen, only_field->name)->data.x_ptr.data.ref.pointee;
|
||||
IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
|
||||
init_const_slice(ira->codegen, result->value, array_val, 0, buf_len(only_field->name), true);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (instr_is_comptime(target)) {
|
||||
if ((err = type_resolve(ira->codegen, target->value->type, ResolveStatusZeroBitsKnown)))
|
||||
return ira->codegen->invalid_instruction;
|
||||
|
||||
@ -65,6 +65,26 @@ test "non-exhaustive enum" {
|
||||
comptime S.doTheTest(52);
|
||||
}
|
||||
|
||||
test "empty non-exhaustive enum" {
|
||||
const S = struct {
|
||||
const E = enum(u8) {
|
||||
_,
|
||||
};
|
||||
fn doTheTest(y: u8) void {
|
||||
var e = @intToEnum(E, y);
|
||||
expect(switch (e) {
|
||||
_ => true,
|
||||
});
|
||||
expect(@enumToInt(e) == y);
|
||||
|
||||
expect(@typeInfo(E).Enum.fields.len == 0);
|
||||
expect(@typeInfo(E).Enum.is_exhaustive == false);
|
||||
}
|
||||
};
|
||||
S.doTheTest(42);
|
||||
comptime S.doTheTest(42);
|
||||
}
|
||||
|
||||
test "enum type" {
|
||||
const foo1 = Foo{ .One = 13 };
|
||||
const foo2 = Foo{
|
||||
|
||||
@ -629,3 +629,12 @@ test "union initializer generates padding only if needed" {
|
||||
var v = U{ .A = 532 };
|
||||
expect(v.A == 532);
|
||||
}
|
||||
|
||||
test "runtime tag name with single field" {
|
||||
const U = union(enum) {
|
||||
A: i32,
|
||||
};
|
||||
|
||||
var v = U{ .A = 42 };
|
||||
expect(std.mem.eql(u8, @tagName(v), "A"));
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user