1 | // RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,cplusplus,alpha.cplusplus.MismatchedIterator -analyzer-config aggressive-binary-operation-simplification=true -analyzer-config c++-container-inlining=false %s -verify |
2 | // RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,cplusplus,alpha.cplusplus.MismatchedIterator -analyzer-config aggressive-binary-operation-simplification=true -analyzer-config c++-container-inlining=true -DINLINE=1 %s -verify |
3 | |
4 | #include "Inputs/system-header-simulator-cxx.h" |
5 | |
6 | void good_insert1(std::vector<int> &v, int n) { |
7 | v.insert(v.cbegin(), n); // no-warning |
8 | } |
9 | |
10 | |
11 | void good_insert2(std::vector<int> &v, int len, int n) { |
12 | v.insert(v.cbegin(), len, n); // no-warning |
13 | } |
14 | |
15 | void good_insert3(std::vector<int> &v1, std::vector<int> &v2) { |
16 | v1.insert(v1.cbegin(), v2.cbegin(), v2.cend()); // no-warning |
17 | } |
18 | |
19 | void good_insert4(std::vector<int> &v, int len, int n) { |
20 | v.insert(v.cbegin(), {n-1, n, n+1}); // no-warning |
21 | } |
22 | |
23 | void good_insert_find(std::vector<int> &v, int n, int m) { |
24 | auto i = std::find(v.cbegin(), v.cend(), n); |
25 | v.insert(i, m); // no-warning |
26 | } |
27 | |
28 | void good_erase1(std::vector<int> &v) { |
29 | v.erase(v.cbegin()); // no-warning |
30 | } |
31 | |
32 | void good_erase2(std::vector<int> &v) { |
33 | v.erase(v.cbegin(), v.cend()); // no-warning |
34 | } |
35 | |
36 | void good_emplace(std::vector<int> &v, int n) { |
37 | v.emplace(v.cbegin(), n); // no-warning |
38 | } |
39 | |
40 | void good_ctor(std::vector<int> &v) { |
41 | std::vector<int> new_v(v.cbegin(), v.cend()); // no-warning |
42 | } |
43 | |
44 | void good_find(std::vector<int> &v, int n) { |
45 | std::find(v.cbegin(), v.cend(), n); // no-warning |
46 | } |
47 | |
48 | void good_find_first_of(std::vector<int> &v1, std::vector<int> &v2) { |
49 | std::find_first_of(v1.cbegin(), v1.cend(), v2.cbegin(), v2.cend()); // no-warning |
50 | } |
51 | |
52 | void good_copy(std::vector<int> &v1, std::vector<int> &v2, int n) { |
53 | std::copy(v1.cbegin(), v1.cend(), v2.begin()); // no-warning |
54 | } |
55 | |
56 | void good_move_find1(std::vector<int> &v1, std::vector<int> &v2, int n) { |
57 | auto i0 = v2.cbegin(); |
58 | v1 = std::move(v2); |
59 | std::find(i0, v1.cend(), n); // no-warning |
60 | } |
61 | |
62 | void bad_insert1(std::vector<int> &v1, std::vector<int> &v2, int n) { |
63 | v2.insert(v1.cbegin(), n); // expected-warning{{Container accessed using foreign iterator argument}} |
64 | } |
65 | |
66 | void bad_insert2(std::vector<int> &v1, std::vector<int> &v2, int len, int n) { |
67 | v2.insert(v1.cbegin(), len, n); // expected-warning{{Container accessed using foreign iterator argument}} |
68 | } |
69 | |
70 | void bad_insert3(std::vector<int> &v1, std::vector<int> &v2) { |
71 | v2.insert(v1.cbegin(), v2.cbegin(), v2.cend()); // expected-warning{{Container accessed using foreign iterator argument}} |
72 | v1.insert(v1.cbegin(), v1.cbegin(), v2.cend()); // expected-warning{{Iterators of different containers used where the same container is expected}} |
73 | v1.insert(v1.cbegin(), v2.cbegin(), v1.cend()); // expected-warning{{Iterators of different containers used where the same container is expected}} |
74 | } |
75 | |
76 | void bad_insert4(std::vector<int> &v1, std::vector<int> &v2, int len, int n) { |
77 | v2.insert(v1.cbegin(), {n-1, n, n+1}); // expected-warning{{Container accessed using foreign iterator argument}} |
78 | } |
79 | |
80 | void bad_erase1(std::vector<int> &v1, std::vector<int> &v2) { |
81 | v2.erase(v1.cbegin()); // expected-warning{{Container accessed using foreign iterator argument}} |
82 | } |
83 | |
84 | void bad_erase2(std::vector<int> &v1, std::vector<int> &v2) { |
85 | v2.erase(v2.cbegin(), v1.cend()); // expected-warning{{Container accessed using foreign iterator argument}} |
86 | v2.erase(v1.cbegin(), v2.cend()); // expected-warning{{Container accessed using foreign iterator argument}} |
87 | v2.erase(v1.cbegin(), v1.cend()); // expected-warning{{Container accessed using foreign iterator argument}} |
88 | } |
89 | |
90 | void bad_emplace(std::vector<int> &v1, std::vector<int> &v2, int n) { |
91 | v2.emplace(v1.cbegin(), n); // expected-warning{{Container accessed using foreign iterator argument}} |
92 | } |
93 | |
94 | void good_move_find2(std::vector<int> &v1, std::vector<int> &v2, int n) { |
95 | auto i0 = --v2.cend(); |
96 | v1 = std::move(v2); |
97 | std::find(i0, v1.cend(), n); // no-warning |
98 | } |
99 | |
100 | void good_move_find3(std::vector<int> &v1, std::vector<int> &v2, int n) { |
101 | auto i0 = v2.cend(); |
102 | v1 = std::move(v2); |
103 | v2.push_back(n); // expected-warning{{Method called on moved-from object of type 'std::vector'}} |
104 | std::find(v2.cbegin(), i0, n); // no-warning |
105 | } |
106 | |
107 | void good_comparison(std::vector<int> &v) { |
108 | if (v.cbegin() == v.cend()) {} // no-warning |
109 | } |
110 | |
111 | void bad_ctor(std::vector<int> &v1, std::vector<int> &v2) { |
112 | std::vector<int> new_v(v1.cbegin(), v2.cend()); // expected-warning{{Iterators of different containers used where the same container is expected}} |
113 | } |
114 | |
115 | void bad_find(std::vector<int> &v1, std::vector<int> &v2, int n) { |
116 | std::find(v1.cbegin(), v2.cend(), n); // expected-warning{{Iterators of different containers used where the same container is expected}} |
117 | } |
118 | |
119 | void bad_find_first_of(std::vector<int> &v1, std::vector<int> &v2) { |
120 | std::find_first_of(v1.cbegin(), v2.cend(), v2.cbegin(), v2.cend()); // expected-warning{{Iterators of different containers used where the same container is expected}} |
121 | std::find_first_of(v1.cbegin(), v1.cend(), v2.cbegin(), v1.cend()); // expected-warning{{Iterators of different containers used where the same container is expected}} |
122 | } |
123 | |
124 | void bad_move_find1(std::vector<int> &v1, std::vector<int> &v2, int n) { |
125 | auto i0 = v2.cbegin(); |
126 | v1 = std::move(v2); |
127 | std::find(i0, v2.cend(), n); // expected-warning{{Iterators of different containers used where the same container is expected}} |
128 | // expected-warning@-1{{Method called on moved-from object of type 'std::vector'}} |
129 | } |
130 | |
131 | void bad_insert_find(std::vector<int> &v1, std::vector<int> &v2, int n, int m) { |
132 | auto i = std::find(v1.cbegin(), v1.cend(), n); |
133 | v2.insert(i, m); // expected-warning{{Container accessed using foreign iterator argument}} |
134 | } |
135 | |
136 | void good_overwrite(std::vector<int> &v1, std::vector<int> &v2, int n) { |
137 | auto i = v1.cbegin(); |
138 | i = v2.cbegin(); |
139 | v2.insert(i, n); // no-warning |
140 | } |
141 | |
142 | void bad_overwrite(std::vector<int> &v1, std::vector<int> &v2, int n) { |
143 | auto i = v1.cbegin(); |
144 | i = v2.cbegin(); |
145 | v1.insert(i, n); // expected-warning{{Container accessed using foreign iterator argument}} |
146 | } |
147 | |
148 | template<typename Container, typename Iterator> |
149 | bool is_cend(Container cont, Iterator it) { |
150 | return it == cont.cend(); |
151 | } |
152 | |
153 | void good_empty(std::vector<int> &v) { |
154 | is_cend(v, v.cbegin()); // no-warning |
155 | } |
156 | |
157 | void bad_empty(std::vector<int> &v1, std::vector<int> &v2) { |
158 | is_cend(v1, v2.cbegin()); // expected-warning@-8{{Iterators of different containers used where the same container is expected}} |
159 | } |
160 | |
161 | void good_move(std::vector<int> &v1, std::vector<int> &v2) { |
162 | const auto i0 = ++v2.cbegin(); |
163 | v1 = std::move(v2); |
164 | v1.erase(i0); // no-warning |
165 | } |
166 | |
167 | void bad_move(std::vector<int> &v1, std::vector<int> &v2) { |
168 | const auto i0 = ++v2.cbegin(); |
169 | v1 = std::move(v2); |
170 | v2.erase(i0); // expected-warning{{Container accessed using foreign iterator argument}} |
171 | // expected-warning@-1{{Method called on moved-from object of type 'std::vector'}} |
172 | } |
173 | |
174 | void bad_move_find2(std::vector<int> &v1, std::vector<int> &v2, int n) { |
175 | auto i0 = --v2.cend(); |
176 | v1 = std::move(v2); |
177 | std::find(i0, v2.cend(), n); // expected-warning{{Iterators of different containers used where the same container is expected}} |
178 | // expected-warning@-1{{Method called on moved-from object of type 'std::vector'}} |
179 | } |
180 | |
181 | void bad_move_find3(std::vector<int> &v1, std::vector<int> &v2, int n) { |
182 | auto i0 = v2.cend(); |
183 | v1 = std::move(v2); |
184 | std::find(v1.cbegin(), i0, n); // expected-warning{{Iterators of different containers used where the same container is expected}} |
185 | } |
186 | |
187 | void bad_comparison(std::vector<int> &v1, std::vector<int> &v2) { |
188 | if (v1.cbegin() != v2.cend()) { // expected-warning{{Iterators of different containers used where the same container is expected}} |
189 | *v1.cbegin(); |
190 | } |
191 | } |
192 | |
193 | std::vector<int> &return_vector_ref(); |
194 | |
195 | void ignore_conjured1() { |
196 | std::vector<int> &v1 = return_vector_ref(), &v2 = return_vector_ref(); |
197 | |
198 | v2.erase(v1.cbegin()); // no-warning |
199 | } |
200 | |
201 | void ignore_conjured2() { |
202 | std::vector<int> &v1 = return_vector_ref(), &v2 = return_vector_ref(); |
203 | |
204 | if (v1.cbegin() == v2.cbegin()) {} //no-warning |
205 | } |
206 | |