[LLD][COFF] Emit tail merge pdata for delay load thunks on ARM64EC (#116810)
[llvm-project.git] / libcxxabi / test / catch_null_pointer_to_object_pr64953.pass.cpp
blob1bd4277e76d809d18c018798e638ad3c265d2f6d
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 bullet 3.3:
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
25 //===----------------------------------------------------------------------===//
27 // UNSUPPORTED: no-exceptions
29 // This test requires the fix to https://github.com/llvm/llvm-project/issues/64953,
30 // which landed in d5f84e6 and is in the libc++abi built library.
31 // XFAIL: using-built-library-before-llvm-18
33 #include <exception>
34 #include <stdlib.h>
35 #include <assert.h>
36 #include <stdio.h>
38 struct Base {
39 int b;
41 struct Base2 {
42 int b;
44 struct Derived1 : Base {
45 int b;
47 struct Derived2 : Base {
48 int b;
50 struct Derived3 : Base2 {
51 int b;
53 struct Private : private Base {
54 int b;
56 struct Protected : protected Base {
57 int b;
59 struct Virtual1 : virtual Base {
60 int b;
62 struct Virtual2 : virtual Base {
63 int b;
66 struct Ambiguous1 : Derived1, Derived2 {
67 int b;
69 struct Ambiguous2 : Derived1, Private {
70 int b;
72 struct Ambiguous3 : Derived1, Protected {
73 int b;
76 struct NoPublic1 : Private, Base2 {
77 int b;
79 struct NoPublic2 : Protected, Base2 {
80 int b;
83 struct Catchable1 : Derived3, Derived1 {
84 int b;
86 struct Catchable2 : Virtual1, Virtual2 {
87 int b;
89 struct Catchable3 : virtual Base, Virtual2 {
90 int b;
93 // Check that, when we have a null pointer-to-object that we catch a nullptr.
94 template <typename T // Handler type
96 typename E // Thrown exception type
98 void assert_catches() {
99 try {
100 throw static_cast<E>(0);
101 printf("%s\n", __PRETTY_FUNCTION__);
102 assert(false && "Statements after throw must be unreachable");
103 } catch (T t) {
104 assert(t == nullptr);
105 return;
106 } catch (...) {
107 printf("%s\n", __PRETTY_FUNCTION__);
108 assert(false && "Should not have entered catch-all");
111 printf("%s\n", __PRETTY_FUNCTION__);
112 assert(false && "The catch should have returned");
115 template <typename T // Handler type
117 typename E // Thrown exception type
119 void assert_cannot_catch() {
120 try {
121 throw static_cast<E>(0);
122 printf("%s\n", __PRETTY_FUNCTION__);
123 assert(false && "Statements after throw must be unreachable");
124 } catch (T t) {
125 printf("%s\n", __PRETTY_FUNCTION__);
126 assert(false && "Should not have entered the catch");
127 } catch (...) {
128 assert(true);
129 return;
132 printf("%s\n", __PRETTY_FUNCTION__);
133 assert(false && "The catch-all should have returned");
136 // Check that when we have a pointer-to-actual-object we, in fact, get the
137 // adjusted pointer to the base class.
138 template <typename T // Handler type
140 typename O // Object type
142 void assert_catches_bp() {
143 O* o = new (O);
144 try {
145 throw o;
146 printf("%s\n", __PRETTY_FUNCTION__);
147 assert(false && "Statements after throw must be unreachable");
148 } catch (T t) {
149 assert(t == static_cast<T>(o));
150 //__builtin_printf("o = %p t = %p\n", o, t);
151 delete o;
152 return;
153 } catch (...) {
154 printf("%s\n", __PRETTY_FUNCTION__);
155 assert(false && "Should not have entered catch-all");
158 printf("%s\n", __PRETTY_FUNCTION__);
159 assert(false && "The catch should have returned");
162 void f1() {
163 assert_catches<Base*, Catchable1*>();
164 assert_catches<Base*, Catchable2*>();
165 assert_catches<Base*, Catchable3*>();
168 void f2() {
169 assert_cannot_catch<Base*, Ambiguous1*>();
170 assert_cannot_catch<Base*, Ambiguous2*>();
171 assert_cannot_catch<Base*, Ambiguous3*>();
172 assert_cannot_catch<Base*, NoPublic1*>();
173 assert_cannot_catch<Base*, NoPublic2*>();
176 void f3() {
177 assert_catches_bp<Base*, Catchable1>();
178 assert_catches_bp<Base*, Catchable2>();
179 assert_catches_bp<Base*, Catchable3>();
182 int main(int, char**) {
183 f1();
184 f2();
185 f3();
186 return 0;