1 //===---------------------- catch_class_03.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.
13 */
14
15 // UNSUPPORTED: no-exceptions
16
17 // FIXME: GCC doesn't allow turning off the warning for exceptions being caught
18 // by earlier handlers, which this test is exercising. We have to disable
19 // warnings altogether to remove the error.
20 // See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97675.
21 // ADDITIONAL_COMPILE_FLAGS: -Wno-error
22
23 #include <exception>
24 #include <stdlib.h>
25 #include <assert.h>
26
27 // Clang emits warnings about exceptions of type 'Child' being caught by
28 // an earlier handler of type 'Base'. Congrats clang, you've just
29 // diagnosed the behavior under test.
30 #if defined(__clang__)
31 #pragma clang diagnostic ignored "-Wexceptions"
32 #endif
33
34 struct B
35 {
36 static int count;
37 int id_;
BB38 explicit B(int id) : id_(id) {count++;}
BB39 B(const B& a) : id_(a.id_) {count++;}
~BB40 ~B() {count--;}
41 };
42
43 int B::count = 0;
44
45 struct C1
46 : B
47 {
48 static int count;
49 int id_;
C1C150 explicit C1(int id) : B(id-2), id_(id) {count++;}
C1C151 C1(const C1& a) : B(a.id_-2), id_(a.id_) {count++;}
~C1C152 ~C1() {count--;}
53 };
54
55 int C1::count = 0;
56
57 struct C2
58 : B
59 {
60 static int count;
61 int id_;
C2C262 explicit C2(int id) : B(id-2), id_(id) {count++;}
C2C263 C2(const C2& a) : B(a.id_-2), id_(a.id_) {count++;}
~C2C264 ~C2() {count--;}
65 };
66
67 int C2::count = 0;
68
69 struct A
70 : C1, C2
71 {
72 static int count;
73 int id_;
AA74 explicit A(int id) : C1(id-1), C2(id-2), id_(id) {count++;}
AA75 A(const A& a) : C1(a.id_-1), C2(a.id_-2), id_(a.id_) {count++;}
~AA76 ~A() {count--;}
77 };
78
79 int A::count = 0;
80
f1()81 void f1()
82 {
83 assert(A::count == 0);
84 assert(C1::count == 0);
85 assert(C2::count == 0);
86 assert(B::count == 0);
87 A a(5);
88 assert(A::count == 1);
89 assert(C1::count == 1);
90 assert(C2::count == 1);
91 assert(B::count == 2);
92
93 assert(a.id_ == 5);
94 assert(static_cast<C1&>(a).id_ == 4);
95 assert(static_cast<C2&>(a).id_ == 3);
96 assert(static_cast<B&>(static_cast<C1&>(a)).id_ == 2);
97 assert(static_cast<B&>(static_cast<C2&>(a)).id_ == 1);
98 throw a;
99 assert(false);
100 }
101
f2()102 void f2()
103 {
104 try
105 {
106 assert(A::count == 0);
107 assert(C1::count == 0);
108 assert(C2::count == 0);
109 assert(B::count == 0);
110 f1();
111 assert(false);
112 }
113 catch (const A& a) // can catch A
114 {
115 assert(a.id_ == 5);
116 assert(static_cast<const C1&>(a).id_ == 4);
117 assert(static_cast<const C2&>(a).id_ == 3);
118 assert(static_cast<const B&>(static_cast<const C1&>(a)).id_ == 2);
119 assert(static_cast<const B&>(static_cast<const C2&>(a)).id_ == 1);
120 throw;
121 }
122 catch (const C1&)
123 {
124 assert(false);
125 }
126 catch (const C2&)
127 {
128 assert(false);
129 }
130 catch (const B&)
131 {
132 assert(false);
133 }
134 }
135
f3()136 void f3()
137 {
138 try
139 {
140 assert(A::count == 0);
141 assert(C1::count == 0);
142 assert(C2::count == 0);
143 assert(B::count == 0);
144 f2();
145 assert(false);
146 }
147 catch (const B& a) // can not catch B (ambiguous base)
148 {
149 assert(false);
150 }
151 catch (const C1& c1) // can catch C1
152 {
153 assert(c1.id_ == 4);
154 assert(static_cast<const B&>(c1).id_ == 2);
155 throw;
156 }
157 catch (const C2&)
158 {
159 assert(false);
160 }
161 }
162
f4()163 void f4()
164 {
165 try
166 {
167 assert(A::count == 0);
168 assert(C1::count == 0);
169 assert(C2::count == 0);
170 assert(B::count == 0);
171 f3();
172 assert(false);
173 }
174 catch (const B& a) // can not catch B (ambiguous base)
175 {
176 assert(false);
177 }
178 catch (const C2& c2) // can catch C2
179 {
180 assert(c2.id_ == 3);
181 assert(static_cast<const B&>(c2).id_ == 1);
182 throw;
183 }
184 catch (const C1&)
185 {
186 assert(false);
187 }
188 }
189
main(int,char **)190 int main(int, char**)
191 {
192 try
193 {
194 f4();
195 assert(false);
196 }
197 catch (...)
198 {
199 }
200 assert(A::count == 0);
201 assert(C1::count == 0);
202 assert(C2::count == 0);
203 assert(B::count == 0);
204
205 return 0;
206 }
207