From 0470fad0d6c2b993e6f9906dc2d17303944dcc14 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Tue, 11 Oct 2016 11:33:36 +0100 Subject: Simplify std::rethrow_if_nested definition * doc/xml/manual/intro.xml: Document LWG 2484 status. * libsupc++/nested_exception.h (_Throw_with_nested_impl) (_Throw_with_nested_helper): Remove. (__throw_with_nested_impl): New overloaded functions to implement throw_with_nested logic. (throw_with_nested): Call __throw_with_nested_impl. (_Rethrow_if_nested_impl): Remove (__rethrow_if_nested_impl): New overloaded functions to implement rethrow_if_nested logic. (rethrow_if_nested): Call __rethrow_if_nested_impl. * testsuite/18_support/nested_exception/rethrow_if_nested.cc: Test problem cases from LWG 2484. From-SVN: r240983 --- libstdc++-v3/ChangeLog | 13 ++++ libstdc++-v3/doc/xml/manual/intro.xml | 8 ++ libstdc++-v3/libsupc++/nested_exception.h | 88 ++++++++++------------ .../nested_exception/rethrow_if_nested.cc | 19 +++++ 4 files changed, 79 insertions(+), 49 deletions(-) diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 14cb404..eb68cbf 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,18 @@ 2016-10-11 Jonathan Wakely + * doc/xml/manual/intro.xml: Document LWG 2484 status. + * libsupc++/nested_exception.h (_Throw_with_nested_impl) + (_Throw_with_nested_helper): Remove. + (__throw_with_nested_impl): New overloaded functions to implement + throw_with_nested logic. + (throw_with_nested): Call __throw_with_nested_impl. + (_Rethrow_if_nested_impl): Remove + (__rethrow_if_nested_impl): New overloaded functions to implement + rethrow_if_nested logic. + (rethrow_if_nested): Call __rethrow_if_nested_impl. + * testsuite/18_support/nested_exception/rethrow_if_nested.cc: Test + problem cases from LWG 2484. + * python/libstdcxx/v6/printers.py (build_libstdcxx_dictionary): Register printer for std::__cxx11::list. * python/libstdcxx/v6/xmethods.py (ListMethodsMatcher.match): Match diff --git a/libstdc++-v3/doc/xml/manual/intro.xml b/libstdc++-v3/doc/xml/manual/intro.xml index 265ef67..22b792a 100644 --- a/libstdc++-v3/doc/xml/manual/intro.xml +++ b/libstdc++-v3/doc/xml/manual/intro.xml @@ -1078,6 +1078,14 @@ requirements of the license of GCC. Divide by the object type. + 2484: + rethrow_if_nested() is doubly unimplementable + + + Avoid using dynamic_cast when it would be + ill-formed. + + 2583: There is no way to supply an allocator for basic_string(str, pos) diff --git a/libstdc++-v3/libsupc++/nested_exception.h b/libstdc++-v3/libsupc++/nested_exception.h index 377b803..0c00d74 100644 --- a/libstdc++-v3/libsupc++/nested_exception.h +++ b/libstdc++-v3/libsupc++/nested_exception.h @@ -92,41 +92,21 @@ namespace std { } }; - template - struct _Throw_with_nested_impl - { - template - static void _S_throw(_Up&& __t) - { throw _Nested_exception<_Tp>{static_cast<_Up&&>(__t)}; } - }; - + // [except.nested]/8 + // Throw an exception of unspecified type that is publicly derived from + // both remove_reference_t<_Tp> and nested_exception. template - struct _Throw_with_nested_impl<_Tp, false> + inline void + __throw_with_nested_impl(_Tp&& __t, true_type) { - template - static void _S_throw(_Up&& __t) - { throw static_cast<_Up&&>(__t); } - }; - - template - struct _Throw_with_nested_helper : _Throw_with_nested_impl<_Tp> - { }; - - template - struct _Throw_with_nested_helper<_Tp, false> - : _Throw_with_nested_impl<_Tp, false> - { }; - - template - struct _Throw_with_nested_helper<_Tp&, false> - : _Throw_with_nested_helper<_Tp> - { }; + using _Up = typename remove_reference<_Tp>::type; + throw _Nested_exception<_Up>{std::forward<_Tp>(__t)}; + } template - struct _Throw_with_nested_helper<_Tp&&, false> - : _Throw_with_nested_helper<_Tp> - { }; + inline void + __throw_with_nested_impl(_Tp&& __t, false_type) + { throw std::forward<_Tp>(__t); } /// If @p __t is derived from nested_exception, throws @p __t. /// Else, throws an implementation-defined object derived from both. @@ -135,33 +115,43 @@ namespace std inline void throw_with_nested(_Tp&& __t) { - _Throw_with_nested_helper<_Tp>::_S_throw(static_cast<_Tp&&>(__t)); + using _Up = typename remove_reference<_Tp>::type; + using _CopyConstructible + = __and_, is_move_constructible<_Up>>; + static_assert(_CopyConstructible::value, + "throw_with_nested argument must be CopyConstructible"); + using __nest = __and_, __bool_constant, + __not_>>; + return std::__throw_with_nested_impl(std::forward<_Tp>(__t), __nest{}); } - template - struct _Rethrow_if_nested_impl - { - static void _S_rethrow(const _Tp& __t) - { - if (auto __tp = - dynamic_cast(std::__addressof(__t))) - __tp->rethrow_nested(); - } - }; - + // Determine if dynamic_cast would be well-formed. template - struct _Rethrow_if_nested_impl<_Tp, false> + using __rethrow_if_nested_cond = typename enable_if< + __and_, + __or_<__not_>, + is_convertible<_Tp*, nested_exception*>>>::value + >::type; + + // Attempt dynamic_cast to nested_exception and call rethrow_nested(). + template + inline __rethrow_if_nested_cond<_Ex> + __rethrow_if_nested_impl(const _Ex* __ptr) { - static void _S_rethrow(const _Tp&) { } - }; + if (auto __ne_ptr = dynamic_cast(__ptr)) + __ne_ptr->rethrow_nested(); + } + + // Otherwise, no effects. + inline void + __rethrow_if_nested_impl(const void*) + { } /// If @p __ex is derived from nested_exception, @p __ex.rethrow_nested(). template inline void rethrow_if_nested(const _Ex& __ex) - { - _Rethrow_if_nested_impl<_Ex>::_S_rethrow(__ex); - } + { std::__rethrow_if_nested_impl(std::__addressof(__ex)); } // @} group exceptions } // namespace std diff --git a/libstdc++-v3/testsuite/18_support/nested_exception/rethrow_if_nested.cc b/libstdc++-v3/testsuite/18_support/nested_exception/rethrow_if_nested.cc index 135679f..7751213 100644 --- a/libstdc++-v3/testsuite/18_support/nested_exception/rethrow_if_nested.cc +++ b/libstdc++-v3/testsuite/18_support/nested_exception/rethrow_if_nested.cc @@ -101,11 +101,30 @@ void test03() VERIFY( test ); } +void +test04() +{ + // LWG 2484 requires that these cases are well-formed, but don't rethrow. + + std::rethrow_if_nested(1); + + struct S { } nonpolymorphic; + std::rethrow_if_nested(nonpolymorphic); + + struct derived3 : derived, derived2 { }; + derived3 ambiguous_base; + std::rethrow_if_nested(ambiguous_base); + + struct derived4 : private std::nested_exception { }; + derived4 private_base; + std::rethrow_if_nested(private_base); +} int main() { test01(); test02(); test03(); + test04(); return 0; } -- cgit v1.1