catch_class_03.pass.cpp
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 // 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 : 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 : 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) : C1(id-1), C2(id-2), id_(id) {count++;} 75 A(const A& a) : 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 == 2); 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&>(static_cast<C1&>(a)).id_ == 2); 97 assert(static_cast<B&>(static_cast<C2&>(a)).id_ == 1); 98 throw a; 99 assert(false); 100 } 101 102 void f2() 103 { 104 try 105 { 106 assert(A::count == 0); 107 assert(C1::count == 0); 108 assert(C2::count == 0); 109 assert(B::count == 0); 110 f1(); 111 assert(false); 112 } 113 catch (const A& a) // can catch A 114 { 115 assert(a.id_ == 5); 116 assert(static_cast<const C1&>(a).id_ == 4); 117 assert(static_cast<const C2&>(a).id_ == 3); 118 assert(static_cast<const B&>(static_cast<const C1&>(a)).id_ == 2); 119 assert(static_cast<const B&>(static_cast<const C2&>(a)).id_ == 1); 120 throw; 121 } 122 catch (const C1&) 123 { 124 assert(false); 125 } 126 catch (const C2&) 127 { 128 assert(false); 129 } 130 catch (const B&) 131 { 132 assert(false); 133 } 134 } 135 136 void f3() 137 { 138 try 139 { 140 assert(A::count == 0); 141 assert(C1::count == 0); 142 assert(C2::count == 0); 143 assert(B::count == 0); 144 f2(); 145 assert(false); 146 } 147 catch (const B& a) // can not catch B (ambiguous base) 148 { 149 assert(false); 150 } 151 catch (const C1& c1) // can catch C1 152 { 153 assert(c1.id_ == 4); 154 assert(static_cast<const B&>(c1).id_ == 2); 155 throw; 156 } 157 catch (const C2&) 158 { 159 assert(false); 160 } 161 } 162 163 void f4() 164 { 165 try 166 { 167 assert(A::count == 0); 168 assert(C1::count == 0); 169 assert(C2::count == 0); 170 assert(B::count == 0); 171 f3(); 172 assert(false); 173 } 174 catch (const B& a) // can not catch B (ambiguous base) 175 { 176 assert(false); 177 } 178 catch (const C2& c2) // can catch C2 179 { 180 assert(c2.id_ == 3); 181 assert(static_cast<const B&>(c2).id_ == 1); 182 throw; 183 } 184 catch (const C1&) 185 { 186 assert(false); 187 } 188 } 189 190 int main(int, char**) 191 { 192 try 193 { 194 f4(); 195 assert(false); 196 } 197 catch (...) 198 { 199 } 200 assert(A::count == 0); 201 assert(C1::count == 0); 202 assert(C2::count == 0); 203 assert(B::count == 0); 204 205 return 0; 206 }