blob: 215bc497427d5bc94f0a234e40d461e2891393bc [file] [log] [blame]
Jordan Rosec36b30c2012-07-12 00:16:25 +00001// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core -analyzer-ipa=none -verify %s
Anna Zakse19f86e2012-04-10 20:59:00 +00002
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
Anna Zaksa2c8d2e2012-04-10 21:29:03 +0000170int 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() {
Anna Zakse19f86e2012-04-10 20:59:00 +0000178 A a;
179 B &b = dynamic_cast<B&>(a);
Anna Zaksa2c8d2e2012-04-10 21:29:03 +0000180 int *x = 0;
181 return *x; // no warning (An exception is thrown by the cast.)
Anna Zakse19f86e2012-04-10 20:59:00 +0000182}
183
Anna Zaks06868aa2012-04-11 22:20:05 +0000184// 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) {
Anna Zakse19f86e2012-04-10 20:59:00 +0000190 B *b = 0;
191 b = dynamic_cast<B*>(c);
Anna Zaks06868aa2012-04-11 22:20:05 +0000192 const int* res = 0;
193 static const int i = 5;
194 if (b) {
195 res = &i;
196 } else {
197 res = 0;
198 }
Jordan Rosec36b30c2012-07-12 00:16:25 +0000199
200 // Note: IPA is turned off for this test because the code below shows how the
201 // dynamic_cast could succeed.
Anna Zaks06868aa2012-04-11 22:20:05 +0000202 return *res; // expected-warning{{Dereference of null pointer}}
203}
204
205class M : public B, public C {};
206void callTestDynCastMostLikelyWillFail() {
207 M m;
208 testDynCastMostLikelyWillFail(&m);
209}
210
211// False positives/negatives.
212
213// Due to symbolic regions not being typed.
214int testDynCastFalsePositive(BB *c) {
215 B *b = 0;
216 b = dynamic_cast<B*>(c);
217 const int* res = 0;
218 static const int i = 5;
219 if (b) {
220 res = &i;
221 } else {
222 res = 0;
223 }
224 return *res; // expected-warning{{Dereference of null pointer}}
Anna Zakse19f86e2012-04-10 20:59:00 +0000225}
226
Anna Zaksc3fa98f2012-04-11 22:29:38 +0000227// Does not work when we new an object.
228int testDynCastFail3() {
229 A *a = new A();
230 B *b = dynamic_cast<B*>(a);
231 return b->m;
232}
233