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
35struct Base {};
36struct Derived  : Base {};
37struct Derived2 : Base {};
38struct Ambiguous : Derived, Derived2 {};
39struct Private : private Base {};
40struct Protected : protected Base {};
41
42template <typename T  // Handler type
43         ,typename E  // Thrown exception type
44         ,typename O  // Object type
45         >
46void 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
70template <typename T  // Handler type
71         ,typename E  // Thrown exception type
72         ,typename O  // Object type
73         >
74void 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
98void 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
122void 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
146void 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
170void 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
194void 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
218void 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
243void 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
267void 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
311void 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
335void 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
359void 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
383void 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
407void 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
431int 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