Re: [committed] libstdc++: Make __int128 meet integer-class requirements [PR 96042]

2020-08-24 Thread Jonathan Wakely via Gcc-patches
On Sat, 22 Aug 2020 at 16:01, Marc Glisse  wrote:
>
> On Sat, 22 Aug 2020, Jonathan Wakely via Gcc-patches wrote:
>
> > On Sat, 22 Aug 2020 at 13:13, Jonathan Wakely  wrote:
> >>
> >> On Sat, 22 Aug 2020 at 10:52, Marc Glisse wrote:
> >>> is there a particular reason to handle only __int128 this way, and not all
> >>> the non-standard integer types? It looks like it would be a bit simpler to
> >>> avoid a special case.
> >>
> >> I have no objection to doing it for all of them, it just wasn't
> >> necessary to solve the immediate problem that the library now uses
> >> __int128 even when integral<__int128> is false. (Hmm, or is size_t  an
> >> alias for __int20 on one arch, which would mean we do use it?)
> >
> > Oh I remember why I didn't do that now. I did actually want to do it
> > that way initially.
> >
> > The macros like __GLIBCXX_TYPE_INT_N_0 are not defined in strict mode,
> > so we have no generic way to name those types.
>
> IIRC, those macros were introduced specifically to help libstdc++. If
> libstdc++ wants them defined in different circumstances, it should be fine
> to change the condition from "!flag_iso || int_n_data[i].bitsize ==
> POINTER_SIZE" to whatever you need.

Hmm, IIRC the purpose of the patch series adding those macros was to
make it possible to use __int20 on a target that needed that. The
macros were added so that libstdc++ support could be enabled, to
support that target.

So IIRC the primary purpose was to improve that target, not to help
libstdc++. Allowing libstdc++ to use those types was just a necessary
step for improving the target. But I can check with DJ.


Re: [committed] libstdc++: Make __int128 meet integer-class requirements [PR 96042]

2020-08-22 Thread Marc Glisse

On Sat, 22 Aug 2020, Jonathan Wakely via Gcc-patches wrote:


On Sat, 22 Aug 2020 at 13:13, Jonathan Wakely  wrote:


On Sat, 22 Aug 2020 at 10:52, Marc Glisse wrote:

is there a particular reason to handle only __int128 this way, and not all
the non-standard integer types? It looks like it would be a bit simpler to
avoid a special case.


I have no objection to doing it for all of them, it just wasn't
necessary to solve the immediate problem that the library now uses
__int128 even when integral<__int128> is false. (Hmm, or is size_t  an
alias for __int20 on one arch, which would mean we do use it?)


Oh I remember why I didn't do that now. I did actually want to do it
that way initially.

The macros like __GLIBCXX_TYPE_INT_N_0 are not defined in strict mode,
so we have no generic way to name those types.


IIRC, those macros were introduced specifically to help libstdc++. If 
libstdc++ wants them defined in different circumstances, it should be fine 
to change the condition from "!flag_iso || int_n_data[i].bitsize == 
POINTER_SIZE" to whatever you need.


But now I understand why you did this, thanks.

--
Marc Glisse


Re: [committed] libstdc++: Make __int128 meet integer-class requirements [PR 96042]

2020-08-22 Thread Jonathan Wakely via Gcc-patches
On Sat, 22 Aug 2020 at 13:13, Jonathan Wakely  wrote:
>
> On Sat, 22 Aug 2020 at 10:52, Marc Glisse wrote:
> > is there a particular reason to handle only __int128 this way, and not all
> > the non-standard integer types? It looks like it would be a bit simpler to
> > avoid a special case.
>
> I have no objection to doing it for all of them, it just wasn't
> necessary to solve the immediate problem that the library now uses
> __int128 even when integral<__int128> is false. (Hmm, or is size_t  an
> alias for __int20 on one arch, which would mean we do use it?)

Oh I remember why I didn't do that now. I did actually want to do it
that way initially.

The macros like __GLIBCXX_TYPE_INT_N_0 are not defined in strict mode,
so we have no generic way to name those types. It's possible to
special case __int128 because I know its name, and I know the macro to
test for its existence (__SIZEOF_INT128__).

To do it for all the other possible non-standard types I'd need to
know all the possible names they can have. I know __int20 is one
possible name on one target, but I don't know of the others. Since
__int128 is the only one we're actually relying on, I just solved the
problem for signed/unsigned __int128.


Re: [committed] libstdc++: Make __int128 meet integer-class requirements [PR 96042]

2020-08-22 Thread Jonathan Wakely via Gcc-patches
On Sat, 22 Aug 2020 at 13:18, JeanHeyd Meneide wrote:
>
> On Sat, Aug 22, 2020 at 8:14 AM Jonathan Wakely via Gcc-patches
>  wrote:
> > I really wish WG14 would just fix the intmax_t mess so we can make
> > them integral types unconditionally.
>
> We're trying, but we're struggling to reach a good consensus. Almost
> nobody's fully agreeing on one /particular/ solution (there's roughly
> 3 ideas of what to do).

