Please use GitHub pull requests for new patches. Phabricator shutdown timeline
Changeset View
Changeset View
Standalone View
Standalone View
libcxx/include/exception
Show First 20 Lines • Show All 71 Lines • ▼ Show 20 Lines | |||||
template <class T> [[noreturn]] void throw_with_nested(T&& t); | template <class T> [[noreturn]] void throw_with_nested(T&& t); | ||||
template <class E> void rethrow_if_nested(const E& e); | template <class E> void rethrow_if_nested(const E& e); | ||||
} // std | } // std | ||||
*/ | */ | ||||
#include <__assert> // all public C++ headers provide the assertion handler | #include <__assert> // all public C++ headers provide the assertion handler | ||||
#include <__availability> | |||||
#include <__config> | #include <__config> | ||||
#include <__memory/addressof.h> | #include <__exception/exception.h> | ||||
#include <__type_traits/decay.h> | #include <__exception/exception_ptr.h> | ||||
#include <__type_traits/is_base_of.h> | #include <__exception/nested_exception.h> | ||||
#include <__type_traits/is_class.h> | #include <__exception/operations.h> | ||||
#include <__type_traits/is_convertible.h> | #include <__exception/terminate.h> | ||||
#include <__type_traits/is_copy_constructible.h> | |||||
#include <__type_traits/is_final.h> | |||||
#include <__type_traits/is_polymorphic.h> | |||||
#include <__utility/forward.h> | |||||
#include <cstddef> | |||||
#include <cstdlib> | |||||
#include <version> | #include <version> | ||||
// <vcruntime_exception.h> defines its own std::exception and std::bad_exception types, | |||||
// which we use in order to be ABI-compatible with other STLs on Windows. | |||||
#if defined(_LIBCPP_ABI_VCRUNTIME) | |||||
# include <vcruntime_exception.h> | |||||
#endif | |||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | ||||
# pragma GCC system_header | # pragma GCC system_header | ||||
#endif | #endif | ||||
namespace std // purposefully not using versioning namespace | |||||
{ | |||||
#if defined(_LIBCPP_ABI_VCRUNTIME) && (!defined(_HAS_EXCEPTIONS) || _HAS_EXCEPTIONS != 0) | |||||
// The std::exception class was already included above, but we're explicit about this condition here for clarity. | |||||
#elif defined(_LIBCPP_ABI_VCRUNTIME) && _HAS_EXCEPTIONS == 0 | |||||
// However, <vcruntime_exception.h> does not define std::exception and std::bad_exception | |||||
// when _HAS_EXCEPTIONS == 0. | |||||
// | |||||
// Since libc++ still wants to provide the std::exception hierarchy even when _HAS_EXCEPTIONS == 0 | |||||
// (after all those are simply types like any other), we define an ABI-compatible version | |||||
// of the VCRuntime std::exception and std::bad_exception types in that mode. | |||||
struct __std_exception_data { | |||||
char const* _What; | |||||
bool _DoFree; | |||||
}; | |||||
class exception { // base of all library exceptions | |||||
public: | |||||
exception() _NOEXCEPT : __data_() {} | |||||
explicit exception(char const* __message) _NOEXCEPT : __data_() { | |||||
__data_._What = __message; | |||||
__data_._DoFree = true; | |||||
} | |||||
exception(exception const&) _NOEXCEPT {} | |||||
exception& operator=(exception const&) _NOEXCEPT { return *this; } | |||||
virtual ~exception() _NOEXCEPT {} | |||||
virtual char const* what() const _NOEXCEPT { return __data_._What ? __data_._What : "Unknown exception"; } | |||||
private: | |||||
__std_exception_data __data_; | |||||
}; | |||||
class bad_exception : public exception { | |||||
public: | |||||
bad_exception() _NOEXCEPT : exception("bad exception") {} | |||||
}; | |||||
#else // !defined(_LIBCPP_ABI_VCRUNTIME) | |||||
// On all other platforms, we define our own std::exception and std::bad_exception types | |||||
// regardless of whether exceptions are turned on as a language feature. | |||||
class _LIBCPP_EXCEPTION_ABI exception { | |||||
public: | |||||
_LIBCPP_INLINE_VISIBILITY exception() _NOEXCEPT {} | |||||
_LIBCPP_INLINE_VISIBILITY exception(const exception&) _NOEXCEPT = default; | |||||
virtual ~exception() _NOEXCEPT; | |||||
virtual const char* what() const _NOEXCEPT; | |||||
}; | |||||
class _LIBCPP_EXCEPTION_ABI bad_exception : public exception { | |||||
public: | |||||
_LIBCPP_INLINE_VISIBILITY bad_exception() _NOEXCEPT {} | |||||
~bad_exception() _NOEXCEPT override; | |||||
const char* what() const _NOEXCEPT override; | |||||
}; | |||||
#endif // !_LIBCPP_ABI_VCRUNTIME | |||||
#if _LIBCPP_STD_VER <= 14 \ | |||||
|| defined(_LIBCPP_ENABLE_CXX17_REMOVED_UNEXPECTED_FUNCTIONS) \ | |||||
|| defined(_LIBCPP_BUILDING_LIBRARY) | |||||
typedef void (*unexpected_handler)(); | |||||
_LIBCPP_FUNC_VIS unexpected_handler set_unexpected(unexpected_handler) _NOEXCEPT; | |||||
_LIBCPP_FUNC_VIS unexpected_handler get_unexpected() _NOEXCEPT; | |||||
_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void unexpected(); | |||||
#endif | |||||
typedef void (*terminate_handler)(); | |||||
_LIBCPP_FUNC_VIS terminate_handler set_terminate(terminate_handler) _NOEXCEPT; | |||||
_LIBCPP_FUNC_VIS terminate_handler get_terminate() _NOEXCEPT; | |||||
_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void terminate() _NOEXCEPT; | |||||
_LIBCPP_FUNC_VIS bool uncaught_exception() _NOEXCEPT; | |||||
_LIBCPP_FUNC_VIS _LIBCPP_AVAILABILITY_UNCAUGHT_EXCEPTIONS int uncaught_exceptions() _NOEXCEPT; | |||||
class _LIBCPP_TYPE_VIS exception_ptr; | |||||
_LIBCPP_FUNC_VIS exception_ptr current_exception() _NOEXCEPT; | |||||
_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void rethrow_exception(exception_ptr); | |||||
#ifndef _LIBCPP_ABI_MICROSOFT | |||||
class _LIBCPP_TYPE_VIS exception_ptr | |||||
{ | |||||
void* __ptr_; | |||||
public: | |||||
_LIBCPP_INLINE_VISIBILITY exception_ptr() _NOEXCEPT : __ptr_() {} | |||||
_LIBCPP_INLINE_VISIBILITY exception_ptr(nullptr_t) _NOEXCEPT : __ptr_() {} | |||||
exception_ptr(const exception_ptr&) _NOEXCEPT; | |||||
exception_ptr& operator=(const exception_ptr&) _NOEXCEPT; | |||||
~exception_ptr() _NOEXCEPT; | |||||
_LIBCPP_INLINE_VISIBILITY explicit operator bool() const _NOEXCEPT | |||||
{return __ptr_ != nullptr;} | |||||
friend _LIBCPP_INLINE_VISIBILITY | |||||
bool operator==(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT | |||||
{return __x.__ptr_ == __y.__ptr_;} | |||||
friend _LIBCPP_INLINE_VISIBILITY | |||||
bool operator!=(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT | |||||
{return !(__x == __y);} | |||||
friend _LIBCPP_FUNC_VIS exception_ptr current_exception() _NOEXCEPT; | |||||
friend _LIBCPP_FUNC_VIS void rethrow_exception(exception_ptr); | |||||
}; | |||||
template<class _Ep> | |||||
_LIBCPP_INLINE_VISIBILITY exception_ptr | |||||
make_exception_ptr(_Ep __e) _NOEXCEPT | |||||
{ | |||||
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS | |||||
try | |||||
{ | |||||
throw __e; | |||||
} | |||||
catch (...) | |||||
{ | |||||
return current_exception(); | |||||
} | |||||
#else | |||||
((void)__e); | |||||
_VSTD::abort(); | |||||
#endif | |||||
} | |||||
#else // _LIBCPP_ABI_MICROSOFT | |||||
class _LIBCPP_TYPE_VIS exception_ptr | |||||
{ | |||||
_LIBCPP_DIAGNOSTIC_PUSH | |||||
_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wunused-private-field") | |||||
void* __ptr1_; | |||||
void* __ptr2_; | |||||
_LIBCPP_DIAGNOSTIC_POP | |||||
public: | |||||
exception_ptr() _NOEXCEPT; | |||||
exception_ptr(nullptr_t) _NOEXCEPT; | |||||
exception_ptr(const exception_ptr& __other) _NOEXCEPT; | |||||
exception_ptr& operator=(const exception_ptr& __other) _NOEXCEPT; | |||||
exception_ptr& operator=(nullptr_t) _NOEXCEPT; | |||||
~exception_ptr() _NOEXCEPT; | |||||
explicit operator bool() const _NOEXCEPT; | |||||
}; | |||||
_LIBCPP_FUNC_VIS | |||||
bool operator==(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT; | |||||
inline _LIBCPP_INLINE_VISIBILITY | |||||
bool operator!=(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT | |||||
{return !(__x == __y);} | |||||
_LIBCPP_FUNC_VIS void swap(exception_ptr&, exception_ptr&) _NOEXCEPT; | |||||
_LIBCPP_FUNC_VIS exception_ptr __copy_exception_ptr(void *__except, const void* __ptr); | |||||
_LIBCPP_FUNC_VIS exception_ptr current_exception() _NOEXCEPT; | |||||
_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void rethrow_exception(exception_ptr); | |||||
// This is a built-in template function which automagically extracts the required | |||||
// information. | |||||
template <class _E> void *__GetExceptionInfo(_E); | |||||
template<class _Ep> | |||||
_LIBCPP_INLINE_VISIBILITY exception_ptr | |||||
make_exception_ptr(_Ep __e) _NOEXCEPT | |||||
{ | |||||
return __copy_exception_ptr(_VSTD::addressof(__e), __GetExceptionInfo(__e)); | |||||
} | |||||
#endif // _LIBCPP_ABI_MICROSOFT | |||||
// nested_exception | |||||
class _LIBCPP_EXCEPTION_ABI nested_exception | |||||
{ | |||||
exception_ptr __ptr_; | |||||
public: | |||||
nested_exception() _NOEXCEPT; | |||||
// nested_exception(const nested_exception&) noexcept = default; | |||||
// nested_exception& operator=(const nested_exception&) noexcept = default; | |||||
virtual ~nested_exception() _NOEXCEPT; | |||||
// access functions | |||||
_LIBCPP_NORETURN void rethrow_nested() const; | |||||
_LIBCPP_INLINE_VISIBILITY exception_ptr nested_ptr() const _NOEXCEPT {return __ptr_;} | |||||
}; | |||||
template <class _Tp> | |||||
struct __nested | |||||
: public _Tp, | |||||
public nested_exception | |||||
{ | |||||
_LIBCPP_INLINE_VISIBILITY explicit __nested(const _Tp& __t) : _Tp(__t) {} | |||||
}; | |||||
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS | |||||
template <class _Tp, class _Up, bool> | |||||
struct __throw_with_nested; | |||||
template <class _Tp, class _Up> | |||||
struct __throw_with_nested<_Tp, _Up, true> { | |||||
_LIBCPP_NORETURN static inline _LIBCPP_INLINE_VISIBILITY void | |||||
__do_throw(_Tp&& __t) | |||||
{ | |||||
throw __nested<_Up>(std::forward<_Tp>(__t)); | |||||
} | |||||
}; | |||||
template <class _Tp, class _Up> | |||||
struct __throw_with_nested<_Tp, _Up, false> { | |||||
_LIBCPP_NORETURN static inline _LIBCPP_INLINE_VISIBILITY void | |||||
__do_throw(_Tp&& __t) | |||||
{ | |||||
throw std::forward<_Tp>(__t); | |||||
} | |||||
}; | |||||
#endif | |||||
template <class _Tp> | |||||
_LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI | |||||
void | |||||
throw_with_nested(_Tp&& __t) | |||||
{ | |||||
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS | |||||
typedef typename decay<_Tp>::type _Up; | |||||
static_assert( is_copy_constructible<_Up>::value, "type thrown must be CopyConstructible"); | |||||
__throw_with_nested<_Tp, _Up, | |||||
is_class<_Up>::value && | |||||
!is_base_of<nested_exception, _Up>::value && | |||||
!__libcpp_is_final<_Up>::value>:: | |||||
__do_throw(std::forward<_Tp>(__t)); | |||||
#else | |||||
((void)__t); | |||||
// FIXME: Make this abort | |||||
#endif | |||||
} | |||||
template <class _From, class _To> | |||||
struct __can_dynamic_cast : _BoolConstant< | |||||
is_polymorphic<_From>::value && | |||||
(!is_base_of<_To, _From>::value || | |||||
is_convertible<const _From*, const _To*>::value)> {}; | |||||
template <class _Ep> | |||||
inline _LIBCPP_INLINE_VISIBILITY | |||||
void | |||||
rethrow_if_nested(const _Ep& __e, | |||||
__enable_if_t< __can_dynamic_cast<_Ep, nested_exception>::value>* = 0) | |||||
{ | |||||
const nested_exception* __nep = dynamic_cast<const nested_exception*>(_VSTD::addressof(__e)); | |||||
if (__nep) | |||||
__nep->rethrow_nested(); | |||||
} | |||||
template <class _Ep> | |||||
inline _LIBCPP_INLINE_VISIBILITY | |||||
void | |||||
rethrow_if_nested(const _Ep&, | |||||
__enable_if_t<!__can_dynamic_cast<_Ep, nested_exception>::value>* = 0) | |||||
{ | |||||
} | |||||
} // namespace std | |||||
#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 | #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 | ||||
# include <cstdlib> | |||||
# include <type_traits> | # include <type_traits> | ||||
#endif | #endif | ||||
#endif // _LIBCPP_EXCEPTION | #endif // _LIBCPP_EXCEPTION |