1 // RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,alpha.core,debug.ExprInspection -analyzer-output=text -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 // expected-note@-1{{TRUE}}
33 }
34
35
36
37 namespace UserDefinedConversions {
38 class Convertible {
39 public:
operator int() const40 operator int() const {
41 return 42;
42 }
operator bool() const43 operator bool() const {
44 return true;
45 }
46 };
47
test(const Convertible & obj)48 void test(const Convertible &obj) {
49 clang_analyzer_eval((int)obj == 42); // expected-warning{{TRUE}}
50 // expected-note@-1{{TRUE}}
51 clang_analyzer_eval(obj); // expected-warning{{TRUE}}
52 // expected-note@-1{{TRUE}}
53 }
54 }
55
56
57 namespace RValues {
58 struct SmallOpaque {
59 float x;
operator +RValues::SmallOpaque60 int operator +() const {
61 return (int)x;
62 }
63 };
64
65 struct LargeOpaque {
66 float x[4];
operator +RValues::LargeOpaque67 int operator +() const {
68 return (int)x[0];
69 }
70 };
71
getSmallOpaque()72 SmallOpaque getSmallOpaque() {
73 SmallOpaque obj;
74 obj.x = 1.0;
75 return obj;
76 }
77
getLargeOpaque()78 LargeOpaque getLargeOpaque() {
79 LargeOpaque obj = LargeOpaque();
80 obj.x[0] = 1.0;
81 return obj;
82 }
83
test(int coin)84 void test(int coin) {
85 // Force a cache-out when we try to conjure a temporary region for the operator call.
86 // ...then, don't crash.
87 clang_analyzer_eval(+(coin ? getSmallOpaque() : getSmallOpaque())); // expected-warning{{UNKNOWN}}
88 // expected-note@-1{{Assuming 'coin' is 0}}
89 // expected-note@-2{{'?' condition is false}}
90 // expected-note@-3{{UNKNOWN}}
91 // expected-note@-4{{Assuming 'coin' is 0}}
92 // expected-note@-5{{'?' condition is false}}
93 clang_analyzer_eval(+(coin ? getLargeOpaque() : getLargeOpaque())); // expected-warning{{UNKNOWN}}
94 // expected-note@-1{{'coin' is 0}}
95 // expected-note@-2{{'?' condition is false}}
96 // expected-note@-3{{UNKNOWN}}
97 }
98 }
99
100 namespace SynthesizedAssignment {
101 struct A {
102 int a;
operator =SynthesizedAssignment::A103 A& operator=(A& other) { a = -other.a; return *this; }
operator =SynthesizedAssignment::A104 A& operator=(A&& other) { a = other.a+1; return *this; }
105 };
106
107 struct B {
108 int x;
109 A a[3];
110 B& operator=(B&) = default;
111 B& operator=(B&&) = default;
112 };
113
114 // This used to produce a warning about the iteration variable in the
115 // synthesized assignment operator being undefined.
116 //
117 // Note: The warning we want to avoid can be found in https://bugs.llvm.org/show_bug.cgi?id=16745.
118 // Back in the day, this function was created we couldn't evaluate non-POD type array construction,
119 // so we couldn't evaluate the copy assignment either, hence we didn't detect that a field is
120 // uninitialized.
testNoWarning()121 void testNoWarning() {
122
123 B v, u;
124 u = v; // expected-warning@110{{Assigned value is garbage or undefined}}
125 // expected-note@-1{{Calling defaulted copy assignment operator for 'B'}}
126 // expected-note@110{{Assigned value is garbage or undefined}}
127 }
128
testNoWarningMove()129 void testNoWarningMove() {
130 B v, u;
131 u = static_cast<B &&>(v); // expected-warning@111{{Assigned value is garbage or undefined}}
132 // expected-note@-1{{Calling defaulted move assignment operator for 'B'}}
133 // expected-note@111{{Assigned value is garbage or undefined}}
134 }
135
testConsistency()136 void testConsistency() {
137 B v, u;
138 v.x = 0;
139 v.a[0].a = 24;
140 v.a[1].a = 47;
141 v.a[2].a = 42;
142 u = v;
143 clang_analyzer_eval(u.a[0].a == -24); // expected-warning{{TRUE}}
144 // expected-note@-1{{TRUE}}
145 clang_analyzer_eval(u.a[1].a == -47); // expected-warning{{TRUE}}
146 // expected-note@-1{{TRUE}}
147 clang_analyzer_eval(u.a[2].a == -42); // expected-warning{{TRUE}}
148 // expected-note@-1{{TRUE}}
149 }
150
testConsistencyMove()151 void testConsistencyMove() {
152 B v, u;
153 v.x = 0;
154 v.a[0].a = 24;
155 v.a[1].a = 47;
156 v.a[2].a = 42;
157 u = static_cast<B &&>(v);
158 clang_analyzer_eval(u.a[0].a == 25); // expected-warning{{TRUE}}
159 // expected-note@-1{{TRUE}}
160 clang_analyzer_eval(u.a[1].a == 48); // expected-warning{{TRUE}}
161 // expected-note@-1{{TRUE}}
162 clang_analyzer_eval(u.a[2].a == 43); // expected-warning{{TRUE}}
163 // expected-note@-1{{TRUE}}
164 }
165 }
166