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