public inbox for libstdc++@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] libstdc++: Avoid hard error in ranges::unique_copy [PR100770]
@ 2021-05-26 16:45 Patrick Palka
  2021-05-26 17:27 ` Tim Song
  2021-05-26 17:28 ` Jonathan Wakely
  0 siblings, 2 replies; 9+ messages in thread
From: Patrick Palka @ 2021-05-26 16:45 UTC (permalink / raw)
  To: gcc-patches; +Cc: libstdc++, Patrick Palka

When input_iterator<_Out> isn't satisfied, we need to avoid substituting
into iter_value_t<_Out> because the latter isn't necessarily
well-formed in that case.  To that end, this patch rewrites the
problematic condition in ranges::unique_copy into a nested requirement
which has the correct short-circuiting behavior.

Tested on x86_64-pc-linux-gnu, does this look OK?

libstdc++-v3/ChangeLog:

	* include/bits/ranges_algo.h (__unique_copy_fn::operator()):
	Rewrite the constexpr if conjunction into a nested requirement
	for sake of short-circuiting.
	* testsuite/25_algorithms/unique_copy/100770.cc: New test.
---
 libstdc++-v3/include/bits/ranges_algo.h       |  5 +--
 .../25_algorithms/unique_copy/100770.cc       | 33 +++++++++++++++++++
 2 files changed, 36 insertions(+), 2 deletions(-)
 create mode 100644 libstdc++-v3/testsuite/25_algorithms/unique_copy/100770.cc

diff --git a/libstdc++-v3/include/bits/ranges_algo.h b/libstdc++-v3/include/bits/ranges_algo.h
index cda3042c11f..ce4719d5642 100644
--- a/libstdc++-v3/include/bits/ranges_algo.h
+++ b/libstdc++-v3/include/bits/ranges_algo.h
@@ -1432,8 +1432,9 @@ namespace ranges
 		}
 	    return {__next, std::move(++__result)};
 	  }
-	else if constexpr (input_iterator<_Out>
-			   && same_as<iter_value_t<_Iter>, iter_value_t<_Out>>)
+	else if constexpr (requires { requires (input_iterator<_Out>
+						&& same_as<iter_value_t<_Iter>,
+							   iter_value_t<_Out>>); })
 	  {
 	    *__result = *__first;
 	    while (++__first != __last)
diff --git a/libstdc++-v3/testsuite/25_algorithms/unique_copy/100770.cc b/libstdc++-v3/testsuite/25_algorithms/unique_copy/100770.cc
new file mode 100644
index 00000000000..ea49eb46a18
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/unique_copy/100770.cc
@@ -0,0 +1,33 @@
+// Copyright (C) 2021 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=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+// PR libstdc++/100770
+
+#include <algorithm>
+#include <sstream>
+
+int main() {
+  std::istringstream str("42 42 42");
+  extern std::ostream out;
+  std::ranges::unique_copy(
+    std::istream_iterator<int>(str),
+    std::istream_iterator<int>(),
+    std::ostream_iterator<int>(out, " "));
+}
-- 
2.32.0.rc0


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] libstdc++: Avoid hard error in ranges::unique_copy [PR100770]
  2021-05-26 16:45 [PATCH] libstdc++: Avoid hard error in ranges::unique_copy [PR100770] Patrick Palka
@ 2021-05-26 17:27 ` Tim Song
  2021-05-26 18:43   ` Patrick Palka
  2021-05-26 17:28 ` Jonathan Wakely
  1 sibling, 1 reply; 9+ messages in thread
From: Tim Song @ 2021-05-26 17:27 UTC (permalink / raw)
  To: Patrick Palka; +Cc: gcc-patches, libstdc++

I noticed that output_iterator_wrapper still has a (non-void)
value_type. Perhaps we can get better coverage if it doesn't have one?
The existing tests should have caught this case with that change, at least.

On Wed, May 26, 2021 at 12:00 PM Patrick Palka via Libstdc++
<libstdc++@gcc.gnu.org> wrote:
>
> -       else if constexpr (input_iterator<_Out>
> -                          && same_as<iter_value_t<_Iter>, iter_value_t<_Out>>)
> +       else if constexpr (requires { requires (input_iterator<_Out>
> +                                               && same_as<iter_value_t<_Iter>,
> +                                                          iter_value_t<_Out>>); })

It's arguably cleaner to extract this into a concept which can then
also be used in the constraint.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] libstdc++: Avoid hard error in ranges::unique_copy [PR100770]
  2021-05-26 16:45 [PATCH] libstdc++: Avoid hard error in ranges::unique_copy [PR100770] Patrick Palka
  2021-05-26 17:27 ` Tim Song
