Home | History | Annotate | Download | only in SemaCXX
      1 // RUN: %clang_cc1 -fsyntax-only -Wloop-analysis -verify %s
      2 
      3 struct S {
      4   bool stop() { return false; }
      5   bool keep_running;
      6 };
      7 
      8 void by_ref(int &value) { }
      9 void by_value(int value) { }
     10 void by_pointer(int *value) {}
     11 
     12 void 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; }
     22 exit_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 
     44 void 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.
    111 void 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.
    123 void 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.
    137 void 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.
    149 int x6;
    150 void test6() {
    151   static int y;
    152   for (;x6;);
    153   for (;y;);
    154 }
    155 
    156 void 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 
    207 struct iterator {
    208   iterator operator++() { return *this; }
    209   iterator operator++(int) { return *this; }
    210   iterator operator--() { return *this; }
    211   iterator operator--(int) { return *this; }
    212 };
    213 void 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 
    264 int f(int);
    265 void 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