| author | |
| committer | |
| log | 6e6d138c2f50f95fe9c6b4acbc16ffa17475a4a5 |
| tree | f89b50b2a9f57c9149b555240e2e9a2fc760c6b8 |
| parent | 651dc31247c2f637925ed6a6e92c8bc1a19efd5c |
5 files changed, 44 insertions(+), 1 deletions(-)
src/all_types.hpp+1| ... | ... | @@ -404,6 +404,7 @@ enum CastOp { |
| 404 | 404 | CastOpBoolToInt, |
| 405 | 405 | CastOpResizeSlice, |
| 406 | 406 | CastOpIntToEnum, |
| 407 | CastOpEnumToInt, | |
| 407 | 408 | CastOpBytesToSlice, |
| 408 | 409 | }; |
| 409 | 410 |
src/analyze.cpp+14-1| ... | ... | @@ -2641,7 +2641,12 @@ static TypeTableEntry *analyze_container_init_expr(CodeGen *g, ImportTableEntry |
| 2641 | 2641 | codegen->type_entry = fixed_size_array_type; |
| 2642 | 2642 | codegen->source_node = node; |
| 2643 | 2643 | if (!const_val->ok) { |
| 2644 | context->fn_entry->struct_val_expr_alloca_list.append(codegen); | |
| 2644 | if (!context->fn_entry) { | |
| 2645 | add_node_error(g, node, | |
| 2646 | buf_sprintf("unable to evaluate constant expression")); | |
| 2647 | } else { | |
| 2648 | context->fn_entry->struct_val_expr_alloca_list.append(codegen); | |
| 2649 | } | |
| 2645 | 2650 | } |
| 2646 | 2651 | |
| 2647 | 2652 | return fixed_size_array_type; |
| ... | ... | @@ -4601,6 +4606,14 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B |
| 4601 | 4606 | return resolve_cast(g, context, node, expr_node, wanted_type, CastOpIntToEnum, false); |
| 4602 | 4607 | } |
| 4603 | 4608 | |
| 4609 | // explicit cast from enum type with no payload to integer | |
| 4610 | if (wanted_type->id == TypeTableEntryIdInt && | |
| 4611 | actual_type->id == TypeTableEntryIdEnum && | |
| 4612 | actual_type->data.enumeration.gen_field_count == 0) | |
| 4613 | { | |
| 4614 | return resolve_cast(g, context, node, expr_node, wanted_type, CastOpEnumToInt, false); | |
| 4615 | } | |
| 4616 | ||
| 4604 | 4617 | add_node_error(g, node, |
| 4605 | 4618 | buf_sprintf("invalid cast from type '%s' to '%s'", |
| 4606 | 4619 | buf_ptr(&actual_type->name), |
src/codegen.cpp+2| ... | ... | @@ -1062,6 +1062,8 @@ static LLVMValueRef gen_cast_expr(CodeGen *g, AstNode *node) { |
| 1062 | 1062 | |
| 1063 | 1063 | case CastOpIntToEnum: |
| 1064 | 1064 | return gen_widen_or_shorten(g, node, actual_type, wanted_type->data.enumeration.tag_type, expr_val); |
| 1065 | case CastOpEnumToInt: | |
| 1066 | return gen_widen_or_shorten(g, node, actual_type->data.enumeration.tag_type, wanted_type, expr_val); | |
| 1065 | 1067 | } |
| 1066 | 1068 | zig_unreachable(); |
| 1067 | 1069 | } |
src/eval.cpp+3| ... | ... | @@ -694,6 +694,9 @@ void eval_const_expr_implicit_cast(CastOp cast_op, |
| 694 | 694 | const_val->ok = true; |
| 695 | 695 | break; |
| 696 | 696 | } |
| 697 | case CastOpEnumToInt: | |
| 698 | bignum_init_unsigned(&const_val->data.x_bignum, other_val->data.x_enum.tag); | |
| 699 | const_val->ok = true; | |
| 697 | 700 | } |
| 698 | 701 | } |
| 699 | 702 |
test/cases/enum_to_int.zig created+24| ... | ... | @@ -0,0 +1,24 @@ |
| 1 | const assert = @import("std").debug.assert; | |
| 2 | ||
| 3 | enum Number { | |
| 4 | Zero, | |
| 5 | One, | |
| 6 | Two, | |
| 7 | Three, | |
| 8 | Four, | |
| 9 | } | |
| 10 | ||
| 11 | #attribute("test") | |
| 12 | fn enumToInt() { | |
| 13 | shouldEqual(Number.Zero, 0); | |
| 14 | shouldEqual(Number.One, 1); | |
| 15 | shouldEqual(Number.Two, 2); | |
| 16 | shouldEqual(Number.Three, 3); | |
| 17 | shouldEqual(Number.Four, 4); | |
| 18 | } | |
| 19 | ||
| 20 | // TODO add test with this disabled | |
| 21 | #static_eval_enable(false) | |
| 22 | fn shouldEqual(n: Number, expected: usize) { | |
| 23 | assert(usize(n) == expected); | |
| 24 | } |