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.
---

Testing x86_64-linux.

 libstdc++-v3/libsupc++/exception_ptr.h | 113 ++++++++++++-------------
 1 file changed, 55 insertions(+), 58 deletions(-)

diff --git a/libstdc++-v3/libsupc++/exception_ptr.h 
b/libstdc++-v3/libsupc++/exception_ptr.h
index ee009155a39c..f673a3343338 100644
--- a/libstdc++-v3/libsupc++/exception_ptr.h
+++ b/libstdc++-v3/libsupc++/exception_ptr.h
@@ -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
 
-- 
2.50.0

Reply via email to