fix casting integer literal to enum
parent
74cea89fce
commit
63a2f9a8b2
26
src/ir.cpp
26
src/ir.cpp
|
@ -8436,14 +8436,16 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour
|
||||||
ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);
|
ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);
|
||||||
if (!val)
|
if (!val)
|
||||||
return ira->codegen->invalid_instruction;
|
return ira->codegen->invalid_instruction;
|
||||||
BigInt enum_member_count;
|
|
||||||
bigint_init_unsigned(&enum_member_count, wanted_type->data.enumeration.src_field_count);
|
TypeEnumField *field = find_enum_field_by_tag(wanted_type, &val->data.x_bigint);
|
||||||
if (bigint_cmp(&val->data.x_bigint, &enum_member_count) != CmpLT) {
|
if (field == nullptr) {
|
||||||
Buf *val_buf = buf_alloc();
|
Buf *val_buf = buf_alloc();
|
||||||
bigint_append_buf(val_buf, &val->data.x_bigint, 10);
|
bigint_append_buf(val_buf, &val->data.x_bigint, 10);
|
||||||
ir_add_error(ira, source_instr,
|
ErrorMsg *msg = ir_add_error(ira, source_instr,
|
||||||
buf_sprintf("integer value %s too big for enum '%s' which has %" PRIu32 " fields",
|
buf_sprintf("enum '%s' has no tag matching integer value %s",
|
||||||
buf_ptr(val_buf), buf_ptr(&wanted_type->name), wanted_type->data.enumeration.src_field_count));
|
buf_ptr(&wanted_type->name), buf_ptr(val_buf)));
|
||||||
|
add_error_note(ira->codegen, msg, wanted_type->data.enumeration.decl_node,
|
||||||
|
buf_sprintf("'%s' declared here", buf_ptr(&wanted_type->name)));
|
||||||
return ira->codegen->invalid_instruction;
|
return ira->codegen->invalid_instruction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8827,7 +8829,17 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
|
||||||
if (actual_type->id == TypeTableEntryIdNumLitFloat ||
|
if (actual_type->id == TypeTableEntryIdNumLitFloat ||
|
||||||
actual_type->id == TypeTableEntryIdNumLitInt)
|
actual_type->id == TypeTableEntryIdNumLitInt)
|
||||||
{
|
{
|
||||||
if (wanted_type->id == TypeTableEntryIdPointer &&
|
if (wanted_type->id == TypeTableEntryIdEnum) {
|
||||||
|
IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.enumeration.tag_int_type, value);
|
||||||
|
if (type_is_invalid(cast1->value.type))
|
||||||
|
return ira->codegen->invalid_instruction;
|
||||||
|
|
||||||
|
IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1);
|
||||||
|
if (type_is_invalid(cast2->value.type))
|
||||||
|
return ira->codegen->invalid_instruction;
|
||||||
|
|
||||||
|
return cast2;
|
||||||
|
} else if (wanted_type->id == TypeTableEntryIdPointer &&
|
||||||
wanted_type->data.pointer.is_const)
|
wanted_type->data.pointer.is_const)
|
||||||
{
|
{
|
||||||
IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.pointer.child_type, value);
|
IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.pointer.child_type, value);
|
||||||
|
|
|
@ -344,3 +344,8 @@ fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) {
|
||||||
MultipleChoice2.Unspecified5 => 9,
|
MultipleChoice2.Unspecified5 => 9,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "cast integer literal to enum" {
|
||||||
|
assert(MultipleChoice2(0) == MultipleChoice2.Unspecified1);
|
||||||
|
assert(MultipleChoice2(40) == MultipleChoice2.B);
|
||||||
|
}
|
||||||
|
|
|
@ -2684,4 +2684,16 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
|
||||||
,
|
,
|
||||||
".tmp_source.zig:11:13: error: switch on union which has no attached enum",
|
".tmp_source.zig:11:13: error: switch on union which has no attached enum",
|
||||||
".tmp_source.zig:1:17: note: consider 'union(enum)' here");
|
".tmp_source.zig:1:17: note: consider 'union(enum)' here");
|
||||||
|
|
||||||
|
cases.add("enum in field count range but not matching tag",
|
||||||
|
\\const Foo = enum(u32) {
|
||||||
|
\\ A = 10,
|
||||||
|
\\ B = 11,
|
||||||
|
\\};
|
||||||
|
\\export fn entry() {
|
||||||
|
\\ var x = Foo(0);
|
||||||
|
\\}
|
||||||
|
,
|
||||||
|
".tmp_source.zig:6:16: error: enum 'Foo' has no tag matching integer value 0",
|
||||||
|
".tmp_source.zig:1:13: note: 'Foo' declared here");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue