diff options
author | Zancanaro; Carlo <czan8762@plang3.cs.usyd.edu.au> | 2012-09-24 09:58:17 +1000 |
---|---|---|
committer | Zancanaro; Carlo <czan8762@plang3.cs.usyd.edu.au> | 2012-09-24 09:58:17 +1000 |
commit | 222e2a7620e6520ffaf4fc4e69d79c18da31542e (patch) | |
tree | 7bfbc05bfa3b41c8f9d2e56d53a0bc3e310df239 /clang/test/Analysis/objc-arc.m | |
parent | 3d206f03985b50beacae843d880bccdc91a9f424 (diff) |
Add the clang library to the repo (with some of my changes, too).
Diffstat (limited to 'clang/test/Analysis/objc-arc.m')
-rw-r--r-- | clang/test/Analysis/objc-arc.m | 220 |
1 files changed, 220 insertions, 0 deletions
diff --git a/clang/test/Analysis/objc-arc.m b/clang/test/Analysis/objc-arc.m new file mode 100644 index 0000000..e6c6ab5 --- /dev/null +++ b/clang/test/Analysis/objc-arc.m @@ -0,0 +1,220 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core,osx.cocoa.RetainCount,deadcode -analyzer-store=region -verify -fblocks -analyzer-opt-analyze-nested-blocks -fobjc-arc %s + +typedef signed char BOOL; +typedef struct _NSZone NSZone; +@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; +typedef unsigned long NSUInteger; + +@protocol NSObject +- (BOOL)isEqual:(id)object; +@end +@protocol NSCopying +- (id)copyWithZone:(NSZone *)zone; +@end +@protocol NSCoding; +@protocol NSMutableCopying; +@protocol NSFastEnumeration +- (void)encodeWithCoder:(NSCoder *)aCoder; +@end +@protocol NSMutableCopying - (id)mutableCopyWithZone:(NSZone *)zone; +@end +@protocol NSCoding - (void)encodeWithCoder:(NSCoder *)aCoder; +@end +@interface NSObject <NSObject> {} ++ (id)alloc; +- (id)init; +- (NSString *)description; +@end +@interface NSArray : NSObject <NSCopying, NSMutableCopying, NSCoding, NSFastEnumeration> +- (NSUInteger)count; +- (id)initWithObjects:(const id [])objects count:(NSUInteger)cnt; ++ (id)arrayWithObject:(id)anObject; ++ (id)arrayWithObjects:(const id [])objects count:(NSUInteger)cnt; ++ (id)arrayWithObjects:(id)firstObj, ... __attribute__((sentinel(0,1))); +- (id)initWithObjects:(id)firstObj, ... __attribute__((sentinel(0,1))); +- (id)initWithArray:(NSArray *)array; +@end + +typedef const struct __CFAllocator * CFAllocatorRef; +extern const CFAllocatorRef kCFAllocatorDefault; +typedef double CFTimeInterval; +typedef CFTimeInterval CFAbsoluteTime; +extern CFAbsoluteTime CFAbsoluteTimeGetCurrent(void); +typedef const struct __CFDate * CFDateRef; +extern CFDateRef CFDateCreate(CFAllocatorRef allocator, CFAbsoluteTime at); + +typedef const void* objc_objectptr_t; +__attribute__((ns_returns_retained)) id objc_retainedObject(objc_objectptr_t __attribute__((cf_consumed)) pointer); +__attribute__((ns_returns_not_retained)) id objc_unretainedObject(objc_objectptr_t pointer); + +// Test the analyzer is working at all. +void test_working() { + int *p = 0; + *p = 0xDEADBEEF; // expected-warning {{null}} +} + +// Test that in ARC mode that blocks are correctly automatically copied +// and not flagged as warnings by the analyzer. +typedef void (^Block)(void); +void testblock_bar(int x); + +Block testblock_foo(int x) { + Block b = ^{ testblock_bar(x); }; + return b; // no-warning +} + +Block testblock_baz(int x) { + return ^{ testblock_bar(x); }; // no-warning +} + +Block global_block; + +void testblock_qux(int x) { + global_block = ^{ testblock_bar(x); }; // no-warning +} + +// Test that Objective-C pointers are null initialized. +void test_nil_initialized() { + id x; + if (x == 0) + return; + int *p = 0; + *p = 0xDEADBEEF; // no-warning +} + +// Test that we don't flag leaks of Objective-C objects. +void test_alloc() { + [NSObject alloc]; // no-warning +} + +// Test that CF allocations are still caught as leaks. +void test_cf_leak() { + CFAbsoluteTime t = CFAbsoluteTimeGetCurrent(); + CFDateRef date = CFDateCreate(0, t); // expected-warning {{Potential leak}} + (void) date; +} + +// Test that 'init' methods do not try to claim ownerhip of an *unowned* allocated object +// in ARC mode. +@interface RDar9424890_A : NSObject +- (id)initWithCleaner:(int)pop mop:(NSString *)mop ; +- (RDar9424890_A *)rdar9424890:(NSString *)identifier; +@end +@interface RDar9424890_B : NSObject +@end +@implementation RDar9424890_B +- (RDar9424890_A *)obj:(RDar9424890_A *)obj { + static NSString *WhizFiz = @"WhizFiz"; + RDar9424890_A *cell = [obj rdar9424890:WhizFiz]; + if (cell == ((void*)0)) { + cell = [[RDar9424890_A alloc] initWithCleaner:0 mop:WhizFiz]; // no-warning + } + return cell; +} +@end + +// Test that dead store checking works in the prescence of "cleanups" in the AST. +void rdar9424882() { + id x = [NSObject alloc]; // expected-warning {{Value stored to 'x' during its initialization is never read}} +} + +// Test +typedef const void *CFTypeRef; +typedef const struct __CFString *CFStringRef; + +@interface NSString +- (id) self; +@end + +CFTypeRef CFCreateSomething(); +CFStringRef CFCreateString(); +CFTypeRef CFGetSomething(); +CFStringRef CFGetString(); + +id CreateSomething(); +NSString *CreateNSString(); + +void from_cf() { + id obj1 = (__bridge_transfer id)CFCreateSomething(); // expected-warning{{never read}} + id obj2 = (__bridge_transfer NSString*)CFCreateString(); + [obj2 self]; // Add a use, to show we can use the object after it has been transfered. + id obj3 = (__bridge id)CFGetSomething(); + [obj3 self]; // Add a use, to show we can use the object after it has been bridged. + id obj4 = (__bridge NSString*)CFGetString(); // expected-warning{{never read}} + id obj5 = (__bridge id)CFCreateSomething(); // expected-warning{{never read}} expected-warning{{leak}} + id obj6 = (__bridge NSString*)CFCreateString(); // expected-warning{{never read}} expected-warning{{leak}} +} + +void to_cf(id obj) { + CFTypeRef cf1 = (__bridge_retained CFTypeRef)CreateSomething(); // expected-warning{{never read}} + CFStringRef cf2 = (__bridge_retained CFStringRef)CreateNSString(); // expected-warning{{never read}} + CFTypeRef cf3 = (__bridge CFTypeRef)CreateSomething(); // expected-warning{{never read}} + CFStringRef cf4 = (__bridge CFStringRef)CreateNSString(); // expected-warning{{never read}} +} + +void test_objc_retainedObject() { + CFAbsoluteTime t = CFAbsoluteTimeGetCurrent(); + CFDateRef date = CFDateCreate(0, t); + id x = objc_retainedObject(date); + (void) x; +} + +void test_objc_unretainedObject() { + CFAbsoluteTime t = CFAbsoluteTimeGetCurrent(); + CFDateRef date = CFDateCreate(0, t); // expected-warning {{Potential leak}} + id x = objc_unretainedObject(date); + (void) x; +} + +// Previously this resulted in a "return of stack address" warning. +id test_return() { + id x = (__bridge_transfer id) CFCreateString(); + return x; // no-warning +} + +void test_objc_arrays() { + { // CASE ONE -- OBJECT IN ARRAY CREATED DIRECTLY + NSObject *o = [[NSObject alloc] init]; + NSArray *a = [[NSArray alloc] initWithObjects:o, (void*)0]; + [a description]; + [o description]; + } + + { // CASE TWO -- OBJECT IN ARRAY CREATED BY DUPING AUTORELEASED ARRAY + NSObject *o = [[NSObject alloc] init]; + NSArray *a1 = [NSArray arrayWithObjects:o, (void*)0]; + NSArray *a2 = [[NSArray alloc] initWithArray:a1]; + [a2 description]; + [o description]; + } + + { // CASE THREE -- OBJECT IN RETAINED @[] + NSObject *o = [[NSObject alloc] init]; + NSArray *a3 = @[o]; + [a3 description]; + [o description]; + } + { + // CASE 4, verify analyzer still working. + CFCreateString(); // expected-warning {{leak}} + } +} + +// <rdar://problem/11059275> - dispatch_set_context and ARC. +__attribute__((cf_returns_retained)) CFTypeRef CFBridgingRetain(id X); +typedef void* dispatch_object_t; +void dispatch_set_context(dispatch_object_t object, const void *context); + +void rdar11059275(dispatch_object_t object) { + NSObject *o = [[NSObject alloc] init]; + dispatch_set_context(object, CFBridgingRetain(o)); // no-warning +} +void rdar11059275_positive() { + NSObject *o = [[NSObject alloc] init]; // expected-warning {{leak}} + CFBridgingRetain(o); +} +void rdar11059275_negative() { + NSObject *o = [[NSObject alloc] init]; // no-warning + (void) o; +} + |