aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/check_expr.cpp144
1 files changed, 62 insertions, 82 deletions
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index fcdabedde..9a776ad08 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -3086,126 +3086,106 @@ gb_internal void check_shift(CheckerContext *c, Operand *x, Operand *y, Ast *nod
GB_ASSERT(node->kind == Ast_BinaryExpr);
ast_node(be, BinaryExpr, node);
- ExactValue x_val = {};
- if (x->mode == Addressing_Constant) {
- x_val = exact_value_to_integer(x->value);
+ bool y_is_untyped = is_type_untyped(y->type);
+ if (y_is_untyped) {
+ convert_to_typed(c, y, t_untyped_integer);
+ if (y->mode == Addressing_Invalid) {
+ x->mode = Addressing_Invalid;
+ return;
+ }
+ } else if (!is_type_unsigned(y->type)) {
+ gbString y_str = expr_to_string(y->expr);
+ error(y->expr, "Shift amount '%s' must be an unsigned integer", y_str);
+ gb_string_free(y_str);
+ x->mode = Addressing_Invalid;
+ return;
}
bool x_is_untyped = is_type_untyped(x->type);
- if (!(is_type_integer(x->type) || (x_is_untyped && x_val.kind == ExactValue_Integer))) {
- gbString err_str = expr_to_string(x->expr);
- error(node, "Shifted operand '%s' must be an integer", err_str);
- gb_string_free(err_str);
+ if (!(x_is_untyped || is_type_integer(x->type))) {
+ gbString x_str = expr_to_string(x->expr);
+ error(x->expr, "Shifted operand '%s' must be an integer", x_str);
+ gb_string_free(x_str);
x->mode = Addressing_Invalid;
return;
}
- if (is_type_unsigned(y->type)) {
-
- } else if (is_type_untyped(y->type)) {
- convert_to_typed(c, y, t_untyped_integer);
- if (y->mode == Addressing_Invalid) {
+ if (y->mode == Addressing_Constant) {
+ if (big_int_is_neg(&y->value.value_integer)) {
+ gbString y_str = expr_to_string(y->expr);
+ error(y->expr, "Shift amount '%s' cannot be negative", y_str);
+ gb_string_free(y_str);
x->mode = Addressing_Invalid;
return;
}
- } else {
- gbString err_str = expr_to_string(y->expr);
- error(node, "Shift amount '%s' must be an unsigned integer", err_str);
- gb_string_free(err_str);
- x->mode = Addressing_Invalid;
- return;
- }
+ BigInt max_shift = {};
+ big_int_from_u64(&max_shift, MAX_BIG_INT_SHIFT);
- if (x->mode == Addressing_Constant) {
- if (y->mode == Addressing_Constant) {
- ExactValue y_val = exact_value_to_integer(y->value);
- if (y_val.kind != ExactValue_Integer) {
- gbString err_str = expr_to_string(y->expr);
- error(node, "Shift amount '%s' must be an unsigned integer", err_str);
- gb_string_free(err_str);
- x->mode = Addressing_Invalid;
- return;
- }
+ if (big_int_cmp(&y->value.value_integer, &max_shift) > 0) {
+ gbString y_str = expr_to_string(y->expr);
+ error(y->expr, "Shift amount '%s' must be <= %u", y_str, MAX_BIG_INT_SHIFT);
+ gb_string_free(y_str);
+ x->mode = Addressing_Invalid;
+ return;
+ }
- BigInt max_shift = {};
- big_int_from_u64(&max_shift, MAX_BIG_INT_SHIFT);
+ if (x->mode == Addressing_Constant) {
+ if (x_is_untyped) {
+ convert_to_typed(c, x, t_untyped_integer);
+ if (x->mode == Addressing_Invalid) {
+ return;
+ }
- if (big_int_cmp(&y_val.value_integer, &max_shift) > 0) {
- gbString err_str = expr_to_string(y->expr);
- error(node, "Shift amount too large: '%s'", err_str);
- gb_string_free(err_str);
- x->mode = Addressing_Invalid;
- return;
- }
+ x->expr = node;
+ x->value = exact_value_shift(be->op.kind, exact_value_to_integer(x->value), exact_value_to_integer(y->value));
- if (!is_type_integer(x->type)) {
- // NOTE(bill): It could be an untyped float but still representable
- // as an integer
- x->type = t_untyped_integer;
+ return;
}
x->expr = node;
- x->value = exact_value_shift(be->op.kind, x_val, y_val);
+ x->value = exact_value_shift(be->op.kind, x->value, y->value);
+ check_is_expressible(c, x, x->type);
- if (is_type_typed(x->type)) {
- check_is_expressible(c, x, x->type);
- }
return;
}
- TokenPos pos = ast_token(x->expr).pos;
+ if (y_is_untyped) {
+ convert_to_typed(c, y, t_uint);
+ }
+
+ return;
+ }
+
+ if (x->mode == Addressing_Constant) {
if (x_is_untyped) {
- if (x->expr != nullptr) {
- x->expr->tav.is_lhs = true;
- }
- x->mode = Addressing_Value;
if (type_hint) {
if (is_type_integer(type_hint)) {
convert_to_typed(c, x, type_hint);
+ } else if (is_type_any(type_hint)) {
+ convert_to_typed(c, x, default_type(t_untyped_integer));
} else {
gbString x_str = expr_to_string(x->expr);
- gbString to_type = type_to_string(type_hint);
- error(node, "Conversion of shifted operand '%s' to '%s' is not allowed", x_str, to_type);
+ gbString type_str = type_to_string(type_hint);
+ error(x->expr, "Shifted operand '%s' cannot convert to non-integer type '%s'", x_str, type_str);
gb_string_free(x_str);
- gb_string_free(to_type);
+ gb_string_free(type_str);
x->mode = Addressing_Invalid;
+ return;
}
- } else if (!is_type_integer(x->type)) {
- gbString x_str = expr_to_string(x->expr);
- error(node, "Non-integer shifted operand '%s' is not allowed", x_str);
- gb_string_free(x_str);
- x->mode = Addressing_Invalid;
+ } else {
+ check_is_expressible(c, x, default_type(t_untyped_integer));
+ }
+ if (x->mode == Addressing_Invalid) {
+ return;
}
- // x->value = x_val;
- return;
}
- }
-
- if (y->mode == Addressing_Constant && big_int_is_neg(&y->value.value_integer)) {
- gbString err_str = expr_to_string(y->expr);
- error(node, "Shift amount cannot be negative: '%s'", err_str);
- gb_string_free(err_str);
- }
-
- if (!is_type_integer(x->type)) {
- gbString err_str = expr_to_string(x->expr);
- error(node, "Shift operand '%s' must be an integer", err_str);
- gb_string_free(err_str);
- x->mode = Addressing_Invalid;
- return;
- }
- if (is_type_untyped(y->type)) {
- convert_to_typed(c, y, t_uint);
+ x->mode = Addressing_Value;
}
-
- x->mode = Addressing_Value;
}
-
-
gb_internal bool check_is_castable_to(CheckerContext *c, Operand *operand, Type *y) {
if (check_is_assignable_to(c, operand, y)) {
return true;