[clang] Implement lifetime analysis for lifetime_capture_by(X) (#115921)
[llvm-project.git] / clang / test / SemaObjCXX / parameterized_classes_subst.mm
blob8aacf21faf0913135843cf7673497dfdbfe7f07c
1 // RUN: %clang_cc1 -fblocks -fsyntax-only -std=c++11 %s -verify
2 //
3 // Test the substitution of type arguments for type parameters when
4 // using parameterized classes in Objective-C.
6 __attribute__((objc_root_class))
7 @interface NSObject
8 + (instancetype)alloc;
9 - (instancetype)init;
10 @end
12 @protocol NSCopying
13 @end
15 @interface NSString : NSObject <NSCopying>
16 @end
18 @interface NSMutableString : NSString
19 @end
21 @interface NSNumber : NSObject <NSCopying>
22 @end
24 @interface NSArray<T> : NSObject <NSCopying> {
25 @public
26   T *data; // don't try this at home
28 - (T)objectAtIndexedSubscript:(int)index;
29 + (NSArray<T> *)array;
30 @property (copy,nonatomic) T lastObject;
31 @end
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}}
36 @end
38 @interface NSStringArray : NSArray<NSString *>
39 @end
41 @interface NSSet<T> : NSObject <NSCopying>
42 - (T)firstObject;
43 @property (nonatomic, copy) NSArray<T> *allObjects;
44 @end
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}}
49 @end
51 @interface Widget : NSObject <NSCopying>
52 @end
54 // Non-parameterized class inheriting from a specialization of a
55 // parameterized class.
56 @interface WidgetSet : NSMutableSet<Widget *>
57 @end
59 // Parameterized inheritance with a more interesting transformation in
60 // the specialization.
61 @interface MutableSetOfArrays<T> : NSMutableSet<NSArray<T>*>
62 @end
64 // Inheriting from an unspecialized form of a parameterized type.
65 @interface UntypedMutableSet : NSMutableSet
66 @end
68 @interface Window : NSObject
69 @end
71 @interface NSDictionary<K, V> : NSObject <NSCopying>
72 - (V)objectForKeyedSubscript:(K)key; // expected-note 2{{parameter 'key'}}
73 @end
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;
84 @end
86 @interface WindowArray : NSArray<Window *>
87 @end
89 @interface NSSet<T> (Searching)
90 - (T)findObject:(T)object;
91 @end
94 // --------------------------------------------------------------------------
95 // Message sends.
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,
103        NSSet *set,
104        NSMutableSet *mutSet,
105        MutableSetOfArrays *mutArraySet,
106        NSArray<NSString *> *stringArray,
107        void (^block)(void)) {
108   int *ip;
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 *'}}
121   // Class messages.
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)) {
144   Window *window;
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,
164        NSSet *set,
165        NSMutableSet *mutSet,
166        MutableSetOfArrays *mutArraySet,
167        NSMutableDictionary *mutDict) {
168   int *ip;
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) {
189   int *ip;
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 // --------------------------------------------------------------------------
202 // Subscripting
203 // --------------------------------------------------------------------------
204 void test_subscripting(
205        NSArray<NSString *> *stringArray,
206        NSMutableArray<NSString *> *mutStringArray,
207        NSArray *array,
208        NSMutableArray *mutArray,
209        NSDictionary<NSString *, Widget *> *stringWidgetDict,
210        NSMutableDictionary<NSString *, Widget *> *mutStringWidgetDict,
211        NSDictionary *dict,
212        NSMutableDictionary *mutDict) {
213   int *ip;
214   NSString *string;
215   Widget *widget;
216   Window *window;
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,
249                             NSArray *array) {
250   int *ip;
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 {
258   int *ip;
260   ip = data; // expected-error{{incompatible pointer types assigning to 'int *' from 'Window **'}}
262 @end
264 // --------------------------------------------------------------------------
265 // Implicit conversions.
266 // --------------------------------------------------------------------------
267 void test_implicit_conversions(NSArray<NSString *> *stringArray,
268                                NSArray<NSNumber *> *numberArray,
269                                NSMutableArray<NSString *> *mutStringArray,
270                                NSArray *array,
271                                NSMutableArray *mutArray) {
272   // Specialized -> unspecialized (same level)
273   array = stringArray;
275   // Unspecialized -> specialized (same level)
276   stringArray = array;
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>
295 @end
297 @interface NSContravariant1<__contravariant T>
298 @end
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 // --------------------------------------------------------------------------
325 // Ternary operator
326 // --------------------------------------------------------------------------
327 void test_ternary_operator(NSArray<NSString *> *stringArray,
328                            NSArray<NSNumber *> *numberArray,
329                            NSMutableArray<NSString *> *mutStringArray,
330                            NSStringArray *stringArray2,
331                            NSArray *array,
332                            NSMutableArray *mutArray,
333                            int cond) {
334   int *ip;
335   id object;
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 // --------------------------------------------------------------------------
355 // super
356 // --------------------------------------------------------------------------
357 @implementation NSStringArray
358 - (void)useSuperMethod {
359   int *ip;
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 {
365   int *ip;
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 *> *'}}
369 @end
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() {
387   int *ip;
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() {
396   int *ip;
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}}
416 template<typename T>
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