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
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to