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:
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// 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
32
33#include <exception>
34#include <stdlib.h>
35#include <assert.h>
36#include <stdio.h>
37
38struct Base {
39 int b;
40};
41struct Base2 {
42 int b;
43};
44struct Derived1 : Base {
45 int b;
46};
47struct Derived2 : Base {
48 int b;
49};
50struct Derived3 : Base2 {
51 int b;
52};
53struct Private : private Base {
54 int b;
55};
56struct Protected : protected Base {
57 int b;
58};
59struct Virtual1 : virtual Base {
60 int b;
61};
62struct Virtual2 : virtual Base {
63 int b;
64};
65
66struct Ambiguous1 : Derived1, Derived2 {
67 int b;
68};
69struct Ambiguous2 : Derived1, Private {
70 int b;
71};
72struct Ambiguous3 : Derived1, Protected {
73 int b;
74};
75
76struct NoPublic1 : Private, Base2 {
77 int b;
78};
79struct NoPublic2 : Protected, Base2 {
80 int b;
81};
82
83struct Catchable1 : Derived3, Derived1 {
84 int b;
85};
86struct Catchable2 : Virtual1, Virtual2 {
87 int b;
88};
89struct Catchable3 : virtual Base, Virtual2 {
90 int b;
91};
92
93// Check that, when we have a null pointer-to-object that we catch a nullptr.
94template <typename T // Handler type
95 ,
96 typename E // Thrown exception type
97 >
98void 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");
109 }
110
111 printf("%s\n", __PRETTY_FUNCTION__);
112 assert(false && "The catch should have returned");
113}
114
115template <typename T // Handler type
116 ,
117 typename E // Thrown exception type
118 >
119void 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;
130 }
131
132 printf("%s\n", __PRETTY_FUNCTION__);
133 assert(false && "The catch-all should have returned");
134}
135
136// Check that when we have a pointer-to-actual-object we, in fact, get the
137// adjusted pointer to the base class.
138template <typename T // Handler type
139 ,
140 typename O // Object type
141 >
142void 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");
156 }
157
158 printf("%s\n", __PRETTY_FUNCTION__);
159 assert(false && "The catch should have returned");
160}
161
162void f1() {
163 assert_catches<Base*, Catchable1*>();
164 assert_catches<Base*, Catchable2*>();
165 assert_catches<Base*, Catchable3*>();
166}
167
168void 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*>();
174}
175
176void f3() {
177 assert_catches_bp<Base*, Catchable1>();
178 assert_catches_bp<Base*, Catchable2>();
179 assert_catches_bp<Base*, Catchable3>();
180}
181
182int main(int, char**) {
183 f1();
184 f2();
185 f3();
186 return 0;
187}
188

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

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