]> granicus.if.org Git - clang/commitdiff
Recognize attributes ns_returns_not_retained and cf_returns_not_retained
authorTed Kremenek <kremenek@apple.com>
Thu, 18 Feb 2010 00:06:12 +0000 (00:06 +0000)
committerTed Kremenek <kremenek@apple.com>
Thu, 18 Feb 2010 00:06:12 +0000 (00:06 +0000)
in the static analyzer.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@96539 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Checker/CFRefCount.cpp
test/Analysis/retain-release.m

index 2eb9607bc92272e6727f458567416d0a10eb753f..ecb98a0496f08af230cfa2fad8f996c194da2157 100644 (file)
@@ -1222,6 +1222,12 @@ RetainSummaryManager::updateSummaryFromAnnotations(RetainSummary &Summ,
     else if (FD->getAttr<CFReturnsRetainedAttr>()) {
       Summ.setRetEffect(RetEffect::MakeOwned(RetEffect::CF, true));
     }
+    else if (FD->getAttr<NSReturnsNotRetainedAttr>()) {
+      Summ.setRetEffect(RetEffect::MakeNotOwned(RetEffect::ObjC));
+    }
+    else if (FD->getAttr<CFReturnsNotRetainedAttr>()) {
+      Summ.setRetEffect(RetEffect::MakeNotOwned(RetEffect::CF));
+    }
   }
   else if (RetTy->getAs<PointerType>()) {
     if (FD->getAttr<CFReturnsRetainedAttr>()) {
@@ -1244,6 +1250,10 @@ RetainSummaryManager::updateSummaryFromAnnotations(RetainSummary &Summ,
       Summ.setRetEffect(ObjCAllocRetE);
       return;
     }
+    if (MD->getAttr<NSReturnsNotRetainedAttr>()) {
+      Summ.setRetEffect(RetEffect::MakeNotOwned(RetEffect::ObjC));
+      return;
+    }
 
     isTrackedLoc = true;
   }
@@ -1251,8 +1261,12 @@ RetainSummaryManager::updateSummaryFromAnnotations(RetainSummary &Summ,
   if (!isTrackedLoc)
     isTrackedLoc = MD->getResultType()->getAs<PointerType>() != NULL;
 
-  if (isTrackedLoc && MD->getAttr<CFReturnsRetainedAttr>())
-    Summ.setRetEffect(RetEffect::MakeOwned(RetEffect::CF, true));
+  if (isTrackedLoc) {
+    if (MD->getAttr<CFReturnsRetainedAttr>())
+      Summ.setRetEffect(RetEffect::MakeOwned(RetEffect::CF, true));
+    else if (MD->getAttr<CFReturnsNotRetainedAttr>())
+      Summ.setRetEffect(RetEffect::MakeNotOwned(RetEffect::CF));
+  }
 }
 
 RetainSummary*
index 1c41d85d23e5fc4a398466d0141ee43f8b6c478c..675e9a6702616a014bc532d889e57a31514cc68c 100644 (file)
@@ -7,6 +7,12 @@
 #if __has_feature(attribute_cf_returns_retained)
 #define CF_RETURNS_RETAINED __attribute__((cf_returns_retained))
 #endif
+#if __has_feature(attribute_ns_returns_not_retained)
+#define NS_RETURNS_NOT_RETAINED __attribute__((ns_returns_not_retained))
+#endif
+#if __has_feature(attribute_cf_returns_not_retained)
+#define CF_RETURNS_NOT_RETAINED __attribute__((cf_returns_not_retained))
+#endif
 
 //===----------------------------------------------------------------------===//
 // The following code is reduced using delta-debugging from Mac OS X headers:
@@ -1188,6 +1194,8 @@ typedef NSString* MyStringTy;
 - (NSString*) returnsAnOwnedString  NS_RETURNS_RETAINED; // no-warning
 - (NSString*) returnsAnOwnedCFString  CF_RETURNS_RETAINED; // no-warning
 - (MyStringTy) returnsAnOwnedTypedString NS_RETURNS_RETAINED; // no-warning
+- (NSString*) newString NS_RETURNS_NOT_RETAINED; // no-warning
+- (NSString*) newStringNoAttr;
 - (int) returnsAnOwnedInt NS_RETURNS_RETAINED; // expected-warning{{'ns_returns_retained' attribute only applies to functions or methods that return a pointer or Objective-C object}}
 @end
 
@@ -1201,9 +1209,16 @@ void test_attr_1b(TestOwnershipAttr *X) {
   NSString *str = [X returnsAnOwnedCFString]; // expected-warning{{leak}}
 }
 
+void test_attr1c(TestOwnershipAttr *X) {
+  NSString *str = [X newString]; // no-warning
+  NSString *str2 = [X newStringNoAttr]; // expected-warning{{leak}}
+}
+
 @interface MyClassTestCFAttr : NSObject {}
 - (NSDate*) returnsCFRetained CF_RETURNS_RETAINED;
 - (CFDateRef) returnsCFRetainedAsCF CF_RETURNS_RETAINED;
+- (CFDateRef) newCFRetainedAsCF CF_RETURNS_NOT_RETAINED;
+- (CFDateRef) newCFRetainedAsCFNoAttr;
 - (NSDate*) alsoReturnsRetained;
 - (CFDateRef) alsoReturnsRetainedAsCF;
 - (NSDate*) returnsNSRetained NS_RETURNS_RETAINED;
@@ -1223,6 +1238,13 @@ CFDateRef returnsRetainedCFDate()  {
   return returnsRetainedCFDate(); // No leak.
 }
 
+- (CFDateRef) newCFRetainedAsCF {
+  return (CFDateRef)[(id)[self returnsCFRetainedAsCF] autorelease];
+}
+
+- (CFDateRef) newCFRetainedAsCFNoAttr {
+  return (CFDateRef)[(id)[self returnsCFRetainedAsCF] autorelease]; // expected-warning{{Object with +0 retain counts returned to caller where a +1 (owning) retain count is expected}}
+}
 
 - (NSDate*) alsoReturnsRetained {
   return (NSDate*) returnsRetainedCFDate(); // expected-warning{{leak}}