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
34struct Base {};
35struct Derived : Base {};
36struct Derived2 : Base {};
37struct Ambiguous : Derived, Derived2 {};
38struct Private : private Base {};
39struct Protected : protected Base {};
40
41template <typename T // Handler type
42 ,typename E // Thrown exception type
43 ,typename O // Object type
44 >
45void 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
69template <typename T // Handler type
70 ,typename E // Thrown exception type
71 ,typename O // Object type
72 >
73void 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
97void 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
121void 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
145void 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
169void 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
193void 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
217void 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
242void 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
266void 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
310void 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
334void 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
358void 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
382void 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
406void 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
430int 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

source code of libcxxabi/test/catch_pointer_reference.pass.cpp