[gcc r16-2227] libstdc++: Fix constexpr exceptions for -fno-exceptions

Jonathan Wakely redi@gcc.gnu.org
Mon Jul 14 11:53:47 GMT 2025


https://gcc.gnu.org/g:8aff55e2598eca1e055d4ec16cec84676ca150c2

commit r16-2227-g8aff55e2598eca1e055d4ec16cec84676ca150c2
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Fri Jul 11 12:40:14 2025 +0100

    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>

Diff:
---
 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
-	{
-	  ::new (__e) _Ex2(__ex);
-	  return exception_ptr(__e);
-	}
-      __catch(...)
+      // 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
 	{
-	  __cxxabiv1::__cxa_free_exception(__e);
-	  return current_exception();
+	  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();
+	    }
 	}
-#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


More information about the Libstdc++-cvs mailing list