[RFC] libstdc++: Partial library support for std::float{16,32,64,128}_t

Message ID YzK4JeacvF923uZd@tucnak
State New, archived
Headers
Series [RFC] libstdc++: Partial library support for std::float{16,32,64,128}_t |

Commit Message

Jakub Jelinek Sept. 27, 2022, 8:45 a.m. UTC
  Hi!

The following patch is partial support for std::float{16,32,64,128}_t
in libstdc++.
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p1467r9.html
says that <ostream>, <istream>, <charconv>, <cmath> and <complex>
need changes too, but before doing that, it would be nice to get an
agreement on what macros to use etc.
The support for cmath/complex is possible in multiple ways:
1) glibc >= 2.26 support whatever{f32,f64,f128} APIs next to
   whatever{f,,l} APIs, so I think we can use
   __builtin_sin{f32,f64,f128} etc. to support _Float{32,64,128}
   overloads
2) if not, pretty much everywhere float is actually the same mode as
   _Float32 and double as _Float64, I guess one could use guards like
   #if __FLT32_MANT_DIG__ == __FLT_MANT_DIG__ \
       && __FLT32_MAX_EXP__ == __FLT_MAX_EXP__
   or
   #if __FLT64_MANT_DIG__ == __DBL_MANT_DIG__ \
       && __FLT64_MAX_EXP__ == __DBL_MAX_EXP__
   or even
   #if __FLT128_MANT_DIG__ == __LDBL_MANT_DIG__ \
       && __FLT128_MAX_EXP__ == __LDBL_MAX_EXP__
   for the few arches like aarch64 where long double and _Float128
   has the same mode.  Then we can use
   __builtin_sin{f,,l} etc. to support _Float{32,64,128} overloads
3) not sure what to do as fallback if neither 1) nor 2) work out,
   not provide the overloads, or even undef __STDCPP_FLOAT32_T__
   etc. in the library?
4) AFAIK glibc doesn't have _Float16 APIs, so we need to widen and
   use __builtin_sinf32 1) or __builtin_sinf 2) for _Float16
   and explicitly do narrowing cast
5) bfloat16_t needs more work even on the compiler side, but once
   the support is there and in stdfloat and other headers touched
   by the patch below (testcases already include bfloat16_t though),
   it will need something like 4) too.

The patch also doesn't include any testcases to cover the <type_traits>
changes, it isn't clear to me where to put that.

Tested on x86_64-linux.

2022-09-27  Jakub Jelinek  <jakub@redhat.com>

	* include/std/stdfloat: New file.
	* include/std/numbers (__glibcxx_numbers): Define and use it
	for __float128 explicit instantiations as well as
	_Float{16,32,64,128}.
	* include/std/atomic (atomic<_Float16>, atomic<_Float32>,
	atomic<_Float64>, atomic<_Float128>): New explicit instantiations.
	* include/std/type_traits (__is_floating_point_helper<_Float16>,
	__is_floating_point_helper<_Float32>,
	__is_floating_point_helper<_Float64>,
	__is_floating_point_helper<_Float128>): Likewise.
	* include/std/limits (__glibcxx_concat3_, __glibcxx_concat3,
	__glibcxx_float_n): Define.
	(numeric_limits<_Float16>, numeric_limits<_Float32>,
	numeric_limits<_Float64>, numeric_limits<_Float128>): New explicit
	instantiations.
	* include/Makefile.am (std_headers): Add stdfloat.
	* include/Makefile.in: Regenerated.
	* include/precompiled/stdc++.h: Include stdfloat.
	* testsuite/18_support/headers/stdfloat/types_std.cc: New test.
	* testsuite/18_support/headers/limits/synopsis_cxx23.cc: New test.
	* testsuite/26_numerics/numbers/4.cc: New test.
	* testsuite/29_atomics/atomic_float/requirements_cxx23.cc: New test.


	Jakub
  

Patch

