diff options
author | Alexander Shaposhnikov <shal1t712@gmail.com> | 2018-07-16 07:23:47 +0000 |
---|---|---|
committer | Alexander Shaposhnikov <shal1t712@gmail.com> | 2018-07-16 07:23:47 +0000 |
commit | b813e9608d5e93c65454d82760e26ea304f925cb (patch) | |
tree | 4d98d153a35958519c6c82213da52f5d6e8fb2cb /lib | |
parent | e3f43c2ae1bd915046fe173d8ac32389672cad83 (diff) |
[Sema] Add fixit for unused lambda captures
This diff adds a fixit to suggest removing unused lambda captures
in the appropriate diagnostic.
Patch by Andrew Comminos!
Test plan: make check-all
Differential revision: https://reviews.llvm.org/D48845
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@337148 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Parse/ParseExprCXX.cpp | 6 | ||||
-rw-r--r-- | lib/Sema/SemaLambda.cpp | 48 |
2 files changed, 48 insertions, 6 deletions
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index 647069760d..26e7599951 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -808,6 +808,7 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro, IdentifierInfo *Id = nullptr; SourceLocation EllipsisLoc; ExprResult Init; + SourceLocation LocStart = Tok.getLocation(); if (Tok.is(tok::star)) { Loc = ConsumeToken(); @@ -981,8 +982,11 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro, Loc, Kind == LCK_ByRef, Id, InitKind, InitExpr); Init = InitExpr; } + + SourceLocation LocEnd = PrevTokLocation; + Intro.addCapture(Kind, Loc, Id, EllipsisLoc, InitKind, Init, - InitCaptureType); + InitCaptureType, SourceRange(LocStart, LocEnd)); } T.consumeClose(); diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp index 9e53beb449..0b768cc9fa 100644 --- a/lib/Sema/SemaLambda.cpp +++ b/lib/Sema/SemaLambda.cpp @@ -993,6 +993,8 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, CheckCXXThisCapture(C->Loc, /*Explicit=*/true, /*BuildAndDiagnose*/ true, /*FunctionScopeIndexToStopAtPtr*/ nullptr, C->Kind == LCK_StarThis); + if (!LSI->Captures.empty()) + LSI->ExplicitCaptureRanges[LSI->Captures.size() - 1] = C->ExplicitRange; continue; } @@ -1139,6 +1141,8 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, TryCapture_ExplicitByVal; tryCaptureVariable(Var, C->Loc, Kind, EllipsisLoc); } + if (!LSI->Captures.empty()) + LSI->ExplicitCaptureRanges[LSI->Captures.size() - 1] = C->ExplicitRange; } finishLambdaExplicitCaptures(LSI); @@ -1478,12 +1482,13 @@ bool Sema::CaptureHasSideEffects(const Capture &From) { return false; } -void Sema::DiagnoseUnusedLambdaCapture(const Capture &From) { +bool Sema::DiagnoseUnusedLambdaCapture(SourceRange CaptureRange, + const Capture &From) { if (CaptureHasSideEffects(From)) - return; + return false; if (From.isVLATypeCapture()) - return; + return false; auto diag = Diag(From.getLocation(), diag::warn_unused_lambda_capture); if (From.isThisCapture()) @@ -1491,6 +1496,8 @@ void Sema::DiagnoseUnusedLambdaCapture(const Capture &From) { else diag << From.getVariable(); diag << From.isNonODRUsed(); + diag << FixItHint::CreateRemoval(CaptureRange); + return true; } ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, @@ -1532,18 +1539,49 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, // Translate captures. auto CurField = Class->field_begin(); + // True if the current capture has a used capture or default before it. + bool CurHasPreviousCapture = CaptureDefault != LCD_None; + SourceLocation PrevCaptureLoc = CurHasPreviousCapture ? + CaptureDefaultLoc : IntroducerRange.getBegin(); + for (unsigned I = 0, N = LSI->Captures.size(); I != N; ++I, ++CurField) { const Capture &From = LSI->Captures[I]; + assert(!From.isBlockCapture() && "Cannot capture __block variables"); bool IsImplicit = I >= LSI->NumExplicitCaptures; + // Use source ranges of explicit captures for fixits where available. + SourceRange CaptureRange = LSI->ExplicitCaptureRanges[I]; + // Warn about unused explicit captures. + bool IsCaptureUsed = true; if (!CurContext->isDependentContext() && !IsImplicit && !From.isODRUsed()) { // Initialized captures that are non-ODR used may not be eliminated. bool NonODRUsedInitCapture = IsGenericLambda && From.isNonODRUsed() && From.getInitExpr(); - if (!NonODRUsedInitCapture) - DiagnoseUnusedLambdaCapture(From); + if (!NonODRUsedInitCapture) { + bool IsLast = (I + 1) == LSI->NumExplicitCaptures; + SourceRange FixItRange; + if (CaptureRange.isValid()) { + if (!CurHasPreviousCapture && !IsLast) { + // If there are no captures preceding this capture, remove the + // following comma. + FixItRange = SourceRange(CaptureRange.getBegin(), + getLocForEndOfToken(CaptureRange.getEnd())); + } else { + // Otherwise, remove the comma since the last used capture. + FixItRange = SourceRange(getLocForEndOfToken(PrevCaptureLoc), + CaptureRange.getEnd()); + } + } + + IsCaptureUsed = !DiagnoseUnusedLambdaCapture(FixItRange, From); + } + } + + if (CaptureRange.isValid()) { + CurHasPreviousCapture |= IsCaptureUsed; + PrevCaptureLoc = CaptureRange.getEnd(); } // Handle 'this' capture. |