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