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