Home | History | Annotate | Download | only in Analysis
      1 // RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.NonNilReturnValue,osx.cocoa.NilArg,osx.cocoa.Loops,debug.ExprInspection -verify -Wno-objc-root-class %s
      2 
      3 void clang_analyzer_eval(int);
      4 
      5 typedef unsigned long NSUInteger;
      6 typedef signed char BOOL;
      7 typedef struct _NSZone NSZone;
      8 @class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator;
      9 @protocol NSObject
     10 @end
     11 @protocol NSCopying
     12 - (id)copyWithZone:(NSZone *)zone;
     13 @end
     14 @protocol NSMutableCopying
     15 - (id)mutableCopyWithZone:(NSZone *)zone;
     16 @end
     17 @protocol NSCoding
     18 - (void)encodeWithCoder:(NSCoder *)aCoder;
     19 @end
     20 @protocol NSSecureCoding <NSCoding>
     21 @required
     22 + (BOOL)supportsSecureCoding;
     23 @end
     24 @interface NSObject <NSObject> {}
     25 - (id)init;
     26 + (id)alloc;
     27 @end
     28 
     29 typedef struct {
     30   unsigned long state;
     31   id *itemsPtr;
     32   unsigned long *mutationsPtr;
     33   unsigned long extra[5];
     34 } NSFastEnumerationState;
     35 @protocol NSFastEnumeration
     36 - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id [])buffer count:(NSUInteger)len;
     37 @end
     38 
     39 @interface NSArray : NSObject <NSCopying, NSMutableCopying, NSSecureCoding, NSFastEnumeration>
     40 - (NSUInteger)count;
     41 - (id)objectAtIndex:(NSUInteger)index;
     42 @end
     43 
     44 @interface NSArray (NSExtendedArray)
     45 - (NSArray *)arrayByAddingObject:(id)anObject;
     46 - (void)setObject:(id)obj atIndexedSubscript:(NSUInteger)idx __attribute__((availability(macosx,introduced=10.8)));
     47 @end
     48 
     49 @interface NSArray (NSArrayCreation)
     50 + (instancetype)arrayWithObjects:(const id [])objects count:(NSUInteger)cnt;
     51 @end
     52 
     53 @interface NSMutableArray : NSArray
     54 
     55 - (void)addObject:(id)anObject;
     56 - (void)insertObject:(id)anObject atIndex:(NSUInteger)index;
     57 - (void)removeLastObject;
     58 - (void)removeObjectAtIndex:(NSUInteger)index;
     59 - (void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject;
     60 
     61 @end
     62 
     63 @interface NSDictionary : NSObject <NSCopying, NSMutableCopying, NSSecureCoding, NSFastEnumeration>
     64 
     65 - (NSUInteger)count;
     66 - (id)objectForKey:(id)aKey;
     67 - (NSEnumerator *)keyEnumerator;
     68 
     69 @end
     70 
     71 @interface NSDictionary (NSDictionaryCreation)
     72 
     73 + (id)dictionary;
     74 + (id)dictionaryWithObject:(id)object forKey:(id <NSCopying>)key;
     75 + (instancetype)dictionaryWithObjects:(const id [])objects forKeys:(const id <NSCopying> [])keys count:(NSUInteger)cnt;
     76 
     77 @end
     78 
     79 @interface NSMutableDictionary : NSDictionary
     80 
     81 - (void)removeObjectForKey:(id)aKey;
     82 - (void)setObject:(id)anObject forKey:(id <NSCopying>)aKey;
     83 
     84 @end
     85 
     86 @interface NSMutableDictionary (NSExtendedMutableDictionary)
     87 
     88 - (void)addEntriesFromDictionary:(NSDictionary *)otherDictionary;
     89 - (void)removeAllObjects;
     90 - (void)removeObjectsForKeys:(NSArray *)keyArray;
     91 - (void)setDictionary:(NSDictionary *)otherDictionary;
     92 - (void)setObject:(id)obj forKeyedSubscript:(id <NSCopying>)key __attribute__((availability(macosx,introduced=10.8)));
     93 
     94 @end
     95 
     96 @interface NSOrderedSet : NSObject <NSFastEnumeration>
     97 @end
     98 @interface NSOrderedSet (NSOrderedSetCreation)
     99 - (NSUInteger)count;
    100 @end
    101 
    102 @interface NSString : NSObject <NSCopying, NSMutableCopying, NSSecureCoding>
    103 
    104 @end
    105 
    106 @interface NSNull : NSObject <NSCopying, NSSecureCoding>
    107 + (NSNull *)null;
    108 @end
    109 
    110 // NSMutableArray API
    111 void testNilArgNSMutableArray1() {
    112   NSMutableArray *marray = [[NSMutableArray alloc] init];
    113   [marray addObject:0]; // expected-warning {{Argument to 'NSMutableArray' method 'addObject:' cannot be nil}}
    114 }
    115 
    116 void testNilArgNSMutableArray2() {
    117   NSMutableArray *marray = [[NSMutableArray alloc] init];
    118   [marray insertObject:0 atIndex:1]; // expected-warning {{Argument to 'NSMutableArray' method 'insertObject:atIndex:' cannot be nil}}
    119 }
    120 
    121 void testNilArgNSMutableArray3() {
    122   NSMutableArray *marray = [[NSMutableArray alloc] init];
    123   [marray replaceObjectAtIndex:1 withObject:0]; // expected-warning {{Argument to 'NSMutableArray' method 'replaceObjectAtIndex:withObject:' cannot be nil}}
    124 }
    125 
    126 void testNilArgNSMutableArray4() {
    127   NSMutableArray *marray = [[NSMutableArray alloc] init];
    128   [marray setObject:0 atIndexedSubscript:1]; // expected-warning {{Argument to 'NSMutableArray' method 'setObject:atIndexedSubscript:' cannot be nil}}
    129 }
    130 
    131 void testNilArgNSMutableArray5() {
    132   NSMutableArray *marray = [[NSMutableArray alloc] init];
    133   marray[1] = 0; // expected-warning {{Array element cannot be nil}}
    134 }
    135 
    136 // NSArray API
    137 void testNilArgNSArray1() {
    138   NSArray *array = [[NSArray alloc] init];
    139   NSArray *copyArray = [array arrayByAddingObject:0]; // expected-warning {{Argument to 'NSArray' method 'arrayByAddingObject:' cannot be nil}}
    140 }
    141 
    142 // NSMutableDictionary and NSDictionary APIs.
    143 void testNilArgNSMutableDictionary1(NSMutableDictionary *d, NSString* key) {
    144   [d setObject:0 forKey:key]; // expected-warning {{Value argument to 'setObject:forKey:' cannot be nil}}
    145 }
    146 
    147 void testNilArgNSMutableDictionary2(NSMutableDictionary *d, NSObject *obj) {
    148   [d setObject:obj forKey:0]; // expected-warning {{Key argument to 'setObject:forKey:' cannot be nil}}
    149 }
    150 
    151 void testNilArgNSMutableDictionary3(NSMutableDictionary *d) {
    152   [d removeObjectForKey:0]; // expected-warning {{Value argument to 'removeObjectForKey:' cannot be nil}}
    153 }
    154 
    155 void testNilArgNSMutableDictionary5(NSMutableDictionary *d, NSString* key) {
    156   d[key] = 0; // expected-warning {{Value stored into 'NSMutableDictionary' cannot be nil}}
    157 }
    158 void testNilArgNSMutableDictionary6(NSMutableDictionary *d, NSString *key) {
    159   if (key)
    160     ;
    161   d[key] = 0; // expected-warning {{'NSMutableDictionary' key cannot be nil}}
    162   // expected-warning@-1 {{Value stored into 'NSMutableDictionary' cannot be nil}}
    163 }
    164 
    165 NSDictionary *testNilArgNSDictionary1(NSString* key) {
    166   return [NSDictionary dictionaryWithObject:0 forKey:key]; // expected-warning {{Value argument to 'dictionaryWithObject:forKey:' cannot be nil}}
    167 }
    168 NSDictionary *testNilArgNSDictionary2(NSObject *obj) {
    169   return [NSDictionary dictionaryWithObject:obj forKey:0]; // expected-warning {{Key argument to 'dictionaryWithObject:forKey:' cannot be nil}}
    170 }
    171 
    172 id testCreateDictionaryLiteralKey(id value, id nilKey) {
    173   if (nilKey)
    174     ;
    175   return @{@"abc":value, nilKey:@"abc"}; // expected-warning {{Dictionary key cannot be nil}}
    176 }
    177 
    178 id testCreateDictionaryLiteralValue(id nilValue) {
    179   if (nilValue)
    180     ;
    181   return @{@"abc":nilValue}; // expected-warning {{Dictionary value cannot be nil}}
    182 }
    183 
    184 id testCreateDictionaryLiteral(id nilValue, id nilKey) {
    185   if (nilValue)
    186     ;
    187   if (nilKey)
    188     ;
    189   return @{@"abc":nilValue, nilKey:@"abc"}; // expected-warning {{Dictionary key cannot be nil}}
    190                                             // expected-warning@-1 {{Dictionary value cannot be nil}}
    191 }
    192 
    193 id testCreateArrayLiteral(id myNil) {
    194   if (myNil)
    195     ;
    196   return @[ @"a", myNil, @"c" ]; // expected-warning {{Array element cannot be nil}}
    197 }
    198 
    199 // Test inline defensive checks suppression.
    200 void idc(id x) {
    201   if (x)
    202     ;
    203 }
    204 void testIDC(NSMutableDictionary *d, NSString *key) {
    205   idc(key);
    206   d[key] = @"abc"; // no-warning
    207 }
    208 
    209 @interface Foo {
    210 @public
    211   int x;
    212 }
    213 - (int *)getPtr;
    214 - (int)getInt;
    215 - (NSMutableDictionary *)getDictPtr;
    216 @property (retain, readonly, nonatomic) Foo* data;
    217 - (NSString*) stringForKeyFE: (id<NSCopying>)key;
    218 @end
    219 
    220 void idc2(id x) {
    221 	if (!x)
    222 		return;
    223 }
    224 Foo *retNil() {
    225   return 0;
    226 }
    227 
    228 void testIDC2(Foo *obj) {
    229 	idc2(obj);
    230 	*[obj getPtr] = 1; // no-warning
    231 }
    232 
    233 int testIDC3(Foo *obj) {
    234 	idc2(obj);
    235   return 1/[obj getInt];
    236 }
    237 
    238 void testNilReceiverIDC(Foo *obj, NSString *key) {
    239 	NSMutableDictionary *D = [obj getDictPtr];
    240   idc(D);
    241   D[key] = @"abc"; // no-warning
    242 }
    243 
    244 void testNilReceiverRetNil2(NSMutableDictionary *D, Foo *FooPtrIn, id value) {
    245   NSString* const kKeyIdentifier = @"key";
    246 	Foo *FooPtr = retNil();
    247   NSString *key = [[FooPtr data] stringForKeyFE: kKeyIdentifier];
    248   // key is nil because FooPtr is nil. However, FooPtr is set to nil inside an
    249   // inlined function, so this error report should be suppressed.
    250   [D setObject: value forKey: key]; // no-warning
    251 }
    252 
    253 void testAssumeNSNullNullReturnsNonNil(NSMutableDictionary *Table, id Object,
    254                                       id InValue) {
    255   id Value = Object ? [Table objectForKey:Object] : [NSNull null];
    256   if (!Value) {
    257     Value = InValue;
    258     [Table setObject:Value forKey:Object]; // no warning
    259   }
    260 }
    261 
    262 void testCollectionIsNotEmptyWhenCountIsGreaterThanZero(NSMutableDictionary *D){
    263   if ([D count] > 0) { // Count is greater than zero.
    264     NSString *s = 0;
    265     for (NSString *key in D) {
    266       s = key;       // Loop is always entered.
    267     }
    268     [D removeObjectForKey:s]; // no warning
    269   }
    270 }
    271 
    272 void testCountAwareNSOrderedSet(NSOrderedSet *containers, int *validptr) {
    273 	int *x = 0;
    274   NSUInteger containerCount = [containers count];
    275   if (containerCount > 0)    
    276 		x = validptr;
    277 	for (id c in containers) {
    278 		*x = 1; // no warning
    279 	}
    280 }
    281 
    282 void testLiteralsNonNil() {
    283   clang_analyzer_eval(!!@[]); // expected-warning{{TRUE}}
    284   clang_analyzer_eval(!!@{}); // expected-warning{{TRUE}}
    285 }
    286 
    287 @interface NSMutableArray (MySafeAdd)
    288 - (void)addObject:(id)obj safe:(BOOL)safe;
    289 @end
    290 
    291 void testArrayCategory(NSMutableArray *arr) {
    292   [arr addObject:0 safe:1]; // no-warning
    293 }
    294 
    295