diff mbox

c++/58796 Make nullptr match exception handlers of pointer type

Message ID 20160720133356.GB4264@redhat.com
State New
Headers show

Commit Message

Jonathan Wakely July 20, 2016, 1:33 p.m. UTC
On 19/07/16 10:32 +0100, Jonathan Wakely wrote:
>On 18/07/16 12:49 -0400, Jason Merrill wrote:
>>Perhaps the right answer is to drop support for catching nullptr as a
>>pointers to member from the language.
>
>Yes, I've been drafting a ballot comment along those lines.

On the CWG reflector Richard Smith suggested using static objects as
the result for pointer to member handlers. I had tried that
unsuccessfully, but must have done something wrong because it works
fine, and avoids any races.

Tested x86_64-linux. I'll commit this to trunk later today.
diff mbox

Patch

commit 6cc1a2bca8dddb8ff5994849fcd3ee22de8776ed
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Wed Jul 20 12:49:50 2016 +0100

    Use static pointer to member when catching nullptr
    
    libstdc++-v3:
    
    	* libsupc++/pbase_type_info.cc (__pbase_type_info::__do_catch): Use
    	static objects for catching nullptr as pointer to member types.
    
    gcc/testsuite:
    
    	* g++.dg/cpp0x/nullptr35.C: Change expected result for catching as
    	pointer to member function and also test catching by reference.

diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr35.C b/gcc/testsuite/g++.dg/cpp0x/nullptr35.C
index c84966f..d932114 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nullptr35.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nullptr35.C
@@ -39,7 +39,7 @@  int main()
           caught(4);
         throw;
       }
-    } catch (int (A::*pmf)()) {  // FIXME: currently unsupported
+    } catch (int (A::*pmf)()) {
       if (pmf == nullptr)
         caught(8);
       throw;
@@ -47,6 +47,35 @@  int main()
   } catch (nullptr_t) {
   }
 
-  if (result != 7) // should be 15
+  try {
+    try {
+      try {
+        try {
+          try {
+            throw nullptr;
+          } catch (void* const& p) {
+            if (p == nullptr)
+              caught(16);
+            throw;
+          }
+        } catch (void(* const& pf)()) {
+          if (pf == nullptr)
+            caught(32);
+          throw;
+        }
+      } catch (int A::* const& pm) {
+        if (pm == nullptr)
+          caught(64);
+        throw;
+      }
+    } catch (int (A::* const& pmf)()) {
+      if (pmf == nullptr)
+        caught(128);
+      throw;
+    }
+  } catch (nullptr_t) {
+  }
+
+  if (result != 255)
     abort ();
 }
diff --git a/libstdc++-v3/libsupc++/pbase_type_info.cc b/libstdc++-v3/libsupc++/pbase_type_info.cc
index a2993e4..ff6b756 100644
--- a/libstdc++-v3/libsupc++/pbase_type_info.cc
+++ b/libstdc++-v3/libsupc++/pbase_type_info.cc
@@ -50,14 +50,16 @@  __do_catch (const type_info *thr_type,
         {
           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;
+              using pmf_type = void (__pbase_type_info::*)();
+              static const pmf_type pmf = nullptr;
+              *thr_obj = const_cast<pmf_type*>(&pmf);
+              return true;
             }
           else
             {
-              *(ptrdiff_t*)*thr_obj = -1; // null pointer to data member
+              using pm_type = int __pbase_type_info::*;
+              static const pm_type pm = nullptr;
+              *thr_obj = const_cast<pm_type*>(&pm);
               return true;
             }
         }