[gcc/devel/ranger] libstdc++: Always return a sentinel<I> from __gnu_test::test_range::end()

Aldy Hernandez aldyh@gcc.gnu.org
Wed Jun 17 18:31:05 GMT 2020


https://gcc.gnu.org/g:6e5a196399d4393f30f2617f6fc042f2e94730b0

commit 6e5a196399d4393f30f2617f6fc042f2e94730b0
Author: Patrick Palka <ppalka@redhat.com>
Date:   Tue Jan 21 17:00:43 2020 -0500

    libstdc++: Always return a sentinel<I> from __gnu_test::test_range::end()
    
    It seems that in practice std::sentinel_for<I, I> is always true, and so the
    test_range container doesn't help us detect bugs in ranges code in which we
    wrongly assume that a sentinel can be manipulated like an iterator.  Make the
    test_range range more strict by having end() unconditionally return a
    sentinel<I>, and adjust some tests accordingly.
    
    libstdc++-v3/ChangeLog:
    
            * testsuite/24_iterators/range_operations/distance.cc: Do not assume
            test_range::end() returns the same type as test_range::begin().
            * testsuite/24_iterators/range_operations/next.cc: Likewise.
            * testsuite/24_iterators/range_operations/prev.cc: Likewise.
            * testsuite/util/testsuite_iterators.h (__gnu_test::test_range::end):
            Always return a sentinel<I>.

Diff:
---
 libstdc++-v3/ChangeLog                             |  9 ++++
 .../24_iterators/range_operations/distance.cc      | 30 +++++++----
 .../24_iterators/range_operations/next.cc          | 58 ++++++++++++----------
 .../24_iterators/range_operations/prev.cc          | 50 ++++++++++---------
 libstdc++-v3/testsuite/util/testsuite_iterators.h  |  5 +-
 5 files changed, 88 insertions(+), 64 deletions(-)

diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 6953a789bc3..966e7dfc3cc 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,12 @@
+2020-01-31  Patrick Palka  <ppalka@redhat.com>
+
+	* testsuite/24_iterators/range_operations/distance.cc: Do not assume
+	test_range::end() returns the same type as test_range::begin().
+	* testsuite/24_iterators/range_operations/next.cc: Likewise.
+	* testsuite/24_iterators/range_operations/prev.cc: Likewise.
+	* testsuite/util/testsuite_iterators.h (__gnu_test::test_range::end):
+	Always return a sentinel<I>.
+
 2020-01-29  Jonathan Wakely  <jwakely@redhat.com>
 
 	PR libstdc++/92895
diff --git a/libstdc++-v3/testsuite/24_iterators/range_operations/distance.cc b/libstdc++-v3/testsuite/24_iterators/range_operations/distance.cc
index 754c0cc200b..cf251b04ec5 100644
--- a/libstdc++-v3/testsuite/24_iterators/range_operations/distance.cc
+++ b/libstdc++-v3/testsuite/24_iterators/range_operations/distance.cc
@@ -39,13 +39,17 @@ test01()
   test_range<int, random_access_iterator_wrapper> c(a);
   VERIFY( std::ranges::distance(c) == 10 );
 
-  auto b = c.begin(), e = c.end();
+  auto b = c.begin();
+  auto e = c.end();
+  auto ei = std::ranges::next(b, e);
   VERIFY( std::ranges::distance(b, e) == 10 );
-  VERIFY( std::ranges::distance(e, b) == -10 );
+  VERIFY( std::ranges::distance(ei, b) == -10 );
 
-  const auto cb = b, ce = e;
+  const auto cb = b;
+  const auto ce = e;
+  const auto cei = ei;
   VERIFY( std::ranges::distance(cb, ce) == 10 );
-  VERIFY( std::ranges::distance(ce, cb) == -10 );
+  VERIFY( std::ranges::distance(cei, cb) == -10 );
 
   test_sized_range<int, random_access_iterator_wrapper> c2(a);
   VERIFY( std::ranges::distance(c2) == 10 );
