import core.stdc.stdio : fprintf, stderr; class MyException : Exception { this() { super(typeof(this).stringof); } } void throw_catch() { try { throw new MyException; } catch (MyException) { } catch (Exception) { assert(false); } } // Test that exceptions that are entirely thrown and caught in finally blocks don't affect exception handling. void test1() { try { try { throw new Exception("p"); } finally { throw_catch(); } } catch (Exception e) { assert(e.msg == "p"); } } // Test that exceptions that are entirely thrown and caught in finally blocks don't interfere with chaining. void test2() { try { try { try { throw new Exception("p"); } finally { throw new Exception("q"); } } finally { throw_catch(); } } catch(Exception e) { assert(e.msg == "p"); assert(e.next.msg == "q"); assert(!e.next.next); } } void test3() { try { try { try { throw new Exception("p"); } finally { throw_catch(); } } finally { throw new Exception("q"); } } catch(Exception e) { assert(e.msg == "p"); assert(e.next.msg == "q"); assert(!e.next.next); } } // Test order of exception handler operations. void test4() { string result; void throw_catch() { pragma(inline, false); try { result ~= "b"; throw new MyException; } catch (MyException) { result ~= "c"; } catch (Exception) { assert(false); } } try { try { result ~= "a"; throw new Exception(""); } finally { throw_catch(); } } catch(Exception e) { result ~= "d"; } assert(result == "abcd"); } void test5() { string result; void fail() { result ~= "b"; throw new Exception("a"); } void throw_catch() { pragma(inline, false); try { fail(); } catch(Exception e) { assert(e.msg == "a"); assert(!e.next); result ~= "c"; } } try { try { result ~= "a"; throw new Exception("x"); } finally { throw_catch(); } } catch (Exception e) { assert(e.msg == "x"); assert(!e.next); result ~= "d"; } assert(result == "abcd"); } void main() { test1(); test2(); test3(); test4(); test5(); fprintf(stderr, "success.\n"); }