xref: /llvm-project/clang/test/AST/ByteCode/lambda.cpp (revision a07aba5d44204a7ca0d891a3da05af9960081e4c)
1 // RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify=expected,both -std=c++20 %s
2 // RUN: %clang_cc1 -verify=ref,both -std=c++20 %s
3 
4 constexpr int a = 12;
5 constexpr int f = [c = a]() { return c; }();
6 static_assert(f == a);
7 
8 
9 constexpr int inc() {
10   int a = 10;
11   auto f = [&a]() {
12     ++a;
13   };
14 
15   f();f();
16 
17   return a;
18 }
19 static_assert(inc() == 12);
20 
21 constexpr int add(int a, int b) {
22   auto doIt = [a, b](int c) {
23     return a + b + c;
24   };
25 
26   return doIt(2);
27 }
28 static_assert(add(4, 5) == 11);
29 
30 
31 constexpr int add2(int a, int b) {
32   auto doIt = [a, b](int c) {
33     auto bar = [a]() { return a; };
34     auto bar2 = [b]() { return b; };
35 
36     return bar() + bar2() + c;
37   };
38 
39   return doIt(2);
40 }
41 static_assert(add2(4, 5) == 11);
42 
43 
44 constexpr int div(int a, int b) {
45   auto f = [=]() {
46     return a / b; // both-note {{division by zero}}
47   };
48 
49   return f(); // both-note {{in call to 'f.operator()()'}}
50 }
51 static_assert(div(8, 2) == 4);
52 static_assert(div(8, 0) == 4); // both-error {{not an integral constant expression}} \
53                                // both-note {{in call to 'div(8, 0)'}}
54 
55 
56 struct F {
57   float f;
58 };
59 
60 constexpr float captureStruct() {
61   F someF = {1.0};
62 
63   auto p = [someF]() {
64     return someF.f;
65   };
66 
67   return p();
68 }
69 
70 static_assert(captureStruct() == 1.0);
71 
72 
73 int constexpr FunCase() {
74     return [x = 10] {
75        decltype(x) y; // type int b/c not odr use
76                       // refers to original init-capture
77        auto &z = x; // type const int & b/c odr use
78                      // refers to lambdas copy of x
79         y = 10; // Ok
80         //z = 10; // Ill-formed
81         return y;
82     }();
83 }
84 
85 constexpr int WC = FunCase();
86 
87 
88 namespace LambdaParams {
89   template<typename T>
90   constexpr void callThis(T t) {
91     return t();
92   }
93 
94   constexpr int foo() {
95     int a = 0;
96     auto f = [&a]() { ++a; };
97 
98     callThis(f);
99 
100     return a;
101   }
102   static_assert(foo() == 1);
103 }
104 
105 namespace StaticInvoker {
106   constexpr int sv1(int i) {
107     auto l = []() { return 12; };
108     int (*fp)() = l;
109     return fp();
110   }
111   static_assert(sv1(12) == 12);
112 
113   constexpr int sv2(int i) {
114     auto l = [](int m, float f, void *A) { return m; };
115     int (*fp)(int, float, void*) = l;
116     return fp(i, 4.0f, nullptr);
117   }
118   static_assert(sv2(12) == 12);
119 
120   constexpr int sv3(int i) {
121     auto l = [](int m, const int &n) { return m; };
122     int (*fp)(int, const int &) = l;
123     return fp(i, 3);
124   }
125   static_assert(sv3(12) == 12);
126 
127   constexpr int sv4(int i) {
128     auto l = [](int &m) { return m; };
129     int (*fp)(int&) = l;
130     return fp(i);
131   }
132   static_assert(sv4(12) == 12);
133 
134   constexpr int sv5(int i) {
135     struct F { int a; float f; };
136     auto l = [](int m, F f) { return m; };
137     int (*fp)(int, F) = l;
138     return fp(i, F{12, 14.0});
139   }
140   static_assert(sv5(12) == 12);
141 
142   constexpr int sv6(int i) {
143     struct F { int a;
144       constexpr F(int a) : a(a) {}
145     };
146 
147     auto l = [](int m) { return F(12); };
148     F (*fp)(int) = l;
149     F f = fp(i);
150 
151     return fp(i).a;
152   }
153   static_assert(sv6(12) == 12);
154 
155 
156   /// A generic lambda.
157   auto GL = [](auto a) { return a; };
158   constexpr char (*fp2)(char) = GL;
159   static_assert(fp2('3') == '3', "");
160 
161   struct GLS {
162     int a;
163   };
164   auto GL2 = [](auto a) { return GLS{a}; };
165   constexpr GLS (*fp3)(char) = GL2;
166   static_assert(fp3('3').a == '3', "");
167 }
168 
169 namespace LambdasAsParams {
170   template<typename F>
171   constexpr auto call(F f) {
172     return f();
173   }
174   static_assert(call([](){ return 1;}) == 1);
175   static_assert(call([](){ return 2;}) == 2);
176 
177 
178   constexpr unsigned L = call([](){ return 12;});
179   static_assert(L == 12);
180 
181 
182   constexpr float heh() {
183     auto a = []() {
184       return 1.0;
185     };
186 
187     return static_cast<float>(a());
188   }
189   static_assert(heh() == 1.0);
190 }
191 
192 namespace ThisCapture {
193   class Foo {
194   public:
195     int b = 32;
196     int a;
197 
198     constexpr Foo() : a([this](){ return b + 1;}()) {}
199 
200     constexpr int Aplus2() const {
201       auto F = [this]() {
202         return a + 2;
203       };
204 
205       return F();
206     }
207   };
208   constexpr Foo F;
209   static_assert(F.a == 33, "");
210   static_assert(F.Aplus2() == (33 + 2), "");
211 }
212 
213 namespace GH62611 {
214   template <auto A = [](auto x){}>
215   struct C {
216     static constexpr auto B = A;
217   };
218 
219   int test() {
220     C<>::B(42);
221     return 0;
222   }
223 }
224 
225 namespace LambdaToAPValue {
226   void wrapper() {
227     constexpr auto f = []() constexpr {
228       return 0;
229     };
230 
231     constexpr auto g = [f]() constexpr {
232       return f();
233     };
234     static_assert(g() == f(), "");
235   }
236 }
237 
238 namespace ns2_capture_this_byval {
239   struct S {
240     int s;
241     constexpr S(int s) : s{s} { }
242     constexpr auto f(S o) {
243       return [*this,o] (auto a) { return s + o.s + a.s; };
244     }
245   };
246 
247   constexpr auto L = S{5}.f(S{10});
248   static_assert(L(S{100}) == 115, "");
249 } // end test_captures_1::ns2_capture_this_byval
250 
251 namespace CaptureDefaults {
252   struct S {
253     int x;
254   };
255 
256   constexpr auto f = [x = S{10}]() {
257       return x.x;
258   };
259   static_assert(f() == 10, "");
260 
261   constexpr auto f2 = [x = 3]() {
262       return x;
263   };
264   static_assert(f2() == 3, "");
265 }
266 
267 constexpr auto t4 = ([x=42]() consteval { return x; }());
268 static_assert(t4 == 42, "");
269 
270 namespace InvalidCapture {
271 
272   int &f(int *p);
273   char &f(...);
274   void g() {
275     int n = -1;   // both-note {{declared here}}
276     [=] {
277       int arr[n]; // both-warning {{variable length arrays in C++ are a Clang extension}} \
278                      both-note {{read of non-const variable 'n' is not allowed in a constant expression}}
279     } ();
280   }
281 }
282 
283 constexpr int fn() {
284   int Capture = 42;
285   return [=]() constexpr { return Capture; }();
286 }
287 static_assert(fn() == 42, "");
288