misc-ps-region-store.cpp revision 214323b78b01ef9c1ad226f0eb5bd1187f3efa70
1// RUN: %clang_cc1 -triple i386-apple-darwin9 -analyze -analyzer-checker=core,experimental.core -analyzer-store=region -verify -fblocks -analyzer-opt-analyze-nested-blocks %s
2// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -analyze -analyzer-checker=core,experimental.core -analyzer-store=region -verify -fblocks   -analyzer-opt-analyze-nested-blocks %s
3
4// Test basic handling of references.
5char &test1_aux();
6char *test1() {
7  return &test1_aux();
8}
9
10// Test test1_aux() evaluates to char &.
11char test1_as_rvalue() {
12  return test1_aux();
13}
14
15// Test passing a value as a reference.  The 'const' in test2_aux() adds
16// an ImplicitCastExpr, which is evaluated as an lvalue.
17int test2_aux(const int &n);
18int test2(int n) {
19  return test2_aux(n);
20}
21
22int test2_b_aux(const short &n);
23int test2_b(int n) {
24  return test2_b_aux(n);
25}
26
27// Test getting the lvalue of a derived and converting it to a base.  This
28// previously crashed.
29class Test3_Base {};
30class Test3_Derived : public Test3_Base {};
31
32int test3_aux(Test3_Base &x);
33int test3(Test3_Derived x) {
34  return test3_aux(x);
35}
36
37//===---------------------------------------------------------------------===//
38// Test CFG support for C++ condition variables.
39//===---------------------------------------------------------------------===//
40
41int test_init_in_condition_aux();
42int test_init_in_condition() {
43  if (int x = test_init_in_condition_aux()) { // no-warning
44    return 1;
45  }
46  return 0;
47}
48
49int test_init_in_condition_switch() {
50  switch (int x = test_init_in_condition_aux()) { // no-warning
51    case 1:
52      return 0;
53    case 2:
54      if (x == 2)
55        return 0;
56      else {
57        // Unreachable.
58        int *p = 0;
59        *p = 0xDEADBEEF; // no-warning
60      }
61    default:
62      break;
63  }
64  return 0;
65}
66
67int test_init_in_condition_while() {
68  int z = 0;
69  while (int x = ++z) { // no-warning
70    if (x == 2)
71      break;
72  }
73
74  if (z == 2)
75    return 0;
76
77  int *p = 0;
78  *p = 0xDEADBEEF; // no-warning
79  return 0;
80}
81
82
83int test_init_in_condition_for() {
84  int z = 0;
85  for (int x = 0; int y = ++z; ++x) {
86    if (x == y) // no-warning
87      break;
88  }
89  if (z == 1)
90    return 0;
91
92  int *p = 0;
93  *p = 0xDEADBEEF; // no-warning
94  return 0;
95}
96
97//===---------------------------------------------------------------------===//
98// Test handling of 'this' pointer.
99//===---------------------------------------------------------------------===//
100
101class TestHandleThis {
102  int x;
103
104  TestHandleThis();
105  int foo();
106  int null_deref_negative();
107  int null_deref_positive();
108};
109
110int TestHandleThis::foo() {
111  // Assume that 'x' is initialized.
112  return x + 1; // no-warning
113}
114
115int TestHandleThis::null_deref_negative() {
116  x = 10;
117  if (x == 10) {
118    return 1;
119  }
120  int *p = 0;
121  *p = 0xDEADBEEF; // no-warning
122  return 0;
123}
124
125int TestHandleThis::null_deref_positive() {
126  x = 10;
127  if (x == 9) {
128    return 1;
129  }
130  int *p = 0;
131  *p = 0xDEADBEEF; // expected-warning{{null pointer}}
132  return 0;
133}
134
135// PR 7675 - passing literals by-reference
136void pr7675(const double &a);
137void pr7675(const int &a);
138void pr7675(const char &a);
139void pr7675_i(const _Complex double &a);
140
141void pr7675_test() {
142  pr7675(10.0);
143  pr7675(10);
144  pr7675('c');
145  pr7675_i(4.0i);
146  // Add null deref to ensure we are analyzing the code up to this point.
147  int *p = 0;
148  *p = 0xDEADBEEF; // expected-warning{{null pointer}}
149}
150
151// <rdar://problem/8375510> - CFGBuilder should handle temporaries.
152struct R8375510 {
153  R8375510();
154  ~R8375510();
155  R8375510 operator++(int);
156};
157
158int r8375510(R8375510 x, R8375510 y) {
159  for (; ; x++) { }
160}
161
162// PR8419 -- this used to crash.
163
164class String8419 {
165 public:
166  char& get(int n);
167  char& operator[](int n);
168};
169
170char& get8419();
171
172void Test8419() {
173  String8419 s;
174  ++(s.get(0));
175  get8419()--;  // used to crash
176  --s[0];       // used to crash
177  s[0] &= 1;    // used to crash
178  s[0]++;       // used to crash
179}
180
181// PR8426 -- this used to crash.
182
183void Use(void* to);
184
185template <class T> class Foo {
186  ~Foo();
187  struct Bar;
188  Bar* bar_;
189};
190
191template <class T> Foo<T>::~Foo() {
192  Use(bar_);
193  T::DoSomething();
194  bar_->Work();
195}
196
197// PR8427 -- this used to crash.
198
199class Dummy {};
200
201bool operator==(Dummy, int);
202
203template <typename T>
204class Foo2 {
205  bool Bar();
206};
207
208template <typename T>
209bool Foo2<T>::Bar() {
210  return 0 == T();
211}
212
213// PR8433 -- this used to crash.
214
215template <typename T>
216class Foo3 {
217 public:
218  void Bar();
219  void Baz();
220  T value_;
221};
222
223template <typename T>
224void Foo3<T>::Bar() {
225  Baz();
226  value_();
227}
228
229//===---------------------------------------------------------------------===//
230// Handle misc. C++ constructs.
231//===---------------------------------------------------------------------===//
232
233namespace fum {
234  int i = 3;
235};
236
237void test_namespace() {
238  // Previously triggered a crash.
239  using namespace fum;
240  int x = i;
241}
242
243// Test handling methods that accept references as parameters, and that
244// variables are properly invalidated.
245class RDar9203355 {
246  bool foo(unsigned valA, long long &result) const;
247  bool foo(unsigned valA, int &result) const;
248};
249bool RDar9203355::foo(unsigned valA, int &result) const {
250  long long val;
251  if (foo(valA, val) ||
252      (int)val != val) // no-warning
253    return true;
254  result = val; // no-warning
255  return false;
256}
257
258// Test handling of new[].
259void rdar9212512() {
260  int *x = new int[10];
261  for (unsigned i = 0 ; i < 2 ; ++i) {
262    // This previously triggered an uninitialized values warning.
263    x[i] = 1;  // no-warning
264  }
265}
266
267// Test basic support for dynamic_cast<>.
268struct Rdar9212495_C { virtual void bar() const; };
269class Rdar9212495_B : public Rdar9212495_C {};
270class Rdar9212495_A : public Rdar9212495_B {};
271const Rdar9212495_A& rdar9212495(const Rdar9212495_C* ptr) {
272  const Rdar9212495_A& val = dynamic_cast<const Rdar9212495_A&>(*ptr);
273
274  if (&val == 0) {
275    val.bar(); // FIXME: This should eventually be a null dereference.
276  }
277
278  return val;
279}
280
281// Test constructors invalidating arguments.  Previously this raised
282// an uninitialized value warning.
283extern "C" void __attribute__((noreturn)) PR9645_exit(int i);
284
285class PR9645_SideEffect
286{
287public:
288  PR9645_SideEffect(int *pi); // caches pi in i_
289  void Read(int *pi); // copies *pi into *i_
290private:
291  int *i_;
292};
293
294void PR9645() {
295  int i;
296
297  PR9645_SideEffect se(&i);
298  int j = 1;
299  se.Read(&j); // this has a side-effect of initializing i.
300
301  PR9645_exit(i); // no-warning
302}
303
304PR9645_SideEffect::PR9645_SideEffect(int *pi) : i_(pi) {}
305void PR9645_SideEffect::Read(int *pi) { *i_ = *pi; }
306
307// Invalidate fields during C++ method calls.
308class RDar9267815 {
309  int x;
310  void test();
311  void test_pos();
312  void test2();
313  void invalidate();
314};
315
316void RDar9267815::test_pos() {
317  int *p = 0;
318  if (x == 42)
319    return;
320  *p = 0xDEADBEEF; // expected-warning {{null}}
321}
322void RDar9267815::test() {
323  int *p = 0;
324  if (x == 42)
325    return;
326  if (x == 42)
327    *p = 0xDEADBEEF; // no-warning
328}
329
330void RDar9267815::test2() {
331  int *p = 0;
332  if (x == 42)
333    return;
334  invalidate();
335  if (x == 42)
336    *p = 0xDEADBEEF; // expected-warning {{null}}
337}
338
339// Test reference parameters.
340void test_ref_double_aux(double &Value);
341float test_ref_double() {
342  double dVal;
343  test_ref_double_aux(dVal);
344  // This previously warned because 'dVal' was thought to be uninitialized.
345  float Val = (float)dVal; // no-warning
346  return Val;
347}
348
349// Test invalidation of class fields.
350class TestInvalidateClass {
351public:
352  int x;
353};
354
355void test_invalidate_class_aux(TestInvalidateClass &x);
356
357int test_invalidate_class() {
358  TestInvalidateClass y;
359  test_invalidate_class_aux(y);
360  return y.x; // no-warning
361}
362
363// Test correct pointer arithmetic using 'p--'.  This is to warn that we
364// were loading beyond the written characters in buf.
365char *RDar9269695(char *dst, unsigned int n)
366{
367  char buff[40], *p;
368
369  p = buff;
370  do
371    *p++ = '0' + n % 10;
372  while (n /= 10);
373
374  do
375    *dst++ = *--p; // no-warning
376  while (p != buff);
377
378  return dst;
379}
380
381// Test that we invalidate byref arguments passed to constructors.
382class TestInvalidateInCtor {
383public:
384  TestInvalidateInCtor(unsigned &x);
385};
386
387unsigned test_invalidate_in_ctor() {
388  unsigned x;
389  TestInvalidateInCtor foo(x);
390  return x; // no-warning
391}
392unsigned test_invalidate_in_ctor_new() {
393  unsigned x;
394  delete (new TestInvalidateInCtor(x));
395  return x; // no-warning
396}
397
398// Test assigning into a symbolic offset.
399struct TestAssignIntoSymbolicOffset {
400  int **stuff[100];
401  void test(int x, int y);
402};
403
404void TestAssignIntoSymbolicOffset::test(int x, int y) {
405  x--;
406  if (x > 8 || x < 0)
407    return;
408  if (stuff[x])
409    return;
410  if (!stuff[x]) {
411    stuff[x] = new int*[y+1];
412    // Previously triggered a null dereference.
413    stuff[x][y] = 0; // no-warning
414  }
415}
416
417// Test loads from static fields.  This previously triggered an uninitialized
418// value warning.
419class ClassWithStatic {
420public:
421    static const unsigned value = 1;
422};
423
424int rdar9948787_negative() {
425    ClassWithStatic classWithStatic;
426    unsigned value = classWithStatic.value;
427    if (value == 1)
428      return 1;
429    int *p = 0;
430    *p = 0xDEADBEEF; // no-warning
431    return 0;
432}
433
434int rdar9948787_positive() {
435    ClassWithStatic classWithStatic;
436    unsigned value = classWithStatic.value;
437    if (value == 0)
438      return 1;
439    int *p = 0;
440    *p = 0xDEADBEEF; // expected-warning {{null}}
441    return 0;
442}
443
444// Regression test against global constants and switches.
445enum rdar10202899_ValT { rdar10202899_ValTA, rdar10202899_ValTB, rdar10202899_ValTC };
446const rdar10202899_ValT val = rdar10202899_ValTA;
447void rdar10202899_test1() {
448  switch (val) {
449    case rdar10202899_ValTA: {}
450  };
451}
452
453void rdar10202899_test2() {
454  if (val == rdar10202899_ValTA)
455   return;
456  int *p = 0;
457  *p = 0xDEADBEEF;
458}
459
460void rdar10202899_test3() {
461  switch (val) {
462    case rdar10202899_ValTA: return;
463    default: ;
464  };
465  int *p = 0;
466  *p = 0xDEADBEEF;
467}
468
469// This used to crash the analyzer because of the unnamed bitfield.
470void PR11249()
471{
472  struct {
473    char f1:4;
474    char   :4;
475    char f2[1];
476    char f3;
477  } V = { 1, {2}, 3 };
478  int *p = 0;
479  if (V.f1 != 1)
480    *p = 0xDEADBEEF;  // no-warning
481  if (V.f2[0] != 2)
482    *p = 0xDEADBEEF;  // no-warning
483  if (V.f3 != 3)
484    *p = 0xDEADBEEF;  // no-warning
485}
486
487// Handle doing a load from the memory associated with the code for
488// a function.
489extern double nan( const char * );
490double PR11450() {
491  double NaN = *(double*) nan;
492  return NaN;
493}
494
495