269 lines
		
	
	
		
			9.1 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			269 lines
		
	
	
		
			9.1 KiB
		
	
	
	
		
			C++
		
	
	
	
| // RUN: %clang_cc1 -fsyntax-only -Wloop-analysis -verify %s
 | |
| 
 | |
| struct S {
 | |
|   bool stop() { return false; }
 | |
|   bool keep_running;
 | |
| };
 | |
| 
 | |
| void by_ref(int &value) { }
 | |
| void by_value(int value) { }
 | |
| void by_pointer(int *value) {}
 | |
| 
 | |
| void test1() {
 | |
|   S s;
 | |
|   for (; !s.stop();) {}
 | |
|   for (; s.keep_running;) {}
 | |
|   for (int i; i < 1; ++i) {}
 | |
|   for (int i; i < 1; ) {}  // expected-warning {{variable 'i' used in loop condition not modified in loop body}}
 | |
|   for (int i; i < 1; ) { ++i; }
 | |
|   for (int i; i < 1; ) { return; }
 | |
|   for (int i; i < 1; ) { break; }
 | |
|   for (int i; i < 1; ) { goto exit_loop; }
 | |
| exit_loop:
 | |
|   for (int i; i < 1; ) { by_ref(i); }
 | |
|   for (int i; i < 1; ) { by_value(i); }  // expected-warning {{variable 'i' used in loop condition not modified in loop body}}
 | |
|   for (int i; i < 1; ) { by_pointer(&i); }
 | |
| 
 | |
|   for (int i; i < 1; ++i)
 | |
|     for (int j; j < 1; ++j)
 | |
|       { }
 | |
|   for (int i; i < 1; ++i)
 | |
|     for (int j; j < 1; ++i)  // expected-warning {{variable 'j' used in loop condition not modified in loop body}}
 | |
|       { }
 | |
|   for (int i; i < 1; ++i)
 | |
|     for (int j; i < 1; ++j)  // expected-warning {{variable 'i' used in loop condition not modified in loop body}}
 | |
|       { }
 | |
| 
 | |
|   for (int *i, *j; i < j; ++i) {}
 | |
|   for (int *i, *j; i < j;) {}  // expected-warning {{variables 'i' and 'j' used in loop condition not modified in loop body}}
 | |
| 
 | |
|   // Dereferencing pointers is ignored for now.
 | |
|   for (int *i; *i; ) {}
 | |
| }
 | |
| 
 | |
| void test2() {
 | |
|   int i, j, k;
 | |
|   int *ptr;
 | |
| 
 | |
|   // Testing CastExpr
 | |
|   for (; i; ) {} // expected-warning {{variable 'i' used in loop condition not modified in loop body}}
 | |
|   for (; i; ) { i = 5; }
 | |
| 
 | |
|   // Testing BinaryOperator
 | |
|   for (; i < j; ) {} // expected-warning {{variables 'i' and 'j' used in loop condition not modified in loop body}}
 | |
|   for (; i < j; ) { i = 5; }
 | |
|   for (; i < j; ) { j = 5; }
 | |
| 
 | |
|   // Testing IntegerLiteral
 | |
|   for (; i < 5; ) {} // expected-warning {{variable 'i' used in loop condition not modified in loop body}}
 | |
|   for (; i < 5; ) { i = 5; }
 | |
| 
 | |
|   // Testing FloatingLiteral
 | |
|   for (; i < 5.0; ) {} // expected-warning {{variable 'i' used in loop condition not modified in loop body}}
 | |
|   for (; i < 5.0; ) { i = 5; }
 | |
| 
 | |
|   // Testing CharacterLiteral
 | |
|   for (; i == 'a'; ) {} // expected-warning {{variable 'i' used in loop condition not modified in loop body}}
 | |
|   for (; i == 'a'; ) { i = 5; }
 | |
| 
 | |
|   // Testing CXXBoolLiteralExpr
 | |
|   for (; i == true; ) {} // expected-warning {{variable 'i' used in loop condition not modified in loop body}}
 | |
|   for (; i == true; ) { i = 5; }
 | |
| 
 | |
|   // Testing GNUNullExpr
 | |
|   for (; ptr == __null; ) {} // expected-warning {{variable 'ptr' used in loop condition not modified in loop body}}
 | |
|   for (; ptr == __null; ) { ptr = &i; }
 | |
| 
 | |
|   // Testing UnaryOperator
 | |
|   for (; -i > 5; ) {} // expected-warning {{variable 'i' used in loop condition not modified in loop body}}
 | |
|   for (; -i > 5; ) { ++i; }
 | |
| 
 | |
|   // Testing ImaginaryLiteral
 | |
|   for (; i != 3i; ) {} // expected-warning {{variable 'i' used in loop condition not modified in loop body}}
 | |
|   for (; i != 3i; ) { ++i; }
 | |
| 
 | |
|   // Testing ConditionalOperator
 | |
|   for (; i ? j : k; ) {} // expected-warning {{variables 'i', 'j', and 'k' used in loop condition not modified in loop body}}
 | |
|   for (; i ? j : k; ) { ++i; }
 | |
|   for (; i ? j : k; ) { ++j; }
 | |
|   for (; i ? j : k; ) { ++k; }
 | |
|   for (; i; ) { j = i ? i : i; }  // expected-warning {{variable 'i' used in loop condition not modified in loop body}}
 | |
|   for (; i; ) { j = (i = 1) ? i : i; }
 | |
|   for (; i; ) { j = i ? i : ++i; }
 | |
| 
 | |
|   // Testing BinaryConditionalOperator
 | |
|   for (; i ?: j; ) {} // expected-warning {{variables 'i' and 'j' used in loop condition not modified in loop body}}
 | |
|   for (; i ?: j; ) { ++i; }
 | |
|   for (; i ?: j; ) { ++j; }
 | |
|   for (; i; ) { j = i ?: i; }  // expected-warning {{variable 'i' used in loop condition not modified in loop body}}
 | |
| 
 | |
|   // Testing ParenExpr
 | |
|   for (; (i); ) { }  // expected-warning {{variable 'i' used in loop condition not modified in loop body}}
 | |
|   for (; (i); ) { ++i; }
 | |
| 
 | |
|   // Testing non-evaluated variables
 | |
|   for (; i < sizeof(j); ) { }  // expected-warning {{variable 'i' used in loop condition not modified in loop body}}
 | |
|   for (; i < sizeof(j); ) { ++j; }  // expected-warning {{variable 'i' used in loop condition not modified in loop body}}
 | |
|   for (; i < sizeof(j); ) { ++i; }
 | |
| }
 | |
