xref: /llvm-project/clang/test/CXX/expr/expr.prim/expr.prim.lambda/templates.cpp (revision b4328233c159b56bcb9bb88a281f56793bd94235)
1 // RUN: %clang_cc1 -fsyntax-only -std=c++11 -Winvalid-noreturn %s -verify
2 
3 template<typename T>
4 void test_attributes() {
5   auto nrl = []() [[noreturn]] {}; // expected-warning{{function declared 'noreturn' should not return}}
6 }
7 
8 template void test_attributes<int>(); // expected-note{{in instantiation of function}}
9 
10 template<typename T>
11 void call_with_zero() {
12   [](T *ptr) -> T& { return *ptr; }(0);
13 }
14 
15 template void call_with_zero<int>();
16 
17 template<typename T>
18 T captures(T x, T y) {
19   auto lambda = [=, &y] () -> T {
20     T i = x;
21     return i + y;
22   };
23 
24   return lambda();
25 }
26 
27 struct X {
28   X(const X&);
29 };
30 
31 X operator+(X, X);
32 X operator-(X, X);
33 
34 template int captures(int, int);
35 template X captures(X, X);
36 
37 template<typename T>
38 int infer_result(T x, T y) {
39   auto lambda = [=](bool b) { return x + y; };
40   return lambda(true); // expected-error{{no viable conversion from 'X' to 'int'}}
41 }
42 
43 template int infer_result(int, int);
44 template int infer_result(X, X); // expected-note{{in instantiation of function template specialization 'infer_result<X>' requested here}}
45 
46 // Make sure that lambda's operator() can be used from templates.
47 template<typename F>
48 void accept_lambda(F f) {
49   f(1);
50 }
51 
52 template<typename T>
53 void pass_lambda(T x) {
54   accept_lambda([&x](T y) { return x + y; });
55 }
56 
57 template void pass_lambda(int);
58 
59 namespace std {
60   class type_info;
61 }
62 
63 namespace p2 {
64   struct P {
65     virtual ~P();
66   };
67 
68   template<typename T>
69   struct Boom {
70     Boom(const Boom&) {
71       T* x = 1; // expected-error{{cannot initialize a variable of type 'int *' with an rvalue of type 'int'}} \
72       // expected-error{{cannot initialize a variable of type 'float *' with an rvalue of type 'int'}}
73     }
74     void tickle() const;
75   };
76 
77   template<typename R, typename T>
78   void odr_used(R &r, Boom<T> boom) {
79     const std::type_info &ti
80       = typeid([=,&r] () -> R& { // expected-error{{lambda expression in an unevaluated operand}}
81           boom.tickle(); // expected-note{{in instantiation of member function}}
82           return r;
83         }());
84   }
85 
86   template void odr_used(int&, Boom<int>); // expected-note{{in instantiation of function template specialization}}
87 
88   template<typename R, typename T>
89   void odr_used2(R &r, Boom<T> boom) {
90     const std::type_info &ti
91       = typeid([=,&r] () -> R& {
92           boom.tickle(); // expected-note{{in instantiation of member function}}
93           return r;
94         }());
95   }
96 
97   template void odr_used2(P&, Boom<float>);
98 }
99 
100 namespace p5 {
101   struct NonConstCopy {
102     NonConstCopy(const NonConstCopy&) = delete;
103     NonConstCopy(NonConstCopy&);
104   };
105 
106   template<typename T>
107   void double_capture(T &nc) {
108     [=] () mutable {
109       [=] () mutable {
110         T nc2(nc);
111       }();
112     }();
113   }
114 
115   template void double_capture(NonConstCopy&);
116 }
117