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