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}} 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 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-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