// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify=expected,both -std=c++20 %s // RUN: %clang_cc1 -verify=ref,both -std=c++20 %s constexpr int a = 12; constexpr int f = [c = a]() { return c; }(); static_assert(f == a); constexpr int inc() { int a = 10; auto f = [&a]() { ++a; }; f();f(); return a; } static_assert(inc() == 12); constexpr int add(int a, int b) { auto doIt = [a, b](int c) { return a + b + c; }; return doIt(2); } static_assert(add(4, 5) == 11); constexpr int add2(int a, int b) { auto doIt = [a, b](int c) { auto bar = [a]() { return a; }; auto bar2 = [b]() { return b; }; return bar() + bar2() + c; }; return doIt(2); } static_assert(add2(4, 5) == 11); constexpr int div(int a, int b) { auto f = [=]() { return a / b; // both-note {{division by zero}} }; return f(); // both-note {{in call to 'f.operator()()'}} } static_assert(div(8, 2) == 4); static_assert(div(8, 0) == 4); // both-error {{not an integral constant expression}} \ // both-note {{in call to 'div(8, 0)'}} struct F { float f; }; constexpr float captureStruct() { F someF = {1.0}; auto p = [someF]() { return someF.f; }; return p(); } static_assert(captureStruct() == 1.0); int constexpr FunCase() { return [x = 10] { decltype(x) y; // type int b/c not odr use // refers to original init-capture auto &z = x; // type const int & b/c odr use // refers to lambdas copy of x y = 10; // Ok //z = 10; // Ill-formed return y; }(); } constexpr int WC = FunCase(); namespace LambdaParams { template constexpr void callThis(T t) { return t(); } constexpr int foo() { int a = 0; auto f = [&a]() { ++a; }; callThis(f); return a; } static_assert(foo() == 1); } namespace StaticInvoker { constexpr int sv1(int i) { auto l = []() { return 12; }; int (*fp)() = l; return fp(); } static_assert(sv1(12) == 12); constexpr int sv2(int i) { auto l = [](int m, float f, void *A) { return m; }; int (*fp)(int, float, void*) = l; return fp(i, 4.0f, nullptr); } static_assert(sv2(12) == 12); constexpr int sv3(int i) { auto l = [](int m, const int &n) { return m; }; int (*fp)(int, const int &) = l; return fp(i, 3); } static_assert(sv3(12) == 12); constexpr int sv4(int i) { auto l = [](int &m) { return m; }; int (*fp)(int&) = l; return fp(i); } static_assert(sv4(12) == 12); constexpr int sv5(int i) { struct F { int a; float f; }; auto l = [](int m, F f) { return m; }; int (*fp)(int, F) = l; return fp(i, F{12, 14.0}); } static_assert(sv5(12) == 12); constexpr int sv6(int i) { struct F { int a; constexpr F(int a) : a(a) {} }; auto l = [](int m) { return F(12); }; F (*fp)(int) = l; F f = fp(i); return fp(i).a; } static_assert(sv6(12) == 12); /// A generic lambda. auto GL = [](auto a) { return a; }; constexpr char (*fp2)(char) = GL; static_assert(fp2('3') == '3', ""); struct GLS { int a; }; auto GL2 = [](auto a) { return GLS{a}; }; constexpr GLS (*fp3)(char) = GL2; static_assert(fp3('3').a == '3', ""); } namespace LambdasAsParams { template constexpr auto call(F f) { return f(); } static_assert(call([](){ return 1;}) == 1); static_assert(call([](){ return 2;}) == 2); constexpr unsigned L = call([](){ return 12;}); static_assert(L == 12); constexpr float heh() { auto a = []() { return 1.0; }; return static_cast(a()); } static_assert(heh() == 1.0); } namespace ThisCapture { class Foo { public: int b = 32; int a; constexpr Foo() : a([this](){ return b + 1;}()) {} constexpr int Aplus2() const { auto F = [this]() { return a + 2; }; return F(); } }; constexpr Foo F; static_assert(F.a == 33, ""); static_assert(F.Aplus2() == (33 + 2), ""); } namespace GH62611 { template struct C { static constexpr auto B = A; }; int test() { C<>::B(42); return 0; } } namespace LambdaToAPValue { void wrapper() { constexpr auto f = []() constexpr { return 0; }; constexpr auto g = [f]() constexpr { return f(); }; static_assert(g() == f(), ""); } } namespace ns2_capture_this_byval { struct S { int s; constexpr S(int s) : s{s} { } constexpr auto f(S o) { return [*this,o] (auto a) { return s + o.s + a.s; }; } }; constexpr auto L = S{5}.f(S{10}); static_assert(L(S{100}) == 115, ""); } // end test_captures_1::ns2_capture_this_byval namespace CaptureDefaults { struct S { int x; }; constexpr auto f = [x = S{10}]() { return x.x; }; static_assert(f() == 10, ""); constexpr auto f2 = [x = 3]() { return x; }; static_assert(f2() == 3, ""); } constexpr auto t4 = ([x=42]() consteval { return x; }()); static_assert(t4 == 42, ""); namespace InvalidCapture { int &f(int *p); char &f(...); void g() { int n = -1; // both-note {{declared here}} [=] { int arr[n]; // both-warning {{variable length arrays in C++ are a Clang extension}} \ both-note {{read of non-const variable 'n' is not allowed in a constant expression}} } (); } } constexpr int fn() { int Capture = 42; return [=]() constexpr { return Capture; }(); } static_assert(fn() == 42, "");