xref: /aosp_15_r20/external/clang/test/SemaObjCXX/parameterized_classes_subst.mm (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li// RUN: %clang_cc1 -fblocks -fsyntax-only -std=c++11 %s -verify
2*67e74705SXin Li//
3*67e74705SXin Li// Test the substitution of type arguments for type parameters when
4*67e74705SXin Li// using parameterized classes in Objective-C.
5*67e74705SXin Li
6*67e74705SXin Li__attribute__((objc_root_class))
7*67e74705SXin Li@interface NSObject
8*67e74705SXin Li+ (instancetype)alloc;
9*67e74705SXin Li- (instancetype)init;
10*67e74705SXin Li@end
11*67e74705SXin Li
12*67e74705SXin Li@protocol NSCopying
13*67e74705SXin Li@end
14*67e74705SXin Li
15*67e74705SXin Li@interface NSString : NSObject <NSCopying>
16*67e74705SXin Li@end
17*67e74705SXin Li
18*67e74705SXin Li@interface NSMutableString : NSString
19*67e74705SXin Li@end
20*67e74705SXin Li
21*67e74705SXin Li@interface NSNumber : NSObject <NSCopying>
22*67e74705SXin Li@end
23*67e74705SXin Li
24*67e74705SXin Li@interface NSArray<T> : NSObject <NSCopying> {
25*67e74705SXin Li@public
26*67e74705SXin Li  T *data; // don't try this at home
27*67e74705SXin Li}
28*67e74705SXin Li- (T)objectAtIndexedSubscript:(int)index;
29*67e74705SXin Li+ (NSArray<T> *)array;
30*67e74705SXin Li@property (copy,nonatomic) T lastObject;
31*67e74705SXin Li@end
32*67e74705SXin Li
33*67e74705SXin Li@interface NSMutableArray<T> : NSArray<T>
34*67e74705SXin Li-(instancetype)initWithArray:(NSArray<T> *)array; // expected-note{{passing argument}}
35*67e74705SXin Li- (void)setObject:(T)object atIndexedSubscript:(int)index; // expected-note 2{{passing argument to parameter 'object' here}}
36*67e74705SXin Li@end
37*67e74705SXin Li
38*67e74705SXin Li@interface NSStringArray : NSArray<NSString *>
39*67e74705SXin Li@end
40*67e74705SXin Li
41*67e74705SXin Li@interface NSSet<T> : NSObject <NSCopying>
42*67e74705SXin Li- (T)firstObject;
43*67e74705SXin Li@property (nonatomic, copy) NSArray<T> *allObjects;
44*67e74705SXin Li@end
45*67e74705SXin Li
46*67e74705SXin Li// Parameterized inheritance (simple case)
47*67e74705SXin Li@interface NSMutableSet<U : id<NSCopying>> : NSSet<U>
48*67e74705SXin Li- (void)addObject:(U)object; // expected-note 7{{passing argument to parameter 'object' here}}
49*67e74705SXin Li@end
50*67e74705SXin Li
51*67e74705SXin Li@interface Widget : NSObject <NSCopying>
52*67e74705SXin Li@end
53*67e74705SXin Li
54*67e74705SXin Li// Non-parameterized class inheriting from a specialization of a
55*67e74705SXin Li// parameterized class.
56*67e74705SXin Li@interface WidgetSet : NSMutableSet<Widget *>
57*67e74705SXin Li@end
58*67e74705SXin Li
59*67e74705SXin Li// Parameterized inheritance with a more interesting transformation in
60*67e74705SXin Li// the specialization.
61*67e74705SXin Li@interface MutableSetOfArrays<T> : NSMutableSet<NSArray<T>*>
62*67e74705SXin Li@end
63*67e74705SXin Li
64*67e74705SXin Li// Inheriting from an unspecialized form of a parameterized type.
65*67e74705SXin Li@interface UntypedMutableSet : NSMutableSet
66*67e74705SXin Li@end
67*67e74705SXin Li
68*67e74705SXin Li@interface Window : NSObject
69*67e74705SXin Li@end
70*67e74705SXin Li
71*67e74705SXin Li@interface NSDictionary<K, V> : NSObject <NSCopying>
72*67e74705SXin Li- (V)objectForKeyedSubscript:(K)key; // expected-note 2{{parameter 'key'}}
73*67e74705SXin Li@end
74*67e74705SXin Li
75*67e74705SXin Li@interface NSMutableDictionary<K : id<NSCopying>, V> : NSDictionary<K, V> // expected-note 2{{type parameter 'K' declared here}} \
76*67e74705SXin Li// expected-note 2{{'NSMutableDictionary' declared here}}
77*67e74705SXin Li- (void)setObject:(V)object forKeyedSubscript:(K)key;
78*67e74705SXin Li// expected-note@-1 {{parameter 'object' here}}
79*67e74705SXin Li// expected-note@-2 {{parameter 'object' here}}
80*67e74705SXin Li// expected-note@-3 {{parameter 'key' here}}
81*67e74705SXin Li// expected-note@-4 {{parameter 'key' here}}
82*67e74705SXin Li
83*67e74705SXin Li@property (strong) K someRandomKey;
84*67e74705SXin Li@end
85*67e74705SXin Li
86*67e74705SXin Li@interface WindowArray : NSArray<Window *>
87*67e74705SXin Li@end
88*67e74705SXin Li
89*67e74705SXin Li@interface NSSet<T> (Searching)
90*67e74705SXin Li- (T)findObject:(T)object;
91*67e74705SXin Li@end
92*67e74705SXin Li
93*67e74705SXin Li
94*67e74705SXin Li// --------------------------------------------------------------------------
95*67e74705SXin Li// Message sends.
96*67e74705SXin Li// --------------------------------------------------------------------------
97*67e74705SXin Livoid test_message_send_result(
98*67e74705SXin Li       NSSet<NSString *> *stringSet,
99*67e74705SXin Li       NSMutableSet<NSString *> *mutStringSet,
100*67e74705SXin Li       WidgetSet *widgetSet,
101*67e74705SXin Li       UntypedMutableSet *untypedMutSet,
102*67e74705SXin Li       MutableSetOfArrays<NSString *> *mutStringArraySet,
103*67e74705SXin Li       NSSet *set,
104*67e74705SXin Li       NSMutableSet *mutSet,
105*67e74705SXin Li       MutableSetOfArrays *mutArraySet,
106*67e74705SXin Li       NSArray<NSString *> *stringArray,
107*67e74705SXin Li       void (^block)(void)) {
108*67e74705SXin Li  int *ip;
109*67e74705SXin Li  ip = [stringSet firstObject]; // expected-error{{from incompatible type 'NSString *'}}
110*67e74705SXin Li  ip = [mutStringSet firstObject]; // expected-error{{from incompatible type 'NSString *'}}
111*67e74705SXin Li  ip = [widgetSet firstObject]; // expected-error{{from incompatible type 'Widget *'}}
112*67e74705SXin Li  ip = [untypedMutSet firstObject]; // expected-error{{from incompatible type 'id'}}
113*67e74705SXin Li  ip = [mutStringArraySet firstObject]; // expected-error{{from incompatible type 'NSArray<NSString *> *'}}
114*67e74705SXin Li  ip = [set firstObject]; // expected-error{{from incompatible type 'id'}}
115*67e74705SXin Li  ip = [mutSet firstObject]; // expected-error{{from incompatible type 'id'}}
116*67e74705SXin Li  ip = [mutArraySet firstObject]; // expected-error{{from incompatible type 'id'}}
117*67e74705SXin Li  ip = [block firstObject]; // expected-error{{from incompatible type 'id'}}
118*67e74705SXin Li
119*67e74705SXin Li  ip = [stringSet findObject:@"blah"]; // expected-error{{from incompatible type 'NSString *'}}
120*67e74705SXin Li
121*67e74705SXin Li  // Class messages.
122*67e74705SXin Li  ip = [NSSet<NSString *> alloc]; // expected-error{{from incompatible type 'NSSet<NSString *> *'}}
123*67e74705SXin Li  ip = [NSSet alloc]; // expected-error{{from incompatible type 'NSSet *'}}
124*67e74705SXin Li  ip = [MutableSetOfArrays<NSString *> alloc]; // expected-error{{from incompatible type 'MutableSetOfArrays<NSString *> *'}}
125*67e74705SXin Li  ip = [MutableSetOfArrays alloc];  // expected-error{{from incompatible type 'MutableSetOfArrays *'}}
126*67e74705SXin Li  ip = [NSArray<NSString *> array]; // expected-error{{from incompatible type 'NSArray<NSString *> *'}}
127*67e74705SXin Li  ip = [NSArray<NSString *><NSCopying> array]; // expected-error{{from incompatible type 'NSArray<NSString *> *'}}
128*67e74705SXin Li
129*67e74705SXin Li  ip = [[NSMutableArray<NSString *> alloc] init];  // expected-error{{from incompatible type 'NSMutableArray<NSString *> *'}}
130*67e74705SXin Li
131*67e74705SXin Li  [[NSMutableArray alloc] initWithArray: stringArray]; // okay
132*67e74705SXin Li  [[NSMutableArray<NSString *> alloc] initWithArray: stringArray]; // okay
133*67e74705SXin Li  [[NSMutableArray<NSNumber *> alloc] initWithArray: stringArray]; // expected-error{{parameter of type 'NSArray<NSNumber *> *' with an lvalue of type 'NSArray<NSString *> *'}}
134*67e74705SXin Li}
135*67e74705SXin Li
136*67e74705SXin Livoid test_message_send_param(
137*67e74705SXin Li       NSMutableSet<NSString *> *mutStringSet,
138*67e74705SXin Li       WidgetSet *widgetSet,
139*67e74705SXin Li       UntypedMutableSet *untypedMutSet,
140*67e74705SXin Li       MutableSetOfArrays<NSString *> *mutStringArraySet,
141*67e74705SXin Li       NSMutableSet *mutSet,
142*67e74705SXin Li       MutableSetOfArrays *mutArraySet,
143*67e74705SXin Li       void (^block)(void)) {
144*67e74705SXin Li  Window *window;
145*67e74705SXin Li
146*67e74705SXin Li  [mutStringSet addObject: window]; // expected-error{{parameter of type 'NSString *'}}
147*67e74705SXin Li  [widgetSet addObject: window]; // expected-error{{parameter of type 'Widget *'}}
148*67e74705SXin Li  [untypedMutSet addObject: window]; // expected-error{{parameter of type 'id<NSCopying>'}}
149*67e74705SXin Li  [mutStringArraySet addObject: window]; // expected-error{{parameter of type 'NSArray<NSString *> *'}}
150*67e74705SXin Li  [mutSet addObject: window]; // expected-error{{parameter of type 'id<NSCopying>'}}
151*67e74705SXin Li  [mutArraySet addObject: window]; // expected-error{{parameter of type 'id<NSCopying>'}}
152*67e74705SXin Li  [block addObject: window]; // expected-error{{parameter of type 'id<NSCopying>'}}
153*67e74705SXin Li}
154*67e74705SXin Li
155*67e74705SXin Li// --------------------------------------------------------------------------
156*67e74705SXin Li// Property accesses.
157*67e74705SXin Li// --------------------------------------------------------------------------
158*67e74705SXin Livoid test_property_read(
159*67e74705SXin Li       NSSet<NSString *> *stringSet,
160*67e74705SXin Li       NSMutableSet<NSString *> *mutStringSet,
161*67e74705SXin Li       WidgetSet *widgetSet,
162*67e74705SXin Li       UntypedMutableSet *untypedMutSet,
163*67e74705SXin Li       MutableSetOfArrays<NSString *> *mutStringArraySet,
164*67e74705SXin Li       NSSet *set,
165*67e74705SXin Li       NSMutableSet *mutSet,
166*67e74705SXin Li       MutableSetOfArrays *mutArraySet,
167*67e74705SXin Li       NSMutableDictionary *mutDict) {
168*67e74705SXin Li  int *ip;
169*67e74705SXin Li  ip = stringSet.allObjects; // expected-error{{from incompatible type 'NSArray<NSString *> *'}}
170*67e74705SXin Li  ip = mutStringSet.allObjects; // expected-error{{from incompatible type 'NSArray<NSString *> *'}}
171*67e74705SXin Li  ip = widgetSet.allObjects; // expected-error{{from incompatible type 'NSArray<Widget *> *'}}
172*67e74705SXin Li  ip = untypedMutSet.allObjects; // expected-error{{from incompatible type 'NSArray *'}}
173*67e74705SXin Li  ip = mutStringArraySet.allObjects; // expected-error{{from incompatible type 'NSArray<NSArray<NSString *> *> *'}}
174*67e74705SXin Li  ip = set.allObjects; // expected-error{{from incompatible type 'NSArray *'}}
175*67e74705SXin Li  ip = mutSet.allObjects; // expected-error{{from incompatible type 'NSArray *'}}
176*67e74705SXin Li  ip = mutArraySet.allObjects; // expected-error{{from incompatible type 'NSArray *'}}
177*67e74705SXin Li
178*67e74705SXin Li  ip = mutDict.someRandomKey; // expected-error{{from incompatible type '__kindof id<NSCopying>'}}
179*67e74705SXin Li}
180*67e74705SXin Li
181*67e74705SXin Livoid test_property_write(
182*67e74705SXin Li       NSMutableSet<NSString *> *mutStringSet,
183*67e74705SXin Li       WidgetSet *widgetSet,
184*67e74705SXin Li       UntypedMutableSet *untypedMutSet,
185*67e74705SXin Li       MutableSetOfArrays<NSString *> *mutStringArraySet,
186*67e74705SXin Li       NSMutableSet *mutSet,
187*67e74705SXin Li       MutableSetOfArrays *mutArraySet,
188*67e74705SXin Li       NSMutableDictionary *mutDict) {
189*67e74705SXin Li  int *ip;
190*67e74705SXin Li
191*67e74705SXin Li  mutStringSet.allObjects = ip; // expected-error{{to 'NSArray<NSString *> *'}}
192*67e74705SXin Li  widgetSet.allObjects = ip; // expected-error{{to 'NSArray<Widget *> *'}}
193*67e74705SXin Li  untypedMutSet.allObjects = ip; // expected-error{{to 'NSArray *'}}
194*67e74705SXin Li  mutStringArraySet.allObjects = ip; // expected-error{{to 'NSArray<NSArray<NSString *> *> *'}}
195*67e74705SXin Li  mutSet.allObjects = ip; // expected-error{{to 'NSArray *'}}
196*67e74705SXin Li  mutArraySet.allObjects = ip; // expected-error{{to 'NSArray *'}}
197*67e74705SXin Li
198*67e74705SXin Li  mutDict.someRandomKey = ip; // expected-error{{to 'id<NSCopying>'}}
199*67e74705SXin Li}
200*67e74705SXin Li
201*67e74705SXin Li// --------------------------------------------------------------------------
202*67e74705SXin Li// Subscripting
203*67e74705SXin Li// --------------------------------------------------------------------------
204*67e74705SXin Livoid test_subscripting(
205*67e74705SXin Li       NSArray<NSString *> *stringArray,
206*67e74705SXin Li       NSMutableArray<NSString *> *mutStringArray,
207*67e74705SXin Li       NSArray *array,
208*67e74705SXin Li       NSMutableArray *mutArray,
209*67e74705SXin Li       NSDictionary<NSString *, Widget *> *stringWidgetDict,
210*67e74705SXin Li       NSMutableDictionary<NSString *, Widget *> *mutStringWidgetDict,
211*67e74705SXin Li       NSDictionary *dict,
212*67e74705SXin Li       NSMutableDictionary *mutDict) {
213*67e74705SXin Li  int *ip;
214*67e74705SXin Li  NSString *string;
215*67e74705SXin Li  Widget *widget;
216*67e74705SXin Li  Window *window;
217*67e74705SXin Li
218*67e74705SXin Li  ip = stringArray[0]; // expected-error{{from incompatible type 'NSString *'}}
219*67e74705SXin Li
220*67e74705SXin Li  ip = mutStringArray[0]; // expected-error{{from incompatible type 'NSString *'}}
221*67e74705SXin Li  mutStringArray[0] = ip; // expected-error{{parameter of type 'NSString *'}}
222*67e74705SXin Li
223*67e74705SXin Li  ip = array[0]; // expected-error{{from incompatible type 'id'}}
224*67e74705SXin Li
225*67e74705SXin Li  ip = mutArray[0]; // expected-error{{from incompatible type 'id'}}
226*67e74705SXin Li  mutArray[0] = ip; // expected-error{{parameter of type 'id'}}
227*67e74705SXin Li
228*67e74705SXin Li  ip = stringWidgetDict[string]; // expected-error{{from incompatible type 'Widget *'}}
229*67e74705SXin Li  widget = stringWidgetDict[widget]; // expected-error{{parameter of type 'NSString *'}}
230*67e74705SXin Li
231*67e74705SXin Li  ip = mutStringWidgetDict[string]; // expected-error{{from incompatible type 'Widget *'}}
232*67e74705SXin Li  widget = mutStringWidgetDict[widget]; // expected-error{{parameter of type 'NSString *'}}
233*67e74705SXin Li  mutStringWidgetDict[string] = ip; // expected-error{{parameter of type 'Widget *'}}
234*67e74705SXin Li  mutStringWidgetDict[widget] = widget; // expected-error{{parameter of type 'NSString *'}}
235*67e74705SXin Li
236*67e74705SXin Li  ip = dict[string]; // expected-error{{from incompatible type 'id'}}
237*67e74705SXin Li
238*67e74705SXin Li  ip = mutDict[string]; // expected-error{{incompatible type 'id'}}
239*67e74705SXin Li  mutDict[string] = ip; // expected-error{{parameter of type 'id'}}
240*67e74705SXin Li
241*67e74705SXin Li  widget = mutDict[window];
242*67e74705SXin Li  mutDict[window] = widget; // expected-error{{parameter of type 'id<NSCopying>'}}
243*67e74705SXin Li}
244*67e74705SXin Li
245*67e74705SXin Li// --------------------------------------------------------------------------
246*67e74705SXin Li// Instance variable access.
247*67e74705SXin Li// --------------------------------------------------------------------------
248*67e74705SXin Livoid test_instance_variable(NSArray<NSString *> *stringArray,
249*67e74705SXin Li                            NSArray *array) {
250*67e74705SXin Li  int *ip;
251*67e74705SXin Li
252*67e74705SXin Li  ip = stringArray->data; // expected-error{{from incompatible type 'NSString **'}}
253*67e74705SXin Li  ip = array->data; // expected-error{{from incompatible type 'id *'}}
254*67e74705SXin Li}
255*67e74705SXin Li
256*67e74705SXin Li@implementation WindowArray
257*67e74705SXin Li- (void)testInstanceVariable {
258*67e74705SXin Li  int *ip;
259*67e74705SXin Li
260*67e74705SXin Li  ip = data; // expected-error{{from incompatible type 'Window **'}}
261*67e74705SXin Li}
262*67e74705SXin Li@end
263*67e74705SXin Li
264*67e74705SXin Li// --------------------------------------------------------------------------
265*67e74705SXin Li// Implicit conversions.
266*67e74705SXin Li// --------------------------------------------------------------------------
267*67e74705SXin Livoid test_implicit_conversions(NSArray<NSString *> *stringArray,
268*67e74705SXin Li                               NSArray<NSNumber *> *numberArray,
269*67e74705SXin Li                               NSMutableArray<NSString *> *mutStringArray,
270*67e74705SXin Li                               NSArray *array,
271*67e74705SXin Li                               NSMutableArray *mutArray) {
272*67e74705SXin Li  // Specialized -> unspecialized (same level)
273*67e74705SXin Li  array = stringArray;
274*67e74705SXin Li
275*67e74705SXin Li  // Unspecialized -> specialized (same level)
276*67e74705SXin Li  stringArray = array;
277*67e74705SXin Li
278*67e74705SXin Li  // Specialized -> specialized failure (same level).
279*67e74705SXin Li  stringArray = numberArray; // expected-error{{assigning to 'NSArray<NSString *> *' from incompatible type 'NSArray<NSNumber *> *'}}
280*67e74705SXin Li
281*67e74705SXin Li  // Specialized -> specialized (different levels).
282*67e74705SXin Li  stringArray = mutStringArray;
283*67e74705SXin Li
284*67e74705SXin Li  // Specialized -> specialized failure (different levels).
285*67e74705SXin Li  numberArray = mutStringArray; // expected-error{{assigning to 'NSArray<NSNumber *> *' from incompatible type 'NSMutableArray<NSString *> *'}}
286*67e74705SXin Li
287*67e74705SXin Li  // Unspecialized -> specialized (different levels).
288*67e74705SXin Li  stringArray = mutArray;
289*67e74705SXin Li
290*67e74705SXin Li  // Specialized -> unspecialized (different levels).
291*67e74705SXin Li  array = mutStringArray;
292*67e74705SXin Li}
293*67e74705SXin Li
294*67e74705SXin Li@interface NSCovariant1<__covariant T>
295*67e74705SXin Li@end
296*67e74705SXin Li
297*67e74705SXin Li@interface NSContravariant1<__contravariant T>
298*67e74705SXin Li@end
299*67e74705SXin Li
300*67e74705SXin Livoid test_variance(NSCovariant1<NSString *> *covariant1,
301*67e74705SXin Li                   NSCovariant1<NSMutableString *> *covariant2,
302*67e74705SXin Li                   NSCovariant1<NSString *(^)(void)> *covariant3,
303*67e74705SXin Li                   NSCovariant1<NSMutableString *(^)(void)> *covariant4,
304*67e74705SXin Li                   NSCovariant1<id> *covariant5,
305*67e74705SXin Li                   NSCovariant1<id<NSCopying>> *covariant6,
306*67e74705SXin Li                   NSContravariant1<NSString *> *contravariant1,
307*67e74705SXin Li                   NSContravariant1<NSMutableString *> *contravariant2) {
308*67e74705SXin Li  covariant1 = covariant2; // okay
309*67e74705SXin Li  covariant2 = covariant1; // expected-warning{{incompatible pointer types assigning to 'NSCovariant1<NSMutableString *> *' from 'NSCovariant1<NSString *> *'}}
310*67e74705SXin Li
311*67e74705SXin Li  covariant3 = covariant4; // okay
312*67e74705SXin Li  covariant4 = covariant3; // expected-warning{{incompatible pointer types assigning to 'NSCovariant1<NSMutableString *(^)()> *' from 'NSCovariant1<NSString *(^)()> *'}}
313*67e74705SXin Li
314*67e74705SXin Li  covariant5 = covariant1; // okay
315*67e74705SXin Li  covariant1 = covariant5; // okay: id is promiscuous
316*67e74705SXin Li
317*67e74705SXin Li  covariant5 = covariant3; // okay
318*67e74705SXin Li  covariant3 = covariant5; // okay
319*67e74705SXin Li
320*67e74705SXin Li  contravariant1 = contravariant2; // expected-warning{{incompatible pointer types assigning to 'NSContravariant1<NSString *> *' from 'NSContravariant1<NSMutableString *> *'}}
321*67e74705SXin Li  contravariant2 = contravariant1; // okay
322*67e74705SXin Li}
323*67e74705SXin Li
324*67e74705SXin Li// --------------------------------------------------------------------------
325*67e74705SXin Li// Ternary operator
326*67e74705SXin Li// --------------------------------------------------------------------------
327*67e74705SXin Livoid test_ternary_operator(NSArray<NSString *> *stringArray,
328*67e74705SXin Li                           NSArray<NSNumber *> *numberArray,
329*67e74705SXin Li                           NSMutableArray<NSString *> *mutStringArray,
330*67e74705SXin Li                           NSStringArray *stringArray2,
331*67e74705SXin Li                           NSArray *array,
332*67e74705SXin Li                           NSMutableArray *mutArray,
333*67e74705SXin Li                           int cond) {
334*67e74705SXin Li  int *ip;
335*67e74705SXin Li  id object;
336*67e74705SXin Li
337*67e74705SXin Li  ip = cond ? stringArray : mutStringArray; // expected-error{{from incompatible type 'NSArray<NSString *> *'}}
338*67e74705SXin Li  ip = cond ? mutStringArray : stringArray; // expected-error{{from incompatible type 'NSArray<NSString *> *'}}
339*67e74705SXin Li
340*67e74705SXin Li  ip = cond ? stringArray2 : mutStringArray; // expected-error{{from incompatible type 'NSArray<NSString *> *'}}
341*67e74705SXin Li  ip = cond ? mutStringArray : stringArray2; // expected-error{{from incompatible type 'NSArray<NSString *> *'}}
342*67e74705SXin Li
343*67e74705SXin Li  ip = cond ? stringArray : mutArray; // expected-error{{from incompatible type 'NSArray *'}}
344*67e74705SXin Li
345*67e74705SXin Li  ip = cond ? stringArray2 : mutArray; // expected-error{{from incompatible type 'NSArray *'}}
346*67e74705SXin Li
347*67e74705SXin Li  ip = cond ? mutArray : stringArray; // expected-error{{from incompatible type 'NSArray *'}}
348*67e74705SXin Li
349*67e74705SXin Li  ip = cond ? mutArray : stringArray2; // expected-error{{from incompatible type 'NSArray *'}}
350*67e74705SXin Li
351*67e74705SXin Li  object = cond ? stringArray : numberArray; // expected-warning{{incompatible operand types ('NSArray<NSString *> *' and 'NSArray<NSNumber *> *')}}
352*67e74705SXin Li}
353*67e74705SXin Li
354*67e74705SXin Li// --------------------------------------------------------------------------
355*67e74705SXin Li// super
356*67e74705SXin Li// --------------------------------------------------------------------------
357*67e74705SXin Li@implementation NSStringArray
358*67e74705SXin Li- (void)useSuperMethod {
359*67e74705SXin Li  int *ip;
360*67e74705SXin Li  ip = super.lastObject; // expected-error{{from incompatible type 'NSString *'}}
361*67e74705SXin Li  ip = [super objectAtIndexedSubscript:0]; // expected-error{{from incompatible type 'NSString *'}}
362*67e74705SXin Li}
363*67e74705SXin Li
364*67e74705SXin Li+ (void)useSuperMethod {
365*67e74705SXin Li  int *ip;
366*67e74705SXin Li  ip = super.array; // expected-error{{from incompatible type 'NSArray<NSString *> *'}}
367*67e74705SXin Li  ip = [super array]; // expected-error{{from incompatible type 'NSArray<NSString *> *'}}
368*67e74705SXin Li}
369*67e74705SXin Li@end
370*67e74705SXin Li
371*67e74705SXin Li// --------------------------------------------------------------------------
372*67e74705SXin Li// Template instantiation
373*67e74705SXin Li// --------------------------------------------------------------------------
374*67e74705SXin Litemplate<typename K, typename V>
375*67e74705SXin Listruct NSMutableDictionaryOf {
376*67e74705SXin Li  typedef NSMutableDictionary<K, V> *type; // expected-error{{type argument 'NSObject *' does not satisfy the bound ('id<NSCopying>') of type parameter 'K'}}
377*67e74705SXin Li};
378*67e74705SXin Li
379*67e74705SXin Litemplate<typename ...Args>
380*67e74705SXin Listruct VariadicNSMutableDictionaryOf {
381*67e74705SXin Li  typedef NSMutableDictionary<Args...> *type; // expected-error{{type argument 'NSObject *' does not satisfy the bound ('id<NSCopying>') of type parameter 'K'}}
382*67e74705SXin Li  // expected-error@-1{{too many type arguments for class 'NSMutableDictionary' (have 3, expected 2)}}
383*67e74705SXin Li  // expected-error@-2{{too few type arguments for class 'NSMutableDictionary' (have 1, expected 2)}}
384*67e74705SXin Li};
385*67e74705SXin Li
386*67e74705SXin Livoid testInstantiation() {
387*67e74705SXin Li  int *ip;
388*67e74705SXin Li
389*67e74705SXin Li  typedef NSMutableDictionaryOf<NSString *, NSObject *>::type Dict1;
390*67e74705SXin Li  Dict1 d1 = ip; // expected-error{{cannot initialize a variable of type 'Dict1' (aka 'NSMutableDictionary<NSString *,NSObject *> *')}}
391*67e74705SXin Li
392*67e74705SXin Li  typedef NSMutableDictionaryOf<NSObject *, NSString *>::type Dict2; // expected-note{{in instantiation of template}}
393*67e74705SXin Li}
394*67e74705SXin Li
395*67e74705SXin Livoid testVariadicInstantiation() {
396*67e74705SXin Li  int *ip;
397*67e74705SXin Li
398*67e74705SXin Li  typedef VariadicNSMutableDictionaryOf<NSString *, NSObject *>::type Dict1;
399*67e74705SXin Li  Dict1 d1 = ip; // expected-error{{cannot initialize a variable of type 'Dict1' (aka 'NSMutableDictionary<NSString *,NSObject *> *')}}
400*67e74705SXin Li
401*67e74705SXin Li  typedef VariadicNSMutableDictionaryOf<NSObject *, NSString *>::type Dict2; // expected-note{{in instantiation of template}}
402*67e74705SXin Li
403*67e74705SXin Li  typedef VariadicNSMutableDictionaryOf<NSString *, NSObject *, NSObject *>::type Dict3; // expected-note{{in instantiation of template}}
404*67e74705SXin Li
405*67e74705SXin Li  typedef VariadicNSMutableDictionaryOf<NSString *>::type Dict3; // expected-note{{in instantiation of template}}
406*67e74705SXin Li}
407*67e74705SXin Li
408*67e74705SXin Li// --------------------------------------------------------------------------
409*67e74705SXin Li// Parameterized classes are not templates
410*67e74705SXin Li// --------------------------------------------------------------------------
411*67e74705SXin Litemplate<template<typename T, typename U> class TT>
412*67e74705SXin Listruct AcceptsTemplateTemplate { };
413*67e74705SXin Li
414*67e74705SXin Litypedef AcceptsTemplateTemplate<NSMutableDictionary> TemplateTemplateFail1; // expected-error{{template argument for template template parameter must be a class template or type alias template}}
415*67e74705SXin Li
416*67e74705SXin Litemplate<typename T>
417*67e74705SXin Listruct DependentTemplate {
418*67e74705SXin Li  typedef typename T::template apply<NSString *, NSObject *> type; // expected-error{{'apply' following the 'template' keyword does not refer to a template}}
419*67e74705SXin Li};
420*67e74705SXin Li
421*67e74705SXin Listruct NSMutableDictionaryBuilder {
422*67e74705SXin Li  typedef NSMutableDictionary apply;
423*67e74705SXin Li};
424*67e74705SXin Li
425*67e74705SXin Litypedef DependentTemplate<NSMutableDictionaryBuilder>::type DependentTemplateFail1; // expected-note{{in instantiation of template class}}
426*67e74705SXin Li
427*67e74705SXin Litemplate<typename K, typename V>
428*67e74705SXin Listruct NonDependentTemplate {
429*67e74705SXin Li  typedef NSMutableDictionaryBuilder::template apply<NSString *, NSObject *> type; // expected-error{{'apply' following the 'template' keyword does not refer to a template}}
430*67e74705SXin Li  // expected-error@-1{{expected member name or }}
431*67e74705SXin Li};
432*67e74705SXin Li
433*67e74705SXin Li// However, one can use an alias template to turn a parameterized
434*67e74705SXin Li// class into a template.
435*67e74705SXin Litemplate<typename K, typename V>
436*67e74705SXin Liusing NSMutableDictionaryAlias = NSMutableDictionary<K, V>;
437*67e74705SXin Li
438*67e74705SXin Litypedef AcceptsTemplateTemplate<NSMutableDictionaryAlias> TemplateTemplateAlias1; // okay
439*67e74705SXin Li
440*67e74705SXin Li
441