1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288
|
// 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(); // expected-note {{in call to '&f->operator()()'}} \
// ref-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<typename T>
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<typename F>
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<float>(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 <auto A = [](auto x){}>
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, "");
|