| author | |
| committer | |
| log | 98237f7c0ba62099e85a8caf8fc09039845b224e |
| tree | 4f0ecbc220a178747c330d457cc1388100bbed43 |
| parent | 54a0db0daf8fd5ef307f275275e10f32ebd7d27a |
See #3054 files changed, 94 insertions(+), 5 deletions(-)
src/analyze.cpp+4| ... | @@ -1399,6 +1399,10 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) { | ... | @@ -1399,6 +1399,10 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) { |
| 1399 | enum_type->data.enumeration.is_invalid = true; | 1399 | enum_type->data.enumeration.is_invalid = true; |
| 1400 | add_node_error(g, decl_node->data.container_decl.init_arg_expr, | 1400 | add_node_error(g, decl_node->data.container_decl.init_arg_expr, |
| 1401 | buf_sprintf("expected integer, found '%s'", buf_ptr(&wanted_tag_int_type->name))); | 1401 | buf_sprintf("expected integer, found '%s'", buf_ptr(&wanted_tag_int_type->name))); |
| 1402 | } else if (wanted_tag_int_type->data.integral.is_signed) { | ||
| 1403 | enum_type->data.enumeration.is_invalid = true; | ||
| 1404 | add_node_error(g, decl_node->data.container_decl.init_arg_expr, | ||
| 1405 | buf_sprintf("expected unsigned integer, found '%s'", buf_ptr(&wanted_tag_int_type->name))); | ||
| 1402 | } else if (wanted_tag_int_type->data.integral.bit_count < tag_int_type->data.integral.bit_count) { | 1406 | } else if (wanted_tag_int_type->data.integral.bit_count < tag_int_type->data.integral.bit_count) { |
| 1403 | enum_type->data.enumeration.is_invalid = true; | 1407 | enum_type->data.enumeration.is_invalid = true; |
| 1404 | add_node_error(g, decl_node->data.container_decl.init_arg_expr, | 1408 | add_node_error(g, decl_node->data.container_decl.init_arg_expr, |
src/ir.cpp+22-2| ... | @@ -8911,7 +8911,17 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -8911,7 +8911,17 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 8911 | wanted_type->id == TypeTableEntryIdEnum && | 8911 | wanted_type->id == TypeTableEntryIdEnum && |
| 8912 | wanted_type->data.enumeration.gen_field_count == 0) | 8912 | wanted_type->data.enumeration.gen_field_count == 0) |
| 8913 | { | 8913 | { |
| 8914 | return ir_analyze_int_to_enum(ira, source_instr, value, wanted_type); | 8914 | ensure_complete_type(ira->codegen, wanted_type); |
| 8915 | if (type_is_invalid(wanted_type)) | ||
| 8916 | return ira->codegen->invalid_instruction; | ||
| 8917 | if (actual_type == wanted_type->data.enumeration.tag_type->data.enum_tag.int_type) { | ||
| 8918 | return ir_analyze_int_to_enum(ira, source_instr, value, wanted_type); | ||
| 8919 | } | ||
| 8920 | ir_add_error(ira, source_instr, | ||
| 8921 | buf_sprintf("integer to enum cast from '%s' instead of its tag type, '%s'", | ||
| 8922 | buf_ptr(&actual_type->name), | ||
| 8923 | buf_ptr(&wanted_type->data.enumeration.tag_type->data.enum_tag.int_type->name))); | ||
| 8924 | return ira->codegen->invalid_instruction; | ||
| 8915 | } | 8925 | } |
| 8916 | 8926 | ||
| 8917 | // explicit cast from enum type with no payload to integer | 8927 | // explicit cast from enum type with no payload to integer |
| ... | @@ -8919,7 +8929,17 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -8919,7 +8929,17 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 8919 | actual_type->id == TypeTableEntryIdEnum && | 8929 | actual_type->id == TypeTableEntryIdEnum && |
| 8920 | actual_type->data.enumeration.gen_field_count == 0) | 8930 | actual_type->data.enumeration.gen_field_count == 0) |
| 8921 | { | 8931 | { |
| 8922 | return ir_analyze_enum_to_int(ira, source_instr, value, wanted_type); | 8932 | ensure_complete_type(ira->codegen, actual_type); |
| 8933 | if (type_is_invalid(actual_type)) | ||
| 8934 | return ira->codegen->invalid_instruction; | ||
| 8935 | if (wanted_type == actual_type->data.enumeration.tag_type->data.enum_tag.int_type) { | ||
| 8936 | return ir_analyze_enum_to_int(ira, source_instr, value, wanted_type); | ||
| 8937 | } | ||
| 8938 | ir_add_error(ira, source_instr, | ||
| 8939 | buf_sprintf("enum to integer cast to '%s' instead of its tag type, '%s'", | ||
| 8940 | buf_ptr(&wanted_type->name), | ||
| 8941 | buf_ptr(&actual_type->data.enumeration.tag_type->data.enum_tag.int_type->name))); | ||
| 8942 | return ira->codegen->invalid_instruction; | ||
| 8923 | } | 8943 | } |
| 8924 | 8944 | ||
| 8925 | // explicit cast from undefined to anything | 8945 | // explicit cast from undefined to anything |
test/cases/enum.zig+11-3| ... | @@ -89,8 +89,8 @@ test "enum to int" { | ... | @@ -89,8 +89,8 @@ test "enum to int" { |
| 89 | shouldEqual(Number.Four, 4); | 89 | shouldEqual(Number.Four, 4); |
| 90 | } | 90 | } |
| 91 | 91 | ||
| 92 | fn shouldEqual(n: Number, expected: usize) { | 92 | fn shouldEqual(n: Number, expected: u3) { |
| 93 | assert(usize(n) == expected); | 93 | assert(u3(n) == expected); |
| 94 | } | 94 | } |
| 95 | 95 | ||
| 96 | 96 | ||
| ... | @@ -98,7 +98,7 @@ test "int to enum" { | ... | @@ -98,7 +98,7 @@ test "int to enum" { |
| 98 | testIntToEnumEval(3); | 98 | testIntToEnumEval(3); |
| 99 | } | 99 | } |
| 100 | fn testIntToEnumEval(x: i32) { | 100 | fn testIntToEnumEval(x: i32) { |
| 101 | assert(IntToEnumNumber(x) == IntToEnumNumber.Three); | 101 | assert(IntToEnumNumber(u3(x)) == IntToEnumNumber.Three); |
| 102 | } | 102 | } |
| 103 | const IntToEnumNumber = enum { | 103 | const IntToEnumNumber = enum { |
| 104 | Zero, | 104 | Zero, |
| ... | @@ -284,3 +284,11 @@ fn getC(data: &const BitFieldOfEnums) -> C { | ... | @@ -284,3 +284,11 @@ fn getC(data: &const BitFieldOfEnums) -> C { |
| 284 | return data.c; | 284 | return data.c; |
| 285 | } | 285 | } |
| 286 | 286 | ||
| 287 | test "casting enum to its tag type" { | ||
| 288 | testCastEnumToTagType(Small2.Two); | ||
| 289 | comptime testCastEnumToTagType(Small2.Two); | ||
| 290 | } | ||
| 291 | |||
| 292 | fn testCastEnumToTagType(value: Small2) { | ||
| 293 | assert(u2(value) == 1); | ||
| 294 | } |
test/compile_errors.zig+57| ... | @@ -2390,4 +2390,61 @@ pub fn addCases(cases: &tests.CompileErrorContext) { | ... | @@ -2390,4 +2390,61 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2390 | \\} | 2390 | \\} |
| 2391 | , | 2391 | , |
| 2392 | ".tmp_source.zig:1:20: error: expected integer, found 'f32'"); | 2392 | ".tmp_source.zig:1:20: error: expected integer, found 'f32'"); |
| 2393 | |||
| 2394 | cases.add("implicitly casting enum to tag type", | ||
| 2395 | \\const Small = enum(u2) { | ||
| 2396 | \\ One, | ||
| 2397 | \\ Two, | ||
| 2398 | \\ Three, | ||
| 2399 | \\ Four, | ||
| 2400 | \\}; | ||
| 2401 | \\ | ||
| 2402 | \\export fn entry() { | ||
| 2403 | \\ var x: u2 = Small.Two; | ||
| 2404 | \\} | ||
| 2405 | , | ||
| 2406 | ".tmp_source.zig:9:22: error: expected type 'u2', found 'Small'"); | ||
| 2407 | |||
| 2408 | cases.add("explicitly casting enum to non tag type", | ||
| 2409 | \\const Small = enum(u2) { | ||
| 2410 | \\ One, | ||
| 2411 | \\ Two, | ||
| 2412 | \\ Three, | ||
| 2413 | \\ Four, | ||
| 2414 | \\}; | ||
| 2415 | \\ | ||
| 2416 | \\export fn entry() { | ||
| 2417 | \\ var x = u3(Small.Two); | ||
| 2418 | \\} | ||
| 2419 | , | ||
| 2420 | ".tmp_source.zig:9:15: error: enum to integer cast to 'u3' instead of its tag type, 'u2'"); | ||
| 2421 | |||
| 2422 | cases.add("explicitly casting non tag type to enum", | ||
| 2423 | \\const Small = enum(u2) { | ||
| 2424 | \\ One, | ||
| 2425 | \\ Two, | ||
| 2426 | \\ Three, | ||
| 2427 | \\ Four, | ||
| 2428 | \\}; | ||
| 2429 | \\ | ||
| 2430 | \\export fn entry() { | ||
| 2431 | \\ var y = u3(3); | ||
| 2432 | \\ var x = Small(y); | ||
| 2433 | \\} | ||
| 2434 | , | ||
| 2435 | ".tmp_source.zig:10:18: error: integer to enum cast from 'u3' instead of its tag type, 'u2'"); | ||
| 2436 | |||
| 2437 | cases.add("non unsigned integer enum tag type", | ||
| 2438 | \\const Small = enum(i2) { | ||
| 2439 | \\ One, | ||
| 2440 | \\ Two, | ||
| 2441 | \\ Three, | ||
| 2442 | \\ Four, | ||
| 2443 | \\}; | ||
| 2444 | \\ | ||
| 2445 | \\export fn entry() { | ||
| 2446 | \\ var y = Small.Two; | ||
| 2447 | \\} | ||
| 2448 | , | ||
| 2449 | ".tmp_source.zig:1:19: error: expected unsigned integer, found 'i2'"); | ||
| 2393 | } | 2450 | } |