1// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.Loops,debug.ExprInspection -verify %s 2 3void clang_analyzer_eval(int); 4 5#define nil ((id)0) 6 7typedef unsigned long NSUInteger; 8@protocol NSFastEnumeration 9- (int)countByEnumeratingWithState:(void *)state objects:(id *)objects count:(unsigned)count; 10- (void)protocolMethod; 11@end 12 13@interface NSObject 14+ (instancetype)testObject; 15@end 16 17@interface NSEnumerator <NSFastEnumeration> 18@end 19 20@interface NSArray : NSObject <NSFastEnumeration> 21- (NSUInteger)count; 22- (NSEnumerator *)objectEnumerator; 23@end 24 25@interface NSDictionary : NSObject <NSFastEnumeration> 26- (NSUInteger)count; 27- (id)objectForKey:(id)key; 28@end 29 30@interface NSDictionary (SomeCategory) 31- (void)categoryMethodOnNSDictionary; 32@end 33 34@interface NSMutableDictionary : NSDictionary 35- (void)setObject:(id)obj forKey:(id)key; 36@end 37 38@interface NSMutableArray : NSArray 39- (void)addObject:(id)obj; 40@end 41 42@interface NSSet : NSObject <NSFastEnumeration> 43- (NSUInteger)count; 44@end 45 46@interface NSPointerArray : NSObject <NSFastEnumeration> 47@end 48 49@interface NSString : NSObject 50@end 51 52void test() { 53 id x; 54 for (x in [NSArray testObject]) 55 clang_analyzer_eval(x != nil); // expected-warning{{TRUE}} 56 57 for (x in [NSMutableDictionary testObject]) 58 clang_analyzer_eval(x != nil); // expected-warning{{TRUE}} 59 60 for (x in [NSSet testObject]) 61 clang_analyzer_eval(x != nil); // expected-warning{{TRUE}} 62 63 for (x in [[NSArray testObject] objectEnumerator]) 64 clang_analyzer_eval(x != nil); // expected-warning{{TRUE}} 65 66 for (x in [NSPointerArray testObject]) 67 clang_analyzer_eval(x != nil); // expected-warning{{UNKNOWN}} 68} 69 70void testWithVarInFor() { 71 for (id x in [NSArray testObject]) 72 clang_analyzer_eval(x != nil); // expected-warning{{TRUE}} 73 for (id x in [NSPointerArray testObject]) 74 clang_analyzer_eval(x != nil); // expected-warning{{UNKNOWN}} 75} 76 77void testNonNil(id a, id b) { 78 clang_analyzer_eval(a != nil); // expected-warning{{UNKNOWN}} 79 for (id x in a) 80 clang_analyzer_eval(a != nil); // expected-warning{{TRUE}} 81 82 if (b != nil) 83 return; 84 for (id x in b) 85 *(volatile int *)0 = 1; // no-warning 86 clang_analyzer_eval(b != nil); // expected-warning{{FALSE}} 87} 88 89void collectionIsEmpty(NSMutableDictionary *D){ 90 if ([D count] == 0) { // Count is zero. 91 NSString *s = 0; 92 for (NSString *key in D) { 93 s = key; // Loop is never entered. 94 } 95 clang_analyzer_eval(s == 0); //expected-warning{{TRUE}} 96 } 97} 98 99void processCollection(NSMutableDictionary *D); 100void collectionIsEmptyCollectionIsModified(NSMutableDictionary *D){ 101 if ([D count] == 0) { // Count is zero. 102 NSString *s = 0; 103 processCollection(D); // However, the collection has changed. 104 for (NSString *key in D) { 105 s = key; // Loop might be entered. 106 } 107 clang_analyzer_eval(s == 0); //expected-warning{{FALSE}} //expected-warning{{TRUE}} 108 } 109} 110 111int collectionIsEmptyNSSet(NSSet *S){ 112 if ([S count] == 2) { // Count is non-zero. 113 int tapCounts[2]; 114 int i = 0; 115 for (NSString *elem in S) { 116 tapCounts[i]= 1; // Loop is entered. 117 i++; 118 } 119 return (tapCounts[0]); //no warning 120 } 121 return 0; 122} 123 124int collectionIsNotEmptyNSArray(NSArray *A) { 125 int count = [A count]; 126 if (count > 0) { 127 int i; 128 int j; 129 for (NSString *a in A) { 130 i = 1; 131 j++; 132 } 133 clang_analyzer_eval(i == 1); // expected-warning {{TRUE}} 134 } 135 return 0; 136} 137 138void onlySuppressExitAfterZeroIterations(NSMutableDictionary *D) { 139 if (D.count > 0) { 140 int *x; 141 int i; 142 for (NSString *key in D) { 143 x = 0; 144 i++; 145 } 146 // Test that this is reachable. 147 int y = *x; // expected-warning {{Dereference of null pointer}} 148 y++; 149 } 150} 151 152void onlySuppressLoopExitAfterZeroIterations_WithContinue(NSMutableDictionary *D) { 153 if (D.count > 0) { 154 int *x; 155 int i; 156 for (NSString *key in D) { 157 x = 0; 158 i++; 159 continue; 160 } 161 // Test that this is reachable. 162 int y = *x; // expected-warning {{Dereference of null pointer}} 163 y++; 164 } 165} 166 167int* getPtr(); 168void onlySuppressLoopExitAfterZeroIterations_WithBreak(NSMutableDictionary *D) { 169 if (D.count > 0) { 170 int *x; 171 int i; 172 for (NSString *key in D) { 173 x = 0; 174 break; 175 x = getPtr(); 176 i++; 177 } 178 int y = *x; // expected-warning {{Dereference of null pointer}} 179 y++; 180 } 181} 182 183int consistencyBetweenLoopsWhenCountIsUnconstrained(NSMutableDictionary *D, 184 int shouldUseCount) { 185 // Test with or without an initial count. 186 int count; 187 if (shouldUseCount) 188 count = [D count]; 189 190 int i; 191 int j = 0; 192 for (NSString *key in D) { 193 i = 5; 194 j++; 195 } 196 for (NSString *key in D) { 197 return i; // no-warning 198 } 199 return 0; 200} 201 202int consistencyBetweenLoopsWhenCountIsUnconstrained_dual(NSMutableDictionary *D, 203 int shouldUseCount) { 204 int count; 205 if (shouldUseCount) 206 count = [D count]; 207 208 int i = 8; 209 int j = 1; 210 for (NSString *key in D) { 211 i = 0; 212 j++; 213 } 214 for (NSString *key in D) { 215 i = 5; 216 j++; 217 } 218 return 5/i; 219} 220 221int consistencyCountThenLoop(NSArray *array) { 222 if ([array count] == 0) 223 return 0; 224 225 int x; 226 for (id y in array) 227 x = 0; 228 return x; // no-warning 229} 230 231int consistencyLoopThenCount(NSArray *array) { 232 int x; 233 for (id y in array) 234 x = 0; 235 236 if ([array count] == 0) 237 return 0; 238 239 return x; // no-warning 240} 241 242void nonMutatingMethodsDoNotInvalidateCountDictionary(NSMutableDictionary *dict, 243 NSMutableArray *other) { 244 if ([dict count]) 245 return; 246 247 for (id key in dict) 248 clang_analyzer_eval(0); // no-warning 249 250 (void)[dict objectForKey:@""]; 251 252 for (id key in dict) 253 clang_analyzer_eval(0); // no-warning 254 255 [dict categoryMethodOnNSDictionary]; 256 257 for (id key in dict) 258 clang_analyzer_eval(0); // no-warning 259 260 [dict setObject:@"" forKey:@""]; 261 262 for (id key in dict) 263 clang_analyzer_eval(0); // expected-warning{{FALSE}} 264 265 // Reset. 266 if ([dict count]) 267 return; 268 269 for (id key in dict) 270 clang_analyzer_eval(0); // no-warning 271 272 [other addObject:dict]; 273 274 for (id key in dict) 275 clang_analyzer_eval(0); // expected-warning{{FALSE}} 276} 277 278void nonMutatingMethodsDoNotInvalidateCountArray(NSMutableArray *array, 279 NSMutableArray *other) { 280 if ([array count]) 281 return; 282 283 for (id key in array) 284 clang_analyzer_eval(0); // no-warning 285 286 (void)[array objectEnumerator]; 287 288 for (id key in array) 289 clang_analyzer_eval(0); // no-warning 290 291 [array addObject:@""]; 292 293 for (id key in array) 294 clang_analyzer_eval(0); // expected-warning{{FALSE}} 295 296 // Reset. 297 if ([array count]) 298 return; 299 300 for (id key in array) 301 clang_analyzer_eval(0); // no-warning 302 303 [other addObject:array]; 304 305 for (id key in array) 306 clang_analyzer_eval(0); // expected-warning{{FALSE}} 307} 308 309void protocolMethods(NSMutableArray *array) { 310 if ([array count]) 311 return; 312 313 for (id key in array) 314 clang_analyzer_eval(0); // no-warning 315 316 NSArray *immutableArray = array; 317 [immutableArray protocolMethod]; 318 319 for (id key in array) 320 clang_analyzer_eval(0); // no-warning 321 322 [array protocolMethod]; 323 324 for (id key in array) 325 clang_analyzer_eval(0); // expected-warning{{FALSE}} 326} 327