blob: 8cdb005968c3141bd7d89e46284b433727ba0290 [file] [log] [blame]
Jordan Rosebc403862013-02-15 00:32:15 +00001// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -fobjc-arc -analyzer-config c++-inlining=constructors -Wno-null-dereference -std=c++11 -verify %s
Jordan Rosebf83e7c2012-08-03 23:08:36 +00002
3void clang_analyzer_eval(bool);
Jordan Rosede5277f2012-08-31 17:06:49 +00004void clang_analyzer_checkInlined(bool);
Jordan Rose1d3ca252012-07-26 20:04:30 +00005
Jordan Rosebc403862013-02-15 00:32:15 +00006// A simplified version of std::move.
7template <typename T>
8T &&move(T &obj) {
9 return static_cast<T &&>(obj);
10}
11
12
Jordan Rose1d3ca252012-07-26 20:04:30 +000013struct Wrapper {
14 __strong id obj;
15};
16
17void test() {
18 Wrapper w;
19 // force a diagnostic
20 *(char *)0 = 1; // expected-warning{{Dereference of null pointer}}
21}
Jordan Rosebf83e7c2012-08-03 23:08:36 +000022
23
24struct IntWrapper {
25 int x;
26};
27
28void testCopyConstructor() {
29 IntWrapper a;
30 a.x = 42;
31
32 IntWrapper b(a);
33 clang_analyzer_eval(b.x == 42); // expected-warning{{TRUE}}
34}
35
36struct NonPODIntWrapper {
37 int x;
38
39 virtual int get();
40};
41
42void testNonPODCopyConstructor() {
43 NonPODIntWrapper a;
44 a.x = 42;
45
46 NonPODIntWrapper b(a);
47 clang_analyzer_eval(b.x == 42); // expected-warning{{TRUE}}
48}
49
Jordan Rose4e79fdf2012-08-15 20:07:17 +000050
51namespace ConstructorVirtualCalls {
52 class A {
53 public:
54 int *out1, *out2, *out3;
55
56 virtual int get() { return 1; }
57
58 A(int *out1) {
59 *out1 = get();
60 }
61 };
62
63 class B : public A {
64 public:
65 virtual int get() { return 2; }
66
67 B(int *out1, int *out2) : A(out1) {
68 *out2 = get();
69 }
70 };
71
72 class C : public B {
73 public:
74 virtual int get() { return 3; }
75
76 C(int *out1, int *out2, int *out3) : B(out1, out2) {
77 *out3 = get();
78 }
79 };
80
81 void test() {
82 int a, b, c;
83
84 C obj(&a, &b, &c);
85 clang_analyzer_eval(a == 1); // expected-warning{{TRUE}}
86 clang_analyzer_eval(b == 2); // expected-warning{{TRUE}}
87 clang_analyzer_eval(c == 3); // expected-warning{{TRUE}}
88
89 clang_analyzer_eval(obj.get() == 3); // expected-warning{{TRUE}}
90
91 // Sanity check for devirtualization.
92 A *base = &obj;
93 clang_analyzer_eval(base->get() == 3); // expected-warning{{TRUE}}
94 }
95}
96
Jordan Rosede5277f2012-08-31 17:06:49 +000097namespace TemporaryConstructor {
98 class BoolWrapper {
99 public:
100 BoolWrapper() {
101 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
102 value = true;
103 }
104 bool value;
105 };
Jordan Rose4e79fdf2012-08-15 20:07:17 +0000106
Jordan Rosede5277f2012-08-31 17:06:49 +0000107 void test() {
108 // PR13717 - Don't crash when a CXXTemporaryObjectExpr is inlined.
109 if (BoolWrapper().value)
110 return;
111 }
112}
Jordan Rose0504a592012-10-01 17:51:35 +0000113
114
115namespace ConstructorUsedAsRValue {
116 using TemporaryConstructor::BoolWrapper;
117
118 bool extractValue(BoolWrapper b) {
119 return b.value;
120 }
121
122 void test() {
123 bool result = extractValue(BoolWrapper());
124 clang_analyzer_eval(result); // expected-warning{{TRUE}}
125 }
126}
Jordan Rosebc403862013-02-15 00:32:15 +0000127
128namespace PODUninitialized {
129 class POD {
130 public:
131 int x, y;
132 };
133
134 class PODWrapper {
135 public:
136 POD p;
137 };
138
139 class NonPOD {
140 public:
141 int x, y;
142
143 NonPOD() {}
144 NonPOD(const NonPOD &Other)
145 : x(Other.x), y(Other.y) // expected-warning {{undefined}}
146 {
147 }
148 NonPOD(NonPOD &&Other)
149 : x(Other.x), y(Other.y) // expected-warning {{undefined}}
150 {
151 }
Jordan Rosea8d937e2013-03-16 02:14:06 +0000152
153 NonPOD &operator=(const NonPOD &Other)
154 {
155 x = Other.x;
156 y = Other.y; // expected-warning {{undefined}}
157 return *this;
158 }
159 NonPOD &operator=(NonPOD &&Other)
160 {
161 x = Other.x;
162 y = Other.y; // expected-warning {{undefined}}
163 return *this;
164 }
Jordan Rosebc403862013-02-15 00:32:15 +0000165 };
166
167 class NonPODWrapper {
168 public:
169 class Inner {
170 public:
171 int x, y;
172
173 Inner() {}
174 Inner(const Inner &Other)
175 : x(Other.x), y(Other.y) // expected-warning {{undefined}}
176 {
177 }
178 Inner(Inner &&Other)
179 : x(Other.x), y(Other.y) // expected-warning {{undefined}}
180 {
181 }
Jordan Rosea8d937e2013-03-16 02:14:06 +0000182
183 Inner &operator=(const Inner &Other)
184 {
185 x = Other.x; // expected-warning {{undefined}}
186 y = Other.y;
187 return *this;
188 }
189 Inner &operator=(Inner &&Other)
190 {
191 x = Other.x; // expected-warning {{undefined}}
192 y = Other.y;
193 return *this;
194 }
Jordan Rosebc403862013-02-15 00:32:15 +0000195 };
196
197 Inner p;
198 };
199
200 void testPOD() {
201 POD p;
202 p.x = 1;
203 POD p2 = p; // no-warning
204 clang_analyzer_eval(p2.x == 1); // expected-warning{{TRUE}}
205 POD p3 = move(p); // no-warning
206 clang_analyzer_eval(p3.x == 1); // expected-warning{{TRUE}}
207
208 // Use rvalues as well.
209 clang_analyzer_eval(POD(p3).x == 1); // expected-warning{{TRUE}}
210
211 PODWrapper w;
212 w.p.y = 1;
213 PODWrapper w2 = w; // no-warning
214 clang_analyzer_eval(w2.p.y == 1); // expected-warning{{TRUE}}
215 PODWrapper w3 = move(w); // no-warning
216 clang_analyzer_eval(w3.p.y == 1); // expected-warning{{TRUE}}
217
218 // Use rvalues as well.
219 clang_analyzer_eval(PODWrapper(w3).p.y == 1); // expected-warning{{TRUE}}
220 }
221
222 void testNonPOD() {
223 NonPOD p;
224 p.x = 1;
225 NonPOD p2 = p;
226 }
227
228 void testNonPODMove() {
229 NonPOD p;
230 p.x = 1;
231 NonPOD p2 = move(p);
232 }
233
234 void testNonPODWrapper() {
235 NonPODWrapper w;
236 w.p.y = 1;
237 NonPODWrapper w2 = w;
238 }
239
240 void testNonPODWrapperMove() {
241 NonPODWrapper w;
242 w.p.y = 1;
243 NonPODWrapper w2 = move(w);
244 }
Jordan Rosea8d937e2013-03-16 02:14:06 +0000245
246 // Not strictly about constructors, but trivial assignment operators should
247 // essentially work the same way.
248 namespace AssignmentOperator {
249 void testPOD() {
250 POD p;
251 p.x = 1;
252 POD p2;
253 p2 = p; // no-warning
254 clang_analyzer_eval(p2.x == 1); // expected-warning{{TRUE}}
255 POD p3;
256 p3 = move(p); // no-warning
257 clang_analyzer_eval(p3.x == 1); // expected-warning{{TRUE}}
258
259 PODWrapper w;
260 w.p.y = 1;
261 PODWrapper w2;
262 w2 = w; // no-warning
263 clang_analyzer_eval(w2.p.y == 1); // expected-warning{{TRUE}}
264 PODWrapper w3;
265 w3 = move(w); // no-warning
266 clang_analyzer_eval(w3.p.y == 1); // expected-warning{{TRUE}}
267 }
268
269 void testReturnValue() {
270 POD p;
271 p.x = 1;
272 POD p2;
273 clang_analyzer_eval(&(p2 = p) == &p2); // expected-warning{{TRUE}}
274
275 PODWrapper w;
276 w.p.y = 1;
277 PODWrapper w2;
278 clang_analyzer_eval(&(w2 = w) == &w2); // expected-warning{{TRUE}}
279 }
280
281 void testNonPOD() {
282 NonPOD p;
283 p.x = 1;
284 NonPOD p2;
285 p2 = p;
286 }
287
288 void testNonPODMove() {
289 NonPOD p;
290 p.x = 1;
291 NonPOD p2;
292 p2 = move(p);
293 }
294
295 void testNonPODWrapper() {
296 NonPODWrapper w;
297 w.p.y = 1;
298 NonPODWrapper w2;
299 w2 = w;
300 }
301
302 void testNonPODWrapperMove() {
303 NonPODWrapper w;
304 w.p.y = 1;
305 NonPODWrapper w2;
306 w2 = move(w);
307 }
308 }
Jordan Rosebc403862013-02-15 00:32:15 +0000309}
Jordan Roseecee1652013-04-03 01:39:08 +0000310
311namespace ArrayMembers {
312 struct Primitive {
313 int values[3];
314 };
315
316 void testPrimitive() {
317 Primitive a = { { 1, 2, 3 } };
318
319 clang_analyzer_eval(a.values[0] == 1); // expected-warning{{TRUE}}
320 clang_analyzer_eval(a.values[1] == 2); // expected-warning{{TRUE}}
321 clang_analyzer_eval(a.values[2] == 3); // expected-warning{{TRUE}}
322
323 Primitive b = a;
324
325 clang_analyzer_eval(b.values[0] == 1); // expected-warning{{TRUE}}
326 clang_analyzer_eval(b.values[1] == 2); // expected-warning{{TRUE}}
327 clang_analyzer_eval(b.values[2] == 3); // expected-warning{{TRUE}}
328
329 Primitive c;
330 c = b;
331
332 clang_analyzer_eval(c.values[0] == 1); // expected-warning{{TRUE}}
333 clang_analyzer_eval(c.values[1] == 2); // expected-warning{{TRUE}}
334 clang_analyzer_eval(c.values[2] == 3); // expected-warning{{TRUE}}
335 }
336
337 struct NestedPrimitive {
338 int values[2][3];
339 };
340
341 void testNestedPrimitive() {
342 NestedPrimitive a = { { { 0, 0, 0 }, { 1, 2, 3 } } };
343
344 clang_analyzer_eval(a.values[1][0] == 1); // expected-warning{{TRUE}}
345 clang_analyzer_eval(a.values[1][1] == 2); // expected-warning{{TRUE}}
346 clang_analyzer_eval(a.values[1][2] == 3); // expected-warning{{TRUE}}
347
348 NestedPrimitive b = a;
349
350 clang_analyzer_eval(b.values[1][0] == 1); // expected-warning{{TRUE}}
351 clang_analyzer_eval(b.values[1][1] == 2); // expected-warning{{TRUE}}
352 clang_analyzer_eval(b.values[1][2] == 3); // expected-warning{{TRUE}}
353
354 NestedPrimitive c;
355 c = b;
356
357 clang_analyzer_eval(c.values[1][0] == 1); // expected-warning{{TRUE}}
358 clang_analyzer_eval(c.values[1][1] == 2); // expected-warning{{TRUE}}
359 clang_analyzer_eval(c.values[1][2] == 3); // expected-warning{{TRUE}}
360 }
361
362 struct POD {
363 IntWrapper values[3];
364 };
365
366 void testPOD() {
367 POD a = { { { 1 }, { 2 }, { 3 } } };
368
369 clang_analyzer_eval(a.values[0].x == 1); // expected-warning{{TRUE}}
370 clang_analyzer_eval(a.values[1].x == 2); // expected-warning{{TRUE}}
371 clang_analyzer_eval(a.values[2].x == 3); // expected-warning{{TRUE}}
372
373 POD b = a;
374
375 clang_analyzer_eval(b.values[0].x == 1); // expected-warning{{TRUE}}
376 clang_analyzer_eval(b.values[1].x == 2); // expected-warning{{TRUE}}
377 clang_analyzer_eval(b.values[2].x == 3); // expected-warning{{TRUE}}
378
379 POD c;
380 c = b;
381
382 clang_analyzer_eval(c.values[0].x == 1); // expected-warning{{TRUE}}
383 clang_analyzer_eval(c.values[1].x == 2); // expected-warning{{TRUE}}
384 clang_analyzer_eval(c.values[2].x == 3); // expected-warning{{TRUE}}
385 }
386
387 struct NestedPOD {
388 IntWrapper values[2][3];
389 };
390
391 void testNestedPOD() {
392 NestedPOD a = { { { { 0 }, { 0 }, { 0 } }, { { 1 }, { 2 }, { 3 } } } };
393
394 clang_analyzer_eval(a.values[1][0].x == 1); // expected-warning{{TRUE}}
395 clang_analyzer_eval(a.values[1][1].x == 2); // expected-warning{{TRUE}}
396 clang_analyzer_eval(a.values[1][2].x == 3); // expected-warning{{TRUE}}
397
398 NestedPOD b = a;
399
400 clang_analyzer_eval(b.values[1][0].x == 1); // expected-warning{{TRUE}}
401 clang_analyzer_eval(b.values[1][1].x == 2); // expected-warning{{TRUE}}
402 clang_analyzer_eval(b.values[1][2].x == 3); // expected-warning{{TRUE}}
403
404 NestedPOD c;
405 c = b;
406
407 clang_analyzer_eval(c.values[1][0].x == 1); // expected-warning{{TRUE}}
408 clang_analyzer_eval(c.values[1][1].x == 2); // expected-warning{{TRUE}}
409 clang_analyzer_eval(c.values[1][2].x == 3); // expected-warning{{TRUE}}
410 }
411
412 struct NonPOD {
413 NonPODIntWrapper values[3];
414 };
415
416 void testNonPOD() {
417 NonPOD a;
418 a.values[0].x = 1;
419 a.values[1].x = 2;
420 a.values[2].x = 3;
421
422 clang_analyzer_eval(a.values[0].x == 1); // expected-warning{{TRUE}}
423 clang_analyzer_eval(a.values[1].x == 2); // expected-warning{{TRUE}}
424 clang_analyzer_eval(a.values[2].x == 3); // expected-warning{{TRUE}}
425
426 NonPOD b = a;
427
428 clang_analyzer_eval(b.values[0].x == 1); // expected-warning{{UNKNOWN}}
429 clang_analyzer_eval(b.values[1].x == 2); // expected-warning{{UNKNOWN}}
430 clang_analyzer_eval(b.values[2].x == 3); // expected-warning{{UNKNOWN}}
431
432 NonPOD c;
433 c = b;
434
435 clang_analyzer_eval(c.values[0].x == 1); // expected-warning{{UNKNOWN}}
436 clang_analyzer_eval(c.values[1].x == 2); // expected-warning{{UNKNOWN}}
437 clang_analyzer_eval(c.values[2].x == 3); // expected-warning{{UNKNOWN}}
438 }
439
440 struct NestedNonPOD {
441 NonPODIntWrapper values[2][3];
442 };
443
444 void testNestedNonPOD() {
445 NestedNonPOD a;
446 a.values[0][0].x = 0;
447 a.values[0][1].x = 0;
448 a.values[0][2].x = 0;
449 a.values[1][0].x = 1;
450 a.values[1][1].x = 2;
451 a.values[1][2].x = 3;
452
453 clang_analyzer_eval(a.values[1][0].x == 1); // expected-warning{{TRUE}}
454 clang_analyzer_eval(a.values[1][1].x == 2); // expected-warning{{TRUE}}
455 clang_analyzer_eval(a.values[1][2].x == 3); // expected-warning{{TRUE}}
456
457 NestedNonPOD b = a;
458
459 clang_analyzer_eval(b.values[1][0].x == 1); // expected-warning{{UNKNOWN}}
460 clang_analyzer_eval(b.values[1][1].x == 2); // expected-warning{{UNKNOWN}}
461 clang_analyzer_eval(b.values[1][2].x == 3); // expected-warning{{UNKNOWN}}
462
463 NestedNonPOD c;
464 c = b;
465
466 clang_analyzer_eval(c.values[1][0].x == 1); // expected-warning{{UNKNOWN}}
467 clang_analyzer_eval(c.values[1][1].x == 2); // expected-warning{{UNKNOWN}}
468 clang_analyzer_eval(c.values[1][2].x == 3); // expected-warning{{UNKNOWN}}
469 }
470
471 struct NonPODDefaulted {
472 NonPODIntWrapper values[3];
473
474 NonPODDefaulted() = default;
475 NonPODDefaulted(const NonPODDefaulted &) = default;
476 NonPODDefaulted &operator=(const NonPODDefaulted &) = default;
477 };
478
479 void testNonPODDefaulted() {
480 NonPODDefaulted a;
481 a.values[0].x = 1;
482 a.values[1].x = 2;
483 a.values[2].x = 3;
484
485 clang_analyzer_eval(a.values[0].x == 1); // expected-warning{{TRUE}}
486 clang_analyzer_eval(a.values[1].x == 2); // expected-warning{{TRUE}}
487 clang_analyzer_eval(a.values[2].x == 3); // expected-warning{{TRUE}}
488
489 NonPODDefaulted b = a;
490
491 clang_analyzer_eval(b.values[0].x == 1); // expected-warning{{UNKNOWN}}
492 clang_analyzer_eval(b.values[1].x == 2); // expected-warning{{UNKNOWN}}
493 clang_analyzer_eval(b.values[2].x == 3); // expected-warning{{UNKNOWN}}
494
495 NonPODDefaulted c;
496 c = b;
497
498 clang_analyzer_eval(c.values[0].x == 1); // expected-warning{{UNKNOWN}}
499 clang_analyzer_eval(c.values[1].x == 2); // expected-warning{{UNKNOWN}}
500 clang_analyzer_eval(c.values[2].x == 3); // expected-warning{{UNKNOWN}}
501 }
502};