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