1d5f84e61SIain Sandoe //===----------------------------------------------------------------------===//
2d5f84e61SIain Sandoe //
3d5f84e61SIain Sandoe // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4d5f84e61SIain Sandoe // See https://llvm.org/LICENSE.txt for license information.
5d5f84e61SIain Sandoe // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6d5f84e61SIain Sandoe //
7d5f84e61SIain Sandoe //===----------------------------------------------------------------------===//
8d5f84e61SIain Sandoe //
9d5f84e61SIain Sandoe // This test case checks specifically the cases under bullet 3.3:
10d5f84e61SIain Sandoe //
11d5f84e61SIain Sandoe // C++ ABI 15.3:
12d5f84e61SIain Sandoe // A handler is a match for an exception object of type E if
13d5f84e61SIain Sandoe // * The handler is of type cv T or cv T& and E and T are the same type
14d5f84e61SIain Sandoe // (ignoring the top-level cv-qualifiers), or
15d5f84e61SIain Sandoe // * the handler is of type cv T or cv T& and T is an unambiguous base
16d5f84e61SIain Sandoe // class of E, or
17d5f84e61SIain Sandoe // > * the handler is of type cv1 T* cv2 and E is a pointer type that can <
18d5f84e61SIain Sandoe // > be converted to the type of the handler by either or both of <
19d5f84e61SIain Sandoe // > o a standard pointer conversion (4.10 [conv.ptr]) not involving <
20d5f84e61SIain Sandoe // > conversions to private or protected or ambiguous classes <
21d5f84e61SIain Sandoe // > o a qualification conversion <
22d5f84e61SIain Sandoe // * the handler is a pointer or pointer to member type and E is
23d5f84e61SIain Sandoe // std::nullptr_t
24d5f84e61SIain Sandoe //
25d5f84e61SIain Sandoe //===----------------------------------------------------------------------===//
26d5f84e61SIain Sandoe
27d5f84e61SIain Sandoe // UNSUPPORTED: no-exceptions
28*34975009SLouis Dionne
29*34975009SLouis Dionne // This test requires the fix to https://github.com/llvm/llvm-project/issues/64953,
30*34975009SLouis Dionne // which landed in d5f84e6 and is in the libc++abi built library.
31*34975009SLouis Dionne // XFAIL: using-built-library-before-llvm-18
32d5f84e61SIain Sandoe
33d5f84e61SIain Sandoe #include <exception>
34d5f84e61SIain Sandoe #include <stdlib.h>
35d5f84e61SIain Sandoe #include <assert.h>
36d5f84e61SIain Sandoe #include <stdio.h>
37d5f84e61SIain Sandoe
38d5f84e61SIain Sandoe struct Base {
39d5f84e61SIain Sandoe int b;
40d5f84e61SIain Sandoe };
41d5f84e61SIain Sandoe struct Base2 {
42d5f84e61SIain Sandoe int b;
43d5f84e61SIain Sandoe };
44d5f84e61SIain Sandoe struct Derived1 : Base {
45d5f84e61SIain Sandoe int b;
46d5f84e61SIain Sandoe };
47d5f84e61SIain Sandoe struct Derived2 : Base {
48d5f84e61SIain Sandoe int b;
49d5f84e61SIain Sandoe };
50d5f84e61SIain Sandoe struct Derived3 : Base2 {
51d5f84e61SIain Sandoe int b;
52d5f84e61SIain Sandoe };
53d5f84e61SIain Sandoe struct Private : private Base {
54d5f84e61SIain Sandoe int b;
55d5f84e61SIain Sandoe };
56d5f84e61SIain Sandoe struct Protected : protected Base {
57d5f84e61SIain Sandoe int b;
58d5f84e61SIain Sandoe };
59d5f84e61SIain Sandoe struct Virtual1 : virtual Base {
60d5f84e61SIain Sandoe int b;
61d5f84e61SIain Sandoe };
62d5f84e61SIain Sandoe struct Virtual2 : virtual Base {
63d5f84e61SIain Sandoe int b;
64d5f84e61SIain Sandoe };
65d5f84e61SIain Sandoe
66d5f84e61SIain Sandoe struct Ambiguous1 : Derived1, Derived2 {
67d5f84e61SIain Sandoe int b;
68d5f84e61SIain Sandoe };
69d5f84e61SIain Sandoe struct Ambiguous2 : Derived1, Private {
70d5f84e61SIain Sandoe int b;
71d5f84e61SIain Sandoe };
72d5f84e61SIain Sandoe struct Ambiguous3 : Derived1, Protected {
73d5f84e61SIain Sandoe int b;
74d5f84e61SIain Sandoe };
75d5f84e61SIain Sandoe
76d5f84e61SIain Sandoe struct NoPublic1 : Private, Base2 {
77d5f84e61SIain Sandoe int b;
78d5f84e61SIain Sandoe };
79d5f84e61SIain Sandoe struct NoPublic2 : Protected, Base2 {
80d5f84e61SIain Sandoe int b;
81d5f84e61SIain Sandoe };
82d5f84e61SIain Sandoe
83d5f84e61SIain Sandoe struct Catchable1 : Derived3, Derived1 {
84d5f84e61SIain Sandoe int b;
85d5f84e61SIain Sandoe };
86d5f84e61SIain Sandoe struct Catchable2 : Virtual1, Virtual2 {
87d5f84e61SIain Sandoe int b;
88d5f84e61SIain Sandoe };
89d5f84e61SIain Sandoe struct Catchable3 : virtual Base, Virtual2 {
90d5f84e61SIain Sandoe int b;
91d5f84e61SIain Sandoe };
92d5f84e61SIain Sandoe
93d5f84e61SIain Sandoe // Check that, when we have a null pointer-to-object that we catch a nullptr.
94d5f84e61SIain Sandoe template <typename T // Handler type
95d5f84e61SIain Sandoe ,
96d5f84e61SIain Sandoe typename E // Thrown exception type
97d5f84e61SIain Sandoe >
assert_catches()98d5f84e61SIain Sandoe void assert_catches() {
99d5f84e61SIain Sandoe try {
100d5f84e61SIain Sandoe throw static_cast<E>(0);
101d5f84e61SIain Sandoe printf("%s\n", __PRETTY_FUNCTION__);
102d5f84e61SIain Sandoe assert(false && "Statements after throw must be unreachable");
103d5f84e61SIain Sandoe } catch (T t) {
104d5f84e61SIain Sandoe assert(t == nullptr);
105d5f84e61SIain Sandoe return;
106d5f84e61SIain Sandoe } catch (...) {
107d5f84e61SIain Sandoe printf("%s\n", __PRETTY_FUNCTION__);
108d5f84e61SIain Sandoe assert(false && "Should not have entered catch-all");
109d5f84e61SIain Sandoe }
110d5f84e61SIain Sandoe
111d5f84e61SIain Sandoe printf("%s\n", __PRETTY_FUNCTION__);
112d5f84e61SIain Sandoe assert(false && "The catch should have returned");
113d5f84e61SIain Sandoe }
114d5f84e61SIain Sandoe
115d5f84e61SIain Sandoe template <typename T // Handler type
116d5f84e61SIain Sandoe ,
117d5f84e61SIain Sandoe typename E // Thrown exception type
118d5f84e61SIain Sandoe >
assert_cannot_catch()119d5f84e61SIain Sandoe void assert_cannot_catch() {
120d5f84e61SIain Sandoe try {
121d5f84e61SIain Sandoe throw static_cast<E>(0);
122d5f84e61SIain Sandoe printf("%s\n", __PRETTY_FUNCTION__);
123d5f84e61SIain Sandoe assert(false && "Statements after throw must be unreachable");
124d5f84e61SIain Sandoe } catch (T t) {
125d5f84e61SIain Sandoe printf("%s\n", __PRETTY_FUNCTION__);
126d5f84e61SIain Sandoe assert(false && "Should not have entered the catch");
127d5f84e61SIain Sandoe } catch (...) {
128d5f84e61SIain Sandoe assert(true);
129d5f84e61SIain Sandoe return;
130d5f84e61SIain Sandoe }
131d5f84e61SIain Sandoe
132d5f84e61SIain Sandoe printf("%s\n", __PRETTY_FUNCTION__);
133d5f84e61SIain Sandoe assert(false && "The catch-all should have returned");
134d5f84e61SIain Sandoe }
135d5f84e61SIain Sandoe
136d5f84e61SIain Sandoe // Check that when we have a pointer-to-actual-object we, in fact, get the
137d5f84e61SIain Sandoe // adjusted pointer to the base class.
138d5f84e61SIain Sandoe template <typename T // Handler type
139d5f84e61SIain Sandoe ,
140d5f84e61SIain Sandoe typename O // Object type
141d5f84e61SIain Sandoe >
assert_catches_bp()142d5f84e61SIain Sandoe void assert_catches_bp() {
143d5f84e61SIain Sandoe O* o = new (O);
144d5f84e61SIain Sandoe try {
145d5f84e61SIain Sandoe throw o;
146d5f84e61SIain Sandoe printf("%s\n", __PRETTY_FUNCTION__);
147d5f84e61SIain Sandoe assert(false && "Statements after throw must be unreachable");
148d5f84e61SIain Sandoe } catch (T t) {
149d5f84e61SIain Sandoe assert(t == static_cast<T>(o));
150d5f84e61SIain Sandoe //__builtin_printf("o = %p t = %p\n", o, t);
151d5f84e61SIain Sandoe delete o;
152d5f84e61SIain Sandoe return;
153d5f84e61SIain Sandoe } catch (...) {
154d5f84e61SIain Sandoe printf("%s\n", __PRETTY_FUNCTION__);
155d5f84e61SIain Sandoe assert(false && "Should not have entered catch-all");
156d5f84e61SIain Sandoe }
157d5f84e61SIain Sandoe
158d5f84e61SIain Sandoe printf("%s\n", __PRETTY_FUNCTION__);
159d5f84e61SIain Sandoe assert(false && "The catch should have returned");
160d5f84e61SIain Sandoe }
161d5f84e61SIain Sandoe
f1()162d5f84e61SIain Sandoe void f1() {
163d5f84e61SIain Sandoe assert_catches<Base*, Catchable1*>();
164d5f84e61SIain Sandoe assert_catches<Base*, Catchable2*>();
165d5f84e61SIain Sandoe assert_catches<Base*, Catchable3*>();
166d5f84e61SIain Sandoe }
167d5f84e61SIain Sandoe
f2()168d5f84e61SIain Sandoe void f2() {
169d5f84e61SIain Sandoe assert_cannot_catch<Base*, Ambiguous1*>();
170d5f84e61SIain Sandoe assert_cannot_catch<Base*, Ambiguous2*>();
171d5f84e61SIain Sandoe assert_cannot_catch<Base*, Ambiguous3*>();
172d5f84e61SIain Sandoe assert_cannot_catch<Base*, NoPublic1*>();
173d5f84e61SIain Sandoe assert_cannot_catch<Base*, NoPublic2*>();
174d5f84e61SIain Sandoe }
175d5f84e61SIain Sandoe
f3()176d5f84e61SIain Sandoe void f3() {
177d5f84e61SIain Sandoe assert_catches_bp<Base*, Catchable1>();
178d5f84e61SIain Sandoe assert_catches_bp<Base*, Catchable2>();
179d5f84e61SIain Sandoe assert_catches_bp<Base*, Catchable3>();
180d5f84e61SIain Sandoe }
181d5f84e61SIain Sandoe
main(int,char **)182d5f84e61SIain Sandoe int main(int, char**) {
183d5f84e61SIain Sandoe f1();
184d5f84e61SIain Sandoe f2();
185d5f84e61SIain Sandoe f3();
186d5f84e61SIain Sandoe return 0;
187d5f84e61SIain Sandoe }
188