--- libstdc++-v3/include/std/stdfloat.jj	2022-09-27 08:49:45.932769534 +0200
+++ libstdc++-v3/include/std/stdfloat	2022-09-27 08:49:45.932769534 +0200
@@ -0,0 +1,58 @@ 
+// <stdfloat> -*- C++ -*-
+
+// Copyright (C) 2022 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.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file include/stdfloat
+ *  This is a Standard C++ Library header.
+ */
+
+#ifndef _GLIBCXX_STDFLOAT
+#define _GLIBCXX_STDFLOAT 1
+
+#if __cplusplus > 202002L
+#include <bits/c++config.h>
+
+namespace std
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+  #ifdef __STDCPP_FLOAT16_T__
+  using float16_t = _Float16;
+  #endif
+
+  #ifdef __STDCPP_FLOAT32_T__
+  using float32_t = _Float32;
+  #endif
+
+  #ifdef __STDCPP_FLOAT64_T__
+  using float64_t = _Float64;
+  #endif
+
+  #ifdef __STDCPP_FLOAT128_T__
+  using float128_t = _Float128;
+  #endif
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+#endif // C++23
+#endif // _GLIBCXX_STDFLOAT
--- libstdc++-v3/include/std/numbers.jj	2022-01-11 22:31:41.525756652 +0100
+++ libstdc++-v3/include/std/numbers	2022-09-27 08:49:45.933769521 +0200
@@ -133,72 +133,94 @@  namespace numbers
   inline constexpr double egamma = egamma_v<double>;
   inline constexpr double phi = phi_v<double>;
 
+#define __glibcxx_numbers(TYPE, SUFFIX) \
+  /* e */						\
+  template<>						\
+    inline constexpr TYPE e_v<TYPE>			\
+      = 2.718281828459045235360287471352662498##SUFFIX;	\
+							\
+  /* log_2 e */						\
+  template<>						\
+    inline constexpr TYPE log2e_v<TYPE>			\
+      = 1.442695040888963407359924681001892137##SUFFIX;	\
+							\
+  /* log_10 e */					\
+  template<>						\
+    inline constexpr TYPE log10e_v<TYPE>		\
+      = 0.434294481903251827651128918916605082##SUFFIX;	\
+							\
+  /* pi */						\
+  template<>						\
+    inline constexpr TYPE pi_v<TYPE>			\
+      = 3.141592653589793238462643383279502884##SUFFIX;	\
+							\
+  /* 1/pi */						\
+  template<>						\
+    inline constexpr TYPE inv_pi_v<TYPE>		\
+      = 0.318309886183790671537767526745028724##SUFFIX;	\
+							\
+  /* 1/sqrt(pi) */					\
+  template<>						\
+    inline constexpr TYPE inv_sqrtpi_v<TYPE>		\
+      = 0.564189583547756286948079451560772586##SUFFIX;	\
+							\
+  /* log_e 2 */						\
+  template<>						\
+    inline constexpr TYPE ln2_v<TYPE>			\
+      = 0.693147180559945309417232121458176568##SUFFIX;	\
+							\
+  /* log_e 10 */					\
+  template<>						\
+    inline constexpr TYPE ln10_v<TYPE>			\
+      = 2.302585092994045684017991454684364208##SUFFIX;	\
+							\
+  /* sqrt(2) */						\
+  template<>						\
+    inline constexpr TYPE sqrt2_v<TYPE>			\
+      = 1.414213562373095048801688724209698079##SUFFIX;	\
+							\
+  /* sqrt(3) */						\
+  template<>						\
+    inline constexpr TYPE sqrt3_v<TYPE>			\
+      = 1.732050807568877293527446341505872367##SUFFIX;	\
+							\
+  /* 1/sqrt(3) */					\
+  template<>						\
+    inline constexpr TYPE inv_sqrt3_v<TYPE>		\
+      = 0.577350269189625764509148780501957456##SUFFIX;	\
+							\
+  /* The Euler-Mascheroni constant */			\
+  template<>						\
+    inline constexpr TYPE egamma_v<TYPE>		\
+      = 0.577215664901532860606512090082402431##SUFFIX;	\
+							\
+  /* The golden ratio, (1+sqrt(5))/2 */			\
+  template<>						\
+    inline constexpr TYPE phi_v<TYPE>			\
+      = 1.618033988749894848204586834365638118##SUFFIX
+
+#ifdef __STDCPP_FLOAT16_T__
+__glibcxx_numbers (_Float16, F16);
+#endif
+
+#ifdef __STDCPP_FLOAT32_T__
+__glibcxx_numbers (_Float32, F32);
+#endif
+
+#ifdef __STDCPP_FLOAT64_T__
+__glibcxx_numbers (_Float64, F64);
+#endif
+
+#ifdef __STDCPP_FLOAT128_T__
+__glibcxx_numbers (_Float128, F128);
+#endif
+
 #if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_FLOAT128)
