Home | History | Annotate | Download | only in Analysis
      1 // RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify -w -std=c++03 %s
      2 // RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify -w -std=c++11 %s
      3 
      4 extern bool clang_analyzer_eval(bool);
      5 
      6 struct Trivial {
      7   Trivial(int x) : value(x) {}
      8   int value;
      9 };
     10 
     11 struct NonTrivial : public Trivial {
     12   NonTrivial(int x) : Trivial(x) {}
     13   ~NonTrivial();
     14 };
     15 
     16 
     17 Trivial getTrivial() {
     18   return Trivial(42); // no-warning
     19 }
     20 
     21 const Trivial &getTrivialRef() {
     22   return Trivial(42); // expected-warning {{Address of stack memory associated with temporary object of type 'Trivial' returned to caller}}
     23 }
     24 
     25 
     26 NonTrivial getNonTrivial() {
     27   return NonTrivial(42); // no-warning
     28 }
     29 
     30 const NonTrivial &getNonTrivialRef() {
     31   return NonTrivial(42); // expected-warning {{Address of stack memory associated with temporary object of type 'NonTrivial' returned to caller}}
     32 }
     33 
     34 namespace rdar13265460 {
     35   struct TrivialSubclass : public Trivial {
     36     TrivialSubclass(int x) : Trivial(x), anotherValue(-x) {}
     37     int anotherValue;
     38   };
     39 
     40   TrivialSubclass getTrivialSub() {
     41     TrivialSubclass obj(1);
     42     obj.value = 42;
     43     obj.anotherValue = -42;
     44     return obj;
     45   }
     46 
     47   void testImmediate() {
     48     TrivialSubclass obj = getTrivialSub();
     49 
     50     clang_analyzer_eval(obj.value == 42); // expected-warning{{TRUE}}
     51     clang_analyzer_eval(obj.anotherValue == -42); // expected-warning{{TRUE}}
     52 
     53     clang_analyzer_eval(getTrivialSub().value == 42); // expected-warning{{TRUE}}
     54     clang_analyzer_eval(getTrivialSub().anotherValue == -42); // expected-warning{{TRUE}}
     55   }
     56 
     57   void testMaterializeTemporaryExpr() {
     58     const TrivialSubclass &ref = getTrivialSub();
     59     clang_analyzer_eval(ref.value == 42); // expected-warning{{TRUE}}
     60 
     61     const Trivial &baseRef = getTrivialSub();
     62     clang_analyzer_eval(baseRef.value == 42); // expected-warning{{TRUE}}
     63   }
     64 }
     65 
     66 namespace rdar13281951 {
     67   struct Derived : public Trivial {
     68     Derived(int value) : Trivial(value), value2(-value) {}
     69     int value2;
     70   };
     71 
     72   void test() {
     73     Derived obj(1);
     74     obj.value = 42;
     75     const Trivial * const &pointerRef = &obj;
     76     clang_analyzer_eval(pointerRef->value == 42); // expected-warning{{TRUE}}
     77   }
     78 }
     79 
     80 namespace compound_literals {
     81   struct POD {
     82     int x, y;
     83   };
     84   struct HasCtor {
     85     HasCtor(int x, int y) : x(x), y(y) {}
     86     int x, y;
     87   };
     88   struct HasDtor {
     89     int x, y;
     90     ~HasDtor();
     91   };
     92   struct HasCtorDtor {
     93     HasCtorDtor(int x, int y) : x(x), y(y) {}
     94     ~HasCtorDtor();
     95     int x, y;
     96   };
     97 
     98   void test() {
     99     clang_analyzer_eval(((POD){1, 42}).y == 42); // expected-warning{{TRUE}}
    100     clang_analyzer_eval(((HasDtor){1, 42}).y == 42); // expected-warning{{TRUE}}
    101 
    102 #if __cplusplus >= 201103L
    103     clang_analyzer_eval(((HasCtor){1, 42}).y == 42); // expected-warning{{TRUE}}
    104 
    105     // FIXME: should be TRUE, but we don't inline the constructors of
    106     // temporaries because we can't model their destructors yet.
    107     clang_analyzer_eval(((HasCtorDtor){1, 42}).y == 42); // expected-warning{{UNKNOWN}}
    108 #endif
    109   }
    110 }
    111 
    112 namespace destructors {
    113   void testPR16664Crash() {
    114     struct Dtor {
    115       ~Dtor();
    116     };
    117     extern bool coin();
    118     extern bool check(const Dtor &);
    119 
    120     // Don't crash here.
    121     if (coin() && (coin() || coin() || check(Dtor()))) {
    122       Dtor();
    123     }
    124   }
    125 
    126   void testConsistency(int i) {
    127     struct NoReturnDtor {
    128       ~NoReturnDtor() __attribute__((noreturn));
    129     };
    130     extern bool check(const NoReturnDtor &);
    131 
    132     if (i == 5 && (i == 4 || i == 5 || check(NoReturnDtor())))
    133       clang_analyzer_eval(true); // expected-warning{{TRUE}}
    134 
    135     if (i != 5)
    136       return;
    137     if (i == 5 && (i == 4 || check(NoReturnDtor()) || i == 5)) {
    138       // FIXME: Should be no-warning, because the noreturn destructor should
    139       // fire on all paths.
    140       clang_analyzer_eval(true); // expected-warning{{TRUE}}
    141     }
    142   }
    143 }
    144 
    145 void testStaticMaterializeTemporaryExpr() {
    146   static const Trivial &ref = getTrivial();
    147   clang_analyzer_eval(ref.value == 42); // expected-warning{{TRUE}}
    148 
    149   static const Trivial &directRef = Trivial(42);
    150   clang_analyzer_eval(directRef.value == 42); // expected-warning{{TRUE}}
    151 
    152 #if __has_feature(cxx_thread_local)
    153   thread_local static const Trivial &threadRef = getTrivial();
    154   clang_analyzer_eval(threadRef.value == 42); // expected-warning{{TRUE}}
    155 
    156   thread_local static const Trivial &threadDirectRef = Trivial(42);
    157   clang_analyzer_eval(threadDirectRef.value == 42); // expected-warning{{TRUE}}
    158 #endif
    159 }
    160