c++/58796 Make nullptr match exception handlers of pointer type
authorJonathan Wakely <jwakely@redhat.com>
Fri, 15 Jul 2016 18:51:51 +0000 (19:51 +0100)
committerJonathan Wakely <redi@gcc.gnu.org>
Fri, 15 Jul 2016 18:51:51 +0000 (19:51 +0100)
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
gcc/testsuite/g++.dg/cpp0x/nullptr21.C
gcc/testsuite/g++.dg/cpp0x/nullptr35.C [new file with mode: 0644]
libstdc++-v3/ChangeLog
libstdc++-v3/libsupc++/pbase_type_info.cc

index 8a03901bc2aa60414cd4fdc184fd5da33bc65556..305f96a4ab6ad64ad3e284df7d512a6145866c98 100644 (file)
@@ -1,3 +1,9 @@
+2016-07-15  Jonathan Wakely  <jwakely@redhat.com>
+
+       PR c++/58796
+       * g++.dg/cpp0x/nullptr21.C: Remove void* handlers.
+       * g++.dg/cpp0x/nullptr35.C: New test.
+
 2016-07-15  Bin Cheng  <bin.cheng@arm.com>
 
        * gcc.dg/tree-ssa/scev-8.c: Update test string.
index 89884b90f72469696c8911ad1f95333af6f89004..c6f560e296b6943a14975ade5a1dabcdf63d263c 100644 (file)
@@ -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 (file)
index 0000000..2f93ce1
--- /dev/null
@@ -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 ();
+}
index 25b8191e2a8ff0f03e436ce698d2203292b85996..3e4a0f5b8502b5a32d4a15d83c25699f966af964 100644 (file)
@@ -1,3 +1,9 @@
+2016-07-15  Jonathan Wakely  <jwakely@redhat.com>
+
+       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.
index d47fb23a4edf8e1c8f48c6bf232ebeb587060d26..a2993e431fe7826526940fb96de9266066514bee 100644 (file)
@@ -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 <ptr,adj> 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