llvm-project/clang/test/SemaCXX/cxx1y-init-captures.cpp

232 lines
5.3 KiB
C++

// RUN: %clang_cc1 -std=c++1y %s -verify -emit-llvm-only
// RUN: %clang_cc1 -std=c++1z %s -verify -emit-llvm-only
namespace variadic_expansion {
int f(int &, char &) { return 0; }
template<class ... Ts> char fv(Ts ... ts) { return 0; }
// FIXME: why do we get 2 error messages
template <typename ... T> void g(T &... t) { //expected-note3{{declared here}}
f([&a(t)]()->decltype(auto) {
return a;
}() ...);
auto L = [x = f([&a(t)]()->decltype(auto) { return a; }()...)]() { return x; };
const int y = 10;
auto M = [x = y,
&z = y](T& ... t) { };
auto N = [x = y,
&z = y, n = f(t...),
o = f([&a(t)](T& ... t)->decltype(auto) { return a; }(t...)...), t...](T& ... s) {
fv([&a(t)]()->decltype(auto) {
return a;
}() ...);
};
auto N2 = [x = y, //expected-note3{{begins here}}
&z = y, n = f(t...),
o = f([&a(t)](T& ... t)->decltype(auto) { return a; }(t...)...)](T& ... s) {
fv([&a(t)]()->decltype(auto) { //expected-error 3{{captured}}
return a;
}() ...);
};
}
void h(int i, char c) { g(i, c); } //expected-note{{in instantiation}}
}
namespace odr_use_within_init_capture {
int test() {
{ // no captures
const int x = 10;
auto L = [z = x + 2](int a) {
auto M = [y = x - 2](char b) {
return y;
};
return M;
};
}
{ // should not capture
const int x = 10;
auto L = [&z = x](int a) {
return a;;
};
}
{
const int x = 10;
auto L = [k = x](char a) { //expected-note {{declared}}
return [](int b) { //expected-note {{begins}}
return [j = k](int c) { //expected-error {{cannot be implicitly captured}}
return c;
};
};
};
}
{
const int x = 10;
auto L = [k = x](char a) {
return [=](int b) {
return [j = k](int c) {
return c;
};
};
};
}
{
const int x = 10;
auto L = [k = x](char a) {
return [k](int b) {
return [j = k](int c) {
return c;
};
};
};
}
return 0;
}
int run = test();
}
namespace odr_use_within_init_capture_template {
template<class T = int>
int test(T t = T{}) {
{ // no captures
const T x = 10;
auto L = [z = x](char a) {
auto M = [y = x](T b) {
return y;
};
return M;
};
}
{ // should not capture
const T x = 10;
auto L = [&z = x](T a) {
return a;;
};
}
{ // will need to capture x in outer lambda
const T x = 10; //expected-note {{declared}}
auto L = [z = x](char a) { //expected-note {{begins}}
auto M = [&y = x](T b) { //expected-error {{cannot be implicitly captured}}
return y;
};
return M;
};
}
{ // will need to capture x in outer lambda
const T x = 10;
auto L = [=,z = x](char a) {
auto M = [&y = x](T b) {
return y;
};
return M;
};
}
{ // will need to capture x in outer lambda
const T x = 10;
auto L = [x, z = x](char a) {
auto M = [&y = x](T b) {
return y;
};
return M;
};
}
{ // will need to capture x in outer lambda
const int x = 10; //expected-note {{declared}}
auto L = [z = x](char a) { //expected-note {{begins}}
auto M = [&y = x](T b) { //expected-error {{cannot be implicitly captured}}
return y;
};
return M;
};
}
{
// no captures
const T x = 10;
auto L = [z =
[z = x, &y = x](char a) { return z + y; }('a')](char a)
{ return z; };
}
return 0;
}
int run = test(); //expected-note {{instantiation}}
}
namespace classification_of_captures_of_init_captures {
template <typename T>
void f() {
[a = 24] () mutable {
[&a] { a = 3; }();
}();
}
template <typename T>
void h() {
[a = 24] (auto param) mutable {
[&a] { a = 3; }();
}(42);
}
int run() {
f<int>();
h<int>();
}
}
namespace N3922 {
struct X { X(); explicit X(const X&); int n; };
auto a = [x{X()}] { return x.n; }; // ok
auto b = [x = {X()}] {}; // expected-error{{<initializer_list>}}
}
namespace init_capture_non_mutable {
void test(double weight) {
double init;
auto find = [max = init](auto current) {
max = current; // expected-error{{cannot assign to a variable captured by copy in a non-mutable lambda}}
};
find(weight); // expected-note {{in instantiation of function template specialization}}
}
}
namespace init_capture_undeclared_identifier {
auto a = [x = y]{}; // expected-error{{use of undeclared identifier 'y'}}
int typo_foo; // expected-note 2 {{'typo_foo' declared here}}
auto b = [x = typo_boo]{}; // expected-error{{use of undeclared identifier 'typo_boo'; did you mean 'typo_foo'}}
auto c = [x(typo_boo)]{}; // expected-error{{use of undeclared identifier 'typo_boo'; did you mean 'typo_foo'}}
}
namespace copy_evasion {
struct A {
A();
A(const A&) = delete;
};
auto x = [a{A()}] {};
#if __cplusplus >= 201702L
// ok, does not copy an 'A'
#else
// expected-error@-4 {{call to deleted}}
// expected-note@-7 {{deleted}}
#endif
}