dynamic-cast.cpp revision e19f86edab8fb3c2c1e99e0e9815b6058504df9b
1// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core -verify %s
2
3class A {
4public:
5    virtual void f(){};
6
7};
8class B : public A{
9public:
10  int m;
11};
12class C : public A{};
13
14class BB: public B{};
15
16// A lot of the tests below have the if statement in them, which forces the
17// analyzer to explore both path - when the result is 0 and not. This makes
18// sure that we definitely know that the result is non-0 (as the result of
19// the cast).
20int testDynCastFromRadar() {
21    B aa;
22    A *a = &aa;
23    const int* res = 0;
24    B *b = dynamic_cast<B*>(a);
25    static const int i = 5;
26    if(b) {
27        res = &i;
28    } else {
29        res = 0;
30    }
31    return *res; // no warning
32}
33
34int testBaseToBase1() {
35  B b;
36  B *pb = &b;
37  B *pbb = dynamic_cast<B*>(pb);
38  const int* res = 0;
39  static const int i = 5;
40  if (pbb) {
41      res = &i;
42  } else {
43      res = 0;
44  }
45  return *res; // no warning
46}
47
48int testMultipleLevelsOfSubclassing1() {
49  BB bb;
50  B *pb = &bb;
51  A *pa = pb;
52  B *b = dynamic_cast<B*>(pa);
53  const int* res = 0;
54  static const int i = 5;
55  if (b) {
56      res = &i;
57  } else {
58      res = 0;
59  }
60  return *res; // no warning
61}
62
63int testMultipleLevelsOfSubclassing2() {
64  BB bb;
65  A *pbb = &bb;
66  B *b = dynamic_cast<B*>(pbb);
67  BB *s = dynamic_cast<BB*>(b);
68  const int* res = 0;
69  static const int i = 5;
70  if (s) {
71      res = &i;
72  } else {
73      res = 0;
74  }
75  return *res; // no warning
76}
77
78int testMultipleLevelsOfSubclassing3() {
79  BB bb;
80  A *pbb = &bb;
81  B *b = dynamic_cast<B*>(pbb);
82  return b->m; // no warning
83}
84
85int testLHS() {
86    B aa;
87    A *a = &aa;
88    return (dynamic_cast<B*>(a))->m;
89}
90
91int testLHS2() {
92    B aa;
93    A *a = &aa;
94    return (*dynamic_cast<B*>(a)).m;
95}
96
97int testDynCastUnknown2(class A *a) {
98  B *b = dynamic_cast<B*>(a);
99  return b->m; // no warning
100}
101
102int testDynCastUnknown(class A *a) {
103  B *b = dynamic_cast<B*>(a);
104  const int* res = 0;
105  static const int i = 5;
106  if (b) {
107    res = &i;
108  } else {
109    res = 0;
110  }
111  return *res; // expected-warning {{Dereference of null pointer}}
112}
113
114int testDynCastFail2() {
115  C c;
116  A *pa = &c;
117  B *b = dynamic_cast<B*>(pa);
118  return b->m; // expected-warning {{dereference of a null pointer}}
119}
120
121int testLHSFail() {
122    C c;
123    A *a = &c;
124    return (*dynamic_cast<B*>(a)).m; // expected-warning {{Dereference of null pointer}}
125}
126
127int testBaseToDerivedFail() {
128  A a;
129  B *b = dynamic_cast<B*>(&a);
130  return b->m; // expected-warning {{dereference of a null pointer}}
131}
132
133int testConstZeroFail() {
134  B *b = dynamic_cast<B*>((A *)0);
135  return b->m; // expected-warning {{dereference of a null pointer}}
136}
137
138int testConstZeroFail2() {
139  A *a = 0;
140  B *b = dynamic_cast<B*>(a);
141  return b->m; // expected-warning {{dereference of a null pointer}}
142}
143
144int testUpcast() {
145  B b;
146  A *a = dynamic_cast<A*>(&b);
147  const int* res = 0;
148  static const int i = 5;
149  if (a) {
150      res = &i;
151  } else {
152      res = 0;
153  }
154  return *res; // no warning
155}
156
157int testCastToVoidStar() {
158  A a;
159  void *b = dynamic_cast<void*>(&a);
160  const int* res = 0;
161  static const int i = 5;
162  if (b) {
163      res = &i;
164  } else {
165      res = 0;
166  }
167  return *res; // no warning
168}
169
170int testReference() {
171  A a;
172  B &b = dynamic_cast<B&>(a);
173  return b.m; // no warning
174}
175
176// False negatives.
177
178// Symbolic regions are not typed, so we cannot deduce that the cast will
179// always fail in this case.
180int testDynCastFail1(class C *c) {
181  B *b = 0;
182  b = dynamic_cast<B*>(c);
183  return b->m;
184}
185
186