<div dir="ltr"><a href="https://bugs.llvm.org/show_bug.cgi?id=31977">https://bugs.llvm.org/show_bug.cgi?id=31977</a> makes the good point that this is warning on a certain idiomatic use of capture-by-value to extend the lifetime of an RAII object; consider:<div><br></div><div> shared_ptr<Foo> p = /*...*/;</div><div> int *q = &p->n;</div><div> return [=, p] { return *q++; }<br><div class="gmail_extra"><br></div><div class="gmail_extra">Here, we'll warn that the capture of p is unused, but it's not -- the "use" is to hold a reference to keep the Foo object alive.</div><div class="gmail_extra"><br></div><div class="gmail_extra">I'd suggest suppressing the warning for a by-copy capture of a variable with a non-trivial destructor (this mirrors what we do for -Wunused-variable).</div><div class="gmail_extra"><br><div class="gmail_quote">On 13 January 2017 at 07:01, Malcolm Parsons via cfe-commits <span dir="ltr"><<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Author: malcolm.parsons<br>
Date: Fri Jan 13 09:01:06 2017<br>
New Revision: 291905<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=291905&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project?rev=291905&view=rev</a><br>
Log:<br>
[Sema] Add warning for unused lambda captures<br>
<br>
Summary:<br>
Warn when a lambda explicitly captures something that is not used in its body.<br>
<br>
The warning is part of -Wunused and can be enabled with -Wunused-lambda-capture.<br>
<br>
Reviewers: rsmith, arphaman, jbcoe, aaron.ballman<br>
<br>
Subscribers: Quuxplusone, arphaman, cfe-commits<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D28467" rel="noreferrer" target="_blank">https://reviews.llvm.org/<wbr>D28467</a><br>
<br>
Added:<br>
cfe/trunk/test/SemaCXX/warn-<wbr>unused-lambda-capture.cpp<br>
Modified:<br>
cfe/trunk/include/clang/Basic/<wbr>DiagnosticGroups.td<br>
cfe/trunk/include/clang/Basic/<wbr>DiagnosticSemaKinds.td<br>
cfe/trunk/include/clang/Sema/<wbr>ScopeInfo.h<br>
cfe/trunk/include/clang/Sema/<wbr>Sema.h<br>
cfe/trunk/lib/Sema/SemaExpr.<wbr>cpp<br>
cfe/trunk/lib/Sema/<wbr>SemaExprCXX.cpp<br>
cfe/trunk/lib/Sema/SemaLambda.<wbr>cpp<br>
cfe/trunk/test/CXX/expr/expr.<wbr>prim/expr.prim.lambda/p12.cpp<br>
cfe/trunk/test/CXX/expr/expr.<wbr>prim/expr.prim.lambda/p13.cpp<br>
cfe/trunk/test/CXX/expr/expr.<wbr>prim/expr.prim.lambda/p16.cpp<br>
cfe/trunk/test/CXX/expr/expr.<wbr>prim/expr.prim.lambda/p18.cpp<br>
cfe/trunk/test/CXX/expr/expr.<wbr>prim/expr.prim.lambda/p19.cpp<br>
cfe/trunk/test/SemaCXX/<wbr>uninitialized.cpp<br>
<br>
Modified: cfe/trunk/include/clang/Basic/<wbr>DiagnosticGroups.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?rev=291905&r1=291904&r2=291905&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/Basic/DiagnosticGroups.<wbr>td?rev=291905&r1=291904&r2=<wbr>291905&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/Basic/<wbr>DiagnosticGroups.td (original)<br>
+++ cfe/trunk/include/clang/Basic/<wbr>DiagnosticGroups.td Fri Jan 13 09:01:06 2017<br>
@@ -480,6 +480,7 @@ def UnusedFunction : DiagGroup<"unused-f<br>
def UnusedMemberFunction : DiagGroup<"unused-member-<wbr>function",<br>
[UnneededMemberFunction]>;<br>
def UnusedLabel : DiagGroup<"unused-label">;<br>
+def UnusedLambdaCapture : DiagGroup<"unused-lambda-<wbr>capture">;<br>
def UnusedParameter : DiagGroup<"unused-parameter">;<br>
def UnusedResult : DiagGroup<"unused-result">;<br>
def PotentiallyEvaluatedExpression : DiagGroup<"potentially-<wbr>evaluated-expression">;<br>
@@ -617,8 +618,9 @@ def Unused : DiagGroup<"unused",<br>
[UnusedArgument, UnusedFunction, UnusedLabel,<br>
// UnusedParameter, (matches GCC's behavior)<br>
// UnusedMemberFunction, (clean-up llvm before enabling)<br>
- UnusedPrivateField, UnusedLocalTypedef,<br>
- UnusedValue, UnusedVariable, UnusedPropertyIvar]>,<br>
+ UnusedPrivateField, UnusedLambdaCapture,<br>
+ UnusedLocalTypedef, UnusedValue, UnusedVariable,<br>
+ UnusedPropertyIvar]>,<br>
DiagCategory<"Unused Entity Issue">;<br>
<br>
// Format settings.<br>
<br>
Modified: cfe/trunk/include/clang/Basic/<wbr>DiagnosticSemaKinds.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=291905&r1=291904&r2=291905&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/Basic/<wbr>DiagnosticSemaKinds.td?rev=<wbr>291905&r1=291904&r2=291905&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/Basic/<wbr>DiagnosticSemaKinds.td (original)<br>
+++ cfe/trunk/include/clang/Basic/<wbr>DiagnosticSemaKinds.td Fri Jan 13 09:01:06 2017<br>
@@ -316,6 +316,9 @@ def warn_unneeded_member_function : Warn<br>
InGroup<<wbr>UnneededMemberFunction>, DefaultIgnore;<br>
def warn_unused_private_field: Warning<"private field %0 is not used">,<br>
InGroup<UnusedPrivateField>, DefaultIgnore;<br>
+def warn_unused_lambda_capture: Warning<"lambda capture %0 is not "<br>
+ "%select{used|required to be captured for use in an unevaluated context}1">,<br>
+ InGroup<UnusedLambdaCapture>, DefaultIgnore;<br>
<br>
def warn_parameter_size: Warning<<br>
"%0 is a large (%1 bytes) pass-by-value argument; "<br>
<br>
Modified: cfe/trunk/include/clang/Sema/<wbr>ScopeInfo.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/ScopeInfo.h?rev=291905&r1=291904&r2=291905&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/Sema/ScopeInfo.h?rev=<wbr>291905&r1=291904&r2=291905&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/Sema/<wbr>ScopeInfo.h (original)<br>
+++ cfe/trunk/include/clang/Sema/<wbr>ScopeInfo.h Fri Jan 13 09:01:06 2017<br>
@@ -452,6 +452,14 @@ public:<br>
/// non-static data member that would hold the capture.<br>
QualType CaptureType;<br>
<br>
+ /// \brief Whether an explicit capture has been odr-used in the body of the<br>
+ /// lambda.<br>
+ bool ODRUsed;<br>
+<br>
+ /// \brief Whether an explicit capture has been non-odr-used in the body of<br>
+ /// the lambda.<br>
+ bool NonODRUsed;<br>
+<br>
public:<br>
Capture(VarDecl *Var, bool Block, bool ByRef, bool IsNested,<br>
SourceLocation Loc, SourceLocation EllipsisLoc,<br>
@@ -460,7 +468,8 @@ public:<br>
InitExprAndCaptureKind(<br>
Cpy, !Var ? Cap_VLA : Block ? Cap_Block : ByRef ? Cap_ByRef<br>
: Cap_ByCopy),<br>
- Loc(Loc), EllipsisLoc(EllipsisLoc), CaptureType(CaptureType) {}<br>
+ Loc(Loc), EllipsisLoc(EllipsisLoc), CaptureType(CaptureType),<br>
+ ODRUsed(false), NonODRUsed(false) {}<br>
<br>
enum IsThisCapture { ThisCapture };<br>
Capture(IsThisCapture, bool IsNested, SourceLocation Loc,<br>
@@ -468,7 +477,8 @@ public:<br>
: VarAndNestedAndThis(<br>
nullptr, (IsThisCaptured | (IsNested ? IsNestedCapture : 0))),<br>
InitExprAndCaptureKind(Cpy, ByCopy ? Cap_ByCopy : Cap_ByRef),<br>
- Loc(Loc), EllipsisLoc(), CaptureType(CaptureType) {}<br>
+ Loc(Loc), EllipsisLoc(), CaptureType(CaptureType), ODRUsed(false),<br>
+ NonODRUsed(false) {}<br>
<br>
bool isThisCapture() const {<br>
return VarAndNestedAndThis.getInt() & IsThisCaptured;<br>
@@ -491,6 +501,9 @@ public:<br>
bool isNested() const {<br>
return VarAndNestedAndThis.getInt() & IsNestedCapture;<br>
}<br>
+ bool isODRUsed() const { return ODRUsed; }<br>
+ bool isNonODRUsed() const { return NonODRUsed; }<br>
+ void markUsed(bool IsODRUse) { (IsODRUse ? ODRUsed : NonODRUsed) = true; }<br>
<br>
VarDecl *getVariable() const {<br>
return VarAndNestedAndThis.<wbr>getPointer();<br>
<br>
Modified: cfe/trunk/include/clang/Sema/<wbr>Sema.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=291905&r1=291904&r2=291905&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/Sema/Sema.h?rev=291905&<wbr>r1=291904&r2=291905&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/Sema/<wbr>Sema.h (original)<br>
+++ cfe/trunk/include/clang/Sema/<wbr>Sema.h Fri Jan 13 09:01:06 2017<br>
@@ -5323,6 +5323,9 @@ public:<br>
ExprResult ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,<br>
Scope *CurScope);<br>
<br>
+ /// \brief Diagnose if an explicit lambda capture is unused.<br>
+ void DiagnoseUnusedLambdaCapture(<wbr>const sema::LambdaScopeInfo::Capture &From);<br>
+<br>
/// \brief Complete a lambda-expression having processed and attached the<br>
/// lambda body.<br>
ExprResult BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaExpr.<wbr>cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=291905&r1=291904&r2=291905&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Sema/<wbr>SemaExpr.cpp?rev=291905&r1=<wbr>291904&r2=291905&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Sema/SemaExpr.<wbr>cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaExpr.<wbr>cpp Fri Jan 13 09:01:06 2017<br>
@@ -13916,8 +13916,10 @@ bool Sema::tryCaptureVariable(<br>
<br>
// Check whether we've already captured it.<br>
if (<wbr>isVariableAlreadyCapturedInSco<wbr>peInfo(CSI, Var, Nested, CaptureType,<br>
- DeclRefType))<br>
+ DeclRefType)) {<br>
+ CSI->getCapture(Var).markUsed(<wbr>BuildAndDiagnose);<br>
break;<br>
+ }<br>
// If we are instantiating a generic lambda call operator body,<br>
// we do not want to capture new variables. What was captured<br>
// during either a lambdas transformation or initial parsing<br>
<br>
Modified: cfe/trunk/lib/Sema/<wbr>SemaExprCXX.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=291905&r1=291904&r2=291905&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Sema/<wbr>SemaExprCXX.cpp?rev=291905&r1=<wbr>291904&r2=291905&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Sema/<wbr>SemaExprCXX.cpp (original)<br>
+++ cfe/trunk/lib/Sema/<wbr>SemaExprCXX.cpp Fri Jan 13 09:01:06 2017<br>
@@ -1106,6 +1106,7 @@ bool Sema::CheckCXXThisCapture(<wbr>SourceLoc<br>
dyn_cast<CapturingScopeInfo>(<wbr>FunctionScopes[idx])) {<br>
if (CSI->CXXThisCaptureIndex != 0) {<br>
// 'this' is already being captured; there isn't anything more to do.<br>
+ CSI->Captures[CSI-><wbr>CXXThisCaptureIndex - 1].markUsed(BuildAndDiagnose);<br>
break;<br>
}<br>
LambdaScopeInfo *LSI = dyn_cast<LambdaScopeInfo>(CSI)<wbr>;<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaLambda.<wbr>cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLambda.cpp?rev=291905&r1=291904&r2=291905&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Sema/<wbr>SemaLambda.cpp?rev=291905&r1=<wbr>291904&r2=291905&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Sema/SemaLambda.<wbr>cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaLambda.<wbr>cpp Fri Jan 13 09:01:06 2017<br>
@@ -1384,7 +1384,7 @@ static void addBlockPointerConversion(Se<br>
}<br>
<br>
static ExprResult performLambdaVarCaptureInitial<wbr>ization(<br>
- Sema &S, LambdaScopeInfo::Capture &Capture, FieldDecl *Field) {<br>
+ Sema &S, const LambdaScopeInfo::Capture &Capture, FieldDecl *Field) {<br>
assert(Capture.<wbr>isVariableCapture() && "not a variable capture");<br>
<br>
auto *Var = Capture.getVariable();<br>
@@ -1438,6 +1438,21 @@ mapImplicitCaptureStyle(<wbr>CapturingScopeIn<br>
llvm_unreachable("Unknown implicit capture style");<br>
}<br>
<br>
+void Sema::<wbr>DiagnoseUnusedLambdaCapture(<wbr>const LambdaScopeInfo::Capture &From) {<br>
+ if (!From.isVLATypeCapture()) {<br>
+ Expr *Init = From.getInitExpr();<br>
+ if (Init && Init->HasSideEffects(Context))<br>
+ return;<br>
+ }<br>
+<br>
+ auto diag = Diag(From.getLocation(), diag::warn_unused_lambda_<wbr>capture);<br>
+ if (From.isThisCapture())<br>
+ diag << "'this'";<br>
+ else<br>
+ diag << From.getVariable();<br>
+ diag << From.isNonODRUsed();<br>
+}<br>
+<br>
ExprResult Sema::BuildLambdaExpr(<wbr>SourceLocation StartLoc, SourceLocation EndLoc,<br>
LambdaScopeInfo *LSI) {<br>
// Collect information from the lambda scope.<br>
@@ -1476,10 +1491,14 @@ ExprResult Sema::BuildLambdaExpr(SourceL<br>
// Translate captures.<br>
auto CurField = Class->field_begin();<br>
for (unsigned I = 0, N = LSI->Captures.size(); I != N; ++I, ++CurField) {<br>
- LambdaScopeInfo::Capture From = LSI->Captures[I];<br>
+ const LambdaScopeInfo::Capture &From = LSI->Captures[I];<br>
assert(!From.isBlockCapture() && "Cannot capture __block variables");<br>
bool IsImplicit = I >= LSI->NumExplicitCaptures;<br>
<br>
+ // Warn about unused explicit captures.<br>
+ if (!CurContext-><wbr>isDependentContext() && !IsImplicit && !From.isODRUsed())<br>
+ DiagnoseUnusedLambdaCapture(<wbr>From);<br>
+<br>
// Handle 'this' capture.<br>
if (From.isThisCapture()) {<br>
Captures.push_back(<br>
<br>
Modified: cfe/trunk/test/CXX/expr/expr.<wbr>prim/expr.prim.lambda/p12.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p12.cpp?rev=291905&r1=291904&r2=291905&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/CXX/<wbr>expr/expr.prim/expr.prim.<wbr>lambda/p12.cpp?rev=291905&r1=<wbr>291904&r2=291905&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/CXX/expr/expr.<wbr>prim/expr.prim.lambda/p12.cpp (original)<br>
+++ cfe/trunk/test/CXX/expr/expr.<wbr>prim/expr.prim.lambda/p12.cpp Fri Jan 13 09:01:06 2017<br>
@@ -1,4 +1,4 @@<br>
-// RUN: %clang_cc1 -std=c++11 %s -Wunused -verify<br>
+// RUN: %clang_cc1 -std=c++11 %s -Wunused -Wno-unused-lambda-capture -verify<br>
<br>
void odr_used() {<br>
int i = 17;<br>
<br>
Modified: cfe/trunk/test/CXX/expr/expr.<wbr>prim/expr.prim.lambda/p13.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p13.cpp?rev=291905&r1=291904&r2=291905&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/CXX/<wbr>expr/expr.prim/expr.prim.<wbr>lambda/p13.cpp?rev=291905&r1=<wbr>291904&r2=291905&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/CXX/expr/expr.<wbr>prim/expr.prim.lambda/p13.cpp (original)<br>
+++ cfe/trunk/test/CXX/expr/expr.<wbr>prim/expr.prim.lambda/p13.cpp Fri Jan 13 09:01:06 2017<br>
@@ -1,4 +1,4 @@<br>
-// RUN: %clang_cc1 -std=c++11 %s -Wunused -verify<br>
+// RUN: %clang_cc1 -std=c++11 %s -Wunused -Wno-unused-lambda-capture -verify<br>
<br>
void f2() {<br>
int i = 1;<br>
<br>
Modified: cfe/trunk/test/CXX/expr/expr.<wbr>prim/expr.prim.lambda/p16.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p16.cpp?rev=291905&r1=291904&r2=291905&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/CXX/<wbr>expr/expr.prim/expr.prim.<wbr>lambda/p16.cpp?rev=291905&r1=<wbr>291904&r2=291905&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/CXX/expr/expr.<wbr>prim/expr.prim.lambda/p16.cpp (original)<br>
+++ cfe/trunk/test/CXX/expr/expr.<wbr>prim/expr.prim.lambda/p16.cpp Fri Jan 13 09:01:06 2017<br>
@@ -1,4 +1,4 @@<br>
-// RUN: %clang_cc1 -std=c++11 %s -Wunused -verify<br>
+// RUN: %clang_cc1 -std=c++11 %s -Wunused -Wno-unused-lambda-capture -verify<br>
<br>
<br>
struct X {<br>
<br>
Modified: cfe/trunk/test/CXX/expr/expr.<wbr>prim/expr.prim.lambda/p18.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p18.cpp?rev=291905&r1=291904&r2=291905&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/CXX/<wbr>expr/expr.prim/expr.prim.<wbr>lambda/p18.cpp?rev=291905&r1=<wbr>291904&r2=291905&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/CXX/expr/expr.<wbr>prim/expr.prim.lambda/p18.cpp (original)<br>
+++ cfe/trunk/test/CXX/expr/expr.<wbr>prim/expr.prim.lambda/p18.cpp Fri Jan 13 09:01:06 2017<br>
@@ -1,4 +1,4 @@<br>
-// RUN: %clang_cc1 -std=c++11 %s -Wunused -verify<br>
+// RUN: %clang_cc1 -std=c++11 %s -Wunused -Wno-unused-lambda-capture -verify<br>
// expected-no-diagnostics<br>
<br>
template<typename T, typename U><br>
<br>
Modified: cfe/trunk/test/CXX/expr/expr.<wbr>prim/expr.prim.lambda/p19.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p19.cpp?rev=291905&r1=291904&r2=291905&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/CXX/<wbr>expr/expr.prim/expr.prim.<wbr>lambda/p19.cpp?rev=291905&r1=<wbr>291904&r2=291905&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/CXX/expr/expr.<wbr>prim/expr.prim.lambda/p19.cpp (original)<br>
+++ cfe/trunk/test/CXX/expr/expr.<wbr>prim/expr.prim.lambda/p19.cpp Fri Jan 13 09:01:06 2017<br>
@@ -1,4 +1,4 @@<br>
-// RUN: %clang_cc1 -std=c++11 %s -Wunused -verify<br>
+// RUN: %clang_cc1 -std=c++11 %s -Wunused -Wno-unused-lambda-capture -verify<br>
<br>
struct MoveOnly {<br>
MoveOnly(MoveOnly&&);<br>
<br>
Modified: cfe/trunk/test/SemaCXX/<wbr>uninitialized.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/uninitialized.cpp?rev=291905&r1=291904&r2=291905&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/<wbr>SemaCXX/uninitialized.cpp?rev=<wbr>291905&r1=291904&r2=291905&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/SemaCXX/<wbr>uninitialized.cpp (original)<br>
+++ cfe/trunk/test/SemaCXX/<wbr>uninitialized.cpp Fri Jan 13 09:01:06 2017<br>
@@ -1,4 +1,4 @@<br>
-// RUN: %clang_cc1 -fsyntax-only -Wall -Wuninitialized -Wno-unused-value -std=c++11 -verify %s<br>
+// RUN: %clang_cc1 -fsyntax-only -Wall -Wuninitialized -Wno-unused-value -Wno-unused-lambda-capture -std=c++11 -verify %s<br>
<br>
// definitions for std::move<br>
namespace std {<br>
<br>
Added: cfe/trunk/test/SemaCXX/warn-<wbr>unused-lambda-capture.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-unused-lambda-capture.cpp?rev=291905&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/<wbr>SemaCXX/warn-unused-lambda-<wbr>capture.cpp?rev=291905&view=<wbr>auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/SemaCXX/warn-<wbr>unused-lambda-capture.cpp (added)<br>
+++ cfe/trunk/test/SemaCXX/warn-<wbr>unused-lambda-capture.cpp Fri Jan 13 09:01:06 2017<br>
@@ -0,0 +1,110 @@<br>
+// RUN: %clang_cc1 -fsyntax-only -Wunused-lambda-capture -Wused-but-marked-unused -Wno-uninitialized -verify -std=c++14 %s<br>
+<br>
+class NonTrivialConstructor {<br>
+public:<br>
+ NonTrivialConstructor() {}<br>
+};<br>
+<br>
+class NonTrivialDestructor {<br>
+public:<br>
+ ~NonTrivialDestructor() {}<br>
+};<br>
+<br>
+class Trivial {<br>
+public:<br>
+ Trivial() = default;<br>
+ Trivial(int a) {}<br>
+};<br>
+<br>
+int side_effect() {<br>
+ return 42;<br>
+}<br>
+<br>
+void test() {<br>
+ int i = 0;<br>
+<br>
+ auto captures_nothing = [] {};<br>
+<br>
+ auto captures_nothing_by_value = [=] {};<br>
+ auto captures_nothing_by_reference = [&] {};<br>
+<br>
+ auto implicit_by_value = [=]() mutable { i++; };<br>
+ auto implicit_by_reference = [&] { i++; };<br>
+<br>
+ auto explicit_by_value_used = [i] { return i + 1; };<br>
+ auto explicit_by_value_used_void = [i] { (void)i; };<br>
+ auto explicit_by_value_unused = [i] {}; // expected-warning{{lambda capture 'i' is not used}}<br>
+ auto explicit_by_value_unused_<wbr>sizeof = [i] { return sizeof(i); }; // expected-warning{{lambda capture 'i' is not required to be captured for use in an unevaluated context}}<br>
+ auto explicit_by_value_unused_<wbr>decltype = [i] { decltype(i) j = 0; }; // expected-warning{{lambda capture 'i' is not required to be captured for use in an unevaluated context}}<br>
+<br>
+ auto explicit_by_reference_used = [&i] { i++; };<br>
+ auto explicit_by_reference_unused = [&i] {}; // expected-warning{{lambda capture 'i' is not used}}<br>
+<br>
+ auto explicit_initialized_<wbr>reference_used = [&j = i] { return j + 1; };<br>
+ auto explicit_initialized_<wbr>reference_unused = [&j = i]{}; // expected-warning{{lambda capture 'j' is not used}}<br>
+<br>
+ auto explicit_initialized_value_<wbr>used = [j = 1] { return j + 1; };<br>
+ auto explicit_initialized_value_<wbr>unused = [j = 1] {}; // expected-warning{{lambda capture 'j' is not used}}<br>
+ auto explicit_initialized_value_<wbr>non_trivial_constructor = [j = NonTrivialConstructor()]{};<br>
+ auto explicit_initialized_value_<wbr>non_trivial_destructor = [j = NonTrivialDestructor()]{};<br>
+ auto explicit_initialized_value_<wbr>trivial_init = [j = Trivial()]{}; // expected-warning{{lambda capture 'j' is not used}}<br>
+ auto explicit_initialized_value_<wbr>non_trivial_init = [j = Trivial(42)]{};<br>
+ auto explicit_initialized_value_<wbr>with_side_effect = [j = side_effect()]{};<br>
+<br>
+ auto nested = [&i] {<br>
+ auto explicit_by_value_used = [i] { return i + 1; };<br>
+ auto explicit_by_value_unused = [i] {}; // expected-warning{{lambda capture 'i' is not used}}<br>
+ };<br>
+}<br>
+<br>
+class Foo<br>
+{<br>
+ void test() {<br>
+ auto explicit_this_used = [this] { return i; };<br>
+ auto explicit_this_used_void = [this] { (void)this; };<br>
+ auto explicit_this_unused = [this] {}; // expected-warning{{lambda capture 'this' is not used}}<br>
+ }<br>
+ int i;<br>
+};<br>
+<br>
+template <typename T><br>
+void test_templated() {<br>
+ int i = 0;<br>
+<br>
+ auto captures_nothing = [] {};<br>
+<br>
+ auto captures_nothing_by_value = [=] {};<br>
+ auto captures_nothing_by_reference = [&] {};<br>
+<br>
+ auto implicit_by_value = [=]() mutable { i++; };<br>
+ auto implicit_by_reference = [&] { i++; };<br>
+<br>
+ auto explicit_by_value_used = [i] { return i + 1; };<br>
+ auto explicit_by_value_used_void = [i] { (void)i; };<br>
+ auto explicit_by_value_unused = [i] {}; // expected-warning{{lambda capture 'i' is not used}}<br>
+ auto explicit_by_value_unused_<wbr>sizeof = [i] { return sizeof(i); }; // expected-warning{{lambda capture 'i' is not required to be captured for use in an unevaluated context}}<br>
+ auto explicit_by_value_unused_<wbr>decltype = [i] { decltype(i) j = 0; }; // expected-warning{{lambda capture 'i' is not used}}<br>
+<br>
+ auto explicit_by_reference_used = [&i] { i++; };<br>
+ auto explicit_by_reference_unused = [&i] {}; // expected-warning{{lambda capture 'i' is not used}}<br>
+<br>
+ auto explicit_initialized_<wbr>reference_used = [&j = i] { return j + 1; };<br>
+ auto explicit_initialized_<wbr>reference_unused = [&j = i]{}; // expected-warning{{lambda capture 'j' is not used}}<br>
+<br>
+ auto explicit_initialized_value_<wbr>used = [j = 1] { return j + 1; };<br>
+ auto explicit_initialized_value_<wbr>unused = [j = 1] {}; // expected-warning{{lambda capture 'j' is not used}}<br>
+ auto explicit_initialized_value_<wbr>non_trivial_constructor = [j = NonTrivialConstructor()]{};<br>
+ auto explicit_initialized_value_<wbr>non_trivial_destructor = [j = NonTrivialDestructor()]{};<br>
+ auto explicit_initialized_value_<wbr>trivial_init = [j = Trivial()]{}; // expected-warning{{lambda capture 'j' is not used}}<br>
+ auto explicit_initialized_value_<wbr>non_trivial_init = [j = Trivial(42)]{};<br>
+ auto explicit_initialized_value_<wbr>with_side_effect = [j = side_effect()]{};<br>
+<br>
+ auto nested = [&i] {<br>
+ auto explicit_by_value_used = [i] { return i + 1; };<br>
+ auto explicit_by_value_unused = [i] {}; // expected-warning{{lambda capture 'i' is not used}}<br>
+ };<br>
+}<br>
+<br>
+void test_use_template() {<br>
+ test_templated<int>(); // expected-note{{in instantiation of function template specialization 'test_templated<int>' requested here}}<br>
+}<br>
<br>
<br>
______________________________<wbr>_________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div></div></div>