blob: 1b6340b2af2897565c06a5b82479906c1c0768f4 [file] [log] [blame]
Chandler Carruth129d9242011-11-05 10:15:30 +00001// RUN: %clang --analyze -Xclang -analyzer-checker=core,experimental.cplusplus.Iterators -Xclang -verify %s
Jakob Stoklund Olesen603ea782011-03-13 00:55:43 +00002// XFAIL: win32
Ted Kremenekdd54de82011-03-12 02:49:15 +00003
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