[clang] 8b093e5 - [webkit.UncountedLambdaCapturesChecker] Recognize std::move(protectedThis) (#130925)

via cfe-commits cfe-commits at lists.llvm.org
Wed Mar 12 10:23:50 PDT 2025


Author: Ryosuke Niwa
Date: 2025-03-12T10:23:46-07:00
New Revision: 8b093e5e1752b3899b4c66f084c33ad1a3d0e8d6

URL: https://github.com/llvm/llvm-project/commit/8b093e5e1752b3899b4c66f084c33ad1a3d0e8d6
DIFF: https://github.com/llvm/llvm-project/commit/8b093e5e1752b3899b4c66f084c33ad1a3d0e8d6.diff

LOG: [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.

Added: 
    

Modified: 
    clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLambdaCapturesChecker.cpp
    clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures.cpp

Removed: 
    


################################################################################
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();
       });
     });


        


More information about the cfe-commits mailing list