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