diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index c88e25416..a83ab6932 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -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);