On Mon, 8 Dec 2025, Jonathan Wakely wrote:

> We have __is_signed_integer and __is_unsigned_integer traits which
> should have been updated by r16-2190-g4faa42ac0dee2c when making
> __int128 an extended integer type (for PR libstdc++/96710). Currently
> they check whether the type is a signed integer type or an unsigned
> integer type, or a cv-qualified version of one of those. This doesn't
> match the standard's definition, which does not include cv-qualified
> types. This change ensures that signed __int128 and unsigned __int128
> are included in those traits in strict -std modes, and it removes the
> use of remove_cv_t so that they are not true for cv-qualified types.
> This makes the traits match the meaning of "signed integer type" and
> "unsigned integer type" in the standard ([basic.fundamental]).
> 
> We also have an __is_standard_integer trait, which is true if either
> __is_signed_integer or __is_unsigned_integer is true, but that's also
> not a match for the definition in the standard. The definitions of
> "signed integer type" and "unsigned integer type" include both standard
> and extended integer types, so only saying "standard" in the trait name
> is misleading (even before this change, because in non-strict -std modes
> the __GLIBCXX_TYPE_INT_N_0 .. __GLIBCXX_TYPE_INT_N_3 types were always
> included in the trait, and they aren't standard integer types).
> 
> This change renames __is_standard_integer to the more accurate
> __is_signed_or_unsigned_integer_type. Because the set of signed and

In the code __is_signed_or_unsigned_integer is the new name, no
_type suffix?  Besides that LGTM, this is a nice improvement.

Btw we probably should define __is_signed/unsigned_integer via explicit
specializations instead of the __is_one_of helper, so that it's O(1)
instead of O(n) to check.

> unsigned integer types is the same as the set of standard and extended
> integer types, the trait could instead have been renamed to
> __is_standard_or_extended_integer_type. I think it's clearer and more
> self-explanatory to avoid "standard and extended" and name it for the
> signed and unsigned integer types.
> 
> N.N. we don't want to call it just __is_integer_type because the integer
> types includes cv-qualified types and also bool and the character types
> char, wchar_t, char16_t etc.
> 
> The consequences of redefining and renaming these traits are small, and
> only positive.
> 
> Apart from the uses in the __is_standard_integer trait, the only other
> uses of __is_signed_integer and __is_unsigned_integer are in <format>
> and those uses are unaffected by this change to add 128-bit integers to
> the traits. In both uses the type argument is already cv-unqualified,
> and there is already explicit handling for 128-bit integers where that
> is required.
> 
> The existing uses of __is_standard_integer can simply be changed to use
> the new name. This does change the behaviour of those uses of the trait,
> because the __is_signed_or_unsigned_integer_type trait now includes
> 128-bit integers in strict modes. However, that is a desirable change
> that fixes some bugs. Specifically, the [utility.intcmp] functions such
> as std::cmp_less and the [numeric.sat.arith] functions such as
> std::add_sat did not support 128-bit integers in strict modes. Since the
> standard says they should be enabled for all signed and unsigned integer
> types (or equivalently, for all standard and extended integer types),
> those functions should all support __int128 and unsigned __int128. That
> is fixed by this change.  Additionally, the same changes in <charconv>,
> <mdspan>, and <stdckdint.h> enable the use of 128-bit integers for those
> APIs in strict modes.
> 
> Finally, this also make a drive-by fix to the enable_if constraints for
> the integer overloads of std::from_chars. That used remove_cv_t and so
> enabled the overload for lvalue arguments of type const char, which
> won't work and should not be enabled.
> 
> libstdc++-v3/ChangeLog:
> 
>       * include/bits/intcmp.h: Replace all uses of
>       __is_standard_integer with __is_signed_or_unsigned_integer_type.
>       * include/bits/max_size_type.h: Fix outdated comment.
>       * include/bits/sat_arith.h: Replace all uses of
>       __is_standard_integer with __is_signed_or_unsigned_integer_type.
>       * include/c_compatibility/stdckdint.h: Replace all uses of the
>       __cv_unqual_signed_or_unsigned_integer_type concept with
>       __is_signed_or_unsigned_integer_type.
>       (__cv_unqual_signed_or_unsigned_integer_type): Remove.
>       * include/ext/numeric_traits.h: Fix outdated comment.
>       * include/std/charconv (from_chars): Replace use of
>       __is_standard_integer with __is_signed_or_unsigned_integer_type.
>       Do not enable for cv-qualified char.
>       * include/std/mdspan: Likewise.
>       * include/std/type_traits (__is_unsigned_integer): Include
>       unsigned __int128 in type list.
>       (__is_signed_integer): Include signed __int128 in type list.
>       (__is_standard_integer): Rename to ...
>       (__is_signed_or_unsigned_integer_type): ... this.
>       * testsuite/23_containers/mdspan/extents/ctor_ints.cc: Test
>       with 128-bit integers.
>       * testsuite/23_containers/mdspan/submdspan/strided_slice.cc:
>       Likewise.
>       * testsuite/20_util/integer_comparisons/extended.cc: New test.
>       * testsuite/26_numerics/saturation/extended.cc: New test.
>       * testsuite/26_numerics/stdckdint/extended.cc: New test.
> ---
> 
> Tested x86_64-linux.
> 
>  libstdc++-v3/include/bits/intcmp.h            | 12 ++--
>  libstdc++-v3/include/bits/max_size_type.h     |  6 +-
>  libstdc++-v3/include/bits/sat_arith.h         | 12 ++--
>  .../include/c_compatibility/stdckdint.h       | 32 +++------
>  libstdc++-v3/include/ext/numeric_traits.h     |  2 +-
>  libstdc++-v3/include/std/charconv             |  4 +-
>  libstdc++-v3/include/std/mdspan               |  8 +--
>  libstdc++-v3/include/std/type_traits          | 13 +++-
>  .../20_util/integer_comparisons/extended.cc   | 60 +++++++++++++++++
>  .../23_containers/mdspan/extents/ctor_ints.cc |  7 ++
>  .../mdspan/submdspan/strided_slice.cc         |  3 +
>  .../26_numerics/saturation/extended.cc        | 55 ++++++++++++++++
>  .../26_numerics/stdckdint/extended.cc         | 65 +++++++++++++++++++
>  13 files changed, 231 insertions(+), 48 deletions(-)
>  create mode 100644 
> libstdc++-v3/testsuite/20_util/integer_comparisons/extended.cc
>  create mode 100644 libstdc++-v3/testsuite/26_numerics/saturation/extended.cc
>  create mode 100644 libstdc++-v3/testsuite/26_numerics/stdckdint/extended.cc
> 
> diff --git a/libstdc++-v3/include/bits/intcmp.h 
> b/libstdc++-v3/include/bits/intcmp.h
> index 3d3fbc43d2c8..bb9c7f2c7ff6 100644
> --- a/libstdc++-v3/include/bits/intcmp.h
> +++ b/libstdc++-v3/include/bits/intcmp.h
> @@ -49,8 +49,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>      constexpr bool
>      cmp_equal(_Tp __t, _Up __u) noexcept
>      {
> -      static_assert(__is_standard_integer<_Tp>::value);
> -      static_assert(__is_standard_integer<_Up>::value);
> +      static_assert(__is_signed_or_unsigned_integer<_Tp>::value);
> +      static_assert(__is_signed_or_unsigned_integer<_Up>::value);
>  
>        if constexpr (is_signed_v<_Tp> == is_signed_v<_Up>)
>       return __t == __u;
> @@ -69,8 +69,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>      constexpr bool
>      cmp_less(_Tp __t, _Up __u) noexcept
>      {
> -      static_assert(__is_standard_integer<_Tp>::value);
> -      static_assert(__is_standard_integer<_Up>::value);
> +      static_assert(__is_signed_or_unsigned_integer<_Tp>::value);
> +      static_assert(__is_signed_or_unsigned_integer<_Up>::value);
>  
>        if constexpr (is_signed_v<_Tp> == is_signed_v<_Up>)
>       return __t < __u;
> @@ -99,8 +99,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>      constexpr bool
>      in_range(_Tp __t) noexcept
>      {
> -      static_assert(__is_standard_integer<_Res>::value);
> -      static_assert(__is_standard_integer<_Tp>::value);
> +      static_assert(__is_signed_or_unsigned_integer<_Res>::value);
> +      static_assert(__is_signed_or_unsigned_integer<_Tp>::value);
>        using __gnu_cxx::__int_traits;
>  
>        if constexpr (is_signed_v<_Tp> == is_signed_v<_Res>)
> diff --git a/libstdc++-v3/include/bits/max_size_type.h 
> b/libstdc++-v3/include/bits/max_size_type.h
> index a34b91a04f1e..537aceeeca02 100644
> --- a/libstdc++-v3/include/bits/max_size_type.h
> +++ b/libstdc++-v3/include/bits/max_size_type.h
> @@ -44,10 +44,8 @@
>  // [iterator.concept.winc]) that are one bit wider than the widest supported
>  // integer type.
>  //
> -// The set of integer types we consider includes __int128 and unsigned 
> __int128
> -// (when they exist), even though they are really integer types only in GNU
> -// mode.  This is to obtain a consistent ABI for these integer-class types
> -// across strict mode and GNU mode.
> +// The set of integer types we consider includes the extended integer types
> +// __int128 and unsigned __int128 (when they exist).
>  
>  namespace std _GLIBCXX_VISIBILITY(default)
>  {
> diff --git a/libstdc++-v3/include/bits/sat_arith.h 
> b/libstdc++-v3/include/bits/sat_arith.h
> index e036fc88e40b..bce86d919919 100644
> --- a/libstdc++-v3/include/bits/sat_arith.h
> +++ b/libstdc++-v3/include/bits/sat_arith.h
> @@ -46,7 +46,7 @@ namespace std _GLIBCXX_VISIBILITY(default)
>  _GLIBCXX_BEGIN_NAMESPACE_VERSION
>  
>    /// Add two integers, with saturation in case of overflow.
> -  template<typename _Tp> requires __is_standard_integer<_Tp>::value
> +  template<typename _Tp> requires __is_signed_or_unsigned_integer<_Tp>::value
>      constexpr _Tp
>      add_sat(_Tp __x, _Tp __y) noexcept
>      {
> @@ -62,7 +62,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>      }
>  
>    /// Subtract one integer from another, with saturation in case of overflow.
> -  template<typename _Tp> requires __is_standard_integer<_Tp>::value
> +  template<typename _Tp> requires __is_signed_or_unsigned_integer<_Tp>::value
>      constexpr _Tp
>      sub_sat(_Tp __x, _Tp __y) noexcept
>      {
> @@ -78,7 +78,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>      }
>  
>    /// Multiply two integers, with saturation in case of overflow.
> -  template<typename _Tp> requires __is_standard_integer<_Tp>::value
> +  template<typename _Tp> requires __is_signed_or_unsigned_integer<_Tp>::value
>      constexpr _Tp
>      mul_sat(_Tp __x, _Tp __y) noexcept
>      {
> @@ -94,7 +94,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>      }
>  
>    /// Divide one integer by another, with saturation in case of overflow.
> -  template<typename _Tp> requires __is_standard_integer<_Tp>::value
> +  template<typename _Tp> requires __is_signed_or_unsigned_integer<_Tp>::value
>      constexpr _Tp
>      div_sat(_Tp __x, _Tp __y) noexcept
>      {
> @@ -107,8 +107,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>  
>    /// Divide one integer by another, with saturation in case of overflow.
>    template<typename _Res, typename _Tp>
> -    requires __is_standard_integer<_Res>::value
> -      && __is_standard_integer<_Tp>::value
> +    requires __is_signed_or_unsigned_integer<_Res>::value
> +      && __is_signed_or_unsigned_integer<_Tp>::value
>      constexpr _Res
>      saturate_cast(_Tp __x) noexcept
>      {
> diff --git a/libstdc++-v3/include/c_compatibility/stdckdint.h 
> b/libstdc++-v3/include/c_compatibility/stdckdint.h
> index 1de2d18dc1aa..5bdf4dc7b24b 100644
> --- a/libstdc++-v3/include/c_compatibility/stdckdint.h
> +++ b/libstdc++-v3/include/c_compatibility/stdckdint.h
> @@ -40,15 +40,6 @@
>  namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
>  {
>  #endif
> -/// @cond undocumented
> -namespace __detail
> -{
> -  template<typename _Tp>
> -    concept __cv_unqual_signed_or_unsigned_integer_type
> -      = std::same_as<_Tp, std::remove_cv_t<_Tp>>
> -       && std::__is_standard_integer<_Tp>::value;
> -}
> -/// @endcond
>  
>  /** Checked integer arithmetic
>   *
> @@ -71,10 +62,9 @@ template<typename _Tp1, typename _Tp2, typename _Tp3>
>    inline bool
>    ckd_add(_Tp1* __result, _Tp2 __a, _Tp3 __b)
>    {
> -    using __gnu_cxx::__detail::__cv_unqual_signed_or_unsigned_integer_type;
> -    static_assert(__cv_unqual_signed_or_unsigned_integer_type<_Tp1>);
> -    static_assert(__cv_unqual_signed_or_unsigned_integer_type<_Tp2>);
> -    static_assert(__cv_unqual_signed_or_unsigned_integer_type<_Tp3>);
> +    static_assert(std::__is_signed_or_unsigned_integer<_Tp1>::value);
> +    static_assert(std::__is_signed_or_unsigned_integer<_Tp2>::value);
> +    static_assert(std::__is_signed_or_unsigned_integer<_Tp3>::value);
>      return __builtin_add_overflow(__a, __b, __result);
>    }
>  
> @@ -82,10 +72,9 @@ template<typename _Tp1, typename _Tp2, typename _Tp3>
>    inline bool
>    ckd_sub(_Tp1* __result, _Tp2 __a, _Tp3 __b)
>    {
> -    using __gnu_cxx::__detail::__cv_unqual_signed_or_unsigned_integer_type;
> -    static_assert(__cv_unqual_signed_or_unsigned_integer_type<_Tp1>);
> -    static_assert(__cv_unqual_signed_or_unsigned_integer_type<_Tp2>);
> -    static_assert(__cv_unqual_signed_or_unsigned_integer_type<_Tp3>);
> +    static_assert(std::__is_signed_or_unsigned_integer<_Tp1>::value);
> +    static_assert(std::__is_signed_or_unsigned_integer<_Tp2>::value);
> +    static_assert(std::__is_signed_or_unsigned_integer<_Tp3>::value);
>      return __builtin_sub_overflow(__a, __b, __result);
>    }
>  
> @@ -93,15 +82,14 @@ template<typename _Tp1, typename _Tp2, typename _Tp3>
>    inline bool
>    ckd_mul(_Tp1* __result, _Tp2 __a, _Tp3 __b)
>    {
> -    using __gnu_cxx::__detail::__cv_unqual_signed_or_unsigned_integer_type;
> -    static_assert(__cv_unqual_signed_or_unsigned_integer_type<_Tp1>);
> -    static_assert(__cv_unqual_signed_or_unsigned_integer_type<_Tp2>);
> -    static_assert(__cv_unqual_signed_or_unsigned_integer_type<_Tp3>);
> +    static_assert(std::__is_signed_or_unsigned_integer<_Tp1>::value);
> +    static_assert(std::__is_signed_or_unsigned_integer<_Tp2>::value);
> +    static_assert(std::__is_signed_or_unsigned_integer<_Tp3>::value);
>      return __builtin_mul_overflow(__a, __b, __result);
>    }
>  /// @}
>  #ifndef _GLIBCXX_DOXYGEN
> -}
> +} // namespace __gnu_cxx
>  
>  using __gnu_cxx::ckd_add;
>  using __gnu_cxx::ckd_sub;
> diff --git a/libstdc++-v3/include/ext/numeric_traits.h 
> b/libstdc++-v3/include/ext/numeric_traits.h
> index 6786dc6a71bc..78cb8e398756 100644
> --- a/libstdc++-v3/include/ext/numeric_traits.h
> +++ b/libstdc++-v3/include/ext/numeric_traits.h
> @@ -48,7 +48,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>    // or is_signed, digits10, max_digits10, or max_exponent10 for floats.
>  
>    // Unlike __is_integer (and std::is_integral) this trait is true for
> -  // non-standard built-in integer types such as __int128 and __int20.
> +  // non-standard built-in integer types such as __int20.
>    template<typename _Tp>
>      struct __is_integer_nonstrict
>      : public std::__is_integer<_Tp>
> diff --git a/libstdc++-v3/include/std/charconv 
> b/libstdc++-v3/include/std/charconv
> index 8cf2c0b01d7c..cc513cd8c226 100644
> --- a/libstdc++-v3/include/std/charconv
> +++ b/libstdc++-v3/include/std/charconv
> @@ -556,8 +556,8 @@ namespace __detail
>  
>    /// std::from_chars for integral types.
>    template<typename _Tp,
> -        enable_if_t<__or_<__is_standard_integer<_Tp>,
> -                          is_same<char, remove_cv_t<_Tp>>>::value, int> = 0>
> +        enable_if_t<__or_<__is_signed_or_unsigned_integer<_Tp>,
> +                          is_same<char, _Tp>>::value, int> = 0>
>      _GLIBCXX23_CONSTEXPR from_chars_result
>      from_chars(const char* __first, const char* __last, _Tp& __value,
>              int __base = 10)
> diff --git a/libstdc++-v3/include/std/mdspan b/libstdc++-v3/include/std/mdspan
> index 03cc4f02a1cd..981fa1c601a1 100644
> --- a/libstdc++-v3/include/std/mdspan
> +++ b/libstdc++-v3/include/std/mdspan
> @@ -352,11 +352,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>    template<typename _OffsetType, typename _ExtentType, typename _StrideType>
>      struct strided_slice
>      {
> -      static_assert(__is_standard_integer<_OffsetType>::value
> +      static_assert(__is_signed_or_unsigned_integer<_OffsetType>::value
>       || __detail::__integral_constant_like<_OffsetType>);
> -      static_assert(__is_standard_integer<_ExtentType>::value
> +      static_assert(__is_signed_or_unsigned_integer<_ExtentType>::value
>       || __detail::__integral_constant_like<_ExtentType>);
> -      static_assert(__is_standard_integer<_StrideType>::value
> +      static_assert(__is_signed_or_unsigned_integer<_StrideType>::value
>       || __detail::__integral_constant_like<_StrideType>);
>  
>        using offset_type = _OffsetType;
> @@ -379,7 +379,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>    template<typename _IndexType, size_t... _Extents>
>      class extents
>      {
> -      static_assert(__is_standard_integer<_IndexType>::value,
> +      static_assert(__is_signed_or_unsigned_integer<_IndexType>::value,
>                   "IndexType must be a signed or unsigned integer type");
>        static_assert(
>         (__mdspan::__valid_static_extent<_Extents, _IndexType> && ...),
> diff --git a/libstdc++-v3/include/std/type_traits 
> b/libstdc++-v3/include/std/type_traits
> index 7c157ea7ba19..39b447b7e17e 100644
> --- a/libstdc++-v3/include/std/type_traits
> +++ b/libstdc++-v3/include/std/type_traits
> @@ -826,7 +826,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>    // Check if a type is one of the signed integer types.
>    __extension__
>    template<typename _Tp>
> -    using __is_signed_integer = __is_one_of<__remove_cv_t<_Tp>,
> +    using __is_signed_integer = __is_one_of<_Tp,
>         signed char, signed short, signed int, signed long,
>         signed long long
>  #if defined(__GLIBCXX_TYPE_INT_N_0)
> @@ -840,13 +840,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>  #endif
>  #if defined(__GLIBCXX_TYPE_INT_N_3)
>         , signed __GLIBCXX_TYPE_INT_N_3
> +#endif
> +#if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__
> +       , signed __int128
>  #endif
>         >;
>  
>    // Check if a type is one of the unsigned integer types.
>    __extension__
>    template<typename _Tp>
> -    using __is_unsigned_integer = __is_one_of<__remove_cv_t<_Tp>,
> +    using __is_unsigned_integer = __is_one_of<_Tp,
>         unsigned char, unsigned short, unsigned int, unsigned long,
>         unsigned long long
>  #if defined(__GLIBCXX_TYPE_INT_N_0)
> @@ -860,12 +863,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>  #endif
>  #if defined(__GLIBCXX_TYPE_INT_N_3)
>         , unsigned __GLIBCXX_TYPE_INT_N_3
> +#endif
> +#if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__
> +       , unsigned __int128
>  #endif
>         >;
>  
>    // Check if a type is one of the signed or unsigned integer types.
> +  // i.e. an integral types except bool, char, wchar_t, and charN_t.
>    template<typename _Tp>
> -    using __is_standard_integer
> +    using __is_signed_or_unsigned_integer
>        = __or_<__is_signed_integer<_Tp>, __is_unsigned_integer<_Tp>>;
>  
>    // __void_t (std::void_t for C++11)
> diff --git a/libstdc++-v3/testsuite/20_util/integer_comparisons/extended.cc 
> b/libstdc++-v3/testsuite/20_util/integer_comparisons/extended.cc
> new file mode 100644
> index 000000000000..d862b16b369b
> --- /dev/null
> +++ b/libstdc++-v3/testsuite/20_util/integer_comparisons/extended.cc
> @@ -0,0 +1,60 @@
> +// { dg-do compile { target c++20 } }
> +
> +#include <utility>
> +
> +template<typename T>
> +constexpr bool
> +test()
> +{
> +  using S = std::make_signed_t<T>;
> +  using U = std::make_unsigned_t<T>;
> +
> +  static_assert( std::cmp_less((S)-1, (U)1));
> +  static_assert( ! std::cmp_less((S)20, (U)10));
> +  static_assert( ! std::cmp_less((U)20, (S)10));
> +
> +  static_assert( std::cmp_greater((S)100, (U)1) );
> +  static_assert( std::cmp_greater((U)100, (S)1) );
> +  static_assert( ! std::cmp_greater((S)-100, (U)1) );
> +
> +  static_assert( std::cmp_less_equal((S)-1, (U)1));
> +  static_assert( std::cmp_less_equal((U)10, (S)10));
> +  static_assert( ! std::cmp_less_equal((U)-100, (S)-100));
> +
> +  static_assert( std::cmp_greater_equal((S)200, (U)2) );
> +  static_assert( std::cmp_greater_equal((U)2000, (S)2000) );
> +  static_assert( ! std::cmp_greater_equal((S)-100, (U)100) );
> +
> +  static_assert( std::cmp_equal((S)1, (U)1) );
> +  static_assert( ! std::cmp_equal((S)-2, (U)-2) );
> +
> +  static_assert( std::cmp_not_equal((S)-1, (U)-1) );
> +  static_assert( ! std::cmp_not_equal((S)100, (U)100) );
> +
> +  static_assert( std::in_range<S>((U)5) );
> +  static_assert( std::in_range<U>((S)5) );
> +  static_assert( ! std::in_range<S>((U)-5) );
> +  static_assert( ! std::in_range<U>((S)-5) );
> +
> +  return true;
> +}
> +
> +#ifdef __SIZEOF_INT128__
> +static_assert(test<__int128>());
> +#endif
> +
> +#ifdef __GLIBCXX_TYPE_INT_N_0
> +static_assert(test<__GLIBCXX_TYPE_INT_N_0>());
> +#endif
> +
> +#ifdef __GLIBCXX_TYPE_INT_N_1
> +static_assert(test<__GLIBCXX_TYPE_INT_N_1>());
> +#endif
> +
> +#ifdef __GLIBCXX_TYPE_INT_N_2
> +static_assert(test<__GLIBCXX_TYPE_INT_N_2>());
> +#endif
> +
> +#ifdef __GLIBCXX_TYPE_INT_N_3
> +static_assert(test<__GLIBCXX_TYPE_INT_N_3>());
> +#endif
> diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_ints.cc 
> b/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_ints.cc
> index d5f07c106aab..fdbcb707bbe0 100644
> --- a/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_ints.cc
> +++ b/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_ints.cc
> @@ -16,6 +16,13 @@ static_assert(!std::is_constructible_v<std::extents<int, 
> 1, dyn, 3>, int, int>);
>  // Not constructible from non integer-like objects.
>  static_assert(!std::is_constructible_v<std::extents<int, 1>, int, A>);
>  
> +#ifdef __SIZEOF_INT128__
> +static_assert(std::is_constructible_v<std::extents<__int128, 1, 2>,
> +                                   __int128, unsigned __int128>);
> +static_assert(std::is_constructible_v<std::extents<unsigned __int128, 1, 2>,
> +                                   unsigned int, int>);
> +#endif
> +
>  // No implicit conversion from integer-like objects.
>  template<typename Extent, typename... OExtents>
>    constexpr bool
> diff --git 
> a/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/strided_slice.cc 
> b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/strided_slice.cc
> index c43a82143214..6fa5aaa2f1ed 100644
> --- a/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/strided_slice.cc
> +++ b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/strided_slice.cc
> @@ -34,6 +34,9 @@ test_all()
>    test_initializers(0, 1, 2);
>    test_initializers(std::integral_constant<short, 0>{}, size_t{1}, 
> std::cw<2>);
>    test_initializers(-1, 2, 2);
> +#ifdef __SIZEOF_INT128__
> +  test_initializers((__int128)1, (unsigned __int128)-2, 
> std::cw<(__int128)3>);
> +#endif
>    return true;
>  }
>  
> diff --git a/libstdc++-v3/testsuite/26_numerics/saturation/extended.cc 
> b/libstdc++-v3/testsuite/26_numerics/saturation/extended.cc
> new file mode 100644
> index 000000000000..fbef62826c23
> --- /dev/null
> +++ b/libstdc++-v3/testsuite/26_numerics/saturation/extended.cc
> @@ -0,0 +1,55 @@
> +// { dg-do compile { target c++26 } }
> +
> +#include <numeric>
> +#include <limits>
> +
> +template<typename T>
> +constexpr bool
> +test()
> +{
> +  using S = std::make_signed_t<T>;
> +  using U = std::make_unsigned_t<T>;
> +
> +  constexpr S smax = std::numeric_limits<S>::max();
> +  constexpr S smin = std::numeric_limits<S>::min();
> +  constexpr U umax = std::numeric_limits<U>::max();
> +
> +  static_assert( std::add_sat(smax, (S)1) == smax );
> +  static_assert( std::add_sat(smin, (S)-2) == smin );
> +  static_assert( std::add_sat(umax, (U)3) == umax );
> +
> +  static_assert( std::sub_sat(smax, (S)-1) == smax );
> +  static_assert( std::sub_sat(smin, (S)2) == smin );
> +  static_assert( std::sub_sat((U)0, (U)3) == (U)0 );
> +
> +  static_assert( std::mul_sat((S)(smax >> 1), (S)3) == smax );
> +  static_assert( std::mul_sat((S)(smin >> 1), (S)5) == smin );
> +  static_assert( std::mul_sat((U)(umax >> 1), (U)7) == umax );
> +
> +  static_assert( std::div_sat(smax, (S)2) == (smax >> 1) );
> +  static_assert( std::div_sat(smin, (S)4) == (smin >> 2) );
> +  static_assert( std::div_sat(smin, (S)-1) == smax );
> +  static_assert( std::div_sat(umax, (U)8) == (umax >> 3) );
> +
> +  return true;
> +}
> +
> +#ifdef __SIZEOF_INT128__
> +static_assert(test<__int128>());
> +#endif
> +
> +#ifdef __GLIBCXX_TYPE_INT_N_0
> +static_assert(test<__GLIBCXX_TYPE_INT_N_0>());
> +#endif
> +
> +#ifdef __GLIBCXX_TYPE_INT_N_1
> +static_assert(test<__GLIBCXX_TYPE_INT_N_1>());
> +#endif
> +
> +#ifdef __GLIBCXX_TYPE_INT_N_2
> +static_assert(test<__GLIBCXX_TYPE_INT_N_2>());
> +#endif
> +
> +#ifdef __GLIBCXX_TYPE_INT_N_3
> +static_assert(test<__GLIBCXX_TYPE_INT_N_3>());
> +#endif
> diff --git a/libstdc++-v3/testsuite/26_numerics/stdckdint/extended.cc 
> b/libstdc++-v3/testsuite/26_numerics/stdckdint/extended.cc
> new file mode 100644
> index 000000000000..efc07923ac07
> --- /dev/null
> +++ b/libstdc++-v3/testsuite/26_numerics/stdckdint/extended.cc
> @@ -0,0 +1,65 @@
> +// { dg-do run { target c++26 } }
> +
> +#include <stdckdint.h>
> +#include <limits>
> +#include <testsuite_hooks.h>
> +
> +template<typename T>
> +void
> +test()
> +{
> +  using S = std::make_signed_t<T>;
> +  using U = std::make_unsigned_t<T>;
> +
> +  constexpr S smax = std::numeric_limits<S>::max();
> +  constexpr S smin = std::numeric_limits<S>::min();
> +  constexpr U umax = std::numeric_limits<U>::max();
> +  S sout{};
> +  U uout{};
> +
> +  VERIFY( ckd_add(&sout, smax, (S)1) );
> +  VERIFY( ! ckd_add(&uout, smax, (U)1) && uout == ((U)smax + (U)1) );
> +  VERIFY( ! ckd_add(&sout, smin, (S)99) && sout == (smin + 99) );
> +  VERIFY( ckd_add(&uout, smin, (S)99) );
> +  VERIFY( ckd_add(&sout, smin, (S)-2) );
> +  VERIFY( ckd_add(&uout, umax, (U)3) );
> +  VERIFY( ! ckd_add(&sout, (U)9, (U)3) && sout == 12 );
> +
> +  VERIFY( ckd_sub(&sout, smax, (S)-1) );
> +  VERIFY( ! ckd_sub(&uout, smax, (S)-1) && uout == ((U)smax + (U)1) );
> +  VERIFY( ckd_sub(&sout, smin, (S)2) );
> +  VERIFY( ! ckd_sub(&sout, smin, (S)-2) && sout == (smin + 2) );
> +  VERIFY( ! ckd_sub(&sout, (U)0, (U)3) && sout == -3 );
> +  VERIFY( ckd_sub(&uout, (U)0, (U)3) );
> +
> +  VERIFY( ! ckd_mul(&sout, (S)(smax >> 2), (S)3) && sout == (smax/4*3) );
> +  VERIFY( ckd_mul(&sout, (S)(smax >> 1), (S)3) );
> +  VERIFY( ! ckd_mul(&uout, (S)(smax >> 1), (S)3) );
> +  VERIFY( ckd_mul(&sout, (S)(smin >> 1), (S)5) );
> +  VERIFY( ! ckd_mul(&uout, (U)(umax >> 2), (U)3) );
> +  VERIFY( ckd_mul(&sout, (U)(umax >> 2), (U)3) );
> +  VERIFY( ckd_mul(&uout, (U)(umax >> 1), (U)7) );
> +}
> +
> +int main()
> +{
> +#ifdef __SIZEOF_INT128__
> +  test<__int128>();
> +#endif
> +
> +#ifdef __GLIBCXX_TYPE_INT_N_0
> +  test<__GLIBCXX_TYPE_INT_N_0>();
> +#endif
> +
> +#ifdef __GLIBCXX_TYPE_INT_N_1
> +  test<__GLIBCXX_TYPE_INT_N_1>();
> +#endif
> +
> +#ifdef __GLIBCXX_TYPE_INT_N_2
> +  test<__GLIBCXX_TYPE_INT_N_2>();
> +#endif
> +
> +#ifdef __GLIBCXX_TYPE_INT_N_3
> +  test<__GLIBCXX_TYPE_INT_N_3>();
> +#endif
> +}
> -- 
> 2.52.0
> 
> 

Reply via email to