1 // RUN: %check_clang_tidy %s bugprone-infinite-loop %t -- -- -fexceptions
2
simple_infinite_loop1()3 void simple_infinite_loop1() {
4 int i = 0;
5 int j = 0;
6 while (i < 10) {
7 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this loop is infinite; none of its condition variables (i) are updated in the loop body [bugprone-infinite-loop]
8 j++;
9 }
10
11 while (int k = 10) {
12 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this loop is infinite; it does not check any variables in the condition [bugprone-infinite-loop]
13 j--;
14 }
15
16 while (int k = 10) {
17 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this loop is infinite; it does not check any variables in the condition [bugprone-infinite-loop]
18 k--;
19 }
20
21 do {
22 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this loop is infinite; none of its condition variables (i) are updated in the loop body [bugprone-infinite-loop]
23 j++;
24 } while (i < 10);
25
26 for (i = 0; i < 10; ++j) {
27 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this loop is infinite; none of its condition variables (i) are updated in the loop body [bugprone-infinite-loop]
28 }
29 }
30
simple_infinite_loop2()31 void simple_infinite_loop2() {
32 int i = 0;
33 int j = 0;
34 int Limit = 10;
35 while (i < Limit) {
36 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this loop is infinite; none of its condition variables (i, Limit) are updated in the loop body [bugprone-infinite-loop]
37 j++;
38 }
39
40 while (int k = Limit) {
41 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this loop is infinite; none of its condition variables (Limit) are updated in the loop body [bugprone-infinite-loop]
42 j--;
43 }
44
45 while (int k = Limit) {
46 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this loop is infinite; none of its condition variables (Limit) are updated in the loop body [bugprone-infinite-loop]
47 k--;
48 }
49
50 do {
51 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this loop is infinite; none of its condition variables (i, Limit) are updated in the loop body [bugprone-infinite-loop]
52 j++;
53 } while (i < Limit);
54
55 for (i = 0; i < Limit; ++j) {
56 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this loop is infinite; none of its condition variables (i, Limit) are updated in the loop body [bugprone-infinite-loop]
57 }
58 }
59
simple_not_infinite1()60 void simple_not_infinite1() {
61 int i = 0;
62 int Limit = 100;
63 while (i < Limit) {
64 // Not an error since 'Limit' is updated.
65 Limit--;
66 }
67
68 while (Limit--) {
69 // Not an error since 'Limit' is updated.
70 i++;
71 }
72
73 while ((Limit)--) {
74 // Not an error since 'Limit' is updated.
75 i++;
76 }
77
78 while ((Limit) -= 1) {
79 // Not an error since 'Limit' is updated.
80 }
81
82 while (int k = Limit) {
83 // Not an error since 'Limit' is updated.
84 Limit--;
85 }
86
87 while (int k = Limit) {
88 // Not an error since 'Limit' is updated
89 (Limit)--;
90 }
91
92 while (int k = Limit--) {
93 // Not an error since 'Limit' is updated.
94 i++;
95 }
96
97 do {
98 Limit--;
99 } while (i < Limit);
100
101 for (i = 0; i < Limit; Limit--) {
102 }
103
104 for (i = 0; i < Limit; (Limit) = Limit - 1) {
105 }
106
107 for (i = 0; i < Limit; (Limit) -= 1) {
108 }
109
110 for (i = 0; i < Limit; --(Limit)) {
111 }
112 }
113
simple_not_infinite2()114 void simple_not_infinite2() {
115 for (int i = 10; i-- > 0;) {
116 // Not an error, since loop variable is modified in its condition part.
117 }
118 }
119
120 int unknown_function();
121
function_call()122 void function_call() {
123 int i = 0;
124 while (i < unknown_function()) {
125 // Not an error, since the function may return different values.
126 }
127
128 do {
129 // Not an error, since the function may return different values.
130 } while (i < unknown_function());
131
132 for (i = 0; i < unknown_function();) {
133 // Not an error, since the function may return different values.
134 }
135 }
136
escape_before1()137 void escape_before1() {
138 int i = 0;
139 int Limit = 100;
140 int *p = &i;
141 while (i < Limit) {
142 // Not an error, since *p is alias of i.
143 (*p)++;
144 }
145
146 do {
147 (*p)++;
148 } while (i < Limit);
149
150 for (i = 0; i < Limit; ++(*p)) {
151 }
152 }
153
escape_before2()154 void escape_before2() {
155 int i = 0;
156 int Limit = 100;
157 int &ii = i;
158 while (i < Limit) {
159 // Not an error, since ii is alias of i.
160 ii++;
161 }
162
163 do {
164 ii++;
165 } while (i < Limit);
166
167 for (i = 0; i < Limit; ++ii) {
168 }
169 }
170
escape_inside1()171 void escape_inside1() {
172 int i = 0;
173 int Limit = 100;
174 int *p = &i;
175 while (i < Limit) {
176 // Not an error, since *p is alias of i.
177 int *p = &i;
178 (*p)++;
179 }
180
181 do {
182 int *p = &i;
183 (*p)++;
184 } while (i < Limit);
185 }
186
escape_inside2()187 void escape_inside2() {
188 int i = 0;
189 int Limit = 100;
190 while (i < Limit) {
191 // Not an error, since ii is alias of i.
192 int &ii = i;
193 ii++;
194 }
195
196 do {
197 int &ii = i;
198 ii++;
199 } while (i < Limit);
200 }
201
escape_after1()202 void escape_after1() {
203 int i = 0;
204 int j = 0;
205 int Limit = 10;
206
207 while (i < Limit) {
208 // False negative, but difficult to detect without CFG-based analysis
209 }
210 int *p = &i;
211 }
212
escape_after2()213 void escape_after2() {
214 int i = 0;
215 int j = 0;
216 int Limit = 10;
217
218 while (i < Limit) {
219 // False negative, but difficult to detect without CFG-based analysis
220 }
221 int &ii = i;
222 }
223
224 int glob;
225
global1(int & x)226 void global1(int &x) {
227 int i = 0, Limit = 100;
228 while (x < Limit) {
229 // Not an error since 'x' can be an alias of 'glob'.
230 glob++;
231 }
232 }
233
global2()234 void global2() {
235 int i = 0, Limit = 100;
236 while (glob < Limit) {
237 // Since 'glob' is declared out of the function we do not warn.
238 i++;
239 }
240 }
241
242 struct X {
243 int m;
244
245 void change_m();
246
member_expr1X247 void member_expr1(int i) {
248 while (i < m) {
249 // False negative: No warning, since skipping the case where a struct or
250 // class can be found in its condition.
251 ;
252 }
253 }
254
member_expr2X255 void member_expr2(int i) {
256 while (i < m) {
257 --m;
258 }
259 }
260
member_expr3X261 void member_expr3(int i) {
262 while (i < m) {
263 change_m();
264 }
265 }
266 };
267
array_index()268 void array_index() {
269 int i = 0;
270 int v[10];
271 while (i < 10) {
272 v[i++] = 0;
273 }
274
275 i = 0;
276 do {
277 v[i++] = 0;
278 } while (i < 9);
279
280 for (i = 0; i < 10;) {
281 v[i++] = 0;
282 }
283
284 for (i = 0; i < 10; v[i++] = 0) {
285 }
286 }
287
no_loop_variable()288 void no_loop_variable() {
289 while (0)
290 ;
291 }
292
volatile_in_condition()293 void volatile_in_condition() {
294 volatile int cond = 0;
295 while (!cond) {
296 }
297 }
298
299 namespace std {
300 template<typename T> class atomic {
301 T val;
302 public:
atomic(T v)303 atomic(T v): val(v) {};
operator T()304 operator T() { return val; };
305 };
306 }
307
atomic_in_condition()308 void atomic_in_condition() {
309 std::atomic<int> cond = 0;
310 while (!cond) {
311 }
312 }
313
loop_exit1()314 void loop_exit1() {
315 int i = 0;
316 while (i) {
317 if (unknown_function())
318 break;
319 }
320 }
321
loop_exit2()322 void loop_exit2() {
323 int i = 0;
324 while (i) {
325 if (unknown_function())
326 return;
327 }
328 }
329
loop_exit3()330 void loop_exit3() {
331 int i = 0;
332 while (i) {
333 if (unknown_function())
334 goto end;
335 }
336 end:
337 ;
338 }
339
loop_exit4()340 void loop_exit4() {
341 int i = 0;
342 while (i) {
343 if (unknown_function())
344 throw 1;
345 }
346 }
347
348 [[noreturn]] void exit(int);
349
loop_exit5()350 void loop_exit5() {
351 int i = 0;
352 while (i) {
353 if (unknown_function())
354 exit(1);
355 }
356 }
357
loop_exit_in_lambda()358 void loop_exit_in_lambda() {
359 int i = 0;
360 while (i) {
361 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this loop is infinite; none of its condition variables (i) are updated in the loop body [bugprone-infinite-loop]
362 auto l = []() { return 0; };
363 }
364 }
365
lambda_capture()366 void lambda_capture() {
367 int i = 0;
368 int Limit = 100;
369 int *p = &i;
370 while (i < Limit) {
371 // Not an error, since i is captured by reference in a lambda.
372 auto l = [&i]() { ++i; };
373 }
374
375 do {
376 int *p = &i;
377 (*p)++;
378 } while (i < Limit);
379 }
380
evaluatable(bool CondVar)381 void evaluatable(bool CondVar) {
382 for (; false && CondVar;) {
383 }
384 while (false && CondVar) {
385 }
386 do {
387 } while (false && CondVar);
388 }
389