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: |
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 | |
50 | template<typename T> |
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> |
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: |
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; } |
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 | }; |
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&); |
169 | template<typename T> void f() { for (auto a : A()) {} } |
170 | void g() { f<int>(); } |
171 | } |
172 | |
173 | namespace 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}} |
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. |
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 { |
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 | |
214 | namespace test7 { |
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 | for (d alignas(1) : arr) {} // expected-error {{requested alignment is less than minimum}} expected-error {{requires type for loop variable}} |
225 | for (e [[deprecated]] : arr) { e = 0; } // expected-warning {{deprecated}} expected-note {{here}} expected-error {{requires type for loop variable}} |
226 | } |
227 | } |
228 | |
229 | namespace pr18587 { |
230 | class Arg {}; |
231 | struct Cont { |
232 | int *begin(); |
233 | int *end(); |
234 | }; |
235 | void AddAllArgs(Cont &x) { |
236 | for (auto Arg: x) { |
237 | } |
238 | } |
239 | } |
240 | |
241 | namespace PR32933 { |
242 | // https://bugs.llvm.org/show_bug.cgi?id=32933 |
243 | void foo () |
244 | { |
245 | int b = 1, a[b]; |
246 | a[0] = 0; |
247 | [&] { for (int c : a) 0; } (); // expected-warning {{expression result unused}} |
248 | } |
249 | |
250 | |
251 | int foo(int b) { |
252 | int varr[b][(b+=8)]; |
253 | b = 15; |
254 | [&] { |
255 | int i = 0; |
256 | for (auto &c : varr) |
257 | { |
258 | c[0] = ++b; |
259 | } |
260 | [&] { |
261 | int i = 0; |
262 | for (auto &c : varr) { |
263 | int j = 0; |
264 | for(auto &c2 : c) { |
265 | ++j; |
266 | } |
267 | ++i; |
268 | } |
269 | }(); |
270 | }(); |
271 | return b; |
272 | } |
273 | } |
274 | |