1*67e74705SXin Li // RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11
2*67e74705SXin Li
3*67e74705SXin Li namespace value_range_detail {
4*67e74705SXin Li template<typename T>
5*67e74705SXin Li class value_range_iter {
6*67e74705SXin Li T t;
7*67e74705SXin Li public:
value_range_iter(const T & t)8*67e74705SXin Li value_range_iter(const T &t) : t(t) {}
operator *() const9*67e74705SXin Li T operator*() const { return t; }
operator !=(const value_range_iter & o) const10*67e74705SXin Li bool operator!=(const value_range_iter &o) const { return t != o.t; }
operator ++()11*67e74705SXin Li value_range_iter &operator++() { ++t; return *this; }
12*67e74705SXin Li };
13*67e74705SXin Li
14*67e74705SXin Li template<typename T>
15*67e74705SXin Li struct value_range {
value_rangevalue_range_detail::value_range16*67e74705SXin Li value_range(const T &a, const T &b) : begin_(a), end_(b) {}
17*67e74705SXin Li value_range_iter<T> begin_, end_;
18*67e74705SXin Li };
19*67e74705SXin Li
20*67e74705SXin Li template<typename T>
begin(const value_range<T> & r)21*67e74705SXin Li value_range_iter<T> begin(const value_range<T> &r) { return r.begin_; }
22*67e74705SXin Li template<typename T>
end(const value_range<T> & r)23*67e74705SXin Li value_range_iter<T> end(const value_range<T> &r) { return r.end_; }
24*67e74705SXin Li
25*67e74705SXin Li
26*67e74705SXin Li struct end_t {};
27*67e74705SXin Li
28*67e74705SXin Li template<typename T>
29*67e74705SXin Li class value_range_step_iter {
30*67e74705SXin Li T it, step;
31*67e74705SXin Li public:
value_range_step_iter(const T & it,const T & step)32*67e74705SXin Li value_range_step_iter(const T &it, const T &step) : it(it), step(step) {}
operator *() const33*67e74705SXin Li T operator*() const { return it; }
operator !=(value_range_step_iter end) const34*67e74705SXin Li bool operator!=(value_range_step_iter end) const { return it != end.it; }
operator ++()35*67e74705SXin Li value_range_step_iter &operator++() { it += step; return *this; }
36*67e74705SXin Li };
37*67e74705SXin Li
38*67e74705SXin Li template<typename T>
39*67e74705SXin Li class value_range_step {
40*67e74705SXin Li T it, step, end_;
41*67e74705SXin Li public:
value_range_step(const T & it,const T & end,const T & step)42*67e74705SXin Li value_range_step(const T &it, const T &end, const T &step) :
43*67e74705SXin Li it(it), end_(end), step(step) {}
44*67e74705SXin Li typedef value_range_step_iter<T> iterator;
begin() const45*67e74705SXin Li iterator begin() const { return iterator(it, step); }
end() const46*67e74705SXin Li iterator end() const { return iterator(end_, step); }
47*67e74705SXin Li };
48*67e74705SXin Li }
49*67e74705SXin Li
50*67e74705SXin Li template<typename T>
range(const T & a,const T & b)51*67e74705SXin Li value_range_detail::value_range<T> range(const T &a, const T &b) { return value_range_detail::value_range<T>(a, b); }
52*67e74705SXin Li
53*67e74705SXin Li template<typename T>
range(const T & a,const T & b,const T & step)54*67e74705SXin Li value_range_detail::value_range_step<T> range(const T &a, const T &b, const T &step) { return value_range_detail::value_range_step<T>(a, b, step); }
55*67e74705SXin Li
56*67e74705SXin Li
57*67e74705SXin Li namespace map_range {
58*67e74705SXin Li template<typename T>
59*67e74705SXin Li class vector {
60*67e74705SXin Li T storage[100];
61*67e74705SXin Li decltype(sizeof(char)) size;
62*67e74705SXin Li public:
vector()63*67e74705SXin Li vector() : size() {}
push_back(T t)64*67e74705SXin Li void push_back(T t) { storage[size++] = t; }
begin()65*67e74705SXin Li T *begin() { return storage; }
end()66*67e74705SXin Li T *end() { return storage + size; }
67*67e74705SXin Li };
68*67e74705SXin Li
69*67e74705SXin Li template<typename T> struct tuple_elem {
70*67e74705SXin Li T t;
tuple_elemmap_range::tuple_elem71*67e74705SXin Li tuple_elem() {}
tuple_elemmap_range::tuple_elem72*67e74705SXin Li tuple_elem(T t) : t(t) {}
73*67e74705SXin Li };
74*67e74705SXin Li template<typename... A>
75*67e74705SXin Li struct tuple : tuple_elem<A>... {
tuplemap_range::tuple76*67e74705SXin Li tuple() : tuple_elem<A>()... {}
tuplemap_range::tuple77*67e74705SXin Li tuple(A... a) : tuple_elem<A>(a)... {}
getmap_range::tuple78*67e74705SXin Li template<typename B> B &get() { return tuple_elem<B>::t; }
79*67e74705SXin Li };
80*67e74705SXin Li
81*67e74705SXin Li template<typename F, typename I>
82*67e74705SXin Li class map_iter {
83*67e74705SXin Li F f;
84*67e74705SXin Li I i;
85*67e74705SXin Li public:
map_iter(F f,I i)86*67e74705SXin Li map_iter(F f, I i) : f(f), i(i) {}
operator *() const87*67e74705SXin Li auto operator*() const -> decltype(f(*i)) { return f(*i); }
operator !=(const map_iter & o) const88*67e74705SXin Li bool operator!=(const map_iter &o) const { return i != o.i; }
operator ++()89*67e74705SXin Li map_iter &operator++() { ++i; return *this; }
90*67e74705SXin Li };
91*67e74705SXin Li
92*67e74705SXin Li template<typename T>
93*67e74705SXin Li struct iter_pair {
94*67e74705SXin Li T begin_, end_;
iter_pairmap_range::iter_pair95*67e74705SXin Li iter_pair(T begin, T end) : begin_(begin), end_(end) {}
96*67e74705SXin Li };
begin(iter_pair<T> p)97*67e74705SXin Li template<typename T> T begin(iter_pair<T> p) { return p.begin_; }
end(iter_pair<T> p)98*67e74705SXin Li template<typename T> T end(iter_pair<T> p) { return p.end_; }
99*67e74705SXin Li
100*67e74705SXin Li template<typename...> class mem_fun_impl;
101*67e74705SXin Li template<typename R, typename T, typename... A>
102*67e74705SXin Li class mem_fun_impl<R (T::*)(A...)> {
103*67e74705SXin Li typedef R (T::*F)(A...);
104*67e74705SXin Li F f;
105*67e74705SXin Li public:
mem_fun_impl(F f)106*67e74705SXin Li mem_fun_impl(F f) : f(f) {}
operator ()(T & t,A &&...a) const107*67e74705SXin Li R operator()(T &t, A &&...a) const { return (t.*f)(static_cast<A&&>(a)...); }
108*67e74705SXin Li };
mem_fun(F f)109*67e74705SXin Li template<typename F> mem_fun_impl<F> mem_fun(F f) { return mem_fun_impl<F>(f); }
110*67e74705SXin Li
111*67e74705SXin Li template<typename F, typename T>
map(const F & f,T & t)112*67e74705SXin Li auto map(const F &f, T &t) -> iter_pair<map_iter<F, decltype(t.begin())>> {
113*67e74705SXin Li typedef map_iter<F, decltype(t.begin())> iter;
114*67e74705SXin Li return iter_pair<iter>(iter(f, t.begin()), iter(f, t.end()));
115*67e74705SXin Li }
116*67e74705SXin Li }
117*67e74705SXin Li
118*67e74705SXin Li #define assert(b) if (!(b)) { return 1; }
main()119*67e74705SXin Li int main() {
120*67e74705SXin Li int total = 0;
121*67e74705SXin Li
122*67e74705SXin Li for (auto n : range(1, 5)) {
123*67e74705SXin Li total += n;
124*67e74705SXin Li }
125*67e74705SXin Li assert(total == 10);
126*67e74705SXin Li
127*67e74705SXin Li for (auto n : range(10, 100, 10)) {
128*67e74705SXin Li total += n;
129*67e74705SXin Li }
130*67e74705SXin Li assert(total == 460);
131*67e74705SXin Li
132*67e74705SXin Li map_range::vector<char> chars;
133*67e74705SXin Li chars.push_back('a');
134*67e74705SXin Li chars.push_back('b');
135*67e74705SXin Li chars.push_back('c');
136*67e74705SXin Li for (char c : chars) {
137*67e74705SXin Li ++total;
138*67e74705SXin Li }
139*67e74705SXin Li assert(total == 463);
140*67e74705SXin Li
141*67e74705SXin Li typedef map_range::tuple<int, double> T;
142*67e74705SXin Li map_range::vector<T> pairs;
143*67e74705SXin Li pairs.push_back(T(42, 12.9));
144*67e74705SXin Li pairs.push_back(T(6, 4.2));
145*67e74705SXin Li pairs.push_back(T(9, 1.1));
146*67e74705SXin Li for (auto a : map(map_range::mem_fun(&T::get<int>), pairs)) {
147*67e74705SXin Li total += a;
148*67e74705SXin Li }
149*67e74705SXin Li assert(total == 500);
150*67e74705SXin Li }
151*67e74705SXin Li
152*67e74705SXin Li // PR11793
153*67e74705SXin Li namespace test2 {
154*67e74705SXin Li class A {
155*67e74705SXin Li int xs[10]; // expected-note {{implicitly declared private here}}
156*67e74705SXin Li };
test(A & a)157*67e74705SXin Li void test(A &a) {
158*67e74705SXin Li for (int x : a.xs) { } // expected-error {{'xs' is a private member of 'test2::A'}}
159*67e74705SXin Li }
160*67e74705SXin Li }
161*67e74705SXin Li
162*67e74705SXin Li namespace test3 {
163*67e74705SXin Li // Make sure this doesn't crash
164*67e74705SXin Li struct A {};
165*67e74705SXin Li struct B { ~B(); operator bool(); };
166*67e74705SXin Li struct C { B operator!=(const C&); C& operator++(); int operator*(); };
167*67e74705SXin Li C begin(const A&);
168*67e74705SXin Li C end(const A&);
f()169*67e74705SXin Li template<typename T> void f() { for (auto a : A()) {} }
g()170*67e74705SXin Li void g() { f<int>(); }
171*67e74705SXin Li }
172*67e74705SXin Li
173*67e74705SXin Li namespace test4 {
f()174*67e74705SXin Li void f() {
175*67e74705SXin Li int y;
176*67e74705SXin Li
177*67e74705SXin Li // Make sure these don't crash. Better diagnostics would be nice.
178*67e74705SXin Li for (: {1, 2, 3}) {} // expected-error {{expected expression}} expected-error {{expected ';'}}
179*67e74705SXin Li for (1 : {1, 2, 3}) {} // expected-error {{must declare a variable}}
180*67e74705SXin Li for (+x : {1, 2, 3}) {} // expected-error {{undeclared identifier}} expected-error {{expected ';'}}
181*67e74705SXin Li for (+y : {1, 2, 3}) {} // expected-error {{must declare a variable}}
182*67e74705SXin Li }
183*67e74705SXin Li }
184*67e74705SXin Li
185*67e74705SXin Li namespace test5 {
186*67e74705SXin Li // Test error-recovery.
f()187*67e74705SXin Li void f() {
188*67e74705SXin Li for (auto x : undeclared_identifier) // expected-error {{undeclared identifier}}
189*67e74705SXin Li for (auto y : x->foo)
190*67e74705SXin Li y->bar();
191*67e74705SXin Li for (auto x : 123) // expected-error {{no viable 'begin'}}
192*67e74705SXin Li x->foo();
193*67e74705SXin Li }
194*67e74705SXin Li }
195*67e74705SXin Li
196*67e74705SXin Li namespace test6 {
foo(int arr[])197*67e74705SXin Li void foo(int arr[]) { // expected-note {{declared here}}
198*67e74705SXin Li for (auto i : arr) { }
199*67e74705SXin Li // expected-error@-1 {{cannot build range expression with array function parameter 'arr' since parameter with array type 'int []' is treated as pointer type 'int *'}}
200*67e74705SXin Li }
201*67e74705SXin Li
202*67e74705SXin Li struct vector {
begintest6::vector203*67e74705SXin Li int *begin() { return 0; }
endtest6::vector204*67e74705SXin Li int *end() { return 0; }
205*67e74705SXin Li };
206*67e74705SXin Li
foo(vector arr[])207*67e74705SXin Li void foo(vector arr[]) { // expected-note {{declared here}}
208*67e74705SXin Li // Don't suggest to dereference arr.
209*67e74705SXin Li for (auto i : arr) { }
210*67e74705SXin Li // expected-error@-1 {{cannot build range expression with array function parameter 'arr' since parameter with array type 'test6::vector []' is treated as pointer type 'test6::vector *'}}
211*67e74705SXin Li }
212*67e74705SXin Li }
213*67e74705SXin Li
214*67e74705SXin Li namespace test7 {
f()215*67e74705SXin Li void f() {
216*67e74705SXin Li int arr[5], b;
217*67e74705SXin Li for (a : arr) {} // expected-error {{requires type for loop variable}}
218*67e74705SXin Li // FIXME: Give a different error in this case?
219*67e74705SXin Li for (b : arr) {} // expected-error {{requires type for loop variable}}
220*67e74705SXin Li for (arr : arr) {} // expected-error {{requires type for loop variable}}
221*67e74705SXin Li for (c alignas(8) : arr) { // expected-error {{requires type for loop variable}}
222*67e74705SXin Li static_assert(alignof(c) == 8, ""); // expected-warning {{extension}}
223*67e74705SXin Li }
224*67e74705SXin Li // FIXME: The fix-it hint here is not sufficient to fix the error.
225*67e74705SXin Li // We fail to diagnose that d is underaligned for its type, because
226*67e74705SXin Li // we check the alignment attribute before we perform the auto
227*67e74705SXin Li // deduction.
228*67e74705SXin Li for (d alignas(1) : arr) {} // expected-error {{requires type for loop variable}}
229*67e74705SXin Li for (e [[deprecated]] : arr) { e = 0; } // expected-warning {{deprecated}} expected-note {{here}} expected-error {{requires type for loop variable}}
230*67e74705SXin Li }
231*67e74705SXin Li }
232*67e74705SXin Li
233*67e74705SXin Li namespace pr18587 {
234*67e74705SXin Li class Arg {};
235*67e74705SXin Li struct Cont {
236*67e74705SXin Li int *begin();
237*67e74705SXin Li int *end();
238*67e74705SXin Li };
AddAllArgs(Cont & x)239*67e74705SXin Li void AddAllArgs(Cont &x) {
240*67e74705SXin Li for (auto Arg: x) {
241*67e74705SXin Li }
242*67e74705SXin Li }
243*67e74705SXin Li }
244