1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 // UNSUPPORTED: c++03
10
11 // <iterator>
12 // template <class C> constexpr auto begin(C& c) -> decltype(c.begin());
13 // template <class C> constexpr auto begin(const C& c) -> decltype(c.begin());
14 // template <class C> constexpr auto cbegin(const C& c) -> decltype(std::begin(c)); // C++14
15 // template <class C> constexpr auto cend(const C& c) -> decltype(std::end(c)); // C++14
16 // template <class C> constexpr auto end (C& c) -> decltype(c.end());
17 // template <class C> constexpr auto end (const C& c) -> decltype(c.end());
18 // template <class E> constexpr reverse_iterator<const E*> rbegin(initializer_list<E> il);
19 // template <class E> constexpr reverse_iterator<const E*> rend (initializer_list<E> il);
20 //
21 // template <class C> auto constexpr rbegin(C& c) -> decltype(c.rbegin()); // C++14
22 // template <class C> auto constexpr rbegin(const C& c) -> decltype(c.rbegin()); // C++14
23 // template <class C> auto constexpr rend(C& c) -> decltype(c.rend()); // C++14
24 // template <class C> constexpr auto rend(const C& c) -> decltype(c.rend()); // C++14
25 // template <class T, size_t N> reverse_iterator<T*> constexpr rbegin(T (&array)[N]); // C++14
26 // template <class T, size_t N> reverse_iterator<T*> constexpr rend(T (&array)[N]); // C++14
27 // template <class C> constexpr auto crbegin(const C& c) -> decltype(std::rbegin(c)); // C++14
28 // template <class C> constexpr auto crend(const C& c) -> decltype(std::rend(c)); // C++14
29 //
30 // All of these are constexpr in C++17
31
32 #include <array>
33 #include <cassert>
34 #include <initializer_list>
35 #include <iterator>
36 #include <list>
37 #include <vector>
38
39 #include "test_macros.h"
40
41 // Throughout this test, we consistently compare against c.begin() instead of c.cbegin()
42 // because some STL types (e.g. initializer_list) don't syntactically support il.cbegin().
43 // Note that std::cbegin(x) effectively calls std::as_const(x).begin(), not x.cbegin();
44 // see the ContainerHijacker test case below.
45
test_arrays_and_initializer_lists_forward()46 TEST_CONSTEXPR_CXX14 bool test_arrays_and_initializer_lists_forward()
47 {
48 {
49 int a[] = {1, 2, 3};
50 ASSERT_SAME_TYPE(decltype(std::begin(a)), int*);
51 ASSERT_SAME_TYPE(decltype(std::end(a)), int*);
52 assert(std::begin(a) == a);
53 assert(std::end(a) == a + 3);
54 #if TEST_STD_VER > 11
55 ASSERT_SAME_TYPE(decltype(std::cbegin(a)), const int*);
56 ASSERT_SAME_TYPE(decltype(std::cend(a)), const int*);
57 assert(std::cbegin(a) == a);
58 assert(std::cend(a) == a + 3);
59 #endif
60
61 const auto& ca = a;
62 ASSERT_SAME_TYPE(decltype(std::begin(ca)), const int*);
63 ASSERT_SAME_TYPE(decltype(std::end(ca)), const int*);
64 assert(std::begin(ca) == a);
65 assert(std::end(ca) == a + 3);
66 #if TEST_STD_VER > 11
67 ASSERT_SAME_TYPE(decltype(std::cbegin(ca)), const int*);
68 ASSERT_SAME_TYPE(decltype(std::cend(ca)), const int*);
69 assert(std::cbegin(ca) == a);
70 assert(std::cend(ca) == a + 3);
71 #endif
72 }
73 {
74 std::initializer_list<int> il = {1, 2, 3};
75 ASSERT_SAME_TYPE(decltype(std::begin(il)), const int*);
76 ASSERT_SAME_TYPE(decltype(std::end(il)), const int*);
77 assert(std::begin(il) == il.begin());
78 assert(std::end(il) == il.end());
79 #if TEST_STD_VER > 11
80 ASSERT_SAME_TYPE(decltype(std::cbegin(il)), const int*);
81 ASSERT_SAME_TYPE(decltype(std::cend(il)), const int*);
82 assert(std::cbegin(il) == il.begin());
83 assert(std::cend(il) == il.end());
84 #endif
85
86 const auto& cil = il;
87 ASSERT_SAME_TYPE(decltype(std::begin(cil)), const int*);
88 ASSERT_SAME_TYPE(decltype(std::end(cil)), const int*);
89 assert(std::begin(cil) == il.begin());
90 assert(std::end(cil) == il.end());
91 #if TEST_STD_VER > 11
92 ASSERT_SAME_TYPE(decltype(std::cbegin(cil)), const int*);
93 ASSERT_SAME_TYPE(decltype(std::cend(cil)), const int*);
94 assert(std::cbegin(cil) == il.begin());
95 assert(std::cend(cil) == il.end());
96 #endif
97 }
98 return true;
99 }
100
101 #if TEST_STD_VER > 11
test_arrays_and_initializer_lists_backward()102 TEST_CONSTEXPR_CXX17 bool test_arrays_and_initializer_lists_backward()
103 {
104 {
105 int a[] = {1, 2, 3};
106 ASSERT_SAME_TYPE(decltype(std::rbegin(a)), std::reverse_iterator<int*>);
107 ASSERT_SAME_TYPE(decltype(std::rend(a)), std::reverse_iterator<int*>);
108 assert(std::rbegin(a).base() == a + 3);
109 assert(std::rend(a).base() == a);
110 ASSERT_SAME_TYPE(decltype(std::crbegin(a)), std::reverse_iterator<const int*>);
111 ASSERT_SAME_TYPE(decltype(std::crend(a)), std::reverse_iterator<const int*>);
112 assert(std::crbegin(a).base() == a + 3);
113 assert(std::crend(a).base() == a);
114
115 const auto& ca = a;
116 ASSERT_SAME_TYPE(decltype(std::rbegin(ca)), std::reverse_iterator<const int*>);
117 ASSERT_SAME_TYPE(decltype(std::rend(ca)), std::reverse_iterator<const int*>);
118 assert(std::rbegin(ca).base() == a + 3);
119 assert(std::rend(ca).base() == a);
120 ASSERT_SAME_TYPE(decltype(std::crbegin(ca)), std::reverse_iterator<const int*>);
121 ASSERT_SAME_TYPE(decltype(std::crend(ca)), std::reverse_iterator<const int*>);
122 assert(std::crbegin(ca).base() == a + 3);
123 assert(std::crend(ca).base() == a);
124 }
125 {
126 std::initializer_list<int> il = {1, 2, 3};
127 ASSERT_SAME_TYPE(decltype(std::rbegin(il)), std::reverse_iterator<const int*>);
128 ASSERT_SAME_TYPE(decltype(std::rend(il)), std::reverse_iterator<const int*>);
129 assert(std::rbegin(il).base() == il.end());
130 assert(std::rend(il).base() == il.begin());
131 ASSERT_SAME_TYPE(decltype(std::crbegin(il)), std::reverse_iterator<const int*>);
132 ASSERT_SAME_TYPE(decltype(std::crend(il)), std::reverse_iterator<const int*>);
133 assert(std::crbegin(il).base() == il.end());
134 assert(std::crend(il).base() == il.begin());
135
136 const auto& cil = il;
137 ASSERT_SAME_TYPE(decltype(std::rbegin(cil)), std::reverse_iterator<const int*>);
138 ASSERT_SAME_TYPE(decltype(std::rend(cil)), std::reverse_iterator<const int*>);
139 assert(std::rbegin(cil).base() == il.end());
140 assert(std::rend(cil).base() == il.begin());
141 ASSERT_SAME_TYPE(decltype(std::crbegin(cil)), std::reverse_iterator<const int*>);
142 ASSERT_SAME_TYPE(decltype(std::crend(cil)), std::reverse_iterator<const int*>);
143 assert(std::crbegin(cil).base() == il.end());
144 assert(std::crend(cil).base() == il.begin());
145 }
146 return true;
147 }
148 #endif
149
150 template<typename C>
test_container()151 TEST_CONSTEXPR_CXX14 bool test_container() {
152 C c = {1, 2, 3};
153 ASSERT_SAME_TYPE(decltype(std::begin(c)), typename C::iterator);
154 ASSERT_SAME_TYPE(decltype(std::end(c)), typename C::iterator);
155 assert(std::begin(c) == c.begin());
156 assert(std::end(c) == c.end());
157 #if TEST_STD_VER > 11
158 ASSERT_SAME_TYPE(decltype(std::cbegin(c)), typename C::const_iterator);
159 ASSERT_SAME_TYPE(decltype(std::cend(c)), typename C::const_iterator);
160 assert(std::cbegin(c) == c.begin());
161 assert(std::cend(c) == c.end());
162 ASSERT_SAME_TYPE(decltype(std::rbegin(c)), typename C::reverse_iterator);
163 ASSERT_SAME_TYPE(decltype(std::rend(c)), typename C::reverse_iterator);
164 assert(std::rbegin(c).base() == c.end());
165 assert(std::rend(c).base() == c.begin());
166 ASSERT_SAME_TYPE(decltype(std::crbegin(c)), typename C::const_reverse_iterator);
167 ASSERT_SAME_TYPE(decltype(std::crend(c)), typename C::const_reverse_iterator);
168 assert(std::crbegin(c).base() == c.end());
169 assert(std::crend(c).base() == c.begin());
170 #endif
171
172 const C& cc = c;
173 ASSERT_SAME_TYPE(decltype(std::begin(cc)), typename C::const_iterator);
174 ASSERT_SAME_TYPE(decltype(std::end(cc)), typename C::const_iterator);
175 assert(std::begin(cc) == c.begin());
176 assert(std::end(cc) == c.end());
177 #if TEST_STD_VER > 11
178 ASSERT_SAME_TYPE(decltype(std::cbegin(cc)), typename C::const_iterator);
179 ASSERT_SAME_TYPE(decltype(std::cend(cc)), typename C::const_iterator);
180 assert(std::cbegin(cc) == c.begin());
181 assert(std::cend(cc) == c.end());
182 ASSERT_SAME_TYPE(decltype(std::rbegin(cc)), typename C::const_reverse_iterator);
183 ASSERT_SAME_TYPE(decltype(std::rend(cc)), typename C::const_reverse_iterator);
184 assert(std::rbegin(cc).base() == c.end());
185 assert(std::rend(cc).base() == c.begin());
186 ASSERT_SAME_TYPE(decltype(std::crbegin(cc)), typename C::const_reverse_iterator);
187 ASSERT_SAME_TYPE(decltype(std::crend(cc)), typename C::const_reverse_iterator);
188 assert(std::crbegin(cc).base() == c.end());
189 assert(std::crend(cc).base() == c.begin());
190 #endif
191
192 return true;
193 }
194
195 struct ArrayHijacker {
begin(ArrayHijacker (&)[3])196 friend constexpr int begin(ArrayHijacker(&)[3]) { return 42; }
end(ArrayHijacker (&)[3])197 friend constexpr int end(ArrayHijacker(&)[3]) { return 42; }
begin(const ArrayHijacker (&)[3])198 friend constexpr int begin(const ArrayHijacker(&)[3]) { return 42; }
end(const ArrayHijacker (&)[3])199 friend constexpr int end(const ArrayHijacker(&)[3]) { return 42; }
200 };
201
202 struct ContainerHijacker {
203 int *a_;
beginContainerHijacker204 constexpr int *begin() const { return a_; }
endContainerHijacker205 constexpr int *end() const { return a_ + 3; }
rbeginContainerHijacker206 constexpr int *rbegin() const { return a_; }
rendContainerHijacker207 constexpr int *rend() const { return a_ + 3; }
begin(ContainerHijacker &)208 friend constexpr int begin(ContainerHijacker&) { return 42; }
end(ContainerHijacker &)209 friend constexpr int end(ContainerHijacker&) { return 42; }
begin(const ContainerHijacker &)210 friend constexpr int begin(const ContainerHijacker&) { return 42; }
end(const ContainerHijacker &)211 friend constexpr int end(const ContainerHijacker&) { return 42; }
cbegin(ContainerHijacker &)212 friend constexpr int cbegin(ContainerHijacker&) { return 42; }
cend(ContainerHijacker &)213 friend constexpr int cend(ContainerHijacker&) { return 42; }
cbegin(const ContainerHijacker &)214 friend constexpr int cbegin(const ContainerHijacker&) { return 42; }
cend(const ContainerHijacker &)215 friend constexpr int cend(const ContainerHijacker&) { return 42; }
rbegin(ContainerHijacker &)216 friend constexpr int rbegin(ContainerHijacker&) { return 42; }
rend(ContainerHijacker &)217 friend constexpr int rend(ContainerHijacker&) { return 42; }
rbegin(const ContainerHijacker &)218 friend constexpr int rbegin(const ContainerHijacker&) { return 42; }
rend(const ContainerHijacker &)219 friend constexpr int rend(const ContainerHijacker&) { return 42; }
crbegin(ContainerHijacker &)220 friend constexpr int crbegin(ContainerHijacker&) { return 42; }
crend(ContainerHijacker &)221 friend constexpr int crend(ContainerHijacker&) { return 42; }
crbegin(const ContainerHijacker &)222 friend constexpr int crbegin(const ContainerHijacker&) { return 42; }
crend(const ContainerHijacker &)223 friend constexpr int crend(const ContainerHijacker&) { return 42; }
224 };
225
test_adl_proofing()226 TEST_CONSTEXPR_CXX17 bool test_adl_proofing() {
227 // https://llvm.org/PR28927
228 {
229 ArrayHijacker a[3] = {};
230 assert(begin(a) == 42);
231 assert(end(a) == 42);
232 assert(std::begin(a) == a);
233 assert(std::end(a) == a + 3);
234 #if TEST_STD_VER > 11
235 assert(std::cbegin(a) == a);
236 assert(std::cend(a) == a + 3);
237 assert(std::rbegin(a).base() == a + 3);
238 assert(std::rend(a).base() == a);
239 assert(std::crbegin(a).base() == a + 3);
240 assert(std::crend(a).base() == a);
241 #endif
242 }
243 {
244 int a[3] = {};
245 ContainerHijacker c{a};
246 assert(begin(c) == 42);
247 assert(end(c) == 42);
248 assert(std::begin(c) == a);
249 assert(std::end(c) == a + 3);
250 #if TEST_STD_VER > 11
251 assert(std::cbegin(c) == a);
252 assert(std::cend(c) == a + 3);
253 assert(std::rbegin(c) == a);
254 assert(std::rend(c) == a + 3);
255 assert(std::crbegin(c) == a);
256 assert(std::crend(c) == a + 3);
257 #endif
258 }
259 return true;
260 }
261
main(int,char **)262 int main(int, char**) {
263 test_arrays_and_initializer_lists_forward();
264 #if TEST_STD_VER > 11
265 test_arrays_and_initializer_lists_backward();
266 #endif
267 test_container<std::array<int, 3>>();
268 test_container<std::list<int>>();
269 test_container<std::vector<int>>();
270 test_adl_proofing();
271
272 #if TEST_STD_VER > 11
273 static_assert(test_arrays_and_initializer_lists_forward(), "");
274 #endif
275 #if TEST_STD_VER > 14
276 static_assert(test_arrays_and_initializer_lists_backward());
277 static_assert(test_container<std::array<int, 3>>());
278 static_assert(test_adl_proofing());
279 #endif
280
281 return 0;
282 }
283