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