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 
33 struct Base {};
34 struct Derived  : Base {};
35 struct Derived2 : Base {};
36 struct Ambiguous : Derived, Derived2 {};
37 struct Private : private Base {};
38 struct Protected : protected Base {};
39 
40 template <typename T  // Handler type
41          ,typename E  // Thrown exception type
42          ,typename O  // Object type
43          >
assert_catches()44 void 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 
68 template <typename T  // Handler type
69          ,typename E  // Thrown exception type
70          ,typename O  // Object type
71          >
assert_cannot_catch()72 void 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 
f1()96 void 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 
f2()120 void 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 
f3()144 void 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 
f4()168 void 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 
f5()192 void 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 
f6()216 void 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 
f7()241 void 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 
f8()265 void 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 
f9()309 void 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 
f10()333 void 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 
f11()357 void 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 
f12()381 void 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 
f13()405 void 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 
main()429 int 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