1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
|
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: no-exceptions
// 1b00fc5d8133 made it in the dylib in macOS 10.11
// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10}}
// XFAIL: *
#include <cassert>
#include <cstdio>
#include <cstdlib>
// Roll our own assertion macro to get better error messages out of the tests.
// In particular on systems that don't use __PRETTY_FUNCTION__ in assertions.
#define my_assert(pred, msg) do_assert(pred, msg, __LINE__, __PRETTY_FUNCTION__)
void do_assert(bool assert_passed, const char* msg, int line, const char* func) {
if (assert_passed)
return;
std::printf("%s:%d %s: Assertion Failed '%s'\n\n", __FILE__, line, func, msg);
std::abort();
}
struct A {};
struct Base {};
struct Derived : public Base {};
template <class To>
bool test_conversion(To) { return true; }
template <class To>
bool test_conversion(...) { return false; }
template <class Pointer>
struct CreatePointer {
Pointer operator()() const {
return (Pointer)0;
}
};
template <class Tp>
struct CreatePointer<Tp*> {
Tp* operator()() const {
return (Tp*)42;
}
};
template <class Throw, class Catch>
void catch_pointer_test() {
Throw throw_ptr = CreatePointer<Throw>()();
// Use the compiler to determine if the exception of type Throw can be
// implicitly converted to type Catch.
const bool can_convert = test_conversion<Catch>(throw_ptr);
try {
throw throw_ptr;
assert(false);
} catch (Catch catch_ptr) {
Catch catch2 = CreatePointer<Catch>()();
my_assert(can_convert, "non-convertible type incorrectly caught");
my_assert(catch_ptr == catch2,
"Thrown pointer does not match caught ptr");
} catch (...) {
my_assert(!can_convert, "convertible type incorrectly not caught");
}
}
// Generate CV qualified pointer typedefs.
template <class Tp, bool First = false>
struct TestTypes {
typedef Tp* Type;
typedef Tp const* CType;
typedef Tp volatile* VType;
typedef Tp const volatile* CVType;
};
// Special case for cv-qualifying a pointer-to-member without adding an extra
// pointer to it.
template <class Member, class Class>
struct TestTypes<Member Class::*, true> {
typedef Member (Class::*Type);
typedef const Member (Class::*CType);
typedef volatile Member (Class::*VType);
typedef const volatile Member (Class::*CVType);
};
template <class Throw, class Catch, int level, bool first = false>
struct generate_tests_imp {
typedef TestTypes<Throw, first> ThrowTypes;
typedef TestTypes<Catch, first> CatchTypes;
void operator()() {
typedef typename ThrowTypes::Type Type;
typedef typename ThrowTypes::CType CType;
typedef typename ThrowTypes::VType VType;
typedef typename ThrowTypes::CVType CVType;
run_catch_tests<Type>();
run_catch_tests<CType>();
run_catch_tests<VType>();
run_catch_tests<CVType>();
}
template <class ThrowTp>
void run_catch_tests() {
typedef typename CatchTypes::Type Type;
typedef typename CatchTypes::CType CType;
typedef typename CatchTypes::VType VType;
typedef typename CatchTypes::CVType CVType;
catch_pointer_test<ThrowTp, Type>();
catch_pointer_test<ThrowTp, CType>();
catch_pointer_test<ThrowTp, VType>();
catch_pointer_test<ThrowTp, CVType>();
generate_tests_imp<ThrowTp, Type, level-1>()();
generate_tests_imp<ThrowTp, CType, level-1>()();
generate_tests_imp<ThrowTp, VType, level-1>()();
generate_tests_imp<ThrowTp, CVType, level-1>()();
}
};
template <class Throw, class Catch, bool first>
struct generate_tests_imp<Throw, Catch, 0, first> {
void operator()() {
catch_pointer_test<Throw, Catch>();
}
};
template <class Throw, class Catch, int level>
struct generate_tests : generate_tests_imp<Throw, Catch, level, true> {};
int main(int, char**)
{
generate_tests<int, int, 3>()();
generate_tests<Base, Derived, 2>()();
generate_tests<Derived, Base, 2>()();
generate_tests<int, void, 2>()();
generate_tests<void, int, 2>()();
generate_tests<int A::*, int A::*, 3>()();
generate_tests<int A::*, void, 2>()();
generate_tests<void, int A::*, 2>()();
return 0;
}
|