@@ -60,10 +64,12 @@ test02()
   test_range<int, bidirectional_iterator_wrapper> c(a);
   VERIFY( std::ranges::distance(c) == 2 );
 
-  auto b = c.begin(), e = c.end();
+  auto b = c.begin();
+  auto e = c.end();
   VERIFY( std::ranges::distance(b, e) == 2 );
 
-  const auto cb = b, ce = e;
+  const auto cb = b;
+  const auto ce = e;
   VERIFY( std::ranges::distance(cb, ce) == 2 );
 
   test_sized_range<int, bidirectional_iterator_wrapper> c2(a);
@@ -77,10 +83,12 @@ test03()
   test_range<int, forward_iterator_wrapper> c(a);
   VERIFY( std::ranges::distance(c) == 3 );
 
-  auto b = c.begin(), e = c.end();
+  auto b = c.begin();
+  auto e = c.end();
   VERIFY( std::ranges::distance(b, e) == 3 );
 
-  const auto cb = b, ce = e;
+  const auto cb = b;
+  const auto ce = e;
   VERIFY( std::ranges::distance(cb, ce) == 3 );
 
   test_sized_range<int, forward_iterator_wrapper> c2(a);
@@ -99,11 +107,13 @@ test04()
   VERIFY( std::ranges::distance(c) == 0 );
 
   c = test_range<int, input_iterator_wrapper>(a);
-  auto b = c.begin(), e = c.end();
+  auto b = c.begin();
+  auto e = c.end();
   VERIFY( std::ranges::distance(b, e) == 4 );
 
   test_range<int, input_iterator_wrapper> c2(a);
-  const auto cb = c2.begin(), ce = c2.end();
+  const auto cb = c2.begin();
+  const auto ce = c2.end();
   VERIFY( std::ranges::distance(cb, ce) == 4 );
 
   test_sized_range<int, input_iterator_wrapper> c3(a);
diff --git a/libstdc++-v3/testsuite/24_iterators/range_operations/next.cc b/libstdc++-v3/testsuite/24_iterators/range_operations/next.cc
index af4ae7eacdb..91baba1d978 100644
--- a/libstdc++-v3/testsuite/24_iterators/range_operations/next.cc
+++ b/libstdc++-v3/testsuite/24_iterators/range_operations/next.cc
@@ -36,27 +36,28 @@ test01()
   test_range<int, random_access_iterator_wrapper> r(a);
   auto begin = r.begin();
   auto end = r.end();
+  auto endi = std::ranges::next(begin, end);
   VERIFY( *std::ranges::next(begin) == 1 );
   VERIFY(  std::ranges::next(begin, 0) == begin );
   VERIFY( *std::ranges::next(begin, 1) == 1 );
   VERIFY( *std::ranges::next(begin, 3) == 3 );
-  VERIFY( *std::ranges::next(end, -4) == 6 );
+  VERIFY( *std::ranges::next(endi, -4) == 6 );
   VERIFY(  std::ranges::next(begin, begin) == begin );
   VERIFY(  std::ranges::next(begin, end) == end );
-  VERIFY(  std::ranges::next(end, end) == end );
-  VERIFY(  std::ranges::next(end, begin) == begin );
+  VERIFY(  std::ranges::next(endi, end) == end );
+  VERIFY(  std::ranges::next(endi, begin) == begin );
   VERIFY(  std::ranges::next(begin, 0, begin) == begin );
   VERIFY(  std::ranges::next(begin, 5, begin) == begin );
   VERIFY(  std::ranges::next(begin, -5, begin) == begin );
   VERIFY(  std::ranges::next(begin, 0, end) == begin );
   VERIFY( *std::ranges::next(begin, 5, end) == 5 );
   VERIFY(  std::ranges::next(begin, 55, end) == end );
