1// RUN: %clang_cc1 -verify -Wno-deprecated-declarations -Wno-objc-root-class %s
2
3@interface Unrelated
4@end
5
6@interface NSObject
7+ (id)new;
8+ (id)alloc;
9- (NSObject *)init;
10
11- (id)retain;  // expected-note{{instance method 'retain' is assumed to return an instance of its receiver type ('NSArray *')}}
12- autorelease;
13
14- (id)self;
15
16- (id)copy;
17- (id)mutableCopy;
18
19// Do not infer when instance/class mismatches
20- (id)newNotInferred;
21- (id)alloc;
22+ (id)initWithBlarg;
23+ (id)self;
24
25// Do not infer when the return types mismatch.
26- (Unrelated *)initAsUnrelated;
27@end
28
29@interface NSString : NSObject
30- (id)init;
31- (id)initWithCString:(const char*)string;
32@end
33
34@interface NSArray : NSObject
35- (unsigned)count;
36@end
37
38@interface NSBlah 
39@end
40
41@interface NSMutableArray : NSArray
42@end
43
44@interface NSBlah ()
45+ (Unrelated *)newUnrelated;
46@end
47
48void test_inference() {
49  // Inference based on method family
50  __typeof__(([[NSString alloc] init])) *str = (NSString**)0;
51  __typeof__(([[[[NSString new] self] retain] autorelease])) *str2 = (NSString **)0;
52  __typeof__(([[NSString alloc] initWithCString:"blah"])) *str3 = (NSString**)0;
53
54  // Not inferred
55  __typeof__(([[NSString new] copy])) *id1 = (id*)0;
56
57  // Not inferred due to instance/class mismatches
58  __typeof__(([[NSString new] newNotInferred])) *id2 = (id*)0;
59  __typeof__(([[NSString new] alloc])) *id3 = (id*)0;
60  __typeof__(([NSString self])) *id4 = (id*)0;
61  __typeof__(([NSString initWithBlarg])) *id5 = (id*)0;
62
63  // Not inferred due to return type mismatch
64  __typeof__(([[NSString alloc] initAsUnrelated])) *unrelated = (Unrelated**)0;
65  __typeof__(([NSBlah newUnrelated])) *unrelated2 = (Unrelated**)0;
66
67  
68  NSArray *arr = [[NSMutableArray alloc] init];
69  NSMutableArray *marr = [arr retain]; // expected-warning{{incompatible pointer types initializing 'NSMutableArray *' with an expression of type 'NSArray *'}}
70}
71
72@implementation NSBlah
73+ (Unrelated *)newUnrelated {
74  return (Unrelated *)0;
75}
76@end
77
78@implementation NSBlah (Cat)
79+ (Unrelated *)newUnrelated2 {
80  return (Unrelated *)0;
81}
82@end
83
84@interface A
85- (id)initBlah; // expected-note 2{{overridden method is part of the 'init' method family}}
86@end
87
88@interface B : A
89- (Unrelated *)initBlah; // expected-warning{{method is expected to return an instance of its class type 'B', but is declared to return 'Unrelated *'}}
90@end
91
92@interface C : A
93@end
94
95@implementation C
96- (Unrelated *)initBlah {  // expected-warning{{method is expected to return an instance of its class type 'C', but is declared to return 'Unrelated *'}}
97  return (Unrelated *)0;
98}
99@end
100
101@interface D
102+ (id)newBlarg; // expected-note{{overridden method is part of the 'new' method family}}
103@end
104
105@interface D ()
106+ alloc; // expected-note{{overridden method is part of the 'alloc' method family}}
107@end
108
109@implementation D
110+ (Unrelated *)newBlarg { // expected-warning{{method is expected to return an instance of its class type 'D', but is declared to return 'Unrelated *'}}
111  return (Unrelated *)0;
112}
113
114+ (Unrelated *)alloc { // expected-warning{{method is expected to return an instance of its class type 'D', but is declared to return 'Unrelated *'}}
115  return (Unrelated *)0;
116}
117@end
118
119@protocol P1
120- (id)initBlah; // expected-note{{overridden method is part of the 'init' method family}}
121- (int)initBlarg;
122@end
123
124@protocol P2 <P1>
125- (int)initBlah; // expected-warning{{protocol method is expected to return an instance of the implementing class, but is declared to return 'int'}}
126- (int)initBlarg;
127- (int)initBlech;
128@end
129
130@interface E
131- init;
132@end
133
134@implementation E
135- init {
136  return self;
137}
138@end
139
140@protocol P3
141+ (NSString *)newString;
142@end
143
144@interface F<P3>
145@end
146
147@implementation F
148+ (NSString *)newString { return @"blah"; }
149@end
150
151// <rdar://problem/9340699>
152@interface G 
153- (id)_ABC_init __attribute__((objc_method_family(init))); // expected-note {{method '_ABC_init' declared here}}
154@end
155
156@interface G (Additions)
157- (id)_ABC_init2 __attribute__((objc_method_family(init)));
158@end
159
160@implementation G (Additions)
161- (id)_ABC_init { // expected-warning {{category is implementing a method which will also be implemented by its primary class}}
162  return 0;
163}
164- (id)_ABC_init2 {
165  return 0;
166}
167- (id)_ABC_init3 {
168  return 0;
169}
170@end
171
172// PR12384
173@interface Fail @end
174@protocol X @end
175@implementation Fail
176- (id<X>) initWithX // expected-note {{compiler has implicitly changed method 'initWithX' return type}}
177{
178  return (id)self; // expected-warning {{casting 'Fail *' to incompatible type 'id<X>'}}
179}
180@end
181
182// <rdar://problem/11460990>
183
184@interface WeirdNSString : NSString
185- (id)initWithCString:(const char*)string, void *blah;
186@end
187
188
189// rdar://14121570
190@protocol PMFilterManager
191@end
192
193@interface UIViewController : NSObject
194@end
195
196@implementation UIViewController
197+ (UIViewController<PMFilterManager> *)newFilterViewControllerForType // expected-note {{compiler has implicitly changed method 'newFilterViewControllerForType' return type}}
198{
199        UIViewController<PMFilterManager> *filterVC;
200        return filterVC; // expected-warning {{incompatible pointer types casting 'UIViewController *' to type 'UIViewController<PMFilterManager> *'}}
201}
202@end
203