Browse Source

[analyzer] deal with unreachable block in binops

closes #11402
Simon Krajewski 1 year ago
parent
commit
7653f686cd
2 changed files with 97 additions and 10 deletions
  1. 19 10
      src/optimization/analyzerTexprTransformer.ml
  2. 78 0
      tests/unit/src/unit/issues/Issue11402.hx

+ 19 - 10
src/optimization/analyzerTexprTransformer.ml

@@ -118,11 +118,15 @@ let rec func ctx bb tf t p =
 			let bb,e2 = value bb e2 in
 			bb,{e with eexpr = TBinop(op,e1,e2)}
 		| TBinop(op,e1,e2) ->
-			let bb,e1,e2 = match ordered_value_list bb [e1;e2] with
-				| bb,[e1;e2] -> bb,e1,e2
-				| _ -> die "" __LOC__
-			in
-			bb,{e with eexpr = TBinop(op,e1,e2)}
+			begin match ordered_value_list bb [e1;e2] with
+				| bb,[e1;e2] ->
+					bb,{e with eexpr = TBinop(op,e1,e2)}
+				| bb,[e] ->
+					assert(bb == g.g_unreachable);
+					bb,e
+				| _ ->
+					die "" __LOC__
+				end
 		| TUnop(op,flag,e1) ->
 			let bb,e1 = value bb e1 in
 			bb,{e with eexpr = TUnop(op,flag,e1)}
@@ -139,11 +143,16 @@ let rec func ctx bb tf t p =
 			let bb,e1 = value bb e1 in
 			bb,{e with eexpr = TField(e1,fa)}
 		| TArray(e1,e2) ->
-			let bb,e1,e2 = match ordered_value_list bb [e1;e2] with
-				| bb,[e1;e2] -> bb,e1,e2
-				| _ -> die "" __LOC__
-			in
-			bb,{e with eexpr = TArray(e1,e2)}
+			begin match ordered_value_list bb [e1;e2] with
+				| bb,[e1;e2] ->
+					bb,{e with eexpr = TArray(e1,e2)}
+
+				| bb,[e] ->
+					assert(bb == g.g_unreachable);
+					bb,e
+				| _ ->
+					die "" __LOC__
+				end
 		| TMeta(m,e1) ->
 			let bb,e1 = value bb e1 in
 			bb,{e with eexpr = TMeta(m,e1)}

+ 78 - 0
tests/unit/src/unit/issues/Issue11402.hx

@@ -0,0 +1,78 @@
+package unit.issues;
+
+class Issue11402 extends Test {
+	static function binopWithReturn() {
+		var ans = Std.string(return "") + "";
+	}
+
+	static function binopWithThrow() {
+		var ans = Std.string(throw "") + "";
+	}
+
+	static function binopWithBreak() {
+		while (true) {
+			var ans = Std.string(break) + "";
+			return "b";
+		}
+		return "a";
+	}
+
+	static function binopWithContinue() {
+		var a = 0;
+		while (true) {
+			if (a++ > 0) {
+				return "a";
+			}
+			var ans = Std.string(continue) + "";
+			return "b";
+		}
+	}
+
+	static function arrayWithReturn() {
+		var ans = [Std.string(return "")][0];
+	}
+
+	static function arrayWithThrow() {
+		var ans = [Std.string(throw "")][0];
+	}
+
+	static function arrayWithBreak() {
+		while (true) {
+			var ans = [Std.string(break)][0];
+			return "b";
+		}
+		return "a";
+	}
+
+	static function arrayWithContinue() {
+		var a = 0;
+		while (true) {
+			if (a++ > 0) {
+				return "a";
+			}
+			var ans = [Std.string(continue)][0];
+			return "b";
+		}
+	}
+
+	static function originalExample() {
+		var cells = [1, 2, 3];
+		var ans = "";
+		ans += '${cells.length} cell${if (cells.length == 1) {return "";} else {return "s";}}.\n';
+		return ans;
+	}
+
+	function test() {
+		eq("", binopWithReturn());
+		exc(binopWithThrow);
+		eq("a", binopWithBreak());
+		eq("a", binopWithContinue());
+
+		eq("", arrayWithReturn());
+		exc(arrayWithThrow);
+		eq("a", arrayWithBreak());
+		eq("a", arrayWithContinue());
+
+		eq("s", originalExample());
+	}
+}