https://github.com/rniwa created https://github.com/llvm/llvm-project/pull/224492
call_once does not store the lambda in heap so consider all its arguments as noescape. >From d70130838b6c6f6c222abfefc55ac401ce8adf97 Mon Sep 17 00:00:00 2001 From: Ryosuke Niwa <[email protected]> Date: Thu, 17 Sep 2026 18:50:59 -0700 Subject: [PATCH] [webkit.UncountedLambdaCapturesChecker] Treat call_once arguments as noescape call_once does not store the lambda in heap so consider all its arguments as noescape. --- .../WebKit/RawPtrRefLambdaCapturesChecker.cpp | 13 ++++++++++--- clang/test/Analysis/Checkers/WebKit/mock-types.h | 13 +++++++++++++ .../Checkers/WebKit/uncounted-lambda-captures.cpp | 9 +++++++++ 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLambdaCapturesChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLambdaCapturesChecker.cpp index 43db3065dd068..a07812d3a48d5 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLambdaCapturesChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLambdaCapturesChecker.cpp @@ -244,9 +244,16 @@ class RawPtrRefLambdaCapturesChecker // workaround that. if (Name == "WTF" && PreviousName == "switchOn") return true; - // Treat every argument of functions in std::ranges as noescape. - if (Name == "std" && PreviousName == "ranges") - return true; + if (Name == "std") { + // Treat every argument of functions in std::ranges as noescape. + if (PreviousName == "ranges") + return true; + // Treat every argument of call_once as noescape even though only + // the second argument is lambda since we can't add annotation to + // a std function. + if (PreviousName == "call_once") + return true; + } PreviousName = Name; } return false; diff --git a/clang/test/Analysis/Checkers/WebKit/mock-types.h b/clang/test/Analysis/Checkers/WebKit/mock-types.h index 9ed5ecab88c6e..46818a9642ee3 100644 --- a/clang/test/Analysis/Checkers/WebKit/mock-types.h +++ b/clang/test/Analysis/Checkers/WebKit/mock-types.h @@ -63,6 +63,19 @@ class unique_ptr { explicit operator bool() const { return !!t; } }; +struct once_flag { + bool did { false }; +}; + +template<typename CallbackType, typename... Args> +void call_once(once_flag& flag, CallbackType callback, Args&&... args) +{ + if (flag.did) + return; + flag.did = true; + callback(args...); +} + namespace ranges { template<typename IteratorType, typename CallbackType> diff --git a/clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures.cpp b/clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures.cpp index d1cc7588ed8d6..27c44af36c2d3 100644 --- a/clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures.cpp +++ b/clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures.cpp @@ -386,6 +386,7 @@ class RefCountedObj { bool isMatch(int); void call() const; + void callOnce() const; void callLambda([[clang::noescape]] const WTF::Function<void ()>& callback) const; void doSomeWork() const; }; @@ -409,6 +410,14 @@ void RefCountedObj::call() const callLambda(lambda); } +void RefCountedObj::callOnce() const +{ + static std::once_flag flag; + std::call_once(flag, [&]() { + call(); + }); +} + void scope_exit(RefCountable* obj) { auto scope = WTF::makeScopeExit([&] { obj->method(); _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
