brintos

brintos / llvm-project-archived public Read only

0
0
Text · 19.1 KiB · 3358194 Raw
483 lines · plain
1// RUN: %clang_cc1 -fblocks -fsyntax-only -Wnullable-to-nonnull-conversion %s -verify2//3// Test the substitution of type arguments for type parameters when4// using parameterized classes in Objective-C.5 6@protocol NSObject7@end8 9__attribute__((objc_root_class))10@interface NSObject <NSObject>11+ (instancetype)alloc;12- (instancetype)init;13@end14 15@protocol NSCopying16@end17 18@interface NSString : NSObject <NSCopying>19@end20 21@interface NSMutableString : NSString22@end23 24@interface NSNumber : NSObject <NSCopying>25@end26 27@interface NSArray<T> : NSObject <NSCopying> {28@public29  T *data; // don't try this at home30}31- (T)objectAtIndexedSubscript:(int)index;32+ (NSArray<T> *)array;33+ (void)setArray:(NSArray <T> *)array;34@property (copy,nonatomic) T lastObject;35@end36 37@interface NSMutableArray<T> : NSArray<T>38-(instancetype)initWithArray:(NSArray<T> *)array; // expected-note{{passing argument}}39- (void)setObject:(T)object atIndexedSubscript:(int)index; // expected-note 2{{passing argument to parameter 'object' here}}40@end41 42@interface NSStringArray : NSArray<NSString *>43@end44 45@interface NSSet<T> : NSObject <NSCopying>46- (T)firstObject;47@property (nonatomic, copy) NSArray<T> *allObjects;48@end49 50// Parameterized inheritance (simple case)51@interface NSMutableSet<U : id<NSCopying>> : NSSet<U>52- (void)addObject:(U)object; // expected-note 7{{passing argument to parameter 'object' here}}53@end54 55@interface Widget : NSObject <NSCopying>56@end57 58// Non-parameterized class inheriting from a specialization of a59// parameterized class.60@interface WidgetSet : NSMutableSet<Widget *>61@end62 63// Parameterized inheritance with a more interesting transformation in64// the specialization.65@interface MutableSetOfArrays<T> : NSMutableSet<NSArray<T>*>66@end67 68// Inheriting from an unspecialized form of a parameterized type.69@interface UntypedMutableSet : NSMutableSet70@end71 72@interface Window : NSObject73@end74 75@interface NSDictionary<K, V> : NSObject <NSCopying>76- (V)objectForKeyedSubscript:(K)key; // expected-note 2{{parameter 'key'}}77@end78 79@interface NSMutableDictionary<K : id<NSCopying>, V> : NSDictionary<K, V>80- (void)setObject:(V)object forKeyedSubscript:(K)key;81// expected-note@-1 {{parameter 'object' here}}82// expected-note@-2 {{parameter 'object' here}}83// expected-note@-3 {{parameter 'key' here}}84// expected-note@-4 {{parameter 'key' here}}85 86@property (strong) K someRandomKey;87@end88 89@interface WindowArray : NSArray<Window *>90@end91 92@interface NSSet<T> (Searching)93- (T)findObject:(T)object;94@end95 96@interface NSView : NSObject97@end98 99@interface NSControl : NSView100- (void)toggle;101@end102 103@interface NSViewController<ViewType : NSView *> : NSObject104@property (nonatomic,retain) ViewType view;105@end106 107@interface TypedefTypeParam<T> : NSObject108typedef T AliasT;109- (void)test:(AliasT)object;110// expected-note@-1 {{parameter 'object' here}}111@end112 113// --------------------------------------------------------------------------114// Nullability115// --------------------------------------------------------------------------116typedef NSControl * _Nonnull Nonnull_NSControl;117 118@interface NSNullableTest<ViewType : NSView *> : NSObject119- (ViewType)view;120- (nullable ViewType)maybeView;121@end122 123@interface NSNullableTest2<ViewType : NSView * _Nullable> : NSObject // expected-error{{type parameter 'ViewType' bound 'NSView * _Nullable' cannot explicitly specify nullability}}124@end125 126void test_nullability(void) {127  NSControl * _Nonnull nonnull_NSControl;128 129  // Nullability introduced by substitution.130  NSNullableTest<NSControl *> *unspecifiedControl;131  nonnull_NSControl = [unspecifiedControl view];132  nonnull_NSControl = [unspecifiedControl maybeView];  // expected-warning{{from nullable pointer 'NSControl * _Nullable' to non-nullable pointer type 'NSControl * _Nonnull'}}133 134  // Nullability overridden by substitution.135  NSNullableTest<Nonnull_NSControl> *nonnullControl;136  nonnull_NSControl = [nonnullControl view];137  nonnull_NSControl = [nonnullControl maybeView];  // expected-warning{{from nullable pointer 'Nonnull_NSControl _Nullable' (aka 'NSControl *') to non-nullable pointer type 'NSControl * _Nonnull'}}138 139  // Nullability cannot be specified directly on a type argument.140  NSNullableTest<NSControl * _Nonnull> *nonnullControl2; // expected-error{{type argument 'NSControl *' cannot explicitly specify nullability}}141}142 143// --------------------------------------------------------------------------144// Message sends.145// --------------------------------------------------------------------------146void test_message_send_result(147       NSSet<NSString *> *stringSet,148       NSMutableSet<NSString *> *mutStringSet,149       WidgetSet *widgetSet,150       UntypedMutableSet *untypedMutSet,151       MutableSetOfArrays<NSString *> *mutStringArraySet,152       NSSet *set,153       NSMutableSet *mutSet,154       MutableSetOfArrays *mutArraySet,155       NSArray<NSString *> *stringArray,156       NSArray<__kindof NSString *> *kindofStringArray,157       void (^block)(void)) {158  int *ip;159  ip = [stringSet firstObject]; // expected-error{{from 'NSString *'}}160  ip = [mutStringSet firstObject]; // expected-error{{from 'NSString *'}}161  ip = [widgetSet firstObject]; // expected-error{{from 'Widget *'}}162  ip = [untypedMutSet firstObject]; // expected-error{{from 'id'}}163  ip = [mutStringArraySet firstObject]; // expected-error{{from 'NSArray<NSString *> *'}}164  ip = [set firstObject]; // expected-error{{from 'id'}}165  ip = [mutSet firstObject]; // expected-error{{from 'id'}}166  ip = [mutArraySet firstObject]; // expected-error{{from 'id'}}167  ip = [block firstObject]; // expected-error{{from 'id'}}168 169  ip = [stringSet findObject:@"blah"]; // expected-error{{from 'NSString *'}}170 171  // Class messages.172  ip = [NSSet<NSString *> alloc]; // expected-error{{from 'NSSet<NSString *> *'}}173  ip = [NSSet alloc]; // expected-error{{from 'NSSet *'}}174  ip = [MutableSetOfArrays<NSString *> alloc]; // expected-error{{from 'MutableSetOfArrays<NSString *> *'}}175  ip = [MutableSetOfArrays alloc];  // expected-error{{from 'MutableSetOfArrays *'}}176  ip = [NSArray<NSString *> array]; // expected-error{{from 'NSArray<NSString *> *'}}177  ip = [NSArray<NSString *><NSCopying> array]; // expected-error{{from 'NSArray<NSString *> *'}}178 179  ip = [[NSMutableArray<NSString *> alloc] init];  // expected-error{{from 'NSMutableArray<NSString *> *'}}180 181  [[NSMutableArray alloc] initWithArray: stringArray]; // okay182  [[NSMutableArray<NSString *> alloc] initWithArray: stringArray]; // okay183  [[NSMutableArray<NSNumber *> alloc] initWithArray: stringArray]; // expected-error{{sending 'NSArray<NSString *> *' to parameter of type 'NSArray<NSNumber *> *'}}184 185  ip = [[[NSViewController alloc] init] view]; // expected-error{{from '__kindof NSView *'}}186  [[[[NSViewController alloc] init] view] toggle];187 188  NSMutableString *mutStr = kindofStringArray[0];189  NSNumber *number = kindofStringArray[0]; // expected-error{{of type '__kindof NSString *'}}190}191 192void test_message_send_param(193       NSMutableSet<NSString *> *mutStringSet,194       WidgetSet *widgetSet,195       UntypedMutableSet *untypedMutSet,196       MutableSetOfArrays<NSString *> *mutStringArraySet,197       NSMutableSet *mutSet,198       MutableSetOfArrays *mutArraySet,199       TypedefTypeParam<NSString *> *typedefTypeParam,200       void (^block)(void)) {201  Window *window;202 203  [mutStringSet addObject: window]; // expected-error{{parameter of type 'NSString *'}}204  [widgetSet addObject: window]; // expected-error{{parameter of type 'Widget *'}}205  [untypedMutSet addObject: window]; // expected-warning{{parameter of incompatible type 'id<NSCopying>'}}206  [mutStringArraySet addObject: window]; // expected-error{{parameter of type 'NSArray<NSString *> *'}}207  [mutSet addObject: window]; // expected-warning{{parameter of incompatible type 'id<NSCopying>'}}208  [mutArraySet addObject: window]; // expected-warning{{parameter of incompatible type 'id<NSCopying>'}}209  [typedefTypeParam test: window]; // expected-error{{parameter of type 'NSString *'}}210  [block addObject: window]; // expected-warning{{parameter of incompatible type 'id<NSCopying>'}}211}212 213// --------------------------------------------------------------------------214// Property accesses.215// --------------------------------------------------------------------------216void test_property_read(217       NSSet<NSString *> *stringSet,218       NSMutableSet<NSString *> *mutStringSet,219       WidgetSet *widgetSet,220       UntypedMutableSet *untypedMutSet,221       MutableSetOfArrays<NSString *> *mutStringArraySet,222       NSSet *set,223       NSMutableSet *mutSet,224       MutableSetOfArrays *mutArraySet,225       NSMutableDictionary *mutDict) {226  int *ip;227  ip = stringSet.allObjects; // expected-error{{from 'NSArray<NSString *> *'}}228  ip = mutStringSet.allObjects; // expected-error{{from 'NSArray<NSString *> *'}}229  ip = widgetSet.allObjects; // expected-error{{from 'NSArray<Widget *> *'}}230  ip = untypedMutSet.allObjects; // expected-error{{from 'NSArray *'}}231  ip = mutStringArraySet.allObjects; // expected-error{{from 'NSArray<NSArray<NSString *> *> *'}}232  ip = set.allObjects; // expected-error{{from 'NSArray *'}}233  ip = mutSet.allObjects; // expected-error{{from 'NSArray *'}}234  ip = mutArraySet.allObjects; // expected-error{{from 'NSArray *'}}235 236  ip = mutDict.someRandomKey; // expected-error{{from '__kindof id<NSCopying>'}}237 238  ip = [[NSViewController alloc] init].view; // expected-error{{from '__kindof NSView *'}}239}240 241void test_property_write(242       NSMutableSet<NSString *> *mutStringSet,243       WidgetSet *widgetSet,244       UntypedMutableSet *untypedMutSet,245       MutableSetOfArrays<NSString *> *mutStringArraySet,246       NSMutableSet *mutSet,247       MutableSetOfArrays *mutArraySet,248       NSMutableDictionary *mutDict) {249  int *ip;250 251  mutStringSet.allObjects = ip; // expected-error{{to 'NSArray<NSString *> *'}}252  widgetSet.allObjects = ip; // expected-error{{to 'NSArray<Widget *> *'}}253  untypedMutSet.allObjects = ip; // expected-error{{to 'NSArray *'}}254  mutStringArraySet.allObjects = ip; // expected-error{{to 'NSArray<NSArray<NSString *> *> *'}}255  mutSet.allObjects = ip; // expected-error{{to 'NSArray *'}}256  mutArraySet.allObjects = ip; // expected-error{{to 'NSArray *'}}257 258  mutDict.someRandomKey = ip; // expected-error{{to 'id<NSCopying>'}}259}260 261// --------------------------------------------------------------------------262// Subscripting263// --------------------------------------------------------------------------264void test_subscripting(265       NSArray<NSString *> *stringArray,266       NSMutableArray<NSString *> *mutStringArray,267       NSArray *array,268       NSMutableArray *mutArray,269       NSDictionary<NSString *, Widget *> *stringWidgetDict,270       NSMutableDictionary<NSString *, Widget *> *mutStringWidgetDict,271       NSDictionary *dict,272       NSMutableDictionary *mutDict) {273  int *ip;274  NSString *string;275  Widget *widget;276  Window *window;277 278  ip = stringArray[0]; // expected-error{{from 'NSString *'}}279 280  ip = mutStringArray[0]; // expected-error{{from 'NSString *'}}281  mutStringArray[0] = ip; // expected-error{{parameter of type 'NSString *'}}282 283  ip = array[0]; // expected-error{{from 'id'}}284 285  ip = mutArray[0]; // expected-error{{from 'id'}}286  mutArray[0] = ip; // expected-error{{parameter of type 'id'}}287 288  ip = stringWidgetDict[string]; // expected-error{{from 'Widget *'}}289  widget = stringWidgetDict[widget]; // expected-error{{to parameter of type 'NSString *'}}290 291  ip = mutStringWidgetDict[string]; // expected-error{{from 'Widget *'}}292  widget = mutStringWidgetDict[widget]; // expected-error{{to parameter of type 'NSString *'}}293  mutStringWidgetDict[string] = ip; // expected-error{{to parameter of type 'Widget *'}}294  mutStringWidgetDict[widget] = widget; // expected-error{{to parameter of type 'NSString *'}}295 296  ip = dict[string]; // expected-error{{from 'id'}}297 298  ip = mutDict[string]; // expected-error{{from 'id'}}299  mutDict[string] = ip; // expected-error{{to parameter of type 'id'}}300 301  widget = mutDict[window];302  mutDict[window] = widget; // expected-warning{{parameter of incompatible type 'id<NSCopying>'}}303}304 305// --------------------------------------------------------------------------306// Instance variable access.307// --------------------------------------------------------------------------308void test_instance_variable(NSArray<NSString *> *stringArray,309                            NSArray *array) {310  int *ip;311 312  ip = stringArray->data; // expected-error{{from 'NSString **'}}313  ip = array->data; // expected-error{{from 'id *'}}314}315 316@implementation WindowArray317- (void)testInstanceVariable {318  int *ip;319 320  ip = data; // expected-error{{from 'Window **'}}321}322@end323 324// --------------------------------------------------------------------------325// Implicit conversions.326// --------------------------------------------------------------------------327void test_implicit_conversions(NSArray<NSString *> *stringArray,328                               NSArray<NSNumber *> *numberArray,329                               NSMutableArray<NSString *> *mutStringArray,330                               NSArray *array,331                               NSMutableArray *mutArray) {332  // Specialized -> unspecialized (same level)333  array = stringArray;334 335  // Unspecialized -> specialized (same level)336  stringArray = array;337 338  // Specialized -> specialized failure (same level).339  stringArray = numberArray; // expected-error{{incompatible pointer types assigning to 'NSArray<NSString *> *' from 'NSArray<NSNumber *> *'}}340 341  // Specialized -> specialized (different levels).342  stringArray = mutStringArray;343 344  // Specialized -> specialized failure (different levels).345  numberArray = mutStringArray; // expected-error{{incompatible pointer types assigning to 'NSArray<NSNumber *> *' from 'NSMutableArray<NSString *> *'}}346 347  // Unspecialized -> specialized (different levels).348  stringArray = mutArray;349 350  // Specialized -> unspecialized (different levels).351  array = mutStringArray;352}353 354@interface NSCovariant1<__covariant T>355@end356 357@interface NSContravariant1<__contravariant T>358@end359 360void test_variance(NSCovariant1<NSString *> *covariant1,361                   NSCovariant1<NSMutableString *> *covariant2,362                   NSCovariant1<NSString *(^)(void)> *covariant3,363                   NSCovariant1<NSMutableString *(^)(void)> *covariant4,364                   NSCovariant1<id> *covariant5,365                   NSCovariant1<id<NSCopying>> *covariant6,366                   NSContravariant1<NSString *> *contravariant1,367                   NSContravariant1<NSMutableString *> *contravariant2) {368  covariant1 = covariant2; // okay369  covariant2 = covariant1; // expected-error{{incompatible pointer types assigning to 'NSCovariant1<NSMutableString *> *' from 'NSCovariant1<NSString *> *'}}370 371  covariant3 = covariant4; // okay372  covariant4 = covariant3; // expected-error{{incompatible pointer types assigning to 'NSCovariant1<NSMutableString *(^)(void)> *' from 'NSCovariant1<NSString *(^)(void)> *'}}373 374  covariant5 = covariant1; // okay375  covariant1 = covariant5; // okay: id is promiscuous376 377  covariant5 = covariant3; // okay378  covariant3 = covariant5; // okay379 380  contravariant1 = contravariant2; // expected-error{{incompatible pointer types assigning to 'NSContravariant1<NSString *> *' from 'NSContravariant1<NSMutableString *> *'}}381  contravariant2 = contravariant1; // okay382}383 384// --------------------------------------------------------------------------385// Ternary operator386// --------------------------------------------------------------------------387void test_ternary_operator(NSArray<NSString *> *stringArray,388                           NSArray<NSNumber *> *numberArray,389                           NSMutableArray<NSString *> *mutStringArray,390                           NSStringArray *stringArray2,391                           NSArray *array,392                           NSMutableArray *mutArray,393                           int cond) {394  int *ip;395  id object;396 397  ip = cond ? stringArray : mutStringArray; // expected-error{{from 'NSArray<NSString *> *'}}398  ip = cond ? mutStringArray : stringArray; // expected-error{{from 'NSArray<NSString *> *'}}399 400  ip = cond ? stringArray2 : mutStringArray; // expected-error{{from 'NSArray<NSString *> *'}}401  ip = cond ? mutStringArray : stringArray2; // expected-error{{from 'NSArray<NSString *> *'}}402 403  ip = cond ? stringArray : mutArray; // expected-error{{from 'NSArray *'}}404 405  ip = cond ? stringArray2 : mutArray; // expected-error{{from 'NSArray *'}}406 407  ip = cond ? mutArray : stringArray; // expected-error{{from 'NSArray *'}}408 409  ip = cond ? mutArray : stringArray2; // expected-error{{from 'NSArray *'}}410 411  object = cond ? stringArray : numberArray; // expected-warning{{incompatible operand types ('NSArray<NSString *> *' and 'NSArray<NSNumber *> *')}}412}413 414// --------------------------------------------------------------------------415// super416// --------------------------------------------------------------------------417@implementation NSStringArray418- (void)useSuperMethod {419  int *ip;420  ip = super.lastObject; // expected-error{{from 'NSString *'}}421  super.lastObject = ip; // expected-error{{to 'NSString *'}}422  ip = [super objectAtIndexedSubscript:0]; // expected-error{{from 'NSString *'}}423}424 425+ (void)useSuperMethod {426  int *ip;427  ip = super.array; // expected-error{{from 'NSArray<NSString *> *'}}428  super.array = ip; // expected-error{{to 'NSArray<NSString *> *'}}429  ip = [super array]; // expected-error{{from 'NSArray<NSString *> *'}}430}431@end432 433// --------------------------------------------------------------------------434// warning about likely protocol/class name typos.435// --------------------------------------------------------------------------436typedef NSArray<NSObject> ArrayOfNSObjectWarning; // expected-warning{{parameterized class 'NSArray' already conforms to the protocols listed; did you forget a '*'?}}437 438@interface MyMutableDictionary<KeyType, ObjectType> : NSObject439- (void)setObject:(ObjectType)obj forKeyedSubscript:(KeyType <NSCopying>)key; // expected-note{{passing argument to parameter 'obj' here}} \440    // expected-note{{passing argument to parameter 'key' here}}441@end442 443void bar(MyMutableDictionary<NSString *, NSString *> *stringsByString,444                             NSNumber *n1, NSNumber *n2) {445  // We warn here when the key types do not match.446  stringsByString[n1] = n2; // expected-error{{incompatible pointer types sending 'NSNumber *' to parameter of type 'NSString *'}} \447    // expected-error{{incompatible pointer types sending 'NSNumber *' to parameter of type 'NSString<NSCopying> *'}}448}449 450@interface MyTest<K, V> : NSObject <NSCopying>451- (V)test:(K)key;452- (V)test2:(K)key; // expected-note{{previous definition is here}}453- (void)mapUsingBlock:(id (^)(V))block;454- (void)mapUsingBlock2:(id (^)(V))block; // expected-note{{previous definition is here}}455@end456 457@implementation MyTest458- (id)test:(id)key {459  return key;460}461- (int)test2:(id)key{ // expected-warning{{conflicting return type in implementation}}462  return 0;463}464- (void)mapUsingBlock:(id (^)(id))block {465}466- (void)mapUsingBlock2:(id)block { // expected-warning{{conflicting parameter types in implementation}}467}468@end469 470// --------------------------------------------------------------------------471// Use a type parameter as a type argument.472// --------------------------------------------------------------------------473// Type bounds in a category/extension are omitted.474@interface ParameterizedContainer<T : id<NSCopying>>475- (ParameterizedContainer<T> *)inInterface;476@end477@interface ParameterizedContainer<T> (Cat)478- (ParameterizedContainer<T> *)inCategory;479@end480@interface ParameterizedContainer<U> ()481- (ParameterizedContainer<U> *)inExtension;482@end483