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 A a(5); 77 78 void f1() 79 { 80 throw &a; 81 assert(false); 82 } 83 84 void f2() 85 { 86 try 87 { 88 f1(); 89 assert(false); 90 } 91 catch (const A* a) // can catch A 92 { 93 assert(a->id_ == 5); 94 assert(static_cast<const C1*>(a)->id_ == 4); 95 assert(static_cast<const C2*>(a)->id_ == 3); 96 assert(static_cast<const B*>(a)->id_ == 8); 97 throw; 98 } 99 catch (const C1*) 100 { 101 assert(false); 102 } 103 catch (const C2*) 104 { 105 assert(false); 106 } 107 catch (const B*) 108 { 109 assert(false); 110 } 111 } 112 113 void f3() 114 { 115 try 116 { 117 f2(); 118 assert(false); 119 } 120 catch (const B* a) // can catch B 121 { 122 assert(static_cast<const B*>(a)->id_ == 8); 123 throw; 124 } 125 catch (const C1* c1) 126 { 127 assert(false); 128 } 129 catch (const C2*) 130 { 131 assert(false); 132 } 133 } 134 135 void f4() 136 { 137 try 138 { 139 f3(); 140 assert(false); 141 } 142 catch (const C2* c2) // can catch C2 143 { 144 assert(c2->id_ == 3); 145 throw; 146 } 147 catch (const B* a) 148 { 149 assert(false); 150 } 151 catch (const C1*) 152 { 153 assert(false); 154 } 155 } 156 157 void f5() 158 { 159 try 160 { 161 f4(); 162 assert(false); 163 } 164 catch (const C1* c1) // can catch C1 165 { 166 assert(c1->id_ == 4); 167 assert(static_cast<const B*>(c1)->id_ == 8); 168 throw; 169 } 170 catch (const B* a) 171 { 172 assert(false); 173 } 174 catch (const C2*) 175 { 176 assert(false); 177 } 178 } 179 180 int main() 181 { 182 try 183 { 184 f5(); 185 assert(false); 186 } 187 catch (...) 188 { 189 } 190 } 191