]> granicus.if.org Git - clang/commitdiff
Implement attribute 'cf_returns_owned' (mirrors 'ns_returns_owned').
authorTed Kremenek <kremenek@apple.com>
Tue, 5 May 2009 00:46:09 +0000 (00:46 +0000)
committerTed Kremenek <kremenek@apple.com>
Tue, 5 May 2009 00:46:09 +0000 (00:46 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@70952 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-gc-only.m
test/Analysis/retain-release.m

index 79f41bda5d69659a8807b697b2678babeb7a314e..d55f26d5427617fff8df11d800db6c00f7ce47c8 100644 (file)
@@ -61,6 +61,7 @@ public:
     ObjCNSObject,
     CFOwnershipRelease,       // Clang/Checker-specific.
     CFOwnershipRetain,        // Clang/Checker-specific.
+    CFOwnershipReturns,       // Clang/Checker-specific.
     NSOwnershipRelease,         // Clang/Checker-specific.
     NSOwnershipRetain,          // Clang/Checker-specific.
     NSOwnershipReturns,         // Clang/Checker-specific.
@@ -135,7 +136,7 @@ public:
 class ATTR##Attr : public Attr {                                        \
 public:                                                                 \
   ATTR##Attr() : Attr(ATTR) {}                                          \
-  virtual Attr *clone(ASTContext &C) const { return ::new (C) ATTR##Attr; }                \
+  virtual Attr *clone(ASTContext &C) const { return ::new (C) ATTR##Attr; }\
   static bool classof(const Attr *A) { return A->getKind() == ATTR; }   \
   static bool classof(const ATTR##Attr *A) { return true; }             \
 }
@@ -466,8 +467,9 @@ public:
 
 // Checker-specific attributes.
 DEF_SIMPLE_ATTR(CFOwnershipRelease);
-DEF_SIMPLE_ATTR(NSOwnershipRelease);
 DEF_SIMPLE_ATTR(CFOwnershipRetain);
+DEF_SIMPLE_ATTR(CFOwnershipReturns);
+DEF_SIMPLE_ATTR(NSOwnershipRelease);
 DEF_SIMPLE_ATTR(NSOwnershipRetain);
 DEF_SIMPLE_ATTR(NSOwnershipReturns);
 
index 3666542d67116abd393f65ff49e0772cba4a71fe..52f0f149f75ba8e98029ac270989a77697dd5138 100644 (file)
@@ -78,11 +78,12 @@ public:
     AT_objc_exception,
     AT_cf_releases,        // Clang-specific.
     AT_cf_retains,         // Clang-specific.
-    AT_ns_releases,          // Clang-specific.
-    AT_ns_retains,           // Clang-specific.
-    AT_ns_returns_owned,          // Clang-specific.
+    AT_cf_returns_owned,   // Clang-specific.
+    AT_ns_releases,        // Clang-specific.
+    AT_ns_retains,         // Clang-specific.
+    AT_ns_returns_owned,   // Clang-specific.
     AT_objc_gc,
-    AT_overloadable,            // Clang-specific.
+    AT_overloadable,       // Clang-specific.
     AT_packed,
     AT_pure,
     AT_regparm,
index 976bfad188de9f09b5d2c1a03b3df5eafd0f7cc7..07dbf10c4081f969bd600160e91c65b9f8d449a2 100644 (file)
@@ -1128,6 +1128,9 @@ RetainSummaryManager::updateSummaryFromAnnotations(RetainSummary &Summ,
                         ? RetEffect::MakeGCNotOwned()
                         : RetEffect::MakeOwned(RetEffect::ObjC, true));
     }
+    else if (FD->getAttr<CFOwnershipReturnsAttr>()) {
+      Summ.setRetEffect(RetEffect::MakeOwned(RetEffect::CF, true));
+    }
   }
   
   // Determine if there are any arguments with a specific ArgEffect.
@@ -1150,6 +1153,9 @@ RetainSummaryManager::updateSummaryFromAnnotations(RetainSummary &Summ,
                         ? RetEffect::MakeGCNotOwned()
                         : RetEffect::MakeOwned(RetEffect::ObjC, true));
     }
+    else if (MD->getAttr<CFOwnershipReturnsAttr>()) {
+      Summ.setRetEffect(RetEffect::MakeOwned(RetEffect::CF, true));
+    }    
   }
   
   // Determine if there are any arguments with a specific ArgEffect.
index ff2eb9f7c92961298ec776ea7b5a37802bb1766f..7bcd296bce2963e5f95d8455e2ab168c02cdd931 100644 (file)
@@ -477,6 +477,7 @@ Attr *PCHReader::ReadAttributes() {
     SIMPLE_ATTR(ObjCNSObject);
     SIMPLE_ATTR(CFOwnershipRelease);
     SIMPLE_ATTR(CFOwnershipRetain);
+    SIMPLE_ATTR(CFOwnershipReturns);
     SIMPLE_ATTR(NSOwnershipRelease);
     SIMPLE_ATTR(NSOwnershipRetain);
     SIMPLE_ATTR(NSOwnershipReturns);
index a1f0cb7f4fe53039989787ea9ad5d2896f17fd7d..98ed063305cf23ab4fb4ece45187282063b9c1f3 100644 (file)
@@ -1551,6 +1551,7 @@ void PCHWriter::WriteAttributeRecord(const Attr *Attr) {
     case Attr::ObjCNSObject:
     case Attr::CFOwnershipRelease:
     case Attr::CFOwnershipRetain:
+    case Attr::CFOwnershipReturns:
     case Attr::NSOwnershipRelease:
     case Attr::NSOwnershipRetain:
     case Attr::NSOwnershipReturns:
index 1cc9a51ec6f76eb6cc14b9080d573e022317fb89..933e9f2b09ba733830ab2baa0cd014bc31da7d36 100644 (file)
@@ -132,6 +132,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) {
     break;
   case 16:
     if (!memcmp(Str, "ns_returns_owned", 16)) return AT_ns_returns_owned;
+    if (!memcmp(Str, "cf_returns_owned", 16)) return AT_cf_returns_owned;
     break;      
   case 17:
     if (!memcmp(Str, "transparent_union", 17)) return AT_transparent_union;
index 033be2c9622757b5d0a2e6065f295fc082df7294..926e5fda68dfb2a523582724d7d1760286105acd 100644 (file)
@@ -1548,15 +1548,37 @@ static void HandleRegparmAttr(Decl *d, const AttributeList &Attr, Sema &S) {
 //===----------------------------------------------------------------------===//
 
 static void HandleNSOwnershipReturnsAttr(Decl *d, const AttributeList &Attr,
-                                           Sema &S) {
+                                         Sema &S) {
 
   if (!isa<ObjCMethodDecl>(d) && !isa<FunctionDecl>(d)) {
+    const char *name;
+    
+    switch (Attr.getKind()) {
+      default:
+        assert(0 && "invalid ownership attribute");
+        return;
+      case AttributeList::AT_cf_returns_owned:
+        name = "cf_returns_owned"; break;
+      case AttributeList::AT_ns_returns_owned:
+        name = "ns_returns_owned"; break;
+    };
+
     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) <<
-      "ns_returns_owned" << 3 /* function or method */;
+      name << 3 /* function or method */;
     return;
   }
   
-  d->addAttr(::new (S.Context) NSOwnershipReturnsAttr());
+  switch (Attr.getKind()) {
+    default:
+      assert(0 && "invalid ownership attribute");
+      return;
+    case AttributeList::AT_cf_returns_owned:
+      d->addAttr(::new (S.Context) CFOwnershipReturnsAttr());
+      return;
+    case AttributeList::AT_ns_returns_owned:
+      d->addAttr(::new (S.Context) NSOwnershipReturnsAttr());
+      return;
+  };
 }
 
 static void HandleNSOwnershipAttr(Decl *d, const AttributeList &Attr,
@@ -1579,9 +1601,9 @@ static void HandleNSOwnershipAttr(Decl *d, const AttributeList &Attr,
         name = "ns_retains"; break;
     };
 
-    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << name
-      << (attachToMethodDecl ? 5 /* parameter or method decl */ 
-                             : 4 /* parameter */);
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) <<
+      name << (attachToMethodDecl ? 5 /* parameter or method decl */ 
+                                  : 4 /* parameter */);
     return;
   }
   
@@ -1590,13 +1612,17 @@ static void HandleNSOwnershipAttr(Decl *d, const AttributeList &Attr,
       assert(0 && "invalid ownership attribute");
       return;
     case AttributeList::AT_cf_releases:
-      d->addAttr(::new (S.Context) CFOwnershipReleaseAttr()); return;      
+      d->addAttr(::new (S.Context) CFOwnershipReleaseAttr());
+      return;
     case AttributeList::AT_cf_retains:
-      d->addAttr(::new (S.Context) CFOwnershipRetainAttr()); return;
+      d->addAttr(::new (S.Context) CFOwnershipRetainAttr());
+      return;
     case AttributeList::AT_ns_releases:
-      d->addAttr(::new (S.Context) NSOwnershipReleaseAttr());   return;
+      d->addAttr(::new (S.Context) NSOwnershipReleaseAttr());
+      return;
     case AttributeList::AT_ns_retains:
-      d->addAttr(::new (S.Context) NSOwnershipRetainAttr());   return;
+      d->addAttr(::new (S.Context) NSOwnershipRetainAttr());
+      return;
   }
 }
 
