| ... | @@ -2586,7 +2586,6 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { | ... | @@ -2586,7 +2586,6 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { |
| 2586 | return ErrorNone; | 2586 | return ErrorNone; |
| 2587 | | 2587 | |
| 2588 | AstNode *decl_node = enum_type->data.enumeration.decl_node; | 2588 | AstNode *decl_node = enum_type->data.enumeration.decl_node; |
| 2589 | assert(decl_node->type == NodeTypeContainerDecl); | | |
| 2590 | | 2589 | |
| 2591 | if (enum_type->data.enumeration.resolve_loop_flag) { | 2590 | if (enum_type->data.enumeration.resolve_loop_flag) { |
| 2592 | if (enum_type->data.enumeration.resolve_status != ResolveStatusInvalid) { | 2591 | if (enum_type->data.enumeration.resolve_status != ResolveStatusInvalid) { |
| ... | @@ -2600,15 +2599,20 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { | ... | @@ -2600,15 +2599,20 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { |
| 2600 | | 2599 | |
| 2601 | enum_type->data.enumeration.resolve_loop_flag = true; | 2600 | enum_type->data.enumeration.resolve_loop_flag = true; |
| 2602 | | 2601 | |
| 2603 | assert(!enum_type->data.enumeration.fields); | 2602 | uint32_t field_count; |
| 2604 | uint32_t field_count = (uint32_t)decl_node->data.container_decl.fields.length; | 2603 | if (decl_node->type == NodeTypeContainerDecl) { |
| 2605 | if (field_count == 0) { | 2604 | assert(!enum_type->data.enumeration.fields); |
| 2606 | add_node_error(g, decl_node, buf_sprintf("enums must have 1 or more fields")); | 2605 | field_count = (uint32_t)decl_node->data.container_decl.fields.length; |
| | 2606 | if (field_count == 0) { |
| | 2607 | add_node_error(g, decl_node, buf_sprintf("enums must have 1 or more fields")); |
| 2607 | | 2608 | |
| 2608 | enum_type->data.enumeration.src_field_count = field_count; | 2609 | enum_type->data.enumeration.src_field_count = field_count; |
| 2609 | enum_type->data.enumeration.fields = nullptr; | 2610 | enum_type->data.enumeration.fields = nullptr; |
| 2610 | enum_type->data.enumeration.resolve_status = ResolveStatusInvalid; | 2611 | enum_type->data.enumeration.resolve_status = ResolveStatusInvalid; |
| 2611 | return ErrorSemanticAnalyzeFail; | 2612 | return ErrorSemanticAnalyzeFail; |
| | 2613 | } |
| | 2614 | } else { |
| | 2615 | field_count = enum_type->data.enumeration.src_field_count; |
| 2612 | } | 2616 | } |
| 2613 | | 2617 | |
| 2614 | Scope *scope = &enum_type->data.enumeration.decls_scope->base; | 2618 | Scope *scope = &enum_type->data.enumeration.decls_scope->base; |
| ... | @@ -2624,8 +2628,16 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { | ... | @@ -2624,8 +2628,16 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { |
| 2624 | enum_type->abi_size = tag_int_type->abi_size; | 2628 | enum_type->abi_size = tag_int_type->abi_size; |
| 2625 | enum_type->abi_align = tag_int_type->abi_align; | 2629 | enum_type->abi_align = tag_int_type->abi_align; |
| 2626 | | 2630 | |
| 2627 | if (decl_node->data.container_decl.init_arg_expr != nullptr) { | 2631 | ZigType *wanted_tag_int_type = nullptr; |
| 2628 | ZigType *wanted_tag_int_type = analyze_type_expr(g, scope, decl_node->data.container_decl.init_arg_expr); | 2632 | if (decl_node->type == NodeTypeContainerDecl) { |
| | 2633 | if (decl_node->data.container_decl.init_arg_expr != nullptr) { |
| | 2634 | wanted_tag_int_type = analyze_type_expr(g, scope, decl_node->data.container_decl.init_arg_expr); |
| | 2635 | } |
| | 2636 | } else { |
| | 2637 | wanted_tag_int_type = enum_type->data.enumeration.tag_int_type; |
| | 2638 | } |
| | 2639 | |
| | 2640 | if (wanted_tag_int_type != nullptr) { |
| 2629 | if (type_is_invalid(wanted_tag_int_type)) { | 2641 | if (type_is_invalid(wanted_tag_int_type)) { |
| 2630 | enum_type->data.enumeration.resolve_status = ResolveStatusInvalid; | 2642 | enum_type->data.enumeration.resolve_status = ResolveStatusInvalid; |
| 2631 | } else if (wanted_tag_int_type->id != ZigTypeIdInt && | 2643 | } else if (wanted_tag_int_type->id != ZigTypeIdInt && |
| ... | @@ -2654,7 +2666,6 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { | ... | @@ -2654,7 +2666,6 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { |
| 2654 | } | 2666 | } |
| 2655 | } | 2667 | } |
| 2656 | | 2668 | |
| 2657 | enum_type->data.enumeration.non_exhaustive = false; | | |
| 2658 | enum_type->data.enumeration.tag_int_type = tag_int_type; | 2669 | enum_type->data.enumeration.tag_int_type = tag_int_type; |
| 2659 | enum_type->size_in_bits = tag_int_type->size_in_bits; | 2670 | enum_type->size_in_bits = tag_int_type->size_in_bits; |
| 2660 | enum_type->abi_size = tag_int_type->abi_size; | 2671 | enum_type->abi_size = tag_int_type->abi_size; |
| ... | @@ -2663,121 +2674,131 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { | ... | @@ -2663,121 +2674,131 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { |
| 2663 | BigInt bi_one; | 2674 | BigInt bi_one; |
| 2664 | bigint_init_unsigned(&bi_one, 1); | 2675 | bigint_init_unsigned(&bi_one, 1); |
| 2665 | | 2676 | |
| 2666 | AstNode *last_field_node = decl_node->data.container_decl.fields.at(field_count - 1); | 2677 | if (decl_node->type == NodeTypeContainerDecl) { |
| 2667 | if (buf_eql_str(last_field_node->data.struct_field.name, "_")) { | 2678 | AstNode *last_field_node = decl_node->data.container_decl.fields.at(field_count - 1); |
| | 2679 | if (buf_eql_str(last_field_node->data.struct_field.name, "_")) { |
| | 2680 | if (last_field_node->data.struct_field.value != nullptr) { |
| | 2681 | add_node_error(g, last_field_node, buf_sprintf("value assigned to '_' field of non-exhaustive enum")); |
| | 2682 | enum_type->data.enumeration.resolve_status = ResolveStatusInvalid; |
| | 2683 | } |
| | 2684 | if (decl_node->data.container_decl.init_arg_expr == nullptr) { |
| | 2685 | add_node_error(g, decl_node, buf_sprintf("non-exhaustive enum must specify size")); |
| | 2686 | enum_type->data.enumeration.resolve_status = ResolveStatusInvalid; |
| | 2687 | } |
| | 2688 | enum_type->data.enumeration.non_exhaustive = true; |
| | 2689 | } else { |
| | 2690 | enum_type->data.enumeration.non_exhaustive = false; |
| | 2691 | } |
| | 2692 | } |
| | 2693 | |
| | 2694 | if (enum_type->data.enumeration.non_exhaustive) { |
| 2668 | field_count -= 1; | 2695 | field_count -= 1; |
| 2669 | if (field_count > 1 && log2_u64(field_count) == enum_type->size_in_bits) { | 2696 | if (field_count > 1 && log2_u64(field_count) == enum_type->size_in_bits) { |
| 2670 | add_node_error(g, last_field_node, buf_sprintf("non-exhaustive enum specifies every value")); | 2697 | add_node_error(g, decl_node, buf_sprintf("non-exhaustive enum specifies every value")); |
| 2671 | enum_type->data.enumeration.resolve_status = ResolveStatusInvalid; | 2698 | enum_type->data.enumeration.resolve_status = ResolveStatusInvalid; |
| 2672 | } | 2699 | } |
| 2673 | if (decl_node->data.container_decl.init_arg_expr == nullptr) { | | |
| 2674 | add_node_error(g, last_field_node, buf_sprintf("non-exhaustive enum must specify size")); | | |
| 2675 | enum_type->data.enumeration.resolve_status = ResolveStatusInvalid; | | |
| 2676 | } | | |
| 2677 | if (last_field_node->data.struct_field.value != nullptr) { | | |
| 2678 | add_node_error(g, last_field_node, buf_sprintf("value assigned to '_' field of non-exhaustive enum")); | | |
| 2679 | enum_type->data.enumeration.resolve_status = ResolveStatusInvalid; | | |
| 2680 | } | | |
| 2681 | enum_type->data.enumeration.non_exhaustive = true; | | |
| 2682 | } | 2700 | } |
| 2683 | | 2701 | |
| 2684 | enum_type->data.enumeration.src_field_count = field_count; | 2702 | if (decl_node->type == NodeTypeContainerDecl) { |
| 2685 | enum_type->data.enumeration.fields = heap::c_allocator.allocate<TypeEnumField>(field_count); | 2703 | enum_type->data.enumeration.src_field_count = field_count; |
| 2686 | enum_type->data.enumeration.fields_by_name.init(field_count); | 2704 | enum_type->data.enumeration.fields = heap::c_allocator.allocate<TypeEnumField>(field_count); |
| 2687 | | 2705 | enum_type->data.enumeration.fields_by_name.init(field_count); |
| 2688 | HashMap<BigInt, AstNode *, bigint_hash, bigint_eql> occupied_tag_values = {}; | | |
| 2689 | occupied_tag_values.init(field_count); | | |
| 2690 | | | |
| 2691 | TypeEnumField *last_enum_field = nullptr; | | |
| 2692 | | | |
| 2693 | for (uint32_t field_i = 0; field_i < field_count; field_i += 1) { | | |
| 2694 | AstNode *field_node = decl_node->data.container_decl.fields.at(field_i); | | |
| 2695 | TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[field_i]; | | |
| 2696 | type_enum_field->name = field_node->data.struct_field.name; | | |
| 2697 | type_enum_field->decl_index = field_i; | | |
| 2698 | type_enum_field->decl_node = field_node; | | |
| 2699 | | 2706 | |
| 2700 | if (field_node->data.struct_field.type != nullptr) { | 2707 | HashMap<BigInt, AstNode *, bigint_hash, bigint_eql> occupied_tag_values = {}; |
| 2701 | ErrorMsg *msg = add_node_error(g, field_node->data.struct_field.type, | 2708 | occupied_tag_values.init(field_count); |
| 2702 | buf_sprintf("structs and unions, not enums, support field types")); | | |
| 2703 | add_error_note(g, msg, decl_node, | | |
| 2704 | buf_sprintf("consider 'union(enum)' here")); | | |
| 2705 | } else if (field_node->data.struct_field.align_expr != nullptr) { | | |
| 2706 | ErrorMsg *msg = add_node_error(g, field_node->data.struct_field.align_expr, | | |
| 2707 | buf_sprintf("structs and unions, not enums, support field alignment")); | | |
| 2708 | add_error_note(g, msg, decl_node, | | |
| 2709 | buf_sprintf("consider 'union(enum)' here")); | | |
| 2710 | } | | |
| 2711 | | 2709 | |
| 2712 | if (buf_eql_str(type_enum_field->name, "_")) { | 2710 | TypeEnumField *last_enum_field = nullptr; |
| 2713 | add_node_error(g, field_node, buf_sprintf("'_' field of non-exhaustive enum must be last")); | | |
| 2714 | enum_type->data.enumeration.resolve_status = ResolveStatusInvalid; | | |
| 2715 | } | | |
| 2716 | | 2711 | |
| 2717 | auto field_entry = enum_type->data.enumeration.fields_by_name.put_unique(type_enum_field->name, type_enum_field); | 2712 | for (uint32_t field_i = 0; field_i < field_count; field_i += 1) { |
| 2718 | if (field_entry != nullptr) { | 2713 | AstNode *field_node = decl_node->data.container_decl.fields.at(field_i); |
| 2719 | ErrorMsg *msg = add_node_error(g, field_node, | 2714 | TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[field_i]; |
| 2720 | buf_sprintf("duplicate enum field: '%s'", buf_ptr(type_enum_field->name))); | 2715 | type_enum_field->name = field_node->data.struct_field.name; |
| 2721 | add_error_note(g, msg, field_entry->value->decl_node, buf_sprintf("other field here")); | 2716 | type_enum_field->decl_index = field_i; |
| 2722 | enum_type->data.enumeration.resolve_status = ResolveStatusInvalid; | 2717 | type_enum_field->decl_node = field_node; |
| 2723 | continue; | 2718 | |
| 2724 | } | 2719 | if (field_node->data.struct_field.type != nullptr) { |
| 2725 | | 2720 | ErrorMsg *msg = add_node_error(g, field_node->data.struct_field.type, |
| 2726 | AstNode *tag_value = field_node->data.struct_field.value; | 2721 | buf_sprintf("structs and unions, not enums, support field types")); |
| | 2722 | add_error_note(g, msg, decl_node, |
| | 2723 | buf_sprintf("consider 'union(enum)' here")); |
| | 2724 | } else if (field_node->data.struct_field.align_expr != nullptr) { |
| | 2725 | ErrorMsg *msg = add_node_error(g, field_node->data.struct_field.align_expr, |
| | 2726 | buf_sprintf("structs and unions, not enums, support field alignment")); |
| | 2727 | add_error_note(g, msg, decl_node, |
| | 2728 | buf_sprintf("consider 'union(enum)' here")); |
| | 2729 | } |
| | 2730 | |
| | 2731 | if (buf_eql_str(type_enum_field->name, "_")) { |
| | 2732 | add_node_error(g, field_node, buf_sprintf("'_' field of non-exhaustive enum must be last")); |
| | 2733 | enum_type->data.enumeration.resolve_status = ResolveStatusInvalid; |
| | 2734 | } |
| 2727 | | 2735 | |
| 2728 | if (tag_value != nullptr) { | 2736 | auto field_entry = enum_type->data.enumeration.fields_by_name.put_unique(type_enum_field->name, type_enum_field); |
| 2729 | // A user-specified value is available | 2737 | if (field_entry != nullptr) { |
| 2730 | ZigValue *result = analyze_const_value(g, scope, tag_value, tag_int_type, | 2738 | ErrorMsg *msg = add_node_error(g, field_node, |
| 2731 | nullptr, UndefBad); | 2739 | buf_sprintf("duplicate enum field: '%s'", buf_ptr(type_enum_field->name))); |
| 2732 | if (type_is_invalid(result->type)) { | 2740 | add_error_note(g, msg, field_entry->value->decl_node, buf_sprintf("other field here")); |
| 2733 | enum_type->data.enumeration.resolve_status = ResolveStatusInvalid; | 2741 | enum_type->data.enumeration.resolve_status = ResolveStatusInvalid; |
| 2734 | continue; | 2742 | continue; |
| 2735 | } | 2743 | } |
| 2736 | | 2744 | |
| 2737 | assert(result->special != ConstValSpecialRuntime); | 2745 | AstNode *tag_value = field_node->data.struct_field.value; |
| 2738 | assert(result->type->id == ZigTypeIdInt || result->type->id == ZigTypeIdComptimeInt); | | |
| 2739 | | 2746 | |
| 2740 | bigint_init_bigint(&type_enum_field->value, &result->data.x_bigint); | 2747 | if (tag_value != nullptr) { |
| 2741 | } else { | 2748 | // A user-specified value is available |
| 2742 | // No value was explicitly specified: allocate the last value + 1 | 2749 | ZigValue *result = analyze_const_value(g, scope, tag_value, tag_int_type, |
| 2743 | // or, if this is the first element, zero | 2750 | nullptr, UndefBad); |
| 2744 | if (last_enum_field != nullptr) { | 2751 | if (type_is_invalid(result->type)) { |
| 2745 | bigint_add(&type_enum_field->value, &last_enum_field->value, &bi_one); | 2752 | enum_type->data.enumeration.resolve_status = ResolveStatusInvalid; |
| | 2753 | continue; |
| | 2754 | } |
| | 2755 | |
| | 2756 | assert(result->special != ConstValSpecialRuntime); |
| | 2757 | assert(result->type->id == ZigTypeIdInt || result->type->id == ZigTypeIdComptimeInt); |
| | 2758 | |
| | 2759 | bigint_init_bigint(&type_enum_field->value, &result->data.x_bigint); |
| 2746 | } else { | 2760 | } else { |
| 2747 | bigint_init_unsigned(&type_enum_field->value, 0); | 2761 | // No value was explicitly specified: allocate the last value + 1 |
| | 2762 | // or, if this is the first element, zero |
| | 2763 | if (last_enum_field != nullptr) { |
| | 2764 | bigint_add(&type_enum_field->value, &last_enum_field->value, &bi_one); |
| | 2765 | } else { |
| | 2766 | bigint_init_unsigned(&type_enum_field->value, 0); |
| | 2767 | } |
| | 2768 | |
| | 2769 | // Make sure we can represent this number with tag_int_type |
| | 2770 | if (!bigint_fits_in_bits(&type_enum_field->value, |
| | 2771 | tag_int_type->size_in_bits, |
| | 2772 | tag_int_type->data.integral.is_signed)) { |
| | 2773 | enum_type->data.enumeration.resolve_status = ResolveStatusInvalid; |
| | 2774 | |
| | 2775 | Buf *val_buf = buf_alloc(); |
| | 2776 | bigint_append_buf(val_buf, &type_enum_field->value, 10); |
| | 2777 | add_node_error(g, field_node, |
| | 2778 | buf_sprintf("enumeration value %s too large for type '%s'", |
| | 2779 | buf_ptr(val_buf), buf_ptr(&tag_int_type->name))); |
| | 2780 | |
| | 2781 | break; |
| | 2782 | } |
| 2748 | } | 2783 | } |
| 2749 | | 2784 | |
| 2750 | // Make sure we can represent this number with tag_int_type | 2785 | // Make sure the value is unique |
| 2751 | if (!bigint_fits_in_bits(&type_enum_field->value, | 2786 | auto entry = occupied_tag_values.put_unique(type_enum_field->value, field_node); |
| 2752 | tag_int_type->size_in_bits, | 2787 | if (entry != nullptr && enum_type->data.enumeration.layout != ContainerLayoutExtern) { |
| 2753 | tag_int_type->data.integral.is_signed)) { | | |
| 2754 | enum_type->data.enumeration.resolve_status = ResolveStatusInvalid; | 2788 | enum_type->data.enumeration.resolve_status = ResolveStatusInvalid; |
| 2755 | | 2789 | |
| 2756 | Buf *val_buf = buf_alloc(); | 2790 | Buf *val_buf = buf_alloc(); |
| 2757 | bigint_append_buf(val_buf, &type_enum_field->value, 10); | 2791 | bigint_append_buf(val_buf, &type_enum_field->value, 10); |
| 2758 | add_node_error(g, field_node, | | |
| 2759 | buf_sprintf("enumeration value %s too large for type '%s'", | | |
| 2760 | buf_ptr(val_buf), buf_ptr(&tag_int_type->name))); | | |
| 2761 | | 2792 | |
| 2762 | break; | 2793 | ErrorMsg *msg = add_node_error(g, field_node, |
| | 2794 | buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf))); |
| | 2795 | add_error_note(g, msg, entry->value, |
| | 2796 | buf_sprintf("other occurrence here")); |
| 2763 | } | 2797 | } |
| 2764 | } | | |
| 2765 | | | |
| 2766 | // Make sure the value is unique | | |
| 2767 | auto entry = occupied_tag_values.put_unique(type_enum_field->value, field_node); | | |
| 2768 | if (entry != nullptr && enum_type->data.enumeration.layout != ContainerLayoutExtern) { | | |
| 2769 | enum_type->data.enumeration.resolve_status = ResolveStatusInvalid; | | |
| 2770 | | | |
| 2771 | Buf *val_buf = buf_alloc(); | | |
| 2772 | bigint_append_buf(val_buf, &type_enum_field->value, 10); | | |
| 2773 | | 2798 | |
| 2774 | ErrorMsg *msg = add_node_error(g, field_node, | 2799 | last_enum_field = type_enum_field; |
| 2775 | buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf))); | | |
| 2776 | add_error_note(g, msg, entry->value, | | |
| 2777 | buf_sprintf("other occurrence here")); | | |
| 2778 | } | 2800 | } |
| 2779 | | 2801 | occupied_tag_values.deinit(); |
| 2780 | last_enum_field = type_enum_field; | | |
| 2781 | } | 2802 | } |
| 2782 | | 2803 | |
| 2783 | if (enum_type->data.enumeration.resolve_status == ResolveStatusInvalid) | 2804 | if (enum_type->data.enumeration.resolve_status == ResolveStatusInvalid) |
| ... | @@ -2786,8 +2807,6 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { | ... | @@ -2786,8 +2807,6 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { |
| 2786 | enum_type->data.enumeration.resolve_loop_flag = false; | 2807 | enum_type->data.enumeration.resolve_loop_flag = false; |
| 2787 | enum_type->data.enumeration.resolve_status = ResolveStatusSizeKnown; | 2808 | enum_type->data.enumeration.resolve_status = ResolveStatusSizeKnown; |
| 2788 | | 2809 | |
| 2789 | occupied_tag_values.deinit(); | | |
| 2790 | | | |
| 2791 | return ErrorNone; | 2810 | return ErrorNone; |
| 2792 | } | 2811 | } |
| 2793 | | 2812 | |