catch_class_04.pass.cpp
1 //===---------------------- catch_class_04.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 /* 10 This test checks that adjustedPtr is correct as there exist offsets in this 11 object for the various subobjects, all of which have a unique id_ to 12 check against. It also checks that virtual bases work properly 13 */ 14 15 // UNSUPPORTED: no-exceptions 16 17 // FIXME: GCC doesn't allow turning off the warning for exceptions being caught 18 // by earlier handlers, which this test is exercising. We have to disable 19 // warnings altogether to remove the error. 20 // See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97675. 21 // ADDITIONAL_COMPILE_FLAGS: -Wno-error 22 23 #include <exception> 24 #include <stdlib.h> 25 #include <assert.h> 26 27 // Clang emits warnings about exceptions of type 'Child' being caught by 28 // an earlier handler of type 'Base'. Congrats clang, you've just 29 // diagnosed the behavior under test. 30 #if defined(__clang__) 31 #pragma clang diagnostic ignored "-Wexceptions" 32 #endif 33 34 struct B 35 { 36 static int count; 37 int id_; 38 explicit B(int id) : id_(id) {count++;} 39 B(const B& a) : id_(a.id_) {count++;} 40 ~B() {count--;} 41 }; 42 43 int B::count = 0; 44 45 struct C1 46 : virtual B 47 { 48 static int count; 49 int id_; 50 explicit C1(int id) : B(id-2), id_(id) {count++;} 51 C1(const C1& a) : B(a.id_-2), id_(a.id_) {count++;} 52 ~C1() {count--;} 53 }; 54 55 int C1::count = 0; 56 57 struct C2 58 : virtual private B 59 { 60 static int count; 61 int id_; 62 explicit C2(int id) : B(id-2), id_(id) {count++;} 63 C2(const C2& a) : B(a.id_-2), id_(a.id_) {count++;} 64 ~C2() {count--;} 65 }; 66 67 int C2::count = 0; 68 69 struct A 70 : C1, C2 71 { 72 static int count; 73 int id_; 74 explicit A(int id) : B(id+3), C1(id-1), C2(id-2), id_(id) {count++;} 75 A(const A& a) : B(a.id_+3), C1(a.id_-1), C2(a.id_-2), id_(a.id_) {count++;} 76 ~A() {count--;} 77 }; 78 79 int A::count = 0; 80 81 void f1() 82 { 83 assert(A::count == 0); 84 assert(C1::count == 0); 85 assert(C2::count == 0); 86 assert(B::count == 0); 87 A a(5); 88 assert(A::count == 1); 89 assert(C1::count == 1); 90 assert(C2::count == 1); 91 assert(B::count == 1); 92 93 assert(a.id_ == 5); 94 assert(static_cast<C1&>(a).id_ == 4); 95 assert(static_cast<C2&>(a).id_ == 3); 96 assert(static_cast<B&>(a).id_ == 8); 97 throw a; 98 assert(false); 99 } 100 101 void f2() 102 { 103 try 104 { 105 assert(A::count == 0); 106 assert(C1::count == 0); 107 assert(C2::count == 0); 108 assert(B::count == 0); 109 f1(); 110 assert(false); 111 } 112 catch (const A& a) // can catch A 113 { 114 assert(a.id_ == 5); 115 assert(static_cast<const C1&>(a).id_ == 4); 116 assert(static_cast<const C2&>(a).id_ == 3); 117 assert(static_cast<const B&>(a).id_ == 8); 118 throw; 119 } 120 catch (const C1&) 121 { 122 assert(false); 123 } 124 catch (const C2&) 125 { 126 assert(false); 127 } 128 catch (const B&) 129 { 130 assert(false); 131 } 132 } 133 134 void f3() 135 { 136 try 137 { 138 assert(A::count == 0); 139 assert(C1::count == 0); 140 assert(C2::count == 0); 141 assert(B::count == 0); 142 f2(); 143 assert(false); 144 } 145 catch (const B& a) // can catch B 146 { 147 assert(static_cast<const B&>(a).id_ == 8); 148 throw; 149 } 150 catch (const C1& c1) 151 { 152 assert(false); 153 } 154 catch (const C2&) 155 { 156 assert(false); 157 } 158 } 159 160 void f4() 161 { 162 try 163 { 164 assert(A::count == 0); 165 assert(C1::count == 0); 166 assert(C2::count == 0); 167 assert(B::count == 0); 168 f3(); 169 assert(false); 170 } 171 catch (const C2& c2) // can catch C2 172 { 173 assert(c2.id_ == 3); 174 throw; 175 } 176 catch (const B& a) // can not catch B (ambiguous base) 177 { 178 assert(false); 179 } 180 catch (const C1&) 181 { 182 assert(false); 183 } 184 } 185 186 void f5() 187 { 188 try 189 { 190 assert(A::count == 0); 191 assert(C1::count == 0); 192 assert(C2::count == 0); 193 assert(B::count == 0); 194 f4(); 195 assert(false); 196 } 197 catch (const C1& c1) // can catch C1 198 { 199 assert(c1.id_ == 4); 200 assert(static_cast<const B&>(c1).id_ == 8); 201 throw; 202 } 203 catch (const B& a) 204 { 205 assert(false); 206 } 207 catch (const C2&) 208 { 209 assert(false); 210 } 211 } 212 213 int main(int, char**) 214 { 215 try 216 { 217 f5(); 218 assert(false); 219 } 220 catch (...) 221 { 222 } 223 assert(A::count == 0); 224 assert(C1::count == 0); 225 assert(C2::count == 0); 226 assert(B::count == 0); 227 228 return 0; 229 }