143562287SNikolas Klauser //===----------------------------------------------------------------------===// 243562287SNikolas Klauser // 343562287SNikolas Klauser // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 443562287SNikolas Klauser // See https://llvm.org/LICENSE.txt for license information. 543562287SNikolas Klauser // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 643562287SNikolas Klauser // 743562287SNikolas Klauser //===----------------------------------------------------------------------===// 843562287SNikolas Klauser 943562287SNikolas Klauser #ifndef _LIBCPP___EXCEPTION_NESTED_EXCEPTION_H 1043562287SNikolas Klauser #define _LIBCPP___EXCEPTION_NESTED_EXCEPTION_H 1143562287SNikolas Klauser 1243562287SNikolas Klauser #include <__config> 1343562287SNikolas Klauser #include <__exception/exception_ptr.h> 1443562287SNikolas Klauser #include <__memory/addressof.h> 1543562287SNikolas Klauser #include <__type_traits/decay.h> 16d6832a61SLouis Dionne #include <__type_traits/enable_if.h> 17d6832a61SLouis Dionne #include <__type_traits/integral_constant.h> 1843562287SNikolas Klauser #include <__type_traits/is_base_of.h> 1943562287SNikolas Klauser #include <__type_traits/is_class.h> 20580f6048SNikolas Klauser #include <__type_traits/is_constructible.h> 2143562287SNikolas Klauser #include <__type_traits/is_convertible.h> 2243562287SNikolas Klauser #include <__type_traits/is_final.h> 2343562287SNikolas Klauser #include <__type_traits/is_polymorphic.h> 2443562287SNikolas Klauser #include <__utility/forward.h> 2543562287SNikolas Klauser 2643562287SNikolas Klauser #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 2743562287SNikolas Klauser # pragma GCC system_header 2843562287SNikolas Klauser #endif 2943562287SNikolas Klauser 3043562287SNikolas Klauser namespace std { // purposefully not using versioning namespace 3143562287SNikolas Klauser 32f1ea0b11SNikolas Klauser class _LIBCPP_EXPORTED_FROM_ABI nested_exception { 3343562287SNikolas Klauser exception_ptr __ptr_; 3443562287SNikolas Klauser 3543562287SNikolas Klauser public: 3643562287SNikolas Klauser nested_exception() _NOEXCEPT; 3770248920SIgor Zhukov _LIBCPP_HIDE_FROM_ABI nested_exception(const nested_exception&) _NOEXCEPT = default; 3870248920SIgor Zhukov _LIBCPP_HIDE_FROM_ABI nested_exception& operator=(const nested_exception&) _NOEXCEPT = default; 3943562287SNikolas Klauser virtual ~nested_exception() _NOEXCEPT; 4043562287SNikolas Klauser 4143562287SNikolas Klauser // access functions 42748023dcSNikolas Klauser [[__noreturn__]] void rethrow_nested() const; 4343562287SNikolas Klauser _LIBCPP_HIDE_FROM_ABI exception_ptr nested_ptr() const _NOEXCEPT { return __ptr_; } 4443562287SNikolas Klauser }; 4543562287SNikolas Klauser 4643562287SNikolas Klauser template <class _Tp> 4743562287SNikolas Klauser struct __nested : public _Tp, public nested_exception { 4843562287SNikolas Klauser _LIBCPP_HIDE_FROM_ABI explicit __nested(const _Tp& __t) : _Tp(__t) {} 4943562287SNikolas Klauser }; 5043562287SNikolas Klauser 51*ba87515fSNikolas Klauser #if _LIBCPP_HAS_EXCEPTIONS 5243562287SNikolas Klauser template <class _Tp, class _Up, bool> 5343562287SNikolas Klauser struct __throw_with_nested; 5443562287SNikolas Klauser 5543562287SNikolas Klauser template <class _Tp, class _Up> 5643562287SNikolas Klauser struct __throw_with_nested<_Tp, _Up, true> { 57748023dcSNikolas Klauser [[__noreturn__]] static inline _LIBCPP_HIDE_FROM_ABI void __do_throw(_Tp&& __t) { 5843562287SNikolas Klauser throw __nested<_Up>(std::forward<_Tp>(__t)); 5943562287SNikolas Klauser } 6043562287SNikolas Klauser }; 6143562287SNikolas Klauser 6243562287SNikolas Klauser template <class _Tp, class _Up> 6343562287SNikolas Klauser struct __throw_with_nested<_Tp, _Up, false> { 64748023dcSNikolas Klauser [[__noreturn__]] static inline _LIBCPP_HIDE_FROM_ABI void __do_throw(_Tp&& __t) { throw std::forward<_Tp>(__t); } 6543562287SNikolas Klauser }; 6643562287SNikolas Klauser #endif 6743562287SNikolas Klauser 6843562287SNikolas Klauser template <class _Tp> 69748023dcSNikolas Klauser [[__noreturn__]] _LIBCPP_HIDE_FROM_ABI void throw_with_nested(_Tp&& __t) { 70*ba87515fSNikolas Klauser #if _LIBCPP_HAS_EXCEPTIONS 71173476eaSNikolas Klauser using _Up = __decay_t<_Tp>; 7243562287SNikolas Klauser static_assert(is_copy_constructible<_Up>::value, "type thrown must be CopyConstructible"); 7343562287SNikolas Klauser __throw_with_nested<_Tp, 7443562287SNikolas Klauser _Up, 7543562287SNikolas Klauser is_class<_Up>::value && !is_base_of<nested_exception, _Up>::value && 7643562287SNikolas Klauser !__libcpp_is_final<_Up>::value>::__do_throw(std::forward<_Tp>(__t)); 7743562287SNikolas Klauser #else 7843562287SNikolas Klauser ((void)__t); 7943562287SNikolas Klauser // FIXME: Make this abort 8043562287SNikolas Klauser #endif 8143562287SNikolas Klauser } 8243562287SNikolas Klauser 8343562287SNikolas Klauser template <class _From, class _To> 8443562287SNikolas Klauser struct __can_dynamic_cast 8543562287SNikolas Klauser : _BoolConstant< is_polymorphic<_From>::value && 8643562287SNikolas Klauser (!is_base_of<_To, _From>::value || is_convertible<const _From*, const _To*>::value)> {}; 8743562287SNikolas Klauser 880865b782SA. Jiang template <class _Ep, __enable_if_t< __can_dynamic_cast<_Ep, nested_exception>::value, int> = 0> 890865b782SA. Jiang inline _LIBCPP_HIDE_FROM_ABI void rethrow_if_nested(const _Ep& __e) { 9043562287SNikolas Klauser const nested_exception* __nep = dynamic_cast<const nested_exception*>(std::addressof(__e)); 9143562287SNikolas Klauser if (__nep) 9243562287SNikolas Klauser __nep->rethrow_nested(); 9343562287SNikolas Klauser } 9443562287SNikolas Klauser 950865b782SA. Jiang template <class _Ep, __enable_if_t<!__can_dynamic_cast<_Ep, nested_exception>::value, int> = 0> 960865b782SA. Jiang inline _LIBCPP_HIDE_FROM_ABI void rethrow_if_nested(const _Ep&) {} 9743562287SNikolas Klauser 9843562287SNikolas Klauser } // namespace std 9943562287SNikolas Klauser 10043562287SNikolas Klauser #endif // _LIBCPP___EXCEPTION_NESTED_EXCEPTION_H 101