// PERMUTE_ARGS: -O -fPIC extern(C) int printf(const char*, ...); /****************************************************/ class Abc : Exception { this() { super(""); } int i; } int y; alias int boo; void foo(int x) { y = cast(boo)1; L6: try { printf("try 1\n"); y += 4; if (y == 5) goto L6; y += 3; } finally { y += 5; printf("finally 1\n"); } try { printf("try 2\n"); y = 1; if (y == 4) goto L6; y++; } catch (Abc c) { printf("catch 2\n"); y = 2 + c.i; } y++; printf("done\n"); } /****************************************************/ class IntException : Exception { this(int i) { m_i = i; super(""); } int getValue() { return m_i; } int m_i; } void test2() { int cIterations = 10; int i; long total_x = 0; long total_nox = 0; for(int WARMUPS = 2; WARMUPS-- > 0; ) { for(total_x = 0, i = 0; i < cIterations; ++i) { total_nox += fn2_nox(); } printf("foo\n"); for(total_nox = 0, i = 0; i < cIterations; ++i) { printf("i = %d\n", i); try { int z = 1; throw new IntException(z); } catch(IntException x) { printf("catch, i = %d\n", i); total_x += x.getValue(); } } } printf("iterations %d totals: %ld, %ld\n", cIterations, total_x, total_nox); } int fn2_nox() { return 47; } /****************************************************/ void test3() { static int x; try { } finally { printf("a\n"); assert(x == 0); x++; } printf("--\n"); assert(x == 1); try { printf("tb\n"); assert(x == 1); } finally { printf("b\n"); assert(x == 1); x++; } assert(x == 2); } /****************************************************/ class Tester { this(void delegate() dg_) { dg = dg_; } void delegate() dg; void stuff() { dg(); } } void test4() { printf("Starting test\n"); int a = 0; int b = 0; int c = 0; int d = 0; try { a++; throw new Exception("test1"); a++; } catch(Exception e) { auto es = e.toString(); printf("%.*s\n", es.length, es.ptr); b++; } finally { c++; } printf("initial test.\n"); assert(a == 1); assert(b == 1); assert(c == 1); printf("pass\n"); Tester t = new Tester( delegate void() { try { a++; throw new Exception("test2"); a++; } catch(Exception e) { b++; throw e; b++; } }); try { c++; t.stuff(); c++; } catch(Exception e) { d++; string es = e.toString; printf("%.*s\n", es.length, es.ptr); } assert(a == 2); assert(b == 2); assert(c == 2); assert(d == 1); int q0 = 0; int q1 = 0; int q2 = 0; int q3 = 0; Tester t2 = new Tester( delegate void() { try { q0++; throw new Exception("test3"); q0++; } catch(Exception e) { printf("Never called.\n"); q1++; throw e; q1++; } }); try { q2++; t2.stuff(); q2++; } catch(Exception e) { q3++; string es = e.toString; printf("%.*s\n", es.length, es.ptr); } assert(q0 == 1); assert(q1 == 1); assert(q2 == 1); assert(q3 == 1); printf("Passed!\n"); } /****************************************************/ void test5() { char[] result; int i = 3; while(i--) { try { printf("i: %d\n", i); result ~= 't'; if (i == 1) continue; } finally { printf("finally\n"); result ~= cast(char)('a' + i); } } printf("--- %.*s", result.length, result.ptr); if (result != "tctbta") assert(0); } /****************************************************/ void test6() { char[] result; while (true) { try { printf("one\n"); result ~= 'a'; break; } finally { printf("two\n"); result ~= 'b'; } } printf("three\n"); result ~= 'c'; if (result != "abc") assert(0); } /****************************************************/ string a7; void doScan(int i) { a7 ~= "a"; try { try { a7 ~= "b"; return; } finally { a7 ~= "c"; } } finally { a7 ~= "d"; } } void test7() { doScan(0); assert(a7 == "abcd"); } /**************************************************** * Exception chaining tests. See also test4.d ****************************************************/ int result1513; void bug1513a() { throw new Exception("d"); } void bug1513b() { try { try { bug1513a(); } finally { result1513 |=4; throw new Exception("f"); } } catch(Exception e) { assert(e.msg == "d"); assert(e.next.msg == "f"); assert(!e.next.next); } } void bug1513c() { try { try { throw new Exception("a"); } finally { result1513 |= 1; throw new Exception("b"); } } finally { bug1513b(); result1513 |= 2; throw new Exception("c"); } } void bug1513() { result1513 = 0; try { bug1513c(); } catch(Exception e) { assert(result1513 == 7); assert(e.msg == "a"); assert(e.next.msg == "b"); assert(e.next.next.msg == "c"); } } void collideone() { try { throw new Exception("x"); } finally { throw new Exception("y"); } } void doublecollide() { try { try { try { throw new Exception("p"); } finally { throw new Exception("q"); } } finally { collideone(); } } catch(Exception e) { assert(e.msg == "p"); assert(e.next.msg == "q"); assert(e.next.next.msg == "x"); assert(e.next.next.next.msg == "y"); assert(!e.next.next.next.next); } } void collidetwo() { try { try { throw new Exception("p2"); } finally { throw new Exception("q2"); } } finally { collideone(); } } void collideMixed() { int works = 6; try { try { try { throw new Exception("e"); } finally { throw new Error("t"); } } catch(Exception f) { // Doesn't catch, because Error is chained to it. works += 2; } } catch(Error z) { works += 4; assert(z.msg=="t"); // Error comes first assert(z.next is null); assert(z.bypassedException.msg == "e"); } assert(works == 10); } class AnotherException : Exception { this(string s) { super(s); } } void multicollide() { try { try { try { try { throw new Exception("m2"); } finally { throw new AnotherException("n2"); } } catch(AnotherException s) { // Not caught -- we needed to catch the root cause "m2", not // just the collateral "n2" (which would leave m2 uncaught). assert(0); } } finally { collidetwo(); } } catch(Exception f) { assert(f.msg == "m2"); assert(f.next.msg == "n2"); Throwable e = f.next.next; assert(e.msg == "p2"); assert(e.next.msg == "q2"); assert(e.next.next.msg == "x"); assert(e.next.next.next.msg == "y"); assert(!e.next.next.next.next); } } /****************************************************/ void use9568(char [] x, char [] y) {} int bug9568() { try return 7; finally use9568(null,null); } void test9568() { assert( bug9568() == 7 ); } /****************************************************/ version (DigitalMars) { void test8a() { int a; goto L2; // L2 is not addressable. try { a += 2; } catch (Exception) { a += 3; L2: ; a += 100; } assert(a == 100); } void test8b() { int a; goto L2; // L2 is not addressable. try { } catch (Exception) { a += 3; L2: ; a += 100; } assert(a == 100); } void test8c() { int a; goto L2; // L2 is not addressable. try static assert(true); catch (Exception) { a += 3; L2: ; a += 100; } assert(a == 100); } void test8() { test8a(); test8b(); test8c(); } } /****************************************************/ uint foo9(uint i) { try { ++i; return 3; } catch (Exception e) { debug printf("Exception happened\n"); } return 4; } void test9() { assert(foo9(7) == 3); } /****************************************************/ // 10964 void test10964() { static struct S { this(this) { throw new Exception("BOOM!"); } } S ss; S[1] sa; int result; result = 0; try { ss = ss; } catch (Exception e) result = 1; catch (Error e) result = 2; catch (Throwable e) result = 3; assert(result == 1); try { sa = ss; } catch (Exception e) result = 1; catch (Error e) result = 2; catch (Throwable e) result = 3; assert(result == 1); try { sa = sa; } catch (Exception e) result = 1; catch (Error e) result = 2; catch (Throwable e) result = 3; assert(result == 1); } /****************************************************/ alias Action = void delegate(); class A10 { invariant() { } public Action foo(Action a) { synchronized { B10 elements = new B10; Action[] actions = [a]; elements.bar(actions); if (actions.length > 1) elements.bar(actions); return actions[0]; } return null; } } class B10 { public bool bar(ref Action[]) { return false; } } class D10 { void baz() { } } void test12989() { auto a = new A10; auto d = new D10; assert(a.foo(&d.baz) == &d.baz); } /****************************************************/ int bar10(int c) { if (c <= 0xFFFF) { L3: return 3; } throw new Exception("msg"); goto L3; } void test10() { int x; try { bar10(0x110000); } catch (Exception e) { printf("caught\n"); x = 1; } assert(x == 1); printf("test10 success\n"); } /****************************************************/ class ParseException : Exception { @safe pure nothrow this( string msg ) { super( msg ); } } class OverflowException : Exception { @safe pure nothrow this( string msg ) { super( msg ); } } void test11() { int x; try { printf("test11()\n"); throw new ParseException("msg"); } catch( OverflowException e ) { printf( "catch OverflowException\n" ); } catch( ParseException e ) { printf( "catch ParseException: %.*s\n", cast(int) e.msg.length, e.msg.ptr ); x = 1; } assert(x == 1); } /****************************************************/ // https://issues.dlang.org/show_bug.cgi?id=17481 class C17481 { synchronized void trigger(){ new ubyte[1]; } } void test17481() { auto k = new shared C17481; k.trigger; } /****************************************************/ int main() { printf("start\n"); foo(3); test2(); test3(); test4(); test5(); test6(); test7(); bug1513(); doublecollide(); collideMixed(); multicollide(); test9568(); version(DigitalMars) test8(); test9(); test10964(); test12989(); test10(); test11(); test17481(); printf("finish\n"); return 0; }