Improve _GLIBCXX_DEBUG safe iterator range size computation.
authorFrançois Dumont <fdumont@gcc.gnu.org>
Fri, 4 Oct 2019 20:22:11 +0000 (20:22 +0000)
committerFrançois Dumont <fdumont@gcc.gnu.org>
Fri, 4 Oct 2019 20:22:11 +0000 (20:22 +0000)
* include/debug/forward_list
(_Sequence_traits<__debug::forward_list<>>::_S_size): Returns __dp_sign
distance when not empty.
* include/debug/list (_Sequence_traits<__debug::list<>>::_S_size):
Likewise.
* include/debug/helper_functions.h (__dp_sign_max_size): New
_Distance_precision enum entry.
(__valid_range_aux(_IIte, _IIte, _Distance_traits<>::__type,
__false_type)): Adapt.
* include/debug/safe_iterator.tcc
(_Safe_iterator<>::_M_get_distance_to(const _Safe_iterator&)): Review
distance computation.

From-SVN: r276600

libstdc++-v3/ChangeLog
libstdc++-v3/include/debug/forward_list
libstdc++-v3/include/debug/helper_functions.h
libstdc++-v3/include/debug/list
libstdc++-v3/include/debug/safe_iterator.tcc

index 4e822def3fe310dc08b427c06ed3d7115ab45370..26d37d7effb43bbae6ddbb62870bc35c9d5be422 100644 (file)
@@ -1,3 +1,18 @@
+2019-10-04  François Dumont  <fdumont@gcc.gnu.org>
+
+       * include/debug/forward_list
+       (_Sequence_traits<__debug::forward_list<>>::_S_size): Returns __dp_sign
+       distance when not empty.
+       * include/debug/list (_Sequence_traits<__debug::list<>>::_S_size):
+       Likewise.
+       * include/debug/helper_functions.h (__dp_sign_max_size): New
+       _Distance_precision enum entry.
+       (__valid_range_aux(_IIte, _IIte, _Distance_traits<>::__type,
+       __false_type)): Adapt.
+       * include/debug/safe_iterator.tcc
+       (_Safe_iterator<>::_M_get_distance_to(const _Safe_iterator&)): Review
+       distance computation.
+
 2019-10-04  Jonathan Wakely  <jwakely@redhat.com>
 
        PR libstdc++/81091
index e30b000009ea2912568a94f540593edc86b6b479..f1756ddec9d2b089885d531def5d3a831d35279f 100644 (file)
@@ -911,7 +911,7 @@ namespace __gnu_debug
       _S_size(const std::__debug::forward_list<_Tp, _Alloc>& __seq)
       {
        return __seq.empty()
-         ? std::make_pair(0, __dp_exact) : std::make_pair(1, __dp_equality);
+         ? std::make_pair(0, __dp_exact) : std::make_pair(1, __dp_sign);
       }
     };
 
index 475fdda1d7b9303dcee1ceea9a1f79b1ad94f1e4..5a920bb9a6f3a329f05a795b35d937ea94c06295 100644 (file)
@@ -50,10 +50,11 @@ namespace __gnu_debug
    */
   enum _Distance_precision
     {
-      __dp_none,       // Not even an iterator type
-      __dp_equality,   //< Can compare iterator equality, only
-      __dp_sign,       //< Can determine equality and ordering
-      __dp_exact       //< Can determine distance precisely
+      __dp_none,               // Not even an iterator type
+      __dp_equality,           //< Can compare iterator equality, only
+      __dp_sign,               //< Can determine equality and ordering
+      __dp_sign_max_size,      //< __dp_sign and gives max range size
+      __dp_exact               //< Can determine distance precisely
     };
 
   template<typename _Iterator,
@@ -176,6 +177,7 @@ namespace __gnu_debug
            return true;
          break;
        case __dp_sign:
+       case __dp_sign_max_size:
        case __dp_exact:
          return __dist.first >= 0;
        }
