1 // RUN: %clang_cc1 -Wno-int-to-pointer-cast -analyze -analyzer-store=region -analyzer-constraints=range -fblocks -analyzer-opt-analyze-nested-blocks -analyzer-checker=alpha.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 238 float testFloatCast(int i) { 239 float f = i; 240 241 // Don't crash when trying to create a "zero" float. 242 return f - f; 243 } 244 245