From e526eb02550c02dcce8de3239829cc26b764fd8d Mon Sep 17 00:00:00 2001 From: Ryosuke Niwa Date: Fri, 22 Aug 2025 13:06:08 -0700 Subject: [PATCH 1/3] [webkit.UncountedLambdaCapturesChecker] Ignore DeclRefExpr to a lambda in an no-escape argument Fix a bug that webkit.UncountedLambdaCapturesChecker was erroneously emitting a warning for a DeclRefExpr which is passed in as an argument to a no-escape function argument. The bug was caused by findLambdaInArg not adding DeclRefExpr to the ignored set even when a lambda was identified as an argument. --- .../WebKit/RawPtrRefLambdaCapturesChecker.cpp | 7 +++++- .../WebKit/uncounted-lambda-captures.cpp | 23 +++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLambdaCapturesChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLambdaCapturesChecker.cpp index 27a91132fa9be..81b08dd0831da 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLambdaCapturesChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLambdaCapturesChecker.cpp @@ -232,14 +232,19 @@ class RawPtrRefLambdaCapturesChecker if (!Init) return nullptr; if (auto *Lambda = dyn_cast(Init)) { + DeclRefExprsToIgnore.insert(DRE); updateIgnoreList(); return Lambda; } TempExpr = dyn_cast(Init->IgnoreParenCasts()); if (!TempExpr) return nullptr; + auto *Lambda = dyn_cast_or_null(TempExpr->getSubExpr()); + if (!Lambda) + return nullptr; + DeclRefExprsToIgnore.insert(DRE); updateIgnoreList(); - return dyn_cast_or_null(TempExpr->getSubExpr()); + return Lambda; } void checkCalleeLambda(CallExpr *CE) { diff --git a/clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures.cpp b/clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures.cpp index 3079f8e833fcd..1dfab439c58dd 100644 --- a/clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures.cpp +++ b/clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures.cpp @@ -448,4 +448,27 @@ void ranges_for_each(RefCountable* obj) { obj->method(); ++(*static_cast(item)); }); +} + +class RefCountedObj { +public: + void ref(); + void deref(); + + void call() const; + void callLambda([[clang::noescape]] const WTF::Function& callback) const; + void doSomeWork() const; +}; + +void RefCountedObj::callLambda([[clang::noescape]] const WTF::Function& callback) const +{ + callback(); +} + +void RefCountedObj::call() const +{ + auto lambda = [&] { + doSomeWork(); + }; + callLambda(lambda); } \ No newline at end of file From 0b90a8b71898f1936d16aed6293f42cc8207366c Mon Sep 17 00:00:00 2001 From: Ryosuke Niwa Date: Fri, 22 Aug 2025 13:11:02 -0700 Subject: [PATCH 2/3] Add a missing new line at the end of the test --- .../test/Analysis/Checkers/WebKit/uncounted-lambda-captures.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures.cpp b/clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures.cpp index 1dfab439c58dd..0b8af0d1e8dc1 100644 --- a/clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures.cpp +++ b/clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures.cpp @@ -471,4 +471,4 @@ void RefCountedObj::call() const doSomeWork(); }; callLambda(lambda); -} \ No newline at end of file +} From 7869ff9a5ff92a2953f42c376cdc2022b7fcb7c0 Mon Sep 17 00:00:00 2001 From: Ryosuke Niwa Date: Tue, 9 Sep 2025 01:16:06 -0700 Subject: [PATCH 3/3] Remove the dead code --- .../Checkers/WebKit/RawPtrRefLambdaCapturesChecker.cpp | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLambdaCapturesChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLambdaCapturesChecker.cpp index 81b08dd0831da..03eeb9999c4dd 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLambdaCapturesChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLambdaCapturesChecker.cpp @@ -236,15 +236,7 @@ class RawPtrRefLambdaCapturesChecker updateIgnoreList(); return Lambda; } - TempExpr = dyn_cast(Init->IgnoreParenCasts()); - if (!TempExpr) - return nullptr; - auto *Lambda = dyn_cast_or_null(TempExpr->getSubExpr()); - if (!Lambda) - return nullptr; - DeclRefExprsToIgnore.insert(DRE); - updateIgnoreList(); - return Lambda; + return nullptr; } void checkCalleeLambda(CallExpr *CE) {