[clang] [webkit.UncountedLambdaCapturesChecker] Look through inline namespaces when recognizing std::ranges algorithms (PR #216229)
Fady Farag via cfe-commits
cfe-commits at lists.llvm.org
Thu Aug 13 19:07:05 PDT 2026
https://github.com/iidmsa created https://github.com/llvm/llvm-project/pull/216229
shouldTreatAllArgAsNoEscape() matches the callee's parent declarations against the literal pair std -> ranges, so the exemption for std::ranges algorithms never fires with libc++, where the path is std::__1::ranges due to the versioning inline namespace. Existing tests pass because they mock std::ranges without an inline namespace. This skips inline namespaces in the parent walk, matching actual libc++ shape.
>From 31118fcaf7a824e7f03b4c99fc72158ae9a98907 Mon Sep 17 00:00:00 2001
From: Fady Farag <com.webkit.iidmsa at gmail.com>
Date: Thu, 13 Aug 2026 21:03:30 -0500
Subject: [PATCH] [webkit.UncountedLambdaCapturesChecker] Look through inline
namespaces when recognizing std::ranges algorithms
shouldTreatAllArgAsNoEscape() matches the callee's parent declarations
against the literal pair std -> ranges, so the exemption for std::ranges
algorithms never fires with libc++, where the path is std::__1::ranges
due to the versioning inline namespace. Existing tests pass because they
mock std::ranges without an inline namespace. This skips inline
namespaces in the parent walk. Matching actual libc++ shape.
---
.../WebKit/RawPtrRefLambdaCapturesChecker.cpp | 2 +
...unted-lambda-captures-inline-namespace.cpp | 55 +++++++++++++++++++
2 files changed, 57 insertions(+)
create mode 100644 clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures-inline-namespace.cpp
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLambdaCapturesChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLambdaCapturesChecker.cpp
index 514562a5c5ce6..69c4ccb006885 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLambdaCapturesChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLambdaCapturesChecker.cpp
@@ -218,6 +218,8 @@ class RawPtrRefLambdaCapturesChecker
for (auto *Decl = FDecl->getParent(); Decl; Decl = Decl->getParent()) {
if (!isa<NamespaceDecl>(Decl) && !isa<CXXRecordDecl>(Decl))
return false;
+ if (auto *NS = dyn_cast<NamespaceDecl>(Decl); NS && NS->isInline())
+ continue;
auto Name = safeGetName(Decl);
// WTF::switchOn(T, F... f) is a variadic template function and
// couldn't be annotated with NOESCAPE. We hard code it here to
diff --git a/clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures-inline-namespace.cpp b/clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures-inline-namespace.cpp
new file mode 100644
index 0000000000000..7cc439dcdab98
--- /dev/null
+++ b/clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures-inline-namespace.cpp
@@ -0,0 +1,55 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=webkit.UncountedLambdaCapturesChecker -verify %s
+
+class RefCountable {
+public:
+ void ref() const;
+ void deref() const;
+};
+
+void someFunction(RefCountable*);
+
+namespace std {
+inline namespace __1 {
+namespace ranges {
+
+template <typename Collection, typename Predicate>
+bool any_of(Collection&& collection, Predicate&& predicate) { return true; }
+
+namespace __all_of {
+struct __fn {
+ template <typename Collection, typename Predicate>
+ constexpr bool operator()(const Collection& collection, Predicate predicate) const { return true; }
+};
+}
+inline constexpr auto all_of = __all_of::__fn {};
+
+}
+
+template <typename Callback>
+void other_function(Callback&& callback) { }
+
+}
+}
+
+struct Collection { };
+
+bool ranges_function_through_inline_namespace(RefCountable* obj, Collection& collection) {
+ return std::ranges::any_of(collection, [obj](int) {
+ someFunction(obj);
+ return true;
+ });
+}
+
+bool ranges_niebloid_through_inline_namespace(RefCountable* obj, Collection& collection) {
+ return std::ranges::all_of(collection, [obj](int) {
+ someFunction(obj);
+ return true;
+ });
+}
+
+void non_ranges_function_through_inline_namespace(RefCountable* obj) {
+ std::other_function([obj] {
+ // expected-warning at -1{{Captured variable 'obj' is a raw pointer to RefPtr-capable type 'RefCountable' [webkit.UncountedLambdaCapturesChecker]}}
+ someFunction(obj);
+ });
+}
More information about the cfe-commits
mailing list