Hi mclow.lists, jroelofs,
Function pointers and member function pointers cannot be converted to void*.
libc++abi incorrectly allows this conversion for function pointers.
I also flushed out some of the pointer to member function conversion tests.
http://reviews.llvm.org/D8811
Files:
src/private_typeinfo.cpp
test/catch_function_01.pass.cpp
test/catch_member_function_pointer_01.pass.cpp
EMAIL PREFERENCES
http://reviews.llvm.org/settings/panel/emailpreferences/
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<const __function_type_info*>(thrown_pointer_type->__pointee);
+ return (thrown_function == nullptr);
+ }
// Handle pointer to pointer
const __pointer_type_info* nested_pointer_type =
dynamic_cast<const __pointer_type_info*>(__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 <cassert>
+template <class Tp>
+bool can_convert(Tp) { return true; }
+
+template <class>
+bool can_convert(...) { return false; }
+
void f() {}
int main()
{
typedef void Function();
+ assert(!can_convert<Function&>(&f));
+ assert(!can_convert<void*>(&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 <class Tp>
+bool can_convert(Tp) { return true; }
+
+template <class>
+bool can_convert(...) { return false; }
+
void test1()
{
try
@@ -50,8 +63,107 @@
}
}
+
+void test_derived()
+{
+ assert(can_convert<dmf1>((mf1)0));
+ assert(!can_convert<dmf2>((mf1)0));
+ try
+ {
+ throw (mf1)0;
+ assert(false);
+ }
+ catch (dmf2)
+ {
+ assert(false);
+ }
+ catch (dmf1)
+ {
+ }
+ catch (...)
+ {
+ assert(false);
+ }
+
+ assert(!can_convert<dmf1>((mf2)0));
+ assert(can_convert<dmf2>((mf2)0));
+ try
+ {
+ throw (mf2)0;
+ assert(false);
+ }
+ catch (dmf1)
+ {
+ assert(false);
+ }
+ catch (dmf2)
+ {
+ }
+ catch (...)
+ {
+ assert(false);
+ }
+
+ assert(!can_convert<mf1>((dmf1)0));
+ assert(!can_convert<mf2>((dmf1)0));
+ try
+ {
+ throw (dmf1)0;
+ assert(false);
+ }
+ catch (mf2)
+ {
+ assert(false);
+ }
+ catch (mf1)
+ {
+ assert(false);
+ }
+ catch (...)
+ {
+ }
+
+ assert(!can_convert<mf1>((dmf2)0));
+ assert(!can_convert<mf2>((dmf2)0));
+ try
+ {
+ throw (dmf2)0;
+ assert(false);
+ }
+ catch (mf2)
+ {
+ assert(false);
+ }
+ catch (mf1)
+ {
+ assert(false);
+ }
+ catch (...)
+ {
+ }
+}
+
+void test_void()
+{
+ assert(!can_convert<void*>(&A::foo));
+ try
+ {
+ throw &A::foo;
+ assert(false);
+ }
+ catch (void*)
+ {
+ assert(false);
+ }
+ catch(...)
+ {
+ }
+}
+
int main()
{
test1();
test2();
+ test_derived();
+ test_void();
}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits