1 //===---------------------- catch_class_03.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. 13 */ 14 15 // UNSUPPORTED: no-exceptions 16 17 #include <exception> 18 #include <stdlib.h> 19 #include <assert.h> 20 21 // Clang emits warnings about exceptions of type 'Child' being caught by 22 // an earlier handler of type 'Base'. Congrats clang, you've just 23 // diagnosed the behavior under test. 24 #if defined(__clang__) 25 #pragma clang diagnostic ignored "-Wexceptions" 26 #endif 27 28 struct B 29 { 30 static int count; 31 int id_; 32 explicit B(int id) : id_(id) {count++;} 33 B(const B& a) : id_(a.id_) {count++;} 34 ~B() {count--;} 35 }; 36 37 int B::count = 0; 38 39 struct C1 40 : B 41 { 42 static int count; 43 int id_; 44 explicit C1(int id) : B(id-2), id_(id) {count++;} 45 C1(const C1& a) : B(a.id_-2), id_(a.id_) {count++;} 46 ~C1() {count--;} 47 }; 48 49 int C1::count = 0; 50 51 struct C2 52 : B 53 { 54 static int count; 55 int id_; 56 explicit C2(int id) : B(id-2), id_(id) {count++;} 57 C2(const C2& a) : B(a.id_-2), id_(a.id_) {count++;} 58 ~C2() {count--;} 59 }; 60 61 int C2::count = 0; 62 63 struct A 64 : C1, C2 65 { 66 static int count; 67 int id_; 68 explicit A(int id) : C1(id-1), C2(id-2), id_(id) {count++;} 69 A(const A& a) : C1(a.id_-1), C2(a.id_-2), id_(a.id_) {count++;} 70 ~A() {count--;} 71 }; 72 73 int A::count = 0; 74 75 void f1() 76 { 77 assert(A::count == 0); 78 assert(C1::count == 0); 79 assert(C2::count == 0); 80 assert(B::count == 0); 81 A a(5); 82 assert(A::count == 1); 83 assert(C1::count == 1); 84 assert(C2::count == 1); 85 assert(B::count == 2); 86 87 assert(a.id_ == 5); 88 assert(static_cast<C1&>(a).id_ == 4); 89 assert(static_cast<C2&>(a).id_ == 3); 90 assert(static_cast<B&>(static_cast<C1&>(a)).id_ == 2); 91 assert(static_cast<B&>(static_cast<C2&>(a)).id_ == 1); 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&>(static_cast<const C1&>(a)).id_ == 2); 113 assert(static_cast<const B&>(static_cast<const C2&>(a)).id_ == 1); 114 throw; 115 } 116 catch (const C1&) 117 { 118 assert(false); 119 } 120 catch (const C2&) 121 { 122 assert(false); 123 } 124 catch (const B&) 125 { 126 assert(false); 127 } 128 } 129 130 void f3() 131 { 132 try 133 { 134 assert(A::count == 0); 135 assert(C1::count == 0); 136 assert(C2::count == 0); 137 assert(B::count == 0); 138 f2(); 139 assert(false); 140 } 141 catch (const B& a) // can not catch B (ambiguous base) 142 { 143 assert(false); 144 } 145 catch (const C1& c1) // can catch C1 146 { 147 assert(c1.id_ == 4); 148 assert(static_cast<const B&>(c1).id_ == 2); 149 throw; 150 } 151 catch (const C2&) 152 { 153 assert(false); 154 } 155 } 156 157 void f4() 158 { 159 try 160 { 161 assert(A::count == 0); 162 assert(C1::count == 0); 163 assert(C2::count == 0); 164 assert(B::count == 0); 165 f3(); 166 assert(false); 167 } 168 catch (const B& a) // can not catch B (ambiguous base) 169 { 170 assert(false); 171 } 172 catch (const C2& c2) // can catch C2 173 { 174 assert(c2.id_ == 3); 175 assert(static_cast<const B&>(c2).id_ == 1); 176 throw; 177 } 178 catch (const C1&) 179 { 180 assert(false); 181 } 182 } 183 184 int main() 185 { 186 try 187 { 188 f4(); 189 assert(false); 190 } 191 catch (...) 192 { 193 } 194 assert(A::count == 0); 195 assert(C1::count == 0); 196 assert(C2::count == 0); 197 assert(B::count == 0); 198 } 199