Home | History | Annotate | Download | only in expr.prim.lambda
      1 // RUN: %clang_cc1 -fsyntax-only -std=c++11 -Winvalid-noreturn %s -verify
      2 
      3 template<typename T>
      4 void test_attributes() {
      5   // FIXME: GCC accepts [[gnu::noreturn]] here.
      6   auto nrl = []() [[gnu::noreturn]] {}; // expected-warning{{attribute 'noreturn' ignored}}
      7 }
      8 
      9 template void test_attributes<int>();
     10 
     11 template<typename T>
     12 void call_with_zero() {
     13   [](T *ptr) -> T& { return *ptr; }(0);
     14 }
     15 
     16 template void call_with_zero<int>();
     17 
     18 template<typename T>
     19 T captures(T x, T y) {
     20   auto lambda = [=, &y] () -> T {
     21     T i = x;
     22     return i + y;
     23   };
     24 
     25   return lambda();
     26 }
     27 
     28 struct X {
     29   X(const X&);
     30 };
     31 
     32 X operator+(X, X);
     33 X operator-(X, X);
     34 
     35 template int captures(int, int);
     36 template X captures(X, X);
     37 
     38 template<typename T>
     39 int infer_result(T x, T y) {
     40   auto lambda = [=](bool b) { return x + y; };
     41   return lambda(true); // expected-error{{no viable conversion from 'X' to 'int'}}
     42 }
     43 
     44 template int infer_result(int, int);
     45 template int infer_result(X, X); // expected-note{{in instantiation of function template specialization 'infer_result<X>' requested here}}
     46 
     47 // Make sure that lambda's operator() can be used from templates.
     48 template<typename F>
     49 void accept_lambda(F f) {
     50   f(1);
     51 }
     52 
     53 template<typename T>
     54 void pass_lambda(T x) {
     55   accept_lambda([&x](T y) { return x + y; });
     56 }
     57 
     58 template void pass_lambda(int);
     59 
     60 namespace std {
     61   class type_info;
     62 }
     63 
     64 namespace p2 {
     65   struct P {
     66     virtual ~P();
     67   };
     68 
     69   template<typename T>
     70   struct Boom {
     71     Boom(const Boom&) {
     72       T* x = 1; // expected-error{{cannot initialize a variable of type 'int *' with an rvalue of type 'int'}} \
     73       // expected-error{{cannot initialize a variable of type 'float *' with an rvalue of type 'int'}}
     74     }
     75     void tickle() const;
     76   };
     77 
     78   template<typename R, typename T>
     79   void odr_used(R &r, Boom<T> boom) {
     80     const std::type_info &ti
     81       = typeid([=,&r] () -> R& { // expected-error{{lambda expression in an unevaluated operand}}
     82           boom.tickle(); // expected-note{{in instantiation of member function}}
     83           return r;
     84         }());
     85   }
     86 
     87   template void odr_used(int&, Boom<int>); // expected-note{{in instantiation of function template specialization}}
     88 
     89   template<typename R, typename T>
     90   void odr_used2(R &r, Boom<T> boom) {
     91     const std::type_info &ti
     92       = typeid([=,&r] () -> R& {
     93           boom.tickle(); // expected-note{{in instantiation of member function}}
     94           return r;
     95         }());
     96   }
     97 
     98   template void odr_used2(P&, Boom<float>);
     99 }
    100 
    101 namespace p5 {
    102   struct NonConstCopy {
    103     NonConstCopy(const NonConstCopy&) = delete;
    104     NonConstCopy(NonConstCopy&);
    105   };
    106 
    107   template<typename T>
    108   void double_capture(T &nc) {
    109     [=] () mutable {
    110       [=] () mutable {
    111         T nc2(nc);
    112       }();
    113     }();
    114   }
    115 
    116   template void double_capture(NonConstCopy&);
    117 }
    118 
    119 namespace NonLocalLambdaInstantation {
    120   template<typename T>
    121   struct X {
    122     static int value;
    123   };
    124 
    125   template<typename T>
    126   int X<T>::value = []{ return T(); }(); // expected-error{{cannot initialize a variable of type 'int' with an rvalue of type 'int *'}}
    127 
    128   template int X<int>::value;
    129   template int X<float>::value;
    130   template int X<int*>::value; // expected-note{{in instantiation of static data member }}
    131 
    132   template<typename T>
    133   void defaults(int x = []{ return T(); }()) { }; // expected-error{{cannot initialize a parameter of type 'int' with an rvalue of type 'int *'}} \
    134      // expected-note{{passing argument to parameter 'x' here}}
    135 
    136   void call_defaults() {
    137     defaults<int>();
    138     defaults<float>();
    139     defaults<int*>(); // expected-note{{in instantiation of default function argument expression for 'defaults<int *>' required here}}
    140   }
    141 
    142   template<typename T>
    143   struct X2 {
    144     int x = []{ return T(); }(); // expected-error{{cannot initialize a member subobject of type 'int' with an rvalue of type 'int *'}}
    145   };
    146 
    147   X2<int> x2i;
    148   X2<float> x2f;
    149   X2<int*> x2ip; // expected-note{{in instantiation of template class 'NonLocalLambdaInstantation::X2<int *>' requested here}}
    150 }
    151