Home | History | Annotate | Download | only in Analysis
      1 // RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.cplusplus.Iterators -verify %s
      2 // XFAIL: win32
      3 
      4 #include <vector>
      5 
      6 void fum(std::vector<int>::iterator t);
      7 
      8 void foo1()
      9 {
     10   // iterators that are defined but not initialized
     11   std::vector<int>::iterator it2;
     12   fum(it2); // expected-warning{{Use of iterator that is not defined}}
     13   *it2;     // expected-warning{{Use of iterator that is not defined}}
     14 
     15   std::vector<int> v, vv;
     16   std::vector<int>::iterator it = v.begin();
     17   fum(it);  // no-warning
     18   *it;  // no-warning
     19   // a valid iterator plus an integer is still valid
     20   std::vector<int>::iterator et = it + 3;
     21   while(it != et) { // no-warning
     22     if (*it == 0) // no-warning
     23       *it = 1;  // no-warning
     24   }
     25   // iterators from different instances Cannot be compared
     26   et = vv.end();
     27   while(it != et) // expected-warning{{Cannot compare iterators from different containers}}
     28     ;
     29 
     30   for( std::vector<int>::iterator it = v.begin(); it != v.end(); it++ ) { // no-warning
     31     if (*it == 1) // no-warning
     32       *it = 0;  // no-warning
     33   }
     34 
     35   // copying a valid iterator results in a valid iterator
     36   et = it;  // no-warning
     37   *et;  // no-warning
     38 
     39   // any combo of valid iterator plus a constant is still valid
     40   et = it + 2;  // no-warning
     41   *et;  // no-warning
     42   et = 2 + it;  // no-warning
     43   *et;  // no-warning
     44   et = 2 + 4 + it;  // no-warning
     45   *et;  // no-warning
     46 
     47   // calling insert invalidates unless assigned to as result, but still
     48   // invalidates other iterators on the same instance
     49   it = v.insert( it, 1 ); // no-warning
     50   *et;  // expected-warning{{Attempt to use an iterator made invalid by call to 'insert'}}
     51   ++it; // no-warning
     52 
     53   // calling erase invalidates the iterator
     54   v.erase(it);  // no-warning
     55   et = it + 2;  // expected-warning{{Attempt to use an iterator made invalid by call to 'erase'}}
     56   et = 2 + it + 2;  // expected-warning{{Attempt to use an iterator made invalid by call to 'erase'}}
     57   et = 2 + it;  // expected-warning{{Attempt to use an iterator made invalid by call to 'erase'}}
     58   ++it; // expected-warning{{Attempt to use an iterator made invalid by call to 'erase'}}
     59   it++; // expected-warning{{Attempt to use an iterator made invalid by call to 'erase'}}
     60   *it;  // expected-warning{{Attempt to use an iterator made invalid by call to 'erase'}}
     61   it = v.insert( it, 1 ); // expected-warning{{Attempt to use an iterator made invalid by call to 'erase'}}
     62   // now valid after return from insert
     63   *it;  // no-warning
     64 }
     65 
     66 // work with using namespace
     67 void foo2()
     68 {
     69   using namespace std;
     70 
     71   vector<int> v;
     72   vector<int>::iterator it = v.begin();
     73   *it;  // no-warning
     74   v.insert( it, 1 );  // no-warning
     75   *it;  // expected-warning{{Attempt to use an iterator made invalid by call to 'insert'}}
     76   it = v.insert( it, 1 ); // expected-warning{{Attempt to use an iterator made invalid by call to 'insert'}}
     77   *it;  // no-warning
     78 }
     79 
     80 // using reserve eliminates some warnings
     81 void foo3()
     82 {
     83   std::vector<long> v;
     84   std::vector<long>::iterator b = v.begin();
     85   v.reserve( 100 );
     86 
     87   // iterator assigned before the reserve is still invalidated
     88   *b; // expected-warning{{Attempt to use an iterator made invalid by call to 'reserve'}}
     89   b = v.begin();
     90   v.insert( b, 1 ); // no-warning
     91 
     92   // iterator after assignment is still valid (probably)
     93   *b; // no-warning
     94 }
     95 
     96 // check on copying one iterator to another
     97 void foo4()
     98 {
     99   std::vector<float> v, vv;
    100   std::vector<float>::iterator it = v.begin();
    101   *it;  // no-warning
    102   v = vv;
    103   *it;  // expected-warning{{Attempt to use an iterator made invalid by copying another container to its container}}
    104 }
    105 
    106