blob: e82610527965a00e6f05d22b8557ec3ab2a77a8a [file] [log] [blame]
Artem Dergachev9d3a7d82018-03-30 19:21:18 +00001// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -std=c++11 -verify %s
2// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -std=c++17 -verify %s
3
4void clang_analyzer_eval(bool);
5
Artem Dergachev1fe52472018-06-14 01:32:46 +00006namespace variable_functional_cast_crash {
7
8struct A {
9 A(int) {}
10};
11
12void foo() {
13 A a = A(0);
14}
15
16struct B {
17 A a;
18 B(): a(A(0)) {}
19};
20
21} // namespace variable_functional_cast_crash
22
23
Artem Dergacheva84374d2018-06-14 01:40:49 +000024namespace ctor_initializer {
25
26struct S {
27 int x, y, z;
28};
29
30struct T {
31 S s;
32 int w;
33 T(int w): s(), w(w) {}
34};
35
36class C {
37 T t;
38public:
39 C() : t(T(4)) {
40 S s = {1, 2, 3};
41 t.s = s;
42 // FIXME: Should be TRUE in C++11 as well.
43 clang_analyzer_eval(t.w == 4);
44#if __cplusplus >= 201703L
45 // expected-warning@-2{{TRUE}}
46#else
47 // expected-warning@-4{{UNKNOWN}}
48#endif
49 }
50};
51
Artem Dergachev53b8ce02018-06-14 01:54:21 +000052
53struct A {
54 int x;
55 A(): x(0) {}
56 ~A() {}
57};
58
59struct B {
60 A a;
61 B() : a(A()) {}
62};
63
64void foo() {
65 B b;
66 clang_analyzer_eval(b.a.x == 0); // expected-warning{{TRUE}}
67}
68
Artem Dergacheva84374d2018-06-14 01:40:49 +000069} // namespace ctor_initializer
70
71
Artem Dergachev53b8ce02018-06-14 01:54:21 +000072namespace elision_on_ternary_op_branches {
73class C1 {
74 int x;
75public:
76 C1(int x): x(x) {}
77 int getX() const { return x; }
78 ~C1();
79};
80
81class C2 {
82 int x;
83 int y;
84public:
85 C2(int x, int y): x(x), y(y) {}
86 int getX() const { return x; }
87 int getY() const { return y; }
88 ~C2();
89};
90
91void foo(int coin) {
92 C1 c1 = coin ? C1(1) : C1(2);
93 if (coin) {
94 clang_analyzer_eval(c1.getX() == 1); // expected-warning{{TRUE}}
95 } else {
96 clang_analyzer_eval(c1.getX() == 2); // expected-warning{{TRUE}}
97 }
98 C2 c2 = coin ? C2(3, 4) : C2(5, 6);
99 if (coin) {
100 clang_analyzer_eval(c2.getX() == 3); // expected-warning{{TRUE}}
101 clang_analyzer_eval(c2.getY() == 4); // expected-warning{{TRUE}}
102 } else {
103 clang_analyzer_eval(c2.getX() == 5); // expected-warning{{TRUE}}
104 clang_analyzer_eval(c2.getY() == 6); // expected-warning{{TRUE}}
105 }
106}
107} // namespace elision_on_ternary_op_branches
108
109
Artem Dergachev1fe52472018-06-14 01:32:46 +0000110namespace address_vector_tests {
111
Artem Dergachev9d3a7d82018-03-30 19:21:18 +0000112template <typename T> struct AddressVector {
113 T *buf[10];
114 int len;
115
116 AddressVector() : len(0) {}
117
118 void push(T *t) {
119 buf[len] = t;
120 ++len;
121 }
122};
123
124class ClassWithoutDestructor {
125 AddressVector<ClassWithoutDestructor> &v;
126
127public:
128 ClassWithoutDestructor(AddressVector<ClassWithoutDestructor> &v) : v(v) {
129 v.push(this);
130 }
131
132 ClassWithoutDestructor(ClassWithoutDestructor &&c) : v(c.v) { v.push(this); }
133 ClassWithoutDestructor(const ClassWithoutDestructor &c) : v(c.v) {
134 v.push(this);
135 }
136};
137
138ClassWithoutDestructor make1(AddressVector<ClassWithoutDestructor> &v) {
139 return ClassWithoutDestructor(v);
140}
141ClassWithoutDestructor make2(AddressVector<ClassWithoutDestructor> &v) {
142 return make1(v);
143}
144ClassWithoutDestructor make3(AddressVector<ClassWithoutDestructor> &v) {
145 return make2(v);
146}
147
148void testMultipleReturns() {
149 AddressVector<ClassWithoutDestructor> v;
150 ClassWithoutDestructor c = make3(v);
151
152#if __cplusplus >= 201703L
Artem Dergachev9d3a7d82018-03-30 19:21:18 +0000153 clang_analyzer_eval(v.len == 1); // expected-warning{{TRUE}}
Artem Dergachevf28d7f172018-06-14 01:59:35 +0000154 clang_analyzer_eval(v.buf[0] == &c); // expected-warning{{TRUE}}
Artem Dergachev9d3a7d82018-03-30 19:21:18 +0000155#else
156 clang_analyzer_eval(v.len == 5); // expected-warning{{TRUE}}
157 clang_analyzer_eval(v.buf[0] != v.buf[1]); // expected-warning{{TRUE}}
158 clang_analyzer_eval(v.buf[1] != v.buf[2]); // expected-warning{{TRUE}}
159 clang_analyzer_eval(v.buf[2] != v.buf[3]); // expected-warning{{TRUE}}
160 clang_analyzer_eval(v.buf[3] != v.buf[4]); // expected-warning{{TRUE}}
161 clang_analyzer_eval(v.buf[4] == &c); // expected-warning{{TRUE}}
162#endif
163}
Artem Dergachev1fe52472018-06-14 01:32:46 +0000164
Artem Dergachev53b8ce02018-06-14 01:54:21 +0000165class ClassWithDestructor {
166 AddressVector<ClassWithDestructor> &v;
167
168public:
169 ClassWithDestructor(AddressVector<ClassWithDestructor> &v) : v(v) {
170 v.push(this);
171 }
172
173 ClassWithDestructor(ClassWithDestructor &&c) : v(c.v) { v.push(this); }
174 ClassWithDestructor(const ClassWithDestructor &c) : v(c.v) {
175 v.push(this);
176 }
177
178 ~ClassWithDestructor() { v.push(this); }
179};
180
181void testVariable() {
182 AddressVector<ClassWithDestructor> v;
183 {
184 ClassWithDestructor c = ClassWithDestructor(v);
Artem Dergachevf28d7f172018-06-14 01:59:35 +0000185 // Check if the last destructor is an automatic destructor.
186 // A temporary destructor would have fired by now.
187#if __cplusplus >= 201703L
188 clang_analyzer_eval(v.len == 1); // expected-warning{{TRUE}}
189#else
190 clang_analyzer_eval(v.len == 3); // expected-warning{{TRUE}}
191#endif
Artem Dergachev53b8ce02018-06-14 01:54:21 +0000192 }
193#if __cplusplus >= 201703L
194 // 0. Construct the variable.
195 // 1. Destroy the variable.
196 clang_analyzer_eval(v.len == 2); // expected-warning{{TRUE}}
197 clang_analyzer_eval(v.buf[0] == v.buf[1]); // expected-warning{{TRUE}}
198#else
199 // 0. Construct the temporary.
200 // 1. Construct the variable.
201 // 2. Destroy the temporary.
202 // 3. Destroy the variable.
203 clang_analyzer_eval(v.len == 4); // expected-warning{{TRUE}}
204 clang_analyzer_eval(v.buf[0] == v.buf[2]); // expected-warning{{TRUE}}
205 clang_analyzer_eval(v.buf[1] == v.buf[3]); // expected-warning{{TRUE}}
206#endif
207}
208
209struct TestCtorInitializer {
210 ClassWithDestructor c;
211 TestCtorInitializer(AddressVector<ClassWithDestructor> &v)
212 : c(ClassWithDestructor(v)) {}
213};
214
215void testCtorInitializer() {
216 AddressVector<ClassWithDestructor> v;
217 {
218 TestCtorInitializer t(v);
Artem Dergachevf28d7f172018-06-14 01:59:35 +0000219 // Check if the last destructor is an automatic destructor.
220 // A temporary destructor would have fired by now.
221#if __cplusplus >= 201703L
222 clang_analyzer_eval(v.len == 1); // expected-warning{{TRUE}}
223#else
224 clang_analyzer_eval(v.len == 3); // expected-warning{{TRUE}}
225#endif
Artem Dergachev53b8ce02018-06-14 01:54:21 +0000226 }
227#if __cplusplus >= 201703L
228 // 0. Construct the member variable.
229 // 1. Destroy the member variable.
230 clang_analyzer_eval(v.len == 2); // expected-warning{{TRUE}}
231 clang_analyzer_eval(v.buf[0] == v.buf[1]); // expected-warning{{TRUE}}
232#else
233 // 0. Construct the temporary.
234 // 1. Construct the member variable.
235 // 2. Destroy the temporary.
236 // 3. Destroy the member variable.
237 clang_analyzer_eval(v.len == 4); // expected-warning{{TRUE}}
238 clang_analyzer_eval(v.buf[0] == v.buf[2]); // expected-warning{{TRUE}}
239 clang_analyzer_eval(v.buf[1] == v.buf[3]); // expected-warning{{TRUE}}
240#endif
241}
242
Artem Dergachevf28d7f172018-06-14 01:59:35 +0000243
244ClassWithDestructor make1(AddressVector<ClassWithDestructor> &v) {
245 return ClassWithDestructor(v);
246}
247ClassWithDestructor make2(AddressVector<ClassWithDestructor> &v) {
248 return make1(v);
249}
250ClassWithDestructor make3(AddressVector<ClassWithDestructor> &v) {
251 return make2(v);
252}
253
254void testMultipleReturnsWithDestructors() {
255 AddressVector<ClassWithDestructor> v;
256 {
257 ClassWithDestructor c = make3(v);
258 // Check if the last destructor is an automatic destructor.
259 // A temporary destructor would have fired by now.
260#if __cplusplus >= 201703L
261 clang_analyzer_eval(v.len == 1); // expected-warning{{TRUE}}
262#else
263 clang_analyzer_eval(v.len == 9); // expected-warning{{TRUE}}
264#endif
265 }
266
267#if __cplusplus >= 201703L
268 // 0. Construct the variable. Yes, constructor in make1() constructs
269 // the variable 'c'.
270 // 1. Destroy the variable.
271 clang_analyzer_eval(v.len == 2); // expected-warning{{TRUE}}
272 clang_analyzer_eval(v.buf[0] == v.buf[1]); // expected-warning{{TRUE}}
273#else
274 // 0. Construct the temporary in make1().
275 // 1. Construct the temporary in make2().
276 // 2. Destroy the temporary in make1().
277 // 3. Construct the temporary in make3().
278 // 4. Destroy the temporary in make2().
279 // 5. Construct the temporary here.
280 // 6. Destroy the temporary in make3().
281 // 7. Construct the variable.
282 // 8. Destroy the temporary here.
283 // 9. Destroy the variable.
284 clang_analyzer_eval(v.len == 10); // expected-warning{{TRUE}}
285 clang_analyzer_eval(v.buf[0] == v.buf[2]); // expected-warning{{TRUE}}
286 clang_analyzer_eval(v.buf[1] == v.buf[4]); // expected-warning{{TRUE}}
287 clang_analyzer_eval(v.buf[3] == v.buf[6]); // expected-warning{{TRUE}}
288 clang_analyzer_eval(v.buf[5] == v.buf[8]); // expected-warning{{TRUE}}
289 clang_analyzer_eval(v.buf[7] == v.buf[9]); // expected-warning{{TRUE}}
290#endif
291}
Artem Dergachev1fe52472018-06-14 01:32:46 +0000292} // namespace address_vector_tests