index 5eb9a6094e3e0904d3caca660c05fb86b609735d..140546a633edf516970beb70ea553f879cdcd871 100644 (file)
@@ -916,7 +916,7 @@ namespace __gnu_debug
       _S_size(const std::__debug::list<_Tp, _Alloc>& __seq)
       {
        return __seq.empty()
-         ? std::make_pair(0, __dp_exact) : std::make_pair(1, __dp_equality);
+         ? std::make_pair(0, __dp_exact) : std::make_pair(1, __dp_sign);
       }
     };
 #endif
index 581c51c9607d95b9ff98b26db92361c5e8356b8f..1750bc473d223f4396f1d3f646c4cdf29784fc85 100644 (file)
@@ -113,18 +113,22 @@ namespace __gnu_debug
     _Safe_iterator<_Iterator, _Sequence, _Category>::
     _M_get_distance_to(const _Safe_iterator& __rhs) const
     {
-      typedef typename _Distance_traits<_Iterator>::__type _Diff;
+      typedef typename _Distance_traits<_Iterator>::__type _Dist;
       typedef _Sequence_traits<_Sequence> _SeqTraits;
 
-      if (this->base() == __rhs.base())
-       return std::make_pair(0, __dp_exact);
+      _Dist __base_dist = __get_distance(this->base(), __rhs.base());
+      if (__base_dist.second == __dp_exact)
+       return __base_dist;
 
+      _Dist __seq_dist = _SeqTraits::_S_size(*this->_M_get_sequence());
       if (this->_M_is_before_begin())
        {
          if (__rhs._M_is_begin())
            return std::make_pair(1, __dp_exact);
 
-         return std::make_pair(1, __dp_sign);
+         return __seq_dist.second == __dp_exact
+           ? std::make_pair(__seq_dist.first + 1, __dp_exact)
+           : __seq_dist;
        }
 
       if (this->_M_is_begin())
@@ -133,30 +137,42 @@ namespace __gnu_debug
            return std::make_pair(-1, __dp_exact);
 
          if (__rhs._M_is_end())
-           return _SeqTraits::_S_size(*this->_M_get_sequence());
+           return __seq_dist;
 
-         return std::make_pair(1, __dp_sign);
+         return std::make_pair(__seq_dist.first,
+                               __seq_dist.second == __dp_exact
+                               ? __dp_sign_max_size : __seq_dist.second);
        }
 
       if (this->_M_is_end())
        {
          if (__rhs._M_is_before_begin())
-           return std::make_pair(-1, __dp_exact);
+           return __seq_dist.second == __dp_exact
+             ? std::make_pair(-__seq_dist.first - 1, __dp_exact)
+             : std::make_pair(-__seq_dist.first, __dp_sign);
 
          if (__rhs._M_is_begin())
-           {
-             _Diff __diff = _SeqTraits::_S_size(*this->_M_get_sequence());
-             return std::make_pair(-__diff.first, __diff.second);
-           }
+           return std::make_pair(-__seq_dist.first, __seq_dist.second);
 
-         return std::make_pair(-1, __dp_sign);
+         return std::make_pair(-__seq_dist.first,
+                               __seq_dist.second == __dp_exact
+                               ? __dp_sign_max_size : __seq_dist.second);
        }
 
-      if (__rhs._M_is_before_begin() || __rhs._M_is_begin())
-       return std::make_pair(-1, __dp_sign);
+      if (__rhs._M_is_before_begin())
+       return __seq_dist.second == __dp_exact
+         ? std::make_pair(__seq_dist.first - 1, __dp_exact)
+         : std::make_pair(-__seq_dist.first, __dp_sign);
+
+      if (__rhs._M_is_begin())
+       return std::make_pair(-__seq_dist.first,
+                             __seq_dist.second == __dp_exact
+                             ? __dp_sign_max_size : __seq_dist.second);
 
       if (__rhs._M_is_end())
-       return std::make_pair(1, __dp_sign);
+       return std::make_pair(__seq_dist.first,
+                             __seq_dist.second == __dp_exact
+                             ? __dp_sign_max_size : __seq_dist.second);
 
       return std::make_pair(1, __dp_equality);
     }