|
|
|
|
@@ -645,8 +645,6 @@ static bool sema_binary_is_expr_lvalue(SemaContext *context, Expr *top_expr, Exp
|
|
|
|
|
case EXPR_LAMBDA:
|
|
|
|
|
if (failed_ref) goto FAILED_REF;
|
|
|
|
|
RETURN_SEMA_ERROR(expr, "This expression is a value and cannot be assigned to.");
|
|
|
|
|
case EXPR_CT_IDENT:
|
|
|
|
|
return true;
|
|
|
|
|
case EXPR_EXT_TRUNC:
|
|
|
|
|
case EXPR_INT_TO_BOOL:
|
|
|
|
|
case EXPR_DISCARD:
|
|
|
|
|
@@ -799,7 +797,6 @@ static bool expr_may_ref(Expr *expr)
|
|
|
|
|
{
|
|
|
|
|
case EXPR_SWIZZLE:
|
|
|
|
|
case EXPR_LAMBDA:
|
|
|
|
|
case EXPR_CT_IDENT:
|
|
|
|
|
case EXPR_DEFAULT_ARG:
|
|
|
|
|
case EXPR_TYPECALL:
|
|
|
|
|
case EXPR_MEMBER_GET:
|
|
|
|
|
@@ -835,18 +832,18 @@ static bool expr_may_ref(Expr *expr)
|
|
|
|
|
decl = decl_raw(decl);
|
|
|
|
|
switch (decl->var.kind)
|
|
|
|
|
{
|
|
|
|
|
case VARDECL_LOCAL_CT:
|
|
|
|
|
case VARDECL_LOCAL_CT_TYPE:
|
|
|
|
|
case VARDECL_LOCAL:
|
|
|
|
|
case VARDECL_GLOBAL:
|
|
|
|
|
case VARDECL_PARAM:
|
|
|
|
|
case VARDECL_PARAM_CT:
|
|
|
|
|
case VARDECL_PARAM_CT_TYPE:
|
|
|
|
|
return true;
|
|
|
|
|
case VARDECL_CONST:
|
|
|
|
|
case VARDECL_PARAM_EXPR:
|
|
|
|
|
case VARDECL_MEMBER:
|
|
|
|
|
case VARDECL_BITMEMBER:
|
|
|
|
|
case VARDECL_LOCAL_CT:
|
|
|
|
|
case VARDECL_LOCAL_CT_TYPE:
|
|
|
|
|
case VARDECL_PARAM_CT:
|
|
|
|
|
case VARDECL_PARAM_CT_TYPE:
|
|
|
|
|
return false;
|
|
|
|
|
case VARDECL_UNWRAPPED:
|
|
|
|
|
case VARDECL_ERASE:
|
|
|
|
|
@@ -1035,15 +1032,14 @@ static inline bool sema_cast_ident_rvalue(SemaContext *context, Expr *expr)
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
case VARDECL_PARAM_EXPR:
|
|
|
|
|
case VARDECL_ERASE:
|
|
|
|
|
case VARDECL_REWRAPPED:
|
|
|
|
|
UNREACHABLE
|
|
|
|
|
case VARDECL_PARAM_CT_TYPE:
|
|
|
|
|
case VARDECL_PARAM_CT:
|
|
|
|
|
case VARDECL_LOCAL_CT:
|
|
|
|
|
case VARDECL_LOCAL_CT_TYPE:
|
|
|
|
|
case VARDECL_ERASE:
|
|
|
|
|
case VARDECL_REWRAPPED:
|
|
|
|
|
// Impossible to reach this, they are already unfolded
|
|
|
|
|
UNREACHABLE
|
|
|
|
|
return sema_cast_ct_ident_rvalue(context, expr);
|
|
|
|
|
case VARDECL_LOCAL:
|
|
|
|
|
if (decl->var.copy_const && decl->var.init_expr && expr_is_const(decl->var.init_expr))
|
|
|
|
|
{
|
|
|
|
|
@@ -1393,9 +1389,9 @@ static inline bool sema_expr_resolve_ct_identifier(SemaContext *context, Expr *e
|
|
|
|
|
ASSERT_SPAN(expr, decl->resolve_status == RESOLVE_DONE);
|
|
|
|
|
|
|
|
|
|
decl->var.is_read = true;
|
|
|
|
|
expr->ct_ident_expr.decl = decl;
|
|
|
|
|
expr->type = decl->type;
|
|
|
|
|
|
|
|
|
|
expr->ident_expr = decl;
|
|
|
|
|
expr->expr_kind = EXPR_IDENTIFIER;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -4095,7 +4091,7 @@ static inline bool sema_expr_resolve_subscript_index(SemaContext *context, Expr
|
|
|
|
|
}
|
|
|
|
|
ArrayIndex size;
|
|
|
|
|
bool check_len = !context->call_env.in_no_eval || current_type == type_untypedlist;
|
|
|
|
|
Expr *len_expr = current_expr->expr_kind == EXPR_CT_IDENT ? current_expr->ct_ident_expr.decl->var.init_expr : current_expr;
|
|
|
|
|
Expr *len_expr = expr_is_ct_ident(current_expr) ? current_expr->ident_expr->var.init_expr : current_expr;
|
|
|
|
|
if (sema_cast_const(index) && expr_is_const_int(index) && (size = sema_len_from_expr(len_expr)) >= 0)
|
|
|
|
|
{
|
|
|
|
|
// 4c. And that it's in range.
|
|
|
|
|
@@ -4219,7 +4215,7 @@ DEFAULT:
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 4. If we are indexing into a complist
|
|
|
|
|
if (current_expr->expr_kind == EXPR_CT_IDENT)
|
|
|
|
|
if (expr_is_ct_ident(current_expr))
|
|
|
|
|
{
|
|
|
|
|
if (index_value == -1)
|
|
|
|
|
{
|
|
|
|
|
@@ -4227,7 +4223,7 @@ DEFAULT:
|
|
|
|
|
RETURN_SEMA_ERROR(index, "Assigning to a compile time constant requires a constant index.");
|
|
|
|
|
}
|
|
|
|
|
expr->expr_kind = EXPR_CT_SUBSCRIPT;
|
|
|
|
|
expr->ct_subscript_expr = (ExprCtSubscript) { .var = current_expr->ct_ident_expr.decl, .index = (ArrayIndex)index_value };
|
|
|
|
|
expr->ct_subscript_expr = (ExprCtSubscript) { .var = current_expr->ident_expr, .index = (ArrayIndex)index_value };
|
|
|
|
|
expr->type = NULL;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
@@ -4327,7 +4323,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 (current_expr->expr_kind == EXPR_CT_IDENT) current_expr = current_expr->ct_ident_expr.decl->var.init_expr;
|
|
|
|
|
while (expr_is_ct_ident(current_expr)) current_expr = current_expr->ident_expr->var.init_expr;
|
|
|
|
|
|
|
|
|
|
// 4b. Now we need to check that we actually have a valid type.
|
|
|
|
|
if (index_value < 0)
|
|
|
|
|
@@ -7085,7 +7081,7 @@ static bool sema_expr_analyse_ct_identifier_assign(SemaContext *context, Expr *e
|
|
|
|
|
if (failed_ref) return *failed_ref = true, false;
|
|
|
|
|
RETURN_SEMA_ERROR(right, "You can only assign constants to a compile time variable.");
|
|
|
|
|
}
|
|
|
|
|
Decl *ident = left->ct_ident_expr.decl;
|
|
|
|
|
Decl *ident = left->ident_expr;
|
|
|
|
|
|
|
|
|
|
ident->var.init_expr = right;
|
|
|
|
|
expr_replace(expr, right);
|
|
|
|
|
@@ -7194,7 +7190,8 @@ static bool sema_expr_analyse_assign(SemaContext *context, Expr *expr, Expr *lef
|
|
|
|
|
if (!sema_analyse_expr_lvalue(context, left, failed_ref)) return false;
|
|
|
|
|
switch (left->expr_kind)
|
|
|
|
|
{
|
|
|
|
|
case EXPR_CT_IDENT:
|
|
|
|
|
case EXPR_IDENTIFIER:
|
|
|
|
|
if (!expr_is_ct_ident(left)) break;
|
|
|
|
|
// $foo = ...
|
|
|
|
|
return sema_expr_analyse_ct_identifier_assign(context, expr, left, right, failed_ref);
|
|
|
|
|
case EXPR_CT_SUBSCRIPT:
|
|
|
|
|
@@ -7258,9 +7255,9 @@ static bool sema_expr_analyse_assign(SemaContext *context, Expr *expr, Expr *lef
|
|
|
|
|
*/
|
|
|
|
|
static bool sema_binary_analyse_ct_op_assign(SemaContext *context, Expr *expr, Expr *left)
|
|
|
|
|
{
|
|
|
|
|
ASSERT_SPAN(left, left->expr_kind == EXPR_CT_IDENT);
|
|
|
|
|
ASSERT_SPAN(left, expr_is_ct_ident(left));
|
|
|
|
|
|
|
|
|
|
Decl *left_var = left->ct_ident_expr.decl;
|
|
|
|
|
Decl *left_var = left->ident_expr;
|
|
|
|
|
if (!sema_cast_ct_ident_rvalue(context, left)) return false;
|
|
|
|
|
|
|
|
|
|
expr->binary_expr.operator = binaryop_assign_base_op(expr->binary_expr.operator);
|
|
|
|
|
@@ -7508,7 +7505,8 @@ static bool sema_expr_analyse_op_assign(SemaContext *context, Expr *expr, Expr *
|
|
|
|
|
|
|
|
|
|
switch (left->expr_kind)
|
|
|
|
|
{
|
|
|
|
|
case EXPR_CT_IDENT:
|
|
|
|
|
case EXPR_IDENTIFIER:
|
|
|
|
|
if (!expr_is_ct_ident(left)) break;
|
|
|
|
|
return sema_binary_analyse_ct_op_assign(context, expr, left);
|
|
|
|
|
case EXPR_CT_SUBSCRIPT:
|
|
|
|
|
return sema_binary_analyse_ct_subscript_op_assign(context, expr, left);
|
|
|
|
|
@@ -9037,8 +9035,7 @@ static inline const char *sema_addr_may_take_of_var(Expr *expr, Decl *decl)
|
|
|
|
|
case VARDECL_PARAM_CT_TYPE:
|
|
|
|
|
case VARDECL_LOCAL_CT_TYPE:
|
|
|
|
|
case VARDECL_LOCAL_CT:
|
|
|
|
|
// May not be reached due to EXPR_CT_IDENT being handled elsewhere.
|
|
|
|
|
UNREACHABLE
|
|
|
|
|
return "It's not possible to take the address of a compile time value.";
|
|
|
|
|
case VARDECL_MEMBER:
|
|
|
|
|
case VARDECL_BITMEMBER:
|
|
|
|
|
case VARDECL_UNWRAPPED:
|
|
|
|
|
@@ -9086,8 +9083,6 @@ static const char *sema_addr_check_may_take(Expr *inner)
|
|
|
|
|
{
|
|
|
|
|
case UNRESOLVED_EXPRS:
|
|
|
|
|
UNREACHABLE
|
|
|
|
|
case EXPR_CT_IDENT:
|
|
|
|
|
return "It's not possible to take the address of a compile time value.";
|
|
|
|
|
case EXPR_IDENTIFIER:
|
|
|
|
|
return sema_addr_may_take_of_ident(inner);
|
|
|
|
|
case EXPR_UNARY:
|
|
|
|
|
@@ -9159,17 +9154,21 @@ RETRY:;
|
|
|
|
|
case EXPR_ACCESS_UNRESOLVED:
|
|
|
|
|
inner->access_unresolved_expr.is_ref = true;
|
|
|
|
|
break;
|
|
|
|
|
case EXPR_CT_IDENT:
|
|
|
|
|
RETURN_SEMA_ERROR(expr, "It's not possible to take the address of a compile time value.");
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
RESOLVED:
|
|
|
|
|
if (inner->expr_kind == EXPR_CT_IDENT)
|
|
|
|
|
|
|
|
|
|
if (!sema_analyse_expr(context, inner)) return false;
|
|
|
|
|
|
|
|
|
|
RESOLVED:
|
|
|
|
|
|
|
|
|
|
if (expr_is_ct_ident(inner))
|
|
|
|
|
{
|
|
|
|
|
RETURN_SEMA_ERROR(expr, "It's not possible to take the address of a compile time value.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!sema_analyse_expr(context, inner)) return false;
|
|
|
|
|
|
|
|
|
|
// 2. Take the address.
|
|
|
|
|
const char *error = sema_addr_check_may_take(inner);
|
|
|
|
|
if (error)
|
|
|
|
|
@@ -9439,9 +9438,9 @@ static inline bool sema_expr_analyse_ct_subscript_incdec(SemaContext *context, E
|
|
|
|
|
|
|
|
|
|
static inline bool sema_expr_analyse_ct_incdec(SemaContext *context, Expr *expr, Expr *inner)
|
|
|
|
|
{
|
|
|
|
|
ASSERT_SPAN(expr, inner->expr_kind == EXPR_CT_IDENT);
|
|
|
|
|
ASSERT_SPAN(expr, expr_is_ct_ident(inner));
|
|
|
|
|
|
|
|
|
|
Decl *var = inner->ct_ident_expr.decl;
|
|
|
|
|
Decl *var = inner->ident_expr;
|
|
|
|
|
Expr *start_value = var->var.init_expr;
|
|
|
|
|
if (!expr_is_const_int(start_value))
|
|
|
|
|
{
|
|
|
|
|
@@ -9565,7 +9564,7 @@ static inline bool sema_expr_analyse_incdec(SemaContext *context, Expr *expr)
|
|
|
|
|
if (!sema_expr_check_assign(context, inner, NULL)) return false;
|
|
|
|
|
|
|
|
|
|
// 3. This might be a $foo, if to handle it.
|
|
|
|
|
if (inner->expr_kind == EXPR_CT_IDENT)
|
|
|
|
|
if (expr_is_ct_ident(inner))
|
|
|
|
|
{
|
|
|
|
|
return sema_expr_analyse_ct_incdec(context, expr, inner);
|
|
|
|
|
}
|
|
|
|
|
@@ -12079,7 +12078,7 @@ NO_MATCH_REF:
|
|
|
|
|
|
|
|
|
|
static inline bool sema_cast_ct_ident_rvalue(SemaContext *context, Expr *expr)
|
|
|
|
|
{
|
|
|
|
|
Decl *decl = expr->ct_ident_expr.decl;
|
|
|
|
|
Decl *decl = expr->ident_expr;
|
|
|
|
|
Expr *copy = copy_expr_single(decl->var.init_expr);
|
|
|
|
|
if (!copy)
|
|
|
|
|
{
|
|
|
|
|
@@ -12137,8 +12136,7 @@ static inline bool sema_cast_rvalue(SemaContext *context, Expr *expr, bool mutat
|
|
|
|
|
}
|
|
|
|
|
UNREACHABLE
|
|
|
|
|
case EXPR_CT_IDENT:
|
|
|
|
|
if (mutate && !sema_cast_ct_ident_rvalue(context, expr)) return false;
|
|
|
|
|
break;
|
|
|
|
|
UNREACHABLE
|
|
|
|
|
case EXPR_IDENTIFIER:
|
|
|
|
|
if (mutate && !sema_cast_ident_rvalue(context, expr)) return false;
|
|
|
|
|
break;
|
|
|
|
|
|