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