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
36struct Base {
37 int b1;
38};
39
40struct Base2 {
41 int b2;
42};
43
44struct Child : public Base, public Base2 {
45 int c;
46};
47
48void f1() {
49 Child child;
50 child.b1 = 10;
51 child.b2 = 11;
52 child.c = 12;
53 throw child;
54}
55
56void f2() {
57 Child child;
58 child.b1 = 10;
59 child.b2 = 11;
60 child.c = 12;
61 throw static_cast<Base2&>(child);
62}
63
64void 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
72int 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

source code of libcxxabi/test/inherited_exception.pass.cpp