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