njames93 updated this revision to Diff 328663.
njames93 marked 5 inline comments as done.
njames93 added a comment.

Address comments


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D96975/new/

https://reviews.llvm.org/D96975

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/Sema/SemaExpr.cpp
  clang/lib/Sema/SemaExprCXX.cpp
  clang/test/CXX/drs/dr6xx.cpp
  clang/test/CXX/expr/expr.prim/expr.prim.lambda/p12.cpp
  clang/test/CXX/expr/expr.prim/expr.prim.lambda/p2-generic-lambda-1y.cpp
  clang/test/SemaCXX/cxx1y-generic-lambdas-capturing.cpp
  clang/test/SemaCXX/cxx1y-generic-lambdas.cpp
  clang/test/SemaCXX/cxx1y-init-captures.cpp
  clang/test/SemaCXX/cxx1z-constexpr-lambdas.cpp
  clang/test/SemaCXX/lambda-expressions.cpp
  clang/test/SemaCXX/lambda-invalid-capture.cpp
  clang/test/SemaObjCXX/capturing-flexible-array-in-block.mm

Index: clang/test/SemaObjCXX/capturing-flexible-array-in-block.mm
===================================================================
--- clang/test/SemaObjCXX/capturing-flexible-array-in-block.mm
+++ 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 4 {{capture}}
 }
Index: clang/test/SemaCXX/lambda-invalid-capture.cpp
===================================================================
--- clang/test/SemaCXX/lambda-invalid-capture.cpp
+++ 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 4 {{capture}}
     return sizeof i <
       i; // expected-error {{variable 'i' cannot be implicitly captured in a lambda with no capture-default specified}}
   }();
Index: clang/test/SemaCXX/lambda-expressions.cpp
===================================================================
--- clang/test/SemaCXX/lambda-expressions.cpp
+++ 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 4 {{capture}}
     [&]() { 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 4 {{capture}}
+    []() { 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 4 {{capture}}
+    []() { 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 8 {{capture}}
     [=]() { 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 4 {{capture}}
 
     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 4 {{capture}}
 
     // 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 4 {{capture}}
 
     static int j;
     int &ref_j = j;
@@ -259,7 +259,9 @@
     // 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 2 {{default capture by value}} \
+    // expected-note 4 {{capture 'ts'}}
   }
   template void nested2(int); // ok
   template void nested2(int, int); // expected-note {{in instantiation of}}
@@ -375,7 +377,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 +663,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}}
 }
 };
Index: clang/test/SemaCXX/cxx1z-constexpr-lambdas.cpp
===================================================================
--- clang/test/SemaCXX/cxx1z-constexpr-lambdas.cpp
+++ 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 4 {{capture}}
   int I = L();
 }
 
Index: clang/test/SemaCXX/cxx1y-init-captures.cpp
===================================================================
--- clang/test/SemaCXX/cxx1y-init-captures.cpp
+++ 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 4 {{capture}}
         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 4 {{capture}}
       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 4 {{capture}}
       auto M = [&y = x](T b) { //expected-error {{cannot be implicitly captured}}
         return y;
       };
Index: clang/test/SemaCXX/cxx1y-generic-lambdas.cpp
===================================================================
--- clang/test/SemaCXX/cxx1y-generic-lambdas.cpp
+++ 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 12 {{capture}}
       i = b;  //expected-error 3{{cannot be implicitly captured}}
       return b;
     };
Index: clang/test/SemaCXX/cxx1y-generic-lambdas-capturing.cpp
===================================================================
--- clang/test/SemaCXX/cxx1y-generic-lambdas-capturing.cpp
+++ clang/test/SemaCXX/cxx1y-generic-lambdas-capturing.cpp
@@ -77,13 +77,13 @@
   {
     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 4 {{capture}}
   //[](){ return ({int b = 5; return 'c'; 'x';}); };
 
   //auto X = ^{ return a; };
   
   //auto Y = []() -> auto { return 3; return 'c'; };
-
   }  
 }  
 }
@@ -102,7 +102,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 4 {{capture}}
       DEFINE_SELECTOR(a);
       F_CALL(x, a); //expected-error{{'x' cannot be implicitly captured}}
     };
@@ -137,7 +137,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 4 {{capture}}
       return j + 1; //expected-error{{cannot be implicitly captured}}
     };
   }
@@ -366,10 +366,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 8 {{capture}}
           f(x, c);  //expected-error{{variable 'x'}}
           f(y, c);  //expected-error{{variable 'y'}}
-          return 0; 
+          return 0;
         };
       };
     };
@@ -530,7 +530,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 +561,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 +585,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 +609,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 +632,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-note {{explicitly capture 'this'}}
           f(b); //expected-error{{'this' cannot}}
           int x = i;
         };
