1 // RUN: %clang_analyze_cc1 -std=c++11 -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 
t2()10 void t2() {
11   test p = {{1,2}};
12   test q;
13   q = p;
14 }
15 
PR7287(X0 a,X0 b)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 {
operator ==IntComparable25   bool operator==(int x) const {
26     return x == 0;
27   }
28 };
29 
testMemberOperator(IntComparable B)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:
operator int() const39     operator int() const {
40       return 42;
41     }
operator bool() const42     operator bool() const {
43       return true;
44     }
45   };
46 
test(const Convertible & obj)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;
operator +RValues::SmallOpaque57     int operator +() const {
58       return (int)x;
59     }
60   };
61 
62   struct LargeOpaque {
63     float x[4];
operator +RValues::LargeOpaque64     int operator +() const {
65       return (int)x[0];
66     }
67   };
68 
getSmallOpaque()69   SmallOpaque getSmallOpaque() {
70     SmallOpaque obj;
71     obj.x = 1.0;
72     return obj;
73   }
74 
getLargeOpaque()75   LargeOpaque getLargeOpaque() {
76     LargeOpaque obj = LargeOpaque();
77     obj.x[0] = 1.0;
78     return obj;
79   }
80 
test(int coin)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;
operator =SynthesizedAssignment::A92     A& operator=(A& other) { a = -other.a; return *this; }
operator =SynthesizedAssignment::A93     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.
testNoWarning()105   void testNoWarning() {
106     B v, u;
107     u = v;
108   }
109 
testNoWarningMove()110   void testNoWarningMove() {
111     B v, u;
112     u = static_cast<B &&>(v);
113   }
114 
testConsistency()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 
testConsistencyMove()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