]> granicus.if.org Git - clang/commitdiff
Implement attribute 'ns_autorelease'.
authorTed Kremenek <kremenek@apple.com>
Tue, 5 May 2009 18:44:20 +0000 (18:44 +0000)
committerTed Kremenek <kremenek@apple.com>
Tue, 5 May 2009 18:44:20 +0000 (18:44 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@70990 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Attr.h
include/clang/Parse/AttributeList.h
lib/Analysis/CFRefCount.cpp
lib/Frontend/PCHReaderDecl.cpp
lib/Frontend/PCHWriter.cpp
lib/Parse/AttributeList.cpp
lib/Sema/SemaDeclAttr.cpp
test/Analysis/retain-release.m

index d55f26d5427617fff8df11d800db6c00f7ce47c8..41f2e9470db9bbf0ef7eb6e34ed0222c704b54b0 100644 (file)
@@ -62,6 +62,7 @@ public:
     CFOwnershipRelease,       // Clang/Checker-specific.
     CFOwnershipRetain,        // Clang/Checker-specific.
     CFOwnershipReturns,       // Clang/Checker-specific.
+    NSOwnershipAutorelease,   // Clang/Checker-specific.
     NSOwnershipRelease,         // Clang/Checker-specific.
     NSOwnershipRetain,          // Clang/Checker-specific.
     NSOwnershipReturns,         // Clang/Checker-specific.
@@ -471,6 +472,7 @@ DEF_SIMPLE_ATTR(CFOwnershipRetain);
 DEF_SIMPLE_ATTR(CFOwnershipReturns);
 DEF_SIMPLE_ATTR(NSOwnershipRelease);
 DEF_SIMPLE_ATTR(NSOwnershipRetain);
+DEF_SIMPLE_ATTR(NSOwnershipAutorelease);
 DEF_SIMPLE_ATTR(NSOwnershipReturns);
 
 #undef DEF_SIMPLE_ATTR
index 52f0f149f75ba8e98029ac270989a77697dd5138..172c07fc6172ebd9ea54de8914562b439add3d69 100644 (file)
@@ -79,6 +79,7 @@ public:
     AT_cf_releases,        // Clang-specific.
     AT_cf_retains,         // Clang-specific.
     AT_cf_returns_owned,   // Clang-specific.
+    AT_ns_autoreleases,    // Clang-specific.
     AT_ns_releases,        // Clang-specific.
     AT_ns_retains,         // Clang-specific.
     AT_ns_returns_owned,   // Clang-specific.
index 07dbf10c4081f969bd600160e91c65b9f8d449a2..ca420006d2439e0a31c5b33bb701280da27f5ee5 100644 (file)
@@ -779,8 +779,8 @@ public:
   RetainSummary* getCommonMethodSummary(const ObjCMethodDecl* MD,
                                         Selector S, QualType RetTy);
 
-  void updateSummaryArgEffFromAnnotations(RetainSummary &Summ, unsigned i,
-                                          const ParmVarDecl *PD);
+  void updateSummaryArgEffFromAnnotations(RetainSummary &Summ, const Decl *D,
+                                          unsigned argIdx = 0);
 
   void updateSummaryFromAnnotations(RetainSummary &Summ,
                                     const ObjCMethodDecl *MD);
@@ -1097,22 +1097,32 @@ RetainSummaryManager::getInitMethodSummary(QualType RetTy) {
   // 'init' methods only return an alias if the return type is a location type.
   return getPersistentSummary(Loc::IsLocType(RetTy)
                               ? RetEffect::MakeReceiverAlias()
-                              : RetEffect::MakeNoRet());  
+                              : RetEffect::MakeNoRet());
 }
 
