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