[cfe-commits] r150256 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td include/clang/Sema/DeclSpec.h lib/Parse/ParseExprCXX.cpp lib/Sema/SemaExprCXX.cpp lib/Sema/SemaLambda.cpp test/CXX/expr/expr.prim/expr.prim.lambda/p8.cpp test/FixIt/fixit-cxx0x.cpp

Douglas Gregor dgregor at apple.com
Fri Feb 10 09:46:20 PST 2012


Author: dgregor
Date: Fri Feb 10 11:46:20 2012
New Revision: 150256

URL: http://llvm.org/viewvc/llvm-project?rev=150256&view=rev
Log:
Allow implicit capture of 'this' in a lambda even when the capture
default is '=', and reword the warning about explicitly capturing
'this' in such lambdas to indicate that only explicit capture is
banned. 

Introduce Fix-Its for this and other "save the programmer from
themself" rules regarding what can be explicitly captured and what
must be implicitly captured.

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Sema/DeclSpec.h
    cfe/trunk/lib/Parse/ParseExprCXX.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/lib/Sema/SemaLambda.cpp
    cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p8.cpp
    cfe/trunk/test/FixIt/fixit-cxx0x.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=150256&r1=150255&r2=150256&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Feb 10 11:46:20 2012
@@ -4093,7 +4093,7 @@
 def err_reference_capture_with_reference_default : Error<
   "'&' cannot precede a capture when the capture default is '&'">;
 def err_this_capture_with_copy_default : Error<
-  "'this' cannot appear in a capture list when the capture default is '='">;
+  "'this' cannot be explicitly captured when the capture default is '='">;
 def err_copy_capture_with_copy_default : Error<
   "'&' must precede a capture when the capture default is '='">;
 def err_capture_does_not_name_variable : Error<

