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 #include <exception>
18 #include <stdlib.h>
19 #include <assert.h>
20 
21 // Clang emits  warnings about exceptions of type 'Child' being caught by
22 // an earlier handler of type 'Base'. Congrats clang, you've just
23 // diagnosed the behavior under test.
24 #if defined(__clang__)
25 #pragma clang diagnostic ignored "-Wexceptions"
26 #endif
27 
28 struct B
29 {
30     static int count;
31     int id_;
32     explicit B(int id) : id_(id) {count++;}
33     B(const B& a) : id_(a.id_) {count++;}
34     ~B() {count--;}
35 };
36 
37 int B::count = 0;
38 
39 struct C1
40     : virtual B
41 {
42     static int count;
43     int id_;
44     explicit C1(int id) : B(id-2), id_(id) {count++;}
45     C1(const C1& a) : B(a.id_-2), id_(a.id_) {count++;}
46     ~C1() {count--;}
47 };
48 
49 int C1::count = 0;
50 
51 struct C2
52     : virtual private B
53 {
54     static int count;
55     int id_;
56     explicit C2(int id) : B(id-2), id_(id) {count++;}
57     C2(const C2& a) : B(a.id_-2), id_(a.id_) {count++;}
58     ~C2() {count--;}
59 };
60 
61 int C2::count = 0;
62 
63 struct A
64     : C1, C2
65 {
66     static int count;
67     int id_;
68     explicit A(int id) : B(id+3), C1(id-1), C2(id-2), id_(id) {count++;}
69     A(const A& a) : B(a.id_+3), C1(a.id_-1), C2(a.id_-2),  id_(a.id_) {count++;}
70     ~A() {count--;}
71 };
72 
73 int A::count = 0;
74 
75 A a(5);
76 
77 void f1()
78 {
79     throw &a;
80     assert(false);
81 }
82 
83 void f2()
84 {
85     try
86     {
87         f1();
88         assert(false);
89     }
90     catch (const A* a)  // can catch A
91     {
92         assert(a->id_ == 5);
93         assert(static_cast<const C1*>(a)->id_ == 4);
94         assert(static_cast<const C2*>(a)->id_ == 3);
95         assert(static_cast<const B*>(a)->id_ == 8);
96         throw;
97     }
98     catch (const C1*)
99     {
100         assert(false);
101     }
102     catch (const C2*)
103     {
104         assert(false);
105     }
106     catch (const B*)
107     {
108         assert(false);
109     }
110 }
111 
112 void f3()
113 {
114     try
115     {
116         f2();
117         assert(false);
118     }
119     catch (const B* a)  // can catch B
120     {
121         assert(static_cast<const B*>(a)->id_ == 8);
122         throw;
123     }
124     catch (const C1* c1)
125     {
126         assert(false);
127     }
128     catch (const C2*)
129     {
130         assert(false);
131     }
132 }
133 
134 void f4()
135 {
136     try
137     {
138         f3();
139         assert(false);
140     }
141     catch (const C2* c2)  // can catch C2
142     {
143         assert(c2->id_ == 3);
144         throw;
145     }
146     catch (const B* a)
147     {
148         assert(false);
149     }
150     catch (const C1*)
151     {
152         assert(false);
153     }
154 }
155 
156 void f5()
157 {
158     try
159     {
160         f4();
161         assert(false);
162     }
163     catch (const C1* c1)  // can catch C1
164     {
165         assert(c1->id_ == 4);
166         assert(static_cast<const B*>(c1)->id_ == 8);
167         throw;
168     }
169     catch (const B* a)
170     {
171         assert(false);
172     }
173     catch (const C2*)
174     {
175         assert(false);
176     }
177 }
178 
179 int main()
180 {
181     try
182     {
183         f5();
184         assert(false);
185     }
186     catch (...)
187     {
188     }
189 }
190