254 lines · cpp
1// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -analyzer-checker=core,debug.ExprInspection -analyzer-config ipa=none -verify %s2 3void clang_analyzer_eval(bool);4 5class A {6public:7 virtual void f(){};8 9};10class B : public A{11public:12 int m;13};14class C : public A{};15 16class BB: public B{};17 18// A lot of the tests below have the if statement in them, which forces the19// analyzer to explore both path - when the result is 0 and not. This makes20// sure that we definitely know that the result is non-0 (as the result of21// the cast).22int 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 warning34}35 36int 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 warning48}49 50int 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 warning63}64 65int 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 warning78}79 80int testMultipleLevelsOfSubclassing3() {81 BB bb;82 A *pbb = &bb;83 B *b = dynamic_cast<B*>(pbb);84 return b->m; // no warning85}86 87int testLHS() {88 B aa;89 A *a = &aa;90 return (dynamic_cast<B*>(a))->m;91}92 93int testLHS2() {94 B aa;95 A *a = &aa;96 return (*dynamic_cast<B*>(a)).m;97}98 99int testDynCastUnknown2(class A *a) {100 B *b = dynamic_cast<B*>(a);101 return b->m; // no warning102}103 104int 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 116int 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 123int testLHSFail() {124 C c;125 A *a = &c;126 return (*dynamic_cast<B*>(a)).m; // expected-warning {{Dereference of null pointer}}127}128 129int testBaseToDerivedFail() {130 A a;131 B *b = dynamic_cast<B*>(&a);132 return b->m; // expected-warning {{dereference of a null pointer}}133}134 135int testConstZeroFail() {136 B *b = dynamic_cast<B*>((A *)0);137 return b->m; // expected-warning {{dereference of a null pointer}}138}139 140int 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 146int 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 warning157}158 159int 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 warning170}171 172int 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 179int 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 a187// situation where this will fail. So if the user has written the code in this188// way, we assume they expect the cast to succeed.189// Note, this might need special handling if we track types of symbolic casts190// and use them for dynamic_cast handling.191int 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 the203 // dynamic_cast could succeed.204 return *res; // expected-warning{{Dereference of null pointer}}205}206 207class M : public B, public C {};208void callTestDynCastMostLikelyWillFail() {209 M m;210 testDynCastMostLikelyWillFail(&m);211}212 213 214void 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.234int 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.248int testDynCastFail3() {249 A *a = new A();250 B *b = dynamic_cast<B*>(a);251 return b->m;252}253 254