Skip to content

Commit

Permalink
Fixes to enum conversions.
Browse files Browse the repository at this point in the history
  • Loading branch information
lerno committed Feb 4, 2025
1 parent fff3cf3 commit 6fcda24
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 18 deletions.
35 changes: 34 additions & 1 deletion src/compiler/compiler_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -2145,7 +2145,7 @@ bool may_cast(SemaContext *context, Expr *expr, Type *to_type, bool is_explicit,

void cast_no_check(Expr *expr, Type *to_type, bool add_optional);

bool cast_to_index(SemaContext *context, Expr *index);
bool cast_to_index_len(SemaContext *context, Expr *index, bool is_len);

const char *llvm_codegen(void *context);
const char *tilde_codegen(void *context);
Expand Down Expand Up @@ -2982,6 +2982,37 @@ static inline Type *type_flat_distinct_inline(Type *type)
return type;
}

static inline Type *type_flat_distinct_enum_inline(Type *type)
{
do
{
type = type->canonical;
Decl *decl;
switch (type->type_kind)
{
case TYPE_DISTINCT:
decl = type->decl;
if (!decl->is_substruct) break;
type = decl->distinct->type;
continue;
case TYPE_ENUM:
decl = type->decl;
if (!decl->is_substruct) break;
if (decl->enums.inline_value)
{
type = decl->enums.type_info->type;
continue;
}
type = decl->enums.parameters[decl->enums.inline_index]->type;
continue;
default:
break;
}
break;
} while (1);
return type;
}

static inline Type *type_flatten_to_int(Type *type)
{
while (1)
Expand All @@ -2999,6 +3030,8 @@ static inline Type *type_flatten_to_int(Type *type)
type = type->decl->strukt.container_type->type;
break;
case TYPE_ENUM:
SEMA_DEPRECATED(type->decl, "Relying on conversion of enums into ordinals is deprecated, use inline on the value instead.");
static_assert(ALLOW_DEPRECATED_6, "Fix deprecation");
type = type->decl->enums.type_info->type;
break;
case TYPE_VECTOR:
Expand Down
16 changes: 8 additions & 8 deletions src/compiler/sema_casts.c
Original file line number Diff line number Diff line change
Expand Up @@ -605,11 +605,11 @@ static void expr_recursively_rewrite_untyped_list(Expr *expr, Type *to_type)
}


bool cast_to_index(SemaContext *context, Expr *index)
bool cast_to_index_len(SemaContext *context, Expr *index, bool is_len)
{
Type *type = index->type;
RETRY:
type = type_flat_distinct_inline(type);
type = type_flat_distinct_enum_inline(type);
type = type_no_optional(type);
switch (type->type_kind)
{
Expand All @@ -624,17 +624,17 @@ bool cast_to_index(SemaContext *context, Expr *index)
case TYPE_U64:
return cast_explicit(context, index, type_usz);
case TYPE_U128:
SEMA_ERROR(index, "You need to explicitly cast this to a uint or ulong.");
return false;
RETURN_SEMA_ERROR(index, "You need to explicitly cast this to a uint or ulong.");
case TYPE_I128:
SEMA_ERROR(index, "You need to explicitly cast this to an int or long.");
return false;
RETURN_SEMA_ERROR(index, "You need to explicitly cast this to an int or long.");
case TYPE_ENUM:
SEMA_DEPRECATED(index, "Implicitly converting enums into an index value is deprecated, use 'inline' on the value type instead.");
static_assert(ALLOW_DEPRECATED_6, "Fix deprecation");
type = type->decl->enums.type_info->type;
goto RETRY;
default:
RETURN_SEMA_ERROR(index, "An integer value was expected here, but it is a value of type %s, which can't be implicitly converted into an integer index.",
type_quoted_error_string(index->type));
RETURN_SEMA_ERROR(index, "An integer value was expected here, but it is a value of type %s, which can't be implicitly converted into an integer %s.",
type_quoted_error_string(index->type), is_len ? "length" : "index");
}
}

