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