xref: /minix3/external/bsd/libc++/dist/libcxxrt/test/test_exception.cc (revision 4684ddb6aab0b36791c8099bc705d6140b3d05d0)
1*4684ddb6SLionel Sambuc #include "test.h"
2*4684ddb6SLionel Sambuc #include <stdio.h>
3*4684ddb6SLionel Sambuc #include <stdlib.h>
4*4684ddb6SLionel Sambuc #include <stdint.h>
5*4684ddb6SLionel Sambuc 
6*4684ddb6SLionel Sambuc #include <exception>
7*4684ddb6SLionel Sambuc 
8*4684ddb6SLionel Sambuc #define fprintf(...)
9*4684ddb6SLionel Sambuc 
log(void * ignored)10*4684ddb6SLionel Sambuc void log(void* ignored)
11*4684ddb6SLionel Sambuc {
12*4684ddb6SLionel Sambuc 	//printf("Cleanup called on %s\n", *(char**)ignored);
13*4684ddb6SLionel Sambuc }
14*4684ddb6SLionel Sambuc #define CLEANUP\
15*4684ddb6SLionel Sambuc 	__attribute__((cleanup(log))) __attribute__((unused))\
16*4684ddb6SLionel Sambuc 		const char *f = __func__;
17*4684ddb6SLionel Sambuc 
18*4684ddb6SLionel Sambuc /**
19*4684ddb6SLionel Sambuc  * Simple struct to test throwing.
20*4684ddb6SLionel Sambuc  */
21*4684ddb6SLionel Sambuc struct foo
22*4684ddb6SLionel Sambuc {
23*4684ddb6SLionel Sambuc 	int i;
24*4684ddb6SLionel Sambuc };
25*4684ddb6SLionel Sambuc 
26*4684ddb6SLionel Sambuc struct bar : foo
27*4684ddb6SLionel Sambuc {
28*4684ddb6SLionel Sambuc 	float bar;
29*4684ddb6SLionel Sambuc };
30*4684ddb6SLionel Sambuc 
31*4684ddb6SLionel Sambuc 
32*4684ddb6SLionel Sambuc /**
33*4684ddb6SLionel Sambuc  * Non-pod type to test throwing
34*4684ddb6SLionel Sambuc  */
35*4684ddb6SLionel Sambuc class non_pod {
36*4684ddb6SLionel Sambuc public:
non_pod(int i)37*4684ddb6SLionel Sambuc     non_pod(int i): x(i) {}
38*4684ddb6SLionel Sambuc     int x;
39*4684ddb6SLionel Sambuc };
40*4684ddb6SLionel Sambuc 
41*4684ddb6SLionel Sambuc 
42*4684ddb6SLionel Sambuc static int cleanup_count;
43*4684ddb6SLionel Sambuc /**
44*4684ddb6SLionel Sambuc  * Simple structure declared with a destructor.  Destroying this object will
45*4684ddb6SLionel Sambuc  * increment cleanup count.  The destructor should be called automatically if
46*4684ddb6SLionel Sambuc  * an instance of cl is allocated with automatic storage.
47*4684ddb6SLionel Sambuc  */
48*4684ddb6SLionel Sambuc struct cl
49*4684ddb6SLionel Sambuc {
50*4684ddb6SLionel Sambuc 	int i;
~clcl51*4684ddb6SLionel Sambuc 	~cl() { fprintf(stderr, "cl destroyed: %d\n", i); cleanup_count++; }
52*4684ddb6SLionel Sambuc };
53*4684ddb6SLionel Sambuc /**
54*4684ddb6SLionel Sambuc  * Test that one cl was destroyed when running the argument.
55*4684ddb6SLionel Sambuc  */
56*4684ddb6SLionel Sambuc #define TEST_CLEANUP(x) do {\
57*4684ddb6SLionel Sambuc 		int cleanups = cleanup_count;\
58*4684ddb6SLionel Sambuc 		{ x; }\
59*4684ddb6SLionel Sambuc 		TEST(cleanup_count == cleanups+1, "Cleanup ran correctly");\
60*4684ddb6SLionel Sambuc 	} while(0)
61*4684ddb6SLionel Sambuc 
inner(int i)62*4684ddb6SLionel Sambuc int inner(int i)
63*4684ddb6SLionel Sambuc {
64*4684ddb6SLionel Sambuc 	CLEANUP
65*4684ddb6SLionel Sambuc 	switch (i)
66*4684ddb6SLionel Sambuc 	{
67*4684ddb6SLionel Sambuc 		case 0: throw (int)1.0;
68*4684ddb6SLionel Sambuc 		case 1: throw (float)1.0;
69*4684ddb6SLionel Sambuc 		case 2: fprintf(stderr, "Throwing int64_t\n");throw (int64_t)1;
70*4684ddb6SLionel Sambuc 		case 3: { foo f = {2} ; throw f; }
71*4684ddb6SLionel Sambuc 		case 4: { bar f; f.i = 2 ; f.bar=1 ; throw f; }
72*4684ddb6SLionel Sambuc         case 5: throw non_pod(3);
73*4684ddb6SLionel Sambuc 	}
74*4684ddb6SLionel Sambuc 	return -1;
75*4684ddb6SLionel Sambuc }
76*4684ddb6SLionel Sambuc 
outer(int i)77*4684ddb6SLionel Sambuc int outer(int i) throw(float, int, foo, non_pod)
78*4684ddb6SLionel Sambuc {
79*4684ddb6SLionel Sambuc 	//CLEANUP
80*4684ddb6SLionel Sambuc 	inner(i);
81*4684ddb6SLionel Sambuc 	return 1;
82*4684ddb6SLionel Sambuc }
83*4684ddb6SLionel Sambuc 
test_const(void)84*4684ddb6SLionel Sambuc static void test_const(void)
85*4684ddb6SLionel Sambuc {
86*4684ddb6SLionel Sambuc 	int a = 1;
87*4684ddb6SLionel Sambuc 	try
88*4684ddb6SLionel Sambuc 	{
89*4684ddb6SLionel Sambuc 		throw a;
90*4684ddb6SLionel Sambuc 	}
91*4684ddb6SLionel Sambuc 	catch (const int b)
92*4684ddb6SLionel Sambuc 	{
93*4684ddb6SLionel Sambuc 		TEST(a == b, "Caught int as const int");
94*4684ddb6SLionel Sambuc 	}
95*4684ddb6SLionel Sambuc 	catch(...)
96*4684ddb6SLionel Sambuc 	{
97*4684ddb6SLionel Sambuc 		TEST(0, "Failed to catch int as const int");
98*4684ddb6SLionel Sambuc 	}
99*4684ddb6SLionel Sambuc 	try
100*4684ddb6SLionel Sambuc 	{
101*4684ddb6SLionel Sambuc 		throw &a;
102*4684ddb6SLionel Sambuc 	}
103*4684ddb6SLionel Sambuc 	catch (const int *b)
104*4684ddb6SLionel Sambuc 	{
105*4684ddb6SLionel Sambuc 		TEST(&a == b, "Caught int* as const int*");
106*4684ddb6SLionel Sambuc 	}
107*4684ddb6SLionel Sambuc 	catch(...)
108*4684ddb6SLionel Sambuc 	{
109*4684ddb6SLionel Sambuc 		TEST(0, "Failed to catch int* as const int*");
110*4684ddb6SLionel Sambuc 	}
111*4684ddb6SLionel Sambuc }
112*4684ddb6SLionel Sambuc 
test_catch(int s)113*4684ddb6SLionel Sambuc static void test_catch(int s)
114*4684ddb6SLionel Sambuc {
115*4684ddb6SLionel Sambuc 	cl c;
116*4684ddb6SLionel Sambuc 	c.i = 12;
117*4684ddb6SLionel Sambuc 	fprintf(stderr, "Entering try\n");
118*4684ddb6SLionel Sambuc 	try
119*4684ddb6SLionel Sambuc 	{
120*4684ddb6SLionel Sambuc 		outer(s);
121*4684ddb6SLionel Sambuc 	}
122*4684ddb6SLionel Sambuc 	catch(int i)
123*4684ddb6SLionel Sambuc 	{
124*4684ddb6SLionel Sambuc 		fprintf(stderr, "Caught int %d in test %d\n", i, s);
125*4684ddb6SLionel Sambuc 		TEST((s == 0 && i == 1) || (s == 2 && i == 0), "Caught int");
126*4684ddb6SLionel Sambuc 		return;
127*4684ddb6SLionel Sambuc 	}
128*4684ddb6SLionel Sambuc 	catch (float f)
129*4684ddb6SLionel Sambuc 	{
130*4684ddb6SLionel Sambuc 		fprintf(stderr, "Caught float %f!\n", f);
131*4684ddb6SLionel Sambuc 		TEST(s == 1 && f == 1, "Caught float");
132*4684ddb6SLionel Sambuc 		return;
133*4684ddb6SLionel Sambuc 	}
134*4684ddb6SLionel Sambuc 	catch (foo f)
135*4684ddb6SLionel Sambuc 	{
136*4684ddb6SLionel Sambuc 		fprintf(stderr, "Caught struct {%d}!\n", f.i);
137*4684ddb6SLionel Sambuc 		TEST((s == 3 || s == 4) && f.i == 2, "Caught struct");
138*4684ddb6SLionel Sambuc 		return;
139*4684ddb6SLionel Sambuc 	}
140*4684ddb6SLionel Sambuc     catch (non_pod np) {
141*4684ddb6SLionel Sambuc         fprintf(stderr, "Caught non_pod {%d}!\n", np.x);
142*4684ddb6SLionel Sambuc         TEST(s == 5 && np.x == 3, "Caught non_pod");
143*4684ddb6SLionel Sambuc         return;
144*4684ddb6SLionel Sambuc     }
145*4684ddb6SLionel Sambuc 	//abort();
146*4684ddb6SLionel Sambuc 	TEST(0, "Unreachable line reached");
147*4684ddb6SLionel Sambuc }
148*4684ddb6SLionel Sambuc 
test_nested1(void)149*4684ddb6SLionel Sambuc void test_nested1(void)
150*4684ddb6SLionel Sambuc {
151*4684ddb6SLionel Sambuc 	CLEANUP;
152*4684ddb6SLionel Sambuc 	cl c;
153*4684ddb6SLionel Sambuc 	c.i = 123;
154*4684ddb6SLionel Sambuc 	try
155*4684ddb6SLionel Sambuc 	{
156*4684ddb6SLionel Sambuc 		outer(0);
157*4684ddb6SLionel Sambuc 	}
158*4684ddb6SLionel Sambuc 	catch (int a)
159*4684ddb6SLionel Sambuc 	{
160*4684ddb6SLionel Sambuc 		try
161*4684ddb6SLionel Sambuc 		{
162*4684ddb6SLionel Sambuc 			TEST(a == 1, "Caught int");
163*4684ddb6SLionel Sambuc 			outer(1);
164*4684ddb6SLionel Sambuc 		}
165*4684ddb6SLionel Sambuc 		catch (float f)
166*4684ddb6SLionel Sambuc 		{
167*4684ddb6SLionel Sambuc 			TEST(f == 1, "Caught float inside outer catch block");
168*4684ddb6SLionel Sambuc 			throw;
169*4684ddb6SLionel Sambuc 		}
170*4684ddb6SLionel Sambuc 	}
171*4684ddb6SLionel Sambuc }
172*4684ddb6SLionel Sambuc 
test_nested()173*4684ddb6SLionel Sambuc void test_nested()
174*4684ddb6SLionel Sambuc {
175*4684ddb6SLionel Sambuc 	try
176*4684ddb6SLionel Sambuc 	{
177*4684ddb6SLionel Sambuc 		test_nested1();
178*4684ddb6SLionel Sambuc 	}
179*4684ddb6SLionel Sambuc 	catch (float f)
180*4684ddb6SLionel Sambuc 	{
181*4684ddb6SLionel Sambuc 		fprintf(stderr, "Caught re-thrown float\n");
182*4684ddb6SLionel Sambuc 		TEST(f == 1, "Caught re-thrown float");
183*4684ddb6SLionel Sambuc 	}
184*4684ddb6SLionel Sambuc }
185*4684ddb6SLionel Sambuc 
186*4684ddb6SLionel Sambuc static int violations = 0;
throw_zero()187*4684ddb6SLionel Sambuc static void throw_zero()
188*4684ddb6SLionel Sambuc {
189*4684ddb6SLionel Sambuc 	violations++;
190*4684ddb6SLionel Sambuc 	fprintf(stderr, "Throwing 0\n");
191*4684ddb6SLionel Sambuc 	throw 0;
192*4684ddb6SLionel Sambuc }
193*4684ddb6SLionel Sambuc 
194*4684ddb6SLionel Sambuc extern "C" void __cxa_bad_cast();
195*4684ddb6SLionel Sambuc 
test_exceptions(void)196*4684ddb6SLionel Sambuc void test_exceptions(void)
197*4684ddb6SLionel Sambuc {
198*4684ddb6SLionel Sambuc 	std::set_unexpected(throw_zero);
199*4684ddb6SLionel Sambuc 	TEST_CLEANUP(test_catch(0));
200*4684ddb6SLionel Sambuc 	TEST_CLEANUP(test_catch(1));
201*4684ddb6SLionel Sambuc 	TEST_CLEANUP(test_catch(3));
202*4684ddb6SLionel Sambuc 	TEST_CLEANUP(test_catch(4));
203*4684ddb6SLionel Sambuc 	TEST_CLEANUP(test_catch(5));
204*4684ddb6SLionel Sambuc 	TEST_CLEANUP(test_nested());
205*4684ddb6SLionel Sambuc 	try{
206*4684ddb6SLionel Sambuc 		test_catch(2);
207*4684ddb6SLionel Sambuc 		TEST(violations == 1, "Exactly one exception spec violation");
208*4684ddb6SLionel Sambuc 	}
209*4684ddb6SLionel Sambuc 	catch (int64_t i) {
210*4684ddb6SLionel Sambuc 		TEST(0, "Caught int64_t, but that violates an exception spec");
211*4684ddb6SLionel Sambuc 	}
212*4684ddb6SLionel Sambuc 	int a;
213*4684ddb6SLionel Sambuc 	try {
214*4684ddb6SLionel Sambuc 		throw &a;
215*4684ddb6SLionel Sambuc 	}
216*4684ddb6SLionel Sambuc 	catch (const int *b)
217*4684ddb6SLionel Sambuc 	{
218*4684ddb6SLionel Sambuc 		TEST(&a==b, "Caught const int from thrown int");
219*4684ddb6SLionel Sambuc 	}
220*4684ddb6SLionel Sambuc 	try {
221*4684ddb6SLionel Sambuc 		throw &a;
222*4684ddb6SLionel Sambuc 	}
223*4684ddb6SLionel Sambuc 	catch (int *b)
224*4684ddb6SLionel Sambuc 	{
225*4684ddb6SLionel Sambuc 		TEST(&a==b, "Caught int from thrown int");
226*4684ddb6SLionel Sambuc 	}
227*4684ddb6SLionel Sambuc 	try
228*4684ddb6SLionel Sambuc 	{
229*4684ddb6SLionel Sambuc 		__cxa_bad_cast();
230*4684ddb6SLionel Sambuc 	}
231*4684ddb6SLionel Sambuc 	catch (std::exception b)
232*4684ddb6SLionel Sambuc 	{
233*4684ddb6SLionel Sambuc 		TEST(1, "Caught bad cast");
234*4684ddb6SLionel Sambuc 	}
235*4684ddb6SLionel Sambuc 	catch (...)
236*4684ddb6SLionel Sambuc 	{
237*4684ddb6SLionel Sambuc 		TEST(0, "Bad cast was not caught correctly");
238*4684ddb6SLionel Sambuc 	}
239*4684ddb6SLionel Sambuc 	test_const();
240*4684ddb6SLionel Sambuc 
241*4684ddb6SLionel Sambuc 
242*4684ddb6SLionel Sambuc 	//printf("Test: %s\n",
243*4684ddb6SLionel Sambuc }
244