-  VERIFY(  std::ranges::next(end, 0, end) == end );
-  VERIFY(  std::ranges::next(end, -5, end) == end );
-  VERIFY(  std::ranges::next(end, -55, end) == end );
-  VERIFY(  std::ranges::next(end, 0, begin) == end );
-  VERIFY( *std::ranges::next(end, -5, begin) == 5 );
-  VERIFY(  std::ranges::next(end, -55, begin) == begin );
+  VERIFY(  std::ranges::next(endi, 0, end) == end );
+  VERIFY(  std::ranges::next(endi, -5, end) == end );
+  VERIFY(  std::ranges::next(endi, -55, end) == end );
+  VERIFY(  std::ranges::next(endi, 0, begin) == end );
+  VERIFY( *std::ranges::next(endi, -5, begin) == 5 );
+  VERIFY(  std::ranges::next(endi, -55, begin) == begin );
 }
 
 void
@@ -66,27 +67,28 @@ test02()
   test_range<int, bidirectional_iterator_wrapper> r(a);
   auto begin = r.begin();
   auto end = r.end();
+  auto endi = std::ranges::next(begin, end);
   VERIFY( *std::ranges::next(begin) == 1 );
   VERIFY(  std::ranges::next(begin, 0) == begin );
   VERIFY( *std::ranges::next(begin, 1) == 1 );
   VERIFY( *std::ranges::next(begin, 3) == 3 );
-  VERIFY( *std::ranges::next(end, -4) == 6 );
+  VERIFY( *std::ranges::next(endi, -4) == 6 );
   VERIFY(  std::ranges::next(begin, begin) == begin );
   VERIFY(  std::ranges::next(begin, end) == end );
-  VERIFY(  std::ranges::next(end, end) == end );
-  VERIFY(  std::ranges::next(end, begin) == begin );
+  VERIFY(  std::ranges::next(endi, end) == end );
+  VERIFY(  std::ranges::next(endi, begin) == begin );
   VERIFY(  std::ranges::next(begin, 0, begin) == begin );
   VERIFY(  std::ranges::next(begin, 5, begin) == begin );
   VERIFY(  std::ranges::next(begin, -5, begin) == begin );
   VERIFY(  std::ranges::next(begin, 0, end) == begin );
   VERIFY( *std::ranges::next(begin, 5, end) == 5 );
   VERIFY(  std::ranges::next(begin, 55, end) == end );
-  VERIFY(  std::ranges::next(end, 0, end) == end );
-  VERIFY(  std::ranges::next(end, -5, end) == end );
-  VERIFY(  std::ranges::next(end, -55, end) == end );
-  VERIFY(  std::ranges::next(end, 0, begin) == end );
-  VERIFY( *std::ranges::next(end, -5, begin) == 5 );
-  VERIFY(  std::ranges::next(end, -55, begin) == begin );
+  VERIFY(  std::ranges::next(endi, 0, end) == end );
+  VERIFY(  std::ranges::next(endi, -5, end) == end );
+  VERIFY(  std::ranges::next(endi, -55, end) == end );
+  VERIFY(  std::ranges::next(endi, 0, begin) == end );
+  VERIFY( *std::ranges::next(endi, -5, begin) == 5 );
+  VERIFY(  std::ranges::next(endi, -55, begin) == begin );
 }
 
 void
@@ -96,23 +98,24 @@ test03()
   test_range<int, forward_iterator_wrapper> r(a);
   auto begin = r.begin();
   auto end = r.end();
+  auto endi = std::ranges::next(begin, end);
   VERIFY( *std::ranges::next(begin) == 1 );
   VERIFY(  std::ranges::next(begin, 0) == begin );
   VERIFY( *std::ranges::next(begin, 1) == 1 );
   VERIFY( *std::ranges::next(begin, 3) == 3 );
   VERIFY(  std::ranges::next(begin, begin) == begin );
   VERIFY(  std::ranges::next(begin, end) == end );
-  VERIFY(  std::ranges::next(end, end) == end );
+  VERIFY(  std::ranges::next(endi, end) == end );
   VERIFY(  std::ranges::next(begin, 0, begin) == begin );
   VERIFY(  std::ranges::next(begin, 5, begin) == begin );
   VERIFY(  std::ranges::next(begin, -5, begin) == begin );
   VERIFY(  std::ranges::next(begin, 0, end) == begin );
   VERIFY( *std::ranges::next(begin, 5, end) == 5 );
   VERIFY(  std::ranges::next(begin, 55, end) == end );
