302 lines · cpp
1// RUN: %clang_cc1 -fsyntax-only -Wloop-analysis -verify -std=c++17 %s2 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 CastExpr49 for (; i; ) {} // expected-warning {{variable 'i' used in loop condition not modified in loop body}}50 for (; i; ) { i = 5; }51 52 // Testing BinaryOperator53 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 IntegerLiteral58 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 FloatingLiteral62 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 CharacterLiteral66 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 CXXBoolLiteralExpr70 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 GNUNullExpr74 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 UnaryOperator78 for (; -i > 5; ) {} // expected-warning {{variable 'i' used in loop condition not modified in loop body}}79 for (; -i > 5; ) { ++i; }80 81 // Testing ImaginaryLiteral82 for (; i != 3i; ) {} // expected-warning {{variable 'i' used in loop condition not modified in loop body}}83 for (; i != 3i; ) { ++i; }84 85 // Testing ConditionalOperator86 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 BinaryConditionalOperator95 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 ParenExpr101 for (; (i); ) { } // expected-warning {{variable 'i' used in loop condition not modified in loop body}}102 for (; (i); ) { ++i; }103 104 // Testing non-evaluated variables105 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 used136// 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 // But do warn if the continue is in a nested loop.207 for (;;i--) { // expected-note{{decremented here}}208 for (int j = 0; j < 10; ++j) continue;209 i--; // expected-warning{{decremented both}}210 }211}212 213struct iterator {214 iterator operator++() { return *this; }215 iterator operator++(int) { return *this; }216 iterator operator--() { return *this; }217 iterator operator--(int) { return *this; }218};219void test8() {220 iterator i;221 for (;;i++) { // expected-note{{incremented here}}222 if (true) test7();223 i++; // expected-warning{{incremented both}}224 }225 for (;;i++) { // expected-note{{incremented here}}226 if (true) break;227 ++i; // expected-warning{{incremented both}}228 }229 for (;;++i) { // expected-note{{incremented here}}230 while (true) return;231 i++; // expected-warning{{incremented both}}232 }233 for (;;++i) { // expected-note{{incremented here}}234 ++i; // expected-warning{{incremented both}}235 }236 237 for (;;i--) { // expected-note{{decremented here}}238 if (true) test7();239 i--; // expected-warning{{decremented both}}240 }241 for (;;i--) { // expected-note{{decremented here}}242 if (true) break;243 --i; // expected-warning{{decremented both}}244 }245 for (;;--i) { // expected-note{{decremented here}}246 while (true) return;247 i--; // expected-warning{{decremented both}}248 }249 for (;;--i) { // expected-note{{decremented here}}250 --i; // expected-warning{{decremented both}}251 }252 253 // Don't warn when loop is only one statement.254 for (;;++i)255 i++;256 for (;;--i)257 --i;258 259 // Don't warn when loop has continue statement.260 for (;;i++) {261 if (true) continue;262 i++;263 }264 for (;;i--) {265 if (true) continue;266 i--;267 }268 269 // But do warn if the continue is in a nested loop.270 for (;;i--) { // expected-note{{decremented here}}271 for (int j = 0; j < 10; ++j) continue;272 i--; // expected-warning{{decremented both}}273 }274}275 276int f(int);277void test9() {278 // Don't warn when variable is defined by the loop condition.279 for (int i = 0; int x = f(i); ++i) {}280}281 282// Don't warn when decomposition variables are in the loop condition.283// TODO: BindingDecl's which make a copy should warn.284void test10() {285 int arr[] = {1, 2, 3};286 for (auto[i, j, k] = arr;;) { }287 for (auto[i, j, k] = arr; i < j; ++i, ++j) { }288 289 for (auto[i, j, k] = arr; i;) { }290 for (auto[i, j, k] = arr; i < j;) { }291 for (auto[i, j, k] = arr; i < j; ++arr[0]) { }292 293 int a = 1, b = 2;294 for (auto[i, j, k] = arr; a < b;) { } // expected-warning{{variables 'a' and 'b' used in loop condition not modified in loop body}}295 for (auto[i, j, k] = arr; a < b; ++a) { }296 297 for (auto [i, j, k] = arr; i < a;) { }298 for (auto[i, j, k] = arr; i < a; ++a) { }299 for (auto[i, j, k] = arr; i < a; ++i) { }300 for (auto[i, j, k] = arr; i < a; ++arr[0]) { }301};302