1 // RUN: %clang_cc1 -fblocks -fsyntax-only -std=c++11 %s -verify
3 // Test the substitution of type arguments for type parameters when
4 // using parameterized classes in Objective-C.
6 __attribute__((objc_root_class))
15 @interface NSString : NSObject <NSCopying>
18 @interface NSMutableString : NSString
21 @interface NSNumber : NSObject <NSCopying>
24 @interface NSArray<T> : NSObject <NSCopying> {
26 T *data; // don't try this at home
28 - (T)objectAtIndexedSubscript:(int)index;
29 + (NSArray<T> *)array;
30 @property (copy,nonatomic) T lastObject;
33 @interface NSMutableArray<T> : NSArray<T>
34 -(instancetype)initWithArray:(NSArray<T> *)array; // expected-note{{passing argument}}
35 - (void)setObject:(T)object atIndexedSubscript:(int)index; // expected-note 2{{passing argument to parameter 'object' here}}
38 @interface NSStringArray : NSArray<NSString *>
41 @interface NSSet<T> : NSObject <NSCopying>
43 @property (nonatomic, copy) NSArray<T> *allObjects;
46 // Parameterized inheritance (simple case)
47 @interface NSMutableSet<U : id<NSCopying>> : NSSet<U>
48 - (void)addObject:(U)object; // expected-note 7{{passing argument to parameter 'object' here}}
51 @interface Widget : NSObject <NSCopying>
54 // Non-parameterized class inheriting from a specialization of a
55 // parameterized class.
56 @interface WidgetSet : NSMutableSet<Widget *>
59 // Parameterized inheritance with a more interesting transformation in
60 // the specialization.
61 @interface MutableSetOfArrays<T> : NSMutableSet<NSArray<T>*>
64 // Inheriting from an unspecialized form of a parameterized type.
65 @interface UntypedMutableSet : NSMutableSet
68 @interface Window : NSObject
71 @interface NSDictionary<K, V> : NSObject <NSCopying>
72 - (V)objectForKeyedSubscript:(K)key; // expected-note 2{{parameter 'key'}}
75 @interface NSMutableDictionary<K : id<NSCopying>, V> : NSDictionary<K, V> // expected-note 2{{type parameter 'K' declared here}} \
76 // expected-note 2{{'NSMutableDictionary' declared here}}
77 - (void)setObject:(V)object forKeyedSubscript:(K)key;
78 // expected-note@-1 {{parameter 'object' here}}
79 // expected-note@-2 {{parameter 'object' here}}
80 // expected-note@-3 {{parameter 'key' here}}
81 // expected-note@-4 {{parameter 'key' here}}
83 @property (strong) K someRandomKey;
86 @interface WindowArray : NSArray<Window *>
89 @interface NSSet<T> (Searching)
90 - (T)findObject:(T)object;
94 // --------------------------------------------------------------------------
96 // --------------------------------------------------------------------------
97 void test_message_send_result(
98 NSSet<NSString *> *stringSet,
99 NSMutableSet<NSString *> *mutStringSet,
100 WidgetSet *widgetSet,
101 UntypedMutableSet *untypedMutSet,
102 MutableSetOfArrays<NSString *> *mutStringArraySet,
104 NSMutableSet *mutSet,
105 MutableSetOfArrays *mutArraySet,
106 NSArray<NSString *> *stringArray,
107 void (^block)(void)) {
109 ip = [stringSet firstObject]; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSString *'}}
110 ip = [mutStringSet firstObject]; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSString *'}}
111 ip = [widgetSet firstObject]; // expected-error{{incompatible pointer types assigning to 'int *' from 'Widget *'}}
112 ip = [untypedMutSet firstObject]; // expected-error{{incompatible pointer types assigning to 'int *' from 'id'}}
113 ip = [mutStringArraySet firstObject]; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray<NSString *> *'}}
114 ip = [set firstObject]; // expected-error{{incompatible pointer types assigning to 'int *' from 'id'}}
115 ip = [mutSet firstObject]; // expected-error{{incompatible pointer types assigning to 'int *' from 'id'}}
116 ip = [mutArraySet firstObject]; // expected-error{{incompatible pointer types assigning to 'int *' from 'id'}}
117 ip = [block firstObject]; // expected-error{{incompatible pointer types assigning to 'int *' from 'id'}}
119 ip = [stringSet findObject:@"blah"]; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSString *'}}
122 ip = [NSSet<NSString *> alloc]; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSSet<NSString *> *'}}
123 ip = [NSSet alloc]; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSSet *'}}
124 ip = [MutableSetOfArrays<NSString *> alloc]; // expected-error{{incompatible pointer types assigning to 'int *' from 'MutableSetOfArrays<NSString *> *'}}
125 ip = [MutableSetOfArrays alloc]; // expected-error{{incompatible pointer types assigning to 'int *' from 'MutableSetOfArrays *'}}
126 ip = [NSArray<NSString *> array]; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray<NSString *> *'}}
127 ip = [NSArray<NSString *><NSCopying> array]; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray<NSString *> *'}}
129 ip = [[NSMutableArray<NSString *> alloc] init]; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSMutableArray<NSString *> *'}}
131 [[NSMutableArray alloc] initWithArray: stringArray]; // okay
132 [[NSMutableArray<NSString *> alloc] initWithArray: stringArray]; // okay
133 [[NSMutableArray<NSNumber *> alloc] initWithArray: stringArray]; // expected-error{{parameter of type 'NSArray<NSNumber *> *' with an lvalue of type 'NSArray<NSString *> *'}}
136 void test_message_send_param(
137 NSMutableSet<NSString *> *mutStringSet,
138 WidgetSet *widgetSet,
139 UntypedMutableSet *untypedMutSet,
140 MutableSetOfArrays<NSString *> *mutStringArraySet,
141 NSMutableSet *mutSet,
142 MutableSetOfArrays *mutArraySet,
143 void (^block)(void)) {
146 [mutStringSet addObject: window]; // expected-error{{parameter of type 'NSString *'}}
147 [widgetSet addObject: window]; // expected-error{{parameter of type 'Widget *'}}
148 [untypedMutSet addObject: window]; // expected-error{{parameter of type 'id<NSCopying>'}}
149 [mutStringArraySet addObject: window]; // expected-error{{parameter of type 'NSArray<NSString *> *'}}
150 [mutSet addObject: window]; // expected-error{{parameter of type 'id<NSCopying>'}}
151 [mutArraySet addObject: window]; // expected-error{{parameter of type 'id<NSCopying>'}}
152 [block addObject: window]; // expected-error{{parameter of type 'id<NSCopying>'}}
155 // --------------------------------------------------------------------------
156 // Property accesses.
157 // --------------------------------------------------------------------------
158 void test_property_read(
159 NSSet<NSString *> *stringSet,
160 NSMutableSet<NSString *> *mutStringSet,
161 WidgetSet *widgetSet,
162 UntypedMutableSet *untypedMutSet,
163 MutableSetOfArrays<NSString *> *mutStringArraySet,
165 NSMutableSet *mutSet,
166 MutableSetOfArrays *mutArraySet,
167 NSMutableDictionary *mutDict) {
169 ip = stringSet.allObjects; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray<NSString *> *'}}
170 ip = mutStringSet.allObjects; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray<NSString *> *'}}
171 ip = widgetSet.allObjects; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray<Widget *> *'}}
172 ip = untypedMutSet.allObjects; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray *'}}
173 ip = mutStringArraySet.allObjects; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray<NSArray<NSString *> *> *'}}
174 ip = set.allObjects; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray *'}}
175 ip = mutSet.allObjects; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray *'}}
176 ip = mutArraySet.allObjects; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray *'}}
178 ip = mutDict.someRandomKey; // expected-error{{incompatible pointer types assigning to 'int *' from '__kindof id<NSCopying>'}}
181 void test_property_write(
182 NSMutableSet<NSString *> *mutStringSet,
183 WidgetSet *widgetSet,
184 UntypedMutableSet *untypedMutSet,
185 MutableSetOfArrays<NSString *> *mutStringArraySet,
186 NSMutableSet *mutSet,
187 MutableSetOfArrays *mutArraySet,
188 NSMutableDictionary *mutDict) {
191 mutStringSet.allObjects = ip; // expected-error{{to 'NSArray<NSString *> *'}}
192 widgetSet.allObjects = ip; // expected-error{{to 'NSArray<Widget *> *'}}
193 untypedMutSet.allObjects = ip; // expected-error{{to 'NSArray *'}}
194 mutStringArraySet.allObjects = ip; // expected-error{{to 'NSArray<NSArray<NSString *> *> *'}}
195 mutSet.allObjects = ip; // expected-error{{to 'NSArray *'}}
196 mutArraySet.allObjects = ip; // expected-error{{to 'NSArray *'}}
198 mutDict.someRandomKey = ip; // expected-error{{to 'id<NSCopying>'}}
201 // --------------------------------------------------------------------------
203 // --------------------------------------------------------------------------
204 void test_subscripting(
205 NSArray<NSString *> *stringArray,
206 NSMutableArray<NSString *> *mutStringArray,
208 NSMutableArray *mutArray,
209 NSDictionary<NSString *, Widget *> *stringWidgetDict,
210 NSMutableDictionary<NSString *, Widget *> *mutStringWidgetDict,
212 NSMutableDictionary *mutDict) {
218 ip = stringArray[0]; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSString *'}}
220 ip = mutStringArray[0]; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSString *'}}
221 mutStringArray[0] = ip; // expected-error{{parameter of type 'NSString *'}}
223 ip = array[0]; // expected-error{{incompatible pointer types assigning to 'int *' from 'id'}}
225 ip = mutArray[0]; // expected-error{{incompatible pointer types assigning to 'int *' from 'id'}}
226 mutArray[0] = ip; // expected-error{{parameter of type 'id'}}
228 ip = stringWidgetDict[string]; // expected-error{{incompatible pointer types assigning to 'int *' from 'Widget *'}}
229 widget = stringWidgetDict[widget]; // expected-error{{parameter of type 'NSString *'}}
231 ip = mutStringWidgetDict[string]; // expected-error{{incompatible pointer types assigning to 'int *' from 'Widget *'}}
232 widget = mutStringWidgetDict[widget]; // expected-error{{parameter of type 'NSString *'}}
233 mutStringWidgetDict[string] = ip; // expected-error{{parameter of type 'Widget *'}}
234 mutStringWidgetDict[widget] = widget; // expected-error{{parameter of type 'NSString *'}}
236 ip = dict[string]; // expected-error{{incompatible pointer types assigning to 'int *' from 'id'}}
238 ip = mutDict[string]; // expected-error{{incompatible pointer types assigning to 'int *' from 'id'}}
239 mutDict[string] = ip; // expected-error{{parameter of type 'id'}}
241 widget = mutDict[window];
242 mutDict[window] = widget; // expected-error{{parameter of type 'id<NSCopying>'}}
245 // --------------------------------------------------------------------------
246 // Instance variable access.
247 // --------------------------------------------------------------------------
248 void test_instance_variable(NSArray<NSString *> *stringArray,
252 ip = stringArray->data; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSString **'}}
253 ip = array->data; // expected-error{{incompatible pointer types assigning to 'int *' from 'id *'}}
256 @implementation WindowArray
257 - (void)testInstanceVariable {
260 ip = data; // expected-error{{incompatible pointer types assigning to 'int *' from 'Window **'}}
264 // --------------------------------------------------------------------------
265 // Implicit conversions.
266 // --------------------------------------------------------------------------
267 void test_implicit_conversions(NSArray<NSString *> *stringArray,
268 NSArray<NSNumber *> *numberArray,
269 NSMutableArray<NSString *> *mutStringArray,
271 NSMutableArray *mutArray) {
272 // Specialized -> unspecialized (same level)
275 // Unspecialized -> specialized (same level)
278 // Specialized -> specialized failure (same level).
279 stringArray = numberArray; // expected-error{{incompatible pointer types assigning to 'NSArray<NSString *> *' from 'NSArray<NSNumber *> *'}}
281 // Specialized -> specialized (different levels).
282 stringArray = mutStringArray;
284 // Specialized -> specialized failure (different levels).
285 numberArray = mutStringArray; // expected-error{{incompatible pointer types assigning to 'NSArray<NSNumber *> *' from 'NSMutableArray<NSString *> *'}}
287 // Unspecialized -> specialized (different levels).
288 stringArray = mutArray;
290 // Specialized -> unspecialized (different levels).
291 array = mutStringArray;
294 @interface NSCovariant1<__covariant T>
297 @interface NSContravariant1<__contravariant T>
300 void test_variance(NSCovariant1<NSString *> *covariant1,
301 NSCovariant1<NSMutableString *> *covariant2,
302 NSCovariant1<NSString *(^)(void)> *covariant3,
303 NSCovariant1<NSMutableString *(^)(void)> *covariant4,
304 NSCovariant1<id> *covariant5,
305 NSCovariant1<id<NSCopying>> *covariant6,
306 NSContravariant1<NSString *> *contravariant1,
307 NSContravariant1<NSMutableString *> *contravariant2) {
308 covariant1 = covariant2; // okay
309 covariant2 = covariant1; // expected-warning{{incompatible pointer types assigning to 'NSCovariant1<NSMutableString *> *' from 'NSCovariant1<NSString *> *'}}
311 covariant3 = covariant4; // okay
312 covariant4 = covariant3; // expected-warning{{incompatible pointer types assigning to 'NSCovariant1<NSMutableString *(^)()> *' from 'NSCovariant1<NSString *(^)()> *'}}
314 covariant5 = covariant1; // okay
315 covariant1 = covariant5; // okay: id is promiscuous
317 covariant5 = covariant3; // okay
318 covariant3 = covariant5; // okay
320 contravariant1 = contravariant2; // expected-warning{{incompatible pointer types assigning to 'NSContravariant1<NSString *> *' from 'NSContravariant1<NSMutableString *> *'}}
321 contravariant2 = contravariant1; // okay
324 // --------------------------------------------------------------------------
326 // --------------------------------------------------------------------------
327 void test_ternary_operator(NSArray<NSString *> *stringArray,
328 NSArray<NSNumber *> *numberArray,
329 NSMutableArray<NSString *> *mutStringArray,
330 NSStringArray *stringArray2,
332 NSMutableArray *mutArray,
337 ip = cond ? stringArray : mutStringArray; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray<NSString *> *'}}
338 ip = cond ? mutStringArray : stringArray; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray<NSString *> *'}}
340 ip = cond ? stringArray2 : mutStringArray; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray<NSString *> *'}}
341 ip = cond ? mutStringArray : stringArray2; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray<NSString *> *'}}
343 ip = cond ? stringArray : mutArray; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray *'}}
345 ip = cond ? stringArray2 : mutArray; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray *'}}
347 ip = cond ? mutArray : stringArray; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray *'}}
349 ip = cond ? mutArray : stringArray2; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray *'}}
351 object = cond ? stringArray : numberArray; // expected-warning{{incompatible operand types ('NSArray<NSString *> *' and 'NSArray<NSNumber *> *')}}
354 // --------------------------------------------------------------------------
356 // --------------------------------------------------------------------------
357 @implementation NSStringArray
358 - (void)useSuperMethod {
360 ip = super.lastObject; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSString *'}}
361 ip = [super objectAtIndexedSubscript:0]; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSString *'}}
364 + (void)useSuperMethod {
366 ip = super.array; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray<NSString *> *'}}
367 ip = [super array]; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray<NSString *> *'}}
371 // --------------------------------------------------------------------------
372 // Template instantiation
373 // --------------------------------------------------------------------------
374 template<typename K, typename V>
375 struct NSMutableDictionaryOf {
376 typedef NSMutableDictionary<K, V> *type; // expected-error{{type argument 'NSObject *' does not satisfy the bound ('id<NSCopying>') of type parameter 'K'}}
379 template<typename ...Args>
380 struct VariadicNSMutableDictionaryOf {
381 typedef NSMutableDictionary<Args...> *type; // expected-error{{type argument 'NSObject *' does not satisfy the bound ('id<NSCopying>') of type parameter 'K'}}
382 // expected-error@-1{{too many type arguments for class 'NSMutableDictionary' (have 3, expected 2)}}
383 // expected-error@-2{{too few type arguments for class 'NSMutableDictionary' (have 1, expected 2)}}
386 void testInstantiation() {
389 typedef NSMutableDictionaryOf<NSString *, NSObject *>::type Dict1;
390 Dict1 d1 = ip; // expected-error{{cannot initialize a variable of type 'Dict1' (aka 'NSMutableDictionary<NSString *,NSObject *> *')}}
392 typedef NSMutableDictionaryOf<NSObject *, NSString *>::type Dict2; // expected-note{{in instantiation of template}}
395 void testVariadicInstantiation() {
398 typedef VariadicNSMutableDictionaryOf<NSString *, NSObject *>::type Dict1;
399 Dict1 d1 = ip; // expected-error{{cannot initialize a variable of type 'Dict1' (aka 'NSMutableDictionary<NSString *,NSObject *> *')}}
401 typedef VariadicNSMutableDictionaryOf<NSObject *, NSString *>::type Dict2; // expected-note{{in instantiation of template}}
403 typedef VariadicNSMutableDictionaryOf<NSString *, NSObject *, NSObject *>::type Dict3; // expected-note{{in instantiation of template}}
405 typedef VariadicNSMutableDictionaryOf<NSString *>::type Dict3; // expected-note{{in instantiation of template}}
408 // --------------------------------------------------------------------------
409 // Parameterized classes are not templates
410 // --------------------------------------------------------------------------
411 template<template<typename T, typename U> class TT>
412 struct AcceptsTemplateTemplate { };
414 typedef AcceptsTemplateTemplate<NSMutableDictionary> TemplateTemplateFail1; // expected-error{{template argument for template template parameter must be a class template or type alias template}}
417 struct DependentTemplate {
418 typedef typename T::template apply<NSString *, NSObject *> type; // expected-error{{'apply' following the 'template' keyword does not refer to a template}}
421 struct NSMutableDictionaryBuilder {
422 typedef NSMutableDictionary apply; // expected-note 2{{declared as a non-template here}}
425 typedef DependentTemplate<NSMutableDictionaryBuilder>::type DependentTemplateFail1; // expected-note{{in instantiation of template class}}
427 template<typename K, typename V>
428 struct NonDependentTemplate {
429 typedef NSMutableDictionaryBuilder::template apply<NSString *, NSObject *> type; // expected-error{{'apply' following the 'template' keyword does not refer to a template}}
432 // However, one can use an alias template to turn a parameterized
433 // class into a template.
434 template<typename K, typename V>
435 using NSMutableDictionaryAlias = NSMutableDictionary<K, V>;
437 typedef AcceptsTemplateTemplate<NSMutableDictionaryAlias> TemplateTemplateAlias1; // okay