dynamic-cast.cpp revision 06868aa7e7231a755f1a5078af6bd2703de665bb
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 testReferenceSuccesfulCast() {
171  B rb;
172  B &b = dynamic_cast<B&>(rb);
173  int *x = 0;
174  return *x; // expected-warning {{Dereference of null pointer}}
175}
176
177int testReferenceFailedCast() {
178  A a;
179  B &b = dynamic_cast<B&>(a);
180  int *x = 0;
181  return *x; // no warning (An exception is thrown by the cast.)
182}
183
184// Here we allow any outcome of the cast and this is good because there is a
185// situation where this will fail. So if the user has written the code in this
186// way, we assume they expect the cast to succeed.
187// Note, this might need special handling if we track types of symbolic casts
188// and use them for dynamic_cast handling.
189int testDynCastMostLikelyWillFail(C *c) {
190  B *b = 0;
191  b = dynamic_cast<B*>(c);
192  const int* res = 0;
193  static const int i = 5;
194  if (b) {
195      res = &i;
196  } else {
197      res = 0;
198  }
199  return *res; // expected-warning{{Dereference of null pointer}}
200}
201
202class M : public B, public C {};
203void callTestDynCastMostLikelyWillFail() {
204  M m;
205  testDynCastMostLikelyWillFail(&m);
206}
207
208// False positives/negatives.
209
210// Due to symbolic regions not being typed.
211int testDynCastFalsePositive(BB *c) {
212  B *b = 0;
213  b = dynamic_cast<B*>(c);
214  const int* res = 0;
215  static const int i = 5;
216  if (b) {
217      res = &i;
218  } else {
219      res = 0;
220  }
221  return *res; // expected-warning{{Dereference of null pointer}}
222}
223
224