xref: /llvm-project/libcxxabi/test/catch_class_03.pass.cpp (revision eb8650a75793b2bd079d0c8901ff066f129061da)
1 //===----------------------------------------------------------------------===//
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 // Compilers emit warnings about exceptions of type 'Child' being caught by
18 // an earlier handler of type 'Base'. Congrats, you've just diagnosed the
19 // behavior under test.
20 // ADDITIONAL_COMPILE_FLAGS: -Wno-exceptions
21 
22 #include <exception>
23 #include <stdlib.h>
24 #include <assert.h>
25 
26 struct B
27 {
28     static int count;
29     int id_;
BB30     explicit B(int id) : id_(id) {count++;}
BB31     B(const B& a) : id_(a.id_) {count++;}
~BB32     ~B() {count--;}
33 };
34 
35 int B::count = 0;
36 
37 struct C1
38     : B
39 {
40     static int count;
41     int id_;
C1C142     explicit C1(int id) : B(id-2), id_(id) {count++;}
C1C143     C1(const C1& a) : B(a.id_-2), id_(a.id_) {count++;}
~C1C144     ~C1() {count--;}
45 };
46 
47 int C1::count = 0;
48 
49 struct C2
50     : B
51 {
52     static int count;
53     int id_;
C2C254     explicit C2(int id) : B(id-2), id_(id) {count++;}
C2C255     C2(const C2& a) : B(a.id_-2), id_(a.id_) {count++;}
~C2C256     ~C2() {count--;}
57 };
58 
59 int C2::count = 0;
60 
61 struct A
62     : C1, C2
63 {
64     static int count;
65     int id_;
AA66     explicit A(int id) : C1(id-1), C2(id-2), id_(id) {count++;}
AA67     A(const A& a) : C1(a.id_-1), C2(a.id_-2), id_(a.id_) {count++;}
~AA68     ~A() {count--;}
69 };
70 
71 int A::count = 0;
72 
f1()73 void f1()
74 {
75     assert(A::count == 0);
76     assert(C1::count == 0);
77     assert(C2::count == 0);
78     assert(B::count == 0);
79     A a(5);
80     assert(A::count == 1);
81     assert(C1::count == 1);
82     assert(C2::count == 1);
83     assert(B::count == 2);
84 
85     assert(a.id_ == 5);
86     assert(static_cast<C1&>(a).id_ == 4);
87     assert(static_cast<C2&>(a).id_ == 3);
88     assert(static_cast<B&>(static_cast<C1&>(a)).id_ == 2);
89     assert(static_cast<B&>(static_cast<C2&>(a)).id_ == 1);
90     throw a;
91     assert(false);
92 }
93 
f2()94 void f2()
95 {
96     try
97     {
98         assert(A::count == 0);
99         assert(C1::count == 0);
100         assert(C2::count == 0);
101         assert(B::count == 0);
102         f1();
103         assert(false);
104     }
105     catch (const A& a)  // can catch A
106     {
107         assert(a.id_ == 5);
108         assert(static_cast<const C1&>(a).id_ == 4);
109         assert(static_cast<const C2&>(a).id_ == 3);
110         assert(static_cast<const B&>(static_cast<const C1&>(a)).id_ == 2);
111         assert(static_cast<const B&>(static_cast<const C2&>(a)).id_ == 1);
112         throw;
113     }
114     catch (const C1&)
115     {
116         assert(false);
117     }
118     catch (const C2&)
119     {
120         assert(false);
121     }
122     catch (const B&)
123     {
124         assert(false);
125     }
126 }
127 
f3()128 void f3()
129 {
130     try
131     {
132         assert(A::count == 0);
133         assert(C1::count == 0);
134         assert(C2::count == 0);
135         assert(B::count == 0);
136         f2();
137         assert(false);
138     }
139     catch (const B& a)  // can not catch B (ambiguous base)
140     {
141         assert(false);
142     }
143     catch (const C1& c1)  // can catch C1
144     {
145         assert(c1.id_ == 4);
146         assert(static_cast<const B&>(c1).id_ == 2);
147         throw;
148     }
149     catch (const C2&)
150     {
151         assert(false);
152     }
153 }
154 
f4()155 void f4()
156 {
157     try
158     {
159         assert(A::count == 0);
160         assert(C1::count == 0);
161         assert(C2::count == 0);
162         assert(B::count == 0);
163         f3();
164         assert(false);
165     }
166     catch (const B& a)  // can not catch B (ambiguous base)
167     {
168         assert(false);
169     }
170     catch (const C2& c2)  // can catch C2
171     {
172         assert(c2.id_ == 3);
173         assert(static_cast<const B&>(c2).id_ == 1);
174         throw;
175     }
176     catch (const C1&)
177     {
178         assert(false);
179     }
180 }
181 
main(int,char **)182 int main(int, char**)
183 {
184     try
185     {
186         f4();
187         assert(false);
188     }
189     catch (...)
190     {
191     }
192     assert(A::count == 0);
193     assert(C1::count == 0);
194     assert(C2::count == 0);
195     assert(B::count == 0);
196 
197     return 0;
198 }
199