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