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