| //===----------------------------------------------------------------------===// | 
 | // | 
 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
 | // See https://llvm.org/LICENSE.txt for license information. | 
 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | /* | 
 |     This test checks that adjustedPtr is correct as there exist offsets in this | 
 |     object for the various subobjects, all of which have a unique id_ to | 
 |     check against.  It also checks that virtual bases work properly | 
 | */ | 
 |  | 
 | // UNSUPPORTED: no-exceptions | 
 |  | 
 | // Compilers emit warnings about exceptions of type 'Child' being caught by | 
 | // an earlier handler of type 'Base'. Congrats, you've just diagnosed the | 
 | // behavior under test. | 
 | // ADDITIONAL_COMPILE_FLAGS: -Wno-exceptions | 
 |  | 
 | #include <exception> | 
 | #include <stdlib.h> | 
 | #include <assert.h> | 
 |  | 
 | struct B | 
 | { | 
 |     static int count; | 
 |     int id_; | 
 |     explicit B(int id) : id_(id) {count++;} | 
 |     B(const B& a) : id_(a.id_) {count++;} | 
 |     ~B() {count--;} | 
 | }; | 
 |  | 
 | int B::count = 0; | 
 |  | 
 | struct C1 | 
 |     : virtual B | 
 | { | 
 |     static int count; | 
 |     int id_; | 
 |     explicit C1(int id) : B(id-2), id_(id) {count++;} | 
 |     C1(const C1& a) : B(a.id_-2), id_(a.id_) {count++;} | 
 |     ~C1() {count--;} | 
 | }; | 
 |  | 
 | int C1::count = 0; | 
 |  | 
 | struct C2 | 
 |     : virtual private B | 
 | { | 
 |     static int count; | 
 |     int id_; | 
 |     explicit C2(int id) : B(id-2), id_(id) {count++;} | 
 |     C2(const C2& a) : B(a.id_-2), id_(a.id_) {count++;} | 
 |     ~C2() {count--;} | 
 | }; | 
 |  | 
 | int C2::count = 0; | 
 |  | 
 | struct A | 
 |     : C1, C2 | 
 | { | 
 |     static int count; | 
 |     int id_; | 
 |     explicit A(int id) : B(id+3), C1(id-1), C2(id-2), id_(id) {count++;} | 
 |     A(const A& a) : B(a.id_+3), C1(a.id_-1), C2(a.id_-2),  id_(a.id_) {count++;} | 
 |     ~A() {count--;} | 
 | }; | 
 |  | 
 | int A::count = 0; | 
 |  | 
 | A global_a(5); | 
 |  | 
 | void f1() | 
 | { | 
 |     throw &global_a; | 
 |     assert(false); | 
 | } | 
 |  | 
 | void f2() | 
 | { | 
 |     try | 
 |     { | 
 |         f1(); | 
 |         assert(false); | 
 |     } | 
 |     catch (const A* a)  // can catch A | 
 |     { | 
 |         assert(a->id_ == 5); | 
 |         assert(static_cast<const C1*>(a)->id_ == 4); | 
 |         assert(static_cast<const C2*>(a)->id_ == 3); | 
 |         assert(static_cast<const B*>(a)->id_ == 8); | 
 |         throw; | 
 |     } | 
 |     catch (const C1*) | 
 |     { | 
 |         assert(false); | 
 |     } | 
 |     catch (const C2*) | 
 |     { | 
 |         assert(false); | 
 |     } | 
 |     catch (const B*) | 
 |     { | 
 |         assert(false); | 
 |     } | 
 | } | 
 |  | 
 | void f3() | 
 | { | 
 |     try | 
 |     { | 
 |         f2(); | 
 |         assert(false); | 
 |     } | 
 |     catch (const B* a)  // can catch B | 
 |     { | 
 |         assert(static_cast<const B*>(a)->id_ == 8); | 
 |         throw; | 
 |     } | 
 |     catch (const C1* c1) | 
 |     { | 
 |         assert(false); | 
 |     } | 
 |     catch (const C2*) | 
 |     { | 
 |         assert(false); | 
 |     } | 
 | } | 
 |  | 
 | void f4() | 
 | { | 
 |     try | 
 |     { | 
 |         f3(); | 
 |         assert(false); | 
 |     } | 
 |     catch (const C2* c2)  // can catch C2 | 
 |     { | 
 |         assert(c2->id_ == 3); | 
 |         throw; | 
 |     } | 
 |     catch (const B* a) | 
 |     { | 
 |         assert(false); | 
 |     } | 
 |     catch (const C1*) | 
 |     { | 
 |         assert(false); | 
 |     } | 
 | } | 
 |  | 
 | void f5() | 
 | { | 
 |     try | 
 |     { | 
 |         f4(); | 
 |         assert(false); | 
 |     } | 
 |     catch (const C1* c1)  // can catch C1 | 
 |     { | 
 |         assert(c1->id_ == 4); | 
 |         assert(static_cast<const B*>(c1)->id_ == 8); | 
 |         throw; | 
 |     } | 
 |     catch (const B* a) | 
 |     { | 
 |         assert(false); | 
 |     } | 
 |     catch (const C2*) | 
 |     { | 
 |         assert(false); | 
 |     } | 
 | } | 
 |  | 
 | int main(int, char**) | 
 | { | 
 |     try | 
 |     { | 
 |         f5(); | 
 |         assert(false); | 
 |     } | 
 |     catch (...) | 
 |     { | 
 |     } | 
 |  | 
 |     return 0; | 
 | } |