libstdc++: Replace __int_limits with __numeric_traits_integer

I recently added std::__detail::__int_limits as a lightweight
alternative to std::numeric_limits, forgetting that the values it
provides (digits, min and max) are already provided by
__gnu_cxx::__numeric_traits.

This change adds __int_traits as an alias for __numeric_traits_integer.
This avoids instantiating __numeric_traits to decide whether to use
__numeric_traits_integer or __numeric_traits_floating. Then all uses of
__int_limits can be replaced with __int_traits, and __int_limits can be
removed.

libstdc++-v3/ChangeLog:

	* include/Makefile.am: Remove bits/int_limits.h.
	* include/Makefile.in: Regenerate.
	* include/bits/int_limits.h: Removed.
	* include/bits/parse_numbers.h (_Select_int_base): Replace
	__int_limits with __int_traits.
	* include/bits/range_access.h (_SSize::operator()): Likewise.
	* include/ext/numeric_traits.h (__numeric_traits_integer): Add
	static assertion.
	(__int_traits): New alias template.
	* include/std/bit (__rotl, __rotr, __countl_zero, __countl_one)
	(__countr_zero, __countr_one, __popcount, __bit_ceil)
	(__bit_floor, __bit_width) Replace __int_limits with
	__int_traits.
	* include/std/charconv (__to_chars_8, __from_chars_binary)
	(__from_chars_alpha_to_num, from_chars): Likewise.
	* include/std/memory_resource (polymorphic_allocator::allocate)
	(polymorphic_allocator::allocate_object): Likewise.
	* include/std/string_view (basic_string_view::_S_compare):
	Likewise.
	* include/std/utility (cmp_equal, cmp_less, in_range): Likewise.
This commit is contained in:
Jonathan Wakely 2020-07-07 23:26:38 +01:00
parent 9ca8fefeb7
commit eb04805be4
11 changed files with 67 additions and 133 deletions

View File

@ -129,7 +129,6 @@ bits_headers = \
${bits_srcdir}/hashtable.h \
${bits_srcdir}/hashtable_policy.h \
${bits_srcdir}/indirect_array.h \
${bits_srcdir}/int_limits.h \
${bits_srcdir}/invoke.h \
${bits_srcdir}/ios_base.h \
${bits_srcdir}/istream.tcc \

View File

@ -475,7 +475,6 @@ bits_headers = \
${bits_srcdir}/hashtable.h \
${bits_srcdir}/hashtable_policy.h \
${bits_srcdir}/indirect_array.h \
${bits_srcdir}/int_limits.h \
${bits_srcdir}/invoke.h \
${bits_srcdir}/ios_base.h \
${bits_srcdir}/istream.tcc \

View File

@ -1,74 +0,0 @@
// Minimal replacement for numeric_limits of integers. -*- C++ -*-
// 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.
// 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 bits/int_limits.h
* This is an internal header file, included by other library headers.
* Do not attempt to use it directly. @headername{limits}
*/
#ifndef _GLIBCXX_INT_LIMITS_H
#define _GLIBCXX_INT_LIMITS_H 1
#pragma GCC system_header
#if __cplusplus >= 201103L
#include <bits/c++config.h>
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
namespace __detail
{
// This template is used for arbitrary signed and unsigned integer types
// (by headers <bit> and <charconv>) and for specific integer types
// (by <memory_resource> and <string_view>) but also for char (<charconv>).
// For simplicity's sake, all integral types except bool are supported.
// Lightweight alternative to numeric_limits<signed integer type>.
template<typename _Tp, bool = is_signed<_Tp>::value>
struct __int_limits
{
static_assert(is_integral<_Tp>::value, "unsupported specialization");
using _Up = typename make_unsigned<_Tp>::type;
static constexpr int digits = sizeof(_Tp) * __CHAR_BIT__ - 1;
static constexpr _Tp min() noexcept { return _Tp(_Up(1) << digits); }
static constexpr _Tp max() noexcept { return _Tp(_Up(~_Up(0)) >> 1); }
};
// Lightweight alternative to numeric_limits<unsigned integer type>.
template<typename _Tp>
struct __int_limits<_Tp, false>
{
static_assert(is_integral<_Tp>::value, "unsupported specialization");
static constexpr int digits = sizeof(_Tp) * __CHAR_BIT__;
static constexpr _Tp min() noexcept { return 0; }
static constexpr _Tp max() noexcept { return _Tp(-1); }
};
template<> struct __int_limits<bool>; // not defined
}
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace
#endif // C++11
#endif // _GLIBCXX_INT_LIMITS_H

