aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2012-02-10 17:46:20 +0000
committerDouglas Gregor <dgregor@apple.com>2012-02-10 17:46:20 +0000
commit3ac109cd17151bb8ad3a40b0cbb0e1923cd6c4a0 (patch)
tree914a4d80e3d45b83bfcf9045f4ceb45b9125dae3 /lib
parent67b2c554dc12f589471713b7b01e9c94257ae593 (diff)
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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150256 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/Parse/ParseExprCXX.cpp4
-rw-r--r--lib/Sema/SemaExprCXX.cpp3
-rw-r--r--lib/Sema/SemaLambda.cpp26
3 files changed, 23 insertions, 10 deletions
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 19a92cc7e7..3974909cb2 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -630,11 +630,11 @@ llvm::Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro)
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;
}
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 63fd869e7b..5a2a827230 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -686,11 +686,10 @@ void Sema::CheckCXXThisCapture(SourceLocation Loc, bool Explicit) {
}
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;
diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp
index 64fe7f7dce..e82654ef06 100644
--- a/lib/Sema/SemaLambda.cpp
+++ b/lib/Sema/SemaLambda.cpp
@@ -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 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
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 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
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 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
// 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 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
// 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 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
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;
}