@ 2021-05-26 17:28 ` Jonathan Wakely
  1 sibling, 0 replies; 9+ messages in thread
From: Jonathan Wakely @ 2021-05-26 17:28 UTC (permalink / raw)
  To: Patrick Palka; +Cc: gcc-patches, libstdc++

On Wed, 26 May 2021 at 18:00, Patrick Palka via Libstdc++
<libstdc++@gcc.gnu.org> wrote:
>
> When input_iterator<_Out> isn't satisfied, we need to avoid substituting
> into iter_value_t<_Out> because the latter isn't necessarily
> well-formed in that case.  To that end, this patch rewrites the
> problematic condition in ranges::unique_copy into a nested requirement
> which has the correct short-circuiting behavior.
>
> Tested on x86_64-pc-linux-gnu, does this look OK?

OK, thanks.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] libstdc++: Avoid hard error in ranges::unique_copy [PR100770]
  2021-05-26 17:27 ` Tim Song
@ 2021-05-26 18:43   ` Patrick Palka
  2021-05-26 19:07     ` Tim Song
  2021-05-26 19:55     ` Jonathan Wakely
  0 siblings, 2 replies; 9+ messages in thread
From: Patrick Palka @ 2021-05-26 18:43 UTC (permalink / raw)
  To: Tim Song; +Cc: Patrick Palka, gcc-patches, libstdc++

On Wed, 26 May 2021, Tim Song wrote:

> I noticed that output_iterator_wrapper still has a (non-void)
> value_type. Perhaps we can get better coverage if it doesn't have one?
> The existing tests should have caught this case with that change, at least.

Good point, and I guess it should be fine to make its pointer and
reference void as well.  I'm testing:

--- a/libstdc++-v3/testsuite/util/testsuite_iterators.h
+++ b/libstdc++-v3/testsuite/util/testsuite_iterators.h
@@ -122,7 +122,7 @@ namespace __gnu_test
    */
   template<class T>
   struct output_iterator_wrapper
-  : public std::iterator<std::output_iterator_tag, T, std::ptrdiff_t, T*, T&>
+  : public std::iterator<std::output_iterator_tag, void, std::ptrdiff_t, void, void>
   {
   protected:
     output_iterator_wrapper() : ptr(0), SharedInfo(0)

> 
> On Wed, May 26, 2021 at 12:00 PM Patrick Palka via Libstdc++
> <libstdc++@gcc.gnu.org> wrote:
> >
> > -       else if constexpr (input_iterator<_Out>
> > -                          && same_as<iter_value_t<_Iter>, iter_value_t<_Out>>)
> > +       else if constexpr (requires { requires (input_iterator<_Out>
> > +                                               && same_as<iter_value_t<_Iter>,
> > +                                                          iter_value_t<_Out>>); })
> 
> It's arguably cleaner to extract this into a concept which can then
> also be used in the constraint.

Sounds good, though I'm not sure what name to give to this relatively
ad-hoc set of requirements.  Any suggestions? :)


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] libstdc++: Avoid hard error in ranges::unique_copy [PR100770]
  2021-05-26 18:43   ` Patrick Palka
