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