brintos

brintos / llvm-project-archived public Read only

0
0
Text · 14.4 KiB · 039a5d2 Raw
409 lines · plain
1// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.ObjCGenerics,alpha.core.DynamicTypeChecker -verify -Wno-objc-method-access %s2// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.ObjCGenerics,alpha.core.DynamicTypeChecker -verify -Wno-objc-method-access %s -analyzer-output=plist -o %t.plist3// RUN: %normalize_plist <%t.plist | diff -ub %S/Inputs/expected-plists/generics.m.plist -4 5#if !__has_feature(objc_generics)6#  error Compiler does not support Objective-C generics?7#endif8 9#if !__has_feature(objc_generics_variance)10#  error Compiler does not support co- and contr-variance?11#endif12 13#define nil 014typedef unsigned long NSUInteger;15typedef int BOOL;16 17@protocol NSObject18+ (id)alloc;19- (id)init;20@end21 22@protocol NSCopying23@end24 25__attribute__((objc_root_class))26@interface NSObject <NSObject>27@end28 29@interface NSString : NSObject <NSCopying>30@end31 32@interface NSMutableString : NSString33@end34 35@interface NSNumber : NSObject <NSCopying>36@end37 38@interface NSSet : NSObject <NSCopying>39@end40 41@interface NSArray<__covariant ObjectType> : NSObject42+ (instancetype)arrayWithObjects:(const ObjectType [])objects count:(NSUInteger)count;43+ (instancetype)getEmpty;44+ (NSArray<ObjectType> *)getEmpty2;45- (BOOL)contains:(ObjectType)obj;46- (BOOL)containsObject:(ObjectType)anObject;47- (ObjectType)getObjAtIndex:(NSUInteger)idx;48- (ObjectType)objectAtIndexedSubscript:(NSUInteger)idx;49- (NSArray<ObjectType> *)arrayByAddingObject:(ObjectType)anObject;50@property(readonly) ObjectType firstObject;51@end52 53@interface NSMutableArray<ObjectType> : NSArray<ObjectType>54- (void)addObject:(ObjectType)anObject;55- (instancetype)init;56@end57 58@interface MutableArray<ObjectType> : NSArray<ObjectType>59- (void)addObject:(ObjectType)anObject;60@end61 62@interface LegacyMutableArray : MutableArray63@end64 65@interface LegacySpecialMutableArray : LegacyMutableArray66@end67 68@interface BuggyMutableArray<T> : MutableArray69@end70 71@interface BuggySpecialMutableArray<T> : BuggyMutableArray<T>72@end73 74@interface MyMutableStringArray : MutableArray<NSString *>75@end76 77@interface ExceptionalArray<ExceptionType> : MutableArray<NSString *>78- (ExceptionType) getException;79@end80 81@interface UnrelatedType : NSObject<NSCopying>82@end83 84int getUnknown(void);85NSArray *getStuff(void);86NSArray *getTypedStuff(void) {87  NSArray<NSNumber *> *c = getStuff();88  return c;89}90 91void doStuff(NSArray<NSNumber *> *);92void withArrString(NSArray<NSString *> *);93void withArrMutableString(NSArray<NSMutableString *> *);94void withMutArrString(MutableArray<NSString *> *);95void withMutArrMutableString(MutableArray<NSMutableString *> *);96 97void incompatibleTypesErased(NSArray *a, NSMutableArray<NSString *> *b,98                             NSArray<NSNumber *> *c,99                             NSMutableArray *d) {100  a = b;101  c = a; // expected-warning  {{Conversion from value of type 'NSMutableArray<NSString *> *' to incompatible type 'NSArray<NSNumber *> *'}}102  [a contains: [[NSNumber alloc] init]];103  [a contains: [[NSString alloc] init]];104  doStuff(a); // expected-warning {{Conversion}}105 106  d = b;107  [d addObject: [[NSNumber alloc] init]]; // expected-warning {{Conversion from value of type 'NSNumber *' to incompatible type 'NSString *'}}108}109 110void crossProceduralErasedTypes(void) {111  NSArray<NSString *> *a = getTypedStuff(); // expected-warning {{Conversion}}112}113 114void incompatibleTypesErasedReverseConversion(NSMutableArray *a,115                                              NSMutableArray<NSString *> *b) {116  b = a;117  [a contains: [[NSNumber alloc] init]];118  [a contains: [[NSString alloc] init]];119  doStuff(a); // expected-warning {{Conversion}}120 121  [a addObject: [[NSNumber alloc] init]]; // expected-warning {{Conversion from value of type 'NSNumber *' to incompatible type 'NSString *'}}122}123 124void idErasedIncompatibleTypesReverseConversion(id a, NSMutableArray<NSString *> *b) {125  b = a;126  [a contains: [[NSNumber alloc] init]];127  [a contains: [[NSString alloc] init]];128  doStuff(a); // expected-warning {{Conversion}}129 130  [a addObject:[[NSNumber alloc] init]]; // expected-warning {{Conversion from value of type 'NSNumber *' to incompatible type 'NSString *'}}131}132 133void idErasedIncompatibleTypes(id a, NSMutableArray<NSString *> *b,134                               NSArray<NSNumber *> *c) {135  a = b;136  c = a; // expected-warning {{Conversion}}137  [a contains: [[NSNumber alloc] init]];138  [a contains: [[NSString alloc] init]];139  doStuff(a); // expected-warning {{Conversion}}140 141  [a addObject:[[NSNumber alloc] init]]; // expected-warning {{Conversion from value of type 'NSNumber *' to incompatible type 'NSString *'}}142}143 144void pathSensitiveInference(MutableArray *m, MutableArray<NSString *> *a,145                            MutableArray<NSMutableString *> *b) {146  if (getUnknown() == 5) {147    m = a;  148    [m contains: [[NSString alloc] init]];149  } else {150    m = b;151    [m contains: [[NSMutableString alloc] init]];152  }153  [m addObject: [[NSString alloc] init]]; // expected-warning {{Conversion}}154  [m addObject: [[NSMutableString alloc] init]];155}156 157void verifyAPIusage(id a, MutableArray<NSString *> *b) {158  b = a;159  doStuff(a); // expected-warning {{Conversion}}160}161 162void dontInferFromExplicitCastsOnUnspecialized(MutableArray *a,163                        MutableArray<NSMutableString *> *b) {164  b = (MutableArray<NSMutableString *> *)a;165  [a addObject: [[NSString alloc] init]]; // no-warning166}167 168void dontWarnOnExplicitCastsAfterInference(MutableArray *a) {169  withMutArrString(a);170  withMutArrMutableString((MutableArray<NSMutableString *> *)a); // no-warning171}172 173void dontDiagnoseOnExplicitCrossCasts(MutableArray<NSSet *> *a,174                        MutableArray<NSMutableString *> *b) {175  // Treat an explicit cast to a specialized type as an indication that176  // Objective-C's type system is not expressive enough to represent a177  // the invariant the programmer wanted. After an explicit cast, do not178  // warn about potential generics shenanigans.179  b = (MutableArray<NSMutableString *> *)a; // no-warning180  [a addObject: [[NSSet alloc] init]]; // no-warning181  [b addObject: [[NSMutableString alloc] init]]; //no-warning182}183 184void subtypeOfGeneric(id d, MyMutableStringArray *a,185                       MutableArray<NSString *> *b,186                       MutableArray<NSNumber *> *c) {187  d = a;188  b = d;189  c = d; // expected-warning {{Conversion}}190}191 192void genericSubtypeOfGeneric(id d, ExceptionalArray<NSString *> *a,193                             MutableArray<NSString *> *b,194                             MutableArray<NSNumber *> *c) {195  d = a;196  [d contains: [[NSString alloc] init]];197  [d contains: [[NSNumber alloc] init]];198  b = d;199  c = d; // expected-warning {{Conversion}}200 201  [d addObject: [[NSNumber alloc] init]]; // expected-warning {{Conversion from value of type 'NSNumber *' to incompatible type 'NSString *'}}202}203 204void genericSubtypeOfGenericReverse(id d, ExceptionalArray<NSString *> *a,205                                    MutableArray<NSString *> *b,206                                    MutableArray<NSNumber *> *c) {207  a = d;208  [d contains: [[NSString alloc] init]];209  [d contains: [[NSNumber alloc] init]];210  b = d;211  c = d; // expected-warning {{Conversion}}212 213 [d addObject: [[NSNumber alloc] init]]; // expected-warning {{Conversion from value of type 'NSNumber *' to incompatible type 'NSString *'}}214}215 216void inferenceFromAPI(id a) {217  // Here the type parameter is invariant. There should be a warning every time218  // when the type parameter changes during the conversions.219  withMutArrString(a);220  withMutArrMutableString(a); // expected-warning {{Conversion}}221}222 223void inferenceFromAPI2(id a) {224  withMutArrMutableString(a);225  withMutArrString(a); // expected-warning {{Conversion}}226}227 228void inferenceFromAPIWithLegacyTypes(LegacyMutableArray *a) {229  withMutArrMutableString(a);230  withMutArrString(a); // expected-warning {{Conversion}}231}232 233void inferenceFromAPIWithLegacyTypes2(LegacySpecialMutableArray *a) {234  withMutArrString(a);235  withMutArrMutableString(a); // expected-warning {{Conversion}}236}237 238void inferenceFromAPIWithLegacyTypes3(__kindof NSArray<NSString *> *a) {239  LegacyMutableArray *b = a;240  withMutArrString(b);241  withMutArrMutableString(b); // expected-warning {{Conversion}}242}243 244void inferenceFromAPIWithBuggyTypes(BuggyMutableArray<NSMutableString *> *a) {245  withMutArrString(a);246  withMutArrMutableString(a); // expected-warning {{Conversion}}247}248 249void InferenceFromAPIWithBuggyTypes2(BuggySpecialMutableArray<NSMutableString *> *a) {250  withMutArrMutableString(a);251  withMutArrString(a); // expected-warning {{Conversion}}252}253 254void InferenceFromAPIWithBuggyTypes3(MutableArray<NSMutableString *> *a) {255  id b = a;256  withMutArrMutableString((BuggyMutableArray<NSMutableString *> *)b);257  withMutArrString(b); // expected-warning {{Conversion}}258}259 260void InferenceFromAPIWithBuggyTypes4(__kindof NSArray<NSString *> *a) {261  BuggyMutableArray<NSMutableString *> *b = a;262  withMutArrString(b);263  withMutArrMutableString(b); // expected-warning {{Conversion}}264}265 266NSArray<NSString *> *getStrings(void);267void enforceDynamicRulesInsteadOfStatic(NSArray<NSNumber *> *a) {268  NSArray *b = a;269  // Valid uses of NSArray of NSNumbers.270  b = getStrings();271  // Valid uses of NSArray of NSStrings.272}273 274void workWithProperties(NSArray<NSNumber *> *a) {275  NSArray *b = a;276  NSString *str = [b getObjAtIndex: 0]; // expected-warning {{Object has a dynamic type 'NSNumber *' which is incompatible with static type 'NSString *'}}277  NSNumber *num = [b getObjAtIndex: 0];278  str = [b firstObject]; // expected-warning {{Object has a dynamic type 'NSNumber *' which is incompatible with static type 'NSString *'}}279  num = [b firstObject];280  str = b.firstObject; // expected-warning {{Object has a dynamic type 'NSNumber *' which is incompatible with static type 'NSString *'}}281  num = b.firstObject;282  str = b[0]; // expected-warning {{Object has a dynamic type 'NSNumber *' which is incompatible with static type 'NSString *'}}283  num = b[0];284}285 286void findMethodDeclInTrackedType(id m, NSArray<NSMutableString *> *a,287                                 MutableArray<NSMutableString *> *b) {288  a = b;289  if (getUnknown() == 5) {290    m = a;  291    [m addObject: [[NSString alloc] init]]; // expected-warning {{Conversion}}292  } else {293    m = b;294    [m addObject: [[NSMutableString alloc] init]];295  }296}297 298void findMethodDeclInTrackedType2(__kindof NSArray<NSString *> *a,299                                  MutableArray<NSMutableString *> *b) {300  a = b;301  if (getUnknown() == 5) {302    [a addObject: [[NSString alloc] init]]; // expected-warning {{Conversion}}303  } else {304    [a addObject: [[NSMutableString alloc] init]];305  }306}307 308void testUnannotatedLiterals(void) {309  // ObjCArrayLiterals are not specialized in the AST. 310  NSArray *arr = @[@"A", @"B"];311  [arr contains: [[NSNumber alloc] init]];312}313 314void testAnnotatedLiterals(void) {315  NSArray<NSString *> *arr = @[@"A", @"B"];316  NSArray *arr2 = arr;317  [arr2 contains: [[NSNumber alloc] init]];318}319 320void nonExistentMethodDoesNotCrash(id a, MutableArray<NSMutableString *> *b) {321  a = b;322  [a nonExistentMethod];323}324 325void trackedClassVariables(void) {326  Class c = [NSArray<NSString *> class];327  NSArray<NSNumber *> *a = [c getEmpty]; // expected-warning {{Conversion}}328  a = [c getEmpty2]; // expected-warning {{Conversion}}329}330 331void nestedCollections(NSArray<NSArray<NSNumber *> *> *mat, NSArray<NSString *> *row) {332  id temp = row;333  [mat contains: temp]; // expected-warning {{Conversion}}334}335 336void testMistmatchedTypeCast(MutableArray<NSMutableString *> *a) {337  MutableArray *b = (MutableArray<NSNumber *> *)a;338  [b addObject: [[NSNumber alloc] init]];339  id c = (UnrelatedType *)a;340  [c addObject: [[NSNumber alloc] init]];341  [c addObject: [[NSString alloc] init]];342}343 344void returnCollectionToIdVariable(NSArray<NSArray<NSString *> *> *arr) {345  NSArray *erased = arr;346  id a = [erased firstObject];347  NSArray<NSNumber *> *res = a; // expected-warning {{Conversion}}348}349 350void eraseSpecialization(NSArray<NSArray<NSString *> *> *arr) {351  NSArray *erased = arr;352  NSArray* a = [erased firstObject];353  NSArray<NSNumber *> *res = a; // expected-warning {{Conversion}}354}355 356void returnToUnrelatedType(NSArray<NSArray<NSString *> *> *arr) {357  NSArray *erased = arr;358  NSSet* a = [erased firstObject]; // expected-warning {{Object has a dynamic type 'NSArray<NSString *> *' which is incompatible with static type 'NSSet *'}}359  (void)a;360}361 362void returnToIdVariable(NSArray<NSString *> *arr) {363  NSArray *erased = arr;364  id a = [erased firstObject];365  NSNumber *res = a; // expected-warning {{Object has a dynamic type 'NSString *' which is incompatible with static type 'NSNumber *'}}366}367 368@interface UnrelatedTypeGeneric<T> : NSObject<NSCopying>369- (void)takesType:(T)v;370@end371 372void testGetMostInformativeDerivedForId(NSArray<NSString *> *a,373                                  UnrelatedTypeGeneric<NSString *> *b) {374  id idB = b;375  a = idB; // expected-warning {{Conversion from value of type 'UnrelatedTypeGeneric<NSString *> *' to incompatible type 'NSArray<NSString *> *'}}376 377  // crash here caused by symbolic type being unrelated to compile-time source378  // type of cast.379  id x = a; // Compile-time type is NSArray<>, Symbolic type is UnrelatedTypeGeneric<>.380  [x takesType:[[NSNumber alloc] init]]; // expected-warning {{Conversion from value of type 'NSNumber *' to incompatible type 'NSString *'}}381}382 383void testArgumentAfterUpcastToRootWithCovariantTypeParameter(NSArray<NSString *> *allStrings, NSNumber *number) {384  NSArray<NSObject *> *allObjects = allStrings; // no-warning385  NSArray<NSObject *> *moreObjects = [allObjects arrayByAddingObject:number]; // no-warning386}387 388void testArgumentAfterUpcastWithCovariantTypeParameter(NSArray<NSMutableString *> *allMutableStrings, NSNumber *number) {389  NSArray<NSString *> *allStrings = allMutableStrings; // no-warning390  id numberAsId = number;391  NSArray<NSString *> *moreStrings = [allStrings arrayByAddingObject:numberAsId]; // Sema: expected-warning {{Object has a dynamic type 'NSNumber *' which is incompatible with static type 'NSString *'}}392}393 394void testArgumentAfterCastToUnspecializedWithCovariantTypeParameter(NSArray<NSMutableString *> *allMutableStrings, NSNumber *number) {395  NSArray *allStrings = allMutableStrings; // no-warning396  id numberAsId = number;397 398  NSArray *moreStringsUnspecialized = [allStrings arrayByAddingObject:numberAsId]; // no-warning399 400  // Ideally the analyzer would warn here.401  NSArray<NSString *> *moreStringsSpecialized = [allStrings arrayByAddingObject:numberAsId];402}403 404void testCallToMethodWithCovariantParameterOnInstanceOfSubclassWithInvariantParameter(NSMutableArray<NSMutableString *> *mutableArrayOfMutableStrings, NSString *someString) {405  NSArray<NSString *> *arrayOfStrings = mutableArrayOfMutableStrings;406  [arrayOfStrings containsObject:someString]; // no-warning407}408 409