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