-
 void
 RetainSummaryManager::updateSummaryArgEffFromAnnotations(RetainSummary &Summ,
-                                                         unsigned i,
-                                                         const ParmVarDecl *PD){
-  if (PD->getAttr<NSOwnershipRetainAttr>())
-    Summ.setArgEffect(AF, i, IncRefMsg);
-  else if (PD->getAttr<CFOwnershipRetainAttr>())
-    Summ.setArgEffect(AF, i, IncRef);
-  else if (PD->getAttr<NSOwnershipReleaseAttr>())
-    Summ.setArgEffect(AF, i, DecRefMsg);
-  else if (PD->getAttr<CFOwnershipReleaseAttr>())
-    Summ.setArgEffect(AF, i, DecRef);
+                                                         const Decl *D,
+                                                         unsigned i) {
+  ArgEffect E = DoNothing;
+  
+  if (D->getAttr<NSOwnershipRetainAttr>())
+    E = IncRefMsg;
+  else if (D->getAttr<CFOwnershipRetainAttr>())
+    E = IncRef;
+  else if (D->getAttr<NSOwnershipReleaseAttr>())
+    E = DecRefMsg;
+  else if (D->getAttr<CFOwnershipReleaseAttr>())
+    E = DecRef;
+  else if (D->getAttr<NSOwnershipAutoreleaseAttr>())
+    E = Autorelease;
+  else
+    return;
+  
+  if (isa<ParmVarDecl>(D))
+    Summ.setArgEffect(AF, i, E);
+  else
+    Summ.setReceiverEffect(E);
 }
 
 void
@@ -1137,7 +1147,7 @@ RetainSummaryManager::updateSummaryFromAnnotations(RetainSummary &Summ,
   unsigned i = 0;
   for (FunctionDecl::param_const_iterator I = FD->param_begin(),
        E = FD->param_end(); I != E; ++I, ++i)
-    updateSummaryArgEffFromAnnotations(Summ, i, *I);
+    updateSummaryArgEffFromAnnotations(Summ, *I, i);
 }
   
 void
@@ -1162,13 +1172,10 @@ RetainSummaryManager::updateSummaryFromAnnotations(RetainSummary &Summ,
   unsigned i = 0;
   for (ObjCMethodDecl::param_iterator I = MD->param_begin(),
        E = MD->param_end(); I != E; ++I, ++i)
-    updateSummaryArgEffFromAnnotations(Summ, i, *I);
+    updateSummaryArgEffFromAnnotations(Summ, *I, i);
   
   // Determine any effects on the receiver.
-  if (MD->getAttr<NSOwnershipRetainAttr>())
-    Summ.setReceiverEffect(IncRefMsg);
-  else if (MD->getAttr<NSOwnershipReleaseAttr>())
-    Summ.setReceiverEffect(DecRefMsg);
+  updateSummaryArgEffFromAnnotations(Summ, MD);
 }
 
 RetainSummary*
