1import core.stdc.stdio : fprintf, stderr;
2
3class MyException : Exception
4{
5    this() { super(typeof(this).stringof); }
6}
7
8void throw_catch()
9{
10    try
11    {
12        throw new MyException;
13    }
14    catch (MyException)
15    {
16    }
17    catch (Exception)
18    {
19        assert(false);
20    }
21}
22
23// Test that exceptions that are entirely thrown and caught in finally blocks don't affect exception handling.
24void test1()
25{
26    try
27    {
28        try
29        {
30            throw new Exception("p");
31        }
32        finally
33        {
34            throw_catch();
35        }
36    }
37    catch (Exception e)
38    {
39        assert(e.msg == "p");
40    }
41}
42
43// Test that exceptions that are entirely thrown and caught in finally blocks don't interfere with chaining.
44void test2()
45{
46    try
47    {
48        try
49        {
50            try
51            {
52                throw new Exception("p");
53            }
54            finally
55            {
56                throw new Exception("q");
57            }
58        }
59        finally
60        {
61            throw_catch();
62        }
63    }
64    catch(Exception e)
65    {
66        assert(e.msg == "p");
67        assert(e.next.msg == "q");
68        assert(!e.next.next);
69    }
70}
71
72void test3()
73{
74    try
75    {
76        try
77        {
78            try
79            {
80                throw new Exception("p");
81            }
82            finally
83            {
84                throw_catch();
85            }
86        }
87        finally
88        {
89            throw new Exception("q");
90        }
91    }
92    catch(Exception e)
93    {
94        assert(e.msg == "p");
95        assert(e.next.msg == "q");
96        assert(!e.next.next);
97    }
98}
99
100// Test order of exception handler operations.
101void test4()
102{
103    string result;
104    void throw_catch()
105    {
106        pragma(inline, false);
107        try
108        {
109            result ~= "b";
110            throw new MyException;
111        }
112        catch (MyException)
113        {
114            result ~= "c";
115        }
116        catch (Exception)
117        {
118            assert(false);
119        }
120    }
121    try
122    {
123        try
124        {
125            result ~= "a";
126            throw new Exception("");
127        }
128        finally
129        {
130            throw_catch();
131        }
132    }
133    catch(Exception e)
134    {
135        result ~= "d";
136    }
137    assert(result == "abcd");
138}
139
140void test5()
141{
142    string result;
143    void fail()
144    {
145        result ~= "b";
146        throw new Exception("a");
147    }
148
149    void throw_catch()
150    {
151        pragma(inline, false);
152        try
153        {
154            fail();
155        }
156        catch(Exception e)
157        {
158            assert(e.msg == "a");
159            assert(!e.next);
160            result ~= "c";
161        }
162    }
163    try
164    {
165        try
166        {
167            result ~= "a";
168            throw new Exception("x");
169        }
170        finally
171        {
172            throw_catch();
173        }
174    }
175    catch (Exception e)
176    {
177        assert(e.msg == "x");
178        assert(!e.next);
179        result ~= "d";
180    }
181    assert(result == "abcd");
182}
183
184void main() {
185    test1();
186    test2();
187    test3();
188    test4();
189    test5();
190    fprintf(stderr, "success.\n");
191}
192