Commit 2a0f6c61 by Jonathan Wakely

libstdc++: Fix weakly_incrementable to allow __int128 (PR 93267)

The __iota_diff_t alias can be the type __int128, but that does not
satisfy the signed_integral and __is_signed_integer_like concepts when
__STRICT_ANSI__ is defined (which is true for -std=c++2a).

Because weakly_incrementable is defined in terms of signed_integral, it
is not satisfied by __int128, which means iota_view's iterator doesn't
always satisfy input_or_output_iterator and so iota_view is not always a
range.

The solution is to define __max_size_type and __max_diff_type using
__int128, so that __is_signed_integer_like allows __int128, and then
make weakly_incrementable use __is_signed_integer_like instead of
signed_integral.

	PR libstdc++/93267
	* include/bits/iterator_concepts.h (__max_diff_type, __max_size_type):
	Move here from <bits/range_access.h> and define using __int128 when
	available.
	(__is_integer_like, __is_signed_integer_like): Move here from
	<bits/range_access.h>.
	(weakly_incrementable): Use __is_signed_integer_like.
	* include/bits/range_access.h (__max_diff_type, __max_size_type)
	(__is_integer_like, __is_signed_integer_like): Move to
	<bits/iterator_concepts.h>.
	(__make_unsigned_like_t): Move here from <ranges>.
	* include/std/ranges (__make_unsigned_like_t): Move to
	<bits/range_access.h>.
	(iota_view): Replace using-directive with using-declarations.
	* testsuite/std/ranges/iota/93267.cc: New test.
	* testsuite/std/ranges/iota_view.cc: Move to new 'iota' sub-directory.
