llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Ryosuke Niwa (rniwa) <details> <summary>Changes</summary> 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. --- Full diff: https://github.com/llvm/llvm-project/pull/138995.diff 2 Files Affected: - (modified) clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLambdaCapturesChecker.cpp (+11-3) - (modified) clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures.cpp (+33) ``````````diff 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 `````````` </details> https://github.com/llvm/llvm-project/pull/138995 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits