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