1// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11
2
3namespace value_range_detail {
4  template<typename T>
5  class value_range_iter {
6    T t;
7  public:
8    value_range_iter(const T &t) : t(t) {}
9    T operator*() const { return t; }
10    bool operator!=(const value_range_iter &o) const { return t != o.t; }
11    value_range_iter &operator++() { ++t; return *this; }
12  };
13
14  template<typename T>
15  struct value_range {
16    value_range(const T &a, const T &b) : begin_(a), end_(b) {}
17    value_range_iter<T> begin_, end_;
18  };
19
20  template<typename T>
21  value_range_iter<T> begin(const value_range<T> &r) { return r.begin_; }
22  template<typename T>
23  value_range_iter<T> end(const value_range<T> &r) { return r.end_; }
24
25
26  struct end_t {};
27
28  template<typename T>
29  class value_range_step_iter {
30    T it, step;
31  public:
32    value_range_step_iter(const T &it, const T &step) : it(it), step(step) {}
33    T operator*() const { return it; }
34    bool operator!=(value_range_step_iter end) const { return it != end.it; }
35    value_range_step_iter &operator++() { it += step; return *this; }
36  };
37
38  template<typename T>
39  class value_range_step {
40    T it, step, end_;
41  public:
42    value_range_step(const T &it, const T &end, const T &step) :
43      it(it), end_(end), step(step) {}
44    typedef value_range_step_iter<T> iterator;
45    iterator begin() const { return iterator(it, step); }
46    iterator end() const { return iterator(end_, step); }
47  };
48}
49
50template<typename T>
51value_range_detail::value_range<T> range(const T &a, const T &b) { return value_range_detail::value_range<T>(a, b); }
52
53template<typename T>
54value_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
56
57namespace map_range {
58  template<typename T>
59  class vector {
60    T storage[100];
61    decltype(sizeof(char)) size;
62  public:
63    vector() : size() {}
64    void push_back(T t) { storage[size++] = t; }
65    T *begin() { return storage; }
66    T *end() { return storage + size; }
67  };
68
69  template<typename T> struct tuple_elem {
70    T t;
71    tuple_elem() {}
72    tuple_elem(T t) : t(t) {}
73  };
74  template<typename... A>
75  struct tuple : tuple_elem<A>... {
76    tuple() : tuple_elem<A>()... {}
77    tuple(A... a) : tuple_elem<A>(a)... {}
78    template<typename B> B &get() { return tuple_elem<B>::t; }
79  };
80
81  template<typename F, typename I>
82  class map_iter {
83    F f;
84    I i;
85  public:
86    map_iter(F f, I i) : f(f), i(i) {}
87    auto operator*() const -> decltype(f(*i)) { return f(*i); }
88    bool operator!=(const map_iter &o) const { return i != o.i; }
89    map_iter &operator++() { ++i; return *this; }
90  };
91
92  template<typename T>
93  struct iter_pair {
94    T begin_, end_;
95    iter_pair(T begin, T end) : begin_(begin), end_(end) {}
96  };
97  template<typename T> T begin(iter_pair<T> p) { return p.begin_; }
98  template<typename T> T end(iter_pair<T> p) { return p.end_; }
99
100  template<typename...> class mem_fun_impl;
101  template<typename R, typename T, typename... A>
102  class mem_fun_impl<R (T::*)(A...)> {
103    typedef R (T::*F)(A...);
104    F f;
105  public:
106    mem_fun_impl(F f) : f(f) {}
107    R operator()(T &t, A &&...a) const { return (t.*f)(static_cast<A&&>(a)...); }
108  };
109  template<typename F> mem_fun_impl<F> mem_fun(F f) { return mem_fun_impl<F>(f); }
110
111  template<typename F, typename T>
112  auto map(const F &f, T &t) -> iter_pair<map_iter<F, decltype(t.begin())>> {
113    typedef map_iter<F, decltype(t.begin())> iter;
114    return iter_pair<iter>(iter(f, t.begin()), iter(f, t.end()));
115  }
116}
117
118#define assert(b) if (!(b)) { return 1; }
119int main() {
120  int total = 0;
121
122  for (auto n : range(1, 5)) {
123    total += n;
124  }
125  assert(total == 10);
126
127  for (auto n : range(10, 100, 10)) {
128    total += n;
129  }
130  assert(total == 460);
131
132  map_range::vector<char> chars;
133  chars.push_back('a');
134  chars.push_back('b');
135  chars.push_back('c');
136  for (char c : chars) {
137    ++total;
138  }
139  assert(total == 463);
140
141  typedef map_range::tuple<int, double> T;
142  map_range::vector<T> pairs;
143  pairs.push_back(T(42, 12.9));
144  pairs.push_back(T(6, 4.2));
145  pairs.push_back(T(9, 1.1));
146  for (auto a : map(map_range::mem_fun(&T::get<int>), pairs)) {
147    total += a;
148  }
149  assert(total == 500);
150}
151
152// PR11793
153namespace test2 {
154  class A {
155    int xs[10]; // expected-note {{implicitly declared private here}}
156  };
157  void test(A &a) {
158    for (int x : a.xs) { } // expected-error {{'xs' is a private member of 'test2::A'}}
159  }
160}
161
162namespace test3 {
163  // Make sure this doesn't crash
164  struct A {};
165  struct B { ~B(); operator bool(); };
166  struct C { B operator!=(const C&); C& operator++(); int operator*(); };
167  C begin(const A&);
168  C end(const A&);
169  template<typename T> void f() { for (auto a : A()) {} }
170  void g() { f<int>(); }
171}
172
173namespace test4 {
174  void f() {
175    int y;
176
177    // Make sure these don't crash. Better diagnostics would be nice.
178    for (: {1, 2, 3}) {} // expected-error {{expected expression}} expected-error {{expected ';'}}
179    for (1 : {1, 2, 3}) {} // expected-error {{must declare a variable}} expected-warning {{result unused}}
180    for (+x : {1, 2, 3}) {} // expected-error {{undeclared identifier}} expected-error {{expected ';'}}
181    for (+y : {1, 2, 3}) {} // expected-error {{must declare a variable}} expected-warning {{result unused}}
182  }
183}
184
185namespace test5 {
186  // Test error-recovery.
187  void f() {
188    for (auto x : undeclared_identifier) // expected-error {{undeclared identifier}}
189      for (auto y : x->foo)
190        y->bar();
191    for (auto x : 123) // expected-error {{no viable 'begin'}}
192      x->foo();
193  }
194}
195
196namespace test6 {
197  void foo(int arr[]) {  // expected-note {{declared here}}
198    for (auto i : arr) { }
199      // 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  }
201
202  struct vector {
203    int *begin() { return 0; }
204    int *end() { return 0; }
205  };
206
207  void foo(vector arr[]) {  // expected-note {{declared here}}
208    // Don't suggest to dereference arr.
209    for (auto i : arr) { }
210      // 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  }
212}
213
214namespace test7 {
215  void f() {
216    int arr[5], b;
217    for (a : arr) {} // expected-warning {{extension}}
218    // FIXME: Give a -Wshadow for this by default?
219    for (b : arr) {} // expected-warning {{extension}}
220    for (arr : arr) {} // expected-warning {{extension}}
221    for (c alignas(8) : arr) { // expected-warning {{extension}}
222      static_assert(alignof(c) == 8, ""); // expected-warning {{extension}}
223    }
224    // FIXME: We should reject this, but don't, because we only check the
225    // attribute before we deduce the 'auto' type.
226    for (d alignas(1) : arr) {} // expected-warning {{extension}}
227    for (e [[deprecated]] : arr) { e = 0; } // expected-warning {{deprecated}} expected-note {{here}} expected-warning {{extension}}
228  }
229}
230