[clang] ec06755 - Add the support for adoptCFNullable/adoptNSNullable (#194539)

via cfe-commits cfe-commits at lists.llvm.org
Tue Apr 28 08:48:22 PDT 2026


Author: Ryosuke Niwa
Date: 2026-04-28T08:48:16-07:00
New Revision: ec0675591f0dd5a4bfed477b0d5e25aa404d7e0f

URL: https://github.com/llvm/llvm-project/commit/ec0675591f0dd5a4bfed477b0d5e25aa404d7e0f
DIFF: https://github.com/llvm/llvm-project/commit/ec0675591f0dd5a4bfed477b0d5e25aa404d7e0f.diff

LOG: Add the support for adoptCFNullable/adoptNSNullable (#194539)

These are two new "adopt" functions to be introduced in WebKit.

Added: 
    

Modified: 
    clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
    clang/lib/StaticAnalyzer/Checkers/WebKit/RetainPtrCtorAdoptChecker.cpp
    clang/test/Analysis/Checkers/WebKit/objc-mock-types.h
    clang/test/Analysis/Checkers/WebKit/retain-ptr-ctor-adopt-use-arc.mm
    clang/test/Analysis/Checkers/WebKit/retain-ptr-ctor-adopt-use.mm
    clang/test/Analysis/Checkers/WebKit/unretained-call-args.mm

Removed: 
    


################################################################################
diff  --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
index d239ed4c8a5ae..b8c8359c22773 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
@@ -175,7 +175,8 @@ bool isCtorOfCheckedPtr(const clang::FunctionDecl *F) {
 bool isCtorOfRetainPtrOrOSPtr(const clang::FunctionDecl *F) {
   const std::string &FunctionName = safeGetName(F);
   return FunctionName == "RetainPtr" || FunctionName == "adoptNS" ||
-         FunctionName == "adoptCF" || FunctionName == "retainPtr" ||
+         FunctionName == "adoptNSNullable" || FunctionName == "adoptCF" ||
+         FunctionName == "adoptCFNullable" || FunctionName == "retainPtr" ||
          FunctionName == "RetainPtrArc" || FunctionName == "adoptNSArc" ||
          FunctionName == "adoptOSObject" || FunctionName == "adoptOSObjectArc";
 }

diff  --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/RetainPtrCtorAdoptChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/RetainPtrCtorAdoptChecker.cpp
index 2af9067f8f808..afa9fc7b1c4a4 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/RetainPtrCtorAdoptChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/RetainPtrCtorAdoptChecker.cpp
@@ -122,11 +122,13 @@ class RetainPtrCtorAdoptChecker
 
   bool isAdoptFnName(const std::string &Name) const {
     return isAdoptNS(Name) || Name == "adoptCF" || Name == "adoptCFArc" ||
+           Name == "adoptCFNullable" || Name == "adoptCFNullableArc" ||
            Name == "adoptOSObject" || Name == "adoptOSObjectArc";
   }
 
   bool isAdoptNS(const std::string &Name) const {
-    return Name == "adoptNS" || Name == "adoptNSArc";
+    return Name == "adoptNS" || Name == "adoptNSArc" ||
+           Name == "adoptNSNullable" || Name == "adoptNSNullableArc";
   }
 
   void visitCallExpr(const CallExpr *CE, const Decl *DeclWithIssue) const {

diff  --git a/clang/test/Analysis/Checkers/WebKit/objc-mock-types.h b/clang/test/Analysis/Checkers/WebKit/objc-mock-types.h
index 124821a8ded55..503d11bea3089 100644
--- a/clang/test/Analysis/Checkers/WebKit/objc-mock-types.h
+++ b/clang/test/Analysis/Checkers/WebKit/objc-mock-types.h
@@ -265,7 +265,9 @@ void WTFCrash(void);
 
 template<typename T> class RetainPtr;
 template<typename T> RetainPtr<T> adoptNS(T*);
+template<typename T> RetainPtr<T> adoptNSNullable(T*);
 template<typename T> RetainPtr<T> adoptCF(T);
+template<typename T> RetainPtr<T> adoptCFNullable(T);
 
 template <typename T, typename S> T *downcast(S *t) { return static_cast<T*>(t); }
 
@@ -367,7 +369,9 @@ template <typename T> struct RetainPtr {
   CFTypeRef toCFTypeRef(const void* ptr) { return (CFTypeRef)ptr; }
 
   template <typename U> friend RetainPtr<U> adoptNS(U*);
+  template <typename U> friend RetainPtr<U> adoptNSNullable(U*);
   template <typename U> friend RetainPtr<U> adoptCF(U);
+  template <typename U> friend RetainPtr<U> adoptCFNullable(U);
 
   enum AdoptTag { Adopt };
   RetainPtr(PtrType t, AdoptTag) : t(t) { }
@@ -395,11 +399,25 @@ RetainPtr<T> adoptNS(T* t) {
 #endif
 }
 
+template <typename T>
+RetainPtr<T> adoptNSNullable(T* t) {
+#if __has_feature(objc_arc)
+  return t;
+#else
+  return RetainPtr<T>(t, RetainPtr<T>::Adopt);
+#endif
+}
+
 template <typename T>
 RetainPtr<T> adoptCF(T t) {
   return RetainPtr<T>(t, RetainPtr<T>::Adopt);
 }
 
+template <typename T>
+RetainPtr<T> adoptCFNullable(T t) {
+  return RetainPtr<T>(t, RetainPtr<T>::Adopt);
+}
+
 template<typename T> inline RetainPtr<T> retainPtr(T ptr)
 {
   return ptr;
@@ -681,7 +699,9 @@ WTF_DECLARE_CF_MUTABLE_TYPE_TRAIT(CFDictionary, CFMutableDictionary);
 
 using WTF::RetainPtr;
 using WTF::adoptNS;
+using WTF::adoptNSNullable;
 using WTF::adoptCF;
+using WTF::adoptCFNullable;
 using WTF::retainPtr;
 using WTF::OSObjectPtr;
 using WTF::adoptOSObject;

diff  --git a/clang/test/Analysis/Checkers/WebKit/retain-ptr-ctor-adopt-use-arc.mm b/clang/test/Analysis/Checkers/WebKit/retain-ptr-ctor-adopt-use-arc.mm
index 79ea95b088167..135fe651a9f16 100644
--- a/clang/test/Analysis/Checkers/WebKit/retain-ptr-ctor-adopt-use-arc.mm
+++ b/clang/test/Analysis/Checkers/WebKit/retain-ptr-ctor-adopt-use-arc.mm
@@ -12,9 +12,11 @@ void basic_correct() {
   auto ns4 = adoptNS([ns3 mutableCopy]);
   auto ns5 = adoptNS([ns3 copyWithValue:3]);
   auto ns6 = retainPtr([ns3 next]);
+  auto ns7 = adoptNSNullable([[SomeObj alloc] init]);
   CFMutableArrayRef cf1 = adoptCF(CFArrayCreateMutable(kCFAllocatorDefault, 10));
   auto cf2 = adoptCF(SecTaskCreateFromSelf(kCFAllocatorDefault));
   auto cf3 = adoptCF(checked_cf_cast<CFArrayRef>(CFCopyArray(cf1)));
+  auto cf4 = adoptCFNullable(CFArrayCreateMutable(kCFAllocatorDefault, 10));
 }
 
 CFMutableArrayRef provide_cf();
@@ -24,6 +26,8 @@ void basic_wrong() {
   // expected-warning at -1{{Incorrect use of RetainPtr constructor. The argument is +1 and results in a memory leak when ARC is disabled [alpha.webkit.RetainPtrCtorAdoptChecker]}}
   auto ns2 = adoptNS([ns1.get() next]);
   // expected-warning at -1{{Incorrect use of adoptNS. The argument is +0 and results in an use-after-free when ARC is disabled [alpha.webkit.RetainPtrCtorAdoptChecker]}}
+  auto ns3 = adoptNSNullable([ns1.get() next]);
+  // expected-warning at -1{{Incorrect use of adoptNSNullable. The argument is +0 and results in an use-after-free when ARC is disabled [alpha.webkit.RetainPtrCtorAdoptChecker]}}
   RetainPtr<CFMutableArrayRef> cf1 = CFArrayCreateMutable(kCFAllocatorDefault, 10);
   // expected-warning at -1{{Incorrect use of RetainPtr constructor. The argument is +1 and results in a memory leak [alpha.webkit.RetainPtrCtorAdoptChecker]}}
   RetainPtr<CFMutableArrayRef> cf2 = adoptCF(provide_cf());
@@ -32,6 +36,8 @@ void basic_wrong() {
   // expected-warning at -1{{Incorrect use of RetainPtr constructor. The argument is +1 and results in a memory leak [alpha.webkit.RetainPtrCtorAdoptChecker]}}
   CFCopyArray(cf1);
   // expected-warning at -1{{The return value is +1 and results in a memory leak [alpha.webkit.RetainPtrCtorAdoptChecker]}}
+  RetainPtr<CFMutableArrayRef> cf4 = adoptCFNullable(provide_cf());
+  // expected-warning at -1{{Incorrect use of adoptCFNullable. The argument is +0 and results in an use-after-free when ARC is disabled [alpha.webkit.RetainPtrCtorAdoptChecker]}}
 }
 
 void basic_correct_arc() {

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 20f951b27a149..c337752d6bd21 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
@@ -15,9 +15,11 @@ void basic_correct() {
   auto ns6 = retainPtr([ns3 next]);
   auto ns7 = retainPtr((SomeObj *)0);
   auto ns8 = adoptNS(nil);
+  auto ns9 = adoptNSNullable([[SomeObj alloc] init]);
   CFMutableArrayRef cf1 = adoptCF(CFArrayCreateMutable(kCFAllocatorDefault, 10));
   auto cf2 = adoptCF(SecTaskCreateFromSelf(kCFAllocatorDefault));
   auto cf3 = adoptCF(checked_cf_cast<CFArrayRef>(CFCopyArray(cf1)));
+  auto cf4 = adoptCFNullable(CFArrayCreateMutable(kCFAllocatorDefault, 10));
   CreateCopy();
 }
 
@@ -28,6 +30,8 @@ void basic_wrong() {
   // expected-warning at -1{{Incorrect use of RetainPtr constructor. The argument is +1 and results in a memory leak [alpha.webkit.RetainPtrCtorAdoptChecker]}}
   auto ns2 = adoptNS([ns1.get() next]);
   // expected-warning at -1{{Incorrect use of adoptNS. The argument is +0 and results in an use-after-free [alpha.webkit.RetainPtrCtorAdoptChecker]}}
+  auto ns3 = adoptNSNullable([ns1.get() next]);
+  // expected-warning at -1{{Incorrect use of adoptNSNullable. The argument is +0 and results in an use-after-free [alpha.webkit.RetainPtrCtorAdoptChecker]}}
   RetainPtr<CFMutableArrayRef> cf1 = CFArrayCreateMutable(kCFAllocatorDefault, 10);
   // expected-warning at -1{{Incorrect use of RetainPtr constructor. The argument is +1 and results in a memory leak [alpha.webkit.RetainPtrCtorAdoptChecker]}}
   RetainPtr<CFMutableArrayRef> cf2 = adoptCF(provide_cf());
@@ -36,6 +40,8 @@ void basic_wrong() {
   // expected-warning at -1{{Incorrect use of RetainPtr constructor. The argument is +1 and results in a memory leak [alpha.webkit.RetainPtrCtorAdoptChecker]}}
   CFCopyArray(cf1);
   // expected-warning at -1{{The return value is +1 and results in a memory leak [alpha.webkit.RetainPtrCtorAdoptChecker]}}
+  RetainPtr<CFMutableArrayRef> cf4 = adoptCFNullable(provide_cf());
+  // expected-warning at -1{{Incorrect use of adoptCFNullable. The argument is +0 and results in an use-after-free [alpha.webkit.RetainPtrCtorAdoptChecker]}}
 }
 
 void basic_correct_arc() {

diff  --git a/clang/test/Analysis/Checkers/WebKit/unretained-call-args.mm b/clang/test/Analysis/Checkers/WebKit/unretained-call-args.mm
index cfc214fae33e5..add9144744db4 100644
--- a/clang/test/Analysis/Checkers/WebKit/unretained-call-args.mm
+++ b/clang/test/Analysis/Checkers/WebKit/unretained-call-args.mm
@@ -385,7 +385,9 @@ void os_ptr() {
 namespace call_with_adopt_ref {
   void foo() {
     [adoptNS(provide()).get() doWork];
+    [adoptNSNullable(provide()).get() doWork];
     CFArrayAppendValue(adoptCF(provide_cf()).get(), nullptr);
+    CFArrayAppendValue(adoptCFNullable(provide_cf()).get(), nullptr);
     consume_dispatch(adoptOSObject(provide_dispatch()).get());
   }
 }


        


More information about the cfe-commits mailing list