Browse Source

Fix range in statement bug caused by incorrectly assigned addressing mode #461

gingerBill 5 years ago
parent
commit
dbdbbcd60f
4 changed files with 11 additions and 90 deletions
  1. 1 1
      src/check_expr.cpp
  2. 5 71
      src/check_stmt.cpp
  3. 3 1
      src/checker.cpp
  4. 2 17
      src/ir.cpp

+ 1 - 1
src/check_expr.cpp

@@ -6739,7 +6739,7 @@ bool check_range(CheckerContext *c, Ast *node, Operand *x, Operand *y, ExactValu
 		}
 		}
 
 
 		if (inline_for_depth_) *inline_for_depth_ = inline_for_depth;
 		if (inline_for_depth_) *inline_for_depth_ = inline_for_depth;
-	} else {
+	} else if (inline_for_depth_ != nullptr) {
 		error(ie->op, "Interval expressions must be constant");
 		error(ie->op, "Interval expressions must be constant");
 		return false;
 		return false;
 	}
 	}

+ 5 - 71
src/check_stmt.cpp

@@ -1476,80 +1476,14 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) {
 
 
 		if (is_ast_range(expr)) {
 		if (is_ast_range(expr)) {
 			ast_node(ie, BinaryExpr, expr);
 			ast_node(ie, BinaryExpr, expr);
-			Operand x = {Addressing_Invalid};
-			Operand y = {Addressing_Invalid};
-
-			check_expr(ctx, &x, ie->left);
-			if (x.mode == Addressing_Invalid) {
-				goto skip_expr_range_stmt;
-			}
-			check_expr(ctx, &y, ie->right);
-			if (y.mode == Addressing_Invalid) {
-				goto skip_expr_range_stmt;
-			}
-
-			convert_to_typed(ctx, &x, y.type);
-			if (x.mode == Addressing_Invalid) {
-				goto skip_expr_range_stmt;
-			}
-			convert_to_typed(ctx, &y, x.type);
-			if (y.mode == Addressing_Invalid) {
-				goto skip_expr_range_stmt;
-			}
-
-			convert_to_typed(ctx, &x, default_type(y.type));
-			if (x.mode == Addressing_Invalid) {
-				goto skip_expr_range_stmt;
-			}
-			convert_to_typed(ctx, &y, default_type(x.type));
-			if (y.mode == Addressing_Invalid) {
-				goto skip_expr_range_stmt;
-			}
-
-			if (!are_types_identical(x.type, y.type)) {
-				if (x.type != t_invalid &&
-				    y.type != t_invalid) {
-					gbString xt = type_to_string(x.type);
-					gbString yt = type_to_string(y.type);
-					gbString expr_str = expr_to_string(x.expr);
-					error(ie->op, "Mismatched types in interval expression '%s' : '%s' vs '%s'", expr_str, xt, yt);
-					gb_string_free(expr_str);
-					gb_string_free(yt);
-					gb_string_free(xt);
-				}
-				goto skip_expr_range_stmt;
-			}
+			Operand x = {};
+			Operand y = {};
 
 
-			Type *type = x.type;
-			if (!is_type_integer(type) && !is_type_float(type) && !is_type_pointer(type) && !is_type_enum(type)) {
-				error(ie->op, "Only numerical and pointer types are allowed within interval expressions");
+			bool ok = check_range(ctx, expr, &x, &y, nullptr);
+			if (!ok) {
 				goto skip_expr_range_stmt;
 				goto skip_expr_range_stmt;
 			}
 			}
-
-			if (x.mode == Addressing_Constant &&
-			    y.mode == Addressing_Constant) {
-				ExactValue a = x.value;
-				ExactValue b = y.value;
-
-				GB_ASSERT(are_types_identical(x.type, y.type));
-
-				TokenKind op = Token_Lt;
-				switch (ie->op.kind) {
-				case Token_Ellipsis:  op = Token_LtEq; break;
-				case Token_RangeHalf: op = Token_Lt; break;
-				default: error(ie->op, "Invalid range operator"); break;
-				}
-				bool ok = compare_exact_values(op, a, b);
-				if (!ok) {
-					// TODO(bill): Better error message
-					error(ie->op, "Invalid interval range");
-					goto skip_expr_range_stmt;
-				}
-			}
-
-			add_type_and_value(&ctx->checker->info, ie->left,  x.mode, x.type, x.value);
-			add_type_and_value(&ctx->checker->info, ie->right, y.mode, y.type, y.value);
-			val0 = type;
+			val0 = x.type;
 			val1 = t_int;
 			val1 = t_int;
 		} else {
 		} else {
 			Operand operand = {Addressing_Invalid};
 			Operand operand = {Addressing_Invalid};

+ 3 - 1
src/checker.cpp

@@ -1033,7 +1033,9 @@ void add_type_and_value(CheckerInfo *i, Ast *expr, AddressingMode mode, Type *ty
 
 
 	expr->tav.mode = mode;
 	expr->tav.mode = mode;
 	expr->tav.type = type;
 	expr->tav.type = type;
-	expr->tav.value = value;
+	if (mode == Addressing_Constant || mode == Addressing_Invalid) {
+		expr->tav.value = value;
+	}
 }
 }
 
 
 void add_entity_definition(CheckerInfo *i, Ast *identifier, Entity *entity) {
 void add_entity_definition(CheckerInfo *i, Ast *identifier, Entity *entity) {

+ 2 - 17
src/ir.cpp

@@ -6613,22 +6613,6 @@ irValue *ir_build_expr_internal(irProcedure *proc, Ast *expr) {
 	GB_ASSERT(tv.mode != Addressing_Invalid);
 	GB_ASSERT(tv.mode != Addressing_Invalid);
 	GB_ASSERT(tv.mode != Addressing_Type);
 	GB_ASSERT(tv.mode != Addressing_Type);
 
 
-	#if 0
-	if (tv.mode == Addressing_Type) {
-		// // TODO(bill): Handle this correctly
-		#if 0
-		i32 entry_index = ir_type_info_index(proc->module->info, tv.type, false);
-		if (entry_index >= 0) {
-			return ir_get_type_info_ptr(proc, tv.type);
-			// i32 id = entry_index+1;
-			// return ir_value_constant(t_int, exact_value_i64(id));
-		}
-		#endif
-		// return v_raw_nil;
-		return ir_value_nil(tv.type);
-	}
-	#endif
-
 	if (tv.value.kind != ExactValue_Invalid) {
 	if (tv.value.kind != ExactValue_Invalid) {
 		// NOTE(bill): Edge case
 		// NOTE(bill): Edge case
 		if (tv.value.kind != ExactValue_Compound &&
 		if (tv.value.kind != ExactValue_Compound &&
@@ -8686,7 +8670,8 @@ void ir_build_range_interval(irProcedure *proc, AstBinaryExpr *node, Type *val_t
 
 
 	upper = ir_build_expr(proc, node->right);
 	upper = ir_build_expr(proc, node->right);
 
 
-	irValue *cond = ir_emit_comp(proc, op, ir_emit_load(proc, value), upper);
+	irValue *curr_value = ir_emit_load(proc, value);
+	irValue *cond = ir_emit_comp(proc, op, curr_value, upper);
 	ir_emit_if(proc, cond, body, done);
 	ir_emit_if(proc, cond, body, done);
 	ir_start_block(proc, body);
 	ir_start_block(proc, body);