Browse Source

Fix comparison for bit field values #386

gingerBill 6 years ago
parent
commit
2af19c496e
2 changed files with 59 additions and 38 deletions
  1. 47 0
      src/check_expr.cpp
  2. 12 38
      src/check_stmt.cpp

+ 47 - 0
src/check_expr.cpp

@@ -2552,6 +2552,45 @@ ExactValue convert_exact_value_for_type(ExactValue v, Type *type) {
 	return v;
 	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) {
 void convert_to_typed(CheckerContext *c, Operand *operand, Type *target_type) {
 	GB_ASSERT_NOT_NULL(target_type);
 	GB_ASSERT_NOT_NULL(target_type);
 	if (operand->mode == Addressing_Invalid ||
 	if (operand->mode == Addressing_Invalid ||
@@ -2640,6 +2679,14 @@ void convert_to_typed(CheckerContext *c, Operand *operand, Type *target_type) {
 		break;
 		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:
 	case Type_Union:
 		if (!is_operand_nil(*operand) && !is_operand_undef(*operand)) {
 		if (!is_operand_nil(*operand) && !is_operand_undef(*operand)) {
 			isize count = t->Union.variants.count;
 			isize count = t->Union.variants.count;

+ 12 - 38
src/check_stmt.cpp

@@ -172,6 +172,9 @@ bool check_is_terminating(Ast *node) {
 	return false;
 	return false;
 }
 }
 
 
+
+
+
 Type *check_assignment_variable(CheckerContext *ctx, Operand *lhs, Operand *rhs) {
 Type *check_assignment_variable(CheckerContext *ctx, Operand *lhs, Operand *rhs) {
 	if (rhs->mode == Addressing_Invalid) {
 	if (rhs->mode == Addressing_Invalid) {
 		return nullptr;
 		return nullptr;
@@ -249,48 +252,19 @@ Type *check_assignment_variable(CheckerContext *ctx, Operand *lhs, Operand *rhs)
 	case Addressing_Invalid:
 	case Addressing_Invalid:
 		return nullptr;
 		return nullptr;
 
 
-	case Addressing_Variable: {
+	case Addressing_Variable:
 		if (is_type_bit_field_value(lhs->type)) {
 		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;
 		break;
-	}
 
 
 	case Addressing_MapIndex: {
 	case Addressing_MapIndex: {
 		Ast *ln = unparen_expr(lhs->expr);
 		Ast *ln = unparen_expr(lhs->expr);