1*67e74705SXin Li// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount -analyzer-store=region -analyzer-constraints=range -verify -fobjc-gc %s -Wno-implicit-function-declaration 2*67e74705SXin Li 3*67e74705SXin Li//===----------------------------------------------------------------------===// 4*67e74705SXin Li// The following code is reduced using delta-debugging from 5*67e74705SXin Li// Foundation.h and CoreFoundation.h (Mac OS X). 6*67e74705SXin Li// 7*67e74705SXin Li// It includes the basic definitions for the test cases below. 8*67e74705SXin Li// Not directly including [Core]Foundation.h directly makes this test case 9*67e74705SXin Li// both svelte and portable to non-Mac platforms. 10*67e74705SXin Li//===----------------------------------------------------------------------===// 11*67e74705SXin Li 12*67e74705SXin Litypedef const void * CFTypeRef; 13*67e74705SXin Livoid CFRelease(CFTypeRef cf); 14*67e74705SXin LiCFTypeRef CFRetain(CFTypeRef cf); 15*67e74705SXin LiCFTypeRef CFMakeCollectable(CFTypeRef cf); 16*67e74705SXin Litypedef const struct __CFAllocator * CFAllocatorRef; 17*67e74705SXin Litypedef double CFTimeInterval; 18*67e74705SXin Litypedef CFTimeInterval CFAbsoluteTime; 19*67e74705SXin Litypedef const struct __CFDate * CFDateRef; 20*67e74705SXin Liextern CFDateRef CFDateCreate(CFAllocatorRef allocator, CFAbsoluteTime at); 21*67e74705SXin Liextern CFAbsoluteTime CFDateGetAbsoluteTime(CFDateRef theDate); 22*67e74705SXin Litypedef struct objc_object {} *id; 23*67e74705SXin Litypedef signed char BOOL; 24*67e74705SXin Listatic __inline__ __attribute__((always_inline)) id NSMakeCollectable(CFTypeRef cf) { return 0; } 25*67e74705SXin Li@protocol NSObject - (BOOL)isEqual:(id)object; 26*67e74705SXin Li- (oneway void)release; 27*67e74705SXin Li- (id)retain; 28*67e74705SXin Li@end 29*67e74705SXin Li@class NSArray; 30*67e74705SXin Li 31*67e74705SXin Li//===----------------------------------------------------------------------===// 32*67e74705SXin Li// Test cases. 33*67e74705SXin Li//===----------------------------------------------------------------------===// 34*67e74705SXin Li 35*67e74705SXin LiCFAbsoluteTime CFAbsoluteTimeGetCurrent(); 36*67e74705SXin Li 37*67e74705SXin LiCFAbsoluteTime f1_use_after_release() { 38*67e74705SXin Li CFAbsoluteTime t = CFAbsoluteTimeGetCurrent(); 39*67e74705SXin Li CFDateRef date = CFDateCreate(0, t); 40*67e74705SXin Li CFRetain(date); 41*67e74705SXin Li [NSMakeCollectable(date) release]; 42*67e74705SXin Li CFDateGetAbsoluteTime(date); // no-warning 43*67e74705SXin Li CFRelease(date); 44*67e74705SXin Li t = CFDateGetAbsoluteTime(date); // expected-warning{{Reference-counted object is used after it is released}} 45*67e74705SXin Li return t; 46*67e74705SXin Li} 47*67e74705SXin Li 48*67e74705SXin Li// The following two test cases verifies that CFMakeCollectable is a no-op 49*67e74705SXin Li// in non-GC mode and a "release" in GC mode. 50*67e74705SXin LiCFAbsoluteTime f2_use_after_release() { 51*67e74705SXin Li CFAbsoluteTime t = CFAbsoluteTimeGetCurrent(); 52*67e74705SXin Li CFDateRef date = CFDateCreate(0, t); 53*67e74705SXin Li CFRetain(date); 54*67e74705SXin Li [(id) CFMakeCollectable(date) release]; 55*67e74705SXin Li CFDateGetAbsoluteTime(date); // no-warning 56*67e74705SXin Li CFRelease(date); 57*67e74705SXin Li t = CFDateGetAbsoluteTime(date); // expected-warning{{Reference-counted object is used after it is released}} 58*67e74705SXin Li return t; 59*67e74705SXin Li} 60*67e74705SXin Li 61*67e74705SXin LiCFAbsoluteTime f2_noleak() { 62*67e74705SXin Li CFAbsoluteTime t = CFAbsoluteTimeGetCurrent(); 63*67e74705SXin Li CFDateRef date = CFDateCreate(0, t); 64*67e74705SXin Li CFRetain(date); 65*67e74705SXin Li [(id) CFMakeCollectable(date) release]; 66*67e74705SXin Li CFDateGetAbsoluteTime(date); // no-warning 67*67e74705SXin Li t = CFDateGetAbsoluteTime(date); // no-warning 68*67e74705SXin Li CFRelease(date); // no-warning 69*67e74705SXin Li return t; 70*67e74705SXin Li} 71*67e74705SXin Li 72*67e74705SXin Livoid f3_leak_with_gc() { 73*67e74705SXin Li CFDateRef date = CFDateCreate(0, CFAbsoluteTimeGetCurrent()); // expected-warning 2 {{leak}} 74*67e74705SXin Li [[(id) date retain] release]; 75*67e74705SXin Li} 76*67e74705SXin Li 77*67e74705SXin Li// The following test case verifies that we "stop tracking" a retained object 78*67e74705SXin Li// when it is passed as an argument to an implicitly defined function. 79*67e74705SXin LiCFAbsoluteTime f4() { 80*67e74705SXin Li CFAbsoluteTime t = CFAbsoluteTimeGetCurrent(); 81*67e74705SXin Li CFDateRef date = CFDateCreate(0, t); 82*67e74705SXin Li CFRetain(date); 83*67e74705SXin Li some_implicitly_defined_function_stop_tracking(date); // no-warning 84*67e74705SXin Li return t; 85*67e74705SXin Li} 86