aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2019-06-21 22:48:37 +0100
committergingerBill <bill@gingerbill.org>2019-06-21 22:48:37 +0100
commit2af19c496e4fa1c01ea218df16d8162307d8419d (patch)
tree83937fd29926ca2cd9290f6a2f37877f5830a7d3 /src
parentfea34b32eab88c1cd4a3af031b5fcf1cec616aec (diff)
Fix comparison for bit field values #386
Diffstat (limited to 'src')
-rw-r--r--src/check_expr.cpp47
-rw-r--r--src/check_stmt.cpp50
2 files changed, 59 insertions, 38 deletions
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index be135ce68..2cb462b9a 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -2552,6 +2552,45 @@ ExactValue convert_exact_value_for_type(ExactValue v, Type *type) {
return v;
}
+Type *check_assignment_bit_field(CheckerContext *ctx, Operand *operand, Type *target_type) {
+ if (is_type_bit_field_value(target_type)) {
+ Type *lt = base_type(target_type);
+ i64 lhs_bits = lt->BitFieldValue.bits;
+ if (operand->mode == Addressing_Constant) {
+ ExactValue v = exact_value_to_integer(operand->value);
+ if (v.kind == ExactValue_Integer) {
+ BigInt i = v.value_integer;
+ if (!i.neg) {
+ u64 imax_ = ~cast(u64)0ull;
+ if (lhs_bits < 64) {
+ imax_ = (1ull << cast(u64)lhs_bits) - 1ull;
+ }
+
+ BigInt imax = big_int_make_u64(imax_);
+ if (big_int_cmp(&i, &imax) <= 0) {
+ return operand->type;
+ }
+ }
+ } else if (operand->value.kind == ExactValue_Bool) {
+ bool b = operand->value.value_bool;
+ if (lhs_bits == 1) {
+ return operand->type;
+ }
+ }
+ } else if (is_type_integer(operand->type)) {
+ // TODO(bill): Any other checks?
+ return operand->type;
+ } else if (is_type_boolean(operand->type)) {
+ if (lhs_bits == 1) {
+ return operand->type;
+ }
+ }
+ return nullptr;
+ }
+
+ return nullptr;
+}
+
void convert_to_typed(CheckerContext *c, Operand *operand, Type *target_type) {
GB_ASSERT_NOT_NULL(target_type);
if (operand->mode == Addressing_Invalid ||
@@ -2640,6 +2679,14 @@ void convert_to_typed(CheckerContext *c, Operand *operand, Type *target_type) {
break;
}
+ case Type_BitFieldValue: {
+ Type *res = check_assignment_bit_field(c, operand, target_type);
+ if (res == nullptr) {
+ convert_untyped_error(c, operand, target_type);
+ }
+ break;
+ }
+
case Type_Union:
if (!is_operand_nil(*operand) && !is_operand_undef(*operand)) {
isize count = t->Union.variants.count;
diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp
index 9a62f4beb..a14aeeaaf 100644
--- a/src/check_stmt.cpp
+++ b/src/check_stmt.cpp
@@ -172,6 +172,9 @@ bool check_is_terminating(Ast *node) {
return false;
}
+
+
+
Type *check_assignment_variable(CheckerContext *ctx, Operand *lhs, Operand *rhs) {
if (rhs->mode == Addressing_Invalid) {
return nullptr;
@@ -249,48 +252,19 @@ Type *check_assignment_variable(CheckerContext *ctx, Operand *lhs, Operand *rhs)
case Addressing_Invalid:
return nullptr;
- case Addressing_Variable: {
+ case Addressing_Variable:
if (is_type_bit_field_value(lhs->type)) {
- Type *lt = base_type(lhs->type);
- i64 lhs_bits = lt->BitFieldValue.bits;
- if (rhs->mode == Addressing_Constant) {
- ExactValue v = exact_value_to_integer(rhs->value);
- if (v.kind == ExactValue_Integer) {
- BigInt i = v.value_integer;
- if (!i.neg) {
- u64 imax_ = ~cast(u64)0ull;
- if (lhs_bits < 64) {
- imax_ = (1ull << cast(u64)lhs_bits) - 1ull;
- }
-
- BigInt imax = big_int_make_u64(imax_);
- if (big_int_cmp(&i, &imax) <= 0) {
- return rhs->type;
- }
- }
- } else if (rhs->value.kind == ExactValue_Bool) {
- bool b = rhs->value.value_bool;
- if (lhs_bits == 1) {
- return rhs->type;
- }
- }
- } else if (is_type_integer(rhs->type)) {
- // TODO(bill): Any other checks?
- return rhs->type;
- } else if (is_type_boolean(rhs->type)) {
- if (lhs_bits == 1) {
- return rhs->type;
- }
+ Type *res = check_assignment_bit_field(ctx, rhs, lhs->type);
+ if (res == nullptr) {
+ gbString lhs_expr = expr_to_string(lhs->expr);
+ gbString rhs_expr = expr_to_string(rhs->expr);
+ error(rhs->expr, "Cannot assign '%s' to bit field '%s'", rhs_expr, lhs_expr);
+ gb_string_free(rhs_expr);
+ gb_string_free(lhs_expr);
}
- gbString lhs_expr = expr_to_string(lhs->expr);
- gbString rhs_expr = expr_to_string(rhs->expr);
- error(rhs->expr, "Cannot assign '%s' to bit field '%s'", rhs_expr, lhs_expr);
- gb_string_free(rhs_expr);
- gb_string_free(lhs_expr);
- return nullptr;
+ return res;
}
break;
- }
case Addressing_MapIndex: {
Ast *ln = unparen_expr(lhs->expr);