// 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}} expected-warning {{result unused}} for (+x : {1, 2, 3}) {} // expected-error {{undeclared identifier}} expected-error {{expected ';'}} for (+y : {1, 2, 3}) {} // expected-error {{must declare a variable}} expected-warning {{result unused}} } } 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-warning {{extension}} // FIXME: Give a -Wshadow for this by default? for (b : arr) {} // expected-warning {{extension}} for (arr : arr) {} // expected-warning {{extension}} for (c alignas(8) : arr) { // expected-warning {{extension}} static_assert(alignof(c) == 8, ""); // expected-warning {{extension}} } // FIXME: We should reject this, but don't, because we only check the // attribute before we deduce the 'auto' type. for (d alignas(1) : arr) {} // expected-warning {{extension}} for (e [[deprecated]] : arr) { e = 0; } // expected-warning {{deprecated}} expected-note {{here}} expected-warning {{extension}} } }