diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -7462,6 +7462,8 @@ "duration">; def err_this_capture : Error< "'this' cannot be %select{implicitly |}0captured in this context">; + def note_lambda_this_capture_fixit : Note< + "explicitly capture 'this'">; def err_lambda_capture_anonymous_var : Error< "unnamed variable cannot be implicitly captured in a lambda expression">; def err_lambda_capture_flexarray_type : Error< @@ -7470,6 +7472,10 @@ def err_lambda_impcap : Error< "variable %0 cannot be implicitly captured in a lambda with no " "capture-default specified">; + def note_lambda_variable_capture_fixit : Note< + "capture %0 by %select{value|reference}1">; + def note_lambda_default_capture_fixit : Note< + "default capture by %select{value|reference}0">; def note_lambda_decl : Note<"lambda expression begins here">; def err_lambda_unevaluated_operand : Error< "lambda expression in an unevaluated operand">; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -46,6 +46,7 @@ #include "clang/Sema/SemaFixItUtils.h" #include "clang/Sema/SemaInternal.h" #include "clang/Sema/Template.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/SaveAndRestore.h" using namespace clang; @@ -17431,6 +17432,107 @@ return !Invalid; } +static bool canCaptureVariableByCopy(VarDecl *Var, const ASTContext &Context) { + // Offer a Copy fix even if the type is dependent. + if (Var->getType()->isDependentType()) + return true; + QualType T = Var->getType().getNonReferenceType(); + if (T.isTriviallyCopyableType(Context)) + return true; + if (CXXRecordDecl *RD = T->getAsCXXRecordDecl()) { + + if (!(RD = RD->getDefinition())) + return false; + if (RD->hasSimpleCopyConstructor()) + return true; + if (RD->hasUserDeclaredCopyConstructor()) + for (CXXConstructorDecl *Ctor : RD->ctors()) + if (Ctor->isCopyConstructor()) + return !Ctor->isDeleted(); + } + return false; +} + +/// Create up to 4 fix-its for explicit reference and value capture of \p Var or +/// default capture. Fixes may be omitted if they aren't allowed by the +/// standard, for example we can't emit a default copy capture fix-it if we +/// already explicitly copy capture capture another variable. +static void buildLambdaCaptureFixit(Sema &Sema, LambdaScopeInfo *LSI, + VarDecl *Var) { + assert(LSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_None); + // Don't offer Capture by copy of default capture by copy fixes if Var is + // known not to be copy constructible. + bool ShouldOfferCopyFix = canCaptureVariableByCopy(Var, Sema.getASTContext()); + + SmallString<32> FixBuffer; + StringRef Separator = LSI->NumExplicitCaptures > 0 ? ", " : ""; + if (Var->getDeclName().isIdentifier() && !Var->getName().empty()) { + SourceLocation VarInsertLoc = LSI->IntroducerRange.getEnd(); + if (ShouldOfferCopyFix) { + // Offer fixes to insert an explicit capture for the variable. + // [] -> [VarName] + // [OtherCapture] -> [OtherCapture, VarName] + FixBuffer.assign({Separator, Var->getName()}); + Sema.Diag(VarInsertLoc, diag::note_lambda_variable_capture_fixit) + << Var << /*value*/ 0 + << FixItHint::CreateInsertion(VarInsertLoc, FixBuffer); + } + // As above but capture by reference. + FixBuffer.assign({Separator, "&", Var->getName()}); + Sema.Diag(VarInsertLoc, diag::note_lambda_variable_capture_fixit) + << Var << /*reference*/ 1 + << FixItHint::CreateInsertion(VarInsertLoc, FixBuffer); + } + + // Only try to offer default capture if there are no captures excluding this + // and init captures. + // [this]: OK. + // [X = Y]: OK. + // [&A, &B]: Don't offer. + // [A, B]: Don't offer. + if (llvm::any_of(LSI->Captures, [](Capture &C) { + return !C.isThisCapture() && !C.isInitCapture(); + })) + return; + + // The default capture specifiers, '=' or '&', must appear first in the + // capture body. + SourceLocation DefaultInsertLoc = + LSI->IntroducerRange.getBegin().getLocWithOffset(1); + + if (ShouldOfferCopyFix) { + bool CanDefaultCopyCapture = true; + // [=, *this] OK since c++17 + // [=, this] OK since c++20 + if (LSI->isCXXThisCaptured() && !Sema.getLangOpts().CPlusPlus20) + CanDefaultCopyCapture = Sema.getLangOpts().CPlusPlus17 + ? LSI->getCXXThisCapture().isCopyCapture() + : false; + // We can't use default capture by copy if any captures already specified + // capture by copy. + if (CanDefaultCopyCapture && llvm::none_of(LSI->Captures, [](Capture &C) { + return !C.isThisCapture() && !C.isInitCapture() && C.isCopyCapture(); + })) { + FixBuffer.assign({"=", Separator}); + Sema.Diag(DefaultInsertLoc, diag::note_lambda_default_capture_fixit) + << /*value*/ 0 + << FixItHint::CreateInsertion(DefaultInsertLoc, FixBuffer); + } + } + + // We can't use default capture by reference if any captures already specified + // capture by reference. + if (llvm::none_of(LSI->Captures, [](Capture &C) { + return !C.isInitCapture() && C.isReferenceCapture() && + !C.isThisCapture(); + })) { + FixBuffer.assign({"&", Separator}); + Sema.Diag(DefaultInsertLoc, diag::note_lambda_default_capture_fixit) + << /*reference*/ 1 + << FixItHint::CreateInsertion(DefaultInsertLoc, FixBuffer); + } +} + bool Sema::tryCaptureVariable( VarDecl *Var, SourceLocation ExprLoc, TryCaptureKind Kind, SourceLocation EllipsisLoc, bool BuildAndDiagnose, QualType &CaptureType, @@ -17520,6 +17622,7 @@ Diag(ExprLoc, diag::err_lambda_impcap) << Var; Diag(Var->getLocation(), diag::note_previous_decl) << Var; Diag(LSI->Lambda->getBeginLoc(), diag::note_lambda_decl); + buildLambdaCaptureFixit(*this, LSI, Var); } else diagnoseUncapturableValueReference(*this, ExprLoc, Var, DC); } @@ -17598,9 +17701,11 @@ if (BuildAndDiagnose) { Diag(ExprLoc, diag::err_lambda_impcap) << Var; Diag(Var->getLocation(), diag::note_previous_decl) << Var; - if (cast(CSI)->Lambda) - Diag(cast(CSI)->Lambda->getBeginLoc(), - diag::note_lambda_decl); + auto *LSI = cast(CSI); + if (LSI->Lambda) { + Diag(LSI->Lambda->getBeginLoc(), diag::note_lambda_decl); + buildLambdaCaptureFixit(*this, LSI, Var); + } // FIXME: If we error out because an outer lambda can not implicitly // capture a variable that an inner lambda explicitly captures, we // should have the inner lambda do the explicit capture - because diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -1226,6 +1226,18 @@ } } +static void buildLambdaThisCaptureFixit(Sema &Sema, LambdaScopeInfo *LSI) { + SourceLocation DiagLoc = LSI->IntroducerRange.getEnd(); + assert(!LSI->isCXXThisCaptured()); + // [=, this] {}; // until C++20: Error: this when = is the default + if (LSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_LambdaByval && + !Sema.getLangOpts().CPlusPlus20) + return; + Sema.Diag(DiagLoc, diag::note_lambda_this_capture_fixit) + << FixItHint::CreateInsertion( + DiagLoc, LSI->NumExplicitCaptures > 0 ? ", this" : "this"); +} + bool Sema::CheckCXXThisCapture(SourceLocation Loc, const bool Explicit, bool BuildAndDiagnose, const unsigned *const FunctionScopeIndexToStopAt, const bool ByCopy) { @@ -1274,9 +1286,12 @@ LambdaScopeInfo *LSI = dyn_cast(CSI); if (LSI && isGenericLambdaCallOperatorSpecialization(LSI->CallOperator)) { // This context can't implicitly capture 'this'; fail out. - if (BuildAndDiagnose) + if (BuildAndDiagnose) { Diag(Loc, diag::err_this_capture) << (Explicit && idx == MaxFunctionScopesIndex); + if (!Explicit) + buildLambdaThisCaptureFixit(*this, LSI); + } return true; } if (CSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_LambdaByref || @@ -1296,6 +1311,9 @@ if (BuildAndDiagnose) Diag(Loc, diag::err_this_capture) << (Explicit && idx == MaxFunctionScopesIndex); + + if (!Explicit) + buildLambdaThisCaptureFixit(*this, LSI); return true; } break; diff --git a/clang/test/CXX/drs/dr6xx.cpp b/clang/test/CXX/drs/dr6xx.cpp --- a/clang/test/CXX/drs/dr6xx.cpp +++ b/clang/test/CXX/drs/dr6xx.cpp @@ -1153,7 +1153,7 @@ }; #if __cplusplus >= 201103L (void) [] { int arr[N]; (void)arr; }; - (void) [] { f(&N); }; // expected-error {{cannot be implicitly captured}} expected-note {{here}} + (void)[] { f(&N); }; // expected-error {{cannot be implicitly captured}} expected-note {{here}} expected-note 2 {{capture 'N' by}} expected-note 2 {{default capture by}} #endif } } diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p12.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p12.cpp --- a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p12.cpp +++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p12.cpp @@ -42,7 +42,7 @@ [i] {}(); }(); - []() { // expected-note{{lambda expression begins here}} + []() { // expected-note{{lambda expression begins here}} expected-note 2 {{capture 'i' by}} expected-note 2 {{default capture by}} [i] {}(); // expected-error{{variable 'i' cannot be implicitly captured in a lambda with no capture-default specified}} }(); } @@ -64,7 +64,7 @@ void work(int n) { // expected-note{{declared here}} int m = n*n; int j = 40; // expected-note{{declared here}} - auto m3 = [this,m] { // expected-note 3{{lambda expression begins here}} + auto m3 = [this, m] { // expected-note 3{{lambda expression begins here}} expected-note 2 {{capture 'i' by}} expected-note 2 {{capture 'j' by}} expected-note 2 {{capture 'n' by}} auto m4 = [&,j] { // expected-error{{variable 'j' cannot be implicitly captured in a lambda with no capture-default specified}} int x = n; // expected-error{{variable 'n' cannot be implicitly captured in a lambda with no capture-default specified}} x += m; diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p2-generic-lambda-1y.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p2-generic-lambda-1y.cpp --- a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p2-generic-lambda-1y.cpp +++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p2-generic-lambda-1y.cpp @@ -19,7 +19,9 @@ int i2 = sizeof([](auto a, auto b)->void{}(3, '4')); // expected-error{{lambda expression in an unevaluated operand}} \ // expected-error{{invalid application of 'sizeof'}} const std::type_info &ti1 = typeid([](auto &a) -> P& { static P p; return p; }(i)); // expected-warning {{expression with side effects will be evaluated despite being used as an operand to 'typeid'}} - const std::type_info &ti2 = typeid([](auto) -> int { return i; }(i)); // expected-error{{lambda expression in an unevaluated operand}}\ + const std::type_info &ti2 = typeid([](auto) -> int { return i; }(i)); // expected-error{{lambda expression in an unevaluated operand}}\ // expected-error{{cannot be implicitly captured}}\ - // expected-note{{begins here}} + // expected-note{{begins here}}\ + // expected-note 2 {{capture 'i' by}}\ + // expected-note 2 {{default capture by}} } diff --git a/clang/test/SemaCXX/cxx1y-generic-lambdas-capturing.cpp b/clang/test/SemaCXX/cxx1y-generic-lambdas-capturing.cpp --- a/clang/test/SemaCXX/cxx1y-generic-lambdas-capturing.cpp +++ b/clang/test/SemaCXX/cxx1y-generic-lambdas-capturing.cpp @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -emit-llvm-only %s -// RUN: %clang_cc1 -std=c++2a -verify -fsyntax-only -fblocks -emit-llvm-only %s +// RUN: %clang_cc1 -std=c++2a -verify -verify=expected-cxx2a -fsyntax-only -fblocks -emit-llvm-only %s // RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -emit-llvm-only -triple i386-windows-pc %s -// RUN: %clang_cc1 -std=c++2a -verify -fsyntax-only -fblocks -emit-llvm-only -triple i386-windows-pc %s +// RUN: %clang_cc1 -std=c++2a -verify -verify=expected-cxx2a -fsyntax-only -fblocks -emit-llvm-only -triple i386-windows-pc %s // DONTRUNYET: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -fdelayed-template-parsing %s -DDELAYED_TEMPLATE_PARSING // DONTRUNYET: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -fms-extensions %s -DMS_EXTENSIONS // DONTRUNYET: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -fdelayed-template-parsing -fms-extensions %s -DMS_EXTENSIONS -DDELAYED_TEMPLATE_PARSING @@ -77,13 +77,14 @@ { int a; //expected-note{{declared here}} auto B = []() { return ^{ return a; }; }; //expected-error{{cannot be implicitly capture}}\ - //expected-note{{begins here}} + //expected-note{{begins here}}\ + //expected-note 2 {{capture 'a' by}}\ + //expected-note 2 {{default capture by}} //[](){ return ({int b = 5; return 'c'; 'x';}); }; //auto X = ^{ return a; }; //auto Y = []() -> auto { return 3; return 'c'; }; - } } } @@ -102,7 +103,7 @@ } { // should not capture 'x' - even though certain instantiations require - auto L = [](auto a) { //expected-note{{begins here}} + auto L = [](auto a) { //expected-note{{begins here}} expected-note 2 {{capture 'x' by}} expected-note 2 {{default capture by}} DEFINE_SELECTOR(a); F_CALL(x, a); //expected-error{{'x' cannot be implicitly captured}} }; @@ -137,7 +138,7 @@ } { int j = 0; //expected-note{{declared}} - auto L = [](auto a) { //expected-note{{begins here}} + auto L = [](auto a) { //expected-note{{begins here}} expected-note 2 {{capture 'j' by}} expected-note 2 {{default capture by}} return j + 1; //expected-error{{cannot be implicitly captured}} }; } @@ -366,10 +367,10 @@ T t2{t}; return [](auto b) { const int y = 0; //expected-note{{declared here}} - return [](auto c) { //expected-note 2{{lambda expression begins here}} + return [](auto c) { //expected-note 2{{lambda expression begins here}} expected-note 2 {{capture 'x' by}} expected-note 2 {{capture 'y' by}} expected-note 4 {{default capture by}} f(x, c); //expected-error{{variable 'x'}} f(y, c); //expected-error{{variable 'y'}} - return 0; + return 0; }; }; }; @@ -530,7 +531,7 @@ L(3.13); } { - auto L = [](auto a) { + auto L = [](auto a) { // expected-note {{explicitly capture 'this'}} f(a); //expected-error{{this}} }; L(3.13); @@ -561,8 +562,8 @@ static void f(double) { } int g() { - auto L = [=](auto a) { - return [](int i) { + auto L = [=](auto a) { + return [](int i) { // expected-note {{explicitly capture 'this'}} return [=](auto b) { f(decltype(a){}); //expected-error{{this}} int x = i; @@ -585,8 +586,8 @@ static void f(double) { } int g() { - auto L = [=](auto a) { - return [](auto b) { + auto L = [=](auto a) { + return [](auto b) { // expected-note {{explicitly capture 'this'}} return [=](int i) { f(b); f(decltype(a){}); //expected-error{{this}} @@ -609,8 +610,8 @@ static void f(double) { } int g() { - auto L = [=](auto a) { - return [](auto b) { + auto L = [=](auto a) { + return [](auto b) { // expected-note {{explicitly capture 'this'}} return [=](int i) { f(b); //expected-error{{this}} f(decltype(a){}); @@ -632,9 +633,9 @@ static void f(double) { } int g() { - auto L = [=](auto a) { + auto L = [=](auto a) { return [](int i) { - return [=](auto b) { + return [=](auto b) { // expected-cxx2a-note {{explicitly capture 'this'}} f(b); //expected-error{{'this' cannot}} int x = i; }; @@ -655,8 +656,8 @@ { // This variable is used and must be caught early, do not need instantiation const int x = 0; //expected-note{{declared}} - auto L = [](auto a) { //expected-note{{begins}} - const int &r = x; //expected-error{{variable}} + auto L = [](auto a) { //expected-note{{begins}} expected-note 2 {{capture 'x' by}} expected-note 2 {{default capture by}} + const int &r = x; //expected-error{{variable}} }; } { // This variable is not used @@ -670,7 +671,7 @@ const int x = 0; //expected-note{{declared}} auto L = [=](auto a) { // <-- #A const int y = 0; - return [](auto b) { //expected-note{{begins}} + return [](auto b) { //expected-note{{begins}} expected-note 2 {{capture 'x' by}} expected-note 2 {{default capture by}} int c[sizeof(b)]; f(x, c); f(y, c); @@ -716,7 +717,7 @@ int x; auto L = [](auto a) { //expected-note {{declared here}} int y = 10; //expected-note {{declared here}} - return [](int b) { //expected-note 2{{expression begins here}} + return [](int b) { //expected-note 2{{expression begins here}} expected-note 2 {{capture 'a' by}} expected-note 2 {{capture 'y' by}} expected-note 4 {{default capture by}} return [=] (auto c) { return a + y; //expected-error 2{{cannot be implicitly captured}} }; @@ -908,7 +909,7 @@ return 0; } int g2() { - auto lam = [](auto a) { f(a); }; // expected-error{{'this'}} + auto lam = [](auto a) { f(a); }; // expected-error{{'this'}} expected-note {{explicitly capture 'this'}} lam(0); // expected-note{{in instantiation of}} lam(0.0); // ok. return 0; @@ -941,9 +942,10 @@ template struct YUnresolvable2 { void f(int) { } static void f(double) { } - + T t = [](auto a) { f(a); return a; }; //expected-error{{'this'}} \ - //expected-note{{in instantiation of}} + //expected-note{{in instantiation of}}\ + //expected-note {{explicitly capture 'this'}} T t2 = [=](auto b) { f(b); return b; }; }; @@ -961,8 +963,8 @@ YOnlyStatic yos; template struct YOnlyNonStatic { void f(int) { } - - T t = [](auto a) { f(a); return a; }; //expected-error{{'this'}} + + T t = [](auto a) { f(a); return a; }; //expected-error{{'this'}} expected-note {{explicitly capture 'this'}} }; @@ -980,8 +982,8 @@ template struct YThisCapture { const int x = 10; - static double d; - T t = [](auto a) { return x; }; //expected-error{{'this'}} + static double d; + T t = [](auto a) { return x; }; //expected-error{{'this'}} expected-note {{explicitly capture 'this'}} T t2 = [](auto b) { return d; }; T t3 = [this](auto a) { return [=](auto b) { @@ -993,10 +995,10 @@ return x; }; }; - T t5 = [](auto a) { - return [=](auto b) { - return x; //expected-error{{'this'}} - }; + T t5 = [](auto a) { // expected-note {{explicitly capture 'this'}} + return [=](auto b) { + return x; //expected-error{{'this'}} + }; }; }; @@ -1020,8 +1022,8 @@ #else template void foo(T t) { //expected-note{{declared here}} - auto L = []() //expected-note{{begins here}} - { return t; }; //expected-error{{cannot be implicitly captured}} + auto L = []() //expected-note{{begins here}} expected-note 2 {{capture 't' by}} expected-note 2 {{default capture by}} + { return t; }; //expected-error{{cannot be implicitly captured}} } #endif @@ -1049,9 +1051,9 @@ void f(double) { } int g() { - auto L = [=](auto a) { f(a); }; - L(0); - auto L2 = [](auto a) { f(a); }; //expected-error {{cannot be implicitly captured}} + auto L = [=](auto a) { f(a); }; + L(0); + auto L2 = [](auto a) { f(a); }; //expected-error {{cannot be implicitly captured}} expected-note {{explicitly capture 'this'}} return 0; } }; @@ -1080,7 +1082,7 @@ static void f(double) { } template int g(T t) { - auto L = [](auto a) { f(a); }; //expected-error{{'this'}} + auto L = [](auto a) { f(a); }; //expected-error{{'this'}} expected-note {{explicitly capture 'this'}} L(t); // expected-note{{in instantiation of}} return 0; } @@ -1099,7 +1101,7 @@ void f(int) { } template int g(T t) { - auto L = [](auto a) { f(a); }; //expected-error{{'this'}} + auto L = [](auto a) { f(a); }; //expected-error{{'this'}} expected-note {{explicitly capture 'this'}} L(t); return 0; } @@ -1209,9 +1211,9 @@ static void f(double) { } int g() { - auto L = [=](auto a) { + auto L = [=](auto a) { return [](int i) { - return [=](auto b) { + return [=](auto b) { // expected-cxx2a-note {{explicitly capture 'this'}} f(b); //expected-error {{'this' cannot}} int x = i; }; @@ -1235,9 +1237,9 @@ static void f(double) { } int g() { - auto L = [](auto a) { + auto L = [](auto a) { return [=](auto i) { - return [=](auto b) { + return [=](auto b) { // expected-cxx2a-note {{explicitly capture 'this'}} f(b); //expected-error {{'this' cannot}} int x = i; }; diff --git a/clang/test/SemaCXX/cxx1y-generic-lambdas.cpp b/clang/test/SemaCXX/cxx1y-generic-lambdas.cpp --- a/clang/test/SemaCXX/cxx1y-generic-lambdas.cpp +++ b/clang/test/SemaCXX/cxx1y-generic-lambdas.cpp @@ -258,7 +258,7 @@ { int i = 10; //expected-note 3{{declared here}} auto L = [](auto a) { - return [](auto b) { //expected-note 3{{begins here}} + return [](auto b) { //expected-note 3{{begins here}} expected-note 6 {{capture 'i' by}} expected-note 6 {{default capture by}} i = b; //expected-error 3{{cannot be implicitly captured}} return b; }; diff --git a/clang/test/SemaCXX/cxx1y-init-captures.cpp b/clang/test/SemaCXX/cxx1y-init-captures.cpp --- a/clang/test/SemaCXX/cxx1y-init-captures.cpp +++ b/clang/test/SemaCXX/cxx1y-init-captures.cpp @@ -21,10 +21,10 @@ return a; }() ...); }; - auto N2 = [x = y, //expected-note3{{begins here}} + auto N2 = [x = y, //expected-note3{{begins here}} expected-note 6 {{default capture by}} &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}} + o = f([&a(t)](T& ... t)->decltype(auto) { return a; }(t...)...)](T& ... s) { // expected-note 6 {{capture 't' by}} + fv([&a(t)]()->decltype(auto) { //expected-error 3{{captured}} return a; }() ...); }; @@ -57,8 +57,8 @@ } { const int x = 10; - auto L = [k = x](char a) { //expected-note {{declared}} - return [](int b) { //expected-note {{begins}} + auto L = [k = x](char a) { //expected-note {{declared}} + return [](int b) { //expected-note {{begins}} expected-note 2 {{capture 'k' by}} expected-note 2 {{default capture by}} return [j = k](int c) { //expected-error {{cannot be implicitly captured}} return c; }; @@ -117,13 +117,12 @@ } { // 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 L = [z = x](char a) { //expected-note {{begins}} expected-note 2 {{capture 'x' by}} expected-note 2 {{default capture by}} 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; @@ -146,7 +145,7 @@ } { // 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 L = [z = x](char a) { //expected-note {{begins}} expected-note 2 {{capture 'x' by}} expected-note 2 {{default capture by}} auto M = [&y = x](T b) { //expected-error {{cannot be implicitly captured}} return y; }; diff --git a/clang/test/SemaCXX/cxx1z-constexpr-lambdas.cpp b/clang/test/SemaCXX/cxx1z-constexpr-lambdas.cpp --- a/clang/test/SemaCXX/cxx1z-constexpr-lambdas.cpp +++ b/clang/test/SemaCXX/cxx1z-constexpr-lambdas.cpp @@ -93,7 +93,7 @@ } void f(char c) { //expected-note{{declared here}} - auto L = [] { return c; }; //expected-error{{cannot be implicitly captured}} expected-note{{lambda expression begins here}} + auto L = [] { return c; }; //expected-error{{cannot be implicitly captured}} expected-note{{lambda expression begins here}} expected-note 2 {{capture 'c' by}} expected-note 2 {{default capture by}} int I = L(); } diff --git a/clang/test/SemaCXX/lambda-expressions.cpp b/clang/test/SemaCXX/lambda-expressions.cpp --- a/clang/test/SemaCXX/lambda-expressions.cpp +++ b/clang/test/SemaCXX/lambda-expressions.cpp @@ -12,17 +12,17 @@ virtual C& Overload(float); void ImplicitThisCapture() { - [](){(void)Member;}; // expected-error {{'this' cannot be implicitly captured in this context}} - const int var = [](){(void)Member; return 0;}(); // expected-error {{'this' cannot be implicitly captured in this context}} + []() { (void)Member; }; // expected-error {{'this' cannot be implicitly captured in this context}} expected-note {{explicitly capture 'this'}} + const int var = []() {(void)Member; return 0; }(); // expected-error {{'this' cannot be implicitly captured in this context}} expected-note {{explicitly capture 'this'}} [&](){(void)Member;}; [this](){(void)Member;}; [this]{[this]{};}; []{[this]{};};// expected-error {{'this' cannot be implicitly captured in this context}} []{Overload(3);}; - []{Overload();}; // expected-error {{'this' cannot be implicitly captured in this context}} + [] { Overload(); }; // expected-error {{'this' cannot be implicitly captured in this context}} expected-note {{explicitly capture 'this'}} []{(void)typeid(Overload());}; - []{(void)typeid(Overload(.5f));};// expected-error {{'this' cannot be implicitly captured in this context}} + [] { (void)typeid(Overload(.5f)); }; // expected-error {{'this' cannot be implicitly captured in this context}} expected-note {{explicitly capture 'this'}} } }; @@ -47,14 +47,14 @@ namespace ImplicitCapture { void test() { int a = 0; // expected-note 5 {{declared}} - []() { return a; }; // expected-error {{variable 'a' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{begins here}} + []() { return a; }; // expected-error {{variable 'a' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{begins here}} expected-note 2 {{capture 'a' by}} expected-note 2 {{default capture by}} [&]() { return a; }; [=]() { return a; }; [=]() { int* b = &a; }; // expected-error {{cannot initialize a variable of type 'int *' with an rvalue of type 'const int *'}} [=]() { return [&]() { return a; }; }; - []() { return [&]() { return a; }; }; // expected-error {{variable 'a' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{lambda expression begins here}} - []() { return ^{ return a; }; };// expected-error {{variable 'a' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{lambda expression begins here}} - []() { return [&a] { return a; }; }; // expected-error 2 {{variable 'a' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note 2 {{lambda expression begins here}} + []() { return [&]() { return a; }; }; // expected-error {{variable 'a' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{lambda expression begins here}} expected-note 2 {{capture 'a' by}} expected-note 2 {{default capture by}} + []() { return ^{ return a; }; };// expected-error {{variable 'a' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{lambda expression begins here}} expected-note 2 {{capture 'a' by}} expected-note 2 {{default capture by}} + []() { return [&a] { return a; }; }; // expected-error 2 {{variable 'a' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note 2 {{lambda expression begins here}} expected-note 4 {{capture 'a' by}} expected-note 4 {{default capture by}} [=]() { return [&a] { return a; }; }; // const int b = 2; @@ -74,7 +74,7 @@ int f[10]; // expected-note {{declared}} [&]() { return f[2]; }; (void) ^{ return []() { return f[2]; }; }; // expected-error {{variable 'f' cannot be implicitly captured in a lambda with no capture-default specified}} \ - // expected-note{{lambda expression begins here}} + // expected-note{{lambda expression begins here}} expected-note 2 {{capture 'f' by}} expected-note 2 {{default capture by}} struct G { G(); G(G&); int a; }; // expected-note 6 {{not viable}} G g; @@ -83,13 +83,13 @@ (void)^{ return [=]{ const G* gg = &g; return gg->a; }(); }; // expected-error 2 {{no matching constructor for initialization of 'const G'}} const int h = a; // expected-note {{declared}} - []() { return h; }; // expected-error {{variable 'h' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{lambda expression begins here}} + []() { return h; }; // expected-error {{variable 'h' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{lambda expression begins here}} expected-note 2 {{capture 'h' by}} expected-note 2 {{default capture by}} // References can appear in constant expressions if they are initialized by // reference constant expressions. int i; int &ref_i = i; // expected-note {{declared}} - [] { return ref_i; }; // expected-error {{variable 'ref_i' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{lambda expression begins here}} + [] { return ref_i; }; // expected-error {{variable 'ref_i' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{lambda expression begins here}} expected-note 2 {{capture 'ref_i' by}} expected-note 2 {{default capture by}} static int j; int &ref_j = j; @@ -259,7 +259,8 @@ // instantiation backtrace. f([&ts] { return (int)f(ts...); } ()...); // \ // expected-error 2{{'ts' cannot be implicitly captured}} \ - // expected-note 2{{lambda expression begins here}} + // expected-note 2{{lambda expression begins here}} \ + // expected-note 4 {{capture 'ts' by}} } template void nested2(int); // ok template void nested2(int, int); // expected-note {{in instantiation of}} @@ -375,7 +376,7 @@ int a = [=]{ return n; }(); // ok int b = [=]{ return [=]{ return n; }(); }(); // ok int c = []{ int k = 0; return [=]{ return k; }(); }(); // ok - int d = []{ return [=]{ return n; }(); }(); // expected-error {{'this' cannot be implicitly captured in this context}} + int d = [] { return [=] { return n; }(); }(); // expected-error {{'this' cannot be implicitly captured in this context}} expected-note {{explicitly capture 'this'}} }; } @@ -661,6 +662,6 @@ }; [] { return i; }; // expected-error {{variable '' cannot be implicitly captured in a lambda with no capture-default specified}} // expected-note@-1 {{lambda expression begins here}} - + // expected-note@-2 2 {{default capture by}} } }; diff --git a/clang/test/SemaCXX/lambda-invalid-capture.cpp b/clang/test/SemaCXX/lambda-invalid-capture.cpp --- a/clang/test/SemaCXX/lambda-invalid-capture.cpp +++ b/clang/test/SemaCXX/lambda-invalid-capture.cpp @@ -18,7 +18,7 @@ } int pr43080(int i) { // expected-note {{declared here}} - return [] { // expected-note {{begins here}} + return [] { // expected-note {{begins here}} expected-note 2 {{capture 'i' by}} expected-note 2 {{default capture by}} return sizeof i < i; // expected-error {{variable 'i' cannot be implicitly captured in a lambda with no capture-default specified}} }(); diff --git a/clang/test/SemaObjCXX/capturing-flexible-array-in-block.mm b/clang/test/SemaObjCXX/capturing-flexible-array-in-block.mm --- a/clang/test/SemaObjCXX/capturing-flexible-array-in-block.mm +++ b/clang/test/SemaObjCXX/capturing-flexible-array-in-block.mm @@ -5,5 +5,5 @@ struct { int x; int y[]; } a; // expected-note 3 {{'a' declared here}} ^{return a.x;}(); // expected-error {{cannot refer to declaration of structure variable with flexible array member inside block}} [=] {return a.x;}(); // expected-error {{variable 'a' with flexible array member cannot be captured in a lambda expression}} - [] {return a.x;}(); // expected-error {{variable 'a' cannot be implicitly captured in a lambda with no capture-default}} expected-note {{here}} + [] {return a.x;}(); // expected-error {{variable 'a' cannot be implicitly captured in a lambda with no capture-default}} expected-note {{here}} expected-note 2 {{capture 'a' by}} expected-note 2 {{default capture by}} }