Commit 6e5a1963 by Patrick Palka

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>.
parent b9270938
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> 2020-01-29 Jonathan Wakely <jwakely@redhat.com>
PR libstdc++/92895 PR libstdc++/92895
......
...@@ -39,13 +39,17 @@ test01() ...@@ -39,13 +39,17 @@ test01()
test_range<int, random_access_iterator_wrapper> c(a); test_range<int, random_access_iterator_wrapper> c(a);
VERIFY( std::ranges::distance(c) == 10 ); 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(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(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); test_sized_range<int, random_access_iterator_wrapper> c2(a);
VERIFY( std::ranges::distance(c2) == 10 ); VERIFY( std::ranges::distance(c2) == 10 );
...@@ -60,10 +64,12 @@ test02() ...@@ -60,10 +64,12 @@ test02()
test_range<int, bidirectional_iterator_wrapper> c(a); test_range<int, bidirectional_iterator_wrapper> c(a);
VERIFY( std::ranges::distance(c) == 2 ); 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 ); 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 ); VERIFY( std::ranges::distance(cb, ce) == 2 );
test_sized_range<int, bidirectional_iterator_wrapper> c2(a); test_sized_range<int, bidirectional_iterator_wrapper> c2(a);
...@@ -77,10 +83,12 @@ test03() ...@@ -77,10 +83,12 @@ test03()
test_range<int, forward_iterator_wrapper> c(a); test_range<int, forward_iterator_wrapper> c(a);
VERIFY( std::ranges::distance(c) == 3 ); 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 ); 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 ); VERIFY( std::ranges::distance(cb, ce) == 3 );
test_sized_range<int, forward_iterator_wrapper> c2(a); test_sized_range<int, forward_iterator_wrapper> c2(a);
...@@ -99,11 +107,13 @@ test04() ...@@ -99,11 +107,13 @@ test04()
VERIFY( std::ranges::distance(c) == 0 ); VERIFY( std::ranges::distance(c) == 0 );
c = test_range<int, input_iterator_wrapper>(a); 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 ); VERIFY( std::ranges::distance(b, e) == 4 );
test_range<int, input_iterator_wrapper> c2(a); 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 ); VERIFY( std::ranges::distance(cb, ce) == 4 );
test_sized_range<int, input_iterator_wrapper> c3(a); test_sized_range<int, input_iterator_wrapper> c3(a);
......
...@@ -36,27 +36,28 @@ test01() ...@@ -36,27 +36,28 @@ test01()
test_range<int, random_access_iterator_wrapper> r(a); test_range<int, random_access_iterator_wrapper> r(a);
auto begin = r.begin(); auto begin = r.begin();
auto end = r.end(); auto end = r.end();
auto endi = std::ranges::next(begin, end);
VERIFY( *std::ranges::next(begin) == 1 ); VERIFY( *std::ranges::next(begin) == 1 );
VERIFY( std::ranges::next(begin, 0) == begin ); VERIFY( std::ranges::next(begin, 0) == begin );
VERIFY( *std::ranges::next(begin, 1) == 1 ); VERIFY( *std::ranges::next(begin, 1) == 1 );
VERIFY( *std::ranges::next(begin, 3) == 3 ); 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, begin) == begin );
VERIFY( std::ranges::next(begin, end) == end ); 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(end, begin) == begin ); VERIFY( std::ranges::next(endi, begin) == begin );
VERIFY( std::ranges::next(begin, 0, 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, -5, begin) == begin ); VERIFY( std::ranges::next(begin, -5, begin) == begin );
VERIFY( std::ranges::next(begin, 0, end) == begin ); VERIFY( std::ranges::next(begin, 0, end) == begin );
VERIFY( *std::ranges::next(begin, 5, end) == 5 ); VERIFY( *std::ranges::next(begin, 5, end) == 5 );
VERIFY( std::ranges::next(begin, 55, end) == end ); VERIFY( std::ranges::next(begin, 55, end) == end );
VERIFY( std::ranges::next(end, 0, end) == end ); VERIFY( std::ranges::next(endi, 0, end) == end );
VERIFY( std::ranges::next(end, -5, end) == end ); VERIFY( std::ranges::next(endi, -5, end) == end );
VERIFY( std::ranges::next(end, -55, end) == end ); VERIFY( std::ranges::next(endi, -55, end) == end );
VERIFY( std::ranges::next(end, 0, begin) == end ); VERIFY( std::ranges::next(endi, 0, begin) == end );
VERIFY( *std::ranges::next(end, -5, begin) == 5 ); VERIFY( *std::ranges::next(endi, -5, begin) == 5 );
VERIFY( std::ranges::next(end, -55, begin) == begin ); VERIFY( std::ranges::next(endi, -55, begin) == begin );
} }
void void
...@@ -66,27 +67,28 @@ test02() ...@@ -66,27 +67,28 @@ test02()
test_range<int, bidirectional_iterator_wrapper> r(a); test_range<int, bidirectional_iterator_wrapper> r(a);
auto begin = r.begin(); auto begin = r.begin();
auto end = r.end(); auto end = r.end();
auto endi = std::ranges::next(begin, end);
VERIFY( *std::ranges::next(begin) == 1 ); VERIFY( *std::ranges::next(begin) == 1 );
VERIFY( std::ranges::next(begin, 0) == begin ); VERIFY( std::ranges::next(begin, 0) == begin );
VERIFY( *std::ranges::next(begin, 1) == 1 ); VERIFY( *std::ranges::next(begin, 1) == 1 );
VERIFY( *std::ranges::next(begin, 3) == 3 ); 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, begin) == begin );
VERIFY( std::ranges::next(begin, end) == end ); 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(end, begin) == begin ); VERIFY( std::ranges::next(endi, begin) == begin );
VERIFY( std::ranges::next(begin, 0, 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, -5, begin) == begin ); VERIFY( std::ranges::next(begin, -5, begin) == begin );
VERIFY( std::ranges::next(begin, 0, end) == begin ); VERIFY( std::ranges::next(begin, 0, end) == begin );
VERIFY( *std::ranges::next(begin, 5, end) == 5 ); VERIFY( *std::ranges::next(begin, 5, end) == 5 );
VERIFY( std::ranges::next(begin, 55, end) == end ); VERIFY( std::ranges::next(begin, 55, end) == end );
VERIFY( std::ranges::next(end, 0, end) == end ); VERIFY( std::ranges::next(endi, 0, end) == end );
VERIFY( std::ranges::next(end, -5, end) == end ); VERIFY( std::ranges::next(endi, -5, end) == end );
VERIFY( std::ranges::next(end, -55, end) == end ); VERIFY( std::ranges::next(endi, -55, end) == end );
VERIFY( std::ranges::next(end, 0, begin) == end ); VERIFY( std::ranges::next(endi, 0, begin) == end );
VERIFY( *std::ranges::next(end, -5, begin) == 5 ); VERIFY( *std::ranges::next(endi, -5, begin) == 5 );
VERIFY( std::ranges::next(end, -55, begin) == begin ); VERIFY( std::ranges::next(endi, -55, begin) == begin );
} }
void void
...@@ -96,23 +98,24 @@ test03() ...@@ -96,23 +98,24 @@ test03()
test_range<int, forward_iterator_wrapper> r(a); test_range<int, forward_iterator_wrapper> r(a);
auto begin = r.begin(); auto begin = r.begin();
auto end = r.end(); auto end = r.end();
auto endi = std::ranges::next(begin, end);
VERIFY( *std::ranges::next(begin) == 1 ); VERIFY( *std::ranges::next(begin) == 1 );
VERIFY( std::ranges::next(begin, 0) == begin ); VERIFY( std::ranges::next(begin, 0) == begin );
VERIFY( *std::ranges::next(begin, 1) == 1 ); VERIFY( *std::ranges::next(begin, 1) == 1 );
VERIFY( *std::ranges::next(begin, 3) == 3 ); VERIFY( *std::ranges::next(begin, 3) == 3 );
VERIFY( std::ranges::next(begin, begin) == begin ); VERIFY( std::ranges::next(begin, begin) == begin );
VERIFY( std::ranges::next(begin, end) == end ); 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, 0, begin) == begin );
VERIFY( std::ranges::next(begin, 5, begin) == begin ); VERIFY( std::ranges::next(begin, 5, 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, 0, end) == begin );
VERIFY( *std::ranges::next(begin, 5, end) == 5 ); VERIFY( *std::ranges::next(begin, 5, end) == 5 );
VERIFY( std::ranges::next(begin, 55, end) == end ); VERIFY( std::ranges::next(begin, 55, end) == end );
VERIFY( std::ranges::next(end, 0, end) == end ); VERIFY( std::ranges::next(endi, 0, end) == end );
VERIFY( std::ranges::next(end, 5, end) == end ); VERIFY( std::ranges::next(endi, 5, end) == end );
VERIFY( std::ranges::next(end, 55, end) == end ); VERIFY( std::ranges::next(endi, 55, end) == end );
VERIFY( std::ranges::next(end, 0, begin) == end ); VERIFY( std::ranges::next(endi, 0, begin) == end );
} }
void void
...@@ -141,6 +144,9 @@ test04() ...@@ -141,6 +144,9 @@ test04()
test_range<int, input_iterator_wrapper> r2(a); test_range<int, input_iterator_wrapper> r2(a);
begin = r2.begin(); begin = r2.begin();
end = r2.end(); 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); iter = std::ranges::next(begin, 0, begin);
VERIFY( *iter == 0 ); VERIFY( *iter == 0 );
iter = std::ranges::next(begin, 5, begin); iter = std::ranges::next(begin, 5, begin);
...@@ -149,15 +155,15 @@ test04() ...@@ -149,15 +155,15 @@ test04()
VERIFY( *iter == 0 ); VERIFY( *iter == 0 );
iter = std::ranges::next(begin, 0, end); iter = std::ranges::next(begin, 0, end);
VERIFY( *iter == 0 ); VERIFY( *iter == 0 );
iter = std::ranges::next(end, 0, begin); iter = std::ranges::next(endi, 0, begin);
VERIFY( iter == end ); VERIFY( iter == end );
iter = std::ranges::next(begin, 5, end); // invalidates begin iter = std::ranges::next(begin, 5, end); // invalidates begin
VERIFY( *iter == 5 ); VERIFY( *iter == 5 );
iter = std::ranges::next(iter, 55, end); iter = std::ranges::next(iter, 55, end);
VERIFY( iter == end ); VERIFY( iter == end );
iter = std::ranges::next(end, 0, end); iter = std::ranges::next(endi, 0, end);
VERIFY( iter == end ); VERIFY( iter == end );
iter = std::ranges::next(end, 5, end); iter = std::ranges::next(endi, 5, end);
VERIFY( iter == end ); VERIFY( iter == end );
} }
......
...@@ -36,23 +36,24 @@ test01() ...@@ -36,23 +36,24 @@ test01()
test_range<int, random_access_iterator_wrapper> r(a); test_range<int, random_access_iterator_wrapper> r(a);
auto begin = r.begin(); auto begin = r.begin();
auto end = r.end(); 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(begin, 0) == begin );
VERIFY( *std::ranges::prev(end, 1) == 9 ); VERIFY( *std::ranges::prev(endi, 1) == 9 );
VERIFY( *std::ranges::prev(end, 3) == 7 ); VERIFY( *std::ranges::prev(endi, 3) == 7 );
VERIFY( *std::ranges::prev(begin, -4) == 4 ); VERIFY( *std::ranges::prev(begin, -4) == 4 );
VERIFY( std::ranges::prev(begin, 0, begin) == begin ); 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, -5, begin) == begin ); VERIFY( std::ranges::prev(begin, -5, begin) == begin );
VERIFY( std::ranges::prev(begin, 0, end) == begin ); VERIFY( std::ranges::prev(begin, 0, endi) == begin );
VERIFY( *std::ranges::prev(end, 5, begin) == 5 ); VERIFY( *std::ranges::prev(endi, 5, begin) == 5 );
VERIFY( std::ranges::prev(end, 55, begin) == begin ); VERIFY( std::ranges::prev(endi, 55, begin) == begin );
VERIFY( std::ranges::prev(end, 0, end) == end ); VERIFY( std::ranges::prev(endi, 0, endi) == end );
VERIFY( std::ranges::prev(end, -5, end) == end ); VERIFY( std::ranges::prev(endi, -5, endi) == end );
VERIFY( std::ranges::prev(end, -55, end) == end ); VERIFY( std::ranges::prev(endi, -55, endi) == end );
VERIFY( std::ranges::prev(end, 0, begin) == end ); VERIFY( std::ranges::prev(endi, 0, begin) == end );
VERIFY( *std::ranges::prev(begin, -5, end) == 5 ); VERIFY( *std::ranges::prev(begin, -5, endi) == 5 );
VERIFY( std::ranges::prev(begin, -55, end) == end ); VERIFY( std::ranges::prev(begin, -55, endi) == end );
} }
void void
...@@ -62,23 +63,24 @@ test02() ...@@ -62,23 +63,24 @@ test02()
test_range<int, bidirectional_iterator_wrapper> r(a); test_range<int, bidirectional_iterator_wrapper> r(a);
auto begin = r.begin(); auto begin = r.begin();
auto end = r.end(); 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(begin, 0) == begin );
VERIFY( *std::ranges::prev(end, 1) == 9 ); VERIFY( *std::ranges::prev(endi, 1) == 9 );
VERIFY( *std::ranges::prev(end, 3) == 7 ); VERIFY( *std::ranges::prev(endi, 3) == 7 );
VERIFY( *std::ranges::prev(begin, -4) == 4 ); VERIFY( *std::ranges::prev(begin, -4) == 4 );
VERIFY( std::ranges::prev(begin, 0, begin) == begin ); 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, -5, begin) == begin ); VERIFY( std::ranges::prev(begin, -5, begin) == begin );
VERIFY( std::ranges::prev(begin, 0, end) == begin ); VERIFY( std::ranges::prev(begin, 0, endi) == begin );
VERIFY( *std::ranges::prev(end, 5, begin) == 5 ); VERIFY( *std::ranges::prev(endi, 5, begin) == 5 );
VERIFY( std::ranges::prev(end, 55, begin) == begin ); VERIFY( std::ranges::prev(endi, 55, begin) == begin );
VERIFY( std::ranges::prev(end, 0, end) == end ); VERIFY( std::ranges::prev(endi, 0, endi) == end );
VERIFY( std::ranges::prev(end, -5, end) == end ); VERIFY( std::ranges::prev(endi, -5, endi) == end );
VERIFY( std::ranges::prev(end, -55, end) == end ); VERIFY( std::ranges::prev(endi, -55, endi) == end );
VERIFY( std::ranges::prev(end, 0, begin) == end ); VERIFY( std::ranges::prev(endi, 0, begin) == end );
VERIFY( *std::ranges::prev(begin, -5, end) == 5 ); VERIFY( *std::ranges::prev(begin, -5, endi) == 5 );
VERIFY( std::ranges::prev(begin, -55, end) == end ); VERIFY( std::ranges::prev(begin, -55, endi) == end );
} }
template<typename T> template<typename T>
......
...@@ -710,10 +710,7 @@ namespace __gnu_test ...@@ -710,10 +710,7 @@ namespace __gnu_test
auto end() & auto end() &
{ {
using I = decltype(get_iterator(bounds.last)); using I = decltype(get_iterator(bounds.last));
if constexpr (std::sentinel_for<I, I>) return sentinel<I>{bounds.last};
return get_iterator(bounds.last);
else
return sentinel<I>{bounds.last};
} }
typename Iter<T>::ContainerType bounds; typename Iter<T>::ContainerType bounds;
......
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