| ... | @@ -1908,6 +1908,30 @@ static Error resolve_union_type(CodeGen *g, ZigType *union_type) { | ... | @@ -1908,6 +1908,30 @@ 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_int_compatible(ZigType *t1, ZigType *t2) { |
| | 1912 | assert(t1->id == ZigTypeIdInt); |
| | 1913 | assert(t2->id == ZigTypeIdInt); |
| | 1914 | |
| | 1915 | if (t1 == t2) |
| | 1916 | return true; |
| | 1917 | |
| | 1918 | return (t1->data.integral.bit_count == t2->data.integral.bit_count && |
| | 1919 | t1->data.integral.is_signed == t2->data.integral.is_signed); |
| | 1920 | } |
| | 1921 | |
| | 1922 | static bool type_is_valid_extern_enum_tag(CodeGen *g, ZigType *ty) { |
| | 1923 | // According to the ANSI C standard: |
| | 1924 | // Each enumerated type shall be compatible with char, a signed integer |
| | 1925 | // type, or an unsigned integer type. |
| | 1926 | ZigType *c_uint_type = get_c_int_type(g, CIntTypeInt); |
| | 1927 | ZigType *c_int_type = get_c_int_type(g, CIntTypeInt); |
| | 1928 | ZigType *c_schar_type = g->builtin_types.entry_i8; |
| | 1929 | |
| | 1930 | return (type_is_int_compatible(ty, c_schar_type) || |
| | 1931 | type_is_int_compatible(ty, c_int_type) || |
| | 1932 | type_is_int_compatible(ty, c_uint_type)); |
| | 1933 | } |
| | 1934 | |
| 1911 | static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { | 1935 | static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { |
| 1912 | assert(enum_type->id == ZigTypeIdEnum); | 1936 | assert(enum_type->id == ZigTypeIdEnum); |
| 1913 | | 1937 | |
| ... | @@ -1965,7 +1989,6 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { | ... | @@ -1965,7 +1989,6 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { |
| 1965 | enum_type->abi_size = tag_int_type->abi_size; | 1989 | enum_type->abi_size = tag_int_type->abi_size; |
| 1966 | enum_type->abi_align = tag_int_type->abi_align; | 1990 | enum_type->abi_align = tag_int_type->abi_align; |
| 1967 | | 1991 | |
| 1968 | // TODO: Are extern enums allowed to have an init_arg_expr? | | |
| 1969 | if (decl_node->data.container_decl.init_arg_expr != nullptr) { | 1992 | 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); | 1993 | 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)) { | 1994 | if (type_is_invalid(wanted_tag_int_type)) { |
| ... | @@ -1974,6 +1997,14 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { | ... | @@ -1974,6 +1997,14 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { |
| 1974 | enum_type->data.enumeration.is_invalid = true; | 1997 | enum_type->data.enumeration.is_invalid = true; |
| 1975 | add_node_error(g, decl_node->data.container_decl.init_arg_expr, | 1998 | 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))); | 1999 | buf_sprintf("expected integer, found '%s'", buf_ptr(&wanted_tag_int_type->name))); |
| | 2000 | } else if (enum_type->data.enumeration.layout == ContainerLayoutExtern && |
| | 2001 | !type_is_valid_extern_enum_tag(g, wanted_tag_int_type)) { |
| | 2002 | enum_type->data.enumeration.is_invalid = true; |
| | 2003 | ErrorMsg *msg = add_node_error(g, decl_node->data.container_decl.init_arg_expr, |
| | 2004 | buf_sprintf("'%s' is not a valid tag type for an extern union", |
| | 2005 | buf_ptr(&wanted_tag_int_type->name))); |
| | 2006 | add_error_note(g, msg, decl_node->data.container_decl.init_arg_expr, |
| | 2007 | buf_sprintf("valid types are 'i8', 'c_int' and 'c_uint' or compatible types")); |
| 1977 | } else if (wanted_tag_int_type->data.integral.is_signed) { | 2008 | } else if (wanted_tag_int_type->data.integral.is_signed) { |
| 1978 | enum_type->data.enumeration.is_invalid = true; | 2009 | enum_type->data.enumeration.is_invalid = true; |
| 1979 | add_node_error(g, decl_node->data.container_decl.init_arg_expr, | 2010 | add_node_error(g, decl_node->data.container_decl.init_arg_expr, |
| ... | @@ -1987,6 +2018,7 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { | ... | @@ -1987,6 +2018,7 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { |
| 1987 | tag_int_type = wanted_tag_int_type; | 2018 | tag_int_type = wanted_tag_int_type; |
| 1988 | } | 2019 | } |
| 1989 | } | 2020 | } |
| | 2021 | |
| 1990 | enum_type->data.enumeration.tag_int_type = tag_int_type; | 2022 | enum_type->data.enumeration.tag_int_type = tag_int_type; |
| 1991 | enum_type->size_in_bits = tag_int_type->size_in_bits; | 2023 | enum_type->size_in_bits = tag_int_type->size_in_bits; |
| 1992 | enum_type->abi_size = tag_int_type->abi_size; | 2024 | enum_type->abi_size = tag_int_type->abi_size; |