-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[webkit.UncountedLambdaCapturesChecker] Recognize std::move(protectedThis) #130925
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…This) In WebKit, it's a common pattern for a lambda to capture "this" along with "protectedThis" of Ref/RefPtr type, and re-capture "this" and "std::move(protectedThis)" for a nested inner lambda. Recognize this pattern and treat it as safe.
@llvm/pr-subscribers-clang-static-analyzer-1 @llvm/pr-subscribers-clang Author: Ryosuke Niwa (rniwa) ChangesIn WebKit, it's a common pattern for a lambda to capture "this" along with "protectedThis" of Ref/RefPtr type, and re-capture "this" and "std::move(protectedThis)" for a nested inner lambda. Recognize this pattern and treat it as safe. Full diff: https://github.com/llvm/llvm-project/pull/130925.diff 2 Files Affected:
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLambdaCapturesChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLambdaCapturesChecker.cpp
index 4a297a6c0ab91..8496a75c1b84f 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLambdaCapturesChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLambdaCapturesChecker.cpp
@@ -282,15 +282,31 @@ class RawPtrRefLambdaCapturesChecker
do {
if (auto *BTE = dyn_cast<CXXBindTemporaryExpr>(Arg))
Arg = BTE->getSubExpr()->IgnoreParenCasts();
- if (auto *CE = dyn_cast_or_null<CXXConstructExpr>(Arg)) {
+ if (auto *CE = dyn_cast<CXXConstructExpr>(Arg)) {
auto *Ctor = CE->getConstructor();
if (!Ctor)
return false;
auto clsName = safeGetName(Ctor->getParent());
- if (!isRefType(clsName) || !CE->getNumArgs())
- return false;
- Arg = CE->getArg(0)->IgnoreParenCasts();
- continue;
+ if (isRefType(clsName) && CE->getNumArgs()) {
+ Arg = CE->getArg(0)->IgnoreParenCasts();
+ continue;
+ }
+ if (auto *Type = ClsType.getTypePtrOrNull()) {
+ if (auto *CXXR = Type->getPointeeCXXRecordDecl()) {
+ if (CXXR == Ctor->getParent() && Ctor->isMoveConstructor() &&
+ CE->getNumArgs() == 1) {
+ Arg = CE->getArg(0)->IgnoreParenCasts();
+ continue;
+ }
+ }
+ }
+ return false;
+ }
+ if (auto *CE = dyn_cast<CallExpr>(Arg)) {
+ if (CE->isCallToStdMove() && CE->getNumArgs() == 1) {
+ Arg = CE->getArg(0)->IgnoreParenCasts();
+ continue;
+ }
}
if (auto *OpCE = dyn_cast<CXXOperatorCallExpr>(Arg)) {
auto OpCode = OpCE->getOperator();
diff --git a/clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures.cpp b/clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures.cpp
index 1746d2b93d469..36135973e78c0 100644
--- a/clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures.cpp
+++ b/clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures.cpp
@@ -2,6 +2,15 @@
#include "mock-types.h"
+namespace std {
+
+template <typename T>
+T&& move(T& t) {
+ return static_cast<T&&>(t);
+}
+
+}
+
namespace WTF {
namespace Detail {
@@ -321,7 +330,7 @@ struct RefCountableWithLambdaCapturingThis {
void method_nested_lambda2() {
callAsync([this, protectedThis = RefPtr { this }] {
- callAsync([this, protectedThis = static_cast<const Ref<RefCountableWithLambdaCapturingThis>&&>(*protectedThis)] {
+ callAsync([this, protectedThis = std::move(*protectedThis)] {
nonTrivial();
});
});
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
Thanks for the review! |
…This) (llvm#130925) In WebKit, it's a common pattern for a lambda to capture "this" along with "protectedThis" of Ref/RefPtr type, and re-capture "this" and "std::move(protectedThis)" for a nested inner lambda. Recognize this pattern and treat it as safe.
…This) (llvm#130925) In WebKit, it's a common pattern for a lambda to capture "this" along with "protectedThis" of Ref/RefPtr type, and re-capture "this" and "std::move(protectedThis)" for a nested inner lambda. Recognize this pattern and treat it as safe.
…This) (llvm#130925) In WebKit, it's a common pattern for a lambda to capture "this" along with "protectedThis" of Ref/RefPtr type, and re-capture "this" and "std::move(protectedThis)" for a nested inner lambda. Recognize this pattern and treat it as safe.
In WebKit, it's a common pattern for a lambda to capture "this" along with "protectedThis" of Ref/RefPtr type, and re-capture "this" and "std::move(protectedThis)" for a nested inner lambda. Recognize this pattern and treat it as safe.