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