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