1 //===----------------------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This test case checks specifically the cases under bullet 3.1 & 3.2:
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
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
25 //===----------------------------------------------------------------------===//
27 // UNSUPPORTED: no-exceptions
35 struct Derived
: Base
{};
36 struct Derived2
: Base
{};
37 struct Ambiguous
: Derived
, Derived2
{};
38 struct Private
: private Base
{};
39 struct Protected
: protected Base
{};
41 template <typename T
// Handler type
42 ,typename E
// Thrown exception type
43 ,typename O
// Object type
50 throw static_cast<E
>(&o
);
51 printf("%s\n", __PRETTY_FUNCTION__
);
52 assert(false && "Statements after throw must be unreachable");
61 printf("%s\n", __PRETTY_FUNCTION__
);
62 assert(false && "Should not have entered catch-all");
65 printf("%s\n", __PRETTY_FUNCTION__
);
66 assert(false && "The catch should have returned");
69 template <typename T
// Handler type
70 ,typename E
// Thrown exception type
71 ,typename O
// Object type
73 void assert_cannot_catch()
78 throw static_cast<E
>(&o
);
79 printf("%s\n", __PRETTY_FUNCTION__
);
80 assert(false && "Statements after throw must be unreachable");
84 printf("%s\n", __PRETTY_FUNCTION__
);
85 assert(false && "Should not have entered the catch");
93 printf("%s\n", __PRETTY_FUNCTION__
);
94 assert(false && "The catch-all should have returned");
99 // Test that every combination of handler of type:
101 // catches an exception of type:
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
>();
123 // Test that every combination of handler of type:
125 // catches an exception of type:
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
>();
147 // Test that every combination of handler of type:
149 // catches an exception of type:
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
>();
171 // Test that every combination of handler of type:
173 // cannot catch an exception of type:
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
>();
195 // Test that every combination of handler of type:
196 // cv1 Derived * cv2 &
197 // catches an exception of type:
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
>();
219 // Test that every combination of handler of type:
221 // catches an exception of type:
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
>();
244 // Test that every combination of handler of type:
245 // cv1 Derived * cv2 &
246 // cannot catch an exception of type:
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
>();
268 // This test case has a caveat noted in the discussion here:
269 // https://gcc.gnu.org/ml/gcc-patches/2009-08/msg00264.html
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&').
284 // See also: http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#388
286 // TL;DR: it is an unresolved C++ ABI defect that these do catch
288 // Test that every combination of handler of type:
290 // catches an exception of type:
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
>();
312 // Test that every combination of handler of type:
314 // cannot catch an exception of type:
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
>();
336 // Test that every combination of handler of type:
338 // cannot catch an exception of type:
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
>();
360 // Test that every combination of handler of type:
362 // cannot catch an exception of type:
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
>();
384 // Test that every combination of handler of type:
386 // cannot catch an exception of type:
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
>();
408 // Test that every combination of handler of type:
410 // cannot catch an exception of type:
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
>();
430 int main(int, char**)