| ... | @@ -1908,6 +1908,18 @@ static Error resolve_union_type(CodeGen *g, ZigType *union_type) { | ... | @@ -1908,6 +1908,18 @@ static Error resolve_union_type(CodeGen *g, ZigType *union_type) { |
| 1908 | return ErrorNone; | 1908 | return ErrorNone; |
| 1909 | } | 1909 | } |
| 1910 | | 1910 | |
| | 1911 | static bool type_is_valid_extern_enum_tag(CodeGen *g, ZigType *ty) { |
| | 1912 | // Only integer types are allowed by the C ABI |
| | 1913 | if(ty->id != ZigTypeIdInt) |
| | 1914 | return false; |
| | 1915 | |
| | 1916 | // According to the ANSI C standard the enumeration type should be either a |
| | 1917 | // signed char, a signed integer or an unsigned one. But GCC/Clang allow |
| | 1918 | // other integral types as a compiler extension so let's accomodate them |
| | 1919 | // aswell. |
| | 1920 | return type_allowed_in_extern(g, ty); |
| | 1921 | } |
| | 1922 | |
| 1911 | static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { | 1923 | static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { |
| 1912 | assert(enum_type->id == ZigTypeIdEnum); | 1924 | assert(enum_type->id == ZigTypeIdEnum); |
| 1913 | | 1925 | |
| ... | @@ -1965,7 +1977,6 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { | ... | @@ -1965,7 +1977,6 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { |
| 1965 | enum_type->abi_size = tag_int_type->abi_size; | 1977 | enum_type->abi_size = tag_int_type->abi_size; |
| 1966 | enum_type->abi_align = tag_int_type->abi_align; | 1978 | enum_type->abi_align = tag_int_type->abi_align; |
| 1967 | | 1979 | |
| 1968 | // TODO: Are extern enums allowed to have an init_arg_expr? | | |
| 1969 | if (decl_node->data.container_decl.init_arg_expr != nullptr) { | 1980 | if (decl_node->data.container_decl.init_arg_expr != nullptr) { |
| 1970 | ZigType *wanted_tag_int_type = analyze_type_expr(g, scope, decl_node->data.container_decl.init_arg_expr); | 1981 | ZigType *wanted_tag_int_type = analyze_type_expr(g, scope, decl_node->data.container_decl.init_arg_expr); |
| 1971 | if (type_is_invalid(wanted_tag_int_type)) { | 1982 | if (type_is_invalid(wanted_tag_int_type)) { |
| ... | @@ -1974,24 +1985,29 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { | ... | @@ -1974,24 +1985,29 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { |
| 1974 | enum_type->data.enumeration.is_invalid = true; | 1985 | enum_type->data.enumeration.is_invalid = true; |
| 1975 | add_node_error(g, decl_node->data.container_decl.init_arg_expr, | 1986 | add_node_error(g, decl_node->data.container_decl.init_arg_expr, |
| 1976 | buf_sprintf("expected integer, found '%s'", buf_ptr(&wanted_tag_int_type->name))); | 1987 | buf_sprintf("expected integer, found '%s'", buf_ptr(&wanted_tag_int_type->name))); |
| 1977 | } else if (wanted_tag_int_type->data.integral.is_signed) { | 1988 | } else if (enum_type->data.enumeration.layout == ContainerLayoutExtern && |
| | 1989 | !type_is_valid_extern_enum_tag(g, wanted_tag_int_type)) { |
| 1978 | enum_type->data.enumeration.is_invalid = true; | 1990 | enum_type->data.enumeration.is_invalid = true; |
| 1979 | add_node_error(g, decl_node->data.container_decl.init_arg_expr, | 1991 | ErrorMsg *msg = add_node_error(g, decl_node->data.container_decl.init_arg_expr, |
| 1980 | buf_sprintf("expected unsigned integer, found '%s'", buf_ptr(&wanted_tag_int_type->name))); | 1992 | buf_sprintf("'%s' is not a valid tag type for an extern enum", |
| 1981 | } else if (wanted_tag_int_type->data.integral.bit_count < tag_int_type->data.integral.bit_count) { | 1993 | buf_ptr(&wanted_tag_int_type->name))); |
| 1982 | enum_type->data.enumeration.is_invalid = true; | 1994 | add_error_note(g, msg, decl_node->data.container_decl.init_arg_expr, |
| 1983 | add_node_error(g, decl_node->data.container_decl.init_arg_expr, | 1995 | buf_sprintf("any integral type of size 8, 16, 32, 64 or 128 bit is valid")); |
| 1984 | buf_sprintf("'%s' too small to hold all bits; must be at least '%s'", | | |
| 1985 | buf_ptr(&wanted_tag_int_type->name), buf_ptr(&tag_int_type->name))); | | |
| 1986 | } else { | 1996 | } else { |
| 1987 | tag_int_type = wanted_tag_int_type; | 1997 | tag_int_type = wanted_tag_int_type; |
| 1988 | } | 1998 | } |
| 1989 | } | 1999 | } |
| | 2000 | |
| 1990 | enum_type->data.enumeration.tag_int_type = tag_int_type; | 2001 | enum_type->data.enumeration.tag_int_type = tag_int_type; |
| 1991 | enum_type->size_in_bits = tag_int_type->size_in_bits; | 2002 | enum_type->size_in_bits = tag_int_type->size_in_bits; |
| 1992 | enum_type->abi_size = tag_int_type->abi_size; | 2003 | enum_type->abi_size = tag_int_type->abi_size; |
| 1993 | enum_type->abi_align = tag_int_type->abi_align; | 2004 | enum_type->abi_align = tag_int_type->abi_align; |
| 1994 | | 2005 | |
| | 2006 | BigInt bi_one; |
| | 2007 | bigint_init_unsigned(&bi_one, 1); |
| | 2008 | |
| | 2009 | TypeEnumField *last_enum_field = nullptr; |
| | 2010 | |
| 1995 | for (uint32_t field_i = 0; field_i < field_count; field_i += 1) { | 2011 | for (uint32_t field_i = 0; field_i < field_count; field_i += 1) { |
| 1996 | AstNode *field_node = decl_node->data.container_decl.fields.at(field_i); | 2012 | AstNode *field_node = decl_node->data.container_decl.fields.at(field_i); |
| 1997 | TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[field_i]; | 2013 | TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[field_i]; |
| ... | @@ -2017,60 +2033,58 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { | ... | @@ -2017,60 +2033,58 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { |
| 2017 | | 2033 | |
| 2018 | AstNode *tag_value = field_node->data.struct_field.value; | 2034 | AstNode *tag_value = field_node->data.struct_field.value; |
| 2019 | | 2035 | |
| 2020 | // In this first pass we resolve explicit tag values. | | |
| 2021 | // In a second pass we will fill in the unspecified ones. | | |
| 2022 | if (tag_value != nullptr) { | 2036 | if (tag_value != nullptr) { |
| | 2037 | // A user-specified value is available |
| 2023 | ConstExprValue *result = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr); | 2038 | ConstExprValue *result = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr); |
| 2024 | if (type_is_invalid(result->type)) { | 2039 | if (type_is_invalid(result->type)) { |
| 2025 | enum_type->data.enumeration.is_invalid = true; | 2040 | enum_type->data.enumeration.is_invalid = true; |
| 2026 | continue; | 2041 | continue; |
| 2027 | } | 2042 | } |
| | 2043 | |
| 2028 | assert(result->special != ConstValSpecialRuntime); | 2044 | assert(result->special != ConstValSpecialRuntime); |
| 2029 | assert(result->type->id == ZigTypeIdInt || | 2045 | assert(result->type->id == ZigTypeIdInt || result->type->id == ZigTypeIdComptimeInt); |
| 2030 | result->type->id == ZigTypeIdComptimeInt); | 2046 | |
| 2031 | auto entry = occupied_tag_values.put_unique(result->data.x_bigint, tag_value); | 2047 | bigint_init_bigint(&type_enum_field->value, &result->data.x_bigint); |
| 2032 | if (entry == nullptr) { | 2048 | } else { |
| 2033 | bigint_init_bigint(&type_enum_field->value, &result->data.x_bigint); | 2049 | // No value was explicitly specified: allocate the last value + 1 |
| | 2050 | // or, if this is the first element, zero |
| | 2051 | if (last_enum_field != nullptr) { |
| | 2052 | bigint_add(&type_enum_field->value, &last_enum_field->value, &bi_one); |
| 2034 | } else { | 2053 | } else { |
| 2035 | Buf *val_buf = buf_alloc(); | 2054 | bigint_init_unsigned(&type_enum_field->value, 0); |
| 2036 | bigint_append_buf(val_buf, &result->data.x_bigint, 10); | 2055 | } |
| 2037 | | 2056 | |
| 2038 | ErrorMsg *msg = add_node_error(g, tag_value, | 2057 | // Make sure we can represent this number with tag_int_type |
| 2039 | buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf))); | 2058 | if (!bigint_fits_in_bits(&type_enum_field->value, |
| 2040 | add_error_note(g, msg, entry->value, | 2059 | tag_int_type->size_in_bits, |
| 2041 | buf_sprintf("other occurrence here")); | 2060 | tag_int_type->data.integral.is_signed)) { |
| 2042 | enum_type->data.enumeration.is_invalid = true; | 2061 | enum_type->data.enumeration.is_invalid = true; |
| 2043 | continue; | 2062 | |
| | 2063 | Buf *val_buf = buf_alloc(); |
| | 2064 | bigint_append_buf(val_buf, &type_enum_field->value, 10); |
| | 2065 | add_node_error(g, field_node, |
| | 2066 | buf_sprintf("enumeration value %s too large for type '%s'", |
| | 2067 | buf_ptr(val_buf), buf_ptr(&tag_int_type->name))); |
| | 2068 | |
| | 2069 | break; |
| 2044 | } | 2070 | } |
| 2045 | } | 2071 | } |
| 2046 | } | | |
| 2047 | | 2072 | |
| 2048 | // Now iterate again and populate the unspecified tag values | 2073 | // Make sure the value is unique |
| 2049 | uint32_t next_maybe_unoccupied_index = 0; | 2074 | auto entry = occupied_tag_values.put_unique(type_enum_field->value, field_node); |
| | 2075 | if (entry != nullptr) { |
| | 2076 | enum_type->data.enumeration.is_invalid = true; |
| 2050 | | 2077 | |
| 2051 | for (uint32_t field_i = 0; field_i < field_count; field_i += 1) { | 2078 | Buf *val_buf = buf_alloc(); |
| 2052 | AstNode *field_node = decl_node->data.container_decl.fields.at(field_i); | 2079 | bigint_append_buf(val_buf, &type_enum_field->value, 10); |
| 2053 | TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[field_i]; | | |
| 2054 | AstNode *tag_value = field_node->data.struct_field.value; | | |
| 2055 | | 2080 | |
| 2056 | if (tag_value == nullptr) { | 2081 | ErrorMsg *msg = add_node_error(g, field_node, |
| 2057 | if (occupied_tag_values.size() == 0) { | 2082 | buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf))); |
| 2058 | bigint_init_unsigned(&type_enum_field->value, next_maybe_unoccupied_index); | 2083 | add_error_note(g, msg, entry->value, |
| 2059 | next_maybe_unoccupied_index += 1; | 2084 | buf_sprintf("other occurrence here")); |
| 2060 | } else { | | |
| 2061 | BigInt proposed_value; | | |
| 2062 | for (;;) { | | |
| 2063 | bigint_init_unsigned(&proposed_value, next_maybe_unoccupied_index); | | |
| 2064 | next_maybe_unoccupied_index += 1; | | |
| 2065 | auto entry = occupied_tag_values.put_unique(proposed_value, field_node); | | |
| 2066 | if (entry != nullptr) { | | |
| 2067 | continue; | | |
| 2068 | } | | |
| 2069 | break; | | |
| 2070 | } | | |
| 2071 | bigint_init_bigint(&type_enum_field->value, &proposed_value); | | |
| 2072 | } | | |
| 2073 | } | 2085 | } |
| | 2086 | |
| | 2087 | last_enum_field = type_enum_field; |
| 2074 | } | 2088 | } |
| 2075 | | 2089 | |
| 2076 | enum_type->data.enumeration.zero_bits_loop_flag = false; | 2090 | enum_type->data.enumeration.zero_bits_loop_flag = false; |