Home | History | Annotate | Download | only in Analysis
      1 // RUN: %clang_cc1 -analyze -analyzer-store=region -analyzer-constraints=range -fblocks -analyzer-opt-analyze-nested-blocks -analyzer-checker=experimental.deadcode.IdempotentOperations -verify %s
      2 
      3 // Basic tests
      4 
      5 extern void test(int i);
      6 extern void test_f(float f);
      7 
      8 unsigned basic() {
      9   int x = 10, zero = 0, one = 1;
     10 
     11   // x op x
     12   x = x;        // expected-warning {{Assigned value is always the same as the existing value}}
     13   test(x - x);  // expected-warning {{Both operands to '-' always have the same value}}
     14   x -= x;       // expected-warning {{Both operands to '-=' always have the same value}}
     15   x = 10;       // no-warning
     16   test(x / x);  // expected-warning {{Both operands to '/' always have the same value}}
     17   x /= x;       // expected-warning {{Both operands to '/=' always have the same value}}
     18   x = 10;       // no-warning
     19   test(x & x);  // expected-warning {{Both operands to '&' always have the same value}}
     20   x &= x;       // expected-warning {{Both operands to '&=' always have the same value}}
     21   test(x | x);  // expected-warning {{Both operands to '|' always have the same value}}
     22   x |= x;       // expected-warning {{Both operands to '|=' always have the same value}}
     23 
     24   // x op 1
     25   test(x * one);  // expected-warning {{The right operand to '*' is always 1}}
     26   x *= one;       // expected-warning {{The right operand to '*=' is always 1}}
     27   test(x / one);  // expected-warning {{The right operand to '/' is always 1}}
     28   x /= one;       // expected-warning {{The right operand to '/=' is always 1}}
     29 
     30   // 1 op x
     31   test(one * x);   // expected-warning {{The left operand to '*' is always 1}}
     32 
     33   // x op 0
     34   test(x + zero);  // expected-warning {{The right operand to '+' is always 0}}
     35   test(x - zero);  // expected-warning {{The right operand to '-' is always 0}}
     36   test(x * zero);  // expected-warning {{The right operand to '*' is always 0}}
     37   test(x & zero);  // expected-warning {{The right operand to '&' is always 0}}
     38   test(x | zero);  // expected-warning {{The right operand to '|' is always 0}}
     39   test(x ^ zero);  // expected-warning {{The right operand to '^' is always 0}}
     40   test(x << zero); // expected-warning {{The right operand to '<<' is always 0}}
     41   test(x >> zero); // expected-warning {{The right operand to '>>' is always 0}}
     42 
     43   // 0 op x
     44   test(zero + x);  // expected-warning {{The left operand to '+' is always 0}}
     45   test(zero - x);  // expected-warning {{The left operand to '-' is always 0}}
     46   test(zero / x);  // expected-warning {{The left operand to '/' is always 0}}
     47   test(zero * x);  // expected-warning {{The left operand to '*' is always 0}}
     48   test(zero & x);  // expected-warning {{The left operand to '&' is always 0}}
     49   test(zero | x);  // expected-warning {{The left operand to '|' is always 0}}
     50   test(zero ^ x);  // expected-warning {{The left operand to '^' is always 0}}
     51   test(zero << x); // expected-warning {{The left operand to '<<' is always 0}}
     52   test(zero >> x); // expected-warning {{The left operand to '>>' is always 0}}
     53 
     54   // Overwrite the values so these aren't marked as Pseudoconstants
     55   x = 1;
     56   zero = 2;
     57   one = 3;
     58 
     59   return x + zero + one;
     60 }
     61 
     62 void floats(float x) {
     63   test_f(x * 1.0);  // no-warning
     64   test_f(x * 1.0F); // no-warning
     65 }
     66 
     67 // Ensure that we don't report false poitives in complex loops
     68 void bailout() {
     69   int unused = 0, result = 4;
     70   result = result; // expected-warning {{Assigned value is always the same as the existing value}}
     71 
     72   for (unsigned bg = 0; bg < 1024; bg ++) {
     73     result = bg * result; // no-warning
     74 
     75     for (int i = 0; i < 256; i++) {
     76       unused *= i; // no-warning
     77     }
     78   }
     79 }
     80 
     81 // Relaxed liveness - check that we don't kill liveness at assignments
     82 typedef unsigned uintptr_t;
     83 void kill_at_assign() {
     84   short array[2];
     85   uintptr_t x = (uintptr_t) array;
     86   short *p = (short *) x;
     87 
     88   // The following branch should be infeasible.
     89   if (!(p = &array[0])) { // expected-warning{{Assigned value is always the same as the existing value}}
     90     p = 0;
     91     *p = 1; // no-warning
     92   }
     93 }
     94 
     95 // False positive tests
     96 
     97 unsigned false1() {
     98   int a = 10;
     99   return a * (5 - 2 - 3); // no-warning
    100 }
    101 
    102 enum testenum { enum1 = 0, enum2 };
    103 unsigned false2() {
    104   int a = 1234;
    105   return enum1 + a; // no-warning
    106 }
    107 
    108 // Self assignments of unused variables are common false positives
    109 unsigned false3(int param, int param2) {
    110   param = param; // no-warning
    111 
    112   // if a self assigned variable is used later, then it should be reported still
    113   param2 = param2; // expected-warning{{Assigned value is always the same as the existing value}}
    114 
    115   unsigned nonparam = 5;
    116 
    117   nonparam = nonparam; // expected-warning{{Assigned value is always the same as the existing value}}
    118 
    119   return param2 + nonparam;
    120 }
    121 
    122 // Pseudo-constants (vars only read) and constants should not be reported
    123 unsigned false4() {
    124   // Trivial constant
    125   const int height = 1;
    126   int c = 42;
    127   test(height * c); // no-warning
    128 
    129   // Pseudo-constant (never changes after decl)
    130   int width = height;
    131 
    132   return width * 10; // no-warning
    133 }
    134 
    135 // Block pseudoconstants
    136 void false4a() {
    137   // Pseudo-constant
    138   __block int a = 1;
    139   int b = 10;
    140   __block int c = 0;
    141   b *= a; // no-warning
    142 
    143   ^{
    144     // Psuedoconstant block var
    145     test(b * c); // no-warning
    146 
    147     // Non-pseudoconstant block var
    148     int d = 0;
    149     test(b * d); // expected-warning{{The right operand to '*' is always 0}}
    150     d = 5;
    151     test(d);
    152   }();
    153 
    154   test(a + b);
    155 }
    156 
    157 // Static vars are common false positives
    158 int false5() {
    159   static int test = 0;
    160   int a = 56;
    161   a *= test; // no-warning
    162   test++;
    163   return a;
    164 }
    165 
    166 // Non-local storage vars are considered false positives
    167 int globalInt = 1;
    168 int false6() {
    169   int localInt = 23;
    170 
    171   localInt /= globalInt;
    172 
    173   return localInt;
    174 }
    175 
    176 // Check that assignments filter out false positives correctly
    177 int false7() {
    178   int zero = 0; // pseudo-constant
    179   int one = 1;
    180 
    181   int a = 55;
    182   a = a; // expected-warning{{Assigned value is always the same as the existing value}}
    183   a = enum1 * a; // no-warning
    184 
    185   int b = 123;
    186   b = b; // no-warning
    187 
    188   return a;
    189 }
    190 
    191 // Check truncations do not flag as self-assignments
    192 void false8() {
    193   int a = 10000000;
    194   a = (short)a; // no-warning
    195   test(a);
    196 }
    197 
    198 // This test case previously flagged a warning at 'b == c' because the
    199 // analyzer previously allowed 'UnknownVal' as the index for ElementRegions.
    200 typedef struct RDar8431728_F {
    201   int RDar8431728_A;
    202   unsigned char *RDar8431728_B;
    203   int RDar8431728_E[6];
    204 } RDar8431728_D;
    205 static inline int RDar8431728_C(RDar8431728_D * s, int n,
    206     unsigned char **RDar8431728_B_ptr) {
    207   int xy, wrap, pred, a, b, c;
    208 
    209   xy = s->RDar8431728_E[n];
    210   wrap = s->RDar8431728_A;
    211 
    212   a = s->RDar8431728_B[xy - 1];
    213   b = s->RDar8431728_B[xy - 1 - wrap];
    214   c = s->RDar8431728_B[xy - wrap];
    215 
    216   if (b == c) { // no-warning
    217     pred = a;
    218   } else {
    219     pred = c;
    220   }
    221 
    222   *RDar8431728_B_ptr = &s->RDar8431728_B[xy];
    223 
    224   return pred;
    225 }
    226 
    227 // <rdar://problem/8601243> - Don't warn on pointer arithmetic.  This
    228 // is often idiomatic.
    229 unsigned rdar8601243_aux(unsigned n);
    230 void rdar8601243() {
    231   char arr[100];
    232   char *start = arr;
    233   start = start + rdar8601243_aux(sizeof(arr) - (arr - start)); // no-warning
    234   (void) start;
    235 }
    236 
    237