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 #include <exception>
18 #include <stdlib.h>
19 #include <assert.h>
20 
21 // Clang emits  warnings about exceptions of type 'Child' being caught by
22 // an earlier handler of type 'Base'. Congrats clang, you've just
23 // diagnosed the behavior under test.
24 #if defined(__clang__)
25 #pragma clang diagnostic ignored "-Wexceptions"
26 #endif
27 
28 struct B
29 {
30     static int count;
31     int id_;
32     explicit B(int id) : id_(id) {count++;}
33     B(const B& a) : id_(a.id_) {count++;}
34     ~B() {count--;}
35 };
36 
37 int B::count = 0;
38 
39 struct C1
40     : virtual B
41 {
42     static int count;
43     int id_;
44     explicit C1(int id) : B(id-2), id_(id) {count++;}
45     C1(const C1& a) : B(a.id_-2), id_(a.id_) {count++;}
46     ~C1() {count--;}
47 };
48 
49 int C1::count = 0;
50 
51 struct C2
52     : virtual private B
53 {
54     static int count;
55     int id_;
56     explicit C2(int id) : B(id-2), id_(id) {count++;}
57     C2(const C2& a) : B(a.id_-2), id_(a.id_) {count++;}
58     ~C2() {count--;}
59 };
60 
61 int C2::count = 0;
62 
63 struct A
64     : C1, C2
65 {
66     static int count;
67     int id_;
68     explicit A(int id) : B(id+3), C1(id-1), C2(id-2), id_(id) {count++;}
69     A(const A& a) :  B(a.id_+3), C1(a.id_-1), C2(a.id_-2), id_(a.id_) {count++;}
70     ~A() {count--;}
71 };
72 
73 int A::count = 0;
74 
75 void f1()
76 {
77     assert(A::count == 0);
78     assert(C1::count == 0);
79     assert(C2::count == 0);
80     assert(B::count == 0);
81     A a(5);
82     assert(A::count == 1);
83     assert(C1::count == 1);
84     assert(C2::count == 1);
85     assert(B::count == 1);
86 
87     assert(a.id_ == 5);
88     assert(static_cast<C1&>(a).id_ == 4);
89     assert(static_cast<C2&>(a).id_ == 3);
90     assert(static_cast<B&>(a).id_ == 8);
91     throw a;
92     assert(false);
93 }
94 
95 void f2()
96 {
97     try
98     {
99         assert(A::count == 0);
100         assert(C1::count == 0);
101         assert(C2::count == 0);
102         assert(B::count == 0);
103         f1();
104         assert(false);
105     }
106     catch (const A& a)  // can catch A
107     {
108         assert(a.id_ == 5);
109         assert(static_cast<const C1&>(a).id_ == 4);
110         assert(static_cast<const C2&>(a).id_ == 3);
111         assert(static_cast<const B&>(a).id_ == 8);
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 
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 catch B
140     {
141         assert(static_cast<const B&>(a).id_ == 8);
142         throw;
143     }
144     catch (const C1& c1)
145     {
146         assert(false);
147     }
148     catch (const C2&)
149     {
150         assert(false);
151     }
152 }
153 
154 void f4()
155 {
156     try
157     {
158         assert(A::count == 0);
159         assert(C1::count == 0);
160         assert(C2::count == 0);
161         assert(B::count == 0);
162         f3();
163         assert(false);
164     }
165     catch (const C2& c2)  // can catch C2
166     {
167         assert(c2.id_ == 3);
168         throw;
169     }
170     catch (const B& a)  // can not catch B (ambiguous base)
171     {
172         assert(false);
173     }
174     catch (const C1&)
175     {
176         assert(false);
177     }
178 }
179 
180 void f5()
181 {
182     try
183     {
184         assert(A::count == 0);
185         assert(C1::count == 0);
186         assert(C2::count == 0);
187         assert(B::count == 0);
188         f4();
189         assert(false);
190     }
191     catch (const C1& c1)  // can catch C1
192     {
193         assert(c1.id_ == 4);
194         assert(static_cast<const B&>(c1).id_ == 8);
195         throw;
196     }
197     catch (const B& a)
198     {
199         assert(false);
200     }
201     catch (const C2&)
202     {
203         assert(false);
204     }
205 }
206 
207 int main(int, char**)
208 {
209     try
210     {
211         f5();
212         assert(false);
213     }
214     catch (...)
215     {
216     }
217     assert(A::count == 0);
218     assert(C1::count == 0);
219     assert(C2::count == 0);
220     assert(B::count == 0);
221 
222     return 0;
223 }
224