| 
 | |
| // False positive and how to silence.
 | |
| void test3() {
 | |
|   int x;
 | |
|   int *ptr = &x;
 | |
|   for (;x<5;) { *ptr = 6; }  // expected-warning {{variable 'x' used in loop condition not modified in loop body}}
 | |
| 
 | |
|   for (;x<5;) {
 | |
|     *ptr = 6;
 | |
|     (void)x;
 | |
|   }
 | |
| }
 | |
| 
 | |
| // Check ordering and printing of variables.  Max variables is currently 4.
 | |
| void test4() {
 | |
|   int a, b, c, d, e, f;
 | |
|   for (; a;);  // expected-warning {{variable 'a' used in loop condition not modified in loop body}}
 | |
|   for (; a + b;);  // expected-warning {{variables 'a' and 'b' used in loop condition not modified in loop body}}
 | |
|   for (; a + b + c;);  // expected-warning {{variables 'a', 'b', and 'c' used in loop condition not modified in loop body}}
 | |
|   for (; a + b + c + d;);  // expected-warning {{variables 'a', 'b', 'c', and 'd' used in loop condition not modified in loop body}}
 | |
|   for (; a + b + c + d + e;);  // expected-warning {{variables used in loop condition not modified in loop body}}
 | |
|   for (; a + b + c + d + e + f;);  // expected-warning {{variables used in loop condition not modified in loop body}}
 | |
|   for (; a + c + d + b;);  // expected-warning {{variables 'a', 'c', 'd', and 'b' used in loop condition not modified in loop body}}
 | |
|   for (; d + c + b + a;);  // expected-warning {{variables 'd', 'c', 'b', and 'a' used in loop condition not modified in loop body}}
 | |
| }
 | |
| 
 | |
| // Ensure that the warning doesn't fail when lots of variables are used
 | |
| // in the conditional.
 | |
| void test5() {
 | |
|   for (int a; a+a+a+a+a+a+a+a+a+a;); // \
 | |
|    // expected-warning {{variable 'a' used in loop condition not modified in loop body}}
 | |
|   for (int a; a+a+a+a+a+a+a+a+a+a+a;); // \
 | |
|    // expected-warning {{variable 'a' used in loop condition not modified in loop body}}
 | |
|   for (int a; a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a;);  // \
 | |
|    // expected-warning {{variable 'a' used in loop condition not modified in loop body}}
 | |
|   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;);//\
 | |
|    // expected-warning {{variable 'a' used in loop condition not modified in loop body}}
 | |
| }
 | |
| 
 | |
| // Ignore global variables and static variables.
 | |
| int x6;
 | |
| void test6() {
 | |
|   static int y;
 | |
|   for (;x6;);
 | |
|   for (;y;);
 | |
| }
 | |