parent ea1966e8
2020-01-15 Jonathan Wakely <jwakely@redhat.com>
PR libstdc++/93267
* include/bits/iterator_concepts.h (__max_diff_type, __max_size_type):
Move here from <bits/range_access.h> and define using __int128 when
available.
(__is_integer_like, __is_signed_integer_like): Move here from
<bits/range_access.h>.
(weakly_incrementable): Use __is_signed_integer_like.
* include/bits/range_access.h (__max_diff_type, __max_size_type)
(__is_integer_like, __is_signed_integer_like): Move to
<bits/iterator_concepts.h>.
(__make_unsigned_like_t): Move here from <ranges>.
* include/std/ranges (__make_unsigned_like_t): Move to
<bits/range_access.h>.
(iota_view): Replace using-directive with using-declarations.
* testsuite/std/ranges/iota/93267.cc: New test.
* testsuite/std/ranges/iota_view.cc: Move to new 'iota' sub-directory.
2020-01-13 Jonathan Wakely <jwakely@redhat.com> 2020-01-13 Jonathan Wakely <jwakely@redhat.com>
PR libstdc++/93244 PR libstdc++/93244
......
...@@ -492,6 +492,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -492,6 +492,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
= std::forward<_Tp>(__t); = std::forward<_Tp>(__t);
}; };
namespace ranges::__detail
{
#if __SIZEOF_INT128__
using __max_diff_type = __int128;
using __max_size_type = unsigned __int128;
#else
using __max_diff_type = long long;
using __max_size_type = unsigned long long;
#endif
template<typename _Tp>
concept __is_integer_like = integral<_Tp>
|| same_as<_Tp, __max_diff_type> || same_as<_Tp, __max_size_type>;
template<typename _Tp>
concept __is_signed_integer_like = signed_integral<_Tp>
|| same_as<_Tp, __max_diff_type>;
} // namespace ranges::__detail
namespace __detail { using ranges::__detail::__is_signed_integer_like; }
/// Requirements on types that can be incremented with ++. /// Requirements on types that can be incremented with ++.
template<typename _Iter> template<typename _Iter>
concept weakly_incrementable = default_initializable<_Iter> concept weakly_incrementable = default_initializable<_Iter>
...@@ -499,7 +521,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -499,7 +521,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
&& requires(_Iter __i) && requires(_Iter __i)
{ {
typename iter_difference_t<_Iter>; typename iter_difference_t<_Iter>;
requires signed_integral<iter_difference_t<_Iter>>; requires __detail::__is_signed_integer_like<iter_difference_t<_Iter>>;
{ ++__i } -> same_as<_Iter&>; { ++__i } -> same_as<_Iter&>;
__i++; __i++;
}; };
......
...@@ -347,22 +347,15 @@ namespace ranges ...@@ -347,22 +347,15 @@ namespace ranges
namespace __detail namespace __detail
{ {
using __max_diff_type = long long;
using __max_size_type = unsigned long long;
template<typename _Tp>
concept __is_integer_like = integral<_Tp>
|| same_as<_Tp, __max_diff_type> || same_as<_Tp, __max_size_type>;
template<typename _Tp>
concept __is_signed_integer_like = signed_integral<_Tp>
|| same_as<_Tp, __max_diff_type>;
template<integral _Tp> template<integral _Tp>
constexpr make_unsigned_t<_Tp> constexpr make_unsigned_t<_Tp>
__to_unsigned_like(_Tp __t) noexcept __to_unsigned_like(_Tp __t) noexcept
{ return __t; } { return __t; }
template<typename _Tp, bool _MaxDiff = same_as<_Tp, __max_diff_type>>
using __make_unsigned_like_t
= conditional_t<_MaxDiff, __max_size_type, make_unsigned_t<_Tp>>;
// Part of the constraints of ranges::safe_range // Part of the constraints of ranges::safe_range
template<typename _Tp> template<typename _Tp>
concept __maybe_safe_range concept __maybe_safe_range
......
...@@ -244,10 +244,6 @@ namespace ranges ...@@ -244,10 +244,6 @@ namespace ranges
= !range<_Tp> && __pair_like<_Tp> = !range<_Tp> && __pair_like<_Tp>
&& sentinel_for<tuple_element_t<1, _Tp>, tuple_element_t<0, _Tp>>; && sentinel_for<tuple_element_t<1, _Tp>, tuple_element_t<0, _Tp>>;
template<typename _Tp, bool _MaxDiff = same_as<_Tp, __max_diff_type>>
using __make_unsigned_like_t
= conditional_t<_MaxDiff, __max_size_type, make_unsigned_t<_Tp>>;
} // namespace __detail } // namespace __detail
enum class subrange_kind : bool { unsized, sized }; enum class subrange_kind : bool { unsized, sized };
...@@ -717,7 +713,8 @@ namespace ranges ...@@ -717,7 +713,8 @@ namespace ranges
constexpr _Iterator& constexpr _Iterator&
operator+=(difference_type __n) requires __detail::__advanceable<_Winc> operator+=(difference_type __n) requires __detail::__advanceable<_Winc>
{ {
using namespace __detail; using __detail::__is_integer_like;
using __detail::__is_signed_integer_like;
if constexpr (__is_integer_like<_Winc> if constexpr (__is_integer_like<_Winc>
&& !__is_signed_integer_like<_Winc>) && !__is_signed_integer_like<_Winc>)
{ {
...@@ -734,7 +731,8 @@ namespace ranges ...@@ -734,7 +731,8 @@ namespace ranges
constexpr _Iterator& constexpr _Iterator&
operator-=(difference_type __n) requires __detail::__advanceable<_Winc> operator-=(difference_type __n) requires __detail::__advanceable<_Winc>
{ {
using namespace __detail; using __detail::__is_integer_like;
using __detail::__is_signed_integer_like;
if constexpr (__is_integer_like<_Winc> if constexpr (__is_integer_like<_Winc>
&& !__is_signed_integer_like<_Winc>) && !__is_signed_integer_like<_Winc>)
{ {
...@@ -804,7 +802,8 @@ namespace ranges ...@@ -804,7 +802,8 @@ namespace ranges
operator-(const _Iterator& __x, const _Iterator& __y) operator-(const _Iterator& __x, const _Iterator& __y)
requires __detail::__advanceable<_Winc> requires __detail::__advanceable<_Winc>
{ {
using namespace __detail; using __detail::__is_integer_like;
using __detail::__is_signed_integer_like;
using _Dt = difference_type; using _Dt = difference_type;
if constexpr (__is_integer_like<_Winc>) if constexpr (__is_integer_like<_Winc>)
{ {
...@@ -892,7 +891,8 @@ namespace ranges ...@@ -892,7 +891,8 @@ namespace ranges
|| (integral<_Winc> && integral<_Bound>) || (integral<_Winc> && integral<_Bound>)
|| sized_sentinel_for<_Bound, _Winc> || sized_sentinel_for<_Bound, _Winc>
{ {
using namespace __detail; using __detail::__is_integer_like;
using __detail::__to_unsigned_like;
if constexpr (__is_integer_like<_Winc> && __is_integer_like<_Bound>) if constexpr (__is_integer_like<_Winc> && __is_integer_like<_Bound>)
return (_M_value < 0) return (_M_value < 0)
? ((_M_bound < 0) ? ((_M_bound < 0)
......
// 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++/93267
std::ranges::iota_view<long long, int> i(0, 3);
static_assert( std::weakly_incrementable<decltype(i.begin())> );
(void) std::ranges::begin(i);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment