authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-12-05 18:09:22-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-12-05 18:09:22-05:00
log63a2f9a8b2251ffdc37d5f28dfbd3f6be1bd7908
tree799f7a95b9cda222a9242aaa5d866c38ace5effc
parent74cea89fce2af41d2af7379ff526d7046c4d8d77

fix casting integer literal to enum


3 files changed, 36 insertions(+), 7 deletions(-)

src/ir.cpp+19-7
...@@ -8436,14 +8436,16 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour...@@ -8436,14 +8436,16 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour
8436 ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);8436 ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);
8437 if (!val)8437 if (!val)
8438 return ira->codegen->invalid_instruction;8438 return ira->codegen->invalid_instruction;
8439 BigInt enum_member_count;8439
8440 bigint_init_unsigned(&enum_member_count, wanted_type->data.enumeration.src_field_count);8440 TypeEnumField *field = find_enum_field_by_tag(wanted_type, &val->data.x_bigint);
8441 if (bigint_cmp(&val->data.x_bigint, &enum_member_count) != CmpLT) {8441 if (field == nullptr) {
8442 Buf *val_buf = buf_alloc();8442 Buf *val_buf = buf_alloc();
8443 bigint_append_buf(val_buf, &val->data.x_bigint, 10);8443 bigint_append_buf(val_buf, &val->data.x_bigint, 10);
8444 ir_add_error(ira, source_instr,8444 ErrorMsg *msg = ir_add_error(ira, source_instr,
8445 buf_sprintf("integer value %s too big for enum '%s' which has %" PRIu32 " fields",8445 buf_sprintf("enum '%s' has no tag matching integer value %s",
8446 buf_ptr(val_buf), buf_ptr(&wanted_type->name), wanted_type->data.enumeration.src_field_count));8446 buf_ptr(&wanted_type->name), buf_ptr(val_buf)));
8447 add_error_note(ira->codegen, msg, wanted_type->data.enumeration.decl_node,
8448 buf_sprintf("'%s' declared here", buf_ptr(&wanted_type->name)));
8447 return ira->codegen->invalid_instruction;8449 return ira->codegen->invalid_instruction;
8448 }8450 }
84498451
...@@ -8827,7 +8829,17 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -8827,7 +8829,17 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
8827 if (actual_type->id == TypeTableEntryIdNumLitFloat ||8829 if (actual_type->id == TypeTableEntryIdNumLitFloat ||
8828 actual_type->id == TypeTableEntryIdNumLitInt)8830 actual_type->id == TypeTableEntryIdNumLitInt)
8829 {8831 {
8830 if (wanted_type->id == TypeTableEntryIdPointer &&8832 if (wanted_type->id == TypeTableEntryIdEnum) {
8833 IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.enumeration.tag_int_type, value);
8834 if (type_is_invalid(cast1->value.type))
8835 return ira->codegen->invalid_instruction;
8836
8837 IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1);
8838 if (type_is_invalid(cast2->value.type))
8839 return ira->codegen->invalid_instruction;
8840
8841 return cast2;
8842 } else if (wanted_type->id == TypeTableEntryIdPointer &&
8831 wanted_type->data.pointer.is_const)8843 wanted_type->data.pointer.is_const)
8832 {8844 {
8833 IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.pointer.child_type, value);8845 IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.pointer.child_type, value);
test/cases/enum.zig+5
...@@ -344,3 +344,8 @@ fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) {...@@ -344,3 +344,8 @@ fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) {
344 MultipleChoice2.Unspecified5 => 9,344 MultipleChoice2.Unspecified5 => 9,
345 });345 });
346}346}
347
348test "cast integer literal to enum" {
349 assert(MultipleChoice2(0) == MultipleChoice2.Unspecified1);
350 assert(MultipleChoice2(40) == MultipleChoice2.B);
351}
test/compile_errors.zig+12
...@@ -2684,4 +2684,16 @@ pub fn addCases(cases: &tests.CompileErrorContext) {...@@ -2684,4 +2684,16 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
2684 ,2684 ,
2685 ".tmp_source.zig:11:13: error: switch on union which has no attached enum",2685 ".tmp_source.zig:11:13: error: switch on union which has no attached enum",
2686 ".tmp_source.zig:1:17: note: consider 'union(enum)' here");2686 ".tmp_source.zig:1:17: note: consider 'union(enum)' here");
2687
2688 cases.add("enum in field count range but not matching tag",
2689 \\const Foo = enum(u32) {
2690 \\ A = 10,
2691 \\ B = 11,
2692 \\};
2693 \\export fn entry() {
2694 \\ var x = Foo(0);
2695 \\}
2696 ,
2697 ".tmp_source.zig:6:16: error: enum 'Foo' has no tag matching integer value 0",
2698 ".tmp_source.zig:1:13: note: 'Foo' declared here");
2687}2699}