This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


This allows exception handlers of pointer and pointer to data members
to match exceptions of type std::nullptr_t.

Pointers to member functions don't work yet, because a nullptr_t
exception object is only a single word, and we need two words for a
pointer to member function, and we don't have anywhere to put those
two words in the exception object. I'm going to raise this with the
C++ ABI group to coordinate with other implementations.

Tested x86_64-linux, I plan to commit this to trunk soon.


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.



commit 2e6bb9fbc1d47915bdfe487efd7e870600b4b442
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Thu Jul 14 14:33:24 2016 +0100

    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.

diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr21.C b/gcc/testsuite/g++.dg/cpp0x/nullptr21.C
index 89884b9..c6f560e 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 0000000..2f93ce1
--- /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/libsupc++/pbase_type_info.cc b/libstdc++-v3/libsupc++/pbase_type_info.cc
index d47fb23..a2993e4 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 <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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]