-  template<>
-    inline constexpr __float128 e_v<__float128>
-      = 2.718281828459045235360287471352662498Q;
-
-  /// log_2 e
-  template<>
-    inline constexpr __float128 log2e_v<__float128>
-      = 1.442695040888963407359924681001892137Q;
-
-  /// log_10 e
-  template<>
-    inline constexpr __float128 log10e_v<__float128>
-      = 0.434294481903251827651128918916605082Q;
-
-  /// pi
-  template<>
-    inline constexpr __float128 pi_v<__float128>
-      = 3.141592653589793238462643383279502884Q;
-
-  /// 1/pi
-  template<>
-    inline constexpr __float128 inv_pi_v<__float128>
-      = 0.318309886183790671537767526745028724Q;
-
-  /// 1/sqrt(pi)
-  template<>
-    inline constexpr __float128 inv_sqrtpi_v<__float128>
-      = 0.564189583547756286948079451560772586Q;
-
-  /// log_e 2
-  template<>
-    inline constexpr __float128 ln2_v<__float128>
-      = 0.693147180559945309417232121458176568Q;
-
-  /// log_e 10
-  template<>
-    inline constexpr __float128 ln10_v<__float128>
-      = 2.302585092994045684017991454684364208Q;
-
-  /// sqrt(2)
-  template<>
-    inline constexpr __float128 sqrt2_v<__float128>
-      = 1.414213562373095048801688724209698079Q;
-
-  /// sqrt(3)
-  template<>
-    inline constexpr __float128 sqrt3_v<__float128>
-      = 1.732050807568877293527446341505872367Q;
-
-  /// 1/sqrt(3)
-  template<>
-    inline constexpr __float128 inv_sqrt3_v<__float128>
-      = 0.577350269189625764509148780501957456Q;
-
-  /// The Euler-Mascheroni constant
-  template<>
-    inline constexpr __float128 egamma_v<__float128>
-      = 0.577215664901532860606512090082402431Q;
-
-  /// The golden ratio, (1+sqrt(5))/2
-  template<>
-    inline constexpr __float128 phi_v<__float128>
-      = 1.618033988749894848204586834365638118Q;
+__glibcxx_numbers (__float128, Q);
 #endif // USE_FLOAT128
 
+#undef __glibcxx_numbers
+
 } // namespace numbers
 /// @}
 _GLIBCXX_END_NAMESPACE_VERSION
--- libstdc++-v3/include/std/atomic.jj	2022-09-11 22:28:56.375164180 +0200
+++ libstdc++-v3/include/std/atomic	2022-09-27 08:49:45.934769507 +0200
@@ -1625,6 +1625,74 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       using __atomic_float<long double>::operator=;
     };
 
+#ifdef __STDCPP_FLOAT16_T__
+  template<>
+    struct atomic<_Float16> : __atomic_float<_Float16>
+    {
+      atomic() noexcept = default;
+
+      constexpr
+      atomic(_Float16 __fp) noexcept : __atomic_float<_Float16>(__fp)
+      { }
+
+      atomic& operator=(const atomic&) volatile = delete;
+      atomic& operator=(const atomic&) = delete;
+
+      using __atomic_float<_Float16>::operator=;
+    };
+#endif
+
+#ifdef __STDCPP_FLOAT32_T__
+  template<>
+    struct atomic<_Float32> : __atomic_float<_Float32>
+    {
+      atomic() noexcept = default;
+
+      constexpr
+      atomic(_Float32 __fp) noexcept : __atomic_float<_Float32>(__fp)
+      { }
+
+      atomic& operator=(const atomic&) volatile = delete;
+      atomic& operator=(const atomic&) = delete;
+
+      using __atomic_float<_Float32>::operator=;
+    };
+#endif
+
+#ifdef __STDCPP_FLOAT64_T__
+  template<>
+    struct atomic<_Float64> : __atomic_float<_Float64>
+    {
+      atomic() noexcept = default;
+
+      constexpr
+      atomic(_Float64 __fp) noexcept : __atomic_float<_Float64>(__fp)
+      { }
+
+      atomic& operator=(const atomic&) volatile = delete;
+      atomic& operator=(const atomic&) = delete;
+
+      using __atomic_float<_Float64>::operator=;
+    };
+#endif
+
+#ifdef __STDCPP_FLOAT128_T__
+  template<>
+    struct atomic<_Float128> : __atomic_float<_Float128>
+    {
+      atomic() noexcept = default;
+
+      constexpr
+      atomic(_Float128 __fp) noexcept : __atomic_float<_Float128>(__fp)
+      { }
+
+      atomic& operator=(const atomic&) volatile = delete;
+      atomic& operator=(const atomic&) = delete;
+
+      using __atomic_float<_Float128>::operator=;
+    };
+#endif
+
 #define __cpp_lib_atomic_ref 201806L
 
   /// Class template to provide atomic operations on a non-atomic variable.
--- libstdc++-v3/include/std/type_traits.jj	2022-09-25 22:22:03.979596700 +0200
+++ libstdc++-v3/include/std/type_traits	2022-09-27 08:49:45.934769507 +0200
@@ -459,6 +459,30 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     struct __is_floating_point_helper<long double>
     : public true_type { };
 
