• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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