1 // RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount,debug.ExprInspection -analyzer-store=region -verify -Wno-objc-root-class %s 2 // RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount,debug.ExprInspection -analyzer-store=region -verify -Wno-objc-root-class -fobjc-arc %s 3 4 void clang_analyzer_eval(int); 5 6 typedef signed char BOOL; 7 typedef unsigned int NSUInteger; 8 typedef struct _NSZone NSZone; 9 @class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; 10 @protocol NSObject - (BOOL)isEqual:(id)object; @end 11 @protocol NSCopying - (id)copyWithZone:(NSZone *)zone; @end 12 @protocol NSCoding - (void)encodeWithCoder:(NSCoder *)aCoder; @end 13 @protocol NSMutableCopying - (id)mutableCopyWithZone:(NSZone *)zone; @end 14 @interface NSObject <NSObject> {} 15 +(id)alloc; 16 -(id)init; 17 -(id)autorelease; 18 -(id)copy; 19 -(id)retain; 20 -(oneway void)release; 21 @end 22 @interface NSString : NSObject <NSCopying, NSMutableCopying, NSCoding> 23 - (NSUInteger)length; 24 -(id)initWithFormat:(NSString *)f,...; 25 -(BOOL)isEqualToString:(NSString *)s; 26 + (id)string; 27 @end 28 @interface NSNumber : NSObject {} 29 +(id)alloc; 30 -(id)initWithInteger:(int)i; 31 @end 32 33 // rdar://6946338 34 35 @interface Test1 : NSObject { 36 NSString *text; 37 } 38 -(id)myMethod; 39 @property (nonatomic, assign) NSString *text; 40 @end 41 42 43 #if !__has_feature(objc_arc) 44 45 @implementation Test1 46 47 @synthesize text; 48 49 -(id)myMethod { 50 Test1 *cell = [[[Test1 alloc] init] autorelease]; 51 52 NSString *string1 = [[NSString alloc] initWithFormat:@"test %f", 0.0]; // expected-warning {{Potential leak}} 53 cell.text = string1; 54 55 return cell; 56 } 57 58 @end 59 60 61 // rdar://8824416 62 63 @interface MyNumber : NSObject 64 { 65 NSNumber* _myNumber; 66 } 67 68 - (id)initWithNumber:(NSNumber *)number; 69 70 @property (nonatomic, readonly) NSNumber* myNumber; 71 @property (nonatomic, readonly) NSNumber* newMyNumber; 72 73 @end 74 75 @implementation MyNumber 76 @synthesize myNumber=_myNumber; 77 78 - (id)initWithNumber:(NSNumber *)number 79 { 80 self = [super init]; 81 82 if ( self ) 83 { 84 _myNumber = [number copy]; 85 } 86 87 return self; 88 } 89 90 - (NSNumber*)newMyNumber 91 { 92 if ( _myNumber ) 93 return [_myNumber retain]; 94 95 return [[NSNumber alloc] initWithInteger:1]; 96 } 97 98 - (id)valueForUndefinedKey:(NSString*)key 99 { 100 id value = 0; 101 102 if ([key isEqualToString:@"MyIvarNumberAsPropertyOverReleased"]) 103 value = self.myNumber; // _myNumber will be over released, since the value returned from self.myNumber is not retained. 104 else if ([key isEqualToString:@"MyIvarNumberAsPropertyOk"]) 105 value = [self.myNumber retain]; // this line fixes the over release 106 else if ([key isEqualToString:@"MyIvarNumberAsNewMyNumber"]) 107 value = self.newMyNumber; // this one is ok, since value is returned retained 108 else 109 value = [[NSNumber alloc] initWithInteger:0]; 110 111 return [value autorelease]; // expected-warning {{Object autoreleased too many times}} 112 } 113 114 @end 115 116 NSNumber* numberFromMyNumberProperty(MyNumber* aMyNumber) 117 { 118 NSNumber* result = aMyNumber.myNumber; 119 120 return [result autorelease]; // expected-warning {{Object autoreleased too many times}} 121 } 122 123 #endif 124 125 126 // rdar://6611873 127 128 @interface Person : NSObject { 129 NSString *_name; 130 } 131 @property (retain) NSString * name; 132 @property (assign) id friend; 133 @end 134 135 @implementation Person 136 @synthesize name = _name; 137 @end 138 139 #if !__has_feature(objc_arc) 140 void rdar6611873() { 141 Person *p = [[[Person alloc] init] autorelease]; 142 143 p.name = [[NSString string] retain]; // expected-warning {{leak}} 144 p.name = [[NSString alloc] init]; // expected-warning {{leak}} 145 146 p.friend = [[Person alloc] init]; // expected-warning {{leak}} 147 } 148 #endif 149 150 @interface SubPerson : Person 151 -(NSString *)foo; 152 @end 153 154 @implementation SubPerson 155 -(NSString *)foo { 156 return super.name; 157 } 158 @end 159 160 161 #if !__has_feature(objc_arc) 162 // <rdar://problem/9241180> Static analyzer doesn't detect uninitialized variable issues for property accesses 163 @interface RDar9241180 164 @property (readwrite,assign) id x; 165 -(id)testAnalyzer1:(int) y; 166 -(void)testAnalyzer2; 167 @end 168 169 @implementation RDar9241180 170 @synthesize x; 171 -(id)testAnalyzer1:(int)y { 172 RDar9241180 *o; 173 if (y && o.x) // expected-warning {{Property access on an uninitialized object pointer}} 174 return o; 175 return o; // expected-warning {{Undefined or garbage value returned to caller}} 176 } 177 -(void)testAnalyzer2 { 178 id y; 179 self.x = y; // expected-warning {{Argument for property setter is an uninitialized value}} 180 } 181 @end 182 #endif 183 184 185 //------ 186 // Property accessor synthesis 187 //------ 188 189 extern void doSomethingWithPerson(Person *p); 190 extern void doSomethingWithName(NSString *name); 191 192 void testConsistencyRetain(Person *p) { 193 clang_analyzer_eval(p.name == p.name); // expected-warning{{TRUE}} 194 195 id origName = p.name; 196 clang_analyzer_eval(p.name == origName); // expected-warning{{TRUE}} 197 doSomethingWithPerson(p); 198 clang_analyzer_eval(p.name == origName); // expected-warning{{UNKNOWN}} 199 } 200 201 void testConsistencyAssign(Person *p) { 202 clang_analyzer_eval(p.friend == p.friend); // expected-warning{{TRUE}} 203 204 id origFriend = p.friend; 205 clang_analyzer_eval(p.friend == origFriend); // expected-warning{{TRUE}} 206 doSomethingWithPerson(p); 207 clang_analyzer_eval(p.friend == origFriend); // expected-warning{{UNKNOWN}} 208 } 209 210 #if !__has_feature(objc_arc) 211 void testOverrelease(Person *p, int coin) { 212 switch (coin) { 213 case 0: 214 [p.name release]; // expected-warning{{not owned}} 215 break; 216 case 1: 217 [p.friend release]; // expected-warning{{not owned}} 218 break; 219 case 2: { 220 id friend = p.friend; 221 doSomethingWithPerson(p); 222 [friend release]; // expected-warning{{not owned}} 223 } 224 } 225 } 226 227 // <rdar://problem/16333368> 228 @implementation Person (Rdar16333368) 229 230 - (void)testDeliberateRelease:(Person *)other { 231 doSomethingWithName(self.name); 232 [_name release]; // no-warning 233 self->_name = 0; 234 235 doSomethingWithName(other->_name); 236 [other.name release]; // expected-warning{{not owned}} 237 } 238 239 - (void)deliberateReleaseFalseNegative { 240 // This is arguably a false negative because the result of p.friend shouldn't 241 // be released, even though we are manipulating the ivar in between the two 242 // actions. 243 id name = self.name; 244 _name = 0; 245 [name release]; 246 } 247 248 - (void)testRetainAndRelease { 249 [self.name retain]; 250 [self.name release]; 251 [self.name release]; // expected-warning{{not owned}} 252 } 253 254 - (void)testRetainAndReleaseIVar { 255 [self.name retain]; 256 [_name release]; 257 [_name release]; // expected-warning{{not owned}} 258 } 259 260 @end 261 #endif 262 263 @interface IntWrapper 264 @property int value; 265 @end 266 267 @implementation IntWrapper 268 @synthesize value; 269 @end 270 271 void testConsistencyInt(IntWrapper *w) { 272 clang_analyzer_eval(w.value == w.value); // expected-warning{{TRUE}} 273 274 int origValue = w.value; 275 if (origValue != 42) 276 return; 277 278 clang_analyzer_eval(w.value == 42); // expected-warning{{TRUE}} 279 } 280 281 void testConsistencyInt2(IntWrapper *w) { 282 if (w.value != 42) 283 return; 284 285 clang_analyzer_eval(w.value == 42); // expected-warning{{TRUE}} 286 } 287 288 289 @interface IntWrapperAuto 290 @property int value; 291 @end 292 293 @implementation IntWrapperAuto 294 @end 295 296 void testConsistencyIntAuto(IntWrapperAuto *w) { 297 clang_analyzer_eval(w.value == w.value); // expected-warning{{TRUE}} 298 299 int origValue = w.value; 300 if (origValue != 42) 301 return; 302 303 clang_analyzer_eval(w.value == 42); // expected-warning{{TRUE}} 304 } 305 306 void testConsistencyIntAuto2(IntWrapperAuto *w) { 307 if (w.value != 42) 308 return; 309 310 clang_analyzer_eval(w.value == 42); // expected-warning{{TRUE}} 311 } 312 313 314 typedef struct { 315 int value; 316 } IntWrapperStruct; 317 318 @interface StructWrapper 319 @property IntWrapperStruct inner; 320 @end 321 322 @implementation StructWrapper 323 @synthesize inner; 324 @end 325 326 void testConsistencyStruct(StructWrapper *w) { 327 clang_analyzer_eval(w.inner.value == w.inner.value); // expected-warning{{TRUE}} 328 329 int origValue = w.inner.value; 330 if (origValue != 42) 331 return; 332 333 clang_analyzer_eval(w.inner.value == 42); // expected-warning{{TRUE}} 334 } 335 336 337 @interface OpaqueIntWrapper 338 @property int value; 339 @end 340 341 // For now, don't assume a property is implemented using an ivar unless we can 342 // actually see that it is. 343 void testOpaqueConsistency(OpaqueIntWrapper *w) { 344 clang_analyzer_eval(w.value == w.value); // expected-warning{{UNKNOWN}} 345 } 346 347