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
4template <typename return_type>
5struct Iterator {
6  return_type operator*();
7  Iterator operator++();
8  bool operator!=(const Iterator);
9};
10
11template <typename T>
12struct Container {
13  typedef Iterator<T> I;
14
15  I begin();
16  I end();
17};
18
19struct Foo {};
20struct 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 varaible, 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
62void 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
80void 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
114void 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
145void 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
169void 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
193void 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
207void 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
221void 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
254void 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
277void 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