1 | //===----------------------------------------------------------------------===// |
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 | // This test case checks specifically the cases under C++ ABI 15.3.1, and 15.3.2 |
10 | // |
11 | // C++ ABI 15.3: |
12 | // A handler is a match for an exception object of type E if |
13 | // > * The handler is of type cv T or cv T& and E and T are the same type < |
14 | // > (ignoring the top-level cv-qualifiers), or < |
15 | // > * the handler is of type cv T or cv T& and T is an unambiguous base < |
16 | // > class of E, or < |
17 | // * the handler is of type cv1 T* cv2 and E is a pointer type that can |
18 | // be converted to the type of the handler by either or both of |
19 | // o a standard pointer conversion (4.10 [conv.ptr]) not involving |
20 | // conversions to private or protected or ambiguous classes |
21 | // o a qualification conversion |
22 | // * the handler is a pointer or pointer to member type and E is |
23 | // std::nullptr_t |
24 | // |
25 | //===----------------------------------------------------------------------===// |
26 | |
27 | // UNSUPPORTED: no-exceptions |
28 | |
29 | // Compilers emit warnings about exceptions of type 'Child' being caught by |
30 | // an earlier handler of type 'Base'. Congrats, you've just diagnosed the |
31 | // behavior under test. |
32 | // ADDITIONAL_COMPILE_FLAGS: -Wno-exceptions |
33 | |
34 | #include <assert.h> |
35 | |
36 | struct Base { |
37 | int b1; |
38 | }; |
39 | |
40 | struct Base2 { |
41 | int b2; |
42 | }; |
43 | |
44 | struct Child : public Base, public Base2 { |
45 | int c; |
46 | }; |
47 | |
48 | void f1() { |
49 | Child child; |
50 | child.b1 = 10; |
51 | child.b2 = 11; |
52 | child.c = 12; |
53 | throw child; |
54 | } |
55 | |
56 | void f2() { |
57 | Child child; |
58 | child.b1 = 10; |
59 | child.b2 = 11; |
60 | child.c = 12; |
61 | throw static_cast<Base2&>(child); |
62 | } |
63 | |
64 | void f3() { |
65 | static Child child; |
66 | child.b1 = 10; |
67 | child.b2 = 11; |
68 | child.c = 12; |
69 | throw static_cast<Base2*>(&child); |
70 | } |
71 | |
72 | int main(int, char**) |
73 | { |
74 | try |
75 | { |
76 | f1(); |
77 | assert(false); |
78 | } |
79 | catch (const Child& c) |
80 | { |
81 | assert(true); |
82 | } |
83 | catch (const Base& b) |
84 | { |
85 | assert(false); |
86 | } |
87 | catch (...) |
88 | { |
89 | assert(false); |
90 | } |
91 | |
92 | try |
93 | { |
94 | f1(); |
95 | assert(false); |
96 | } |
97 | catch (const Base& c) |
98 | { |
99 | assert(true); |
100 | } |
101 | catch (const Child& b) |
102 | { |
103 | assert(false); |
104 | } |
105 | catch (...) |
106 | { |
107 | assert(false); |
108 | } |
109 | |
110 | try |
111 | { |
112 | f1(); |
113 | assert(false); |
114 | } |
115 | catch (const Base2& c) |
116 | { |
117 | assert(true); |
118 | } |
119 | catch (const Child& b) |
120 | { |
121 | assert(false); |
122 | } |
123 | catch (...) |
124 | { |
125 | assert(false); |
126 | } |
127 | |
128 | try |
129 | { |
130 | f2(); |
131 | assert(false); |
132 | } |
133 | catch (const Child& c) |
134 | { |
135 | assert(false); |
136 | } |
137 | catch (const Base& b) |
138 | { |
139 | assert(false); |
140 | } |
141 | catch (const Base2& b) |
142 | { |
143 | assert(true); |
144 | } |
145 | catch (...) |
146 | { |
147 | assert(false); |
148 | } |
149 | |
150 | try |
151 | { |
152 | f3(); |
153 | assert(false); |
154 | } |
155 | catch (const Base* c) |
156 | { |
157 | assert(false); |
158 | } |
159 | catch (const Child* b) |
160 | { |
161 | assert(false); |
162 | } |
163 | catch (const Base2* c) |
164 | { |
165 | assert(true); |
166 | } |
167 | catch (...) |
168 | { |
169 | assert(false); |
170 | } |
171 | |
172 | return 0; |
173 | } |
174 | |