[gcc r16-2199] libstdc++: Implement C++26 P3748R0 - Inspecting exception_ptr should be constexpr
Jakub Jelinek
jakub@gcc.gnu.org
Fri Jul 11 11:51:41 GMT 2025
https://gcc.gnu.org/g:dc503631a5086d20e633638d8631334385f9cf13
commit r16-2199-gdc503631a5086d20e633638d8631334385f9cf13
Author: Jakub Jelinek <jakub@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 <jakub@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 (...)
+ {
+ }
}
More information about the Libstdc++-cvs
mailing list