Commit 05779e2c by Patrick Palka

libstdc++: Fix use of is_nothrow_assignable_v in <bits/ranges_uninitialized.h>

We are passing a value type as the first argument to is_nothrow_assignable_v,
but the result of that is inevitably false.  Since this predicate is a part of
the condition that guards the corresponding optimizations for these algorithms,
this bug means these optimizations are never used.  We should be passing a
reference type to is_nothrow_assignable_v instead.

libstdc++-v3/ChangeLog:

	* include/bits/ranges_uninitialized.h
	(uninitialized_copy_fn::operator()): Pass a reference type as the first
	argument to is_nothrow_assignable_v.
	(uninitialized_copy_fn::operator()): Likewise.
	(uninitialized_move_fn::operator()): Likewise.  Return an in_out_result
	with the input iterator stripped of its move_iterator.
	(uninitialized_move_n_fn::operator()): Likewise.
	(uninitialized_fill_fn::operator()): Pass a reference type as the first
	argument to is_nothrow_assignable_v.
	(uninitialized_fill_n_fn::operator()): Likewise.
parent 7f327e87
2020-03-04 Patrick Palka <ppalka@redhat.com>
* include/bits/ranges_uninitialized.h
(uninitialized_copy_fn::operator()): Pass a reference type as the first
argument to is_nothrow_assignable_v.
(uninitialized_copy_fn::operator()): Likewise.
(uninitialized_move_fn::operator()): Likewise. Return an in_out_result
with the input iterator stripped of its move_iterator.
(uninitialized_move_n_fn::operator()): Likewise.
(uninitialized_fill_fn::operator()): Pass a reference type as the first
argument to is_nothrow_assignable_v.
(uninitialized_fill_n_fn::operator()): Likewise.
2020-03-03 Jonathan Wakely <jwakely@redhat.com> 2020-03-03 Jonathan Wakely <jwakely@redhat.com>
PR libstdc++/94013 PR libstdc++/94013
......
...@@ -269,7 +269,7 @@ namespace ranges ...@@ -269,7 +269,7 @@ namespace ranges
if constexpr (sized_sentinel_for<_ISent, _Iter> if constexpr (sized_sentinel_for<_ISent, _Iter>
&& sized_sentinel_for<_OSent, _Out> && sized_sentinel_for<_OSent, _Out>
&& is_trivial_v<_OutType> && is_trivial_v<_OutType>
&& is_nothrow_assignable_v<_OutType, && is_nothrow_assignable_v<_OutType&,
iter_reference_t<_Iter>>) iter_reference_t<_Iter>>)
{ {
auto __d1 = ranges::distance(__ifirst, __ilast); auto __d1 = ranges::distance(__ifirst, __ilast);
...@@ -316,7 +316,7 @@ namespace ranges ...@@ -316,7 +316,7 @@ namespace ranges
using _OutType = remove_reference_t<iter_reference_t<_Out>>; using _OutType = remove_reference_t<iter_reference_t<_Out>>;
if constexpr (sized_sentinel_for<_Sent, _Out> if constexpr (sized_sentinel_for<_Sent, _Out>
&& is_trivial_v<_OutType> && is_trivial_v<_OutType>
&& is_nothrow_assignable_v<_OutType, && is_nothrow_assignable_v<_OutType&,
iter_reference_t<_Iter>>) iter_reference_t<_Iter>>)
{ {
auto __d = ranges::distance(__ofirst, __olast); auto __d = ranges::distance(__ofirst, __olast);
...@@ -354,13 +354,15 @@ namespace ranges ...@@ -354,13 +354,15 @@ namespace ranges
if constexpr (sized_sentinel_for<_ISent, _Iter> if constexpr (sized_sentinel_for<_ISent, _Iter>
&& sized_sentinel_for<_OSent, _Out> && sized_sentinel_for<_OSent, _Out>
&& is_trivial_v<_OutType> && is_trivial_v<_OutType>
&& is_nothrow_assignable_v<_OutType, && is_nothrow_assignable_v<_OutType&,
iter_rvalue_reference_t<_Iter>>) iter_rvalue_reference_t<_Iter>>)
{ {
auto __d1 = ranges::distance(__ifirst, __ilast); auto __d1 = ranges::distance(__ifirst, __ilast);
auto __d2 = ranges::distance(__ofirst, __olast); auto __d2 = ranges::distance(__ofirst, __olast);
return ranges::copy_n(std::make_move_iterator(__ifirst), auto [__in, __out]
std::min(__d1, __d2), __ofirst); = ranges::copy_n(std::make_move_iterator(__ifirst),
std::min(__d1, __d2), __ofirst);
return {std::move(__in).base(), __out};
} }
else else
{ {
...@@ -404,12 +406,14 @@ namespace ranges ...@@ -404,12 +406,14 @@ namespace ranges
using _OutType = remove_reference_t<iter_reference_t<_Out>>; using _OutType = remove_reference_t<iter_reference_t<_Out>>;
if constexpr (sized_sentinel_for<_Sent, _Out> if constexpr (sized_sentinel_for<_Sent, _Out>
&& is_trivial_v<_OutType> && is_trivial_v<_OutType>
&& is_nothrow_assignable_v<_OutType, && is_nothrow_assignable_v<_OutType&,
iter_rvalue_reference_t<_Iter>>) iter_rvalue_reference_t<_Iter>>)
{ {
auto __d = ranges::distance(__ofirst, __olast); auto __d = ranges::distance(__ofirst, __olast);
return ranges::copy_n(std::make_move_iterator(__ifirst), auto [__in, __out]
std::min(__n, __d), __ofirst); = ranges::copy_n(std::make_move_iterator(__ifirst),
std::min(__n, __d), __ofirst);
return {std::move(__in).base(), __out};
} }
else else
{ {
...@@ -436,7 +440,7 @@ namespace ranges ...@@ -436,7 +440,7 @@ namespace ranges
{ {
using _ValueType = remove_reference_t<iter_reference_t<_Iter>>; using _ValueType = remove_reference_t<iter_reference_t<_Iter>>;
if constexpr (is_trivial_v<_ValueType> if constexpr (is_trivial_v<_ValueType>
&& is_nothrow_assignable_v<_ValueType, const _Tp&>) && is_nothrow_assignable_v<_ValueType&, const _Tp&>)
return ranges::fill(__first, __last, __x); return ranges::fill(__first, __last, __x);
else else
{ {
...@@ -469,7 +473,7 @@ namespace ranges ...@@ -469,7 +473,7 @@ namespace ranges
{ {
using _ValueType = remove_reference_t<iter_reference_t<_Iter>>; using _ValueType = remove_reference_t<iter_reference_t<_Iter>>;
if constexpr (is_trivial_v<_ValueType> if constexpr (is_trivial_v<_ValueType>
&& is_nothrow_assignable_v<_ValueType, const _Tp&>) && is_nothrow_assignable_v<_ValueType&, const _Tp&>)
return ranges::fill_n(__first, __n, __x); return ranges::fill_n(__first, __n, __x);
else else
{ {
......
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