@@ -1645,6 +1671,7 @@ static void ProcessDeclAttribute(Decl *D, const AttributeList &Attr, Sema &S) {
   case AttributeList::AT_ns_retains:
       HandleNSOwnershipAttr(D, Attr, S, true); break;
   case AttributeList::AT_ns_returns_owned:
+  case AttributeList::AT_cf_returns_owned:
     HandleNSOwnershipReturnsAttr(D, Attr, S); break;
 
   case AttributeList::AT_packed:      HandlePackedAttr    (D, Attr, S); break;
index 74d2c9479763e497520b2ee144caf8b4acb32ddf..3a57bead476de01a3449c0d6329b74219867e9fe 100644 (file)
@@ -130,6 +130,7 @@ void f3() {
 
 @interface TestOwnershipAttr : NSObject
 - (NSString*) returnsAnOwnedString __attribute__((ns_returns_owned));
+- (NSString*) returnsAnOwnedCFString  __attribute__((cf_returns_owned));
 - (void) myRetain:(id)__attribute__((ns_retains))obj;
 - (void) myCFRetain:(id)__attribute__((cf_retains))obj;
 - (void) myRelease:(id)__attribute__((ns_releases))obj;
@@ -140,12 +141,22 @@ void test_attr_1(TestOwnershipAttr *X) {
   NSString *str = [X returnsAnOwnedString]; // no-warning
 }
 
+void test_attr_1b(TestOwnershipAttr *X) {
+  NSString *str = [X returnsAnOwnedCFString]; // expected-warning{{leak}}
+}
+
 void test_attr_2(TestOwnershipAttr *X) {
   NSString *str = [X returnsAnOwnedString]; // no-warning
   [X myRetain:str];
   [str release];
 }
 
+void test_attr_2b(TestOwnershipAttr *X) {
+  NSString *str = [X returnsAnOwnedCFString]; // expected-warning{{leak}}
+  [X myRetain:str];
+  [str release];
+}
+
 void test_attr_3(TestOwnershipAttr *X) {
   NSString *str = [X returnsAnOwnedString]; // expected-warning{{leak}}
   [X myCFRetain:str];
index a25c0e262547fa3ab7d4564ce1130a25d6de6226..b7b2efa7976ac28e8e7a2104ce39a40a9c2d8d59 100644 (file)
@@ -432,6 +432,7 @@ void rdar6704930(unsigned char *s, unsigned int length) {
 
 @interface TestOwnershipAttr : NSObject
 - (NSString*) returnsAnOwnedString  __attribute__((ns_returns_owned));
+- (NSString*) returnsAnOwnedCFString  __attribute__((cf_returns_owned));
 - (void) myRetain:(id)__attribute__((ns_retains))obj;
 - (void) myCFRetain:(id)__attribute__((cf_retains))obj;
 - (void) myRelease:(id)__attribute__((ns_releases))obj;
@@ -458,12 +459,22 @@ void test_attr_1(TestOwnershipAttr *X) {
   NSString *str = [X returnsAnOwnedString]; // expected-warning{{leak}}
 }
 
+void test_attr_1b(TestOwnershipAttr *X) {
+  NSString *str = [X returnsAnOwnedCFString]; // expected-warning{{leak}}
+}
+
 void test_attr_2(TestOwnershipAttr *X) {
   NSString *str = [X returnsAnOwnedString]; // expected-warning{{leak}}
   [X myRetain:str];
   [str release];
 }
 
+void test_attr_2b(TestOwnershipAttr *X) {
+  NSString *str = [X returnsAnOwnedCFString]; // expected-warning{{leak}}
+  [X myRetain:str];
+  [str release];
+}
+
 void test_attr_3(TestOwnershipAttr *X) {
   NSString *str = [X returnsAnOwnedString]; // expected-warning{{leak}}
   [X myCFRetain:str];