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