diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2016-10-11 11:33:36 +0100 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2016-10-11 11:33:36 +0100 |
commit | 0470fad0d6c2b993e6f9906dc2d17303944dcc14 (patch) | |
tree | f4a14a82455e28eafab455288f29438bc8312154 | |
parent | bf1de1ac983d607f5097ed1a6b004e50eabb3dde (diff) | |
download | gcc-0470fad0d6c2b993e6f9906dc2d17303944dcc14.zip gcc-0470fad0d6c2b993e6f9906dc2d17303944dcc14.tar.gz gcc-0470fad0d6c2b993e6f9906dc2d17303944dcc14.tar.bz2 |
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
-rw-r--r-- | libstdc++-v3/ChangeLog | 13 | ||||
-rw-r--r-- | libstdc++-v3/doc/xml/manual/intro.xml | 8 | ||||
-rw-r--r-- | libstdc++-v3/libsupc++/nested_exception.h | 88 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/18_support/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 <jwakely@redhat.com> + * 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. <listitem><para>Divide by the object type. </para></listitem></varlistentry> + <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="../ext/lwg-defects.html#2484">2484</link>: + <emphasis><code>rethrow_if_nested()</code> is doubly unimplementable + </emphasis> + </term> + <listitem><para>Avoid using <code>dynamic_cast</code> when it would be + ill-formed. + </para></listitem></varlistentry> + <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="../ext/lwg-defects.html#2583">2583</link>: <emphasis>There is no way to supply an allocator for <code> basic_string(str, pos)</code> </emphasis> 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<typename _Tp, - bool __with_nested = !__is_base_of(nested_exception, _Tp)> - struct _Throw_with_nested_impl - { - template<typename _Up> - 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<typename _Tp> - struct _Throw_with_nested_impl<_Tp, false> + inline void + __throw_with_nested_impl(_Tp&& __t, true_type) { - template<typename _Up> - static void _S_throw(_Up&& __t) - { throw static_cast<_Up&&>(__t); } - }; - - template<typename _Tp, bool = __is_class(_Tp) && !__is_final(_Tp)> - struct _Throw_with_nested_helper : _Throw_with_nested_impl<_Tp> - { }; - - template<typename _Tp> - struct _Throw_with_nested_helper<_Tp, false> - : _Throw_with_nested_impl<_Tp, false> - { }; - - template<typename _Tp> - 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<typename _Tp> - 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_copy_constructible<_Up>, is_move_constructible<_Up>>; + static_assert(_CopyConstructible::value, + "throw_with_nested argument must be CopyConstructible"); + using __nest = __and_<is_class<_Up>, __bool_constant<!__is_final(_Up)>, + __not_<is_base_of<nested_exception, _Up>>>; + return std::__throw_with_nested_impl(std::forward<_Tp>(__t), __nest{}); } - template<typename _Tp, bool = __is_polymorphic(_Tp)> - struct _Rethrow_if_nested_impl - { - static void _S_rethrow(const _Tp& __t) - { - if (auto __tp = - dynamic_cast<const nested_exception*>(std::__addressof(__t))) - __tp->rethrow_nested(); - } - }; - + // Determine if dynamic_cast<const nested_exception&> would be well-formed. template<typename _Tp> - struct _Rethrow_if_nested_impl<_Tp, false> + using __rethrow_if_nested_cond = typename enable_if< + __and_<is_polymorphic<_Tp>, + __or_<__not_<is_base_of<nested_exception, _Tp>>, + is_convertible<_Tp*, nested_exception*>>>::value + >::type; + + // Attempt dynamic_cast to nested_exception and call rethrow_nested(). + template<typename _Ex> + 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<const nested_exception*>(__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<typename _Ex> 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; } |