Home | History | Annotate | Download | only in test
      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          >
     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          >
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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