1 // RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-config ipa=none -verify %s 2 3 void clang_analyzer_eval(bool); 4 5 class A { 6 public: f()7 virtual void f(){}; 8 9 }; 10 class B : public A{ 11 public: 12 int m; 13 }; 14 class C : public A{}; 15 16 class BB: public B{}; 17 18 // A lot of the tests below have the if statement in them, which forces the 19 // analyzer to explore both path - when the result is 0 and not. This makes 20 // sure that we definitely know that the result is non-0 (as the result of 21 // the cast). testDynCastFromRadar()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 warning 34 } 35 testBaseToBase1()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 warning 48 } 49 testMultipleLevelsOfSubclassing1()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 warning 63 } 64 testMultipleLevelsOfSubclassing2()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 warning 78 } 79 testMultipleLevelsOfSubclassing3()80int testMultipleLevelsOfSubclassing3() { 81 BB bb; 82 A *pbb = &bb; 83 B *b = dynamic_cast<B*>(pbb); 84 return b->m; // no warning 85 } 86 testLHS()87int testLHS() { 88 B aa; 89 A *a = &aa; 90 return (dynamic_cast<B*>(a))->m; 91 } 92 testLHS2()93int testLHS2() { 94 B aa; 95 A *a = &aa; 96 return (*dynamic_cast<B*>(a)).m; 97 } 98 testDynCastUnknown2(class A * a)99int testDynCastUnknown2(class A *a) { 100 B *b = dynamic_cast<B*>(a); 101 return b->m; // no warning 102 } 103 testDynCastUnknown(class A * a)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 testDynCastFail2()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 testLHSFail()123int testLHSFail() { 124 C c; 125 A *a = &c; 126 return (*dynamic_cast<B*>(a)).m; // expected-warning {{Dereference of null pointer}} 127 } 128 testBaseToDerivedFail()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 testConstZeroFail()135int testConstZeroFail() { 136 B *b = dynamic_cast<B*>((A *)0); 137 return b->m; // expected-warning {{dereference of a null pointer}} 138 } 139 testConstZeroFail2()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 testUpcast()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 warning 157 } 158 testCastToVoidStar()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 warning 170 } 171 testReferenceSuccessfulCast()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 testReferenceFailedCast()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 a 187 // situation where this will fail. So if the user has written the code in this 188 // way, we assume they expect the cast to succeed. 189 // Note, this might need special handling if we track types of symbolic casts 190 // and use them for dynamic_cast handling. testDynCastMostLikelyWillFail(C * c)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 the 203 // dynamic_cast could succeed. 204 return *res; // expected-warning{{Dereference of null pointer}} 205 } 206 207 class M : public B, public C {}; callTestDynCastMostLikelyWillFail()208void callTestDynCastMostLikelyWillFail() { 209 M m; 210 testDynCastMostLikelyWillFail(&m); 211 } 212 213 testDynCastToMiddleClass()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. testDynCastFalsePositive(BB * c)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. testDynCastFail3()248int testDynCastFail3() { 249 A *a = new A(); 250 B *b = dynamic_cast<B*>(a); 251 return b->m; 252 } 253 254