1// RUN: %clang_cc1 -fsyntax-only -Wloop-analysis -verify %s
2
3struct S {
4  bool stop() { return false; }
5  bool keep_running;
6};
7
8void by_ref(int &value) { }
9void by_value(int value) { }
10void by_pointer(int *value) {}
11
12void test1() {
13  S s;
14  for (; !s.stop();) {}
15  for (; s.keep_running;) {}
16  for (int i; i < 1; ++i) {}
17  for (int i; i < 1; ) {}  // expected-warning {{variable 'i' used in loop condition not modified in loop body}}
18  for (int i; i < 1; ) { ++i; }
19  for (int i; i < 1; ) { return; }
20  for (int i; i < 1; ) { break; }
21  for (int i; i < 1; ) { goto exit_loop; }
22exit_loop:
23  for (int i; i < 1; ) { by_ref(i); }
24  for (int i; i < 1; ) { by_value(i); }  // expected-warning {{variable 'i' used in loop condition not modified in loop body}}
25  for (int i; i < 1; ) { by_pointer(&i); }
26
27  for (int i; i < 1; ++i)
28    for (int j; j < 1; ++j)
29      { }
30  for (int i; i < 1; ++i)
31    for (int j; j < 1; ++i)  // expected-warning {{variable 'j' used in loop condition not modified in loop body}}
32      { }
33  for (int i; i < 1; ++i)
34    for (int j; i < 1; ++j)  // expected-warning {{variable 'i' used in loop condition not modified in loop body}}
35      { }
36
37  for (int *i, *j; i < j; ++i) {}
38  for (int *i, *j; i < j;) {}  // expected-warning {{variables 'i' and 'j' used in loop condition not modified in loop body}}
39
40  // Dereferencing pointers is ignored for now.
41  for (int *i; *i; ) {}
42}
43
44void test2() {
45  int i, j, k;
46  int *ptr;
47
48  // Testing CastExpr
49  for (; i; ) {} // expected-warning {{variable 'i' used in loop condition not modified in loop body}}
50  for (; i; ) { i = 5; }
51
52  // Testing BinaryOperator
53  for (; i < j; ) {} // expected-warning {{variables 'i' and 'j' used in loop condition not modified in loop body}}
54  for (; i < j; ) { i = 5; }
55  for (; i < j; ) { j = 5; }
56
57  // Testing IntegerLiteral
58  for (; i < 5; ) {} // expected-warning {{variable 'i' used in loop condition not modified in loop body}}
59  for (; i < 5; ) { i = 5; }
60
61  // Testing FloatingLiteral
62  for (; i < 5.0; ) {} // expected-warning {{variable 'i' used in loop condition not modified in loop body}}
63  for (; i < 5.0; ) { i = 5; }
64
65  // Testing CharacterLiteral
66  for (; i == 'a'; ) {} // expected-warning {{variable 'i' used in loop condition not modified in loop body}}
67  for (; i == 'a'; ) { i = 5; }
68
69  // Testing CXXBoolLiteralExpr
70  for (; i == true; ) {} // expected-warning {{variable 'i' used in loop condition not modified in loop body}}
71  for (; i == true; ) { i = 5; }
72
73  // Testing GNUNullExpr
74  for (; ptr == __null; ) {} // expected-warning {{variable 'ptr' used in loop condition not modified in loop body}}
75  for (; ptr == __null; ) { ptr = &i; }
76
77  // Testing UnaryOperator
78  for (; -i > 5; ) {} // expected-warning {{variable 'i' used in loop condition not modified in loop body}}
79  for (; -i > 5; ) { ++i; }
80
81  // Testing ImaginaryLiteral
82  for (; i != 3i; ) {} // expected-warning {{variable 'i' used in loop condition not modified in loop body}}
83  for (; i != 3i; ) { ++i; }
84
85  // Testing ConditionalOperator
86  for (; i ? j : k; ) {} // expected-warning {{variables 'i', 'j', and 'k' used in loop condition not modified in loop body}}
87  for (; i ? j : k; ) { ++i; }
88  for (; i ? j : k; ) { ++j; }
89  for (; i ? j : k; ) { ++k; }
90  for (; i; ) { j = i ? i : i; }  // expected-warning {{variable 'i' used in loop condition not modified in loop body}}
91  for (; i; ) { j = (i = 1) ? i : i; }
92  for (; i; ) { j = i ? i : ++i; }
93
94  // Testing BinaryConditionalOperator
95  for (; i ?: j; ) {} // expected-warning {{variables 'i' and 'j' used in loop condition not modified in loop body}}
96  for (; i ?: j; ) { ++i; }
97  for (; i ?: j; ) { ++j; }
98  for (; i; ) { j = i ?: i; }  // expected-warning {{variable 'i' used in loop condition not modified in loop body}}
99
100  // Testing ParenExpr
101  for (; (i); ) { }  // expected-warning {{variable 'i' used in loop condition not modified in loop body}}
102  for (; (i); ) { ++i; }
103
104  // Testing non-evaluated variables
105  for (; i < sizeof(j); ) { }  // expected-warning {{variable 'i' used in loop condition not modified in loop body}}
106  for (; i < sizeof(j); ) { ++j; }  // expected-warning {{variable 'i' used in loop condition not modified in loop body}}
107  for (; i < sizeof(j); ) { ++i; }
108}
109
110// False positive and how to silence.
111void test3() {
112  int x;
113  int *ptr = &x;
114  for (;x<5;) { *ptr = 6; }  // expected-warning {{variable 'x' used in loop condition not modified in loop body}}
115
116  for (;x<5;) {
117    *ptr = 6;
118    (void)x;
119  }
120}
121
122// Check ordering and printing of variables.  Max variables is currently 4.
123void test4() {
124  int a, b, c, d, e, f;
125  for (; a;);  // expected-warning {{variable 'a' used in loop condition not modified in loop body}}
126  for (; a + b;);  // expected-warning {{variables 'a' and 'b' used in loop condition not modified in loop body}}
127  for (; a + b + c;);  // expected-warning {{variables 'a', 'b', and 'c' used in loop condition not modified in loop body}}
128  for (; a + b + c + d;);  // expected-warning {{variables 'a', 'b', 'c', and 'd' used in loop condition not modified in loop body}}
129  for (; a + b + c + d + e;);  // expected-warning {{variables used in loop condition not modified in loop body}}
130  for (; a + b + c + d + e + f;);  // expected-warning {{variables used in loop condition not modified in loop body}}
131  for (; a + c + d + b;);  // expected-warning {{variables 'a', 'c', 'd', and 'b' used in loop condition not modified in loop body}}
132  for (; d + c + b + a;);  // expected-warning {{variables 'd', 'c', 'b', and 'a' used in loop condition not modified in loop body}}
133}
134
135// Ensure that the warning doesn't fail when lots of variables are used
136// in the conditional.
137void test5() {
138  for (int a; a+a+a+a+a+a+a+a+a+a;); // \
139   // expected-warning {{variable 'a' used in loop condition not modified in loop body}}
140  for (int a; a+a+a+a+a+a+a+a+a+a+a;); // \
141   // expected-warning {{variable 'a' used in loop condition not modified in loop body}}
142  for (int a; a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a;);  // \
143   // expected-warning {{variable 'a' used in loop condition not modified in loop body}}
144  for (int a; a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a;);//\
145   // expected-warning {{variable 'a' used in loop condition not modified in loop body}}
146}
147
148// Ignore global variables and static variables.
149int x6;
150void test6() {
151  static int y;
152  for (;x6;);
153  for (;y;);
154}
155
156void test7() {
157  int i;
158  for (;;i++) {  // expected-note{{incremented here}}
159    if (true) test7();
160    i++;  // expected-warning{{incremented both}}
161  }
162  for (;;i++) {  // expected-note{{incremented here}}
163    if (true) break;
164    ++i;  // expected-warning{{incremented both}}
165  }
166  for (;;++i) {  // expected-note{{incremented here}}
167    while (true) return;
168    i++;  // expected-warning{{incremented both}}
169  }
170  for (;;++i) {  // expected-note{{incremented here}}
171    ++i;  // expected-warning{{incremented both}}
172  }
173
174  for (;;i--) {  // expected-note{{decremented here}}
175    if (true) test7();
176    i--;  // expected-warning{{decremented both}}
177  }
178  for (;;i--) {  // expected-note{{decremented here}}
179    if (true) break;
180    --i;  // expected-warning{{decremented both}}
181  }
182  for (;;--i) {  // expected-note{{decremented here}}
183    while (true) return;
184    i--;  // expected-warning{{decremented both}}
185  }
186  for (;;--i) {  // expected-note{{decremented here}}
187    --i;  // expected-warning{{decremented both}}
188  }
189
190  // Don't warn when loop is only one statement.
191  for (;;++i)
192    i++;
193  for (;;--i)
194    --i;
195
196  // Don't warn when loop has continue statement.
197  for (;;i++) {
198    if (true) continue;
199    i++;
200  }
201  for (;;i--) {
202    if (true) continue;
203    i--;
204  }
205}
206
207struct iterator {
208  iterator operator++() { return *this; }
209  iterator operator++(int) { return *this; }
210  iterator operator--() { return *this; }
211  iterator operator--(int) { return *this; }
212};
213void test8() {
214  iterator i;
215  for (;;i++) {  // expected-note{{incremented here}}
216    if (true) test7();
217    i++;  // expected-warning{{incremented both}}
218  }
219  for (;;i++) {  // expected-note{{incremented here}}
220    if (true) break;
221    ++i;  // expected-warning{{incremented both}}
222  }
223  for (;;++i) {  // expected-note{{incremented here}}
224    while (true) return;
225    i++;  // expected-warning{{incremented both}}
226  }
227  for (;;++i) {  // expected-note{{incremented here}}
228    ++i;  // expected-warning{{incremented both}}
229  }
230
231  for (;;i--) {  // expected-note{{decremented here}}
232    if (true) test7();
233    i--;  // expected-warning{{decremented both}}
234  }
235  for (;;i--) {  // expected-note{{decremented here}}
236    if (true) break;
237    --i;  // expected-warning{{decremented both}}
238  }
239  for (;;--i) {  // expected-note{{decremented here}}
240    while (true) return;
241    i--;  // expected-warning{{decremented both}}
242  }
243  for (;;--i) {  // expected-note{{decremented here}}
244    --i;  // expected-warning{{decremented both}}
245  }
246
247  // Don't warn when loop is only one statement.
248  for (;;++i)
249    i++;
250  for (;;--i)
251    --i;
252
253  // Don't warn when loop has continue statement.
254  for (;;i++) {
255    if (true) continue;
256    i++;
257  }
258  for (;;i--) {
259    if (true) continue;
260    i--;
261  }
262}
263