Home | History | Annotate | Download | only in test
      1 //===--------------------- inherited_exception.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 C++ ABI 15.3.1, and 15.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 // Clang emits  warnings about exceptions of type 'Child' being caught by
     31 // an earlier handler of type 'Base'. Congrats clang, you've just
     32 // diagnosed the behavior under test.
     33 #if defined(__clang__)
     34 #pragma clang diagnostic ignored "-Wexceptions"
     35 #endif
     36 
     37 #include <assert.h>
     38 
     39 struct Base {
     40   int b1;
     41 };
     42 
     43 struct Base2 {
     44   int b2;
     45 };
     46 
     47 struct Child : public Base, public Base2 {
     48   int c;
     49 };
     50 
     51 void f1() {
     52   Child child;
     53   child.b1 = 10;
     54   child.b2 = 11;
     55   child.c = 12;
     56   throw child;
     57 }
     58 
     59 void f2() {
     60   Child child;
     61   child.b1 = 10;
     62   child.b2 = 11;
     63   child.c = 12;
     64   throw static_cast<Base2&>(child);
     65 }
     66 
     67 void f3() {
     68   static Child child;
     69   child.b1 = 10;
     70   child.b2 = 11;
     71   child.c = 12;
     72   throw static_cast<Base2*>(&child);
     73 }
     74 
     75 int main()
     76 {
     77     try
     78     {
     79         f1();
     80         assert(false);
     81     }
     82     catch (const Child& c)
     83     {
     84         assert(true);
     85     }
     86     catch (const Base& b)
     87     {
     88         assert(false);
     89     }
     90     catch (...)
     91     {
     92         assert(false);
     93     }
     94 
     95     try
     96     {
     97         f1();
     98         assert(false);
     99     }
    100     catch (const Base& c)
    101     {
    102         assert(true);
    103     }
    104     catch (const Child& b)
    105     {
    106         assert(false);
    107     }
    108     catch (...)
    109     {
    110         assert(false);
    111     }
    112 
    113     try
    114     {
    115         f1();
    116         assert(false);
    117     }
    118     catch (const Base2& c)
    119     {
    120         assert(true);
    121     }
    122     catch (const Child& b)
    123     {
    124         assert(false);
    125     }
    126     catch (...)
    127     {
    128         assert(false);
    129     }
    130 
    131     try
    132     {
    133         f2();
    134         assert(false);
    135     }
    136     catch (const Child& c)
    137     {
    138         assert(false);
    139     }
    140     catch (const Base& b)
    141     {
    142         assert(false);
    143     }
    144     catch (const Base2& b)
    145     {
    146         assert(true);
    147     }
    148     catch (...)
    149     {
    150         assert(false);
    151     }
    152 
    153     try
    154     {
    155         f3();
    156         assert(false);
    157     }
    158     catch (const Base* c)
    159     {
    160         assert(false);
    161     }
    162     catch (const Child* b)
    163     {
    164         assert(false);
    165     }
    166     catch (const Base2* c)
    167     {
    168         assert(true);
    169     }
    170     catch (...)
    171     {
    172         assert(false);
    173     }
    174 }
    175