[clang] [alpha.webkit.RetainPtrCtorAdoptChecker] Allow leakRef in copy methods (PR #160986)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Sep 26 23:21:17 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-static-analyzer-1
Author: Ryosuke Niwa (rniwa)
<details>
<summary>Changes</summary>
Allow leakRef() in the return statement of an Objective-C copy method and other methods which return +1.
---
Full diff: https://github.com/llvm/llvm-project/pull/160986.diff
3 Files Affected:
- (modified) clang/lib/StaticAnalyzer/Checkers/WebKit/RetainPtrCtorAdoptChecker.cpp (+4)
- (modified) clang/test/Analysis/Checkers/WebKit/objc-mock-types.h (+35-1)
- (modified) clang/test/Analysis/Checkers/WebKit/retain-ptr-ctor-adopt-use.mm (+10-2)
``````````diff
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/RetainPtrCtorAdoptChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/RetainPtrCtorAdoptChecker.cpp
index e1f9a77f5a5ca..955b8d19a820c 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/RetainPtrCtorAdoptChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/RetainPtrCtorAdoptChecker.cpp
@@ -385,6 +385,10 @@ class RetainPtrCtorAdoptChecker
if (RTC.isUnretained(RetValue->getType()))
return;
}
+ if (retainsRet && *retainsRet) {
+ CreateOrCopyFnCall.insert(RetValue);
+ return;
+ }
if (auto *CE = dyn_cast<CallExpr>(RetValue)) {
auto *Callee = CE->getDirectCallee();
if (!Callee || !isCreateOrCopyFunction(Callee))
diff --git a/clang/test/Analysis/Checkers/WebKit/objc-mock-types.h b/clang/test/Analysis/Checkers/WebKit/objc-mock-types.h
index 39dee1746158b..dacb713130818 100644
--- a/clang/test/Analysis/Checkers/WebKit/objc-mock-types.h
+++ b/clang/test/Analysis/Checkers/WebKit/objc-mock-types.h
@@ -17,6 +17,20 @@ template<typename T> typename remove_reference<T>::type&& move(T&& t);
#endif
+namespace std {
+
+template <bool, typename U = void> struct enable_if {
+};
+
+template <typename T> struct enable_if<true, T> {
+ using type = T;
+};
+
+template <bool value, class T = void>
+using enable_if_t = typename enable_if<value, T>::type;
+
+}
+
@class NSString;
@class NSArray;
@class NSMutableArray;
@@ -100,6 +114,7 @@ id CFBridgingRelease(CFTypeRef X) {
__attribute__((objc_root_class))
@interface NSObject
+ (instancetype) alloc;
++ (instancetype) allocWithZone:(NSZone *)zone;
+ (Class) class;
+ (Class) superclass;
- (instancetype) init;
@@ -232,6 +247,14 @@ template <typename T> struct RemovePointer<T*> {
typedef T Type;
};
+template <typename T> struct IsPointer {
+ static constexpr bool value = false;
+};
+
+template <typename T> struct IsPointer<T*> {
+ static constexpr bool value = true;
+};
+
template <typename T> struct RetainPtr {
using ValueType = typename RemovePointer<T>::Type;
using PtrType = ValueType*;
@@ -285,12 +308,23 @@ template <typename T> struct RetainPtr {
PtrType operator->() const { return t; }
T &operator*() const { return *t; }
RetainPtr &operator=(PtrType t);
- PtrType leakRef()
+
+ template <typename U = PtrType>
+ std::enable_if_t<IsPointer<U>::value, U> leakRef() CF_RETURNS_RETAINED
+ {
+ PtrType s = t;
+ t = nullptr;
+ return s;
+ }
+
+ template <typename U = PtrType>
+ std::enable_if_t<!IsPointer<U>::value, U> leakRef() NS_RETURNS_RETAINED
{
PtrType s = t;
t = nullptr;
return s;
}
+
operator PtrType() const { return t; }
operator bool() const { return t; }
diff --git a/clang/test/Analysis/Checkers/WebKit/retain-ptr-ctor-adopt-use.mm b/clang/test/Analysis/Checkers/WebKit/retain-ptr-ctor-adopt-use.mm
index 769901778cdf0..45705615f3196 100644
--- a/clang/test/Analysis/Checkers/WebKit/retain-ptr-ctor-adopt-use.mm
+++ b/clang/test/Analysis/Checkers/WebKit/retain-ptr-ctor-adopt-use.mm
@@ -104,6 +104,14 @@ - (void)setValue:value {
_number = value;
}
+- (id)copyWithZone:(NSZone *)zone {
+ auto copy = adoptNS([(SomeObj *)[SomeObj allocWithZone:zone] init]);
+ [copy setValue:_number];
+ [copy setNext:_next];
+ [copy setOther:_other];
+ return copy.leakRef();
+}
+
@end;
RetainPtr<CVPixelBufferRef> cf_out_argument() {
@@ -151,7 +159,7 @@ CFTypeRef LeakWrapper() {
extern Class (*getNSArrayClass)();
NSArray *allocArrayInstance() NS_RETURNS_RETAINED {
- return [[getNSArrayClass() alloc] init];
+ return adoptNS([[getNSArrayClass() alloc] init]).leakRef();
}
extern int (*GetObj)(CF_RETURNS_RETAINED CFTypeRef* objOut);
@@ -294,7 +302,7 @@ -(NSString *)leak_string {
}
-(NSString *)make_string {
- return [[NSString alloc] initWithUTF8String:"hello"];
+ return adoptNS([[NSString alloc] initWithUTF8String:"hello"]).leakRef();
}
-(void)local_leak_string {
``````````
</details>
https://github.com/llvm/llvm-project/pull/160986
More information about the cfe-commits
mailing list