//===--------------------- catch_pointer_nullptr.cpp ----------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include #include #include // 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::cerr << __FILE__ << ":" << line << " " << func << ": Assertion Failed `" << msg << "'\n\n"; std::abort(); } struct A {}; struct Base {}; struct Derived : public Base {}; template bool test_conversion(To) { return true; } template bool test_conversion(...) { return false; } template struct CreatePointer { Pointer operator()() const { return (Pointer)0; } }; template struct CreatePointer { Tp* operator()() const { return (Tp*)42; } }; template void catch_pointer_test() { Throw throw_ptr = CreatePointer()(); // Use the compiler to determine if the exception of type Throw can be // implicitly converted to type Catch. const bool can_convert = test_conversion(throw_ptr); try { throw throw_ptr; assert(false); } catch (Catch catch_ptr) { Catch catch2 = CreatePointer()(); 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 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 struct TestTypes { typedef Member (Class::*Type); typedef const Member (Class::*CType); typedef volatile Member (Class::*VType); typedef const volatile Member (Class::*CVType); }; template struct generate_tests_imp { typedef TestTypes ThrowTypes; typedef TestTypes 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(); run_catch_tests(); run_catch_tests(); run_catch_tests(); } template 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(); catch_pointer_test(); catch_pointer_test(); catch_pointer_test(); generate_tests_imp()(); generate_tests_imp()(); generate_tests_imp()(); generate_tests_imp()(); } }; template struct generate_tests_imp { void operator()() { catch_pointer_test(); } }; template struct generate_tests : generate_tests_imp {}; int main() { generate_tests()(); generate_tests()(); generate_tests()(); generate_tests()(); generate_tests()(); generate_tests()(); generate_tests()(); generate_tests()(); }