1*c05d8e5dSAndroid Build Coastguard Worker //===--------------------- catch_pointer_nullptr.cpp ----------------------===//
2*c05d8e5dSAndroid Build Coastguard Worker //
3*c05d8e5dSAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*c05d8e5dSAndroid Build Coastguard Worker //
5*c05d8e5dSAndroid Build Coastguard Worker // This file is dual licensed under the MIT and the University of Illinois Open
6*c05d8e5dSAndroid Build Coastguard Worker // Source Licenses. See LICENSE.TXT for details.
7*c05d8e5dSAndroid Build Coastguard Worker //
8*c05d8e5dSAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*c05d8e5dSAndroid Build Coastguard Worker
10*c05d8e5dSAndroid Build Coastguard Worker // UNSUPPORTED: libcxxabi-no-exceptions
11*c05d8e5dSAndroid Build Coastguard Worker
12*c05d8e5dSAndroid Build Coastguard Worker #include <cassert>
13*c05d8e5dSAndroid Build Coastguard Worker #include <cstdlib>
14*c05d8e5dSAndroid Build Coastguard Worker #include <iostream>
15*c05d8e5dSAndroid Build Coastguard Worker
16*c05d8e5dSAndroid Build Coastguard Worker // Roll our own assertion macro to get better error messages out of the tests.
17*c05d8e5dSAndroid Build Coastguard Worker // In particular on systems that don't use __PRETTY_FUNCTION__ in assertions.
18*c05d8e5dSAndroid Build Coastguard Worker #define my_assert(pred, msg) do_assert(pred, msg, __LINE__, __PRETTY_FUNCTION__)
19*c05d8e5dSAndroid Build Coastguard Worker
do_assert(bool assert_passed,const char * msg,int line,const char * func)20*c05d8e5dSAndroid Build Coastguard Worker void do_assert(bool assert_passed, const char* msg, int line, const char* func) {
21*c05d8e5dSAndroid Build Coastguard Worker if (assert_passed) return;
22*c05d8e5dSAndroid Build Coastguard Worker std::cerr << __FILE__ << ":" << line << " " << func
23*c05d8e5dSAndroid Build Coastguard Worker << ": Assertion Failed `" << msg << "'\n\n";
24*c05d8e5dSAndroid Build Coastguard Worker std::abort();
25*c05d8e5dSAndroid Build Coastguard Worker }
26*c05d8e5dSAndroid Build Coastguard Worker
27*c05d8e5dSAndroid Build Coastguard Worker struct A {};
28*c05d8e5dSAndroid Build Coastguard Worker struct Base {};
29*c05d8e5dSAndroid Build Coastguard Worker struct Derived : public Base {};
30*c05d8e5dSAndroid Build Coastguard Worker
31*c05d8e5dSAndroid Build Coastguard Worker template <class To>
test_conversion(To)32*c05d8e5dSAndroid Build Coastguard Worker bool test_conversion(To) { return true; }
33*c05d8e5dSAndroid Build Coastguard Worker
34*c05d8e5dSAndroid Build Coastguard Worker template <class To>
test_conversion(...)35*c05d8e5dSAndroid Build Coastguard Worker bool test_conversion(...) { return false; }
36*c05d8e5dSAndroid Build Coastguard Worker
37*c05d8e5dSAndroid Build Coastguard Worker template <class Pointer>
38*c05d8e5dSAndroid Build Coastguard Worker struct CreatePointer {
operator ()CreatePointer39*c05d8e5dSAndroid Build Coastguard Worker Pointer operator()() const {
40*c05d8e5dSAndroid Build Coastguard Worker return (Pointer)0;
41*c05d8e5dSAndroid Build Coastguard Worker }
42*c05d8e5dSAndroid Build Coastguard Worker };
43*c05d8e5dSAndroid Build Coastguard Worker
44*c05d8e5dSAndroid Build Coastguard Worker template <class Tp>
45*c05d8e5dSAndroid Build Coastguard Worker struct CreatePointer<Tp*> {
operator ()CreatePointer46*c05d8e5dSAndroid Build Coastguard Worker Tp* operator()() const {
47*c05d8e5dSAndroid Build Coastguard Worker return (Tp*)42;
48*c05d8e5dSAndroid Build Coastguard Worker }
49*c05d8e5dSAndroid Build Coastguard Worker };
50*c05d8e5dSAndroid Build Coastguard Worker
51*c05d8e5dSAndroid Build Coastguard Worker template <class Throw, class Catch>
catch_pointer_test()52*c05d8e5dSAndroid Build Coastguard Worker void catch_pointer_test() {
53*c05d8e5dSAndroid Build Coastguard Worker Throw throw_ptr = CreatePointer<Throw>()();
54*c05d8e5dSAndroid Build Coastguard Worker // Use the compiler to determine if the exception of type Throw can be
55*c05d8e5dSAndroid Build Coastguard Worker // implicitly converted to type Catch.
56*c05d8e5dSAndroid Build Coastguard Worker const bool can_convert = test_conversion<Catch>(throw_ptr);
57*c05d8e5dSAndroid Build Coastguard Worker try {
58*c05d8e5dSAndroid Build Coastguard Worker throw throw_ptr;
59*c05d8e5dSAndroid Build Coastguard Worker assert(false);
60*c05d8e5dSAndroid Build Coastguard Worker } catch (Catch catch_ptr) {
61*c05d8e5dSAndroid Build Coastguard Worker Catch catch2 = CreatePointer<Catch>()();
62*c05d8e5dSAndroid Build Coastguard Worker my_assert(can_convert, "non-convertible type incorrectly caught");
63*c05d8e5dSAndroid Build Coastguard Worker my_assert(catch_ptr == catch2,
64*c05d8e5dSAndroid Build Coastguard Worker "Thrown pointer does not match caught ptr");
65*c05d8e5dSAndroid Build Coastguard Worker } catch (...) {
66*c05d8e5dSAndroid Build Coastguard Worker my_assert(!can_convert, "convertible type incorrectly not caught");
67*c05d8e5dSAndroid Build Coastguard Worker }
68*c05d8e5dSAndroid Build Coastguard Worker }
69*c05d8e5dSAndroid Build Coastguard Worker
70*c05d8e5dSAndroid Build Coastguard Worker // Generate CV qualified pointer typedefs.
71*c05d8e5dSAndroid Build Coastguard Worker template <class Tp, bool First = false>
72*c05d8e5dSAndroid Build Coastguard Worker struct TestTypes {
73*c05d8e5dSAndroid Build Coastguard Worker typedef Tp* Type;
74*c05d8e5dSAndroid Build Coastguard Worker typedef Tp const* CType;
75*c05d8e5dSAndroid Build Coastguard Worker typedef Tp volatile* VType;
76*c05d8e5dSAndroid Build Coastguard Worker typedef Tp const volatile* CVType;
77*c05d8e5dSAndroid Build Coastguard Worker };
78*c05d8e5dSAndroid Build Coastguard Worker
79*c05d8e5dSAndroid Build Coastguard Worker // Special case for cv-qualifying a pointer-to-member without adding an extra
80*c05d8e5dSAndroid Build Coastguard Worker // pointer to it.
81*c05d8e5dSAndroid Build Coastguard Worker template <class Member, class Class>
82*c05d8e5dSAndroid Build Coastguard Worker struct TestTypes<Member Class::*, true> {
83*c05d8e5dSAndroid Build Coastguard Worker typedef Member (Class::*Type);
84*c05d8e5dSAndroid Build Coastguard Worker typedef const Member (Class::*CType);
85*c05d8e5dSAndroid Build Coastguard Worker typedef volatile Member (Class::*VType);
86*c05d8e5dSAndroid Build Coastguard Worker typedef const volatile Member (Class::*CVType);
87*c05d8e5dSAndroid Build Coastguard Worker };
88*c05d8e5dSAndroid Build Coastguard Worker
89*c05d8e5dSAndroid Build Coastguard Worker template <class Throw, class Catch, int level, bool first = false>
90*c05d8e5dSAndroid Build Coastguard Worker struct generate_tests_imp {
91*c05d8e5dSAndroid Build Coastguard Worker typedef TestTypes<Throw, first> ThrowTypes;
92*c05d8e5dSAndroid Build Coastguard Worker typedef TestTypes<Catch, first> CatchTypes;
operator ()generate_tests_imp93*c05d8e5dSAndroid Build Coastguard Worker void operator()() {
94*c05d8e5dSAndroid Build Coastguard Worker typedef typename ThrowTypes::Type Type;
95*c05d8e5dSAndroid Build Coastguard Worker typedef typename ThrowTypes::CType CType;
96*c05d8e5dSAndroid Build Coastguard Worker typedef typename ThrowTypes::VType VType;
97*c05d8e5dSAndroid Build Coastguard Worker typedef typename ThrowTypes::CVType CVType;
98*c05d8e5dSAndroid Build Coastguard Worker
99*c05d8e5dSAndroid Build Coastguard Worker run_catch_tests<Type>();
100*c05d8e5dSAndroid Build Coastguard Worker run_catch_tests<CType>();
101*c05d8e5dSAndroid Build Coastguard Worker run_catch_tests<VType>();
102*c05d8e5dSAndroid Build Coastguard Worker run_catch_tests<CVType>();
103*c05d8e5dSAndroid Build Coastguard Worker }
104*c05d8e5dSAndroid Build Coastguard Worker
105*c05d8e5dSAndroid Build Coastguard Worker template <class ThrowTp>
run_catch_testsgenerate_tests_imp106*c05d8e5dSAndroid Build Coastguard Worker void run_catch_tests() {
107*c05d8e5dSAndroid Build Coastguard Worker typedef typename CatchTypes::Type Type;
108*c05d8e5dSAndroid Build Coastguard Worker typedef typename CatchTypes::CType CType;
109*c05d8e5dSAndroid Build Coastguard Worker typedef typename CatchTypes::VType VType;
110*c05d8e5dSAndroid Build Coastguard Worker typedef typename CatchTypes::CVType CVType;
111*c05d8e5dSAndroid Build Coastguard Worker
112*c05d8e5dSAndroid Build Coastguard Worker catch_pointer_test<ThrowTp, Type>();
113*c05d8e5dSAndroid Build Coastguard Worker catch_pointer_test<ThrowTp, CType>();
114*c05d8e5dSAndroid Build Coastguard Worker catch_pointer_test<ThrowTp, VType>();
115*c05d8e5dSAndroid Build Coastguard Worker catch_pointer_test<ThrowTp, CVType>();
116*c05d8e5dSAndroid Build Coastguard Worker
117*c05d8e5dSAndroid Build Coastguard Worker generate_tests_imp<ThrowTp, Type, level-1>()();
118*c05d8e5dSAndroid Build Coastguard Worker generate_tests_imp<ThrowTp, CType, level-1>()();
119*c05d8e5dSAndroid Build Coastguard Worker generate_tests_imp<ThrowTp, VType, level-1>()();
120*c05d8e5dSAndroid Build Coastguard Worker generate_tests_imp<ThrowTp, CVType, level-1>()();
121*c05d8e5dSAndroid Build Coastguard Worker }
122*c05d8e5dSAndroid Build Coastguard Worker };
123*c05d8e5dSAndroid Build Coastguard Worker
124*c05d8e5dSAndroid Build Coastguard Worker template <class Throw, class Catch, bool first>
125*c05d8e5dSAndroid Build Coastguard Worker struct generate_tests_imp<Throw, Catch, 0, first> {
operator ()generate_tests_imp126*c05d8e5dSAndroid Build Coastguard Worker void operator()() {
127*c05d8e5dSAndroid Build Coastguard Worker catch_pointer_test<Throw, Catch>();
128*c05d8e5dSAndroid Build Coastguard Worker }
129*c05d8e5dSAndroid Build Coastguard Worker };
130*c05d8e5dSAndroid Build Coastguard Worker
131*c05d8e5dSAndroid Build Coastguard Worker template <class Throw, class Catch, int level>
132*c05d8e5dSAndroid Build Coastguard Worker struct generate_tests : generate_tests_imp<Throw, Catch, level, true> {};
133*c05d8e5dSAndroid Build Coastguard Worker
main()134*c05d8e5dSAndroid Build Coastguard Worker int main()
135*c05d8e5dSAndroid Build Coastguard Worker {
136*c05d8e5dSAndroid Build Coastguard Worker generate_tests<int, int, 3>()();
137*c05d8e5dSAndroid Build Coastguard Worker generate_tests<Base, Derived, 2>()();
138*c05d8e5dSAndroid Build Coastguard Worker generate_tests<Derived, Base, 2>()();
139*c05d8e5dSAndroid Build Coastguard Worker generate_tests<int, void, 2>()();
140*c05d8e5dSAndroid Build Coastguard Worker generate_tests<void, int, 2>()();
141*c05d8e5dSAndroid Build Coastguard Worker
142*c05d8e5dSAndroid Build Coastguard Worker generate_tests<int A::*, int A::*, 3>()();
143*c05d8e5dSAndroid Build Coastguard Worker generate_tests<int A::*, void, 2>()();
144*c05d8e5dSAndroid Build Coastguard Worker generate_tests<void, int A::*, 2>()();
145*c05d8e5dSAndroid Build Coastguard Worker }
146