@@ -655,8 +655,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 4 {{capture}}
+      const int &r = x;   //expected-error{{variable}}
     };
   }
   { // This variable is not used 
@@ -670,7 +670,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 4 {{capture}}
         int c[sizeof(b)];
         f(x, c);
         f(y, c);
@@ -716,7 +716,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 8 {{capture}}
         return [=] (auto c) {
           return a + y; //expected-error 2{{cannot be implicitly captured}}
         };
@@ -908,7 +908,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 +941,10 @@
 template<class T> 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 +962,8 @@
 YOnlyStatic<FunctorDouble> yos;
 template<class T> 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 +981,8 @@
 
 template<class T> 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 +994,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 +1021,8 @@
 #else
 
 template<class T> 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 4 {{capture}}
+  { return t; };                  //expected-error{{cannot be implicitly captured}}
 }
 
 #endif
@@ -1049,9 +1050,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 +1081,7 @@
   static void f(double) { }
   template<class T>
   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 +1100,7 @@
   void f(int) { }
   template<class T>
   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 +1210,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-note {{explicitly capture 'this'}}
           f(b); //expected-error {{'this' cannot}}
           int x = i;
         };
@@ -1235,9 +1236,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-note {{explicitly capture 'this'}}
           f(b); //expected-error {{'this' cannot}}
           int x = i;
         };
Index: clang/test/CXX/expr/expr.prim/expr.prim.lambda/p2-generic-lambda-1y.cpp
===================================================================
--- clang/test/CXX/expr/expr.prim/expr.prim.lambda/p2-generic-lambda-1y.cpp
+++ clang/test/CXX/expr/expr.prim/expr.prim.lambda/p2-generic-lambda-1y.cpp
@@ -19,7 +19,8 @@
   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 4 {{capture}}
 }
Index: clang/test/CXX/expr/expr.prim/expr.prim.lambda/p12.cpp
===================================================================
--- clang/test/CXX/expr/expr.prim/expr.prim.lambda/p12.cpp
+++ 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 4 {{capture}}
     [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 9 {{capture}}
         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;
Index: clang/test/CXX/drs/dr6xx.cpp
===================================================================
--- clang/test/CXX/drs/dr6xx.cpp
+++ 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 4 {{capture}}
 #endif
   }
 }
Index: clang/lib/Sema/SemaExprCXX.cpp
===================================================================
--- clang/lib/Sema/SemaExprCXX.cpp
+++ clang/lib/Sema/SemaExprCXX.cpp
@@ -1226,6 +1226,14 @@
   }
 }
 
+static void buildLambdaThisCaptureFixit(Sema &Sema, LambdaScopeInfo *LSI) {
+  SourceLocation DiagLoc = LSI->IntroducerRange.getEnd();
+  assert(!LSI->isCXXThisCaptured());
+  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 +1282,12 @@
       LambdaScopeInfo *LSI = dyn_cast<LambdaScopeInfo>(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 +1307,9 @@
       if (BuildAndDiagnose)
         Diag(Loc, diag::err_this_capture)
             << (Explicit && idx == MaxFunctionScopesIndex);
+
+      if (!Explicit)
+        buildLambdaThisCaptureFixit(*this, LSI);
       return true;
     }
     break;
Index: clang/lib/Sema/SemaExpr.cpp
===================================================================
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -17423,6 +17423,71 @@
   return !Invalid;
 }
 
+/// 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) {
+  SmallString<32> FixBuffer;
+  StringRef Separator = LSI->NumExplicitCaptures > 0 ? ", " : "";
+  if (Var->getDeclName().isIdentifier() && !Var->getName().empty()) {
+    // Offer fixes to insert an explicit capture for the variable.
+    // [] -> [VarName]
+    // [OtherCapture] -> [OtherCapture, VarName]
+    SourceLocation VarInsertLoc = LSI->IntroducerRange.getEnd();
+    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);
+  }
+
+  // The default capture specifiers, '=' or '&', must appear first in the
+  // capture body.
+  SourceLocation DefaultInsertLoc =
+      LSI->IntroducerRange.getBegin().getLocWithOffset(1);
+
+  bool CanDefaultCopyCapture = true;
+  // [=, *this] OK since c++17
+  // [=, this] OK since c++20
+  if (LSI->isCXXThisCaptured() && !Sema.getLangOpts().CPlusPlus20) {
+    if (Sema.getLangOpts().CPlusPlus17)
+      CanDefaultCopyCapture = LSI->getCXXThisCapture().isCopyCapture();
+    else
+      CanDefaultCopyCapture = false;
+  }
+
+  if (CanDefaultCopyCapture) {
+    // We can't use default capture by copy if any captures already specified
+    // capture by copy.
+    if (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,
@@ -17512,6 +17577,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);
       }
@@ -17590,9 +17656,11 @@
       if (BuildAndDiagnose) {
         Diag(ExprLoc, diag::err_lambda_impcap) << Var;
         Diag(Var->getLocation(), diag::note_previous_decl) << Var;
-        if (cast<LambdaScopeInfo>(CSI)->Lambda)
-          Diag(cast<LambdaScopeInfo>(CSI)->Lambda->getBeginLoc(),
-               diag::note_lambda_decl);
+        auto *LSI = cast<LambdaScopeInfo>(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
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7455,6 +7455,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<
@@ -7463,6 +7465,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">;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to