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