@ 2021-05-26 19:07     ` Tim Song
  2021-05-27 13:50       ` Patrick Palka
  2021-05-26 19:55     ` Jonathan Wakely
  1 sibling, 1 reply; 9+ messages in thread
From: Tim Song @ 2021-05-26 19:07 UTC (permalink / raw)
  To: Patrick Palka; +Cc: gcc-patches, libstdc++

On Wed, May 26, 2021 at 1:43 PM Patrick Palka <ppalka@redhat.com> wrote:
>
> On Wed, 26 May 2021, Tim Song wrote:
> >
> > On Wed, May 26, 2021 at 12:00 PM Patrick Palka via Libstdc++
> > <libstdc++@gcc.gnu.org> wrote:
> > >
> > > -       else if constexpr (input_iterator<_Out>
> > > -                          && same_as<iter_value_t<_Iter>, iter_value_t<_Out>>)
> > > +       else if constexpr (requires { requires (input_iterator<_Out>
> > > +                                               && same_as<iter_value_t<_Iter>,
> > > +                                                          iter_value_t<_Out>>); })
> >
> > It's arguably cleaner to extract this into a concept which can then
> > also be used in the constraint.
>
> Sounds good, though I'm not sure what name to give to this relatively
> ad-hoc set of requirements.  Any suggestions? :)
>

Something along the lines of "__can_reread_output", perhaps?

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] libstdc++: Avoid hard error in ranges::unique_copy [PR100770]
  2021-05-26 18:43   ` Patrick Palka
  2021-05-26 19:07     ` Tim Song
@ 2021-05-26 19:55     ` Jonathan Wakely
  2021-05-27  0:38       ` Tim Song
  1 sibling, 1 reply; 9+ messages in thread
From: Jonathan Wakely @ 2021-05-26 19:55 UTC (permalink / raw)
  To: Patrick Palka; +Cc: Tim Song, libstdc++, gcc-patches

On Wed, 26 May 2021 at 20:11, Patrick Palka via Libstdc++
<libstdc++@gcc.gnu.org> wrote:
>
> On Wed, 26 May 2021, Tim Song wrote:
>
> > I noticed that output_iterator_wrapper still has a (non-void)
> > value_type. Perhaps we can get better coverage if it doesn't have one?
> > The existing tests should have caught this case with that change, at least.
>
> Good point, and I guess it should be fine to make its pointer and
> reference void as well.  I'm testing:

Defining difference_type as void is also OK.

Before C++20 output iterators could define all of them as void. In
C++20 defining pointer as void means it doesn't support operator->(),
so either way it's OK for our output_iterator_wrapper.



> --- a/libstdc++-v3/testsuite/util/testsuite_iterators.h
> +++ b/libstdc++-v3/testsuite/util/testsuite_iterators.h
> @@ -122,7 +122,7 @@ namespace __gnu_test
>     */
>    template<class T>
>    struct output_iterator_wrapper
> -  : public std::iterator<std::output_iterator_tag, T, std::ptrdiff_t, T*, T&>
> +  : public std::iterator<std::output_iterator_tag, void, std::ptrdiff_t, void, void>
>    {
>    protected:
>      output_iterator_wrapper() : ptr(0), SharedInfo(0)
>
> >
> > On Wed, May 26, 2021 at 12:00 PM Patrick Palka via Libstdc++
> > <libstdc++@gcc.gnu.org> wrote:
> > >
> > > -       else if constexpr (input_iterator<_Out>
> > > -                          && same_as<iter_value_t<_Iter>, iter_value_t<_Out>>)
> > > +       else if constexpr (requires { requires (input_iterator<_Out>
> > > +                                               && same_as<iter_value_t<_Iter>,
> > > +                                                          iter_value_t<_Out>>); })
> >
> > It's arguably cleaner to extract this into a concept which can then
> > also be used in the constraint.
>
> Sounds good, though I'm not sure what name to give to this relatively
> ad-hoc set of requirements.  Any suggestions? :)
>

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] libstdc++: Avoid hard error in ranges::unique_copy [PR100770]
  2021-05-26 19:55     ` Jonathan Wakely
