From 9d2f4e72c2868559d8a7448d33824eaea468746d Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Mon, 3 Feb 2025 22:51:44 +0100 Subject: [PATCH] Add `inline` to enums #1819. --- releasenotes.md | 1 + resources/grammar/grammar.y | 4 + src/compiler/compiler_internal.h | 2 + src/compiler/parse_global.c | 28 ++++- src/compiler/sema_casts.c | 117 +++++++++++++----- src/compiler/sema_decls.c | 1 + test/test_suite/enumerations/inline_enums.c3t | 38 ++++++ test/test_suite/symbols/various.c3 | 4 +- 8 files changed, 156 insertions(+), 39 deletions(-) create mode 100644 test/test_suite/enumerations/inline_enums.c3t diff --git a/releasenotes.md b/releasenotes.md index 196963d50..58a88f511 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -16,6 +16,7 @@ - Compile time array inc/dec. - Improve error message when using ',' in struct declarations. #1920 - Compile time array assign ops, e.g. `$c[1] += 3` #1890. +- Add `inline` to enums #1819. ### Fixes - Fix issue requiring prefix on a generic interface declaration. diff --git a/resources/grammar/grammar.y b/resources/grammar/grammar.y index 068b39f50..df1ebf551 100644 --- a/resources/grammar/grammar.y +++ b/resources/grammar/grammar.y @@ -514,6 +514,7 @@ identifier_list enum_param_decl : type IDENT + | INLINE type IDENT ; base_type @@ -1045,9 +1046,12 @@ struct_member_decl | INLINE type opt_attributes ';' ; + enum_spec : ':' base_type '(' enum_params ')' + | ':' INLINE base_type '(' enum_params ')' | ':' base_type + | ':' INLINE base_type | ':' '(' enum_params ')' ; diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index ebaa934c6..5deb81c9c 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -474,6 +474,8 @@ typedef struct Decl** values; Decl** parameters; TypeInfo *type_info; + int16_t inline_index; + bool inline_value; } EnumDecl; struct Signature_ diff --git a/src/compiler/parse_global.c b/src/compiler/parse_global.c index cd26765f9..c4b4d4515 100644 --- a/src/compiler/parse_global.c +++ b/src/compiler/parse_global.c @@ -15,7 +15,7 @@ typedef enum FunctionParse_ static inline Decl *parse_func_definition(ParseContext *c, AstId contracts, FunctionParse parse_kind); static inline bool parse_bitstruct_body(ParseContext *c, Decl *decl); -static inline bool parse_enum_param_list(ParseContext *c, Decl*** parameters_ref); +static inline bool parse_enum_param_list(ParseContext *c, Decl*** parameters_ref, ArrayIndex *inline_index); static Decl *parse_include(ParseContext *c); static Decl *parse_exec(ParseContext *c); static bool parse_attributes_for_global(ParseContext *c, Decl *decl); @@ -1235,8 +1235,14 @@ static inline Decl *parse_global_declaration(ParseContext *c) /** * enum_param_decl ::= type IDENT attributes? */ -static inline bool parse_enum_param_decl(ParseContext *c, Decl*** parameters) +static inline bool parse_enum_param_decl(ParseContext *c, Decl*** parameters, bool *has_inline) { + bool is_inline = try_consume(c, TOKEN_INLINE); + if (is_inline) + { + if (*has_inline) RETURN_PRINT_ERROR_HERE("An enum may only have one inline parameter."); + *has_inline = true; + } ASSIGN_TYPE_OR_RET(TypeInfo *type, parse_optional_type(c), false); if (type->optional) RETURN_PRINT_ERROR_AT(false, type, "Parameters may not be optional."); Decl *param = decl_new_var_current(c, type, VARDECL_PARAM); @@ -2270,14 +2276,21 @@ static inline Decl *parse_fault_declaration(ParseContext *c) /** * enum_param_list ::= '(' enum_param* ')' */ -static inline bool parse_enum_param_list(ParseContext *c, Decl*** parameters_ref) +static inline bool parse_enum_param_list(ParseContext *c, Decl*** parameters_ref, ArrayIndex *inline_index) { // If no left parenthesis we're done. if (!try_consume(c, TOKEN_LPAREN)) return true; + ArrayIndex index = -1; while (!try_consume(c, TOKEN_RPAREN)) { - if (!parse_enum_param_decl(c, parameters_ref)) return false; + index++; + bool has_inline = !inline_index || *inline_index > -1; + if (!parse_enum_param_decl(c, parameters_ref, &has_inline)) return false; + if (has_inline) + { + *inline_index = index; + } Decl *last_parameter = VECLAST(*parameters_ref); ASSERT(last_parameter); last_parameter->var.index = vec_size(*parameters_ref) - 1; // NOLINT @@ -2307,17 +2320,20 @@ static inline Decl *parse_enum_declaration(ParseContext *c) TypeInfo *type = NULL; + bool val_is_inline = false; + ArrayIndex inline_index = -1; if (try_consume(c, TOKEN_COLON)) { if (!tok_is(c, TOKEN_LPAREN) && !tok_is(c, TOKEN_LBRACE)) { + val_is_inline = try_consume(c, TOKEN_INLINE); ASSIGN_TYPE_OR_RET(type, parse_optional_type(c), poisoned_decl); if (type->optional) { RETURN_PRINT_ERROR_AT(poisoned_decl, type, "An enum can't have an optional type."); } } - if (!parse_enum_param_list(c, &decl->enums.parameters)) return poisoned_decl; + if (!parse_enum_param_list(c, &decl->enums.parameters, val_is_inline ? NULL : &inline_index)) return poisoned_decl; } if (!parse_attributes_for_global(c, decl)) return poisoned_decl; @@ -2326,6 +2342,8 @@ static inline Decl *parse_enum_declaration(ParseContext *c) CONSUME_OR_RET(TOKEN_LBRACE, poisoned_decl); decl->enums.type_info = type ? type : type_info_new_base(type_int, decl->span); + decl->enums.inline_index = (int16_t)inline_index; + decl->enums.inline_value = val_is_inline; while (!try_consume(c, TOKEN_RBRACE)) { Decl *enum_const = decl_new(DECL_ENUM_CONSTANT, symstr(c), c->span); diff --git a/src/compiler/sema_casts.c b/src/compiler/sema_casts.c index a04f0caea..3bc4671a4 100644 --- a/src/compiler/sema_casts.c +++ b/src/compiler/sema_casts.c @@ -1430,6 +1430,36 @@ static bool rule_int_to_enum(CastContext *cc, bool is_explicit, bool is_silent) return true; } + +static bool rule_enum_to_value(CastContext *cc, bool is_explicit, bool is_silent) +{ + Decl *enum_decl = cc->from->decl; + + if (!enum_decl->is_substruct) + { + if (is_explicit && cc->to_group == CONV_INT) return true; + return sema_cast_error(cc, false, is_silent); + } + + Type *inline_type; + if (enum_decl->enums.inline_value) + { + inline_type = enum_decl->enums.type_info->type; + } + else + { + inline_type = enum_decl->enums.parameters[enum_decl->enums.inline_index]->type; + } + if (is_explicit) + { + cast_context_set_from(cc, type_flatten(inline_type)); + // Explicit just flattens and tries again. + return cast_is_allowed(cc, is_explicit, is_silent); + } + cast_context_set_from(cc, inline_type->canonical); + return cast_is_allowed(cc, is_explicit, is_silent); +} + static bool rule_bits_to_arr(CastContext *cc, bool is_explicit, bool is_silent) { if (is_silent && !is_explicit) return false; @@ -1708,12 +1738,34 @@ static void cast_int_to_float(Expr *expr, Type *type) expr_rewrite_const_float(expr, type, f); } -static void cast_enum_to_int(Expr* expr, Type *to_type) +static void cast_enum_to_value(Expr* expr, Type *to_type) { - static_assert(ALLOW_DEPRECATED_6, "Fix deprecation"); - SEMA_DEPRECATED(expr, "Using casts to convert enums to integers is deprecated in favour of using 'the_enum.ordinal`."); - sema_expr_convert_enum_to_int(expr); - cast_int_to_int(expr, to_type); + Type *enum_type = type_flatten(expr->type); + Decl *decl = enum_type->decl; + if (!decl->is_substruct) + { + static_assert(ALLOW_DEPRECATED_6, "Fix deprecation"); + SEMA_DEPRECATED(expr, "Using casts to convert enums to integers is deprecated in favour of using 'the_enum.ordinal`, use `inline` on the enum storage type to recover this behaviour."); + sema_expr_convert_enum_to_int(expr); + cast_int_to_int(expr, to_type); + return; + } + if (decl->enums.inline_value) + { + sema_expr_convert_enum_to_int(expr); + cast_int_to_int(expr, to_type); + return; + } + Expr *copy = expr_copy(expr); + expr->expr_kind = EXPR_ACCESS_RESOLVED; + expr->access_resolved_expr.parent = copy; + Decl *member = decl->enums.parameters[decl->enums.inline_index]; + expr->access_resolved_expr.ref = member; + expr->type = type_add_optional(member->type, IS_OPTIONAL(expr)); + if (member->type != to_type) + { + cast_no_check(expr, to_type, IS_OPTIONAL(expr)); + } } /** @@ -2202,7 +2254,7 @@ static void cast_typeid_to_bool(Expr *expr, Type *to_type) { expr_rewrite_int_to #define IN2FP &cast_int_to_float #define IN2PT &cast_int_to_ptr #define IN2EN &cast_int_to_enum -#define EN2IN &cast_enum_to_int +#define EN2XX &cast_enum_to_value #define FP2BO &cast_float_to_bool #define FP2IN &cast_float_to_int #define FP2FP &cast_float_to_float @@ -2260,6 +2312,7 @@ static void cast_typeid_to_bool(Expr *expr, Type *to_type) { expr_rewrite_int_to #define RBSAR &rule_bits_to_arr /* Bits -> arr (explicit + base match) */ #define RBSIN &rule_bits_to_int /* Bits -> int (explicit + size match) */ #define RDIXX &rule_from_distinct /* Distinct -> internal (explicit or inline) */ +#define RENXX &rule_enum_to_value /* Distinct -> internal inline */ #define RDIDI &rule_to_from_distinct /* Distinct -> other distinct */ #define RARVC &rule_arr_to_vec /* Arr -> Vec (len matches, valid elements, flatten if explicit) */ #define RVCAR &rule_vec_to_arr /* Vec -> Arr (len matches, if base can be converted, flatten if explicit) */ @@ -2296,7 +2349,7 @@ CastRule cast_rules[CONV_LAST + 1][CONV_LAST + 1] = { {REXPL, _NO__, REXPL, _NO__, _NO__, REXPL, _NO__, _NO__, _NO__, RXXDI, _NO__, _NO__, _NO__, _NA__, REXPL, _NO__, _NO__, _NO__, _NO__, _NO__, ROKOK, REXPL, _NO__, _NO__}, // ANY {REXPL, _NO__, REXPL, _NO__, _NO__, REXPL, _NO__, _NO__, _NO__, RXXDI, _NO__, _NO__, _NO__, ROKOK, RIFIF, _NO__, _NO__, _NO__, _NO__, _NO__, ROKOK, REXPL, _NO__, _NO__}, // INTERFACE {REXPL, _NO__, REXPL, RPTIN, _NO__, REXPL, _NO__, REXVC, _NO__, RXXDI, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, ROKOK, REXPL, REXPL, _NO__, _NO__}, // FAULT - {REXPL, _NO__, _NO__, REXPL, _NO__, _NO__, _NO__, REXVC, _NO__, RXXDI, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__}, // ENUM + {REXPL, _NO__, RENXX, RENXX, RENXX, RENXX, RENXX, RENXX, RENXX, RENXX, RENXX, RENXX, RENXX, RENXX, RENXX, RENXX, RENXX, RENXX, RENXX, RENXX, RENXX, RENXX, RENXX, _NO__}, // ENUM {REXPL, _NO__, REXPL, RPTIN, _NO__, _NO__, _NO__, REXVC, _NO__, RXXDI, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, RPTPT, _NO__, _NO__, ROKOK, _NO__, _NO__, _NO__}, // FUNC {REXPL, _NO__, REXPL, RPTIN, _NO__, REXPL, _NO__, REXVC, _NO__, RXXDI, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NA__, _NO__, REXPL, REXPL, _NO__, _NO__}, // TYPEID {REXPL, _NO__, REXPL, RPTIN, _NO__, REXPL, _NO__, REXVC, _NO__, RXXDI, _NO__, _NO__, _NO__, _NO__, _NO__, RAFFA, _NO__, _NO__, _NO__, _NA__, REXPL, REXPL, _NO__, _NO__}, // ANYFAULT @@ -2307,31 +2360,31 @@ CastRule cast_rules[CONV_LAST + 1][CONV_LAST + 1] = { }; CastFunction cast_function[CONV_LAST + 1][CONV_LAST + 1] = { -//void, wildcd, bool, int, float, ptr, slice, vec, bitst, dist, array, struct,union, any, infc, fault, enum, func,typeid, anyfa, vptr, aptr, infer, ulist (to) - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // VOID (from) - {XX2XX, 0, XX2XX, XX2XX, XX2XX, XX2XX, XX2XX, XX2XX, XX2XX, 0, XX2XX, XX2XX, XX2XX, XX2XX, XX2XX, XX2XX, XX2XX, XX2XX,XX2XX, XX2XX, XX2XX, XX2XX, 0, 0 }, // WILDCARD - {XX2VO, 0, 0, BO2IN, BO2FP, 0, 0, EX2VC, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // BOOL - {XX2VO, 0, IN2BO, IN2IN, IN2FP, IN2PT, 0, EX2VC, IA2BS, 0, 0, 0, 0, 0, 0, 0, IN2EN, IN2PT, 0, 0, IN2PT, IN2PT, 0, 0 }, // INT - {XX2VO, 0, FP2BO, FP2IN, FP2FP, 0, 0, EX2VC, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // FLOAT - {XX2VO, 0, PT2BO, PT2IN, 0, PT2PT, 0, EX2VC, 0, 0, 0, 0, 0, PT2AY, PT2AY, 0, 0, 0, 0, 0, PT2PT, PT2PT, PT2FE, 0 }, // PTR - {XX2VO, 0, SL2BO, 0, 0, SL2PT, SL2SL, SL2VA, 0, 0, SL2VA, 0, 0, 0, 0, 0, 0, 0, 0, 0, SL2PT, SL2PT, SL2FE, 0 }, // SLICE - {XX2VO, 0, 0, 0, 0, 0, VA2SL, VC2VC, 0, 0, VC2AR, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, VA2FE, 0 }, // VECTOR - {XX2VO, 0, BS2BO, BS2IA, 0, 0, 0, 0, 0, 0, BS2IA, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // BITSTRUCT - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // DISTINCT - {XX2VO, 0, 0, 0, 0, 0, VA2SL, AR2VC, IA2BS, 0, AR2AR, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, VA2FE, 0 }, // ARRAY - {XX2VO, 0, ST2LN, ST2LN, ST2LN, ST2LN, ST2LN, ST2LN, ST2LN, 0, ST2LN, ST2LN, ST2LN, ST2LN, ST2LN, ST2LN, ST2LN, ST2LN,ST2LN, ST2LN, ST2LN, ST2LN, 0, 0 }, // STRUCT - {XX2VO, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // UNION - {XX2VO, 0, AY2BO, 0, 0, AY2PT, 0, 0, 0, 0, 0, 0, 0, PT2PT, PT2PT, 0, 0, 0, 0, 0, AY2PT, AY2PT, 0, 0 }, // ANY - {XX2VO, 0, AY2BO, 0, 0, AY2PT, 0, 0, 0, 0, 0, 0, 0, PT2PT, PT2PT, 0, 0, 0, 0, 0, AY2PT, AY2PT, 0, 0 }, // INTERFACE - {XX2VO, 0, AF2BO, FA2IN, 0, FA2PT, 0, EX2VC, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, FA2AF, FA2PT, FA2PT, 0, 0 }, // FAULT - {XX2VO, 0, 0, EN2IN, 0, 0, 0, EX2VC, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // ENUM - {XX2VO, 0, PT2BO, PT2IN, 0, 0, 0, EX2VC, 0, 0, 0, 0, 0, 0, 0, 0, 0, PT2PT, 0, 0, PT2PT, 0, 0, 0 }, // FUNC - {XX2VO, 0, TI2BO, TI2IN, 0, TI2PT, 0, EX2VC, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, TI2PT, TI2PT, 0, 0 }, // TYPEID - {XX2VO, 0, AF2BO, FA2IN, 0, FA2IN, 0, EX2VC, 0, 0, 0, 0, 0, 0, 0, AF2FA, 0, 0, 0, 0, FA2IN, FA2IN, 0, 0 }, // ANYFAULT - {XX2VO, 0, PT2BO, PT2IN, 0, PT2PT, 0, EX2VC, 0, 0, 0, 0, 0, PT2AY, PT2AY, 0, 0, PT2PT, 0, 0, 0, PT2PT, 0, 0 }, // VOIDPTR - {XX2VO, 0, PT2BO, PT2IN, 0, PT2PT, AP2SL, EX2VC, 0, 0, 0, 0, 0, PT2AY, PT2AY, 0, 0, 0, 0, 0, PT2PT, PT2PT, PT2FE, 0 }, // ARRAYPTR - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // INFERRED - { 0, 0, 0, 0, 0, 0, UL2XX, UL2XX, UL2XX, 0, UL2XX, UL2XX, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, UL2XX, 0 }, // UNTYPED +//void, wildcd, bool, int, float, ptr, slice, vec, bitst, dist, array,struct,union, any, infc, fault, enum, func, typeid, anyfa, vptr, aptr, infer, ulist (to) + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // VOID (from) + {XX2XX, 0, XX2XX, XX2XX, XX2XX, XX2XX, XX2XX, XX2XX, XX2XX, 0, XX2XX, XX2XX, XX2XX, XX2XX, XX2XX, XX2XX, XX2XX, XX2XX, XX2XX, XX2XX, XX2XX, XX2XX, 0, 0 }, // WILDCARD + {XX2VO, 0, 0, BO2IN, BO2FP, 0, 0, EX2VC, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // BOOL + {XX2VO, 0, IN2BO, IN2IN, IN2FP, IN2PT, 0, EX2VC, IA2BS, 0, 0, 0, 0, 0, 0, 0, IN2EN, IN2PT, 0, 0, IN2PT, IN2PT, 0, 0 }, // INT + {XX2VO, 0, FP2BO, FP2IN, FP2FP, 0, 0, EX2VC, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // FLOAT + {XX2VO, 0, PT2BO, PT2IN, 0, PT2PT, 0, EX2VC, 0, 0, 0, 0, 0, PT2AY, PT2AY, 0, 0, 0, 0, 0, PT2PT, PT2PT, PT2FE, 0 }, // PTR + {XX2VO, 0, SL2BO, 0, 0, SL2PT, SL2SL, SL2VA, 0, 0, SL2VA, 0, 0, 0, 0, 0, 0, 0, 0, 0, SL2PT, SL2PT, SL2FE, 0 }, // SLICE + {XX2VO, 0, 0, 0, 0, 0, VA2SL, VC2VC, 0, 0, VC2AR, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, VA2FE, 0 }, // VECTOR + {XX2VO, 0, BS2BO, BS2IA, 0, 0, 0, 0, 0, 0, BS2IA, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // BITSTRUCT + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // DISTINCT + {XX2VO, 0, 0, 0, 0, 0, VA2SL, AR2VC, IA2BS, 0, AR2AR, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, VA2FE, 0 }, // ARRAY + {XX2VO, 0, ST2LN, ST2LN, ST2LN, ST2LN, ST2LN, ST2LN, ST2LN, 0, ST2LN, ST2LN, ST2LN, ST2LN, ST2LN, ST2LN, ST2LN, ST2LN, ST2LN, ST2LN, ST2LN, ST2LN, 0, 0 }, // STRUCT + {XX2VO, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // UNION + {XX2VO, 0, AY2BO, 0, 0, AY2PT, 0, 0, 0, 0, 0, 0, 0, PT2PT, PT2PT, 0, 0, 0, 0, 0, AY2PT, AY2PT, 0, 0 }, // ANY + {XX2VO, 0, AY2BO, 0, 0, AY2PT, 0, 0, 0, 0, 0, 0, 0, PT2PT, PT2PT, 0, 0, 0, 0, 0, AY2PT, AY2PT, 0, 0 }, // INTERFACE + {XX2VO, 0, AF2BO, FA2IN, 0, FA2PT, 0, EX2VC, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, FA2AF, FA2PT, FA2PT, 0, 0 }, // FAULT + {XX2VO, 0, EN2XX, EN2XX, EN2XX, EN2XX, EN2XX, EN2XX, EN2XX, EN2XX, EN2XX, EN2XX, EN2XX, EN2XX, EN2XX, EN2XX, EN2XX, EN2XX, EN2XX, EN2XX, EN2XX, EN2XX, EN2XX, EN2XX }, // ENUM + {XX2VO, 0, PT2BO, PT2IN, 0, 0, 0, EX2VC, 0, 0, 0, 0, 0, 0, 0, 0, 0, PT2PT, 0, 0, PT2PT, 0, 0, 0 }, // FUNC + {XX2VO, 0, TI2BO, TI2IN, 0, TI2PT, 0, EX2VC, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, TI2PT, TI2PT, 0, 0 }, // TYPEID + {XX2VO, 0, AF2BO, FA2IN, 0, FA2IN, 0, EX2VC, 0, 0, 0, 0, 0, 0, 0, AF2FA, 0, 0, 0, 0, FA2IN, FA2IN, 0, 0 }, // ANYFAULT + {XX2VO, 0, PT2BO, PT2IN, 0, PT2PT, 0, EX2VC, 0, 0, 0, 0, 0, PT2AY, PT2AY, 0, 0, PT2PT, 0, 0, 0, PT2PT, 0, 0 }, // VOIDPTR + {XX2VO, 0, PT2BO, PT2IN, 0, PT2PT, AP2SL, EX2VC, 0, 0, 0, 0, 0, PT2AY, PT2AY, 0, 0, 0, 0, 0, PT2PT, PT2PT, PT2FE, 0 }, // ARRAYPTR + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // INFERRED + { 0, 0, 0, 0, 0, 0, UL2XX, UL2XX, UL2XX, 0, UL2XX, UL2XX, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, UL2XX, 0 }, // UNTYPED }; static ConvGroup group_from_type[TYPE_LAST + 1] = { diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index fb96df6d1..1659794b4 100755 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -1463,6 +1463,7 @@ static inline bool sema_analyse_enum(SemaContext *context, Decl *decl, bool *era // Resolve the type of the enum. if (!sema_resolve_type_info(context, decl->enums.type_info, RESOLVE_TYPE_DEFAULT)) return false; + if (decl->enums.inline_index > -1 || decl->enums.inline_value) decl->is_substruct = true; Type *type = decl->enums.type_info->type; ASSERT(!type_is_optional(type) && "Already stopped when parsing."); diff --git a/test/test_suite/enumerations/inline_enums.c3t b/test/test_suite/enumerations/inline_enums.c3t new file mode 100644 index 000000000..bbbbaa011 --- /dev/null +++ b/test/test_suite/enumerations/inline_enums.c3t @@ -0,0 +1,38 @@ +// #target: macos-x64 +module test; + +enum Abc : inline int +{ + ABC, + DEF, +} + +enum Foo : int (inline String name) +{ + ABC = "Hello", + DEF = "World" +} +fn void main() +{ + int a = Abc.DEF; + Foo x = ABC; + Foo y = DEF; + String hello = Foo.ABC; + String world = Foo.DEF; +} +/* #expect: test.ll + +define void @test.main() #0 { +entry: + %a = alloca i32, align 4 + %x = alloca i32, align 4 + %y = alloca i32, align 4 + %hello = alloca %"char[]", align 8 + %world = alloca %"char[]", align 8 + store i32 1, ptr %a, align 4 + store i32 0, ptr %x, align 4 + store i32 1, ptr %y, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %hello, ptr align 8 @"test.Foo$name", i32 16, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %world, ptr align 8 getelementptr inbounds (i8, ptr @"test.Foo$name", i32 16), i32 16, i1 false) + ret void +} diff --git a/test/test_suite/symbols/various.c3 b/test/test_suite/symbols/various.c3 index e42525be9..1218be130 100644 --- a/test/test_suite/symbols/various.c3 +++ b/test/test_suite/symbols/various.c3 @@ -81,8 +81,8 @@ enum Enum : int fn void test11() { - int a = Enum.A; // #error: implicitly be converted - ichar b = Enum.B; // #error: implicitly be converted + int a = Enum.A; // #error: It is not possible to cast + ichar b = Enum.B; // #error: It is not possible to cast } fn void test12()