Index: src/private_typeinfo.cpp =================================================================== --- src/private_typeinfo.cpp +++ src/private_typeinfo.cpp @@ -387,9 +387,13 @@ if (is_equal(__pointee, thrown_pointer_type->__pointee, false)) return true; // bullet 3A - if (is_equal(__pointee, &typeid(void), false)) - return true; - + if (is_equal(__pointee, &typeid(void), false)) { + // pointers to functions cannot be converted to void*. + // pointers to member functions are not handled here. + const __function_type_info* thrown_function = + dynamic_cast(thrown_pointer_type->__pointee); + return (thrown_function == nullptr); + } // Handle pointer to pointer const __pointer_type_info* nested_pointer_type = dynamic_cast(__pointee); Index: test/catch_function_01.pass.cpp =================================================================== --- test/catch_function_01.pass.cpp +++ test/catch_function_01.pass.cpp @@ -11,11 +11,19 @@ #include +template +bool can_convert(Tp) { return true; } + +template +bool can_convert(...) { return false; } + void f() {} int main() { typedef void Function(); + assert(!can_convert(&f)); + assert(!can_convert(&f)); try { throw f; // converts to void (*)() @@ -25,7 +33,15 @@ { assert(false); } + catch (void*) // can't catch as void* + { + assert(false); + } + catch(Function*) + { + } catch (...) { + assert(false); } } Index: test/catch_member_function_pointer_01.pass.cpp =================================================================== --- test/catch_member_function_pointer_01.pass.cpp +++ test/catch_member_function_pointer_01.pass.cpp @@ -18,6 +18,19 @@ typedef void (A::*mf1)(); typedef void (A::*mf2)() const; +struct B : public A +{ +}; + +typedef void (B::*dmf1)(); +typedef void (B::*dmf2)() const; + +template +bool can_convert(Tp) { return true; } + +template +bool can_convert(...) { return false; } + void test1() { try @@ -50,8 +63,107 @@ } } + +void test_derived() +{ + assert(can_convert((mf1)0)); + assert(!can_convert((mf1)0)); + try + { + throw (mf1)0; + assert(false); + } + catch (dmf2) + { + assert(false); + } + catch (dmf1) + { + } + catch (...) + { + assert(false); + } + + assert(!can_convert((mf2)0)); + assert(can_convert((mf2)0)); + try + { + throw (mf2)0; + assert(false); + } + catch (dmf1) + { + assert(false); + } + catch (dmf2) + { + } + catch (...) + { + assert(false); + } + + assert(!can_convert((dmf1)0)); + assert(!can_convert((dmf1)0)); + try + { + throw (dmf1)0; + assert(false); + } + catch (mf2) + { + assert(false); + } + catch (mf1) + { + assert(false); + } + catch (...) + { + } + + assert(!can_convert((dmf2)0)); + assert(!can_convert((dmf2)0)); + try + { + throw (dmf2)0; + assert(false); + } + catch (mf2) + { + assert(false); + } + catch (mf1) + { + assert(false); + } + catch (...) + { + } +} + +void test_void() +{ + assert(!can_convert(&A::foo)); + try + { + throw &A::foo; + assert(false); + } + catch (void*) + { + assert(false); + } + catch(...) + { + } +} + int main() { test1(); test2(); + test_derived(); + test_void(); }