r296602 - [Sema] Improve side effect checking for unused-lambda-capture warning
Malcolm Parsons via cfe-commits
cfe-commits at lists.llvm.org
Wed Mar 1 02:23:39 PST 2017
Author: malcolm.parsons
Date: Wed Mar 1 04:23:38 2017
New Revision: 296602
URL: http://llvm.org/viewvc/llvm-project?rev=296602&view=rev
Log:
[Sema] Improve side effect checking for unused-lambda-capture warning
Summary:
Don't warn about unused lambda captures that involve copying a
value of a type that cannot be trivially copied and destroyed.
Fixes PR31977
Reviewers: rsmith, aaron.ballman
Subscribers: cfe-commits
Differential Revision: https://reviews.llvm.org/D30327
Modified:
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Sema/SemaLambda.cpp
cfe/trunk/test/SemaCXX/warn-unused-lambda-capture.cpp
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=296602&r1=296601&r2=296602&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Wed Mar 1 04:23:38 2017
@@ -5340,6 +5340,9 @@ public:
ExprResult ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
Scope *CurScope);
+ /// \brief Does copying/destroying the captured variable have side effects?
+ bool CaptureHasSideEffects(const sema::LambdaScopeInfo::Capture &From);
+
/// \brief Diagnose if an explicit lambda capture is unused.
void DiagnoseUnusedLambdaCapture(const sema::LambdaScopeInfo::Capture &From);
Modified: cfe/trunk/lib/Sema/SemaLambda.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLambda.cpp?rev=296602&r1=296601&r2=296602&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLambda.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLambda.cpp Wed Mar 1 04:23:38 2017
@@ -1438,13 +1438,35 @@ mapImplicitCaptureStyle(CapturingScopeIn
llvm_unreachable("Unknown implicit capture style");
}
-void Sema::DiagnoseUnusedLambdaCapture(const LambdaScopeInfo::Capture &From) {
+bool Sema::CaptureHasSideEffects(const LambdaScopeInfo::Capture &From) {
if (!From.isVLATypeCapture()) {
Expr *Init = From.getInitExpr();
if (Init && Init->HasSideEffects(Context))
- return;
+ return true;
}
+ if (!From.isCopyCapture())
+ return false;
+
+ const QualType T = From.isThisCapture()
+ ? getCurrentThisType()->getPointeeType()
+ : From.getCaptureType();
+
+ if (T.isVolatileQualified())
+ return true;
+
+ const Type *BaseT = T->getBaseElementTypeUnsafe();
+ if (const CXXRecordDecl *RD = BaseT->getAsCXXRecordDecl())
+ return !RD->isCompleteDefinition() || !RD->hasTrivialCopyConstructor() ||
+ !RD->hasTrivialDestructor();
+
+ return false;
+}
+
+void Sema::DiagnoseUnusedLambdaCapture(const LambdaScopeInfo::Capture &From) {
+ if (CaptureHasSideEffects(From))
+ return;
+
auto diag = Diag(From.getLocation(), diag::warn_unused_lambda_capture);
if (From.isThisCapture())
diag << "'this'";
Modified: 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=296602&r1=296601&r2=296602&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/warn-unused-lambda-capture.cpp (original)
+++ cfe/trunk/test/SemaCXX/warn-unused-lambda-capture.cpp Wed Mar 1 04:23:38 2017
@@ -1,10 +1,16 @@
-// RUN: %clang_cc1 -fsyntax-only -Wunused-lambda-capture -Wused-but-marked-unused -Wno-uninitialized -verify -std=c++14 %s
+// RUN: %clang_cc1 -fsyntax-only -Wunused-lambda-capture -Wused-but-marked-unused -Wno-uninitialized -verify -std=c++1z %s
class NonTrivialConstructor {
public:
NonTrivialConstructor() {}
};
+class NonTrivialCopyConstructor {
+public:
+ NonTrivialCopyConstructor() = default;
+ NonTrivialCopyConstructor(const NonTrivialCopyConstructor &) {}
+};
+
class NonTrivialDestructor {
public:
~NonTrivialDestructor() {}
@@ -57,14 +63,67 @@ void test() {
auto explicit_by_value_used = [i] { return i + 1; };
auto explicit_by_value_unused = [i] {}; // expected-warning{{lambda capture 'i' is not used}}
};
+
+ Trivial trivial;
+ auto explicit_by_value_trivial = [trivial] {}; // expected-warning{{lambda capture 'trivial' is not used}}
+
+ NonTrivialConstructor cons;
+ auto explicit_by_value_non_trivial_constructor = [cons] {}; // expected-warning{{lambda capture 'cons' is not used}}
+
+ NonTrivialCopyConstructor copy_cons;
+ auto explicit_by_value_non_trivial_copy_constructor = [copy_cons] {};
+
+ NonTrivialDestructor dest;
+ auto explicit_by_value_non_trivial_destructor = [dest] {};
+
+ volatile int v;
+ auto explicit_by_value_volatile = [v] {};
}
-class Foo
-{
+class TrivialThis : Trivial {
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}}
+ auto explicit_star_this_used = [*this] { return i; };
+ auto explicit_star_this_used_void = [*this] { (void)this; };
+ auto explicit_star_this_unused = [*this] {}; // expected-warning{{lambda capture 'this' is not used}}
+ }
+ int i;
+};
+
+class NonTrivialConstructorThis : NonTrivialConstructor {
+ 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}}
+ auto explicit_star_this_used = [*this] { return i; };
+ auto explicit_star_this_used_void = [*this] { (void)this; };
+ auto explicit_star_this_unused = [*this] {}; // expected-warning{{lambda capture 'this' is not used}}
+ }
+ int i;
+};
+
+class NonTrivialCopyConstructorThis : NonTrivialCopyConstructor {
+ 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}}
+ auto explicit_star_this_used = [*this] { return i; };
+ auto explicit_star_this_used_void = [*this] { (void)this; };
+ auto explicit_star_this_unused = [*this] {};
+ }
+ int i;
+};
+
+class NonTrivialDestructorThis : NonTrivialDestructor {
+ 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}}
+ auto explicit_star_this_used = [*this] { return i; };
+ auto explicit_star_this_used_void = [*this] { (void)this; };
+ auto explicit_star_this_unused = [*this] {};
}
int i;
};
@@ -107,6 +166,21 @@ void test_templated() {
auto explicit_by_value_used = [i] { return i + 1; };
auto explicit_by_value_unused = [i] {}; // expected-warning{{lambda capture 'i' is not used}}
};
+
+ Trivial trivial;
+ auto explicit_by_value_trivial = [trivial] {}; // expected-warning{{lambda capture 'trivial' is not used}}
+
+ NonTrivialConstructor cons;
+ auto explicit_by_value_non_trivial_constructor = [cons] {}; // expected-warning{{lambda capture 'cons' is not used}}
+
+ NonTrivialCopyConstructor copy_cons;
+ auto explicit_by_value_non_trivial_copy_constructor = [copy_cons] {};
+
+ NonTrivialDestructor dest;
+ auto explicit_by_value_non_trivial_destructor = [dest] {};
+
+ volatile int v;
+ auto explicit_by_value_volatile = [v] {};
}
void test_use_template() {
More information about the cfe-commits
mailing list