[RISCV] Add shrinkwrap test cases showing gaps in current impl
[llvm-project.git] / clang / test / Analysis / dynamic-cast.cpp
blob0c86f81cb81987b502cd353ecd2820fd1beea1ca
1 // RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -analyzer-checker=core,debug.ExprInspection -analyzer-config ipa=none -verify %s
3 void clang_analyzer_eval(bool);
5 class A {
6 public:
7 virtual void f(){};
9 };
10 class B : public A{
11 public:
12 int m;
14 class C : public A{};
16 class BB: public B{};
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;
33 return *res; // no warning
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;
47 return *res; // no warning
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;
62 return *res; // no warning
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;
77 return *res; // no warning
80 int testMultipleLevelsOfSubclassing3() {
81 BB bb;
82 A *pbb = &bb;
83 B *b = dynamic_cast<B*>(pbb);
84 return b->m; // no warning
87 int testLHS() {
88 B aa;
89 A *a = &aa;
90 return (dynamic_cast<B*>(a))->m;
93 int testLHS2() {
94 B aa;
95 A *a = &aa;
96 return (*dynamic_cast<B*>(a)).m;
99 int testDynCastUnknown2(class A *a) {
100 B *b = dynamic_cast<B*>(a);
101 return b->m; // no warning
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;
113 return *res; // expected-warning {{Dereference of null pointer}}
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}}
123 int testLHSFail() {
124 C c;
125 A *a = &c;
126 return (*dynamic_cast<B*>(a)).m; // expected-warning {{Dereference of null pointer}}
129 int testBaseToDerivedFail() {
130 A a;
131 B *b = dynamic_cast<B*>(&a);
132 return b->m; // expected-warning {{dereference of a null pointer}}
135 int testConstZeroFail() {
136 B *b = dynamic_cast<B*>((A *)0);
137 return b->m; // expected-warning {{dereference of a null pointer}}
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}}
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;
156 return *res; // no warning
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;
169 return *res; // no warning
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}}
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.)
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;
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}}
207 class M : public B, public C {};
208 void callTestDynCastMostLikelyWillFail() {
209 M m;
210 testDynCastMostLikelyWillFail(&m);
214 void testDynCastToMiddleClass () {
215 class BBB : public BB {};
216 BBB obj;
217 A &ref = obj;
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}}
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}}
229 // -----------------------------
230 // False positives/negatives.
231 // -----------------------------
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;
244 return *res; // expected-warning{{Dereference of null pointer}}
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;