libstdc++: Make __int128 meet integer-class requirements [PR 96042]
Because __int128 can be used as the difference type for iota_view, we need to ensure that it meets the requirements of an integer-class type. The requirements in [iterator.concept.winc] p10 include numeric_limits being specialized and giving meaningful answers. Currently we only specialize numeric_limits for non-standard integer types in non-strict modes. However, nothing prevents us from defining an explicit specialization for any implementation-defined type, so it doesn't matter whether std::is_integral<__int128> is true or not. This patch ensures that the numeric_limits specializations for signed and unsigned __int128 are defined whenever __int128 is available. It also makes the __numeric_traits and __int_limits helpers work for __int128, via a new __gnu_cxx::__is_integer_nonstrict trait. libstdc++-v3/ChangeLog: PR libstdc++/96042 * include/ext/numeric_traits.h (__is_integer_nonstrict): New trait which is true for 128-bit integers even in strict modes. (__numeric_traits_integer, __numeric_traits): Use __is_integer_nonstrict instead of __is_integer. * include/std/limits [__STRICT_ANSI__ && __SIZEOF_INT128__] (numeric_limits<__int128>, (numeric_limits<unsigned __int128>): Define. * testsuite/std/ranges/iota/96042.cc: New test.
This commit is contained in:
parent
4432066509
commit
386fd16c55
|
@ -51,11 +51,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
(__glibcxx_signed(_Tp) ? \
|
||||
(((((_Tp)1 << (__glibcxx_digits(_Tp) - 1)) - 1) << 1) + 1) : ~(_Tp)0)
|
||||
|
||||
template<typename _Tp>
|
||||
struct __is_integer_nonstrict
|
||||
: public std::__is_integer<_Tp>
|
||||
{ };
|
||||
|
||||
#if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__
|
||||
// __is_integer<__int128> is false, but we still want to allow it here.
|
||||
template<> struct __is_integer_nonstrict<__int128>
|
||||
{ enum { __value = 1 }; typedef std::__true_type __type; };
|
||||
|
||||
template<> struct __is_integer_nonstrict<unsigned __int128>
|
||||
{ enum { __value = 1 }; typedef std::__true_type __type; };
|
||||
#endif
|
||||
|
||||
template<typename _Value>
|
||||
struct __numeric_traits_integer
|
||||
{
|
||||
#if __cplusplus >= 201103L
|
||||
static_assert(std::__is_integer<_Value>::__value,
|
||||
static_assert(__is_integer_nonstrict<_Value>::__value,
|
||||
"invalid specialization");
|
||||
#endif
|
||||
|
||||
|
@ -132,7 +146,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
|
||||
template<typename _Value>
|
||||
struct __numeric_traits
|
||||
: public __conditional_type<std::__is_integer<_Value>::__value,
|
||||
: public __conditional_type<__is_integer_nonstrict<_Value>::__value,
|
||||
__numeric_traits_integer<_Value>,
|
||||
__numeric_traits_floating<_Value> >::__type
|
||||
{ };
|
||||
|
|
|
@ -1477,8 +1477,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
= round_toward_zero;
|
||||
};
|
||||
|
||||
#if !defined(__STRICT_ANSI__)
|
||||
|
||||
#define __INT_N(TYPE, BITSIZE, EXT, UEXT) \
|
||||
template<> \
|
||||
struct numeric_limits<TYPE> \
|
||||
|
@ -1632,6 +1630,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
#define __INT_N_U201103(TYPE)
|
||||
#endif
|
||||
|
||||
#if !defined(__STRICT_ANSI__)
|
||||
#ifdef __GLIBCXX_TYPE_INT_N_0
|
||||
__INT_N(__GLIBCXX_TYPE_INT_N_0, __GLIBCXX_BITSIZE_INT_N_0,
|
||||
__INT_N_201103 (__GLIBCXX_TYPE_INT_N_0),
|
||||
|
@ -1653,11 +1652,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
__INT_N_U201103 (__GLIBCXX_TYPE_INT_N_3))
|
||||
#endif
|
||||
|
||||
#elif defined __STRICT_ANSI__ && defined __SIZEOF_INT128__
|
||||
__INT_N(__int128, 128,
|
||||
__INT_N_201103 (__int128),
|
||||
__INT_N_U201103 (__int128))
|
||||
#endif
|
||||
|
||||
#undef __INT_N
|
||||
#undef __INT_N_201103
|
||||
#undef __INT_N_U201103
|
||||
|
||||
#endif
|
||||
|
||||
/// numeric_limits<float> specialization.
|
||||
template<>
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
// Copyright (C) 2020 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=c++2a" }
|
||||
// { dg-do compile { target c++2a } }
|
||||
|
||||
#include <ranges>
|
||||
|
||||
void
|
||||
test01()
|
||||
{
|
||||
// PR libstdc++/96042
|
||||
using V = std::ranges::iota_view<long long, int>;
|
||||
using D = std::ranges::range_difference_t<V>;
|
||||
using L = std::numeric_limits<D>;
|
||||
static_assert( L::is_specialized );
|
||||
static_assert( L::is_signed );
|
||||
static_assert( L::is_integer );
|
||||
static_assert( L::is_exact );
|
||||
static_assert( L::digits > std::numeric_limits<long long>::digits );
|
||||
static_assert( L::digits10 == static_cast<int>(L::digits * 0.30103) );
|
||||
static_assert( L::min() == (D(1) << L::digits) );
|
||||
static_assert( L::max() == ~L::min() );
|
||||
static_assert( L::lowest() == L::min() );
|
||||
}
|
Loading…
Reference in New Issue