@ 2021-05-27  0:38       ` Tim Song
  0 siblings, 0 replies; 9+ messages in thread
From: Tim Song @ 2021-05-27  0:38 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: Patrick Palka, libstdc++, gcc-patches

On Wed, May 26, 2021 at 2:55 PM Jonathan Wakely <jwakely.gcc@gmail.com> wrote:
>
> On Wed, 26 May 2021 at 20:11, Patrick Palka via Libstdc++
> <libstdc++@gcc.gnu.org> wrote:
> >
> > On Wed, 26 May 2021, Tim Song wrote:
> >
> > > I noticed that output_iterator_wrapper still has a (non-void)
> > > value_type. Perhaps we can get better coverage if it doesn't have one?
> > > The existing tests should have caught this case with that change, at least.
> >
> > Good point, and I guess it should be fine to make its pointer and
> > reference void as well.  I'm testing:
>
> Defining difference_type as void is also OK.

C++20 requires (new-style) output iterators to have a valid
difference_type too (that requirement comes from
weakly_incrementable).

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] libstdc++: Avoid hard error in ranges::unique_copy [PR100770]
  2021-05-26 19:07     ` Tim Song
@ 2021-05-27 13:50       ` Patrick Palka
  2021-06-03 11:54         ` Jonathan Wakely
  0 siblings, 1 reply; 9+ messages in thread
From: Patrick Palka @ 2021-05-27 13:50 UTC (permalink / raw)
  To: Tim Song; +Cc: Patrick Palka, gcc-patches, libstdc++

On Wed, 26 May 2021, Tim Song wrote:

> On Wed, May 26, 2021 at 1:43 PM Patrick Palka <ppalka@redhat.com> wrote:
> >
> > On Wed, 26 May 2021, Tim Song wrote:
> > >
> > > On Wed, May 26, 2021 at 12:00 PM Patrick Palka via Libstdc++
> > > <libstdc++@gcc.gnu.org> wrote:
> > > >
> > > > -       else if constexpr (input_iterator<_Out>
> > > > -                          && same_as<iter_value_t<_Iter>, iter_value_t<_Out>>)
> > > > +       else if constexpr (requires { requires (input_iterator<_Out>
> > > > +                                               && same_as<iter_value_t<_Iter>,
> > > > +                                                          iter_value_t<_Out>>); })
> > >
> > > It's arguably cleaner to extract this into a concept which can then
> > > also be used in the constraint.
> >
> > Sounds good, though I'm not sure what name to give to this relatively
> > ad-hoc set of requirements.  Any suggestions? :)
> >
> 
> Something along the lines of "__can_reread_output", perhaps?

Works for me.  Here's v2, which factors out the condition into a concept
and defines the value_type, pointer and reference of output_iterator_wrapper
to void but leaves alone its difference_type.  Tested on x86_64-pc-linux-gnu.

-- >8 --

Subject: [PATCH] libstdc++: Avoid hard error in ranges::unique_copy [PR100770]

Here, in the constexpr if condition within unique_copy, when
input_iterator<_Out> isn't satisfied we must avoid substituting into
iter_value_t<_Out> because the latter isn't necessarily well-formed in
this case.  To that end, this patch factors out the condition into a
concept and uses it throughout.

This patch also makes the definition of our testsuite
output_iterator_wrapper more minimal by defining its value_type, pointer
and reference member types to void.  This means our existing tests for
unique_copy already exercise the fix for this bug, so we don't need
to add another test.  The only other fallout of this testsuite iterator
change appears in std/ranges/range.cc, where the use of range_value_t
on a test_output_range is now ill-formed.

libstdc++-v3/ChangeLog:

	* include/bits/ranges_algo.h (__detail::__can_reread_output):
	Factor out this concept from ...
	(__unique_copy_fn::operator()): ... here.  Use the concept
	throughout.
	* testsuite/std/ranges/range.cc: Remove now ill-formed use
	of range_value_t on an output_range.
	* testsuite/util/testsuite_iterators.h (output_iterator_wrapper):
	Define value_type, pointer and reference member types to void.
---
 libstdc++-v3/include/bits/ranges_algo.h          | 16 ++++++++++------
 libstdc++-v3/testsuite/std/ranges/range.cc       |  3 ---
 .../testsuite/util/testsuite_iterators.h         |  2 +-
 3 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/libstdc++-v3/include/bits/ranges_algo.h b/libstdc++-v3/include/bits/ranges_algo.h
index cda3042c11f..ecf1378742d 100644
--- a/libstdc++-v3/include/bits/ranges_algo.h
+++ b/libstdc++-v3/include/bits/ranges_algo.h
@@ -1396,6 +1396,13 @@ namespace ranges
 
   inline constexpr __unique_fn unique{};
 