View File

@ -36,7 +36,7 @@
#if __cplusplus >= 201402L
#include <bits/int_limits.h>
#include <ext/numeric_traits.h>
namespace std _GLIBCXX_VISIBILITY(default)
{
@ -265,7 +265,7 @@ namespace __select_int
template<unsigned long long _Val, typename _IntType, typename... _Ints>
struct _Select_int_base<_Val, _IntType, _Ints...>
: conditional_t<(_Val <= __detail::__int_limits<_IntType>::max()),
: conditional_t<(_Val <= __gnu_cxx::__int_traits<_IntType>::__max),
integral_constant<_IntType, _Val>,
_Select_int_base<_Val, _Ints...>>
{ };

View File

@ -35,7 +35,7 @@
#if __cplusplus >= 201103L
#include <initializer_list>
#include <bits/iterator_concepts.h>
#include <bits/int_limits.h>
#include <ext/numeric_traits.h>
namespace std _GLIBCXX_VISIBILITY(default)
{
@ -727,12 +727,12 @@ namespace ranges
{
using __iter_type = decltype(_Begin{}(std::forward<_Tp>(__e)));
using __diff_type = iter_difference_t<__iter_type>;
using std::__detail::__int_limits;
using __gnu_cxx::__int_traits;
auto __size = _Size{}(std::forward<_Tp>(__e));
if constexpr (integral<__diff_type>)
{
if constexpr (__int_limits<__diff_type>::digits
< __int_limits<ptrdiff_t>::digits)
if constexpr (__int_traits<__diff_type>::__digits
< __int_traits<ptrdiff_t>::__digits)
return static_cast<ptrdiff_t>(__size);
}
return static_cast<__diff_type>(__size);

View File

@ -54,6 +54,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Value>
struct __numeric_traits_integer
{
#if __cplusplus >= 201103L
static_assert(std::__is_integer<_Value>::__value,
"invalid specialization");
#endif
// Only integers for initialization of member constant.
static const _Value __min = __glibcxx_min(_Value);
static const _Value __max = __glibcxx_max(_Value);
@ -76,6 +81,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Value>
const int __numeric_traits_integer<_Value>::__digits;
#if __cplusplus >= 201103L
template<typename _Tp>
using __int_traits = __numeric_traits_integer<_Tp>;
#endif
#undef __glibcxx_signed
#undef __glibcxx_digits
#undef __glibcxx_min

View File

@ -34,7 +34,7 @@
#if __cplusplus >= 201402L
#include <type_traits>
#include <bits/int_limits.h>
#include <ext/numeric_traits.h>
namespace std _GLIBCXX_VISIBILITY(default)
{
@ -55,7 +55,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
constexpr _Tp
__rotl(_Tp __x, int __s) noexcept
{
constexpr auto _Nd = __detail::__int_limits<_Tp>::digits;
constexpr auto _Nd = __gnu_cxx::__int_traits<_Tp>::__digits;
const int __r = __s % _Nd;
if (__r == 0)
return __x;
@ -69,7 +69,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
constexpr _Tp
__rotr(_Tp __x, int __s) noexcept
{
constexpr auto _Nd = __detail::__int_limits<_Tp>::digits;
constexpr auto _Nd = __gnu_cxx::__int_traits<_Tp>::__digits;
const int __r = __s % _Nd;
if (__r == 0)
return __x;
@ -83,15 +83,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
constexpr int
__countl_zero(_Tp __x) noexcept
{
using std::__detail::__int_limits;
constexpr auto _Nd = __int_limits<_Tp>::digits;
using __gnu_cxx::__int_traits;
constexpr auto _Nd = __int_traits<_Tp>::__digits;
if (__x == 0)
return _Nd;
constexpr auto _Nd_ull = __int_limits<unsigned long long>::digits;
constexpr auto _Nd_ul = __int_limits<unsigned long>::digits;
constexpr auto _Nd_u = __int_limits<unsigned>::digits;
constexpr auto _Nd_ull = __int_traits<unsigned long long>::__digits;
constexpr auto _Nd_ul = __int_traits<unsigned long>::__digits;
constexpr auto _Nd_u = __int_traits<unsigned>::__digits;
if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_u)
{
@ -119,7 +119,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
constexpr int __diff = (2 * _Nd_ull) - _Nd;
return __builtin_clzll(__high) - __diff;
}
constexpr auto __max_ull = __int_limits<unsigned long long>::max();
constexpr auto __max_ull = __int_traits<unsigned long long>::__max;
unsigned long long __low = __x & __max_ull;
return (_Nd - _Nd_ull) + __builtin_clzll(__low);
}
@ -129,8 +129,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
constexpr int
__countl_one(_Tp __x) noexcept
{
if (__x == __detail::__int_limits<_Tp>::max())
return __detail::__int_limits<_Tp>::digits;
if (__x == __gnu_cxx::__int_traits<_Tp>::__max)
return __gnu_cxx::__int_traits<_Tp>::__digits;
return std::__countl_zero<_Tp>((_Tp)~__x);
}
@ -138,15 +138,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
constexpr int
__countr_zero(_Tp __x) noexcept
{
using std::__detail::__int_limits;
constexpr auto _Nd = __int_limits<_Tp>::digits;
using __gnu_cxx::__int_traits;
constexpr auto _Nd = __int_traits<_Tp>::__digits;
if (__x == 0)
return _Nd;
constexpr auto _Nd_ull = __int_limits<unsigned long long>::digits;
constexpr auto _Nd_ul = __int_limits<unsigned long>::digits;
constexpr auto _Nd_u = __int_limits<unsigned>::digits;
constexpr auto _Nd_ull = __int_traits<unsigned long long>::__digits;
constexpr auto _Nd_ul = __int_traits<unsigned long>::__digits;
constexpr auto _Nd_u = __int_traits<unsigned>::__digits;
if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_u)
return __builtin_ctz(__x);
@ -159,7 +159,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
static_assert(_Nd <= (2 * _Nd_ull),
"Maximum supported integer size is 128-bit");
constexpr auto __max_ull = __int_limits<unsigned long long>::max();
constexpr auto __max_ull = __int_traits<unsigned long long>::__max;
unsigned long long __low = __x & __max_ull;
if (__low != 0)
return __builtin_ctzll(__low);
@ -172,8 +172,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
constexpr int
__countr_one(_Tp __x) noexcept
{
if (__x == __detail::__int_limits<_Tp>::max())
return __detail::__int_limits<_Tp>::digits;
if (__x == __gnu_cxx::__int_traits<_Tp>::__max)
return __gnu_cxx::__int_traits<_Tp>::__digits;
return std::__countr_zero((_Tp)~__x);
}
@ -181,15 +181,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
constexpr int
__popcount(_Tp __x) noexcept
{
using std::__detail::__int_limits;
constexpr auto _Nd = __int_limits<_Tp>::digits;
using __gnu_cxx::__int_traits;
constexpr auto _Nd = __int_traits<_Tp>::__digits;
if (__x == 0)
return 0;
constexpr auto _Nd_ull = __int_limits<unsigned long long>::digits;
constexpr auto _Nd_ul = __int_limits<unsigned long>::digits;
constexpr auto _Nd_u = __int_limits<unsigned>::digits;
constexpr auto _Nd_ull = __int_traits<unsigned long long>::__digits;
constexpr auto _Nd_ul = __int_traits<unsigned long>::__digits;
constexpr auto _Nd_u = __int_traits<unsigned>::__digits;
if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_u)
return __builtin_popcount(__x);
@ -202,7 +202,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
static_assert(_Nd <= (2 * _Nd_ull),
"Maximum supported integer size is 128-bit");
constexpr auto __max_ull = __int_limits<unsigned long long>::max();
constexpr auto __max_ull = __int_traits<unsigned long long>::__max;
unsigned long long __low = __x & __max_ull;
unsigned long long __high = __x >> _Nd_ull;
return __builtin_popcountll(__low) + __builtin_popcountll(__high);
@ -218,8 +218,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
constexpr _Tp
__bit_ceil(_Tp __x) noexcept
{
using std::__detail::__int_limits;
constexpr auto _Nd = __int_limits<_Tp>::digits;
using __gnu_cxx::__int_traits;
constexpr auto _Nd = __int_traits<_Tp>::__digits;
if (__x == 0 || __x == 1)
return 1;
auto __shift_exponent = _Nd - std::__countl_zero((_Tp)(__x - 1u));
@ -230,7 +230,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED
if (!__builtin_is_constant_evaluated())
{
__glibcxx_assert( __shift_exponent != __int_limits<_Tp>::digits );
__glibcxx_assert( __shift_exponent != __int_traits<_Tp>::__digits );
}
#endif
using __promoted_type = decltype(__x << 1);
@ -251,7 +251,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
constexpr _Tp
__bit_floor(_Tp __x) noexcept
{
constexpr auto _Nd = __detail::__int_limits<_Tp>::digits;
constexpr auto _Nd = __gnu_cxx::__int_traits<_Tp>::__digits;
if (__x == 0)
return 0;
return (_Tp)1u << (_Nd - std::__countl_zero((_Tp)(__x >> 1)));
@ -261,7 +261,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
constexpr _Tp
__bit_width(_Tp __x) noexcept
{
constexpr auto _Nd = __detail::__int_limits<_Tp>::digits;
constexpr auto _Nd = __gnu_cxx::__int_traits<_Tp>::__digits;
return _Nd - std::__countl_zero(__x);
}

View File

@ -42,7 +42,7 @@
#include <cctype> // for isdigit
#include <bits/charconv.h> // for __to_chars_len, __to_chars_10_impl
#include <bits/error_constants.h> // for std::errc
#include <bits/int_limits.h>
#include <ext/numeric_traits.h>
// FIXME: Define when floating point is supported:
// #define __cpp_lib_to_chars 201611L
@ -237,7 +237,7 @@ namespace __detail
to_chars_result __res;
unsigned __len;
if _GLIBCXX17_CONSTEXPR (__detail::__int_limits<_Tp>::digits <= 16)
if _GLIBCXX17_CONSTEXPR (__gnu_cxx::__int_traits<_Tp>::__digits <= 16)
{
__len = __val > 077777u ? 6u
: __val > 07777u ? 5u
@ -432,7 +432,7 @@ namespace __detail
__i++;
}
__first += __i;
return (__i - __leading_zeroes) <= __detail::__int_limits<_Tp>::digits;
return (__i - __leading_zeroes) <= __gnu_cxx::__int_traits<_Tp>::__digits;
}
/// std::from_chars implementation for integers in bases 3 to 10.
@ -551,7 +551,7 @@ namespace __detail
case 'Z':
return 35;
}
return __detail::__int_limits<unsigned char>::max();
return __gnu_cxx::__int_traits<unsigned char>::__max;
}
/// std::from_chars implementation for integers in bases 11 to 26.
@ -638,10 +638,10 @@ namespace __detail
}
else
{
if _GLIBCXX17_CONSTEXPR (__detail::__int_limits<_Up>::max()
> __detail::__int_limits<_Tp>::max())
if _GLIBCXX17_CONSTEXPR (__gnu_cxx::__int_traits<_Up>::__max
> __gnu_cxx::__int_traits<_Tp>::__max)
{
if (__val > __detail::__int_limits<_Tp>::max())
if (__val > __gnu_cxx::__int_traits<_Tp>::__max)
__res.ec = errc::result_out_of_range;
else
__value = __val;

View File

@ -39,7 +39,7 @@
#include <cstddef> // size_t, max_align_t, byte
#include <shared_mutex> // shared_mutex
#include <bits/functexcept.h>
#include <bits/int_limits.h>
#include <ext/numeric_traits.h>
#include <debug/assertions.h>
namespace std _GLIBCXX_VISIBILITY(default)
@ -168,7 +168,7 @@ namespace pmr
allocate(size_t __n)
__attribute__((__returns_nonnull__))
{
if (__n > (__detail::__int_limits<size_t>::max() / sizeof(_Tp)))
if (__n > (__gnu_cxx::__int_traits<size_t>::__max / sizeof(_Tp)))
_GLIBCXX_THROW_OR_ABORT(bad_array_new_length());
return static_cast<_Tp*>(_M_resource->allocate(__n * sizeof(_Tp),
alignof(_Tp)));
@ -194,7 +194,7 @@ namespace pmr
[[nodiscard]] _Up*
allocate_object(size_t __n = 1)
{
if ((__detail::__int_limits<size_t>::max() / sizeof(_Up)) < __n)
if ((__gnu_cxx::__int_traits<size_t>::__max / sizeof(_Up)) < __n)
_GLIBCXX_THROW_OR_ABORT(bad_array_new_length());
return static_cast<_Up*>(allocate_bytes(__n * sizeof(_Up),
alignof(_Up)));

View File

@ -40,9 +40,9 @@
#include <iosfwd>
#include <bits/char_traits.h>
#include <bits/functional_hash.h>
#include <bits/int_limits.h>
#include <bits/range_access.h>
#include <bits/ostream_insert.h>
#include <ext/numeric_traits.h>
namespace std _GLIBCXX_VISIBILITY(default)
{
@ -462,10 +462,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_S_compare(size_type __n1, size_type __n2) noexcept
{
const difference_type __diff = __n1 - __n2;
if (__diff > __detail::__int_limits<int>::max())
return __detail::__int_limits<int>::max();
if (__diff < __detail::__int_limits<int>::min())
return __detail::__int_limits<int>::min();
if (__diff > __gnu_cxx::__int_traits<int>::__max)
return __gnu_cxx::__int_traits<int>::__max;
if (__diff < __gnu_cxx::__int_traits<int>::__min)
return __gnu_cxx::__int_traits<int>::__min;
return static_cast<int>(__diff);
}

View File

@ -76,7 +76,7 @@
#include <initializer_list>
#if __cplusplus > 201703L
#include <bits/int_limits.h>
#include <ext/numeric_traits.h>
#endif
namespace std _GLIBCXX_VISIBILITY(default)
@ -456,16 +456,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
static_assert(__is_standard_integer<_Up>::value);
static_assert(__is_standard_integer<_Tp>::value);
using std::__detail::__int_limits;
using __gnu_cxx::__int_traits;
if constexpr (is_signed_v<_Tp> == is_signed_v<_Up>)
return __int_limits<_Up>::min() <= __t
&& __t <= __int_limits<_Up>::max();
return __int_traits<_Up>::__min <= __t
&& __t <= __int_traits<_Up>::__max;
else if constexpr (is_signed_v<_Tp>)
return __t >= 0
&& make_unsigned_t<_Tp>(__t) <= __int_limits<_Up>::max();
&& make_unsigned_t<_Tp>(__t) <= __int_traits<_Up>::__max;
else
return __t <= make_unsigned_t<_Up>(__int_limits<_Up>::max());
return __t <= make_unsigned_t<_Up>(__int_traits<_Up>::__max);
}
#endif // C++20
#endif // C++17