Add inline to enums #1819.

This commit is contained in:
Christoffer Lerno
2025-02-03 22:51:44 +01:00
parent 70a849cbb5
commit 9d2f4e72c2
8 changed files with 156 additions and 39 deletions

View File

@@ -16,6 +16,7 @@
- Compile time array inc/dec. - Compile time array inc/dec.
- Improve error message when using ',' in struct declarations. #1920 - Improve error message when using ',' in struct declarations. #1920
- Compile time array assign ops, e.g. `$c[1] += 3` #1890. - Compile time array assign ops, e.g. `$c[1] += 3` #1890.
- Add `inline` to enums #1819.
### Fixes ### Fixes
- Fix issue requiring prefix on a generic interface declaration. - Fix issue requiring prefix on a generic interface declaration.

View File

@@ -514,6 +514,7 @@ identifier_list
enum_param_decl enum_param_decl
: type IDENT : type IDENT
| INLINE type IDENT
; ;
base_type base_type
@@ -1045,9 +1046,12 @@ struct_member_decl
| INLINE type opt_attributes ';' | INLINE type opt_attributes ';'
; ;
enum_spec enum_spec
: ':' base_type '(' enum_params ')' : ':' base_type '(' enum_params ')'
| ':' INLINE base_type '(' enum_params ')'
| ':' base_type | ':' base_type
| ':' INLINE base_type
| ':' '(' enum_params ')' | ':' '(' enum_params ')'
; ;

View File

@@ -474,6 +474,8 @@ typedef struct
Decl** values; Decl** values;
Decl** parameters; Decl** parameters;
TypeInfo *type_info; TypeInfo *type_info;
int16_t inline_index;
bool inline_value;
} EnumDecl; } EnumDecl;
struct Signature_ struct Signature_

View File

@@ -15,7 +15,7 @@ typedef enum FunctionParse_
static inline Decl *parse_func_definition(ParseContext *c, AstId contracts, FunctionParse parse_kind); 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_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_include(ParseContext *c);
static Decl *parse_exec(ParseContext *c); static Decl *parse_exec(ParseContext *c);
static bool parse_attributes_for_global(ParseContext *c, Decl *decl); 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? * 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); 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."); if (type->optional) RETURN_PRINT_ERROR_AT(false, type, "Parameters may not be optional.");
Decl *param = decl_new_var_current(c, type, VARDECL_PARAM); 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* ')' * 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 no left parenthesis we're done.
if (!try_consume(c, TOKEN_LPAREN)) return true; if (!try_consume(c, TOKEN_LPAREN)) return true;
ArrayIndex index = -1;
while (!try_consume(c, TOKEN_RPAREN)) 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); Decl *last_parameter = VECLAST(*parameters_ref);
ASSERT(last_parameter); ASSERT(last_parameter);
last_parameter->var.index = vec_size(*parameters_ref) - 1; // NOLINT 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; TypeInfo *type = NULL;
bool val_is_inline = false;
ArrayIndex inline_index = -1;
if (try_consume(c, TOKEN_COLON)) if (try_consume(c, TOKEN_COLON))
{ {
if (!tok_is(c, TOKEN_LPAREN) && !tok_is(c, TOKEN_LBRACE)) 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); ASSIGN_TYPE_OR_RET(type, parse_optional_type(c), poisoned_decl);
if (type->optional) if (type->optional)
{ {
RETURN_PRINT_ERROR_AT(poisoned_decl, type, "An enum can't have an optional type."); 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; 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); CONSUME_OR_RET(TOKEN_LBRACE, poisoned_decl);
decl->enums.type_info = type ? type : type_info_new_base(type_int, decl->span); 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)) while (!try_consume(c, TOKEN_RBRACE))
{ {
Decl *enum_const = decl_new(DECL_ENUM_CONSTANT, symstr(c), c->span); Decl *enum_const = decl_new(DECL_ENUM_CONSTANT, symstr(c), c->span);

View File

@@ -1430,6 +1430,36 @@ static bool rule_int_to_enum(CastContext *cc, bool is_explicit, bool is_silent)
return true; 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) static bool rule_bits_to_arr(CastContext *cc, bool is_explicit, bool is_silent)
{ {
if (is_silent && !is_explicit) return false; 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); 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"); Type *enum_type = type_flatten(expr->type);
SEMA_DEPRECATED(expr, "Using casts to convert enums to integers is deprecated in favour of using 'the_enum.ordinal`."); Decl *decl = enum_type->decl;
sema_expr_convert_enum_to_int(expr); if (!decl->is_substruct)
cast_int_to_int(expr, 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`, 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 IN2FP &cast_int_to_float
#define IN2PT &cast_int_to_ptr #define IN2PT &cast_int_to_ptr
#define IN2EN &cast_int_to_enum #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 FP2BO &cast_float_to_bool
#define FP2IN &cast_float_to_int #define FP2IN &cast_float_to_int
#define FP2FP &cast_float_to_float #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 RBSAR &rule_bits_to_arr /* Bits -> arr (explicit + base match) */
#define RBSIN &rule_bits_to_int /* Bits -> int (explicit + size match) */ #define RBSIN &rule_bits_to_int /* Bits -> int (explicit + size match) */
#define RDIXX &rule_from_distinct /* Distinct -> internal (explicit or inline) */ #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 RDIDI &rule_to_from_distinct /* Distinct -> other distinct */
#define RARVC &rule_arr_to_vec /* Arr -> Vec (len matches, valid elements, flatten if explicit) */ #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) */ #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__, _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, _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__, 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__, _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__, _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 {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] = { 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) //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) {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 {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, 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, 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, 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, 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, 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, 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 {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 { 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, 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, 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, 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 }, // 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, 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, 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, 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, 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, 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, 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, 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 {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, 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 { 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] = { static ConvGroup group_from_type[TYPE_LAST + 1] = {

View File

@@ -1463,6 +1463,7 @@ static inline bool sema_analyse_enum(SemaContext *context, Decl *decl, bool *era
// Resolve the type of the enum. // Resolve the type of the enum.
if (!sema_resolve_type_info(context, decl->enums.type_info, RESOLVE_TYPE_DEFAULT)) return false; 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; Type *type = decl->enums.type_info->type;
ASSERT(!type_is_optional(type) && "Already stopped when parsing."); ASSERT(!type_is_optional(type) && "Already stopped when parsing.");

View File

@@ -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
}

View File

@@ -81,8 +81,8 @@ enum Enum : int
fn void test11() fn void test11()
{ {
int a = Enum.A; // #error: implicitly be converted int a = Enum.A; // #error: It is not possible to cast
ichar b = Enum.B; // #error: implicitly be converted ichar b = Enum.B; // #error: It is not possible to cast
} }
fn void test12() fn void test12()