authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-01-18 19:25:23-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-01-18 19:25:23-05:00
log7bb4c855ad3776d7f7d21f2bf1c5c93366205ff2
tree1695efe0e849848743d3c152f4349b054a7bf96e
parent405b8e9eeefda07b16044690471cfd57fc654c75
parentb0f753e21d6fcaafd0b35dc02fdfe23b14e310d6
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #4222 from LemonBoy/eutwouwth

Prevent crash with empty non-exhaustive enum

4 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
83128312
83138313 uint32_t field_count = enum_type->data.enumeration.src_field_count;
83148314
8315 assert(enum_type->data.enumeration.fields);
8315 assert(field_count == 0 || enum_type->data.enumeration.fields != nullptr);
83168316 ZigLLVMDIEnumerator **di_enumerators = allocate<ZigLLVMDIEnumerator*>(field_count);
83178317
83188318 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,
2161421614 case ZigTypeIdEnum: {
2161521615 if ((err = type_resolve(ira->codegen, target_type, ResolveStatusZeroBitsKnown)))
2161621616 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) {
2161821618 TypeEnumField *only_field = &target_type->data.enumeration.fields[0];
2161921619 IrInstruction *result = ir_const(ira, &switch_target_instruction->base, target_type);
2162021620 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
2235122351
2235222352 assert(target->value->type->id == ZigTypeIdEnum);
2235322353
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
2235422363 if (instr_is_comptime(target)) {
2235522364 if ((err = type_resolve(ira->codegen, target->value->type, ResolveStatusZeroBitsKnown)))
2235622365 return ira->codegen->invalid_instruction;
test/stage1/behavior/enum.zig+20
......@@ -65,6 +65,26 @@ test "non-exhaustive enum" {
6565 comptime S.doTheTest(52);
6666}
6767
68test "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
6888test "enum type" {
6989 const foo1 = Foo{ .One = 13 };
7090 const foo2 = Foo{
test/stage1/behavior/union.zig+9
......@@ -629,3 +629,12 @@ test "union initializer generates padding only if needed" {
629629 var v = U{ .A = 532 };
630630 expect(v.A == 532);
631631}
632
633test "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}