1 // Copyright (C) 2019-2021 Free Software Foundation, Inc.
2 //
3 // This file is part of the GNU ISO C++ Library.  This library is free
4 // software; you can redistribute it and/or modify it under the
5 // terms of the GNU General Public License as published by the
6 // Free Software Foundation; either version 3, or (at your option)
7 // any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13 
14 // You should have received a copy of the GNU General Public License along
15 // with this library; see the file COPYING3.  If not see
16 // <http://www.gnu.org/licenses/>.
17 
18 // { dg-options "-std=gnu++2a" }
19 // { dg-do run { target c++2a } }
20 
21 #include <ranges>
22 #include <testsuite_hooks.h>
23 #include <testsuite_iterators.h>
24 
25 using std::same_as;
26 
27 void
test01()28 test01()
29 {
30   int a[2] = {};
31 
32   // t + extent_v<T> if E is of array type T.
33 
34   static_assert(same_as<decltype(std::ranges::end(a)), decltype(a + 2)>);
35   static_assert(noexcept(std::ranges::end(a)));
36   VERIFY( std::ranges::end(a) == (a + 2) );
37 }
38 
39 void
test02()40 test02()
41 {
42   using __gnu_test::test_range;
43   using __gnu_test::random_access_iterator_wrapper;
44   using __gnu_test::input_iterator_wrapper;
45   using __gnu_test::output_iterator_wrapper;
46 
47   int a[] = { 0, 1 };
48 
49   // Otherwise, decay-copy(t.end()) if it is a valid expression
50   // and its type S models sentinel_for<decltype(ranges::begin(E))>.
51 
52   test_range<int, random_access_iterator_wrapper> r(a);
53   static_assert(same_as<decltype(std::ranges::end(r)), decltype(r.end())>);
54   VERIFY( std::ranges::end(r) == std::ranges::next(r.begin(), 2) );
55 
56   test_range<int, input_iterator_wrapper> i(a);
57   static_assert(same_as<decltype(std::ranges::end(i)), decltype(i.end())>);
58   VERIFY( std::ranges::end(i) == std::ranges::next(i.begin(), 2) );
59 
60   test_range<int, output_iterator_wrapper> o(a);
61   static_assert(same_as<decltype(std::ranges::end(o)), decltype(o.end())>);
62   VERIFY( std::ranges::end(o) == std::ranges::next(o.begin(), 2) );
63 }
64 
65 struct R
66 {
67   int a[4] = { 0, 1, 2, 3 };
68 
69   const int* begin() const;
70   friend int* begin(R&&) noexcept;
71   friend const int* begin(const R&&) noexcept;
72 
73   // Should be ignored because it doesn't return a sentinel for int*
74   const long* end() const;
75 
end(R & r)76   friend int* end(R& r) { return r.a + 0; }
end(R && r)77   friend int* end(R&& r) { return r.a + 1; }
end(const R & r)78   friend const int* end(const R& r) noexcept { return r.a + 2; }
end(const R && r)79   friend const int* end(const R&& r) noexcept { return r.a + 3; }
80 };
81 
82 struct RV // view on an R
83 {
84   R& r;
85 
86   const int* begin() const;
87 
end(RV & v)88   friend int* end(RV& v) noexcept { return end(v.r); }
end(const RV & v)89   friend const int* end(const RV& v) { return end(std::as_const(v.r)); }
90 };
91 
92 // Allow ranges::begin to work with RV&&
93 template<> constexpr bool std::ranges::enable_borrowed_range<RV> = true;
94 
95 void
test03()96 test03()
97 {
98   R r;
99   const R& c = r;
100 
101   // Otherwise, decay-copy(end(t)) if it is a valid expression
102   // and its type S models sentinel_for<decltype(ranges::begin(E))>.
103 
104   static_assert(same_as<decltype(std::ranges::end(r)), decltype(end(r))>);
105   static_assert(!noexcept(std::ranges::end(r)));
106   VERIFY( std::ranges::end(r) == end(r) );
107 
108   static_assert(same_as<decltype(std::ranges::end(c)), decltype(end(c))>);
109   static_assert(noexcept(std::ranges::end(c)));
110   VERIFY( std::ranges::end(c) == end(c) );
111 
112   RV v{r};
113   static_assert(same_as<decltype(std::ranges::end(std::move(v))),
114 		decltype(end(r))>);
115   static_assert(noexcept(std::ranges::end(std::move(v))));
116   VERIFY( std::ranges::end(std::move(v)) == end(r) );
117 
118   const RV cv{r};
119   static_assert(same_as<decltype(std::ranges::end(std::move(cv))),
120 		decltype(end(c))>);
121   static_assert(!noexcept(std::ranges::end(std::move(cv))));
122   VERIFY( std::ranges::end(std::move(cv)) == end(c) );
123 }
124 
125 struct RR
126 {
127   short s = 0;
128   long l = 0;
129   int a[4] = { 0, 1, 2, 3 };
130 
131   const void* begin() const; // return type not an iterator
132 
133   friend const short* begin(RR&) noexcept;
endRR134   short* end() noexcept { return &s; }
135 
136   friend const long* begin(const RR&) noexcept;
endRR137   const long* end() const { return &l; }
138 
139   friend const int* begin(RR&&) noexcept;
end(RR &)140   friend int* end(RR&) { throw 1; } // not valid for rvalues
end(RR && r)141   friend int* end(RR&& r) { return r.a + 1; }
142 
143   friend const int* begin(const RR&&) noexcept;
end(const RR &)144   friend const int* end(const RR&) { throw 1; } // not valid for rvalues
end(const RR && r)145   friend const int* end(const RR&& r) noexcept { return r.a + 3; }
146 };
147 
148 // N.B. this is a lie, end on an RR rvalue will return a dangling pointer.
149 template<> constexpr bool std::ranges::enable_borrowed_range<RR> = true;
150 
151 void
test04()152 test04()
153 {
154   RR r;
155   const RR& c = r;
156   VERIFY( std::ranges::end(r) == &r.s );
157   static_assert(noexcept(std::ranges::end(r)));
158 
159   VERIFY( std::ranges::end(std::move(r)) == &r.s );
160   static_assert(noexcept(std::ranges::end(std::move(r))));
161 
162   VERIFY( std::ranges::end(c) == &r.l );
163   static_assert(!noexcept(std::ranges::end(c)));
164 
165   VERIFY( std::ranges::end(std::move(c)) == &r.l );
166   static_assert(!noexcept(std::ranges::end(std::move(c))));
167 }
168 
169 int
main()170 main()
171 {
172   test01();
173   test02();
174   test03();
175   test04();
176 }
177