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