Modified: cfe/trunk/include/clang/Sema/DeclSpec.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/DeclSpec.h?rev=150256&r1=150255&r2=150256&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/DeclSpec.h (original)
+++ cfe/trunk/include/clang/Sema/DeclSpec.h Fri Feb 10 11:46:20 2012
@@ -1933,6 +1933,7 @@
 /// LambdaIntroducer - Represents a complete lambda introducer.
 struct LambdaIntroducer {
   SourceRange Range;
+  SourceLocation DefaultLoc;
   LambdaCaptureDefault Default;
   llvm::SmallVector<LambdaCapture, 4> Captures;
 

Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=150256&r1=150255&r2=150256&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Fri Feb 10 11:46:20 2012
@@ -630,11 +630,11 @@
   if (Tok.is(tok::amp) &&
       (NextToken().is(tok::comma) || NextToken().is(tok::r_square))) {
     Intro.Default = LCD_ByRef;
-    ConsumeToken();
+    Intro.DefaultLoc = ConsumeToken();
     first = false;
   } else if (Tok.is(tok::equal)) {
     Intro.Default = LCD_ByCopy;
-    ConsumeToken();
+    Intro.DefaultLoc = ConsumeToken();
     first = false;
   }
 

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=150256&r1=150255&r2=150256&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Fri Feb 10 11:46:20 2012
@@ -686,11 +686,10 @@
       }
       
       if (CSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_LambdaByref ||
+          CSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_LambdaByval ||
           CSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_Block ||
           Explicit) {
         // This closure can capture 'this'; continue looking upwards.
-        // FIXME: Is this check correct?  The rules in the standard are a bit
-        // unclear.
         NumClosures++;
         Explicit = false;
         continue;

Modified: cfe/trunk/lib/Sema/SemaLambda.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLambda.cpp?rev=150256&r1=150255&r2=150256&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLambda.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLambda.cpp Fri Feb 10 11:46:20 2012
@@ -15,6 +15,7 @@
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/ScopeInfo.h"
 #include "clang/Sema/SemaInternal.h"
+#include "clang/Lex/Preprocessor.h"
 #include "clang/AST/ExprCXX.h"
 using namespace clang;
 using namespace sema;
@@ -125,10 +126,13 @@
   LSI->Mutable = (Method->getTypeQualifiers() & Qualifiers::Const) == 0;
  
   // Handle explicit captures.
+  SourceLocation PrevCaptureLoc
+    = Intro.Default == LCD_None? Intro.Range.getBegin() : Intro.DefaultLoc;
   for (llvm::SmallVector<LambdaCapture, 4>::const_iterator
          C = Intro.Captures.begin(), 
          E = Intro.Captures.end(); 
-       C != E; ++C) {
+       C != E; 
+       PrevCaptureLoc = C->Loc, ++C) {
     if (C->Kind == LCK_This) {
       // C++11 [expr.prim.lambda]p8:
       //   An identifier or this shall not appear more than once in a 
@@ -136,7 +140,9 @@
       if (LSI->isCXXThisCaptured()) {
         Diag(C->Loc, diag::err_capture_more_than_once) 
           << "'this'"
-          << SourceRange(LSI->getCXXThisCapture().getLocation());
+          << SourceRange(LSI->getCXXThisCapture().getLocation())
+          << FixItHint::CreateRemoval(
+               SourceRange(PP.getLocForEndOfToken(PrevCaptureLoc), C->Loc));
         continue;
       }
 
@@ -144,7 +150,9 @@
       //   If a lambda-capture includes a capture-default that is =, the 
       //   lambda-capture shall not contain this [...].
       if (Intro.Default == LCD_ByCopy) {
-        Diag(C->Loc, diag::err_this_capture_with_copy_default);
+        Diag(C->Loc, diag::err_this_capture_with_copy_default)
+          << FixItHint::CreateRemoval(
+               SourceRange(PP.getLocForEndOfToken(PrevCaptureLoc), C->Loc));
         continue;
       }
 
@@ -169,10 +177,14 @@
     //   If a lambda-capture includes a capture-default that is =, [...]
     //   each identifier it contains shall be preceded by &.
     if (C->Kind == LCK_ByRef && Intro.Default == LCD_ByRef) {
-      Diag(C->Loc, diag::err_reference_capture_with_reference_default);
+      Diag(C->Loc, diag::err_reference_capture_with_reference_default)
+        << FixItHint::CreateRemoval(
+             SourceRange(PP.getLocForEndOfToken(PrevCaptureLoc), C->Loc));
       continue;
     } else if (C->Kind == LCK_ByCopy && Intro.Default == LCD_ByCopy) {
-      Diag(C->Loc, diag::err_copy_capture_with_copy_default);
+      Diag(C->Loc, diag::err_copy_capture_with_copy_default)
+        << FixItHint::CreateRemoval(
+             SourceRange(PP.getLocForEndOfToken(PrevCaptureLoc), C->Loc));
       continue;
     }
 
@@ -213,7 +225,9 @@
     if (LSI->isCaptured(Var)) {
       Diag(C->Loc, diag::err_capture_more_than_once) 
         << C->Id
-        << SourceRange(LSI->getCapture(Var).getLocation());
+        << SourceRange(LSI->getCapture(Var).getLocation())
+        << FixItHint::CreateRemoval(
+             SourceRange(PP.getLocForEndOfToken(PrevCaptureLoc), C->Loc));
       continue;
     }
 

Modified: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p8.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p8.cpp?rev=150256&r1=150255&r2=150256&view=diff
==============================================================================
--- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p8.cpp (original)
+++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p8.cpp Fri Feb 10 11:46:20 2012
@@ -8,18 +8,22 @@
     (void)[this, this] () {}; // expected-error {{'this' can appear only once}}
     (void)[=, foo] () {}; // expected-error {{'&' must precede a capture when}}
     (void)[=, &foo] () {};
-    (void)[=, this] () {}; // expected-error {{'this' cannot appear}}
+    (void)[=, this] () {}; // expected-error {{'this' cannot be explicitly captured}}
     (void)[&, foo] () {};
     (void)[&, &foo] () {}; // expected-error {{'&' cannot precede a capture when}} 
     (void)[&, this] () {};
   }
 };
 
-struct S2 { void f(int i); };
+struct S2 { 
+  void f(int i); 
+  void g(int i);
+};
 
 void S2::f(int i) {
   (void)[&, i]{ };
   (void)[&, &i]{ }; // expected-error{{'&' cannot precede a capture when the capture default is '&'}}
-  (void)[=, this]{ }; // expected-error{{'this' cannot appear in a capture list when the capture default is '='}}
+  (void)[=, this]{ }; // expected-error{{'this' cannot be explicitly captured}}
+  (void)[=]{ this->g(i); };
   (void)[i, i]{ }; // expected-error{{'i' can appear only once in a capture list}}
 }

Modified: cfe/trunk/test/FixIt/fixit-cxx0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/FixIt/fixit-cxx0x.cpp?rev=150256&r1=150255&r2=150256&view=diff
==============================================================================
--- cfe/trunk/test/FixIt/fixit-cxx0x.cpp (original)
+++ cfe/trunk/test/FixIt/fixit-cxx0x.cpp Fri Feb 10 11:46:20 2012
@@ -46,3 +46,15 @@
     friend enum class E; // expected-error {{must use 'enum' not 'enum class'}}
   };
 }
+
+struct S2 { 
+  void f(int i); 
+  void g(int i);
+};
+
+void S2::f(int i) {
+  (void)[&, &i, &i]{}; // expected-error 2{{'&' cannot precede a capture when the capture default is '&'}}
+  (void)[=, this]{ this->g(5); }; // expected-error{{'this' cannot be explicitly captured}}
+  (void)[i, i]{ }; // expected-error{{'i' can appear only once in a capture list}}
+  (void)[&, i, i]{ }; // expected-error{{'i' can appear only once in a capture list}}
+}





More information about the cfe-commits mailing list