C++14 init-capture: error out instead of crashing.

When we have template arguments, we have a function and a pattern, the variable
in init-capture belongs to the pattern decl when checking if the lhs of
"max = current" is modifiable:
  auto find = [max = init](auto current) {
    max = current;
  };

In function isReferenceToNonConstCapture, we handle the case where the decl
context for the variable is not part of the current context.

Instead of crashing, we emit an error message:
cannot assign to a variable captured by copy in a non-mutable lambda

rdar://26997922

llvm-svn: 274392
This commit is contained in:
Manman Ren 2016-07-01 22:27:16 +00:00
parent ad56ea3129
commit ebe8cf55ac
2 changed files with 20 additions and 1 deletions

View File

@ -9653,7 +9653,16 @@ static NonConstCaptureKind isReferenceToNonConstCapture(Sema &S, Expr *E) {
// Decide whether the first capture was for a block or a lambda.
DeclContext *DC = S.CurContext, *Prev = nullptr;
while (DC != var->getDeclContext()) {
// Decide whether the first capture was for a block or a lambda.
while (DC) {
// For init-capture, it is possible that the variable belongs to the
// template pattern of the current context.
if (auto *FD = dyn_cast<FunctionDecl>(DC))
if (var->isInitCapture() &&
FD->getTemplateInstantiationPattern() == var->getDeclContext())
break;
if (DC == var->getDeclContext())
break;
Prev = DC;
DC = DC->getParent();
}

View File

@ -196,3 +196,13 @@ namespace N3922 {
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}}
}
}