brintos

brintos / llvm-project-archived public Read only

0
0
Text · 20.0 KiB · 4658c3d Raw
440 lines · plain
1// RUN: %clang_cc1 -fblocks -fsyntax-only -std=c++11 %s -verify2//3// Test the substitution of type arguments for type parameters when4// using parameterized classes in Objective-C.5 6__attribute__((objc_root_class))7@interface NSObject8+ (instancetype)alloc;9- (instancetype)init;10@end11 12@protocol NSCopying13@end14 15@interface NSString : NSObject <NSCopying>16@end17 18@interface NSMutableString : NSString19@end20 21@interface NSNumber : NSObject <NSCopying>22@end23 24@interface NSArray<T> : NSObject <NSCopying> {25@public26  T *data; // don't try this at home27}28- (T)objectAtIndexedSubscript:(int)index;29+ (NSArray<T> *)array;30@property (copy,nonatomic) T lastObject;31@end32 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@end37 38@interface NSStringArray : NSArray<NSString *>39@end40 41@interface NSSet<T> : NSObject <NSCopying>42- (T)firstObject;43@property (nonatomic, copy) NSArray<T> *allObjects;44@end45 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@end50 51@interface Widget : NSObject <NSCopying>52@end53 54// Non-parameterized class inheriting from a specialization of a55// parameterized class.56@interface WidgetSet : NSMutableSet<Widget *>57@end58 59// Parameterized inheritance with a more interesting transformation in60// the specialization.61@interface MutableSetOfArrays<T> : NSMutableSet<NSArray<T>*>62@end63 64// Inheriting from an unspecialized form of a parameterized type.65@interface UntypedMutableSet : NSMutableSet66@end67 68@interface Window : NSObject69@end70 71@interface NSDictionary<K, V> : NSObject <NSCopying>72- (V)objectForKeyedSubscript:(K)key; // expected-note 2{{parameter 'key'}}73@end74 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}}82 83@property (strong) K someRandomKey;84@end85 86@interface WindowArray : NSArray<Window *>87@end88 89@interface NSSet<T> (Searching)90- (T)findObject:(T)object;91@end92 93 94// --------------------------------------------------------------------------95// Message sends.96// --------------------------------------------------------------------------97void 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'}}118 119  ip = [stringSet findObject:@"blah"]; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSString *'}}120 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 *> *'}}128 129  ip = [[NSMutableArray<NSString *> alloc] init];  // expected-error{{incompatible pointer types assigning to 'int *' from 'NSMutableArray<NSString *> *'}}130 131  [[NSMutableArray alloc] initWithArray: stringArray]; // okay132  [[NSMutableArray<NSString *> alloc] initWithArray: stringArray]; // okay133  [[NSMutableArray<NSNumber *> alloc] initWithArray: stringArray]; // expected-error{{parameter of type 'NSArray<NSNumber *> *' with an lvalue of type 'NSArray<NSString *> *'}}134}135 136void 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;145 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>'}}153}154 155// --------------------------------------------------------------------------156// Property accesses.157// --------------------------------------------------------------------------158void 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 *'}}177 178  ip = mutDict.someRandomKey; // expected-error{{incompatible pointer types assigning to 'int *' from '__kindof id<NSCopying>'}}179}180 181void 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;190 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 *'}}197 198  mutDict.someRandomKey = ip; // expected-error{{to 'id<NSCopying>'}}199}200 201// --------------------------------------------------------------------------202// Subscripting203// --------------------------------------------------------------------------204void 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;217 218  ip = stringArray[0]; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSString *'}}219 220  ip = mutStringArray[0]; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSString *'}}221  mutStringArray[0] = ip; // expected-error{{parameter of type 'NSString *'}}222 223  ip = array[0]; // expected-error{{incompatible pointer types assigning to 'int *' from 'id'}}224 225  ip = mutArray[0]; // expected-error{{incompatible pointer types assigning to 'int *' from 'id'}}226  mutArray[0] = ip; // expected-error{{parameter of type 'id'}}227 228  ip = stringWidgetDict[string]; // expected-error{{incompatible pointer types assigning to 'int *' from 'Widget *'}}229  widget = stringWidgetDict[widget]; // expected-error{{parameter of type 'NSString *'}}230 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 *'}}235 236  ip = dict[string]; // expected-error{{incompatible pointer types assigning to 'int *' from 'id'}}237 238  ip = mutDict[string]; // expected-error{{incompatible pointer types assigning to 'int *' from 'id'}}239  mutDict[string] = ip; // expected-error{{parameter of type 'id'}}240 241  widget = mutDict[window];242  mutDict[window] = widget; // expected-error{{parameter of type 'id<NSCopying>'}}243}244 245// --------------------------------------------------------------------------246// Instance variable access.247// --------------------------------------------------------------------------248void test_instance_variable(NSArray<NSString *> *stringArray,249                            NSArray *array) {250  int *ip;251 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 *'}}254}255 256@implementation WindowArray257- (void)testInstanceVariable {258  int *ip;259 260  ip = data; // expected-error{{incompatible pointer types assigning to 'int *' from 'Window **'}}261}262@end263 264// --------------------------------------------------------------------------265// Implicit conversions.266// --------------------------------------------------------------------------267void 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;274 275  // Unspecialized -> specialized (same level)276  stringArray = array;277 278  // Specialized -> specialized failure (same level).279  stringArray = numberArray; // expected-error{{incompatible pointer types assigning to 'NSArray<NSString *> *' from 'NSArray<NSNumber *> *'}}280 281  // Specialized -> specialized (different levels).282  stringArray = mutStringArray;283 284  // Specialized -> specialized failure (different levels).285  numberArray = mutStringArray; // expected-error{{incompatible pointer types assigning to 'NSArray<NSNumber *> *' from 'NSMutableArray<NSString *> *'}}286 287  // Unspecialized -> specialized (different levels).288  stringArray = mutArray;289 290  // Specialized -> unspecialized (different levels).291  array = mutStringArray;292}293 294@interface NSCovariant1<__covariant T>295@end296 297@interface NSContravariant1<__contravariant T>298@end299 300void 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; // okay309  covariant2 = covariant1; // expected-error{{incompatible pointer types assigning to 'NSCovariant1<NSMutableString *> *' from 'NSCovariant1<NSString *> *'}}310 311  covariant3 = covariant4; // okay312  covariant4 = covariant3; // expected-error{{incompatible pointer types assigning to 'NSCovariant1<NSMutableString *(^)()> *' from 'NSCovariant1<NSString *(^)()> *'}}313 314  covariant5 = covariant1; // okay315  covariant1 = covariant5; // okay: id is promiscuous316 317  covariant5 = covariant3; // okay318  covariant3 = covariant5; // okay319 320  contravariant1 = contravariant2; // expected-error{{incompatible pointer types assigning to 'NSContravariant1<NSString *> *' from 'NSContravariant1<NSMutableString *> *'}}321  contravariant2 = contravariant1; // okay322}323 324// --------------------------------------------------------------------------325// Ternary operator326// --------------------------------------------------------------------------327void 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;336 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 *> *'}}339 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 *> *'}}342 343  ip = cond ? stringArray : mutArray; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray *'}}344 345  ip = cond ? stringArray2 : mutArray; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray *'}}346 347  ip = cond ? mutArray : stringArray; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray *'}}348 349  ip = cond ? mutArray : stringArray2; // expected-error{{incompatible pointer types assigning to 'int *' from 'NSArray *'}}350 351  object = cond ? stringArray : numberArray; // expected-warning{{incompatible operand types ('NSArray<NSString *> *' and 'NSArray<NSNumber *> *')}}352}353 354// --------------------------------------------------------------------------355// super356// --------------------------------------------------------------------------357@implementation NSStringArray358- (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 *'}}362}363 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 *> *'}}368}369@end370 371// --------------------------------------------------------------------------372// Template instantiation373// --------------------------------------------------------------------------374template<typename K, typename V>375struct NSMutableDictionaryOf {376  typedef NSMutableDictionary<K, V> *type; // expected-error{{type argument 'NSObject *' does not satisfy the bound ('id<NSCopying>') of type parameter 'K'}}377};378 379template<typename ...Args>380struct 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)}}384};385 386void testInstantiation() {387  int *ip;388 389  typedef NSMutableDictionaryOf<NSString *, NSObject *>::type Dict1;390  Dict1 d1 = ip; // expected-error{{cannot initialize a variable of type 'Dict1' (aka 'NSMutableDictionary<NSString *,NSObject *> *')}}391 392  typedef NSMutableDictionaryOf<NSObject *, NSString *>::type Dict2; // expected-note{{in instantiation of template}}393}394 395void testVariadicInstantiation() {396  int *ip;397 398  typedef VariadicNSMutableDictionaryOf<NSString *, NSObject *>::type Dict1;399  Dict1 d1 = ip; // expected-error{{cannot initialize a variable of type 'Dict1' (aka 'NSMutableDictionary<NSString *,NSObject *> *')}}400 401  typedef VariadicNSMutableDictionaryOf<NSObject *, NSString *>::type Dict2; // expected-note{{in instantiation of template}}402 403  typedef VariadicNSMutableDictionaryOf<NSString *, NSObject *, NSObject *>::type Dict3; // expected-note{{in instantiation of template}}404 405  typedef VariadicNSMutableDictionaryOf<NSString *>::type Dict3; // expected-note{{in instantiation of template}}406}407 408// --------------------------------------------------------------------------409// Parameterized classes are not templates410// --------------------------------------------------------------------------411template<template<typename T, typename U> class TT>412struct AcceptsTemplateTemplate { };413 414typedef AcceptsTemplateTemplate<NSMutableDictionary> TemplateTemplateFail1; // expected-error{{template argument for template template parameter must be a class template or type alias template}}415 416template<typename T>417struct DependentTemplate {418  typedef typename T::template apply<NSString *, NSObject *> type; // expected-error{{'apply' following the 'template' keyword does not refer to a template}}419};420 421struct NSMutableDictionaryBuilder {422  typedef NSMutableDictionary apply; // expected-note 2{{declared as a non-template here}}423};424 425typedef DependentTemplate<NSMutableDictionaryBuilder>::type DependentTemplateFail1; // expected-note{{in instantiation of template class}}426 427template<typename K, typename V>428struct NonDependentTemplate {429  typedef NSMutableDictionaryBuilder::template apply<NSString *, NSObject *> type; // expected-error{{'apply' following the 'template' keyword does not refer to a template}}430};431 432// However, one can use an alias template to turn a parameterized433// class into a template.434template<typename K, typename V>435using NSMutableDictionaryAlias = NSMutableDictionary<K, V>;436 437typedef AcceptsTemplateTemplate<NSMutableDictionaryAlias> TemplateTemplateAlias1; // okay438 439 440