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 | A global_a(5); |
74 | |
75 | void f1() |
76 | { |
77 | throw &global_a; |
78 | assert(false); |
79 | } |
80 | |
81 | void f2() |
82 | { |
83 | try |
84 | { |
85 | f1(); |
86 | assert(false); |
87 | } |
88 | catch (const A* a) // can catch A |
89 | { |
90 | assert(a->id_ == 5); |
91 | assert(static_cast<const C1*>(a)->id_ == 4); |
92 | assert(static_cast<const C2*>(a)->id_ == 3); |
93 | assert(static_cast<const B*>(a)->id_ == 8); |
94 | throw; |
95 | } |
96 | catch (const C1*) |
97 | { |
98 | assert(false); |
99 | } |
100 | catch (const C2*) |
101 | { |
102 | assert(false); |
103 | } |
104 | catch (const B*) |
105 | { |
106 | assert(false); |
107 | } |
108 | } |
109 | |
110 | void f3() |
111 | { |
112 | try |
113 | { |
114 | f2(); |
115 | assert(false); |
116 | } |
117 | catch (const B* a) // can catch B |
118 | { |
119 | assert(static_cast<const B*>(a)->id_ == 8); |
120 | throw; |
121 | } |
122 | catch (const C1* c1) |
123 | { |
124 | assert(false); |
125 | } |
126 | catch (const C2*) |
127 | { |
128 | assert(false); |
129 | } |
130 | } |
131 | |
132 | void f4() |
133 | { |
134 | try |
135 | { |
136 | f3(); |
137 | assert(false); |
138 | } |
139 | catch (const C2* c2) // can catch C2 |
140 | { |
141 | assert(c2->id_ == 3); |
142 | throw; |
143 | } |
144 | catch (const B* a) |
145 | { |
146 | assert(false); |
147 | } |
148 | catch (const C1*) |
149 | { |
150 | assert(false); |
151 | } |
152 | } |
153 | |
154 | void f5() |
155 | { |
156 | try |
157 | { |
158 | f4(); |
159 | assert(false); |
160 | } |
161 | catch (const C1* c1) // can catch C1 |
162 | { |
163 | assert(c1->id_ == 4); |
164 | assert(static_cast<const B*>(c1)->id_ == 8); |
165 | throw; |
166 | } |
167 | catch (const B* a) |
168 | { |
169 | assert(false); |
170 | } |
171 | catch (const C2*) |
172 | { |
173 | assert(false); |
174 | } |
175 | } |
176 | |
177 | int main(int, char**) |
178 | { |
179 | try |
180 | { |
181 | f5(); |
182 | assert(false); |
183 | } |
184 | catch (...) |
185 | { |
186 | } |
187 | |
188 | return 0; |
189 | } |
190 | |