-
Notifications
You must be signed in to change notification settings - Fork 13.4k
[webkit.UncountedLambdaCapturesChecker] Treat every argument of std::ranges functions as noescape. #138995
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[webkit.UncountedLambdaCapturesChecker] Treat every argument of std::ranges functions as noescape. #138995
Conversation
…ranges functions as noescape. Functions in std::ranges namespace does not store the lambada passed-in as an arugment in heap so treat such an argument as if it has [[noescape]] in the WebKit lambda capture checker so that we don't emit warnings for capturing raw pointers or references to smart-pointer capable objects.
@llvm/pr-subscribers-clang-static-analyzer-1 @llvm/pr-subscribers-clang Author: Ryosuke Niwa (rniwa) ChangesFunctions in std::ranges namespace does not store the lambada passed-in as an arugment in heap so treat such an argument as if it has [[noescape]] in the WebKit lambda capture checker so that we don't emit warnings for capturing raw pointers or references to smart-pointer capable objects. Full diff: https://github.com/llvm/llvm-project/pull/138995.diff 2 Files Affected:
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLambdaCapturesChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLambdaCapturesChecker.cpp
index 01faa9217982d..d3b8d8b6995bf 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLambdaCapturesChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLambdaCapturesChecker.cpp
@@ -127,13 +127,21 @@ class RawPtrRefLambdaCapturesChecker
return true;
}
- // WTF::switchOn(T, F... f) is a variadic template function and couldn't
- // be annotated with NOESCAPE. We hard code it here to workaround that.
bool shouldTreatAllArgAsNoEscape(FunctionDecl *Decl) {
auto *NsDecl = Decl->getParent();
if (!NsDecl || !isa<NamespaceDecl>(NsDecl))
return false;
- return safeGetName(NsDecl) == "WTF" && safeGetName(Decl) == "switchOn";
+ // WTF::switchOn(T, F... f) is a variadic template function and couldn't
+ // be annotated with NOESCAPE. We hard code it here to workaround that.
+ if (safeGetName(NsDecl) == "WTF" && safeGetName(Decl) == "switchOn")
+ return true;
+ // Treat every argument of functions in std::ranges as noescape.
+ if (safeGetName(NsDecl) == "ranges") {
+ if (auto *OuterDecl = NsDecl->getParent(); OuterDecl &&
+ isa<NamespaceDecl>(OuterDecl) && safeGetName(OuterDecl) == "std")
+ return true;
+ }
+ return false;
}
bool VisitCXXConstructExpr(CXXConstructExpr *CE) override {
diff --git a/clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures.cpp b/clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures.cpp
index 6b7593a821c64..3079f8e833fcd 100644
--- a/clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures.cpp
+++ b/clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures.cpp
@@ -9,6 +9,16 @@ T&& move(T& t) {
return static_cast<T&&>(t);
}
+namespace ranges {
+
+template<typename IteratorType, typename CallbackType>
+void for_each(IteratorType first, IteratorType last, CallbackType callback) {
+ for (auto it = first; !(it == last); ++it)
+ callback(*it);
+}
+
+}
+
}
namespace WTF {
@@ -416,3 +426,26 @@ void capture_copy_in_lambda(CheckedObj& checked) {
ptr->method();
});
}
+
+class Iterator {
+public:
+ Iterator(void* array, unsigned long sizeOfElement, unsigned int index);
+ Iterator(const Iterator&);
+ Iterator& operator=(const Iterator&);
+ bool operator==(const Iterator&);
+
+ Iterator& operator++();
+ void* operator*();
+
+private:
+ void* current { nullptr };
+ unsigned long sizeOfElement { 0 };
+};
+
+void ranges_for_each(RefCountable* obj) {
+ int array[] = { 1, 2, 3, 4, 5 };
+ std::ranges::for_each(Iterator(array, sizeof(*array), 0), Iterator(array, sizeof(*array), 5), [&](void* item) {
+ obj->method();
+ ++(*static_cast<unsigned*>(item));
+ });
+}
\ No newline at end of file
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
Thanks for the review! |
…ranges functions as noescape. (llvm#138995) Functions in std::ranges namespace does not store the lambada passed-in as an arugment in heap so treat such an argument as if it has [[noescape]] in the WebKit lambda capture checker so that we don't emit warnings for capturing raw pointers or references to smart-pointer capable objects.
Functions in std::ranges namespace does not store the lambada passed-in as an arugment in heap so treat such an argument as if it has [[noescape]] in the WebKit lambda capture checker so that we don't emit warnings for capturing raw pointers or references to smart-pointer capable objects.