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
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