Home | History | Annotate | Download | only in Analysis
      1 // RUN: %clang_cc1 -std=c++11 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection -verify %s
      2 void clang_analyzer_eval(bool);
      3 
      4 struct X0 { };
      5 bool operator==(const X0&, const X0&);
      6 
      7 // PR7287
      8 struct test { int a[2]; };
      9 
     10 void t2() {
     11   test p = {{1,2}};
     12   test q;
     13   q = p;
     14 }
     15 
     16 bool PR7287(X0 a, X0 b) {
     17   return operator==(a, b);
     18 }
     19 
     20 
     21 // Inlining non-static member operators mistakenly treated 'this' as the first
     22 // argument for a while.
     23 
     24 struct IntComparable {
     25   bool operator==(int x) const {
     26     return x == 0;
     27   }
     28 };
     29 
     30 void testMemberOperator(IntComparable B) {
     31   clang_analyzer_eval(B == 0); // expected-warning{{TRUE}}
     32 }
     33 
     34 
     35 
     36 namespace UserDefinedConversions {
     37   class Convertible {
     38   public:
     39     operator int() const {
     40       return 42;
     41     }
     42     operator bool() const {
     43       return true;
     44     }
     45   };
     46 
     47   void test(const Convertible &obj) {
     48     clang_analyzer_eval((int)obj == 42); // expected-warning{{TRUE}}
     49     clang_analyzer_eval(obj); // expected-warning{{TRUE}}
     50   }
     51 }
     52 
     53 
     54 namespace RValues {
     55   struct SmallOpaque {
     56     float x;
     57     int operator +() const {
     58       return (int)x;
     59     }
     60   };
     61 
     62   struct LargeOpaque {
     63     float x[4];
     64     int operator +() const {
     65       return (int)x[0];
     66     }
     67   };
     68 
     69   SmallOpaque getSmallOpaque() {
     70     SmallOpaque obj;
     71     obj.x = 1.0;
     72     return obj;
     73   }
     74 
     75   LargeOpaque getLargeOpaque() {
     76     LargeOpaque obj = LargeOpaque();
     77     obj.x[0] = 1.0;
     78     return obj;
     79   }
     80 
     81   void test(int coin) {
     82     // Force a cache-out when we try to conjure a temporary region for the operator call.
     83     // ...then, don't crash.
     84     clang_analyzer_eval(+(coin ? getSmallOpaque() : getSmallOpaque())); // expected-warning{{UNKNOWN}}
     85     clang_analyzer_eval(+(coin ? getLargeOpaque() : getLargeOpaque())); // expected-warning{{UNKNOWN}}
     86   }
     87 }
     88 
     89 namespace SynthesizedAssignment {
     90   struct A {
     91     int a;
     92     A& operator=(A& other) { a = -other.a; return *this; }
     93     A& operator=(A&& other) { a = other.a+1; return *this; }
     94   };
     95 
     96   struct B {
     97     int x;
     98     A a[3];
     99     B& operator=(B&) = default;
    100     B& operator=(B&&) = default;
    101   };
    102 
    103   // This used to produce a warning about the iteration variable in the
    104   // synthesized assignment operator being undefined.
    105   void testNoWarning() {
    106     B v, u;
    107     u = v;
    108   }
    109 
    110   void testNoWarningMove() {
    111     B v, u;
    112     u = static_cast<B &&>(v);
    113   }
    114 
    115   void testConsistency() {
    116     B v, u;
    117     v.a[1].a = 47;
    118     v.a[2].a = 42;
    119     u = v;
    120     clang_analyzer_eval(u.a[1].a == -47); // expected-warning{{TRUE}}
    121     clang_analyzer_eval(u.a[2].a == -42); // expected-warning{{TRUE}}
    122   }
    123 
    124   void testConsistencyMove() {
    125     B v, u;
    126     v.a[1].a = 47;
    127     v.a[2].a = 42;
    128     u = static_cast<B &&>(v);
    129     clang_analyzer_eval(u.a[1].a == 48); // expected-warning{{TRUE}}
    130     clang_analyzer_eval(u.a[2].a == 43); // expected-warning{{TRUE}}
    131   }
    132 }
    133