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