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 #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_;
BB32     explicit B(int id) : id_(id) {count++;}
BB33     B(const B& a) : id_(a.id_) {count++;}
~BB34     ~B() {count--;}
35 };
36 
37 int B::count = 0;
38 
39 struct C1
40     : B
41 {
42     static int count;
43     int id_;
C1C144     explicit C1(int id) : B(id-2), id_(id) {count++;}
C1C145     C1(const C1& a) : B(a.id_-2), id_(a.id_) {count++;}
~C1C146     ~C1() {count--;}
47 };
48 
49 int C1::count = 0;
50 
51 struct C2
52     : B
53 {
54     static int count;
55     int id_;
C2C256     explicit C2(int id) : B(id-2), id_(id) {count++;}
C2C257     C2(const C2& a) : B(a.id_-2), id_(a.id_) {count++;}
~C2C258     ~C2() {count--;}
59 };
60 
61 int C2::count = 0;
62 
63 struct A
64     : C1, C2
65 {
66     static int count;
67     int id_;
AA68     explicit A(int id) : C1(id-1), C2(id-2), id_(id) {count++;}
AA69     A(const A& a) : C1(a.id_-1), C2(a.id_-2), id_(a.id_) {count++;}
~AA70     ~A() {count--;}
71 };
72 
73 int A::count = 0;
74 
f1()75 void f1()
76 {
77     assert(A::count == 0);
78     assert(C1::count == 0);
79     assert(C2::count == 0);
80     assert(B::count == 0);
81     A a(5);
82     assert(A::count == 1);
83     assert(C1::count == 1);
84     assert(C2::count == 1);
85     assert(B::count == 2);
86 
87     assert(a.id_ == 5);
88     assert(static_cast<C1&>(a).id_ == 4);
89     assert(static_cast<C2&>(a).id_ == 3);
90     assert(static_cast<B&>(static_cast<C1&>(a)).id_ == 2);
91     assert(static_cast<B&>(static_cast<C2&>(a)).id_ == 1);
92     throw a;
93     assert(false);
94 }
95 
f2()96 void f2()
97 {
98     try
99     {
100         assert(A::count == 0);
101         assert(C1::count == 0);
102         assert(C2::count == 0);
103         assert(B::count == 0);
104         f1();
105         assert(false);
106     }
107     catch (const A& a)  // can catch A
108     {
109         assert(a.id_ == 5);
110         assert(static_cast<const C1&>(a).id_ == 4);
111         assert(static_cast<const C2&>(a).id_ == 3);
112         assert(static_cast<const B&>(static_cast<const C1&>(a)).id_ == 2);
113         assert(static_cast<const B&>(static_cast<const C2&>(a)).id_ == 1);
114         throw;
115     }
116     catch (const C1&)
117     {
118         assert(false);
119     }
120     catch (const C2&)
121     {
122         assert(false);
123     }
124     catch (const B&)
125     {
126         assert(false);
127     }
128 }
129 
f3()130 void f3()
131 {
132     try
133     {
134         assert(A::count == 0);
135         assert(C1::count == 0);
136         assert(C2::count == 0);
137         assert(B::count == 0);
138         f2();
139         assert(false);
140     }
141     catch (const B& a)  // can not catch B (ambiguous base)
142     {
143         assert(false);
144     }
145     catch (const C1& c1)  // can catch C1
146     {
147         assert(c1.id_ == 4);
148         assert(static_cast<const B&>(c1).id_ == 2);
149         throw;
150     }
151     catch (const C2&)
152     {
153         assert(false);
154     }
155 }
156 
f4()157 void f4()
158 {
159     try
160     {
161         assert(A::count == 0);
162         assert(C1::count == 0);
163         assert(C2::count == 0);
164         assert(B::count == 0);
165         f3();
166         assert(false);
167     }
168     catch (const B& a)  // can not catch B (ambiguous base)
169     {
170         assert(false);
171     }
172     catch (const C2& c2)  // can catch C2
173     {
174         assert(c2.id_ == 3);
175         assert(static_cast<const B&>(c2).id_ == 1);
176         throw;
177     }
178     catch (const C1&)
179     {
180         assert(false);
181     }
182 }
183 
main()184 int main()
185 {
186     try
187     {
188         f4();
189         assert(false);
190     }
191     catch (...)
192     {
193     }
194     assert(A::count == 0);
195     assert(C1::count == 0);
196     assert(C2::count == 0);
197     assert(B::count == 0);
198 }
199