1// RUN: %clang --analyze -Xclang -analyzer-checker=core,experimental.cplusplus.Iterators -Xclang -verify %s 2// XFAIL: win32 3 4#include <vector> 5 6void fum(std::vector<int>::iterator t); 7 8void 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 67void 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 81void 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 97void 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