Skip to content

Commit 8b093e5

Browse files
authored
[webkit.UncountedLambdaCapturesChecker] Recognize std::move(protectedThis) (#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 184f944 commit 8b093e5

File tree

2 files changed

+31
-6
lines changed

2 files changed

+31
-6
lines changed

clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLambdaCapturesChecker.cpp

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -282,15 +282,31 @@ class RawPtrRefLambdaCapturesChecker
282282
do {
283283
if (auto *BTE = dyn_cast<CXXBindTemporaryExpr>(Arg))
284284
Arg = BTE->getSubExpr()->IgnoreParenCasts();
285-
if (auto *CE = dyn_cast_or_null<CXXConstructExpr>(Arg)) {
285+
if (auto *CE = dyn_cast<CXXConstructExpr>(Arg)) {
286286
auto *Ctor = CE->getConstructor();
287287
if (!Ctor)
288288
return false;
289289
auto clsName = safeGetName(Ctor->getParent());
290-
if (!isRefType(clsName) || !CE->getNumArgs())
291-
return false;
292-
Arg = CE->getArg(0)->IgnoreParenCasts();
293-
continue;
290+
if (isRefType(clsName) && CE->getNumArgs()) {
291+
Arg = CE->getArg(0)->IgnoreParenCasts();
292+
continue;
293+
}
294+
if (auto *Type = ClsType.getTypePtrOrNull()) {
295+
if (auto *CXXR = Type->getPointeeCXXRecordDecl()) {
296+
if (CXXR == Ctor->getParent() && Ctor->isMoveConstructor() &&
297+
CE->getNumArgs() == 1) {
298+
Arg = CE->getArg(0)->IgnoreParenCasts();
299+
continue;
300+
}
301+
}
302+
}
303+
return false;
304+
}
305+
if (auto *CE = dyn_cast<CallExpr>(Arg)) {
306+
if (CE->isCallToStdMove() && CE->getNumArgs() == 1) {
307+
Arg = CE->getArg(0)->IgnoreParenCasts();
308+
continue;
309+
}
294310
}
295311
if (auto *OpCE = dyn_cast<CXXOperatorCallExpr>(Arg)) {
296312
auto OpCode = OpCE->getOperator();

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

Lines changed: 10 additions & 1 deletion
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)