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