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 (...) + { + } }