244 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			244 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			C++
		
	
	
	
| // 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-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}}
 | |
|     }
 | |
|     // FIXME: The fix-it hint here is not sufficient to fix the error.
 | |
|     // We fail to diagnose that d is underaligned for its type, because
 | |
|     // we check the alignment attribute before we perform the auto
 | |
|     // deduction.
 | |
|     for (d alignas(1) : arr) {} // expected-error {{requires type for loop variable}}
 | |
|     for (e [[deprecated]] : arr) { e = 0; } // expected-warning{{use of the 'deprecated' attribute is a C++14 extension}} 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) {
 | |
|     }
 | |
|   }
 | |
| }
 |