| 
 | |
| void test7() {
 | |
|   int i;
 | |
|   for (;;i++) {  // expected-note{{incremented here}}
 | |
|     if (true) test7();
 | |
|     i++;  // expected-warning{{incremented both}}
 | |
|   }
 | |
|   for (;;i++) {  // expected-note{{incremented here}}
 | |
|     if (true) break;
 | |
|     ++i;  // expected-warning{{incremented both}}
 | |
|   }
 | |
|   for (;;++i) {  // expected-note{{incremented here}}
 | |
|     while (true) return;
 | |
|     i++;  // expected-warning{{incremented both}}
 | |
|   }
 | |
|   for (;;++i) {  // expected-note{{incremented here}}
 | |
|     ++i;  // expected-warning{{incremented both}}
 | |
|   }
 | |
| 
 | |
|   for (;;i--) {  // expected-note{{decremented here}}
 | |
|     if (true) test7();
 | |
|     i--;  // expected-warning{{decremented both}}
 | |
|   }
 | |
|   for (;;i--) {  // expected-note{{decremented here}}
 | |
|     if (true) break;
 | |
|     --i;  // expected-warning{{decremented both}}
 | |
|   }
 | |
|   for (;;--i) {  // expected-note{{decremented here}}
 | |
|     while (true) return;
 | |
|     i--;  // expected-warning{{decremented both}}
 | |
|   }
 | |
|   for (;;--i) {  // expected-note{{decremented here}}
 | |
|     --i;  // expected-warning{{decremented both}}
 | |
|   }
 | |
| 
 | |
|   // Don't warn when loop is only one statement.
 | |
|   for (;;++i)
 | |
|     i++;
 | |
|   for (;;--i)
 | |
|     --i;
 | |
| 
 | |
|   // Don't warn when loop has continue statement.
 | |
|   for (;;i++) {
 | |
|     if (true) continue;
 | |
|     i++;
 | |
|   }
 | |
|   for (;;i--) {
 | |
|     if (true) continue;
 | |
|     i--;
 | |
|   }
 | |
| }
 | |
| 
 | |
| struct iterator {
 | |
|   iterator operator++() { return *this; }
 | |
|   iterator operator++(int) { return *this; }
 | |
|   iterator operator--() { return *this; }
 | |
|   iterator operator--(int) { return *this; }
 | |
| };
 | |
| void test8() {
 | |
|   iterator i;
 | |
|   for (;;i++) {  // expected-note{{incremented here}}
 | |
|     if (true) test7();
 | |
|     i++;  // expected-warning{{incremented both}}
 | |
|   }
 | |
|   for (;;i++) {  // expected-note{{incremented here}}
 | |
|     if (true) break;
 | |
|     ++i;  // expected-warning{{incremented both}}
 | |
|   }
 | |
|   for (;;++i) {  // expected-note{{incremented here}}
 | |
|     while (true) return;
 | |
|     i++;  // expected-warning{{incremented both}}
 | |
|   }
 | |
|   for (;;++i) {  // expected-note{{incremented here}}
 | |
|     ++i;  // expected-warning{{incremented both}}
 | |
|   }
 | |
| 
 | |
|   for (;;i--) {  // expected-note{{decremented here}}
 | |
|     if (true) test7();
 | |
|     i--;  // expected-warning{{decremented both}}
 | |
|   }
 | |
|   for (;;i--) {  // expected-note{{decremented here}}
 | |
|     if (true) break;
 | |
|     --i;  // expected-warning{{decremented both}}
 | |
|   }
 | |
|   for (;;--i) {  // expected-note{{decremented here}}
 | |
|     while (true) return;
 | |
|     i--;  // expected-warning{{decremented both}}
 | |
|   }
 | |
|   for (;;--i) {  // expected-note{{decremented here}}
 | |
|     --i;  // expected-warning{{decremented both}}
 | |
|   }
 | |
| 
 | |
|   // Don't warn when loop is only one statement.
 | |
|   for (;;++i)
 | |
|     i++;
 | |
|   for (;;--i)
 | |
|     --i;
 | |
| 
 | |
|   // Don't warn when loop has continue statement.
 | |
|   for (;;i++) {
 | |
|     if (true) continue;
 | |
|     i++;
 | |
|   }
 | |
|   for (;;i--) {
 | |
|     if (true) continue;
 | |
|     i--;
 | |
|   }
 | |
| }
 | |
| 
 | |
| int f(int);
 | |
| void test9() {
 | |
|   // Don't warn when variable is defined by the loop condition.
 | |
|   for (int i = 0; int x = f(i); ++i) {}
 | |
| }
 |