Expand Down
12 changes: 6 additions & 6 deletions src/compiler/sema_expr.c
Original file line number Diff line number Diff line change
Expand Up @@ -3188,7 +3188,7 @@ static inline bool sema_expr_analyse_subscript_lvalue(SemaContext *context, Expr
}

// Cast to an appropriate type for index.
if (!cast_to_index(context, index)) return false;
if (!cast_to_index_len(context, index, false)) return false;

optional |= IS_OPTIONAL(index);
// Check range
Expand Down Expand Up @@ -3304,7 +3304,7 @@ static inline bool sema_expr_analyse_subscript(SemaContext *context, Expr *expr,
}

// Cast to an appropriate type for index.
if (!cast_to_index(context, index)) return false;
if (!cast_to_index_len(context, index, false)) return false;

optional |= IS_OPTIONAL(index);
// Check range
Expand Down Expand Up @@ -3418,7 +3418,7 @@ typedef enum RangeEnv
RANGE_FLEXIBLE,
} RangeEnv;

INLINE bool sema_expr_analyse_range_internal(SemaContext *context, Range *range, Type *indexed_type, ArrayIndex len, RangeEnv env)
INLINE bool sema_expr_analyse_range_internal(SemaContext *context, Range *range, ArrayIndex len, RangeEnv env)
{
Expr *start = exprptr(range->start);
ASSERT(start);
Expand All @@ -3427,8 +3427,8 @@ INLINE bool sema_expr_analyse_range_internal(SemaContext *context, Range *range,
if (!sema_analyse_expr(context, start)) return false;
if (end && !sema_analyse_expr(context, end)) return false;

if (!cast_to_index(context, start)) return false;
if (end && !cast_to_index(context, end)) return false;
if (!cast_to_index_len(context, start, false)) return false;
if (end && !cast_to_index_len(context, end, false)) return false;
Type *end_type = end ? type_no_optional(end->type) : NULL;
Type *start_type = type_no_optional(start->type);
if (end && IS_OPTIONAL(end)) range->is_optional = true;
Expand Down Expand Up @@ -3588,7 +3588,7 @@ static inline bool sema_expr_analyse_range(SemaContext *context, Range *range, T
return true;
case RESOLVE_NOT_DONE:
range->status = RESOLVE_RUNNING;
if (!sema_expr_analyse_range_internal(context, range, indexed_type, len, env))
if (!sema_expr_analyse_range_internal(context, range, len, env))
{
range->status = RESOLVE_NOT_DONE;
return false;
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/sema_initializers.c
Original file line number Diff line number Diff line change
Expand Up @@ -1300,7 +1300,7 @@ static ArrayIndex sema_analyse_designator_index(SemaContext *context, Expr *inde
}

// Unless we already have type_usz, cast to type_isz;
if (!cast_to_index(context, index))
if (!cast_to_index_len(context, index, false))
{
return -1;
}
Expand Down
4 changes: 3 additions & 1 deletion src/compiler/sema_types.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ bool sema_resolve_array_like_len(SemaContext *context, TypeInfo *type_info, Arra
Expr *len_expr = type_info->array.len;

// Analyse it.
if (!sema_analyse_expr_rhs(context, type_isz, len_expr, false, NULL, false)) return type_info_poison(type_info);
if (!sema_analyse_expr(context, len_expr)) return type_info_poison(type_info);

if (!cast_to_index_len(context, len_expr, true)) return type_info_poison(type_info);

// A constant expression is assumed.
if (!sema_cast_const(len_expr))
Expand Down
2 changes: 1 addition & 1 deletion test/test_suite/arrays/global_array_non_const.c3
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const int CONSTANT = 1;
int[CONSTANT] a2;
int[3] a3 = { [CONSTANT] = 1 };
const bool B = true;
int[B] c2; // #error: cannot implicitly be converted
int[B] c2; // #error: be implicitly converted

int non_constant = 10;
int[non_constant] b; // #error: Expected a constant value as
Expand Down

0 comments on commit 6fcda24

Please sign in to comment.