libstdc++: Fix use of is_nothrow_assignable_v in <bits/ranges_uninitialized.h>
authorPatrick Palka <ppalka@redhat.com>
Tue, 3 Mar 2020 00:39:13 +0000 (19:39 -0500)
committerPatrick Palka <ppalka@redhat.com>
Wed, 4 Mar 2020 03:35:34 +0000 (22:35 -0500)
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.

libstdc++-v3/ChangeLog
libstdc++-v3/include/bits/ranges_uninitialized.h

index 640c5be90abd3307d013fdddd4ec83ee8828a2b5..45ff06d4ea705054cb5f99c758e9cdaf8890d7f1 100644 (file)
@@ -1,3 +1,16 @@
+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>
 
        PR libstdc++/94013
index 01e1cad646c21d9091db4aa67cf2b6198b321053..f97a07a9b4a298106d1f7fc464ae2a79cca64b2b 100644 (file)
@@ -269,7 +269,7 @@ namespace ranges
        if constexpr (sized_sentinel_for<_ISent, _Iter>
                      && sized_sentinel_for<_OSent, _Out>
                      && is_trivial_v<_OutType>
-                     && is_nothrow_assignable_v<_OutType,
+                     && is_nothrow_assignable_v<_OutType&,
                                                 iter_reference_t<_Iter>>)
          {
            auto __d1 = ranges::distance(__ifirst, __ilast);
@@ -316,7 +316,7 @@ namespace ranges
        using _OutType = remove_reference_t<iter_reference_t<_Out>>;
        if constexpr (sized_sentinel_for<_Sent, _Out>
                      && is_trivial_v<_OutType>
-                     && is_nothrow_assignable_v<_OutType,
+                     && is_nothrow_assignable_v<_OutType&,
                                                 iter_reference_t<_Iter>>)
          {
            auto __d = ranges::distance(__ofirst, __olast);
@@ -354,13 +354,15 @@ namespace ranges
        if constexpr (sized_sentinel_for<_ISent, _Iter>
                      && sized_sentinel_for<_OSent, _Out>
                      && is_trivial_v<_OutType>
-                     && is_nothrow_assignable_v<_OutType,
+                     && is_nothrow_assignable_v<_OutType&,
                                                 iter_rvalue_reference_t<_Iter>>)
          {
            auto __d1 = ranges::distance(__ifirst, __ilast);
            auto __d2 = ranges::distance(__ofirst, __olast);
-           return ranges::copy_n(std::make_move_iterator(__ifirst),
-                                 std::min(__d1, __d2), __ofirst);
+           auto [__in, __out]
+             = ranges::copy_n(std::make_move_iterator(__ifirst),
+                              std::min(__d1, __d2), __ofirst);
+           return {std::move(__in).base(), __out};
          }
        else
          {
@@ -404,12 +406,14 @@ namespace ranges
        using _OutType = remove_reference_t<iter_reference_t<_Out>>;
        if constexpr (sized_sentinel_for<_Sent, _Out>
                      && is_trivial_v<_OutType>
-                     && is_nothrow_assignable_v<_OutType,
+                     && is_nothrow_assignable_v<_OutType&,
                                                 iter_rvalue_reference_t<_Iter>>)
          {
            auto __d = ranges::distance(__ofirst, __olast);
-           return ranges::copy_n(std::make_move_iterator(__ifirst),
-                                 std::min(__n, __d), __ofirst);
+           auto [__in, __out]
+             = ranges::copy_n(std::make_move_iterator(__ifirst),
+                              std::min(__n, __d), __ofirst);
+           return {std::move(__in).base(), __out};
          }
        else
          {
@@ -436,7 +440,7 @@ namespace ranges
       {
        using _ValueType = remove_reference_t<iter_reference_t<_Iter>>;
        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);
        else
          {
@@ -469,7 +473,7 @@ namespace ranges
       {
        using _ValueType = remove_reference_t<iter_reference_t<_Iter>>;
        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);
        else
          {