1// RUN: %clang_cc1 -fsyntax-only -Wloop-analysis -verify %s 2 3struct S { 4 bool stop() { return false; } 5 bool keep_running; 6}; 7 8void by_ref(int &value) { } 9void by_value(int value) { } 10void by_pointer(int *value) {} 11 12void 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; } 22exit_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 44void 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. 111void 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. 123void 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. 137void 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. 149int x6; 150void test6() { 151 static int y; 152 for (;x6;); 153 for (;y;); 154} 155 156void 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 207struct iterator { 208 iterator operator++() { return *this; } 209 iterator operator++(int) { return *this; } 210 iterator operator--() { return *this; } 211 iterator operator--(int) { return *this; } 212}; 213void test8() { 214 iterator i; 215 for (;;i++) { // expected-note{{incremented here}} 216 if (true) test7(); 217 i++; // expected-warning{{incremented both}} 218 } 219 for (;;i++) { // expected-note{{incremented here}} 220 if (true) break; 221 ++i; // expected-warning{{incremented both}} 222 } 223 for (;;++i) { // expected-note{{incremented here}} 224 while (true) return; 225 i++; // expected-warning{{incremented both}} 226 } 227 for (;;++i) { // expected-note{{incremented here}} 228 ++i; // expected-warning{{incremented both}} 229 } 230 231 for (;;i--) { // expected-note{{decremented here}} 232 if (true) test7(); 233 i--; // expected-warning{{decremented both}} 234 } 235 for (;;i--) { // expected-note{{decremented here}} 236 if (true) break; 237 --i; // expected-warning{{decremented both}} 238 } 239 for (;;--i) { // expected-note{{decremented here}} 240 while (true) return; 241 i--; // expected-warning{{decremented both}} 242 } 243 for (;;--i) { // expected-note{{decremented here}} 244 --i; // expected-warning{{decremented both}} 245 } 246 247 // Don't warn when loop is only one statement. 248 for (;;++i) 249 i++; 250 for (;;--i) 251 --i; 252 253 // Don't warn when loop has continue statement. 254 for (;;i++) { 255 if (true) continue; 256 i++; 257 } 258 for (;;i--) { 259 if (true) continue; 260 i--; 261 } 262} 263 264int f(int); 265void test9() { 266 // Don't warn when variable is defined by the loop condition. 267 for (int i = 0; int x = f(i); ++i) {} 268} 269