Clang Project

clang_source_code/test/Analysis/properties.m
1// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.RetainCount,osx.cocoa.Dealloc,debug.ExprInspection -analyzer-store=region -verify -Wno-objc-root-class -analyzer-config eagerly-assume=false %s
2// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.RetainCount,osx.cocoa.Dealloc,debug.ExprInspection -analyzer-store=region -verify -Wno-objc-root-class -fobjc-arc -analyzer-config eagerly-assume=false %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__attribute__((objc_root_class))
319@interface ClassWithPrivatePropertyInClassExtensionWithProtocolShadowingCategory
320@end
321
322@protocol HasStuff
323@property (nonatomic, readonly) int stuffProperty;
324@end
325
326@interface ClassWithPrivatePropertyInClassExtensionWithProtocolShadowingCategory (Private)
327@property (nonatomic, readonly) int stuffProperty;
328@end
329
330@interface ClassWithPrivatePropertyInClassExtensionWithProtocolShadowingCategory (Internal) <HasStuff>
331@end
332
333@interface ClassWithPrivatePropertyInClassExtensionWithProtocolShadowingCategory() <HasStuff>
334@end
335
336@implementation ClassWithPrivatePropertyInClassExtensionWithProtocolShadowingCategory
337@synthesize stuffProperty = _stuffProperty;
338
339-(void)foo {
340  (void)self.stuffProperty;
341}
342@end
343
344//------
345// Setter ivar invalidation.
346//------
347
348@interface ClassWithSetters
349// Note: These properties have implicit @synthesize implementations to be
350// backed with ivars.
351@property (assign) int propWithIvar1;
352@property (assign) int propWithIvar2;
353
354@property (retain) NSNumber *retainedProperty;
355
356@end
357
358@interface ClassWithSetters (InOtherTranslationUnit)
359// The implementation of this property is in another translation unit.
360// We don't know whether it is backed by an ivar or not.
361@property (assign) int propInOther;
362@end
363
364@implementation ClassWithSetters
365- (void) testSettingPropWithIvarInvalidatesExactlyThatIvar; {
366  _propWithIvar1 = 1;
367  _propWithIvar2 = 2;
368  self.propWithIvar1 = 66;
369
370  // Calling the setter of a property backed by the instance variable
371  // should invalidate the storage for the instance variable but not
372  // the rest of the receiver. Ideally we would model the setter completely
373  // but doing so would cause the new value to escape when it is bound
374  // to the ivar. This would cause bad false negatives in the retain count
375  // checker. (There is a test for this scenario in
376  // testWriteRetainedValueToRetainedProperty below).
377  clang_analyzer_eval(_propWithIvar1 == 66); // expected-warning{{UNKNOWN}}
378  clang_analyzer_eval(_propWithIvar2 == 2);  // expected-warning{{TRUE}}
379
380  _propWithIvar1 = 1;
381  [self setPropWithIvar1:66];
382
383  clang_analyzer_eval(_propWithIvar1 == 66); // expected-warning{{UNKNOWN}}
384  clang_analyzer_eval(_propWithIvar2 == 2);  // expected-warning{{TRUE}}
385}
386
387- (void) testSettingPropWithoutIvarInvalidatesEntireInstance; {
388  _propWithIvar1 = 1;
389  _propWithIvar2 = 2;
390  self.propInOther = 66;
391
392  clang_analyzer_eval(_propWithIvar1 == 66); // expected-warning{{UNKNOWN}}
393  clang_analyzer_eval(_propWithIvar2 == 2);  // expected-warning{{UNKNOWN}}
394
395  _propWithIvar1 = 1;
396  _propWithIvar2 = 2;
397  [self setPropInOther:66];
398
399  clang_analyzer_eval(_propWithIvar1 == 66); // expected-warning{{UNKNOWN}}
400  clang_analyzer_eval(_propWithIvar2 == 2);  // expected-warning{{UNKNOWN}}
401}
402
403#if !__has_feature(objc_arc)
404- (void) testWriteRetainedValueToRetainedProperty; {
405  NSNumber *number = [[NSNumber alloc] initWithInteger:5]; // expected-warning {{Potential leak of an object stored into 'number'}}
406
407  // Make sure we catch this leak.
408  self.retainedProperty = number;
409}
410#endif
411@end
412
413//------
414// class properties
415//------
416
417int gBackingForReadWriteClassProp = 0;
418
419@interface ClassWithClassProperties
420@property(class, readonly) int readOnlyClassProp;
421
422@property(class) int readWriteClassProp;
423
424// Make sure we handle when a class and instance property have the same
425// name. Test both when instance comes first and when class comes first.
426@property(readonly) int classAndInstancePropWithSameNameOrderInstanceFirst;
427@property(class, readonly) int classAndInstancePropWithSameNameOrderInstanceFirst;
428
429@property(class, readonly) int classAndInstancePropWithSameNameOrderClassFirst;
430@property(readonly) int classAndInstancePropWithSameNameOrderClassFirst;
431
432
433@property(class, readonly) int dynamicClassProp;
434
435@end
436
437@interface ClassWithClassProperties (OtherTranslationUnit)
438@property(class, assign) id propInOtherTranslationUnit;
439@end
440
441@implementation ClassWithClassProperties
442
443@dynamic dynamicClassProp;
444
445+ (int)readOnlyClassProp {
446  return 1;
447}
448
449+ (int)readWriteClassProp {
450  return gBackingForReadWriteClassProp;
451}
452
453+ (void)setReadWriteClassProp:(int)val {
454  gBackingForReadWriteClassProp = val;
455}
456
457- (int)classAndInstancePropWithSameNameOrderInstanceFirst {
458  return 12;
459}
460
461+ (int)classAndInstancePropWithSameNameOrderInstanceFirst {
462  return 13;
463}
464
465+ (int)classAndInstancePropWithSameNameOrderClassFirst {
466  return 14;
467}
468
469- (int)classAndInstancePropWithSameNameOrderClassFirst {
470  return 15;
471}
472
473- (void)testInlineClassProp {
474  clang_analyzer_eval(ClassWithClassProperties.readOnlyClassProp == 1); // expected-warning{{TRUE}}
475
476  ClassWithClassProperties.readWriteClassProp = 7;
477  clang_analyzer_eval(ClassWithClassProperties.readWriteClassProp == 7); // expected-warning{{TRUE}}
478  ClassWithClassProperties.readWriteClassProp = 8;
479  clang_analyzer_eval(ClassWithClassProperties.readWriteClassProp == 8); // expected-warning{{TRUE}}
480}
481
482- (void)testUnknownClassProp {
483  clang_analyzer_eval(ClassWithClassProperties.propInOtherTranslationUnit == ClassWithClassProperties.propInOtherTranslationUnit); // expected-warning{{UNKNOWN}}
484}
485
486- (void)testEscapeGlobalOnUnknownProp {
487  gBackingForReadWriteClassProp = 33;
488  ClassWithClassProperties.propInOtherTranslationUnit = 0;
489  clang_analyzer_eval(gBackingForReadWriteClassProp == 33); // expected-warning{{UNKNOWN}}
490}
491
492- (void)testClassAndInstancePropertyWithSameName {
493  clang_analyzer_eval(self.classAndInstancePropWithSameNameOrderInstanceFirst == 12); // expected-warning{{TRUE}}
494  clang_analyzer_eval(ClassWithClassProperties.classAndInstancePropWithSameNameOrderInstanceFirst == 13); // expected-warning{{TRUE}}
495
496  clang_analyzer_eval(ClassWithClassProperties.classAndInstancePropWithSameNameOrderClassFirst == 14); // expected-warning{{TRUE}}
497  clang_analyzer_eval(self.classAndInstancePropWithSameNameOrderClassFirst == 15); // expected-warning{{TRUE}}
498}
499
500- (void)testDynamicClassProp {
501  clang_analyzer_eval(ClassWithClassProperties.dynamicClassProp == 16); // expected-warning{{UNKNOWN}}
502}
503
504@end
505
506@interface SubclassOfClassWithClassProperties : ClassWithClassProperties
507@end
508
509@implementation SubclassOfClassWithClassProperties
510+ (int)dynamicClassProp; {
511 return 16;
512}
513
514- (void)testDynamicClassProp {
515  clang_analyzer_eval(SubclassOfClassWithClassProperties.dynamicClassProp == 16); // expected-warning{{TRUE}}
516}
517
518@end
519
520
521#if !__has_feature(objc_arc)
522void testOverrelease(Person *p, int coin) {
523  switch (coin) {
524  case 0:
525    [p.name release]; // expected-warning{{not owned}}
526    break;
527  case 1:
528    [p.friend release]; // expected-warning{{not owned}}
529    break;
530  case 2: {
531    id friend = p.friend;
532    doSomethingWithPerson(p);
533    [friend release]; // expected-warning{{not owned}}
534  }
535  }
536}
537
538// <rdar://problem/16333368>
539@implementation Person (Rdar16333368)
540
541- (void)testDeliberateRelease:(Person *)other {
542  doSomethingWithName(self.name);
543  [_name release]; // no-warning
544  self->_name = 0;
545
546  doSomethingWithName(other->_name);
547  [other.name release]; // no-warning
548}
549
550- (void)deliberateReleaseFalseNegative {
551  // This is arguably a false negative because the result of p.friend shouldn't
552  // be released, even though we are manipulating the ivar in between the two
553  // actions.
554  id name = self.name;
555  _name = 0;
556  [name release];
557}
558
559- (void)testRetainAndRelease {
560  [self.name retain];
561  [self.name release];
562  [self.name release]; // expected-warning{{not owned}}
563}
564
565- (void)testRetainAndReleaseIVar {
566  [self.name retain];
567  [_name release];
568  [_name release];
569}
570
571@end
572#endif
573
574@interface IntWrapper
575@property int value;
576@end
577
578@implementation IntWrapper
579@synthesize value;
580@end
581
582void testConsistencyInt(IntWrapper *w) {
583  clang_analyzer_eval(w.value == w.value); // expected-warning{{TRUE}}
584
585  int origValue = w.value;
586  if (origValue != 42)
587    return;
588
589  clang_analyzer_eval(w.value == 42); // expected-warning{{TRUE}}
590}
591
592void testConsistencyInt2(IntWrapper *w) {
593  if (w.value != 42)
594    return;
595
596  clang_analyzer_eval(w.value == 42); // expected-warning{{TRUE}}
597}
598
599
600@interface IntWrapperAuto
601@property int value;
602@end
603
604@implementation IntWrapperAuto
605@end
606
607void testConsistencyIntAuto(IntWrapperAuto *w) {
608  clang_analyzer_eval(w.value == w.value); // expected-warning{{TRUE}}
609
610  int origValue = w.value;
611  if (origValue != 42)
612    return;
613
614  clang_analyzer_eval(w.value == 42); // expected-warning{{TRUE}}
615}
616
617void testConsistencyIntAuto2(IntWrapperAuto *w) {
618  if (w.value != 42)
619    return;
620
621  clang_analyzer_eval(w.value == 42); // expected-warning{{TRUE}}
622}
623
624
625typedef struct {
626  int value;
627} IntWrapperStruct;
628
629@interface StructWrapper
630@property IntWrapperStruct inner;
631@end
632
633@implementation StructWrapper
634@synthesize inner;
635@end
636
637void testConsistencyStruct(StructWrapper *w) {
638  clang_analyzer_eval(w.inner.value == w.inner.value); // expected-warning{{TRUE}}
639
640  int origValue = w.inner.value;
641  if (origValue != 42)
642    return;
643
644  clang_analyzer_eval(w.inner.value == 42); // expected-warning{{TRUE}}
645}
646
647
648@interface OpaqueIntWrapper
649@property int value;
650@end
651
652// For now, don't assume a property is implemented using an ivar unless we can
653// actually see that it is.
654void testOpaqueConsistency(OpaqueIntWrapper *w) {
655  clang_analyzer_eval(w.value == w.value); // expected-warning{{UNKNOWN}}
656}
657
658
659#if !__has_feature(objc_arc)
660// Test quite a few cases of retain/release issues.
661
662@interface RetainCountTesting
663@property (strong) id ownedProp;
664@property (unsafe_unretained) id unownedProp;
665@property (nonatomic, strong) id manualProp;
666@property (readonly) id readonlyProp;
667@property (nonatomic, readwrite/*, assign */) id implicitManualProp; // expected-warning {{'assign' is assumed}} expected-warning {{'assign' not appropriate}}
668@property (nonatomic, readwrite/*, assign */) id implicitSynthProp; // expected-warning {{'assign' is assumed}} expected-warning {{'assign' not appropriate}}
669@property CFTypeRef cfProp;
670@end
671
672@implementation RetainCountTesting {
673  id _ivarOnly;
674}
675
676- (id)manualProp {
677  return _manualProp;
678}
679
680- (void)setImplicitManualProp:(id)newValue {}
681
682- (void)testOverreleaseOwnedIvar {
683  [_ownedProp retain];
684  [_ownedProp release];
685  [_ownedProp release];
686  [_ownedProp release]; // FIXME-warning{{used after it is released}}
687}
688
689- (void)testOverreleaseUnownedIvar {
690  [_unownedProp retain];
691  [_unownedProp release];
692  [_unownedProp release]; // FIXME-warning{{not owned at this point by the caller}}
693}
694
695- (void)testOverreleaseIvarOnly {
696  [_ivarOnly retain];
697  [_ivarOnly release];
698  [_ivarOnly release];
699  [_ivarOnly release]; // FIXME-warning{{used after it is released}}
700}
701
702- (void)testOverreleaseReadonlyIvar {
703  [_readonlyProp retain];
704  [_readonlyProp release];
705  [_readonlyProp release];
706  [_readonlyProp release]; // FIXME-warning{{used after it is released}}
707}
708
709- (void)testOverreleaseImplicitManualIvar {
710  [_implicitManualProp retain];
711  [_implicitManualProp release];
712  [_implicitManualProp release];
713  [_implicitManualProp release]; // FIXME-warning{{used after it is released}}
714}
715
716- (void)testOverreleaseImplicitSynthIvar {
717  [_implicitSynthProp retain];
718  [_implicitSynthProp release];
719  [_implicitSynthProp release]; // FIXME-warning{{not owned at this point by the caller}}
720}
721
722- (void)testOverreleaseCF {
723  CFRetain(_cfProp);
724  CFRelease(_cfProp);
725  CFRelease(_cfProp);
726  CFRelease(_cfProp); // FIXME-warning{{used after it is released}}
727}
728
729- (void)testOverreleaseOwnedIvarUse {
730  [_ownedProp retain];
731  [_ownedProp release];
732  [_ownedProp release];
733  [_ownedProp myMethod]; // FIXME-warning{{used after it is released}}
734}
735
736- (void)testOverreleaseIvarOnlyUse {
737  [_ivarOnly retain];
738  [_ivarOnly release];
739  [_ivarOnly release];
740  [_ivarOnly myMethod]; // FIXME-warning{{used after it is released}}
741}
742
743- (void)testOverreleaseCFUse {
744  CFRetain(_cfProp);
745  CFRelease(_cfProp);
746  CFRelease(_cfProp);
747
748  extern void CFUse(CFTypeRef);
749  CFUse(_cfProp); // FIXME-warning{{used after it is released}}
750}
751
752- (void)testOverreleaseOwnedIvarAutoreleaseOkay {
753  [_ownedProp retain];
754  [_ownedProp release];
755  [_ownedProp autorelease];
756} // no-warning
757
758- (void)testOverreleaseIvarOnlyAutoreleaseOkay {
759  [_ivarOnly retain];
760  [_ivarOnly release];
761  [_ivarOnly autorelease];
762} // no-warning
763
764- (void)testOverreleaseOwnedIvarAutorelease {
765  [_ownedProp retain];
766  [_ownedProp release];
767  [_ownedProp autorelease];
768  [_ownedProp autorelease];
769} // FIXME-warning{{Object autoreleased too many times}}
770
771- (void)testOverreleaseIvarOnlyAutorelease {
772  [_ivarOnly retain];
773  [_ivarOnly release];
774  [_ivarOnly autorelease];
775  [_ivarOnly autorelease];
776} // FIXME-warning{{Object autoreleased too many times}}
777
778- (void)testPropertyAccessThenReleaseOwned {
779  id owned = [self.ownedProp retain];
780  [owned release];
781  [_ownedProp release];
782  clang_analyzer_eval(owned == _ownedProp); // expected-warning{{TRUE}}
783}
784
785- (void)testPropertyAccessThenReleaseOwned2 {
786  id fromIvar = _ownedProp;
787  id owned = [self.ownedProp retain];
788  [owned release];
789  [fromIvar release];
790  clang_analyzer_eval(owned == fromIvar); // expected-warning{{TRUE}}
791}
792
793- (void)testPropertyAccessThenReleaseUnowned {
794  id unowned = [self.unownedProp retain];
795  [unowned release];
796  [_unownedProp release]; // FIXME-warning{{not owned}}
797}
798
799- (void)testPropertyAccessThenReleaseUnowned2 {
800  id fromIvar = _unownedProp;
801  id unowned = [self.unownedProp retain];
802  [unowned release];
803  clang_analyzer_eval(unowned == fromIvar); // expected-warning{{TRUE}}
804  [fromIvar release]; // FIXME-warning{{not owned}}
805}
806
807- (void)testPropertyAccessThenReleaseManual {
808  id prop = [self.manualProp retain];
809  [prop release];
810  [_manualProp release]; // no-warning
811}
812
813- (void)testPropertyAccessThenReleaseManual2 {
814  id fromIvar = _manualProp;
815  id prop = [self.manualProp retain];
816  [prop release];
817  clang_analyzer_eval(prop == fromIvar); // expected-warning{{TRUE}}
818  [fromIvar release]; // no-warning
819}
820
821- (void)testPropertyAccessThenReleaseCF {
822  CFTypeRef owned = CFRetain(self.cfProp);
823  CFRelease(owned);
824  CFRelease(_cfProp); // no-warning
825  clang_analyzer_eval(owned == _cfProp); // expected-warning{{TRUE}}
826}
827
828- (void)testPropertyAccessThenReleaseCF2 {
829  CFTypeRef fromIvar = _cfProp;
830  CFTypeRef owned = CFRetain(self.cfProp);
831  CFRelease(owned);
832  CFRelease(fromIvar);
833  clang_analyzer_eval(owned == fromIvar); // expected-warning{{TRUE}}
834}
835
836- (void)testPropertyAccessThenReleaseReadonly {
837  id prop = [self.readonlyProp retain];
838  [prop release];
839  [_readonlyProp release]; // no-warning
840}
841
842- (void)testPropertyAccessThenReleaseReadonly2 {
843  id fromIvar = _readonlyProp;
844  id prop = [self.readonlyProp retain];
845  [prop release];
846  clang_analyzer_eval(prop == fromIvar); // expected-warning{{TRUE}}
847  [fromIvar release]; // no-warning
848}
849
850- (void)testPropertyAccessThenReleaseImplicitManual {
851  id prop = [self.implicitManualProp retain];
852  [prop release];
853  [_implicitManualProp release]; // no-warning
854}
855
856- (void)testPropertyAccessThenReleaseImplicitManual2 {
857  id fromIvar = _implicitManualProp;
858  id prop = [self.implicitManualProp retain];
859  [prop release];
860  clang_analyzer_eval(prop == fromIvar); // expected-warning{{TRUE}}
861  [fromIvar release]; // no-warning
862}
863
864- (void)testPropertyAccessThenReleaseImplicitSynth {
865  id prop = [self.implicitSynthProp retain];
866  [prop release];
867  [_implicitSynthProp release]; // FIXME-warning{{not owned}}
868}
869
870- (void)testPropertyAccessThenReleaseImplicitSynth2 {
871  id fromIvar = _implicitSynthProp;
872  id prop = [self.implicitSynthProp retain];
873  [prop release];
874  clang_analyzer_eval(prop == fromIvar); // expected-warning{{TRUE}}
875  [fromIvar release]; // FIXME-warning{{not owned}}
876}
877
878- (id)getUnownedFromProperty {
879  [_ownedProp retain];
880  [_ownedProp autorelease];
881  return _ownedProp; // no-warning
882}
883
884- (id)transferUnownedFromProperty {
885  [_ownedProp retain];
886  [_ownedProp autorelease];
887  return [_ownedProp autorelease]; // no-warning
888}
889
890- (id)transferOwnedFromProperty __attribute__((ns_returns_retained)) {
891  [_ownedProp retain];
892  [_ownedProp autorelease];
893  return _ownedProp; // no-warning
894}
895
896- (void)testAssignOwned:(id)newValue {
897  _ownedProp = newValue;
898  [_ownedProp release]; // FIXME: no-warning{{not owned}}
899}
900
901- (void)testAssignUnowned:(id)newValue {
902  _unownedProp = newValue;
903  [_unownedProp release]; // FIXME: no-warning{{not owned}}
904}
905
906- (void)testAssignIvarOnly:(id)newValue {
907  _ivarOnly = newValue;
908  [_ivarOnly release]; // FIXME: no-warning{{not owned}}
909}
910
911- (void)testAssignCF:(CFTypeRef)newValue {
912  _cfProp = newValue;
913  CFRelease(_cfProp); // FIXME: no-warning{{not owned}}
914}
915
916- (void)testAssignReadonly:(id)newValue {
917  _readonlyProp = newValue;
918  [_readonlyProp release]; // FIXME: no-warning{{not owned}}
919}
920
921- (void)testAssignImplicitManual:(id)newValue {
922  _implicitManualProp = newValue;
923  [_implicitManualProp release]; // FIXME: no-warning{{not owned}}
924}
925
926- (void)testAssignImplicitSynth:(id)newValue {
927  _implicitSynthProp = newValue;
928  [_implicitSynthProp release]; // FIXME: no-warning{{not owned}}
929}
930
931- (void)testAssignOwnedOkay:(id)newValue {
932  _ownedProp = [newValue retain];
933  [_ownedProp release]; // no-warning
934}
935
936- (void)testAssignUnownedOkay:(id)newValue {
937  _unownedProp = [newValue retain];
938  [_unownedProp release]; // no-warning
939}
940
941- (void)testAssignIvarOnlyOkay:(id)newValue {
942  _ivarOnly = [newValue retain];
943  [_ivarOnly release]; // no-warning
944}
945
946- (void)testAssignCFOkay:(CFTypeRef)newValue {
947  _cfProp = CFRetain(newValue);
948  CFRelease(_cfProp); // no-warning
949}
950
951- (void)testAssignReadonlyOkay:(id)newValue {
952  _readonlyProp = [newValue retain];
953  [_readonlyProp release]; // FIXME: no-warning{{not owned}}
954}
955
956- (void)testAssignImplicitManualOkay:(id)newValue {
957  _implicitManualProp = [newValue retain];
958  [_implicitManualProp release]; // FIXME: no-warning{{not owned}}
959}
960
961- (void)testAssignImplicitSynthOkay:(id)newValue {
962  _implicitSynthProp = [newValue retain];
963  [_implicitSynthProp release]; // FIXME: no-warning{{not owned}}
964}
965
966// rdar://problem/19862648
967- (void)establishIvarIsNilDuringLoops {
968  extern id getRandomObject();
969
970  int i = 4; // Must be at least 4 to trigger the bug.
971  while (--i) {
972    id x = 0;
973    if (getRandomObject())
974      x = _ivarOnly;
975    if (!x)
976      x = getRandomObject();
977    [x myMethod];
978  }
979}
980
981// rdar://problem/20335433
982- (void)retainIvarAndInvalidateSelf {
983  extern void invalidate(id);
984  [_unownedProp retain];
985  invalidate(self);
986  [_unownedProp release]; // no-warning
987}
988
989@end
990
991@interface Wrapper
992@property(nonatomic, readonly) int value;
993@end
994
995@implementation Wrapper
996@synthesize value;
997@end
998
999void testNoCrashWhenAccessPropertyAndThereAreNoDirectBindingsAtAll() {
1000   union {
1001    Wrapper *wrapper;
1002   } u = { 0 };
1003   [u.wrapper value];
1004}
1005
1006#endif // non-ARC
1007
1008@interface ExplicitAccessorInCategory : NSObject
1009@property(readonly) int normal;
1010- (int)normal;
1011@property(readonly) int no_custom_accessor;
1012@end
1013
1014@interface ExplicitAccessorInCategory ()
1015@property(readonly) int in_category;
1016
1017@property(readonly) int still_no_custom_accessor;
1018// This is an ordinary method, not a getter.
1019- (int)still_no_custom_accessor;
1020@end
1021
1022@interface ExplicitAccessorInCategory ()
1023- (int)in_category;
1024
1025// This is an ordinary method, not a getter.
1026- (int)no_custom_accessor;
1027@end
1028
1029@implementation ExplicitAccessorInCategory
1030- (void)foo {
1031 // Make sure we don't farm bodies for explicit accessors: in particular,
1032 // we're not sure that the accessor always returns the same value.
1033 clang_analyzer_eval(self.normal == self.normal); // expected-warning{{UNKNOWN}}
1034 // Also this used to crash.
1035 clang_analyzer_eval(self.in_category == self.in_category); // expected-warning{{UNKNOWN}}
1036
1037 // When there is no explicit accessor defined (even if it looks like there is),
1038 // farm the getter body and see if it does actually always yield the same value.
1039 clang_analyzer_eval(self.no_custom_accessor == self.no_custom_accessor); // expected-warning{{TRUE}}
1040 clang_analyzer_eval(self.still_no_custom_accessor == self.still_no_custom_accessor); // expected-warning{{TRUE}}
1041}
1042@end
1043