1 //===---------------------- catch_pointer_referece.cpp --------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This test case checks specifically the cases under bullet 3.1 & 3.2:
11 //
12 // C++ ABI 15.3:
13 // A handler is a match for an exception object of type E if
14 // * The handler is of type cv T or cv T& and E and T are the same type
15 // (ignoring the top-level cv-qualifiers), or
16 // * the handler is of type cv T or cv T& and T is an unambiguous base
17 // class of E, or
18 // / * the handler is of type cv1 T* cv2 and E is a pointer type that can \
19 // | be converted to the type of the handler by either or both of |
20 // | o a standard pointer conversion (4.10 [conv.ptr]) not involving |
21 // | conversions to private or protected or ambiguous classes |
22 // \ o a qualification conversion /
23 // * the handler is a pointer or pointer to member type and E is
24 // std::nullptr_t
25 //
26 //===----------------------------------------------------------------------===//
27
28 // UNSUPPORTED: libcxxabi-no-exceptions
29
30 #include <exception>
31 #include <stdlib.h>
32 #include <assert.h>
33 #include <stdio.h>
34
35 struct Base {};
36 struct Derived : Base {};
37 struct Derived2 : Base {};
38 struct Ambiguous : Derived, Derived2 {};
39 struct Private : private Base {};
40 struct Protected : protected Base {};
41
42 template <typename T // Handler type
43 ,typename E // Thrown exception type
44 ,typename O // Object type
45 >
assert_catches()46 void assert_catches()
47 {
48 try
49 {
50 O o;
51 throw static_cast<E>(&o);
52 printf("%s\n", __PRETTY_FUNCTION__);
53 assert(false && "Statements after throw must be unreachable");
54 }
55 catch (T t)
56 {
57 assert(true);
58 return;
59 }
60 catch (...)
61 {
62 printf("%s\n", __PRETTY_FUNCTION__);
63 assert(false && "Should not have entered catch-all");
64 }
65
66 printf("%s\n", __PRETTY_FUNCTION__);
67 assert(false && "The catch should have returned");
68 }
69
70 template <typename T // Handler type
71 ,typename E // Thrown exception type
72 ,typename O // Object type
73 >
assert_cannot_catch()74 void assert_cannot_catch()
75 {
76 try
77 {
78 O o;
79 throw static_cast<E>(&o);
80 printf("%s\n", __PRETTY_FUNCTION__);
81 assert(false && "Statements after throw must be unreachable");
82 }
83 catch (T t)
84 {
85 printf("%s\n", __PRETTY_FUNCTION__);
86 assert(false && "Should not have entered the catch");
87 }
88 catch (...)
89 {
90 assert(true);
91 return;
92 }
93
94 printf("%s\n", __PRETTY_FUNCTION__);
95 assert(false && "The catch-all should have returned");
96 }
97
f1()98 void f1()
99 {
100 // Test that every combination of handler of type:
101 // cv1 Base * cv2
102 // catches an exception of type:
103 // Derived *
104 assert_catches< Base * , Derived *, Derived>();
105 assert_catches<const Base * , Derived *, Derived>();
106 assert_catches< volatile Base * , Derived *, Derived>();
107 assert_catches<const volatile Base * , Derived *, Derived>();
108 assert_catches< Base * const , Derived *, Derived>();
109 assert_catches<const Base * const , Derived *, Derived>();
110 assert_catches< volatile Base * const , Derived *, Derived>();
111 assert_catches<const volatile Base * const , Derived *, Derived>();
112 assert_catches< Base * volatile, Derived *, Derived>();
113 assert_catches<const Base * volatile, Derived *, Derived>();
114 assert_catches< volatile Base * volatile, Derived *, Derived>();
115 assert_catches<const volatile Base * volatile, Derived *, Derived>();
116 assert_catches< Base * const volatile, Derived *, Derived>();
117 assert_catches<const Base * const volatile, Derived *, Derived>();
118 assert_catches< volatile Base * const volatile, Derived *, Derived>();
119 assert_catches<const volatile Base * const volatile, Derived *, Derived>();
120 }
121
f2()122 void f2()
123 {
124 // Test that every combination of handler of type:
125 // cv1 Base * cv2
126 // catches an exception of type:
127 // Base *
128 assert_catches< Base * , Base *, Derived>();
129 assert_catches<const Base * , Base *, Derived>();
130 assert_catches< volatile Base * , Base *, Derived>();
131 assert_catches<const volatile Base * , Base *, Derived>();
132 assert_catches< Base * const , Base *, Derived>();
133 assert_catches<const Base * const , Base *, Derived>();
134 assert_catches< volatile Base * const , Base *, Derived>();
135 assert_catches<const volatile Base * const , Base *, Derived>();
136 assert_catches< Base * volatile, Base *, Derived>();
137 assert_catches<const Base * volatile, Base *, Derived>();
138 assert_catches< volatile Base * volatile, Base *, Derived>();
139 assert_catches<const volatile Base * volatile, Base *, Derived>();
140 assert_catches< Base * const volatile, Base *, Derived>();
141 assert_catches<const Base * const volatile, Base *, Derived>();
142 assert_catches< volatile Base * const volatile, Base *, Derived>();
143 assert_catches<const volatile Base * const volatile, Base *, Derived>();
144 }
145
f3()146 void f3()
147 {
148 // Test that every combination of handler of type:
149 // cv1 Derived * cv2
150 // catches an exception of type:
151 // Derived *
152 assert_catches< Derived * , Derived *, Derived>();
153 assert_catches<const Derived * , Derived *, Derived>();
154 assert_catches< volatile Derived * , Derived *, Derived>();
155 assert_catches<const volatile Derived * , Derived *, Derived>();
156 assert_catches< Derived * const , Derived *, Derived>();
157 assert_catches<const Derived * const , Derived *, Derived>();
158 assert_catches< volatile Derived * const , Derived *, Derived>();
159 assert_catches<const volatile Derived * const , Derived *, Derived>();
160 assert_catches< Derived * volatile, Derived *, Derived>();
161 assert_catches<const Derived * volatile, Derived *, Derived>();
162 assert_catches< volatile Derived * volatile, Derived *, Derived>();
163 assert_catches<const volatile Derived * volatile, Derived *, Derived>();
164 assert_catches< Derived * const volatile, Derived *, Derived>();
165 assert_catches<const Derived * const volatile, Derived *, Derived>();
166 assert_catches< volatile Derived * const volatile, Derived *, Derived>();
167 assert_catches<const volatile Derived * const volatile, Derived *, Derived>();
168 }
169
f4()170 void f4()
171 {
172 // Test that every combination of handler of type:
173 // cv1 Derived * cv2
174 // cannot catch an exception of type:
175 // Base *
176 assert_cannot_catch< Derived * , Base *, Derived>();
177 assert_cannot_catch<const Derived * , Base *, Derived>();
178 assert_cannot_catch< volatile Derived * , Base *, Derived>();
179 assert_cannot_catch<const volatile Derived * , Base *, Derived>();
180 assert_cannot_catch< Derived * const , Base *, Derived>();
181 assert_cannot_catch<const Derived * const , Base *, Derived>();
182 assert_cannot_catch< volatile Derived * const , Base *, Derived>();
183 assert_cannot_catch<const volatile Derived * const , Base *, Derived>();
184 assert_cannot_catch< Derived * volatile, Base *, Derived>();
185 assert_cannot_catch<const Derived * volatile, Base *, Derived>();
186 assert_cannot_catch< volatile Derived * volatile, Base *, Derived>();
187 assert_cannot_catch<const volatile Derived * volatile, Base *, Derived>();
188 assert_cannot_catch< Derived * const volatile, Base *, Derived>();
189 assert_cannot_catch<const Derived * const volatile, Base *, Derived>();
190 assert_cannot_catch< volatile Derived * const volatile, Base *, Derived>();
191 assert_cannot_catch<const volatile Derived * const volatile, Base *, Derived>();
192 }
193
f5()194 void f5()
195 {
196 // Test that every combination of handler of type:
197 // cv1 Derived * cv2 &
198 // catches an exception of type:
199 // Derived *
200 assert_catches< Derived * &, Derived *, Derived>();
201 assert_catches<const Derived * &, Derived *, Derived>();
202 assert_catches< volatile Derived * &, Derived *, Derived>();
203 assert_catches<const volatile Derived * &, Derived *, Derived>();
204 assert_catches< Derived * const &, Derived *, Derived>();
205 assert_catches<const Derived * const &, Derived *, Derived>();
206 assert_catches< volatile Derived * const &, Derived *, Derived>();
207 assert_catches<const volatile Derived * const &, Derived *, Derived>();
208 assert_catches< Derived * volatile &, Derived *, Derived>();
209 assert_catches<const Derived * volatile &, Derived *, Derived>();
210 assert_catches< volatile Derived * volatile &, Derived *, Derived>();
211 assert_catches<const volatile Derived * volatile &, Derived *, Derived>();
212 assert_catches< Derived * const volatile &, Derived *, Derived>();
213 assert_catches<const Derived * const volatile &, Derived *, Derived>();
214 assert_catches< volatile Derived * const volatile &, Derived *, Derived>();
215 assert_catches<const volatile Derived * const volatile &, Derived *, Derived>();
216 }
217
f6()218 void f6()
219 {
220 // Test that every combination of handler of type:
221 // cv1 Base * cv2 &
222 // catches an exception of type:
223 // Base *
224 assert_catches< Base * &, Base *, Derived>();
225 assert_catches<const Base * &, Base *, Derived>();
226 assert_catches< volatile Base * &, Base *, Derived>();
227 assert_catches<const volatile Base * &, Base *, Derived>();
228 assert_catches< Base * const &, Base *, Derived>();
229 assert_catches<const Base * const &, Base *, Derived>();
230 assert_catches< volatile Base * const &, Base *, Derived>();
231 assert_catches<const volatile Base * const &, Base *, Derived>();
232 assert_catches< Base * volatile &, Base *, Derived>();
233 assert_catches<const Base * volatile &, Base *, Derived>();
234 assert_catches< volatile Base * volatile &, Base *, Derived>();
235 assert_catches<const volatile Base * volatile &, Base *, Derived>();
236 assert_catches< Base * const volatile &, Base *, Derived>();
237 assert_catches<const Base * const volatile &, Base *, Derived>();
238 assert_catches< volatile Base * const volatile &, Base *, Derived>();
239 assert_catches<const volatile Base * const volatile &, Base *, Derived>();
240
241 }
242
f7()243 void f7()
244 {
245 // Test that every combination of handler of type:
246 // cv1 Derived * cv2 &
247 // cannot catch an exception of type:
248 // Base *
249 assert_cannot_catch< Derived * &, Base *, Derived>();
250 assert_cannot_catch<const Derived * &, Base *, Derived>();
251 assert_cannot_catch< volatile Derived * &, Base *, Derived>();
252 assert_cannot_catch<const volatile Derived * &, Base *, Derived>();
253 assert_cannot_catch< Derived * const &, Base *, Derived>();
254 assert_cannot_catch<const Derived * const &, Base *, Derived>();
255 assert_cannot_catch< volatile Derived * const &, Base *, Derived>();
256 assert_cannot_catch<const volatile Derived * const &, Base *, Derived>();
257 assert_cannot_catch< Derived * volatile &, Base *, Derived>();
258 assert_cannot_catch<const Derived * volatile &, Base *, Derived>();
259 assert_cannot_catch< volatile Derived * volatile &, Base *, Derived>();
260 assert_cannot_catch<const volatile Derived * volatile &, Base *, Derived>();
261 assert_cannot_catch< Derived * const volatile &, Base *, Derived>();
262 assert_cannot_catch<const Derived * const volatile &, Base *, Derived>();
263 assert_cannot_catch< volatile Derived * const volatile &, Base *, Derived>();
264 assert_cannot_catch<const volatile Derived * const volatile &, Base *, Derived>();
265 }
266
f8()267 void f8()
268 {
269 // This test case has a caveat noted in the discussion here:
270 // https://gcc.gnu.org/ml/gcc-patches/2009-08/msg00264.html
271 // Specifically:
272 // This [test exposes a] corner case of the ARM C++ ABI. The generic C++
273 // ABI also gets this wrong, because I failed to notice the subtlety here.
274 // The issue is that 15.3/3 3rd bullet says:
275 // The handler is of type cv1 T* cv2 and E is a pointer type that
276 // can be converted to the type of the handler by either or both of:
277 // * a standard pointer conversion (4.10) not involving conversions
278 // to pointers to private or protected or ambiguous classes
279 // Notice that the handlers of type "cv1 T*cv2&" are not allowed such
280 // freedom to find a base class. The ABI error is that we treat handlers
281 // of reference type exactly the same as the corresponding hander of
282 // non-reference type. Elsewhere in the exception handling this makes no
283 // difference (for instance bullet 1 explicitly says 'cv T or cv T&').
284 //
285 // See also: http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#388
286 //
287 // TL;DR: it is an unresolved C++ ABI defect that these do catch
288
289 // Test that every combination of handler of type:
290 // cv1 Base * cv2 &
291 // catches an exception of type:
292 // Derived *
293 assert_catches< Base * &, Derived *, Derived>();
294 assert_catches<const Base * &, Derived *, Derived>();
295 assert_catches< volatile Base * &, Derived *, Derived>();
296 assert_catches<const volatile Base * &, Derived *, Derived>();
297 assert_catches< Base * const &, Derived *, Derived>();
298 assert_catches<const Base * const &, Derived *, Derived>();
299 assert_catches< volatile Base * const &, Derived *, Derived>();
300 assert_catches<const volatile Base * const &, Derived *, Derived>();
301 assert_catches< Base * volatile &, Derived *, Derived>();
302 assert_catches<const Base * volatile &, Derived *, Derived>();
303 assert_catches< volatile Base * volatile &, Derived *, Derived>();
304 assert_catches<const volatile Base * volatile &, Derived *, Derived>();
305 assert_catches< Base * const volatile &, Derived *, Derived>();
306 assert_catches<const Base * const volatile &, Derived *, Derived>();
307 assert_catches< volatile Base * const volatile &, Derived *, Derived>();
308 assert_catches<const volatile Base * const volatile &, Derived *, Derived>();
309 }
310
f9()311 void f9()
312 {
313 // Test that every combination of handler of type:
314 // cv1 Base * cv2
315 // cannot catch an exception of type:
316 // Ambiguous *
317 assert_cannot_catch< Base * , Ambiguous *, Ambiguous>();
318 assert_cannot_catch<const Base * , Ambiguous *, Ambiguous>();
319 assert_cannot_catch< volatile Base * , Ambiguous *, Ambiguous>();
320 assert_cannot_catch<const volatile Base * , Ambiguous *, Ambiguous>();
321 assert_cannot_catch< Base * const , Ambiguous *, Ambiguous>();
322 assert_cannot_catch<const Base * const , Ambiguous *, Ambiguous>();
323 assert_cannot_catch< volatile Base * const , Ambiguous *, Ambiguous>();
324 assert_cannot_catch<const volatile Base * const , Ambiguous *, Ambiguous>();
325 assert_cannot_catch< Base * volatile, Ambiguous *, Ambiguous>();
326 assert_cannot_catch<const Base * volatile, Ambiguous *, Ambiguous>();
327 assert_cannot_catch< volatile Base * volatile, Ambiguous *, Ambiguous>();
328 assert_cannot_catch<const volatile Base * volatile, Ambiguous *, Ambiguous>();
329 assert_cannot_catch< Base * const volatile, Ambiguous *, Ambiguous>();
330 assert_cannot_catch<const Base * const volatile, Ambiguous *, Ambiguous>();
331 assert_cannot_catch< volatile Base * const volatile, Ambiguous *, Ambiguous>();
332 assert_cannot_catch<const volatile Base * const volatile, Ambiguous *, Ambiguous>();
333 }
334
f10()335 void f10()
336 {
337 // Test that every combination of handler of type:
338 // cv1 Base * cv2
339 // cannot catch an exception of type:
340 // Private *
341 assert_cannot_catch< Base * , Private *, Private>();
342 assert_cannot_catch<const Base * , Private *, Private>();
343 assert_cannot_catch< volatile Base * , Private *, Private>();
344 assert_cannot_catch<const volatile Base * , Private *, Private>();
345 assert_cannot_catch< Base * const , Private *, Private>();
346 assert_cannot_catch<const Base * const , Private *, Private>();
347 assert_cannot_catch< volatile Base * const , Private *, Private>();
348 assert_cannot_catch<const volatile Base * const , Private *, Private>();
349 assert_cannot_catch< Base * volatile, Private *, Private>();
350 assert_cannot_catch<const Base * volatile, Private *, Private>();
351 assert_cannot_catch< volatile Base * volatile, Private *, Private>();
352 assert_cannot_catch<const volatile Base * volatile, Private *, Private>();
353 assert_cannot_catch< Base * const volatile, Private *, Private>();
354 assert_cannot_catch<const Base * const volatile, Private *, Private>();
355 assert_cannot_catch< volatile Base * const volatile, Private *, Private>();
356 assert_cannot_catch<const volatile Base * const volatile, Private *, Private>();
357 }
358
f11()359 void f11()
360 {
361 // Test that every combination of handler of type:
362 // cv1 Base * cv2
363 // cannot catch an exception of type:
364 // Protected *
365 assert_cannot_catch< Base * , Protected *, Protected>();
366 assert_cannot_catch<const Base * , Protected *, Protected>();
367 assert_cannot_catch< volatile Base * , Protected *, Protected>();
368 assert_cannot_catch<const volatile Base * , Protected *, Protected>();
369 assert_cannot_catch< Base * const , Protected *, Protected>();
370 assert_cannot_catch<const Base * const , Protected *, Protected>();
371 assert_cannot_catch< volatile Base * const , Protected *, Protected>();
372 assert_cannot_catch<const volatile Base * const , Protected *, Protected>();
373 assert_cannot_catch< Base * volatile, Protected *, Protected>();
374 assert_cannot_catch<const Base * volatile, Protected *, Protected>();
375 assert_cannot_catch< volatile Base * volatile, Protected *, Protected>();
376 assert_cannot_catch<const volatile Base * volatile, Protected *, Protected>();
377 assert_cannot_catch< Base * const volatile, Protected *, Protected>();
378 assert_cannot_catch<const Base * const volatile, Protected *, Protected>();
379 assert_cannot_catch< volatile Base * const volatile, Protected *, Protected>();
380 assert_cannot_catch<const volatile Base * const volatile, Protected *, Protected>();
381 }
382
f12()383 void f12()
384 {
385 // Test that every combination of handler of type:
386 // cv1 Base * cv2 &
387 // cannot catch an exception of type:
388 // Private *
389 assert_cannot_catch< Base * &, Private *, Private>();
390 assert_cannot_catch<const Base * &, Private *, Private>();
391 assert_cannot_catch< volatile Base * &, Private *, Private>();
392 assert_cannot_catch<const volatile Base * &, Private *, Private>();
393 assert_cannot_catch< Base * const &, Private *, Private>();
394 assert_cannot_catch<const Base * const &, Private *, Private>();
395 assert_cannot_catch< volatile Base * const &, Private *, Private>();
396 assert_cannot_catch<const volatile Base * const &, Private *, Private>();
397 assert_cannot_catch< Base * volatile &, Private *, Private>();
398 assert_cannot_catch<const Base * volatile &, Private *, Private>();
399 assert_cannot_catch< volatile Base * volatile &, Private *, Private>();
400 assert_cannot_catch<const volatile Base * volatile &, Private *, Private>();
401 assert_cannot_catch< Base * const volatile &, Private *, Private>();
402 assert_cannot_catch<const Base * const volatile &, Private *, Private>();
403 assert_cannot_catch< volatile Base * const volatile &, Private *, Private>();
404 assert_cannot_catch<const volatile Base * const volatile &, Private *, Private>();
405 }
406
f13()407 void f13()
408 {
409 // Test that every combination of handler of type:
410 // cv1 Base * cv2 &
411 // cannot catch an exception of type:
412 // Protected *
413 assert_cannot_catch< Base * &, Protected *, Protected>();
414 assert_cannot_catch<const Base * &, Protected *, Protected>();
415 assert_cannot_catch< volatile Base * &, Protected *, Protected>();
416 assert_cannot_catch<const volatile Base * &, Protected *, Protected>();
417 assert_cannot_catch< Base * const &, Protected *, Protected>();
418 assert_cannot_catch<const Base * const &, Protected *, Protected>();
419 assert_cannot_catch< volatile Base * const &, Protected *, Protected>();
420 assert_cannot_catch<const volatile Base * const &, Protected *, Protected>();
421 assert_cannot_catch< Base * volatile &, Protected *, Protected>();
422 assert_cannot_catch<const Base * volatile &, Protected *, Protected>();
423 assert_cannot_catch< volatile Base * volatile &, Protected *, Protected>();
424 assert_cannot_catch<const volatile Base * volatile &, Protected *, Protected>();
425 assert_cannot_catch< Base * const volatile &, Protected *, Protected>();
426 assert_cannot_catch<const Base * const volatile &, Protected *, Protected>();
427 assert_cannot_catch< volatile Base * const volatile &, Protected *, Protected>();
428 assert_cannot_catch<const volatile Base * const volatile &, Protected *, Protected>();
429 }
430
main()431 int main()
432 {
433 f1();
434 f2();
435 f3();
436 f4();
437 f5();
438 f6();
439 f7();
440 f8();
441 f9();
442 f10();
443 f11();
444 f12();
445 f13();
446 }
447