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 requires __is_standard_integer<_Tp>::value + template 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 requires __is_standard_integer<_Tp>::value + template 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 requires __is_standard_integer<_Tp>::value + template 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 requires __is_standard_integer<_Tp>::value + template 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 - 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 - 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 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 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 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 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..47f5aaa0f7cd 100644 --- a/libstdc++-v3/include/std/charconv +++ b/libstdc++-v3/include/std/charconv @@ -554,10 +554,10 @@ namespace __detail } // namespace __detail - /// std::from_chars for integral types. + /// std::from_chars for integer types. template, - is_same>>::value, int> = 0> + enable_if_t<__or_<__is_signed_or_unsigned_integer<_Tp>, + is_same>::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 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 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..3f0bcc4e77d2 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 - 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 - 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 type except bool, char, wchar_t, and charN_t. template - 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 + +template +constexpr bool +test() +{ + using S = std::make_signed_t; + using U = std::make_unsigned_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((U)5) ); + static_assert( std::in_range((S)5) ); + static_assert( ! std::in_range((U)-5) ); + static_assert( ! std::in_range((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, int, int>); // Not constructible from non integer-like objects. static_assert(!std::is_constructible_v, int, A>); +#ifdef __SIZEOF_INT128__ +static_assert(std::is_constructible_v, + __int128, unsigned __int128>); +static_assert(std::is_constructible_v, + unsigned int, int>); +#endif + // No implicit conversion from integer-like objects. template 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{}, 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 +#include + +template +constexpr bool +test() +{ + using S = std::make_signed_t; + using U = std::make_unsigned_t; + + constexpr S smax = std::numeric_limits::max(); + constexpr S smin = std::numeric_limits::min(); + constexpr U umax = std::numeric_limits::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 +#include +#include + +template +void +test() +{ + using S = std::make_signed_t; + using U = std::make_unsigned_t; + + constexpr S smax = std::numeric_limits::max(); + constexpr S smin = std::numeric_limits::min(); + constexpr U umax = std::numeric_limits::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 +}