aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2025-06-26 16:18:38 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2025-06-26 16:18:38 +0200
commitaf5b72cf9f5640d24f28398b37c7208d6b2439ab (patch)
tree22b8e29401e2aca55c76940348480d0d8987565d
parent29c7661c6f92d80f63a9a3cc37f3dc790a161f3f (diff)
downloadgcc-af5b72cf9f5640d24f28398b37c7208d6b2439ab.zip
gcc-af5b72cf9f5640d24f28398b37c7208d6b2439ab.tar.gz
gcc-af5b72cf9f5640d24f28398b37c7208d6b2439ab.tar.bz2
libstdc++: Implement C++26 P2927R3 - Inspecting exception_ptr
The following patch attempts to implement the C++26 P2927R3 - Inspecting exception_ptr paper (but not including P3748R0, I plan to play with it incrementally and it will really depend on the Constexpr exceptions patch). The function template is implemented using an out of line private method of exception_ptr, so that P3748R0 then can use if consteval and provide a constant evaluation variant of it. 2025-06-26 Jakub Jelinek <jakub@redhat.com> * include/bits/version.def (exception_ptr_cast): Add. * include/bits/version.h: Regenerate. * libsupc++/exception: Define __glibcxx_want_exception_ptr_cast before including bits/version.h. * libsupc++/exception_ptr.h (std::exception_ptr_cast): Define. (std::__exception_ptr::exception_ptr::_M_exception_ptr_cast): Declare. * libsupc++/eh_ptr.cc (std::__exception_ptr::exception_ptr::_M_exception_ptr_cast): Define. * src/c++23/std.cc.in (std::exception_ptr_cast): Export. * config/abi/pre/gnu.ver: Export _ZNKSt15__exception_ptr13exception_ptr21_M_exception_ptr_castERKSt9type_info at CXXABI_1.3.17. * testsuite/util/testsuite_abi.cc (check_version): Allow CXXABI_1.3.17. * testsuite/18_support/exception_ptr/exception_ptr_cast.cc: New test.
-rw-r--r--libstdc++-v3/config/abi/pre/gnu.ver10
-rw-r--r--libstdc++-v3/include/bits/version.def8
-rw-r--r--libstdc++-v3/include/bits/version.h10
-rw-r--r--libstdc++-v3/libsupc++/eh_ptr.cc16
-rw-r--r--libstdc++-v3/libsupc++/exception1
-rw-r--r--libstdc++-v3/libsupc++/exception_ptr.h28
-rw-r--r--libstdc++-v3/src/c++23/std.cc.in3
-rw-r--r--libstdc++-v3/testsuite/18_support/exception_ptr/exception_ptr_cast.cc81
-rw-r--r--libstdc++-v3/testsuite/util/testsuite_abi.cc1
9 files changed, 158 insertions, 0 deletions
diff --git a/libstdc++-v3/config/abi/pre/gnu.ver b/libstdc++-v3/config/abi/pre/gnu.ver
index c36f1c3..bba5705 100644
--- a/libstdc++-v3/config/abi/pre/gnu.ver
+++ b/libstdc++-v3/config/abi/pre/gnu.ver
@@ -2899,6 +2899,16 @@ CXXABI_1.3.16 {
} CXXABI_1.3.15;
#endif
+CXXABI_1.3.17 {
+ # std::exception_ptr::_M_exception_ptr_cast
+ _ZNKSt15__exception_ptr13exception_ptr21_M_exception_ptr_castERKSt9type_info;
+}
+#ifdef __riscv
+CXXABI_1.3.16;
+#else
+CXXABI_1.3.15;
+#endif
+
# Symbols in the support library (libsupc++) supporting transactional memory.
CXXABI_TM_1 {
diff --git a/libstdc++-v3/include/bits/version.def b/libstdc++-v3/include/bits/version.def
index caec5d1..f4ba501 100644
--- a/libstdc++-v3/include/bits/version.def
+++ b/libstdc++-v3/include/bits/version.def
@@ -2022,6 +2022,14 @@ ftms = {
};
};
+ftms = {
+ name = exception_ptr_cast;
+ values = {
+ v = 202506;
+ cxxmin = 26;
+ };
+};
+
// Standard test specifications.
stds[97] = ">= 199711L";
stds[03] = ">= 199711L";
diff --git a/libstdc++-v3/include/bits/version.h b/libstdc++-v3/include/bits/version.h
index 2dc21b6..dc8ac07 100644
--- a/libstdc++-v3/include/bits/version.h
+++ b/libstdc++-v3/include/bits/version.h
@@ -2263,4 +2263,14 @@
#endif /* !defined(__cpp_lib_type_order) && defined(__glibcxx_want_type_order) */
#undef __glibcxx_want_type_order
+#if !defined(__cpp_lib_exception_ptr_cast)
+# if (__cplusplus > 202302L)
+# define __glibcxx_exception_ptr_cast 202506L
+# if defined(__glibcxx_want_all) || defined(__glibcxx_want_exception_ptr_cast)
+# define __cpp_lib_exception_ptr_cast 202506L
+# endif
+# endif
+#endif /* !defined(__cpp_lib_exception_ptr_cast) && defined(__glibcxx_want_exception_ptr_cast) */
+#undef __glibcxx_want_exception_ptr_cast
+
#undef __glibcxx_want_all
diff --git a/libstdc++-v3/libsupc++/eh_ptr.cc b/libstdc++-v3/libsupc++/eh_ptr.cc
index 6512449..1fb35d8 100644
--- a/libstdc++-v3/libsupc++/eh_ptr.cc
+++ b/libstdc++-v3/libsupc++/eh_ptr.cc
@@ -220,4 +220,20 @@ std::rethrow_exception(std::exception_ptr ep)
std::terminate();
}
+const void*
+std::__exception_ptr::exception_ptr::_M_exception_ptr_cast(const type_info& t)
+ const noexcept
+{
+ void *ptr = _M_exception_object;
+ if (__builtin_expect(ptr == nullptr, false))
+ return nullptr;
+ __cxa_refcounted_exception *eh
+ = __get_refcounted_exception_header_from_obj (_M_exception_object);
+ const type_info* __thr_type = eh->exc.exceptionType;
+ if (t.__do_catch(__thr_type, &ptr, 1))
+ return ptr;
+ return nullptr;
+}
+
+
#undef _GLIBCXX_EH_PTR_COMPAT
diff --git a/libstdc++-v3/libsupc++/exception b/libstdc++-v3/libsupc++/exception
index 8c3bb33..61d4131 100644
--- a/libstdc++-v3/libsupc++/exception
+++ b/libstdc++-v3/libsupc++/exception
@@ -38,6 +38,7 @@
#include <bits/exception.h>
#define __glibcxx_want_uncaught_exceptions
+#define __glibcxx_want_exception_ptr_cast
#include <bits/version.h>
extern "C++" {
diff --git a/libstdc++-v3/libsupc++/exception_ptr.h b/libstdc++-v3/libsupc++/exception_ptr.h
index a7e5e52..a6ff8c0 100644
--- a/libstdc++-v3/libsupc++/exception_ptr.h
+++ b/libstdc++-v3/libsupc++/exception_ptr.h
@@ -80,6 +80,13 @@ namespace std _GLIBCXX_VISIBILITY(default)
/// Throw the object pointed to by the exception_ptr.
void rethrow_exception(exception_ptr) __attribute__ ((__noreturn__));
+#if __cpp_lib_exception_ptr_cast >= 202506L
+ template<typename _Ex>
+ const _Ex* exception_ptr_cast(const exception_ptr&) noexcept;
+ template<typename _Ex>
+ void exception_ptr_cast(const exception_ptr&&) = delete;
+#endif
+
namespace __exception_ptr
{
using std::rethrow_exception; // So that ADL finds it.
@@ -109,6 +116,13 @@ namespace std _GLIBCXX_VISIBILITY(default)
friend void std::rethrow_exception(exception_ptr);
template<typename _Ex>
friend exception_ptr std::make_exception_ptr(_Ex) _GLIBCXX_USE_NOEXCEPT;
+#if __cpp_lib_exception_ptr_cast >= 202506L
+ template<typename _Ex>
+ friend const _Ex* std::exception_ptr_cast(const exception_ptr&) noexcept;
+#endif
+
+ const void* _M_exception_ptr_cast(const type_info&) const
+ _GLIBCXX_USE_NOEXCEPT;
public:
exception_ptr() _GLIBCXX_USE_NOEXCEPT;
@@ -284,6 +298,20 @@ namespace std _GLIBCXX_VISIBILITY(default)
{ return exception_ptr(); }
#endif
+#if __cpp_lib_exception_ptr_cast >= 202506L
+ template<typename _Ex>
+ [[__gnu__::__always_inline__]]
+ inline const _Ex* exception_ptr_cast(const exception_ptr& __p) noexcept
+ {
+#ifdef __cpp_rtti
+ const type_info &__id = typeid(const _Ex&);
+ return static_cast<const _Ex*>(__p._M_exception_ptr_cast(__id));
+#else
+ return nullptr;
+#endif
+ }
+#endif
+
#undef _GLIBCXX_EH_PTR_USED
/// @} group exceptions
diff --git a/libstdc++-v3/src/c++23/std.cc.in b/libstdc++-v3/src/c++23/std.cc.in
index 36b19ae..9336118 100644
--- a/libstdc++-v3/src/c++23/std.cc.in
+++ b/libstdc++-v3/src/c++23/std.cc.in
@@ -1054,6 +1054,9 @@ export namespace std
using std::throw_with_nested;
using std::uncaught_exception;
using std::uncaught_exceptions;
+#if __cpp_lib_exception_ptr_cast >= 202506L
+ using std::exception_ptr_cast;
+#endif
}
// 34.4 <execution>
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
new file mode 100644
index 0000000..6a6fbfe
--- /dev/null
+++ b/libstdc++-v3/testsuite/18_support/exception_ptr/exception_ptr_cast.cc
@@ -0,0 +1,81 @@
+// { dg-do run { target c++26 } }
+
+// Copyright (C) 2025 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// exception_ptr_cast.
+
+#include <exception>
+#include <testsuite_hooks.h>
+
+#if __cpp_lib_exception_ptr_cast != 202506L
+# error "__cpp_lib_exception_ptr_cast != 202506"
+#endif
+
+struct A { int a; };
+struct B : A {};
+struct C : B {};
+struct D {};
+struct E : virtual C { int e; 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;
+};
+
+void test01()
+{
+ auto a = std::make_exception_ptr(C{ 42 });
+ auto b = std::exception_ptr_cast<C>(a);
+ VERIFY( b != nullptr );
+ VERIFY( b->a == 42 );
+ auto c = std::exception_ptr_cast<B>(a);
+ VERIFY( c == static_cast<const B*>(b) );
+ auto d = std::exception_ptr_cast<A>(a);
+ VERIFY( d == static_cast<const A*>(b) );
+ auto e = std::exception_ptr_cast<D>(a);
+ VERIFY( e == nullptr );
+ auto f = std::make_exception_ptr(42L);
+ auto g = std::exception_ptr_cast<long>(f);
+ VERIFY( g != nullptr );
+ VERIFY( *g == 42L );
+ try
+ {
+ throw G ();
+ }
+ catch (...)
+ {
+ auto h = std::current_exception();
+ auto i = std::exception_ptr_cast<G>(h);
+ VERIFY( i != nullptr );
+ VERIFY( i->a == 1 && i->e == 2 && i->f == 3 && i->g == 4 );
+ auto j = std::exception_ptr_cast<A>(h);
+ VERIFY( j == static_cast<const A*>(i) );
+ auto k = std::exception_ptr_cast<C>(h);
+ VERIFY( k == static_cast<const C*>(i) );
+ auto l = std::exception_ptr_cast<E>(h);
+ VERIFY( l == static_cast<const E*>(i) );
+ auto m = std::exception_ptr_cast<F>(h);
+ VERIFY( m == static_cast<const F*>(i) );
+ auto n = std::exception_ptr_cast<G>(a);
+ VERIFY( n == nullptr );
+ }
+}
+
+int main()
+{
+ test01();
+}
diff --git a/libstdc++-v3/testsuite/util/testsuite_abi.cc b/libstdc++-v3/testsuite/util/testsuite_abi.cc
index 7bffc6b..4b01023 100644
--- a/libstdc++-v3/testsuite/util/testsuite_abi.cc
+++ b/libstdc++-v3/testsuite/util/testsuite_abi.cc
@@ -241,6 +241,7 @@ check_version(symbol& test, bool added)
#ifdef __riscv
known_versions.push_back("CXXABI_1.3.16");
#endif
+ known_versions.push_back("CXXABI_1.3.17");
known_versions.push_back("CXXABI_IEEE128_1.3.13");
known_versions.push_back("CXXABI_TM_1");
known_versions.push_back("CXXABI_FLOAT128");