| // RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 |
| |
| namespace value_range_detail { |
| template<typename T> |
| class value_range_iter { |
| T t; |
| public: |
| value_range_iter(const T &t) : t(t) {} |
| T operator*() const { return t; } |
| bool operator!=(const value_range_iter &o) const { return t != o.t; } |
| value_range_iter &operator++() { ++t; return *this; } |
| }; |
| |
| template<typename T> |
| struct value_range { |
| value_range(const T &a, const T &b) : begin_(a), end_(b) {} |
| value_range_iter<T> begin_, end_; |
| }; |
| |
| template<typename T> |
| value_range_iter<T> begin(const value_range<T> &r) { return r.begin_; } |
| template<typename T> |
| value_range_iter<T> end(const value_range<T> &r) { return r.end_; } |
| |
| |
| struct end_t {}; |
| |
| template<typename T> |
| class value_range_step_iter { |
| T it, step; |
| public: |
| value_range_step_iter(const T &it, const T &step) : it(it), step(step) {} |
| T operator*() const { return it; } |
| bool operator!=(value_range_step_iter end) const { return it != end.it; } |
| value_range_step_iter &operator++() { it += step; return *this; } |
| }; |
| |
| template<typename T> |
| class value_range_step { |
| T it, step, end_; |
| public: |
| value_range_step(const T &it, const T &end, const T &step) : |
| it(it), end_(end), step(step) {} |
| typedef value_range_step_iter<T> iterator; |
| iterator begin() const { return iterator(it, step); } |
| iterator end() const { return iterator(end_, step); } |
| }; |
| } |
| |
| template<typename T> |
| value_range_detail::value_range<T> range(const T &a, const T &b) { return value_range_detail::value_range<T>(a, b); } |
| |
| template<typename T> |
| 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); } |
| |
| |
| namespace map_range { |
| template<typename T> |
| class vector { |
| T storage[100]; |
| decltype(sizeof(char)) size; |
| public: |
| vector() : size() {} |
| void push_back(T t) { storage[size++] = t; } |
| T *begin() { return storage; } |
| T *end() { return storage + size; } |
| }; |
| |
| template<typename T> struct tuple_elem { |
| T t; |
| tuple_elem() {} |
| tuple_elem(T t) : t(t) {} |
| }; |
| template<typename... A> |
| struct tuple : tuple_elem<A>... { |
| tuple() : tuple_elem<A>()... {} |
| tuple(A... a) : tuple_elem<A>(a)... {} |
| template<typename B> B &get() { return tuple_elem<B>::t; } |
| }; |
| |
| template<typename F, typename I> |
| class map_iter { |
| F f; |
| I i; |
| public: |
| map_iter(F f, I i) : f(f), i(i) {} |
| auto operator*() const -> decltype(f(*i)) { return f(*i); } |
| bool operator!=(const map_iter &o) const { return i != o.i; } |
| map_iter &operator++() { ++i; return *this; } |
| }; |
| |
| template<typename T> |
| struct iter_pair { |
| T begin_, end_; |
| iter_pair(T begin, T end) : begin_(begin), end_(end) {} |
| }; |
| template<typename T> T begin(iter_pair<T> p) { return p.begin_; } |
| template<typename T> T end(iter_pair<T> p) { return p.end_; } |
| |
| template<typename...> class mem_fun_impl; |
| template<typename R, typename T, typename... A> |
| class mem_fun_impl<R (T::*)(A...)> { |
| typedef R (T::*F)(A...); |
| F f; |
| public: |
| mem_fun_impl(F f) : f(f) {} |
| R operator()(T &t, A &&...a) const { return (t.*f)(static_cast<A&&>(a)...); } |
| }; |
| template<typename F> mem_fun_impl<F> mem_fun(F f) { return mem_fun_impl<F>(f); } |
| |
| template<typename F, typename T> |
| auto map(const F &f, T &t) -> iter_pair<map_iter<F, decltype(t.begin())>> { |
| typedef map_iter<F, decltype(t.begin())> iter; |
| return iter_pair<iter>(iter(f, t.begin()), iter(f, t.end())); |
| } |
| } |
| |
| #define assert(b) if (!(b)) { return 1; } |
| int main() { |
| int total = 0; |
| |
| for (auto n : range(1, 5)) { |
| total += n; |
| } |
| assert(total == 10); |
| |
| for (auto n : range(10, 100, 10)) { |
| total += n; |
| } |
| assert(total == 460); |
| |
| map_range::vector<char> chars; |
| chars.push_back('a'); |
| chars.push_back('b'); |
| chars.push_back('c'); |
| for (char c : chars) { |
| ++total; |
| } |
| assert(total == 463); |
| |
| typedef map_range::tuple<int, double> T; |
| map_range::vector<T> pairs; |
| pairs.push_back(T(42, 12.9)); |
| pairs.push_back(T(6, 4.2)); |
| pairs.push_back(T(9, 1.1)); |
| for (auto a : map(map_range::mem_fun(&T::get<int>), pairs)) { |
| total += a; |
| } |
| assert(total == 500); |
| } |
| |
| // PR11793 |
| namespace test2 { |
| class A { |
| int xs[10]; // expected-note {{implicitly declared private here}} |
| }; |
| void test(A &a) { |
| for (int x : a.xs) { } // expected-error {{'xs' is a private member of 'test2::A'}} |
| } |
| } |
| |
| namespace test3 { |
| // Make sure this doesn't crash |
| struct A {}; |
| struct B { ~B(); operator bool(); }; |
| struct C { B operator!=(const C&); C& operator++(); int operator*(); }; |
| C begin(const A&); |
| C end(const A&); |
| template<typename T> void f() { for (auto a : A()) {} } |
| void g() { f<int>(); } |
| } |
| |
| namespace test4 { |
| void f() { |
| int y; |
| |
| // Make sure these don't crash. Better diagnostics would be nice. |
| for (: {1, 2, 3}) {} // expected-error {{expected expression}} expected-error {{expected ';'}} |
| for (1 : {1, 2, 3}) {} // expected-error {{must declare a variable}} |
| for (+x : {1, 2, 3}) {} // expected-error {{undeclared identifier}} expected-error {{expected ';'}} |
| for (+y : {1, 2, 3}) {} // expected-error {{must declare a variable}} |
| } |
| } |
| |
| namespace test5 { |
| // Test error-recovery. |
| void f() { |
| for (auto x : undeclared_identifier) // expected-error {{undeclared identifier}} |
| for (auto y : x->foo) |
| y->bar(); |
| for (auto x : 123) // expected-error {{no viable 'begin'}} |
| x->foo(); |
| } |
| } |
| |
| namespace test6 { |
| void foo(int arr[]) { // expected-note {{declared here}} |
| for (auto i : arr) { } |
| // expected-error@-1 {{cannot build range expression with array function parameter 'arr' since parameter with array type 'int []' is treated as pointer type 'int *'}} |
| } |
| |
| struct vector { |
| int *begin() { return 0; } |
| int *end() { return 0; } |
| }; |
| |
| void foo(vector arr[]) { // expected-note {{declared here}} |
| // Don't suggest to dereference arr. |
| for (auto i : arr) { } |
| // 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 *'}} |
| } |
| } |
| |
| namespace test7 { |
| void f() { |
| int arr[5], b; |
| for (a : arr) {} // expected-error {{requires type for loop variable}} |
| // FIXME: Give a different error in this case? |
| for (b : arr) {} // expected-error {{requires type for loop variable}} |
| for (arr : arr) {} // expected-error {{requires type for loop variable}} |
| for (c alignas(8) : arr) { // expected-error {{requires type for loop variable}} |
| static_assert(alignof(c) == 8, ""); // expected-warning {{extension}} |
| } |
| for (d alignas(1) : arr) {} // expected-error {{requested alignment is less than minimum}} expected-error {{requires type for loop variable}} |
| for (e [[deprecated]] : arr) { e = 0; } // expected-warning {{deprecated}} expected-note {{here}} expected-error {{requires type for loop variable}} |
| } |
| } |
| |
| namespace pr18587 { |
| class Arg {}; |
| struct Cont { |
| int *begin(); |
| int *end(); |
| }; |
| void AddAllArgs(Cont &x) { |
| for (auto Arg: x) { |
| } |
| } |
| } |
| |
| namespace PR32933 { |
| // https://bugs.llvm.org/show_bug.cgi?id=32933 |
| void foo () |
| { |
| int b = 1, a[b]; |
| a[0] = 0; |
| [&] { for (int c : a) 0; } (); |
| } |
| |
| |
| int foo(int b) { |
| int varr[b][(b+=8)]; |
| b = 15; |
| [&] { |
| int i = 0; |
| for (auto &c : varr) |
| { |
| c[0] = ++b; |
| } |
| [&] { |
| int i = 0; |
| for (auto &c : varr) { |
| int j = 0; |
| for(auto &c2 : c) { |
| ++j; |
| } |
| ++i; |
| } |
| }(); |
| }(); |
| return b; |
| } |
| } |