index 7bcd296bce2963e5f95d8455e2ab168c02cdd931..059aa259c79103cdc6cd30693766af4ad5d19864 100644 (file)
@@ -478,6 +478,7 @@ Attr *PCHReader::ReadAttributes() {
     SIMPLE_ATTR(CFOwnershipRelease);
     SIMPLE_ATTR(CFOwnershipRetain);
     SIMPLE_ATTR(CFOwnershipReturns);
+    SIMPLE_ATTR(NSOwnershipAutorelease);
     SIMPLE_ATTR(NSOwnershipRelease);
     SIMPLE_ATTR(NSOwnershipRetain);
     SIMPLE_ATTR(NSOwnershipReturns);
index 98ed063305cf23ab4fb4ece45187282063b9c1f3..9b14a94fad20dc3fd12d6ad4b684dfce312e0477 100644 (file)
@@ -1552,6 +1552,7 @@ void PCHWriter::WriteAttributeRecord(const Attr *Attr) {
     case Attr::CFOwnershipRelease:
     case Attr::CFOwnershipRetain:
     case Attr::CFOwnershipReturns:
+    case Attr::NSOwnershipAutorelease:
     case Attr::NSOwnershipRelease:
     case Attr::NSOwnershipRetain:
     case Attr::NSOwnershipReturns:
index 933e9f2b09ba733830ab2baa0cd014bc31da7d36..6dceda6432eeccf28cc9c653d8e8458e003309cf 100644 (file)
@@ -129,6 +129,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) {
     break;
   case 15:
     if (!memcmp(Str, "ext_vector_type", 15)) return AT_ext_vector_type;
+    if (!memcmp(Str, "ns_autoreleases", 15)) return AT_ns_autoreleases;
     break;
   case 16:
     if (!memcmp(Str, "ns_returns_owned", 16)) return AT_ns_returns_owned;
index 926e5fda68dfb2a523582724d7d1760286105acd..7701835b38b427fc37bf43bfaa5971301ddc9c60 100644 (file)
@@ -1595,6 +1595,8 @@ static void HandleNSOwnershipAttr(Decl *d, const AttributeList &Attr,
         name = "cf_releases"; break;
       case AttributeList::AT_cf_retains:
         name = "cf_retains"; break;
+      case AttributeList::AT_ns_autoreleases:
+        name = "ns_autoreleases"; break;
       case AttributeList::AT_ns_releases:
         name = "ns_releases"; break;
       case AttributeList::AT_ns_retains:
@@ -1617,6 +1619,9 @@ static void HandleNSOwnershipAttr(Decl *d, const AttributeList &Attr,
     case AttributeList::AT_cf_retains:
       d->addAttr(::new (S.Context) CFOwnershipRetainAttr());
       return;
+    case AttributeList::AT_ns_autoreleases:
+      d->addAttr(::new (S.Context) NSOwnershipAutoreleaseAttr());
+      return;            
     case AttributeList::AT_ns_releases:
       d->addAttr(::new (S.Context) NSOwnershipReleaseAttr());
       return;
@@ -1667,6 +1672,7 @@ static void ProcessDeclAttribute(Decl *D, const AttributeList &Attr, Sema &S) {
   case AttributeList::AT_cf_releases:     
   case AttributeList::AT_cf_retains:
       HandleNSOwnershipAttr(D, Attr, S); break;
+  case AttributeList::AT_ns_autoreleases:
   case AttributeList::AT_ns_releases:
   case AttributeList::AT_ns_retains:
       HandleNSOwnershipAttr(D, Attr, S, true); break;
index 9ed10f812f83b52407b3e28ac1b1642cdb194dce..e9c3f5189bac9aa2dca58f27fe2c569f70f9acdf 100644 (file)
@@ -439,6 +439,8 @@ void rdar6704930(unsigned char *s, unsigned int length) {
 - (void) myCFRelease:(id)__attribute__((cf_releases))obj;
 - (void) myRetain __attribute__((ns_retains));
 - (void) myRelease __attribute__((ns_releases));
+- (void) myAutorelease __attribute__((ns_autoreleases));
+- (void) myAutorelease:(id)__attribute__((ns_autoreleases))obj;
 @end
 
 @interface TestAttrHelper : NSObject
@@ -478,6 +480,10 @@ NSString* test_attr_1d(TestOwnershipAttr *X) {
   return str;
 }
 
+void test_attr_1e(TestOwnershipAttr *X) {
+  NSString *str = [X returnsAnOwnedString]; // no-warning
+  [X myAutorelease:str];
+}
 
 void test_attr_2(TestOwnershipAttr *X) {
   NSString *str = [X returnsAnOwnedString]; // expected-warning{{leak}}
@@ -548,6 +554,11 @@ void test_attr_6c() {
   [X myRelease];
 }
 
+void test_attr_6d() {
+  TestOwnershipAttr *X = [TestOwnershipAttr alloc]; // no-warning
+  [X myAutorelease];
+}
+
 //===----------------------------------------------------------------------===//
 // <rdar://problem/6833332>
 // One build of the analyzer accidentally stopped tracking the allocated