summaryrefslogtreecommitdiffstats
path: root/clang/test/Analysis/objc-for.m
diff options
context:
space:
mode:
Diffstat (limited to 'clang/test/Analysis/objc-for.m')
-rw-r--r--clang/test/Analysis/objc-for.m131
1 files changed, 131 insertions, 0 deletions
diff --git a/clang/test/Analysis/objc-for.m b/clang/test/Analysis/objc-for.m
index ef149c4b14a..dc855aaada2 100644
--- a/clang/test/Analysis/objc-for.m
+++ b/clang/test/Analysis/objc-for.m
@@ -4,6 +4,7 @@ void clang_analyzer_eval(int);
#define nil ((id)0)
+typedef unsigned long NSUInteger;
@protocol NSFastEnumeration
- (int)countByEnumeratingWithState:(void *)state objects:(id *)objects count:(unsigned)count;
@end
@@ -16,21 +17,27 @@ void clang_analyzer_eval(int);
@end
@interface NSArray : NSObject <NSFastEnumeration>
+- (NSUInteger)count;
- (NSEnumerator *)objectEnumerator;
@end
@interface NSDictionary : NSObject <NSFastEnumeration>
+- (NSUInteger)count;
@end
@interface NSMutableDictionary : NSDictionary
@end
@interface NSSet : NSObject <NSFastEnumeration>
+- (NSUInteger)count;
@end
@interface NSPointerArray : NSObject <NSFastEnumeration>
@end
+@interface NSString : NSObject
+@end
+
void test() {
id x;
for (x in [NSArray testObject])
@@ -68,3 +75,127 @@ void testNonNil(id a, id b) {
clang_analyzer_eval(b != nil); // expected-warning{{FALSE}}
}
+void collectionIsEmpty(NSMutableDictionary *D){
+ if ([D count] == 0) { // Count is zero.
+ NSString *s = 0;
+ for (NSString *key in D) {
+ s = key; // Loop is never entered.
+ }
+ clang_analyzer_eval(s == 0); //expected-warning{{TRUE}}
+ }
+}
+
+void processCollection(NSMutableDictionary *D);
+void collectionIsEmptyCollectionIsModified(NSMutableDictionary *D){
+ if ([D count] == 0) { // Count is zero.
+ NSString *s = 0;
+ processCollection(D); // However, the collection has changed.
+ for (NSString *key in D) {
+ s = key; // Loop might be entered.
+ }
+ clang_analyzer_eval(s == 0); //expected-warning{{FALSE}} //expected-warning{{TRUE}}
+ }
+}
+
+int collectionIsEmptyNSSet(NSSet *S){
+ if ([S count] == 2) { // Count is non zero.
+ int tapCounts[2];
+ int i = 0;
+ for (NSString *elem in S) {
+ tapCounts[i]= 1; // Loop is entered.
+ i++;
+ }
+ return (tapCounts[0]); //no warning
+ }
+ return 0;
+}
+
+int collectionIsNotEmptyNSArray(NSArray *A) {
+ int count = [A count];
+ if (count > 0) {
+ int i;
+ int j;
+ for (NSString *a in A) {
+ i = 1;
+ j++;
+ }
+ clang_analyzer_eval(i == 1); // expected-warning {{TRUE}}
+ }
+ return 0;
+}
+
+void onlySuppressExitAfterZeroIterations(NSMutableDictionary *D) {
+ if (D.count > 0) {
+ int *x;
+ int i;
+ for (NSString *key in D) {
+ x = 0;
+ i++;
+ }
+ // Test that this is reachable.
+ int y = *x; // expected-warning {{Dereference of null pointer}}
+ y++;
+ }
+}
+
+void onlySuppressLoopExitAfterZeroIterations_WithContinue(NSMutableDictionary *D) {
+ if (D.count > 0) {
+ int *x;
+ int i;
+ for (NSString *key in D) {
+ x = 0;
+ i++;
+ continue;
+ }
+ // Test that this is reachable.
+ int y = *x; // expected-warning {{Dereference of null pointer}}
+ y++;
+ }
+}
+
+int* getPtr();
+void onlySuppressLoopExitAfterZeroIterations_WithBreak(NSMutableDictionary *D) {
+ if (D.count > 0) {
+ int *x;
+ int i;
+ for (NSString *key in D) {
+ x = 0;
+ break;
+ x = getPtr();
+ i++;
+ }
+ int y = *x; // expected-warning {{Dereference of null pointer}}
+ y++;
+ }
+}
+
+int consistencyBetweenLoopsWhenCountIsUnconstrained(NSMutableDictionary *D) {
+ // Note, The current limitation is that we need to have a count.
+ // TODO: This should work even when we do not call count.
+ int count = [D count];
+ int i;
+ int j = 0;
+ for (NSString *key in D) {
+ i = 5;
+ j++;
+ }
+ for (NSString *key in D) {
+ return i; // no-warning
+ }
+ return 0;
+}
+
+int consistencyBetweenLoopsWhenCountIsUnconstrained_dual(NSMutableDictionary *D) {
+ int count = [D count];
+ int i = 8;
+ int j = 1;
+ for (NSString *key in D) {
+ i = 0;
+ j++;
+ }
+ for (NSString *key in D) {
+ i = 5;
+ j++;
+ }
+ return 5/i;
+}
OpenPOWER on IntegriCloud