1 //===---------------------- catch_class_04.cpp ----------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 /*
11     This test checks that adjustedPtr is correct as there exist offsets in this
12     object for the various subobjects, all of which have a unique id_ to
13     check against.  It also checks that virtual bases work properly
14 */
15 
16 #include <exception>
17 #include <stdlib.h>
18 #include <assert.h>
19 
20 struct B
21 {
22     static int count;
23     int id_;
BB24     explicit B(int id) : id_(id) {count++;}
BB25     B(const B& a) : id_(a.id_) {count++;}
~BB26     ~B() {count--;}
27 };
28 
29 int B::count = 0;
30 
31 struct C1
32     : virtual B
33 {
34     static int count;
35     int id_;
C1C136     explicit C1(int id) : B(id-2), id_(id) {count++;}
C1C137     C1(const C1& a) : B(a.id_-2), id_(a.id_) {count++;}
~C1C138     ~C1() {count--;}
39 };
40 
41 int C1::count = 0;
42 
43 struct C2
44     : virtual private B
45 {
46     static int count;
47     int id_;
C2C248     explicit C2(int id) : B(id-2), id_(id) {count++;}
C2C249     C2(const C2& a) : B(a.id_-2), id_(a.id_) {count++;}
~C2C250     ~C2() {count--;}
51 };
52 
53 int C2::count = 0;
54 
55 struct A
56     : C1, C2
57 {
58     static int count;
59     int id_;
AA60     explicit A(int id) : C1(id-1), C2(id-2), B(id+3), id_(id) {count++;}
AA61     A(const A& a) : C1(a.id_-1), C2(a.id_-2), B(a.id_+3), id_(a.id_) {count++;}
~AA62     ~A() {count--;}
63 };
64 
65 int A::count = 0;
66 
f1()67 void f1()
68 {
69     assert(A::count == 0);
70     assert(C1::count == 0);
71     assert(C2::count == 0);
72     assert(B::count == 0);
73     A a(5);
74     assert(A::count == 1);
75     assert(C1::count == 1);
76     assert(C2::count == 1);
77     assert(B::count == 1);
78 
79     assert(a.id_ == 5);
80     assert(static_cast<C1&>(a).id_ == 4);
81     assert(static_cast<C2&>(a).id_ == 3);
82     assert(static_cast<B&>(a).id_ == 8);
83     throw a;
84     assert(false);
85 }
86 
f2()87 void f2()
88 {
89     try
90     {
91         assert(A::count == 0);
92         assert(C1::count == 0);
93         assert(C2::count == 0);
94         assert(B::count == 0);
95         f1();
96         assert(false);
97     }
98     catch (const A& a)  // can catch A
99     {
100         assert(a.id_ == 5);
101         assert(static_cast<const C1&>(a).id_ == 4);
102         assert(static_cast<const C2&>(a).id_ == 3);
103         assert(static_cast<const B&>(a).id_ == 8);
104         throw;
105     }
106     catch (const C1&)
107     {
108         assert(false);
109     }
110     catch (const C2&)
111     {
112         assert(false);
113     }
114     catch (const B&)
115     {
116         assert(false);
117     }
118 }
119 
f3()120 void f3()
121 {
122     try
123     {
124         assert(A::count == 0);
125         assert(C1::count == 0);
126         assert(C2::count == 0);
127         assert(B::count == 0);
128         f2();
129         assert(false);
130     }
131     catch (const B& a)  // can catch B
132     {
133         assert(static_cast<const B&>(a).id_ == 8);
134         throw;
135     }
136     catch (const C1& c1)
137     {
138         assert(false);
139     }
140     catch (const C2&)
141     {
142         assert(false);
143     }
144 }
145 
f4()146 void f4()
147 {
148     try
149     {
150         assert(A::count == 0);
151         assert(C1::count == 0);
152         assert(C2::count == 0);
153         assert(B::count == 0);
154         f3();
155         assert(false);
156     }
157     catch (const C2& c2)  // can catch C2
158     {
159         assert(c2.id_ == 3);
160         throw;
161     }
162     catch (const B& a)  // can not catch B (ambiguous base)
163     {
164         assert(false);
165     }
166     catch (const C1&)
167     {
168         assert(false);
169     }
170 }
171 
f5()172 void f5()
173 {
174     try
175     {
176         assert(A::count == 0);
177         assert(C1::count == 0);
178         assert(C2::count == 0);
179         assert(B::count == 0);
180         f4();
181         assert(false);
182     }
183     catch (const C1& c1)  // can catch C1
184     {
185         assert(c1.id_ == 4);
186         assert(static_cast<const B&>(c1).id_ == 8);
187         throw;
188     }
189     catch (const B& a)
190     {
191         assert(false);
192     }
193     catch (const C2&)
194     {
195         assert(false);
196     }
197 }
198 
main()199 int main()
200 {
201     try
202     {
203         f5();
204         assert(false);
205     }
206     catch (...)
207     {
208     }
209     assert(A::count == 0);
210     assert(C1::count == 0);
211     assert(C2::count == 0);
212     assert(B::count == 0);
213 }
214