1*184c6242SDominic Chen // RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -analyzer-checker=core,debug.ExprInspection -analyzer-config ipa=none -verify %s 207a7ed80SJordan Rose 307a7ed80SJordan Rose void clang_analyzer_eval(bool); 43bc6809eSAnna Zaks 53bc6809eSAnna Zaks class A { 63bc6809eSAnna Zaks public: f()73bc6809eSAnna Zaks virtual void f(){}; 83bc6809eSAnna Zaks 93bc6809eSAnna Zaks }; 103bc6809eSAnna Zaks class B : public A{ 113bc6809eSAnna Zaks public: 123bc6809eSAnna Zaks int m; 133bc6809eSAnna Zaks }; 143bc6809eSAnna Zaks class C : public A{}; 153bc6809eSAnna Zaks 163bc6809eSAnna Zaks class BB: public B{}; 173bc6809eSAnna Zaks 183bc6809eSAnna Zaks // A lot of the tests below have the if statement in them, which forces the 193bc6809eSAnna Zaks // analyzer to explore both path - when the result is 0 and not. This makes 203bc6809eSAnna Zaks // sure that we definitely know that the result is non-0 (as the result of 213bc6809eSAnna Zaks // the cast). testDynCastFromRadar()223bc6809eSAnna Zaksint testDynCastFromRadar() { 233bc6809eSAnna Zaks B aa; 243bc6809eSAnna Zaks A *a = &aa; 253bc6809eSAnna Zaks const int* res = 0; 263bc6809eSAnna Zaks B *b = dynamic_cast<B*>(a); 273bc6809eSAnna Zaks static const int i = 5; 283bc6809eSAnna Zaks if(b) { 293bc6809eSAnna Zaks res = &i; 303bc6809eSAnna Zaks } else { 313bc6809eSAnna Zaks res = 0; 323bc6809eSAnna Zaks } 333bc6809eSAnna Zaks return *res; // no warning 343bc6809eSAnna Zaks } 353bc6809eSAnna Zaks testBaseToBase1()363bc6809eSAnna Zaksint testBaseToBase1() { 373bc6809eSAnna Zaks B b; 383bc6809eSAnna Zaks B *pb = &b; 393bc6809eSAnna Zaks B *pbb = dynamic_cast<B*>(pb); 403bc6809eSAnna Zaks const int* res = 0; 413bc6809eSAnna Zaks static const int i = 5; 423bc6809eSAnna Zaks if (pbb) { 433bc6809eSAnna Zaks res = &i; 443bc6809eSAnna Zaks } else { 453bc6809eSAnna Zaks res = 0; 463bc6809eSAnna Zaks } 473bc6809eSAnna Zaks return *res; // no warning 483bc6809eSAnna Zaks } 493bc6809eSAnna Zaks testMultipleLevelsOfSubclassing1()503bc6809eSAnna Zaksint testMultipleLevelsOfSubclassing1() { 513bc6809eSAnna Zaks BB bb; 523bc6809eSAnna Zaks B *pb = &bb; 533bc6809eSAnna Zaks A *pa = pb; 543bc6809eSAnna Zaks B *b = dynamic_cast<B*>(pa); 553bc6809eSAnna Zaks const int* res = 0; 563bc6809eSAnna Zaks static const int i = 5; 573bc6809eSAnna Zaks if (b) { 583bc6809eSAnna Zaks res = &i; 593bc6809eSAnna Zaks } else { 603bc6809eSAnna Zaks res = 0; 613bc6809eSAnna Zaks } 623bc6809eSAnna Zaks return *res; // no warning 633bc6809eSAnna Zaks } 643bc6809eSAnna Zaks testMultipleLevelsOfSubclassing2()653bc6809eSAnna Zaksint testMultipleLevelsOfSubclassing2() { 663bc6809eSAnna Zaks BB bb; 673bc6809eSAnna Zaks A *pbb = &bb; 683bc6809eSAnna Zaks B *b = dynamic_cast<B*>(pbb); 693bc6809eSAnna Zaks BB *s = dynamic_cast<BB*>(b); 703bc6809eSAnna Zaks const int* res = 0; 713bc6809eSAnna Zaks static const int i = 5; 723bc6809eSAnna Zaks if (s) { 733bc6809eSAnna Zaks res = &i; 743bc6809eSAnna Zaks } else { 753bc6809eSAnna Zaks res = 0; 763bc6809eSAnna Zaks } 773bc6809eSAnna Zaks return *res; // no warning 783bc6809eSAnna Zaks } 793bc6809eSAnna Zaks testMultipleLevelsOfSubclassing3()803bc6809eSAnna Zaksint testMultipleLevelsOfSubclassing3() { 813bc6809eSAnna Zaks BB bb; 823bc6809eSAnna Zaks A *pbb = &bb; 833bc6809eSAnna Zaks B *b = dynamic_cast<B*>(pbb); 843bc6809eSAnna Zaks return b->m; // no warning 853bc6809eSAnna Zaks } 863bc6809eSAnna Zaks testLHS()873bc6809eSAnna Zaksint testLHS() { 883bc6809eSAnna Zaks B aa; 893bc6809eSAnna Zaks A *a = &aa; 903bc6809eSAnna Zaks return (dynamic_cast<B*>(a))->m; 913bc6809eSAnna Zaks } 923bc6809eSAnna Zaks testLHS2()933bc6809eSAnna Zaksint testLHS2() { 943bc6809eSAnna Zaks B aa; 953bc6809eSAnna Zaks A *a = &aa; 963bc6809eSAnna Zaks return (*dynamic_cast<B*>(a)).m; 973bc6809eSAnna Zaks } 983bc6809eSAnna Zaks testDynCastUnknown2(class A * a)993bc6809eSAnna Zaksint testDynCastUnknown2(class A *a) { 1003bc6809eSAnna Zaks B *b = dynamic_cast<B*>(a); 1013bc6809eSAnna Zaks return b->m; // no warning 1023bc6809eSAnna Zaks } 1033bc6809eSAnna Zaks testDynCastUnknown(class A * a)1043bc6809eSAnna Zaksint testDynCastUnknown(class A *a) { 1053bc6809eSAnna Zaks B *b = dynamic_cast<B*>(a); 1063bc6809eSAnna Zaks const int* res = 0; 1073bc6809eSAnna Zaks static const int i = 5; 1083bc6809eSAnna Zaks if (b) { 1093bc6809eSAnna Zaks res = &i; 1103bc6809eSAnna Zaks } else { 1113bc6809eSAnna Zaks res = 0; 1123bc6809eSAnna Zaks } 1133bc6809eSAnna Zaks return *res; // expected-warning {{Dereference of null pointer}} 1143bc6809eSAnna Zaks } 1153bc6809eSAnna Zaks testDynCastFail2()1163bc6809eSAnna Zaksint testDynCastFail2() { 1173bc6809eSAnna Zaks C c; 1183bc6809eSAnna Zaks A *pa = &c; 1193bc6809eSAnna Zaks B *b = dynamic_cast<B*>(pa); 1203bc6809eSAnna Zaks return b->m; // expected-warning {{dereference of a null pointer}} 1213bc6809eSAnna Zaks } 1223bc6809eSAnna Zaks testLHSFail()1233bc6809eSAnna Zaksint testLHSFail() { 1243bc6809eSAnna Zaks C c; 1253bc6809eSAnna Zaks A *a = &c; 1263bc6809eSAnna Zaks return (*dynamic_cast<B*>(a)).m; // expected-warning {{Dereference of null pointer}} 1273bc6809eSAnna Zaks } 1283bc6809eSAnna Zaks testBaseToDerivedFail()1293bc6809eSAnna Zaksint testBaseToDerivedFail() { 1303bc6809eSAnna Zaks A a; 1313bc6809eSAnna Zaks B *b = dynamic_cast<B*>(&a); 1323bc6809eSAnna Zaks return b->m; // expected-warning {{dereference of a null pointer}} 1333bc6809eSAnna Zaks } 1343bc6809eSAnna Zaks testConstZeroFail()1353bc6809eSAnna Zaksint testConstZeroFail() { 1363bc6809eSAnna Zaks B *b = dynamic_cast<B*>((A *)0); 1373bc6809eSAnna Zaks return b->m; // expected-warning {{dereference of a null pointer}} 1383bc6809eSAnna Zaks } 1393bc6809eSAnna Zaks testConstZeroFail2()1403bc6809eSAnna Zaksint testConstZeroFail2() { 1413bc6809eSAnna Zaks A *a = 0; 1423bc6809eSAnna Zaks B *b = dynamic_cast<B*>(a); 1433bc6809eSAnna Zaks return b->m; // expected-warning {{dereference of a null pointer}} 1443bc6809eSAnna Zaks } 1453bc6809eSAnna Zaks testUpcast()1463bc6809eSAnna Zaksint testUpcast() { 1473bc6809eSAnna Zaks B b; 1483bc6809eSAnna Zaks A *a = dynamic_cast<A*>(&b); 1493bc6809eSAnna Zaks const int* res = 0; 1503bc6809eSAnna Zaks static const int i = 5; 1513bc6809eSAnna Zaks if (a) { 1523bc6809eSAnna Zaks res = &i; 1533bc6809eSAnna Zaks } else { 1543bc6809eSAnna Zaks res = 0; 1553bc6809eSAnna Zaks } 1563bc6809eSAnna Zaks return *res; // no warning 1573bc6809eSAnna Zaks } 1583bc6809eSAnna Zaks testCastToVoidStar()1593bc6809eSAnna Zaksint testCastToVoidStar() { 1603bc6809eSAnna Zaks A a; 1613bc6809eSAnna Zaks void *b = dynamic_cast<void*>(&a); 1623bc6809eSAnna Zaks const int* res = 0; 1633bc6809eSAnna Zaks static const int i = 5; 1643bc6809eSAnna Zaks if (b) { 1653bc6809eSAnna Zaks res = &i; 1663bc6809eSAnna Zaks } else { 1673bc6809eSAnna Zaks res = 0; 1683bc6809eSAnna Zaks } 1693bc6809eSAnna Zaks return *res; // no warning 1703bc6809eSAnna Zaks } 1713bc6809eSAnna Zaks testReferenceSuccessfulCast()172f6a24ce4SAlp Tokerint testReferenceSuccessfulCast() { 17302ecae92SAnna Zaks B rb; 17402ecae92SAnna Zaks B &b = dynamic_cast<B&>(rb); 17502ecae92SAnna Zaks int *x = 0; 17602ecae92SAnna Zaks return *x; // expected-warning {{Dereference of null pointer}} 17702ecae92SAnna Zaks } 17802ecae92SAnna Zaks testReferenceFailedCast()17902ecae92SAnna Zaksint testReferenceFailedCast() { 1803bc6809eSAnna Zaks A a; 1813bc6809eSAnna Zaks B &b = dynamic_cast<B&>(a); 18202ecae92SAnna Zaks int *x = 0; 18302ecae92SAnna Zaks return *x; // no warning (An exception is thrown by the cast.) 1843bc6809eSAnna Zaks } 1853bc6809eSAnna Zaks 1861a3a2470SAnna Zaks // Here we allow any outcome of the cast and this is good because there is a 1871a3a2470SAnna Zaks // situation where this will fail. So if the user has written the code in this 1881a3a2470SAnna Zaks // way, we assume they expect the cast to succeed. 1891a3a2470SAnna Zaks // Note, this might need special handling if we track types of symbolic casts 1901a3a2470SAnna Zaks // and use them for dynamic_cast handling. testDynCastMostLikelyWillFail(C * c)1911a3a2470SAnna Zaksint testDynCastMostLikelyWillFail(C *c) { 1923bc6809eSAnna Zaks B *b = 0; 1933bc6809eSAnna Zaks b = dynamic_cast<B*>(c); 1941a3a2470SAnna Zaks const int* res = 0; 1951a3a2470SAnna Zaks static const int i = 5; 1961a3a2470SAnna Zaks if (b) { 1971a3a2470SAnna Zaks res = &i; 1981a3a2470SAnna Zaks } else { 1991a3a2470SAnna Zaks res = 0; 2001a3a2470SAnna Zaks } 201d66bee3fSJordan Rose 202d66bee3fSJordan Rose // Note: IPA is turned off for this test because the code below shows how the 203d66bee3fSJordan Rose // dynamic_cast could succeed. 2041a3a2470SAnna Zaks return *res; // expected-warning{{Dereference of null pointer}} 2051a3a2470SAnna Zaks } 2061a3a2470SAnna Zaks 2071a3a2470SAnna Zaks class M : public B, public C {}; callTestDynCastMostLikelyWillFail()2081a3a2470SAnna Zaksvoid callTestDynCastMostLikelyWillFail() { 2091a3a2470SAnna Zaks M m; 2101a3a2470SAnna Zaks testDynCastMostLikelyWillFail(&m); 2111a3a2470SAnna Zaks } 2121a3a2470SAnna Zaks 21307a7ed80SJordan Rose testDynCastToMiddleClass()21407a7ed80SJordan Rosevoid testDynCastToMiddleClass () { 21507a7ed80SJordan Rose class BBB : public BB {}; 21607a7ed80SJordan Rose BBB obj; 21707a7ed80SJordan Rose A &ref = obj; 21807a7ed80SJordan Rose 21907a7ed80SJordan Rose // These didn't always correctly layer base regions. 22007a7ed80SJordan Rose B *ptr = dynamic_cast<B*>(&ref); 22107a7ed80SJordan Rose clang_analyzer_eval(ptr != 0); // expected-warning{{TRUE}} 22207a7ed80SJordan Rose 22307a7ed80SJordan Rose // This is actually statically resolved to be a DerivedToBase cast. 22407a7ed80SJordan Rose ptr = dynamic_cast<B*>(&obj); 22507a7ed80SJordan Rose clang_analyzer_eval(ptr != 0); // expected-warning{{TRUE}} 22607a7ed80SJordan Rose } 22707a7ed80SJordan Rose 22807a7ed80SJordan Rose 22907a7ed80SJordan Rose // ----------------------------- 2301a3a2470SAnna Zaks // False positives/negatives. 23107a7ed80SJordan Rose // ----------------------------- 2321a3a2470SAnna Zaks 2331a3a2470SAnna Zaks // Due to symbolic regions not being typed. testDynCastFalsePositive(BB * c)2341a3a2470SAnna Zaksint testDynCastFalsePositive(BB *c) { 2351a3a2470SAnna Zaks B *b = 0; 2361a3a2470SAnna Zaks b = dynamic_cast<B*>(c); 2371a3a2470SAnna Zaks const int* res = 0; 2381a3a2470SAnna Zaks static const int i = 5; 2391a3a2470SAnna Zaks if (b) { 2401a3a2470SAnna Zaks res = &i; 2411a3a2470SAnna Zaks } else { 2421a3a2470SAnna Zaks res = 0; 2431a3a2470SAnna Zaks } 2441a3a2470SAnna Zaks return *res; // expected-warning{{Dereference of null pointer}} 2453bc6809eSAnna Zaks } 2463bc6809eSAnna Zaks 247918d52ccSAnna Zaks // Does not work when we new an object. testDynCastFail3()248918d52ccSAnna Zaksint testDynCastFail3() { 249918d52ccSAnna Zaks A *a = new A(); 250918d52ccSAnna Zaks B *b = dynamic_cast<B*>(a); 251918d52ccSAnna Zaks return b->m; 252918d52ccSAnna Zaks } 253918d52ccSAnna Zaks 254