Skip to content

Commit 42b9e5c

Browse files
committed
[webkit.UncountedLambdaCapturesChecker] Recognize std::move(protectedThis) (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.
1 parent 0f09e54 commit 42b9e5c

File tree

2 files changed

+31
-6
lines changed

2 files changed

+31
-6
lines changed

Diff for: clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLambdaCapturesChecker.cpp

+21-5
Original file line numberDiff line numberDiff line change
@@ -285,15 +285,31 @@ class RawPtrRefLambdaCapturesChecker
285285
do {
286286
if (auto *BTE = dyn_cast<CXXBindTemporaryExpr>(Arg))
287287
Arg = BTE->getSubExpr()->IgnoreParenCasts();
288-
if (auto *CE = dyn_cast_or_null<CXXConstructExpr>(Arg)) {
288+
if (auto *CE = dyn_cast<CXXConstructExpr>(Arg)) {
289289
auto *Ctor = CE->getConstructor();
290290
if (!Ctor)
291291
return false;
292292
auto clsName = safeGetName(Ctor->getParent());
293-
if (!isRefType(clsName) || !CE->getNumArgs())
294-
return false;
295-
Arg = CE->getArg(0)->IgnoreParenCasts();
296-
continue;
293+
if (isRefType(clsName) && CE->getNumArgs()) {
294+
Arg = CE->getArg(0)->IgnoreParenCasts();
295+
continue;
296+
}
297+
if (auto *Type = ClsType.getTypePtrOrNull()) {
298+
if (auto *CXXR = Type->getPointeeCXXRecordDecl()) {
299+
if (CXXR == Ctor->getParent() && Ctor->isMoveConstructor() &&
300+
CE->getNumArgs() == 1) {
301+
Arg = CE->getArg(0)->IgnoreParenCasts();
302+
continue;
303+
}
304+
}
305+
}
306+
return false;
307+
}
308+
if (auto *CE = dyn_cast<CallExpr>(Arg)) {
309+
if (CE->isCallToStdMove() && CE->getNumArgs() == 1) {
310+
Arg = CE->getArg(0)->IgnoreParenCasts();
311+
continue;
312+
}
297313
}
298314
if (auto *OpCE = dyn_cast<CXXOperatorCallExpr>(Arg)) {
299315
auto OpCode = OpCE->getOperator();

Diff for: clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures.cpp

+10-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,15 @@
22

33
#include "mock-types.h"
44

5+
namespace std {
6+
7+
template <typename T>
8+
T&& move(T& t) {
9+
return static_cast<T&&>(t);
10+
}
11+
12+
}
13+
514
namespace WTF {
615

716
namespace Detail {
@@ -321,7 +330,7 @@ struct RefCountableWithLambdaCapturingThis {
321330

322331
void method_nested_lambda2() {
323332
callAsync([this, protectedThis = RefPtr { this }] {
324-
callAsync([this, protectedThis = static_cast<const Ref<RefCountableWithLambdaCapturingThis>&&>(*protectedThis)] {
333+
callAsync([this, protectedThis = std::move(*protectedThis)] {
325334
nonTrivial();
326335
});
327336
});

0 commit comments

Comments
 (0)