From: Jakub Jelinek Date: Fri, 11 Jul 2025 11:50:07 +0000 (+0200) Subject: libstdc++: Implement C++26 P3748R0 - Inspecting exception_ptr should be constexpr X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=dc503631a5086d20e633638d8631334385f9cf13;p=thirdparty%2Fgcc.git 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 * 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 --git a/libstdc++-v3/libsupc++/exception_ptr.h b/libstdc++-v3/libsupc++/exception_ptr.h index be516d7aae1..ee009155a39 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 - const _Ex* exception_ptr_cast(const exception_ptr&) noexcept; + constexpr const _Ex* exception_ptr_cast(const exception_ptr&) noexcept; template 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 - 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 [[__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(__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(__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 6a6fbfee67a..de371d1b7b7 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(a); @@ -73,9 +73,20 @@ void test01() auto n = std::exception_ptr_cast(a); VERIFY( n == nullptr ); } + if (x) + throw 1; + return true; } +static_assert(test01(false)); + int main() { - test01(); + try + { + test01(true); + } + catch (...) + { + } }