// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.RetainCount,osx.cocoa.Dealloc,debug.ExprInspection -analyzer-store=region -verify -Wno-objc-root-class %s // 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 %s void clang_analyzer_eval(int); typedef const void * CFTypeRef; extern CFTypeRef CFRetain(CFTypeRef cf); void CFRelease(CFTypeRef cf); typedef signed char BOOL; typedef unsigned int NSUInteger; typedef struct _NSZone NSZone; @class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; @protocol NSObject - (BOOL)isEqual:(id)object; @end @protocol NSCopying - (id)copyWithZone:(NSZone *)zone; @end @protocol NSCoding - (void)encodeWithCoder:(NSCoder *)aCoder; @end @protocol NSMutableCopying - (id)mutableCopyWithZone:(NSZone *)zone; @end @interface NSObject {} +(id)alloc; -(id)init; -(id)autorelease; -(id)copy; -(id)retain; -(oneway void)release; -(void)dealloc; @end @interface NSString : NSObject - (NSUInteger)length; -(id)initWithFormat:(NSString *)f,...; -(BOOL)isEqualToString:(NSString *)s; + (id)string; @end @interface NSNumber : NSObject {} +(id)alloc; -(id)initWithInteger:(int)i; @end // rdar://6946338 @interface Test1 : NSObject { NSString *text; } -(id)myMethod; @property (nonatomic, assign) NSString *text; @end #if !__has_feature(objc_arc) @implementation Test1 @synthesize text; -(id)myMethod { Test1 *cell = [[[Test1 alloc] init] autorelease]; NSString *string1 = [[NSString alloc] initWithFormat:@"test %f", 0.0]; // expected-warning {{Potential leak}} cell.text = string1; return cell; } @end // rdar://8824416 @interface MyNumber : NSObject { NSNumber* _myNumber; } - (id)initWithNumber:(NSNumber *)number; @property (nonatomic, readonly) NSNumber* myNumber; @property (nonatomic, readonly) NSNumber* newMyNumber; @end @implementation MyNumber @synthesize myNumber=_myNumber; - (id)initWithNumber:(NSNumber *)number { self = [super init]; if ( self ) { _myNumber = [number copy]; } return self; } - (NSNumber*)newMyNumber { if ( _myNumber ) return [_myNumber retain]; return [[NSNumber alloc] initWithInteger:1]; } - (id)valueForUndefinedKey:(NSString*)key { id value = 0; if ([key isEqualToString:@"MyIvarNumberAsPropertyOverReleased"]) value = self.myNumber; // _myNumber will be over released, since the value returned from self.myNumber is not retained. else if ([key isEqualToString:@"MyIvarNumberAsPropertyOk"]) value = [self.myNumber retain]; // this line fixes the over release else if ([key isEqualToString:@"MyIvarNumberAsNewMyNumber"]) value = self.newMyNumber; // this one is ok, since value is returned retained else value = [[NSNumber alloc] initWithInteger:0]; return [value autorelease]; // expected-warning {{Object autoreleased too many times}} } @end NSNumber* numberFromMyNumberProperty(MyNumber* aMyNumber) { NSNumber* result = aMyNumber.myNumber; return [result autorelease]; // expected-warning {{Object autoreleased too many times}} } #endif // rdar://6611873 @interface Person : NSObject { NSString *_name; } @property (retain) NSString * name; @property (assign) id friend; @end @implementation Person @synthesize name = _name; -(void)dealloc { #if !__has_feature(objc_arc) self.name = [[NSString alloc] init]; // expected-warning {{leak}} [super dealloc]; // expected-warning {{The '_name' ivar in 'Person' was retained by a synthesized property but not released before '[super dealloc]}} #endif } @end #if !__has_feature(objc_arc) void rdar6611873() { Person *p = [[[Person alloc] init] autorelease]; p.name = [[NSString string] retain]; // expected-warning {{leak}} p.name = [[NSString alloc] init]; // expected-warning {{leak}} p.friend = [[Person alloc] init]; // expected-warning {{leak}} } #endif @interface SubPerson : Person -(NSString *)foo; @end @implementation SubPerson -(NSString *)foo { return super.name; } @end #if !__has_feature(objc_arc) // Static analyzer doesn't detect uninitialized variable issues for property accesses @interface RDar9241180 @property (readwrite,assign) id x; -(id)testAnalyzer1:(int) y; -(void)testAnalyzer2; @end @implementation RDar9241180 @synthesize x; -(id)testAnalyzer1:(int)y { RDar9241180 *o; if (y && o.x) // expected-warning {{Property access on an uninitialized object pointer}} return o; return o; // expected-warning {{Undefined or garbage value returned to caller}} } -(void)testAnalyzer2 { id y; self.x = y; // expected-warning {{Argument for property setter is an uninitialized value}} } @end #endif //------ // Property accessor synthesis //------ extern void doSomethingWithPerson(Person *p); extern void doSomethingWithName(NSString *name); void testConsistencyRetain(Person *p) { clang_analyzer_eval(p.name == p.name); // expected-warning{{TRUE}} id origName = p.name; clang_analyzer_eval(p.name == origName); // expected-warning{{TRUE}} doSomethingWithPerson(p); clang_analyzer_eval(p.name == origName); // expected-warning{{UNKNOWN}} } void testConsistencyAssign(Person *p) { clang_analyzer_eval(p.friend == p.friend); // expected-warning{{TRUE}} id origFriend = p.friend; clang_analyzer_eval(p.friend == origFriend); // expected-warning{{TRUE}} doSomethingWithPerson(p); clang_analyzer_eval(p.friend == origFriend); // expected-warning{{UNKNOWN}} } @interface ClassWithShadowedReadWriteProperty { int _f; } @property (readonly) int someProp; @end @interface ClassWithShadowedReadWriteProperty () @property (readwrite) int someProp; @end @implementation ClassWithShadowedReadWriteProperty - (void)testSynthesisForShadowedReadWriteProperties; { clang_analyzer_eval(self.someProp == self.someProp); // expected-warning{{TRUE}} _f = 1; // Read of shadowed property should not invalidate receiver. (void)self.someProp; clang_analyzer_eval(_f == 1); // expected-warning{{TRUE}} _f = 2; // Call to getter of shadowed property should not invalidate receiver. (void)[self someProp]; clang_analyzer_eval(_f == 2); // expected-warning{{TRUE}} } @end // Tests for the analyzer fix that works around a Sema bug // where multiple methods are created for properties in class extensions that // are redeclared in a category method. // The Sema bug is tracked as . @interface ClassWithRedeclaredPropertyInExtensionFollowedByCategory @end @interface ClassWithRedeclaredPropertyInExtensionFollowedByCategory () @end @interface ClassWithRedeclaredPropertyInExtensionFollowedByCategory () @property (readwrite) int someProp; @property (readonly) int otherProp; @end @interface ClassWithRedeclaredPropertyInExtensionFollowedByCategory (MyCat) @property (readonly) int someProp; @property (readonly) int otherProp; @end @implementation ClassWithRedeclaredPropertyInExtensionFollowedByCategory - (void)testSynthesisForRedeclaredProperties; { clang_analyzer_eval(self.someProp == self.someProp); // expected-warning{{TRUE}} clang_analyzer_eval([self someProp] == self.someProp); // expected-warning{{TRUE}} clang_analyzer_eval(self.otherProp == self.otherProp); // expected-warning{{TRUE}} clang_analyzer_eval([self otherProp] == self.otherProp); // expected-warning{{TRUE}} } @end // The relative order of the extension and the category matter, so test both. @interface ClassWithRedeclaredPropertyInCategoryFollowedByExtension @end @interface ClassWithRedeclaredPropertyInCategoryFollowedByExtension () @property (readwrite) int someProp; @end @interface ClassWithRedeclaredPropertyInCategoryFollowedByExtension (MyCat) @property (readonly) int someProp; @end @implementation ClassWithRedeclaredPropertyInCategoryFollowedByExtension - (void)testSynthesisForRedeclaredProperties; { clang_analyzer_eval(self.someProp == self.someProp); // expected-warning{{TRUE}} clang_analyzer_eval([self someProp] == self.someProp); // expected-warning{{TRUE}} } @end @interface ClassWithSynthesizedPropertyAndGetter @property (readonly) int someProp; @end @implementation ClassWithSynthesizedPropertyAndGetter @synthesize someProp; // Make sure that the actual getter is inlined and not a getter created // by BodyFarm - (void)testBodyFarmGetterNotUsed { int i = self.someProp; clang_analyzer_eval(i == 22); // expected-warning {{TRUE}} } -(int)someProp { return 22; } @end __attribute__((objc_root_class)) @interface ClassWithPrivatePropertyInClassExtensionWithProtocolShadowingCategory @end @protocol HasStuff @property (nonatomic, readonly) int stuffProperty; @end @interface ClassWithPrivatePropertyInClassExtensionWithProtocolShadowingCategory (Private) @property (nonatomic, readonly) int stuffProperty; @end @interface ClassWithPrivatePropertyInClassExtensionWithProtocolShadowingCategory (Internal) @end @interface ClassWithPrivatePropertyInClassExtensionWithProtocolShadowingCategory() @end @implementation ClassWithPrivatePropertyInClassExtensionWithProtocolShadowingCategory @synthesize stuffProperty = _stuffProperty; -(void)foo { (void)self.stuffProperty; } @end //------ // Setter ivar invalidation. //------ @interface ClassWithSetters // Note: These properties have implicit @synthesize implementations to be // backed with ivars. @property (assign) int propWithIvar1; @property (assign) int propWithIvar2; @property (retain) NSNumber *retainedProperty; @end @interface ClassWithSetters (InOtherTranslationUnit) // The implementation of this property is in another translation unit. // We don't know whether it is backed by an ivar or not. @property (assign) int propInOther; @end @implementation ClassWithSetters - (void) testSettingPropWithIvarInvalidatesExactlyThatIvar; { _propWithIvar1 = 1; _propWithIvar2 = 2; self.propWithIvar1 = 66; // Calling the setter of a property backed by the instance variable // should invalidate the storage for the instance variable but not // the rest of the receiver. Ideally we would model the setter completely // but doing so would cause the new value to escape when it is bound // to the ivar. This would cause bad false negatives in the retain count // checker. (There is a test for this scenario in // testWriteRetainedValueToRetainedProperty below). clang_analyzer_eval(_propWithIvar1 == 66); // expected-warning{{UNKNOWN}} clang_analyzer_eval(_propWithIvar2 == 2); // expected-warning{{TRUE}} _propWithIvar1 = 1; [self setPropWithIvar1:66]; clang_analyzer_eval(_propWithIvar1 == 66); // expected-warning{{UNKNOWN}} clang_analyzer_eval(_propWithIvar2 == 2); // expected-warning{{TRUE}} } - (void) testSettingPropWithoutIvarInvalidatesEntireInstance; { _propWithIvar1 = 1; _propWithIvar2 = 2; self.propInOther = 66; clang_analyzer_eval(_propWithIvar1 == 66); // expected-warning{{UNKNOWN}} clang_analyzer_eval(_propWithIvar2 == 2); // expected-warning{{UNKNOWN}} _propWithIvar1 = 1; _propWithIvar2 = 2; [self setPropInOther:66]; clang_analyzer_eval(_propWithIvar1 == 66); // expected-warning{{UNKNOWN}} clang_analyzer_eval(_propWithIvar2 == 2); // expected-warning{{UNKNOWN}} } #if !__has_feature(objc_arc) - (void) testWriteRetainedValueToRetainedProperty; { NSNumber *number = [[NSNumber alloc] initWithInteger:5]; // expected-warning {{Potential leak of an object stored into 'number'}} // Make sure we catch this leak. self.retainedProperty = number; } #endif @end //------ // class properties //------ int gBackingForReadWriteClassProp = 0; @interface ClassWithClassProperties @property(class, readonly) int readOnlyClassProp; @property(class) int readWriteClassProp; // Make sure we handle when a class and instance property have the same // name. Test both when instance comes first and when class comes first. @property(readonly) int classAndInstancePropWithSameNameOrderInstanceFirst; @property(class, readonly) int classAndInstancePropWithSameNameOrderInstanceFirst; @property(class, readonly) int classAndInstancePropWithSameNameOrderClassFirst; @property(readonly) int classAndInstancePropWithSameNameOrderClassFirst; @property(class, readonly) int dynamicClassProp; @end @interface ClassWithClassProperties (OtherTranslationUnit) @property(class, assign) id propInOtherTranslationUnit; @end @implementation ClassWithClassProperties @dynamic dynamicClassProp; + (int)readOnlyClassProp { return 1; } + (int)readWriteClassProp { return gBackingForReadWriteClassProp; } + (void)setReadWriteClassProp:(int)val { gBackingForReadWriteClassProp = val; } - (int)classAndInstancePropWithSameNameOrderInstanceFirst { return 12; } + (int)classAndInstancePropWithSameNameOrderInstanceFirst { return 13; } + (int)classAndInstancePropWithSameNameOrderClassFirst { return 14; } - (int)classAndInstancePropWithSameNameOrderClassFirst { return 15; } - (void)testInlineClassProp { clang_analyzer_eval(ClassWithClassProperties.readOnlyClassProp == 1); // expected-warning{{TRUE}} ClassWithClassProperties.readWriteClassProp = 7; clang_analyzer_eval(ClassWithClassProperties.readWriteClassProp == 7); // expected-warning{{TRUE}} ClassWithClassProperties.readWriteClassProp = 8; clang_analyzer_eval(ClassWithClassProperties.readWriteClassProp == 8); // expected-warning{{TRUE}} } - (void)testUnknownClassProp { clang_analyzer_eval(ClassWithClassProperties.propInOtherTranslationUnit == ClassWithClassProperties.propInOtherTranslationUnit); // expected-warning{{UNKNOWN}} } - (void)testEscapeGlobalOnUnknownProp { gBackingForReadWriteClassProp = 33; ClassWithClassProperties.propInOtherTranslationUnit = 0; clang_analyzer_eval(gBackingForReadWriteClassProp == 33); // expected-warning{{UNKNOWN}} } - (void)testClassAndInstancePropertyWithSameName { clang_analyzer_eval(self.classAndInstancePropWithSameNameOrderInstanceFirst == 12); // expected-warning{{TRUE}} clang_analyzer_eval(ClassWithClassProperties.classAndInstancePropWithSameNameOrderInstanceFirst == 13); // expected-warning{{TRUE}} clang_analyzer_eval(ClassWithClassProperties.classAndInstancePropWithSameNameOrderClassFirst == 14); // expected-warning{{TRUE}} clang_analyzer_eval(self.classAndInstancePropWithSameNameOrderClassFirst == 15); // expected-warning{{TRUE}} } - (void)testDynamicClassProp { clang_analyzer_eval(ClassWithClassProperties.dynamicClassProp == 16); // expected-warning{{UNKNOWN}} } @end @interface SubclassOfClassWithClassProperties : ClassWithClassProperties @end @implementation SubclassOfClassWithClassProperties + (int)dynamicClassProp; { return 16; } - (void)testDynamicClassProp { clang_analyzer_eval(SubclassOfClassWithClassProperties.dynamicClassProp == 16); // expected-warning{{TRUE}} } @end #if !__has_feature(objc_arc) void testOverrelease(Person *p, int coin) { switch (coin) { case 0: [p.name release]; // expected-warning{{not owned}} break; case 1: [p.friend release]; // expected-warning{{not owned}} break; case 2: { id friend = p.friend; doSomethingWithPerson(p); [friend release]; // expected-warning{{not owned}} } } } // @implementation Person (Rdar16333368) - (void)testDeliberateRelease:(Person *)other { doSomethingWithName(self.name); [_name release]; // no-warning self->_name = 0; doSomethingWithName(other->_name); [other.name release]; // no-warning } - (void)deliberateReleaseFalseNegative { // This is arguably a false negative because the result of p.friend shouldn't // be released, even though we are manipulating the ivar in between the two // actions. id name = self.name; _name = 0; [name release]; } - (void)testRetainAndRelease { [self.name retain]; [self.name release]; [self.name release]; // expected-warning{{not owned}} } - (void)testRetainAndReleaseIVar { [self.name retain]; [_name release]; [_name release]; } @end #endif @interface IntWrapper @property int value; @end @implementation IntWrapper @synthesize value; @end void testConsistencyInt(IntWrapper *w) { clang_analyzer_eval(w.value == w.value); // expected-warning{{TRUE}} int origValue = w.value; if (origValue != 42) return; clang_analyzer_eval(w.value == 42); // expected-warning{{TRUE}} } void testConsistencyInt2(IntWrapper *w) { if (w.value != 42) return; clang_analyzer_eval(w.value == 42); // expected-warning{{TRUE}} } @interface IntWrapperAuto @property int value; @end @implementation IntWrapperAuto @end void testConsistencyIntAuto(IntWrapperAuto *w) { clang_analyzer_eval(w.value == w.value); // expected-warning{{TRUE}} int origValue = w.value; if (origValue != 42) return; clang_analyzer_eval(w.value == 42); // expected-warning{{TRUE}} } void testConsistencyIntAuto2(IntWrapperAuto *w) { if (w.value != 42) return; clang_analyzer_eval(w.value == 42); // expected-warning{{TRUE}} } typedef struct { int value; } IntWrapperStruct; @interface StructWrapper @property IntWrapperStruct inner; @end @implementation StructWrapper @synthesize inner; @end void testConsistencyStruct(StructWrapper *w) { clang_analyzer_eval(w.inner.value == w.inner.value); // expected-warning{{TRUE}} int origValue = w.inner.value; if (origValue != 42) return; clang_analyzer_eval(w.inner.value == 42); // expected-warning{{TRUE}} } @interface OpaqueIntWrapper @property int value; @end // For now, don't assume a property is implemented using an ivar unless we can // actually see that it is. void testOpaqueConsistency(OpaqueIntWrapper *w) { clang_analyzer_eval(w.value == w.value); // expected-warning{{UNKNOWN}} } #if !__has_feature(objc_arc) // Test quite a few cases of retain/release issues. @interface RetainCountTesting @property (strong) id ownedProp; @property (unsafe_unretained) id unownedProp; @property (nonatomic, strong) id manualProp; @property (readonly) id readonlyProp; @property (nonatomic, readwrite/*, assign */) id implicitManualProp; // expected-warning {{'assign' is assumed}} expected-warning {{'assign' not appropriate}} @property (nonatomic, readwrite/*, assign */) id implicitSynthProp; // expected-warning {{'assign' is assumed}} expected-warning {{'assign' not appropriate}} @property CFTypeRef cfProp; @end @implementation RetainCountTesting { id _ivarOnly; } - (id)manualProp { return _manualProp; } - (void)setImplicitManualProp:(id)newValue {} - (void)testOverreleaseOwnedIvar { [_ownedProp retain]; [_ownedProp release]; [_ownedProp release]; [_ownedProp release]; // FIXME-warning{{used after it is released}} } - (void)testOverreleaseUnownedIvar { [_unownedProp retain]; [_unownedProp release]; [_unownedProp release]; // FIXME-warning{{not owned at this point by the caller}} } - (void)testOverreleaseIvarOnly { [_ivarOnly retain]; [_ivarOnly release]; [_ivarOnly release]; [_ivarOnly release]; // FIXME-warning{{used after it is released}} } - (void)testOverreleaseReadonlyIvar { [_readonlyProp retain]; [_readonlyProp release]; [_readonlyProp release]; [_readonlyProp release]; // FIXME-warning{{used after it is released}} } - (void)testOverreleaseImplicitManualIvar { [_implicitManualProp retain]; [_implicitManualProp release]; [_implicitManualProp release]; [_implicitManualProp release]; // FIXME-warning{{used after it is released}} } - (void)testOverreleaseImplicitSynthIvar { [_implicitSynthProp retain]; [_implicitSynthProp release]; [_implicitSynthProp release]; // FIXME-warning{{not owned at this point by the caller}} } - (void)testOverreleaseCF { CFRetain(_cfProp); CFRelease(_cfProp); CFRelease(_cfProp); CFRelease(_cfProp); // FIXME-warning{{used after it is released}} } - (void)testOverreleaseOwnedIvarUse { [_ownedProp retain]; [_ownedProp release]; [_ownedProp release]; [_ownedProp myMethod]; // FIXME-warning{{used after it is released}} } - (void)testOverreleaseIvarOnlyUse { [_ivarOnly retain]; [_ivarOnly release]; [_ivarOnly release]; [_ivarOnly myMethod]; // FIXME-warning{{used after it is released}} } - (void)testOverreleaseCFUse { CFRetain(_cfProp); CFRelease(_cfProp); CFRelease(_cfProp); extern void CFUse(CFTypeRef); CFUse(_cfProp); // FIXME-warning{{used after it is released}} } - (void)testOverreleaseOwnedIvarAutoreleaseOkay { [_ownedProp retain]; [_ownedProp release]; [_ownedProp autorelease]; } // no-warning - (void)testOverreleaseIvarOnlyAutoreleaseOkay { [_ivarOnly retain]; [_ivarOnly release]; [_ivarOnly autorelease]; } // no-warning - (void)testOverreleaseOwnedIvarAutorelease { [_ownedProp retain]; [_ownedProp release]; [_ownedProp autorelease]; [_ownedProp autorelease]; } // FIXME-warning{{Object autoreleased too many times}} - (void)testOverreleaseIvarOnlyAutorelease { [_ivarOnly retain]; [_ivarOnly release]; [_ivarOnly autorelease]; [_ivarOnly autorelease]; } // FIXME-warning{{Object autoreleased too many times}} - (void)testPropertyAccessThenReleaseOwned { id owned = [self.ownedProp retain]; [owned release]; [_ownedProp release]; clang_analyzer_eval(owned == _ownedProp); // expected-warning{{TRUE}} } - (void)testPropertyAccessThenReleaseOwned2 { id fromIvar = _ownedProp; id owned = [self.ownedProp retain]; [owned release]; [fromIvar release]; clang_analyzer_eval(owned == fromIvar); // expected-warning{{TRUE}} } - (void)testPropertyAccessThenReleaseUnowned { id unowned = [self.unownedProp retain]; [unowned release]; [_unownedProp release]; // FIXME-warning{{not owned}} } - (void)testPropertyAccessThenReleaseUnowned2 { id fromIvar = _unownedProp; id unowned = [self.unownedProp retain]; [unowned release]; clang_analyzer_eval(unowned == fromIvar); // expected-warning{{TRUE}} [fromIvar release]; // FIXME-warning{{not owned}} } - (void)testPropertyAccessThenReleaseManual { id prop = [self.manualProp retain]; [prop release]; [_manualProp release]; // no-warning } - (void)testPropertyAccessThenReleaseManual2 { id fromIvar = _manualProp; id prop = [self.manualProp retain]; [prop release]; clang_analyzer_eval(prop == fromIvar); // expected-warning{{TRUE}} [fromIvar release]; // no-warning } - (void)testPropertyAccessThenReleaseCF { CFTypeRef owned = CFRetain(self.cfProp); CFRelease(owned); CFRelease(_cfProp); // no-warning clang_analyzer_eval(owned == _cfProp); // expected-warning{{TRUE}} } - (void)testPropertyAccessThenReleaseCF2 { CFTypeRef fromIvar = _cfProp; CFTypeRef owned = CFRetain(self.cfProp); CFRelease(owned); CFRelease(fromIvar); clang_analyzer_eval(owned == fromIvar); // expected-warning{{TRUE}} } - (void)testPropertyAccessThenReleaseReadonly { id prop = [self.readonlyProp retain]; [prop release]; [_readonlyProp release]; // no-warning } - (void)testPropertyAccessThenReleaseReadonly2 { id fromIvar = _readonlyProp; id prop = [self.readonlyProp retain]; [prop release]; clang_analyzer_eval(prop == fromIvar); // expected-warning{{TRUE}} [fromIvar release]; // no-warning } - (void)testPropertyAccessThenReleaseImplicitManual { id prop = [self.implicitManualProp retain]; [prop release]; [_implicitManualProp release]; // no-warning } - (void)testPropertyAccessThenReleaseImplicitManual2 { id fromIvar = _implicitManualProp; id prop = [self.implicitManualProp retain]; [prop release]; clang_analyzer_eval(prop == fromIvar); // expected-warning{{TRUE}} [fromIvar release]; // no-warning } - (void)testPropertyAccessThenReleaseImplicitSynth { id prop = [self.implicitSynthProp retain]; [prop release]; [_implicitSynthProp release]; // FIXME-warning{{not owned}} } - (void)testPropertyAccessThenReleaseImplicitSynth2 { id fromIvar = _implicitSynthProp; id prop = [self.implicitSynthProp retain]; [prop release]; clang_analyzer_eval(prop == fromIvar); // expected-warning{{TRUE}} [fromIvar release]; // FIXME-warning{{not owned}} } - (id)getUnownedFromProperty { [_ownedProp retain]; [_ownedProp autorelease]; return _ownedProp; // no-warning } - (id)transferUnownedFromProperty { [_ownedProp retain]; [_ownedProp autorelease]; return [_ownedProp autorelease]; // no-warning } - (id)transferOwnedFromProperty __attribute__((ns_returns_retained)) { [_ownedProp retain]; [_ownedProp autorelease]; return _ownedProp; // no-warning } - (void)testAssignOwned:(id)newValue { _ownedProp = newValue; [_ownedProp release]; // FIXME: no-warning{{not owned}} } - (void)testAssignUnowned:(id)newValue { _unownedProp = newValue; [_unownedProp release]; // FIXME: no-warning{{not owned}} } - (void)testAssignIvarOnly:(id)newValue { _ivarOnly = newValue; [_ivarOnly release]; // FIXME: no-warning{{not owned}} } - (void)testAssignCF:(CFTypeRef)newValue { _cfProp = newValue; CFRelease(_cfProp); // FIXME: no-warning{{not owned}} } - (void)testAssignReadonly:(id)newValue { _readonlyProp = newValue; [_readonlyProp release]; // FIXME: no-warning{{not owned}} } - (void)testAssignImplicitManual:(id)newValue { _implicitManualProp = newValue; [_implicitManualProp release]; // FIXME: no-warning{{not owned}} } - (void)testAssignImplicitSynth:(id)newValue { _implicitSynthProp = newValue; [_implicitSynthProp release]; // FIXME: no-warning{{not owned}} } - (void)testAssignOwnedOkay:(id)newValue { _ownedProp = [newValue retain]; [_ownedProp release]; // no-warning } - (void)testAssignUnownedOkay:(id)newValue { _unownedProp = [newValue retain]; [_unownedProp release]; // no-warning } - (void)testAssignIvarOnlyOkay:(id)newValue { _ivarOnly = [newValue retain]; [_ivarOnly release]; // no-warning } - (void)testAssignCFOkay:(CFTypeRef)newValue { _cfProp = CFRetain(newValue); CFRelease(_cfProp); // no-warning } - (void)testAssignReadonlyOkay:(id)newValue { _readonlyProp = [newValue retain]; [_readonlyProp release]; // FIXME: no-warning{{not owned}} } - (void)testAssignImplicitManualOkay:(id)newValue { _implicitManualProp = [newValue retain]; [_implicitManualProp release]; // FIXME: no-warning{{not owned}} } - (void)testAssignImplicitSynthOkay:(id)newValue { _implicitSynthProp = [newValue retain]; [_implicitSynthProp release]; // FIXME: no-warning{{not owned}} } // rdar://problem/19862648 - (void)establishIvarIsNilDuringLoops { extern id getRandomObject(); int i = 4; // Must be at least 4 to trigger the bug. while (--i) { id x = 0; if (getRandomObject()) x = _ivarOnly; if (!x) x = getRandomObject(); [x myMethod]; } } // rdar://problem/20335433 - (void)retainIvarAndInvalidateSelf { extern void invalidate(id); [_unownedProp retain]; invalidate(self); [_unownedProp release]; // no-warning } @end @interface Wrapper @property(nonatomic, readonly) int value; @end @implementation Wrapper @synthesize value; @end void testNoCrashWhenAccessPropertyAndThereAreNoDirectBindingsAtAll() { union { Wrapper *wrapper; } u = { 0 }; [u.wrapper value]; } #endif // non-ARC