mirror of
https://github.com/gcc-mirror/gcc.git
synced 2025-07-23 01:00:40 +00:00
libstdc++: Fix constexpr exceptions for -fno-exceptions
The if-consteval branches in std::make_exception_ptr and std::exception_ptr_cast use a try-catch block, which gives an error for -fno-exceptions. Just make them return a null pointer at compile-time when -fno-exceptions is used, because there's no way to get an active exception with -fno-exceptions. For both functions we have a runtime-only branch that depends on RTTI, and a fallback using try-catch which works for runtime and consteval. Rearrange both functions to express this logic more clearly. Also adjust some formatting and whitespace elsewhere in the file. libstdc++-v3/ChangeLog: * libsupc++/exception_ptr.h (make_exception_ptr): Return null for consteval when -fno-exceptions is used. (exception_ptr_cast): Likewise. Allow consteval path to work with -fno-rtti. Reviewed-by: Jakub Jelinek <jakub@redhat.com>
This commit is contained in:

committed by
Jonathan Wakely

parent
b513e4f3e0
commit
8aff55e259
@ -83,9 +83,9 @@ namespace std _GLIBCXX_VISIBILITY(default)
|
||||
|
||||
#if __cpp_lib_exception_ptr_cast >= 202506L
|
||||
template<typename _Ex>
|
||||
constexpr const _Ex* exception_ptr_cast(const exception_ptr&) noexcept;
|
||||
constexpr const _Ex* exception_ptr_cast(const exception_ptr&) noexcept;
|
||||
template<typename _Ex>
|
||||
void exception_ptr_cast(const exception_ptr&&) = delete;
|
||||
void exception_ptr_cast(const exception_ptr&&) = delete;
|
||||
#endif
|
||||
|
||||
namespace __exception_ptr
|
||||
@ -138,8 +138,8 @@ namespace std _GLIBCXX_VISIBILITY(default)
|
||||
_GLIBCXX_USE_NOEXCEPT;
|
||||
#if __cpp_lib_exception_ptr_cast >= 202506L
|
||||
template<typename _Ex>
|
||||
friend constexpr const _Ex* std::exception_ptr_cast(const exception_ptr&)
|
||||
noexcept;
|
||||
friend constexpr const _Ex*
|
||||
std::exception_ptr_cast(const exception_ptr&) noexcept;
|
||||
#endif
|
||||
|
||||
const void* _M_exception_ptr_cast(const type_info&) const
|
||||
@ -296,40 +296,41 @@ namespace std _GLIBCXX_VISIBILITY(default)
|
||||
using __exception_ptr::swap; // So that std::swap(exp1, exp2) finds it.
|
||||
|
||||
/// Obtain an exception_ptr pointing to a copy of the supplied object.
|
||||
#if (__cplusplus >= 201103L && __cpp_rtti) || __cpp_exceptions
|
||||
template<typename _Ex>
|
||||
#if !(__cplusplus >= 201103L && __cpp_rtti) && !__cpp_exceptions
|
||||
// This is always_inline so the linker will never use a useless definition
|
||||
// instead of a working one compiled with RTTI and/or exceptions enabled.
|
||||
__attribute__ ((__always_inline__)) inline
|
||||
#endif
|
||||
_GLIBCXX26_CONSTEXPR exception_ptr
|
||||
make_exception_ptr(_Ex __ex) _GLIBCXX_USE_NOEXCEPT
|
||||
{
|
||||
#if __cplusplus >= 202400L
|
||||
if consteval {
|
||||
try
|
||||
{
|
||||
throw __ex;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return current_exception();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if __cplusplus >= 201103L && __cpp_rtti
|
||||
using _Ex2 = typename decay<_Ex>::type;
|
||||
void* __e = __cxxabiv1::__cxa_allocate_exception(sizeof(_Ex));
|
||||
(void) __cxxabiv1::__cxa_init_primary_exception(
|
||||
__e, const_cast<std::type_info*>(&typeid(_Ex)),
|
||||
__exception_ptr::__dest_thunk<_Ex2>);
|
||||
__try
|
||||
// For runtime calls with -frtti enabled we can avoid try-catch overhead.
|
||||
// We can't use this for C++98 because it relies on std::decay.
|
||||
#ifdef __glibcxx_constexpr_exceptions
|
||||
if ! consteval
|
||||
#endif
|
||||
{
|
||||
::new (__e) _Ex2(__ex);
|
||||
return exception_ptr(__e);
|
||||
using _Ex2 = typename decay<_Ex>::type;
|
||||
void* __e = __cxxabiv1::__cxa_allocate_exception(sizeof(_Ex));
|
||||
(void) __cxxabiv1::__cxa_init_primary_exception(
|
||||
__e, const_cast<std::type_info*>(&typeid(_Ex)),
|
||||
__exception_ptr::__dest_thunk<_Ex2>);
|
||||
__try
|
||||
{
|
||||
::new (__e) _Ex2(__ex);
|
||||
return exception_ptr(__e);
|
||||
}
|
||||
__catch(...)
|
||||
{
|
||||
__cxxabiv1::__cxa_free_exception(__e);
|
||||
return current_exception();
|
||||
}
|
||||
}
|
||||
__catch(...)
|
||||
{
|
||||
__cxxabiv1::__cxa_free_exception(__e);
|
||||
return current_exception();
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
|
||||
#ifdef __cpp_exceptions
|
||||
try
|
||||
{
|
||||
throw __ex;
|
||||
@ -339,21 +340,14 @@ namespace std _GLIBCXX_VISIBILITY(default)
|
||||
return current_exception();
|
||||
}
|
||||
#endif
|
||||
return exception_ptr();
|
||||
}
|
||||
#else // no RTTI and no exceptions
|
||||
// This is always_inline so the linker will never use this useless definition
|
||||
// instead of a working one compiled with RTTI and/or exceptions enabled.
|
||||
template<typename _Ex>
|
||||
__attribute__ ((__always_inline__))
|
||||
_GLIBCXX26_CONSTEXPR inline exception_ptr
|
||||
make_exception_ptr(_Ex) _GLIBCXX_USE_NOEXCEPT
|
||||
{ return exception_ptr(); }
|
||||
#endif
|
||||
|
||||
#if __cpp_lib_exception_ptr_cast >= 202506L
|
||||
template<typename _Ex>
|
||||
[[__gnu__::__always_inline__]]
|
||||
constexpr const _Ex* exception_ptr_cast(const exception_ptr& __p) noexcept
|
||||
constexpr const _Ex*
|
||||
exception_ptr_cast(const exception_ptr& __p) noexcept
|
||||
{
|
||||
static_assert(!std::is_const_v<_Ex>);
|
||||
static_assert(!std::is_reference_v<_Ex>);
|
||||
@ -361,28 +355,31 @@ namespace std _GLIBCXX_VISIBILITY(default)
|
||||
static_assert(!std::is_array_v<_Ex>);
|
||||
static_assert(!std::is_pointer_v<_Ex>);
|
||||
static_assert(!std::is_member_pointer_v<_Ex>);
|
||||
|
||||
#ifdef __cpp_rtti
|
||||
if consteval {
|
||||
if (__p._M_exception_object)
|
||||
try
|
||||
{
|
||||
std::rethrow_exception(__p);
|
||||
}
|
||||
catch (const _Ex& __exc)
|
||||
{
|
||||
return &__exc;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
return nullptr;
|
||||
} else {
|
||||
// For runtime calls with -frtti enabled we can avoid try-catch overhead.
|
||||
if ! consteval {
|
||||
const type_info &__id = typeid(const _Ex&);
|
||||
return static_cast<const _Ex*>(__p._M_exception_ptr_cast(__id));
|
||||
}
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
|
||||
#ifdef __cpp_exceptions
|
||||
if (__p._M_exception_object)
|
||||
try
|
||||
{
|
||||
std::rethrow_exception(__p);
|
||||
}
|
||||
catch (const _Ex& __exc)
|
||||
{
|
||||
return &__exc;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
Reference in New Issue
Block a user