1 | // RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -analyzer-checker=core,debug.ExprInspection -analyzer-config ipa=none -verify %s |
2 | |
3 | void clang_analyzer_eval(bool); |
4 | |
5 | class A { |
6 | public: |
7 | virtual void f(){}; |
8 | |
9 | }; |
10 | class B : public A{ |
11 | public: |
12 | int m; |
13 | }; |
14 | class C : public A{}; |
15 | |
16 | class BB: public B{}; |
17 | |
18 | // A lot of the tests below have the if statement in them, which forces the |
19 | // analyzer to explore both path - when the result is 0 and not. This makes |
20 | // sure that we definitely know that the result is non-0 (as the result of |
21 | // the cast). |
22 | int testDynCastFromRadar() { |
23 | B aa; |
24 | A *a = &aa; |
25 | const int* res = 0; |
26 | B *b = dynamic_cast<B*>(a); |
27 | static const int i = 5; |
28 | if(b) { |
29 | res = &i; |
30 | } else { |
31 | res = 0; |
32 | } |
33 | return *res; // no warning |
34 | } |
35 | |
36 | int testBaseToBase1() { |
37 | B b; |
38 | B *pb = &b; |
39 | B *pbb = dynamic_cast<B*>(pb); |
40 | const int* res = 0; |
41 | static const int i = 5; |
42 | if (pbb) { |
43 | res = &i; |
44 | } else { |
45 | res = 0; |
46 | } |
47 | return *res; // no warning |
48 | } |
49 | |
50 | int testMultipleLevelsOfSubclassing1() { |
51 | BB bb; |
52 | B *pb = &bb; |
53 | A *pa = pb; |
54 | B *b = dynamic_cast<B*>(pa); |
55 | const int* res = 0; |
56 | static const int i = 5; |
57 | if (b) { |
58 | res = &i; |
59 | } else { |
60 | res = 0; |
61 | } |
62 | return *res; // no warning |
63 | } |
64 | |
65 | int testMultipleLevelsOfSubclassing2() { |
66 | BB bb; |
67 | A *pbb = &bb; |
68 | B *b = dynamic_cast<B*>(pbb); |
69 | BB *s = dynamic_cast<BB*>(b); |
70 | const int* res = 0; |
71 | static const int i = 5; |
72 | if (s) { |
73 | res = &i; |
74 | } else { |
75 | res = 0; |
76 | } |
77 | return *res; // no warning |
78 | } |
79 | |
80 | int testMultipleLevelsOfSubclassing3() { |
81 | BB bb; |
82 | A *pbb = &bb; |
83 | B *b = dynamic_cast<B*>(pbb); |
84 | return b->m; // no warning |
85 | } |
86 | |
87 | int testLHS() { |
88 | B aa; |
89 | A *a = &aa; |
90 | return (dynamic_cast<B*>(a))->m; |
91 | } |
92 | |
93 | int testLHS2() { |
94 | B aa; |
95 | A *a = &aa; |
96 | return (*dynamic_cast<B*>(a)).m; |
97 | } |
98 | |
99 | int testDynCastUnknown2(class A *a) { |
100 | B *b = dynamic_cast<B*>(a); |
101 | return b->m; // no warning |
102 | } |
103 | |
104 | int testDynCastUnknown(class A *a) { |
105 | B *b = dynamic_cast<B*>(a); |
106 | const int* res = 0; |
107 | static const int i = 5; |
108 | if (b) { |
109 | res = &i; |
110 | } else { |
111 | res = 0; |
112 | } |
113 | return *res; // expected-warning {{Dereference of null pointer}} |
114 | } |
115 | |
116 | int testDynCastFail2() { |
117 | C c; |
118 | A *pa = &c; |
119 | B *b = dynamic_cast<B*>(pa); |
120 | return b->m; // expected-warning {{dereference of a null pointer}} |
121 | } |
122 | |
123 | int testLHSFail() { |
124 | C c; |
125 | A *a = &c; |
126 | return (*dynamic_cast<B*>(a)).m; // expected-warning {{Dereference of null pointer}} |
127 | } |
128 | |
129 | int testBaseToDerivedFail() { |
130 | A a; |
131 | B *b = dynamic_cast<B*>(&a); |
132 | return b->m; // expected-warning {{dereference of a null pointer}} |
133 | } |
134 | |
135 | int testConstZeroFail() { |
136 | B *b = dynamic_cast<B*>((A *)0); |
137 | return b->m; // expected-warning {{dereference of a null pointer}} |
138 | } |
139 | |
140 | int testConstZeroFail2() { |
141 | A *a = 0; |
142 | B *b = dynamic_cast<B*>(a); |
143 | return b->m; // expected-warning {{dereference of a null pointer}} |
144 | } |
145 | |
146 | int testUpcast() { |
147 | B b; |
148 | A *a = dynamic_cast<A*>(&b); |
149 | const int* res = 0; |
150 | static const int i = 5; |
151 | if (a) { |
152 | res = &i; |
153 | } else { |
154 | res = 0; |
155 | } |
156 | return *res; // no warning |
157 | } |
158 | |
159 | int testCastToVoidStar() { |
160 | A a; |
161 | void *b = dynamic_cast<void*>(&a); |
162 | const int* res = 0; |
163 | static const int i = 5; |
164 | if (b) { |
165 | res = &i; |
166 | } else { |
167 | res = 0; |
168 | } |
169 | return *res; // no warning |
170 | } |
171 | |
172 | int testReferenceSuccessfulCast() { |
173 | B rb; |
174 | B &b = dynamic_cast<B&>(rb); |
175 | int *x = 0; |
176 | return *x; // expected-warning {{Dereference of null pointer}} |
177 | } |
178 | |
179 | int testReferenceFailedCast() { |
180 | A a; |
181 | B &b = dynamic_cast<B&>(a); |
182 | int *x = 0; |
183 | return *x; // no warning (An exception is thrown by the cast.) |
184 | } |
185 | |
186 | // Here we allow any outcome of the cast and this is good because there is a |
187 | // situation where this will fail. So if the user has written the code in this |
188 | // way, we assume they expect the cast to succeed. |
189 | // Note, this might need special handling if we track types of symbolic casts |
190 | // and use them for dynamic_cast handling. |
191 | int testDynCastMostLikelyWillFail(C *c) { |
192 | B *b = 0; |
193 | b = dynamic_cast<B*>(c); |
194 | const int* res = 0; |
195 | static const int i = 5; |
196 | if (b) { |
197 | res = &i; |
198 | } else { |
199 | res = 0; |
200 | } |
201 | |
202 | // Note: IPA is turned off for this test because the code below shows how the |
203 | // dynamic_cast could succeed. |
204 | return *res; // expected-warning{{Dereference of null pointer}} |
205 | } |
206 | |
207 | class M : public B, public C {}; |
208 | void callTestDynCastMostLikelyWillFail() { |
209 | M m; |
210 | testDynCastMostLikelyWillFail(&m); |
211 | } |
212 | |
213 | |
214 | void testDynCastToMiddleClass () { |
215 | class BBB : public BB {}; |
216 | BBB obj; |
217 | A &ref = obj; |
218 | |
219 | // These didn't always correctly layer base regions. |
220 | B *ptr = dynamic_cast<B*>(&ref); |
221 | clang_analyzer_eval(ptr != 0); // expected-warning{{TRUE}} |
222 | |
223 | // This is actually statically resolved to be a DerivedToBase cast. |
224 | ptr = dynamic_cast<B*>(&obj); |
225 | clang_analyzer_eval(ptr != 0); // expected-warning{{TRUE}} |
226 | } |
227 | |
228 | |
229 | // ----------------------------- |
230 | // False positives/negatives. |
231 | // ----------------------------- |
232 | |
233 | // Due to symbolic regions not being typed. |
234 | int testDynCastFalsePositive(BB *c) { |
235 | B *b = 0; |
236 | b = dynamic_cast<B*>(c); |
237 | const int* res = 0; |
238 | static const int i = 5; |
239 | if (b) { |
240 | res = &i; |
241 | } else { |
242 | res = 0; |
243 | } |
244 | return *res; // expected-warning{{Dereference of null pointer}} |
245 | } |
246 | |
247 | // Does not work when we new an object. |
248 | int testDynCastFail3() { |
249 | A *a = new A(); |
250 | B *b = dynamic_cast<B*>(a); |
251 | return b->m; |
252 | } |
253 | |
254 | |