Home | History | Annotate | Download | only in Analysis
      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:
      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).
     22 int 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 
     36 int 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 
     50 int 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 
     65 int 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 
     80 int testMultipleLevelsOfSubclassing3() {
     81   BB bb;
     82   A *pbb = &bb;
     83   B *b = dynamic_cast<B*>(pbb);
     84   return b->m; // no warning
     85 }
     86 
     87 int testLHS() {
     88     B aa;
     89     A *a = &aa;
     90     return (dynamic_cast<B*>(a))->m;
     91 }
     92 
     93 int testLHS2() {
     94     B aa;
     95     A *a = &aa;
     96     return (*dynamic_cast<B*>(a)).m;
     97 }
     98 
     99 int testDynCastUnknown2(class A *a) {
    100   B *b = dynamic_cast<B*>(a);
    101   return b->m; // no warning
    102 }
    103 
    104 int 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 
    116 int 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 
    123 int testLHSFail() {
    124     C c;
    125     A *a = &c;
    126     return (*dynamic_cast<B*>(a)).m; // expected-warning {{Dereference of null pointer}}
    127 }
    128 
    129 int testBaseToDerivedFail() {
    130   A a;
    131   B *b = dynamic_cast<B*>(&a);
    132   return b->m; // expected-warning {{dereference of a null pointer}}
    133 }
    134 
    135 int testConstZeroFail() {
    136   B *b = dynamic_cast<B*>((A *)0);
    137   return b->m; // expected-warning {{dereference of a null pointer}}
    138 }
    139 
    140 int 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 
    146 int 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 
    159 int 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 
    172 int testReferenceSuccesfulCast() {
    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 
    179 int 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.
    191 int 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 {};
    208 void callTestDynCastMostLikelyWillFail() {
    209   M m;
    210   testDynCastMostLikelyWillFail(&m);
    211 }
    212 
    213 
    214 void 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.
    234 int 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.
    248 int testDynCastFail3() {
    249   A *a = new A();
    250   B *b = dynamic_cast<B*>(a);
    251   return b->m;
    252 }
    253 
    254