-  VERIFY(  std::ranges::next(end, 0, end) == end );
-  VERIFY(  std::ranges::next(end, 5, end) == end );
-  VERIFY(  std::ranges::next(end, 55, end) == end );
-  VERIFY(  std::ranges::next(end, 0, begin) == end );
+  VERIFY(  std::ranges::next(endi, 0, end) == end );
+  VERIFY(  std::ranges::next(endi, 5, end) == end );
+  VERIFY(  std::ranges::next(endi, 55, end) == end );
+  VERIFY(  std::ranges::next(endi, 0, begin) == end );
 }
 
 void
@@ -141,6 +144,9 @@ test04()
   test_range<int, input_iterator_wrapper> r2(a);
   begin = r2.begin();
   end = r2.end();
+  auto endi = std::ranges::next(begin, end);
+  // reset single-pass input range
+  r2.bounds.first = a;
   iter = std::ranges::next(begin, 0, begin);
   VERIFY( *iter == 0 );
   iter = std::ranges::next(begin, 5, begin);
@@ -149,15 +155,15 @@ test04()
   VERIFY( *iter == 0 );
   iter = std::ranges::next(begin, 0, end);
   VERIFY( *iter == 0 );
-  iter = std::ranges::next(end, 0, begin);
+  iter = std::ranges::next(endi, 0, begin);
   VERIFY( iter == end );
   iter = std::ranges::next(begin, 5, end); // invalidates begin
   VERIFY( *iter == 5 );
   iter = std::ranges::next(iter, 55, end);
   VERIFY( iter == end );
-  iter = std::ranges::next(end, 0, end);
+  iter = std::ranges::next(endi, 0, end);
   VERIFY( iter == end );
-  iter = std::ranges::next(end, 5, end);
+  iter = std::ranges::next(endi, 5, end);
   VERIFY( iter == end );
 }
 
diff --git a/libstdc++-v3/testsuite/24_iterators/range_operations/prev.cc b/libstdc++-v3/testsuite/24_iterators/range_operations/prev.cc
index ebf7c3f1323..70064b1b810 100644
--- a/libstdc++-v3/testsuite/24_iterators/range_operations/prev.cc
+++ b/libstdc++-v3/testsuite/24_iterators/range_operations/prev.cc
@@ -36,23 +36,24 @@ test01()
   test_range<int, random_access_iterator_wrapper> r(a);
   auto begin = r.begin();
   auto end = r.end();
-  VERIFY( *std::ranges::prev(end) == 9 );
+  auto endi = std::ranges::next(begin, end);
+  VERIFY( *std::ranges::prev(endi) == 9 );
   VERIFY(  std::ranges::prev(begin, 0) == begin );
-  VERIFY( *std::ranges::prev(end, 1) == 9 );
-  VERIFY( *std::ranges::prev(end, 3) == 7 );
+  VERIFY( *std::ranges::prev(endi, 1) == 9 );
+  VERIFY( *std::ranges::prev(endi, 3) == 7 );
   VERIFY( *std::ranges::prev(begin, -4) == 4 );
   VERIFY(  std::ranges::prev(begin, 0, begin) == begin );
   VERIFY(  std::ranges::prev(begin, 5, begin) == begin );
   VERIFY(  std::ranges::prev(begin, -5, begin) == begin );
