1 // RUN: %clang_cc1 -fsyntax-only -verify %s 2 3 #if !__has_feature(objc_instancetype) 4 # error Missing 'instancetype' feature macro. 5 #endif 6 7 @interface Root 8 + (instancetype)alloc; 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; 12 13 @property (assign) Root *selfProp; 14 - (instancetype)selfProp; 15 @end 16 17 @protocol Proto1 18 @optional 19 - (instancetype)methodInProto1; 20 @end 21 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 27 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 33 34 @interface Subclass2 : Root 35 - (instancetype)initSubclass2; 36 - (void)methodOnSubclass2; 37 @end 38 39 // Sanity check: the basic initialization pattern. 40 void test_instancetype_alloc_init_simple() { 41 Root *r1 = [[Root alloc] init]; 42 Subclass1 *sc1 = [[Subclass1 alloc] init]; 43 } 44 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 50 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]; 60 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]; 66 67 // Exact type checks 68 typeof([[Subclass1 alloc] init]) *ptr1 = (Subclass1 **)0; 69 typeof([[Subclass2 alloc] init]) *ptr2 = (Subclass2 **)0; 70 71 // Message sends to Class. 72 Subclass1<Proto1> *sc1proto1_2 = [[[sc1proto1 class] alloc] init]; 73 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]; 79 80 [sc1proto1.selfProp methodInProto2]; // expected-warning{{method '-methodInProto2' not found (return type defaults to 'id')}} 81 [sc1proto2.selfProp methodInProto2]; 82 } 83 84 // Test that message sends to super methods have the right type. 85 @interface Subsubclass1 : Subclass1 86 - (instancetype)initSubclass1; 87 + (instancetype)allocSubclass1; 88 89 - (void)onlyInSubsubclass1; 90 @end 91 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'}} 97 98 self = [super init]; // common pattern 99 100 // Exact type check. 101 typeof([super initSubclass1]) *ptr1 = (Subsubclass1**)0; 102 103 return self; 104 } 105 106 + (instancetype)allocSubclass1 { 107 // Check based on method search. 108 [[super allocSubclass1] methodOnSubclass2]; // expected-warning{{'Subsubclass1' may not respond to 'methodOnSubclass2'}} 109 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'}} 112 113 // Exact type check. 114 typeof([super allocSubclass1]) *ptr1 = (Subsubclass1**)0; 115 116 return [super allocSubclass1]; 117 } 118 119 - (void)onlyInSubsubclass1 {} 120 @end 121 122 // Check compatibility rules for inheritance of related return types. 123 @class Subclass4; 124 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 129 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 136 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 143 144 @implementation Subclass4 145 + (id)alloc { 146 return self; // FIXME: we accept this in ObjC++ but not ObjC? 147 } 148 149 - (Subclass3 *)init { return 0; } // don't complain: we lost the related return type 150 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 *'}} 152 153 - (Subclass4 *)initOther { return 0; } 154 155 @end 156 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]; 162 } 163 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 *'}} 170 } 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 *'}} 175 } 176 @end 177 178 @interface MyClass : Root 179 + (int)myClassMethod; 180 @end 181 182 @implementation MyClass 183 + (int)myClassMethod { return 0; } 184 185 - (void)blah { 186 int i = [[MyClass self] myClassMethod]; 187 } 188 189 @end 190 191 // rdar://12493140 192 @protocol P4 193 - (instancetype) foo; // expected-note {{current method is explicitly declared 'instancetype' and is expected to return an instance of its class type}} 194 @end 195 @interface A4 : Root <P4> 196 - (instancetype) bar; // expected-note {{current method is explicitly declared 'instancetype' and is expected to return an instance of its class type}} 197 - (instancetype) baz; // expected-note {{overridden method returns an instance of its class type}} expected-note {{previous definition is here}} 198 @end 199 @interface B4 : Root @end 200 201 @implementation A4 { 202 B4 *_b; 203 } 204 - (id) foo { 205 return _b; // expected-error {{cannot initialize return object of type 'A4 *' with an lvalue of type 'B4 *'}} 206 } 207 - (id) bar { 208 return _b; // expected-error {{cannot initialize return object of type 'A4 *' with an lvalue of type 'B4 *'}} 209 } 210 211 // This is really just to ensure that we don't crash. 212 // FIXME: only one diagnostic, please 213 - (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}} 214 return 0; 215 } 216 @end 217 218 // PR27822 219 @class NSString; 220 namespace pr27822 { } 221 @interface AXPlatformNodeCocoa 222 + (NSString*)nativeRoleFromAXRole:(pr27822::UndeclaredIdentifier)role; // expected-error {{expected a type}} 223 @end 224