Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / clang / test / SemaObjCXX / instancetype.mm
blob5e479f5f27456090b291494098c880e4d149685d
1 // RUN: %clang_cc1 -fsyntax-only -verify %s
3 #if !__has_feature(objc_instancetype)
4 # error Missing 'instancetype' feature macro.
5 #endif
7 @interface Root
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'}}
11 - (Class)class;
13 @property (assign) Root *selfProp;
14 - (instancetype)selfProp;
15 @end
17 @protocol Proto1
18 @optional
19 - (instancetype)methodInProto1;
20 @end
22 @protocol Proto2
23 @optional
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}}
26 @end
28 @interface Subclass1 : Root // expected-note 4 {{receiver is instance of class declared here}}
29 - (instancetype)initSubclass1;
30 - (void)methodOnSubclass1;
31 + (instancetype)allocSubclass1;
32 @end
34 @interface Subclass2 : Root
35 - (instancetype)initSubclass2;
36 - (void)methodOnSubclass2;
37 @end
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];
54   
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];
67   // Exact type checks
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];
74   // Property access
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;
90 @end
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
100   // Exact type check.
101   typeof([super initSubclass1]) *ptr1 = (Subsubclass1**)0;
103   return self;
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'}}
113   // Exact type check.
114   typeof([super allocSubclass1]) *ptr1 = (Subsubclass1**)0;
115   
116   return [super allocSubclass1];
119 - (void)onlyInSubsubclass1 {}
120 @end
122 // Check compatibility rules for inheritance of related return types.
123 @class Subclass4;
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 *'}}
128 @end
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;
135 @end
137 @protocol Proto3 <Proto1, Proto2>
138 @optional
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'}}
142 @end
144 @implementation Subclass4
145 + (id)alloc {
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; }
155 @end
157 // Check that inherited related return types influence the types of
158 // message sends.
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 {}
172 - (id)self {
173   Subclass1 *sc1 = [[Subclass1 alloc] init];
174   return sc1; // expected-error{{cannot initialize return object of type 'Subclass2 *' with an lvalue of type 'Subclass1 *'}}
176 @end
178 @interface MyClass : Root
179 + (int)myClassMethod;
180 @end
182 @implementation MyClass
183 + (int)myClassMethod { return 0; }
185 - (void)blah {
186   int i = [[MyClass self] myClassMethod];
189 @end
191 @protocol P4
192 - (instancetype) foo; // expected-note {{current method is explicitly declared 'instancetype' and is expected to return an instance of its class type}}
193 @end
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}}
197 @end
198 @interface B4 : Root @end
200 @implementation A4 {
201   B4 *_b;
203 - (id) foo {
204   return _b; // expected-error {{cannot initialize return object of type 'A4 *' with an lvalue of type 'B4 *'}}
206 - (id) bar {
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}}
213   return 0;
215 @end
217 // PR27822
218 @class NSString;
219 namespace pr27822 { }
220 @interface AXPlatformNodeCocoa
221 + (NSString*)nativeRoleFromAXRole:(pr27822::UndeclaredIdentifier)role; // expected-error {{expected a type}}
222 @end