summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorMalcolm Parsons <malcolm.parsons@gmail.com>2017-01-13 15:01:06 +0000
committerMalcolm Parsons <malcolm.parsons@gmail.com>2017-01-13 15:01:06 +0000
commit87a036259bb47624f9257b1d247fd50162b2734d (patch)
tree3f63533f3f0257d666d869f6d1cc8027902dd5e0 /clang/lib
parent061f4a5fe6c60116831fa18e7db7faa24c7bd1e2 (diff)
downloadbcm5719-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.cpp4
-rw-r--r--clang/lib/Sema/SemaExprCXX.cpp1
-rw-r--r--clang/lib/Sema/SemaLambda.cpp23
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(
OpenPOWER on IntegriCloud