From 479d0ed5900b8e87634cd92383c11a5571cc43d9 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Fri, 15 Jul 2016 19:51:51 +0100 Subject: [PATCH] c++/58796 Make nullptr match exception handlers of pointer type libstdc++-v3: PR c++/58796 * libsupc++/pbase_type_info.cc (__pbase_type_info::__do_catch): Make nullptr match handlers of pointer type. gcc/testsuite: PR c++/58796 * g++.dg/cpp0x/nullptr21.C: Remove void* handlers. * g++.dg/cpp0x/nullptr35.C: New test. From-SVN: r238396 --- gcc/testsuite/ChangeLog | 6 +++ gcc/testsuite/g++.dg/cpp0x/nullptr21.C | 4 -- gcc/testsuite/g++.dg/cpp0x/nullptr35.C | 52 +++++++++++++++++++++++ libstdc++-v3/ChangeLog | 6 +++ libstdc++-v3/libsupc++/pbase_type_info.cc | 25 +++++++++++ 5 files changed, 89 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/nullptr35.C diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 8a03901bc2a..305f96a4ab6 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2016-07-15 Jonathan Wakely + + PR c++/58796 + * g++.dg/cpp0x/nullptr21.C: Remove void* handlers. + * g++.dg/cpp0x/nullptr35.C: New test. + 2016-07-15 Bin Cheng * gcc.dg/tree-ssa/scev-8.c: Update test string. diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr21.C b/gcc/testsuite/g++.dg/cpp0x/nullptr21.C index 89884b90f72..c6f560e296b 100644 --- a/gcc/testsuite/g++.dg/cpp0x/nullptr21.C +++ b/gcc/testsuite/g++.dg/cpp0x/nullptr21.C @@ -18,8 +18,6 @@ int main() { try { throw nullptr; - } catch (void*) { - foo (0, 1); } catch (bool) { foo (0, 2); } catch (int) { @@ -35,8 +33,6 @@ int main() nullptr_t mynull = 0; try { throw mynull; - } catch (void*) { - foo (1, 1); } catch (bool) { foo (1, 2); } catch (int) { diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr35.C b/gcc/testsuite/g++.dg/cpp0x/nullptr35.C new file mode 100644 index 00000000000..2f93ce15731 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/nullptr35.C @@ -0,0 +1,52 @@ +// { dg-do run { target c++11 } } + +// Test catching as pointer and pointer to member types, [except.handle] p3. + +extern "C" void abort (void); + +typedef decltype(nullptr) nullptr_t; + +int result = 0; + +void __attribute__((noinline)) +caught(int bit) +{ + result &= bit; +} + +struct A { }; + +int main() +{ + try { + try { + try { + try { + try { + throw nullptr; + } catch (void* p) { + if (p == nullptr) + caught(1); + throw; + } + } catch (void(*pf)()) { + if (pf == nullptr) + caught(2); + throw; + } + } catch (int A::*pm) { + if (pm == nullptr) + caught(4); + throw; + } + } catch (int (A::*pmf)()) { // FIXME: currently unsupported + if (pmf == nullptr) + caught(8); + throw; + } + } catch (nullptr_t) { + } + + if (result != 7) // should be 15 + abort (); +} diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 25b8191e2a8..3e4a0f5b850 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,9 @@ +2016-07-15 Jonathan Wakely + + PR c++/58796 + * libsupc++/pbase_type_info.cc (__pbase_type_info::__do_catch): Make + nullptr match handlers of pointer type. + 2016-07-15 Edward Smith-Rowland <3dw4rd@verizon.net> Implement C++17 P0025 clamp. diff --git a/libstdc++-v3/libsupc++/pbase_type_info.cc b/libstdc++-v3/libsupc++/pbase_type_info.cc index d47fb23a4ed..a2993e431fe 100644 --- a/libstdc++-v3/libsupc++/pbase_type_info.cc +++ b/libstdc++-v3/libsupc++/pbase_type_info.cc @@ -38,6 +38,31 @@ __do_catch (const type_info *thr_type, return true; // same type #if __cpp_rtti + if (*thr_type == typeid (nullptr)) + { + // A catch handler for any pointer type matches nullptr_t. + if (typeid (*this) == typeid(__pointer_type_info)) + { + *thr_obj = nullptr; + return true; + } + else if (typeid (*this) == typeid(__pointer_to_member_type_info)) + { + if (__pointee->__is_function_p ()) + { + // A pointer-to-member-function is two words but the + // nullptr_t exception object at *(nullptr_t*)*thr_obj is only + // one word, so we can't safely return it as a PMF. FIXME. + return false; + } + else + { + *(ptrdiff_t*)*thr_obj = -1; // null pointer to data member + return true; + } + } + } + if (typeid (*this) != typeid (*thr_type)) return false; // not both same kind of pointers #endif -- 2.30.2