1// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount,debug.ExprInspection -analyzer-store=region -verify -Wno-objc-root-class %s
2// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount,debug.ExprInspection -analyzer-store=region -verify -Wno-objc-root-class -fobjc-arc %s
3
4void clang_analyzer_eval(int);
5
6typedef signed char BOOL;
7typedef unsigned int NSUInteger;
8typedef struct _NSZone NSZone;
9@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator;
10@protocol NSObject  - (BOOL)isEqual:(id)object; @end
11@protocol NSCopying  - (id)copyWithZone:(NSZone *)zone; @end
12@protocol NSCoding  - (void)encodeWithCoder:(NSCoder *)aCoder; @end
13@protocol NSMutableCopying  - (id)mutableCopyWithZone:(NSZone *)zone; @end
14@interface NSObject <NSObject> {}
15+(id)alloc;
16-(id)init;
17-(id)autorelease;
18-(id)copy;
19-(id)retain;
20-(oneway void)release;
21@end
22@interface NSString : NSObject <NSCopying, NSMutableCopying, NSCoding>
23- (NSUInteger)length;
24-(id)initWithFormat:(NSString *)f,...;
25-(BOOL)isEqualToString:(NSString *)s;
26+ (id)string;
27@end
28@interface NSNumber : NSObject {}
29+(id)alloc;
30-(id)initWithInteger:(int)i;
31@end
32
33// rdar://6946338
34
35@interface Test1 : NSObject {
36  NSString *text;
37}
38-(id)myMethod;
39@property (nonatomic, assign) NSString *text;
40@end
41
42
43#if !__has_feature(objc_arc)
44
45@implementation Test1
46
47@synthesize text;
48
49-(id)myMethod {
50  Test1 *cell = [[[Test1 alloc] init] autorelease];
51
52  NSString *string1 = [[NSString alloc] initWithFormat:@"test %f", 0.0]; // expected-warning {{Potential leak}}
53  cell.text = string1;
54
55  return cell;
56}
57
58@end
59
60
61// rdar://8824416
62
63@interface MyNumber : NSObject
64{
65  NSNumber* _myNumber;
66}
67
68- (id)initWithNumber:(NSNumber *)number;
69
70@property (nonatomic, readonly) NSNumber* myNumber;
71@property (nonatomic, readonly) NSNumber* newMyNumber;
72
73@end
74
75@implementation MyNumber
76@synthesize myNumber=_myNumber;
77 
78- (id)initWithNumber:(NSNumber *)number
79{
80  self = [super init];
81  
82  if ( self )
83  {
84    _myNumber = [number copy];
85  }
86  
87  return self;
88}
89
90- (NSNumber*)newMyNumber
91{
92  if ( _myNumber )
93    return [_myNumber retain];
94  
95  return [[NSNumber alloc] initWithInteger:1];
96}
97
98- (id)valueForUndefinedKey:(NSString*)key
99{
100  id value = 0;
101  
102  if ([key isEqualToString:@"MyIvarNumberAsPropertyOverReleased"])
103    value = self.myNumber; // _myNumber will be over released, since the value returned from self.myNumber is not retained.
104  else if ([key isEqualToString:@"MyIvarNumberAsPropertyOk"])
105    value = [self.myNumber retain]; // this line fixes the over release
106  else if ([key isEqualToString:@"MyIvarNumberAsNewMyNumber"])
107    value = self.newMyNumber; // this one is ok, since value is returned retained
108  else 
109    value = [[NSNumber alloc] initWithInteger:0];
110  
111  return [value autorelease]; // expected-warning {{Object autoreleased too many times}}
112}
113
114@end
115
116NSNumber* numberFromMyNumberProperty(MyNumber* aMyNumber)
117{
118  NSNumber* result = aMyNumber.myNumber;
119    
120  return [result autorelease]; // expected-warning {{Object autoreleased too many times}}
121}
122
123#endif
124
125
126// rdar://6611873
127
128@interface Person : NSObject {
129  NSString *_name;
130}
131@property (retain) NSString * name;
132@property (assign) id friend;
133@end
134
135@implementation Person
136@synthesize name = _name;
137@end
138
139#if !__has_feature(objc_arc)
140void rdar6611873() {
141  Person *p = [[[Person alloc] init] autorelease];
142  
143  p.name = [[NSString string] retain]; // expected-warning {{leak}}
144  p.name = [[NSString alloc] init]; // expected-warning {{leak}}
145
146  p.friend = [[Person alloc] init]; // expected-warning {{leak}}
147}
148#endif
149
150@interface SubPerson : Person
151-(NSString *)foo;
152@end
153
154@implementation SubPerson
155-(NSString *)foo {
156  return super.name;
157}
158@end
159
160
161#if !__has_feature(objc_arc)
162// <rdar://problem/9241180> Static analyzer doesn't detect uninitialized variable issues for property accesses
163@interface RDar9241180
164@property (readwrite,assign) id x;
165-(id)testAnalyzer1:(int) y;
166-(void)testAnalyzer2;
167@end
168
169@implementation RDar9241180
170@synthesize x;
171-(id)testAnalyzer1:(int)y {
172    RDar9241180 *o;
173    if (y && o.x) // expected-warning {{Property access on an uninitialized object pointer}}
174      return o;
175    return o; // expected-warning {{Undefined or garbage value returned to caller}}
176}
177-(void)testAnalyzer2 {
178  id y;
179  self.x = y;  // expected-warning {{Argument for property setter is an uninitialized value}}
180}
181@end
182#endif
183
184
185//------
186// Property accessor synthesis
187//------
188
189extern void doSomethingWithPerson(Person *p);
190extern void doSomethingWithName(NSString *name);
191
192void testConsistencyRetain(Person *p) {
193  clang_analyzer_eval(p.name == p.name); // expected-warning{{TRUE}}
194
195  id origName = p.name;
196  clang_analyzer_eval(p.name == origName); // expected-warning{{TRUE}}
197  doSomethingWithPerson(p);
198  clang_analyzer_eval(p.name == origName); // expected-warning{{UNKNOWN}}
199}
200
201void testConsistencyAssign(Person *p) {
202  clang_analyzer_eval(p.friend == p.friend); // expected-warning{{TRUE}}
203
204  id origFriend = p.friend;
205  clang_analyzer_eval(p.friend == origFriend); // expected-warning{{TRUE}}
206  doSomethingWithPerson(p);
207  clang_analyzer_eval(p.friend == origFriend); // expected-warning{{UNKNOWN}}
208}
209
210#if !__has_feature(objc_arc)
211void testOverrelease(Person *p, int coin) {
212  switch (coin) {
213  case 0:
214    [p.name release]; // expected-warning{{not owned}}
215    break;
216  case 1:
217    [p.friend release]; // expected-warning{{not owned}}
218    break;
219  case 2: {
220    id friend = p.friend;
221    doSomethingWithPerson(p);
222    [friend release]; // expected-warning{{not owned}}
223  }
224  }
225}
226
227// <rdar://problem/16333368>
228@implementation Person (Rdar16333368)
229
230- (void)testDeliberateRelease:(Person *)other {
231  doSomethingWithName(self.name);
232  [_name release]; // no-warning
233  self->_name = 0;
234
235  doSomethingWithName(other->_name);
236  [other.name release]; // expected-warning{{not owned}}
237}
238
239- (void)deliberateReleaseFalseNegative {
240  // This is arguably a false negative because the result of p.friend shouldn't
241  // be released, even though we are manipulating the ivar in between the two
242  // actions.
243  id name = self.name;
244  _name = 0;
245  [name release];
246}
247
248- (void)testRetainAndRelease {
249  [self.name retain];
250  [self.name release];
251  [self.name release]; // expected-warning{{not owned}}
252}
253
254- (void)testRetainAndReleaseIVar {
255  [self.name retain];
256  [_name release];
257  [_name release]; // expected-warning{{not owned}}
258}
259
260@end
261#endif
262
263@interface IntWrapper
264@property int value;
265@end
266
267@implementation IntWrapper
268@synthesize value;
269@end
270
271void testConsistencyInt(IntWrapper *w) {
272  clang_analyzer_eval(w.value == w.value); // expected-warning{{TRUE}}
273
274  int origValue = w.value;
275  if (origValue != 42)
276    return;
277
278  clang_analyzer_eval(w.value == 42); // expected-warning{{TRUE}}
279}
280
281void testConsistencyInt2(IntWrapper *w) {
282  if (w.value != 42)
283    return;
284
285  clang_analyzer_eval(w.value == 42); // expected-warning{{TRUE}}
286}
287
288
289@interface IntWrapperAuto
290@property int value;
291@end
292
293@implementation IntWrapperAuto
294@end
295
296void testConsistencyIntAuto(IntWrapperAuto *w) {
297  clang_analyzer_eval(w.value == w.value); // expected-warning{{TRUE}}
298
299  int origValue = w.value;
300  if (origValue != 42)
301    return;
302
303  clang_analyzer_eval(w.value == 42); // expected-warning{{TRUE}}
304}
305
306void testConsistencyIntAuto2(IntWrapperAuto *w) {
307  if (w.value != 42)
308    return;
309
310  clang_analyzer_eval(w.value == 42); // expected-warning{{TRUE}}
311}
312
313
314typedef struct {
315  int value;
316} IntWrapperStruct;
317
318@interface StructWrapper
319@property IntWrapperStruct inner;
320@end
321
322@implementation StructWrapper
323@synthesize inner;
324@end
325
326void testConsistencyStruct(StructWrapper *w) {
327  clang_analyzer_eval(w.inner.value == w.inner.value); // expected-warning{{TRUE}}
328
329  int origValue = w.inner.value;
330  if (origValue != 42)
331    return;
332
333  clang_analyzer_eval(w.inner.value == 42); // expected-warning{{TRUE}}
334}
335
336
337@interface OpaqueIntWrapper
338@property int value;
339@end
340
341// For now, don't assume a property is implemented using an ivar unless we can
342// actually see that it is.
343void testOpaqueConsistency(OpaqueIntWrapper *w) {
344  clang_analyzer_eval(w.value == w.value); // expected-warning{{UNKNOWN}}
345}
346
347