• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11
2 
3 namespace value_range_detail {
4   template<typename T>
5   class value_range_iter {
6     T t;
7   public:
value_range_iter(const T & t)8     value_range_iter(const T &t) : t(t) {}
operator *() const9     T operator*() const { return t; }
operator !=(const value_range_iter & o) const10     bool operator!=(const value_range_iter &o) const { return t != o.t; }
operator ++()11     value_range_iter &operator++() { ++t; return *this; }
12   };
13 
14   template<typename T>
15   struct value_range {
value_rangevalue_range_detail::value_range16     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>
begin(const value_range<T> & r)21   value_range_iter<T> begin(const value_range<T> &r) { return r.begin_; }
22   template<typename T>
end(const value_range<T> & r)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:
value_range_step_iter(const T & it,const T & step)32     value_range_step_iter(const T &it, const T &step) : it(it), step(step) {}
operator *() const33     T operator*() const { return it; }
operator !=(value_range_step_iter end) const34     bool operator!=(value_range_step_iter end) const { return it != end.it; }
operator ++()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:
value_range_step(const T & it,const T & end,const T & step)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;
begin() const45     iterator begin() const { return iterator(it, step); }
end() const46     iterator end() const { return iterator(end_, step); }
47   };
48 }
49 
50 template<typename T>
range(const T & a,const T & b)51 value_range_detail::value_range<T> range(const T &a, const T &b) { return value_range_detail::value_range<T>(a, b); }
52 
53 template<typename T>
range(const T & a,const T & b,const T & step)54 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 
56 
57 namespace map_range {
58   template<typename T>
59   class vector {
60     T storage[100];
61     decltype(sizeof(char)) size;
62   public:
vector()63     vector() : size() {}
push_back(T t)64     void push_back(T t) { storage[size++] = t; }
begin()65     T *begin() { return storage; }
end()66     T *end() { return storage + size; }
67   };
68 
69   template<typename T> struct tuple_elem {
70     T t;
tuple_elemmap_range::tuple_elem71     tuple_elem() {}
tuple_elemmap_range::tuple_elem72     tuple_elem(T t) : t(t) {}
73   };
74   template<typename... A>
75   struct tuple : tuple_elem<A>... {
tuplemap_range::tuple76     tuple() : tuple_elem<A>()... {}
tuplemap_range::tuple77     tuple(A... a) : tuple_elem<A>(a)... {}
getmap_range::tuple78     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:
map_iter(F f,I i)86     map_iter(F f, I i) : f(f), i(i) {}
operator *() const87     auto operator*() const -> decltype(f(*i)) { return f(*i); }
operator !=(const map_iter & o) const88     bool operator!=(const map_iter &o) const { return i != o.i; }
operator ++()89     map_iter &operator++() { ++i; return *this; }
90   };
91 
92   template<typename T>
93   struct iter_pair {
94     T begin_, end_;
iter_pairmap_range::iter_pair95     iter_pair(T begin, T end) : begin_(begin), end_(end) {}
96   };
begin(iter_pair<T> p)97   template<typename T> T begin(iter_pair<T> p) { return p.begin_; }
end(iter_pair<T> p)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:
mem_fun_impl(F f)106     mem_fun_impl(F f) : f(f) {}
operator ()(T & t,A &&...a) const107     R operator()(T &t, A &&...a) const { return (t.*f)(static_cast<A&&>(a)...); }
108   };
mem_fun(F f)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>
map(const F & f,T & 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; }
main()119 int 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
153 namespace test2 {
154   class A {
155     int xs[10]; // expected-note {{implicitly declared private here}}
156   };
test(A & a)157   void test(A &a) {
158     for (int x : a.xs) { } // expected-error {{'xs' is a private member of 'test2::A'}}
159   }
160 }
161 
162 namespace 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&);
f()169   template<typename T> void f() { for (auto a : A()) {} }
g()170   void g() { f<int>(); }
171 }
172 
173 namespace test4 {
f()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}}
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}}
182   }
183 }
184 
185 namespace test5 {
186   // Test error-recovery.
f()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 
196 namespace test6 {
foo(int arr[])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 {
begintest6::vector203     int *begin() { return 0; }
endtest6::vector204     int *end() { return 0; }
205   };
206 
foo(vector arr[])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 
214 namespace test7 {
f()215   void f() {
216     int arr[5], b;
217     for (a : arr) {} // expected-error {{requires type for loop variable}}
218     // FIXME: Give a different error in this case?
219     for (b : arr) {} // expected-error {{requires type for loop variable}}
220     for (arr : arr) {} // expected-error {{requires type for loop variable}}
221     for (c alignas(8) : arr) { // expected-error {{requires type for loop variable}}
222       static_assert(alignof(c) == 8, ""); // expected-warning {{extension}}
223     }
224     // FIXME: The fix-it hint here is not sufficient to fix the error.
225     // We fail to diagnose that d is underaligned for its type, because
226     // we check the alignment attribute before we perform the auto
227     // deduction.
228     for (d alignas(1) : arr) {} // expected-error {{requires type for loop variable}}
229     for (e [[deprecated]] : arr) { e = 0; } // expected-warning {{deprecated}} expected-note {{here}} expected-error {{requires type for loop variable}}
230   }
231 }
232 
233 namespace pr18587 {
234   class Arg {};
235   struct Cont {
236     int *begin();
237     int *end();
238   };
AddAllArgs(Cont & x)239   void AddAllArgs(Cont &x) {
240     for (auto Arg: x) {
241     }
242   }
243 }
244