Home | History | Annotate | Download | only in SemaCXX
      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