Skip to content

Commit 63a2f9a

Browse files
committedDec 5, 2017
fix casting integer literal to enum
1 parent 74cea89 commit 63a2f9a

File tree

3 files changed

+36
-7
lines changed

3 files changed

+36
-7
lines changed
 

‎src/ir.cpp‎

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8436,14 +8436,16 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour
84368436
ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);
84378437
if (!val)
84388438
return ira->codegen->invalid_instruction;
8439-
BigInt enum_member_count;
8440-
bigint_init_unsigned(&enum_member_count, wanted_type->data.enumeration.src_field_count);
8441-
if (bigint_cmp(&val->data.x_bigint, &enum_member_count) != CmpLT) {
8439+
8440+
TypeEnumField *field = find_enum_field_by_tag(wanted_type, &val->data.x_bigint);
8441+
if (field == nullptr) {
84428442
Buf *val_buf = buf_alloc();
84438443
bigint_append_buf(val_buf, &val->data.x_bigint, 10);
8444-
ir_add_error(ira, source_instr,
8445-
buf_sprintf("integer value %s too big for enum '%s' which has %" PRIu32 " fields",
8446-
buf_ptr(val_buf), buf_ptr(&wanted_type->name), wanted_type->data.enumeration.src_field_count));
8444+
ErrorMsg *msg = ir_add_error(ira, source_instr,
8445+
buf_sprintf("enum '%s' has no tag matching integer value %s",
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)));
84478449
return ira->codegen->invalid_instruction;
84488450
}
84498451

@@ -8827,7 +8829,17 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
88278829
if (actual_type->id == TypeTableEntryIdNumLitFloat ||
88288830
actual_type->id == TypeTableEntryIdNumLitInt)
88298831
{
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 &&
88318843
wanted_type->data.pointer.is_const)
88328844
{
88338845
IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.pointer.child_type, value);

‎test/cases/enum.zig‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,3 +344,8 @@ fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) {
344344
MultipleChoice2.Unspecified5 => 9,
345345
});
346346
}
347+
348+
test "cast integer literal to enum" {
349+
assert(MultipleChoice2(0) == MultipleChoice2.Unspecified1);
350+
assert(MultipleChoice2(40) == MultipleChoice2.B);
351+
}

‎test/compile_errors.zig‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2684,4 +2684,16 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
26842684
,
26852685
".tmp_source.zig:11:13: error: switch on union which has no attached enum",
26862686
".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");
26872699
}

0 commit comments

Comments
 (0)