mirror of
https://github.com/ziglang/zig.git
synced 2026-02-14 21:38:33 +00:00
parent
54a0db0daf
commit
98237f7c0b
@ -1399,6 +1399,10 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) {
|
||||
enum_type->data.enumeration.is_invalid = true;
|
||||
add_node_error(g, decl_node->data.container_decl.init_arg_expr,
|
||||
buf_sprintf("expected integer, found '%s'", buf_ptr(&wanted_tag_int_type->name)));
|
||||
} else if (wanted_tag_int_type->data.integral.is_signed) {
|
||||
enum_type->data.enumeration.is_invalid = true;
|
||||
add_node_error(g, decl_node->data.container_decl.init_arg_expr,
|
||||
buf_sprintf("expected unsigned integer, found '%s'", buf_ptr(&wanted_tag_int_type->name)));
|
||||
} else if (wanted_tag_int_type->data.integral.bit_count < tag_int_type->data.integral.bit_count) {
|
||||
enum_type->data.enumeration.is_invalid = true;
|
||||
add_node_error(g, decl_node->data.container_decl.init_arg_expr,
|
||||
|
||||
24
src/ir.cpp
24
src/ir.cpp
@ -8911,7 +8911,17 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
|
||||
wanted_type->id == TypeTableEntryIdEnum &&
|
||||
wanted_type->data.enumeration.gen_field_count == 0)
|
||||
{
|
||||
return ir_analyze_int_to_enum(ira, source_instr, value, wanted_type);
|
||||
ensure_complete_type(ira->codegen, wanted_type);
|
||||
if (type_is_invalid(wanted_type))
|
||||
return ira->codegen->invalid_instruction;
|
||||
if (actual_type == wanted_type->data.enumeration.tag_type->data.enum_tag.int_type) {
|
||||
return ir_analyze_int_to_enum(ira, source_instr, value, wanted_type);
|
||||
}
|
||||
ir_add_error(ira, source_instr,
|
||||
buf_sprintf("integer to enum cast from '%s' instead of its tag type, '%s'",
|
||||
buf_ptr(&actual_type->name),
|
||||
buf_ptr(&wanted_type->data.enumeration.tag_type->data.enum_tag.int_type->name)));
|
||||
return ira->codegen->invalid_instruction;
|
||||
}
|
||||
|
||||
// explicit cast from enum type with no payload to integer
|
||||
@ -8919,7 +8929,17 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
|
||||
actual_type->id == TypeTableEntryIdEnum &&
|
||||
actual_type->data.enumeration.gen_field_count == 0)
|
||||
{
|
||||
return ir_analyze_enum_to_int(ira, source_instr, value, wanted_type);
|
||||
ensure_complete_type(ira->codegen, actual_type);
|
||||
if (type_is_invalid(actual_type))
|
||||
return ira->codegen->invalid_instruction;
|
||||
if (wanted_type == actual_type->data.enumeration.tag_type->data.enum_tag.int_type) {
|
||||
return ir_analyze_enum_to_int(ira, source_instr, value, wanted_type);
|
||||
}
|
||||
ir_add_error(ira, source_instr,
|
||||
buf_sprintf("enum to integer cast to '%s' instead of its tag type, '%s'",
|
||||
buf_ptr(&wanted_type->name),
|
||||
buf_ptr(&actual_type->data.enumeration.tag_type->data.enum_tag.int_type->name)));
|
||||
return ira->codegen->invalid_instruction;
|
||||
}
|
||||
|
||||
// explicit cast from undefined to anything
|
||||
|
||||
@ -89,8 +89,8 @@ test "enum to int" {
|
||||
shouldEqual(Number.Four, 4);
|
||||
}
|
||||
|
||||
fn shouldEqual(n: Number, expected: usize) {
|
||||
assert(usize(n) == expected);
|
||||
fn shouldEqual(n: Number, expected: u3) {
|
||||
assert(u3(n) == expected);
|
||||
}
|
||||
|
||||
|
||||
@ -98,7 +98,7 @@ test "int to enum" {
|
||||
testIntToEnumEval(3);
|
||||
}
|
||||
fn testIntToEnumEval(x: i32) {
|
||||
assert(IntToEnumNumber(x) == IntToEnumNumber.Three);
|
||||
assert(IntToEnumNumber(u3(x)) == IntToEnumNumber.Three);
|
||||
}
|
||||
const IntToEnumNumber = enum {
|
||||
Zero,
|
||||
@ -284,3 +284,11 @@ fn getC(data: &const BitFieldOfEnums) -> C {
|
||||
return data.c;
|
||||
}
|
||||
|
||||
test "casting enum to its tag type" {
|
||||
testCastEnumToTagType(Small2.Two);
|
||||
comptime testCastEnumToTagType(Small2.Two);
|
||||
}
|
||||
|
||||
fn testCastEnumToTagType(value: Small2) {
|
||||
assert(u2(value) == 1);
|
||||
}
|
||||
|
||||
@ -2390,4 +2390,61 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:1:20: error: expected integer, found 'f32'");
|
||||
|
||||
cases.add("implicitly casting enum to tag type",
|
||||
\\const Small = enum(u2) {
|
||||
\\ One,
|
||||
\\ Two,
|
||||
\\ Three,
|
||||
\\ Four,
|
||||
\\};
|
||||
\\
|
||||
\\export fn entry() {
|
||||
\\ var x: u2 = Small.Two;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:9:22: error: expected type 'u2', found 'Small'");
|
||||
|
||||
cases.add("explicitly casting enum to non tag type",
|
||||
\\const Small = enum(u2) {
|
||||
\\ One,
|
||||
\\ Two,
|
||||
\\ Three,
|
||||
\\ Four,
|
||||
\\};
|
||||
\\
|
||||
\\export fn entry() {
|
||||
\\ var x = u3(Small.Two);
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:9:15: error: enum to integer cast to 'u3' instead of its tag type, 'u2'");
|
||||
|
||||
cases.add("explicitly casting non tag type to enum",
|
||||
\\const Small = enum(u2) {
|
||||
\\ One,
|
||||
\\ Two,
|
||||
\\ Three,
|
||||
\\ Four,
|
||||
\\};
|
||||
\\
|
||||
\\export fn entry() {
|
||||
\\ var y = u3(3);
|
||||
\\ var x = Small(y);
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:10:18: error: integer to enum cast from 'u3' instead of its tag type, 'u2'");
|
||||
|
||||
cases.add("non unsigned integer enum tag type",
|
||||
\\const Small = enum(i2) {
|
||||
\\ One,
|
||||
\\ Two,
|
||||
\\ Three,
|
||||
\\ Four,
|
||||
\\};
|
||||
\\
|
||||
\\export fn entry() {
|
||||
\\ var y = Small.Two;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:1:19: error: expected unsigned integer, found 'i2'");
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user