1 // RUN: %clang_cc1 -fsyntax-only -Wloop-analysis -verify -std=c++17 %s
2
3 struct S {
stopS4 bool stop() { return false; }
5 bool keep_running;
6 };
7
by_ref(int & value)8 void by_ref(int &value) { }
by_value(int value)9 void by_value(int value) { }
by_pointer(int * value)10 void by_pointer(int *value) {}
11
test1()12 void 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; }
22 exit_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
test2()44 void 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.
test3()111 void 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.
test4()123 void 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.
test5()137 void 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.
149 int x6;
test6()150 void test6() {
151 static int y;
152 for (;x6;);
153 for (;y;);
154 }
155
test7()156 void 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 // But do warn if the continue is in a nested loop.
207 for (;;i--) { // expected-note{{decremented here}}
208 for (int j = 0; j < 10; ++j) continue;
209 i--; // expected-warning{{decremented both}}
210 }
211 }
212
213 struct iterator {
operator ++iterator214 iterator operator++() { return *this; }
operator ++iterator215 iterator operator++(int) { return *this; }
operator --iterator216 iterator operator--() { return *this; }
operator --iterator217 iterator operator--(int) { return *this; }
218 };
test8()219 void test8() {
220 iterator i;
221 for (;;i++) { // expected-note{{incremented here}}
222 if (true) test7();
223 i++; // expected-warning{{incremented both}}
224 }
225 for (;;i++) { // expected-note{{incremented here}}
226 if (true) break;
227 ++i; // expected-warning{{incremented both}}
228 }
229 for (;;++i) { // expected-note{{incremented here}}
230 while (true) return;
231 i++; // expected-warning{{incremented both}}
232 }
233 for (;;++i) { // expected-note{{incremented here}}
234 ++i; // expected-warning{{incremented both}}
235 }
236
237 for (;;i--) { // expected-note{{decremented here}}
238 if (true) test7();
239 i--; // expected-warning{{decremented both}}
240 }
241 for (;;i--) { // expected-note{{decremented here}}
242 if (true) break;
243 --i; // expected-warning{{decremented both}}
244 }
245 for (;;--i) { // expected-note{{decremented here}}
246 while (true) return;
247 i--; // expected-warning{{decremented both}}
248 }
249 for (;;--i) { // expected-note{{decremented here}}
250 --i; // expected-warning{{decremented both}}
251 }
252
253 // Don't warn when loop is only one statement.
254 for (;;++i)
255 i++;
256 for (;;--i)
257 --i;
258
259 // Don't warn when loop has continue statement.
260 for (;;i++) {
261 if (true) continue;
262 i++;
263 }
264 for (;;i--) {
265 if (true) continue;
266 i--;
267 }
268
269 // But do warn if the continue is in a nested loop.
270 for (;;i--) { // expected-note{{decremented here}}
271 for (int j = 0; j < 10; ++j) continue;
272 i--; // expected-warning{{decremented both}}
273 }
274 }
275
276 int f(int);
test9()277 void test9() {
278 // Don't warn when variable is defined by the loop condition.
279 for (int i = 0; int x = f(i); ++i) {}
280 }
281
282 // Don't warn when decomposition variables are in the loop condition.
283 // TODO: BindingDecl's which make a copy should warn.
test10()284 void test10() {
285 int arr[] = {1, 2, 3};
286 for (auto[i, j, k] = arr;;) { }
287 for (auto[i, j, k] = arr; i < j; ++i, ++j) { }
288
289 for (auto[i, j, k] = arr; i;) { }
290 for (auto[i, j, k] = arr; i < j;) { }
291 for (auto[i, j, k] = arr; i < j; ++arr[0]) { }
292
293 int a = 1, b = 2;
294 for (auto[i, j, k] = arr; a < b;) { } // expected-warning{{variables 'a' and 'b' used in loop condition not modified in loop body}}
295 for (auto[i, j, k] = arr; a < b; ++a) { }
296
297 for (auto [i, j, k] = arr; i < a;) { }
298 for (auto[i, j, k] = arr; i < a; ++a) { }
299 for (auto[i, j, k] = arr; i < a; ++i) { }
300 for (auto[i, j, k] = arr; i < a; ++arr[0]) { }
301 };
302