+#ifdef __STDCPP_FLOAT16_T__
+  template<>
+    struct __is_floating_point_helper<_Float16>
+    : public true_type { };
+#endif
+
+#ifdef __STDCPP_FLOAT32_T__
+  template<>
+    struct __is_floating_point_helper<_Float32>
+    : public true_type { };
+#endif
+
+#ifdef __STDCPP_FLOAT64_T__
+  template<>
+    struct __is_floating_point_helper<_Float64>
+    : public true_type { };
+#endif
+
+#ifdef __STDCPP_FLOAT128_T__
+  template<>
+    struct __is_floating_point_helper<_Float128>
+    : public true_type { };
+#endif
+
 #if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_FLOAT128)
   template<>
     struct __is_floating_point_helper<__float128>
--- libstdc++-v3/include/std/limits.jj	2022-01-11 22:31:41.525756652 +0100
+++ libstdc++-v3/include/std/limits	2022-09-27 08:49:45.933769521 +0200
@@ -1890,6 +1890,115 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #undef __glibcxx_long_double_traps
 #undef __glibcxx_long_double_tinyness_before
 
+#if __cplusplus > 202202L
+
+#define __glibcxx_concat3_(P,M,S) P ## M ## S
+#define __glibcxx_concat3(P,M,S) __glibcxx_concat3_ (P,M,S)
+
+#define __glibcxx_float_n(BITSIZE)					\
+  __extension__								\
+  template<>								\
+    struct numeric_limits<_Float##BITSIZE>				\
+    {									\
+      static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true;		\
+									\
+      static _GLIBCXX_CONSTEXPR _Float##BITSIZE				\
+      min() _GLIBCXX_USE_NOEXCEPT					\
+      { return __glibcxx_concat3 (__FLT, BITSIZE, _MIN__); }		\
+									\
+      static _GLIBCXX_CONSTEXPR _Float##BITSIZE				\
+      max() _GLIBCXX_USE_NOEXCEPT					\
+      { return __glibcxx_concat3 (__FLT, BITSIZE, _MAX__); }		\
+									\
+      static _GLIBCXX_CONSTEXPR _Float##BITSIZE				\
+      lowest() noexcept							\
+      { return -__glibcxx_concat3 (__FLT, BITSIZE, _MAX__); }		\
+									\
+      static _GLIBCXX_USE_CONSTEXPR int digits				\
+	= __glibcxx_concat3 (__FLT, BITSIZE, _MANT_DIG__);		\
+      static _GLIBCXX_USE_CONSTEXPR int digits10			\
+	= __glibcxx_concat3 (__FLT, BITSIZE, _DIG__);			\
+      static _GLIBCXX_USE_CONSTEXPR int max_digits10			\
+	= __glibcxx_max_digits10 (__glibcxx_concat3 (__FLT, BITSIZE,	\
+						     _MANT_DIG__));	\
+      static _GLIBCXX_USE_CONSTEXPR bool is_signed = true;		\
+      static _GLIBCXX_USE_CONSTEXPR bool is_integer = false;		\
+      static _GLIBCXX_USE_CONSTEXPR bool is_exact = false;		\
+      static _GLIBCXX_USE_CONSTEXPR int radix				\
+	= __glibcxx_concat3 (__FLT, BITSIZE, _RADIX__);			\
+									\
+      static _GLIBCXX_CONSTEXPR _Float##BITSIZE				\
+      epsilon() _GLIBCXX_USE_NOEXCEPT					\
+      { return __glibcxx_concat3 (__FLT, BITSIZE, _EPSILON__); }	\
+									\
+      static _GLIBCXX_CONSTEXPR _Float##BITSIZE 			\
+      round_error() _GLIBCXX_USE_NOEXCEPT { return 0.5F##BITSIZE; }	\
+									\
+      static _GLIBCXX_USE_CONSTEXPR int min_exponent			\
+	= __glibcxx_concat3 (__FLT, BITSIZE, _MIN_EXP__);		\
+      static _GLIBCXX_USE_CONSTEXPR int min_exponent10			\
+	= __glibcxx_concat3 (__FLT, BITSIZE, _MIN_10_EXP__);		\
+      static _GLIBCXX_USE_CONSTEXPR int max_exponent			\
+	= __glibcxx_concat3 (__FLT, BITSIZE, _MAX_EXP__);		\
+      static _GLIBCXX_USE_CONSTEXPR int max_exponent10			\
+	= __glibcxx_concat3 (__FLT, BITSIZE, _MAX_10_EXP__);		\
+									\
+      static _GLIBCXX_USE_CONSTEXPR bool has_infinity			\
+	= __glibcxx_concat3 (__FLT, BITSIZE, _HAS_INFINITY__);		\
+      static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN			\
+	= __glibcxx_concat3 (__FLT, BITSIZE, _HAS_QUIET_NAN__);		\
+      static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN		\
+	= has_quiet_NaN;						\
+      static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm	\
+	= bool(__glibcxx_concat3 (__FLT, BITSIZE, _HAS_DENORM__))	\
+	  ? denorm_present : denorm_absent;				\
+      static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false;	\
+									\
+      static _GLIBCXX_CONSTEXPR _Float##BITSIZE				\
+      infinity() _GLIBCXX_USE_NOEXCEPT					\
+      { return __builtin_huge_valf##BITSIZE(); }			\
+									\
+      static _GLIBCXX_CONSTEXPR _Float##BITSIZE				\
+      quiet_NaN() _GLIBCXX_USE_NOEXCEPT					\
+      { return __builtin_nanf##BITSIZE(""); }				\
+									\
+      static _GLIBCXX_CONSTEXPR _Float##BITSIZE				\
+      signaling_NaN() _GLIBCXX_USE_NOEXCEPT				\
+      { return __builtin_nansf##BITSIZE(""); }				\
+									\
+      static _GLIBCXX_CONSTEXPR _Float##BITSIZE				\
+      denorm_min() _GLIBCXX_USE_NOEXCEPT				\
+      { return __glibcxx_concat3 (__FLT, BITSIZE, _DENORM_MIN__); }	\
+									\
+      static _GLIBCXX_USE_CONSTEXPR bool is_iec559			\
+	= as_infinity && has_quiet_NaN && has_denorm == denorm_present;	\
+      static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; 		\
+      static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; 		\
+									\
+      static _GLIBCXX_USE_CONSTEXPR bool traps = false; 		\
+      static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; 	\
+      static _GLIBCXX_USE_CONSTEXPR float_round_style round_style 	\
+	= round_to_nearest; 						\
+    }; 									\
+
+#ifdef __STDCPP_FLOAT16_T__
+__glibcxx_float_n(16)
+#endif
+#ifdef __STDCPP_FLOAT32_T__
+__glibcxx_float_n(32)
+#endif
+#ifdef __STDCPP_FLOAT64_T__
+__glibcxx_float_n(64)
+#endif
+#ifdef __STDCPP_FLOAT128_T__
+__glibcxx_float_n(128)
+#endif
+#undef __glibcxx_float_n
+#undef __glibcxx_concat3
+#undef __glibcxx_concat3_
+
+#endif
+
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace
 
--- libstdc++-v3/include/Makefile.am.jj	2022-08-10 23:16:41.981479135 +0200
+++ libstdc++-v3/include/Makefile.am	2022-09-27 09:33:16.838564748 +0200
@@ -83,6 +83,7 @@  std_headers = \
 	${std_srcdir}/stack \
 	${std_srcdir}/stacktrace \
 	${std_srcdir}/stdexcept \
+	${std_srcdir}/stdfloat \
 	${std_srcdir}/stop_token \
 	${std_srcdir}/streambuf \
 	${std_srcdir}/string \
--- libstdc++-v3/include/Makefile.in.jj	2022-08-10 23:16:41.982479122 +0200
+++ libstdc++-v3/include/Makefile.in	2022-09-27 09:33:30.089386201 +0200
@@ -441,6 +441,7 @@  std_headers = \
 	${std_srcdir}/stack \
 	${std_srcdir}/stacktrace \
 	${std_srcdir}/stdexcept \
+	${std_srcdir}/stdfloat \
 	${std_srcdir}/stop_token \
 	${std_srcdir}/streambuf \
 	${std_srcdir}/string \
--- libstdc++-v3/include/precompiled/stdc++.h.jj	2022-05-23 21:44:49.094846916 +0200
+++ libstdc++-v3/include/precompiled/stdc++.h	2022-09-27 08:49:45.932769534 +0200
@@ -159,4 +159,5 @@ 
 # include <stacktrace>
 #endif
 #include <stdatomic.h>
+#include <stdfloat>
 #endif
--- libstdc++-v3/testsuite/18_support/headers/stdfloat/types_std.cc.jj	2022-09-27 08:56:15.806529350 +0200
+++ libstdc++-v3/testsuite/18_support/headers/stdfloat/types_std.cc	2022-09-27 09:26:58.681660524 +0200
@@ -0,0 +1,40 @@ 
+// { dg-options "-std=gnu++2b" }
+// { dg-do compile { target c++23 } }
+
+// Copyright (C) 2022 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/>.
+
+#include <stdfloat>
+
+namespace gnu
+{
+#if defined(__STDCPP_FLOAT16_T__)
+  typedef std::float16_t t1;
+#endif
+#if defined(__STDCPP_FLOAT32_T__)
+  typedef std::float32_t t2;
+#endif
+#if defined(__STDCPP_FLOAT64_T__)
+  typedef std::float64_t t3;
+#endif
+#if defined(__STDCPP_FLOAT128_T__)
+  typedef std::float128_t t4;
+#endif
+#if defined(__STDCPP_BFLOAT16_T__)
+  typedef std::bfloat16_t t5;
+#endif
+}
--- libstdc++-v3/testsuite/18_support/headers/limits/synopsis_cxx23.cc.jj	2022-09-27 09:00:16.815274177 +0200
+++ libstdc++-v3/testsuite/18_support/headers/limits/synopsis_cxx23.cc	2022-09-27 09:26:44.055857783 +0200
@@ -0,0 +1,43 @@ 
+// { dg-options "-std=gnu++2b" }
+// { dg-do compile { target c++23 } }
+// { dg-require-normal-namespace "" }
+
+// Copyright (C) 2022 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/>.
+
+#include <limits>
+#include <stdfloat>
+
+namespace std {
+  template<class T> class numeric_limits;
+
+#if defined(__STDCPP_FLOAT16_T__)
+  template<> class numeric_limits<float16_t>;
+#endif
+#if defined(__STDCPP_FLOAT32_T__)
+  template<> class numeric_limits<float32_t>;
+#endif
+#if defined(__STDCPP_FLOAT64_T__)
+  template<> class numeric_limits<float64_t>;
+#endif
+#if defined(__STDCPP_FLOAT128_T__)
+  template<> class numeric_limits<float128_t>;
+#endif
+#if defined(__STDCPP_BFLOAT16_T__)
+  template<> class numeric_limits<bfloat16_t>;
+#endif
+}
--- libstdc++-v3/testsuite/26_numerics/numbers/4.cc.jj	2022-09-27 09:04:07.578159213 +0200
+++ libstdc++-v3/testsuite/26_numerics/numbers/4.cc	2022-09-27 09:06:44.603039943 +0200
@@ -0,0 +1,122 @@ 
+// Copyright (C) 2022 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/>.
+
+// { dg-options "-std=gnu++2b" }
+// { dg-do compile { target c++23 } }
+
+#include <numbers>
+#include <stdfloat>
+
+#if defined(__STDCPP_FLOAT16_T__)
+void
+test01()
+{
+  const std::float16_t* d1  = &std::numbers::e_v<std::float16_t>;
+  const std::float16_t* d2  = &std::numbers::log2e_v<std::float16_t>;
+  const std::float16_t* d3  = &std::numbers::log10e_v<std::float16_t>;
+  const std::float16_t* d4  = &std::numbers::pi_v<std::float16_t>;
+  const std::float16_t* d5  = &std::numbers::inv_pi_v<std::float16_t>;
+  const std::float16_t* d6  = &std::numbers::inv_sqrtpi_v<std::float16_t>;
+  const std::float16_t* d7  = &std::numbers::ln2_v<std::float16_t>;
+  const std::float16_t* d8  = &std::numbers::ln10_v<std::float16_t>;
+  const std::float16_t* d9  = &std::numbers::sqrt2_v<std::float16_t>;
+  const std::float16_t* d10 = &std::numbers::sqrt3_v<std::float16_t>;
+  const std::float16_t* d11 = &std::numbers::inv_sqrt3_v<std::float16_t>;
+  const std::float16_t* d12 = &std::numbers::egamma_v<std::float16_t>;
+  const std::float16_t* d13 = &std::numbers::phi_v<std::float16_t>;
+}
+#endif
+
+#if defined(__STDCPP_FLOAT32_T__)
+void
+test02()
+{
+  const std::float32_t* d1  = &std::numbers::e_v<std::float32_t>;
+  const std::float32_t* d2  = &std::numbers::log2e_v<std::float32_t>;
+  const std::float32_t* d3  = &std::numbers::log10e_v<std::float32_t>;
+  const std::float32_t* d4  = &std::numbers::pi_v<std::float32_t>;
+  const std::float32_t* d5  = &std::numbers::inv_pi_v<std::float32_t>;
+  const std::float32_t* d6  = &std::numbers::inv_sqrtpi_v<std::float32_t>;
+  const std::float32_t* d7  = &std::numbers::ln2_v<std::float32_t>;
+  const std::float32_t* d8  = &std::numbers::ln10_v<std::float32_t>;
+  const std::float32_t* d9  = &std::numbers::sqrt2_v<std::float32_t>;
+  const std::float32_t* d10 = &std::numbers::sqrt3_v<std::float32_t>;
+  const std::float32_t* d11 = &std::numbers::inv_sqrt3_v<std::float32_t>;
+  const std::float32_t* d12 = &std::numbers::egamma_v<std::float32_t>;
+  const std::float32_t* d13 = &std::numbers::phi_v<std::float32_t>;
+}
+#endif
+
+#if defined(__STDCPP_FLOAT64_T__)
+void
+test03()
+{
+  const std::float64_t* d1  = &std::numbers::e_v<std::float64_t>;
+  const std::float64_t* d2  = &std::numbers::log2e_v<std::float64_t>;
+  const std::float64_t* d3  = &std::numbers::log10e_v<std::float64_t>;
+  const std::float64_t* d4  = &std::numbers::pi_v<std::float64_t>;
+  const std::float64_t* d5  = &std::numbers::inv_pi_v<std::float64_t>;
+  const std::float64_t* d6  = &std::numbers::inv_sqrtpi_v<std::float64_t>;
+  const std::float64_t* d7  = &std::numbers::ln2_v<std::float64_t>;
+  const std::float64_t* d8  = &std::numbers::ln10_v<std::float64_t>;
+  const std::float64_t* d9  = &std::numbers::sqrt2_v<std::float64_t>;
+  const std::float64_t* d10 = &std::numbers::sqrt3_v<std::float64_t>;
+  const std::float64_t* d11 = &std::numbers::inv_sqrt3_v<std::float64_t>;
+  const std::float64_t* d12 = &std::numbers::egamma_v<std::float64_t>;
+  const std::float64_t* d13 = &std::numbers::phi_v<std::float64_t>;
+}
+#endif
+
+#if defined(__STDCPP_FLOAT128_T__)
+void
+test04()
+{
+  const std::float128_t* d1  = &std::numbers::e_v<std::float128_t>;
+  const std::float128_t* d2  = &std::numbers::log2e_v<std::float128_t>;
+  const std::float128_t* d3  = &std::numbers::log10e_v<std::float128_t>;
+  const std::float128_t* d4  = &std::numbers::pi_v<std::float128_t>;
+  const std::float128_t* d5  = &std::numbers::inv_pi_v<std::float128_t>;
+  const std::float128_t* d6  = &std::numbers::inv_sqrtpi_v<std::float128_t>;
+  const std::float128_t* d7  = &std::numbers::ln2_v<std::float128_t>;
+  const std::float128_t* d8  = &std::numbers::ln10_v<std::float128_t>;
+  const std::float128_t* d9  = &std::numbers::sqrt2_v<std::float128_t>;
+  const std::float128_t* d10 = &std::numbers::sqrt3_v<std::float128_t>;
+  const std::float128_t* d11 = &std::numbers::inv_sqrt3_v<std::float128_t>;
+  const std::float128_t* d12 = &std::numbers::egamma_v<std::float128_t>;
+  const std::float128_t* d13 = &std::numbers::phi_v<std::float128_t>;
+}
+#endif
+
+#if defined(__STDCPP_BFLOAT16_T__)
+void
+test05()
+{
+  const std::bfloat16_t* d1  = &std::numbers::e_v<std::bfloat16_t>;
+  const std::bfloat16_t* d2  = &std::numbers::log2e_v<std::bfloat16_t>;
+  const std::bfloat16_t* d3  = &std::numbers::log10e_v<std::bfloat16_t>;
+  const std::bfloat16_t* d4  = &std::numbers::pi_v<std::bfloat16_t>;
+  const std::bfloat16_t* d5  = &std::numbers::inv_pi_v<std::bfloat16_t>;
+  const std::bfloat16_t* d6  = &std::numbers::inv_sqrtpi_v<std::bfloat16_t>;
+  const std::bfloat16_t* d7  = &std::numbers::ln2_v<std::bfloat16_t>;
+  const std::bfloat16_t* d8  = &std::numbers::ln10_v<std::bfloat16_t>;
+  const std::bfloat16_t* d9  = &std::numbers::sqrt2_v<std::bfloat16_t>;
+  const std::bfloat16_t* d10 = &std::numbers::sqrt3_v<std::bfloat16_t>;
+  const std::bfloat16_t* d11 = &std::numbers::inv_sqrt3_v<std::bfloat16_t>;
+  const std::bfloat16_t* d12 = &std::numbers::egamma_v<std::bfloat16_t>;
+  const std::bfloat16_t* d13 = &std::numbers::phi_v<std::bfloat16_t>;
+}
+#endif
--- libstdc++-v3/testsuite/29_atomics/atomic_float/requirements_cxx23.cc.jj	2022-09-27 09:14:12.423997581 +0200
+++ libstdc++-v3/testsuite/29_atomics/atomic_float/requirements_cxx23.cc	2022-09-27 09:16:26.005195519 +0200
@@ -0,0 +1,112 @@ 
+// Copyright (C) 2022 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/>.
+
+// { dg-options "-std=gnu++2b" }
+// { dg-do compile { target c++23 } }
+
+#include <atomic>
+#include <stdfloat>
+
+#if defined(__STDCPP_FLOAT16_T__)
+void
+test01()
+{
+  using A = std::atomic<std::float16_t>;
+  static_assert( std::is_standard_layout_v<A> );
+  static_assert( !std::is_trivially_default_constructible_v<A> );
+  static_assert( std::is_trivially_destructible_v<A> );
+  static_assert( std::is_same_v<A::value_type, std::float16_t> );
+  static_assert( std::is_same_v<A::difference_type, A::value_type> );
+  static_assert( !std::is_copy_constructible_v<A> );
+  static_assert( !std::is_move_constructible_v<A> );
+  static_assert( !std::is_copy_assignable_v<A> );
+  static_assert( !std::is_move_assignable_v<A> );
+  static_assert( !std::is_assignable_v<volatile A&, const A&> );
+}
+#endif
+
+#if defined(__STDCPP_FLOAT32_T__)
+void
+test02()
+{
+  using A = std::atomic<std::float32_t>;
+  static_assert( std::is_standard_layout_v<A> );
+  static_assert( !std::is_trivially_default_constructible_v<A> );
+  static_assert( std::is_trivially_destructible_v<A> );
+  static_assert( std::is_same_v<A::value_type, std::float32_t> );
+  static_assert( std::is_same_v<A::difference_type, A::value_type> );
+  static_assert( !std::is_copy_constructible_v<A> );
+  static_assert( !std::is_move_constructible_v<A> );
+  static_assert( !std::is_copy_assignable_v<A> );
+  static_assert( !std::is_move_assignable_v<A> );
+  static_assert( !std::is_assignable_v<volatile A&, const A&> );
+}
+#endif
+
+#if defined(__STDCPP_FLOAT64_T__)
+void
+test03()
+{
+  using A = std::atomic<std::float64_t>;
+  static_assert( std::is_standard_layout_v<A> );
+  static_assert( !std::is_trivially_default_constructible_v<A> );
+  static_assert( std::is_trivially_destructible_v<A> );
+  static_assert( std::is_same_v<A::value_type, std::float64_t> );
+  static_assert( std::is_same_v<A::difference_type, A::value_type> );
+  static_assert( !std::is_copy_constructible_v<A> );
+  static_assert( !std::is_move_constructible_v<A> );
+  static_assert( !std::is_copy_assignable_v<A> );
+  static_assert( !std::is_move_assignable_v<A> );
+  static_assert( !std::is_assignable_v<volatile A&, const A&> );
+}
+#endif
+
+#if defined(__STDCPP_FLOAT128_T__)
+void
+test04()
+{
+  using A = std::atomic<std::float128_t>;
+  static_assert( std::is_standard_layout_v<A> );
+  static_assert( !std::is_trivially_default_constructible_v<A> );
+  static_assert( std::is_trivially_destructible_v<A> );
+  static_assert( std::is_same_v<A::value_type, std::float128_t> );
+  static_assert( std::is_same_v<A::difference_type, A::value_type> );
+  static_assert( !std::is_copy_constructible_v<A> );
+  static_assert( !std::is_move_constructible_v<A> );
+  static_assert( !std::is_copy_assignable_v<A> );
+  static_assert( !std::is_move_assignable_v<A> );
+  static_assert( !std::is_assignable_v<volatile A&, const A&> );
+}
+#endif
+
+#if defined(__STDCPP_BFLOAT16_T__)
+void
+test05()
+{
+  using A = std::atomic<std::bfloat16_t>;
+  static_assert( std::is_standard_layout_v<A> );
+  static_assert( !std::is_trivially_default_constructible_v<A> );
+  static_assert( std::is_trivially_destructible_v<A> );
+  static_assert( std::is_same_v<A::value_type, std::bfloat16_t> );
+  static_assert( std::is_same_v<A::difference_type, A::value_type> );
+  static_assert( !std::is_copy_constructible_v<A> );
+  static_assert( !std::is_move_constructible_v<A> );
+  static_assert( !std::is_copy_assignable_v<A> );
+  static_assert( !std::is_move_assignable_v<A> );
+  static_assert( !std::is_assignable_v<volatile A&, const A&> );
+}
+#endif