| author | |
| committer | |
| log | 7bb4c855ad3776d7f7d21f2bf1c5c93366205ff2 |
| tree | 1695efe0e849848743d3c152f4349b054a7bf96e |
| parent | 405b8e9eeefda07b16044690471cfd57fc654c75 |
| parent | b0f753e21d6fcaafd0b35dc02fdfe23b14e310d6 |
| signature |
Prevent crash with empty non-exhaustive enum4 files changed, 40 insertions(+), 2 deletions(-)
src/analyze.cpp+1-1| ... | @@ -8312,7 +8312,7 @@ static void resolve_llvm_types_enum(CodeGen *g, ZigType *enum_type, ResolveStatu | ... | @@ -8312,7 +8312,7 @@ static void resolve_llvm_types_enum(CodeGen *g, ZigType *enum_type, ResolveStatu |
| 8312 | 8312 | ||
| 8313 | uint32_t field_count = enum_type->data.enumeration.src_field_count; | 8313 | uint32_t field_count = enum_type->data.enumeration.src_field_count; |
| 8314 | 8314 | ||
| 8315 | assert(enum_type->data.enumeration.fields); | 8315 | assert(field_count == 0 || enum_type->data.enumeration.fields != nullptr); |
| 8316 | ZigLLVMDIEnumerator **di_enumerators = allocate<ZigLLVMDIEnumerator*>(field_count); | 8316 | ZigLLVMDIEnumerator **di_enumerators = allocate<ZigLLVMDIEnumerator*>(field_count); |
| 8317 | 8317 | ||
| 8318 | for (uint32_t i = 0; i < field_count; i += 1) { | 8318 | for (uint32_t i = 0; i < field_count; i += 1) { |
src/ir.cpp+10-1| ... | @@ -21614,7 +21614,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira, | ... | @@ -21614,7 +21614,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira, |
| 21614 | case ZigTypeIdEnum: { | 21614 | case ZigTypeIdEnum: { |
| 21615 | if ((err = type_resolve(ira->codegen, target_type, ResolveStatusZeroBitsKnown))) | 21615 | if ((err = type_resolve(ira->codegen, target_type, ResolveStatusZeroBitsKnown))) |
| 21616 | return ira->codegen->invalid_instruction; | 21616 | return ira->codegen->invalid_instruction; |
| 21617 | if (target_type->data.enumeration.src_field_count < 2) { | 21617 | if (target_type->data.enumeration.src_field_count == 1) { |
| 21618 | TypeEnumField *only_field = &target_type->data.enumeration.fields[0]; | 21618 | TypeEnumField *only_field = &target_type->data.enumeration.fields[0]; |
| 21619 | IrInstruction *result = ir_const(ira, &switch_target_instruction->base, target_type); | 21619 | IrInstruction *result = ir_const(ira, &switch_target_instruction->base, target_type); |
| 21620 | bigint_init_bigint(&result->value->data.x_enum_tag, &only_field->value); | 21620 | 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 | ... | @@ -22351,6 +22351,15 @@ static IrInstruction *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrIns |
| 22351 | 22351 | ||
| 22352 | assert(target->value->type->id == ZigTypeIdEnum); | 22352 | assert(target->value->type->id == ZigTypeIdEnum); |
| 22353 | 22353 | ||
| 22354 | if (target->value->type->data.enumeration.src_field_count == 1 && | ||
| 22355 | !target->value->type->data.enumeration.non_exhaustive) { | ||
| 22356 | TypeEnumField *only_field = &target->value->type->data.enumeration.fields[0]; | ||
| 22357 | ZigValue *array_val = create_const_str_lit(ira->codegen, only_field->name)->data.x_ptr.data.ref.pointee; | ||
| 22358 | IrInstruction *result = ir_const(ira, &instruction->base, nullptr); | ||
| 22359 | init_const_slice(ira->codegen, result->value, array_val, 0, buf_len(only_field->name), true); | ||
| 22360 | return result; | ||
| 22361 | } | ||
| 22362 | |||
| 22354 | if (instr_is_comptime(target)) { | 22363 | if (instr_is_comptime(target)) { |
| 22355 | if ((err = type_resolve(ira->codegen, target->value->type, ResolveStatusZeroBitsKnown))) | 22364 | if ((err = type_resolve(ira->codegen, target->value->type, ResolveStatusZeroBitsKnown))) |
| 22356 | return ira->codegen->invalid_instruction; | 22365 | return ira->codegen->invalid_instruction; |
test/stage1/behavior/enum.zig+20| ... | @@ -65,6 +65,26 @@ test "non-exhaustive enum" { | ... | @@ -65,6 +65,26 @@ test "non-exhaustive enum" { |
| 65 | comptime S.doTheTest(52); | 65 | comptime S.doTheTest(52); |
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | test "empty non-exhaustive enum" { | ||
| 69 | const S = struct { | ||
| 70 | const E = enum(u8) { | ||
| 71 | _, | ||
| 72 | }; | ||
| 73 | fn doTheTest(y: u8) void { | ||
| 74 | var e = @intToEnum(E, y); | ||
| 75 | expect(switch (e) { | ||
| 76 | _ => true, | ||
| 77 | }); | ||
| 78 | expect(@enumToInt(e) == y); | ||
| 79 | |||
| 80 | expect(@typeInfo(E).Enum.fields.len == 0); | ||
| 81 | expect(@typeInfo(E).Enum.is_exhaustive == false); | ||
| 82 | } | ||
| 83 | }; | ||
| 84 | S.doTheTest(42); | ||
| 85 | comptime S.doTheTest(42); | ||
| 86 | } | ||
| 87 | |||
| 68 | test "enum type" { | 88 | test "enum type" { |
| 69 | const foo1 = Foo{ .One = 13 }; | 89 | const foo1 = Foo{ .One = 13 }; |
| 70 | const foo2 = Foo{ | 90 | const foo2 = Foo{ |
test/stage1/behavior/union.zig+9| ... | @@ -629,3 +629,12 @@ test "union initializer generates padding only if needed" { | ... | @@ -629,3 +629,12 @@ test "union initializer generates padding only if needed" { |
| 629 | var v = U{ .A = 532 }; | 629 | var v = U{ .A = 532 }; |
| 630 | expect(v.A == 532); | 630 | expect(v.A == 532); |
| 631 | } | 631 | } |
| 632 | |||
| 633 | test "runtime tag name with single field" { | ||
| 634 | const U = union(enum) { | ||
| 635 | A: i32, | ||
| 636 | }; | ||
| 637 | |||
| 638 | var v = U{ .A = 42 }; | ||
| 639 | expect(std.mem.eql(u8, @tagName(v), "A")); | ||
| 640 | } |