| 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 | 8312 | |
| 8313 | 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 | 8316 | ZigLLVMDIEnumerator **di_enumerators = allocate<ZigLLVMDIEnumerator*>(field_count); |
| 8317 | 8317 | |
| 8318 | 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 | 21614 | case ZigTypeIdEnum: { |
| 21615 | 21615 | if ((err = type_resolve(ira->codegen, target_type, ResolveStatusZeroBitsKnown))) |
| 21616 | 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 | 21618 | TypeEnumField *only_field = &target_type->data.enumeration.fields[0]; |
| 21619 | 21619 | IrInstruction *result = ir_const(ira, &switch_target_instruction->base, target_type); |
| 21620 | 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 | 22351 | |
| 22352 | 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 | 22363 | if (instr_is_comptime(target)) { |
| 22355 | 22364 | if ((err = type_resolve(ira->codegen, target->value->type, ResolveStatusZeroBitsKnown))) |
| 22356 | 22365 | return ira->codegen->invalid_instruction; |
test/stage1/behavior/enum.zig+20| ... | ... | @@ -65,6 +65,26 @@ test "non-exhaustive enum" { |
| 65 | 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 | 88 | test "enum type" { |
| 69 | 89 | const foo1 = Foo{ .One = 13 }; |
| 70 | 90 | const foo2 = Foo{ |
test/stage1/behavior/union.zig+9| ... | ... | @@ -629,3 +629,12 @@ test "union initializer generates padding only if needed" { |
| 629 | 629 | var v = U{ .A = 532 }; |
| 630 | 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 | } |