diff options
author | Malcolm Parsons <malcolm.parsons@gmail.com> | 2017-01-13 15:01:06 +0000 |
---|---|---|
committer | Malcolm Parsons <malcolm.parsons@gmail.com> | 2017-01-13 15:01:06 +0000 |
commit | 87a036259bb47624f9257b1d247fd50162b2734d (patch) | |
tree | 3f63533f3f0257d666d869f6d1cc8027902dd5e0 /clang/lib | |
parent | 061f4a5fe6c60116831fa18e7db7faa24c7bd1e2 (diff) | |
download | bcm5719-llvm-87a036259bb47624f9257b1d247fd50162b2734d.tar.gz bcm5719-llvm-87a036259bb47624f9257b1d247fd50162b2734d.zip |
[Sema] Add warning for unused lambda captures
Summary:
Warn when a lambda explicitly captures something that is not used in its body.
The warning is part of -Wunused and can be enabled with -Wunused-lambda-capture.
Reviewers: rsmith, arphaman, jbcoe, aaron.ballman
Subscribers: Quuxplusone, arphaman, cfe-commits
Differential Revision: https://reviews.llvm.org/D28467
llvm-svn: 291905
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Sema/SemaLambda.cpp | 23 |
3 files changed, 25 insertions, 3 deletions
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index d62e8fd68b6..7b404f40a76 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -13916,8 +13916,10 @@ bool Sema::tryCaptureVariable( // Check whether we've already captured it. if (isVariableAlreadyCapturedInScopeInfo(CSI, Var, Nested, CaptureType, - DeclRefType)) + DeclRefType)) { + CSI->getCapture(Var).markUsed(BuildAndDiagnose); break; + } // If we are instantiating a generic lambda call operator body, // we do not want to capture new variables. What was captured // during either a lambdas transformation or initial parsing diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index b2fb33f5343..66bdf1a2da8 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -1106,6 +1106,7 @@ bool Sema::CheckCXXThisCapture(SourceLocation Loc, const bool Explicit, dyn_cast<CapturingScopeInfo>(FunctionScopes[idx])) { if (CSI->CXXThisCaptureIndex != 0) { // 'this' is already being captured; there isn't anything more to do. + CSI->Captures[CSI->CXXThisCaptureIndex - 1].markUsed(BuildAndDiagnose); break; } LambdaScopeInfo *LSI = dyn_cast<LambdaScopeInfo>(CSI); diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index a0d574915eb..da2768f2131 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -1384,7 +1384,7 @@ static void addBlockPointerConversion(Sema &S, } static ExprResult performLambdaVarCaptureInitialization( - Sema &S, LambdaScopeInfo::Capture &Capture, FieldDecl *Field) { + Sema &S, const LambdaScopeInfo::Capture &Capture, FieldDecl *Field) { assert(Capture.isVariableCapture() && "not a variable capture"); auto *Var = Capture.getVariable(); @@ -1438,6 +1438,21 @@ mapImplicitCaptureStyle(CapturingScopeInfo::ImplicitCaptureStyle ICS) { llvm_unreachable("Unknown implicit capture style"); } +void Sema::DiagnoseUnusedLambdaCapture(const LambdaScopeInfo::Capture &From) { + if (!From.isVLATypeCapture()) { + Expr *Init = From.getInitExpr(); + if (Init && Init->HasSideEffects(Context)) + return; + } + + auto diag = Diag(From.getLocation(), diag::warn_unused_lambda_capture); + if (From.isThisCapture()) + diag << "'this'"; + else + diag << From.getVariable(); + diag << From.isNonODRUsed(); +} + ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, LambdaScopeInfo *LSI) { // Collect information from the lambda scope. @@ -1476,10 +1491,14 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, // Translate captures. auto CurField = Class->field_begin(); for (unsigned I = 0, N = LSI->Captures.size(); I != N; ++I, ++CurField) { - LambdaScopeInfo::Capture From = LSI->Captures[I]; + const LambdaScopeInfo::Capture &From = LSI->Captures[I]; assert(!From.isBlockCapture() && "Cannot capture __block variables"); bool IsImplicit = I >= LSI->NumExplicitCaptures; + // Warn about unused explicit captures. + if (!CurContext->isDependentContext() && !IsImplicit && !From.isODRUsed()) + DiagnoseUnusedLambdaCapture(From); + // Handle 'this' capture. if (From.isThisCapture()) { Captures.push_back( |