From: Manman Ren Date: Fri, 1 Jul 2016 22:27:16 +0000 (+0000) Subject: C++14 init-capture: error out instead of crashing. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9f8590177859cf3325c79e98e77d443ee1504cbf;p=clang 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 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@274392 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index cc2a11fccf..65d2341863 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -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(DC)) + if (var->isInitCapture() && + FD->getTemplateInstantiationPattern() == var->getDeclContext()) + break; + if (DC == var->getDeclContext()) + break; Prev = DC; DC = DC->getParent(); } diff --git a/test/SemaCXX/cxx1y-init-captures.cpp b/test/SemaCXX/cxx1y-init-captures.cpp index d36882d8e5..d681954707 100644 --- a/test/SemaCXX/cxx1y-init-captures.cpp +++ b/test/SemaCXX/cxx1y-init-captures.cpp @@ -196,3 +196,13 @@ namespace N3922 { auto a = [x{X()}] { return x.n; }; // ok auto b = [x = {X()}] {}; // expected-error{{}} } + +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}} +} +}