1 // RUN: %clang_cc1 -fsyntax-only -verify %s
3 #if !__has_feature(objc_instancetype)
4 # error Missing 'instancetype' feature macro.
8 + (instancetype)alloc; // expected-note {{explicitly declared 'instancetype'}}
9 - (instancetype)init; // expected-note{{overridden method is part of the 'init' method family}}
10 - (instancetype)self; // expected-note {{explicitly declared 'instancetype'}}
13 @property (assign) Root *selfProp;
14 - (instancetype)selfProp;
19 - (instancetype)methodInProto1;
24 - (instancetype)methodInProto2; // expected-note{{overridden method returns an instance of its class type}}
25 - (instancetype)otherMethodInProto2; // expected-note{{overridden method returns an instance of its class type}}
28 @interface Subclass1 : Root // expected-note 4 {{receiver is instance of class declared here}}
29 - (instancetype)initSubclass1;
30 - (void)methodOnSubclass1;
31 + (instancetype)allocSubclass1;
34 @interface Subclass2 : Root
35 - (instancetype)initSubclass2;
36 - (void)methodOnSubclass2;
39 // Verify the basic initialization pattern.
40 void test_instancetype_alloc_init_simple() {
41 Root *r1 = [[Root alloc] init];
42 Subclass1 *sc1 = [[Subclass1 alloc] init];
45 // Test that message sends to instancetype methods have the right type.
46 void test_instancetype_narrow_method_search() {
47 // instancetype on class methods
48 Subclass1 *sc1 = [[Subclass1 alloc] initSubclass2]; // expected-warning{{'Subclass1' may not respond to 'initSubclass2'}}
49 Subclass2 *sc2 = [[Subclass2 alloc] initSubclass2]; // okay
51 // instancetype on instance methods
52 [[[Subclass1 alloc] init] methodOnSubclass2]; // expected-warning{{'Subclass1' may not respond to 'methodOnSubclass2'}}
53 [[[Subclass2 alloc] init] methodOnSubclass2];
55 // instancetype on class methods using protocols
56 typedef Subclass1<Proto1> SC1Proto1;
57 typedef Subclass1<Proto2> SC1Proto2;
58 [[SC1Proto1 alloc] methodInProto2]; // expected-warning{{method '-methodInProto2' not found (return type defaults to 'id')}}
59 [[SC1Proto2 alloc] methodInProto2];
61 // instancetype on instance methods
62 Subclass1<Proto1> *sc1proto1 = 0;
63 [[sc1proto1 self] methodInProto2]; // expected-warning{{method '-methodInProto2' not found (return type defaults to 'id')}}
64 Subclass1<Proto2> *sc1proto2 = 0;
65 [[sc1proto2 self] methodInProto2];
68 typeof([[Subclass1 alloc] init]) *ptr1 = (Subclass1 **)0;
69 typeof([[Subclass2 alloc] init]) *ptr2 = (Subclass2 **)0;
71 // Message sends to Class.
72 Subclass1<Proto1> *sc1proto1_2 = [[[sc1proto1 class] alloc] init];
75 [sc1proto1.self methodInProto2]; // expected-warning{{method '-methodInProto2' not found (return type defaults to 'id')}}
76 [sc1proto2.self methodInProto2];
77 [Subclass1.alloc initSubclass2]; // expected-warning{{'Subclass1' may not respond to 'initSubclass2'}}
78 [Subclass2.alloc initSubclass2];
80 [sc1proto1.selfProp methodInProto2]; // expected-warning{{method '-methodInProto2' not found (return type defaults to 'id')}}
81 [sc1proto2.selfProp methodInProto2];
84 // Test that message sends to super methods have the right type.
85 @interface Subsubclass1 : Subclass1
86 - (instancetype)initSubclass1;
87 + (instancetype)allocSubclass1;
89 - (void)onlyInSubsubclass1;
92 @implementation Subsubclass1
93 - (instancetype)initSubclass1 {
94 // Check based on method search.
95 [[super initSubclass1] methodOnSubclass2]; // expected-warning{{'Subsubclass1' may not respond to 'methodOnSubclass2'}}
96 [super.initSubclass1 methodOnSubclass2]; // expected-warning{{'Subsubclass1' may not respond to 'methodOnSubclass2'}}
98 self = [super init]; // common pattern
101 typeof([super initSubclass1]) *ptr1 = (Subsubclass1**)0;
106 + (instancetype)allocSubclass1 {
107 // Check based on method search.
108 [[super allocSubclass1] methodOnSubclass2]; // expected-warning{{'Subsubclass1' may not respond to 'methodOnSubclass2'}}
110 // The ASTs don't model super property accesses well enough to get this right
111 [super.allocSubclass1 methodOnSubclass2]; // expected-warning{{'Subsubclass1' may not respond to 'methodOnSubclass2'}}
114 typeof([super allocSubclass1]) *ptr1 = (Subsubclass1**)0;
116 return [super allocSubclass1];
119 - (void)onlyInSubsubclass1 {}
122 // Check compatibility rules for inheritance of related return types.
125 @interface Subclass3 <Proto1, Proto2>
126 - (Subclass3 *)methodInProto1;
127 - (Subclass4 *)methodInProto2; // expected-warning{{method is expected to return an instance of its class type 'Subclass3', but is declared to return 'Subclass4 *'}}
130 @interface Subclass4 : Root
131 + (Subclass4 *)alloc; // okay
132 - (Subclass3 *)init; // expected-warning{{method is expected to return an instance of its class type 'Subclass4', but is declared to return 'Subclass3 *'}}
133 - (id)self; // expected-note{{overridden method is part of the 'self' method family}}
134 - (instancetype)initOther;
137 @protocol Proto3 <Proto1, Proto2>
139 - (id)methodInProto1;
140 - (Subclass1 *)methodInProto2;
141 - (int)otherMethodInProto2; // expected-warning{{protocol method is expected to return an instance of the implementing class, but is declared to return 'int'}}
144 @implementation Subclass4
146 return self; // expected-error{{cannot initialize return object of type 'Subclass4 *' with an lvalue of type 'Class'}}
149 - (Subclass3 *)init { return 0; } // don't complain: we lost the related return type
151 - (Subclass3 *)self { return 0; } // expected-warning{{method is expected to return an instance of its class type 'Subclass4', but is declared to return 'Subclass3 *'}}
153 - (Subclass4 *)initOther { return 0; }
157 // Check that inherited related return types influence the types of
159 void test_instancetype_inherited() {
160 [[Subclass4 alloc] initSubclass1]; // expected-warning{{'Subclass4' may not respond to 'initSubclass1'}}
161 [[Subclass4 alloc] initOther];
164 // Check that related return types tighten up the semantics of
165 // Objective-C method implementations.
166 @implementation Subclass2
167 - (instancetype)initSubclass2 { // expected-note {{explicitly declared 'instancetype'}}
168 Subclass1 *sc1 = [[Subclass1 alloc] init];
169 return sc1; // expected-error{{cannot initialize return object of type 'Subclass2 *' with an lvalue of type 'Subclass1 *'}}
171 - (void)methodOnSubclass2 {}
173 Subclass1 *sc1 = [[Subclass1 alloc] init];
174 return sc1; // expected-error{{cannot initialize return object of type 'Subclass2 *' with an lvalue of type 'Subclass1 *'}}
178 @interface MyClass : Root
179 + (int)myClassMethod;
182 @implementation MyClass
183 + (int)myClassMethod { return 0; }
186 int i = [[MyClass self] myClassMethod];
192 - (instancetype) foo; // expected-note {{current method is explicitly declared 'instancetype' and is expected to return an instance of its class type}}
194 @interface A4 : Root <P4>
195 - (instancetype) bar; // expected-note {{current method is explicitly declared 'instancetype' and is expected to return an instance of its class type}}
196 - (instancetype) baz; // expected-note {{overridden method returns an instance of its class type}} expected-note {{previous definition is here}}
198 @interface B4 : Root @end
204 return _b; // expected-error {{cannot initialize return object of type 'A4 *' with an lvalue of type 'B4 *'}}
207 return _b; // expected-error {{cannot initialize return object of type 'A4 *' with an lvalue of type 'B4 *'}}
210 // This is really just to ensure that we don't crash.
211 // FIXME: only one diagnostic, please
212 - (float) baz { // expected-warning {{method is expected to return an instance of its class type 'A4', but is declared to return 'float'}} expected-warning {{conflicting return type in implementation}}
219 namespace pr27822 { }
220 @interface AXPlatformNodeCocoa
221 + (NSString*)nativeRoleFromAXRole:(pr27822::UndeclaredIdentifier)role; // expected-error {{expected a type}}