Implement lambda capture of *this by copy.
For e.g.:
struct A {
int d = 10;
auto foo() { return [*this] (auto a) mutable { d+=a; return d; }; }
};
auto L = A{}.foo(); // A{}'s lifetime is gone.
// Below is still ok, because *this was captured by value.
assert(L(10) == 20);
assert(L(100) == 120);
If the capture was implicit, or [this] (i.e. *this was captured by reference), this code would be otherwise undefined.
Implementation Strategy:
- amend the parser to accept *this in the lambda introducer
- add a new king of capture LCK_StarThis
- teach Sema::CheckCXXThisCapture to handle by copy captures of the
enclosing object (i.e. *this)
- when CheckCXXThisCapture does capture by copy, the corresponding
initializer expression for the closure's data member
direct-initializes it thus making a copy of '*this'.
- in codegen, when assigning to CXXThisValue, if *this was captured by
copy, make sure it points to the corresponding field member, and
not, unlike when captured by reference, what the field member points
to.
- mark feature as implemented in svn
Much gratitude to Richard Smith for his carefully illuminating reviews!
llvm-svn: 263921
23 lines
766 B
C++
23 lines
766 B
C++
// RUN: %clang_cc1 -fsyntax-only -std=c++1z %s -verify
|
|
|
|
class NonCopyable {
|
|
NonCopyable(const NonCopyable&) = delete; //expected-note3{{explicitly marked deleted here}}
|
|
int x = 10;
|
|
void foo() {
|
|
auto L = [this] { return x; };
|
|
const auto &M = [*this] { return x; };//expected-error{{call to deleted}}
|
|
const auto &M2 = [this] () -> auto&& {
|
|
++x;
|
|
return [*this] { //expected-error{{call to deleted}} expected-warning{{reference to local}}
|
|
return ++x; //expected-error{{read-only}}
|
|
};
|
|
};
|
|
const auto &M3 = [*this] () mutable -> auto&& { //expected-error{{call to deleted}}
|
|
++x;
|
|
return [this] { // expected-warning{{reference to local}}
|
|
return x;
|
|
};
|
|
};
|
|
}
|
|
};
|