xref: /llvm-project/clang/test/SemaObjC/related-result-type-inference.m (revision 0f1c1be1968076d6f96f8a7bcc4a15cf195ecd97)
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(void) {
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@interface G
152- (id)_ABC_init __attribute__((objc_method_family(init))); // expected-note {{method '_ABC_init' declared here}}
153@end
154
155@interface G (Additions)
156- (id)_ABC_init2 __attribute__((objc_method_family(init)));
157@end
158
159@implementation G (Additions)
160- (id)_ABC_init { // expected-warning {{category is implementing a method which will also be implemented by its primary class}}
161  return 0;
162}
163- (id)_ABC_init2 {
164  return 0;
165}
166- (id)_ABC_init3 {
167  return 0;
168}
169@end
170
171// PR12384
172@interface Fail @end
173@protocol X @end
174@implementation Fail
175- (id<X>) initWithX // expected-note {{compiler has implicitly changed method 'initWithX' return type}}
176{
177  return (id)self; // expected-warning {{casting 'Fail *' to incompatible type 'id<X>'}}
178}
179@end
180
181@interface WeirdNSString : NSString
182- (id)initWithCString:(const char*)string, void *blah;
183@end
184
185@protocol PMFilterManager
186@end
187
188@interface UIViewController : NSObject
189@end
190
191@implementation UIViewController
192+ (UIViewController<PMFilterManager> *)newFilterViewControllerForType // expected-note {{compiler has implicitly changed method 'newFilterViewControllerForType' return type}}
193{
194        UIViewController<PMFilterManager> *filterVC;
195        return filterVC; // expected-warning {{incompatible pointer types casting 'UIViewController *' to type 'UIViewController<PMFilterManager> *'}}
196}
197@end
198