[PATCH] c++/58796 Make nullptr match exception handlers of pointer type
Jonathan Wakely
jwakely@redhat.com
Fri Jul 15 21:07:00 GMT 2016
On 15/07/16 12:47 +0100, Jonathan Wakely wrote:
>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
This store could race with accesses in other threads, if the same
exception object gets thrown in multiple threads and the value of the
pointer-to-data-member is read concurrently with the write:
#include <exception>
#include <thread>
#include <cassert>
std::exception_ptr p;
struct A { };
void t()
{
try {
std::rethrow_exception(p);
} catch (int A::* const& e) {
assert( e == nullptr );
}
}
int main()
{
try {
throw nullptr;
} catch (...) {
p = std::current_exception();
}
std::thread t1(t);
std::thread t2(t);
t1.join();
t2.join();
}
We could use __atomic_store to do the write, but the reads would still
be non-atomic. The attached patch makes __cxa_throw do that write on
the initial throw, so that a thrown nullptr_t always has the right
content to act as a null pointer-to-member. However that adds
overhead for every throw. A more efficient solution might be for the
front-end to do that write when it sees a nullptr_t being thrown.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: patch.txt
Type: text/x-patch
Size: 1068 bytes
Desc: not available
URL: <http://gcc.gnu.org/pipermail/gcc-patches/attachments/20160715/cfa06db4/attachment.bin>
More information about the Gcc-patches
mailing list