[vala] Fix binary operations between nullable types



commit 2d45d82676ea741c56c7f681a5ac792d1767ac0c
Author: Luca Bruno <lucabru src gnome org>
Date:   Sat Apr 9 12:22:04 2011 +0200

    Fix binary operations between nullable types
    
    Based on patch by Geert Jordaens.
    
    Fixes bug 591552.

 codegen/valaccodebasemodule.vala |    2 +-
 tests/Makefile.am                |    1 +
 tests/basic-types/bug591552.vala |   27 +++++++++++++++++++++++++++
 vala/valabinaryexpression.vala   |   37 +++++++++++++++++++++++++------------
 4 files changed, 54 insertions(+), 13 deletions(-)
---
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index bed29d4..3b69357 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -4818,7 +4818,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
 		if (expr.chained) {
 			var lbe = (BinaryExpression) expr.left;
 
-			var temp_decl = get_temp_variable (lbe.right.value_type, true, null, false);
+			var temp_decl = get_temp_variable (lbe.right.target_type, true, null, false);
 			emit_temp_var (temp_decl);
 			var cvar = get_variable_cexpression (temp_decl.name);
 			var clbe = (CCodeBinaryExpression) get_cvalue (lbe);
diff --git a/tests/Makefile.am b/tests/Makefile.am
index f4bb5c1..c3c90d3 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -20,6 +20,7 @@ TESTS = \
 	basic-types/strings.vala \
 	basic-types/arrays.vala \
 	basic-types/pointers.vala \
+	basic-types/bug591552.vala \
 	basic-types/bug595751.vala \
 	basic-types/bug596637.vala \
 	basic-types/bug596785.vala \
diff --git a/tests/basic-types/bug591552.vala b/tests/basic-types/bug591552.vala
new file mode 100644
index 0000000..e51a48c
--- /dev/null
+++ b/tests/basic-types/bug591552.vala
@@ -0,0 +1,27 @@
+void main () {
+	int a = 1, b = 2;
+	int? c = 3, d = 4;
+	bool? test = null;
+
+	a = 1; b = 2;
+	c = 3; d = 4;
+	test = false;
+
+	a = a + b;
+	a = b - c;
+	a = c & d;
+	c = a ^ b;
+	c = b | c;
+	c = c % d;
+
+	d %= c;
+	c |= a & d;
+
+	test = c in d;
+	test = b > d;
+	test = test || test;
+	test = b > c > d < a;
+
+	test = a == c;
+	test = c == d;
+}
diff --git a/vala/valabinaryexpression.vala b/vala/valabinaryexpression.vala
index 0b46104..2cddc2f 100644
--- a/vala/valabinaryexpression.vala
+++ b/vala/valabinaryexpression.vala
@@ -243,6 +243,11 @@ public class Vala.BinaryExpression : Expression {
 			return false;
 		}
 
+		left.target_type = left.value_type.copy ();
+		left.target_type.value_owned = false;
+		right.target_type = right.value_type.copy ();
+		right.target_type.value_owned = false;
+
 		if (left.value_type.data_type == context.analyzer.string_type.data_type
 		    && operator == BinaryOperator.PLUS) {
 			// string concatenation
@@ -319,10 +324,13 @@ public class Vala.BinaryExpression : Expression {
 						value_type = context.analyzer.size_t_type;
 					}
 				}
+			} else {
+				left.target_type.nullable = false;
+				right.target_type.nullable = false;
 			}
 
 			if (value_type == null) {
-				value_type = context.analyzer.get_arithmetic_result_type (left.value_type, right.value_type);
+				value_type = context.analyzer.get_arithmetic_result_type (left.target_type, right.target_type);
 			}
 
 			if (value_type == null) {
@@ -334,7 +342,10 @@ public class Vala.BinaryExpression : Expression {
 			   || operator == BinaryOperator.SHIFT_LEFT
 			   || operator == BinaryOperator.SHIFT_RIGHT
 			   || operator == BinaryOperator.BITWISE_XOR) {
-			value_type = context.analyzer.get_arithmetic_result_type (left.value_type, right.value_type);
+			left.target_type.nullable = false;
+			right.target_type.nullable = false;
+
+			value_type = context.analyzer.get_arithmetic_result_type (left.target_type, right.target_type);
 
 			if (value_type == null) {
 				error = true;
@@ -353,11 +364,14 @@ public class Vala.BinaryExpression : Expression {
 			} else {
 				DataType resulting_type;
 
+				left.target_type.nullable = false;
+				right.target_type.nullable = false;
+
 				if (chained) {
 					var lbe = (BinaryExpression) left;
-					resulting_type = context.analyzer.get_arithmetic_result_type (lbe.right.value_type, right.value_type);
+					resulting_type = context.analyzer.get_arithmetic_result_type (lbe.right.target_type, right.target_type);
 				} else {
-					resulting_type = context.analyzer.get_arithmetic_result_type (left.value_type, right.value_type);
+					resulting_type = context.analyzer.get_arithmetic_result_type (left.target_type, right.target_type);
 				}
 
 				if (resulting_type == null) {
@@ -365,13 +379,6 @@ public class Vala.BinaryExpression : Expression {
 					Report.error (source_reference, "Relational operation not supported for types `%s' and `%s'".printf (left.value_type.to_string (), right.value_type.to_string ()));
 					return false;
 				}
-
-				left.target_type = left.value_type.copy ();
-				left.target_type.nullable = false;
-				left.target_type.value_owned = false;
-				right.target_type = right.value_type.copy ();
-				right.target_type.nullable = false;
-				right.target_type.value_owned = false;
 			}
 
 			value_type = context.analyzer.bool_type;
@@ -424,20 +431,26 @@ public class Vala.BinaryExpression : Expression {
 		} else if (operator == BinaryOperator.BITWISE_AND
 			   || operator == BinaryOperator.BITWISE_OR) {
 			// integer type or flags type
+			left.target_type.nullable = false;
+			right.target_type.nullable = false;
 
-			value_type = left.value_type;
+			value_type = left.target_type.copy ();
 		} else if (operator == BinaryOperator.AND
 			   || operator == BinaryOperator.OR) {
 			if (!left.value_type.compatible (context.analyzer.bool_type) || !right.value_type.compatible (context.analyzer.bool_type)) {
 				error = true;
 				Report.error (source_reference, "Operands must be boolean");
 			}
+			left.target_type.nullable = false;
+			right.target_type.nullable = false;
 
 			value_type = context.analyzer.bool_type;
 		} else if (operator == BinaryOperator.IN) {
 			if (left.value_type.compatible (context.analyzer.int_type)
 			    && right.value_type.compatible (context.analyzer.int_type)) {
 				// integers or enums
+				left.target_type.nullable = false;
+				right.target_type.nullable = false;
 			} else if (right.value_type is ArrayType) {
 				if (!left.value_type.compatible (((ArrayType) right.value_type).element_type)) {
 					Report.error (source_reference, "Cannot look for `%s' in `%s'".printf (left.value_type.to_string (), right.value_type.to_string ()));



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]