I liked Jens Gustedt's original proposal, it looked perfect to me. I
should catch up on WG14 mails to see what the other proposals are and
where the discussion is going.


Re: [committed] libstdc++: Make __int128 meet integer-class requirements [PR 96042]

2020-08-22 Thread JeanHeyd Meneide via Gcc-patches
On Sat, Aug 22, 2020 at 8:14 AM Jonathan Wakely via Gcc-patches
 wrote:
> I really wish WG14 would just fix the intmax_t mess so we can make
> them integral types unconditionally.

We're trying, but we're struggling to reach a good consensus. Almost
nobody's fully agreeing on one /particular/ solution (there's roughly
3 ideas of what to do).

But the papers are coming in and it's on our radar so maybe we can fix
it for C2x and then pass the solution on to WG21!


Re: [committed] libstdc++: Make __int128 meet integer-class requirements [PR 96042]

2020-08-22 Thread Jonathan Wakely via Gcc-patches
On Sat, 22 Aug 2020 at 10:52, Marc Glisse wrote:
> is there a particular reason to handle only __int128 this way, and not all
> the non-standard integer types? It looks like it would be a bit simpler to
> avoid a special case.

I have no objection to doing it for all of them, it just wasn't
necessary to solve the immediate problem that the library now uses
__int128 even when integral<__int128> is false. (Hmm, or is size_t  an
alias for __int20 on one arch, which would mean we do use it?)

In case you didn't see it, I've created https://gcc.gnu.org/PR96710 to
try and make our treatment of __int128 a bit more useful and
consistent. Even if it's not a standard integer type, it's definitely
an object type. And although it doesn't fit the standard's definition
of a scalar type, I think it should (I prefer to think of scalar types
as objects that aren't classes or arrays, rather than the list of
specific types in the standard that attempts to be exhaustive). What
we do for __int128 could/should be done for the other non-standard
integers.

I really wish WG14 would just fix the intmax_t mess so we can make
them integral types unconditionally.


Re: [committed] libstdc++: Make __int128 meet integer-class requirements [PR 96042]

2020-08-22 Thread Marc Glisse

On Wed, 19 Aug 2020, Jonathan Wakely via Gcc-patches wrote:


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.


Hello,

is there a particular reason to handle only __int128 this way, and not all 
the non-standard integer types? It looks like it would be a bit simpler to 
avoid a special case.


--
Marc Glisse


Re: [committed] libstdc++: Make __int128 meet integer-class requirements [PR 96042]

2020-08-20 Thread Jonathan Wakely via Gcc-patches

On 19/08/20 20:36 +0100, Jonathan Wakely wrote:

On 19/08/20 17:00 +0100, Jonathan Wakely wrote:

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):
Define.
* testsuite/std/ranges/iota/96042.cc: New test.


The attached patch is another change needed to support __int128 as an
integer-like type in strict mode.


And one more piece of __int128 support.

Tested x86_64-linux, -m32 and -m64. Committed to trunk.

I'll backport this to gcc-10 too.


commit 5e9ad288eb6fb366142b166e7985d16727b398e1
Author: Jonathan Wakely 
Date:   Thu Aug 20 19:41:15 2020

libstdc++: Make incrementable<__int128> satisfied in strict mode

This adds specializations of std::incrementable_traits so that 128-bit
integers are always considered incrementable (and therefore usable with
std::ranges::iota_view) even when they don't satisfy std::integral.

libstdc++-v3/ChangeLog:

* include/bits/iterator_concepts.h [__STRICT_ANSI__]
(incrementable_traits<__int128>): Define specialization.
(incrementable_traits): Likewise.
* testsuite/std/ranges/iota/96042.cc: Test iota_view with
__int128.

diff --git a/libstdc++-v3/include/bits/iterator_concepts.h b/libstdc++-v3/include/bits/iterator_concepts.h
index 5033f2bddc3..bd6660c5f22 100644
--- a/libstdc++-v3/include/bits/iterator_concepts.h
+++ b/libstdc++-v3/include/bits/iterator_concepts.h
@@ -173,6 +173,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	= make_signed_t() - std::declval<_Tp>())>;
 };
 
