xref: /llvm-project/clang/test/SemaCXX/cxx1z-constexpr-lambdas.cpp (revision a625da716c8300d2ff9ec2313e7b38892bcfcfcb)
1 // RUN: %clang_cc1 -std=c++1z -verify -fsyntax-only -fblocks %s -fcxx-exceptions
2 // RUN: %clang_cc1 -std=c++2a -verify -fsyntax-only -fblocks %s -fcxx-exceptions
3 // RUN: %clang_cc1 -std=c++1z -verify -fsyntax-only -fblocks -fdelayed-template-parsing %s -fcxx-exceptions
4 // RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -fblocks %s -DCPP14_AND_EARLIER -fcxx-exceptions
5 
6 
7 namespace test_lambda_is_literal {
8 #ifdef CPP14_AND_EARLIER
9 //expected-error@+4{{not a literal type}}
10 //expected-note@+2{{lambda closure types are non-literal types before C++17}}
11 #endif
12 auto L = [] { };
13 constexpr int foo(decltype(L) l) { return 0; }
14 
15 }
16 
17 #ifndef CPP14_AND_EARLIER
18 namespace test_constexpr_checking {
19 
20 namespace ns1 {
21   struct NonLit { ~NonLit(); };  //expected-note{{not literal}}
22   auto L = [](NonLit NL) constexpr { }; //expected-error{{not a literal type}}
23 } // end ns1
24 
25 namespace ns2 {
26   auto L = [](int I) constexpr { asm("non-constexpr");  }; //expected-error{{not allowed in constexpr function}}
27 } // end ns1
28 
29 // This is not constexpr until C++20, as the requirements on constexpr
30 // functions don't permit try-catch blocks.
31 #if __cplusplus <= 201703L
32 // expected-error@#try-catch {{constant expression}}
33 // expected-note@#try-catch {{non-constexpr function 'operator()'}}
34 // expected-note@#try-catch {{declared here}}
35 #endif
36 constexpr int try_catch = [] { // #try-catch
37   try { return 0; } catch (...) { return 1; }
38 }();
39 
40 // These lambdas have constexpr operator() even though they can never produce a
41 // constant expression.
42 auto never_constant_1 = [] { // expected-note {{here}}
43   volatile int n = 0;
44   return n;
45 };
46 auto never_constant_2 = [] () -> int { // expected-note {{here}}
47 };
48 struct test_never_constant {
49   #if __cplusplus >= 201703L
50   // expected-error@+3 {{non-constexpr declaration of 'operator()' follows constexpr declaration}}
51   // expected-error@+3 {{non-constexpr declaration of 'operator()' follows constexpr declaration}}
52   #endif
53   friend auto decltype(never_constant_1)::operator()() const;
54   friend int decltype(never_constant_2)::operator()() const;
55 };
56 
57 } // end ns test_constexpr_checking
58 
59 namespace test_constexpr_call {
60 
61 namespace ns1 {
62   auto L = [](int I) { return I; };
63   static_assert(L(3) == 3);
64 } // end ns1
65 namespace ns2 {
66   auto L = [](auto a) { return a; };
67   static_assert(L(3) == 3);
68   static_assert(L(3.14) == 3.14);
69 }
70 namespace ns3 {
71   auto L = [](auto a) { asm("non-constexpr"); return a; }; //expected-note{{declared here}}
72   constexpr int I =  //expected-error{{must be initialized by a constant expression}}
73       L(3); //expected-note{{non-constexpr function}}
74 }
75 
76 } // end ns test_constexpr_call
77 
78 namespace test_captureless_lambda {
79 void f() {
80   const char c = 'c';
81   auto L = [] { return c; };
82   constexpr char C = L();
83 }
84 
85 void f(char c) { //expected-note{{declared here}}
86   auto L = [] { return c; }; //expected-error{{cannot be implicitly captured}} expected-note{{lambda expression begins here}}
87   int I = L();
88 }
89 
90 }
91 
92 namespace test_conversion_function_for_non_capturing_lambdas {
93 
94 namespace ns1 {
95 auto L = [](int i) { return i; };
96 constexpr int (*fpi)(int) = L;
97 static_assert(fpi(3) == 3);
98 auto GL = [](auto a) { return a; };
99 
100 constexpr char (*fp2)(char) = GL;
101 constexpr double (*fp3)(double) = GL;
102 constexpr const char* (*fp4)(const char*) = GL;
103 static_assert(fp2('3') == '3');
104 static_assert(fp3(3.14) == 3.14);
105 constexpr const char *Str = "abc";
106 static_assert(fp4(Str) == Str);
107 
108 auto NCL = [](int i) { static int j; return j; }; //expected-note{{declared here}}
109 constexpr int (*fp5)(int) = NCL;
110 constexpr int I =  //expected-error{{must be initialized by a constant expression}}
111                   fp5(5); //expected-note{{non-constexpr function}}
112 
113 namespace test_dont_always_instantiate_constexpr_templates {
114 
115 auto explicit_return_type = [](auto x) -> int { return x.get(); };
116 decltype(explicit_return_type(0)) c;  // OK
117 
118 auto deduced_return_type = [](auto x) { return x.get(); }; //expected-error{{not a structure or union}}
119 decltype(deduced_return_type(0)) d;  //expected-note{{requested here}}
120 
121 
122 
123 } // end ns test_dont_always_instantiate_constexpr_templates
124 } // end ns1
125 
126 } // end ns test_conversion_function_for_non_capturing_lambdas
127 
128 namespace test_lambda_is_cce {
129 namespace ns1_simple_lambda {
130 
131 namespace ns0 {
132 constexpr int I = [](auto a) { return a; }(10);
133 
134 static_assert(I == 10);
135 static_assert(10 == [](auto a) { return a; }(10));
136 static_assert(3.14 == [](auto a) { return a; }(3.14));
137 
138 } //end ns0
139 
140 namespace ns1 {
141 constexpr auto f(int i) {
142   double d = 3.14;
143   auto L = [=](auto a) {
144     int Isz = sizeof(i);
145     return sizeof(i) + sizeof(a) + sizeof(d);
146   };
147   int I = L("abc") + L(nullptr);
148   return L;
149 }
150 constexpr auto L = f(3);
151 constexpr auto M =  L("abc") + L(nullptr);
152 
153 static_assert(M == sizeof(int) * 2 + sizeof(double) * 2 + sizeof(nullptr) + sizeof(const char*));
154 
155 } // end ns1
156 
157 namespace ns2 {
158 constexpr auto f(int i) {
159   auto L = [](auto a) { return a + a; };
160   return L;
161 }
162 constexpr auto L = f(3);
163 constexpr int I = L(6);
164 static_assert(I == 12);
165 } // end ns2
166 
167 namespace contained_lambdas_call_operator_is_not_constexpr {
168 constexpr auto f(int i) {
169   double d = 3.14;
170   auto L = [=](auto a) { //expected-note{{declared here}}
171     int Isz = sizeof(i);
172     asm("hello");
173     return sizeof(i) + sizeof(a) + sizeof(d);
174   };
175   return L;
176 }
177 
178 constexpr auto L = f(3);
179 
180 constexpr auto M =  // expected-error{{must be initialized by}}
181     L("abc"); //expected-note{{non-constexpr function}}
182 
183 } // end ns contained_lambdas_call_operator_is_not_constexpr
184 
185 
186 
187 } // end ns1_simple_lambda
188 
189 namespace test_captures_1 {
190 namespace ns1 {
191 constexpr auto f(int i) {
192   struct S { int x; } s = { i * 2 };
193   auto L = [=](auto a) {
194     return i + s.x + a;
195   };
196   return L;
197 }
198 constexpr auto M = f(3);
199 
200 static_assert(M(10) == 19);
201 
202 } // end test_captures_1::ns1
203 
204 namespace ns2 {
205 
206 constexpr auto foo(int n) {
207   auto L = [i = n] (auto N) mutable {
208     if (!N(i)) throw "error";
209     return [&i] {
210       return ++i;
211     };
212   };
213   auto M = L([n](int p) { return p == n; });
214   M(); M();
215   L([n](int p) { return p == n + 2; });
216 
217   return L;
218 }
219 
220 constexpr auto L = foo(3);
221 
222 } // end test_captures_1::ns2
223 namespace ns3 {
224 
225 constexpr auto foo(int n) {
226   auto L = [i = n] (auto N) mutable {
227     if (!N(i)) throw "error";
228     return [&i] {
229       return [i]() mutable {
230         return ++i;
231       };
232     };
233   };
234   auto M = L([n](int p) { return p == n; });
235   M()(); M()();
236   L([n](int p) { return p == n; });
237 
238   return L;
239 }
240 
241 constexpr auto L = foo(3);
242 } // end test_captures_1::ns3
243 
244 namespace ns2_capture_this_byval {
245 struct S {
246   int s;
247   constexpr S(int s) : s{s} { }
248   constexpr auto f(S o) {
249     return [*this,o] (auto a) { return s + o.s + a.s; };
250   }
251 };
252 
253 constexpr auto L = S{5}.f(S{10});
254 static_assert(L(S{100}) == 115);
255 } // end test_captures_1::ns2_capture_this_byval
256 
257 namespace ns2_capture_this_byref {
258 
259 struct S {
260   int s;
261   constexpr S(int s) : s{s} { }
262   constexpr auto f() const {
263     return [this] { return s; };
264   }
265 };
266 
267 constexpr S SObj{5};
268 constexpr auto L = SObj.f();
269 constexpr int I = L();
270 static_assert(I == 5);
271 
272 } // end ns2_capture_this_byref
273 
274 } // end test_captures_1
275 
276 namespace test_capture_array {
277 namespace ns1 {
278 constexpr auto f(int I) {
279   int arr[] = { I, I *2, I * 3 };
280   auto L1 = [&] (auto a) { return arr[a]; };
281   int r = L1(2);
282   struct X { int x, y; };
283   return [=](auto a) { return X{arr[a],r}; };
284 }
285 constexpr auto L = f(3);
286 static_assert(L(0).x == 3);
287 static_assert(L(0).y == 9);
288 static_assert(L(1).x == 6);
289 static_assert(L(1).y == 9);
290 } // end ns1
291 
292 } // end test_capture_array
293 namespace ns1_test_lvalue_type {
294   void f() {
295     volatile int n;
296     constexpr bool B = [&]{ return &n; }() == &n; // should be accepted
297   }
298 } // end ns1_unimplemented
299 
300 } // end ns test_lambda_is_cce
301 
302 namespace PR36054 {
303 constexpr int fn() {
304   int Capture = 42;
305   return [=]() constexpr { return Capture; }();
306 }
307 
308 static_assert(fn() == 42, "");
309 
310 template <class T>
311 constexpr int tfn() {
312   int Capture = 42;
313   return [=]() constexpr { return Capture; }();
314 }
315 
316 static_assert(tfn<int>() == 42, "");
317 
318 constexpr int gfn() {
319   int Capture = 42;
320   return [=](auto P) constexpr { return Capture + P; }(58);
321 }
322 
323 static_assert(gfn() == 100, "");
324 
325 constexpr bool OtherCaptures() {
326   int Capture = 42;
327   constexpr auto Outer = [](auto P) constexpr { return 42 + P; };
328   auto Inner = [&](auto O) constexpr { return O(58) + Capture; };
329   return Inner(Outer) == 142;
330 }
331 
332 static_assert(OtherCaptures(), "");
333 } // namespace PR36054
334 
335 #endif // ndef CPP14_AND_EARLIER
336