vsk updated this revision to Diff 165403.
vsk marked an inline comment as done.
https://reviews.llvm.org/D52064
Files:
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/include/clang/Sema/Sema.h
clang/lib/Frontend/FrontendActions.cpp
clang/lib/Sema/SemaLambda.cpp
clang/lib/Sema/SemaTemplateInstantiate.cpp
clang/test/CXX/expr/expr.prim/expr.prim.lambda/p14.cpp
clang/test/SemaCXX/lambda-expressions.cpp
Index: clang/test/SemaCXX/lambda-expressions.cpp
===================================================================
--- clang/test/SemaCXX/lambda-expressions.cpp
+++ clang/test/SemaCXX/lambda-expressions.cpp
@@ -77,8 +77,18 @@
struct G { G(); G(G&); int a; }; // expected-note 6 {{not viable}}
G g;
[=]() { const G* gg = &g; return gg->a; };
- [=]() { return [=]{ const G* gg = &g; return gg->a; }(); }; // expected-error {{no matching constructor for initialization of 'G'}}
- (void)^{ return [=]{ const G* gg = &g; return gg->a; }(); }; // expected-error 2 {{no matching constructor for initialization of 'const G'}}
+ [=]() {
+ return [=]{ // expected-error {{no matching constructor for initialization of 'G'}}
+ const G* gg = &g; // expected-note {{implicitly capturing 'g', first used here}}
+ return gg->a;
+ }();
+ };
+ (void)^{
+ return [=]{ // expected-error {{no matching constructor for initialization of 'const G'}}
+ const G* gg = &g; // expected-error {{no matching constructor for initialization of 'const G'}} expected-note {{implicitly capturing 'g', first used here}}
+ return gg->a;
+ }();
+ };
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}}
@@ -378,7 +388,9 @@
namespace PR18473 {
template<typename T> void f() {
T t(0);
- (void) [=]{ int n = t; }; // expected-error {{deleted}}
+ (void)[=] { // expected-error {{call to deleted constructor of 'PR18473::NoCopy'}}
+ int n = t; // expected-note {{implicitly capturing 't', first used here}}
+ };
}
template void f<int>();
Index: clang/test/CXX/expr/expr.prim/expr.prim.lambda/p14.cpp
===================================================================
--- clang/test/CXX/expr/expr.prim/expr.prim.lambda/p14.cpp
+++ clang/test/CXX/expr/expr.prim/expr.prim.lambda/p14.cpp
@@ -16,7 +16,7 @@
void capture_by_copy(NonCopyable nc, NonCopyable &ncr, const NonConstCopy nco) {
(void)[nc] { }; // expected-error{{capture of variable 'nc' as type 'NonCopyable' calls private copy constructor}}
(void)[=] { // expected-error{{capture of variable 'ncr' as type 'NonCopyable' calls private copy constructor}}
- ncr.foo();
+ ncr.foo(); // expected-note{{implicitly capturing 'ncr', first used here}}
}();
[nco] {}(); // expected-error{{no matching constructor for initialization of 'const NonConstCopy'}}
Index: clang/lib/Sema/SemaTemplateInstantiate.cpp
===================================================================
--- clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -200,6 +200,7 @@
case DeclaringSpecialMember:
case DefiningSynthesizedFunction:
case ExceptionSpecEvaluation:
+ case ImplicitLambdaCaptureInitialization:
return false;
// This function should never be called when Kind's value is Memoization.
@@ -653,6 +654,13 @@
break;
}
+ case CodeSynthesisContext::ImplicitLambdaCaptureInitialization: {
+ Diags.Report(Active->PointOfInstantiation,
+ diag::note_implicitly_capturing_var_first_used_here)
+ << cast<NamedDecl>(Active->Entity);
+ break;
+ }
+
case CodeSynthesisContext::Memoization:
break;
}
@@ -698,6 +706,7 @@
case CodeSynthesisContext::DeclaringSpecialMember:
case CodeSynthesisContext::DefiningSynthesizedFunction:
+ case CodeSynthesisContext::ImplicitLambdaCaptureInitialization:
// This happens in a context unrelated to template instantiation, so
// there is no SFINAE.
return None;
Index: clang/lib/Sema/SemaLambda.cpp
===================================================================
--- clang/lib/Sema/SemaLambda.cpp
+++ clang/lib/Sema/SemaLambda.cpp
@@ -21,6 +21,7 @@
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/SemaLambda.h"
+#include "llvm/ADT/ScopeExit.h"
using namespace clang;
using namespace sema;
@@ -1401,6 +1402,18 @@
SourceLocation Loc =
IsImplicitCapture ? ImplicitCaptureLoc : Capture.getLocation();
+ if (IsImplicitCapture) {
+ Sema::CodeSynthesisContext Ctx;
+ Ctx.Entity = Var;
+ Ctx.Kind = Sema::CodeSynthesisContext::ImplicitLambdaCaptureInitialization;
+ Ctx.PointOfInstantiation = Capture.getLocation();
+ S.pushCodeSynthesisContext(Ctx);
+ }
+ auto PopCodeSynthesisStackOnExit = llvm::make_scope_exit([&] {
+ if (IsImplicitCapture)
+ S.popCodeSynthesisContext();
+ });
+
// C++11 [expr.prim.lambda]p21:
// When the lambda-expression is evaluated, the entities that
// are captured by copy are used to direct-initialize each
Index: clang/lib/Frontend/FrontendActions.cpp
===================================================================
--- clang/lib/Frontend/FrontendActions.cpp
+++ clang/lib/Frontend/FrontendActions.cpp
@@ -351,6 +351,8 @@
return "DefiningSynthesizedFunction";
case CodeSynthesisContext::Memoization:
return "Memoization";
+ case CodeSynthesisContext::ImplicitLambdaCaptureInitialization:
+ return "ImplicitLambdaCaptureInitialization";
}
return "";
}
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -7178,7 +7178,10 @@
/// Memoization means we are _not_ instantiating a template because
/// it is already instantiated (but we entered a context where we
/// would have had to if it was not already instantiated).
- Memoization
+ Memoization,
+
+ /// We are initializing an implicit capture for a lambda.
+ ImplicitLambdaCaptureInitialization,
} Kind;
/// Was the enclosing context a non-instantiation SFINAE context?
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1765,6 +1765,10 @@
"the function it overrides (class type %1 is more qualified than class "
"type %2">;
+// C++ lambdas
+def note_implicitly_capturing_var_first_used_here : Note<
+ "implicitly capturing %0, first used here">;
+
// C++ implicit special member functions
def note_in_declaration_of_implicit_special_member : Note<
"while declaring the implicit %sub{select_special_member_kind}1"
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits