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 // UNSUPPORTED: libcxxabi-no-exceptions
     29 
     30 #include <exception>
     31 #include <stdlib.h>
     32 #include <assert.h>
     33 #include <stdio.h>
     34 
     35 struct Base {};
     36 struct Derived  : Base {};
     37 struct Derived2 : Base {};
     38 struct Ambiguous : Derived, Derived2 {};
     39 struct Private : private Base {};
     40 struct Protected : protected Base {};
     41 
     42 template <typename T  // Handler type
     43          ,typename E  // Thrown exception type
     44          ,typename O  // Object type
     45          >
     46 void assert_catches()
     47 {
     48     try
     49     {
     50         O o;
     51         throw static_cast<E>(&o);
     52         printf("%s\n", __PRETTY_FUNCTION__);
     53         assert(false && "Statements after throw must be unreachable");
     54     }
     55     catch (T t)
     56     {
     57         assert(true);
     58         return;
     59     }
     60     catch (...)
     61     {
     62         printf("%s\n", __PRETTY_FUNCTION__);
     63         assert(false && "Should not have entered catch-all");
     64     }
     65 
     66     printf("%s\n", __PRETTY_FUNCTION__);
     67     assert(false && "The catch should have returned");
     68 }
     69 
     70 template <typename T  // Handler type
     71          ,typename E  // Thrown exception type
     72          ,typename O  // Object type
     73          >
     74 void assert_cannot_catch()
     75 {
     76     try
     77     {
     78         O o;
     79         throw static_cast<E>(&o);
     80         printf("%s\n", __PRETTY_FUNCTION__);
     81         assert(false && "Statements after throw must be unreachable");
     82     }
     83     catch (T t)
     84     {
     85         printf("%s\n", __PRETTY_FUNCTION__);
     86         assert(false && "Should not have entered the catch");
     87     }
     88     catch (...)
     89     {
     90         assert(true);
     91         return;
     92     }
     93 
     94     printf("%s\n", __PRETTY_FUNCTION__);
     95     assert(false && "The catch-all should have returned");
     96 }
     97 
     98 void f1()
     99 {
    100     // Test that every combination of handler of type:
    101     //   cv1 Base * cv2
    102     // catches an exception of type:
    103     //   Derived *
    104     assert_catches<               Base *               , Derived *, Derived>();
    105     assert_catches<const          Base *               , Derived *, Derived>();
    106     assert_catches<      volatile Base *               , Derived *, Derived>();
    107     assert_catches<const volatile Base *               , Derived *, Derived>();
    108     assert_catches<               Base * const         , Derived *, Derived>();
    109     assert_catches<const          Base * const         , Derived *, Derived>();
    110     assert_catches<      volatile Base * const         , Derived *, Derived>();
    111     assert_catches<const volatile Base * const         , Derived *, Derived>();
    112     assert_catches<               Base *       volatile, Derived *, Derived>();
    113     assert_catches<const          Base *       volatile, Derived *, Derived>();
    114     assert_catches<      volatile Base *       volatile, Derived *, Derived>();
    115     assert_catches<const volatile Base *       volatile, Derived *, Derived>();
    116     assert_catches<               Base * const volatile, Derived *, Derived>();
    117     assert_catches<const          Base * const volatile, Derived *, Derived>();
    118     assert_catches<      volatile Base * const volatile, Derived *, Derived>();
    119     assert_catches<const volatile Base * const volatile, Derived *, Derived>();
    120 }
    121 
    122 void f2()
    123 {
    124     // Test that every combination of handler of type:
    125     //   cv1 Base * cv2
    126     // catches an exception of type:
    127     //   Base *
    128     assert_catches<               Base *               , Base *, Derived>();
    129     assert_catches<const          Base *               , Base *, Derived>();
    130     assert_catches<      volatile Base *               , Base *, Derived>();
    131     assert_catches<const volatile Base *               , Base *, Derived>();
    132     assert_catches<               Base * const         , Base *, Derived>();
    133     assert_catches<const          Base * const         , Base *, Derived>();
    134     assert_catches<      volatile Base * const         , Base *, Derived>();
    135     assert_catches<const volatile Base * const         , Base *, Derived>();
    136     assert_catches<               Base *       volatile, Base *, Derived>();
    137     assert_catches<const          Base *       volatile, Base *, Derived>();
    138     assert_catches<      volatile Base *       volatile, Base *, Derived>();
    139     assert_catches<const volatile Base *       volatile, Base *, Derived>();
    140     assert_catches<               Base * const volatile, Base *, Derived>();
    141     assert_catches<const          Base * const volatile, Base *, Derived>();
    142     assert_catches<      volatile Base * const volatile, Base *, Derived>();
    143     assert_catches<const volatile Base * const volatile, Base *, Derived>();
    144 }
    145 
    146 void f3()
    147 {
    148     // Test that every combination of handler of type:
    149     //   cv1 Derived * cv2
    150     // catches an exception of type:
    151     //   Derived *
    152     assert_catches<               Derived *               , Derived *, Derived>();
    153     assert_catches<const          Derived *               , Derived *, Derived>();
    154     assert_catches<      volatile Derived *               , Derived *, Derived>();
    155     assert_catches<const volatile Derived *               , Derived *, Derived>();
    156     assert_catches<               Derived * const         , Derived *, Derived>();
    157     assert_catches<const          Derived * const         , Derived *, Derived>();
    158     assert_catches<      volatile Derived * const         , Derived *, Derived>();
    159     assert_catches<const volatile Derived * const         , Derived *, Derived>();
    160     assert_catches<               Derived *       volatile, Derived *, Derived>();
    161     assert_catches<const          Derived *       volatile, Derived *, Derived>();
    162     assert_catches<      volatile Derived *       volatile, Derived *, Derived>();
    163     assert_catches<const volatile Derived *       volatile, Derived *, Derived>();
    164     assert_catches<               Derived * const volatile, Derived *, Derived>();
    165     assert_catches<const          Derived * const volatile, Derived *, Derived>();
    166     assert_catches<      volatile Derived * const volatile, Derived *, Derived>();
    167     assert_catches<const volatile Derived * const volatile, Derived *, Derived>();
    168 }
    169 
    170 void f4()
    171 {
    172     // Test that every combination of handler of type:
    173     //   cv1 Derived * cv2
    174     // cannot catch an exception of type:
    175     //   Base *
    176     assert_cannot_catch<               Derived *               , Base *, Derived>();
    177     assert_cannot_catch<const          Derived *               , Base *, Derived>();
    178     assert_cannot_catch<      volatile Derived *               , Base *, Derived>();
    179     assert_cannot_catch<const volatile Derived *               , Base *, Derived>();
    180     assert_cannot_catch<               Derived * const         , Base *, Derived>();
    181     assert_cannot_catch<const          Derived * const         , Base *, Derived>();
    182     assert_cannot_catch<      volatile Derived * const         , Base *, Derived>();
    183     assert_cannot_catch<const volatile Derived * const         , Base *, Derived>();
    184     assert_cannot_catch<               Derived *       volatile, Base *, Derived>();
    185     assert_cannot_catch<const          Derived *       volatile, Base *, Derived>();
    186     assert_cannot_catch<      volatile Derived *       volatile, Base *, Derived>();
    187     assert_cannot_catch<const volatile Derived *       volatile, Base *, Derived>();
    188     assert_cannot_catch<               Derived * const volatile, Base *, Derived>();
    189     assert_cannot_catch<const          Derived * const volatile, Base *, Derived>();
    190     assert_cannot_catch<      volatile Derived * const volatile, Base *, Derived>();
    191     assert_cannot_catch<const volatile Derived * const volatile, Base *, Derived>();
    192 }
    193 
    194 void f5()
    195 {
    196     // Test that every combination of handler of type:
    197     //   cv1 Derived * cv2 &
    198     // catches an exception of type:
    199     //   Derived *
    200     assert_catches<               Derived *                &, Derived *, Derived>();
    201     assert_catches<const          Derived *                &, Derived *, Derived>();
    202     assert_catches<      volatile Derived *                &, Derived *, Derived>();
    203     assert_catches<const volatile Derived *                &, Derived *, Derived>();
    204     assert_catches<               Derived * const          &, Derived *, Derived>();
    205     assert_catches<const          Derived * const          &, Derived *, Derived>();
    206     assert_catches<      volatile Derived * const          &, Derived *, Derived>();
    207     assert_catches<const volatile Derived * const          &, Derived *, Derived>();
    208     assert_catches<               Derived *       volatile &, Derived *, Derived>();
    209     assert_catches<const          Derived *       volatile &, Derived *, Derived>();
    210     assert_catches<      volatile Derived *       volatile &, Derived *, Derived>();
    211     assert_catches<const volatile Derived *       volatile &, Derived *, Derived>();
    212     assert_catches<               Derived * const volatile &, Derived *, Derived>();
    213     assert_catches<const          Derived * const volatile &, Derived *, Derived>();
    214     assert_catches<      volatile Derived * const volatile &, Derived *, Derived>();
    215     assert_catches<const volatile Derived * const volatile &, Derived *, Derived>();
    216 }
    217 
    218 void f6()
    219 {
    220     // Test that every combination of handler of type:
    221     //   cv1 Base * cv2 &
    222     // catches an exception of type:
    223     //   Base *
    224     assert_catches<               Base *                &, Base *, Derived>();
    225     assert_catches<const          Base *                &, Base *, Derived>();
    226     assert_catches<      volatile Base *                &, Base *, Derived>();
    227     assert_catches<const volatile Base *                &, Base *, Derived>();
    228     assert_catches<               Base * const          &, Base *, Derived>();
    229     assert_catches<const          Base * const          &, Base *, Derived>();
    230     assert_catches<      volatile Base * const          &, Base *, Derived>();
    231     assert_catches<const volatile Base * const          &, Base *, Derived>();
    232     assert_catches<               Base *       volatile &, Base *, Derived>();
    233     assert_catches<const          Base *       volatile &, Base *, Derived>();
    234     assert_catches<      volatile Base *       volatile &, Base *, Derived>();
    235     assert_catches<const volatile Base *       volatile &, Base *, Derived>();
    236     assert_catches<               Base * const volatile &, Base *, Derived>();
    237     assert_catches<const          Base * const volatile &, Base *, Derived>();
    238     assert_catches<      volatile Base * const volatile &, Base *, Derived>();
    239     assert_catches<const volatile Base * const volatile &, Base *, Derived>();
    240 
    241 }
    242 
    243 void f7()
    244 {
    245     // Test that every combination of handler of type:
    246     //   cv1 Derived * cv2 &
    247     // cannot catch an exception of type:
    248     //   Base *
    249     assert_cannot_catch<               Derived *                &, Base *, Derived>();
    250     assert_cannot_catch<const          Derived *                &, Base *, Derived>();
    251     assert_cannot_catch<      volatile Derived *                &, Base *, Derived>();
    252     assert_cannot_catch<const volatile Derived *                &, Base *, Derived>();
    253     assert_cannot_catch<               Derived * const          &, Base *, Derived>();
    254     assert_cannot_catch<const          Derived * const          &, Base *, Derived>();
    255     assert_cannot_catch<      volatile Derived * const          &, Base *, Derived>();
    256     assert_cannot_catch<const volatile Derived * const          &, Base *, Derived>();
    257     assert_cannot_catch<               Derived *       volatile &, Base *, Derived>();
    258     assert_cannot_catch<const          Derived *       volatile &, Base *, Derived>();
    259     assert_cannot_catch<      volatile Derived *       volatile &, Base *, Derived>();
    260     assert_cannot_catch<const volatile Derived *       volatile &, Base *, Derived>();
    261     assert_cannot_catch<               Derived * const volatile &, Base *, Derived>();
    262     assert_cannot_catch<const          Derived * const volatile &, Base *, Derived>();
    263     assert_cannot_catch<      volatile Derived * const volatile &, Base *, Derived>();
    264     assert_cannot_catch<const volatile Derived * const volatile &, Base *, Derived>();
    265 }
    266 
    267 void f8()
    268 {
    269     // This test case has a caveat noted in the discussion here:
    270     //   https://gcc.gnu.org/ml/gcc-patches/2009-08/msg00264.html
    271     // Specifically:
    272     //   This [test exposes a] corner case of the ARM C++ ABI. The generic C++
    273     //   ABI also gets this wrong, because I failed to notice the subtlety here.
    274     //   The issue is that 15.3/3 3rd bullet says:
    275     //     The handler is of type cv1 T* cv2 and E is a pointer type that
    276     //     can be converted to the type of the handler by either or both of:
    277     //       * a standard pointer conversion (4.10) not involving conversions
    278     //         to pointers to private or protected or ambiguous classes
    279     //   Notice that the handlers of type "cv1 T*cv2&" are not allowed such
    280     //   freedom to find a base class. The ABI error is that we treat handlers
    281     //   of reference type exactly the same as the corresponding hander of
    282     //   non-reference type. Elsewhere in the exception handling this makes no
    283     //   difference (for instance bullet 1 explicitly says 'cv T or cv T&').
    284     //
    285     // See also: http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#388
    286     //
    287     //  TL;DR: it is an unresolved C++ ABI defect that these do catch
    288 
    289     // Test that every combination of handler of type:
    290     //   cv1 Base * cv2 &
    291     // catches an exception of type:
    292     //   Derived *
    293     assert_catches<               Base *                &, Derived *, Derived>();
    294     assert_catches<const          Base *                &, Derived *, Derived>();
    295     assert_catches<      volatile Base *                &, Derived *, Derived>();
    296     assert_catches<const volatile Base *                &, Derived *, Derived>();
    297     assert_catches<               Base * const          &, Derived *, Derived>();
    298     assert_catches<const          Base * const          &, Derived *, Derived>();
    299     assert_catches<      volatile Base * const          &, Derived *, Derived>();
    300     assert_catches<const volatile Base * const          &, Derived *, Derived>();
    301     assert_catches<               Base *       volatile &, Derived *, Derived>();
    302     assert_catches<const          Base *       volatile &, Derived *, Derived>();
    303     assert_catches<      volatile Base *       volatile &, Derived *, Derived>();
    304     assert_catches<const volatile Base *       volatile &, Derived *, Derived>();
    305     assert_catches<               Base * const volatile &, Derived *, Derived>();
    306     assert_catches<const          Base * const volatile &, Derived *, Derived>();
    307     assert_catches<      volatile Base * const volatile &, Derived *, Derived>();
    308     assert_catches<const volatile Base * const volatile &, Derived *, Derived>();
    309 }
    310 
    311 void f9()
    312 {
    313     // Test that every combination of handler of type:
    314     //   cv1 Base * cv2
    315     // cannot catch an exception of type:
    316     //   Ambiguous *
    317     assert_cannot_catch<               Base *               , Ambiguous *, Ambiguous>();
    318     assert_cannot_catch<const          Base *               , Ambiguous *, Ambiguous>();
    319     assert_cannot_catch<      volatile Base *               , Ambiguous *, Ambiguous>();
    320     assert_cannot_catch<const volatile Base *               , Ambiguous *, Ambiguous>();
    321     assert_cannot_catch<               Base * const         , Ambiguous *, Ambiguous>();
    322     assert_cannot_catch<const          Base * const         , Ambiguous *, Ambiguous>();
    323     assert_cannot_catch<      volatile Base * const         , Ambiguous *, Ambiguous>();
    324     assert_cannot_catch<const volatile Base * const         , Ambiguous *, Ambiguous>();
    325     assert_cannot_catch<               Base *       volatile, Ambiguous *, Ambiguous>();
    326     assert_cannot_catch<const          Base *       volatile, Ambiguous *, Ambiguous>();
    327     assert_cannot_catch<      volatile Base *       volatile, Ambiguous *, Ambiguous>();
    328     assert_cannot_catch<const volatile Base *       volatile, Ambiguous *, Ambiguous>();
    329     assert_cannot_catch<               Base * const volatile, Ambiguous *, Ambiguous>();
    330     assert_cannot_catch<const          Base * const volatile, Ambiguous *, Ambiguous>();
    331     assert_cannot_catch<      volatile Base * const volatile, Ambiguous *, Ambiguous>();
    332     assert_cannot_catch<const volatile Base * const volatile, Ambiguous *, Ambiguous>();
    333 }
    334 
    335 void f10()
    336 {
    337     // Test that every combination of handler of type:
    338     //  cv1 Base * cv2
    339     // cannot catch an exception of type:
    340     //  Private *
    341     assert_cannot_catch<               Base *               , Private *, Private>();
    342     assert_cannot_catch<const          Base *               , Private *, Private>();
    343     assert_cannot_catch<      volatile Base *               , Private *, Private>();
    344     assert_cannot_catch<const volatile Base *               , Private *, Private>();
    345     assert_cannot_catch<               Base * const         , Private *, Private>();
    346     assert_cannot_catch<const          Base * const         , Private *, Private>();
    347     assert_cannot_catch<      volatile Base * const         , Private *, Private>();
    348     assert_cannot_catch<const volatile Base * const         , Private *, Private>();
    349     assert_cannot_catch<               Base *       volatile, Private *, Private>();
    350     assert_cannot_catch<const          Base *       volatile, Private *, Private>();
    351     assert_cannot_catch<      volatile Base *       volatile, Private *, Private>();
    352     assert_cannot_catch<const volatile Base *       volatile, Private *, Private>();
    353     assert_cannot_catch<               Base * const volatile, Private *, Private>();
    354     assert_cannot_catch<const          Base * const volatile, Private *, Private>();
    355     assert_cannot_catch<      volatile Base * const volatile, Private *, Private>();
    356     assert_cannot_catch<const volatile Base * const volatile, Private *, Private>();
    357 }
    358 
    359 void f11()
    360 {
    361     // Test that every combination of handler of type:
    362     //  cv1 Base * cv2
    363     // cannot catch an exception of type:
    364     //  Protected *
    365     assert_cannot_catch<               Base *               , Protected *, Protected>();
    366     assert_cannot_catch<const          Base *               , Protected *, Protected>();
    367     assert_cannot_catch<      volatile Base *               , Protected *, Protected>();
    368     assert_cannot_catch<const volatile Base *               , Protected *, Protected>();
    369     assert_cannot_catch<               Base * const         , Protected *, Protected>();
    370     assert_cannot_catch<const          Base * const         , Protected *, Protected>();
    371     assert_cannot_catch<      volatile Base * const         , Protected *, Protected>();
    372     assert_cannot_catch<const volatile Base * const         , Protected *, Protected>();
    373     assert_cannot_catch<               Base *       volatile, Protected *, Protected>();
    374     assert_cannot_catch<const          Base *       volatile, Protected *, Protected>();
    375     assert_cannot_catch<      volatile Base *       volatile, Protected *, Protected>();
    376     assert_cannot_catch<const volatile Base *       volatile, Protected *, Protected>();
    377     assert_cannot_catch<               Base * const volatile, Protected *, Protected>();
    378     assert_cannot_catch<const          Base * const volatile, Protected *, Protected>();
    379     assert_cannot_catch<      volatile Base * const volatile, Protected *, Protected>();
    380     assert_cannot_catch<const volatile Base * const volatile, Protected *, Protected>();
    381 }
    382 
    383 void f12()
    384 {
    385     // Test that every combination of handler of type:
    386     //  cv1 Base * cv2 &
    387     // cannot catch an exception of type:
    388     //  Private *
    389     assert_cannot_catch<               Base *                &, Private *, Private>();
    390     assert_cannot_catch<const          Base *                &, Private *, Private>();
    391     assert_cannot_catch<      volatile Base *                &, Private *, Private>();
    392     assert_cannot_catch<const volatile Base *                &, Private *, Private>();
    393     assert_cannot_catch<               Base * const          &, Private *, Private>();
    394     assert_cannot_catch<const          Base * const          &, Private *, Private>();
    395     assert_cannot_catch<      volatile Base * const          &, Private *, Private>();
    396     assert_cannot_catch<const volatile Base * const          &, Private *, Private>();
    397     assert_cannot_catch<               Base *       volatile &, Private *, Private>();
    398     assert_cannot_catch<const          Base *       volatile &, Private *, Private>();
    399     assert_cannot_catch<      volatile Base *       volatile &, Private *, Private>();
    400     assert_cannot_catch<const volatile Base *       volatile &, Private *, Private>();
    401     assert_cannot_catch<               Base * const volatile &, Private *, Private>();
    402     assert_cannot_catch<const          Base * const volatile &, Private *, Private>();
    403     assert_cannot_catch<      volatile Base * const volatile &, Private *, Private>();
    404     assert_cannot_catch<const volatile Base * const volatile &, Private *, Private>();
    405 }
    406 
    407 void f13()
    408 {
    409     // Test that every combination of handler of type:
    410     //  cv1 Base * cv2 &
    411     // cannot catch an exception of type:
    412     //  Protected *
    413     assert_cannot_catch<               Base *                &, Protected *, Protected>();
    414     assert_cannot_catch<const          Base *                &, Protected *, Protected>();
    415     assert_cannot_catch<      volatile Base *                &, Protected *, Protected>();
    416     assert_cannot_catch<const volatile Base *                &, Protected *, Protected>();
    417     assert_cannot_catch<               Base * const          &, Protected *, Protected>();
    418     assert_cannot_catch<const          Base * const          &, Protected *, Protected>();
    419     assert_cannot_catch<      volatile Base * const          &, Protected *, Protected>();
    420     assert_cannot_catch<const volatile Base * const          &, Protected *, Protected>();
    421     assert_cannot_catch<               Base *       volatile &, Protected *, Protected>();
    422     assert_cannot_catch<const          Base *       volatile &, Protected *, Protected>();
    423     assert_cannot_catch<      volatile Base *       volatile &, Protected *, Protected>();
    424     assert_cannot_catch<const volatile Base *       volatile &, Protected *, Protected>();
    425     assert_cannot_catch<               Base * const volatile &, Protected *, Protected>();
    426     assert_cannot_catch<const          Base * const volatile &, Protected *, Protected>();
    427     assert_cannot_catch<      volatile Base * const volatile &, Protected *, Protected>();
    428     assert_cannot_catch<const volatile Base * const volatile &, Protected *, Protected>();
    429 }
    430 
    431 int main()
    432 {
    433     f1();
    434     f2();
    435     f3();
    436     f4();
    437     f5();
    438     f6();
    439     f7();
    440     f8();
    441     f9();
    442     f10();
    443     f11();
    444     f12();
    445     f13();
    446 }
    447