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(); }); }); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits