diff options
Diffstat (limited to 'clang/test/SemaCXX/for-range-examples.cpp')
-rw-r--r-- | clang/test/SemaCXX/for-range-examples.cpp | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/clang/test/SemaCXX/for-range-examples.cpp b/clang/test/SemaCXX/for-range-examples.cpp new file mode 100644 index 0000000..8bda510 --- /dev/null +++ b/clang/test/SemaCXX/for-range-examples.cpp @@ -0,0 +1,182 @@ +// 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 (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}} + } +} |