diff --git a/src/generators/hlopt.ml b/src/generators/hlopt.ml index 79fb79203c0..c56b7e5010d 100644 --- a/src/generators/hlopt.ml +++ b/src/generators/hlopt.ml @@ -47,6 +47,7 @@ type block = { mutable bneed : ISet.t; mutable bneed_all : ISet.t option; mutable bwrite : (int, int) PMap.t; + mutable btrap : int list; } type control = @@ -54,6 +55,7 @@ type control = | CJCond of int | CJAlways of int | CTry of int + | CCatch | CSwitch of int array | CRet | CThrow @@ -75,6 +77,8 @@ let control = function CSwitch cases | OTrap (_,d) -> CTry d + | OEndTrap _ -> + CCatch | _ -> CNo @@ -460,7 +464,7 @@ let code_graph (f:fundecl) = | CJAlways d | CJCond d -> Hashtbl.replace all_blocks (i + 1 + d) true | _ -> () done; - let rec make_block pos = + let rec make_block trapl pos = try Hashtbl.find blocks_pos pos with Not_found -> @@ -474,11 +478,12 @@ let code_graph (f:fundecl) = bneed = ISet.empty; bwrite = PMap.empty; bneed_all = None; + btrap = trapl; } in Hashtbl.add blocks_pos pos b; let rec loop i = - let goto d = - let b2 = make_block (i + 1 + d) in + let goto ?(tl=b.btrap) d = + let b2 = make_block tl (i + 1 + d) in b2.bprev <- b :: b2.bprev; b2 in @@ -488,7 +493,8 @@ let code_graph (f:fundecl) = end else match control (op i) with | CNo -> loop (i + 1) - | CRet | CThrow -> + | CRet -> + assert(b.btrap = []); b.bend <- i | CJAlways d -> b.bend <- i; @@ -496,9 +502,27 @@ let code_graph (f:fundecl) = | CSwitch pl -> b.bend <- i; b.bnext <- goto 0 :: Array.to_list (Array.map goto pl) - | CJCond d | CTry d -> + | CJCond d -> b.bend <- i; b.bnext <- [goto 0; goto d]; + | CTry d -> + b.bend <- i; + b.bnext <- [goto ~tl:((i+1+d)::b.btrap) 0; goto d]; + | CThrow -> + b.bend <- i; + match b.btrap with + | [] -> () + | [p] -> b.bnext <- [goto ~tl:[] (p-1-i)]; + | p :: pl -> b.bnext <- [goto ~tl:pl (p-1-i)]; + ; + | CCatch -> + let p, pl = match b.btrap with + | [] -> assert false; + | [p] -> p, [] + | p :: pl -> p, pl + in + b.bend <- i; + b.bnext <- [goto ~tl:pl 0; goto ~tl:pl (p-1-i)]; | CLabel -> b.bloop <- true; loop (i + 1) @@ -506,7 +530,7 @@ let code_graph (f:fundecl) = loop pos; b in - blocks_pos, make_block 0 + blocks_pos, make_block [] 0 type rctx = { r_root : block; diff --git a/tests/unit/src/unit/issues/Issue11466.hx b/tests/unit/src/unit/issues/Issue11466.hx new file mode 100644 index 00000000000..c401eb9b7bb --- /dev/null +++ b/tests/unit/src/unit/issues/Issue11466.hx @@ -0,0 +1,30 @@ +package unit.issues; + +private function doThrow() { + throw "from doThrow"; +} + +class Issue11466 extends unit.Test { + var b = 10; + function test() { + var x = 0; + try { + x = b; + throw ''; + } catch(_) { + x += 1; + } + eq(11, x); + } + + function test2() { + var x = 0; + try { + x = b; + doThrow(); + } catch(_) { + x += 1; + } + eq(11, x); + } +} diff --git a/tests/unit/src/unit/issues/Issue9174.hx b/tests/unit/src/unit/issues/Issue9174.hx new file mode 100644 index 00000000000..4f3a9f8257d --- /dev/null +++ b/tests/unit/src/unit/issues/Issue9174.hx @@ -0,0 +1,37 @@ +package unit.issues; + +private function doThrow() { + throw "from doThrow"; +} + +class Issue9174 extends unit.Test { + function test() { + var value = ""; + try { + try { + throw "from throw"; + } catch (e:String) { + value += "inner catch"; + throw e; + } + } catch (e:String) { + value += ", outer catch, " + e; + } + eq("inner catch, outer catch, from throw", value); + } + + function test2() { + var value = ""; + try { + try { + doThrow(); + } catch (e:String) { + value += "inner catch"; + throw e; + } + } catch (e:String) { + value += ", outer catch, " + e; + } + eq("inner catch, outer catch, from doThrow", value); + } +}