r291905 - [Sema] Add warning for unused lambda captures
Daniel Jasper via cfe-commits
cfe-commits at lists.llvm.org
Sun Jan 15 16:08:47 PST 2017
This patch seems to break on some of our code. Reproducer:
$ cat /tmp/ctor.cc
template <typename T>
struct A {
A() {}
};
template <class T>
class B : T {
using T::T;
};
struct C {
B<A<int>> d;
C(A<int> b) : d(b) {}
};
djasper at dj:~/llvm/release$ bin/clang -cc1 -std=c++11 /tmp/ctor.cc
/tmp/ctor.cc:13:17: error: no matching constructor for initialization of
'B<A<int> >'
C(A<int> b) : d(b) {}
^ ~
/tmp/ctor.cc:7:7: note: candidate constructor (the implicit copy
constructor) not viable: no known conversion from 'A<int>' to 'const
B<A<int> >' for 1st argument
class B : T {
^
/tmp/ctor.cc:7:7: note: candidate constructor (the implicit move
constructor) not viable: no known conversion from 'A<int>' to 'B<A<int> >'
for 1st argument
class B : T {
^
/tmp/ctor.cc:7:7: note: candidate constructor (the implicit default
constructor) not viable: requires 0 arguments, but 1 was provided
1 error generated.
As far as I can tell, the copy constructor of class A does not get
forwarded with the "using T::T". I am not an expert on this parts of the
language, but this does seem like an unwanted side-effect. It builds find
with a version of Clang prior to this patch.
On Fri, Jan 13, 2017 at 4:01 PM, Malcolm Parsons via cfe-commits <
cfe-commits at lists.llvm.org> wrote:
> Author: malcolm.parsons
> Date: Fri Jan 13 09:01:06 2017
> New Revision: 291905
>
> URL: http://llvm.org/viewvc/llvm-project?rev=291905&view=rev
> Log:
> [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
>
> Added:
> cfe/trunk/test/SemaCXX/warn-unused-lambda-capture.cpp
> Modified:
> cfe/trunk/include/clang/Basic/DiagnosticGroups.td
> cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> cfe/trunk/include/clang/Sema/ScopeInfo.h
> cfe/trunk/include/clang/Sema/Sema.h
> cfe/trunk/lib/Sema/SemaExpr.cpp
> cfe/trunk/lib/Sema/SemaExprCXX.cpp
> cfe/trunk/lib/Sema/SemaLambda.cpp
> cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p12.cpp
> cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p13.cpp
> cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p16.cpp
> cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p18.cpp
> cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p19.cpp
> cfe/trunk/test/SemaCXX/uninitialized.cpp
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticGroups.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/
> clang/Basic/DiagnosticGroups.td?rev=291905&r1=291904&r2=291905&view=diff
> ============================================================
> ==================
> --- cfe/trunk/include/clang/Basic/DiagnosticGroups.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticGroups.td Fri Jan 13 09:01:06
> 2017
> @@ -480,6 +480,7 @@ def UnusedFunction : DiagGroup<"unused-f
> def UnusedMemberFunction : DiagGroup<"unused-member-function",
> [UnneededMemberFunction]>;
> def UnusedLabel : DiagGroup<"unused-label">;
> +def UnusedLambdaCapture : DiagGroup<"unused-lambda-capture">;
> def UnusedParameter : DiagGroup<"unused-parameter">;
> def UnusedResult : DiagGroup<"unused-result">;
> def PotentiallyEvaluatedExpression : DiagGroup<"potentially-
> evaluated-expression">;
> @@ -617,8 +618,9 @@ def Unused : DiagGroup<"unused",
> [UnusedArgument, UnusedFunction, UnusedLabel,
> // UnusedParameter, (matches GCC's behavior)
> // UnusedMemberFunction, (clean-up llvm before
> enabling)
> - UnusedPrivateField, UnusedLocalTypedef,
> - UnusedValue, UnusedVariable, UnusedPropertyIvar]>,
> + UnusedPrivateField, UnusedLambdaCapture,
> + UnusedLocalTypedef, UnusedValue, UnusedVariable,
> + UnusedPropertyIvar]>,
> DiagCategory<"Unused Entity Issue">;
>
> // Format settings.
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/
> DiagnosticSemaKinds.td?rev=291905&r1=291904&r2=291905&view=diff
> ============================================================
> ==================
> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Jan 13
> 09:01:06 2017
> @@ -316,6 +316,9 @@ def warn_unneeded_member_function : Warn
> InGroup<UnneededMemberFunction>, DefaultIgnore;
> def warn_unused_private_field: Warning<"private field %0 is not used">,
> InGroup<UnusedPrivateField>, DefaultIgnore;
> +def warn_unused_lambda_capture: Warning<"lambda capture %0 is not "
> + "%select{used|required to be captured for use in an unevaluated
> context}1">,
> + InGroup<UnusedLambdaCapture>, DefaultIgnore;
>
> def warn_parameter_size: Warning<
> "%0 is a large (%1 bytes) pass-by-value argument; "
>
> Modified: cfe/trunk/include/clang/Sema/ScopeInfo.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/
> clang/Sema/ScopeInfo.h?rev=291905&r1=291904&r2=291905&view=diff
> ============================================================
> ==================
> --- cfe/trunk/include/clang/Sema/ScopeInfo.h (original)
> +++ cfe/trunk/include/clang/Sema/ScopeInfo.h Fri Jan 13 09:01:06 2017
> @@ -452,6 +452,14 @@ public:
> /// non-static data member that would hold the capture.
> QualType CaptureType;
>
> + /// \brief Whether an explicit capture has been odr-used in the body
> of the
> + /// lambda.
> + bool ODRUsed;
> +
> + /// \brief Whether an explicit capture has been non-odr-used in the
> body of
> + /// the lambda.
> + bool NonODRUsed;
> +
> public:
> Capture(VarDecl *Var, bool Block, bool ByRef, bool IsNested,
> SourceLocation Loc, SourceLocation EllipsisLoc,
> @@ -460,7 +468,8 @@ public:
> InitExprAndCaptureKind(
> Cpy, !Var ? Cap_VLA : Block ? Cap_Block : ByRef ? Cap_ByRef
> :
> Cap_ByCopy),
> - Loc(Loc), EllipsisLoc(EllipsisLoc), CaptureType(CaptureType) {}
> + Loc(Loc), EllipsisLoc(EllipsisLoc), CaptureType(CaptureType),
> + ODRUsed(false), NonODRUsed(false) {}
>
> enum IsThisCapture { ThisCapture };
> Capture(IsThisCapture, bool IsNested, SourceLocation Loc,
> @@ -468,7 +477,8 @@ public:
> : VarAndNestedAndThis(
> nullptr, (IsThisCaptured | (IsNested ? IsNestedCapture :
> 0))),
> InitExprAndCaptureKind(Cpy, ByCopy ? Cap_ByCopy : Cap_ByRef),
> - Loc(Loc), EllipsisLoc(), CaptureType(CaptureType) {}
> + Loc(Loc), EllipsisLoc(), CaptureType(CaptureType),
> ODRUsed(false),
> + NonODRUsed(false) {}
>
> bool isThisCapture() const {
> return VarAndNestedAndThis.getInt() & IsThisCaptured;
> @@ -491,6 +501,9 @@ public:
> bool isNested() const {
> return VarAndNestedAndThis.getInt() & IsNestedCapture;
> }
> + bool isODRUsed() const { return ODRUsed; }
> + bool isNonODRUsed() const { return NonODRUsed; }
> + void markUsed(bool IsODRUse) { (IsODRUse ? ODRUsed : NonODRUsed) =
> true; }
>
> VarDecl *getVariable() const {
> return VarAndNestedAndThis.getPointer();
>
> Modified: cfe/trunk/include/clang/Sema/Sema.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/
> clang/Sema/Sema.h?rev=291905&r1=291904&r2=291905&view=diff
> ============================================================
> ==================
> --- cfe/trunk/include/clang/Sema/Sema.h (original)
> +++ cfe/trunk/include/clang/Sema/Sema.h Fri Jan 13 09:01:06 2017
> @@ -5323,6 +5323,9 @@ public:
> ExprResult ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
> Scope *CurScope);
>
> + /// \brief Diagnose if an explicit lambda capture is unused.
> + void DiagnoseUnusedLambdaCapture(const sema::LambdaScopeInfo::Capture
> &From);
> +
> /// \brief Complete a lambda-expression having processed and attached
> the
> /// lambda body.
> ExprResult BuildLambdaExpr(SourceLocation StartLoc, SourceLocation
> EndLoc,
>
> Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/
> SemaExpr.cpp?rev=291905&r1=291904&r2=291905&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExpr.cpp Fri Jan 13 09:01:06 2017
> @@ -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
>
> Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/
> SemaExprCXX.cpp?rev=291905&r1=291904&r2=291905&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Fri Jan 13 09:01:06 2017
> @@ -1106,6 +1106,7 @@ bool Sema::CheckCXXThisCapture(SourceLoc
> 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);
>
> Modified: cfe/trunk/lib/Sema/SemaLambda.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/
> SemaLambda.cpp?rev=291905&r1=291904&r2=291905&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Sema/SemaLambda.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaLambda.cpp Fri Jan 13 09:01:06 2017
> @@ -1384,7 +1384,7 @@ static void addBlockPointerConversion(Se
> }
>
> 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(CapturingScopeIn
> 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(SourceL
> // 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(
>
> Modified: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p12.cpp
> URL: 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
> ============================================================
> ==================
> --- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p12.cpp (original)
> +++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p12.cpp Fri Jan 13
> 09:01:06 2017
> @@ -1,4 +1,4 @@
> -// RUN: %clang_cc1 -std=c++11 %s -Wunused -verify
> +// RUN: %clang_cc1 -std=c++11 %s -Wunused -Wno-unused-lambda-capture
> -verify
>
> void odr_used() {
> int i = 17;
>
> Modified: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p13.cpp
> URL: 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
> ============================================================
> ==================
> --- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p13.cpp (original)
> +++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p13.cpp Fri Jan 13
> 09:01:06 2017
> @@ -1,4 +1,4 @@
> -// RUN: %clang_cc1 -std=c++11 %s -Wunused -verify
> +// RUN: %clang_cc1 -std=c++11 %s -Wunused -Wno-unused-lambda-capture
> -verify
>
> void f2() {
> int i = 1;
>
> Modified: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p16.cpp
> URL: 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
> ============================================================
> ==================
> --- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p16.cpp (original)
> +++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p16.cpp Fri Jan 13
> 09:01:06 2017
> @@ -1,4 +1,4 @@
> -// RUN: %clang_cc1 -std=c++11 %s -Wunused -verify
> +// RUN: %clang_cc1 -std=c++11 %s -Wunused -Wno-unused-lambda-capture
> -verify
>
>
> struct X {
>
> Modified: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p18.cpp
> URL: 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
> ============================================================
> ==================
> --- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p18.cpp (original)
> +++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p18.cpp Fri Jan 13
> 09:01:06 2017
> @@ -1,4 +1,4 @@
> -// RUN: %clang_cc1 -std=c++11 %s -Wunused -verify
> +// RUN: %clang_cc1 -std=c++11 %s -Wunused -Wno-unused-lambda-capture
> -verify
> // expected-no-diagnostics
>
> template<typename T, typename U>
>
> Modified: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p19.cpp
> URL: 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
> ============================================================
> ==================
> --- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p19.cpp (original)
> +++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p19.cpp Fri Jan 13
> 09:01:06 2017
> @@ -1,4 +1,4 @@
> -// RUN: %clang_cc1 -std=c++11 %s -Wunused -verify
> +// RUN: %clang_cc1 -std=c++11 %s -Wunused -Wno-unused-lambda-capture
> -verify
>
> struct MoveOnly {
> MoveOnly(MoveOnly&&);
>
> Modified: cfe/trunk/test/SemaCXX/uninitialized.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/
> SemaCXX/uninitialized.cpp?rev=291905&r1=291904&r2=291905&view=diff
> ============================================================
> ==================
> --- cfe/trunk/test/SemaCXX/uninitialized.cpp (original)
> +++ cfe/trunk/test/SemaCXX/uninitialized.cpp Fri Jan 13 09:01:06 2017
> @@ -1,4 +1,4 @@
> -// RUN: %clang_cc1 -fsyntax-only -Wall -Wuninitialized -Wno-unused-value
> -std=c++11 -verify %s
> +// RUN: %clang_cc1 -fsyntax-only -Wall -Wuninitialized -Wno-unused-value
> -Wno-unused-lambda-capture -std=c++11 -verify %s
>
> // definitions for std::move
> namespace std {
>
> Added: cfe/trunk/test/SemaCXX/warn-unused-lambda-capture.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/
> SemaCXX/warn-unused-lambda-capture.cpp?rev=291905&view=auto
> ============================================================
> ==================
> --- cfe/trunk/test/SemaCXX/warn-unused-lambda-capture.cpp (added)
> +++ cfe/trunk/test/SemaCXX/warn-unused-lambda-capture.cpp Fri Jan 13
> 09:01:06 2017
> @@ -0,0 +1,110 @@
> +// RUN: %clang_cc1 -fsyntax-only -Wunused-lambda-capture
> -Wused-but-marked-unused -Wno-uninitialized -verify -std=c++14 %s
> +
> +class NonTrivialConstructor {
> +public:
> + NonTrivialConstructor() {}
> +};
> +
> +class NonTrivialDestructor {
> +public:
> + ~NonTrivialDestructor() {}
> +};
> +
> +class Trivial {
> +public:
> + Trivial() = default;
> + Trivial(int a) {}
> +};
> +
> +int side_effect() {
> + return 42;
> +}
> +
> +void test() {
> + int i = 0;
> +
> + auto captures_nothing = [] {};
> +
> + auto captures_nothing_by_value = [=] {};
> + auto captures_nothing_by_reference = [&] {};
> +
> + auto implicit_by_value = [=]() mutable { i++; };
> + auto implicit_by_reference = [&] { i++; };
> +
> + auto explicit_by_value_used = [i] { return i + 1; };
> + auto explicit_by_value_used_void = [i] { (void)i; };
> + auto explicit_by_value_unused = [i] {}; // expected-warning{{lambda
> capture 'i' is not used}}
> + auto explicit_by_value_unused_sizeof = [i] { return sizeof(i); }; //
> expected-warning{{lambda capture 'i' is not required to be captured for use
> in an unevaluated context}}
> + auto explicit_by_value_unused_decltype = [i] { decltype(i) j = 0; };
> // expected-warning{{lambda capture 'i' is not required to be captured for
> use in an unevaluated context}}
> +
> + auto explicit_by_reference_used = [&i] { i++; };
> + auto explicit_by_reference_unused = [&i] {}; //
> expected-warning{{lambda capture 'i' is not used}}
> +
> + auto explicit_initialized_reference_used = [&j = i] { return j + 1; };
> + auto explicit_initialized_reference_unused = [&j = i]{}; //
> expected-warning{{lambda capture 'j' is not used}}
> +
> + auto explicit_initialized_value_used = [j = 1] { return j + 1; };
> + auto explicit_initialized_value_unused = [j = 1] {}; //
> expected-warning{{lambda capture 'j' is not used}}
> + auto explicit_initialized_value_non_trivial_constructor = [j =
> NonTrivialConstructor()]{};
> + auto explicit_initialized_value_non_trivial_destructor = [j =
> NonTrivialDestructor()]{};
> + auto explicit_initialized_value_trivial_init = [j = Trivial()]{}; //
> expected-warning{{lambda capture 'j' is not used}}
> + auto explicit_initialized_value_non_trivial_init = [j = Trivial(42)]{};
> + auto explicit_initialized_value_with_side_effect = [j =
> side_effect()]{};
> +
> + auto nested = [&i] {
> + auto explicit_by_value_used = [i] { return i + 1; };
> + auto explicit_by_value_unused = [i] {}; // expected-warning{{lambda
> capture 'i' is not used}}
> + };
> +}
> +
> +class Foo
> +{
> + void test() {
> + auto explicit_this_used = [this] { return i; };
> + auto explicit_this_used_void = [this] { (void)this; };
> + auto explicit_this_unused = [this] {}; // expected-warning{{lambda
> capture 'this' is not used}}
> + }
> + int i;
> +};
> +
> +template <typename T>
> +void test_templated() {
> + int i = 0;
> +
> + auto captures_nothing = [] {};
> +
> + auto captures_nothing_by_value = [=] {};
> + auto captures_nothing_by_reference = [&] {};
> +
> + auto implicit_by_value = [=]() mutable { i++; };
> + auto implicit_by_reference = [&] { i++; };
> +
> + auto explicit_by_value_used = [i] { return i + 1; };
> + auto explicit_by_value_used_void = [i] { (void)i; };
> + auto explicit_by_value_unused = [i] {}; // expected-warning{{lambda
> capture 'i' is not used}}
> + auto explicit_by_value_unused_sizeof = [i] { return sizeof(i); }; //
> expected-warning{{lambda capture 'i' is not required to be captured for use
> in an unevaluated context}}
> + auto explicit_by_value_unused_decltype = [i] { decltype(i) j = 0; };
> // expected-warning{{lambda capture 'i' is not used}}
> +
> + auto explicit_by_reference_used = [&i] { i++; };
> + auto explicit_by_reference_unused = [&i] {}; //
> expected-warning{{lambda capture 'i' is not used}}
> +
> + auto explicit_initialized_reference_used = [&j = i] { return j + 1; };
> + auto explicit_initialized_reference_unused = [&j = i]{}; //
> expected-warning{{lambda capture 'j' is not used}}
> +
> + auto explicit_initialized_value_used = [j = 1] { return j + 1; };
> + auto explicit_initialized_value_unused = [j = 1] {}; //
> expected-warning{{lambda capture 'j' is not used}}
> + auto explicit_initialized_value_non_trivial_constructor = [j =
> NonTrivialConstructor()]{};
> + auto explicit_initialized_value_non_trivial_destructor = [j =
> NonTrivialDestructor()]{};
> + auto explicit_initialized_value_trivial_init = [j = Trivial()]{}; //
> expected-warning{{lambda capture 'j' is not used}}
> + auto explicit_initialized_value_non_trivial_init = [j = Trivial(42)]{};
> + auto explicit_initialized_value_with_side_effect = [j =
> side_effect()]{};
> +
> + auto nested = [&i] {
> + auto explicit_by_value_used = [i] { return i + 1; };
> + auto explicit_by_value_unused = [i] {}; // expected-warning{{lambda
> capture 'i' is not used}}
> + };
> +}
> +
> +void test_use_template() {
> + test_templated<int>(); // expected-note{{in instantiation of function
> template specialization 'test_templated<int>' requested here}}
> +}
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20170116/debc200f/attachment-0001.html>
More information about the cfe-commits
mailing list