浏览代码

deal with `if (throw)` situations (closes #6315)

Simon Krajewski 8 年之前
父节点
当前提交
a70630cd7e
共有 2 个文件被更改,包括 61 次插入28 次删除
  1. 36 28
      src/optimization/analyzerTexprTransformer.ml
  2. 25 0
      tests/unit/src/unit/issues/Issue6315.hx

+ 36 - 28
src/optimization/analyzerTexprTransformer.ml

@@ -385,39 +385,47 @@ let rec func ctx bb tf t p =
 			end
 		| TIf(e1,e2,None) ->
 			let bb,e1 = bind_to_temp bb false e1 in
-			let bb_then = create_node BKConditional e2.etype e2.epos in
-			add_texpr bb (wrap_meta ":cond-branch" e1);
-			add_cfg_edge bb bb_then (CFGCondBranch (mk (TConst (TBool true)) ctx.com.basic.tbool e2.epos));
-			let bb_then_next = block bb_then e2 in
-			let bb_next = create_node BKNormal bb.bb_type bb.bb_pos in
-			set_syntax_edge bb (SEIfThen(bb_then,bb_next,e.epos));
-			add_cfg_edge bb bb_next CFGCondElse;
-			close_node g bb;
-			add_cfg_edge bb_then_next bb_next CFGGoto;
-			close_node g bb_then_next;
-			bb_next
-		| TIf(e1,e2,Some e3) ->
-			let bb,e1 = bind_to_temp bb false e1 in
-			let bb_then = create_node BKConditional e2.etype e2.epos in
-			let bb_else = create_node BKConditional e3.etype e3.epos in
-			add_texpr bb (wrap_meta ":cond-branch" e1);
-			add_cfg_edge bb bb_then (CFGCondBranch (mk (TConst (TBool true)) ctx.com.basic.tbool e2.epos));
-			add_cfg_edge bb bb_else CFGCondElse;
-			close_node g bb;
-			let bb_then_next = block bb_then e2 in
-			let bb_else_next = block bb_else e3 in
-			if bb_then_next == g.g_unreachable && bb_else_next == g.g_unreachable then begin
-				set_syntax_edge bb (SEIfThenElse(bb_then,bb_else,g.g_unreachable,e.etype,e.epos));
-				g.g_unreachable
-			end else begin
+			if bb == g.g_unreachable then
+				bb
+			else begin
+				let bb_then = create_node BKConditional e2.etype e2.epos in
+				add_texpr bb (wrap_meta ":cond-branch" e1);
+				add_cfg_edge bb bb_then (CFGCondBranch (mk (TConst (TBool true)) ctx.com.basic.tbool e2.epos));
+				let bb_then_next = block bb_then e2 in
 				let bb_next = create_node BKNormal bb.bb_type bb.bb_pos in
-				set_syntax_edge bb (SEIfThenElse(bb_then,bb_else,bb_next,e.etype,e.epos));
+				set_syntax_edge bb (SEIfThen(bb_then,bb_next,e.epos));
+				add_cfg_edge bb bb_next CFGCondElse;
+				close_node g bb;
 				add_cfg_edge bb_then_next bb_next CFGGoto;
-				add_cfg_edge bb_else_next bb_next CFGGoto;
 				close_node g bb_then_next;
-				close_node g bb_else_next;
 				bb_next
 			end
+		| TIf(e1,e2,Some e3) ->
+			let bb,e1 = bind_to_temp bb false e1 in
+			if bb == g.g_unreachable then
+				bb
+			else begin
+				let bb_then = create_node BKConditional e2.etype e2.epos in
+				let bb_else = create_node BKConditional e3.etype e3.epos in
+				add_texpr bb (wrap_meta ":cond-branch" e1);
+				add_cfg_edge bb bb_then (CFGCondBranch (mk (TConst (TBool true)) ctx.com.basic.tbool e2.epos));
+				add_cfg_edge bb bb_else CFGCondElse;
+				close_node g bb;
+				let bb_then_next = block bb_then e2 in
+				let bb_else_next = block bb_else e3 in
+				if bb_then_next == g.g_unreachable && bb_else_next == g.g_unreachable then begin
+					set_syntax_edge bb (SEIfThenElse(bb_then,bb_else,g.g_unreachable,e.etype,e.epos));
+					g.g_unreachable
+				end else begin
+					let bb_next = create_node BKNormal bb.bb_type bb.bb_pos in
+					set_syntax_edge bb (SEIfThenElse(bb_then,bb_else,bb_next,e.etype,e.epos));
+					add_cfg_edge bb_then_next bb_next CFGGoto;
+					add_cfg_edge bb_else_next bb_next CFGGoto;
+					close_node g bb_then_next;
+					close_node g bb_else_next;
+					bb_next
+				end
+			end
 		| TSwitch(e1,cases,edef) ->
 			let is_exhaustive = edef <> None || is_exhaustive e1 in
 			let bb,e1 = bind_to_temp bb false e1 in

+ 25 - 0
tests/unit/src/unit/issues/Issue6315.hx

@@ -0,0 +1,25 @@
+package unit.issues;
+
+class Issue6315 extends unit.Test {
+	function test() {
+		try if(throw "ok") { } catch(e:Dynamic) { }
+		try if(throw "ok") { } else { } catch(e:Dynamic) { }
+		try switch throw "ok" { case _: } catch(e:Dynamic) { }
+
+		try if(return "ok") { } catch(e:Dynamic) { }
+		try if(return "ok") { } else { } catch(e:Dynamic) { }
+		try switch return "ok" { case _: } catch(e:Dynamic) { }
+
+		while (true) {
+			try if(break) { } catch(e:Dynamic) { }
+			try if(break) { } else { } catch(e:Dynamic) { }
+			try switch break { case _: } catch(e:Dynamic) { }
+
+			try if(continue) { } catch(e:Dynamic) { }
+			try if(continue) { } else { } catch(e:Dynamic) { }
+			try switch continue { case _: } catch(e:Dynamic) { }
+		}
+
+		return "";
+	}
+}