diff options
author | redi <redi@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-08-15 15:22:44 +0000 |
---|---|---|
committer | redi <redi@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-08-15 15:22:44 +0000 |
commit | 334ac6132c99dea1e4ab6d202d88f83ff25e421c (patch) | |
tree | 0d0f1af2fe64278459b483900acea39afc2c15b1 | |
parent | dc8078a346fcfa8315589cce06808c03a5804d98 (diff) | |
download | gcc-334ac6132c99dea1e4ab6d202d88f83ff25e421c.tar.gz |
PR libstdc++/62154
* libsupc++/nested_exception.h (throw_with_nested, rethrow_if_nested):
Rewrite to conform to C++11 requirements.
* testsuite/18_support/nested_exception/62154.cc: New.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@214025 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | libstdc++-v3/ChangeLog | 7 | ||||
-rw-r--r-- | libstdc++-v3/libsupc++/nested_exception.h | 125 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/18_support/nested_exception/62154.cc | 60 |
3 files changed, 133 insertions, 59 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 6b304096a05..71541111c75 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,10 @@ +2014-08-15 Jonathan Wakely <jwakely@redhat.com> + + PR libstdc++/62154 + * libsupc++/nested_exception.h (throw_with_nested, rethrow_if_nested): + Rewrite to conform to C++11 requirements. + * testsuite/18_support/nested_exception/62154.cc: New. + 2014-08-14 Matthias Klose <doko@ubuntu.com> * testsuite/ext/random/uniform_on_sphere_distribution/requirements: diff --git a/libstdc++-v3/libsupc++/nested_exception.h b/libstdc++-v3/libsupc++/nested_exception.h index 7e2b2f264ee..841c2237f66 100644 --- a/libstdc++-v3/libsupc++/nested_exception.h +++ b/libstdc++-v3/libsupc++/nested_exception.h @@ -59,101 +59,108 @@ namespace std public: nested_exception() noexcept : _M_ptr(current_exception()) { } - nested_exception(const nested_exception&) = default; + nested_exception(const nested_exception&) noexcept = default; - nested_exception& operator=(const nested_exception&) = default; + nested_exception& operator=(const nested_exception&) noexcept = default; virtual ~nested_exception() noexcept; + [[noreturn]] void - rethrow_nested() const __attribute__ ((__noreturn__)) - { rethrow_exception(_M_ptr); } + rethrow_nested() const + { + if (_M_ptr) + rethrow_exception(_M_ptr); + std::terminate(); + } exception_ptr - nested_ptr() const + nested_ptr() const noexcept { return _M_ptr; } }; template<typename _Except> struct _Nested_exception : public _Except, public nested_exception { + explicit _Nested_exception(const _Except& __ex) + : _Except(__ex) + { } + explicit _Nested_exception(_Except&& __ex) : _Except(static_cast<_Except&&>(__ex)) { } }; - template<typename _Ex> - struct __get_nested_helper + template<typename _Tp, + bool __with_nested = !__is_base_of(nested_exception, _Tp)> + struct _Throw_with_nested_impl { - static const nested_exception* - _S_get(const _Ex& __ex) - { return dynamic_cast<const nested_exception*>(&__ex); } + template<typename _Up> + static void _S_throw(_Up&& __t) + { throw _Nested_exception<_Tp>{static_cast<_Up&&>(__t)}; } }; - template<typename _Ex> - struct __get_nested_helper<_Ex*> + template<typename _Tp> + struct _Throw_with_nested_impl<_Tp, false> { - static const nested_exception* - _S_get(const _Ex* __ex) - { return dynamic_cast<const nested_exception*>(__ex); } + template<typename _Up> + static void _S_throw(_Up&& __t) + { throw static_cast<_Up&&>(__t); } }; - template<typename _Ex> - inline const nested_exception* - __get_nested_exception(const _Ex& __ex) - { return __get_nested_helper<_Ex>::_S_get(__ex); } - - template<typename _Ex> - void - __throw_with_nested(_Ex&&, const nested_exception* = 0) - __attribute__ ((__noreturn__)); - - template<typename _Ex> - void - __throw_with_nested(_Ex&&, ...) __attribute__ ((__noreturn__)); - - // This function should never be called, but is needed to avoid a warning - // about ambiguous base classes when instantiating throw_with_nested<_Ex>() - // with a type that has an accessible nested_exception base. - template<typename _Ex> + template<typename _Tp, bool = __is_class(_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> + { }; + + template<typename _Tp> + struct _Throw_with_nested_helper<_Tp&&, false> + : _Throw_with_nested_helper<_Tp> + { }; + + /// If @p __t is derived from nested_exception, throws @p __t. + /// Else, throws an implementation-defined object derived from both. + template<typename _Tp> + [[noreturn]] inline void - __throw_with_nested(_Ex&& __ex, const nested_exception*) - { throw __ex; } + throw_with_nested(_Tp&& __t) + { + _Throw_with_nested_helper<_Tp>::_S_throw(static_cast<_Tp&&>(__t)); + } - template<typename _Ex> - inline void - __throw_with_nested(_Ex&& __ex, ...) - { throw _Nested_exception<_Ex>(static_cast<_Ex&&>(__ex)); } - - template<typename _Ex> - void - throw_with_nested(_Ex __ex) __attribute__ ((__noreturn__)); + 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*>(&__t)) + __tp->rethrow_nested(); + } + }; - /// If @p __ex is derived from nested_exception, @p __ex. - /// Else, an implementation-defined object derived from both. - template<typename _Ex> - inline void - throw_with_nested(_Ex __ex) + template<typename _Tp> + struct _Rethrow_if_nested_impl<_Tp, false> { - if (__get_nested_exception(__ex)) - throw __ex; - __throw_with_nested(static_cast<_Ex&&>(__ex), &__ex); - } + static void _S_rethrow(const _Tp&) { } + }; /// If @p __ex is derived from nested_exception, @p __ex.rethrow_nested(). template<typename _Ex> inline void rethrow_if_nested(const _Ex& __ex) { - if (const nested_exception* __nested = __get_nested_exception(__ex)) - __nested->rethrow_nested(); + _Rethrow_if_nested_impl<_Ex>::_S_rethrow(__ex); } - /// Overload, See N2619 - inline void - rethrow_if_nested(const nested_exception& __ex) - { __ex.rethrow_nested(); } - // @} group exceptions } // namespace std diff --git a/libstdc++-v3/testsuite/18_support/nested_exception/62154.cc b/libstdc++-v3/testsuite/18_support/nested_exception/62154.cc new file mode 100644 index 00000000000..9c6725f603a --- /dev/null +++ b/libstdc++-v3/testsuite/18_support/nested_exception/62154.cc @@ -0,0 +1,60 @@ +// { dg-options "-std=gnu++11" } + +// Copyright (C) 2014 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include <exception> +#include <testsuite_hooks.h> + +struct E { E(int) {} }; + +void +test01() +{ + bool caught = false; + try + { + std::throw_with_nested(E(42)); + } + catch (const std::nested_exception& e) + { + caught = true; + } + VERIFY(caught); +} + +void +test02() +{ + bool caught = false; + try + { + std::throw_with_nested(42); + } + catch (int) + { + caught = true; + } + VERIFY(caught); +} + +int +main() +{ + test01(); + test02(); +} |