1 | // RUN: %clang_cc1 -fblocks %s -verify |
2 | |
3 | #if !__has_feature(objc_generics) |
4 | # error Compiler does not support Objective-C generics? |
5 | #endif |
6 | |
7 | #if !__has_feature(objc_generics_variance) |
8 | # error Compiler does not support co- and contr-variance? |
9 | #endif |
10 | |
11 | @protocol NSObject // expected-note{{'NSObject' declared here}} |
12 | @end |
13 | |
14 | @protocol NSCopying // expected-note{{'NSCopying' declared here}} |
15 | @end |
16 | |
17 | __attribute__((objc_root_class)) |
18 | @interface NSObject <NSObject> // expected-note{{'NSObject' defined here}} |
19 | @end |
20 | |
21 | @interface NSString : NSObject <NSCopying> |
22 | @end |
23 | |
24 | // -------------------------------------------------------------------------- |
25 | // Parsing parameterized classes. |
26 | // -------------------------------------------------------------------------- |
27 | |
28 | // Parse type parameters with a bound |
29 | @interface PC1<T, U : NSObject*> : NSObject // expected-note{{'PC1' declared here}} |
30 | // expected-note@-1{{type parameter 'T' declared here}} |
31 | // expected-note@-2{{type parameter 'U' declared here}} |
32 | // expected-note@-3{{type parameter 'U' declared here}} |
33 | @end |
34 | |
35 | // Parse a type parameter with a bound that terminates in '>>'. |
36 | @interface PC2<T : id<NSObject>> : NSObject |
37 | @end |
38 | |
39 | // Parse multiple type parameters. |
40 | @interface PC3<T, U : id> : NSObject |
41 | @end |
42 | |
43 | // Parse multiple type parameters--grammatically ambiguous with protocol refs. |
44 | @interface PC4<T, U, V> : NSObject // expected-note 2{{'PC4' declared here}} |
45 | @end |
46 | |
47 | // Parse a type parameter list without a superclass. |
48 | @interface PC5<T : id> |
49 | @end |
50 | |
51 | // Parse a type parameter with name conflicts. |
52 | @interface PC6<T, U, |
53 | T> : NSObject // expected-error{{redeclaration of type parameter 'T'}} |
54 | @end |
55 | |
56 | // Parse Objective-C protocol references. |
57 | @interface PC7<T> // expected-error{{cannot find protocol declaration for 'T'}} |
58 | @end |
59 | |
60 | // Parse both type parameters and protocol references. |
61 | @interface PC8<T> : NSObject <NSObject> |
62 | @end |
63 | |
64 | // Type parameters with improper bounds. |
65 | @interface PC9<T : int, // expected-error{{type bound 'int' for type parameter 'T' is not an Objective-C pointer type}} |
66 | U : NSString> : NSObject // expected-error{{missing '*' in type bound 'NSString' for type parameter 'U'}} |
67 | @end |
68 | |
69 | // -------------------------------------------------------------------------- |
70 | // Parsing parameterized forward declarations classes. |
71 | // -------------------------------------------------------------------------- |
72 | |
73 | // Okay: forward declaration without type parameters. |
74 | @class PC10; |
75 | |
76 | // Okay: forward declarations with type parameters. |
77 | @class PC10<T, U : NSObject *>, PC11<T : NSObject *, U : id>; // expected-note{{type parameter 'T' declared here}} |
78 | |
79 | // Okay: forward declaration without type parameters following ones |
80 | // with type parameters. |
81 | @class PC10, PC11; |
82 | |
83 | // Okay: definition of class with type parameters that was formerly |
84 | // declared with the same type parameters. |
85 | @interface PC10<T, U : NSObject *> : NSObject |
86 | @end |
87 | |
88 | // Mismatched parameters in declaration of @interface following @class. |
89 | @interface PC11<T, U> : NSObject // expected-error{{missing type bound 'NSObject *' for type parameter 'T' in @interface}} |
90 | @end |
91 | |
92 | @interface PC12<T : NSObject *> : NSObject // expected-note{{type parameter 'T' declared here}} |
93 | @end |
94 | |
95 | @class PC12; |
96 | |
97 | // Mismatched parameters in subsequent forward declarations. |
98 | @class PC13<T : NSObject *>; // expected-note{{type parameter 'T' declared here}} |
99 | @class PC13; |
100 | @class PC13<U>; // expected-error{{missing type bound 'NSObject *' for type parameter 'U' in @class}} |
101 | |
102 | // Mismatch parameters in declaration of @class following @interface. |
103 | @class PC12<T>; // expected-error{{missing type bound 'NSObject *' for type parameter 'T' in @class}} |
104 | |
105 | // Parameterized forward declaration a class that is not parameterized. |
106 | @class NSObject<T>; // expected-error{{forward declaration of non-parameterized class 'NSObject' cannot have type parameters}} |
107 | // expected-note@-1{{'NSObject' declared here}} |
108 | |
109 | // Parameterized forward declaration preceding the definition (that is |
110 | // not parameterized). |
111 | @class NSNumber<T : NSObject *>; // expected-note{{'NSNumber' declared here}} |
112 | @interface NSNumber : NSObject // expected-error{{class 'NSNumber' previously declared with type parameters}} |
113 | @end |
114 | |
115 | @class PC14; |
116 | |
117 | // Okay: definition of class with type parameters that was formerly |
118 | // declared without type parameters. |
119 | @interface PC14<T, U : NSObject *> : NSObject |
120 | @end |
121 | |
122 | // -------------------------------------------------------------------------- |
123 | // Parsing parameterized categories and extensions. |
124 | // -------------------------------------------------------------------------- |
125 | |
126 | // Inferring type bounds |
127 | @interface PC1<T, U> (Cat1) <NSObject> |
128 | @end |
129 | |
130 | // Matching type bounds |
131 | @interface PC1<T : id, U : NSObject *> (Cat2) <NSObject> |
132 | @end |
133 | |
134 | // Inferring type bounds |
135 | @interface PC1<T, U> () <NSObject> |
136 | @end |
137 | |
138 | // Matching type bounds |
139 | @interface PC1<T : id, U : NSObject *> () <NSObject> |
140 | @end |
141 | |
142 | // Missing type parameters. |
143 | @interface PC1<T> () // expected-error{{extension has too few type parameters (expected 2, have 1)}} |
144 | @end |
145 | |
146 | // Extra type parameters. |
147 | @interface PC1<T, U, V> (Cat3) // expected-error{{category has too many type parameters (expected 2, have 3)}} |
148 | @end |
149 | |
150 | // Mismatched bounds. |
151 | @interface PC1<T : NSObject *, // expected-error{{type bound 'NSObject *' for type parameter 'T' conflicts with implicit bound 'id'}} |
152 | X : id> () // expected-error{{type bound 'id' for type parameter 'X' conflicts with previous bound 'NSObject *'for type parameter 'U'}} |
153 | @end |
154 | |
155 | // Parameterized category/extension of non-parameterized class. |
156 | @interface NSObject<T> (Cat1) // expected-error{{category of non-parameterized class 'NSObject' cannot have type parameters}} |
157 | @end |
158 | |
159 | @interface NSObject<T> () // expected-error{{extension of non-parameterized class 'NSObject' cannot have type parameters}} |
160 | @end |
161 | |
162 | // -------------------------------------------------------------------------- |
163 | // @implementations cannot have type parameters |
164 | // -------------------------------------------------------------------------- |
165 | @implementation PC1<T : id> // expected-error{{@implementation cannot have type parameters}} |
166 | @end |
167 | |
168 | @implementation PC2<T> // expected-error{{@implementation declaration cannot be protocol qualified}} |
169 | @end |
170 | |
171 | @implementation PC1<T> (Cat1) // expected-error{{@implementation cannot have type parameters}} |
172 | @end |
173 | |
174 | @implementation PC1<T : id> (Cat2) // expected-error{{@implementation cannot have type parameters}} |
175 | @end |
176 | |
177 | typedef T undeclaredT; // expected-error{{unknown type name 'T'}} |
178 | |
179 | // -------------------------------------------------------------------------- |
180 | // Interfaces involving type parameters |
181 | // -------------------------------------------------------------------------- |
182 | @interface PC20<T : id, U : NSObject *, V : NSString *> : NSObject { |
183 | T object; |
184 | } |
185 | |
186 | - (U)method:(V)param; |
187 | @end |
188 | |
189 | @interface PC20<T, U, V> (Cat1) |
190 | - (U)catMethod:(V)param; |
191 | @end |
192 | |
193 | @interface PC20<X, Y, Z>() |
194 | - (X)extMethod:(Y)param; |
195 | @end |
196 | |
197 | // -------------------------------------------------------------------------- |
198 | // Parsing type arguments. |
199 | // -------------------------------------------------------------------------- |
200 | |
201 | typedef NSString * ObjCStringRef; // expected-note{{'ObjCStringRef' declared here}} |
202 | |
203 | // Type arguments with a mix of identifiers and type-names. |
204 | typedef PC4<id, NSObject *, NSString *> typeArgs1; |
205 | |
206 | // Type arguments with only identifiers. |
207 | typedef PC4<id, id, id> typeArgs2; |
208 | |
209 | // Type arguments with only identifiers; one is ambiguous (resolved as |
210 | // types). |
211 | typedef PC4<NSObject, id, id> typeArgs3; // expected-error{{type argument 'NSObject' must be a pointer (requires a '*')}} |
212 | |
213 | // Type arguments with only identifiers; one is ambiguous (resolved as |
214 | // protocol qualifiers). |
215 | typedef PC4<NSObject, NSCopying> protocolQuals1; |
216 | |
217 | // Type arguments and protocol qualifiers. |
218 | typedef PC4<id, NSObject *, id><NSObject, NSCopying> typeArgsAndProtocolQuals1; |
219 | |
220 | // Type arguments and protocol qualifiers in the wrong order. |
221 | typedef PC4<NSObject, NSCopying><id, NSObject *, id> typeArgsAndProtocolQuals2; // expected-error{{protocol qualifiers must precede type arguments}} |
222 | |
223 | // Type arguments and protocol qualifiers (identifiers). |
224 | typedef PC4<id, NSObject, id><NSObject, NSCopying> typeArgsAndProtocolQuals3; // expected-error{{type argument 'NSObject' must be a pointer (requires a '*')}} |
225 | |
226 | // Typo correction: protocol bias. |
227 | typedef PC4<NSCopying, NSObjec> protocolQuals2; // expected-error{{cannot find protocol declaration for 'NSObjec'; did you mean 'NSObject'?}} |
228 | |
229 | // Typo correction: type bias. |
230 | typedef PC4<id, id, NSObjec> typeArgs4; // expected-error{{unknown class name 'NSObjec'; did you mean 'NSObject'?}} |
231 | // expected-error@-1{{type argument 'NSObject' must be a pointer (requires a '*')}} |
232 | |
233 | // Typo correction: bias set by correction itself to a protocol. |
234 | typedef PC4<NSObject, NSObject, NSCopyin> protocolQuals3; // expected-error{{cannot find protocol declaration for 'NSCopyin'; did you mean 'NSCopying'?}} |
235 | |
236 | // Typo correction: bias set by correction itself to a type. |
237 | typedef PC4<NSObject, NSObject, ObjCStringref> typeArgs5; // expected-error{{unknown type name 'ObjCStringref'; did you mean 'ObjCStringRef'?}} |
238 | // expected-error@-1{{type argument 'NSObject' must be a pointer (requires a '*')}} |
239 | // expected-error@-2{{type argument 'NSObject' must be a pointer (requires a '*')}} |
240 | |
241 | // Type/protocol conflict. |
242 | typedef PC4<NSCopying, ObjCStringRef> typeArgsProtocolQualsConflict1; // expected-error{{angle brackets contain both a type ('ObjCStringRef') and a protocol ('NSCopying')}} |
243 | typedef PC4<NSCopying, NSString *> typeArgsProtocolQualsConflict2; // expected-error{{angle brackets contain both a type ('NSString') and a protocol ('NSCopying')}} |
244 | typedef PC4<NSCopying, UnknownType, NSString *> typeArgsProtocolQualsConflict3; // expected-error{{angle brackets contain both a type ('NSString') and a protocol ('NSCopying')}} expected-error{{unknown type name 'UnknownType'}} |
245 | typedef PC4<UnknownType, NSString *> typeArgsProtocolQualsConflict4; // expected-error{{unknown type name 'UnknownType'}} |
246 | typedef PC4<NSString, NSCopying, NSString *> typeArgsProtocolQualsConflict5; // expected-error{{angle brackets contain both a type ('NSString') and a protocol ('NSCopying')}} |
247 | |
248 | // Handling the '>>' in type argument lists. |
249 | typedef PC4<id<NSCopying>, NSObject *, id<NSObject>> typeArgs6; |
250 | |
251 | // -------------------------------------------------------------------------- |
252 | // Checking type arguments. |
253 | // -------------------------------------------------------------------------- |
254 | |
255 | @interface PC15<T : id, U : NSObject *, V : id<NSCopying>> : NSObject |
256 | // expected-note@-1{{type parameter 'V' declared here}} |
257 | // expected-note@-2{{type parameter 'V' declared here}} |
258 | // expected-note@-3{{type parameter 'U' declared here}} |
259 | @end |
260 | |
261 | typedef PC4<NSString *> tooFewTypeArgs1; // expected-error{{too few type arguments for class 'PC4' (have 1, expected 3)}} |
262 | |
263 | typedef PC4<NSString *, NSString *, NSString *, NSString *> tooManyTypeArgs1; // expected-error{{too many type arguments for class 'PC4' (have 4, expected 3)}} |
264 | |
265 | typedef PC15<int (^)(int, int), // block pointers as 'id' |
266 | NSString *, // subclass |
267 | NSString *> typeArgs7; // class that conforms to the protocol |
268 | |
269 | typedef PC15<NSObject *, NSObject *, id<NSCopying>> typeArgs8; |
270 | |
271 | typedef PC15<NSObject *, NSObject *, |
272 | NSObject *> typeArgs8b; // expected-error{{type argument 'NSObject *' does not satisfy the bound ('id<NSCopying>') of type parameter 'V'}} |
273 | |
274 | typedef PC15<id, |
275 | id, // expected-error{{type argument 'id' does not satisfy the bound ('NSObject *') of type parameter 'U'}} |
276 | id> typeArgs9; |
277 | |
278 | typedef PC15<id, NSObject *, |
279 | id> typeArgs10; // expected-error{{type argument 'id' does not satisfy the bound ('id<NSCopying>') of type parameter 'V'}} |
280 | |
281 | typedef PC15<id, |
282 | int (^)(int, int), // okay |
283 | id<NSCopying, NSObject>> typeArgs11; |
284 | |
285 | typedef PC15<id, NSString *, int (^)(int, int)> typeArgs12; // okay |
286 | |
287 | typedef NSObject<id, id> typeArgs13; // expected-error{{type arguments cannot be applied to non-parameterized class 'NSObject'}} |
288 | |
289 | typedef id<id, id> typeArgs14; // expected-error{{type arguments cannot be applied to non-class type 'id'}} |
290 | |
291 | typedef PC1<NSObject *, NSString *> typeArgs15; |
292 | |
293 | typedef PC1<NSObject *, NSString *><NSCopying> typeArgsAndProtocolQuals4; |
294 | |
295 | typedef typeArgs15<NSCopying> typeArgsAndProtocolQuals5; |
296 | |
297 | typedef typeArgs15<NSObject *, NSString *> typeArgs16; // expected-error{{type arguments cannot be applied to already-specialized class type 'typeArgs15' (aka 'PC1<NSObject *,NSString *>')}} |
298 | |
299 | typedef typeArgs15<NSObject> typeArgsAndProtocolQuals6; |
300 | |
301 | void testSpecializedTypePrinting() { |
302 | int *ip; |
303 | |
304 | ip = (typeArgs15*)0; // expected-warning{{'typeArgs15 *' (aka 'PC1<NSObject *,NSString *> *')}} |
305 | ip = (typeArgsAndProtocolQuals4*)0; // expected-warning{{'typeArgsAndProtocolQuals4 *' (aka 'PC1<NSObject *,NSString *><NSCopying> *')}} |
306 | ip = (typeArgsAndProtocolQuals5*)0; // expected-warning{{'typeArgsAndProtocolQuals5 *' (aka 'typeArgs15<NSCopying> *')}} |
307 | ip = (typeArgsAndProtocolQuals6)0; // expected-error{{used type 'typeArgsAndProtocolQuals6' (aka 'typeArgs15<NSObject>')}} |
308 | ip = (typeArgsAndProtocolQuals6*)0;// expected-warning{{'typeArgsAndProtocolQuals6 *' (aka 'typeArgs15<NSObject> *')}} |
309 | } |
310 | |
311 | // -------------------------------------------------------------------------- |
312 | // Specialized superclasses |
313 | // -------------------------------------------------------------------------- |
314 | @interface PC21<T : NSObject *> : PC1<T, T> |
315 | @end |
316 | |
317 | @interface PC22<T : NSObject *> : PC1<T> // expected-error{{too few type arguments for class 'PC1' (have 1, expected 2)}} |
318 | @end |
319 | |
320 | @interface PC23<T : NSObject *> : PC1<T, U> // expected-error{{unknown type name 'U'}} |
321 | @end |
322 | |
323 | @interface PC24<T> : PC1<T, T> // expected-error{{type argument 'T' (aka 'id') does not satisfy the bound ('NSObject *') of type parameter 'U'}} |
324 | @end |
325 | |
326 | @interface NSFoo : PC1<NSObject *, NSObject *> // okay |
327 | @end |
328 | |
329 | // -------------------------------------------------------------------------- |
330 | // Co- and contra-variance. |
331 | // -------------------------------------------------------------------------- |
332 | @class Variance1<T, U>; |
333 | |
334 | @class Variance1<__covariant T, __contravariant U>; |
335 | |
336 | @interface Variance1<__covariant T, __contravariant U> : NSObject // expected-note 2{{declared here}} |
337 | @end |
338 | |
339 | @interface Variance1<T, U> () // okay, inferred |
340 | @end |
341 | |
342 | @interface Variance1<T, U> (Cat1) // okay, inferred |
343 | @end |
344 | |
345 | @class Variance1<T, U>; // okay, inferred |
346 | |
347 | @interface Variance1<__covariant T, __contravariant U> () // okay, matches |
348 | @end |
349 | |
350 | @interface Variance1<__covariant T, __contravariant U> (Cat2) // okay, matches |
351 | @end |
352 | |
353 | @class Variance1<__covariant T, __contravariant U>; // okay, matches |
354 | |
355 | @interface Variance1<__contravariant X, // expected-error{{contravariant type parameter 'X' conflicts with previous covariant type parameter 'T'}} |
356 | __covariant Y> () // expected-error{{covariant type parameter 'Y' conflicts with previous contravariant type parameter 'U'}} |
357 | @end |
358 | |
359 | @class Variance2<__covariant T, __contravariant U>; // expected-note 2{{declared here}} |
360 | |
361 | @interface Variance2<__contravariant T, // expected-error{{contravariant type parameter 'T' conflicts with previous covariant type parameter 'T'}} |
362 | U> : NSObject // expected-error{{invariant type parameter 'U' conflicts with previous contravariant type parameter 'U'}} |
363 | @end |
364 | |