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_; |
30 | explicit B(int id) : id_(id) {count++;} |
31 | B(const B& a) : id_(a.id_) {count++;} |
32 | ~B() {count--;} |
33 | }; |
34 | |
35 | int B::count = 0; |
36 | |
37 | struct C1 |
38 | : virtual B |
39 | { |
40 | static int count; |
41 | int id_; |
42 | explicit C1(int id) : B(id-2), id_(id) {count++;} |
43 | C1(const C1& a) : B(a.id_-2), id_(a.id_) {count++;} |
44 | ~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_; |
54 | explicit C2(int id) : B(id-2), id_(id) {count++;} |
55 | C2(const C2& a) : B(a.id_-2), id_(a.id_) {count++;} |
56 | ~C2() {count--;} |
57 | }; |
58 | |
59 | int C2::count = 0; |
60 | |
61 | struct A |
62 | : C1, C2 |
63 | { |
64 | static int count; |
65 | int id_; |
66 | explicit A(int id) : B(id+3), C1(id-1), C2(id-2), id_(id) {count++;} |
67 | A(const A& a) : B(a.id_+3), C1(a.id_-1), C2(a.id_-2), id_(a.id_) {count++;} |
68 | ~A() {count--;} |
69 | }; |
70 | |
71 | int A::count = 0; |
72 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |