1// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount,osx.cocoa.Dealloc,debug.ExprInspection -analyzer-store=region -verify -Wno-objc-root-class %s
2// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount,osx.cocoa.Dealloc,debug.ExprInspection -analyzer-store=region -verify -Wno-objc-root-class -fobjc-arc %s
3
4void clang_analyzer_eval(int);
5
6typedef const void * CFTypeRef;
7extern CFTypeRef CFRetain(CFTypeRef cf);
8void CFRelease(CFTypeRef cf);
9
10typedef signed char BOOL;
11typedef unsigned int NSUInteger;
12typedef struct _NSZone NSZone;
13@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator;
14@protocol NSObject  - (BOOL)isEqual:(id)object; @end
15@protocol NSCopying  - (id)copyWithZone:(NSZone *)zone; @end
16@protocol NSCoding  - (void)encodeWithCoder:(NSCoder *)aCoder; @end
17@protocol NSMutableCopying  - (id)mutableCopyWithZone:(NSZone *)zone; @end
18@interface NSObject <NSObject> {}
19+(id)alloc;
20-(id)init;
21-(id)autorelease;
22-(id)copy;
23-(id)retain;
24-(oneway void)release;
25-(void)dealloc;
26@end
27@interface NSString : NSObject <NSCopying, NSMutableCopying, NSCoding>
28- (NSUInteger)length;
29-(id)initWithFormat:(NSString *)f,...;
30-(BOOL)isEqualToString:(NSString *)s;
31+ (id)string;
32@end
33@interface NSNumber : NSObject {}
34+(id)alloc;
35-(id)initWithInteger:(int)i;
36@end
37
38// rdar://6946338
39
40@interface Test1 : NSObject {
41  NSString *text;
42}
43-(id)myMethod;
44@property (nonatomic, assign) NSString *text;
45@end
46
47
48#if !__has_feature(objc_arc)
49
50@implementation Test1
51
52@synthesize text;
53
54-(id)myMethod {
55  Test1 *cell = [[[Test1 alloc] init] autorelease];
56
57  NSString *string1 = [[NSString alloc] initWithFormat:@"test %f", 0.0]; // expected-warning {{Potential leak}}
58  cell.text = string1;
59
60  return cell;
61}
62
63@end
64
65
66// rdar://8824416
67
68@interface MyNumber : NSObject
69{
70  NSNumber* _myNumber;
71}
72
73- (id)initWithNumber:(NSNumber *)number;
74
75@property (nonatomic, readonly) NSNumber* myNumber;
76@property (nonatomic, readonly) NSNumber* newMyNumber;
77
78@end
79
80@implementation MyNumber
81@synthesize myNumber=_myNumber;
82 
83- (id)initWithNumber:(NSNumber *)number
84{
85  self = [super init];
86  
87  if ( self )
88  {
89    _myNumber = [number copy];
90  }
91  
92  return self;
93}
94
95- (NSNumber*)newMyNumber
96{
97  if ( _myNumber )
98    return [_myNumber retain];
99  
100  return [[NSNumber alloc] initWithInteger:1];
101}
102
103- (id)valueForUndefinedKey:(NSString*)key
104{
105  id value = 0;
106  
107  if ([key isEqualToString:@"MyIvarNumberAsPropertyOverReleased"])
108    value = self.myNumber; // _myNumber will be over released, since the value returned from self.myNumber is not retained.
109  else if ([key isEqualToString:@"MyIvarNumberAsPropertyOk"])
110    value = [self.myNumber retain]; // this line fixes the over release
111  else if ([key isEqualToString:@"MyIvarNumberAsNewMyNumber"])
112    value = self.newMyNumber; // this one is ok, since value is returned retained
113  else 
114    value = [[NSNumber alloc] initWithInteger:0];
115  
116  return [value autorelease]; // expected-warning {{Object autoreleased too many times}}
117}
118
119@end
120
121NSNumber* numberFromMyNumberProperty(MyNumber* aMyNumber)
122{
123  NSNumber* result = aMyNumber.myNumber;
124    
125  return [result autorelease]; // expected-warning {{Object autoreleased too many times}}
126}
127
128#endif
129
130
131// rdar://6611873
132
133@interface Person : NSObject {
134  NSString *_name;
135}
136@property (retain) NSString * name;
137@property (assign) id friend;
138@end
139
140@implementation Person
141@synthesize name = _name;
142
143-(void)dealloc {
144#if !__has_feature(objc_arc)
145  self.name = [[NSString alloc] init]; // expected-warning {{leak}}
146
147  [super dealloc]; // expected-warning {{The '_name' ivar in 'Person' was retained by a synthesized property but not released before '[super dealloc]}}
148#endif
149}
150@end
151
152#if !__has_feature(objc_arc)
153void rdar6611873() {
154  Person *p = [[[Person alloc] init] autorelease];
155  
156  p.name = [[NSString string] retain]; // expected-warning {{leak}}
157  p.name = [[NSString alloc] init]; // expected-warning {{leak}}
158
159  p.friend = [[Person alloc] init]; // expected-warning {{leak}}
160}
161#endif
162
163@interface SubPerson : Person
164-(NSString *)foo;
165@end
166
167@implementation SubPerson
168-(NSString *)foo {
169  return super.name;
170}
171@end
172
173
174#if !__has_feature(objc_arc)
175// <rdar://problem/9241180> Static analyzer doesn't detect uninitialized variable issues for property accesses
176@interface RDar9241180
177@property (readwrite,assign) id x;
178-(id)testAnalyzer1:(int) y;
179-(void)testAnalyzer2;
180@end
181
182@implementation RDar9241180
183@synthesize x;
184-(id)testAnalyzer1:(int)y {
185    RDar9241180 *o;
186    if (y && o.x) // expected-warning {{Property access on an uninitialized object pointer}}
187      return o;
188    return o; // expected-warning {{Undefined or garbage value returned to caller}}
189}
190-(void)testAnalyzer2 {
191  id y;
192  self.x = y;  // expected-warning {{Argument for property setter is an uninitialized value}}
193}
194@end
195#endif
196
197
198//------
199// Property accessor synthesis
200//------
201
202extern void doSomethingWithPerson(Person *p);
203extern void doSomethingWithName(NSString *name);
204
205void testConsistencyRetain(Person *p) {
206  clang_analyzer_eval(p.name == p.name); // expected-warning{{TRUE}}
207
208  id origName = p.name;
209  clang_analyzer_eval(p.name == origName); // expected-warning{{TRUE}}
210  doSomethingWithPerson(p);
211  clang_analyzer_eval(p.name == origName); // expected-warning{{UNKNOWN}}
212}
213
214void testConsistencyAssign(Person *p) {
215  clang_analyzer_eval(p.friend == p.friend); // expected-warning{{TRUE}}
216
217  id origFriend = p.friend;
218  clang_analyzer_eval(p.friend == origFriend); // expected-warning{{TRUE}}
219  doSomethingWithPerson(p);
220  clang_analyzer_eval(p.friend == origFriend); // expected-warning{{UNKNOWN}}
221}
222
223@interface ClassWithShadowedReadWriteProperty {
224  int _f;
225}
226@property (readonly) int someProp;
227@end
228
229@interface ClassWithShadowedReadWriteProperty ()
230@property (readwrite) int someProp;
231@end
232
233@implementation ClassWithShadowedReadWriteProperty
234- (void)testSynthesisForShadowedReadWriteProperties; {
235  clang_analyzer_eval(self.someProp == self.someProp); // expected-warning{{TRUE}}
236
237  _f = 1;
238
239  // Read of shadowed property should not invalidate receiver.
240  (void)self.someProp;
241  clang_analyzer_eval(_f == 1); // expected-warning{{TRUE}}
242
243  _f = 2;
244  // Call to getter of shadowed property should not invalidate receiver.
245  (void)[self someProp];
246  clang_analyzer_eval(_f == 2); // expected-warning{{TRUE}}
247}
248@end
249
250// Tests for the analyzer fix that works around a Sema bug
251// where multiple methods are created for properties in class extensions that
252// are redeclared in a category method.
253// The Sema bug is tracked as <rdar://problem/25481164>.
254@interface ClassWithRedeclaredPropertyInExtensionFollowedByCategory
255@end
256
257@interface ClassWithRedeclaredPropertyInExtensionFollowedByCategory ()
258@end
259
260@interface ClassWithRedeclaredPropertyInExtensionFollowedByCategory ()
261@property (readwrite) int someProp;
262@property (readonly) int otherProp;
263@end
264
265@interface ClassWithRedeclaredPropertyInExtensionFollowedByCategory (MyCat)
266@property (readonly) int someProp;
267@property (readonly) int otherProp;
268@end
269
270@implementation ClassWithRedeclaredPropertyInExtensionFollowedByCategory
271- (void)testSynthesisForRedeclaredProperties; {
272  clang_analyzer_eval(self.someProp == self.someProp); // expected-warning{{TRUE}}
273  clang_analyzer_eval([self someProp] == self.someProp); // expected-warning{{TRUE}}
274
275  clang_analyzer_eval(self.otherProp == self.otherProp); // expected-warning{{TRUE}}
276  clang_analyzer_eval([self otherProp] == self.otherProp); // expected-warning{{TRUE}}
277}
278@end
279
280// The relative order of the extension and the category matter, so test both.
281@interface ClassWithRedeclaredPropertyInCategoryFollowedByExtension
282@end
283
284@interface ClassWithRedeclaredPropertyInCategoryFollowedByExtension ()
285@property (readwrite) int someProp;
286@end
287
288@interface ClassWithRedeclaredPropertyInCategoryFollowedByExtension (MyCat)
289@property (readonly) int someProp;
290@end
291
292@implementation ClassWithRedeclaredPropertyInCategoryFollowedByExtension
293- (void)testSynthesisForRedeclaredProperties; {
294  clang_analyzer_eval(self.someProp == self.someProp); // expected-warning{{TRUE}}
295  clang_analyzer_eval([self someProp] == self.someProp); // expected-warning{{TRUE}}
296}
297@end
298
299@interface ClassWithSynthesizedPropertyAndGetter
300@property (readonly) int someProp;
301@end
302
303@implementation ClassWithSynthesizedPropertyAndGetter
304@synthesize someProp;
305
306// Make sure that the actual getter is inlined and not a getter created
307// by BodyFarm
308- (void)testBodyFarmGetterNotUsed {
309  int i = self.someProp;
310  clang_analyzer_eval(i == 22); // expected-warning {{TRUE}}
311}
312
313-(int)someProp {
314  return 22;
315}
316@end
317
318//------
319// Setter ivar invalidation.
320//------
321
322@interface ClassWithSetters
323// Note: These properties have implicit @synthesize implementations to be
324// backed with ivars.
325@property (assign) int propWithIvar1;
326@property (assign) int propWithIvar2;
327
328@property (retain) NSNumber *retainedProperty;
329
330@end
331
332@interface ClassWithSetters (InOtherTranslationUnit)
333// The implementation of this property is in another translation unit.
334// We don't know whether it is backed by an ivar or not.
335@property (assign) int propInOther;
336@end
337
338@implementation ClassWithSetters
339- (void) testSettingPropWithIvarInvalidatesExactlyThatIvar; {
340  _propWithIvar1 = 1;
341  _propWithIvar2 = 2;
342  self.propWithIvar1 = 66;
343
344  // Calling the setter of a property backed by the instance variable
345  // should invalidate the storage for the instance variable but not
346  // the rest of the receiver. Ideally we would model the setter completely
347  // but doing so would cause the new value to escape when it is bound
348  // to the ivar. This would cause bad false negatives in the retain count
349  // checker. (There is a test for this scenario in
350  // testWriteRetainedValueToRetainedProperty below).
351  clang_analyzer_eval(_propWithIvar1 == 66); // expected-warning{{UNKNOWN}}
352  clang_analyzer_eval(_propWithIvar2 == 2);  // expected-warning{{TRUE}}
353
354  _propWithIvar1 = 1;
355  [self setPropWithIvar1:66];
356
357  clang_analyzer_eval(_propWithIvar1 == 66); // expected-warning{{UNKNOWN}}
358  clang_analyzer_eval(_propWithIvar2 == 2);  // expected-warning{{TRUE}}
359}
360
361- (void) testSettingPropWithoutIvarInvalidatesEntireInstance; {
362  _propWithIvar1 = 1;
363  _propWithIvar2 = 2;
364  self.propInOther = 66;
365
366  clang_analyzer_eval(_propWithIvar1 == 66); // expected-warning{{UNKNOWN}}
367  clang_analyzer_eval(_propWithIvar2 == 2);  // expected-warning{{UNKNOWN}}
368
369  _propWithIvar1 = 1;
370  _propWithIvar2 = 2;
371  [self setPropInOther:66];
372
373  clang_analyzer_eval(_propWithIvar1 == 66); // expected-warning{{UNKNOWN}}
374  clang_analyzer_eval(_propWithIvar2 == 2);  // expected-warning{{UNKNOWN}}
375}
376
377#if !__has_feature(objc_arc)
378- (void) testWriteRetainedValueToRetainedProperty; {
379  NSNumber *number = [[NSNumber alloc] initWithInteger:5]; // expected-warning {{Potential leak of an object stored into 'number'}}
380
381  // Make sure we catch this leak.
382  self.retainedProperty = number;
383}
384#endif
385@end
386
387//------
388// class properties
389//------
390
391int gBackingForReadWriteClassProp = 0;
392
393@interface ClassWithClassProperties
394@property(class, readonly) int readOnlyClassProp;
395
396@property(class) int readWriteClassProp;
397
398// Make sure we handle when a class and instance property have the same
399// name. Test both when instance comes first and when class comes first.
400@property(readonly) int classAndInstancePropWithSameNameOrderInstanceFirst;
401@property(class, readonly) int classAndInstancePropWithSameNameOrderInstanceFirst;
402
403@property(class, readonly) int classAndInstancePropWithSameNameOrderClassFirst;
404@property(readonly) int classAndInstancePropWithSameNameOrderClassFirst;
405
406
407@property(class, readonly) int dynamicClassProp;
408
409@end
410
411@interface ClassWithClassProperties (OtherTranslationUnit)
412@property(class, assign) id propInOtherTranslationUnit;
413@end
414
415@implementation ClassWithClassProperties
416
417@dynamic dynamicClassProp;
418
419+ (int)readOnlyClassProp {
420  return 1;
421}
422
423+ (int)readWriteClassProp {
424  return gBackingForReadWriteClassProp;
425}
426
427+ (void)setReadWriteClassProp:(int)val {
428  gBackingForReadWriteClassProp = val;
429}
430
431- (int)classAndInstancePropWithSameNameOrderInstanceFirst {
432  return 12;
433}
434
435+ (int)classAndInstancePropWithSameNameOrderInstanceFirst {
436  return 13;
437}
438
439+ (int)classAndInstancePropWithSameNameOrderClassFirst {
440  return 14;
441}
442
443- (int)classAndInstancePropWithSameNameOrderClassFirst {
444  return 15;
445}
446
447- (void)testInlineClassProp {
448  clang_analyzer_eval(ClassWithClassProperties.readOnlyClassProp == 1); // expected-warning{{TRUE}}
449
450  ClassWithClassProperties.readWriteClassProp = 7;
451  clang_analyzer_eval(ClassWithClassProperties.readWriteClassProp == 7); // expected-warning{{TRUE}}
452  ClassWithClassProperties.readWriteClassProp = 8;
453  clang_analyzer_eval(ClassWithClassProperties.readWriteClassProp == 8); // expected-warning{{TRUE}}
454}
455
456- (void)testUnknownClassProp {
457  clang_analyzer_eval(ClassWithClassProperties.propInOtherTranslationUnit == ClassWithClassProperties.propInOtherTranslationUnit); // expected-warning{{UNKNOWN}}
458}
459
460- (void)testEscapeGlobalOnUnknownProp {
461  gBackingForReadWriteClassProp = 33;
462  ClassWithClassProperties.propInOtherTranslationUnit = 0;
463  clang_analyzer_eval(gBackingForReadWriteClassProp == 33); // expected-warning{{UNKNOWN}}
464}
465
466- (void)testClassAndInstancePropertyWithSameName {
467  clang_analyzer_eval(self.classAndInstancePropWithSameNameOrderInstanceFirst == 12); // expected-warning{{TRUE}}
468  clang_analyzer_eval(ClassWithClassProperties.classAndInstancePropWithSameNameOrderInstanceFirst == 13); // expected-warning{{TRUE}}
469
470  clang_analyzer_eval(ClassWithClassProperties.classAndInstancePropWithSameNameOrderClassFirst == 14); // expected-warning{{TRUE}}
471  clang_analyzer_eval(self.classAndInstancePropWithSameNameOrderClassFirst == 15); // expected-warning{{TRUE}}
472}
473
474- (void)testDynamicClassProp {
475  clang_analyzer_eval(ClassWithClassProperties.dynamicClassProp == 16); // expected-warning{{UNKNOWN}}
476}
477
478@end
479
480@interface SubclassOfClassWithClassProperties : ClassWithClassProperties
481@end
482
483@implementation SubclassOfClassWithClassProperties
484+ (int)dynamicClassProp; {
485 return 16;
486}
487
488- (void)testDynamicClassProp {
489  clang_analyzer_eval(SubclassOfClassWithClassProperties.dynamicClassProp == 16); // expected-warning{{TRUE}}
490}
491
492@end
493
494
495#if !__has_feature(objc_arc)
496void testOverrelease(Person *p, int coin) {
497  switch (coin) {
498  case 0:
499    [p.name release]; // expected-warning{{not owned}}
500    break;
501  case 1:
502    [p.friend release]; // expected-warning{{not owned}}
503    break;
504  case 2: {
505    id friend = p.friend;
506    doSomethingWithPerson(p);
507    [friend release]; // expected-warning{{not owned}}
508  }
509  }
510}
511
512// <rdar://problem/16333368>
513@implementation Person (Rdar16333368)
514
515- (void)testDeliberateRelease:(Person *)other {
516  doSomethingWithName(self.name);
517  [_name release]; // no-warning
518  self->_name = 0;
519
520  doSomethingWithName(other->_name);
521  [other.name release]; // no-warning
522}
523
524- (void)deliberateReleaseFalseNegative {
525  // This is arguably a false negative because the result of p.friend shouldn't
526  // be released, even though we are manipulating the ivar in between the two
527  // actions.
528  id name = self.name;
529  _name = 0;
530  [name release];
531}
532
533- (void)testRetainAndRelease {
534  [self.name retain];
535  [self.name release];
536  [self.name release]; // expected-warning{{not owned}}
537}
538
539- (void)testRetainAndReleaseIVar {
540  [self.name retain];
541  [_name release];
542  [_name release];
543}
544
545@end
546#endif
547
548@interface IntWrapper
549@property int value;
550@end
551
552@implementation IntWrapper
553@synthesize value;
554@end
555
556void testConsistencyInt(IntWrapper *w) {
557  clang_analyzer_eval(w.value == w.value); // expected-warning{{TRUE}}
558
559  int origValue = w.value;
560  if (origValue != 42)
561    return;
562
563  clang_analyzer_eval(w.value == 42); // expected-warning{{TRUE}}
564}
565
566void testConsistencyInt2(IntWrapper *w) {
567  if (w.value != 42)
568    return;
569
570  clang_analyzer_eval(w.value == 42); // expected-warning{{TRUE}}
571}
572
573
574@interface IntWrapperAuto
575@property int value;
576@end
577
578@implementation IntWrapperAuto
579@end
580
581void testConsistencyIntAuto(IntWrapperAuto *w) {
582  clang_analyzer_eval(w.value == w.value); // expected-warning{{TRUE}}
583
584  int origValue = w.value;
585  if (origValue != 42)
586    return;
587
588  clang_analyzer_eval(w.value == 42); // expected-warning{{TRUE}}
589}
590
591void testConsistencyIntAuto2(IntWrapperAuto *w) {
592  if (w.value != 42)
593    return;
594
595  clang_analyzer_eval(w.value == 42); // expected-warning{{TRUE}}
596}
597
598
599typedef struct {
600  int value;
601} IntWrapperStruct;
602
603@interface StructWrapper
604@property IntWrapperStruct inner;
605@end
606
607@implementation StructWrapper
608@synthesize inner;
609@end
610
611void testConsistencyStruct(StructWrapper *w) {
612  clang_analyzer_eval(w.inner.value == w.inner.value); // expected-warning{{TRUE}}
613
614  int origValue = w.inner.value;
615  if (origValue != 42)
616    return;
617
618  clang_analyzer_eval(w.inner.value == 42); // expected-warning{{TRUE}}
619}
620
621
622@interface OpaqueIntWrapper
623@property int value;
624@end
625
626// For now, don't assume a property is implemented using an ivar unless we can
627// actually see that it is.
628void testOpaqueConsistency(OpaqueIntWrapper *w) {
629  clang_analyzer_eval(w.value == w.value); // expected-warning{{UNKNOWN}}
630}
631
632
633#if !__has_feature(objc_arc)
634// Test quite a few cases of retain/release issues.
635
636@interface RetainCountTesting
637@property (strong) id ownedProp;
638@property (unsafe_unretained) id unownedProp;
639@property (nonatomic, strong) id manualProp;
640@property (readonly) id readonlyProp;
641@property (nonatomic, readwrite/*, assign */) id implicitManualProp; // expected-warning {{'assign' is assumed}} expected-warning {{'assign' not appropriate}}
642@property (nonatomic, readwrite/*, assign */) id implicitSynthProp; // expected-warning {{'assign' is assumed}} expected-warning {{'assign' not appropriate}}
643@property CFTypeRef cfProp;
644@end
645
646@implementation RetainCountTesting {
647  id _ivarOnly;
648}
649
650- (id)manualProp {
651  return _manualProp;
652}
653
654- (void)setImplicitManualProp:(id)newValue {}
655
656- (void)testOverreleaseOwnedIvar {
657  [_ownedProp retain];
658  [_ownedProp release];
659  [_ownedProp release];
660  [_ownedProp release]; // FIXME-warning{{used after it is released}}
661}
662
663- (void)testOverreleaseUnownedIvar {
664  [_unownedProp retain];
665  [_unownedProp release];
666  [_unownedProp release]; // FIXME-warning{{not owned at this point by the caller}}
667}
668
669- (void)testOverreleaseIvarOnly {
670  [_ivarOnly retain];
671  [_ivarOnly release];
672  [_ivarOnly release];
673  [_ivarOnly release]; // FIXME-warning{{used after it is released}}
674}
675
676- (void)testOverreleaseReadonlyIvar {
677  [_readonlyProp retain];
678  [_readonlyProp release];
679  [_readonlyProp release];
680  [_readonlyProp release]; // FIXME-warning{{used after it is released}}
681}
682
683- (void)testOverreleaseImplicitManualIvar {
684  [_implicitManualProp retain];
685  [_implicitManualProp release];
686  [_implicitManualProp release];
687  [_implicitManualProp release]; // FIXME-warning{{used after it is released}}
688}
689
690- (void)testOverreleaseImplicitSynthIvar {
691  [_implicitSynthProp retain];
692  [_implicitSynthProp release];
693  [_implicitSynthProp release]; // FIXME-warning{{not owned at this point by the caller}}
694}
695
696- (void)testOverreleaseCF {
697  CFRetain(_cfProp);
698  CFRelease(_cfProp);
699  CFRelease(_cfProp);
700  CFRelease(_cfProp); // FIXME-warning{{used after it is released}}
701}
702
703- (void)testOverreleaseOwnedIvarUse {
704  [_ownedProp retain];
705  [_ownedProp release];
706  [_ownedProp release];
707  [_ownedProp myMethod]; // FIXME-warning{{used after it is released}}
708}
709
710- (void)testOverreleaseIvarOnlyUse {
711  [_ivarOnly retain];
712  [_ivarOnly release];
713  [_ivarOnly release];
714  [_ivarOnly myMethod]; // FIXME-warning{{used after it is released}}
715}
716
717- (void)testOverreleaseCFUse {
718  CFRetain(_cfProp);
719  CFRelease(_cfProp);
720  CFRelease(_cfProp);
721
722  extern void CFUse(CFTypeRef);
723  CFUse(_cfProp); // FIXME-warning{{used after it is released}}
724}
725
726- (void)testOverreleaseOwnedIvarAutoreleaseOkay {
727  [_ownedProp retain];
728  [_ownedProp release];
729  [_ownedProp autorelease];
730} // no-warning
731
732- (void)testOverreleaseIvarOnlyAutoreleaseOkay {
733  [_ivarOnly retain];
734  [_ivarOnly release];
735  [_ivarOnly autorelease];
736} // no-warning
737
738- (void)testOverreleaseOwnedIvarAutorelease {
739  [_ownedProp retain];
740  [_ownedProp release];
741  [_ownedProp autorelease];
742  [_ownedProp autorelease];
743} // FIXME-warning{{Object autoreleased too many times}}
744
745- (void)testOverreleaseIvarOnlyAutorelease {
746  [_ivarOnly retain];
747  [_ivarOnly release];
748  [_ivarOnly autorelease];
749  [_ivarOnly autorelease];
750} // FIXME-warning{{Object autoreleased too many times}}
751
752- (void)testPropertyAccessThenReleaseOwned {
753  id owned = [self.ownedProp retain];
754  [owned release];
755  [_ownedProp release];
756  clang_analyzer_eval(owned == _ownedProp); // expected-warning{{TRUE}}
757}
758
759- (void)testPropertyAccessThenReleaseOwned2 {
760  id fromIvar = _ownedProp;
761  id owned = [self.ownedProp retain];
762  [owned release];
763  [fromIvar release];
764  clang_analyzer_eval(owned == fromIvar); // expected-warning{{TRUE}}
765}
766
767- (void)testPropertyAccessThenReleaseUnowned {
768  id unowned = [self.unownedProp retain];
769  [unowned release];
770  [_unownedProp release]; // FIXME-warning{{not owned}}
771}
772
773- (void)testPropertyAccessThenReleaseUnowned2 {
774  id fromIvar = _unownedProp;
775  id unowned = [self.unownedProp retain];
776  [unowned release];
777  clang_analyzer_eval(unowned == fromIvar); // expected-warning{{TRUE}}
778  [fromIvar release]; // FIXME-warning{{not owned}}
779}
780
781- (void)testPropertyAccessThenReleaseManual {
782  id prop = [self.manualProp retain];
783  [prop release];
784  [_manualProp release]; // no-warning
785}
786
787- (void)testPropertyAccessThenReleaseManual2 {
788  id fromIvar = _manualProp;
789  id prop = [self.manualProp retain];
790  [prop release];
791  clang_analyzer_eval(prop == fromIvar); // expected-warning{{TRUE}}
792  [fromIvar release]; // no-warning
793}
794
795- (void)testPropertyAccessThenReleaseCF {
796  CFTypeRef owned = CFRetain(self.cfProp);
797  CFRelease(owned);
798  CFRelease(_cfProp); // no-warning
799  clang_analyzer_eval(owned == _cfProp); // expected-warning{{TRUE}}
800}
801
802- (void)testPropertyAccessThenReleaseCF2 {
803  CFTypeRef fromIvar = _cfProp;
804  CFTypeRef owned = CFRetain(self.cfProp);
805  CFRelease(owned);
806  CFRelease(fromIvar);
807  clang_analyzer_eval(owned == fromIvar); // expected-warning{{TRUE}}
808}
809
810- (void)testPropertyAccessThenReleaseReadonly {
811  id prop = [self.readonlyProp retain];
812  [prop release];
813  [_readonlyProp release]; // no-warning
814}
815
816- (void)testPropertyAccessThenReleaseReadonly2 {
817  id fromIvar = _readonlyProp;
818  id prop = [self.readonlyProp retain];
819  [prop release];
820  clang_analyzer_eval(prop == fromIvar); // expected-warning{{TRUE}}
821  [fromIvar release]; // no-warning
822}
823
824- (void)testPropertyAccessThenReleaseImplicitManual {
825  id prop = [self.implicitManualProp retain];
826  [prop release];
827  [_implicitManualProp release]; // no-warning
828}
829
830- (void)testPropertyAccessThenReleaseImplicitManual2 {
831  id fromIvar = _implicitManualProp;
832  id prop = [self.implicitManualProp retain];
833  [prop release];
834  clang_analyzer_eval(prop == fromIvar); // expected-warning{{TRUE}}
835  [fromIvar release]; // no-warning
836}
837
838- (void)testPropertyAccessThenReleaseImplicitSynth {
839  id prop = [self.implicitSynthProp retain];
840  [prop release];
841  [_implicitSynthProp release]; // FIXME-warning{{not owned}}
842}
843
844- (void)testPropertyAccessThenReleaseImplicitSynth2 {
845  id fromIvar = _implicitSynthProp;
846  id prop = [self.implicitSynthProp retain];
847  [prop release];
848  clang_analyzer_eval(prop == fromIvar); // expected-warning{{TRUE}}
849  [fromIvar release]; // FIXME-warning{{not owned}}
850}
851
852- (id)getUnownedFromProperty {
853  [_ownedProp retain];
854  [_ownedProp autorelease];
855  return _ownedProp; // no-warning
856}
857
858- (id)transferUnownedFromProperty {
859  [_ownedProp retain];
860  [_ownedProp autorelease];
861  return [_ownedProp autorelease]; // no-warning
862}
863
864- (id)transferOwnedFromProperty __attribute__((ns_returns_retained)) {
865  [_ownedProp retain];
866  [_ownedProp autorelease];
867  return _ownedProp; // no-warning
868}
869
870- (void)testAssignOwned:(id)newValue {
871  _ownedProp = newValue;
872  [_ownedProp release]; // FIXME: no-warning{{not owned}}
873}
874
875- (void)testAssignUnowned:(id)newValue {
876  _unownedProp = newValue;
877  [_unownedProp release]; // FIXME: no-warning{{not owned}}
878}
879
880- (void)testAssignIvarOnly:(id)newValue {
881  _ivarOnly = newValue;
882  [_ivarOnly release]; // FIXME: no-warning{{not owned}}
883}
884
885- (void)testAssignCF:(CFTypeRef)newValue {
886  _cfProp = newValue;
887  CFRelease(_cfProp); // FIXME: no-warning{{not owned}}
888}
889
890- (void)testAssignReadonly:(id)newValue {
891  _readonlyProp = newValue;
892  [_readonlyProp release]; // FIXME: no-warning{{not owned}}
893}
894
895- (void)testAssignImplicitManual:(id)newValue {
896  _implicitManualProp = newValue;
897  [_implicitManualProp release]; // FIXME: no-warning{{not owned}}
898}
899
900- (void)testAssignImplicitSynth:(id)newValue {
901  _implicitSynthProp = newValue;
902  [_implicitSynthProp release]; // FIXME: no-warning{{not owned}}
903}
904
905- (void)testAssignOwnedOkay:(id)newValue {
906  _ownedProp = [newValue retain];
907  [_ownedProp release]; // no-warning
908}
909
910- (void)testAssignUnownedOkay:(id)newValue {
911  _unownedProp = [newValue retain];
912  [_unownedProp release]; // no-warning
913}
914
915- (void)testAssignIvarOnlyOkay:(id)newValue {
916  _ivarOnly = [newValue retain];
917  [_ivarOnly release]; // no-warning
918}
919
920- (void)testAssignCFOkay:(CFTypeRef)newValue {
921  _cfProp = CFRetain(newValue);
922  CFRelease(_cfProp); // no-warning
923}
924
925- (void)testAssignReadonlyOkay:(id)newValue {
926  _readonlyProp = [newValue retain];
927  [_readonlyProp release]; // FIXME: no-warning{{not owned}}
928}
929
930- (void)testAssignImplicitManualOkay:(id)newValue {
931  _implicitManualProp = [newValue retain];
932  [_implicitManualProp release]; // FIXME: no-warning{{not owned}}
933}
934
935- (void)testAssignImplicitSynthOkay:(id)newValue {
936  _implicitSynthProp = [newValue retain];
937  [_implicitSynthProp release]; // FIXME: no-warning{{not owned}}
938}
939
940// rdar://problem/19862648
941- (void)establishIvarIsNilDuringLoops {
942  extern id getRandomObject();
943
944  int i = 4; // Must be at least 4 to trigger the bug.
945  while (--i) {
946    id x = 0;
947    if (getRandomObject())
948      x = _ivarOnly;
949    if (!x)
950      x = getRandomObject();
951    [x myMethod];
952  }
953}
954
955// rdar://problem/20335433
956- (void)retainIvarAndInvalidateSelf {
957  extern void invalidate(id);
958  [_unownedProp retain];
959  invalidate(self);
960  [_unownedProp release]; // no-warning
961}
962
963@end
964#endif // non-ARC
965
966