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