354 lines · plain
1// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.cocoa.Loops,debug.ExprInspection -verify -analyzer-config eagerly-assume=false %s2 3void clang_analyzer_eval(int);4void clang_analyzer_warnIfReached(void);5 6#define nil ((id)0)7 8typedef unsigned long NSUInteger;9@protocol NSFastEnumeration10- (int)countByEnumeratingWithState:(void *)state objects:(id *)objects count:(unsigned)count;11- (void)protocolMethod;12@end13 14@interface NSObject15+ (instancetype)testObject;16@end17 18@interface NSEnumerator <NSFastEnumeration>19@end20 21@interface NSArray : NSObject <NSFastEnumeration>22- (NSUInteger)count;23- (NSEnumerator *)objectEnumerator;24+ (NSArray *)arrayWithObjects:(const id [])objects count:(NSUInteger)count;25@end26 27@interface NSDictionary : NSObject <NSFastEnumeration>28- (NSUInteger)count;29- (id)objectForKey:(id)key;30+ (id)dictionaryWithObjects:(const id [])objects forKeys:(const id /* <NSCopying> */ [])keys count:(NSUInteger)count;31@end32 33@interface NSDictionary (SomeCategory)34- (void)categoryMethodOnNSDictionary;35- (id) allKeys;36@end37 38@interface NSMutableDictionary : NSDictionary39- (void)setObject:(id)obj forKey:(id)key;40@end41 42@interface NSMutableArray : NSArray43- (void)addObject:(id)obj;44@end45 46@interface NSSet : NSObject <NSFastEnumeration>47- (NSUInteger)count;48@end49 50@interface NSPointerArray : NSObject <NSFastEnumeration>51@end52 53@interface NSString : NSObject54@end55 56void test(void) {57 id x;58 for (x in [NSArray testObject])59 clang_analyzer_eval(x != nil); // expected-warning{{TRUE}}60 61 for (x in [NSMutableDictionary testObject])62 clang_analyzer_eval(x != nil); // expected-warning{{TRUE}}63 64 for (x in [NSSet testObject])65 clang_analyzer_eval(x != nil); // expected-warning{{TRUE}}66 67 for (x in [[NSArray testObject] objectEnumerator])68 clang_analyzer_eval(x != nil); // expected-warning{{TRUE}}69 70 for (x in [NSPointerArray testObject])71 clang_analyzer_eval(x != nil); // expected-warning{{UNKNOWN}}72}73 74void testWithVarInFor(void) {75 for (id x in [NSArray testObject])76 clang_analyzer_eval(x != nil); // expected-warning{{TRUE}}77 for (id x in [NSPointerArray testObject])78 clang_analyzer_eval(x != nil); // expected-warning{{UNKNOWN}}79}80 81void testNonNil(id a, id b) {82 clang_analyzer_eval(a != nil); // expected-warning{{UNKNOWN}}83 for (id x in a)84 clang_analyzer_eval(a != nil); // expected-warning{{TRUE}}85 86 if (b != nil)87 return;88 for (id x in b)89 *(volatile int *)0 = 1; // no-warning90 clang_analyzer_eval(b != nil); // expected-warning{{FALSE}}91}92 93void collectionIsEmpty(NSMutableDictionary *D){94 if ([D count] == 0) { // Count is zero.95 NSString *s = 0;96 for (NSString *key in D) {97 s = key; // Loop is never entered.98 }99 clang_analyzer_eval(s == 0); //expected-warning{{TRUE}}100 }101}102 103void processCollection(NSMutableDictionary *D);104void collectionIsEmptyCollectionIsModified(NSMutableDictionary *D){105 if ([D count] == 0) { // Count is zero.106 NSString *s = 0;107 processCollection(D); // However, the collection has changed.108 for (NSString *key in D) {109 s = key; // Loop might be entered.110 }111 clang_analyzer_eval(s == 0); //expected-warning{{FALSE}} //expected-warning{{TRUE}}112 }113}114 115int collectionIsEmptyNSSet(NSSet *S){116 if ([S count] == 2) { // Count is non-zero.117 int tapCounts[2];118 int i = 0;119 for (NSString *elem in S) {120 tapCounts[i]= 1; // Loop is entered.121 i++;122 }123 return (tapCounts[0]); //no warning124 }125 return 0;126}127 128int collectionIsNotEmptyNSArray(NSArray *A) {129 int count = [A count];130 if (count > 0) {131 int i;132 int j = 0;133 for (NSString *a in A) {134 i = 1;135 j++;136 }137 clang_analyzer_eval(i == 1); // expected-warning {{TRUE}}138 }139 return 0;140}141 142void onlySuppressExitAfterZeroIterations(NSMutableDictionary *D) {143 if (D.count > 0) {144 int *x;145 int i = 0;146 for (NSString *key in D) {147 x = 0;148 i++;149 }150 // Test that this is reachable.151 int y = *x; // expected-warning {{Dereference of null pointer}}152 y++;153 }154}155 156void onlySuppressLoopExitAfterZeroIterations_WithContinue(NSMutableDictionary *D) {157 if (D.count > 0) {158 int *x;159 int i = 0;160 for (NSString *key in D) {161 x = 0;162 i++;163 continue;164 }165 // Test that this is reachable.166 int y = *x; // expected-warning {{Dereference of null pointer}}167 y++;168 }169}170 171int* getPtr(void);172void onlySuppressLoopExitAfterZeroIterations_WithBreak(NSMutableDictionary *D) {173 if (D.count > 0) {174 int *x;175 int i;176 for (NSString *key in D) {177 x = 0;178 break;179 x = getPtr();180 i++;181 }182 int y = *x; // expected-warning {{Dereference of null pointer}}183 y++;184 }185}186 187int consistencyBetweenLoopsWhenCountIsUnconstrained(NSMutableDictionary *D,188 int shouldUseCount) {189 // Test with or without an initial count.190 int count;191 if (shouldUseCount)192 count = [D count];193 194 int i;195 int j = 0;196 for (NSString *key in D) {197 i = 5;198 j++;199 }200 for (NSString *key in D) {201 return i; // no-warning202 }203 return 0;204}205 206int consistencyBetweenLoopsWhenCountIsUnconstrained_dual(NSMutableDictionary *D,207 int shouldUseCount) {208 int count;209 if (shouldUseCount)210 count = [D count];211 212 int i = 8;213 int j = 1;214 for (NSString *key in D) {215 i = 0;216 j++;217 }218 for (NSString *key in D) {219 i = 5;220 j++;221 }222 return 5/i;223}224 225int consistencyCountThenLoop(NSArray *array) {226 if ([array count] == 0)227 return 0;228 229 int x;230 for (id y in array)231 x = 0;232 return x; // no-warning233}234 235int consistencyLoopThenCount(NSArray *array) {236 int x;237 for (id y in array)238 x = 0;239 240 if ([array count] == 0)241 return 0;242 243 return x; // no-warning244}245 246void nonMutatingMethodsDoNotInvalidateCountDictionary(NSMutableDictionary *dict,247 NSMutableArray *other) {248 if ([dict count])249 return;250 251 for (id key in dict)252 clang_analyzer_eval(0); // no-warning253 254 (void)[dict objectForKey:@""];255 256 for (id key in dict)257 clang_analyzer_eval(0); // no-warning258 259 [dict categoryMethodOnNSDictionary];260 261 for (id key in dict)262 clang_analyzer_eval(0); // no-warning263 264 [dict setObject:@"" forKey:@""];265 266 for (id key in dict)267 clang_analyzer_eval(0); // expected-warning{{FALSE}}268 269 // Reset.270 if ([dict count])271 return;272 273 for (id key in dict)274 clang_analyzer_eval(0); // no-warning275 276 [other addObject:dict];277 278 for (id key in dict)279 clang_analyzer_eval(0); // expected-warning{{FALSE}}280}281 282void nonMutatingMethodsDoNotInvalidateCountArray(NSMutableArray *array,283 NSMutableArray *other) {284 if ([array count])285 return;286 287 for (id key in array)288 clang_analyzer_eval(0); // no-warning289 290 (void)[array objectEnumerator];291 292 for (id key in array)293 clang_analyzer_eval(0); // no-warning294 295 [array addObject:@""];296 297 for (id key in array)298 clang_analyzer_eval(0); // expected-warning{{FALSE}}299 300 // Reset.301 if ([array count])302 return;303 304 for (id key in array)305 clang_analyzer_eval(0); // no-warning306 307 [other addObject:array];308 309 for (id key in array)310 clang_analyzer_eval(0); // expected-warning{{FALSE}}311}312 313void protocolMethods(NSMutableArray *array) {314 if ([array count])315 return;316 317 for (id key in array)318 clang_analyzer_eval(0); // no-warning319 320 NSArray *immutableArray = array;321 [immutableArray protocolMethod];322 323 for (id key in array)324 clang_analyzer_eval(0); // no-warning325 326 [array protocolMethod];327 328 for (id key in array)329 clang_analyzer_eval(0); // expected-warning{{FALSE}}330}331 332NSArray *globalArray;333NSDictionary *globalDictionary;334void boxedArrayEscape(NSMutableArray *array) {335 if ([array count])336 return;337 globalArray = @[array];338 for (id key in array)339 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}340 341 if ([array count])342 return;343 globalDictionary = @{ @"array" : array };344 for (id key in array)345 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}346}347 348int not_reachable_on_iteration_through_nil(void) {349 NSDictionary* d = nil;350 for (NSString* s in [d allKeys])351 clang_analyzer_warnIfReached(); // no-warning352 return 0;353}354