| // 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; |
| } |