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