• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===--------------------- inherited_exception.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 // 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 // FIXME: GCC doesn't allow turning off the warning for exceptions being caught
30 //        by earlier handlers, which this test is exercising. We have to disable
31 //        warnings altogether to remove the error.
32 //        See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97675.
33 // ADDITIONAL_COMPILE_FLAGS: -Wno-error
34 
35 // Clang emits  warnings about exceptions of type 'Child' being caught by
36 // an earlier handler of type 'Base'. Congrats clang, you've just
37 // diagnosed the behavior under test.
38 #if defined(__clang__)
39 #pragma clang diagnostic ignored "-Wexceptions"
40 #endif
41 
42 #include <assert.h>
43 
44 struct Base {
45   int b1;
46 };
47 
48 struct Base2 {
49   int b2;
50 };
51 
52 struct Child : public Base, public Base2 {
53   int c;
54 };
55 
f1()56 void f1() {
57   Child child;
58   child.b1 = 10;
59   child.b2 = 11;
60   child.c = 12;
61   throw child;
62 }
63 
f2()64 void f2() {
65   Child child;
66   child.b1 = 10;
67   child.b2 = 11;
68   child.c = 12;
69   throw static_cast<Base2&>(child);
70 }
71 
f3()72 void f3() {
73   static Child child;
74   child.b1 = 10;
75   child.b2 = 11;
76   child.c = 12;
77   throw static_cast<Base2*>(&child);
78 }
79 
main(int,char **)80 int main(int, char**)
81 {
82     try
83     {
84         f1();
85         assert(false);
86     }
87     catch (const Child& c)
88     {
89         assert(true);
90     }
91     catch (const Base& b)
92     {
93         assert(false);
94     }
95     catch (...)
96     {
97         assert(false);
98     }
99 
100     try
101     {
102         f1();
103         assert(false);
104     }
105     catch (const Base& c)
106     {
107         assert(true);
108     }
109     catch (const Child& b)
110     {
111         assert(false);
112     }
113     catch (...)
114     {
115         assert(false);
116     }
117 
118     try
119     {
120         f1();
121         assert(false);
122     }
123     catch (const Base2& c)
124     {
125         assert(true);
126     }
127     catch (const Child& b)
128     {
129         assert(false);
130     }
131     catch (...)
132     {
133         assert(false);
134     }
135 
136     try
137     {
138         f2();
139         assert(false);
140     }
141     catch (const Child& c)
142     {
143         assert(false);
144     }
145     catch (const Base& b)
146     {
147         assert(false);
148     }
149     catch (const Base2& b)
150     {
151         assert(true);
152     }
153     catch (...)
154     {
155         assert(false);
156     }
157 
158     try
159     {
160         f3();
161         assert(false);
162     }
163     catch (const Base* c)
164     {
165         assert(false);
166     }
167     catch (const Child* b)
168     {
169         assert(false);
170     }
171     catch (const Base2* c)
172     {
173         assert(true);
174     }
175     catch (...)
176     {
177         assert(false);
178     }
179 
180     return 0;
181 }
182