Skip to content

Conversation

@rniwa
Copy link
Contributor

@rniwa rniwa commented Sep 27, 2025

Allow leakRef() in the return statement of an Objective-C copy method and other methods which return +1.

Allow leakRef() in the return statement of an Objective-C copy method and other methods which return +1.
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:static analyzer labels Sep 27, 2025
@rniwa rniwa requested a review from t-rasmud September 27, 2025 06:20
@llvmbot
Copy link
Member

llvmbot commented Sep 27, 2025

@llvm/pr-subscribers-clang

@llvm/pr-subscribers-clang-static-analyzer-1

Author: Ryosuke Niwa (rniwa)

Changes

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 --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 {

Copy link
Contributor

@t-rasmud t-rasmud left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@rniwa
Copy link
Contributor Author

rniwa commented Oct 1, 2025

Thank you!

@rniwa rniwa merged commit 103d2ca into llvm:main Oct 1, 2025
10 of 12 checks passed
@rniwa rniwa deleted the fix-webkit-allow-leak-ref-in-copy branch October 1, 2025 22:01
rniwa added a commit to rniwa/llvm-project that referenced this pull request Oct 1, 2025
llvm#160986)

Allow leakRef() in the return statement of an Objective-C copy method
and other methods which return +1.
mahesh-attarde pushed a commit to mahesh-attarde/llvm-project that referenced this pull request Oct 3, 2025
llvm#160986)

Allow leakRef() in the return statement of an Objective-C copy method
and other methods which return +1.
rniwa added a commit to rniwa/llvm-project that referenced this pull request Oct 16, 2025
llvm#160986)

Allow leakRef() in the return statement of an Objective-C copy method
and other methods which return +1.

(cherry picked from commit 103d2ca)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

clang:static analyzer clang Clang issues not falling into any other category

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants