Home | History | Annotate | Download | only in Analysis
      1 // RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.Loops,debug.ExprInspection -verify %s
      2 
      3 void clang_analyzer_eval(int);
      4 
      5 #define nil ((id)0)
      6 
      7 typedef unsigned long NSUInteger;
      8 @protocol NSFastEnumeration
      9 - (int)countByEnumeratingWithState:(void *)state objects:(id *)objects count:(unsigned)count;
     10 @end
     11 
     12 @interface NSObject
     13 + (instancetype)testObject;
     14 @end
     15 
     16 @interface NSEnumerator <NSFastEnumeration>
     17 @end
     18 
     19 @interface NSArray : NSObject <NSFastEnumeration>
     20 - (NSUInteger)count;
     21 - (NSEnumerator *)objectEnumerator;
     22 @end
     23 
     24 @interface NSDictionary : NSObject <NSFastEnumeration>
     25 - (NSUInteger)count;
     26 @end
     27 
     28 @interface NSMutableDictionary : NSDictionary
     29 @end
     30 
     31 @interface NSSet : NSObject <NSFastEnumeration>
     32 - (NSUInteger)count;
     33 @end
     34 
     35 @interface NSPointerArray : NSObject <NSFastEnumeration>
     36 @end
     37 
     38 @interface NSString : NSObject
     39 @end
     40 
     41 void test() {
     42   id x;
     43   for (x in [NSArray testObject])
     44     clang_analyzer_eval(x != nil); // expected-warning{{TRUE}}
     45 
     46   for (x in [NSMutableDictionary testObject])
     47     clang_analyzer_eval(x != nil); // expected-warning{{TRUE}}
     48 
     49   for (x in [NSSet testObject])
     50     clang_analyzer_eval(x != nil); // expected-warning{{TRUE}}
     51 
     52   for (x in [[NSArray testObject] objectEnumerator])
     53     clang_analyzer_eval(x != nil); // expected-warning{{TRUE}}
     54 
     55   for (x in [NSPointerArray testObject])
     56     clang_analyzer_eval(x != nil); // expected-warning{{UNKNOWN}}
     57 }
     58 
     59 void testWithVarInFor() {
     60   for (id x in [NSArray testObject])
     61     clang_analyzer_eval(x != nil); // expected-warning{{TRUE}}
     62   for (id x in [NSPointerArray testObject])
     63     clang_analyzer_eval(x != nil); // expected-warning{{UNKNOWN}}
     64 }
     65 
     66 void testNonNil(id a, id b) {
     67   clang_analyzer_eval(a != nil); // expected-warning{{UNKNOWN}}
     68   for (id x in a)
     69     clang_analyzer_eval(a != nil); // expected-warning{{TRUE}}
     70 
     71   if (b != nil)
     72     return;
     73   for (id x in b)
     74     *(volatile int *)0 = 1; // no-warning
     75   clang_analyzer_eval(b != nil); // expected-warning{{FALSE}}
     76 }
     77 
     78 void collectionIsEmpty(NSMutableDictionary *D){
     79   if ([D count] == 0) { // Count is zero.
     80     NSString *s = 0;
     81     for (NSString *key in D) {
     82       s = key;       // Loop is never entered.
     83     }
     84     clang_analyzer_eval(s == 0); //expected-warning{{TRUE}}
     85   }
     86 }
     87 
     88 void processCollection(NSMutableDictionary *D);
     89 void collectionIsEmptyCollectionIsModified(NSMutableDictionary *D){
     90   if ([D count] == 0) {      // Count is zero.
     91     NSString *s = 0;
     92     processCollection(D);  // However, the collection has changed.
     93     for (NSString *key in D) {
     94       s = key;       // Loop might be entered.
     95     }
     96     clang_analyzer_eval(s == 0); //expected-warning{{FALSE}} //expected-warning{{TRUE}}
     97   }
     98 }
     99 
    100 int collectionIsEmptyNSSet(NSSet *S){
    101   if ([S count] == 2) { // Count is non zero.
    102     int tapCounts[2];
    103     int i = 0;
    104     for (NSString *elem in S) {
    105       tapCounts[i]= 1;       // Loop is entered.
    106       i++;
    107     }
    108     return (tapCounts[0]); //no warning
    109   }
    110   return 0;
    111 }
    112 
    113 int collectionIsNotEmptyNSArray(NSArray *A) {
    114   int count = [A count];
    115   if (count > 0) {
    116     int i;
    117     int j;
    118     for (NSString *a in A) {
    119       i = 1;
    120       j++;
    121     }
    122     clang_analyzer_eval(i == 1); // expected-warning {{TRUE}}
    123   }
    124   return 0;
    125 }
    126 
    127 void onlySuppressExitAfterZeroIterations(NSMutableDictionary *D) {
    128   if (D.count > 0) {
    129     int *x;
    130     int i;
    131     for (NSString *key in D) {
    132       x = 0;
    133       i++;
    134     }
    135     // Test that this is reachable.
    136     int y = *x; // expected-warning {{Dereference of null pointer}}
    137     y++;
    138   }
    139 }
    140 
    141 void onlySuppressLoopExitAfterZeroIterations_WithContinue(NSMutableDictionary *D) {
    142   if (D.count > 0) {
    143     int *x;
    144     int i;
    145     for (NSString *key in D) {
    146       x = 0;
    147       i++;
    148       continue;
    149     }
    150     // Test that this is reachable.
    151     int y = *x; // expected-warning {{Dereference of null pointer}}
    152     y++;
    153   }
    154 }
    155 
    156 int* getPtr();
    157 void onlySuppressLoopExitAfterZeroIterations_WithBreak(NSMutableDictionary *D) {
    158   if (D.count > 0) {
    159     int *x;
    160     int i;
    161     for (NSString *key in D) {
    162       x = 0;
    163       break;
    164       x = getPtr();
    165       i++;
    166     }
    167     int y = *x; // expected-warning {{Dereference of null pointer}}
    168     y++;
    169   }
    170 }
    171 
    172 int consistencyBetweenLoopsWhenCountIsUnconstrained(NSMutableDictionary *D) {
    173   // Note, The current limitation is that we need to have a count.
    174   // TODO: This should work even when we do not call count.
    175   int count = [D count];
    176   int i;
    177   int j = 0;
    178   for (NSString *key in D) {
    179     i = 5;
    180     j++;
    181   }
    182   for (NSString *key in D)  {
    183     return i; // no-warning
    184   }
    185   return 0;
    186 }
    187 
    188 int consistencyBetweenLoopsWhenCountIsUnconstrained_dual(NSMutableDictionary *D) {
    189   int count = [D count];
    190   int i = 8;
    191   int j = 1;
    192   for (NSString *key in D) {
    193     i = 0;
    194     j++;
    195   }
    196   for (NSString *key in D)  {
    197     i = 5;
    198     j++;
    199   }
    200   return 5/i;
    201 }
    202