https://gcc.gnu.org/g:dc503631a5086d20e633638d8631334385f9cf13

commit r16-2199-gdc503631a5086d20e633638d8631334385f9cf13
Author: Jakub Jelinek <ja...@redhat.com>
Date:   Fri Jul 11 13:50:07 2025 +0200

    libstdc++: Implement C++26 P3748R0 - Inspecting exception_ptr should be 
constexpr
    
    The following patch makes std::exception_ptr_cast constexpr.
    The paper suggests using dynamic_cast, but that does only work for
    polymorphic exceptions, doesn't work if they are scalar or non-polymorphic
    classes.
    
    Furthermore, the patch adds some static_asserts for
    "Mandates: E is a cv-unqualified complete object type. E is not an array 
type.
    E is not a pointer or pointer-to-member type."
    
    2025-07-11  Jakub Jelinek  <ja...@redhat.com>
    
            * libsupc++/exception_ptr.h: Implement C++26 P3748R0 - Inspecting
            exception_ptr should be constexpr.
            (std::exception_ptr_cast): Make constexpr, remove inline keyword.  
Add
            static_asserts for Mandates.  For if consteval use 
std::rethrow_exception,
            catch it and return its address or nullptr.
            * testsuite/18_support/exception_ptr/exception_ptr_cast.cc (E::~E): 
Add
            constexpr.
            (G::G): Likewise.
            (test01): Likewise.  Return bool and take bool argument, throw if 
the
            argument is true.  Add static_assert(test01(false)).
            (main): Call test01(true) in try.

Diff:
---
 libstdc++-v3/libsupc++/exception_ptr.h             | 33 ++++++++++++++++++----
 .../18_support/exception_ptr/exception_ptr_cast.cc | 19 ++++++++++---
 2 files changed, 43 insertions(+), 9 deletions(-)

diff --git a/libstdc++-v3/libsupc++/exception_ptr.h 
b/libstdc++-v3/libsupc++/exception_ptr.h
index be516d7aae17..ee009155a39c 100644
--- a/libstdc++-v3/libsupc++/exception_ptr.h
+++ b/libstdc++-v3/libsupc++/exception_ptr.h
@@ -83,7 +83,7 @@ namespace std _GLIBCXX_VISIBILITY(default)
 
 #if __cpp_lib_exception_ptr_cast >= 202506L
   template<typename _Ex>
-  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;
 #endif
@@ -138,7 +138,8 @@ namespace std _GLIBCXX_VISIBILITY(default)
        _GLIBCXX_USE_NOEXCEPT;
 #if __cpp_lib_exception_ptr_cast >= 202506L
       template<typename _Ex>
-      friend 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
@@ -352,11 +353,33 @@ namespace std _GLIBCXX_VISIBILITY(default)
 #if __cpp_lib_exception_ptr_cast >= 202506L
   template<typename _Ex>
     [[__gnu__::__always_inline__]]
-    inline 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>);
+      static_assert(std::is_object_v<_Ex>);
+      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
-      const type_info &__id = typeid(const _Ex&);
-      return static_cast<const _Ex*>(__p._M_exception_ptr_cast(__id));
+      if consteval {
+       if (__p._M_exception_object)
+         try
+           {
+             std::rethrow_exception(__p);
+           }
+         catch (const _Ex& __exc)
+           {
+             return &__exc;
+           }
+         catch (...)
+           {
+           }
+       return nullptr;
+      } else {
+       const type_info &__id = typeid(const _Ex&);
+       return static_cast<const _Ex*>(__p._M_exception_ptr_cast(__id));
+      }
 #else
       return nullptr;
 #endif
diff --git 
a/libstdc++-v3/testsuite/18_support/exception_ptr/exception_ptr_cast.cc 
b/libstdc++-v3/testsuite/18_support/exception_ptr/exception_ptr_cast.cc
index 6a6fbfee67aa..de371d1b7b7f 100644
--- a/libstdc++-v3/testsuite/18_support/exception_ptr/exception_ptr_cast.cc
+++ b/libstdc++-v3/testsuite/18_support/exception_ptr/exception_ptr_cast.cc
@@ -30,13 +30,13 @@ struct A { int a; };
 struct B : A {};
 struct C : B {};
 struct D {};
-struct E : virtual C { int e; virtual ~E () {} };
+struct E : virtual C { int e; constexpr virtual ~E () {} };
 struct F : virtual E, virtual C { int f; };
 struct G : virtual F, virtual C, virtual E {
-  G () : g (4) { a = 1; e = 2; f = 3; } int g;
+  constexpr G () : g (4) { a = 1; e = 2; f = 3; } int g;
 };
 
-void test01()
+constexpr bool test01(bool x)
 {
   auto a = std::make_exception_ptr(C{ 42 });
   auto b = std::exception_ptr_cast<C>(a);
@@ -73,9 +73,20 @@ void test01()
       auto n = std::exception_ptr_cast<G>(a);
       VERIFY( n == nullptr );
     }
+  if (x)
+    throw 1;
+  return true;
 }
 
+static_assert(test01(false));
+
 int main()
 {
-  test01();
+  try
+    {
+      test01(true);
+    }
+  catch (...)
+    {
+    }
 }

Reply via email to