1 | // RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wloop-analysis -verify %s |
2 | // RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wrange-loop-analysis -verify %s |
3 | |
4 | template <typename return_type> |
5 | struct Iterator { |
6 | return_type operator*(); |
7 | Iterator operator++(); |
8 | bool operator!=(const Iterator); |
9 | }; |
10 | |
11 | template <typename T> |
12 | struct Container { |
13 | typedef Iterator<T> I; |
14 | |
15 | I begin(); |
16 | I end(); |
17 | }; |
18 | |
19 | struct Foo {}; |
20 | struct Bar { |
21 | Bar(Foo); |
22 | Bar(int); |
23 | operator int(); |
24 | }; |
25 | |
26 | // Testing notes: |
27 | // test0 checks that the full text of the warnings and notes is correct. The |
28 | // rest of the tests checks a smaller portion of the text. |
29 | // test1-6 are set in pairs, the odd numbers are the non-reference returning |
30 | // versions of the even numbers. |
31 | // test7-9 use an array instead of a range object |
32 | // tests use all four versions of the loop variable, const &T, const T, T&, and |
33 | // T. Versions producing errors and are commented out. |
34 | // |
35 | // Conversion chart: |
36 | // double <=> int |
37 | // int <=> Bar |
38 | // double => Bar |
39 | // Foo => Bar |
40 | // |
41 | // Conversions during tests: |
42 | // test1-2 |
43 | // int => int |
44 | // int => double |
45 | // int => Bar |
46 | // test3-4 |
47 | // Bar => Bar |
48 | // Bar => int |
49 | // test5-6 |
50 | // Foo => Bar |
51 | // test7 |
52 | // double => double |
53 | // double => int |
54 | // double => Bar |
55 | // test8 |
56 | // Foo => Foo |
57 | // Foo => Bar |
58 | // test9 |
59 | // Bar => Bar |
60 | // Bar => int |
61 | |
62 | void test0() { |
63 | Container<int> int_non_ref_container; |
64 | Container<int&> int_container; |
65 | Container<Bar&> bar_container; |
66 | |
67 | for (const int &x : int_non_ref_container) {} |
68 | // expected-warning@-1 {{loop variable 'x' is always a copy because the range of type 'Container<int>' does not return a reference}} |
69 | // expected-note@-2 {{use non-reference type 'int'}} |
70 | |
71 | for (const double &x : int_container) {} |
72 | // expected-warning@-1 {{loop variable 'x' has type 'const double &' but is initialized with type 'int' resulting in a copy}} |
73 | // expected-note@-2 {{use non-reference type 'double' to keep the copy or type 'const int &' to prevent copying}} |
74 | |
75 | for (const Bar x : bar_container) {} |
76 | // expected-warning@-1 {{loop variable 'x' of type 'const Bar' creates a copy from type 'const Bar'}} |
77 | // expected-note@-2 {{use reference type 'const Bar &' to prevent copying}} |
78 | } |
79 | |
80 | void test1() { |
81 | Container<int> A; |
82 | |
83 | for (const int &x : A) {} |
84 | // expected-warning@-1 {{always a copy}} |
85 | // expected-note@-2 {{'int'}} |
86 | for (const int x : A) {} |
87 | // No warning, non-reference type indicates copy is made |
88 | //for (int &x : A) {} |
89 | // Binding error |
90 | for (int x : A) {} |
91 | // No warning, non-reference type indicates copy is made |
92 | |
93 | for (const double &x : A) {} |
94 | // expected-warning@-1 {{always a copy}} |
95 | // expected-note@-2 {{'double'}} |
96 | for (const double x : A) {} |
97 | // No warning, non-reference type indicates copy is made |
98 | //for (double &x : A) {} |
99 | // Binding error |
100 | for (double x : A) {} |
101 | // No warning, non-reference type indicates copy is made |
102 | |
103 | for (const Bar &x : A) {} |
104 | // expected-warning@-1 {{always a copy}} |
105 | // expected-note@-2 {{'Bar'}} |
106 | for (const Bar x : A) {} |
107 | // No warning, non-reference type indicates copy is made |
108 | //for (Bar &x : A) {} |
109 | // Binding error |
110 | for (Bar x : A) {} |
111 | // No warning, non-reference type indicates copy is made |
112 | } |
113 | |
114 | void test2() { |
115 | Container<int&> B; |
116 | |
117 | for (const int &x : B) {} |
118 | // No warning, this reference is not a temporary |
119 | for (const int x : B) {} |
120 | // No warning on POD copy |
121 | for (int &x : B) {} |
122 | // No warning |
123 | for (int x : B) {} |
124 | // No warning |
125 | |
126 | for (const double &x : B) {} |
127 | // expected-warning@-1 {{resulting in a copy}} |
128 | // expected-note-re@-2 {{'double'{{.*}}'const int &'}} |
129 | for (const double x : B) {} |
130 | //for (double &x : B) {} |
131 | // Binding error |
132 | for (double x : B) {} |
133 | // No warning |
134 | |
135 | for (const Bar &x : B) {} |
136 | // expected-warning@-1 {{resulting in a copy}} |
137 | // expected-note@-2 {{'Bar'}} |
138 | for (const Bar x : B) {} |
139 | //for (Bar &x : B) {} |
140 | // Binding error |
141 | for (Bar x : B) {} |
142 | // No warning |
143 | } |
144 | |
145 | void test3() { |
146 | Container<Bar> C; |
147 | |
148 | for (const Bar &x : C) {} |
149 | // expected-warning@-1 {{always a copy}} |
150 | // expected-note@-2 {{'Bar'}} |
151 | for (const Bar x : C) {} |
152 | // No warning, non-reference type indicates copy is made |
153 | //for (Bar &x : C) {} |
154 | // Binding error |
155 | for (Bar x : C) {} |
156 | // No warning, non-reference type indicates copy is made |
157 | |
158 | for (const int &x : C) {} |
159 | // expected-warning@-1 {{always a copy}} |
160 | // expected-note@-2 {{'int'}} |
161 | for (const int x : C) {} |
162 | // No warning, copy made |
163 | //for (int &x : C) {} |
164 | // Binding error |
165 | for (int x : C) {} |
166 | // No warning, copy made |
167 | } |
168 | |
169 | void test4() { |
170 | Container<Bar&> D; |
171 | |
172 | for (const Bar &x : D) {} |
173 | // No warning, this reference is not a temporary |
174 | for (const Bar x : D) {} |
175 | // expected-warning@-1 {{creates a copy}} |
176 | // expected-note@-2 {{'const Bar &'}} |
177 | for (Bar &x : D) {} |
178 | // No warning |
179 | for (Bar x : D) {} |
180 | // No warning |
181 | |
182 | for (const int &x : D) {} |
183 | // expected-warning@-1 {{resulting in a copy}} |
184 | // expected-note-re@-2 {{'int'{{.*}}'const Bar &'}} |
185 | for (const int x : D) {} |
186 | // No warning |
187 | //for (int &x : D) {} |
188 | // Binding error |
189 | for (int x : D) {} |
190 | // No warning |
191 | } |
192 | |
193 | void test5() { |
194 | Container<Foo> E; |
195 | |
196 | for (const Bar &x : E) {} |
197 | // expected-warning@-1 {{always a copy}} |
198 | // expected-note@-2 {{'Bar'}} |
199 | for (const Bar x : E) {} |
200 | // No warning, non-reference type indicates copy is made |
201 | //for (Bar &x : E) {} |
202 | // Binding error |
203 | for (Bar x : E) {} |
204 | // No warning, non-reference type indicates copy is made |
205 | } |
206 | |
207 | void test6() { |
208 | Container<Foo&> F; |
209 | |
210 | for (const Bar &x : F) {} |
211 | // expected-warning@-1 {{resulting in a copy}} |
212 | // expected-note-re@-2 {{'Bar'{{.*}}'const Foo &'}} |
213 | for (const Bar x : F) {} |
214 | // No warning. |
215 | //for (Bar &x : F) {} |
216 | // Binding error |
217 | for (Bar x : F) {} |
218 | // No warning |
219 | } |
220 | |
221 | void test7() { |
222 | double G[2]; |
223 | |
224 | for (const double &x : G) {} |
225 | // No warning |
226 | for (const double x : G) {} |
227 | // No warning on POD copy |
228 | for (double &x : G) {} |
229 | // No warning |
230 | for (double x : G) {} |
231 | // No warning |
232 | |
233 | for (const int &x : G) {} |
234 | // expected-warning@-1 {{resulting in a copy}} |
235 | // expected-note-re@-2 {{'int'{{.*}}'const double &'}} |
236 | for (const int x : G) {} |
237 | // No warning |
238 | //for (int &x : G) {} |
239 | // Binding error |
240 | for (int x : G) {} |
241 | // No warning |
242 | |
243 | for (const Bar &x : G) {} |
244 | // expected-warning@-1 {{resulting in a copy}} |
245 | // expected-note-re@-2 {{'Bar'{{.*}}'const double &'}} |
246 | for (const Bar x : G) {} |
247 | // No warning |
248 | //for (int &Bar : G) {} |
249 | // Binding error |
250 | for (int Bar : G) {} |
251 | // No warning |
252 | } |
253 | |
254 | void test8() { |
255 | Foo H[2]; |
256 | |
257 | for (const Foo &x : H) {} |
258 | // No warning |
259 | for (const Foo x : H) {} |
260 | // No warning on POD copy |
261 | for (Foo &x : H) {} |
262 | // No warning |
263 | for (Foo x : H) {} |
264 | // No warning |
265 | |
266 | for (const Bar &x : H) {} |
267 | // expected-warning@-1 {{resulting in a copy}} |
268 | // expected-note-re@-2 {{'Bar'{{.*}}'const Foo &'}} |
269 | for (const Bar x : H) {} |
270 | // No warning |
271 | //for (Bar &x: H) {} |
272 | // Binding error |
273 | for (Bar x: H) {} |
274 | // No warning |
275 | } |
276 | |
277 | void test9() { |
278 | Bar I[2] = {1,2}; |
279 | |
280 | for (const Bar &x : I) {} |
281 | // No warning |
282 | for (const Bar x : I) {} |
283 | // expected-warning@-1 {{creates a copy}} |
284 | // expected-note@-2 {{'const Bar &'}} |
285 | for (Bar &x : I) {} |
286 | // No warning |
287 | for (Bar x : I) {} |
288 | // No warning |
289 | |
290 | for (const int &x : I) {} |
291 | // expected-warning@-1 {{resulting in a copy}} |
292 | // expected-note-re@-2 {{'int'{{.*}}'const Bar &'}} |
293 | for (const int x : I) {} |
294 | // No warning |
295 | //for (int &x : I) {} |
296 | // Binding error |
297 | for (int x : I) {} |
298 | // No warning |
299 | } |
300 | |