-  VERIFY(  std::ranges::prev(begin, 0, end) == begin );
-  VERIFY( *std::ranges::prev(end, 5, begin) == 5 );
-  VERIFY(  std::ranges::prev(end, 55, begin) == begin );
-  VERIFY(  std::ranges::prev(end, 0, end) == end );
-  VERIFY(  std::ranges::prev(end, -5, end) == end );
-  VERIFY(  std::ranges::prev(end, -55, end) == end );
-  VERIFY(  std::ranges::prev(end, 0, begin) == end );
-  VERIFY( *std::ranges::prev(begin, -5, end) == 5 );
-  VERIFY(  std::ranges::prev(begin, -55, end) == end );
+  VERIFY(  std::ranges::prev(begin, 0, endi) == begin );
+  VERIFY( *std::ranges::prev(endi, 5, begin) == 5 );
+  VERIFY(  std::ranges::prev(endi, 55, begin) == begin );
+  VERIFY(  std::ranges::prev(endi, 0, endi) == end );
+  VERIFY(  std::ranges::prev(endi, -5, endi) == end );
+  VERIFY(  std::ranges::prev(endi, -55, endi) == end );
+  VERIFY(  std::ranges::prev(endi, 0, begin) == end );
+  VERIFY( *std::ranges::prev(begin, -5, endi) == 5 );
+  VERIFY(  std::ranges::prev(begin, -55, endi) == end );
 }
 
 void
@@ -62,23 +63,24 @@ test02()
   test_range<int, bidirectional_iterator_wrapper> r(a);
   auto begin = r.begin();
   auto end = r.end();
-  VERIFY( *std::ranges::prev(end) == 9 );
+  auto endi = std::ranges::next(begin, end);
+  VERIFY( *std::ranges::prev(endi) == 9 );
   VERIFY(  std::ranges::prev(begin, 0) == begin );
-  VERIFY( *std::ranges::prev(end, 1) == 9 );
-  VERIFY( *std::ranges::prev(end, 3) == 7 );
+  VERIFY( *std::ranges::prev(endi, 1) == 9 );
+  VERIFY( *std::ranges::prev(endi, 3) == 7 );
   VERIFY( *std::ranges::prev(begin, -4) == 4 );
   VERIFY(  std::ranges::prev(begin, 0, begin) == begin );
   VERIFY(  std::ranges::prev(begin, 5, begin) == begin );
   VERIFY(  std::ranges::prev(begin, -5, begin) == begin );
-  VERIFY(  std::ranges::prev(begin, 0, end) == begin );
-  VERIFY( *std::ranges::prev(end, 5, begin) == 5 );
-  VERIFY(  std::ranges::prev(end, 55, begin) == begin );
-  VERIFY(  std::ranges::prev(end, 0, end) == end );
-  VERIFY(  std::ranges::prev(end, -5, end) == end );
-  VERIFY(  std::ranges::prev(end, -55, end) == end );
-  VERIFY(  std::ranges::prev(end, 0, begin) == end );
-  VERIFY( *std::ranges::prev(begin, -5, end) == 5 );
-  VERIFY(  std::ranges::prev(begin, -55, end) == end );
+  VERIFY(  std::ranges::prev(begin, 0, endi) == begin );
+  VERIFY( *std::ranges::prev(endi, 5, begin) == 5 );
+  VERIFY(  std::ranges::prev(endi, 55, begin) == begin );
+  VERIFY(  std::ranges::prev(endi, 0, endi) == end );
+  VERIFY(  std::ranges::prev(endi, -5, endi) == end );
+  VERIFY(  std::ranges::prev(endi, -55, endi) == end );
+  VERIFY(  std::ranges::prev(endi, 0, begin) == end );
+  VERIFY( *std::ranges::prev(begin, -5, endi) == 5 );
+  VERIFY(  std::ranges::prev(begin, -55, endi) == end );
 }
 
 template<typename T>
diff --git a/libstdc++-v3/testsuite/util/testsuite_iterators.h b/libstdc++-v3/testsuite/util/testsuite_iterators.h
index 1c7fbd001e0..6887d806a31 100644
--- a/libstdc++-v3/testsuite/util/testsuite_iterators.h
+++ b/libstdc++-v3/testsuite/util/testsuite_iterators.h
@@ -710,10 +710,7 @@ namespace __gnu_test
       auto end() &
       {
 	using I = decltype(get_iterator(bounds.last));
-	if constexpr (std::sentinel_for<I, I>)
-	  return get_iterator(bounds.last);
-	else
-	  return sentinel<I>{bounds.last};
+	return sentinel<I>{bounds.last};
       }
 
       typename Iter<T>::ContainerType bounds;


More information about the Libstdc++-cvs mailing list