| 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 | 1399 | enum_type->data.enumeration.is_invalid = true; |
| 1400 | 1400 | add_node_error(g, decl_node->data.container_decl.init_arg_expr, |
| 1401 | 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 | 1406 | } else if (wanted_tag_int_type->data.integral.bit_count < tag_int_type->data.integral.bit_count) { |
| 1403 | 1407 | enum_type->data.enumeration.is_invalid = true; |
| 1404 | 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 | 8911 | wanted_type->id == TypeTableEntryIdEnum && |
| 8912 | 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 | 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 | 8929 | actual_type->id == TypeTableEntryIdEnum && |
| 8920 | 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 | 8945 | // explicit cast from undefined to anything |
test/cases/enum.zig+11-3| ... | ... | @@ -89,8 +89,8 @@ test "enum to int" { |
| 89 | 89 | shouldEqual(Number.Four, 4); |
| 90 | 90 | } |
| 91 | 91 | |
| 92 | fn shouldEqual(n: Number, expected: usize) { | |
| 93 | assert(usize(n) == expected); | |
| 92 | fn shouldEqual(n: Number, expected: u3) { | |
| 93 | assert(u3(n) == expected); | |
| 94 | 94 | } |
| 95 | 95 | |
| 96 | 96 | |
| ... | ... | @@ -98,7 +98,7 @@ test "int to enum" { |
| 98 | 98 | testIntToEnumEval(3); |
| 99 | 99 | } |
| 100 | 100 | fn testIntToEnumEval(x: i32) { |
| 101 | assert(IntToEnumNumber(x) == IntToEnumNumber.Three); | |
| 101 | assert(IntToEnumNumber(u3(x)) == IntToEnumNumber.Three); | |
| 102 | 102 | } |
| 103 | 103 | const IntToEnumNumber = enum { |
| 104 | 104 | Zero, |
| ... | ... | @@ -284,3 +284,11 @@ fn getC(data: &const BitFieldOfEnums) -> C { |
| 284 | 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 | 2390 | \\} |
| 2391 | 2391 | , |
| 2392 | 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 | } |