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