mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Add inline to enums #1819.
This commit is contained in:
@@ -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.
|
||||||
|
|||||||
@@ -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 ')'
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|||||||
@@ -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_
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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] = {
|
||||||
|
|||||||
@@ -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.");
|
||||||
|
|
||||||
|
|||||||
38
test/test_suite/enumerations/inline_enums.c3t
Normal file
38
test/test_suite/enumerations/inline_enums.c3t
Normal 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
|
||||||
|
}
|
||||||
@@ -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()
|
||||||
|
|||||||
Reference in New Issue
Block a user