+  namespace __detail
+  {
+    template<typename _Out, typename _Tp>
+      concept __can_reread_output = input_iterator<_Out>
+	&& same_as<_Tp, iter_value_t<_Out>>;
+  }
+
   template<typename _Iter, typename _Out>
     using unique_copy_result = in_out_result<_Iter, _Out>;
 
@@ -1407,8 +1414,7 @@ namespace ranges
 	       projected<_Iter, _Proj>> _Comp = ranges::equal_to>
       requires indirectly_copyable<_Iter, _Out>
 	&& (forward_iterator<_Iter>
-	    || (input_iterator<_Out>
-		&& same_as<iter_value_t<_Iter>, iter_value_t<_Out>>)
+	    || __detail::__can_reread_output<_Out, iter_value_t<_Iter>>
 	    || indirectly_copyable_storable<_Iter, _Out>)
       constexpr unique_copy_result<_Iter, _Out>
       operator()(_Iter __first, _Sent __last, _Out __result,
@@ -1432,8 +1438,7 @@ namespace ranges
 		}
 	    return {__next, std::move(++__result)};
 	  }
-	else if constexpr (input_iterator<_Out>
-			   && same_as<iter_value_t<_Iter>, iter_value_t<_Out>>)
+	else if constexpr (__detail::__can_reread_output<_Out, iter_value_t<_Iter>>)
 	  {
 	    *__result = *__first;
 	    while (++__first != __last)
@@ -1467,8 +1472,7 @@ namespace ranges
 	       projected<iterator_t<_Range>, _Proj>> _Comp = ranges::equal_to>
       requires indirectly_copyable<iterator_t<_Range>, _Out>
 	&& (forward_iterator<iterator_t<_Range>>
-	    || (input_iterator<_Out>
-		&& same_as<range_value_t<_Range>, iter_value_t<_Out>>)
+	    || __detail::__can_reread_output<_Out, range_value_t<_Range>>
 	    || indirectly_copyable_storable<iterator_t<_Range>, _Out>)
       constexpr unique_copy_result<borrowed_iterator_t<_Range>, _Out>
       operator()(_Range&& __r, _Out __result,
diff --git a/libstdc++-v3/testsuite/std/ranges/range.cc b/libstdc++-v3/testsuite/std/ranges/range.cc
index 795aca472e5..aa29af471a4 100644
--- a/libstdc++-v3/testsuite/std/ranges/range.cc
+++ b/libstdc++-v3/testsuite/std/ranges/range.cc
@@ -75,9 +75,6 @@ static_assert( same_as<std::ranges::range_difference_t<C>,
 static_assert( same_as<std::ranges::range_difference_t<O>,
 		       std::ptrdiff_t> );
 
-static_assert( same_as<std::ranges::range_value_t<O>,
-		       char> );
-
 static_assert( same_as<std::ranges::range_reference_t<I>,
 		       char&> );
 static_assert( same_as<std::ranges::range_reference_t<O>,
diff --git a/libstdc++-v3/testsuite/util/testsuite_iterators.h b/libstdc++-v3/testsuite/util/testsuite_iterators.h
index 67da06b8482..4e668d648f2 100644
--- a/libstdc++-v3/testsuite/util/testsuite_iterators.h
+++ b/libstdc++-v3/testsuite/util/testsuite_iterators.h
@@ -122,7 +122,7 @@ namespace __gnu_test
    */
   template<class T>
   struct output_iterator_wrapper
-  : public std::iterator<std::output_iterator_tag, T, std::ptrdiff_t, T*, T&>
+  : public std::iterator<std::output_iterator_tag, void, std::ptrdiff_t, void, void>
   {
   protected:
     output_iterator_wrapper() : ptr(0), SharedInfo(0)
-- 
2.32.0.rc0


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] libstdc++: Avoid hard error in ranges::unique_copy [PR100770]
  2021-05-27 13:50       ` Patrick Palka
@ 2021-06-03 11:54         ` Jonathan Wakely
  0 siblings, 0 replies; 9+ messages in thread
From: Jonathan Wakely @ 2021-06-03 11:54 UTC (permalink / raw)
  To: Patrick Palka; +Cc: Tim Song, libstdc++, gcc-patches

On 27/05/21 09:50 -0400, Patrick Palka via Libstdc++ wrote:
>On Wed, 26 May 2021, Tim Song wrote:
>
>> On Wed, May 26, 2021 at 1:43 PM Patrick Palka <ppalka@redhat.com> wrote:
>> >
>> > On Wed, 26 May 2021, Tim Song wrote:
>> > >
>> > > On Wed, May 26, 2021 at 12:00 PM Patrick Palka via Libstdc++
>> > > <libstdc++@gcc.gnu.org> wrote:
>> > > >
>> > > > -       else if constexpr (input_iterator<_Out>
>> > > > -                          && same_as<iter_value_t<_Iter>, iter_value_t<_Out>>)
>> > > > +       else if constexpr (requires { requires (input_iterator<_Out>
>> > > > +                                               && same_as<iter_value_t<_Iter>,
>> > > > +                                                          iter_value_t<_Out>>); })
>> > >
>> > > It's arguably cleaner to extract this into a concept which can then
>> > > also be used in the constraint.
>> >
>> > Sounds good, though I'm not sure what name to give to this relatively
>> > ad-hoc set of requirements.  Any suggestions? :)
>> >
>>
>> Something along the lines of "__can_reread_output", perhaps?
>
>Works for me.  Here's v2, which factors out the condition into a concept
>and defines the value_type, pointer and reference of output_iterator_wrapper
>to void but leaves alone its difference_type.  Tested on x86_64-pc-linux-gnu.

OK for 10, 11 and trunk, thanks.

>-- >8 --
>
>Subject: [PATCH] libstdc++: Avoid hard error in ranges::unique_copy [PR100770]
>
>Here, in the constexpr if condition within unique_copy, when
>input_iterator<_Out> isn't satisfied we must avoid substituting into
>iter_value_t<_Out> because the latter isn't necessarily well-formed in
>this case.  To that end, this patch factors out the condition into a
>concept and uses it throughout.
>
>This patch also makes the definition of our testsuite
>output_iterator_wrapper more minimal by defining its value_type, pointer
>and reference member types to void.  This means our existing tests for
>unique_copy already exercise the fix for this bug, so we don't need
>to add another test.  The only other fallout of this testsuite iterator
>change appears in std/ranges/range.cc, where the use of range_value_t
>on a test_output_range is now ill-formed.
>
>libstdc++-v3/ChangeLog:
>
>	* include/bits/ranges_algo.h (__detail::__can_reread_output):
>	Factor out this concept from ...
>	(__unique_copy_fn::operator()): ... here.  Use the concept
>	throughout.
>	* testsuite/std/ranges/range.cc: Remove now ill-formed use
>	of range_value_t on an output_range.
>	* testsuite/util/testsuite_iterators.h (output_iterator_wrapper):
>	Define value_type, pointer and reference member types to void.
>---
> libstdc++-v3/include/bits/ranges_algo.h          | 16 ++++++++++------
> libstdc++-v3/testsuite/std/ranges/range.cc       |  3 ---
> .../testsuite/util/testsuite_iterators.h         |  2 +-
> 3 files changed, 11 insertions(+), 10 deletions(-)
>
>diff --git a/libstdc++-v3/include/bits/ranges_algo.h b/libstdc++-v3/include/bits/ranges_algo.h
>index cda3042c11f..ecf1378742d 100644
>--- a/libstdc++-v3/include/bits/ranges_algo.h
>+++ b/libstdc++-v3/include/bits/ranges_algo.h
>@@ -1396,6 +1396,13 @@ namespace ranges
>
>   inline constexpr __unique_fn unique{};
>
>+  namespace __detail
>+  {
>+    template<typename _Out, typename _Tp>
>+      concept __can_reread_output = input_iterator<_Out>
>+	&& same_as<_Tp, iter_value_t<_Out>>;
>+  }
>+
>   template<typename _Iter, typename _Out>
>     using unique_copy_result = in_out_result<_Iter, _Out>;
>
>@@ -1407,8 +1414,7 @@ namespace ranges
> 	       projected<_Iter, _Proj>> _Comp = ranges::equal_to>
>       requires indirectly_copyable<_Iter, _Out>
> 	&& (forward_iterator<_Iter>
>-	    || (input_iterator<_Out>
>-		&& same_as<iter_value_t<_Iter>, iter_value_t<_Out>>)
>+	    || __detail::__can_reread_output<_Out, iter_value_t<_Iter>>
> 	    || indirectly_copyable_storable<_Iter, _Out>)
>       constexpr unique_copy_result<_Iter, _Out>
>       operator()(_Iter __first, _Sent __last, _Out __result,
>@@ -1432,8 +1438,7 @@ namespace ranges
> 		}
> 	    return {__next, std::move(++__result)};
> 	  }
>-	else if constexpr (input_iterator<_Out>
>-			   && same_as<iter_value_t<_Iter>, iter_value_t<_Out>>)
>+	else if constexpr (__detail::__can_reread_output<_Out, iter_value_t<_Iter>>)
> 	  {
> 	    *__result = *__first;
> 	    while (++__first != __last)
>@@ -1467,8 +1472,7 @@ namespace ranges
> 	       projected<iterator_t<_Range>, _Proj>> _Comp = ranges::equal_to>
>       requires indirectly_copyable<iterator_t<_Range>, _Out>
> 	&& (forward_iterator<iterator_t<_Range>>
>-	    || (input_iterator<_Out>
>-		&& same_as<range_value_t<_Range>, iter_value_t<_Out>>)
>+	    || __detail::__can_reread_output<_Out, range_value_t<_Range>>
> 	    || indirectly_copyable_storable<iterator_t<_Range>, _Out>)
>       constexpr unique_copy_result<borrowed_iterator_t<_Range>, _Out>
>       operator()(_Range&& __r, _Out __result,
>diff --git a/libstdc++-v3/testsuite/std/ranges/range.cc b/libstdc++-v3/testsuite/std/ranges/range.cc
>index 795aca472e5..aa29af471a4 100644
>--- a/libstdc++-v3/testsuite/std/ranges/range.cc
>+++ b/libstdc++-v3/testsuite/std/ranges/range.cc
>@@ -75,9 +75,6 @@ static_assert( same_as<std::ranges::range_difference_t<C>,
> static_assert( same_as<std::ranges::range_difference_t<O>,
> 		       std::ptrdiff_t> );
>
>-static_assert( same_as<std::ranges::range_value_t<O>,
>-		       char> );
>-
> static_assert( same_as<std::ranges::range_reference_t<I>,
> 		       char&> );
> static_assert( same_as<std::ranges::range_reference_t<O>,
>diff --git a/libstdc++-v3/testsuite/util/testsuite_iterators.h b/libstdc++-v3/testsuite/util/testsuite_iterators.h
>index 67da06b8482..4e668d648f2 100644
>--- a/libstdc++-v3/testsuite/util/testsuite_iterators.h
>+++ b/libstdc++-v3/testsuite/util/testsuite_iterators.h
>@@ -122,7 +122,7 @@ namespace __gnu_test
>    */
>   template<class T>
>   struct output_iterator_wrapper
>-  : public std::iterator<std::output_iterator_tag, T, std::ptrdiff_t, T*, T&>
>+  : public std::iterator<std::output_iterator_tag, void, std::ptrdiff_t, void, void>
>   {
>   protected:
>     output_iterator_wrapper() : ptr(0), SharedInfo(0)
>-- 
>2.32.0.rc0
>


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2021-06-03 11:54 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-26 16:45 [PATCH] libstdc++: Avoid hard error in ranges::unique_copy [PR100770] Patrick Palka
2021-05-26 17:27 ` Tim Song
2021-05-26 18:43   ` Patrick Palka
2021-05-26 19:07     ` Tim Song
2021-05-27 13:50       ` Patrick Palka
2021-06-03 11:54         ` Jonathan Wakely
2021-05-26 19:55     ` Jonathan Wakely
2021-05-27  0:38       ` Tim Song
2021-05-26 17:28 ` Jonathan Wakely

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).