1 //===--------------------- inherited_exception.cpp ------------------------===// 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 // FIXME: GCC doesn't allow turning off the warning for exceptions being caught 30 // by earlier handlers, which this test is exercising. We have to disable 31 // warnings altogether to remove the error. 32 // See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97675. 33 // ADDITIONAL_COMPILE_FLAGS: -Wno-error 34 35 // Clang emits warnings about exceptions of type 'Child' being caught by 36 // an earlier handler of type 'Base'. Congrats clang, you've just 37 // diagnosed the behavior under test. 38 #if defined(__clang__) 39 #pragma clang diagnostic ignored "-Wexceptions" 40 #endif 41 42 #include <assert.h> 43 44 struct Base { 45 int b1; 46 }; 47 48 struct Base2 { 49 int b2; 50 }; 51 52 struct Child : public Base, public Base2 { 53 int c; 54 }; 55 f1()56void f1() { 57 Child child; 58 child.b1 = 10; 59 child.b2 = 11; 60 child.c = 12; 61 throw child; 62 } 63 f2()64void f2() { 65 Child child; 66 child.b1 = 10; 67 child.b2 = 11; 68 child.c = 12; 69 throw static_cast<Base2&>(child); 70 } 71 f3()72void f3() { 73 static Child child; 74 child.b1 = 10; 75 child.b2 = 11; 76 child.c = 12; 77 throw static_cast<Base2*>(&child); 78 } 79 main(int,char **)80int main(int, char**) 81 { 82 try 83 { 84 f1(); 85 assert(false); 86 } 87 catch (const Child& c) 88 { 89 assert(true); 90 } 91 catch (const Base& b) 92 { 93 assert(false); 94 } 95 catch (...) 96 { 97 assert(false); 98 } 99 100 try 101 { 102 f1(); 103 assert(false); 104 } 105 catch (const Base& c) 106 { 107 assert(true); 108 } 109 catch (const Child& b) 110 { 111 assert(false); 112 } 113 catch (...) 114 { 115 assert(false); 116 } 117 118 try 119 { 120 f1(); 121 assert(false); 122 } 123 catch (const Base2& c) 124 { 125 assert(true); 126 } 127 catch (const Child& b) 128 { 129 assert(false); 130 } 131 catch (...) 132 { 133 assert(false); 134 } 135 136 try 137 { 138 f2(); 139 assert(false); 140 } 141 catch (const Child& c) 142 { 143 assert(false); 144 } 145 catch (const Base& b) 146 { 147 assert(false); 148 } 149 catch (const Base2& b) 150 { 151 assert(true); 152 } 153 catch (...) 154 { 155 assert(false); 156 } 157 158 try 159 { 160 f3(); 161 assert(false); 162 } 163 catch (const Base* c) 164 { 165 assert(false); 166 } 167 catch (const Child* b) 168 { 169 assert(false); 170 } 171 catch (const Base2* c) 172 { 173 assert(true); 174 } 175 catch (...) 176 { 177 assert(false); 178 } 179 180 return 0; 181 } 182