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_; |
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 | : 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 | : 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) : C1(id-1), C2(id-2), id_(id) {count++;} |
67 | A(const A& a) : 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 == 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 | |
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 | |
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 | |
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 | |
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 | |