| author | |
| committer | |
| log | fdadab40c61a6f70a65472cc95ccd5ba52c01772 |
| tree | f471173c1e54a3cd4e35759970adfcd36c991c0b |
| parent | 3a9009b08e278dafd7b59b7d09408c80ea67f1fe |
4 files changed, 41 insertions(+), 3 deletions(-)
src/all_types.hpp+1| ... | @@ -859,6 +859,7 @@ struct TypeTableEntryEnum { | ... | @@ -859,6 +859,7 @@ struct TypeTableEntryEnum { |
| 859 | TypeEnumField *fields; | 859 | TypeEnumField *fields; |
| 860 | bool is_invalid; // true if any fields are invalid | 860 | bool is_invalid; // true if any fields are invalid |
| 861 | TypeTableEntry *tag_type; | 861 | TypeTableEntry *tag_type; |
| 862 | TypeTableEntry *union_type; | ||
| 862 | 863 | ||
| 863 | // reminder: hash tables must be initialized before use | 864 | // reminder: hash tables must be initialized before use |
| 864 | HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table; | 865 | HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table; |
src/analyze.cpp+4| ... | @@ -973,6 +973,7 @@ static void resolve_enum_type(CodeGen *g, ImportTableEntry *import, TypeTableEnt | ... | @@ -973,6 +973,7 @@ static void resolve_enum_type(CodeGen *g, ImportTableEntry *import, TypeTableEnt |
| 973 | 973 | ||
| 974 | if (!enum_type->data.enumeration.is_invalid) { | 974 | if (!enum_type->data.enumeration.is_invalid) { |
| 975 | enum_type->data.enumeration.gen_field_count = gen_field_index; | 975 | enum_type->data.enumeration.gen_field_count = gen_field_index; |
| 976 | enum_type->data.enumeration.union_type = biggest_union_member; | ||
| 976 | 977 | ||
| 977 | TypeTableEntry *tag_type_entry = get_smallest_unsigned_int_type(g, field_count); | 978 | TypeTableEntry *tag_type_entry = get_smallest_unsigned_int_type(g, field_count); |
| 978 | enum_type->data.enumeration.tag_type = tag_type_entry; | 979 | enum_type->data.enumeration.tag_type = tag_type_entry; |
| ... | @@ -2034,6 +2035,9 @@ static TypeTableEntry *analyze_enum_value_expr(CodeGen *g, ImportTableEntry *imp | ... | @@ -2034,6 +2035,9 @@ static TypeTableEntry *analyze_enum_value_expr(CodeGen *g, ImportTableEntry *imp |
| 2034 | codegen->type_entry = enum_type; | 2035 | codegen->type_entry = enum_type; |
| 2035 | codegen->source_node = field_access_node; | 2036 | codegen->source_node = field_access_node; |
| 2036 | context->struct_val_expr_alloca_list.append(codegen); | 2037 | context->struct_val_expr_alloca_list.append(codegen); |
| 2038 | |||
| 2039 | Expr *expr = get_resolved_expr(field_access_node); | ||
| 2040 | expr->const_val.ok = false; | ||
| 2037 | } else if (type_enum_field->type_entry->id != TypeTableEntryIdVoid) { | 2041 | } else if (type_enum_field->type_entry->id != TypeTableEntryIdVoid) { |
| 2038 | add_node_error(g, field_access_node, | 2042 | add_node_error(g, field_access_node, |
| 2039 | buf_sprintf("enum value '%s.%s' requires parameter of type '%s'", | 2043 | buf_sprintf("enum value '%s.%s' requires parameter of type '%s'", |
src/codegen.cpp+14-1| ... | @@ -2567,7 +2567,20 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE | ... | @@ -2567,7 +2567,20 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE |
| 2567 | if (type_entry->data.enumeration.gen_field_count == 0) { | 2567 | if (type_entry->data.enumeration.gen_field_count == 0) { |
| 2568 | return tag_value; | 2568 | return tag_value; |
| 2569 | } else { | 2569 | } else { |
| 2570 | zig_panic("TODO"); | 2570 | TypeTableEntry *union_type = type_entry->data.enumeration.union_type; |
| 2571 | TypeEnumField *enum_field = &type_entry->data.enumeration.fields[const_val->data.x_enum.tag]; | ||
| 2572 | assert(enum_field->value == const_val->data.x_enum.tag); | ||
| 2573 | LLVMValueRef union_value; | ||
| 2574 | if (type_has_bits(enum_field->type_entry)) { | ||
| 2575 | union_value = gen_const_val(g, union_type, const_val->data.x_enum.payload); | ||
| 2576 | } else { | ||
| 2577 | union_value = LLVMGetUndef(union_type->type_ref); | ||
| 2578 | } | ||
| 2579 | LLVMValueRef fields[] = { | ||
| 2580 | tag_value, | ||
| 2581 | union_value, | ||
| 2582 | }; | ||
| 2583 | return LLVMConstNamedStruct(type_entry->type_ref, fields, 2); | ||
| 2571 | } | 2584 | } |
| 2572 | } | 2585 | } |
| 2573 | case TypeTableEntryIdFn: | 2586 | case TypeTableEntryIdFn: |
test/self_hosted.zig+22-2| ... | @@ -38,11 +38,31 @@ fn call_struct_field(foo: Foo) -> i32 { | ... | @@ -38,11 +38,31 @@ fn call_struct_field(foo: Foo) -> i32 { |
| 38 | 38 | ||
| 39 | 39 | ||
| 40 | 40 | ||
| 41 | #attribute("test") | ||
| 42 | fn redefinition_of_error_values_allowed() { | ||
| 43 | if (error.AnError == error.SecondError) unreachable{} | ||
| 44 | } | ||
| 41 | error AnError; | 45 | error AnError; |
| 42 | error AnError; | 46 | error AnError; |
| 43 | error SecondError; | 47 | error SecondError; |
| 44 | 48 | ||
| 49 | |||
| 50 | |||
| 51 | |||
| 45 | #attribute("test") | 52 | #attribute("test") |
| 46 | fn redefinition_of_error_values_allowed() { | 53 | fn constant_enum_with_payload() { |
| 47 | if (error.AnError == error.SecondError) unreachable{} | 54 | should_be_empty(AnEnumWithPayload.Empty); |
| 55 | should_be_13(AnEnumWithPayload.Full(13)); | ||
| 56 | } | ||
| 57 | |||
| 58 | fn should_be_empty(x: AnEnumWithPayload) { | ||
| 59 | if (x != AnEnumWithPayload.Empty) unreachable{} | ||
| 60 | } | ||
| 61 | |||
| 62 | fn should_be_13(x: AnEnumWithPayload) { | ||
| 63 | } | ||
| 64 | |||
| 65 | enum AnEnumWithPayload { | ||
| 66 | Empty, | ||
| 67 | Full: i32, | ||
| 48 | } | 68 | } |