• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
basic()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 
floats(float x)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
bailout()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;
kill_at_assign()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 
false1()97 unsigned false1() {
98   int a = 10;
99   return a * (5 - 2 - 3); // no-warning
100 }
101 
102 enum testenum { enum1 = 0, enum2 };
false2()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
false3(int param,int param2)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
false4()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
false4a()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
false5()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;
false6()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
false7()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
false8()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;
RDar8431728_C(RDar8431728_D * s,int n,unsigned char ** RDar8431728_B_ptr)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);
rdar8601243()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 
testFloatCast(int i)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