Skip to content

Conversation

@rniwa
Copy link
Contributor

@rniwa rniwa commented Oct 2, 2025

Make RetainPtrCtorAdoptChecker recognize an assignment to an +1 out argument so that it won't emit a memory leak warning.

… +1 out argument as a leak

Make RetainPtrCtorAdoptChecker recognize an assignment to an +1 out argument so that it won't
emit a memory leak warning.
@rniwa rniwa requested a review from t-rasmud October 2, 2025 06:58
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:static analyzer labels Oct 2, 2025
@llvmbot
Copy link
Member

llvmbot commented Oct 2, 2025

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

@llvm/pr-subscribers-clang

Author: Ryosuke Niwa (rniwa)

Changes

Make RetainPtrCtorAdoptChecker recognize an assignment to an +1 out argument so that it won't emit a memory leak warning.


Full diff: https://github.com/llvm/llvm-project/pull/161633.diff

2 Files Affected:

  • (modified) clang/lib/StaticAnalyzer/Checkers/WebKit/RetainPtrCtorAdoptChecker.cpp (+23-7)
  • (modified) clang/test/Analysis/Checkers/WebKit/retain-ptr-ctor-adopt-use.mm (+8)
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/RetainPtrCtorAdoptChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/RetainPtrCtorAdoptChecker.cpp
index e1f9a77f5a5ca..7440352d8482d 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/RetainPtrCtorAdoptChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/RetainPtrCtorAdoptChecker.cpp
@@ -355,14 +355,30 @@ class RetainPtrCtorAdoptChecker
   void visitBinaryOperator(const BinaryOperator *BO) const {
     if (!BO->isAssignmentOp())
       return;
-    if (!isa<ObjCIvarRefExpr>(BO->getLHS()))
-      return;
+    auto *LHS = BO->getLHS();
     auto *RHS = BO->getRHS()->IgnoreParenCasts();
-    const Expr *Inner = nullptr;
-    if (isAllocInit(RHS, &Inner)) {
-      CreateOrCopyFnCall.insert(RHS);
-      if (Inner)
-        CreateOrCopyFnCall.insert(Inner);
+    if (isa<ObjCIvarRefExpr>(LHS)) {
+      const Expr *Inner = nullptr;
+      if (isAllocInit(RHS, &Inner)) {
+        CreateOrCopyFnCall.insert(RHS);
+        if (Inner)
+          CreateOrCopyFnCall.insert(Inner);
+      }
+      return;
+    } else if (auto *UO = dyn_cast<UnaryOperator>(LHS)) {
+      auto OpCode = UO->getOpcode();
+      if (OpCode == UO_Deref) {
+        if (auto *DerefTarget = UO->getSubExpr()) {
+          DerefTarget = DerefTarget->IgnoreParenCasts();
+          auto *DRE = dyn_cast<DeclRefExpr>(DerefTarget);
+          if (auto *Decl = DRE->getDecl()) {
+            if (!isa<ParmVarDecl>(Decl) || !isCreateOrCopy(RHS))
+              return;
+            if (Decl->hasAttr<CFReturnsRetainedAttr>())
+              CreateOrCopyFnCall.insert(RHS);
+          }
+        }
+      }
     }
   }
 
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..3b0f19404097b 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
@@ -182,6 +182,14 @@ void adopt_retainptr() {
   auto bar = adoptNS([allocSomeObj() init]);
 }
 
+CFTypeRef make_cf_obj() CF_RETURNS_RETAINED {
+  return CFArrayCreateMutable(kCFAllocatorDefault, 1);
+}
+
+void get_cf_obj(CFTypeRef* CF_RETURNS_RETAINED result) {
+  *result = CFArrayCreateMutable(kCFAllocatorDefault, 1);
+}
+
 RetainPtr<CFArrayRef> return_arg(CFArrayRef arg) {
   return arg;
 }

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.

2 participants