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