mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Correctly handle known length slices with index checks.
This commit is contained in:
@@ -170,7 +170,6 @@ static inline void sema_create_const_membersof(SemaContext *context, Expr *expr,
|
||||
AlignSize offset);
|
||||
static inline void sema_create_const_methodsof(SemaContext *context, Expr *expr, Type *type);
|
||||
|
||||
static inline int64_t expr_get_index_max(Expr *expr);
|
||||
static inline bool expr_both_any_integer_or_integer_vector(Expr *left, Expr *right);
|
||||
static inline bool expr_both_any_integer_or_integer_bool_vector(Expr *left, Expr *right);
|
||||
static inline bool expr_both_const(Expr *left, Expr *right);
|
||||
@@ -3075,8 +3074,9 @@ static inline bool sema_expr_analyse_subscript(SemaContext *context, Expr *expr,
|
||||
"and flexible array members.");
|
||||
}
|
||||
|
||||
int64_t size;
|
||||
if (expr_is_const_int(index) && (size = expr_get_index_max(subscripted)) >= 0)
|
||||
ArrayIndex size;
|
||||
bool check_len = !context->call_env.in_no_eval || current_type == type_untypedlist;
|
||||
if (check_len && expr_is_const_int(index) && (size = sema_len_from_expr(current_expr)) >= 0)
|
||||
{
|
||||
// 4c. And that it's in range.
|
||||
if (int_is_neg(index->const_expr.ixx))
|
||||
@@ -3124,7 +3124,7 @@ static inline bool sema_expr_analyse_subscript(SemaContext *context, Expr *expr,
|
||||
RETURN_SEMA_ERROR(subscripted, "You need to use && to take the address of a temporary.");
|
||||
}
|
||||
// 4a. This may either be an initializer list or a CT value
|
||||
while (subscripted->expr_kind == EXPR_CT_IDENT) current_expr = current_expr->ct_ident_expr.decl->var.init_expr;
|
||||
while (current_expr->expr_kind == EXPR_CT_IDENT) current_expr = current_expr->ct_ident_expr.decl->var.init_expr;
|
||||
|
||||
// 4b. Now we need to check that we actually have a valid type.
|
||||
if (index_value < 0)
|
||||
@@ -3132,7 +3132,10 @@ static inline bool sema_expr_analyse_subscript(SemaContext *context, Expr *expr,
|
||||
if (check_valid) goto VALID_FAIL_POISON;
|
||||
RETURN_SEMA_ERROR(index, "To subscript an untyped list a compile time integer index is needed.");
|
||||
}
|
||||
if (check == CHECK_LVALUE) TODO;
|
||||
if (check == CHECK_LVALUE)
|
||||
{
|
||||
REMINDER("Fix LVALUE");
|
||||
}
|
||||
expr_replace(expr, current_expr->const_expr.untyped_list[index_value]);
|
||||
return true;
|
||||
}
|
||||
@@ -9260,13 +9263,19 @@ static inline bool sema_expr_analyse_castable(SemaContext *context, Expr *expr)
|
||||
{
|
||||
ASSERT_SPAN(expr, expr->resolve_status == RESOLVE_RUNNING);
|
||||
TypeInfo *type_info = type_infoptr(expr->castable_expr.type);
|
||||
if (!sema_resolve_type_info(context, type_info, RESOLVE_TYPE_ALLOW_INFER)) return false;
|
||||
bool in_no_eval = context->call_env.in_no_eval;
|
||||
context->call_env.in_no_eval = true;
|
||||
if (!sema_resolve_type_info(context, type_info, RESOLVE_TYPE_ALLOW_INFER)) goto FAILED;
|
||||
Type *type = type_info->type;
|
||||
Expr *inner = exprptr(expr->castable_expr.expr);
|
||||
if (!sema_analyse_inferred_expr(context, type, inner)) return false;
|
||||
if (!sema_analyse_inferred_expr(context, type, inner)) goto FAILED;
|
||||
bool ok = may_cast(context, inner, type, !expr->castable_expr.is_assign, true);
|
||||
expr_rewrite_const_bool(expr, type_bool, ok);
|
||||
context->call_env.in_no_eval = in_no_eval;
|
||||
return true;
|
||||
FAILED:
|
||||
context->call_env.in_no_eval = in_no_eval;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -9870,24 +9879,28 @@ bool sema_analyse_expr_value(SemaContext *context, Expr *expr)
|
||||
}
|
||||
}
|
||||
|
||||
#define RESOLVE(expr__, check__) \
|
||||
do { \
|
||||
Expr *expr_temp__ = expr__; \
|
||||
switch (expr_temp__->resolve_status) { \
|
||||
case RESOLVE_NOT_DONE: \
|
||||
expr_temp__->resolve_status = RESOLVE_RUNNING; \
|
||||
if (!check__) return expr_poison(expr_temp__); \
|
||||
expr_temp__->resolve_status = RESOLVE_DONE; \
|
||||
return true; \
|
||||
case RESOLVE_RUNNING: \
|
||||
SEMA_ERROR(expr, "Recursive resolution of expression"); \
|
||||
return expr_poison(expr_temp__); \
|
||||
case RESOLVE_DONE: \
|
||||
return expr_ok(expr_temp__); \
|
||||
default: \
|
||||
UNREACHABLE \
|
||||
} } while (0);
|
||||
|
||||
|
||||
static inline bool sema_analyse_expr_check(SemaContext *context, Expr *expr, CheckType check)
|
||||
{
|
||||
ASSERT0(expr);
|
||||
switch (expr->resolve_status)
|
||||
{
|
||||
case RESOLVE_NOT_DONE:
|
||||
expr->resolve_status = RESOLVE_RUNNING;
|
||||
if (!sema_analyse_expr_dispatch(context, expr, check)) return expr_poison(expr);
|
||||
expr->resolve_status = RESOLVE_DONE;
|
||||
return true;
|
||||
case RESOLVE_RUNNING:
|
||||
SEMA_ERROR(expr, "Recursive resolution of expression");
|
||||
return expr_poison(expr);
|
||||
case RESOLVE_DONE:
|
||||
return expr_ok(expr);
|
||||
default:
|
||||
UNREACHABLE
|
||||
}
|
||||
RESOLVE(expr, sema_analyse_expr_dispatch(context, expr, check));
|
||||
}
|
||||
|
||||
bool sema_analyse_expr_address(SemaContext *context, Expr *expr)
|
||||
@@ -10029,36 +10042,6 @@ bool sema_cast_const(Expr *expr)
|
||||
UNREACHABLE
|
||||
}
|
||||
|
||||
static inline int64_t expr_get_index_max(Expr *expr)
|
||||
{
|
||||
if (expr_is_const_untyped_list(expr))
|
||||
{
|
||||
return vec_size(expr->const_expr.untyped_list);
|
||||
}
|
||||
Type *type = expr->type;
|
||||
RETRY:
|
||||
switch (type->type_kind)
|
||||
{
|
||||
case TYPE_TYPEDEF:
|
||||
type = type->canonical;
|
||||
goto RETRY;
|
||||
case TYPE_DISTINCT:
|
||||
type = type->decl->distinct->type;
|
||||
goto RETRY;
|
||||
case TYPE_UNTYPED_LIST:
|
||||
UNREACHABLE;
|
||||
case TYPE_ARRAY:
|
||||
case TYPE_VECTOR:
|
||||
return type->array.len;
|
||||
case TYPE_OPTIONAL:
|
||||
type = type->optional;
|
||||
goto RETRY;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
UNREACHABLE
|
||||
}
|
||||
|
||||
bool sema_analyse_inferred_expr(SemaContext *context, Type *infer_type, Expr *expr)
|
||||
{
|
||||
infer_type = type_no_optional(infer_type);
|
||||
|
||||
Reference in New Issue
Block a user