+#if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__
+  // __int128 is incrementable even if !integral<__int128>
+  template<>
+struct incrementable_traits<__int128>
+{ using difference_type = __int128; };
+
+  template<>
+struct incrementable_traits
+{ using difference_type = __int128; };
+#endif
+
   namespace __detail
   {
 // An iterator such that iterator_traits<_Iter> names a specialization
diff --git a/libstdc++-v3/testsuite/std/ranges/iota/96042.cc b/libstdc++-v3/testsuite/std/ranges/iota/96042.cc
index 6f5c8f61fd2..911663bc413 100644
--- a/libstdc++-v3/testsuite/std/ranges/iota/96042.cc
+++ b/libstdc++-v3/testsuite/std/ranges/iota/96042.cc
@@ -24,8 +24,13 @@ void
 test01()
 {
   // PR libstdc++/96042
-  using V = std::ranges::iota_view;
+  using V = std::ranges::iota_view;
+
+  // In strict -std=c++20 mode there is no integer wider than long long,
+  // so V's difference type is an integer-class type, [iterator.concept.winc].
+  // In practice this is either __int128 or __detail::__max_diff_type.
   using D = std::ranges::range_difference_t;
+  // Ensure that numeric_limits is correctly specialized for the type.
   using L = std::numeric_limits;
   static_assert( L::is_specialized );
   static_assert( L::is_signed );
@@ -37,3 +42,24 @@ test01()
   static_assert( L::max() == ~L::min() );
   static_assert( L::lowest() == L::min() );
 }
+
+#ifdef __SIZEOF_INT128__
+void
+test02()
+{
+  // When the target supports __int128 it can be used in iota_view
+  // even in strict mode where !integral<__int128>.
+  using V = std::ranges::iota_view<__int128, __int128>;
+  using D = std::ranges::range_difference_t; // __detail::__max_diff_type
+  using L = std::numeric_limits;
+  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::digits );
+  static_assert( L::digits10 == static_cast(L::digits * 0.30103) );
+  static_assert( L::min() == (D(1) << L::digits) );
+  static_assert( L::max() == ~L::min() );
+  static_assert( L::lowest() == L::min() );
+}
+#endif


Re: [committed] libstdc++: Make __int128 meet integer-class requirements [PR 96042]

2020-08-19 Thread Jonathan Wakely via Gcc-patches

On 19/08/20 17:00 +0100, Jonathan Wakely wrote:

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):
Define.
* testsuite/std/ranges/iota/96042.cc: New test.


The attached patch is another change needed to support __int128 as an
integer-like type in strict mode.

Tested x86_64-linux, -m32 and -m64. Committed to trunk.

I'll backport this to gcc-10 too.


commit e6e01618e83bcd9eb3a2b27df30ed87106a748b4
Author: Jonathan Wakely 
Date:   Wed Aug 19 20:36:10 2020

libstdc++: Make make-unsigned-like-t<__int128> work [PR 96042]

As well as ensuring that numeric_limits<__int128> is defined, we need to
ensure that make-unsigned-like-t and to-unsigned-like work correctly for
128-bit integers in strict mode. This ensures that a subrange created
from an iota_view's iterator and sentinel can represent its size.

Co-authored-by: Patrick Palka  

libstdc++-v3/ChangeLog:

2020-08-19  Jonathan Wakely  
Patrick Palka  

PR libstdc++/96042
* include/bits/range_access.h (__detail::__to_unsigned_like):
Do not use make_unsigned_t in the return type, as it can
result in an error before the integral constraint is checked.
[__STRICT_ANSI__]: Add overloads for 128-bit integer types.
(__detail::__make_unsigned_like_t): Define as the return type
of __to_unsigned_like.
* testsuite/std/ranges/subrange/96042.cc: New test.

diff --git a/libstdc++-v3/include/bits/range_access.h b/libstdc++-v3/include/bits/range_access.h
index 3eb1f2fd272..bafced31ea8 100644
--- a/libstdc++-v3/include/bits/range_access.h
+++ b/libstdc++-v3/include/bits/range_access.h
@@ -364,13 +364,23 @@ namespace ranges
 { return __max_size_type(__t); }
 
 template
-  constexpr make_unsigned_t<_Tp>
+  constexpr auto
   __to_unsigned_like(_Tp __t) noexcept
-  { return __t; }
+  { return static_cast>(__t); }
 
-template>
+#if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__
+constexpr unsigned __int128
+__to_unsigned_like(__int128 __t) noexcept
+{ return __t; }
+
+constexpr unsigned __int128
+__to_unsigned_like(unsigned __int128 __t) noexcept
+{ return __t; }
+#endif
+
+template
   using __make_unsigned_like_t
-	= conditional_t<_MaxDiff, __max_size_type, make_unsigned_t<_Tp>>;
+	= decltype(__detail::__to_unsigned_like(std::declval<_Tp>()));
 
 // Part of the constraints of ranges::borrowed_range
 template
diff --git a/libstdc++-v3/testsuite/std/ranges/subrange/96042.cc b/libstdc++-v3/testsuite/std/ranges/subrange/96042.cc
new file mode 100644
index 000..5826203f03c
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/ranges/subrange/96042.cc
@@ -0,0 +1,34 @@
+// 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
+// .
+
+// { dg-options "-std=c++20" }
+// { dg-do compile { target c++2a } }
+
+#include 
+
+constexpr bool
+test01()
+{
+  using I = unsigned long long;
+  // view with a difference type that doesn't fit in long long:
+  std::ranges::iota_view v(0,