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