]> granicus.if.org Git - clang/commitdiff
[analyzer] More tests for "release and stop tracking".
authorJordan Rose <jordan_rose@apple.com>
Mon, 20 Aug 2012 22:15:44 +0000 (22:15 +0000)
committerJordan Rose <jordan_rose@apple.com>
Mon, 20 Aug 2012 22:15:44 +0000 (22:15 +0000)
Under GC, a release message is ignored, so "release and stop tracking" just
becomes "stop tracking". But CFRelease is still honored. This is the main
difference between ns_consumed and cf_consumed.

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

test/Analysis/retain-release-gc-only.m
test/Analysis/retain-release.m

index 0340a3c2a140e36d4c64c44627c30ac5a650eda7..1a5ed34c9f3983b9567eee0c30223035934da79c 100644 (file)
@@ -107,9 +107,14 @@ NSFastEnumerationState;
 @end  @interface NSNumber : NSValue  - (char)charValue;
 - (id)initWithInt:(int)value;
 @end   @class NSString;
-@interface NSArray : NSObject <NSCopying, NSMutableCopying, NSCoding, NSFastEnumeration>  - (NSUInteger)count;
-@end  @interface NSArray (NSArrayCreation)  + (id)array;
-@end       @interface NSAutoreleasePool : NSObject {
+@interface NSArray : NSObject <NSCopying, NSMutableCopying, NSCoding, NSFastEnumeration>
+- (NSUInteger)count;
+@end
+@interface NSArray (NSArrayCreation)
++ (id)array;
++ (id)arrayWithObjects:(const id [])objects count:(NSUInteger)cnt;
+@end
+       @interface NSAutoreleasePool : NSObject {
 }
 - (void)drain;
 - (id)init;
@@ -385,3 +390,45 @@ CFDateRef returnsRetainedCFDate()  {
   return (NSDate*) returnsRetainedCFDate(); // expected-warning{{leak}}
 }
 @end
+
+
+#if __has_feature(attribute_ns_consumed)
+#define NS_CONSUMED __attribute__((ns_consumed))
+#endif
+#if __has_feature(attribute_cf_consumed)
+#define CF_CONSUMED __attribute__((cf_consumed))
+#endif
+
+void consumeAndStopTracking(id NS_CONSUMED obj, void (^callback)(void));
+void CFConsumeAndStopTracking(CFTypeRef CF_CONSUMED obj, void (^callback)(void));
+
+void testConsumeAndStopTracking() {
+  id retained = [@[] retain]; // +0, GC
+  consumeAndStopTracking(retained, ^{}); // no-warning
+
+  id doubleRetained = [[@[] retain] retain]; // +0, GC
+  consumeAndStopTracking(doubleRetained, ^{
+    [doubleRetained release];
+  }); // no-warning
+
+  id unretained = @[]; // +0
+  consumeAndStopTracking(unretained, ^{}); // no-warning, GC
+}
+
+void testCFConsumeAndStopTrackingMsg() {
+  id retained = [@[] retain]; // +0, GC
+  CFConsumeAndStopTracking((CFTypeRef)retained, ^{}); // expected-warning {{Incorrect decrement of the reference count of an object that is not owned at this point by the caller}}
+}
+
+void testCFConsumeAndStopTracking() {
+  CFTypeRef retained = returnsRetainedCFDate(); // +1
+  CFConsumeAndStopTracking(retained, ^{}); // no-warning
+
+  CFTypeRef doubleRetained = CFRetain(returnsRetainedCFDate()); // +2
+  CFConsumeAndStopTracking(doubleRetained, ^{
+    CFRelease(doubleRetained);
+  }); // no-warning
+
+  id unretained = @[]; // +0
+  CFConsumeAndStopTracking((CFTypeRef)unretained, ^{}); // expected-warning {{Incorrect decrement of the reference count of an object that is not owned at this point by the caller}}
+}
index efd0532945549b485bc8987a0a913316315a521d..da1477bb5888ba31a879a7dbdff77596d899916e 100644 (file)
@@ -1748,7 +1748,7 @@ extern id NSApp;
 @end
 //===----------------------------------------------------------------------===//
 // Test returning allocated memory in a struct.
-// 
+//
 // We currently don't have a general way to track pointers that "escape".
 // Here we test that RetainCountChecker doesn't get excited about returning
 // allocated CF objects in struct fields.
@@ -1856,7 +1856,10 @@ id makeCollectableNonLeak() {
   return [objCObject autorelease]; // +0
 }
 
+
 void consumeAndStopTracking(id NS_CONSUMED obj, void (^callback)(void));
+void CFConsumeAndStopTracking(CFTypeRef CF_CONSUMED obj, void (^callback)(void));
+
 void testConsumeAndStopTracking() {
   id retained = [@[] retain]; // +1
   consumeAndStopTracking(retained, ^{}); // no-warning
@@ -1869,3 +1872,16 @@ void testConsumeAndStopTracking() {
   id unretained = @[]; // +0
   consumeAndStopTracking(unretained, ^{}); // expected-warning {{Incorrect decrement of the reference count of an object that is not owned at this point by the caller}}
 }
+
+void testCFConsumeAndStopTracking() {
+  id retained = [@[] retain]; // +1
+  CFConsumeAndStopTracking((CFTypeRef)retained, ^{}); // no-warning
+
+  id doubleRetained = [[@[] retain] retain]; // +2
+  CFConsumeAndStopTracking((CFTypeRef)doubleRetained, ^{
+    [doubleRetained release];
+  }); // no-warning
+
+  id unretained = @[]; // +0
+  CFConsumeAndStopTracking((CFTypeRef)unretained, ^{}); // expected-warning {{Incorrect decrement of the reference count of an object that is not owned at this point by the caller}}
+}