xref: /llvm-project/libcxxabi/test/catch_class_04.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.  It also checks that virtual bases work properly
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     : virtual 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     : virtual private 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) : B(id+3), C1(id-1), C2(id-2), id_(id) {count++;}
AA67     A(const A& a) :  B(a.id_+3), 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 == 1);
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&>(a).id_ == 8);
89     throw a;
90     assert(false);
91 }
92 
f2()93 void f2()
94 {
95     try
96     {
97         assert(A::count == 0);
98         assert(C1::count == 0);
99         assert(C2::count == 0);
100         assert(B::count == 0);
101         f1();
102         assert(false);
103     }
104     catch (const A& a)  // can catch A
105     {
106         assert(a.id_ == 5);
107         assert(static_cast<const C1&>(a).id_ == 4);
108         assert(static_cast<const C2&>(a).id_ == 3);
109         assert(static_cast<const B&>(a).id_ == 8);
110         throw;
111     }
112     catch (const C1&)
113     {
114         assert(false);
115     }
116     catch (const C2&)
117     {
118         assert(false);
119     }
120     catch (const B&)
121     {
122         assert(false);
123     }
124 }
125 
f3()126 void f3()
127 {
128     try
129     {
130         assert(A::count == 0);
131         assert(C1::count == 0);
132         assert(C2::count == 0);
133         assert(B::count == 0);
134         f2();
135         assert(false);
136     }
137     catch (const B& a)  // can catch B
138     {
139         assert(static_cast<const B&>(a).id_ == 8);
140         throw;
141     }
142     catch (const C1& c1)
143     {
144         assert(false);
145     }
146     catch (const C2&)
147     {
148         assert(false);
149     }
150 }
151 
f4()152 void f4()
153 {
154     try
155     {
156         assert(A::count == 0);
157         assert(C1::count == 0);
158         assert(C2::count == 0);
159         assert(B::count == 0);
160         f3();
161         assert(false);
162     }
163     catch (const C2& c2)  // can catch C2
164     {
165         assert(c2.id_ == 3);
166         throw;
167     }
168     catch (const B& a)  // can not catch B (ambiguous base)
169     {
170         assert(false);
171     }
172     catch (const C1&)
173     {
174         assert(false);
175     }
176 }
177 
f5()178 void f5()
179 {
180     try
181     {
182         assert(A::count == 0);
183         assert(C1::count == 0);
184         assert(C2::count == 0);
185         assert(B::count == 0);
186         f4();
187         assert(false);
188     }
189     catch (const C1& c1)  // can catch C1
190     {
191         assert(c1.id_ == 4);
192         assert(static_cast<const B&>(c1).id_ == 8);
193         throw;
194     }
195     catch (const B& a)
196     {
197         assert(false);
198     }
199     catch (const C2&)
200     {
201         assert(false);
202     }
203 }
204 
main(int,char **)205 int main(int, char**)
206 {
207     try
208     {
209         f5();
210         assert(false);
211     }
212     catch (...)
213     {
214     }
215     assert(A::count == 0);
216     assert(C1::count == 0);
217     assert(C2::count == 0);
218     assert(B::count == 0);
219 
220     return 0;
221 }
222